webdavd_test.go 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676
  1. package webdavd_test
  2. import (
  3. "bytes"
  4. "crypto/rand"
  5. "encoding/json"
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "net"
  10. "net/http"
  11. "os"
  12. "os/exec"
  13. "path"
  14. "path/filepath"
  15. "runtime"
  16. "strings"
  17. "sync"
  18. "testing"
  19. "time"
  20. "github.com/minio/sio"
  21. "github.com/rs/zerolog"
  22. "github.com/stretchr/testify/assert"
  23. "github.com/studio-b12/gowebdav"
  24. "github.com/drakkan/sftpgo/common"
  25. "github.com/drakkan/sftpgo/config"
  26. "github.com/drakkan/sftpgo/dataprovider"
  27. "github.com/drakkan/sftpgo/httpclient"
  28. "github.com/drakkan/sftpgo/httpdtest"
  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. "github.com/drakkan/sftpgo/webdavd"
  34. )
  35. const (
  36. logSender = "webavdTesting"
  37. webDavServerAddr = "127.0.0.1:9090"
  38. webDavServerPort = 9090
  39. sftpServerAddr = "127.0.0.1:9022"
  40. defaultUsername = "test_user_dav"
  41. defaultPassword = "test_password"
  42. configDir = ".."
  43. osWindows = "windows"
  44. webDavCert = `-----BEGIN CERTIFICATE-----
  45. MIICHTCCAaKgAwIBAgIUHnqw7QnB1Bj9oUsNpdb+ZkFPOxMwCgYIKoZIzj0EAwIw
  46. RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
  47. dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDAyMDQwOTUzMDRaFw0zMDAyMDEw
  48. OTUzMDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD
  49. VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwdjAQBgcqhkjOPQIBBgUrgQQA
  50. IgNiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVqWvrJ51t5OxV0v25NsOgR82CA
  51. NXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIVCzgWkxiz7XE4lgUwX44FCXZM
  52. 3+JeUbKjUzBRMB0GA1UdDgQWBBRhLw+/o3+Z02MI/d4tmaMui9W16jAfBgNVHSME
  53. GDAWgBRhLw+/o3+Z02MI/d4tmaMui9W16jAPBgNVHRMBAf8EBTADAQH/MAoGCCqG
  54. SM49BAMCA2kAMGYCMQDqLt2lm8mE+tGgtjDmtFgdOcI72HSbRQ74D5rYTzgST1rY
  55. /8wTi5xl8TiFUyLMUsICMQC5ViVxdXbhuG7gX6yEqSkMKZICHpO8hqFwOD/uaFVI
  56. dV4vKmHUzwK/eIx+8Ay3neE=
  57. -----END CERTIFICATE-----`
  58. webDavKey = `-----BEGIN EC PARAMETERS-----
  59. BgUrgQQAIg==
  60. -----END EC PARAMETERS-----
  61. -----BEGIN EC PRIVATE KEY-----
  62. MIGkAgEBBDCfMNsN6miEE3rVyUPwElfiJSWaR5huPCzUenZOfJT04GAcQdWvEju3
  63. UM2lmBLIXpGgBwYFK4EEACKhZANiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVq
  64. WvrJ51t5OxV0v25NsOgR82CANXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIV
  65. CzgWkxiz7XE4lgUwX44FCXZM3+JeUbI=
  66. -----END EC PRIVATE KEY-----`
  67. testFileName = "test_file_dav.dat"
  68. testDLFileName = "test_download_dav.dat"
  69. )
  70. var (
  71. allPerms = []string{dataprovider.PermAny}
  72. homeBasePath string
  73. hookCmdPath string
  74. extAuthPath string
  75. preLoginPath string
  76. postConnectPath string
  77. logFilePath string
  78. certPath string
  79. keyPath string
  80. )
  81. func TestMain(m *testing.M) {
  82. logFilePath = filepath.Join(configDir, "sftpgo_webdavd_test.log")
  83. logger.InitLogger(logFilePath, 5, 1, 28, false, zerolog.DebugLevel)
  84. err := config.LoadConfig(configDir, "")
  85. if err != nil {
  86. logger.ErrorToConsole("error loading configuration: %v", err)
  87. os.Exit(1)
  88. }
  89. providerConf := config.GetProviderConf()
  90. logger.InfoToConsole("Starting WebDAVD tests, provider: %v", providerConf.Driver)
  91. commonConf := config.GetCommonConfig()
  92. commonConf.UploadMode = 2
  93. homeBasePath = os.TempDir()
  94. if runtime.GOOS != osWindows {
  95. commonConf.Actions.ExecuteOn = []string{"download", "upload", "rename", "delete"}
  96. commonConf.Actions.Hook = hookCmdPath
  97. hookCmdPath, err = exec.LookPath("true")
  98. if err != nil {
  99. logger.Warn(logSender, "", "unable to get hook command: %v", err)
  100. logger.WarnToConsole("unable to get hook command: %v", err)
  101. }
  102. }
  103. certPath = filepath.Join(os.TempDir(), "test_dav.crt")
  104. keyPath = filepath.Join(os.TempDir(), "test_dav.key")
  105. err = ioutil.WriteFile(certPath, []byte(webDavCert), os.ModePerm)
  106. if err != nil {
  107. logger.ErrorToConsole("error writing WebDAV certificate: %v", err)
  108. os.Exit(1)
  109. }
  110. err = ioutil.WriteFile(keyPath, []byte(webDavKey), os.ModePerm)
  111. if err != nil {
  112. logger.ErrorToConsole("error writing WebDAV private key: %v", err)
  113. os.Exit(1)
  114. }
  115. err = common.Initialize(commonConf)
  116. if err != nil {
  117. logger.WarnToConsole("error initializing common: %v", err)
  118. os.Exit(1)
  119. }
  120. err = dataprovider.Initialize(providerConf, configDir, true)
  121. if err != nil {
  122. logger.ErrorToConsole("error initializing data provider: %v", err)
  123. os.Exit(1)
  124. }
  125. httpConfig := config.GetHTTPConfig()
  126. httpConfig.Initialize(configDir)
  127. kmsConfig := config.GetKMSConfig()
  128. err = kmsConfig.Initialize()
  129. if err != nil {
  130. logger.ErrorToConsole("error initializing kms: %v", err)
  131. os.Exit(1)
  132. }
  133. httpdConf := config.GetHTTPDConfig()
  134. httpdConf.Bindings[0].Port = 8078
  135. httpdtest.SetBaseURL("http://127.0.0.1:8078")
  136. // required to test sftpfs
  137. sftpdConf := config.GetSFTPDConfig()
  138. sftpdConf.Bindings = []sftpd.Binding{
  139. {
  140. Port: 9022,
  141. },
  142. }
  143. hostKeyPath := filepath.Join(os.TempDir(), "id_ecdsa")
  144. sftpdConf.HostKeys = []string{hostKeyPath}
  145. webDavConf := config.GetWebDAVDConfig()
  146. webDavConf.Bindings = []webdavd.Binding{
  147. {
  148. Port: webDavServerPort,
  149. },
  150. }
  151. webDavConf.Cors = webdavd.Cors{
  152. Enabled: true,
  153. AllowedOrigins: []string{"*"},
  154. AllowedMethods: []string{
  155. http.MethodHead,
  156. http.MethodGet,
  157. http.MethodPost,
  158. http.MethodPut,
  159. http.MethodPatch,
  160. http.MethodDelete,
  161. },
  162. AllowedHeaders: []string{"*"},
  163. AllowCredentials: true,
  164. }
  165. status := webdavd.GetStatus()
  166. if status.IsActive {
  167. logger.ErrorToConsole("webdav server is already active")
  168. os.Exit(1)
  169. }
  170. extAuthPath = filepath.Join(homeBasePath, "extauth.sh")
  171. preLoginPath = filepath.Join(homeBasePath, "prelogin.sh")
  172. postConnectPath = filepath.Join(homeBasePath, "postconnect.sh")
  173. go func() {
  174. logger.Debug(logSender, "", "initializing WebDAV server with config %+v", webDavConf)
  175. if err := webDavConf.Initialize(configDir); err != nil {
  176. logger.ErrorToConsole("could not start WebDAV server: %v", err)
  177. os.Exit(1)
  178. }
  179. }()
  180. go func() {
  181. if err := httpdConf.Initialize(configDir); err != nil {
  182. logger.ErrorToConsole("could not start HTTP server: %v", err)
  183. os.Exit(1)
  184. }
  185. }()
  186. go func() {
  187. logger.Debug(logSender, "", "initializing SFTP server with config %+v", sftpdConf)
  188. if err := sftpdConf.Initialize(configDir); err != nil {
  189. logger.ErrorToConsole("could not start SFTP server: %v", err)
  190. os.Exit(1)
  191. }
  192. }()
  193. waitTCPListening(webDavConf.Bindings[0].GetAddress())
  194. waitTCPListening(httpdConf.Bindings[0].GetAddress())
  195. waitTCPListening(sftpdConf.Bindings[0].GetAddress())
  196. webdavd.ReloadCertificateMgr() //nolint:errcheck
  197. exitCode := m.Run()
  198. os.Remove(logFilePath)
  199. os.Remove(extAuthPath)
  200. os.Remove(preLoginPath)
  201. os.Remove(postConnectPath)
  202. os.Remove(certPath)
  203. os.Remove(keyPath)
  204. os.Remove(hostKeyPath)
  205. os.Remove(hostKeyPath + ".pub")
  206. os.Exit(exitCode)
  207. }
  208. func TestInitialization(t *testing.T) {
  209. cfg := webdavd.Configuration{
  210. Bindings: []webdavd.Binding{
  211. {
  212. Port: 1234,
  213. EnableHTTPS: true,
  214. },
  215. {
  216. Port: 0,
  217. },
  218. },
  219. CertificateFile: "missing path",
  220. CertificateKeyFile: "bad path",
  221. }
  222. err := cfg.Initialize(configDir)
  223. assert.Error(t, err)
  224. cfg.Cache = config.GetWebDAVDConfig().Cache
  225. cfg.Bindings[0].Port = webDavServerPort
  226. cfg.CertificateFile = certPath
  227. cfg.CertificateKeyFile = keyPath
  228. err = cfg.Initialize(configDir)
  229. assert.Error(t, err)
  230. err = webdavd.ReloadCertificateMgr()
  231. assert.NoError(t, err)
  232. cfg.Bindings = []webdavd.Binding{
  233. {
  234. Port: 0,
  235. },
  236. }
  237. err = cfg.Initialize(configDir)
  238. assert.EqualError(t, err, common.ErrNoBinding.Error())
  239. cfg.CertificateFile = certPath
  240. cfg.CertificateKeyFile = keyPath
  241. cfg.CACertificates = []string{""}
  242. cfg.Bindings = []webdavd.Binding{
  243. {
  244. Port: 9022,
  245. ClientAuthType: 1,
  246. EnableHTTPS: true,
  247. },
  248. }
  249. err = cfg.Initialize(configDir)
  250. assert.Error(t, err)
  251. cfg.CACertificates = nil
  252. cfg.CARevocationLists = []string{""}
  253. err = cfg.Initialize(configDir)
  254. assert.Error(t, err)
  255. cfg.CARevocationLists = nil
  256. err = cfg.Initialize(configDir)
  257. assert.Error(t, err)
  258. }
  259. func TestBasicHandling(t *testing.T) {
  260. u := getTestUser()
  261. u.QuotaSize = 6553600
  262. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  263. assert.NoError(t, err)
  264. u = getTestSFTPUser()
  265. u.QuotaSize = 6553600
  266. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  267. assert.NoError(t, err)
  268. for _, user := range []dataprovider.User{localUser, sftpUser} {
  269. client := getWebDavClient(user)
  270. assert.NoError(t, checkBasicFunc(client))
  271. testFilePath := filepath.Join(homeBasePath, testFileName)
  272. testFileSize := int64(65535)
  273. expectedQuotaSize := testFileSize
  274. expectedQuotaFiles := 1
  275. err = createTestFile(testFilePath, testFileSize)
  276. assert.NoError(t, err)
  277. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  278. assert.NoError(t, err)
  279. // overwrite an existing file
  280. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  281. assert.NoError(t, err)
  282. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  283. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  284. assert.NoError(t, err)
  285. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  286. assert.NoError(t, err)
  287. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  288. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  289. err = client.Rename(testFileName, testFileName+"1", false)
  290. assert.NoError(t, err)
  291. _, err = client.Stat(testFileName)
  292. assert.Error(t, err)
  293. // the webdav client hide the error we check the quota
  294. err = client.Remove(testFileName)
  295. assert.NoError(t, err)
  296. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  297. assert.NoError(t, err)
  298. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  299. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  300. err = client.Remove(testFileName + "1")
  301. assert.NoError(t, err)
  302. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  303. assert.NoError(t, err)
  304. assert.Equal(t, expectedQuotaFiles-1, user.UsedQuotaFiles)
  305. assert.Equal(t, expectedQuotaSize-testFileSize, user.UsedQuotaSize)
  306. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  307. assert.Error(t, err)
  308. testDir := "testdir"
  309. err = client.Mkdir(testDir, os.ModePerm)
  310. assert.NoError(t, err)
  311. err = client.MkdirAll(path.Join(testDir, "sub", "sub"), os.ModePerm)
  312. assert.NoError(t, err)
  313. err = client.MkdirAll(path.Join(testDir, "sub1", "sub1"), os.ModePerm)
  314. assert.NoError(t, err)
  315. err = client.MkdirAll(path.Join(testDir, "sub2", "sub2"), os.ModePerm)
  316. assert.NoError(t, err)
  317. err = uploadFile(testFilePath, path.Join(testDir, testFileName+".txt"), testFileSize, client)
  318. assert.NoError(t, err)
  319. err = uploadFile(testFilePath, path.Join(testDir, testFileName), testFileSize, client)
  320. assert.NoError(t, err)
  321. files, err := client.ReadDir(testDir)
  322. assert.NoError(t, err)
  323. assert.Len(t, files, 5)
  324. err = client.Copy(testDir, testDir+"_copy", false)
  325. assert.NoError(t, err)
  326. err = client.RemoveAll(testDir)
  327. assert.NoError(t, err)
  328. err = os.Remove(testFilePath)
  329. assert.NoError(t, err)
  330. err = os.Remove(localDownloadPath)
  331. assert.NoError(t, err)
  332. if user.Username == defaultUsername {
  333. err = os.RemoveAll(user.GetHomeDir())
  334. assert.NoError(t, err)
  335. }
  336. }
  337. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  338. assert.NoError(t, err)
  339. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  340. assert.NoError(t, err)
  341. err = os.RemoveAll(localUser.GetHomeDir())
  342. assert.NoError(t, err)
  343. assert.Len(t, common.Connections.GetStats(), 0)
  344. status := webdavd.GetStatus()
  345. assert.True(t, status.IsActive)
  346. }
  347. func TestBasicHandlingCryptFs(t *testing.T) {
  348. u := getTestUserWithCryptFs()
  349. u.QuotaSize = 6553600
  350. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  351. assert.NoError(t, err)
  352. client := getWebDavClient(user)
  353. assert.NoError(t, checkBasicFunc(client))
  354. testFilePath := filepath.Join(homeBasePath, testFileName)
  355. testFileSize := int64(65535)
  356. encryptedFileSize, err := getEncryptedFileSize(testFileSize)
  357. assert.NoError(t, err)
  358. expectedQuotaSize := user.UsedQuotaSize + encryptedFileSize
  359. expectedQuotaFiles := user.UsedQuotaFiles + 1
  360. err = createTestFile(testFilePath, testFileSize)
  361. assert.NoError(t, err)
  362. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  363. assert.NoError(t, err)
  364. // overwrite an existing file
  365. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  366. assert.NoError(t, err)
  367. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  368. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  369. assert.NoError(t, err)
  370. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  371. assert.NoError(t, err)
  372. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  373. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  374. files, err := client.ReadDir("/")
  375. assert.NoError(t, err)
  376. if assert.Len(t, files, 1) {
  377. assert.Equal(t, testFileSize, files[0].Size())
  378. }
  379. err = client.Remove(testFileName)
  380. assert.NoError(t, err)
  381. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  382. assert.NoError(t, err)
  383. assert.Equal(t, expectedQuotaFiles-1, user.UsedQuotaFiles)
  384. assert.Equal(t, expectedQuotaSize-encryptedFileSize, user.UsedQuotaSize)
  385. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  386. assert.Error(t, err)
  387. testDir := "testdir"
  388. err = client.Mkdir(testDir, os.ModePerm)
  389. assert.NoError(t, err)
  390. err = client.MkdirAll(path.Join(testDir, "sub", "sub"), os.ModePerm)
  391. assert.NoError(t, err)
  392. err = client.MkdirAll(path.Join(testDir, "sub1", "sub1"), os.ModePerm)
  393. assert.NoError(t, err)
  394. err = client.MkdirAll(path.Join(testDir, "sub2", "sub2"), os.ModePerm)
  395. assert.NoError(t, err)
  396. err = uploadFile(testFilePath, path.Join(testDir, testFileName+".txt"), testFileSize, client)
  397. assert.NoError(t, err)
  398. err = uploadFile(testFilePath, path.Join(testDir, testFileName), testFileSize, client)
  399. assert.NoError(t, err)
  400. files, err = client.ReadDir(testDir)
  401. assert.NoError(t, err)
  402. assert.Len(t, files, 5)
  403. for _, f := range files {
  404. if strings.HasPrefix(f.Name(), testFileName) {
  405. assert.Equal(t, testFileSize, f.Size())
  406. } else {
  407. assert.True(t, f.IsDir())
  408. }
  409. }
  410. err = os.Remove(testFilePath)
  411. assert.NoError(t, err)
  412. err = os.Remove(localDownloadPath)
  413. assert.NoError(t, err)
  414. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  415. assert.NoError(t, err)
  416. err = os.RemoveAll(user.GetHomeDir())
  417. assert.NoError(t, err)
  418. assert.Len(t, common.Connections.GetStats(), 0)
  419. }
  420. func TestPropPatch(t *testing.T) {
  421. u := getTestUser()
  422. u.Username = u.Username + "1"
  423. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  424. assert.NoError(t, err)
  425. sftpUser := getTestSFTPUser()
  426. sftpUser.FsConfig.SFTPConfig.Username = localUser.Username
  427. for _, u := range []dataprovider.User{getTestUser(), getTestUserWithCryptFs(), sftpUser} {
  428. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  429. assert.NoError(t, err)
  430. client := getWebDavClient(user)
  431. assert.NoError(t, checkBasicFunc(client), sftpUser.Username)
  432. testFilePath := filepath.Join(homeBasePath, testFileName)
  433. testFileSize := int64(65535)
  434. err = createTestFile(testFilePath, testFileSize)
  435. assert.NoError(t, err)
  436. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  437. assert.NoError(t, err)
  438. httpClient := httpclient.GetHTTPClient()
  439. propatchBody := `<?xml version="1.0" encoding="utf-8" ?><D:propertyupdate xmlns:D="DAV:" xmlns:Z="urn:schemas-microsoft-com:"><D:set><D:prop><Z:Win32CreationTime>Wed, 04 Nov 2020 13:25:51 GMT</Z:Win32CreationTime><Z:Win32LastAccessTime>Sat, 05 Dec 2020 21:16:12 GMT</Z:Win32LastAccessTime><Z:Win32LastModifiedTime>Wed, 04 Nov 2020 13:25:51 GMT</Z:Win32LastModifiedTime><Z:Win32FileAttributes>00000000</Z:Win32FileAttributes></D:prop></D:set></D:propertyupdate>`
  440. req, err := http.NewRequest("PROPPATCH", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(propatchBody)))
  441. assert.NoError(t, err)
  442. req.SetBasicAuth(u.Username, u.Password)
  443. resp, err := httpClient.Do(req)
  444. assert.NoError(t, err)
  445. assert.Equal(t, 207, resp.StatusCode)
  446. err = resp.Body.Close()
  447. assert.NoError(t, err)
  448. info, err := client.Stat(testFileName)
  449. if assert.NoError(t, err) {
  450. assert.Equal(t, testFileSize, info.Size())
  451. }
  452. err = os.Remove(testFilePath)
  453. assert.NoError(t, err)
  454. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  455. assert.NoError(t, err)
  456. err = os.RemoveAll(user.GetHomeDir())
  457. assert.NoError(t, err)
  458. assert.Len(t, common.Connections.GetStats(), 0)
  459. }
  460. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  461. assert.NoError(t, err)
  462. err = os.RemoveAll(localUser.GetHomeDir())
  463. assert.NoError(t, err)
  464. }
  465. func TestLoginInvalidPwd(t *testing.T) {
  466. u := getTestUser()
  467. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  468. assert.NoError(t, err)
  469. client := getWebDavClient(user)
  470. assert.NoError(t, checkBasicFunc(client))
  471. user.Password = "wrong"
  472. client = getWebDavClient(user)
  473. assert.Error(t, checkBasicFunc(client))
  474. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  475. assert.NoError(t, err)
  476. }
  477. func TestLoginNonExistentUser(t *testing.T) {
  478. user := getTestUser()
  479. client := getWebDavClient(user)
  480. assert.Error(t, checkBasicFunc(client))
  481. }
  482. func TestDefender(t *testing.T) {
  483. oldConfig := config.GetCommonConfig()
  484. cfg := config.GetCommonConfig()
  485. cfg.DefenderConfig.Enabled = true
  486. cfg.DefenderConfig.Threshold = 3
  487. err := common.Initialize(cfg)
  488. assert.NoError(t, err)
  489. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  490. assert.NoError(t, err)
  491. client := getWebDavClient(user)
  492. assert.NoError(t, checkBasicFunc(client))
  493. for i := 0; i < 3; i++ {
  494. user.Password = "wrong_pwd"
  495. client = getWebDavClient(user)
  496. assert.Error(t, checkBasicFunc(client))
  497. }
  498. user.Password = defaultPassword
  499. client = getWebDavClient(user)
  500. err = checkBasicFunc(client)
  501. if assert.Error(t, err) {
  502. assert.Contains(t, err.Error(), "403")
  503. }
  504. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  505. assert.NoError(t, err)
  506. err = os.RemoveAll(user.GetHomeDir())
  507. assert.NoError(t, err)
  508. err = common.Initialize(oldConfig)
  509. assert.NoError(t, err)
  510. }
  511. func TestLoginExternalAuth(t *testing.T) {
  512. if runtime.GOOS == osWindows {
  513. t.Skip("this test is not available on Windows")
  514. }
  515. u := getTestUser()
  516. err := dataprovider.Close()
  517. assert.NoError(t, err)
  518. err = config.LoadConfig(configDir, "")
  519. assert.NoError(t, err)
  520. providerConf := config.GetProviderConf()
  521. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, ""), os.ModePerm)
  522. assert.NoError(t, err)
  523. providerConf.ExternalAuthHook = extAuthPath
  524. providerConf.ExternalAuthScope = 0
  525. err = dataprovider.Initialize(providerConf, configDir, true)
  526. assert.NoError(t, err)
  527. client := getWebDavClient(u)
  528. assert.NoError(t, checkBasicFunc(client))
  529. u.Username = defaultUsername + "1"
  530. client = getWebDavClient(u)
  531. assert.Error(t, checkBasicFunc(client))
  532. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  533. assert.NoError(t, err)
  534. assert.Equal(t, defaultUsername, user.Username)
  535. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  536. assert.NoError(t, err)
  537. err = os.RemoveAll(user.GetHomeDir())
  538. assert.NoError(t, err)
  539. err = dataprovider.Close()
  540. assert.NoError(t, err)
  541. err = config.LoadConfig(configDir, "")
  542. assert.NoError(t, err)
  543. providerConf = config.GetProviderConf()
  544. err = dataprovider.Initialize(providerConf, configDir, true)
  545. assert.NoError(t, err)
  546. err = os.Remove(extAuthPath)
  547. assert.NoError(t, err)
  548. }
  549. func TestPreLoginHook(t *testing.T) {
  550. if runtime.GOOS == osWindows {
  551. t.Skip("this test is not available on Windows")
  552. }
  553. u := getTestUser()
  554. err := dataprovider.Close()
  555. assert.NoError(t, err)
  556. err = config.LoadConfig(configDir, "")
  557. assert.NoError(t, err)
  558. providerConf := config.GetProviderConf()
  559. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
  560. assert.NoError(t, err)
  561. providerConf.PreLoginHook = preLoginPath
  562. err = dataprovider.Initialize(providerConf, configDir, true)
  563. assert.NoError(t, err)
  564. _, _, err = httpdtest.GetUserByUsername(defaultUsername, http.StatusNotFound)
  565. assert.NoError(t, err)
  566. client := getWebDavClient(u)
  567. assert.NoError(t, checkBasicFunc(client))
  568. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  569. assert.NoError(t, err)
  570. // test login with an existing user
  571. client = getWebDavClient(user)
  572. assert.NoError(t, checkBasicFunc(client))
  573. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), os.ModePerm)
  574. assert.NoError(t, err)
  575. // update the user to remove it from the cache
  576. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  577. assert.NoError(t, err)
  578. client = getWebDavClient(user)
  579. assert.Error(t, checkBasicFunc(client))
  580. // update the user to remove it from the cache
  581. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  582. assert.NoError(t, err)
  583. user.Status = 0
  584. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), os.ModePerm)
  585. assert.NoError(t, err)
  586. client = getWebDavClient(user)
  587. assert.Error(t, checkBasicFunc(client))
  588. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  589. assert.NoError(t, err)
  590. err = os.RemoveAll(user.GetHomeDir())
  591. assert.NoError(t, err)
  592. err = dataprovider.Close()
  593. assert.NoError(t, err)
  594. err = config.LoadConfig(configDir, "")
  595. assert.NoError(t, err)
  596. providerConf = config.GetProviderConf()
  597. err = dataprovider.Initialize(providerConf, configDir, true)
  598. assert.NoError(t, err)
  599. err = os.Remove(preLoginPath)
  600. assert.NoError(t, err)
  601. }
  602. func TestPostConnectHook(t *testing.T) {
  603. if runtime.GOOS == osWindows {
  604. t.Skip("this test is not available on Windows")
  605. }
  606. common.Config.PostConnectHook = postConnectPath
  607. u := getTestUser()
  608. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  609. assert.NoError(t, err)
  610. err = ioutil.WriteFile(postConnectPath, getPostConnectScriptContent(0), os.ModePerm)
  611. assert.NoError(t, err)
  612. client := getWebDavClient(user)
  613. assert.NoError(t, checkBasicFunc(client))
  614. err = ioutil.WriteFile(postConnectPath, getPostConnectScriptContent(1), os.ModePerm)
  615. assert.NoError(t, err)
  616. assert.Error(t, checkBasicFunc(client))
  617. common.Config.PostConnectHook = "http://127.0.0.1:8078/healthz"
  618. assert.NoError(t, checkBasicFunc(client))
  619. common.Config.PostConnectHook = "http://127.0.0.1:8078/notfound"
  620. assert.Error(t, checkBasicFunc(client))
  621. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  622. assert.NoError(t, err)
  623. err = os.RemoveAll(user.GetHomeDir())
  624. assert.NoError(t, err)
  625. common.Config.PostConnectHook = ""
  626. }
  627. func TestMaxConnections(t *testing.T) {
  628. oldValue := common.Config.MaxTotalConnections
  629. common.Config.MaxTotalConnections = 1
  630. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  631. assert.NoError(t, err)
  632. client := getWebDavClient(user)
  633. assert.NoError(t, checkBasicFunc(client))
  634. // now add a fake connection
  635. fs := vfs.NewOsFs("id", os.TempDir(), nil)
  636. connection := &webdavd.Connection{
  637. BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, user, fs),
  638. }
  639. common.Connections.Add(connection)
  640. assert.Error(t, checkBasicFunc(client))
  641. common.Connections.Remove(connection.GetID())
  642. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  643. assert.NoError(t, err)
  644. err = os.RemoveAll(user.GetHomeDir())
  645. assert.NoError(t, err)
  646. assert.Len(t, common.Connections.GetStats(), 0)
  647. common.Config.MaxTotalConnections = oldValue
  648. }
  649. func TestMaxSessions(t *testing.T) {
  650. u := getTestUser()
  651. u.MaxSessions = 1
  652. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  653. assert.NoError(t, err)
  654. client := getWebDavClient(user)
  655. assert.NoError(t, checkBasicFunc(client))
  656. // now add a fake connection
  657. fs := vfs.NewOsFs("id", os.TempDir(), nil)
  658. connection := &webdavd.Connection{
  659. BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, user, fs),
  660. }
  661. common.Connections.Add(connection)
  662. assert.Error(t, checkBasicFunc(client))
  663. common.Connections.Remove(connection.GetID())
  664. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  665. assert.NoError(t, err)
  666. err = os.RemoveAll(user.GetHomeDir())
  667. assert.NoError(t, err)
  668. assert.Len(t, common.Connections.GetStats(), 0)
  669. }
  670. func TestLoginWithIPilters(t *testing.T) {
  671. u := getTestUser()
  672. u.Filters.DeniedIP = []string{"192.167.0.0/24", "172.18.0.0/16"}
  673. u.Filters.AllowedIP = []string{"172.19.0.0/16"}
  674. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  675. assert.NoError(t, err)
  676. client := getWebDavClient(user)
  677. assert.Error(t, checkBasicFunc(client))
  678. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  679. assert.NoError(t, err)
  680. err = os.RemoveAll(user.GetHomeDir())
  681. assert.NoError(t, err)
  682. }
  683. func TestDownloadErrors(t *testing.T) {
  684. u := getTestUser()
  685. u.QuotaFiles = 1
  686. subDir1 := "sub1"
  687. subDir2 := "sub2"
  688. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems}
  689. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  690. dataprovider.PermDelete, dataprovider.PermDownload}
  691. // use an unknown mime to trigger content type detection
  692. u.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  693. {
  694. Path: "/sub2",
  695. AllowedExtensions: []string{},
  696. DeniedExtensions: []string{".zipp"},
  697. },
  698. }
  699. u.Filters.FilePatterns = []dataprovider.PatternsFilter{
  700. {
  701. Path: "/sub2",
  702. AllowedPatterns: []string{},
  703. DeniedPatterns: []string{"*.jpg"},
  704. },
  705. }
  706. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  707. assert.NoError(t, err)
  708. client := getWebDavClient(user)
  709. testFilePath1 := filepath.Join(user.HomeDir, subDir1, "file.zipp")
  710. testFilePath2 := filepath.Join(user.HomeDir, subDir2, "file.zipp")
  711. testFilePath3 := filepath.Join(user.HomeDir, subDir2, "file.jpg")
  712. err = os.MkdirAll(filepath.Dir(testFilePath1), os.ModePerm)
  713. assert.NoError(t, err)
  714. err = os.MkdirAll(filepath.Dir(testFilePath2), os.ModePerm)
  715. assert.NoError(t, err)
  716. err = ioutil.WriteFile(testFilePath1, []byte("file1"), os.ModePerm)
  717. assert.NoError(t, err)
  718. err = ioutil.WriteFile(testFilePath2, []byte("file2"), os.ModePerm)
  719. assert.NoError(t, err)
  720. err = ioutil.WriteFile(testFilePath3, []byte("file3"), os.ModePerm)
  721. assert.NoError(t, err)
  722. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  723. err = downloadFile(path.Join("/", subDir1, "file.zipp"), localDownloadPath, 5, client)
  724. assert.Error(t, err)
  725. err = downloadFile(path.Join("/", subDir2, "file.zipp"), localDownloadPath, 5, client)
  726. assert.Error(t, err)
  727. err = downloadFile(path.Join("/", subDir2, "file.jpg"), localDownloadPath, 5, client)
  728. assert.Error(t, err)
  729. err = downloadFile(path.Join("missing.zip"), localDownloadPath, 5, client)
  730. assert.Error(t, err)
  731. err = os.Remove(localDownloadPath)
  732. assert.NoError(t, err)
  733. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  734. assert.NoError(t, err)
  735. err = os.RemoveAll(user.GetHomeDir())
  736. assert.NoError(t, err)
  737. }
  738. func TestUploadErrors(t *testing.T) {
  739. u := getTestUser()
  740. u.QuotaSize = 65535
  741. subDir1 := "sub1"
  742. subDir2 := "sub2"
  743. // we need download permission to get size since PROPFIND will open the file
  744. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems, dataprovider.PermDownload}
  745. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  746. dataprovider.PermDelete, dataprovider.PermDownload}
  747. u.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  748. {
  749. Path: "/sub2",
  750. AllowedExtensions: []string{},
  751. DeniedExtensions: []string{".zip"},
  752. },
  753. }
  754. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  755. assert.NoError(t, err)
  756. client := getWebDavClient(user)
  757. testFilePath := filepath.Join(homeBasePath, testFileName)
  758. testFileSize := user.QuotaSize
  759. err = createTestFile(testFilePath, testFileSize)
  760. assert.NoError(t, err)
  761. err = client.Mkdir(subDir1, os.ModePerm)
  762. assert.NoError(t, err)
  763. err = client.Mkdir(subDir2, os.ModePerm)
  764. assert.NoError(t, err)
  765. err = uploadFile(testFilePath, path.Join(subDir1, testFileName), testFileSize, client)
  766. assert.Error(t, err)
  767. err = uploadFile(testFilePath, path.Join(subDir2, testFileName+".zip"), testFileSize, client)
  768. assert.Error(t, err)
  769. err = uploadFile(testFilePath, path.Join(subDir2, testFileName), testFileSize, client)
  770. assert.NoError(t, err)
  771. err = client.Rename(path.Join(subDir2, testFileName), path.Join(subDir1, testFileName), false)
  772. assert.Error(t, err)
  773. err = uploadFile(testFilePath, path.Join(subDir2, testFileName), testFileSize, client)
  774. assert.Error(t, err)
  775. err = uploadFile(testFilePath, subDir1, testFileSize, client)
  776. assert.Error(t, err)
  777. // overquota
  778. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  779. assert.Error(t, err)
  780. err = client.Remove(path.Join(subDir2, testFileName))
  781. assert.NoError(t, err)
  782. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  783. assert.NoError(t, err)
  784. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  785. assert.Error(t, err)
  786. err = os.Remove(testFilePath)
  787. assert.NoError(t, err)
  788. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  789. assert.NoError(t, err)
  790. err = os.RemoveAll(user.GetHomeDir())
  791. assert.NoError(t, err)
  792. }
  793. func TestDeniedLoginMethod(t *testing.T) {
  794. u := getTestUser()
  795. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword}
  796. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  797. assert.NoError(t, err)
  798. client := getWebDavClient(user)
  799. assert.Error(t, checkBasicFunc(client))
  800. user.Filters.DeniedLoginMethods = []string{dataprovider.SSHLoginMethodPublicKey, dataprovider.SSHLoginMethodKeyAndKeyboardInt}
  801. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  802. assert.NoError(t, err)
  803. client = getWebDavClient(user)
  804. assert.NoError(t, checkBasicFunc(client))
  805. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  806. assert.NoError(t, err)
  807. err = os.RemoveAll(user.GetHomeDir())
  808. assert.NoError(t, err)
  809. }
  810. func TestDeniedProtocols(t *testing.T) {
  811. u := getTestUser()
  812. u.Filters.DeniedProtocols = []string{common.ProtocolWebDAV}
  813. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  814. assert.NoError(t, err)
  815. client := getWebDavClient(user)
  816. assert.Error(t, checkBasicFunc(client))
  817. user.Filters.DeniedProtocols = []string{common.ProtocolSSH, common.ProtocolFTP}
  818. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  819. assert.NoError(t, err)
  820. client = getWebDavClient(user)
  821. assert.NoError(t, checkBasicFunc(client))
  822. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  823. assert.NoError(t, err)
  824. err = os.RemoveAll(user.GetHomeDir())
  825. assert.NoError(t, err)
  826. }
  827. func TestQuotaLimits(t *testing.T) {
  828. u := getTestUser()
  829. u.QuotaFiles = 1
  830. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  831. assert.NoError(t, err)
  832. u = getTestSFTPUser()
  833. u.QuotaFiles = 1
  834. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  835. assert.NoError(t, err)
  836. for _, user := range []dataprovider.User{localUser, sftpUser} {
  837. testFileSize := int64(65535)
  838. testFilePath := filepath.Join(homeBasePath, testFileName)
  839. err = createTestFile(testFilePath, testFileSize)
  840. assert.NoError(t, err)
  841. testFileSize1 := int64(131072)
  842. testFileName1 := "test_file1.dat"
  843. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  844. err = createTestFile(testFilePath1, testFileSize1)
  845. assert.NoError(t, err)
  846. testFileSize2 := int64(32768)
  847. testFileName2 := "test_file2.dat"
  848. testFilePath2 := filepath.Join(homeBasePath, testFileName2)
  849. err = createTestFile(testFilePath2, testFileSize2)
  850. assert.NoError(t, err)
  851. client := getWebDavClient(user)
  852. // test quota files
  853. err = uploadFile(testFilePath, testFileName+".quota", testFileSize, client)
  854. assert.NoError(t, err)
  855. err = uploadFile(testFilePath, testFileName+".quota1", testFileSize, client)
  856. assert.Error(t, err)
  857. err = client.Rename(testFileName+".quota", testFileName, false)
  858. assert.NoError(t, err)
  859. files, err := client.ReadDir("/")
  860. assert.NoError(t, err)
  861. assert.Len(t, files, 1)
  862. // test quota size
  863. user.QuotaSize = testFileSize - 1
  864. user.QuotaFiles = 0
  865. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  866. assert.NoError(t, err)
  867. err = uploadFile(testFilePath, testFileName+".quota", testFileSize, client)
  868. assert.Error(t, err)
  869. err = client.Rename(testFileName, testFileName+".quota", false)
  870. assert.NoError(t, err)
  871. // now test quota limits while uploading the current file, we have 1 bytes remaining
  872. user.QuotaSize = testFileSize + 1
  873. user.QuotaFiles = 0
  874. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  875. assert.NoError(t, err)
  876. err = uploadFile(testFilePath1, testFileName1, testFileSize1, client)
  877. assert.Error(t, err)
  878. _, err = client.Stat(testFileName1)
  879. assert.Error(t, err)
  880. err = client.Rename(testFileName+".quota", testFileName, false)
  881. assert.NoError(t, err)
  882. // overwriting an existing file will work if the resulting size is lesser or equal than the current one
  883. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  884. assert.NoError(t, err)
  885. err = uploadFile(testFilePath2, testFileName, testFileSize2, client)
  886. assert.NoError(t, err)
  887. err = uploadFile(testFilePath1, testFileName, testFileSize1, client)
  888. assert.Error(t, err)
  889. err = uploadFile(testFilePath2, testFileName, testFileSize2, client)
  890. assert.NoError(t, err)
  891. err = os.Remove(testFilePath)
  892. assert.NoError(t, err)
  893. err = os.Remove(testFilePath1)
  894. assert.NoError(t, err)
  895. err = os.Remove(testFilePath2)
  896. assert.NoError(t, err)
  897. if user.Username == defaultUsername {
  898. err = os.RemoveAll(user.GetHomeDir())
  899. assert.NoError(t, err)
  900. user.QuotaFiles = 0
  901. user.QuotaSize = 0
  902. _, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  903. assert.NoError(t, err)
  904. }
  905. }
  906. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  907. assert.NoError(t, err)
  908. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  909. assert.NoError(t, err)
  910. err = os.RemoveAll(localUser.GetHomeDir())
  911. assert.NoError(t, err)
  912. }
  913. func TestUploadMaxSize(t *testing.T) {
  914. testFileSize := int64(65535)
  915. u := getTestUser()
  916. u.Filters.MaxUploadFileSize = testFileSize + 1
  917. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  918. assert.NoError(t, err)
  919. u = getTestSFTPUser()
  920. u.Filters.MaxUploadFileSize = testFileSize + 1
  921. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  922. assert.NoError(t, err)
  923. for _, user := range []dataprovider.User{localUser, sftpUser} {
  924. testFilePath := filepath.Join(homeBasePath, testFileName)
  925. err = createTestFile(testFilePath, testFileSize)
  926. assert.NoError(t, err)
  927. testFileSize1 := int64(131072)
  928. testFileName1 := "test_file_dav1.dat"
  929. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  930. err = createTestFile(testFilePath1, testFileSize1)
  931. assert.NoError(t, err)
  932. client := getWebDavClient(user)
  933. err = uploadFile(testFilePath1, testFileName1, testFileSize1, client)
  934. assert.Error(t, err)
  935. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  936. assert.NoError(t, err)
  937. // now test overwrite an existing file with a size bigger than the allowed one
  938. err = createTestFile(filepath.Join(user.GetHomeDir(), testFileName1), testFileSize1)
  939. assert.NoError(t, err)
  940. err = uploadFile(testFilePath1, testFileName1, testFileSize1, client)
  941. assert.Error(t, err)
  942. err = os.Remove(testFilePath)
  943. assert.NoError(t, err)
  944. err = os.Remove(testFilePath1)
  945. assert.NoError(t, err)
  946. if user.Username == defaultUsername {
  947. err = os.RemoveAll(user.GetHomeDir())
  948. assert.NoError(t, err)
  949. user.Filters.MaxUploadFileSize = 65536000
  950. _, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  951. assert.NoError(t, err)
  952. }
  953. }
  954. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  955. assert.NoError(t, err)
  956. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  957. assert.NoError(t, err)
  958. err = os.RemoveAll(localUser.GetHomeDir())
  959. assert.NoError(t, err)
  960. }
  961. func TestClientClose(t *testing.T) {
  962. u := getTestUser()
  963. u.UploadBandwidth = 64
  964. u.DownloadBandwidth = 64
  965. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  966. assert.NoError(t, err)
  967. u = getTestSFTPUser()
  968. u.UploadBandwidth = 64
  969. u.DownloadBandwidth = 64
  970. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  971. assert.NoError(t, err)
  972. for _, user := range []dataprovider.User{localUser, sftpUser} {
  973. testFileSize := int64(1048576)
  974. testFilePath := filepath.Join(homeBasePath, testFileName)
  975. err = createTestFile(testFilePath, testFileSize)
  976. assert.NoError(t, err)
  977. client := getWebDavClient(user)
  978. assert.NoError(t, checkBasicFunc(client))
  979. var wg sync.WaitGroup
  980. wg.Add(1)
  981. go func() {
  982. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  983. assert.Error(t, err)
  984. wg.Done()
  985. }()
  986. assert.Eventually(t, func() bool {
  987. for _, stat := range common.Connections.GetStats() {
  988. if len(stat.Transfers) > 0 {
  989. return true
  990. }
  991. }
  992. return false
  993. }, 1*time.Second, 50*time.Millisecond)
  994. for _, stat := range common.Connections.GetStats() {
  995. common.Connections.Close(stat.ConnectionID)
  996. }
  997. wg.Wait()
  998. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 },
  999. 1*time.Second, 100*time.Millisecond)
  1000. err = os.Remove(testFilePath)
  1001. assert.NoError(t, err)
  1002. testFilePath = filepath.Join(user.HomeDir, testFileName)
  1003. err = createTestFile(testFilePath, testFileSize)
  1004. assert.NoError(t, err)
  1005. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1006. wg.Add(1)
  1007. go func() {
  1008. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1009. assert.Error(t, err)
  1010. wg.Done()
  1011. }()
  1012. assert.Eventually(t, func() bool {
  1013. for _, stat := range common.Connections.GetStats() {
  1014. if len(stat.Transfers) > 0 {
  1015. return true
  1016. }
  1017. }
  1018. return false
  1019. }, 1*time.Second, 50*time.Millisecond)
  1020. for _, stat := range common.Connections.GetStats() {
  1021. common.Connections.Close(stat.ConnectionID)
  1022. }
  1023. wg.Wait()
  1024. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 },
  1025. 1*time.Second, 100*time.Millisecond)
  1026. err = os.Remove(localDownloadPath)
  1027. assert.NoError(t, err)
  1028. }
  1029. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1030. assert.NoError(t, err)
  1031. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1032. assert.NoError(t, err)
  1033. err = os.RemoveAll(localUser.GetHomeDir())
  1034. assert.NoError(t, err)
  1035. }
  1036. func TestLoginWithDatabaseCredentials(t *testing.T) {
  1037. u := getTestUser()
  1038. u.FsConfig.Provider = dataprovider.GCSFilesystemProvider
  1039. u.FsConfig.GCSConfig.Bucket = "test"
  1040. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret(`{ "type": "service_account" }`)
  1041. providerConf := config.GetProviderConf()
  1042. providerConf.PreferDatabaseCredentials = true
  1043. credentialsFile := filepath.Join(providerConf.CredentialsPath, fmt.Sprintf("%v_gcs_credentials.json", u.Username))
  1044. if !filepath.IsAbs(credentialsFile) {
  1045. credentialsFile = filepath.Join(configDir, credentialsFile)
  1046. }
  1047. assert.NoError(t, dataprovider.Close())
  1048. err := dataprovider.Initialize(providerConf, configDir, true)
  1049. assert.NoError(t, err)
  1050. if _, err = os.Stat(credentialsFile); err == nil {
  1051. // remove the credentials file
  1052. assert.NoError(t, os.Remove(credentialsFile))
  1053. }
  1054. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1055. assert.NoError(t, err)
  1056. assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.GCSConfig.Credentials.GetStatus())
  1057. assert.NotEmpty(t, user.FsConfig.GCSConfig.Credentials.GetPayload())
  1058. assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetAdditionalData())
  1059. assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetKey())
  1060. assert.NoFileExists(t, credentialsFile)
  1061. client := getWebDavClient(user)
  1062. err = client.Connect()
  1063. assert.NoError(t, err)
  1064. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1065. assert.NoError(t, err)
  1066. err = os.RemoveAll(user.GetHomeDir())
  1067. assert.NoError(t, err)
  1068. assert.NoError(t, dataprovider.Close())
  1069. assert.NoError(t, config.LoadConfig(configDir, ""))
  1070. providerConf = config.GetProviderConf()
  1071. assert.NoError(t, dataprovider.Initialize(providerConf, configDir, true))
  1072. }
  1073. func TestLoginInvalidFs(t *testing.T) {
  1074. u := getTestUser()
  1075. u.FsConfig.Provider = dataprovider.GCSFilesystemProvider
  1076. u.FsConfig.GCSConfig.Bucket = "test"
  1077. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("invalid JSON for credentials")
  1078. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1079. assert.NoError(t, err)
  1080. providerConf := config.GetProviderConf()
  1081. credentialsFile := filepath.Join(providerConf.CredentialsPath, fmt.Sprintf("%v_gcs_credentials.json", u.Username))
  1082. if !filepath.IsAbs(credentialsFile) {
  1083. credentialsFile = filepath.Join(configDir, credentialsFile)
  1084. }
  1085. // now remove the credentials file so the filesystem creation will fail
  1086. err = os.Remove(credentialsFile)
  1087. assert.NoError(t, err)
  1088. client := getWebDavClient(user)
  1089. assert.Error(t, checkBasicFunc(client))
  1090. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1091. assert.NoError(t, err)
  1092. err = os.RemoveAll(user.GetHomeDir())
  1093. assert.NoError(t, err)
  1094. }
  1095. func TestBytesRangeRequests(t *testing.T) {
  1096. u := getTestUser()
  1097. u.Username = u.Username + "1"
  1098. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1099. assert.NoError(t, err)
  1100. sftpUser := getTestSFTPUser()
  1101. sftpUser.FsConfig.SFTPConfig.Username = localUser.Username
  1102. for _, u := range []dataprovider.User{getTestUser(), getTestUserWithCryptFs(), sftpUser} {
  1103. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1104. assert.NoError(t, err)
  1105. testFileName := "test_file.txt"
  1106. testFilePath := filepath.Join(homeBasePath, testFileName)
  1107. fileContent := []byte("test file contents")
  1108. err = ioutil.WriteFile(testFilePath, fileContent, os.ModePerm)
  1109. assert.NoError(t, err)
  1110. client := getWebDavClient(user)
  1111. err = uploadFile(testFilePath, testFileName, int64(len(fileContent)), client)
  1112. assert.NoError(t, err)
  1113. remotePath := fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName)
  1114. req, err := http.NewRequest(http.MethodGet, remotePath, nil)
  1115. if assert.NoError(t, err) {
  1116. httpClient := httpclient.GetHTTPClient()
  1117. req.SetBasicAuth(user.Username, defaultPassword)
  1118. req.Header.Set("Range", "bytes=5-")
  1119. resp, err := httpClient.Do(req)
  1120. if assert.NoError(t, err) {
  1121. defer resp.Body.Close()
  1122. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  1123. bodyBytes, err := ioutil.ReadAll(resp.Body)
  1124. assert.NoError(t, err)
  1125. assert.Equal(t, "file contents", string(bodyBytes))
  1126. }
  1127. req.Header.Set("Range", "bytes=5-8")
  1128. resp, err = httpClient.Do(req)
  1129. if assert.NoError(t, err) {
  1130. defer resp.Body.Close()
  1131. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  1132. bodyBytes, err := ioutil.ReadAll(resp.Body)
  1133. assert.NoError(t, err)
  1134. assert.Equal(t, "file", string(bodyBytes))
  1135. }
  1136. }
  1137. assert.NoError(t, err)
  1138. err = os.Remove(testFilePath)
  1139. assert.NoError(t, err)
  1140. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1141. assert.NoError(t, err)
  1142. err = os.RemoveAll(user.GetHomeDir())
  1143. assert.NoError(t, err)
  1144. }
  1145. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1146. assert.NoError(t, err)
  1147. err = os.RemoveAll(localUser.GetHomeDir())
  1148. assert.NoError(t, err)
  1149. }
  1150. func TestHEAD(t *testing.T) {
  1151. u := getTestUser()
  1152. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1153. assert.NoError(t, err)
  1154. rootPath := fmt.Sprintf("http://%v", webDavServerAddr)
  1155. httpClient := httpclient.GetHTTPClient()
  1156. req, err := http.NewRequest(http.MethodHead, rootPath, nil)
  1157. if assert.NoError(t, err) {
  1158. req.SetBasicAuth(u.Username, u.Password)
  1159. resp, err := httpClient.Do(req)
  1160. if assert.NoError(t, err) {
  1161. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  1162. assert.Equal(t, "text/xml; charset=utf-8", resp.Header.Get("Content-Type"))
  1163. resp.Body.Close()
  1164. }
  1165. }
  1166. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1167. assert.NoError(t, err)
  1168. err = os.RemoveAll(user.GetHomeDir())
  1169. assert.NoError(t, err)
  1170. }
  1171. func TestGETAsPROPFIND(t *testing.T) {
  1172. u := getTestUser()
  1173. subDir1 := "/sub1"
  1174. u.Permissions[subDir1] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs}
  1175. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1176. assert.NoError(t, err)
  1177. rootPath := fmt.Sprintf("http://%v/", webDavServerAddr)
  1178. httpClient := httpclient.GetHTTPClient()
  1179. req, err := http.NewRequest(http.MethodGet, rootPath, nil)
  1180. if assert.NoError(t, err) {
  1181. req.SetBasicAuth(u.Username, u.Password)
  1182. resp, err := httpClient.Do(req)
  1183. if assert.NoError(t, err) {
  1184. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  1185. resp.Body.Close()
  1186. }
  1187. }
  1188. client := getWebDavClient(user)
  1189. err = client.MkdirAll(path.Join(subDir1, "sub", "sub1"), os.ModePerm)
  1190. assert.NoError(t, err)
  1191. subPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, subDir1)
  1192. req, err = http.NewRequest(http.MethodGet, subPath, nil)
  1193. if assert.NoError(t, err) {
  1194. req.SetBasicAuth(u.Username, u.Password)
  1195. resp, err := httpClient.Do(req)
  1196. if assert.NoError(t, err) {
  1197. // before the performance patch we have a 500 here, now we have 207 but an empty list
  1198. //assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
  1199. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  1200. resp.Body.Close()
  1201. }
  1202. }
  1203. // we cannot stat the sub at all
  1204. subPath1 := fmt.Sprintf("http://%v/%v", webDavServerAddr, path.Join(subDir1, "sub"))
  1205. req, err = http.NewRequest(http.MethodGet, subPath1, nil)
  1206. if assert.NoError(t, err) {
  1207. req.SetBasicAuth(u.Username, u.Password)
  1208. resp, err := httpClient.Do(req)
  1209. if assert.NoError(t, err) {
  1210. // here the stat will fail, so the request will not be changed in propfind
  1211. assert.Equal(t, http.StatusForbidden, resp.StatusCode)
  1212. resp.Body.Close()
  1213. }
  1214. }
  1215. // we have no permission, we get an empty list
  1216. files, err := client.ReadDir(subDir1)
  1217. assert.NoError(t, err)
  1218. assert.Len(t, files, 0)
  1219. // if we grant the permissions the files are listed
  1220. user.Permissions[subDir1] = []string{dataprovider.PermDownload, dataprovider.PermListItems}
  1221. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1222. assert.NoError(t, err)
  1223. files, err = client.ReadDir(subDir1)
  1224. assert.NoError(t, err)
  1225. assert.Len(t, files, 1)
  1226. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1227. assert.NoError(t, err)
  1228. err = os.RemoveAll(user.GetHomeDir())
  1229. assert.NoError(t, err)
  1230. }
  1231. func TestStat(t *testing.T) {
  1232. u := getTestUser()
  1233. u.Permissions["/subdir"] = []string{dataprovider.PermUpload, dataprovider.PermListItems, dataprovider.PermDownload}
  1234. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1235. assert.NoError(t, err)
  1236. client := getWebDavClient(user)
  1237. subDir := "subdir"
  1238. testFilePath := filepath.Join(homeBasePath, testFileName)
  1239. testFileSize := int64(65535)
  1240. err = createTestFile(testFilePath, testFileSize)
  1241. assert.NoError(t, err)
  1242. err = client.Mkdir(subDir, os.ModePerm)
  1243. assert.NoError(t, err)
  1244. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  1245. assert.NoError(t, err)
  1246. err = uploadFile(testFilePath, path.Join("/", subDir, testFileName), testFileSize, client)
  1247. assert.NoError(t, err)
  1248. user.Permissions["/subdir"] = []string{dataprovider.PermUpload, dataprovider.PermDownload}
  1249. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1250. assert.NoError(t, err)
  1251. _, err = client.Stat(testFileName)
  1252. assert.NoError(t, err)
  1253. _, err = client.Stat(path.Join("/", subDir, testFileName))
  1254. assert.Error(t, err)
  1255. err = os.Remove(testFilePath)
  1256. assert.NoError(t, err)
  1257. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1258. assert.NoError(t, err)
  1259. err = os.RemoveAll(user.GetHomeDir())
  1260. assert.NoError(t, err)
  1261. }
  1262. func TestUploadOverwriteVfolder(t *testing.T) {
  1263. u := getTestUser()
  1264. vdir := "/vdir"
  1265. mappedPath := filepath.Join(os.TempDir(), "mappedDir")
  1266. folderName := filepath.Base(mappedPath)
  1267. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1268. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1269. Name: folderName,
  1270. MappedPath: mappedPath,
  1271. },
  1272. VirtualPath: vdir,
  1273. QuotaSize: -1,
  1274. QuotaFiles: -1,
  1275. })
  1276. err := os.MkdirAll(mappedPath, os.ModePerm)
  1277. assert.NoError(t, err)
  1278. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1279. assert.NoError(t, err)
  1280. client := getWebDavClient(user)
  1281. files, err := client.ReadDir(".")
  1282. assert.NoError(t, err)
  1283. vdirFound := false
  1284. for _, info := range files {
  1285. if info.Name() == path.Base(vdir) {
  1286. vdirFound = true
  1287. break
  1288. }
  1289. }
  1290. assert.True(t, vdirFound)
  1291. info, err := client.Stat(vdir)
  1292. if assert.NoError(t, err) {
  1293. assert.Equal(t, path.Base(vdir), info.Name())
  1294. }
  1295. testFilePath := filepath.Join(homeBasePath, testFileName)
  1296. testFileSize := int64(65535)
  1297. err = createTestFile(testFilePath, testFileSize)
  1298. assert.NoError(t, err)
  1299. err = uploadFile(testFilePath, path.Join(vdir, testFileName), testFileSize, client)
  1300. assert.NoError(t, err)
  1301. folder, _, err := httpdtest.GetFolderByName(folderName, http.StatusOK)
  1302. assert.NoError(t, err)
  1303. assert.Equal(t, testFileSize, folder.UsedQuotaSize)
  1304. assert.Equal(t, 1, folder.UsedQuotaFiles)
  1305. err = uploadFile(testFilePath, path.Join(vdir, testFileName), testFileSize, client)
  1306. assert.NoError(t, err)
  1307. folder, _, err = httpdtest.GetFolderByName(folderName, http.StatusOK)
  1308. assert.NoError(t, err)
  1309. assert.Equal(t, testFileSize, folder.UsedQuotaSize)
  1310. assert.Equal(t, 1, folder.UsedQuotaFiles)
  1311. err = os.Remove(testFilePath)
  1312. assert.NoError(t, err)
  1313. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1314. assert.NoError(t, err)
  1315. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  1316. assert.NoError(t, err)
  1317. err = os.RemoveAll(user.GetHomeDir())
  1318. assert.NoError(t, err)
  1319. err = os.RemoveAll(mappedPath)
  1320. assert.NoError(t, err)
  1321. }
  1322. func TestMiscCommands(t *testing.T) {
  1323. u := getTestUser()
  1324. u.QuotaFiles = 100
  1325. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1326. assert.NoError(t, err)
  1327. u = getTestSFTPUser()
  1328. u.QuotaFiles = 100
  1329. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1330. assert.NoError(t, err)
  1331. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1332. dir := "testDir"
  1333. client := getWebDavClient(user)
  1334. err = client.MkdirAll(path.Join(dir, "sub1", "sub2"), os.ModePerm)
  1335. assert.NoError(t, err)
  1336. testFilePath := filepath.Join(homeBasePath, testFileName)
  1337. testFileSize := int64(65535)
  1338. err = createTestFile(testFilePath, testFileSize)
  1339. assert.NoError(t, err)
  1340. err = uploadFile(testFilePath, path.Join(dir, testFileName), testFileSize, client)
  1341. assert.NoError(t, err)
  1342. err = uploadFile(testFilePath, path.Join(dir, "sub1", testFileName), testFileSize, client)
  1343. assert.NoError(t, err)
  1344. err = uploadFile(testFilePath, path.Join(dir, "sub1", "sub2", testFileName), testFileSize, client)
  1345. assert.NoError(t, err)
  1346. err = client.Copy(dir, dir+"_copy", false)
  1347. assert.NoError(t, err)
  1348. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1349. assert.NoError(t, err)
  1350. assert.Equal(t, 6, user.UsedQuotaFiles)
  1351. assert.Equal(t, 6*testFileSize, user.UsedQuotaSize)
  1352. err = client.Copy(dir, dir+"_copy1", false)
  1353. assert.NoError(t, err)
  1354. err = client.Copy(dir+"_copy", dir+"_copy1", false)
  1355. assert.Error(t, err)
  1356. err = client.Copy(dir+"_copy", dir+"_copy1", true)
  1357. assert.NoError(t, err)
  1358. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1359. assert.NoError(t, err)
  1360. assert.Equal(t, 9, user.UsedQuotaFiles)
  1361. assert.Equal(t, 9*testFileSize, user.UsedQuotaSize)
  1362. err = client.Rename(dir+"_copy1", dir+"_copy2", false)
  1363. assert.NoError(t, err)
  1364. err = client.Remove(path.Join(dir+"_copy", testFileName))
  1365. assert.NoError(t, err)
  1366. err = client.Rename(dir+"_copy2", dir+"_copy", true)
  1367. assert.NoError(t, err)
  1368. err = client.Copy(dir+"_copy", dir+"_copy1", false)
  1369. assert.NoError(t, err)
  1370. err = client.RemoveAll(dir + "_copy1")
  1371. assert.NoError(t, err)
  1372. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1373. assert.NoError(t, err)
  1374. assert.Equal(t, 6, user.UsedQuotaFiles)
  1375. assert.Equal(t, 6*testFileSize, user.UsedQuotaSize)
  1376. err = os.Remove(testFilePath)
  1377. assert.NoError(t, err)
  1378. if user.Username == defaultUsername {
  1379. err = os.RemoveAll(user.GetHomeDir())
  1380. assert.NoError(t, err)
  1381. user.QuotaFiles = 0
  1382. _, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1383. assert.NoError(t, err)
  1384. }
  1385. }
  1386. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1387. assert.NoError(t, err)
  1388. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1389. assert.NoError(t, err)
  1390. err = os.RemoveAll(localUser.GetHomeDir())
  1391. assert.NoError(t, err)
  1392. }
  1393. func checkBasicFunc(client *gowebdav.Client) error {
  1394. err := client.Connect()
  1395. if err != nil {
  1396. return err
  1397. }
  1398. _, err = client.ReadDir("/")
  1399. return err
  1400. }
  1401. func uploadFile(localSourcePath string, remoteDestPath string, expectedSize int64, client *gowebdav.Client) error {
  1402. srcFile, err := os.Open(localSourcePath)
  1403. if err != nil {
  1404. return err
  1405. }
  1406. defer srcFile.Close()
  1407. err = client.WriteStream(remoteDestPath, srcFile, os.ModePerm)
  1408. if err != nil {
  1409. return err
  1410. }
  1411. if expectedSize > 0 {
  1412. info, err := client.Stat(remoteDestPath)
  1413. if err != nil {
  1414. return err
  1415. }
  1416. if info.Size() != expectedSize {
  1417. return fmt.Errorf("uploaded file size does not match, actual: %v, expected: %v", info.Size(), expectedSize)
  1418. }
  1419. }
  1420. return nil
  1421. }
  1422. func downloadFile(remoteSourcePath string, localDestPath string, expectedSize int64, client *gowebdav.Client) error {
  1423. downloadDest, err := os.Create(localDestPath)
  1424. if err != nil {
  1425. return err
  1426. }
  1427. defer downloadDest.Close()
  1428. reader, err := client.ReadStream(remoteSourcePath)
  1429. if err != nil {
  1430. return err
  1431. }
  1432. defer reader.Close()
  1433. written, err := io.Copy(downloadDest, reader)
  1434. if err != nil {
  1435. return err
  1436. }
  1437. if written != expectedSize {
  1438. return fmt.Errorf("downloaded file size does not match, actual: %v, expected: %v", written, expectedSize)
  1439. }
  1440. return nil
  1441. }
  1442. func getWebDavClient(user dataprovider.User) *gowebdav.Client {
  1443. rootPath := fmt.Sprintf("http://%v/", webDavServerAddr)
  1444. pwd := defaultPassword
  1445. if len(user.Password) > 0 {
  1446. pwd = user.Password
  1447. }
  1448. client := gowebdav.NewClient(rootPath, user.Username, pwd)
  1449. client.SetTimeout(5 * time.Second)
  1450. return client
  1451. }
  1452. func waitTCPListening(address string) {
  1453. for {
  1454. conn, err := net.Dial("tcp", address)
  1455. if err != nil {
  1456. logger.WarnToConsole("tcp server %v not listening: %v\n", address, err)
  1457. time.Sleep(100 * time.Millisecond)
  1458. continue
  1459. }
  1460. logger.InfoToConsole("tcp server %v now listening\n", address)
  1461. conn.Close()
  1462. break
  1463. }
  1464. }
  1465. func getTestUser() dataprovider.User {
  1466. user := dataprovider.User{
  1467. Username: defaultUsername,
  1468. Password: defaultPassword,
  1469. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  1470. Status: 1,
  1471. ExpirationDate: 0,
  1472. }
  1473. user.Permissions = make(map[string][]string)
  1474. user.Permissions["/"] = allPerms
  1475. return user
  1476. }
  1477. func getTestSFTPUser() dataprovider.User {
  1478. u := getTestUser()
  1479. u.Username = u.Username + "_sftp"
  1480. u.FsConfig.Provider = dataprovider.SFTPFilesystemProvider
  1481. u.FsConfig.SFTPConfig.Endpoint = sftpServerAddr
  1482. u.FsConfig.SFTPConfig.Username = defaultUsername
  1483. u.FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword)
  1484. return u
  1485. }
  1486. func getTestUserWithCryptFs() dataprovider.User {
  1487. user := getTestUser()
  1488. user.FsConfig.Provider = dataprovider.CryptedFilesystemProvider
  1489. user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret("testPassphrase")
  1490. return user
  1491. }
  1492. func getEncryptedFileSize(size int64) (int64, error) {
  1493. encSize, err := sio.EncryptedSize(uint64(size))
  1494. return int64(encSize) + 33, err
  1495. }
  1496. func getExtAuthScriptContent(user dataprovider.User, nonJSONResponse bool, username string) []byte {
  1497. extAuthContent := []byte("#!/bin/sh\n\n")
  1498. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("if test \"$SFTPGO_AUTHD_USERNAME\" = \"%v\"; then\n", user.Username))...)
  1499. if len(username) > 0 {
  1500. user.Username = username
  1501. }
  1502. u, _ := json.Marshal(user)
  1503. if nonJSONResponse {
  1504. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  1505. } else {
  1506. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  1507. }
  1508. extAuthContent = append(extAuthContent, []byte("else\n")...)
  1509. if nonJSONResponse {
  1510. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  1511. } else {
  1512. extAuthContent = append(extAuthContent, []byte("echo '{\"username\":\"\"}'\n")...)
  1513. }
  1514. extAuthContent = append(extAuthContent, []byte("fi\n")...)
  1515. return extAuthContent
  1516. }
  1517. func getPreLoginScriptContent(user dataprovider.User, nonJSONResponse bool) []byte {
  1518. content := []byte("#!/bin/sh\n\n")
  1519. if nonJSONResponse {
  1520. content = append(content, []byte("echo 'text response'\n")...)
  1521. return content
  1522. }
  1523. if len(user.Username) > 0 {
  1524. u, _ := json.Marshal(user)
  1525. content = append(content, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  1526. }
  1527. return content
  1528. }
  1529. func getPostConnectScriptContent(exitCode int) []byte {
  1530. content := []byte("#!/bin/sh\n\n")
  1531. content = append(content, []byte(fmt.Sprintf("exit %v", exitCode))...)
  1532. return content
  1533. }
  1534. func createTestFile(path string, size int64) error {
  1535. baseDir := filepath.Dir(path)
  1536. if _, err := os.Stat(baseDir); os.IsNotExist(err) {
  1537. err = os.MkdirAll(baseDir, os.ModePerm)
  1538. if err != nil {
  1539. return err
  1540. }
  1541. }
  1542. content := make([]byte, size)
  1543. _, err := rand.Read(content)
  1544. if err != nil {
  1545. return err
  1546. }
  1547. return ioutil.WriteFile(path, content, os.ModePerm)
  1548. }