connection_test.go 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255
  1. package common
  2. import (
  3. "io/ioutil"
  4. "os"
  5. "path"
  6. "path/filepath"
  7. "runtime"
  8. "testing"
  9. "time"
  10. "github.com/minio/sio"
  11. "github.com/pkg/sftp"
  12. "github.com/stretchr/testify/assert"
  13. "github.com/stretchr/testify/require"
  14. "github.com/drakkan/sftpgo/dataprovider"
  15. "github.com/drakkan/sftpgo/kms"
  16. "github.com/drakkan/sftpgo/vfs"
  17. )
  18. // MockOsFs mockable OsFs
  19. type MockOsFs struct {
  20. vfs.Fs
  21. hasVirtualFolders bool
  22. }
  23. // Name returns the name for the Fs implementation
  24. func (fs MockOsFs) Name() string {
  25. return "mockOsFs"
  26. }
  27. // HasVirtualFolders returns true if folders are emulated
  28. func (fs MockOsFs) HasVirtualFolders() bool {
  29. return fs.hasVirtualFolders
  30. }
  31. func (fs MockOsFs) IsUploadResumeSupported() bool {
  32. return !fs.hasVirtualFolders
  33. }
  34. func newMockOsFs(hasVirtualFolders bool, connectionID, rootDir string) vfs.Fs {
  35. return &MockOsFs{
  36. Fs: vfs.NewOsFs(connectionID, rootDir, nil),
  37. hasVirtualFolders: hasVirtualFolders,
  38. }
  39. }
  40. func TestListDir(t *testing.T) {
  41. user := dataprovider.User{
  42. Username: userTestUsername,
  43. HomeDir: filepath.Join(os.TempDir(), "home"),
  44. }
  45. mappedPath := filepath.Join(os.TempDir(), "vdir")
  46. user.Permissions = make(map[string][]string)
  47. user.Permissions["/"] = []string{dataprovider.PermUpload}
  48. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  49. BaseVirtualFolder: vfs.BaseVirtualFolder{
  50. MappedPath: mappedPath,
  51. },
  52. VirtualPath: "/vdir",
  53. })
  54. err := os.Mkdir(user.GetHomeDir(), os.ModePerm)
  55. assert.NoError(t, err)
  56. fs, err := user.GetFilesystem("")
  57. assert.NoError(t, err)
  58. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  59. _, err = c.ListDir(user.GetHomeDir(), "/")
  60. if assert.Error(t, err) {
  61. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  62. }
  63. c.User.Permissions["/"] = []string{dataprovider.PermAny}
  64. files, err := c.ListDir(user.GetHomeDir(), "/")
  65. if assert.NoError(t, err) {
  66. vdirFound := false
  67. for _, f := range files {
  68. if f.Name() == "vdir" {
  69. vdirFound = true
  70. break
  71. }
  72. }
  73. assert.True(t, vdirFound)
  74. }
  75. _, err = c.ListDir(mappedPath, "/vdir")
  76. assert.Error(t, err)
  77. err = os.RemoveAll(user.GetHomeDir())
  78. assert.NoError(t, err)
  79. }
  80. func TestCreateDir(t *testing.T) {
  81. user := dataprovider.User{
  82. Username: userTestUsername,
  83. HomeDir: filepath.Join(os.TempDir(), "home"),
  84. }
  85. mappedPath := filepath.Join(os.TempDir(), "vdir")
  86. user.Permissions = make(map[string][]string)
  87. user.Permissions["/"] = []string{dataprovider.PermAny}
  88. user.Permissions["/sub"] = []string{dataprovider.PermListItems}
  89. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  90. BaseVirtualFolder: vfs.BaseVirtualFolder{
  91. MappedPath: mappedPath,
  92. },
  93. VirtualPath: "/vdir",
  94. })
  95. err := os.Mkdir(user.GetHomeDir(), os.ModePerm)
  96. assert.NoError(t, err)
  97. fs, err := user.GetFilesystem("")
  98. assert.NoError(t, err)
  99. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  100. err = c.CreateDir("", "/sub/dir")
  101. if assert.Error(t, err) {
  102. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  103. }
  104. err = c.CreateDir("", "/vdir")
  105. if assert.Error(t, err) {
  106. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  107. }
  108. err = c.CreateDir(filepath.Join(mappedPath, "adir"), "/vdir/adir")
  109. assert.Error(t, err)
  110. err = c.CreateDir(filepath.Join(user.GetHomeDir(), "dir"), "/dir")
  111. assert.NoError(t, err)
  112. err = os.RemoveAll(user.GetHomeDir())
  113. assert.NoError(t, err)
  114. }
  115. func TestRemoveFile(t *testing.T) {
  116. user := dataprovider.User{
  117. Username: userTestUsername,
  118. HomeDir: filepath.Join(os.TempDir(), "home"),
  119. }
  120. mappedPath := filepath.Join(os.TempDir(), "vdir")
  121. user.Permissions = make(map[string][]string)
  122. user.Permissions["/"] = []string{dataprovider.PermAny}
  123. user.Permissions["/sub"] = []string{dataprovider.PermListItems}
  124. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  125. BaseVirtualFolder: vfs.BaseVirtualFolder{
  126. MappedPath: mappedPath,
  127. },
  128. VirtualPath: "/vdir",
  129. QuotaFiles: -1,
  130. QuotaSize: -1,
  131. })
  132. user.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  133. {
  134. Path: "/p",
  135. AllowedExtensions: []string{},
  136. DeniedExtensions: []string{".zip"},
  137. },
  138. }
  139. err := os.Mkdir(user.GetHomeDir(), os.ModePerm)
  140. assert.NoError(t, err)
  141. err = os.Mkdir(mappedPath, os.ModePerm)
  142. assert.NoError(t, err)
  143. fs, err := user.GetFilesystem("")
  144. assert.NoError(t, err)
  145. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  146. err = c.RemoveFile("", "/sub/file", nil)
  147. if assert.Error(t, err) {
  148. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  149. }
  150. err = c.RemoveFile("", "/p/file.zip", nil)
  151. if assert.Error(t, err) {
  152. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  153. }
  154. testFile := filepath.Join(mappedPath, "afile")
  155. err = ioutil.WriteFile(testFile, []byte("test data"), os.ModePerm)
  156. assert.NoError(t, err)
  157. info, err := os.Stat(testFile)
  158. assert.NoError(t, err)
  159. err = c.RemoveFile(filepath.Join(user.GetHomeDir(), "missing"), "/missing", info)
  160. assert.Error(t, err)
  161. err = c.RemoveFile(testFile, "/vdir/afile", info)
  162. assert.NoError(t, err)
  163. err = os.RemoveAll(mappedPath)
  164. assert.NoError(t, err)
  165. err = os.RemoveAll(user.GetHomeDir())
  166. assert.NoError(t, err)
  167. }
  168. func TestRemoveDir(t *testing.T) {
  169. user := dataprovider.User{
  170. Username: userTestUsername,
  171. HomeDir: filepath.Join(os.TempDir(), "home"),
  172. }
  173. mappedPath := filepath.Join(os.TempDir(), "vdir")
  174. user.Permissions = make(map[string][]string)
  175. user.Permissions["/"] = []string{dataprovider.PermAny}
  176. user.Permissions["/sub"] = []string{dataprovider.PermListItems}
  177. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  178. BaseVirtualFolder: vfs.BaseVirtualFolder{
  179. MappedPath: mappedPath,
  180. },
  181. VirtualPath: "/adir/vdir",
  182. })
  183. err := os.Mkdir(user.GetHomeDir(), os.ModePerm)
  184. assert.NoError(t, err)
  185. err = os.Mkdir(mappedPath, os.ModePerm)
  186. assert.NoError(t, err)
  187. fs, err := user.GetFilesystem("")
  188. assert.NoError(t, err)
  189. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  190. err = c.RemoveDir(user.GetHomeDir(), "/")
  191. if assert.Error(t, err) {
  192. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  193. }
  194. err = c.RemoveDir(mappedPath, "/adir/vdir")
  195. if assert.Error(t, err) {
  196. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  197. }
  198. err = c.RemoveDir(mappedPath, "/adir")
  199. if assert.Error(t, err) {
  200. assert.EqualError(t, err, c.GetOpUnsupportedError().Error())
  201. }
  202. err = c.RemoveDir(mappedPath, "/adir/dir")
  203. if assert.Error(t, err) {
  204. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  205. }
  206. err = c.RemoveDir(filepath.Join(user.GetHomeDir(), "/sub/dir"), "/sub/dir")
  207. if assert.Error(t, err) {
  208. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  209. }
  210. testDir := filepath.Join(user.GetHomeDir(), "testDir")
  211. err = c.RemoveDir(testDir, "testDir")
  212. assert.Error(t, err)
  213. err = ioutil.WriteFile(testDir, []byte("data"), os.ModePerm)
  214. assert.NoError(t, err)
  215. err = c.RemoveDir(testDir, "testDir")
  216. if assert.Error(t, err) {
  217. assert.EqualError(t, err, c.GetGenericError(err).Error())
  218. }
  219. err = os.Remove(testDir)
  220. assert.NoError(t, err)
  221. testDirSub := filepath.Join(testDir, "sub")
  222. err = os.MkdirAll(testDirSub, os.ModePerm)
  223. assert.NoError(t, err)
  224. err = c.RemoveDir(testDir, "/testDir")
  225. assert.Error(t, err)
  226. err = os.RemoveAll(testDirSub)
  227. assert.NoError(t, err)
  228. err = c.RemoveDir(testDir, "/testDir")
  229. assert.NoError(t, err)
  230. err = c.RemoveDir(testDir, "/testDir")
  231. assert.Error(t, err)
  232. fs = newMockOsFs(true, "", user.GetHomeDir())
  233. c.Fs = fs
  234. err = c.RemoveDir(testDir, "/testDir")
  235. assert.NoError(t, err)
  236. err = os.RemoveAll(mappedPath)
  237. assert.NoError(t, err)
  238. err = os.RemoveAll(user.GetHomeDir())
  239. assert.NoError(t, err)
  240. }
  241. func TestRename(t *testing.T) {
  242. user := dataprovider.User{
  243. Username: userTestUsername,
  244. HomeDir: filepath.Join(os.TempDir(), "home"),
  245. QuotaSize: 10485760,
  246. }
  247. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  248. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  249. user.Permissions = make(map[string][]string)
  250. user.Permissions["/"] = []string{dataprovider.PermAny}
  251. user.Permissions["/sub"] = []string{dataprovider.PermListItems}
  252. user.Permissions["/sub1"] = []string{dataprovider.PermRename}
  253. user.Permissions["/dir"] = []string{dataprovider.PermListItems}
  254. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  255. BaseVirtualFolder: vfs.BaseVirtualFolder{
  256. MappedPath: mappedPath1,
  257. },
  258. VirtualPath: "/vdir1/sub",
  259. QuotaFiles: -1,
  260. QuotaSize: -1,
  261. })
  262. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  263. BaseVirtualFolder: vfs.BaseVirtualFolder{
  264. MappedPath: mappedPath2,
  265. },
  266. VirtualPath: "/vdir2",
  267. QuotaFiles: -1,
  268. QuotaSize: -1,
  269. })
  270. err := os.MkdirAll(filepath.Join(user.GetHomeDir(), "sub"), os.ModePerm)
  271. assert.NoError(t, err)
  272. err = os.MkdirAll(filepath.Join(user.GetHomeDir(), "dir", "sub"), os.ModePerm)
  273. assert.NoError(t, err)
  274. err = os.Mkdir(mappedPath1, os.ModePerm)
  275. assert.NoError(t, err)
  276. err = os.Mkdir(mappedPath2, os.ModePerm)
  277. assert.NoError(t, err)
  278. fs, err := user.GetFilesystem("")
  279. assert.NoError(t, err)
  280. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  281. err = c.Rename(mappedPath1, "", "", "")
  282. if assert.Error(t, err) {
  283. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  284. }
  285. err = c.Rename("", mappedPath2, "", "")
  286. if assert.Error(t, err) {
  287. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  288. }
  289. err = c.Rename("missing", "", "", "")
  290. assert.Error(t, err)
  291. testFile := filepath.Join(user.GetHomeDir(), "file")
  292. err = ioutil.WriteFile(testFile, []byte("data"), os.ModePerm)
  293. assert.NoError(t, err)
  294. testSubFile := filepath.Join(user.GetHomeDir(), "sub", "file")
  295. err = ioutil.WriteFile(testSubFile, []byte("data"), os.ModePerm)
  296. assert.NoError(t, err)
  297. err = c.Rename(testSubFile, filepath.Join(user.GetHomeDir(), "file"), "/sub/file", "/file")
  298. if assert.Error(t, err) {
  299. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  300. }
  301. err = c.Rename(testFile, filepath.Join(user.GetHomeDir(), "sub"), "/file", "/sub")
  302. if assert.Error(t, err) {
  303. assert.EqualError(t, err, c.GetOpUnsupportedError().Error())
  304. }
  305. err = c.Rename(testSubFile, testFile, "/file", "/sub1/file")
  306. if assert.Error(t, err) {
  307. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  308. }
  309. err = c.Rename(filepath.Join(user.GetHomeDir(), "sub"), filepath.Join(user.GetHomeDir(), "adir"), "/vdir1", "/adir")
  310. if assert.Error(t, err) {
  311. assert.EqualError(t, err, c.GetOpUnsupportedError().Error())
  312. }
  313. err = c.Rename(filepath.Join(user.GetHomeDir(), "dir"), filepath.Join(user.GetHomeDir(), "adir"), "/dir", "/adir")
  314. if assert.Error(t, err) {
  315. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  316. }
  317. err = os.MkdirAll(filepath.Join(user.GetHomeDir(), "testdir"), os.ModePerm)
  318. assert.NoError(t, err)
  319. err = c.Rename(filepath.Join(user.GetHomeDir(), "testdir"), filepath.Join(user.GetHomeDir(), "tdir", "sub"), "/testdir", "/tdir/sub")
  320. assert.Error(t, err)
  321. err = os.Remove(testSubFile)
  322. assert.NoError(t, err)
  323. err = c.Rename(filepath.Join(user.GetHomeDir(), "sub"), filepath.Join(user.GetHomeDir(), "adir"), "/sub", "/adir")
  324. assert.NoError(t, err)
  325. err = os.MkdirAll(filepath.Join(user.GetHomeDir(), "adir"), os.ModePerm)
  326. assert.NoError(t, err)
  327. err = ioutil.WriteFile(filepath.Join(user.GetHomeDir(), "adir", "file"), []byte("data"), os.ModePerm)
  328. assert.NoError(t, err)
  329. err = c.Rename(filepath.Join(user.GetHomeDir(), "adir", "file"), filepath.Join(user.GetHomeDir(), "file"), "/adir/file", "/file")
  330. assert.NoError(t, err)
  331. // rename between virtual folder this should fail since the virtual folder is not found inside the data provider
  332. // and so the remaining space cannot be computed
  333. err = c.Rename(filepath.Join(user.GetHomeDir(), "adir"), filepath.Join(user.GetHomeDir(), "another"), "/vdir1/sub/a", "/vdir2/b")
  334. if assert.Error(t, err) {
  335. assert.EqualError(t, err, c.GetGenericError(err).Error())
  336. }
  337. err = os.RemoveAll(mappedPath1)
  338. assert.NoError(t, err)
  339. err = os.RemoveAll(mappedPath2)
  340. assert.NoError(t, err)
  341. err = os.RemoveAll(user.GetHomeDir())
  342. assert.NoError(t, err)
  343. }
  344. func TestCreateSymlink(t *testing.T) {
  345. user := dataprovider.User{
  346. Username: userTestUsername,
  347. HomeDir: filepath.Join(os.TempDir(), "home"),
  348. }
  349. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  350. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  351. user.Permissions = make(map[string][]string)
  352. user.Permissions["/"] = []string{dataprovider.PermAny}
  353. user.Permissions["/sub"] = []string{dataprovider.PermListItems}
  354. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  355. BaseVirtualFolder: vfs.BaseVirtualFolder{
  356. MappedPath: mappedPath1,
  357. },
  358. VirtualPath: "/vdir1",
  359. QuotaFiles: -1,
  360. QuotaSize: -1,
  361. })
  362. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  363. BaseVirtualFolder: vfs.BaseVirtualFolder{
  364. MappedPath: mappedPath2,
  365. },
  366. VirtualPath: "/vdir2",
  367. QuotaFiles: -1,
  368. QuotaSize: -1,
  369. })
  370. err := os.Mkdir(user.GetHomeDir(), os.ModePerm)
  371. assert.NoError(t, err)
  372. err = os.Mkdir(mappedPath1, os.ModePerm)
  373. assert.NoError(t, err)
  374. err = os.Mkdir(mappedPath2, os.ModePerm)
  375. assert.NoError(t, err)
  376. fs, err := user.GetFilesystem("")
  377. assert.NoError(t, err)
  378. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  379. err = c.CreateSymlink(user.GetHomeDir(), mappedPath1, "/", "/vdir1")
  380. if assert.Error(t, err) {
  381. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  382. }
  383. err = c.CreateSymlink(filepath.Join(user.GetHomeDir(), "a"), mappedPath1, "/a", "/vdir1")
  384. if assert.Error(t, err) {
  385. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  386. }
  387. err = c.CreateSymlink(filepath.Join(user.GetHomeDir(), "b"), mappedPath1, "/b", "/sub/b")
  388. if assert.Error(t, err) {
  389. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  390. }
  391. err = c.CreateSymlink(filepath.Join(user.GetHomeDir(), "b"), mappedPath1, "/vdir1/b", "/vdir2/b")
  392. if assert.Error(t, err) {
  393. assert.EqualError(t, err, c.GetOpUnsupportedError().Error())
  394. }
  395. err = c.CreateSymlink(mappedPath1, filepath.Join(mappedPath1, "b"), "/vdir1/a", "/vdir1/b")
  396. if assert.Error(t, err) {
  397. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  398. }
  399. err = c.CreateSymlink(filepath.Join(mappedPath1, "b"), mappedPath1, "/vdir1/a", "/vdir1/b")
  400. if assert.Error(t, err) {
  401. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  402. }
  403. err = os.Mkdir(filepath.Join(user.GetHomeDir(), "b"), os.ModePerm)
  404. assert.NoError(t, err)
  405. err = c.CreateSymlink(filepath.Join(user.GetHomeDir(), "b"), filepath.Join(user.GetHomeDir(), "c"), "/b", "/c")
  406. assert.NoError(t, err)
  407. err = c.CreateSymlink(filepath.Join(user.GetHomeDir(), "b"), filepath.Join(user.GetHomeDir(), "c"), "/b", "/c")
  408. assert.Error(t, err)
  409. err = os.RemoveAll(mappedPath1)
  410. assert.NoError(t, err)
  411. err = os.RemoveAll(mappedPath2)
  412. assert.NoError(t, err)
  413. err = os.RemoveAll(user.GetHomeDir())
  414. assert.NoError(t, err)
  415. }
  416. func TestDoStat(t *testing.T) {
  417. testFile := filepath.Join(os.TempDir(), "afile.txt")
  418. fs := vfs.NewOsFs("123", os.TempDir(), nil)
  419. u := dataprovider.User{
  420. Username: "user",
  421. HomeDir: os.TempDir(),
  422. }
  423. u.Permissions = make(map[string][]string)
  424. u.Permissions["/"] = []string{dataprovider.PermAny}
  425. err := ioutil.WriteFile(testFile, []byte("data"), os.ModePerm)
  426. require.NoError(t, err)
  427. err = os.Symlink(testFile, testFile+".sym")
  428. require.NoError(t, err)
  429. conn := NewBaseConnection(fs.ConnectionID(), ProtocolSFTP, u, fs)
  430. infoStat, err := conn.DoStat(testFile+".sym", 0)
  431. if assert.NoError(t, err) {
  432. assert.Equal(t, int64(4), infoStat.Size())
  433. }
  434. infoLstat, err := conn.DoStat(testFile+".sym", 1)
  435. if assert.NoError(t, err) {
  436. assert.NotEqual(t, int64(4), infoLstat.Size())
  437. }
  438. assert.False(t, os.SameFile(infoStat, infoLstat))
  439. fs, err = vfs.NewCryptFs(fs.ConnectionID(), os.TempDir(), vfs.CryptFsConfig{
  440. Passphrase: kms.NewPlainSecret("payload"),
  441. })
  442. assert.NoError(t, err)
  443. conn = NewBaseConnection(fs.ConnectionID(), ProtocolFTP, u, fs)
  444. dataSize := int64(32768)
  445. data := make([]byte, dataSize)
  446. err = ioutil.WriteFile(testFile, data, os.ModePerm)
  447. assert.NoError(t, err)
  448. infoStat, err = conn.DoStat(testFile, 0)
  449. assert.NoError(t, err)
  450. assert.Less(t, infoStat.Size(), dataSize)
  451. encSize, err := sio.EncryptedSize(uint64(infoStat.Size()))
  452. assert.NoError(t, err)
  453. assert.Equal(t, int64(encSize)+33, dataSize)
  454. err = os.Remove(testFile)
  455. assert.NoError(t, err)
  456. err = os.Remove(testFile + ".sym")
  457. assert.NoError(t, err)
  458. assert.Len(t, conn.GetTransfers(), 0)
  459. }
  460. func TestSetStat(t *testing.T) {
  461. oldSetStatMode := Config.SetstatMode
  462. Config.SetstatMode = 1
  463. user := dataprovider.User{
  464. Username: userTestUsername,
  465. HomeDir: filepath.Join(os.TempDir(), "home"),
  466. }
  467. user.Permissions = make(map[string][]string)
  468. user.Permissions["/"] = []string{dataprovider.PermAny}
  469. user.Permissions["/dir1"] = []string{dataprovider.PermChmod}
  470. user.Permissions["/dir2"] = []string{dataprovider.PermChown}
  471. user.Permissions["/dir3"] = []string{dataprovider.PermChtimes}
  472. dir1 := filepath.Join(user.GetHomeDir(), "dir1")
  473. dir2 := filepath.Join(user.GetHomeDir(), "dir2")
  474. dir3 := filepath.Join(user.GetHomeDir(), "dir3")
  475. err := os.Mkdir(user.GetHomeDir(), os.ModePerm)
  476. assert.NoError(t, err)
  477. err = os.Mkdir(dir1, os.ModePerm)
  478. assert.NoError(t, err)
  479. err = os.Mkdir(dir2, os.ModePerm)
  480. assert.NoError(t, err)
  481. err = os.Mkdir(dir3, os.ModePerm)
  482. assert.NoError(t, err)
  483. fs, err := user.GetFilesystem("")
  484. assert.NoError(t, err)
  485. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  486. err = c.SetStat(user.GetHomeDir(), "/", &StatAttributes{})
  487. assert.NoError(t, err)
  488. err = c.SetStat(dir2, "/dir1/file", &StatAttributes{
  489. Mode: os.ModePerm,
  490. Flags: StatAttrPerms,
  491. })
  492. assert.NoError(t, err)
  493. err = c.SetStat(dir1, "/dir2/file", &StatAttributes{
  494. UID: os.Getuid(),
  495. GID: os.Getgid(),
  496. Flags: StatAttrUIDGID,
  497. })
  498. assert.NoError(t, err)
  499. err = c.SetStat(dir1, "/dir3/file", &StatAttributes{
  500. Atime: time.Now(),
  501. Mtime: time.Now(),
  502. Flags: StatAttrTimes,
  503. })
  504. assert.NoError(t, err)
  505. Config.SetstatMode = 2
  506. assert.False(t, c.ignoreSetStat())
  507. c1 := NewBaseConnection("", ProtocolSFTP, user, newMockOsFs(false, fs.ConnectionID(), user.GetHomeDir()))
  508. assert.True(t, c1.ignoreSetStat())
  509. Config.SetstatMode = oldSetStatMode
  510. // chmod
  511. err = c.SetStat(dir1, "/dir1/file", &StatAttributes{
  512. Mode: os.ModePerm,
  513. Flags: StatAttrPerms,
  514. })
  515. assert.NoError(t, err)
  516. err = c.SetStat(dir2, "/dir2/file", &StatAttributes{
  517. Mode: os.ModePerm,
  518. Flags: StatAttrPerms,
  519. })
  520. if assert.Error(t, err) {
  521. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  522. }
  523. err = c.SetStat(filepath.Join(user.GetHomeDir(), "missing"), "/missing", &StatAttributes{
  524. Mode: os.ModePerm,
  525. Flags: StatAttrPerms,
  526. })
  527. assert.Error(t, err)
  528. // chown
  529. if runtime.GOOS != osWindows {
  530. err = c.SetStat(dir1, "/dir2/file", &StatAttributes{
  531. UID: os.Getuid(),
  532. GID: os.Getgid(),
  533. Flags: StatAttrUIDGID,
  534. })
  535. assert.NoError(t, err)
  536. }
  537. err = c.SetStat(dir1, "/dir3/file", &StatAttributes{
  538. UID: os.Getuid(),
  539. GID: os.Getgid(),
  540. Flags: StatAttrUIDGID,
  541. })
  542. if assert.Error(t, err) {
  543. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  544. }
  545. err = c.SetStat(filepath.Join(user.GetHomeDir(), "missing"), "/missing", &StatAttributes{
  546. UID: os.Getuid(),
  547. GID: os.Getgid(),
  548. Flags: StatAttrUIDGID,
  549. })
  550. assert.Error(t, err)
  551. // chtimes
  552. err = c.SetStat(dir1, "/dir3/file", &StatAttributes{
  553. Atime: time.Now(),
  554. Mtime: time.Now(),
  555. Flags: StatAttrTimes,
  556. })
  557. assert.NoError(t, err)
  558. err = c.SetStat(dir1, "/dir1/file", &StatAttributes{
  559. Atime: time.Now(),
  560. Mtime: time.Now(),
  561. Flags: StatAttrTimes,
  562. })
  563. if assert.Error(t, err) {
  564. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  565. }
  566. err = c.SetStat(filepath.Join(user.GetHomeDir(), "missing"), "/missing", &StatAttributes{
  567. Atime: time.Now(),
  568. Mtime: time.Now(),
  569. Flags: StatAttrTimes,
  570. })
  571. assert.Error(t, err)
  572. // truncate
  573. err = c.SetStat(filepath.Join(user.GetHomeDir(), "/missing/missing"), "/missing/missing", &StatAttributes{
  574. Size: 1,
  575. Flags: StatAttrSize,
  576. })
  577. assert.Error(t, err)
  578. err = c.SetStat(filepath.Join(dir3, "afile.txt"), "/dir3/afile.txt", &StatAttributes{
  579. Size: 1,
  580. Flags: StatAttrSize,
  581. })
  582. assert.Error(t, err)
  583. filePath := filepath.Join(user.GetHomeDir(), "afile.txt")
  584. err = ioutil.WriteFile(filePath, []byte("hello"), os.ModePerm)
  585. assert.NoError(t, err)
  586. err = c.SetStat(filePath, "/afile.txt", &StatAttributes{
  587. Flags: StatAttrSize,
  588. Size: 1,
  589. })
  590. assert.NoError(t, err)
  591. fi, err := os.Stat(filePath)
  592. if assert.NoError(t, err) {
  593. assert.Equal(t, int64(1), fi.Size())
  594. }
  595. vDir := filepath.Join(os.TempDir(), "vdir")
  596. err = os.MkdirAll(vDir, os.ModePerm)
  597. assert.NoError(t, err)
  598. c.User.VirtualFolders = nil
  599. c.User.VirtualFolders = append(c.User.VirtualFolders, vfs.VirtualFolder{
  600. BaseVirtualFolder: vfs.BaseVirtualFolder{
  601. MappedPath: vDir,
  602. },
  603. VirtualPath: "/vpath",
  604. QuotaSize: -1,
  605. QuotaFiles: -1,
  606. })
  607. filePath = filepath.Join(vDir, "afile.txt")
  608. err = ioutil.WriteFile(filePath, []byte("hello"), os.ModePerm)
  609. assert.NoError(t, err)
  610. err = c.SetStat(filePath, "/vpath/afile.txt", &StatAttributes{
  611. Flags: StatAttrSize,
  612. Size: 1,
  613. })
  614. assert.NoError(t, err)
  615. fi, err = os.Stat(filePath)
  616. if assert.NoError(t, err) {
  617. assert.Equal(t, int64(1), fi.Size())
  618. }
  619. err = os.RemoveAll(user.GetHomeDir())
  620. assert.NoError(t, err)
  621. err = os.RemoveAll(vDir)
  622. assert.NoError(t, err)
  623. }
  624. func TestSpaceForCrossRename(t *testing.T) {
  625. permissions := make(map[string][]string)
  626. permissions["/"] = []string{dataprovider.PermAny}
  627. user := dataprovider.User{
  628. Username: userTestUsername,
  629. Permissions: permissions,
  630. HomeDir: filepath.Clean(os.TempDir()),
  631. }
  632. fs, err := user.GetFilesystem("123")
  633. assert.NoError(t, err)
  634. conn := NewBaseConnection("", ProtocolSFTP, user, fs)
  635. quotaResult := vfs.QuotaCheckResult{
  636. HasSpace: true,
  637. }
  638. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, -1, filepath.Join(os.TempDir(), "a missing file")))
  639. if runtime.GOOS != osWindows {
  640. testDir := filepath.Join(os.TempDir(), "dir")
  641. err = os.MkdirAll(testDir, os.ModePerm)
  642. assert.NoError(t, err)
  643. err = ioutil.WriteFile(filepath.Join(testDir, "afile.txt"), []byte("content"), os.ModePerm)
  644. assert.NoError(t, err)
  645. err = os.Chmod(testDir, 0001)
  646. assert.NoError(t, err)
  647. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, -1, testDir))
  648. err = os.Chmod(testDir, os.ModePerm)
  649. assert.NoError(t, err)
  650. err = os.RemoveAll(testDir)
  651. assert.NoError(t, err)
  652. }
  653. testFile := filepath.Join(os.TempDir(), "afile.txt")
  654. err = ioutil.WriteFile(testFile, []byte("test data"), os.ModePerm)
  655. assert.NoError(t, err)
  656. quotaResult = vfs.QuotaCheckResult{
  657. HasSpace: false,
  658. QuotaSize: 0,
  659. }
  660. assert.True(t, conn.hasSpaceForCrossRename(quotaResult, 123, testFile))
  661. quotaResult = vfs.QuotaCheckResult{
  662. HasSpace: false,
  663. QuotaSize: 124,
  664. UsedSize: 125,
  665. }
  666. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, 8, testFile))
  667. quotaResult = vfs.QuotaCheckResult{
  668. HasSpace: false,
  669. QuotaSize: 124,
  670. UsedSize: 124,
  671. }
  672. assert.True(t, conn.hasSpaceForCrossRename(quotaResult, 123, testFile))
  673. quotaResult = vfs.QuotaCheckResult{
  674. HasSpace: true,
  675. QuotaSize: 10,
  676. UsedSize: 1,
  677. }
  678. assert.True(t, conn.hasSpaceForCrossRename(quotaResult, -1, testFile))
  679. quotaResult = vfs.QuotaCheckResult{
  680. HasSpace: true,
  681. QuotaSize: 7,
  682. UsedSize: 0,
  683. }
  684. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, -1, testFile))
  685. err = os.Remove(testFile)
  686. assert.NoError(t, err)
  687. testDir := filepath.Join(os.TempDir(), "testDir")
  688. err = os.MkdirAll(testDir, os.ModePerm)
  689. assert.NoError(t, err)
  690. err = ioutil.WriteFile(filepath.Join(testDir, "1"), []byte("1"), os.ModePerm)
  691. assert.NoError(t, err)
  692. err = ioutil.WriteFile(filepath.Join(testDir, "2"), []byte("2"), os.ModePerm)
  693. assert.NoError(t, err)
  694. quotaResult = vfs.QuotaCheckResult{
  695. HasSpace: true,
  696. QuotaFiles: 2,
  697. UsedFiles: 1,
  698. }
  699. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, -1, testDir))
  700. quotaResult = vfs.QuotaCheckResult{
  701. HasSpace: true,
  702. QuotaFiles: 2,
  703. UsedFiles: 0,
  704. }
  705. assert.True(t, conn.hasSpaceForCrossRename(quotaResult, -1, testDir))
  706. err = os.RemoveAll(testDir)
  707. assert.NoError(t, err)
  708. }
  709. func TestRenamePermission(t *testing.T) {
  710. permissions := make(map[string][]string)
  711. permissions["/"] = []string{dataprovider.PermAny}
  712. permissions["/dir1"] = []string{dataprovider.PermRename}
  713. permissions["/dir2"] = []string{dataprovider.PermUpload}
  714. permissions["/dir3"] = []string{dataprovider.PermDelete}
  715. permissions["/dir4"] = []string{dataprovider.PermListItems}
  716. permissions["/dir5"] = []string{dataprovider.PermCreateDirs, dataprovider.PermUpload}
  717. permissions["/dir6"] = []string{dataprovider.PermCreateDirs, dataprovider.PermUpload,
  718. dataprovider.PermListItems, dataprovider.PermCreateSymlinks}
  719. permissions["/dir7"] = []string{dataprovider.PermAny}
  720. permissions["/dir8"] = []string{dataprovider.PermAny}
  721. user := dataprovider.User{
  722. Username: userTestUsername,
  723. Permissions: permissions,
  724. HomeDir: os.TempDir(),
  725. }
  726. fs, err := user.GetFilesystem("123")
  727. assert.NoError(t, err)
  728. conn := NewBaseConnection("", ProtocolSFTP, user, fs)
  729. request := sftp.NewRequest("Rename", "/testfile")
  730. request.Target = "/dir1/testfile"
  731. // rename is granted on Source and Target
  732. assert.True(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  733. request.Target = "/dir4/testfile"
  734. // rename is not granted on Target
  735. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  736. request = sftp.NewRequest("Rename", "/dir1/testfile")
  737. request.Target = "/dir2/testfile" //nolint:goconst
  738. // rename is granted on Source but not on Target
  739. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  740. request = sftp.NewRequest("Rename", "/dir4/testfile")
  741. request.Target = "/dir1/testfile"
  742. // rename is granted on Target but not on Source
  743. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  744. request = sftp.NewRequest("Rename", "/dir4/testfile")
  745. request.Target = "/testfile"
  746. // rename is granted on Target but not on Source
  747. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  748. request = sftp.NewRequest("Rename", "/dir3/testfile")
  749. request.Target = "/dir2/testfile"
  750. // delete is granted on Source and Upload on Target, the target is a file this is enough
  751. assert.True(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  752. request = sftp.NewRequest("Rename", "/dir2/testfile")
  753. request.Target = "/dir3/testfile"
  754. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  755. tmpDir := filepath.Join(os.TempDir(), "dir")
  756. tmpDirLink := filepath.Join(os.TempDir(), "link")
  757. err = os.Mkdir(tmpDir, os.ModePerm)
  758. assert.NoError(t, err)
  759. err = os.Symlink(tmpDir, tmpDirLink)
  760. assert.NoError(t, err)
  761. request.Filepath = "/dir"
  762. request.Target = "/dir2/dir"
  763. // the source is a dir and the target has no createDirs perm
  764. info, err := os.Lstat(tmpDir)
  765. if assert.NoError(t, err) {
  766. assert.False(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info))
  767. conn.User.Permissions["/dir2"] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs}
  768. // the source is a dir and the target has createDirs perm
  769. assert.True(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info))
  770. request = sftp.NewRequest("Rename", "/testfile")
  771. request.Target = "/dir5/testfile"
  772. // the source is a dir and the target has createDirs and upload perm
  773. assert.True(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info))
  774. }
  775. info, err = os.Lstat(tmpDirLink)
  776. if assert.NoError(t, err) {
  777. assert.True(t, info.Mode()&os.ModeSymlink != 0)
  778. // the source is a symlink and the target has createDirs and upload perm
  779. assert.False(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info))
  780. }
  781. err = os.RemoveAll(tmpDir)
  782. assert.NoError(t, err)
  783. err = os.Remove(tmpDirLink)
  784. assert.NoError(t, err)
  785. conn.User.VirtualFolders = append(conn.User.VirtualFolders, vfs.VirtualFolder{
  786. BaseVirtualFolder: vfs.BaseVirtualFolder{
  787. MappedPath: os.TempDir(),
  788. },
  789. VirtualPath: "/dir1",
  790. })
  791. request = sftp.NewRequest("Rename", "/dir1")
  792. request.Target = "/dir2/testfile"
  793. // renaming a virtual folder is not allowed
  794. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  795. err = conn.checkRecursiveRenameDirPermissions("invalid", "invalid")
  796. assert.Error(t, err)
  797. dir3 := filepath.Join(conn.User.HomeDir, "dir3")
  798. dir6 := filepath.Join(conn.User.HomeDir, "dir6")
  799. err = os.MkdirAll(filepath.Join(dir3, "subdir"), os.ModePerm)
  800. assert.NoError(t, err)
  801. err = ioutil.WriteFile(filepath.Join(dir3, "subdir", "testfile"), []byte("test"), os.ModePerm)
  802. assert.NoError(t, err)
  803. err = conn.checkRecursiveRenameDirPermissions(dir3, dir6)
  804. assert.NoError(t, err)
  805. err = os.RemoveAll(dir3)
  806. assert.NoError(t, err)
  807. dir7 := filepath.Join(conn.User.HomeDir, "dir7")
  808. dir8 := filepath.Join(conn.User.HomeDir, "dir8")
  809. err = os.MkdirAll(filepath.Join(dir8, "subdir"), os.ModePerm)
  810. assert.NoError(t, err)
  811. err = ioutil.WriteFile(filepath.Join(dir8, "subdir", "testfile"), []byte("test"), os.ModePerm)
  812. assert.NoError(t, err)
  813. err = conn.checkRecursiveRenameDirPermissions(dir8, dir7)
  814. assert.NoError(t, err)
  815. err = os.RemoveAll(dir8)
  816. assert.NoError(t, err)
  817. assert.False(t, conn.isRenamePermitted(user.GetHomeDir(), "", "", nil))
  818. conn.User.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  819. {
  820. Path: "/p",
  821. AllowedExtensions: []string{},
  822. DeniedExtensions: []string{".zip"},
  823. },
  824. }
  825. testFile := filepath.Join(user.HomeDir, "testfile")
  826. err = ioutil.WriteFile(testFile, []byte("data"), os.ModePerm)
  827. assert.NoError(t, err)
  828. info, err = os.Stat(testFile)
  829. assert.NoError(t, err)
  830. assert.False(t, conn.isRenamePermitted(dir7, "/file", "/p/file.zip", info))
  831. err = os.Remove(testFile)
  832. assert.NoError(t, err)
  833. }
  834. func TestHasSpaceForRename(t *testing.T) {
  835. err := closeDataprovider()
  836. assert.NoError(t, err)
  837. _, err = initializeDataprovider(0)
  838. assert.NoError(t, err)
  839. user := dataprovider.User{
  840. Username: userTestUsername,
  841. HomeDir: filepath.Join(os.TempDir(), "home"),
  842. }
  843. mappedPath := filepath.Join(os.TempDir(), "vdir")
  844. user.Permissions = make(map[string][]string)
  845. user.Permissions["/"] = []string{dataprovider.PermAny}
  846. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  847. BaseVirtualFolder: vfs.BaseVirtualFolder{
  848. MappedPath: mappedPath,
  849. },
  850. VirtualPath: "/vdir1",
  851. })
  852. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  853. BaseVirtualFolder: vfs.BaseVirtualFolder{
  854. MappedPath: mappedPath,
  855. },
  856. VirtualPath: "/vdir2",
  857. QuotaSize: -1,
  858. QuotaFiles: -1,
  859. })
  860. fs, err := user.GetFilesystem("id")
  861. assert.NoError(t, err)
  862. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  863. // with quota tracking disabled hasSpaceForRename will always return true
  864. assert.True(t, c.hasSpaceForRename("", "", 0, ""))
  865. quotaResult := c.HasSpace(true, "")
  866. assert.True(t, quotaResult.HasSpace)
  867. err = closeDataprovider()
  868. assert.NoError(t, err)
  869. _, err = initializeDataprovider(-1)
  870. assert.NoError(t, err)
  871. // rename inside the same mapped path
  872. assert.True(t, c.hasSpaceForRename("/vdir1/file", "/vdir2/file", 0, filepath.Join(mappedPath, "file")))
  873. // rename between user root dir and a virtual folder included in user quota
  874. assert.True(t, c.hasSpaceForRename("/file", "/vdir2/file", 0, filepath.Join(mappedPath, "file")))
  875. assert.True(t, c.isCrossFoldersRequest("/file", "/vdir2/file"))
  876. }
  877. func TestUpdateQuotaAfterRename(t *testing.T) {
  878. user := dataprovider.User{
  879. Username: userTestUsername,
  880. HomeDir: filepath.Join(os.TempDir(), "home"),
  881. }
  882. mappedPath := filepath.Join(os.TempDir(), "vdir")
  883. user.Permissions = make(map[string][]string)
  884. user.Permissions["/"] = []string{dataprovider.PermAny}
  885. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  886. BaseVirtualFolder: vfs.BaseVirtualFolder{
  887. MappedPath: mappedPath,
  888. },
  889. VirtualPath: "/vdir",
  890. QuotaFiles: -1,
  891. QuotaSize: -1,
  892. })
  893. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  894. BaseVirtualFolder: vfs.BaseVirtualFolder{
  895. MappedPath: mappedPath,
  896. },
  897. VirtualPath: "/vdir1",
  898. QuotaFiles: -1,
  899. QuotaSize: -1,
  900. })
  901. err := os.MkdirAll(user.GetHomeDir(), os.ModePerm)
  902. assert.NoError(t, err)
  903. err = os.MkdirAll(mappedPath, os.ModePerm)
  904. assert.NoError(t, err)
  905. fs, err := user.GetFilesystem("id")
  906. assert.NoError(t, err)
  907. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  908. request := sftp.NewRequest("Rename", "/testfile")
  909. if runtime.GOOS != osWindows {
  910. request.Filepath = "/dir"
  911. request.Target = path.Join("/vdir", "dir")
  912. testDirPath := filepath.Join(mappedPath, "dir")
  913. err := os.MkdirAll(testDirPath, os.ModePerm)
  914. assert.NoError(t, err)
  915. err = os.Chmod(testDirPath, 0001)
  916. assert.NoError(t, err)
  917. err = c.updateQuotaAfterRename(request.Filepath, request.Target, testDirPath, 0)
  918. assert.Error(t, err)
  919. err = os.Chmod(testDirPath, os.ModePerm)
  920. assert.NoError(t, err)
  921. }
  922. testFile1 := "/testfile1"
  923. request.Target = testFile1
  924. request.Filepath = path.Join("/vdir", "file")
  925. err = c.updateQuotaAfterRename(request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 0)
  926. assert.Error(t, err)
  927. err = ioutil.WriteFile(filepath.Join(mappedPath, "file"), []byte("test content"), os.ModePerm)
  928. assert.NoError(t, err)
  929. request.Filepath = testFile1
  930. request.Target = path.Join("/vdir", "file")
  931. err = c.updateQuotaAfterRename(request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 12)
  932. assert.NoError(t, err)
  933. err = ioutil.WriteFile(filepath.Join(user.GetHomeDir(), "testfile1"), []byte("test content"), os.ModePerm)
  934. assert.NoError(t, err)
  935. request.Target = testFile1
  936. request.Filepath = path.Join("/vdir", "file")
  937. err = c.updateQuotaAfterRename(request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 12)
  938. assert.NoError(t, err)
  939. request.Target = path.Join("/vdir1", "file")
  940. request.Filepath = path.Join("/vdir", "file")
  941. err = c.updateQuotaAfterRename(request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 12)
  942. assert.NoError(t, err)
  943. err = os.RemoveAll(mappedPath)
  944. assert.NoError(t, err)
  945. err = os.RemoveAll(user.GetHomeDir())
  946. assert.NoError(t, err)
  947. }
  948. func TestHasSpace(t *testing.T) {
  949. user := dataprovider.User{
  950. Username: userTestUsername,
  951. HomeDir: filepath.Join(os.TempDir(), "home"),
  952. Password: userTestPwd,
  953. }
  954. mappedPath := filepath.Join(os.TempDir(), "vdir")
  955. user.Permissions = make(map[string][]string)
  956. user.Permissions["/"] = []string{dataprovider.PermAny}
  957. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  958. BaseVirtualFolder: vfs.BaseVirtualFolder{
  959. MappedPath: mappedPath,
  960. },
  961. VirtualPath: "/vdir",
  962. QuotaFiles: -1,
  963. QuotaSize: -1,
  964. })
  965. fs, err := user.GetFilesystem("id")
  966. assert.NoError(t, err)
  967. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  968. quotaResult := c.HasSpace(true, "/")
  969. assert.True(t, quotaResult.HasSpace)
  970. user.VirtualFolders[0].QuotaFiles = 0
  971. user.VirtualFolders[0].QuotaSize = 0
  972. err = dataprovider.AddUser(user)
  973. assert.NoError(t, err)
  974. user, err = dataprovider.UserExists(user.Username)
  975. assert.NoError(t, err)
  976. c.User = user
  977. quotaResult = c.HasSpace(true, "/vdir/file")
  978. assert.True(t, quotaResult.HasSpace)
  979. user.VirtualFolders[0].QuotaFiles = 10
  980. user.VirtualFolders[0].QuotaSize = 1048576
  981. err = dataprovider.UpdateUser(user)
  982. assert.NoError(t, err)
  983. c.User = user
  984. quotaResult = c.HasSpace(true, "/vdir/file1")
  985. assert.True(t, quotaResult.HasSpace)
  986. quotaResult = c.HasSpace(true, "/file")
  987. assert.True(t, quotaResult.HasSpace)
  988. folder, err := dataprovider.GetFolderByPath(mappedPath)
  989. assert.NoError(t, err)
  990. err = dataprovider.UpdateVirtualFolderQuota(folder, 10, 1048576, true)
  991. assert.NoError(t, err)
  992. quotaResult = c.HasSpace(true, "/vdir/file1")
  993. assert.False(t, quotaResult.HasSpace)
  994. err = dataprovider.DeleteUser(user)
  995. assert.NoError(t, err)
  996. err = dataprovider.DeleteFolder(folder)
  997. assert.NoError(t, err)
  998. }
  999. func TestUpdateQuotaMoveVFolders(t *testing.T) {
  1000. user := dataprovider.User{
  1001. Username: userTestUsername,
  1002. HomeDir: filepath.Join(os.TempDir(), "home"),
  1003. Password: userTestPwd,
  1004. QuotaFiles: 100,
  1005. }
  1006. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  1007. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  1008. user.Permissions = make(map[string][]string)
  1009. user.Permissions["/"] = []string{dataprovider.PermAny}
  1010. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  1011. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1012. MappedPath: mappedPath1,
  1013. },
  1014. VirtualPath: "/vdir1",
  1015. QuotaFiles: -1,
  1016. QuotaSize: -1,
  1017. })
  1018. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  1019. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1020. MappedPath: mappedPath2,
  1021. },
  1022. VirtualPath: "/vdir2",
  1023. QuotaFiles: -1,
  1024. QuotaSize: -1,
  1025. })
  1026. err := dataprovider.AddUser(user)
  1027. assert.NoError(t, err)
  1028. user, err = dataprovider.UserExists(user.Username)
  1029. assert.NoError(t, err)
  1030. folder1, err := dataprovider.GetFolderByPath(mappedPath1)
  1031. assert.NoError(t, err)
  1032. folder2, err := dataprovider.GetFolderByPath(mappedPath2)
  1033. assert.NoError(t, err)
  1034. err = dataprovider.UpdateVirtualFolderQuota(folder1, 1, 100, true)
  1035. assert.NoError(t, err)
  1036. err = dataprovider.UpdateVirtualFolderQuota(folder2, 2, 150, true)
  1037. assert.NoError(t, err)
  1038. fs, err := user.GetFilesystem("id")
  1039. assert.NoError(t, err)
  1040. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  1041. c.updateQuotaMoveBetweenVFolders(user.VirtualFolders[0], user.VirtualFolders[1], -1, 100, 1)
  1042. folder1, err = dataprovider.GetFolderByPath(mappedPath1)
  1043. assert.NoError(t, err)
  1044. assert.Equal(t, 0, folder1.UsedQuotaFiles)
  1045. assert.Equal(t, int64(0), folder1.UsedQuotaSize)
  1046. folder2, err = dataprovider.GetFolderByPath(mappedPath2)
  1047. assert.NoError(t, err)
  1048. assert.Equal(t, 3, folder2.UsedQuotaFiles)
  1049. assert.Equal(t, int64(250), folder2.UsedQuotaSize)
  1050. c.updateQuotaMoveBetweenVFolders(user.VirtualFolders[1], user.VirtualFolders[0], 10, 100, 1)
  1051. folder1, err = dataprovider.GetFolderByPath(mappedPath1)
  1052. assert.NoError(t, err)
  1053. assert.Equal(t, 0, folder1.UsedQuotaFiles)
  1054. assert.Equal(t, int64(90), folder1.UsedQuotaSize)
  1055. folder2, err = dataprovider.GetFolderByPath(mappedPath2)
  1056. assert.NoError(t, err)
  1057. assert.Equal(t, 2, folder2.UsedQuotaFiles)
  1058. assert.Equal(t, int64(150), folder2.UsedQuotaSize)
  1059. err = dataprovider.UpdateUserQuota(user, 1, 100, true)
  1060. assert.NoError(t, err)
  1061. c.updateQuotaMoveFromVFolder(user.VirtualFolders[1], -1, 50, 1)
  1062. folder2, err = dataprovider.GetFolderByPath(mappedPath2)
  1063. assert.NoError(t, err)
  1064. assert.Equal(t, 1, folder2.UsedQuotaFiles)
  1065. assert.Equal(t, int64(100), folder2.UsedQuotaSize)
  1066. user, err = dataprovider.GetUserByID(user.ID)
  1067. assert.NoError(t, err)
  1068. assert.Equal(t, 1, user.UsedQuotaFiles)
  1069. assert.Equal(t, int64(100), user.UsedQuotaSize)
  1070. c.updateQuotaMoveToVFolder(user.VirtualFolders[1], -1, 100, 1)
  1071. folder2, err = dataprovider.GetFolderByPath(mappedPath2)
  1072. assert.NoError(t, err)
  1073. assert.Equal(t, 2, folder2.UsedQuotaFiles)
  1074. assert.Equal(t, int64(200), folder2.UsedQuotaSize)
  1075. user, err = dataprovider.GetUserByID(user.ID)
  1076. assert.NoError(t, err)
  1077. assert.Equal(t, 1, user.UsedQuotaFiles)
  1078. assert.Equal(t, int64(100), user.UsedQuotaSize)
  1079. err = dataprovider.DeleteUser(user)
  1080. assert.NoError(t, err)
  1081. err = dataprovider.DeleteFolder(folder1)
  1082. assert.NoError(t, err)
  1083. err = dataprovider.DeleteFolder(folder2)
  1084. assert.NoError(t, err)
  1085. }
  1086. func TestErrorsMapping(t *testing.T) {
  1087. fs := vfs.NewOsFs("", os.TempDir(), nil)
  1088. conn := NewBaseConnection("", ProtocolSFTP, dataprovider.User{}, fs)
  1089. for _, protocol := range supportedProtocols {
  1090. conn.SetProtocol(protocol)
  1091. err := conn.GetFsError(os.ErrNotExist)
  1092. if protocol == ProtocolSFTP {
  1093. assert.EqualError(t, err, sftp.ErrSSHFxNoSuchFile.Error())
  1094. } else if protocol == ProtocolWebDAV {
  1095. assert.EqualError(t, err, os.ErrNotExist.Error())
  1096. } else {
  1097. assert.EqualError(t, err, ErrNotExist.Error())
  1098. }
  1099. err = conn.GetFsError(os.ErrPermission)
  1100. if protocol == ProtocolSFTP {
  1101. assert.EqualError(t, err, sftp.ErrSSHFxPermissionDenied.Error())
  1102. } else {
  1103. assert.EqualError(t, err, ErrPermissionDenied.Error())
  1104. }
  1105. err = conn.GetFsError(os.ErrClosed)
  1106. if protocol == ProtocolSFTP {
  1107. assert.EqualError(t, err, sftp.ErrSSHFxFailure.Error())
  1108. } else {
  1109. assert.EqualError(t, err, ErrGenericFailure.Error())
  1110. }
  1111. err = conn.GetFsError(ErrPermissionDenied)
  1112. if protocol == ProtocolSFTP {
  1113. assert.EqualError(t, err, sftp.ErrSSHFxFailure.Error())
  1114. } else {
  1115. assert.EqualError(t, err, ErrPermissionDenied.Error())
  1116. }
  1117. err = conn.GetFsError(vfs.ErrVfsUnsupported)
  1118. if protocol == ProtocolSFTP {
  1119. assert.EqualError(t, err, sftp.ErrSSHFxOpUnsupported.Error())
  1120. } else {
  1121. assert.EqualError(t, err, ErrOpUnsupported.Error())
  1122. }
  1123. err = conn.GetFsError(nil)
  1124. assert.NoError(t, err)
  1125. err = conn.GetOpUnsupportedError()
  1126. if protocol == ProtocolSFTP {
  1127. assert.EqualError(t, err, sftp.ErrSSHFxOpUnsupported.Error())
  1128. } else {
  1129. assert.EqualError(t, err, ErrOpUnsupported.Error())
  1130. }
  1131. }
  1132. }
  1133. func TestMaxWriteSize(t *testing.T) {
  1134. permissions := make(map[string][]string)
  1135. permissions["/"] = []string{dataprovider.PermAny}
  1136. user := dataprovider.User{
  1137. Username: userTestUsername,
  1138. Permissions: permissions,
  1139. HomeDir: filepath.Clean(os.TempDir()),
  1140. }
  1141. fs, err := user.GetFilesystem("123")
  1142. assert.NoError(t, err)
  1143. conn := NewBaseConnection("", ProtocolFTP, user, fs)
  1144. quotaResult := vfs.QuotaCheckResult{
  1145. HasSpace: true,
  1146. }
  1147. size, err := conn.GetMaxWriteSize(quotaResult, false, 0)
  1148. assert.NoError(t, err)
  1149. assert.Equal(t, int64(0), size)
  1150. conn.User.Filters.MaxUploadFileSize = 100
  1151. size, err = conn.GetMaxWriteSize(quotaResult, false, 0)
  1152. assert.NoError(t, err)
  1153. assert.Equal(t, int64(100), size)
  1154. quotaResult.QuotaSize = 1000
  1155. size, err = conn.GetMaxWriteSize(quotaResult, false, 50)
  1156. assert.NoError(t, err)
  1157. assert.Equal(t, int64(100), size)
  1158. quotaResult.QuotaSize = 1000
  1159. quotaResult.UsedSize = 990
  1160. size, err = conn.GetMaxWriteSize(quotaResult, false, 50)
  1161. assert.NoError(t, err)
  1162. assert.Equal(t, int64(60), size)
  1163. quotaResult.QuotaSize = 0
  1164. quotaResult.UsedSize = 0
  1165. size, err = conn.GetMaxWriteSize(quotaResult, true, 100)
  1166. assert.EqualError(t, err, ErrQuotaExceeded.Error())
  1167. assert.Equal(t, int64(0), size)
  1168. size, err = conn.GetMaxWriteSize(quotaResult, true, 10)
  1169. assert.NoError(t, err)
  1170. assert.Equal(t, int64(90), size)
  1171. conn.Fs = newMockOsFs(true, fs.ConnectionID(), user.GetHomeDir())
  1172. size, err = conn.GetMaxWriteSize(quotaResult, true, 100)
  1173. assert.EqualError(t, err, ErrOpUnsupported.Error())
  1174. assert.Equal(t, int64(0), size)
  1175. }