network.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. package main
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "strconv"
  6. "strings"
  7. "imuslab.com/arozos/mod/fileservers"
  8. "imuslab.com/arozos/mod/fileservers/servers/dirserv"
  9. "imuslab.com/arozos/mod/fileservers/servers/ftpserv"
  10. "imuslab.com/arozos/mod/fileservers/servers/sftpserv"
  11. "imuslab.com/arozos/mod/fileservers/servers/webdavserv"
  12. network "imuslab.com/arozos/mod/network"
  13. mdns "imuslab.com/arozos/mod/network/mdns"
  14. "imuslab.com/arozos/mod/network/netstat"
  15. ssdp "imuslab.com/arozos/mod/network/ssdp"
  16. upnp "imuslab.com/arozos/mod/network/upnp"
  17. "imuslab.com/arozos/mod/network/websocket"
  18. prout "imuslab.com/arozos/mod/prouter"
  19. "imuslab.com/arozos/mod/utils"
  20. "imuslab.com/arozos/mod/www"
  21. )
  22. var (
  23. //Network Services Managers
  24. MDNS *mdns.MDNSHost
  25. UPNP *upnp.UPnPClient
  26. SSDP *ssdp.SSDPHost
  27. WebSocketRouter *websocket.Router
  28. //File Server Managers
  29. FTPManager *ftpserv.Manager
  30. WebDAVManager *webdavserv.Manager
  31. SFTPManager *sftpserv.Manager
  32. DirListManager *dirserv.Manager
  33. )
  34. func NetworkServiceInit() {
  35. systemWideLogger.PrintAndLog("Network", "Starting ArOZ Network Services", nil)
  36. //Create a router that allow users with System Setting access to access these api endpoints
  37. router := prout.NewModuleRouter(prout.RouterOption{
  38. ModuleName: "System Setting",
  39. AdminOnly: false,
  40. UserHandler: userHandler,
  41. DeniedHandler: func(w http.ResponseWriter, r *http.Request) {
  42. utils.SendErrorResponse(w, "Permission Denied")
  43. },
  44. })
  45. /*
  46. Standard Network Utilties
  47. */
  48. //Register handler endpoints
  49. if *allow_hardware_management {
  50. router.HandleFunc("/system/network/getNICinfo", network.GetNICInfo)
  51. router.HandleFunc("/system/network/getPing", network.GetPing)
  52. //Register as a system setting
  53. registerSetting(settingModule{
  54. Name: "Network Info",
  55. Desc: "System Information",
  56. IconPath: "SystemAO/network/img/ethernet.png",
  57. Group: "Network",
  58. StartDir: "SystemAO/network/hardware.html",
  59. })
  60. }
  61. router.HandleFunc("/system/network/getNICUsage", netstat.HandleGetNetworkInterfaceStats)
  62. //Start the services that depends on network interface
  63. StartNetworkServices()
  64. //Start the port forward configuration interface
  65. portForwardInit()
  66. //Start userhomepage if enabled
  67. //Handle user webroot routings if homepage is enabled
  68. if *allow_homepage {
  69. userWwwHandler = www.NewWebRootHandler(www.Options{
  70. UserHandler: userHandler,
  71. Database: sysdb,
  72. AgiGateway: AGIGateway,
  73. })
  74. router.HandleFunc("/system/network/www/toggle", userWwwHandler.HandleToggleHomepage)
  75. router.HandleFunc("/system/network/www/webRoot", userWwwHandler.HandleSetWebRoot)
  76. //Register as a system setting
  77. registerSetting(settingModule{
  78. Name: "Personal Page",
  79. Desc: "Personal Web Page",
  80. IconPath: "SystemAO/www/img/homepage.png",
  81. Group: "Network",
  82. StartDir: "SystemAO/www/config.html",
  83. })
  84. }
  85. userRouter := prout.NewModuleRouter(prout.RouterOption{
  86. AdminOnly: false,
  87. UserHandler: userHandler,
  88. DeniedHandler: func(w http.ResponseWriter, r *http.Request) {
  89. utils.SendErrorResponse(w, "Permission Denied")
  90. },
  91. })
  92. WebSocketRouter = websocket.NewRouter()
  93. userRouter.HandleFunc("/system/ws", WebSocketRouter.HandleWebSocketRouting)
  94. }
  95. func StartNetworkServices() {
  96. /*
  97. MDNS Services
  98. */
  99. if *allow_mdns {
  100. m, err := mdns.NewMDNS(mdns.NetworkHost{
  101. HostName: *host_name + "_" + deviceUUID, //To handle more than one identical model within the same network, this must be unique
  102. Port: *listen_port,
  103. Domain: "arozos.com",
  104. Model: deviceModel,
  105. UUID: deviceUUID,
  106. Vendor: deviceVendor,
  107. BuildVersion: build_version,
  108. MinorVersion: internal_version,
  109. }, *force_mac)
  110. if err != nil {
  111. systemWideLogger.PrintAndLog("Network", "MDNS Startup Failed. Running in Offline Mode.", err)
  112. } else {
  113. MDNS = m
  114. }
  115. }
  116. /*
  117. SSDP Discovery Services
  118. */
  119. if *allow_ssdp {
  120. //Get outbound ip
  121. obip, err := network.GetOutboundIP()
  122. if err != nil {
  123. systemWideLogger.PrintAndLog("Network", "SSDP Startup Failed. Running in Offline Mode.", err)
  124. } else {
  125. thisIp := obip.String()
  126. adv, err := ssdp.NewSSDPHost(thisIp, *listen_port, "system/ssdp.xml", ssdp.SSDPOption{
  127. URLBase: "http://" + thisIp + ":" + strconv.Itoa(*listen_port), //This must be http if used as local hosting devices
  128. Hostname: *host_name,
  129. Vendor: deviceVendor,
  130. VendorURL: deviceVendorURL,
  131. ModelName: deviceModel,
  132. ModelDesc: deviceModelDesc,
  133. UUID: deviceUUID,
  134. Serial: "generic",
  135. })
  136. if err != nil {
  137. systemWideLogger.PrintAndLog("Network", "SSDP Startup Failed. Running in Offline Mode.", err)
  138. } else {
  139. //OK! Start SSDP Service
  140. SSDP = adv
  141. SSDP.Start()
  142. }
  143. }
  144. }
  145. /*
  146. UPNP / Setup automatic port forwarding
  147. */
  148. if *allow_upnp {
  149. var u *upnp.UPnPClient
  150. var err error = nil
  151. if *use_tls {
  152. u, err = upnp.NewUPNPClient(*tls_listen_port, *host_name+"-https")
  153. } else {
  154. u, err = upnp.NewUPNPClient(*listen_port, *host_name+"-http")
  155. }
  156. if err != nil {
  157. systemWideLogger.PrintAndLog("Network", "UPnP Startup Failed: "+err.Error(), err)
  158. } else {
  159. //Bind the http port if running in https and http server is not disabled
  160. if *use_tls && !*disable_http {
  161. u.ForwardPort(*listen_port, *host_name+"-http")
  162. }
  163. UPNP = u
  164. //Register nightly listener for upnp renew
  165. nightlyManager.RegisterNightlyTask(func() {
  166. UPNP.RenewForwardRules()
  167. })
  168. //Show a tip for success port forward
  169. connectionEndpoint := UPNP.ExternalIP + ":" + strconv.Itoa(*listen_port)
  170. obip, err := network.GetOutboundIP()
  171. obipstring := "[Outbound IP]"
  172. if err != nil {
  173. } else {
  174. obipstring = obip.String()
  175. }
  176. localEndpoint := obipstring + ":" + strconv.Itoa(*listen_port)
  177. systemWideLogger.PrintAndLog("Network", "Automatic Port Forwarding Completed. Forwarding all request from "+connectionEndpoint+" to "+localEndpoint, nil)
  178. }
  179. }
  180. }
  181. func StopNetworkServices() {
  182. //systemWideLogger.PrintAndLog("Shutting Down Network Services...",nil)
  183. //Shutdown uPNP service if enabled
  184. if *allow_upnp {
  185. systemWideLogger.PrintAndLog("System", "<!> Shutting down uPNP service", nil)
  186. UPNP.Close()
  187. }
  188. //Shutdown SSDP service if enabled
  189. if *allow_ssdp {
  190. systemWideLogger.PrintAndLog("System", "<!> Shutting down SSDP service", nil)
  191. SSDP.Close()
  192. }
  193. //Shutdown MDNS if enabled
  194. if *allow_mdns {
  195. systemWideLogger.PrintAndLog("System", "<!> Shutting down MDNS service", nil)
  196. MDNS.Close()
  197. }
  198. }
  199. /*
  200. File Server Services
  201. */
  202. var networkFileServerDaemon []*fileservers.Server = []*fileservers.Server{}
  203. // Initiate all File Server services
  204. func FileServerInit() {
  205. //Register System Setting
  206. registerSetting(settingModule{
  207. Name: "File Servers",
  208. Desc: "Network File Transfer Servers",
  209. IconPath: "SystemAO/disk/smart/img/small_icon.png",
  210. Group: "Network",
  211. StartDir: "SystemAO/disk/services.html",
  212. RequireAdmin: false,
  213. })
  214. //Create request routers
  215. adminRouter := prout.NewModuleRouter(prout.RouterOption{
  216. ModuleName: "System Setting",
  217. AdminOnly: true,
  218. UserHandler: userHandler,
  219. DeniedHandler: func(w http.ResponseWriter, r *http.Request) {
  220. errorHandlePermissionDenied(w, r)
  221. },
  222. })
  223. router := prout.NewModuleRouter(prout.RouterOption{
  224. ModuleName: "System Setting",
  225. AdminOnly: false,
  226. UserHandler: userHandler,
  227. DeniedHandler: func(w http.ResponseWriter, r *http.Request) {
  228. utils.SendErrorResponse(w, "Permission Denied")
  229. },
  230. })
  231. //Create File Server Managers
  232. webdavPort := *listen_port
  233. if *use_tls {
  234. webdavPort = *tls_listen_port
  235. }
  236. WebDAVManager = webdavserv.NewWebDAVManager(&webdavserv.ManagerOption{
  237. Sysdb: sysdb,
  238. Hostname: *host_name,
  239. TmpDir: *tmp_directory,
  240. Port: webdavPort,
  241. UseTls: *use_tls,
  242. UserHandler: userHandler,
  243. })
  244. FTPManager = ftpserv.NewFTPManager(&ftpserv.ManagerOption{
  245. Hostname: *host_name,
  246. TmpFolder: *tmp_directory,
  247. Logger: systemWideLogger,
  248. UserManager: userHandler,
  249. FtpServer: nil,
  250. Sysdb: sysdb,
  251. Upnp: UPNP,
  252. AllowUpnp: *allow_upnp,
  253. })
  254. SFTPManager = sftpserv.NewSFTPServer(&sftpserv.ManagerOption{
  255. Hostname: *host_name,
  256. Upnp: UPNP,
  257. UserManager: userHandler,
  258. KeyFile: "system/auth/id_rsa.key",
  259. Logger: systemWideLogger,
  260. Sysdb: sysdb,
  261. })
  262. listeningPort := *listen_port
  263. if *use_tls {
  264. listeningPort = *tls_listen_port
  265. }
  266. DirListManager = dirserv.NewDirectoryServer(&dirserv.Option{
  267. Sysdb: sysdb,
  268. ServerPort: listeningPort,
  269. UserManager: userHandler,
  270. ServerUUID: deviceUUID,
  271. })
  272. //Register Endpoints
  273. //WebDAV
  274. http.HandleFunc("/system/network/webdav/list", WebDAVManager.HandleConnectionList)
  275. router.HandleFunc("/system/network/webdav/edit", WebDAVManager.HandlePermissionEdit)
  276. router.HandleFunc("/system/network/webdav/clear", WebDAVManager.HandleClearAllPending)
  277. router.HandleFunc("/system/network/webdav/status", WebDAVManager.HandleStatusChange)
  278. //SFTP
  279. adminRouter.HandleFunc("/system/storage/sftp/port", SFTPManager.HandleListeningPort)
  280. adminRouter.HandleFunc("/system/storage/sftp/upnp", SFTPManager.HandleToogleUPnP)
  281. adminRouter.HandleFunc("/system/storage/sftp/users", SFTPManager.HandleGetConnectedClients)
  282. //FTP
  283. //adminRouter.HandleFunc("/system/storage/ftp/start", FTPManager.HandleFTPServerStart)
  284. //adminRouter.HandleFunc("/system/storage/ftp/stop", FTPManager.HandleFTPServerStop)
  285. adminRouter.HandleFunc("/system/storage/ftp/upnp", FTPManager.HandleFTPUPnP)
  286. adminRouter.HandleFunc("/system/storage/ftp/status", FTPManager.HandleFTPServerStatus)
  287. adminRouter.HandleFunc("/system/storage/ftp/updateGroups", FTPManager.HandleFTPAccessUpdate)
  288. adminRouter.HandleFunc("/system/storage/ftp/setPort", FTPManager.HandleFTPSetPort)
  289. adminRouter.HandleFunc("/system/storage/ftp/passivemode", FTPManager.HandleFTPPassiveModeSettings)
  290. networkFileServerDaemon = append(networkFileServerDaemon, &fileservers.Server{
  291. ID: "webdav",
  292. Name: "WebDAV",
  293. Desc: "WebDAV Server",
  294. IconPath: "img/system/network-folder-blue.svg",
  295. DefaultPorts: []int{},
  296. Ports: []int{},
  297. ForwardPortIfUpnp: false,
  298. ConnInstrPage: "SystemAO/disk/instr/webdav.html",
  299. ConfigPage: "SystemAO/disk/webdav.html",
  300. EnableCheck: WebDAVManager.GetWebDavEnabled,
  301. ToggleFunc: WebDAVManager.WebDavToogle,
  302. GetEndpoints: WebDAVManager.WebDavGetEndpoints,
  303. })
  304. networkFileServerDaemon = append(networkFileServerDaemon, &fileservers.Server{
  305. ID: "sftp",
  306. Name: "SFTP",
  307. Desc: "SSH File Transfer Protocol Server",
  308. IconPath: "img/system/network-folder-sftp.svg",
  309. DefaultPorts: []int{2022},
  310. Ports: []int{},
  311. ForwardPortIfUpnp: true,
  312. ConnInstrPage: "SystemAO/disk/instr/sftp.html",
  313. ConfigPage: "SystemAO/disk/sftp.html",
  314. EnableCheck: SFTPManager.IsEnabled,
  315. ToggleFunc: SFTPManager.ServerToggle,
  316. GetEndpoints: SFTPManager.GetEndpoints,
  317. })
  318. networkFileServerDaemon = append(networkFileServerDaemon, &fileservers.Server{
  319. ID: "ftp",
  320. Name: "FTP",
  321. Desc: "File Transfer Protocol Server",
  322. IconPath: "img/system/network-folder.svg",
  323. DefaultPorts: []int{21, 22, 23},
  324. Ports: []int{},
  325. ForwardPortIfUpnp: true,
  326. ConnInstrPage: "SystemAO/disk/instr/ftp.html",
  327. ConfigPage: "SystemAO/disk/ftp.html",
  328. EnableCheck: FTPManager.IsFtpServerEnabled,
  329. ToggleFunc: FTPManager.FTPServerToggle,
  330. GetEndpoints: FTPManager.FTPGetEndpoints,
  331. })
  332. networkFileServerDaemon = append(networkFileServerDaemon, &fileservers.Server{
  333. ID: "dirserv",
  334. Name: "Directory Server",
  335. Desc: "Web file viewer for legacy devices",
  336. IconPath: "img/system/network-dirserv.svg",
  337. DefaultPorts: []int{},
  338. Ports: []int{},
  339. ForwardPortIfUpnp: false,
  340. ConnInstrPage: "SystemAO/disk/instr/dirserv.html",
  341. ConfigPage: "SystemAO/disk/dirserv.html",
  342. EnableCheck: DirListManager.DirServerEnabled,
  343. ToggleFunc: DirListManager.Toggle,
  344. GetEndpoints: DirListManager.ListEndpoints,
  345. })
  346. router.HandleFunc("/system/network/server/list", NetworkHandleGetFileServerServiceList)
  347. router.HandleFunc("/system/network/server/endpoints", NetworkHandleGetFileServerEndpoints)
  348. router.HandleFunc("/system/network/server/status", NetworkHandleGetFileServerStatus)
  349. adminRouter.HandleFunc("/system/network/server/toggle", NetworkHandleFileServerToggle)
  350. }
  351. // Toggle the target File Server Services
  352. func NetworkHandleFileServerToggle(w http.ResponseWriter, r *http.Request) {
  353. servid, err := utils.PostPara(r, "id")
  354. if err != nil {
  355. utils.SendErrorResponse(w, "invalid service id given")
  356. return
  357. }
  358. newState, err := utils.PostPara(r, "enable")
  359. if err != nil {
  360. utils.SendErrorResponse(w, "undefined enable state")
  361. return
  362. }
  363. targetfserv := fileservers.GetFileServerById(networkFileServerDaemon, servid)
  364. if targetfserv == nil {
  365. utils.SendErrorResponse(w, "target service not exists")
  366. return
  367. }
  368. if newState == "true" {
  369. //Start up the target service
  370. err = targetfserv.ToggleFunc(true)
  371. if err != nil {
  372. utils.SendErrorResponse(w, "startup failed: "+err.Error())
  373. return
  374. }
  375. } else if newState == "false" {
  376. err = targetfserv.ToggleFunc(false)
  377. if err != nil {
  378. utils.SendErrorResponse(w, "shutdown failed: "+err.Error())
  379. return
  380. }
  381. } else {
  382. utils.SendErrorResponse(w, "unknown state keyword")
  383. return
  384. }
  385. }
  386. // Return a list of supported File Server Services
  387. func NetworkHandleGetFileServerServiceList(w http.ResponseWriter, r *http.Request) {
  388. js, _ := json.Marshal(networkFileServerDaemon)
  389. utils.SendJSONResponse(w, string(js))
  390. }
  391. // Get the status of a file server type.
  392. func NetworkHandleGetFileServerStatus(w http.ResponseWriter, r *http.Request) {
  393. servid, _ := utils.GetPara(r, "id")
  394. if servid == "" {
  395. //List all state in map
  396. result := map[string]bool{}
  397. for _, fserv := range networkFileServerDaemon {
  398. result[fserv.ID] = fserv.EnableCheck()
  399. }
  400. js, _ := json.Marshal(result)
  401. utils.SendJSONResponse(w, string(js))
  402. } else {
  403. //ID is defined. Get the target server and return its status
  404. targetfserv := fileservers.GetFileServerById(networkFileServerDaemon, servid)
  405. if targetfserv == nil {
  406. utils.SendErrorResponse(w, "target file server type not found")
  407. return
  408. }
  409. js, _ := json.Marshal(targetfserv.EnableCheck())
  410. utils.SendJSONResponse(w, string(js))
  411. }
  412. }
  413. // Get a list of endpoint usable by this service
  414. func NetworkHandleGetFileServerEndpoints(w http.ResponseWriter, r *http.Request) {
  415. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  416. if err != nil {
  417. utils.SendErrorResponse(w, "user not logged in")
  418. return
  419. }
  420. targetServerTypeID, _ := utils.GetPara(r, "fserv")
  421. targetServerTypeID = strings.TrimSpace(targetServerTypeID)
  422. if targetServerTypeID == "" {
  423. //List all the endpoints
  424. results := map[string][]*fileservers.Endpoint{}
  425. for _, fser := range networkFileServerDaemon {
  426. if fser.GetEndpoints == nil {
  427. results[fser.ID] = []*fileservers.Endpoint{}
  428. continue
  429. }
  430. thisEndpoints := fser.GetEndpoints(userinfo)
  431. results[fser.ID] = thisEndpoints
  432. }
  433. js, _ := json.Marshal(results)
  434. utils.SendJSONResponse(w, string(js))
  435. } else {
  436. //List the target endpoint
  437. for _, fser := range networkFileServerDaemon {
  438. if targetServerTypeID == fser.ID {
  439. thisEndpoints := fser.GetEndpoints(userinfo)
  440. js, _ := json.Marshal(thisEndpoints)
  441. utils.SendJSONResponse(w, string(js))
  442. return
  443. }
  444. }
  445. utils.SendErrorResponse(w, "target service not found")
  446. }
  447. }