network.go 15 KB

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