network.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. package main
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "strconv"
  6. "strings"
  7. "imuslab.com/arozos/mod/common"
  8. "imuslab.com/arozos/mod/fileservers"
  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/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. common.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. common.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. common.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. UserManager: userHandler,
  254. KeyFile: "system/auth/id_rsa.key",
  255. Logger: systemWideLogger,
  256. Sysdb: sysdb,
  257. })
  258. //Register Endpoints
  259. //WebDAV
  260. http.HandleFunc("/system/network/webdav/list", WebDAVManager.HandleConnectionList)
  261. router.HandleFunc("/system/network/webdav/edit", WebDAVManager.HandlePermissionEdit)
  262. router.HandleFunc("/system/network/webdav/clear", WebDAVManager.HandleClearAllPending)
  263. router.HandleFunc("/system/network/webdav/status", WebDAVManager.HandleStatusChange)
  264. //FTP
  265. //adminRouter.HandleFunc("/system/storage/ftp/start", FTPManager.HandleFTPServerStart)
  266. //adminRouter.HandleFunc("/system/storage/ftp/stop", FTPManager.HandleFTPServerStop)
  267. adminRouter.HandleFunc("/system/storage/ftp/upnp", FTPManager.HandleFTPUPnP)
  268. adminRouter.HandleFunc("/system/storage/ftp/status", FTPManager.HandleFTPServerStatus)
  269. adminRouter.HandleFunc("/system/storage/ftp/updateGroups", FTPManager.HandleFTPAccessUpdate)
  270. adminRouter.HandleFunc("/system/storage/ftp/setPort", FTPManager.HandleFTPSetPort)
  271. adminRouter.HandleFunc("/system/storage/ftp/passivemode", FTPManager.HandleFTPPassiveModeSettings)
  272. networkFileServerDaemon = append(networkFileServerDaemon, &fileservers.Server{
  273. ID: "webdav",
  274. Name: "WebDAV",
  275. Desc: "WebDAV Server",
  276. IconPath: "img/system/network-folder-blue.svg",
  277. DefaultPorts: []int{},
  278. Ports: []int{},
  279. ForwardPortIfUpnp: false,
  280. ConnInstrPage: "SystemAO/disk/instr/webdav.html",
  281. ConfigPage: "SystemAO/disk/webdav.html",
  282. EnableCheck: WebDAVManager.GetWebDavEnabled,
  283. ToggleFunc: WebDAVManager.WebDavToogle,
  284. GetEndpoints: WebDAVManager.WebDavGetEndpoints,
  285. })
  286. networkFileServerDaemon = append(networkFileServerDaemon, &fileservers.Server{
  287. ID: "sftp",
  288. Name: "SFTP",
  289. Desc: "SSH File Transfer Protocol Server",
  290. IconPath: "img/system/network-folder-sftp.svg",
  291. DefaultPorts: []int{2022},
  292. Ports: []int{},
  293. ForwardPortIfUpnp: true,
  294. ConnInstrPage: "SystemAO/disk/instr/sftp.html",
  295. ConfigPage: "SystemAO/disk/sftp.html",
  296. EnableCheck: SFTPManager.IsEnabled,
  297. ToggleFunc: SFTPManager.ServerToggle,
  298. GetEndpoints: SFTPManager.GetEndpoints,
  299. })
  300. networkFileServerDaemon = append(networkFileServerDaemon, &fileservers.Server{
  301. ID: "ftp",
  302. Name: "FTP",
  303. Desc: "File Transfer Protocol Server",
  304. IconPath: "img/system/network-folder.svg",
  305. DefaultPorts: []int{21, 22, 23},
  306. Ports: []int{},
  307. ForwardPortIfUpnp: true,
  308. ConnInstrPage: "SystemAO/disk/instr/ftp.html",
  309. ConfigPage: "SystemAO/disk/ftp.html",
  310. EnableCheck: FTPManager.IsFtpServerEnabled,
  311. ToggleFunc: FTPManager.FTPServerToggle,
  312. GetEndpoints: FTPManager.FTPGetEndpoints,
  313. })
  314. router.HandleFunc("/system/network/server/list", NetworkHandleGetFileServerServiceList)
  315. router.HandleFunc("/system/network/server/endpoints", NetworkHandleGetFileServerEndpoints)
  316. router.HandleFunc("/system/network/server/status", NetworkHandleGetFileServerStatus)
  317. adminRouter.HandleFunc("/system/network/server/toggle", NetworkHandleFileServerToggle)
  318. }
  319. //Toggle the target File Server Services
  320. func NetworkHandleFileServerToggle(w http.ResponseWriter, r *http.Request) {
  321. servid, err := common.Mv(r, "id", true)
  322. if err != nil {
  323. common.SendErrorResponse(w, "invalid service id given")
  324. return
  325. }
  326. newState, err := common.Mv(r, "enable", true)
  327. if err != nil {
  328. common.SendErrorResponse(w, "undefined enable state")
  329. return
  330. }
  331. targetfserv := fileservers.GetFileServerById(networkFileServerDaemon, servid)
  332. if targetfserv == nil {
  333. common.SendErrorResponse(w, "target service not exists")
  334. return
  335. }
  336. if newState == "true" {
  337. //Start up the target service
  338. err = targetfserv.ToggleFunc(true)
  339. if err != nil {
  340. common.SendErrorResponse(w, "startup failed: "+err.Error())
  341. return
  342. }
  343. } else if newState == "false" {
  344. err = targetfserv.ToggleFunc(false)
  345. if err != nil {
  346. common.SendErrorResponse(w, "shutdown failed: "+err.Error())
  347. return
  348. }
  349. } else {
  350. common.SendErrorResponse(w, "unknown state keyword")
  351. return
  352. }
  353. }
  354. //Return a list of supported File Server Services
  355. func NetworkHandleGetFileServerServiceList(w http.ResponseWriter, r *http.Request) {
  356. js, _ := json.Marshal(networkFileServerDaemon)
  357. common.SendJSONResponse(w, string(js))
  358. }
  359. //Get the status of a file server type.
  360. func NetworkHandleGetFileServerStatus(w http.ResponseWriter, r *http.Request) {
  361. servid, _ := common.Mv(r, "id", false)
  362. if servid == "" {
  363. //List all state in map
  364. result := map[string]bool{}
  365. for _, fserv := range networkFileServerDaemon {
  366. result[fserv.ID] = fserv.EnableCheck()
  367. }
  368. js, _ := json.Marshal(result)
  369. common.SendJSONResponse(w, string(js))
  370. } else {
  371. //ID is defined. Get the target server and return its status
  372. targetfserv := fileservers.GetFileServerById(networkFileServerDaemon, servid)
  373. if targetfserv == nil {
  374. common.SendErrorResponse(w, "target file server type not found")
  375. return
  376. }
  377. js, _ := json.Marshal(targetfserv.EnableCheck())
  378. common.SendJSONResponse(w, string(js))
  379. }
  380. }
  381. //Get a list of endpoint usable by this service
  382. func NetworkHandleGetFileServerEndpoints(w http.ResponseWriter, r *http.Request) {
  383. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  384. if err != nil {
  385. common.SendErrorResponse(w, "user not logged in")
  386. return
  387. }
  388. targetServerTypeID, _ := common.Mv(r, "fserv", false)
  389. targetServerTypeID = strings.TrimSpace(targetServerTypeID)
  390. if targetServerTypeID == "" {
  391. //List all the endpoints
  392. results := map[string][]*fileservers.Endpoint{}
  393. for _, fser := range networkFileServerDaemon {
  394. if fser.GetEndpoints == nil {
  395. results[fser.ID] = []*fileservers.Endpoint{}
  396. continue
  397. }
  398. thisEndpoints := fser.GetEndpoints(userinfo)
  399. results[fser.ID] = thisEndpoints
  400. }
  401. js, _ := json.Marshal(results)
  402. common.SendJSONResponse(w, string(js))
  403. } else {
  404. //List the target endpoint
  405. for _, fser := range networkFileServerDaemon {
  406. if targetServerTypeID == fser.ID {
  407. thisEndpoints := fser.GetEndpoints(userinfo)
  408. js, _ := json.Marshal(thisEndpoints)
  409. common.SendJSONResponse(w, string(js))
  410. return
  411. }
  412. }
  413. common.SendErrorResponse(w, "target service not found")
  414. }
  415. }