user.go 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482
  1. package dataprovider
  2. import (
  3. "crypto/sha256"
  4. "encoding/base64"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "math"
  9. "net"
  10. "os"
  11. "path"
  12. "path/filepath"
  13. "strings"
  14. "time"
  15. "github.com/sftpgo/sdk"
  16. "github.com/drakkan/sftpgo/v2/kms"
  17. "github.com/drakkan/sftpgo/v2/logger"
  18. "github.com/drakkan/sftpgo/v2/mfa"
  19. "github.com/drakkan/sftpgo/v2/plugin"
  20. "github.com/drakkan/sftpgo/v2/util"
  21. "github.com/drakkan/sftpgo/v2/vfs"
  22. )
  23. // Available permissions for SFTPGo users
  24. const (
  25. // All permissions are granted
  26. PermAny = "*"
  27. // List items such as files and directories is allowed
  28. PermListItems = "list"
  29. // download files is allowed
  30. PermDownload = "download"
  31. // upload files is allowed
  32. PermUpload = "upload"
  33. // overwrite an existing file, while uploading, is allowed
  34. // upload permission is required to allow file overwrite
  35. PermOverwrite = "overwrite"
  36. // delete files or directories is allowed
  37. PermDelete = "delete"
  38. // delete files is allowed
  39. PermDeleteFiles = "delete_files"
  40. // delete directories is allowed
  41. PermDeleteDirs = "delete_dirs"
  42. // rename files or directories is allowed
  43. PermRename = "rename"
  44. // rename files is allowed
  45. PermRenameFiles = "rename_files"
  46. // rename directories is allowed
  47. PermRenameDirs = "rename_dirs"
  48. // create directories is allowed
  49. PermCreateDirs = "create_dirs"
  50. // create symbolic links is allowed
  51. PermCreateSymlinks = "create_symlinks"
  52. // changing file or directory permissions is allowed
  53. PermChmod = "chmod"
  54. // changing file or directory owner and group is allowed
  55. PermChown = "chown"
  56. // changing file or directory access and modification time is allowed
  57. PermChtimes = "chtimes"
  58. )
  59. // Available login methods
  60. const (
  61. LoginMethodNoAuthTryed = "no_auth_tryed"
  62. LoginMethodPassword = "password"
  63. SSHLoginMethodPublicKey = "publickey"
  64. SSHLoginMethodKeyboardInteractive = "keyboard-interactive"
  65. SSHLoginMethodKeyAndPassword = "publickey+password"
  66. SSHLoginMethodKeyAndKeyboardInt = "publickey+keyboard-interactive"
  67. LoginMethodTLSCertificate = "TLSCertificate"
  68. LoginMethodTLSCertificateAndPwd = "TLSCertificate+password"
  69. LoginMethodIDP = "IDP"
  70. )
  71. var (
  72. errNoMatchingVirtualFolder = errors.New("no matching virtual folder found")
  73. permsRenameAny = []string{PermRename, PermRenameDirs, PermRenameFiles}
  74. permsDeleteAny = []string{PermDelete, PermDeleteDirs, PermDeleteFiles}
  75. )
  76. // RecoveryCode defines a 2FA recovery code
  77. type RecoveryCode struct {
  78. Secret *kms.Secret `json:"secret"`
  79. Used bool `json:"used,omitempty"`
  80. }
  81. // UserTOTPConfig defines the time-based one time password configuration
  82. type UserTOTPConfig struct {
  83. Enabled bool `json:"enabled,omitempty"`
  84. ConfigName string `json:"config_name,omitempty"`
  85. Secret *kms.Secret `json:"secret,omitempty"`
  86. // TOTP will be required for the specified protocols.
  87. // SSH protocol (SFTP/SCP/SSH commands) will ask for the TOTP passcode if the client uses keyboard interactive
  88. // authentication.
  89. // FTP have no standard way to support two factor authentication, if you
  90. // enable the support for this protocol you have to add the TOTP passcode after the password.
  91. // For example if your password is "password" and your one time passcode is
  92. // "123456" you have to use "password123456" as password.
  93. Protocols []string `json:"protocols,omitempty"`
  94. }
  95. // UserFilters defines additional restrictions for a user
  96. // TODO: rename to UserOptions in v3
  97. type UserFilters struct {
  98. sdk.BaseUserFilters
  99. // Time-based one time passwords configuration
  100. TOTPConfig UserTOTPConfig `json:"totp_config,omitempty"`
  101. // Recovery codes to use if the user loses access to their second factor auth device.
  102. // Each code can only be used once, you should use these codes to login and disable or
  103. // reset 2FA for your account
  104. RecoveryCodes []RecoveryCode `json:"recovery_codes,omitempty"`
  105. }
  106. // User defines a SFTPGo user
  107. type User struct {
  108. sdk.BaseUser
  109. // Additional restrictions
  110. Filters UserFilters `json:"filters"`
  111. // Mapping between virtual paths and virtual folders
  112. VirtualFolders []vfs.VirtualFolder `json:"virtual_folders,omitempty"`
  113. // Filesystem configuration details
  114. FsConfig vfs.Filesystem `json:"filesystem"`
  115. // we store the filesystem here using the base path as key.
  116. fsCache map[string]vfs.Fs `json:"-"`
  117. }
  118. // GetFilesystem returns the base filesystem for this user
  119. func (u *User) GetFilesystem(connectionID string) (fs vfs.Fs, err error) {
  120. fs, err = u.getRootFs(connectionID)
  121. if err != nil {
  122. return fs, err
  123. }
  124. u.fsCache = make(map[string]vfs.Fs)
  125. u.fsCache["/"] = fs
  126. return fs, err
  127. }
  128. func (u *User) getRootFs(connectionID string) (fs vfs.Fs, err error) {
  129. switch u.FsConfig.Provider {
  130. case sdk.S3FilesystemProvider:
  131. return vfs.NewS3Fs(connectionID, u.GetHomeDir(), "", u.FsConfig.S3Config)
  132. case sdk.GCSFilesystemProvider:
  133. config := u.FsConfig.GCSConfig
  134. config.CredentialFile = u.GetGCSCredentialsFilePath()
  135. return vfs.NewGCSFs(connectionID, u.GetHomeDir(), "", config)
  136. case sdk.AzureBlobFilesystemProvider:
  137. return vfs.NewAzBlobFs(connectionID, u.GetHomeDir(), "", u.FsConfig.AzBlobConfig)
  138. case sdk.CryptedFilesystemProvider:
  139. return vfs.NewCryptFs(connectionID, u.GetHomeDir(), "", u.FsConfig.CryptConfig)
  140. case sdk.SFTPFilesystemProvider:
  141. forbiddenSelfUsers, err := u.getForbiddenSFTPSelfUsers(u.FsConfig.SFTPConfig.Username)
  142. if err != nil {
  143. return nil, err
  144. }
  145. forbiddenSelfUsers = append(forbiddenSelfUsers, u.Username)
  146. return vfs.NewSFTPFs(connectionID, "", u.GetHomeDir(), forbiddenSelfUsers, u.FsConfig.SFTPConfig)
  147. default:
  148. return vfs.NewOsFs(connectionID, u.GetHomeDir(), ""), nil
  149. }
  150. }
  151. func (u *User) checkDirWithParents(virtualDirPath, connectionID string) error {
  152. dirs := util.GetDirsForVirtualPath(virtualDirPath)
  153. for idx := len(dirs) - 1; idx >= 0; idx-- {
  154. vPath := dirs[idx]
  155. if vPath == "/" {
  156. continue
  157. }
  158. fs, err := u.GetFilesystemForPath(vPath, connectionID)
  159. if err != nil {
  160. return fmt.Errorf("unable to get fs for path %#v: %w", vPath, err)
  161. }
  162. if fs.HasVirtualFolders() {
  163. continue
  164. }
  165. fsPath, err := fs.ResolvePath(vPath)
  166. if err != nil {
  167. return fmt.Errorf("unable to resolve path %#v: %w", vPath, err)
  168. }
  169. _, err = fs.Stat(fsPath)
  170. if err == nil {
  171. continue
  172. }
  173. if fs.IsNotExist(err) {
  174. err = fs.Mkdir(fsPath)
  175. if err != nil {
  176. return err
  177. }
  178. vfs.SetPathPermissions(fs, fsPath, u.GetUID(), u.GetGID())
  179. } else {
  180. return fmt.Errorf("unable to stat path %#v: %w", vPath, err)
  181. }
  182. }
  183. return nil
  184. }
  185. // CheckFsRoot check the root directory for the main fs and the virtual folders.
  186. // It returns an error if the main filesystem cannot be created
  187. func (u *User) CheckFsRoot(connectionID string) error {
  188. if u.Filters.DisableFsChecks {
  189. return nil
  190. }
  191. delay := lastLoginMinDelay
  192. if u.Filters.ExternalAuthCacheTime > 0 {
  193. cacheTime := time.Duration(u.Filters.ExternalAuthCacheTime) * time.Second
  194. if cacheTime > delay {
  195. delay = cacheTime
  196. }
  197. }
  198. if isLastActivityRecent(u.LastLogin, delay) {
  199. return nil
  200. }
  201. fs, err := u.GetFilesystemForPath("/", connectionID)
  202. if err != nil {
  203. logger.Warn(logSender, connectionID, "could not create main filesystem for user %#v err: %v", u.Username, err)
  204. return err
  205. }
  206. fs.CheckRootPath(u.Username, u.GetUID(), u.GetGID())
  207. for idx := range u.VirtualFolders {
  208. v := &u.VirtualFolders[idx]
  209. fs, err = u.GetFilesystemForPath(v.VirtualPath, connectionID)
  210. if err == nil {
  211. fs.CheckRootPath(u.Username, u.GetUID(), u.GetGID())
  212. }
  213. // now check intermediary folders
  214. err = u.checkDirWithParents(path.Dir(v.VirtualPath), connectionID)
  215. if err != nil {
  216. logger.Warn(logSender, connectionID, "could not create intermediary dir to %#v, err: %v", v.VirtualPath, err)
  217. }
  218. }
  219. return nil
  220. }
  221. // isFsEqual returns true if the fs has the same configuration
  222. func (u *User) isFsEqual(other *User) bool {
  223. if u.FsConfig.Provider == sdk.LocalFilesystemProvider && u.GetHomeDir() != other.GetHomeDir() {
  224. return false
  225. }
  226. if !u.FsConfig.IsEqual(&other.FsConfig) {
  227. return false
  228. }
  229. if len(u.VirtualFolders) != len(other.VirtualFolders) {
  230. return false
  231. }
  232. for idx := range u.VirtualFolders {
  233. f := &u.VirtualFolders[idx]
  234. found := false
  235. for idx1 := range other.VirtualFolders {
  236. f1 := &other.VirtualFolders[idx1]
  237. if f.VirtualPath == f1.VirtualPath {
  238. found = true
  239. if f.FsConfig.Provider == sdk.LocalFilesystemProvider && f.MappedPath != f1.MappedPath {
  240. return false
  241. }
  242. if !f.FsConfig.IsEqual(&f1.FsConfig) {
  243. return false
  244. }
  245. }
  246. }
  247. if !found {
  248. return false
  249. }
  250. }
  251. return true
  252. }
  253. // CheckLoginConditions checks if the user is active and not expired
  254. func (u *User) CheckLoginConditions() error {
  255. if u.Status < 1 {
  256. return fmt.Errorf("user %#v is disabled", u.Username)
  257. }
  258. if u.ExpirationDate > 0 && u.ExpirationDate < util.GetTimeAsMsSinceEpoch(time.Now()) {
  259. return fmt.Errorf("user %#v is expired, expiration timestamp: %v current timestamp: %v", u.Username,
  260. u.ExpirationDate, util.GetTimeAsMsSinceEpoch(time.Now()))
  261. }
  262. return nil
  263. }
  264. // hideConfidentialData hides user confidential data
  265. func (u *User) hideConfidentialData() {
  266. u.Password = ""
  267. u.FsConfig.HideConfidentialData()
  268. if u.Filters.TOTPConfig.Secret != nil {
  269. u.Filters.TOTPConfig.Secret.Hide()
  270. }
  271. for _, code := range u.Filters.RecoveryCodes {
  272. if code.Secret != nil {
  273. code.Secret.Hide()
  274. }
  275. }
  276. }
  277. // GetSubDirPermissions returns permissions for sub directories
  278. func (u *User) GetSubDirPermissions() []sdk.DirectoryPermissions {
  279. var result []sdk.DirectoryPermissions
  280. for k, v := range u.Permissions {
  281. if k == "/" {
  282. continue
  283. }
  284. dirPerms := sdk.DirectoryPermissions{
  285. Path: k,
  286. Permissions: v,
  287. }
  288. result = append(result, dirPerms)
  289. }
  290. return result
  291. }
  292. // RenderAsJSON implements the renderer interface used within plugins
  293. func (u *User) RenderAsJSON(reload bool) ([]byte, error) {
  294. if reload {
  295. user, err := provider.userExists(u.Username)
  296. if err != nil {
  297. providerLog(logger.LevelError, "unable to reload user before rendering as json: %v", err)
  298. return nil, err
  299. }
  300. user.PrepareForRendering()
  301. return json.Marshal(user)
  302. }
  303. u.PrepareForRendering()
  304. return json.Marshal(u)
  305. }
  306. // PrepareForRendering prepares a user for rendering.
  307. // It hides confidential data and set to nil the empty secrets
  308. // so they are not serialized
  309. func (u *User) PrepareForRendering() {
  310. u.hideConfidentialData()
  311. u.FsConfig.SetNilSecretsIfEmpty()
  312. for idx := range u.VirtualFolders {
  313. folder := &u.VirtualFolders[idx]
  314. folder.PrepareForRendering()
  315. }
  316. }
  317. // HasRedactedSecret returns true if the user has a redacted secret
  318. func (u *User) hasRedactedSecret() bool {
  319. if u.FsConfig.HasRedactedSecret() {
  320. return true
  321. }
  322. for idx := range u.VirtualFolders {
  323. folder := &u.VirtualFolders[idx]
  324. if folder.HasRedactedSecret() {
  325. return true
  326. }
  327. }
  328. return u.Filters.TOTPConfig.Secret.IsRedacted()
  329. }
  330. // CloseFs closes the underlying filesystems
  331. func (u *User) CloseFs() error {
  332. if u.fsCache == nil {
  333. return nil
  334. }
  335. var err error
  336. for _, fs := range u.fsCache {
  337. errClose := fs.Close()
  338. if err == nil {
  339. err = errClose
  340. }
  341. }
  342. return err
  343. }
  344. // IsPasswordHashed returns true if the password is hashed
  345. func (u *User) IsPasswordHashed() bool {
  346. return util.IsStringPrefixInSlice(u.Password, hashPwdPrefixes)
  347. }
  348. // IsTLSUsernameVerificationEnabled returns true if we need to extract the username
  349. // from the client TLS certificate
  350. func (u *User) IsTLSUsernameVerificationEnabled() bool {
  351. if u.Filters.TLSUsername != "" {
  352. return u.Filters.TLSUsername != sdk.TLSUsernameNone
  353. }
  354. return false
  355. }
  356. // SetEmptySecrets sets to empty any user secret
  357. func (u *User) SetEmptySecrets() {
  358. u.FsConfig.SetEmptySecrets()
  359. for idx := range u.VirtualFolders {
  360. folder := &u.VirtualFolders[idx]
  361. folder.FsConfig.SetEmptySecrets()
  362. }
  363. u.Filters.TOTPConfig.Secret = kms.NewEmptySecret()
  364. }
  365. // GetPermissionsForPath returns the permissions for the given path.
  366. // The path must be a SFTPGo exposed path
  367. func (u *User) GetPermissionsForPath(p string) []string {
  368. permissions := []string{}
  369. if perms, ok := u.Permissions["/"]; ok {
  370. // if only root permissions are defined returns them unconditionally
  371. if len(u.Permissions) == 1 {
  372. return perms
  373. }
  374. // fallback permissions
  375. permissions = perms
  376. }
  377. dirsForPath := util.GetDirsForVirtualPath(p)
  378. // dirsForPath contains all the dirs for a given path in reverse order
  379. // for example if the path is: /1/2/3/4 it contains:
  380. // [ "/1/2/3/4", "/1/2/3", "/1/2", "/1", "/" ]
  381. // so the first match is the one we are interested to
  382. for idx := range dirsForPath {
  383. if perms, ok := u.Permissions[dirsForPath[idx]]; ok {
  384. permissions = perms
  385. break
  386. }
  387. }
  388. return permissions
  389. }
  390. // HasBufferedSFTP returns true if the user has a SFTP filesystem with buffering enabled
  391. func (u *User) HasBufferedSFTP(name string) bool {
  392. fs := u.GetFsConfigForPath(name)
  393. if fs.Provider == sdk.SFTPFilesystemProvider {
  394. return fs.SFTPConfig.BufferSize > 0
  395. }
  396. return false
  397. }
  398. func (u *User) getForbiddenSFTPSelfUsers(username string) ([]string, error) {
  399. sftpUser, err := UserExists(username)
  400. if err == nil {
  401. // we don't allow local nested SFTP folders
  402. var forbiddens []string
  403. if sftpUser.FsConfig.Provider == sdk.SFTPFilesystemProvider {
  404. forbiddens = append(forbiddens, sftpUser.Username)
  405. return forbiddens, nil
  406. }
  407. for idx := range sftpUser.VirtualFolders {
  408. v := &sftpUser.VirtualFolders[idx]
  409. if v.FsConfig.Provider == sdk.SFTPFilesystemProvider {
  410. forbiddens = append(forbiddens, sftpUser.Username)
  411. return forbiddens, nil
  412. }
  413. }
  414. return forbiddens, nil
  415. }
  416. if _, ok := err.(*util.RecordNotFoundError); !ok {
  417. return nil, err
  418. }
  419. return nil, nil
  420. }
  421. // GetFsConfigForPath returns the file system configuration for the specified virtual path
  422. func (u *User) GetFsConfigForPath(virtualPath string) vfs.Filesystem {
  423. if virtualPath != "" && virtualPath != "/" && len(u.VirtualFolders) > 0 {
  424. folder, err := u.GetVirtualFolderForPath(virtualPath)
  425. if err == nil {
  426. return folder.FsConfig
  427. }
  428. }
  429. return u.FsConfig
  430. }
  431. // GetFilesystemForPath returns the filesystem for the given path
  432. func (u *User) GetFilesystemForPath(virtualPath, connectionID string) (vfs.Fs, error) {
  433. if u.fsCache == nil {
  434. u.fsCache = make(map[string]vfs.Fs)
  435. }
  436. if virtualPath != "" && virtualPath != "/" && len(u.VirtualFolders) > 0 {
  437. folder, err := u.GetVirtualFolderForPath(virtualPath)
  438. if err == nil {
  439. if fs, ok := u.fsCache[folder.VirtualPath]; ok {
  440. return fs, nil
  441. }
  442. forbiddenSelfUsers := []string{u.Username}
  443. if folder.FsConfig.Provider == sdk.SFTPFilesystemProvider {
  444. forbiddens, err := u.getForbiddenSFTPSelfUsers(folder.FsConfig.SFTPConfig.Username)
  445. if err != nil {
  446. return nil, err
  447. }
  448. forbiddenSelfUsers = append(forbiddenSelfUsers, forbiddens...)
  449. }
  450. fs, err := folder.GetFilesystem(connectionID, forbiddenSelfUsers)
  451. if err == nil {
  452. u.fsCache[folder.VirtualPath] = fs
  453. }
  454. return fs, err
  455. }
  456. }
  457. if val, ok := u.fsCache["/"]; ok {
  458. return val, nil
  459. }
  460. return u.GetFilesystem(connectionID)
  461. }
  462. // GetVirtualFolderForPath returns the virtual folder containing the specified virtual path.
  463. // If the path is not inside a virtual folder an error is returned
  464. func (u *User) GetVirtualFolderForPath(virtualPath string) (vfs.VirtualFolder, error) {
  465. var folder vfs.VirtualFolder
  466. if virtualPath == "/" || len(u.VirtualFolders) == 0 {
  467. return folder, errNoMatchingVirtualFolder
  468. }
  469. dirsForPath := util.GetDirsForVirtualPath(virtualPath)
  470. for index := range dirsForPath {
  471. for idx := range u.VirtualFolders {
  472. v := &u.VirtualFolders[idx]
  473. if v.VirtualPath == dirsForPath[index] {
  474. return *v, nil
  475. }
  476. }
  477. }
  478. return folder, errNoMatchingVirtualFolder
  479. }
  480. // CheckMetadataConsistency checks the consistency between the metadata stored
  481. // in the configured metadata plugin and the filesystem
  482. func (u *User) CheckMetadataConsistency() error {
  483. fs, err := u.getRootFs("")
  484. if err != nil {
  485. return err
  486. }
  487. defer fs.Close()
  488. if err = fs.CheckMetadata(); err != nil {
  489. return err
  490. }
  491. for idx := range u.VirtualFolders {
  492. v := &u.VirtualFolders[idx]
  493. if err = v.CheckMetadataConsistency(); err != nil {
  494. return err
  495. }
  496. }
  497. return nil
  498. }
  499. // ScanQuota scans the user home dir and virtual folders, included in its quota,
  500. // and returns the number of files and their size
  501. func (u *User) ScanQuota() (int, int64, error) {
  502. fs, err := u.getRootFs("")
  503. if err != nil {
  504. return 0, 0, err
  505. }
  506. defer fs.Close()
  507. numFiles, size, err := fs.ScanRootDirContents()
  508. if err != nil {
  509. return numFiles, size, err
  510. }
  511. for idx := range u.VirtualFolders {
  512. v := &u.VirtualFolders[idx]
  513. if !v.IsIncludedInUserQuota() {
  514. continue
  515. }
  516. num, s, err := v.ScanQuota()
  517. if err != nil {
  518. return numFiles, size, err
  519. }
  520. numFiles += num
  521. size += s
  522. }
  523. return numFiles, size, nil
  524. }
  525. // GetVirtualFoldersInPath returns the virtual folders inside virtualPath including
  526. // any parents
  527. func (u *User) GetVirtualFoldersInPath(virtualPath string) map[string]bool {
  528. result := make(map[string]bool)
  529. for idx := range u.VirtualFolders {
  530. v := &u.VirtualFolders[idx]
  531. dirsForPath := util.GetDirsForVirtualPath(v.VirtualPath)
  532. for index := range dirsForPath {
  533. d := dirsForPath[index]
  534. if d == "/" {
  535. continue
  536. }
  537. if path.Dir(d) == virtualPath {
  538. result[d] = true
  539. }
  540. }
  541. }
  542. return result
  543. }
  544. // FilterListDir adds virtual folders and remove hidden items from the given files list
  545. func (u *User) FilterListDir(dirContents []os.FileInfo, virtualPath string) []os.FileInfo {
  546. filter := u.getPatternsFilterForPath(virtualPath)
  547. if len(u.VirtualFolders) == 0 && filter.DenyPolicy != sdk.DenyPolicyHide {
  548. return dirContents
  549. }
  550. vdirs := make(map[string]bool)
  551. for dir := range u.GetVirtualFoldersInPath(virtualPath) {
  552. dirName := path.Base(dir)
  553. if filter.DenyPolicy == sdk.DenyPolicyHide {
  554. if !filter.CheckAllowed(dirName) {
  555. continue
  556. }
  557. }
  558. vdirs[dirName] = true
  559. }
  560. validIdx := 0
  561. for index, fi := range dirContents {
  562. for dir := range vdirs {
  563. if fi.Name() == dir {
  564. if !fi.IsDir() {
  565. fi = vfs.NewFileInfo(dir, true, 0, time.Now(), false)
  566. dirContents[index] = fi
  567. }
  568. delete(vdirs, dir)
  569. }
  570. }
  571. if filter.DenyPolicy == sdk.DenyPolicyHide {
  572. if filter.CheckAllowed(fi.Name()) {
  573. dirContents[validIdx] = fi
  574. validIdx++
  575. }
  576. }
  577. }
  578. if filter.DenyPolicy == sdk.DenyPolicyHide {
  579. for idx := validIdx; idx < len(dirContents); idx++ {
  580. dirContents[idx] = nil
  581. }
  582. dirContents = dirContents[:validIdx]
  583. }
  584. for dir := range vdirs {
  585. fi := vfs.NewFileInfo(dir, true, 0, time.Now(), false)
  586. dirContents = append(dirContents, fi)
  587. }
  588. return dirContents
  589. }
  590. // IsMappedPath returns true if the specified filesystem path has a virtual folder mapping.
  591. // The filesystem path must be cleaned before calling this method
  592. func (u *User) IsMappedPath(fsPath string) bool {
  593. for idx := range u.VirtualFolders {
  594. v := &u.VirtualFolders[idx]
  595. if fsPath == v.MappedPath {
  596. return true
  597. }
  598. }
  599. return false
  600. }
  601. // IsVirtualFolder returns true if the specified virtual path is a virtual folder
  602. func (u *User) IsVirtualFolder(virtualPath string) bool {
  603. for idx := range u.VirtualFolders {
  604. v := &u.VirtualFolders[idx]
  605. if virtualPath == v.VirtualPath {
  606. return true
  607. }
  608. }
  609. return false
  610. }
  611. // HasVirtualFoldersInside returns true if there are virtual folders inside the
  612. // specified virtual path. We assume that path are cleaned
  613. func (u *User) HasVirtualFoldersInside(virtualPath string) bool {
  614. if virtualPath == "/" && len(u.VirtualFolders) > 0 {
  615. return true
  616. }
  617. for idx := range u.VirtualFolders {
  618. v := &u.VirtualFolders[idx]
  619. if len(v.VirtualPath) > len(virtualPath) {
  620. if strings.HasPrefix(v.VirtualPath, virtualPath+"/") {
  621. return true
  622. }
  623. }
  624. }
  625. return false
  626. }
  627. // HasPermissionsInside returns true if the specified virtualPath has no permissions itself and
  628. // no subdirs with defined permissions
  629. func (u *User) HasPermissionsInside(virtualPath string) bool {
  630. for dir := range u.Permissions {
  631. if dir == virtualPath {
  632. return true
  633. } else if len(dir) > len(virtualPath) {
  634. if strings.HasPrefix(dir, virtualPath+"/") {
  635. return true
  636. }
  637. }
  638. }
  639. return false
  640. }
  641. // HasPerm returns true if the user has the given permission or any permission
  642. func (u *User) HasPerm(permission, path string) bool {
  643. perms := u.GetPermissionsForPath(path)
  644. if util.IsStringInSlice(PermAny, perms) {
  645. return true
  646. }
  647. return util.IsStringInSlice(permission, perms)
  648. }
  649. // HasAnyPerm returns true if the user has at least one of the given permissions
  650. func (u *User) HasAnyPerm(permissions []string, path string) bool {
  651. perms := u.GetPermissionsForPath(path)
  652. if util.IsStringInSlice(PermAny, perms) {
  653. return true
  654. }
  655. for _, permission := range permissions {
  656. if util.IsStringInSlice(permission, perms) {
  657. return true
  658. }
  659. }
  660. return false
  661. }
  662. // HasPerms returns true if the user has all the given permissions
  663. func (u *User) HasPerms(permissions []string, path string) bool {
  664. perms := u.GetPermissionsForPath(path)
  665. if util.IsStringInSlice(PermAny, perms) {
  666. return true
  667. }
  668. for _, permission := range permissions {
  669. if !util.IsStringInSlice(permission, perms) {
  670. return false
  671. }
  672. }
  673. return true
  674. }
  675. // HasPermsDeleteAll returns true if the user can delete both files and directories
  676. // for the given path
  677. func (u *User) HasPermsDeleteAll(path string) bool {
  678. perms := u.GetPermissionsForPath(path)
  679. canDeleteFiles := false
  680. canDeleteDirs := false
  681. for _, permission := range perms {
  682. if permission == PermAny || permission == PermDelete {
  683. return true
  684. }
  685. if permission == PermDeleteFiles {
  686. canDeleteFiles = true
  687. }
  688. if permission == PermDeleteDirs {
  689. canDeleteDirs = true
  690. }
  691. }
  692. return canDeleteFiles && canDeleteDirs
  693. }
  694. // HasPermsRenameAll returns true if the user can rename both files and directories
  695. // for the given path
  696. func (u *User) HasPermsRenameAll(path string) bool {
  697. perms := u.GetPermissionsForPath(path)
  698. canRenameFiles := false
  699. canRenameDirs := false
  700. for _, permission := range perms {
  701. if permission == PermAny || permission == PermRename {
  702. return true
  703. }
  704. if permission == PermRenameFiles {
  705. canRenameFiles = true
  706. }
  707. if permission == PermRenameDirs {
  708. canRenameDirs = true
  709. }
  710. }
  711. return canRenameFiles && canRenameDirs
  712. }
  713. // HasNoQuotaRestrictions returns true if no quota restrictions need to be applyed
  714. func (u *User) HasNoQuotaRestrictions(checkFiles bool) bool {
  715. if u.QuotaSize == 0 && (!checkFiles || u.QuotaFiles == 0) {
  716. return true
  717. }
  718. return false
  719. }
  720. // IsLoginMethodAllowed returns true if the specified login method is allowed
  721. func (u *User) IsLoginMethodAllowed(loginMethod string, partialSuccessMethods []string) bool {
  722. if len(u.Filters.DeniedLoginMethods) == 0 {
  723. return true
  724. }
  725. if len(partialSuccessMethods) == 1 {
  726. for _, method := range u.GetNextAuthMethods(partialSuccessMethods, true) {
  727. if method == loginMethod {
  728. return true
  729. }
  730. }
  731. }
  732. if util.IsStringInSlice(loginMethod, u.Filters.DeniedLoginMethods) {
  733. return false
  734. }
  735. return true
  736. }
  737. // GetNextAuthMethods returns the list of authentications methods that
  738. // can continue for multi-step authentication
  739. func (u *User) GetNextAuthMethods(partialSuccessMethods []string, isPasswordAuthEnabled bool) []string {
  740. var methods []string
  741. if len(partialSuccessMethods) != 1 {
  742. return methods
  743. }
  744. if partialSuccessMethods[0] != SSHLoginMethodPublicKey {
  745. return methods
  746. }
  747. for _, method := range u.GetAllowedLoginMethods() {
  748. if method == SSHLoginMethodKeyAndPassword && isPasswordAuthEnabled {
  749. methods = append(methods, LoginMethodPassword)
  750. }
  751. if method == SSHLoginMethodKeyAndKeyboardInt {
  752. methods = append(methods, SSHLoginMethodKeyboardInteractive)
  753. }
  754. }
  755. return methods
  756. }
  757. // IsPartialAuth returns true if the specified login method is a step for
  758. // a multi-step Authentication.
  759. // We support publickey+password and publickey+keyboard-interactive, so
  760. // only publickey can returns partial success.
  761. // We can have partial success if only multi-step Auth methods are enabled
  762. func (u *User) IsPartialAuth(loginMethod string) bool {
  763. if loginMethod != SSHLoginMethodPublicKey {
  764. return false
  765. }
  766. for _, method := range u.GetAllowedLoginMethods() {
  767. if method == LoginMethodTLSCertificate || method == LoginMethodTLSCertificateAndPwd {
  768. continue
  769. }
  770. if !util.IsStringInSlice(method, SSHMultiStepsLoginMethods) {
  771. return false
  772. }
  773. }
  774. return true
  775. }
  776. // GetAllowedLoginMethods returns the allowed login methods
  777. func (u *User) GetAllowedLoginMethods() []string {
  778. var allowedMethods []string
  779. for _, method := range ValidLoginMethods {
  780. if !util.IsStringInSlice(method, u.Filters.DeniedLoginMethods) {
  781. allowedMethods = append(allowedMethods, method)
  782. }
  783. }
  784. return allowedMethods
  785. }
  786. // GetFlatFilePatterns returns file patterns as flat list
  787. // duplicating a path if it has both allowed and denied patterns
  788. func (u *User) GetFlatFilePatterns() []sdk.PatternsFilter {
  789. var result []sdk.PatternsFilter
  790. for _, pattern := range u.Filters.FilePatterns {
  791. if len(pattern.AllowedPatterns) > 0 {
  792. result = append(result, sdk.PatternsFilter{
  793. Path: pattern.Path,
  794. AllowedPatterns: pattern.AllowedPatterns,
  795. DenyPolicy: pattern.DenyPolicy,
  796. })
  797. }
  798. if len(pattern.DeniedPatterns) > 0 {
  799. result = append(result, sdk.PatternsFilter{
  800. Path: pattern.Path,
  801. DeniedPatterns: pattern.DeniedPatterns,
  802. DenyPolicy: pattern.DenyPolicy,
  803. })
  804. }
  805. }
  806. return result
  807. }
  808. func (u *User) getPatternsFilterForPath(virtualPath string) sdk.PatternsFilter {
  809. var filter sdk.PatternsFilter
  810. if len(u.Filters.FilePatterns) == 0 {
  811. return filter
  812. }
  813. dirsForPath := util.GetDirsForVirtualPath(virtualPath)
  814. for _, dir := range dirsForPath {
  815. for _, f := range u.Filters.FilePatterns {
  816. if f.Path == dir {
  817. filter = f
  818. break
  819. }
  820. }
  821. if filter.Path != "" {
  822. break
  823. }
  824. }
  825. return filter
  826. }
  827. func (u *User) isDirHidden(virtualPath string) bool {
  828. if len(u.Filters.FilePatterns) == 0 {
  829. return false
  830. }
  831. for _, dirPath := range util.GetDirsForVirtualPath(virtualPath) {
  832. if dirPath == "/" {
  833. return false
  834. }
  835. filter := u.getPatternsFilterForPath(dirPath)
  836. if filter.DenyPolicy == sdk.DenyPolicyHide {
  837. if !filter.CheckAllowed(path.Base(dirPath)) {
  838. return true
  839. }
  840. }
  841. }
  842. return false
  843. }
  844. // IsFileAllowed returns true if the specified file is allowed by the file restrictions filters.
  845. // The second parameter returned is the deny policy
  846. func (u *User) IsFileAllowed(virtualPath string) (bool, int) {
  847. dirPath := path.Dir(virtualPath)
  848. if u.isDirHidden(dirPath) {
  849. return false, sdk.DenyPolicyHide
  850. }
  851. filter := u.getPatternsFilterForPath(dirPath)
  852. return filter.CheckAllowed(path.Base(virtualPath)), filter.DenyPolicy
  853. }
  854. // CanManageMFA returns true if the user can add a multi-factor authentication configuration
  855. func (u *User) CanManageMFA() bool {
  856. if util.IsStringInSlice(sdk.WebClientMFADisabled, u.Filters.WebClient) {
  857. return false
  858. }
  859. return len(mfa.GetAvailableTOTPConfigs()) > 0
  860. }
  861. func (u *User) isExternalAuthCached() bool {
  862. if u.ID <= 0 {
  863. return false
  864. }
  865. if u.Filters.ExternalAuthCacheTime <= 0 {
  866. return false
  867. }
  868. return isLastActivityRecent(u.LastLogin, time.Duration(u.Filters.ExternalAuthCacheTime)*time.Second)
  869. }
  870. // CanManageShares returns true if the user can add, update and list shares
  871. func (u *User) CanManageShares() bool {
  872. return !util.IsStringInSlice(sdk.WebClientSharesDisabled, u.Filters.WebClient)
  873. }
  874. // CanResetPassword returns true if this user is allowed to reset its password
  875. func (u *User) CanResetPassword() bool {
  876. return !util.IsStringInSlice(sdk.WebClientPasswordResetDisabled, u.Filters.WebClient)
  877. }
  878. // CanChangePassword returns true if this user is allowed to change its password
  879. func (u *User) CanChangePassword() bool {
  880. return !util.IsStringInSlice(sdk.WebClientPasswordChangeDisabled, u.Filters.WebClient)
  881. }
  882. // CanChangeAPIKeyAuth returns true if this user is allowed to enable/disable API key authentication
  883. func (u *User) CanChangeAPIKeyAuth() bool {
  884. return !util.IsStringInSlice(sdk.WebClientAPIKeyAuthChangeDisabled, u.Filters.WebClient)
  885. }
  886. // CanChangeInfo returns true if this user is allowed to change its info such as email and description
  887. func (u *User) CanChangeInfo() bool {
  888. return !util.IsStringInSlice(sdk.WebClientInfoChangeDisabled, u.Filters.WebClient)
  889. }
  890. // CanManagePublicKeys returns true if this user is allowed to manage public keys
  891. // from the web client. Used in web client UI
  892. func (u *User) CanManagePublicKeys() bool {
  893. return !util.IsStringInSlice(sdk.WebClientPubKeyChangeDisabled, u.Filters.WebClient)
  894. }
  895. // CanAddFilesFromWeb returns true if the client can add files from the web UI.
  896. // The specified target is the directory where the files must be uploaded
  897. func (u *User) CanAddFilesFromWeb(target string) bool {
  898. if util.IsStringInSlice(sdk.WebClientWriteDisabled, u.Filters.WebClient) {
  899. return false
  900. }
  901. return u.HasPerm(PermUpload, target) || u.HasPerm(PermOverwrite, target)
  902. }
  903. // CanAddDirsFromWeb returns true if the client can add directories from the web UI.
  904. // The specified target is the directory where the new directory must be created
  905. func (u *User) CanAddDirsFromWeb(target string) bool {
  906. if util.IsStringInSlice(sdk.WebClientWriteDisabled, u.Filters.WebClient) {
  907. return false
  908. }
  909. return u.HasPerm(PermCreateDirs, target)
  910. }
  911. // CanRenameFromWeb returns true if the client can rename objects from the web UI.
  912. // The specified src and dest are the source and target directories for the rename.
  913. func (u *User) CanRenameFromWeb(src, dest string) bool {
  914. if util.IsStringInSlice(sdk.WebClientWriteDisabled, u.Filters.WebClient) {
  915. return false
  916. }
  917. return u.HasAnyPerm(permsRenameAny, src) && u.HasAnyPerm(permsRenameAny, dest)
  918. }
  919. // CanDeleteFromWeb returns true if the client can delete objects from the web UI.
  920. // The specified target is the parent directory for the object to delete
  921. func (u *User) CanDeleteFromWeb(target string) bool {
  922. if util.IsStringInSlice(sdk.WebClientWriteDisabled, u.Filters.WebClient) {
  923. return false
  924. }
  925. return u.HasAnyPerm(permsDeleteAny, target)
  926. }
  927. // GetSignature returns a signature for this admin.
  928. // It could change after an update
  929. func (u *User) GetSignature() string {
  930. data := []byte(fmt.Sprintf("%v_%v_%v", u.Username, u.Status, u.ExpirationDate))
  931. data = append(data, []byte(u.Password)...)
  932. signature := sha256.Sum256(data)
  933. return base64.StdEncoding.EncodeToString(signature[:])
  934. }
  935. // GetBandwidthForIP returns the upload and download bandwidth for the specified IP
  936. func (u *User) GetBandwidthForIP(clientIP, connectionID string) (int64, int64) {
  937. if len(u.Filters.BandwidthLimits) > 0 {
  938. ip := net.ParseIP(clientIP)
  939. if ip != nil {
  940. for _, bwLimit := range u.Filters.BandwidthLimits {
  941. for _, source := range bwLimit.Sources {
  942. _, ipNet, err := net.ParseCIDR(source)
  943. if err == nil {
  944. if ipNet.Contains(ip) {
  945. logger.Debug(logSender, connectionID, "override bandwidth limit for ip %#v, upload limit: %v KB/s, download limit: %v KB/s",
  946. clientIP, bwLimit.UploadBandwidth, bwLimit.DownloadBandwidth)
  947. return bwLimit.UploadBandwidth, bwLimit.DownloadBandwidth
  948. }
  949. }
  950. }
  951. }
  952. }
  953. }
  954. return u.UploadBandwidth, u.DownloadBandwidth
  955. }
  956. // IsLoginFromAddrAllowed returns true if the login is allowed from the specified remoteAddr.
  957. // If AllowedIP is defined only the specified IP/Mask can login.
  958. // If DeniedIP is defined the specified IP/Mask cannot login.
  959. // If an IP is both allowed and denied then login will be denied
  960. func (u *User) IsLoginFromAddrAllowed(remoteAddr string) bool {
  961. if len(u.Filters.AllowedIP) == 0 && len(u.Filters.DeniedIP) == 0 {
  962. return true
  963. }
  964. remoteIP := net.ParseIP(util.GetIPFromRemoteAddress(remoteAddr))
  965. // if remoteIP is invalid we allow login, this should never happen
  966. if remoteIP == nil {
  967. logger.Warn(logSender, "", "login allowed for invalid IP. remote address: %#v", remoteAddr)
  968. return true
  969. }
  970. for _, IPMask := range u.Filters.DeniedIP {
  971. _, IPNet, err := net.ParseCIDR(IPMask)
  972. if err != nil {
  973. return false
  974. }
  975. if IPNet.Contains(remoteIP) {
  976. return false
  977. }
  978. }
  979. for _, IPMask := range u.Filters.AllowedIP {
  980. _, IPNet, err := net.ParseCIDR(IPMask)
  981. if err != nil {
  982. return false
  983. }
  984. if IPNet.Contains(remoteIP) {
  985. return true
  986. }
  987. }
  988. return len(u.Filters.AllowedIP) == 0
  989. }
  990. // GetPermissionsAsJSON returns the permissions as json byte array
  991. func (u *User) GetPermissionsAsJSON() ([]byte, error) {
  992. return json.Marshal(u.Permissions)
  993. }
  994. // GetPublicKeysAsJSON returns the public keys as json byte array
  995. func (u *User) GetPublicKeysAsJSON() ([]byte, error) {
  996. return json.Marshal(u.PublicKeys)
  997. }
  998. // GetFiltersAsJSON returns the filters as json byte array
  999. func (u *User) GetFiltersAsJSON() ([]byte, error) {
  1000. return json.Marshal(u.Filters)
  1001. }
  1002. // GetFsConfigAsJSON returns the filesystem config as json byte array
  1003. func (u *User) GetFsConfigAsJSON() ([]byte, error) {
  1004. return json.Marshal(u.FsConfig)
  1005. }
  1006. // GetUID returns a validate uid, suitable for use with os.Chown
  1007. func (u *User) GetUID() int {
  1008. if u.UID <= 0 || u.UID > math.MaxInt32 {
  1009. return -1
  1010. }
  1011. return u.UID
  1012. }
  1013. // GetGID returns a validate gid, suitable for use with os.Chown
  1014. func (u *User) GetGID() int {
  1015. if u.GID <= 0 || u.GID > math.MaxInt32 {
  1016. return -1
  1017. }
  1018. return u.GID
  1019. }
  1020. // GetHomeDir returns the shortest path name equivalent to the user's home directory
  1021. func (u *User) GetHomeDir() string {
  1022. return filepath.Clean(u.HomeDir)
  1023. }
  1024. // HasRecentActivity returns true if the last user login is recent and so we can skip some expensive checks
  1025. func (u *User) HasRecentActivity() bool {
  1026. return isLastActivityRecent(u.LastLogin, lastLoginMinDelay)
  1027. }
  1028. // HasQuotaRestrictions returns true if there are any disk quota restrictions
  1029. func (u *User) HasQuotaRestrictions() bool {
  1030. return u.QuotaFiles > 0 || u.QuotaSize > 0
  1031. }
  1032. // HasTransferQuotaRestrictions returns true if there are any data transfer restrictions
  1033. func (u *User) HasTransferQuotaRestrictions() bool {
  1034. if len(u.Filters.DataTransferLimits) > 0 {
  1035. return true
  1036. }
  1037. return u.UploadDataTransfer > 0 || u.TotalDataTransfer > 0 || u.DownloadDataTransfer > 0
  1038. }
  1039. // GetDataTransferLimits returns upload, download and total data transfer limits
  1040. func (u *User) GetDataTransferLimits(clientIP string) (int64, int64, int64) {
  1041. var total, ul, dl int64
  1042. if len(u.Filters.DataTransferLimits) > 0 {
  1043. ip := net.ParseIP(clientIP)
  1044. if ip != nil {
  1045. for _, limit := range u.Filters.DataTransferLimits {
  1046. for _, source := range limit.Sources {
  1047. _, ipNet, err := net.ParseCIDR(source)
  1048. if err == nil {
  1049. if ipNet.Contains(ip) {
  1050. if limit.TotalDataTransfer > 0 {
  1051. total = limit.TotalDataTransfer * 1048576
  1052. }
  1053. if limit.DownloadDataTransfer > 0 {
  1054. dl = limit.DownloadDataTransfer * 1048576
  1055. }
  1056. if limit.UploadDataTransfer > 0 {
  1057. ul = limit.UploadDataTransfer * 1048576
  1058. }
  1059. return ul, dl, total
  1060. }
  1061. }
  1062. }
  1063. }
  1064. }
  1065. }
  1066. if u.TotalDataTransfer > 0 {
  1067. total = u.TotalDataTransfer * 1048576
  1068. }
  1069. if u.DownloadDataTransfer > 0 {
  1070. dl = u.DownloadDataTransfer * 1048576
  1071. }
  1072. if u.UploadDataTransfer > 0 {
  1073. ul = u.UploadDataTransfer * 1048576
  1074. }
  1075. return ul, dl, total
  1076. }
  1077. // GetQuotaSummary returns used quota and limits if defined
  1078. func (u *User) GetQuotaSummary() string {
  1079. var sb strings.Builder
  1080. addSection := func() {
  1081. if sb.Len() > 0 {
  1082. sb.WriteString(". ")
  1083. }
  1084. }
  1085. if u.UsedQuotaFiles > 0 || u.QuotaFiles > 0 {
  1086. sb.WriteString(fmt.Sprintf("Files: %v", u.UsedQuotaFiles))
  1087. if u.QuotaFiles > 0 {
  1088. sb.WriteString(fmt.Sprintf("/%v", u.QuotaFiles))
  1089. }
  1090. }
  1091. if u.UsedQuotaSize > 0 || u.QuotaSize > 0 {
  1092. addSection()
  1093. sb.WriteString(fmt.Sprintf("Size: %v", util.ByteCountIEC(u.UsedQuotaSize)))
  1094. if u.QuotaSize > 0 {
  1095. sb.WriteString(fmt.Sprintf("/%v", util.ByteCountIEC(u.QuotaSize)))
  1096. }
  1097. }
  1098. if u.TotalDataTransfer > 0 {
  1099. addSection()
  1100. total := u.UsedDownloadDataTransfer + u.UsedUploadDataTransfer
  1101. sb.WriteString(fmt.Sprintf("Transfer: %v/%v", util.ByteCountIEC(total),
  1102. util.ByteCountIEC(u.TotalDataTransfer*1048576)))
  1103. }
  1104. if u.UploadDataTransfer > 0 {
  1105. addSection()
  1106. sb.WriteString(fmt.Sprintf("UL: %v/%v", util.ByteCountIEC(u.UsedUploadDataTransfer),
  1107. util.ByteCountIEC(u.UploadDataTransfer*1048576)))
  1108. }
  1109. if u.DownloadDataTransfer > 0 {
  1110. addSection()
  1111. sb.WriteString(fmt.Sprintf("DL: %v/%v", util.ByteCountIEC(u.UsedDownloadDataTransfer),
  1112. util.ByteCountIEC(u.DownloadDataTransfer*1048576)))
  1113. }
  1114. if u.LastQuotaUpdate > 0 {
  1115. addSection()
  1116. t := util.GetTimeFromMsecSinceEpoch(u.LastQuotaUpdate)
  1117. sb.WriteString(fmt.Sprintf("Last update: %v", t.Format("2006-01-02 15:04"))) // YYYY-MM-DD HH:MM
  1118. }
  1119. return sb.String()
  1120. }
  1121. // GetPermissionsAsString returns the user's permissions as comma separated string
  1122. func (u *User) GetPermissionsAsString() string {
  1123. result := ""
  1124. for dir, perms := range u.Permissions {
  1125. dirPerms := strings.Join(perms, ", ")
  1126. dp := fmt.Sprintf("%#v: %#v", dir, dirPerms)
  1127. if dir == "/" {
  1128. if result != "" {
  1129. result = dp + ", " + result
  1130. } else {
  1131. result = dp
  1132. }
  1133. } else {
  1134. if result != "" {
  1135. result += ", "
  1136. }
  1137. result += dp
  1138. }
  1139. }
  1140. return result
  1141. }
  1142. // GetBandwidthAsString returns bandwidth limits if defines
  1143. func (u *User) GetBandwidthAsString() string {
  1144. result := "DL: "
  1145. if u.DownloadBandwidth > 0 {
  1146. result += util.ByteCountIEC(u.DownloadBandwidth*1000) + "/s."
  1147. } else {
  1148. result += "unlimited."
  1149. }
  1150. result += " UL: "
  1151. if u.UploadBandwidth > 0 {
  1152. result += util.ByteCountIEC(u.UploadBandwidth*1000) + "/s."
  1153. } else {
  1154. result += "unlimited."
  1155. }
  1156. return result
  1157. }
  1158. // GetInfoString returns user's info as string.
  1159. // Storage provider, number of public keys, max sessions, uid,
  1160. // gid, denied and allowed IP/Mask are returned
  1161. func (u *User) GetInfoString() string {
  1162. var result strings.Builder
  1163. if u.LastLogin > 0 {
  1164. t := util.GetTimeFromMsecSinceEpoch(u.LastLogin)
  1165. result.WriteString(fmt.Sprintf("Last login: %v. ", t.Format("2006-01-02 15:04"))) // YYYY-MM-DD HH:MM
  1166. }
  1167. if u.FsConfig.Provider != sdk.LocalFilesystemProvider {
  1168. result.WriteString(fmt.Sprintf("Storage: %s. ", u.FsConfig.Provider.ShortInfo()))
  1169. }
  1170. if len(u.PublicKeys) > 0 {
  1171. result.WriteString(fmt.Sprintf("Public keys: %v. ", len(u.PublicKeys)))
  1172. }
  1173. if u.MaxSessions > 0 {
  1174. result.WriteString(fmt.Sprintf("Max sessions: %v. ", u.MaxSessions))
  1175. }
  1176. if u.UID > 0 {
  1177. result.WriteString(fmt.Sprintf("UID: %v. ", u.UID))
  1178. }
  1179. if u.GID > 0 {
  1180. result.WriteString(fmt.Sprintf("GID: %v. ", u.GID))
  1181. }
  1182. if len(u.Filters.DeniedIP) > 0 {
  1183. result.WriteString(fmt.Sprintf("Denied IP/Mask: %v. ", len(u.Filters.DeniedIP)))
  1184. }
  1185. if len(u.Filters.AllowedIP) > 0 {
  1186. result.WriteString(fmt.Sprintf("Allowed IP/Mask: %v", len(u.Filters.AllowedIP)))
  1187. }
  1188. return result.String()
  1189. }
  1190. // GetStatusAsString returns the user status as a string
  1191. func (u *User) GetStatusAsString() string {
  1192. if u.ExpirationDate > 0 && u.ExpirationDate < util.GetTimeAsMsSinceEpoch(time.Now()) {
  1193. return "Expired"
  1194. }
  1195. if u.Status == 1 {
  1196. return "Active"
  1197. }
  1198. return "Inactive"
  1199. }
  1200. // GetExpirationDateAsString returns expiration date formatted as YYYY-MM-DD
  1201. func (u *User) GetExpirationDateAsString() string {
  1202. if u.ExpirationDate > 0 {
  1203. t := util.GetTimeFromMsecSinceEpoch(u.ExpirationDate)
  1204. return t.Format("2006-01-02")
  1205. }
  1206. return ""
  1207. }
  1208. // GetAllowedIPAsString returns the allowed IP as comma separated string
  1209. func (u *User) GetAllowedIPAsString() string {
  1210. return strings.Join(u.Filters.AllowedIP, ",")
  1211. }
  1212. // GetDeniedIPAsString returns the denied IP as comma separated string
  1213. func (u *User) GetDeniedIPAsString() string {
  1214. return strings.Join(u.Filters.DeniedIP, ",")
  1215. }
  1216. // HasExternalAuth returns true if the external authentication is globally enabled
  1217. // and it is not disabled for this user
  1218. func (u *User) HasExternalAuth() bool {
  1219. if u.Filters.Hooks.ExternalAuthDisabled {
  1220. return false
  1221. }
  1222. if config.ExternalAuthHook != "" {
  1223. return true
  1224. }
  1225. return plugin.Handler.HasAuthenticators()
  1226. }
  1227. // CountUnusedRecoveryCodes returns the number of unused recovery codes
  1228. func (u *User) CountUnusedRecoveryCodes() int {
  1229. unused := 0
  1230. for _, code := range u.Filters.RecoveryCodes {
  1231. if !code.Used {
  1232. unused++
  1233. }
  1234. }
  1235. return unused
  1236. }
  1237. // SetEmptySecretsIfNil sets the secrets to empty if nil
  1238. func (u *User) SetEmptySecretsIfNil() {
  1239. u.FsConfig.SetEmptySecretsIfNil()
  1240. for idx := range u.VirtualFolders {
  1241. vfolder := &u.VirtualFolders[idx]
  1242. vfolder.FsConfig.SetEmptySecretsIfNil()
  1243. }
  1244. if u.Filters.TOTPConfig.Secret == nil {
  1245. u.Filters.TOTPConfig.Secret = kms.NewEmptySecret()
  1246. }
  1247. }
  1248. func (u *User) getACopy() User {
  1249. u.SetEmptySecretsIfNil()
  1250. pubKeys := make([]string, len(u.PublicKeys))
  1251. copy(pubKeys, u.PublicKeys)
  1252. virtualFolders := make([]vfs.VirtualFolder, 0, len(u.VirtualFolders))
  1253. for idx := range u.VirtualFolders {
  1254. vfolder := u.VirtualFolders[idx].GetACopy()
  1255. virtualFolders = append(virtualFolders, vfolder)
  1256. }
  1257. permissions := make(map[string][]string)
  1258. for k, v := range u.Permissions {
  1259. perms := make([]string, len(v))
  1260. copy(perms, v)
  1261. permissions[k] = perms
  1262. }
  1263. filters := UserFilters{}
  1264. filters.MaxUploadFileSize = u.Filters.MaxUploadFileSize
  1265. filters.TLSUsername = u.Filters.TLSUsername
  1266. filters.UserType = u.Filters.UserType
  1267. filters.TOTPConfig.Enabled = u.Filters.TOTPConfig.Enabled
  1268. filters.TOTPConfig.ConfigName = u.Filters.TOTPConfig.ConfigName
  1269. filters.TOTPConfig.Secret = u.Filters.TOTPConfig.Secret.Clone()
  1270. filters.TOTPConfig.Protocols = make([]string, len(u.Filters.TOTPConfig.Protocols))
  1271. copy(filters.TOTPConfig.Protocols, u.Filters.TOTPConfig.Protocols)
  1272. filters.AllowedIP = make([]string, len(u.Filters.AllowedIP))
  1273. copy(filters.AllowedIP, u.Filters.AllowedIP)
  1274. filters.DeniedIP = make([]string, len(u.Filters.DeniedIP))
  1275. copy(filters.DeniedIP, u.Filters.DeniedIP)
  1276. filters.DeniedLoginMethods = make([]string, len(u.Filters.DeniedLoginMethods))
  1277. copy(filters.DeniedLoginMethods, u.Filters.DeniedLoginMethods)
  1278. filters.FilePatterns = make([]sdk.PatternsFilter, len(u.Filters.FilePatterns))
  1279. copy(filters.FilePatterns, u.Filters.FilePatterns)
  1280. filters.DeniedProtocols = make([]string, len(u.Filters.DeniedProtocols))
  1281. copy(filters.DeniedProtocols, u.Filters.DeniedProtocols)
  1282. filters.Hooks.ExternalAuthDisabled = u.Filters.Hooks.ExternalAuthDisabled
  1283. filters.Hooks.PreLoginDisabled = u.Filters.Hooks.PreLoginDisabled
  1284. filters.Hooks.CheckPasswordDisabled = u.Filters.Hooks.CheckPasswordDisabled
  1285. filters.DisableFsChecks = u.Filters.DisableFsChecks
  1286. filters.AllowAPIKeyAuth = u.Filters.AllowAPIKeyAuth
  1287. filters.ExternalAuthCacheTime = u.Filters.ExternalAuthCacheTime
  1288. filters.WebClient = make([]string, len(u.Filters.WebClient))
  1289. copy(filters.WebClient, u.Filters.WebClient)
  1290. filters.RecoveryCodes = make([]RecoveryCode, 0, len(u.Filters.RecoveryCodes))
  1291. for _, code := range u.Filters.RecoveryCodes {
  1292. if code.Secret == nil {
  1293. code.Secret = kms.NewEmptySecret()
  1294. }
  1295. filters.RecoveryCodes = append(filters.RecoveryCodes, RecoveryCode{
  1296. Secret: code.Secret.Clone(),
  1297. Used: code.Used,
  1298. })
  1299. }
  1300. filters.BandwidthLimits = make([]sdk.BandwidthLimit, 0, len(u.Filters.BandwidthLimits))
  1301. for _, limit := range u.Filters.BandwidthLimits {
  1302. bwLimit := sdk.BandwidthLimit{
  1303. UploadBandwidth: limit.UploadBandwidth,
  1304. DownloadBandwidth: limit.DownloadBandwidth,
  1305. Sources: make([]string, 0, len(limit.Sources)),
  1306. }
  1307. bwLimit.Sources = make([]string, len(limit.Sources))
  1308. copy(bwLimit.Sources, limit.Sources)
  1309. filters.BandwidthLimits = append(filters.BandwidthLimits, bwLimit)
  1310. }
  1311. filters.DataTransferLimits = make([]sdk.DataTransferLimit, 0, len(u.Filters.DataTransferLimits))
  1312. for _, limit := range u.Filters.DataTransferLimits {
  1313. dtLimit := sdk.DataTransferLimit{
  1314. UploadDataTransfer: limit.UploadDataTransfer,
  1315. DownloadDataTransfer: limit.DownloadDataTransfer,
  1316. TotalDataTransfer: limit.TotalDataTransfer,
  1317. Sources: make([]string, 0, len(limit.Sources)),
  1318. }
  1319. dtLimit.Sources = make([]string, len(limit.Sources))
  1320. copy(dtLimit.Sources, limit.Sources)
  1321. filters.DataTransferLimits = append(filters.DataTransferLimits, dtLimit)
  1322. }
  1323. return User{
  1324. BaseUser: sdk.BaseUser{
  1325. ID: u.ID,
  1326. Username: u.Username,
  1327. Email: u.Email,
  1328. Password: u.Password,
  1329. PublicKeys: pubKeys,
  1330. HomeDir: u.HomeDir,
  1331. UID: u.UID,
  1332. GID: u.GID,
  1333. MaxSessions: u.MaxSessions,
  1334. QuotaSize: u.QuotaSize,
  1335. QuotaFiles: u.QuotaFiles,
  1336. Permissions: permissions,
  1337. UsedQuotaSize: u.UsedQuotaSize,
  1338. UsedQuotaFiles: u.UsedQuotaFiles,
  1339. LastQuotaUpdate: u.LastQuotaUpdate,
  1340. UploadBandwidth: u.UploadBandwidth,
  1341. DownloadBandwidth: u.DownloadBandwidth,
  1342. UploadDataTransfer: u.UploadDataTransfer,
  1343. DownloadDataTransfer: u.DownloadDataTransfer,
  1344. TotalDataTransfer: u.TotalDataTransfer,
  1345. UsedUploadDataTransfer: u.UsedUploadDataTransfer,
  1346. UsedDownloadDataTransfer: u.UsedDownloadDataTransfer,
  1347. Status: u.Status,
  1348. ExpirationDate: u.ExpirationDate,
  1349. LastLogin: u.LastLogin,
  1350. AdditionalInfo: u.AdditionalInfo,
  1351. Description: u.Description,
  1352. CreatedAt: u.CreatedAt,
  1353. UpdatedAt: u.UpdatedAt,
  1354. },
  1355. Filters: filters,
  1356. VirtualFolders: virtualFolders,
  1357. FsConfig: u.FsConfig.GetACopy(),
  1358. }
  1359. }
  1360. // GetEncryptionAdditionalData returns the additional data to use for AEAD
  1361. func (u *User) GetEncryptionAdditionalData() string {
  1362. return u.Username
  1363. }
  1364. // GetGCSCredentialsFilePath returns the path for GCS credentials
  1365. func (u *User) GetGCSCredentialsFilePath() string {
  1366. return filepath.Join(credentialsDirPath, fmt.Sprintf("%v_gcs_credentials.json", u.Username))
  1367. }