network.go 16 KB

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