ftpd_test.go 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107
  1. package ftpd_test
  2. import (
  3. "crypto/rand"
  4. "crypto/sha256"
  5. "crypto/tls"
  6. "encoding/hex"
  7. "encoding/json"
  8. "fmt"
  9. "io"
  10. "io/ioutil"
  11. "net"
  12. "net/http"
  13. "os"
  14. "os/exec"
  15. "path"
  16. "path/filepath"
  17. "runtime"
  18. "testing"
  19. "time"
  20. "github.com/jlaffaye/ftp"
  21. "github.com/rs/zerolog"
  22. "github.com/stretchr/testify/assert"
  23. "github.com/stretchr/testify/require"
  24. "github.com/drakkan/sftpgo/common"
  25. "github.com/drakkan/sftpgo/config"
  26. "github.com/drakkan/sftpgo/dataprovider"
  27. "github.com/drakkan/sftpgo/ftpd"
  28. "github.com/drakkan/sftpgo/httpd"
  29. "github.com/drakkan/sftpgo/kms"
  30. "github.com/drakkan/sftpgo/logger"
  31. "github.com/drakkan/sftpgo/sftpd"
  32. "github.com/drakkan/sftpgo/vfs"
  33. )
  34. const (
  35. logSender = "ftpdTesting"
  36. ftpServerAddr = "127.0.0.1:2121"
  37. sftpServerAddr = "127.0.0.1:2122"
  38. ftpSrvAddrTLS = "127.0.0.1:2124" // ftp server with implicit tls
  39. defaultUsername = "test_user_ftp"
  40. defaultPassword = "test_password"
  41. configDir = ".."
  42. osWindows = "windows"
  43. ftpsCert = `-----BEGIN CERTIFICATE-----
  44. MIICHTCCAaKgAwIBAgIUHnqw7QnB1Bj9oUsNpdb+ZkFPOxMwCgYIKoZIzj0EAwIw
  45. RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
  46. dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDAyMDQwOTUzMDRaFw0zMDAyMDEw
  47. OTUzMDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD
  48. VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwdjAQBgcqhkjOPQIBBgUrgQQA
  49. IgNiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVqWvrJ51t5OxV0v25NsOgR82CA
  50. NXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIVCzgWkxiz7XE4lgUwX44FCXZM
  51. 3+JeUbKjUzBRMB0GA1UdDgQWBBRhLw+/o3+Z02MI/d4tmaMui9W16jAfBgNVHSME
  52. GDAWgBRhLw+/o3+Z02MI/d4tmaMui9W16jAPBgNVHRMBAf8EBTADAQH/MAoGCCqG
  53. SM49BAMCA2kAMGYCMQDqLt2lm8mE+tGgtjDmtFgdOcI72HSbRQ74D5rYTzgST1rY
  54. /8wTi5xl8TiFUyLMUsICMQC5ViVxdXbhuG7gX6yEqSkMKZICHpO8hqFwOD/uaFVI
  55. dV4vKmHUzwK/eIx+8Ay3neE=
  56. -----END CERTIFICATE-----`
  57. ftpsKey = `-----BEGIN EC PARAMETERS-----
  58. BgUrgQQAIg==
  59. -----END EC PARAMETERS-----
  60. -----BEGIN EC PRIVATE KEY-----
  61. MIGkAgEBBDCfMNsN6miEE3rVyUPwElfiJSWaR5huPCzUenZOfJT04GAcQdWvEju3
  62. UM2lmBLIXpGgBwYFK4EEACKhZANiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVq
  63. WvrJ51t5OxV0v25NsOgR82CANXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIV
  64. CzgWkxiz7XE4lgUwX44FCXZM3+JeUbI=
  65. -----END EC PRIVATE KEY-----`
  66. testFileName = "test_file_ftp.dat"
  67. testDLFileName = "test_download_ftp.dat"
  68. )
  69. var (
  70. allPerms = []string{dataprovider.PermAny}
  71. homeBasePath string
  72. hookCmdPath string
  73. extAuthPath string
  74. preLoginPath string
  75. postConnectPath string
  76. logFilePath string
  77. )
  78. func TestMain(m *testing.M) {
  79. logFilePath = filepath.Join(configDir, "sftpgo_ftpd_test.log")
  80. bannerFileName := "banner_file"
  81. bannerFile := filepath.Join(configDir, bannerFileName)
  82. logger.InitLogger(logFilePath, 5, 1, 28, false, zerolog.DebugLevel)
  83. err := ioutil.WriteFile(bannerFile, []byte("SFTPGo test ready\nsimple banner line\n"), os.ModePerm)
  84. if err != nil {
  85. logger.ErrorToConsole("error creating banner file: %v", err)
  86. }
  87. err = config.LoadConfig(configDir, "")
  88. if err != nil {
  89. logger.ErrorToConsole("error loading configuration: %v", err)
  90. os.Exit(1)
  91. }
  92. providerConf := config.GetProviderConf()
  93. logger.InfoToConsole("Starting FTPD tests, provider: %v", providerConf.Driver)
  94. commonConf := config.GetCommonConfig()
  95. // we run the test cases with UploadMode atomic and resume support. The non atomic code path
  96. // simply does not execute some code so if it works in atomic mode will
  97. // work in non atomic mode too
  98. commonConf.UploadMode = 2
  99. homeBasePath = os.TempDir()
  100. if runtime.GOOS != osWindows {
  101. commonConf.Actions.ExecuteOn = []string{"download", "upload", "rename", "delete"}
  102. commonConf.Actions.Hook = hookCmdPath
  103. hookCmdPath, err = exec.LookPath("true")
  104. if err != nil {
  105. logger.Warn(logSender, "", "unable to get hook command: %v", err)
  106. logger.WarnToConsole("unable to get hook command: %v", err)
  107. }
  108. }
  109. certPath := filepath.Join(os.TempDir(), "test_ftpd.crt")
  110. keyPath := filepath.Join(os.TempDir(), "test_ftpd.key")
  111. err = ioutil.WriteFile(certPath, []byte(ftpsCert), os.ModePerm)
  112. if err != nil {
  113. logger.ErrorToConsole("error writing FTPS certificate: %v", err)
  114. os.Exit(1)
  115. }
  116. err = ioutil.WriteFile(keyPath, []byte(ftpsKey), os.ModePerm)
  117. if err != nil {
  118. logger.ErrorToConsole("error writing FTPS private key: %v", err)
  119. os.Exit(1)
  120. }
  121. common.Initialize(commonConf)
  122. err = dataprovider.Initialize(providerConf, configDir)
  123. if err != nil {
  124. logger.ErrorToConsole("error initializing data provider: %v", err)
  125. os.Exit(1)
  126. }
  127. httpConfig := config.GetHTTPConfig()
  128. httpConfig.Initialize(configDir)
  129. kmsConfig := config.GetKMSConfig()
  130. err = kmsConfig.Initialize()
  131. if err != nil {
  132. logger.ErrorToConsole("error initializing kms: %v", err)
  133. os.Exit(1)
  134. }
  135. httpdConf := config.GetHTTPDConfig()
  136. httpdConf.BindPort = 8079
  137. httpd.SetBaseURLAndCredentials("http://127.0.0.1:8079", "", "")
  138. ftpdConf := config.GetFTPDConfig()
  139. ftpdConf.Bindings = []ftpd.Binding{
  140. {
  141. Port: 2121,
  142. },
  143. }
  144. ftpdConf.PassivePortRange.Start = 0
  145. ftpdConf.PassivePortRange.End = 0
  146. ftpdConf.BannerFile = bannerFileName
  147. ftpdConf.CertificateFile = certPath
  148. ftpdConf.CertificateKeyFile = keyPath
  149. ftpdConf.EnableSite = true
  150. // required to test sftpfs
  151. sftpdConf := config.GetSFTPDConfig()
  152. sftpdConf.Bindings = []sftpd.Binding{
  153. {
  154. Port: 2122,
  155. },
  156. }
  157. hostKeyPath := filepath.Join(os.TempDir(), "id_ed25519")
  158. sftpdConf.HostKeys = []string{hostKeyPath}
  159. extAuthPath = filepath.Join(homeBasePath, "extauth.sh")
  160. preLoginPath = filepath.Join(homeBasePath, "prelogin.sh")
  161. postConnectPath = filepath.Join(homeBasePath, "postconnect.sh")
  162. status := ftpd.GetStatus()
  163. if status.IsActive {
  164. logger.ErrorToConsole("ftpd is already active")
  165. os.Exit(1)
  166. }
  167. go func() {
  168. logger.Debug(logSender, "", "initializing FTP server with config %+v", ftpdConf)
  169. if err := ftpdConf.Initialize(configDir); err != nil {
  170. logger.ErrorToConsole("could not start FTP server: %v", err)
  171. os.Exit(1)
  172. }
  173. }()
  174. go func() {
  175. logger.Debug(logSender, "", "initializing SFTP server with config %+v", sftpdConf)
  176. if err := sftpdConf.Initialize(configDir); err != nil {
  177. logger.ErrorToConsole("could not start SFTP server: %v", err)
  178. os.Exit(1)
  179. }
  180. }()
  181. go func() {
  182. if err := httpdConf.Initialize(configDir); err != nil {
  183. logger.ErrorToConsole("could not start HTTP server: %v", err)
  184. os.Exit(1)
  185. }
  186. }()
  187. waitTCPListening(ftpdConf.Bindings[0].GetAddress())
  188. waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
  189. waitTCPListening(sftpdConf.Bindings[0].GetAddress())
  190. ftpd.ReloadTLSCertificate() //nolint:errcheck
  191. ftpdConf = config.GetFTPDConfig()
  192. ftpdConf.Bindings = []ftpd.Binding{
  193. {
  194. Port: 2124,
  195. TLSMode: 2,
  196. },
  197. }
  198. ftpdConf.CertificateFile = certPath
  199. ftpdConf.CertificateKeyFile = keyPath
  200. ftpdConf.EnableSite = false
  201. ftpdConf.DisableActiveMode = true
  202. ftpdConf.CombineSupport = 1
  203. ftpdConf.HASHSupport = 1
  204. go func() {
  205. logger.Debug(logSender, "", "initializing FTP server with config %+v", ftpdConf)
  206. if err := ftpdConf.Initialize(configDir); err != nil {
  207. logger.ErrorToConsole("could not start FTP server: %v", err)
  208. os.Exit(1)
  209. }
  210. }()
  211. waitTCPListening(ftpdConf.Bindings[0].GetAddress())
  212. // ensure all the initial connections to check if the service is alive are disconnected
  213. for len(common.Connections.GetStats()) > 0 {
  214. time.Sleep(50 * time.Millisecond)
  215. }
  216. exitCode := m.Run()
  217. os.Remove(logFilePath)
  218. os.Remove(bannerFile)
  219. os.Remove(extAuthPath)
  220. os.Remove(preLoginPath)
  221. os.Remove(postConnectPath)
  222. os.Remove(certPath)
  223. os.Remove(keyPath)
  224. os.Remove(hostKeyPath)
  225. os.Remove(hostKeyPath + ".pub")
  226. os.Exit(exitCode)
  227. }
  228. func TestInitializationFailure(t *testing.T) {
  229. ftpdConf := config.GetFTPDConfig()
  230. ftpdConf.Bindings = []ftpd.Binding{}
  231. ftpdConf.CertificateFile = filepath.Join(os.TempDir(), "test_ftpd.crt")
  232. ftpdConf.CertificateKeyFile = filepath.Join(os.TempDir(), "test_ftpd.key")
  233. err := ftpdConf.Initialize(configDir)
  234. require.EqualError(t, err, common.ErrNoBinding.Error())
  235. ftpdConf.Bindings = []ftpd.Binding{
  236. {
  237. Port: 0,
  238. },
  239. {
  240. Port: 2121,
  241. },
  242. }
  243. ftpdConf.BannerFile = "a-missing-file"
  244. err = ftpdConf.Initialize(configDir)
  245. require.Error(t, err)
  246. ftpdConf.BannerFile = ""
  247. ftpdConf.Bindings[1].TLSMode = 10
  248. err = ftpdConf.Initialize(configDir)
  249. require.Error(t, err)
  250. ftpdConf.CertificateFile = ""
  251. ftpdConf.CertificateKeyFile = ""
  252. ftpdConf.Bindings[1].TLSMode = 1
  253. err = ftpdConf.Initialize(configDir)
  254. require.Error(t, err)
  255. }
  256. func TestBasicFTPHandling(t *testing.T) {
  257. u := getTestUser()
  258. u.QuotaSize = 6553600
  259. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  260. assert.NoError(t, err)
  261. u = getTestSFTPUser()
  262. u.QuotaSize = 6553600
  263. sftpUser, _, err := httpd.AddUser(u, http.StatusOK)
  264. assert.NoError(t, err)
  265. for _, user := range []dataprovider.User{localUser, sftpUser} {
  266. client, err := getFTPClient(user, true)
  267. if assert.NoError(t, err) {
  268. if user.Username == defaultUsername {
  269. assert.Len(t, common.Connections.GetStats(), 1)
  270. } else {
  271. assert.Len(t, common.Connections.GetStats(), 2)
  272. }
  273. testFilePath := filepath.Join(homeBasePath, testFileName)
  274. testFileSize := int64(65535)
  275. expectedQuotaSize := testFileSize
  276. expectedQuotaFiles := 1
  277. err = createTestFile(testFilePath, testFileSize)
  278. assert.NoError(t, err)
  279. err = checkBasicFTP(client)
  280. assert.NoError(t, err)
  281. err = ftpUploadFile(testFilePath, path.Join("/missing_dir", testFileName), testFileSize, client, 0)
  282. assert.Error(t, err)
  283. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  284. assert.NoError(t, err)
  285. // overwrite an existing file
  286. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  287. assert.NoError(t, err)
  288. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  289. err = ftpDownloadFile(testFileName, localDownloadPath, testFileSize, client, 0)
  290. assert.NoError(t, err)
  291. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  292. assert.NoError(t, err)
  293. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  294. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  295. err = client.Rename(testFileName, testFileName+"1")
  296. assert.NoError(t, err)
  297. err = client.Delete(testFileName)
  298. assert.Error(t, err)
  299. err = client.Delete(testFileName + "1")
  300. assert.NoError(t, err)
  301. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  302. assert.NoError(t, err)
  303. assert.Equal(t, expectedQuotaFiles-1, user.UsedQuotaFiles)
  304. assert.Equal(t, expectedQuotaSize-testFileSize, user.UsedQuotaSize)
  305. curDir, err := client.CurrentDir()
  306. if assert.NoError(t, err) {
  307. assert.Equal(t, "/", curDir)
  308. }
  309. testDir := "testDir"
  310. err = client.MakeDir(testDir)
  311. assert.NoError(t, err)
  312. err = client.ChangeDir(testDir)
  313. assert.NoError(t, err)
  314. curDir, err = client.CurrentDir()
  315. if assert.NoError(t, err) {
  316. assert.Equal(t, path.Join("/", testDir), curDir)
  317. }
  318. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  319. assert.NoError(t, err)
  320. size, err := client.FileSize(path.Join("/", testDir, testFileName))
  321. assert.NoError(t, err)
  322. assert.Equal(t, testFileSize, size)
  323. err = client.ChangeDirToParent()
  324. assert.NoError(t, err)
  325. curDir, err = client.CurrentDir()
  326. if assert.NoError(t, err) {
  327. assert.Equal(t, "/", curDir)
  328. }
  329. err = client.Delete(path.Join("/", testDir, testFileName))
  330. assert.NoError(t, err)
  331. err = client.Delete(testDir)
  332. assert.Error(t, err)
  333. err = client.RemoveDir(testDir)
  334. assert.NoError(t, err)
  335. err = os.Remove(testFilePath)
  336. assert.NoError(t, err)
  337. err = os.Remove(localDownloadPath)
  338. assert.NoError(t, err)
  339. err = client.Quit()
  340. assert.NoError(t, err)
  341. }
  342. }
  343. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  344. assert.NoError(t, err)
  345. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  346. assert.NoError(t, err)
  347. err = os.RemoveAll(localUser.GetHomeDir())
  348. assert.NoError(t, err)
  349. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 }, 1*time.Second, 50*time.Millisecond)
  350. }
  351. func TestLoginInvalidPwd(t *testing.T) {
  352. u := getTestUser()
  353. user, _, err := httpd.AddUser(u, http.StatusOK)
  354. assert.NoError(t, err)
  355. user.Password = "wrong"
  356. _, err = getFTPClient(user, false)
  357. assert.Error(t, err)
  358. _, err = httpd.RemoveUser(user, http.StatusOK)
  359. assert.NoError(t, err)
  360. }
  361. func TestLoginExternalAuth(t *testing.T) {
  362. if runtime.GOOS == osWindows {
  363. t.Skip("this test is not available on Windows")
  364. }
  365. u := getTestUser()
  366. err := dataprovider.Close()
  367. assert.NoError(t, err)
  368. err = config.LoadConfig(configDir, "")
  369. assert.NoError(t, err)
  370. providerConf := config.GetProviderConf()
  371. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, ""), os.ModePerm)
  372. assert.NoError(t, err)
  373. providerConf.ExternalAuthHook = extAuthPath
  374. providerConf.ExternalAuthScope = 0
  375. err = dataprovider.Initialize(providerConf, configDir)
  376. assert.NoError(t, err)
  377. client, err := getFTPClient(u, true)
  378. if assert.NoError(t, err) {
  379. err = checkBasicFTP(client)
  380. assert.NoError(t, err)
  381. err := client.Quit()
  382. assert.NoError(t, err)
  383. }
  384. u.Username = defaultUsername + "1"
  385. client, err = getFTPClient(u, true)
  386. if !assert.Error(t, err) {
  387. err := client.Quit()
  388. assert.NoError(t, err)
  389. }
  390. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  391. assert.NoError(t, err)
  392. if assert.Len(t, users, 1) {
  393. user := users[0]
  394. assert.Equal(t, defaultUsername, user.Username)
  395. _, err = httpd.RemoveUser(user, http.StatusOK)
  396. assert.NoError(t, err)
  397. err = os.RemoveAll(user.GetHomeDir())
  398. assert.NoError(t, err)
  399. }
  400. err = dataprovider.Close()
  401. assert.NoError(t, err)
  402. err = config.LoadConfig(configDir, "")
  403. assert.NoError(t, err)
  404. providerConf = config.GetProviderConf()
  405. err = dataprovider.Initialize(providerConf, configDir)
  406. assert.NoError(t, err)
  407. err = os.Remove(extAuthPath)
  408. assert.NoError(t, err)
  409. }
  410. func TestPreLoginHook(t *testing.T) {
  411. if runtime.GOOS == osWindows {
  412. t.Skip("this test is not available on Windows")
  413. }
  414. u := getTestUser()
  415. err := dataprovider.Close()
  416. assert.NoError(t, err)
  417. err = config.LoadConfig(configDir, "")
  418. assert.NoError(t, err)
  419. providerConf := config.GetProviderConf()
  420. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
  421. assert.NoError(t, err)
  422. providerConf.PreLoginHook = preLoginPath
  423. err = dataprovider.Initialize(providerConf, configDir)
  424. assert.NoError(t, err)
  425. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  426. assert.NoError(t, err)
  427. assert.Equal(t, 0, len(users))
  428. client, err := getFTPClient(u, false)
  429. if assert.NoError(t, err) {
  430. err = checkBasicFTP(client)
  431. assert.NoError(t, err)
  432. err := client.Quit()
  433. assert.NoError(t, err)
  434. }
  435. users, _, err = httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  436. assert.NoError(t, err)
  437. assert.Equal(t, 1, len(users))
  438. user := users[0]
  439. // test login with an existing user
  440. client, err = getFTPClient(user, true)
  441. if assert.NoError(t, err) {
  442. err = checkBasicFTP(client)
  443. assert.NoError(t, err)
  444. err := client.Quit()
  445. assert.NoError(t, err)
  446. }
  447. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), os.ModePerm)
  448. assert.NoError(t, err)
  449. client, err = getFTPClient(u, false)
  450. if !assert.Error(t, err) {
  451. err := client.Quit()
  452. assert.NoError(t, err)
  453. }
  454. user.Status = 0
  455. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), os.ModePerm)
  456. assert.NoError(t, err)
  457. client, err = getFTPClient(u, false)
  458. if !assert.Error(t, err, "pre-login script returned a disabled user, login must fail") {
  459. err := client.Quit()
  460. assert.NoError(t, err)
  461. }
  462. _, err = httpd.RemoveUser(user, http.StatusOK)
  463. assert.NoError(t, err)
  464. err = os.RemoveAll(user.GetHomeDir())
  465. assert.NoError(t, err)
  466. err = dataprovider.Close()
  467. assert.NoError(t, err)
  468. err = config.LoadConfig(configDir, "")
  469. assert.NoError(t, err)
  470. providerConf = config.GetProviderConf()
  471. err = dataprovider.Initialize(providerConf, configDir)
  472. assert.NoError(t, err)
  473. err = os.Remove(preLoginPath)
  474. assert.NoError(t, err)
  475. }
  476. func TestPostConnectHook(t *testing.T) {
  477. if runtime.GOOS == osWindows {
  478. t.Skip("this test is not available on Windows")
  479. }
  480. common.Config.PostConnectHook = postConnectPath
  481. u := getTestUser()
  482. user, _, err := httpd.AddUser(u, http.StatusOK)
  483. assert.NoError(t, err)
  484. err = ioutil.WriteFile(postConnectPath, getPostConnectScriptContent(0), os.ModePerm)
  485. assert.NoError(t, err)
  486. client, err := getFTPClient(user, true)
  487. if assert.NoError(t, err) {
  488. err = checkBasicFTP(client)
  489. assert.NoError(t, err)
  490. err := client.Quit()
  491. assert.NoError(t, err)
  492. }
  493. err = ioutil.WriteFile(postConnectPath, getPostConnectScriptContent(1), os.ModePerm)
  494. assert.NoError(t, err)
  495. client, err = getFTPClient(user, true)
  496. if !assert.Error(t, err) {
  497. err := client.Quit()
  498. assert.NoError(t, err)
  499. }
  500. common.Config.PostConnectHook = "http://127.0.0.1:8079/api/v1/version"
  501. client, err = getFTPClient(user, false)
  502. if assert.NoError(t, err) {
  503. err = checkBasicFTP(client)
  504. assert.NoError(t, err)
  505. err := client.Quit()
  506. assert.NoError(t, err)
  507. }
  508. common.Config.PostConnectHook = "http://127.0.0.1:8079/notfound"
  509. client, err = getFTPClient(user, true)
  510. if !assert.Error(t, err) {
  511. err := client.Quit()
  512. assert.NoError(t, err)
  513. }
  514. _, err = httpd.RemoveUser(user, http.StatusOK)
  515. assert.NoError(t, err)
  516. err = os.RemoveAll(user.GetHomeDir())
  517. assert.NoError(t, err)
  518. common.Config.PostConnectHook = ""
  519. }
  520. func TestMaxConnections(t *testing.T) {
  521. oldValue := common.Config.MaxTotalConnections
  522. common.Config.MaxTotalConnections = 1
  523. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  524. assert.NoError(t, err)
  525. client, err := getFTPClient(user, true)
  526. if assert.NoError(t, err) {
  527. err = checkBasicFTP(client)
  528. assert.NoError(t, err)
  529. _, err = getFTPClient(user, false)
  530. assert.Error(t, err)
  531. err = client.Quit()
  532. assert.NoError(t, err)
  533. }
  534. _, err = httpd.RemoveUser(user, http.StatusOK)
  535. assert.NoError(t, err)
  536. err = os.RemoveAll(user.GetHomeDir())
  537. assert.NoError(t, err)
  538. common.Config.MaxTotalConnections = oldValue
  539. }
  540. func TestMaxSessions(t *testing.T) {
  541. u := getTestUser()
  542. u.MaxSessions = 1
  543. user, _, err := httpd.AddUser(u, http.StatusOK)
  544. assert.NoError(t, err)
  545. client, err := getFTPClient(user, true)
  546. if assert.NoError(t, err) {
  547. err = checkBasicFTP(client)
  548. assert.NoError(t, err)
  549. _, err = getFTPClient(user, false)
  550. assert.Error(t, err)
  551. err = client.Quit()
  552. assert.NoError(t, err)
  553. }
  554. _, err = httpd.RemoveUser(user, http.StatusOK)
  555. assert.NoError(t, err)
  556. err = os.RemoveAll(user.GetHomeDir())
  557. assert.NoError(t, err)
  558. }
  559. func TestZeroBytesTransfers(t *testing.T) {
  560. u := getTestUser()
  561. user, _, err := httpd.AddUser(u, http.StatusOK)
  562. assert.NoError(t, err)
  563. for _, useTLS := range []bool{true, false} {
  564. client, err := getFTPClient(user, useTLS)
  565. if assert.NoError(t, err) {
  566. testFileName := "testfilename"
  567. err = checkBasicFTP(client)
  568. assert.NoError(t, err)
  569. localDownloadPath := filepath.Join(homeBasePath, "empty_download")
  570. err = ioutil.WriteFile(localDownloadPath, []byte(""), os.ModePerm)
  571. assert.NoError(t, err)
  572. err = ftpUploadFile(localDownloadPath, testFileName, 0, client, 0)
  573. assert.NoError(t, err)
  574. size, err := client.FileSize(testFileName)
  575. assert.NoError(t, err)
  576. assert.Equal(t, int64(0), size)
  577. err = os.Remove(localDownloadPath)
  578. assert.NoError(t, err)
  579. assert.NoFileExists(t, localDownloadPath)
  580. err = ftpDownloadFile(testFileName, localDownloadPath, 0, client, 0)
  581. assert.NoError(t, err)
  582. assert.FileExists(t, localDownloadPath)
  583. err = client.Quit()
  584. assert.NoError(t, err)
  585. err = os.Remove(localDownloadPath)
  586. assert.NoError(t, err)
  587. }
  588. }
  589. _, err = httpd.RemoveUser(user, http.StatusOK)
  590. assert.NoError(t, err)
  591. err = os.RemoveAll(user.GetHomeDir())
  592. assert.NoError(t, err)
  593. }
  594. func TestDownloadErrors(t *testing.T) {
  595. u := getTestUser()
  596. u.QuotaFiles = 1
  597. subDir1 := "sub1"
  598. subDir2 := "sub2"
  599. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems}
  600. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  601. dataprovider.PermDelete, dataprovider.PermDownload}
  602. u.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  603. {
  604. Path: "/sub2",
  605. AllowedExtensions: []string{},
  606. DeniedExtensions: []string{".zip"},
  607. },
  608. }
  609. u.Filters.FilePatterns = []dataprovider.PatternsFilter{
  610. {
  611. Path: "/sub2",
  612. AllowedPatterns: []string{},
  613. DeniedPatterns: []string{"*.jpg"},
  614. },
  615. }
  616. user, _, err := httpd.AddUser(u, http.StatusOK)
  617. assert.NoError(t, err)
  618. client, err := getFTPClient(user, true)
  619. if assert.NoError(t, err) {
  620. testFilePath1 := filepath.Join(user.HomeDir, subDir1, "file.zip")
  621. testFilePath2 := filepath.Join(user.HomeDir, subDir2, "file.zip")
  622. testFilePath3 := filepath.Join(user.HomeDir, subDir2, "file.jpg")
  623. err = os.MkdirAll(filepath.Dir(testFilePath1), os.ModePerm)
  624. assert.NoError(t, err)
  625. err = os.MkdirAll(filepath.Dir(testFilePath2), os.ModePerm)
  626. assert.NoError(t, err)
  627. err = ioutil.WriteFile(testFilePath1, []byte("file1"), os.ModePerm)
  628. assert.NoError(t, err)
  629. err = ioutil.WriteFile(testFilePath2, []byte("file2"), os.ModePerm)
  630. assert.NoError(t, err)
  631. err = ioutil.WriteFile(testFilePath3, []byte("file3"), os.ModePerm)
  632. assert.NoError(t, err)
  633. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  634. err = ftpDownloadFile(path.Join("/", subDir1, "file.zip"), localDownloadPath, 5, client, 0)
  635. assert.Error(t, err)
  636. err = ftpDownloadFile(path.Join("/", subDir2, "file.zip"), localDownloadPath, 5, client, 0)
  637. assert.Error(t, err)
  638. err = ftpDownloadFile(path.Join("/", subDir2, "file.jpg"), localDownloadPath, 5, client, 0)
  639. assert.Error(t, err)
  640. err = ftpDownloadFile("/missing.zip", localDownloadPath, 5, client, 0)
  641. assert.Error(t, err)
  642. err = client.Quit()
  643. assert.NoError(t, err)
  644. err = os.Remove(localDownloadPath)
  645. assert.NoError(t, err)
  646. }
  647. _, err = httpd.RemoveUser(user, http.StatusOK)
  648. assert.NoError(t, err)
  649. err = os.RemoveAll(user.GetHomeDir())
  650. assert.NoError(t, err)
  651. }
  652. func TestUploadErrors(t *testing.T) {
  653. u := getTestUser()
  654. u.QuotaSize = 65535
  655. subDir1 := "sub1"
  656. subDir2 := "sub2"
  657. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems}
  658. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  659. dataprovider.PermDelete}
  660. u.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  661. {
  662. Path: "/sub2",
  663. AllowedExtensions: []string{},
  664. DeniedExtensions: []string{".zip"},
  665. },
  666. }
  667. user, _, err := httpd.AddUser(u, http.StatusOK)
  668. assert.NoError(t, err)
  669. client, err := getFTPClient(user, true)
  670. if assert.NoError(t, err) {
  671. testFilePath := filepath.Join(homeBasePath, testFileName)
  672. testFileSize := user.QuotaSize
  673. err = createTestFile(testFilePath, testFileSize)
  674. assert.NoError(t, err)
  675. err = client.MakeDir(subDir1)
  676. assert.NoError(t, err)
  677. err = client.MakeDir(subDir2)
  678. assert.NoError(t, err)
  679. err = client.ChangeDir(subDir1)
  680. assert.NoError(t, err)
  681. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  682. assert.Error(t, err)
  683. err = client.ChangeDirToParent()
  684. assert.NoError(t, err)
  685. err = client.ChangeDir(subDir2)
  686. assert.NoError(t, err)
  687. err = ftpUploadFile(testFilePath, testFileName+".zip", testFileSize, client, 0)
  688. assert.Error(t, err)
  689. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  690. assert.NoError(t, err)
  691. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  692. assert.Error(t, err)
  693. err = client.ChangeDir("/")
  694. assert.NoError(t, err)
  695. err = ftpUploadFile(testFilePath, subDir1, testFileSize, client, 0)
  696. assert.Error(t, err)
  697. // overquota
  698. err = ftpUploadFile(testFilePath, testFileName+"1", testFileSize, client, 0)
  699. assert.Error(t, err)
  700. err = client.Delete(path.Join("/", subDir2, testFileName))
  701. assert.NoError(t, err)
  702. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  703. assert.NoError(t, err)
  704. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  705. assert.Error(t, err)
  706. err = client.Quit()
  707. assert.NoError(t, err)
  708. err = os.Remove(testFilePath)
  709. assert.NoError(t, err)
  710. }
  711. _, err = httpd.RemoveUser(user, http.StatusOK)
  712. assert.NoError(t, err)
  713. err = os.RemoveAll(user.GetHomeDir())
  714. assert.NoError(t, err)
  715. }
  716. func TestResume(t *testing.T) {
  717. u := getTestUser()
  718. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  719. assert.NoError(t, err)
  720. sftpUser, _, err := httpd.AddUser(getTestSFTPUser(), http.StatusOK)
  721. assert.NoError(t, err)
  722. for _, user := range []dataprovider.User{localUser, sftpUser} {
  723. client, err := getFTPClient(user, true)
  724. if assert.NoError(t, err) {
  725. testFilePath := filepath.Join(homeBasePath, testFileName)
  726. data := []byte("test data")
  727. err = ioutil.WriteFile(testFilePath, data, os.ModePerm)
  728. assert.NoError(t, err)
  729. err = ftpUploadFile(testFilePath, testFileName, int64(len(data)), client, 0)
  730. assert.NoError(t, err)
  731. err = ftpUploadFile(testFilePath, testFileName, int64(len(data)+5), client, 5)
  732. assert.NoError(t, err)
  733. readed, err := ioutil.ReadFile(filepath.Join(user.GetHomeDir(), testFileName))
  734. assert.NoError(t, err)
  735. assert.Equal(t, "test test data", string(readed))
  736. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  737. err = ftpDownloadFile(testFileName, localDownloadPath, int64(len(data)), client, 5)
  738. assert.NoError(t, err)
  739. readed, err = ioutil.ReadFile(localDownloadPath)
  740. assert.NoError(t, err)
  741. assert.Equal(t, data, readed)
  742. err = client.Delete(testFileName)
  743. assert.NoError(t, err)
  744. err = ftpUploadFile(testFilePath, testFileName, int64(len(data)), client, 0)
  745. assert.NoError(t, err)
  746. // now append to a file
  747. srcFile, err := os.Open(testFilePath)
  748. if assert.NoError(t, err) {
  749. err = client.Append(testFileName, srcFile)
  750. assert.NoError(t, err)
  751. err = srcFile.Close()
  752. assert.NoError(t, err)
  753. size, err := client.FileSize(testFileName)
  754. assert.NoError(t, err)
  755. assert.Equal(t, int64(2*len(data)), size)
  756. err = ftpDownloadFile(testFileName, localDownloadPath, int64(2*len(data)), client, 0)
  757. assert.NoError(t, err)
  758. readed, err = ioutil.ReadFile(localDownloadPath)
  759. assert.NoError(t, err)
  760. expected := append(data, data...)
  761. assert.Equal(t, expected, readed)
  762. }
  763. err = client.Quit()
  764. assert.NoError(t, err)
  765. err = os.Remove(testFilePath)
  766. assert.NoError(t, err)
  767. err = os.Remove(localDownloadPath)
  768. assert.NoError(t, err)
  769. if user.Username == defaultUsername {
  770. err = os.RemoveAll(user.GetHomeDir())
  771. assert.NoError(t, err)
  772. }
  773. }
  774. }
  775. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  776. assert.NoError(t, err)
  777. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  778. assert.NoError(t, err)
  779. err = os.RemoveAll(localUser.GetHomeDir())
  780. assert.NoError(t, err)
  781. }
  782. //nolint:dupl
  783. func TestDeniedLoginMethod(t *testing.T) {
  784. u := getTestUser()
  785. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword}
  786. user, _, err := httpd.AddUser(u, http.StatusOK)
  787. assert.NoError(t, err)
  788. _, err = getFTPClient(user, false)
  789. assert.Error(t, err)
  790. user.Filters.DeniedLoginMethods = []string{dataprovider.SSHLoginMethodPublicKey, dataprovider.SSHLoginMethodKeyAndPassword}
  791. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  792. assert.NoError(t, err)
  793. client, err := getFTPClient(user, true)
  794. if assert.NoError(t, err) {
  795. assert.NoError(t, checkBasicFTP(client))
  796. err = client.Quit()
  797. assert.NoError(t, err)
  798. }
  799. _, err = httpd.RemoveUser(user, http.StatusOK)
  800. assert.NoError(t, err)
  801. err = os.RemoveAll(user.GetHomeDir())
  802. assert.NoError(t, err)
  803. }
  804. //nolint:dupl
  805. func TestDeniedProtocols(t *testing.T) {
  806. u := getTestUser()
  807. u.Filters.DeniedProtocols = []string{common.ProtocolFTP}
  808. user, _, err := httpd.AddUser(u, http.StatusOK)
  809. assert.NoError(t, err)
  810. _, err = getFTPClient(user, false)
  811. assert.Error(t, err)
  812. user.Filters.DeniedProtocols = []string{common.ProtocolSSH, common.ProtocolWebDAV}
  813. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  814. assert.NoError(t, err)
  815. client, err := getFTPClient(user, true)
  816. if assert.NoError(t, err) {
  817. assert.NoError(t, checkBasicFTP(client))
  818. err = client.Quit()
  819. assert.NoError(t, err)
  820. }
  821. _, err = httpd.RemoveUser(user, http.StatusOK)
  822. assert.NoError(t, err)
  823. err = os.RemoveAll(user.GetHomeDir())
  824. assert.NoError(t, err)
  825. }
  826. func TestQuotaLimits(t *testing.T) {
  827. u := getTestUser()
  828. u.QuotaFiles = 1
  829. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  830. assert.NoError(t, err)
  831. u = getTestSFTPUser()
  832. u.QuotaFiles = 1
  833. sftpUser, _, err := httpd.AddUser(u, http.StatusOK)
  834. assert.NoError(t, err)
  835. for _, user := range []dataprovider.User{localUser, sftpUser} {
  836. testFileSize := int64(65535)
  837. testFilePath := filepath.Join(homeBasePath, testFileName)
  838. err = createTestFile(testFilePath, testFileSize)
  839. assert.NoError(t, err)
  840. testFileSize1 := int64(131072)
  841. testFileName1 := "test_file1.dat"
  842. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  843. err = createTestFile(testFilePath1, testFileSize1)
  844. assert.NoError(t, err)
  845. testFileSize2 := int64(32768)
  846. testFileName2 := "test_file2.dat"
  847. testFilePath2 := filepath.Join(homeBasePath, testFileName2)
  848. err = createTestFile(testFilePath2, testFileSize2)
  849. assert.NoError(t, err)
  850. // test quota files
  851. client, err := getFTPClient(user, false)
  852. if assert.NoError(t, err) {
  853. err = ftpUploadFile(testFilePath, testFileName+".quota", testFileSize, client, 0)
  854. assert.NoError(t, err)
  855. err = ftpUploadFile(testFilePath, testFileName+".quota1", testFileSize, client, 0)
  856. assert.Error(t, err)
  857. err = client.Rename(testFileName+".quota", testFileName)
  858. assert.NoError(t, err)
  859. err = client.Quit()
  860. assert.NoError(t, err)
  861. }
  862. // test quota size
  863. user.QuotaSize = testFileSize - 1
  864. user.QuotaFiles = 0
  865. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  866. assert.NoError(t, err)
  867. client, err = getFTPClient(user, true)
  868. if assert.NoError(t, err) {
  869. err = ftpUploadFile(testFilePath, testFileName+".quota", testFileSize, client, 0)
  870. assert.Error(t, err)
  871. err = client.Rename(testFileName, testFileName+".quota")
  872. assert.NoError(t, err)
  873. err = client.Quit()
  874. assert.NoError(t, err)
  875. }
  876. // now test quota limits while uploading the current file, we have 1 bytes remaining
  877. user.QuotaSize = testFileSize + 1
  878. user.QuotaFiles = 0
  879. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  880. assert.NoError(t, err)
  881. client, err = getFTPClient(user, false)
  882. if assert.NoError(t, err) {
  883. err = ftpUploadFile(testFilePath1, testFileName1, testFileSize1, client, 0)
  884. assert.Error(t, err)
  885. _, err = client.FileSize(testFileName1)
  886. assert.Error(t, err)
  887. err = client.Rename(testFileName+".quota", testFileName)
  888. assert.NoError(t, err)
  889. // overwriting an existing file will work if the resulting size is lesser or equal than the current one
  890. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  891. assert.NoError(t, err)
  892. err = ftpUploadFile(testFilePath2, testFileName, testFileSize2, client, 0)
  893. assert.NoError(t, err)
  894. err = ftpUploadFile(testFilePath1, testFileName, testFileSize1, client, 0)
  895. assert.Error(t, err)
  896. err = ftpUploadFile(testFilePath1, testFileName, testFileSize1, client, 10)
  897. assert.Error(t, err)
  898. err = ftpUploadFile(testFilePath2, testFileName, testFileSize2, client, 0)
  899. assert.NoError(t, err)
  900. err = client.Quit()
  901. assert.NoError(t, err)
  902. }
  903. err = os.Remove(testFilePath)
  904. assert.NoError(t, err)
  905. err = os.Remove(testFilePath1)
  906. assert.NoError(t, err)
  907. err = os.Remove(testFilePath2)
  908. assert.NoError(t, err)
  909. if user.Username == defaultUsername {
  910. err = os.RemoveAll(user.GetHomeDir())
  911. assert.NoError(t, err)
  912. user.QuotaFiles = 0
  913. user.QuotaSize = 0
  914. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  915. assert.NoError(t, err)
  916. }
  917. }
  918. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  919. assert.NoError(t, err)
  920. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  921. assert.NoError(t, err)
  922. err = os.RemoveAll(localUser.GetHomeDir())
  923. assert.NoError(t, err)
  924. }
  925. func TestUploadMaxSize(t *testing.T) {
  926. testFileSize := int64(65535)
  927. u := getTestUser()
  928. u.Filters.MaxUploadFileSize = testFileSize + 1
  929. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  930. assert.NoError(t, err)
  931. u = getTestSFTPUser()
  932. u.Filters.MaxUploadFileSize = testFileSize + 1
  933. sftpUser, _, err := httpd.AddUser(u, http.StatusOK)
  934. assert.NoError(t, err)
  935. for _, user := range []dataprovider.User{localUser, sftpUser} {
  936. testFilePath := filepath.Join(homeBasePath, testFileName)
  937. err = createTestFile(testFilePath, testFileSize)
  938. assert.NoError(t, err)
  939. testFileSize1 := int64(131072)
  940. testFileName1 := "test_file1.dat"
  941. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  942. err = createTestFile(testFilePath1, testFileSize1)
  943. assert.NoError(t, err)
  944. client, err := getFTPClient(user, false)
  945. if assert.NoError(t, err) {
  946. err = ftpUploadFile(testFilePath1, testFileName1, testFileSize1, client, 0)
  947. assert.Error(t, err)
  948. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  949. assert.NoError(t, err)
  950. // now test overwrite an existing file with a size bigger than the allowed one
  951. err = createTestFile(filepath.Join(user.GetHomeDir(), testFileName1), testFileSize1)
  952. assert.NoError(t, err)
  953. err = ftpUploadFile(testFilePath1, testFileName1, testFileSize1, client, 0)
  954. assert.Error(t, err)
  955. err = client.Quit()
  956. assert.NoError(t, err)
  957. }
  958. err = os.Remove(testFilePath)
  959. assert.NoError(t, err)
  960. err = os.Remove(testFilePath1)
  961. assert.NoError(t, err)
  962. if user.Username == defaultUsername {
  963. err = os.RemoveAll(user.GetHomeDir())
  964. assert.NoError(t, err)
  965. user.Filters.MaxUploadFileSize = 65536000
  966. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  967. assert.NoError(t, err)
  968. }
  969. }
  970. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  971. assert.NoError(t, err)
  972. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  973. assert.NoError(t, err)
  974. err = os.RemoveAll(localUser.GetHomeDir())
  975. assert.NoError(t, err)
  976. }
  977. func TestLoginWithIPilters(t *testing.T) {
  978. u := getTestUser()
  979. u.Filters.DeniedIP = []string{"192.167.0.0/24", "172.18.0.0/16"}
  980. u.Filters.AllowedIP = []string{"172.19.0.0/16"}
  981. user, _, err := httpd.AddUser(u, http.StatusOK)
  982. assert.NoError(t, err)
  983. client, err := getFTPClient(user, true)
  984. if !assert.Error(t, err) {
  985. err = client.Quit()
  986. assert.NoError(t, err)
  987. }
  988. _, err = httpd.RemoveUser(user, http.StatusOK)
  989. assert.NoError(t, err)
  990. err = os.RemoveAll(user.GetHomeDir())
  991. assert.NoError(t, err)
  992. }
  993. func TestLoginWithDatabaseCredentials(t *testing.T) {
  994. u := getTestUser()
  995. u.FsConfig.Provider = dataprovider.GCSFilesystemProvider
  996. u.FsConfig.GCSConfig.Bucket = "test"
  997. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret(`{ "type": "service_account" }`)
  998. providerConf := config.GetProviderConf()
  999. providerConf.PreferDatabaseCredentials = true
  1000. credentialsFile := filepath.Join(providerConf.CredentialsPath, fmt.Sprintf("%v_gcs_credentials.json", u.Username))
  1001. if !filepath.IsAbs(credentialsFile) {
  1002. credentialsFile = filepath.Join(configDir, credentialsFile)
  1003. }
  1004. assert.NoError(t, dataprovider.Close())
  1005. err := dataprovider.Initialize(providerConf, configDir)
  1006. assert.NoError(t, err)
  1007. if _, err = os.Stat(credentialsFile); err == nil {
  1008. // remove the credentials file
  1009. assert.NoError(t, os.Remove(credentialsFile))
  1010. }
  1011. user, _, err := httpd.AddUser(u, http.StatusOK)
  1012. assert.NoError(t, err)
  1013. assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.GCSConfig.Credentials.GetStatus())
  1014. assert.NotEmpty(t, user.FsConfig.GCSConfig.Credentials.GetPayload())
  1015. assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetAdditionalData())
  1016. assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetKey())
  1017. assert.NoFileExists(t, credentialsFile)
  1018. client, err := getFTPClient(user, false)
  1019. if assert.NoError(t, err) {
  1020. err = client.Quit()
  1021. assert.NoError(t, err)
  1022. }
  1023. _, err = httpd.RemoveUser(user, http.StatusOK)
  1024. assert.NoError(t, err)
  1025. err = os.RemoveAll(user.GetHomeDir())
  1026. assert.NoError(t, err)
  1027. assert.NoError(t, dataprovider.Close())
  1028. assert.NoError(t, config.LoadConfig(configDir, ""))
  1029. providerConf = config.GetProviderConf()
  1030. assert.NoError(t, dataprovider.Initialize(providerConf, configDir))
  1031. }
  1032. func TestLoginInvalidFs(t *testing.T) {
  1033. u := getTestUser()
  1034. u.FsConfig.Provider = dataprovider.GCSFilesystemProvider
  1035. u.FsConfig.GCSConfig.Bucket = "test"
  1036. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("invalid JSON for credentials")
  1037. user, _, err := httpd.AddUser(u, http.StatusOK)
  1038. assert.NoError(t, err)
  1039. providerConf := config.GetProviderConf()
  1040. credentialsFile := filepath.Join(providerConf.CredentialsPath, fmt.Sprintf("%v_gcs_credentials.json", u.Username))
  1041. if !filepath.IsAbs(credentialsFile) {
  1042. credentialsFile = filepath.Join(configDir, credentialsFile)
  1043. }
  1044. // now remove the credentials file so the filesystem creation will fail
  1045. err = os.Remove(credentialsFile)
  1046. assert.NoError(t, err)
  1047. client, err := getFTPClient(user, false)
  1048. if !assert.Error(t, err) {
  1049. err = client.Quit()
  1050. assert.NoError(t, err)
  1051. }
  1052. _, err = httpd.RemoveUser(user, http.StatusOK)
  1053. assert.NoError(t, err)
  1054. err = os.RemoveAll(user.GetHomeDir())
  1055. assert.NoError(t, err)
  1056. }
  1057. func TestClientClose(t *testing.T) {
  1058. u := getTestUser()
  1059. user, _, err := httpd.AddUser(u, http.StatusOK)
  1060. assert.NoError(t, err)
  1061. client, err := getFTPClient(user, true)
  1062. if assert.NoError(t, err) {
  1063. err = checkBasicFTP(client)
  1064. assert.NoError(t, err)
  1065. stats := common.Connections.GetStats()
  1066. if assert.Len(t, stats, 1) {
  1067. common.Connections.Close(stats[0].ConnectionID)
  1068. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 },
  1069. 1*time.Second, 50*time.Millisecond)
  1070. }
  1071. }
  1072. _, err = httpd.RemoveUser(user, http.StatusOK)
  1073. assert.NoError(t, err)
  1074. err = os.RemoveAll(user.GetHomeDir())
  1075. assert.NoError(t, err)
  1076. }
  1077. func TestRename(t *testing.T) {
  1078. u := getTestUser()
  1079. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  1080. assert.NoError(t, err)
  1081. sftpUser, _, err := httpd.AddUser(getTestSFTPUser(), http.StatusOK)
  1082. assert.NoError(t, err)
  1083. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1084. testDir := "adir"
  1085. testFilePath := filepath.Join(homeBasePath, testFileName)
  1086. testFileSize := int64(65535)
  1087. err = createTestFile(testFilePath, testFileSize)
  1088. assert.NoError(t, err)
  1089. client, err := getFTPClient(user, false)
  1090. if assert.NoError(t, err) {
  1091. err = checkBasicFTP(client)
  1092. assert.NoError(t, err)
  1093. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  1094. assert.NoError(t, err)
  1095. err = client.MakeDir(testDir)
  1096. assert.NoError(t, err)
  1097. err = client.Rename(testFileName, path.Join("missing", testFileName))
  1098. assert.Error(t, err)
  1099. err = client.Rename(testFileName, path.Join(testDir, testFileName))
  1100. assert.NoError(t, err)
  1101. size, err := client.FileSize(path.Join(testDir, testFileName))
  1102. assert.NoError(t, err)
  1103. assert.Equal(t, testFileSize, size)
  1104. if runtime.GOOS != osWindows {
  1105. otherDir := "dir"
  1106. err = client.MakeDir(otherDir)
  1107. assert.NoError(t, err)
  1108. err = client.MakeDir(path.Join(otherDir, testDir))
  1109. assert.NoError(t, err)
  1110. code, response, err := client.SendCustomCommand(fmt.Sprintf("SITE CHMOD 0001 %v", otherDir))
  1111. assert.NoError(t, err)
  1112. assert.Equal(t, ftp.StatusCommandOK, code)
  1113. assert.Equal(t, "SITE CHMOD command successful", response)
  1114. err = client.Rename(testDir, path.Join(otherDir, testDir))
  1115. assert.Error(t, err)
  1116. code, response, err = client.SendCustomCommand(fmt.Sprintf("SITE CHMOD 755 %v", otherDir))
  1117. assert.NoError(t, err)
  1118. assert.Equal(t, ftp.StatusCommandOK, code)
  1119. assert.Equal(t, "SITE CHMOD command successful", response)
  1120. }
  1121. err = client.Quit()
  1122. assert.NoError(t, err)
  1123. }
  1124. user.Permissions[path.Join("/", testDir)] = []string{dataprovider.PermListItems}
  1125. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1126. assert.NoError(t, err)
  1127. client, err = getFTPClient(user, false)
  1128. if assert.NoError(t, err) {
  1129. err = client.Rename(path.Join(testDir, testFileName), testFileName)
  1130. assert.Error(t, err)
  1131. err := client.Quit()
  1132. assert.NoError(t, err)
  1133. }
  1134. err = os.Remove(testFilePath)
  1135. assert.NoError(t, err)
  1136. if user.Username == defaultUsername {
  1137. user.Permissions = make(map[string][]string)
  1138. user.Permissions["/"] = allPerms
  1139. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1140. assert.NoError(t, err)
  1141. err = os.RemoveAll(user.GetHomeDir())
  1142. assert.NoError(t, err)
  1143. }
  1144. }
  1145. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  1146. assert.NoError(t, err)
  1147. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  1148. assert.NoError(t, err)
  1149. err = os.RemoveAll(localUser.GetHomeDir())
  1150. assert.NoError(t, err)
  1151. }
  1152. func TestSymlink(t *testing.T) {
  1153. u := getTestUser()
  1154. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  1155. assert.NoError(t, err)
  1156. sftpUser, _, err := httpd.AddUser(getTestSFTPUser(), http.StatusOK)
  1157. assert.NoError(t, err)
  1158. testFilePath := filepath.Join(homeBasePath, testFileName)
  1159. testFileSize := int64(65535)
  1160. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1161. err = createTestFile(testFilePath, testFileSize)
  1162. assert.NoError(t, err)
  1163. client, err := getFTPClient(user, false)
  1164. if assert.NoError(t, err) {
  1165. err = checkBasicFTP(client)
  1166. assert.NoError(t, err)
  1167. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  1168. assert.NoError(t, err)
  1169. code, _, err := client.SendCustomCommand(fmt.Sprintf("SITE SYMLINK %v %v", testFileName, testFileName+".link"))
  1170. assert.NoError(t, err)
  1171. assert.Equal(t, ftp.StatusCommandOK, code)
  1172. if runtime.GOOS != osWindows {
  1173. testDir := "adir"
  1174. otherDir := "dir"
  1175. err = client.MakeDir(otherDir)
  1176. assert.NoError(t, err)
  1177. err = client.MakeDir(path.Join(otherDir, testDir))
  1178. assert.NoError(t, err)
  1179. code, response, err := client.SendCustomCommand(fmt.Sprintf("SITE CHMOD 0001 %v", otherDir))
  1180. assert.NoError(t, err)
  1181. assert.Equal(t, ftp.StatusCommandOK, code)
  1182. assert.Equal(t, "SITE CHMOD command successful", response)
  1183. code, _, err = client.SendCustomCommand(fmt.Sprintf("SITE SYMLINK %v %v", testDir, path.Join(otherDir, testDir)))
  1184. assert.NoError(t, err)
  1185. assert.Equal(t, ftp.StatusFileUnavailable, code)
  1186. code, response, err = client.SendCustomCommand(fmt.Sprintf("SITE CHMOD 755 %v", otherDir))
  1187. assert.NoError(t, err)
  1188. assert.Equal(t, ftp.StatusCommandOK, code)
  1189. assert.Equal(t, "SITE CHMOD command successful", response)
  1190. }
  1191. err = client.Quit()
  1192. assert.NoError(t, err)
  1193. if user.Username == defaultUsername {
  1194. err = os.RemoveAll(user.GetHomeDir())
  1195. assert.NoError(t, err)
  1196. }
  1197. }
  1198. err = os.Remove(testFilePath)
  1199. assert.NoError(t, err)
  1200. }
  1201. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  1202. assert.NoError(t, err)
  1203. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  1204. assert.NoError(t, err)
  1205. err = os.RemoveAll(localUser.GetHomeDir())
  1206. assert.NoError(t, err)
  1207. }
  1208. func TestStat(t *testing.T) {
  1209. u := getTestUser()
  1210. u.Permissions["/subdir"] = []string{dataprovider.PermUpload}
  1211. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  1212. assert.NoError(t, err)
  1213. sftpUser, _, err := httpd.AddUser(getTestSFTPUser(), http.StatusOK)
  1214. assert.NoError(t, err)
  1215. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1216. client, err := getFTPClient(user, false)
  1217. if assert.NoError(t, err) {
  1218. subDir := "subdir"
  1219. testFilePath := filepath.Join(homeBasePath, testFileName)
  1220. testFileSize := int64(65535)
  1221. err = createTestFile(testFilePath, testFileSize)
  1222. assert.NoError(t, err)
  1223. err = client.MakeDir(subDir)
  1224. assert.NoError(t, err)
  1225. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  1226. assert.NoError(t, err)
  1227. err = ftpUploadFile(testFilePath, path.Join("/", subDir, testFileName), testFileSize, client, 0)
  1228. assert.Error(t, err)
  1229. size, err := client.FileSize(testFileName)
  1230. assert.NoError(t, err)
  1231. assert.Equal(t, testFileSize, size)
  1232. _, err = client.FileSize(path.Join("/", subDir, testFileName))
  1233. assert.Error(t, err)
  1234. _, err = client.FileSize("missing file")
  1235. assert.Error(t, err)
  1236. err = client.Quit()
  1237. assert.NoError(t, err)
  1238. err = os.Remove(testFilePath)
  1239. assert.NoError(t, err)
  1240. if user.Username == defaultUsername {
  1241. err = os.RemoveAll(user.GetHomeDir())
  1242. assert.NoError(t, err)
  1243. }
  1244. }
  1245. }
  1246. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  1247. assert.NoError(t, err)
  1248. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  1249. assert.NoError(t, err)
  1250. err = os.RemoveAll(localUser.GetHomeDir())
  1251. assert.NoError(t, err)
  1252. }
  1253. func TestUploadOverwriteVfolder(t *testing.T) {
  1254. u := getTestUser()
  1255. vdir := "/vdir"
  1256. mappedPath := filepath.Join(os.TempDir(), "vdir")
  1257. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1258. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1259. MappedPath: mappedPath,
  1260. },
  1261. VirtualPath: vdir,
  1262. QuotaSize: -1,
  1263. QuotaFiles: -1,
  1264. })
  1265. err := os.MkdirAll(mappedPath, os.ModePerm)
  1266. assert.NoError(t, err)
  1267. user, _, err := httpd.AddUser(u, http.StatusOK)
  1268. assert.NoError(t, err)
  1269. client, err := getFTPClient(user, false)
  1270. if assert.NoError(t, err) {
  1271. testFilePath := filepath.Join(homeBasePath, testFileName)
  1272. testFileSize := int64(65535)
  1273. err = createTestFile(testFilePath, testFileSize)
  1274. assert.NoError(t, err)
  1275. err = ftpUploadFile(testFilePath, path.Join(vdir, testFileName), testFileSize, client, 0)
  1276. assert.NoError(t, err)
  1277. folder, _, err := httpd.GetFolders(0, 0, mappedPath, http.StatusOK)
  1278. assert.NoError(t, err)
  1279. if assert.Len(t, folder, 1) {
  1280. f := folder[0]
  1281. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  1282. assert.Equal(t, 1, f.UsedQuotaFiles)
  1283. }
  1284. err = ftpUploadFile(testFilePath, path.Join(vdir, testFileName), testFileSize, client, 0)
  1285. assert.NoError(t, err)
  1286. folder, _, err = httpd.GetFolders(0, 0, mappedPath, http.StatusOK)
  1287. assert.NoError(t, err)
  1288. if assert.Len(t, folder, 1) {
  1289. f := folder[0]
  1290. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  1291. assert.Equal(t, 1, f.UsedQuotaFiles)
  1292. }
  1293. err = client.Quit()
  1294. assert.NoError(t, err)
  1295. err = os.Remove(testFilePath)
  1296. assert.NoError(t, err)
  1297. }
  1298. _, err = httpd.RemoveUser(user, http.StatusOK)
  1299. assert.NoError(t, err)
  1300. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath}, http.StatusOK)
  1301. assert.NoError(t, err)
  1302. err = os.RemoveAll(user.GetHomeDir())
  1303. assert.NoError(t, err)
  1304. err = os.RemoveAll(mappedPath)
  1305. assert.NoError(t, err)
  1306. }
  1307. func TestAllocateAvailable(t *testing.T) {
  1308. u := getTestUser()
  1309. mappedPath := filepath.Join(os.TempDir(), "vdir")
  1310. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1311. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1312. MappedPath: mappedPath,
  1313. },
  1314. VirtualPath: "/vdir",
  1315. QuotaSize: 110,
  1316. })
  1317. err := os.MkdirAll(mappedPath, os.ModePerm)
  1318. assert.NoError(t, err)
  1319. user, _, err := httpd.AddUser(u, http.StatusOK)
  1320. assert.NoError(t, err)
  1321. client, err := getFTPClient(user, false)
  1322. if assert.NoError(t, err) {
  1323. code, response, err := client.SendCustomCommand("allo 2000000")
  1324. assert.NoError(t, err)
  1325. assert.Equal(t, ftp.StatusCommandOK, code)
  1326. assert.Equal(t, "Done !", response)
  1327. code, response, err = client.SendCustomCommand("AVBL /vdir")
  1328. assert.NoError(t, err)
  1329. assert.Equal(t, ftp.StatusFile, code)
  1330. assert.Equal(t, "110", response)
  1331. code, _, err = client.SendCustomCommand("AVBL")
  1332. assert.NoError(t, err)
  1333. assert.Equal(t, ftp.StatusFile, code)
  1334. err = client.Quit()
  1335. assert.NoError(t, err)
  1336. }
  1337. user.QuotaSize = 100
  1338. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1339. assert.NoError(t, err)
  1340. client, err = getFTPClient(user, false)
  1341. if assert.NoError(t, err) {
  1342. testFilePath := filepath.Join(homeBasePath, testFileName)
  1343. testFileSize := user.QuotaSize - 1
  1344. err = createTestFile(testFilePath, testFileSize)
  1345. assert.NoError(t, err)
  1346. code, response, err := client.SendCustomCommand("allo 99")
  1347. assert.NoError(t, err)
  1348. assert.Equal(t, ftp.StatusCommandOK, code)
  1349. assert.Equal(t, "Done !", response)
  1350. code, response, err = client.SendCustomCommand("allo 100")
  1351. assert.NoError(t, err)
  1352. assert.Equal(t, ftp.StatusCommandOK, code)
  1353. assert.Equal(t, "Done !", response)
  1354. code, response, err = client.SendCustomCommand("allo 150")
  1355. assert.NoError(t, err)
  1356. assert.Equal(t, ftp.StatusFileUnavailable, code)
  1357. assert.Contains(t, response, common.ErrQuotaExceeded.Error())
  1358. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  1359. assert.NoError(t, err)
  1360. code, response, err = client.SendCustomCommand("AVBL")
  1361. assert.NoError(t, err)
  1362. assert.Equal(t, ftp.StatusFile, code)
  1363. assert.Equal(t, "1", response)
  1364. // we still have space in vdir
  1365. code, response, err = client.SendCustomCommand("allo 50")
  1366. assert.NoError(t, err)
  1367. assert.Equal(t, ftp.StatusCommandOK, code)
  1368. assert.Equal(t, "Done !", response)
  1369. err = ftpUploadFile(testFilePath, path.Join("/vdir", testFileName), testFileSize, client, 0)
  1370. assert.NoError(t, err)
  1371. code, response, err = client.SendCustomCommand("allo 50")
  1372. assert.NoError(t, err)
  1373. assert.Equal(t, ftp.StatusFileUnavailable, code)
  1374. assert.Contains(t, response, common.ErrQuotaExceeded.Error())
  1375. err = client.Quit()
  1376. assert.NoError(t, err)
  1377. err = os.Remove(testFilePath)
  1378. assert.NoError(t, err)
  1379. }
  1380. user.Filters.MaxUploadFileSize = 100
  1381. user.QuotaSize = 0
  1382. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1383. assert.NoError(t, err)
  1384. client, err = getFTPClient(user, false)
  1385. if assert.NoError(t, err) {
  1386. code, response, err := client.SendCustomCommand("allo 99")
  1387. assert.NoError(t, err)
  1388. assert.Equal(t, ftp.StatusCommandOK, code)
  1389. assert.Equal(t, "Done !", response)
  1390. code, response, err = client.SendCustomCommand("allo 150")
  1391. assert.NoError(t, err)
  1392. assert.Equal(t, ftp.StatusFileUnavailable, code)
  1393. assert.Contains(t, response, common.ErrQuotaExceeded.Error())
  1394. code, response, err = client.SendCustomCommand("AVBL")
  1395. assert.NoError(t, err)
  1396. assert.Equal(t, ftp.StatusFile, code)
  1397. assert.Equal(t, "100", response)
  1398. err = client.Quit()
  1399. assert.NoError(t, err)
  1400. }
  1401. user.QuotaSize = 50
  1402. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1403. assert.NoError(t, err)
  1404. client, err = getFTPClient(user, false)
  1405. if assert.NoError(t, err) {
  1406. code, response, err := client.SendCustomCommand("AVBL")
  1407. assert.NoError(t, err)
  1408. assert.Equal(t, ftp.StatusFile, code)
  1409. assert.Equal(t, "0", response)
  1410. }
  1411. user.QuotaSize = 1000
  1412. user.Filters.MaxUploadFileSize = 1
  1413. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1414. assert.NoError(t, err)
  1415. client, err = getFTPClient(user, false)
  1416. if assert.NoError(t, err) {
  1417. code, response, err := client.SendCustomCommand("AVBL")
  1418. assert.NoError(t, err)
  1419. assert.Equal(t, ftp.StatusFile, code)
  1420. assert.Equal(t, "1", response)
  1421. }
  1422. _, err = httpd.RemoveUser(user, http.StatusOK)
  1423. assert.NoError(t, err)
  1424. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath}, http.StatusOK)
  1425. assert.NoError(t, err)
  1426. err = os.RemoveAll(user.GetHomeDir())
  1427. assert.NoError(t, err)
  1428. err = os.RemoveAll(mappedPath)
  1429. assert.NoError(t, err)
  1430. }
  1431. func TestAvailableUnsupportedFs(t *testing.T) {
  1432. u := getTestUser()
  1433. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  1434. assert.NoError(t, err)
  1435. sftpUser, _, err := httpd.AddUser(getTestSFTPUser(), http.StatusOK)
  1436. assert.NoError(t, err)
  1437. client, err := getFTPClient(sftpUser, false)
  1438. if assert.NoError(t, err) {
  1439. code, response, err := client.SendCustomCommand("AVBL")
  1440. assert.NoError(t, err)
  1441. assert.Equal(t, ftp.StatusFileUnavailable, code)
  1442. assert.Contains(t, response, "unable to get available size for this storage backend")
  1443. err = client.Quit()
  1444. assert.NoError(t, err)
  1445. }
  1446. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  1447. assert.NoError(t, err)
  1448. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  1449. assert.NoError(t, err)
  1450. err = os.RemoveAll(localUser.GetHomeDir())
  1451. assert.NoError(t, err)
  1452. }
  1453. func TestChtimes(t *testing.T) {
  1454. u := getTestUser()
  1455. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  1456. assert.NoError(t, err)
  1457. sftpUser, _, err := httpd.AddUser(getTestSFTPUser(), http.StatusOK)
  1458. assert.NoError(t, err)
  1459. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1460. client, err := getFTPClient(user, false)
  1461. if assert.NoError(t, err) {
  1462. testFilePath := filepath.Join(homeBasePath, testFileName)
  1463. testFileSize := int64(65535)
  1464. err = createTestFile(testFilePath, testFileSize)
  1465. assert.NoError(t, err)
  1466. err = checkBasicFTP(client)
  1467. assert.NoError(t, err)
  1468. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  1469. assert.NoError(t, err)
  1470. mtime := time.Now().Format("20060102150405")
  1471. code, response, err := client.SendCustomCommand(fmt.Sprintf("MFMT %v %v", mtime, testFileName))
  1472. assert.NoError(t, err)
  1473. assert.Equal(t, ftp.StatusFile, code)
  1474. assert.Equal(t, fmt.Sprintf("Modify=%v; %v", mtime, testFileName), response)
  1475. err = client.Quit()
  1476. assert.NoError(t, err)
  1477. err = os.Remove(testFilePath)
  1478. assert.NoError(t, err)
  1479. if user.Username == defaultUsername {
  1480. err = os.RemoveAll(user.GetHomeDir())
  1481. assert.NoError(t, err)
  1482. }
  1483. }
  1484. }
  1485. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  1486. assert.NoError(t, err)
  1487. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  1488. assert.NoError(t, err)
  1489. err = os.RemoveAll(localUser.GetHomeDir())
  1490. assert.NoError(t, err)
  1491. }
  1492. func TestChown(t *testing.T) {
  1493. if runtime.GOOS == osWindows {
  1494. t.Skip("chown is not supported on Windows")
  1495. }
  1496. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  1497. assert.NoError(t, err)
  1498. client, err := getFTPClient(user, true)
  1499. if assert.NoError(t, err) {
  1500. testFilePath := filepath.Join(homeBasePath, testFileName)
  1501. testFileSize := int64(131072)
  1502. err = createTestFile(testFilePath, testFileSize)
  1503. assert.NoError(t, err)
  1504. err = checkBasicFTP(client)
  1505. assert.NoError(t, err)
  1506. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  1507. assert.NoError(t, err)
  1508. code, response, err := client.SendCustomCommand(fmt.Sprintf("SITE CHOWN 1000:1000 %v", testFileName))
  1509. assert.NoError(t, err)
  1510. assert.Equal(t, ftp.StatusFileUnavailable, code)
  1511. assert.Equal(t, "Couldn't chown: operation unsupported", response)
  1512. err = client.Quit()
  1513. assert.NoError(t, err)
  1514. err = os.Remove(testFilePath)
  1515. assert.NoError(t, err)
  1516. }
  1517. _, err = httpd.RemoveUser(user, http.StatusOK)
  1518. assert.NoError(t, err)
  1519. err = os.RemoveAll(user.GetHomeDir())
  1520. assert.NoError(t, err)
  1521. }
  1522. func TestChmod(t *testing.T) {
  1523. if runtime.GOOS == osWindows {
  1524. t.Skip("chmod is partially supported on Windows")
  1525. }
  1526. u := getTestUser()
  1527. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  1528. assert.NoError(t, err)
  1529. sftpUser, _, err := httpd.AddUser(getTestSFTPUser(), http.StatusOK)
  1530. assert.NoError(t, err)
  1531. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1532. client, err := getFTPClient(user, true)
  1533. if assert.NoError(t, err) {
  1534. testFilePath := filepath.Join(homeBasePath, testFileName)
  1535. testFileSize := int64(131072)
  1536. err = createTestFile(testFilePath, testFileSize)
  1537. assert.NoError(t, err)
  1538. err = checkBasicFTP(client)
  1539. assert.NoError(t, err)
  1540. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  1541. assert.NoError(t, err)
  1542. code, response, err := client.SendCustomCommand(fmt.Sprintf("SITE CHMOD 600 %v", testFileName))
  1543. assert.NoError(t, err)
  1544. assert.Equal(t, ftp.StatusCommandOK, code)
  1545. assert.Equal(t, "SITE CHMOD command successful", response)
  1546. fi, err := os.Stat(filepath.Join(user.HomeDir, testFileName))
  1547. if assert.NoError(t, err) {
  1548. assert.Equal(t, os.FileMode(0600), fi.Mode().Perm())
  1549. }
  1550. err = client.Quit()
  1551. assert.NoError(t, err)
  1552. err = os.Remove(testFilePath)
  1553. assert.NoError(t, err)
  1554. if user.Username == defaultUsername {
  1555. err = os.RemoveAll(user.GetHomeDir())
  1556. assert.NoError(t, err)
  1557. }
  1558. }
  1559. }
  1560. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  1561. assert.NoError(t, err)
  1562. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  1563. assert.NoError(t, err)
  1564. err = os.RemoveAll(localUser.GetHomeDir())
  1565. assert.NoError(t, err)
  1566. }
  1567. func TestCombineDisabled(t *testing.T) {
  1568. u := getTestUser()
  1569. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  1570. assert.NoError(t, err)
  1571. sftpUser, _, err := httpd.AddUser(getTestSFTPUser(), http.StatusOK)
  1572. assert.NoError(t, err)
  1573. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1574. client, err := getFTPClient(user, true)
  1575. if assert.NoError(t, err) {
  1576. err = checkBasicFTP(client)
  1577. assert.NoError(t, err)
  1578. code, response, err := client.SendCustomCommand("COMB file file.1 file.2")
  1579. assert.NoError(t, err)
  1580. assert.Equal(t, ftp.StatusNotImplemented, code)
  1581. assert.Equal(t, "COMB support is disabled", response)
  1582. err = client.Quit()
  1583. assert.NoError(t, err)
  1584. }
  1585. }
  1586. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  1587. assert.NoError(t, err)
  1588. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  1589. assert.NoError(t, err)
  1590. err = os.RemoveAll(localUser.GetHomeDir())
  1591. assert.NoError(t, err)
  1592. }
  1593. func TestActiveModeDisabled(t *testing.T) {
  1594. u := getTestUser()
  1595. user, _, err := httpd.AddUser(u, http.StatusOK)
  1596. assert.NoError(t, err)
  1597. client, err := getFTPClientImplicitTLS(user)
  1598. if assert.NoError(t, err) {
  1599. err = checkBasicFTP(client)
  1600. assert.NoError(t, err)
  1601. code, response, err := client.SendCustomCommand("PORT 10,2,0,2,4,31")
  1602. assert.NoError(t, err)
  1603. assert.Equal(t, ftp.StatusNotAvailable, code)
  1604. assert.Equal(t, "PORT command is disabled", response)
  1605. code, response, err = client.SendCustomCommand("EPRT |1|132.235.1.2|6275|")
  1606. assert.NoError(t, err)
  1607. assert.Equal(t, ftp.StatusNotAvailable, code)
  1608. assert.Equal(t, "EPRT command is disabled", response)
  1609. err = client.Quit()
  1610. assert.NoError(t, err)
  1611. }
  1612. client, err = getFTPClient(user, false)
  1613. if assert.NoError(t, err) {
  1614. code, response, err := client.SendCustomCommand("PORT 10,2,0,2,4,31")
  1615. assert.NoError(t, err)
  1616. assert.Equal(t, ftp.StatusCommandOK, code)
  1617. assert.Equal(t, "PORT command successful", response)
  1618. code, response, err = client.SendCustomCommand("EPRT |1|132.235.1.2|6275|")
  1619. assert.NoError(t, err)
  1620. assert.Equal(t, ftp.StatusCommandOK, code)
  1621. assert.Equal(t, "EPRT command successful", response)
  1622. err = client.Quit()
  1623. assert.NoError(t, err)
  1624. }
  1625. _, err = httpd.RemoveUser(user, http.StatusOK)
  1626. assert.NoError(t, err)
  1627. err = os.RemoveAll(user.GetHomeDir())
  1628. assert.NoError(t, err)
  1629. }
  1630. func TestSITEDisabled(t *testing.T) {
  1631. u := getTestUser()
  1632. user, _, err := httpd.AddUser(u, http.StatusOK)
  1633. assert.NoError(t, err)
  1634. client, err := getFTPClientImplicitTLS(user)
  1635. if assert.NoError(t, err) {
  1636. err = checkBasicFTP(client)
  1637. assert.NoError(t, err)
  1638. code, response, err := client.SendCustomCommand("SITE CHMOD 600 afile.txt")
  1639. assert.NoError(t, err)
  1640. assert.Equal(t, ftp.StatusBadCommand, code)
  1641. assert.Equal(t, "SITE support is disabled", response)
  1642. err = client.Quit()
  1643. assert.NoError(t, err)
  1644. }
  1645. _, err = httpd.RemoveUser(user, http.StatusOK)
  1646. assert.NoError(t, err)
  1647. err = os.RemoveAll(user.GetHomeDir())
  1648. assert.NoError(t, err)
  1649. }
  1650. func TestHASH(t *testing.T) {
  1651. u := getTestUser()
  1652. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  1653. assert.NoError(t, err)
  1654. sftpUser, _, err := httpd.AddUser(getTestSFTPUser(), http.StatusOK)
  1655. assert.NoError(t, err)
  1656. u = getTestUserWithCryptFs()
  1657. u.Username += "_crypt"
  1658. cryptUser, _, err := httpd.AddUser(u, http.StatusOK)
  1659. assert.NoError(t, err)
  1660. for _, user := range []dataprovider.User{localUser, sftpUser, cryptUser} {
  1661. client, err := getFTPClientImplicitTLS(user)
  1662. if assert.NoError(t, err) {
  1663. testFilePath := filepath.Join(homeBasePath, testFileName)
  1664. testFileSize := int64(131072)
  1665. err = createTestFile(testFilePath, testFileSize)
  1666. assert.NoError(t, err)
  1667. err = checkBasicFTP(client)
  1668. assert.NoError(t, err)
  1669. err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
  1670. assert.NoError(t, err)
  1671. h := sha256.New()
  1672. f, err := os.Open(testFilePath)
  1673. assert.NoError(t, err)
  1674. _, err = io.Copy(h, f)
  1675. assert.NoError(t, err)
  1676. hash := hex.EncodeToString(h.Sum(nil))
  1677. err = f.Close()
  1678. assert.NoError(t, err)
  1679. code, response, err := client.SendCustomCommand(fmt.Sprintf("XSHA256 %v", testFileName))
  1680. assert.NoError(t, err)
  1681. assert.Equal(t, ftp.StatusRequestedFileActionOK, code)
  1682. assert.Contains(t, response, hash)
  1683. code, response, err = client.SendCustomCommand(fmt.Sprintf("HASH %v", testFileName))
  1684. assert.NoError(t, err)
  1685. assert.Equal(t, ftp.StatusFile, code)
  1686. assert.Contains(t, response, hash)
  1687. err = client.Quit()
  1688. assert.NoError(t, err)
  1689. err = os.Remove(testFilePath)
  1690. assert.NoError(t, err)
  1691. if user.Username == defaultUsername {
  1692. err = os.RemoveAll(user.GetHomeDir())
  1693. assert.NoError(t, err)
  1694. }
  1695. }
  1696. }
  1697. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  1698. assert.NoError(t, err)
  1699. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  1700. assert.NoError(t, err)
  1701. err = os.RemoveAll(localUser.GetHomeDir())
  1702. assert.NoError(t, err)
  1703. _, err = httpd.RemoveUser(cryptUser, http.StatusOK)
  1704. assert.NoError(t, err)
  1705. err = os.RemoveAll(cryptUser.GetHomeDir())
  1706. assert.NoError(t, err)
  1707. }
  1708. func TestCombine(t *testing.T) {
  1709. u := getTestUser()
  1710. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  1711. assert.NoError(t, err)
  1712. sftpUser, _, err := httpd.AddUser(getTestSFTPUser(), http.StatusOK)
  1713. assert.NoError(t, err)
  1714. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1715. client, err := getFTPClientImplicitTLS(user)
  1716. if assert.NoError(t, err) {
  1717. testFilePath := filepath.Join(homeBasePath, testFileName)
  1718. testFileSize := int64(131072)
  1719. err = createTestFile(testFilePath, testFileSize)
  1720. assert.NoError(t, err)
  1721. err = checkBasicFTP(client)
  1722. assert.NoError(t, err)
  1723. err = ftpUploadFile(testFilePath, testFileName+".1", testFileSize, client, 0)
  1724. assert.NoError(t, err)
  1725. err = ftpUploadFile(testFilePath, testFileName+".2", testFileSize, client, 0)
  1726. assert.NoError(t, err)
  1727. code, response, err := client.SendCustomCommand(fmt.Sprintf("COMB %v %v %v", testFileName, testFileName+".1", testFileName+".2"))
  1728. assert.NoError(t, err)
  1729. if user.Username == defaultUsername {
  1730. assert.Equal(t, ftp.StatusRequestedFileActionOK, code)
  1731. assert.Equal(t, "COMB succeeded!", response)
  1732. } else {
  1733. assert.Equal(t, ftp.StatusFileUnavailable, code)
  1734. assert.Contains(t, response, "COMB is not supported for this filesystem")
  1735. }
  1736. err = client.Quit()
  1737. assert.NoError(t, err)
  1738. err = os.Remove(testFilePath)
  1739. assert.NoError(t, err)
  1740. if user.Username == defaultUsername {
  1741. err = os.RemoveAll(user.GetHomeDir())
  1742. assert.NoError(t, err)
  1743. }
  1744. }
  1745. }
  1746. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  1747. assert.NoError(t, err)
  1748. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  1749. assert.NoError(t, err)
  1750. err = os.RemoveAll(localUser.GetHomeDir())
  1751. assert.NoError(t, err)
  1752. }
  1753. func checkBasicFTP(client *ftp.ServerConn) error {
  1754. _, err := client.CurrentDir()
  1755. if err != nil {
  1756. return err
  1757. }
  1758. err = client.NoOp()
  1759. if err != nil {
  1760. return err
  1761. }
  1762. _, err = client.List(".")
  1763. if err != nil {
  1764. return err
  1765. }
  1766. return nil
  1767. }
  1768. func ftpUploadFile(localSourcePath string, remoteDestPath string, expectedSize int64, client *ftp.ServerConn, offset uint64) error {
  1769. srcFile, err := os.Open(localSourcePath)
  1770. if err != nil {
  1771. return err
  1772. }
  1773. defer srcFile.Close()
  1774. if offset > 0 {
  1775. err = client.StorFrom(remoteDestPath, srcFile, offset)
  1776. } else {
  1777. err = client.Stor(remoteDestPath, srcFile)
  1778. }
  1779. if err != nil {
  1780. return err
  1781. }
  1782. if expectedSize > 0 {
  1783. size, err := client.FileSize(remoteDestPath)
  1784. if err != nil {
  1785. return err
  1786. }
  1787. if size != expectedSize {
  1788. return fmt.Errorf("uploaded file size does not match, actual: %v, expected: %v", size, expectedSize)
  1789. }
  1790. }
  1791. return nil
  1792. }
  1793. func ftpDownloadFile(remoteSourcePath string, localDestPath string, expectedSize int64, client *ftp.ServerConn, offset uint64) error {
  1794. downloadDest, err := os.Create(localDestPath)
  1795. if err != nil {
  1796. return err
  1797. }
  1798. defer downloadDest.Close()
  1799. var r *ftp.Response
  1800. if offset > 0 {
  1801. r, err = client.RetrFrom(remoteSourcePath, offset)
  1802. } else {
  1803. r, err = client.Retr(remoteSourcePath)
  1804. }
  1805. if err != nil {
  1806. return err
  1807. }
  1808. defer r.Close()
  1809. written, err := io.Copy(downloadDest, r)
  1810. if err != nil {
  1811. return err
  1812. }
  1813. if written != expectedSize {
  1814. return fmt.Errorf("downloaded file size does not match, actual: %v, expected: %v", written, expectedSize)
  1815. }
  1816. return nil
  1817. }
  1818. func getFTPClientImplicitTLS(user dataprovider.User) (*ftp.ServerConn, error) {
  1819. ftpOptions := []ftp.DialOption{ftp.DialWithTimeout(5 * time.Second)}
  1820. tlsConfig := &tls.Config{
  1821. ServerName: "localhost",
  1822. InsecureSkipVerify: true, // use this for tests only
  1823. MinVersion: tls.VersionTLS12,
  1824. }
  1825. ftpOptions = append(ftpOptions, ftp.DialWithTLS(tlsConfig))
  1826. ftpOptions = append(ftpOptions, ftp.DialWithDisabledEPSV(true))
  1827. client, err := ftp.Dial(ftpSrvAddrTLS, ftpOptions...)
  1828. if err != nil {
  1829. return nil, err
  1830. }
  1831. pwd := defaultPassword
  1832. if user.Password != "" {
  1833. pwd = user.Password
  1834. }
  1835. err = client.Login(user.Username, pwd)
  1836. if err != nil {
  1837. return nil, err
  1838. }
  1839. return client, err
  1840. }
  1841. func getFTPClient(user dataprovider.User, useTLS bool) (*ftp.ServerConn, error) {
  1842. ftpOptions := []ftp.DialOption{ftp.DialWithTimeout(5 * time.Second)}
  1843. if useTLS {
  1844. tlsConfig := &tls.Config{
  1845. ServerName: "localhost",
  1846. InsecureSkipVerify: true, // use this for tests only
  1847. MinVersion: tls.VersionTLS12,
  1848. }
  1849. ftpOptions = append(ftpOptions, ftp.DialWithExplicitTLS(tlsConfig))
  1850. }
  1851. client, err := ftp.Dial(ftpServerAddr, ftpOptions...)
  1852. if err != nil {
  1853. return nil, err
  1854. }
  1855. pwd := defaultPassword
  1856. if user.Password != "" {
  1857. pwd = user.Password
  1858. }
  1859. err = client.Login(user.Username, pwd)
  1860. if err != nil {
  1861. return nil, err
  1862. }
  1863. return client, err
  1864. }
  1865. func waitTCPListening(address string) {
  1866. for {
  1867. conn, err := net.Dial("tcp", address)
  1868. if err != nil {
  1869. logger.WarnToConsole("tcp server %v not listening: %v\n", address, err)
  1870. time.Sleep(100 * time.Millisecond)
  1871. continue
  1872. }
  1873. logger.InfoToConsole("tcp server %v now listening\n", address)
  1874. conn.Close()
  1875. break
  1876. }
  1877. }
  1878. func getTestUser() dataprovider.User {
  1879. user := dataprovider.User{
  1880. Username: defaultUsername,
  1881. Password: defaultPassword,
  1882. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  1883. Status: 1,
  1884. ExpirationDate: 0,
  1885. }
  1886. user.Permissions = make(map[string][]string)
  1887. user.Permissions["/"] = allPerms
  1888. return user
  1889. }
  1890. func getTestSFTPUser() dataprovider.User {
  1891. u := getTestUser()
  1892. u.Username = u.Username + "_sftp"
  1893. u.FsConfig.Provider = dataprovider.SFTPFilesystemProvider
  1894. u.FsConfig.SFTPConfig.Endpoint = sftpServerAddr
  1895. u.FsConfig.SFTPConfig.Username = defaultUsername
  1896. u.FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword)
  1897. return u
  1898. }
  1899. func getExtAuthScriptContent(user dataprovider.User, nonJSONResponse bool, username string) []byte {
  1900. extAuthContent := []byte("#!/bin/sh\n\n")
  1901. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("if test \"$SFTPGO_AUTHD_USERNAME\" = \"%v\"; then\n", user.Username))...)
  1902. if len(username) > 0 {
  1903. user.Username = username
  1904. }
  1905. u, _ := json.Marshal(user)
  1906. if nonJSONResponse {
  1907. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  1908. } else {
  1909. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  1910. }
  1911. extAuthContent = append(extAuthContent, []byte("else\n")...)
  1912. if nonJSONResponse {
  1913. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  1914. } else {
  1915. extAuthContent = append(extAuthContent, []byte("echo '{\"username\":\"\"}'\n")...)
  1916. }
  1917. extAuthContent = append(extAuthContent, []byte("fi\n")...)
  1918. return extAuthContent
  1919. }
  1920. func getPreLoginScriptContent(user dataprovider.User, nonJSONResponse bool) []byte {
  1921. content := []byte("#!/bin/sh\n\n")
  1922. if nonJSONResponse {
  1923. content = append(content, []byte("echo 'text response'\n")...)
  1924. return content
  1925. }
  1926. if len(user.Username) > 0 {
  1927. u, _ := json.Marshal(user)
  1928. content = append(content, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  1929. }
  1930. return content
  1931. }
  1932. func getPostConnectScriptContent(exitCode int) []byte {
  1933. content := []byte("#!/bin/sh\n\n")
  1934. content = append(content, []byte(fmt.Sprintf("exit %v", exitCode))...)
  1935. return content
  1936. }
  1937. func createTestFile(path string, size int64) error {
  1938. baseDir := filepath.Dir(path)
  1939. if _, err := os.Stat(baseDir); os.IsNotExist(err) {
  1940. err = os.MkdirAll(baseDir, os.ModePerm)
  1941. if err != nil {
  1942. return err
  1943. }
  1944. }
  1945. content := make([]byte, size)
  1946. _, err := rand.Read(content)
  1947. if err != nil {
  1948. return err
  1949. }
  1950. return ioutil.WriteFile(path, content, os.ModePerm)
  1951. }