directoryHandler.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. package user
  2. import (
  3. "errors"
  4. "os"
  5. "path/filepath"
  6. "strings"
  7. fs "imuslab.com/arozos/mod/filesystem"
  8. )
  9. func (u *User) GetHomeDirectory() (string, error) {
  10. //Return the realpath of the user home directory
  11. for _, dir := range u.HomeDirectories.Storages {
  12. if dir.UUID == "user" {
  13. //This is the target user root
  14. root := filepath.ToSlash(filepath.Clean(dir.Path) + "/users/" + u.Username + "/")
  15. os.MkdirAll(root, 0755)
  16. return root, nil
  17. }
  18. }
  19. return "", errors.New("User root not found. Is this a permission group instead of a real user?")
  20. }
  21. //Get all user Acessible file system handlers (ignore special fsh like backups)
  22. func (u *User) GetAllAccessibleFileSystemHandler() []*fs.FileSystemHandler {
  23. results := []*fs.FileSystemHandler{}
  24. fshs := u.GetAllFileSystemHandler()
  25. for _, fsh := range fshs {
  26. if fsh.Hierarchy != "backup" {
  27. results = append(results, fsh)
  28. }
  29. }
  30. return results
  31. }
  32. func (u *User) GetAllFileSystemHandler() []*fs.FileSystemHandler {
  33. results := []*fs.FileSystemHandler{}
  34. uuids := []string{}
  35. //Get all FileSystem Handler from this user's Home Directory (aka base directory)
  36. for _, store := range u.HomeDirectories.Storages {
  37. if store.Closed == false {
  38. //Only return opened file system handlers
  39. results = append(results, store)
  40. uuids = append(uuids, store.UUID)
  41. }
  42. }
  43. //Get all the FileSystem handler that is accessable by this user
  44. for _, pg := range u.PermissionGroup {
  45. //For each permission group that this user is in
  46. for _, store := range pg.StoragePool.Storages {
  47. //Get each of the storage of this permission group is assigned to
  48. if !inSlice(uuids, store.UUID) {
  49. if store.Closed == false {
  50. //Only return opened file system handlers
  51. results = append(results, store)
  52. uuids = append(uuids, store.UUID)
  53. }
  54. }
  55. }
  56. }
  57. return results
  58. }
  59. func (u *User) VirtualPathToRealPath(vpath string) (string, error) {
  60. //Get all usable filesystem handler from the user's home directory and permission groups
  61. userFsHandlers := u.GetAllFileSystemHandler()
  62. //Clear the path
  63. virtualPath := filepath.ToSlash(filepath.Clean(vpath))
  64. //Check for path escape
  65. if len(virtualPath) > 2 && virtualPath[:2] == ".." {
  66. return "", errors.New("Request path out of storage root")
  67. }
  68. //Check for valid virtual device id
  69. vid, subpath, err := getIDFromVirtualPath(vpath)
  70. if err != nil {
  71. return "", err
  72. }
  73. if strings.Contains(filepath.ToSlash(filepath.Clean(subpath)), "../") || filepath.Clean(subpath) == ".." {
  74. return "", errors.New("Request path out of storage root")
  75. }
  76. //Look for the handler with the same virtualPath ID
  77. for _, storage := range userFsHandlers {
  78. if storage.UUID == vid {
  79. //This storage is the one we are looking at
  80. //Check if this has been closed
  81. if storage.Closed == true {
  82. return "", errors.New("Request Filesystem Handler has been closed by another process")
  83. }
  84. //Check if this is a backup drive
  85. if storage.Hierarchy == "backup" {
  86. return "", errors.New("Request Filesystem Handler do not allow direct access")
  87. }
  88. //A bit hacky to make sure subpath contains no traversal
  89. //Will migrate this to File System Vpath Resolver in the next large update
  90. subpath = strings.ReplaceAll(subpath, "..", "")
  91. //Handle general cases
  92. if storage.Hierarchy == "user" {
  93. return filepath.ToSlash(filepath.Join(filepath.Clean(storage.Path), "/users/", u.Username, subpath)), nil
  94. } else if storage.Hierarchy == "public" {
  95. return filepath.ToSlash(filepath.Join(filepath.Clean(storage.Path), subpath)), nil
  96. } else if storage.Hierarchy == "share" {
  97. return (*u.parent.shareEntryTable).ResolveShareVrootPath(subpath, u.Username, u.GetUserPermissionGroupNames())
  98. } else {
  99. return "", errors.New("Unknown Filesystem Handler Hierarchy")
  100. }
  101. }
  102. }
  103. return "", errors.New("Translation failed: Vitrual storage ID not found")
  104. }
  105. func (u *User) RealPathToVirtualPath(rpath string) (string, error) {
  106. //Get all usable filesystem handler
  107. userFsHandlers := u.GetAllFileSystemHandler()
  108. //Clear the path
  109. realPath := filepath.ToSlash(filepath.Clean(rpath))
  110. //Check for path escape
  111. if len(realPath) > 2 && realPath[:2] == ".." {
  112. //Fix: 20 May 2021: Allow using ../folder as virtual root directory
  113. //Check if there are vroots that actually use relative path as root directory.
  114. allowSpecialCasePassThrough := false
  115. for _, fsh := range userFsHandlers {
  116. thisVrootPath := fsh.Path
  117. if len(realPath) > len(thisVrootPath) && filepath.ToSlash(realPath[:len(thisVrootPath)]) == filepath.ToSlash(thisVrootPath) {
  118. allowSpecialCasePassThrough = true
  119. }
  120. }
  121. if !allowSpecialCasePassThrough {
  122. return "", errors.New("Request path out of storage root")
  123. }
  124. }
  125. //Look for a real path of a virtual device that the realpath is containing
  126. for _, storage := range userFsHandlers {
  127. thisStorageRoot := filepath.Clean(filepath.ToSlash(storage.Path))
  128. thisStorageRootAbs, err := filepath.Abs(thisStorageRoot)
  129. if err != nil {
  130. //Fail to abs this path. Maybe this is a emulated file system?
  131. thisStorageRootAbs = thisStorageRoot
  132. }
  133. thisStorageRootAbs = filepath.ToSlash(filepath.Clean(thisStorageRootAbs))
  134. pathContained := false
  135. subPath := ""
  136. if len(realPath) > len(thisStorageRoot) && filepath.ToSlash(realPath[:len(thisStorageRoot)]) == filepath.ToSlash(thisStorageRoot) {
  137. //This realpath is in contained inside this storage root
  138. pathContained = true
  139. subtractionPath := thisStorageRoot
  140. if storage.Hierarchy == "user" {
  141. //Check if this file is belongs to this user
  142. startOffset := len(filepath.Clean(thisStorageRoot) + "/users/")
  143. if len(realPath) < startOffset+len(u.Username) {
  144. //This file is not owned by this user
  145. return "", errors.New("File not owned by this user")
  146. } else {
  147. userNameMatch := realPath[startOffset : startOffset+len(u.Username)]
  148. if userNameMatch != u.Username {
  149. //This file is not owned by this user
  150. return "", errors.New("File not owned by this user")
  151. }
  152. }
  153. //Generate subtraction path
  154. subtractionPath = thisStorageRoot + "/users/" + u.Username + "/"
  155. }
  156. if len(subtractionPath) < len(realPath) {
  157. subPath = realPath[len(subtractionPath):]
  158. }
  159. } else if len(realPath) > len(thisStorageRootAbs) && filepath.ToSlash(realPath[:len(thisStorageRootAbs)]) == filepath.ToSlash(thisStorageRootAbs) {
  160. //The realpath contains the absolute path of this storage root
  161. pathContained = true
  162. subtractionPath := thisStorageRootAbs
  163. if storage.Hierarchy == "user" {
  164. subtractionPath = thisStorageRootAbs + "/users/" + u.Username + "/"
  165. }
  166. if len(subtractionPath) < len(realPath) {
  167. subPath = realPath[len(subtractionPath):]
  168. }
  169. } else if filepath.ToSlash(realPath) == filepath.ToSlash(thisStorageRoot) {
  170. //Storage Root's root
  171. pathContained = true
  172. subPath = ""
  173. }
  174. if len(subPath) > 1 && subPath[:1] == "/" {
  175. subPath = subPath[1:]
  176. }
  177. if pathContained == true {
  178. //This storage is one of the root of the given realpath. Translate it into this
  179. if storage.Closed == true {
  180. return "", errors.New("Request Filesystem Handler has been closed by another process")
  181. }
  182. return storage.UUID + ":/" + subPath, nil
  183. }
  184. }
  185. return "", errors.New("Unable to resolve realpath in virtual devices root path")
  186. }
  187. //Get a file system handler from a virtual path, this file system handler might not be the highest prioity one
  188. func (u *User) GetFileSystemHandlerFromVirtualPath(vpath string) (*fs.FileSystemHandler, error) {
  189. fsHandlers := u.GetAllFileSystemHandler()
  190. handler, err := getHandlerFromVirtualPath(fsHandlers, vpath)
  191. return handler, err
  192. }
  193. func (u *User) GetFileSystemHandlerFromRealPath(rpath string) (*fs.FileSystemHandler, error) {
  194. vpath, err := u.RealPathToVirtualPath(rpath)
  195. if err != nil {
  196. return &fs.FileSystemHandler{}, err
  197. }
  198. return u.GetFileSystemHandlerFromVirtualPath(vpath)
  199. }