webdavd_test.go 99 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824
  1. package webdavd_test
  2. import (
  3. "bufio"
  4. "bytes"
  5. "crypto/rand"
  6. "crypto/tls"
  7. "encoding/json"
  8. "fmt"
  9. "io"
  10. "net"
  11. "net/http"
  12. "os"
  13. "os/exec"
  14. "path"
  15. "path/filepath"
  16. "regexp"
  17. "runtime"
  18. "strings"
  19. "sync"
  20. "testing"
  21. "time"
  22. "github.com/minio/sio"
  23. "github.com/rs/zerolog"
  24. "github.com/sftpgo/sdk"
  25. sdkkms "github.com/sftpgo/sdk/kms"
  26. "github.com/stretchr/testify/assert"
  27. "github.com/studio-b12/gowebdav"
  28. "github.com/drakkan/sftpgo/v2/common"
  29. "github.com/drakkan/sftpgo/v2/config"
  30. "github.com/drakkan/sftpgo/v2/dataprovider"
  31. "github.com/drakkan/sftpgo/v2/httpclient"
  32. "github.com/drakkan/sftpgo/v2/httpdtest"
  33. "github.com/drakkan/sftpgo/v2/kms"
  34. "github.com/drakkan/sftpgo/v2/logger"
  35. "github.com/drakkan/sftpgo/v2/sftpd"
  36. "github.com/drakkan/sftpgo/v2/vfs"
  37. "github.com/drakkan/sftpgo/v2/webdavd"
  38. )
  39. const (
  40. logSender = "webavdTesting"
  41. webDavServerAddr = "localhost:9090"
  42. webDavTLSServerAddr = "localhost:9443"
  43. webDavServerPort = 9090
  44. webDavTLSServerPort = 9443
  45. sftpServerAddr = "127.0.0.1:9022"
  46. defaultUsername = "test_user_dav"
  47. defaultPassword = "test_password"
  48. configDir = ".."
  49. osWindows = "windows"
  50. webDavCert = `-----BEGIN CERTIFICATE-----
  51. MIICHTCCAaKgAwIBAgIUHnqw7QnB1Bj9oUsNpdb+ZkFPOxMwCgYIKoZIzj0EAwIw
  52. RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
  53. dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDAyMDQwOTUzMDRaFw0zMDAyMDEw
  54. OTUzMDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD
  55. VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwdjAQBgcqhkjOPQIBBgUrgQQA
  56. IgNiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVqWvrJ51t5OxV0v25NsOgR82CA
  57. NXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIVCzgWkxiz7XE4lgUwX44FCXZM
  58. 3+JeUbKjUzBRMB0GA1UdDgQWBBRhLw+/o3+Z02MI/d4tmaMui9W16jAfBgNVHSME
  59. GDAWgBRhLw+/o3+Z02MI/d4tmaMui9W16jAPBgNVHRMBAf8EBTADAQH/MAoGCCqG
  60. SM49BAMCA2kAMGYCMQDqLt2lm8mE+tGgtjDmtFgdOcI72HSbRQ74D5rYTzgST1rY
  61. /8wTi5xl8TiFUyLMUsICMQC5ViVxdXbhuG7gX6yEqSkMKZICHpO8hqFwOD/uaFVI
  62. dV4vKmHUzwK/eIx+8Ay3neE=
  63. -----END CERTIFICATE-----`
  64. webDavKey = `-----BEGIN EC PARAMETERS-----
  65. BgUrgQQAIg==
  66. -----END EC PARAMETERS-----
  67. -----BEGIN EC PRIVATE KEY-----
  68. MIGkAgEBBDCfMNsN6miEE3rVyUPwElfiJSWaR5huPCzUenZOfJT04GAcQdWvEju3
  69. UM2lmBLIXpGgBwYFK4EEACKhZANiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVq
  70. WvrJ51t5OxV0v25NsOgR82CANXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIV
  71. CzgWkxiz7XE4lgUwX44FCXZM3+JeUbI=
  72. -----END EC PRIVATE KEY-----`
  73. caCRT = `-----BEGIN CERTIFICATE-----
  74. MIIE5jCCAs6gAwIBAgIBATANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDEwhDZXJ0
  75. QXV0aDAeFw0yMTAxMDIyMTIwNTVaFw0yMjA3MDIyMTMwNTJaMBMxETAPBgNVBAMT
  76. CENlcnRBdXRoMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4Tiho5xW
  77. AC15JRkMwfp3/TJwI2As7MY5dele5cmdr5bHAE+sRKqC+Ti88OJWCV5saoyax/1S
  78. CjxJlQMZMl169P1QYJskKjdG2sdv6RLWLMgwSNRRjxp/Bw9dHdiEb9MjLgu28Jro
  79. 9peQkHcRHeMf5hM9WvlIJGrdzbC4hUehmqggcqgARainBkYjf0SwuWxHeu4nMqkp
  80. Ak5tcSTLCjHfEFHZ9Te0TIPG5YkWocQKyeLgu4lvuU+DD2W2lym+YVUtRMGs1Env
  81. k7p+N0DcGU26qfzZ2sF5ZXkqm7dBsGQB9pIxwc2Q8T1dCIyP9OQCKVILdc5aVFf1
  82. cryQFHYzYNNZXFlIBims5VV5Mgfp8ESHQSue+v6n6ykecLEyKt1F1Y/MWY/nWUSI
  83. 8zdq83jdBAZVjo9MSthxVn57/06s/hQca65IpcTZV2gX0a+eRlAVqaRbAhL3LaZe
  84. bYsW3WHKoUOftwemuep3nL51TzlXZVL7Oz/ClGaEOsnGG9KFO6jh+W768qC0zLQI
  85. CdE7v2Zex98sZteHCg9fGJHIaYoF0aJG5P3WI5oZf2fy7UIYN9ADLFZiorCXAZEh
  86. CSU6mDoRViZ4RGR9GZxbDZ9KYn7O8M/KCR72bkQg73TlMsk1zSXEw0MKLUjtsw6c
  87. rZ0Jt8t3sRatHO3JrYHALMt9vZfyNCZp0IsCAwEAAaNFMEMwDgYDVR0PAQH/BAQD
  88. AgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFO1yCNAGr/zQTJIi8lw3
  89. w5OiuBvMMA0GCSqGSIb3DQEBCwUAA4ICAQA6gCNuM7r8mnx674dm31GxBjQy5ZwB
  90. 7CxDzYEvL/oiZ3Tv3HlPfN2LAAsJUfGnghh9DOytenL2CTZWjl/emP5eijzmlP+9
  91. zva5I6CIMCf/eDDVsRdO244t0o4uG7+At0IgSDM3bpVaVb4RHZNjEziYChsEYY8d
  92. HK6iwuRSvFniV6yhR/Vj1Ymi9yZ5xclqseLXiQnUB0PkfIk23+7s42cXB16653fH
  93. O/FsPyKBLiKJArizLYQc12aP3QOrYoYD9+fAzIIzew7A5C0aanZCGzkuFpO6TRlD
  94. Tb7ry9Gf0DfPpCgxraH8tOcmnqp/ka3hjqo/SRnnTk0IFrmmLdarJvjD46rKwBo4
  95. MjyAIR1mQ5j8GTlSFBmSgETOQ/EYvO3FPLmra1Fh7L+DvaVzTpqI9fG3TuyyY+Ri
  96. Fby4ycTOGSZOe5Fh8lqkX5Y47mCUJ3zHzOA1vUJy2eTlMRGpu47Eb1++Vm6EzPUP
  97. 2EF5aD+zwcssh+atZvQbwxpgVqVcyLt91RSkKkmZQslh0rnlTb68yxvUnD3zw7So
  98. o6TAf9UvwVMEvdLT9NnFd6hwi2jcNte/h538GJwXeBb8EkfpqLKpTKyicnOdkamZ
  99. 7E9zY8SHNRYMwB9coQ/W8NvufbCgkvOoLyMXk5edbXofXl3PhNGOlraWbghBnzf5
  100. r3rwjFsQOoZotA==
  101. -----END CERTIFICATE-----`
  102. caCRL = `-----BEGIN X509 CRL-----
  103. MIICpzCBkAIBATANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDEwhDZXJ0QXV0aBcN
  104. MjEwMTAyMjEzNDA1WhcNMjMwMTAyMjEzNDA1WjAkMCICEQC+l04DbHWMyC3fG09k
  105. VXf+Fw0yMTAxMDIyMTM0MDVaoCMwITAfBgNVHSMEGDAWgBTtcgjQBq/80EySIvJc
  106. N8OTorgbzDANBgkqhkiG9w0BAQsFAAOCAgEAEJ7z+uNc8sqtxlOhSdTGDzX/xput
  107. E857kFQkSlMnU2whQ8c+XpYrBLA5vIZJNSSwohTpM4+zVBX/bJpmu3wqqaArRO9/
  108. YcW5mQk9Anvb4WjQW1cHmtNapMTzoC9AiYt/OWPfy+P6JCgCr4Hy6LgQyIRL6bM9
  109. VYTalolOm1qa4Y5cIeT7iHq/91mfaqo8/6MYRjLl8DOTROpmw8OS9bCXkzGKdCat
  110. AbAzwkQUSauyoCQ10rpX+Y64w9ng3g4Dr20aCqPf5osaqplEJ2HTK8ljDTidlslv
  111. 9anQj8ax3Su89vI8+hK+YbfVQwrThabgdSjQsn+veyx8GlP8WwHLAQ379KjZjWg+
  112. OlOSwBeU1vTdP0QcB8X5C2gVujAyuQekbaV86xzIBOj7vZdfHZ6ee30TZ2FKiMyg
  113. 7/N2OqW0w77ChsjB4MSHJCfuTgIeg62GzuZXLM+Q2Z9LBdtm4Byg+sm/P52adOEg
  114. gVb2Zf4KSvsAmA0PIBlu449/QXUFcMxzLFy7mwTeZj2B4Ln0Hm0szV9f9R8MwMtB
  115. SyLYxVH+mgqaR6Jkk22Q/yYyLPaELfafX5gp/AIXG8n0zxfVaTvK3auSgb1Q6ZLS
  116. 5QH9dSIsmZHlPq7GoSXmKpMdjUL8eaky/IMteioyXgsBiATzl5L2dsw6MTX3MDF0
  117. QbDK+MzhmbKfDxs=
  118. -----END X509 CRL-----`
  119. client1Crt = `-----BEGIN CERTIFICATE-----
  120. MIIEITCCAgmgAwIBAgIRAIppZHoj1hM80D7WzTEKLuAwDQYJKoZIhvcNAQELBQAw
  121. EzERMA8GA1UEAxMIQ2VydEF1dGgwHhcNMjEwMTAyMjEyMzEwWhcNMjIwNzAyMjEz
  122. MDUxWjASMRAwDgYDVQQDEwdjbGllbnQxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
  123. MIIBCgKCAQEAoKbYY9MdF2kF/nhBESIiZTdVYtA8XL9xrIZyDj9EnCiTxHiVbJtH
  124. XVwszqSl5TRrotPmnmAQcX3r8OCk+z+RQZ0QQj257P3kG6q4rNnOcWCS5xEd20jP
  125. yhQ3m+hMGfZsotNTQze1ochuQgLUN6IPyPxZkH22ia3jX4iu1eo/QxeLYHj1UHw4
  126. 3Cii9yE+j5kPUC21xmnrGKdUrB55NYLXHx6yTIqYR5znSOVB8oJi18/hwdZmH859
  127. DHhm0Hx1HrS+jbjI3+CMorZJ3WUyNf+CkiVLD3xYutPbxzEpwiqkG/XYzLH0habT
  128. cDcILo18n+o3jvem2KWBrDhyairjIDscwQIDAQABo3EwbzAOBgNVHQ8BAf8EBAMC
  129. A7gwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBSJ5GIv
  130. zIrE4ZSQt2+CGblKTDswizAfBgNVHSMEGDAWgBTtcgjQBq/80EySIvJcN8OTorgb
  131. zDANBgkqhkiG9w0BAQsFAAOCAgEALh4f5GhvNYNou0Ab04iQBbLEdOu2RlbK1B5n
  132. K9P/umYenBHMY/z6HT3+6tpcHsDuqE8UVdq3f3Gh4S2Gu9m8PRitT+cJ3gdo9Plm
  133. 3rD4ufn/s6rGg3ppydXcedm17492tbccUDWOBZw3IO/ASVq13WPgT0/Kev7cPq0k
  134. sSdSNhVeXqx8Myc2/d+8GYyzbul2Kpfa7h9i24sK49E9ftnSmsIvngONo08eT1T0
  135. 3wAOyK2981LIsHaAWcneShKFLDB6LeXIT9oitOYhiykhFlBZ4M1GNlSNfhQ8IIQP
  136. xbqMNXCLkW4/BtLhGEEcg0QVso6Kudl9rzgTfQknrdF7pHp6rS46wYUjoSyIY6dl
  137. oLmnoAVJX36J3QPWelePI9e07X2wrTfiZWewwgw3KNRWjd6/zfPLe7GoqXnK1S2z
  138. PT8qMfCaTwKTtUkzXuTFvQ8bAo2My/mS8FOcpkt2oQWeOsADHAUX7fz5BCoa2DL3
  139. k/7Mh4gVT+JYZEoTwCFuYHgMWFWe98naqHi9lB4yR981p1QgXgxO7qBeipagKY1F
  140. LlH1iwXUqZ3MZnkNA+4e1Fglsw3sa/rC+L98HnznJ/YbTfQbCP6aQ1qcOymrjMud
  141. 7MrFwqZjtd/SK4Qx1VpK6jGEAtPgWBTUS3p9ayg6lqjMBjsmySWfvRsDQbq6P5Ct
  142. O/e3EH8=
  143. -----END CERTIFICATE-----`
  144. client1Key = `-----BEGIN RSA PRIVATE KEY-----
  145. MIIEpAIBAAKCAQEAoKbYY9MdF2kF/nhBESIiZTdVYtA8XL9xrIZyDj9EnCiTxHiV
  146. bJtHXVwszqSl5TRrotPmnmAQcX3r8OCk+z+RQZ0QQj257P3kG6q4rNnOcWCS5xEd
  147. 20jPyhQ3m+hMGfZsotNTQze1ochuQgLUN6IPyPxZkH22ia3jX4iu1eo/QxeLYHj1
  148. UHw43Cii9yE+j5kPUC21xmnrGKdUrB55NYLXHx6yTIqYR5znSOVB8oJi18/hwdZm
  149. H859DHhm0Hx1HrS+jbjI3+CMorZJ3WUyNf+CkiVLD3xYutPbxzEpwiqkG/XYzLH0
  150. habTcDcILo18n+o3jvem2KWBrDhyairjIDscwQIDAQABAoIBAEBSjVFqtbsp0byR
  151. aXvyrtLX1Ng7h++at2jca85Ihq//jyqbHTje8zPuNAKI6eNbmb0YGr5OuEa4pD9N
  152. ssDmMsKSoG/lRwwcm7h4InkSvBWpFShvMgUaohfHAHzsBYxfnh+TfULsi0y7c2n6
  153. t/2OZcOTRkkUDIITnXYiw93ibHHv2Mv2bBDu35kGrcK+c2dN5IL5ZjTjMRpbJTe2
  154. 44RBJbdTxHBVSgoGBnugF+s2aEma6Ehsj70oyfoVpM6Aed5kGge0A5zA1JO7WCn9
  155. Ay/DzlULRXHjJIoRWd2NKvx5n3FNppUc9vJh2plRHalRooZ2+MjSf8HmXlvG2Hpb
  156. ScvmWgECgYEA1G+A/2KnxWsr/7uWIJ7ClcGCiNLdk17Pv3DZ3G4qUsU2ITftfIbb
  157. tU0Q/b19na1IY8Pjy9ptP7t74/hF5kky97cf1FA8F+nMj/k4+wO8QDI8OJfzVzh9
  158. PwielA5vbE+xmvis5Hdp8/od1Yrc/rPSy2TKtPFhvsqXjqoUmOAjDP8CgYEAwZjH
  159. 9dt1sc2lx/rMxihlWEzQ3JPswKW9/LJAmbRBoSWF9FGNjbX7uhWtXRKJkzb8ZAwa
  160. 88azluNo2oftbDD/+jw8b2cDgaJHlLAkSD4O1D1RthW7/LKD15qZ/oFsRb13NV85
  161. ZNKtwslXGbfVNyGKUVFm7fVA8vBAOUey+LKDFj8CgYEAg8WWstOzVdYguMTXXuyb
  162. ruEV42FJaDyLiSirOvxq7GTAKuLSQUg1yMRBIeQEo2X1XU0JZE3dLodRVhuO4EXP
  163. g7Dn4X7Th9HSvgvNuIacowWGLWSz4Qp9RjhGhXhezUSx2nseY6le46PmFavJYYSR
  164. 4PBofMyt4PcyA6Cknh+KHmkCgYEAnTriG7ETE0a7v4DXUpB4TpCEiMCy5Xs2o8Z5
  165. ZNva+W+qLVUWq+MDAIyechqeFSvxK6gRM69LJ96lx+XhU58wJiFJzAhT9rK/g+jS
  166. bsHH9WOfu0xHkuHA5hgvvV2Le9B2wqgFyva4HJy82qxMxCu/VG/SMqyfBS9OWbb7
  167. ibQhdq0CgYAl53LUWZsFSZIth1vux2LVOsI8C3X1oiXDGpnrdlQ+K7z57hq5EsRq
  168. GC+INxwXbvKNqp5h0z2MvmKYPDlGVTgw8f8JjM7TkN17ERLcydhdRrMONUryZpo8
  169. 1xTob+8blyJgfxZUIAKbMbMbIiU0WAF0rfD/eJJwS4htOW/Hfv4TGA==
  170. -----END RSA PRIVATE KEY-----`
  171. // client 2 crt is revoked
  172. client2Crt = `-----BEGIN CERTIFICATE-----
  173. MIIEITCCAgmgAwIBAgIRAL6XTgNsdYzILd8bT2RVd/4wDQYJKoZIhvcNAQELBQAw
  174. EzERMA8GA1UEAxMIQ2VydEF1dGgwHhcNMjEwMTAyMjEyMzIwWhcNMjIwNzAyMjEz
  175. MDUxWjASMRAwDgYDVQQDEwdjbGllbnQyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
  176. MIIBCgKCAQEA6xjW5KQR3/OFQtV5M75WINqQ4AzXSu6DhSz/yumaaQZP/UxY+6hi
  177. jcrFzGo9MMie/Sza8DhkXOFAl2BelUubrOeB2cl+/Gr8OCyRi2Gv6j3zCsuN/4jQ
  178. tNaoez/IbkDvI3l/ZpzBtnuNY2RiemGgHuORXHRVf3qVlsw+npBIRW5rM2HkO/xG
  179. oZjeBErWVu390Lyn+Gvk2TqQDnkutWnxUC60/zPlHhXZ4BwaFAekbSnjsSDB1YFM
  180. s8HwW4oBryoxdj3/+/qLrBHt75IdLw3T7/V1UDJQM3EvSQOr12w4egpldhtsC871
  181. nnBQZeY6qA5feffIwwg/6lJm70o6S6OX6wIDAQABo3EwbzAOBgNVHQ8BAf8EBAMC
  182. A7gwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBTB84v5
  183. t9HqhLhMODbn6oYkEQt3KzAfBgNVHSMEGDAWgBTtcgjQBq/80EySIvJcN8OTorgb
  184. zDANBgkqhkiG9w0BAQsFAAOCAgEALGtBCve5k8tToL3oLuXp/oSik6ovIB/zq4I/
  185. 4zNMYPU31+ZWz6aahysgx1JL1yqTa3Qm8o2tu52MbnV10dM7CIw7c/cYa+c+OPcG
  186. 5LF97kp13X+r2axy+CmwM86b4ILaDGs2Qyai6VB6k7oFUve+av5o7aUrNFpqGCJz
  187. HWdtHZSVA3JMATzy0TfWanwkzreqfdw7qH0yZ9bDURlBKAVWrqnCstva9jRuv+AI
  188. eqxr/4Ro986TFjJdoAP3Vr16CPg7/B6GA/KmsBWJrpeJdPWq4i2gpLKvYZoy89qD
  189. mUZf34RbzcCtV4NvV1DadGnt4us0nvLrvS5rL2+2uWD09kZYq9RbLkvgzF/cY0fz
  190. i7I1bi5XQ+alWe0uAk5ZZL/D+GTRYUX1AWwCqwJxmHrMxcskMyO9pXvLyuSWRDLo
  191. YNBrbX9nLcfJzVCp+X+9sntTHjs4l6Cw+fLepJIgtgqdCHtbhTiv68vSM6cgb4br
  192. 6n2xrXRKuioiWFOrTSRr+oalZh8dGJ/xvwY8IbWknZAvml9mf1VvfE7Ma5P777QM
  193. fsbYVTq0Y3R/5hIWsC3HA5z6MIM8L1oRe/YyhP3CTmrCHkVKyDOosGXpGz+JVcyo
  194. cfYkY5A3yFKB2HaCwZSfwFmRhxkrYWGEbHv3Cd9YkZs1J3hNhGFZyVMC9Uh0S85a
  195. 6zdDidU=
  196. -----END CERTIFICATE-----`
  197. client2Key = `-----BEGIN RSA PRIVATE KEY-----
  198. MIIEpAIBAAKCAQEA6xjW5KQR3/OFQtV5M75WINqQ4AzXSu6DhSz/yumaaQZP/UxY
  199. +6hijcrFzGo9MMie/Sza8DhkXOFAl2BelUubrOeB2cl+/Gr8OCyRi2Gv6j3zCsuN
  200. /4jQtNaoez/IbkDvI3l/ZpzBtnuNY2RiemGgHuORXHRVf3qVlsw+npBIRW5rM2Hk
  201. O/xGoZjeBErWVu390Lyn+Gvk2TqQDnkutWnxUC60/zPlHhXZ4BwaFAekbSnjsSDB
  202. 1YFMs8HwW4oBryoxdj3/+/qLrBHt75IdLw3T7/V1UDJQM3EvSQOr12w4egpldhts
  203. C871nnBQZeY6qA5feffIwwg/6lJm70o6S6OX6wIDAQABAoIBAFatstVb1KdQXsq0
  204. cFpui8zTKOUiduJOrDkWzTygAmlEhYtrccdfXu7OWz0x0lvBLDVGK3a0I/TGrAzj
  205. 4BuFY+FM/egxTVt9in6fmA3et4BS1OAfCryzUdfK6RV//8L+t+zJZ/qKQzWnugpy
  206. QYjDo8ifuMFwtvEoXizaIyBNLAhEp9hnrv+Tyi2O2gahPvCHsD48zkyZRCHYRstD
  207. NH5cIrwz9/RJgPO1KI+QsJE7Nh7stR0sbr+5TPU4fnsL2mNhMUF2TJrwIPrc1yp+
  208. YIUjdnh3SO88j4TQT3CIrWi8i4pOy6N0dcVn3gpCRGaqAKyS2ZYUj+yVtLO4KwxZ
  209. SZ1lNvECgYEA78BrF7f4ETfWSLcBQ3qxfLs7ibB6IYo2x25685FhZjD+zLXM1AKb
  210. FJHEXUm3mUYrFJK6AFEyOQnyGKBOLs3S6oTAswMPbTkkZeD1Y9O6uv0AHASLZnK6
  211. pC6ub0eSRF5LUyTQ55Jj8D7QsjXJueO8v+G5ihWhNSN9tB2UA+8NBmkCgYEA+weq
  212. cvoeMIEMBQHnNNLy35bwfqrceGyPIRBcUIvzQfY1vk7KW6DYOUzC7u+WUzy/hA52
  213. DjXVVhua2eMQ9qqtOav7djcMc2W9RbLowxvno7K5qiCss013MeWk64TCWy+WMp5A
  214. AVAtOliC3hMkIKqvR2poqn+IBTh1449agUJQqTMCgYEAu06IHGq1GraV6g9XpGF5
  215. wqoAlMzUTdnOfDabRilBf/YtSr+J++ThRcuwLvXFw7CnPZZ4TIEjDJ7xjj3HdxeE
  216. fYYjineMmNd40UNUU556F1ZLvJfsVKizmkuCKhwvcMx+asGrmA+tlmds4p3VMS50
  217. KzDtpKzLWlmU/p/RINWlRmkCgYBy0pHTn7aZZx2xWKqCDg+L2EXPGqZX6wgZDpu7
  218. OBifzlfM4ctL2CmvI/5yPmLbVgkgBWFYpKUdiujsyyEiQvWTUKhn7UwjqKDHtcsk
  219. G6p7xS+JswJrzX4885bZJ9Oi1AR2yM3sC9l0O7I4lDbNPmWIXBLeEhGMmcPKv/Kc
  220. 91Ff4wKBgQCF3ur+Vt0PSU0ucrPVHjCe7tqazm0LJaWbPXL1Aw0pzdM2EcNcW/MA
  221. w0kqpr7MgJ94qhXCBcVcfPuFN9fBOadM3UBj1B45Cz3pptoK+ScI8XKno6jvVK/p
  222. xr5cb9VBRBtB9aOKVfuRhpatAfS2Pzm2Htae9lFn7slGPUmu2hkjDw==
  223. -----END RSA PRIVATE KEY-----`
  224. testFileName = "test_file_dav.dat"
  225. testDLFileName = "test_download_dav.dat"
  226. tlsClient1Username = "client1"
  227. tlsClient2Username = "client2"
  228. )
  229. var (
  230. allPerms = []string{dataprovider.PermAny}
  231. homeBasePath string
  232. hookCmdPath string
  233. extAuthPath string
  234. preLoginPath string
  235. postConnectPath string
  236. preDownloadPath string
  237. preUploadPath string
  238. logFilePath string
  239. certPath string
  240. keyPath string
  241. caCrtPath string
  242. caCRLPath string
  243. )
  244. func TestMain(m *testing.M) {
  245. logFilePath = filepath.Join(configDir, "sftpgo_webdavd_test.log")
  246. logger.InitLogger(logFilePath, 5, 1, 28, false, false, zerolog.DebugLevel)
  247. os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1")
  248. os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin")
  249. os.Setenv("SFTPGO_DEFAULT_ADMIN_PASSWORD", "password")
  250. err := config.LoadConfig(configDir, "")
  251. if err != nil {
  252. logger.ErrorToConsole("error loading configuration: %v", err)
  253. os.Exit(1)
  254. }
  255. providerConf := config.GetProviderConf()
  256. logger.InfoToConsole("Starting WebDAVD tests, provider: %v", providerConf.Driver)
  257. commonConf := config.GetCommonConfig()
  258. commonConf.UploadMode = 2
  259. homeBasePath = os.TempDir()
  260. if runtime.GOOS != osWindows {
  261. commonConf.Actions.ExecuteOn = []string{"download", "upload", "rename", "delete"}
  262. commonConf.Actions.Hook = hookCmdPath
  263. hookCmdPath, err = exec.LookPath("true")
  264. if err != nil {
  265. logger.Warn(logSender, "", "unable to get hook command: %v", err)
  266. logger.WarnToConsole("unable to get hook command: %v", err)
  267. }
  268. }
  269. certPath = filepath.Join(os.TempDir(), "test_dav.crt")
  270. keyPath = filepath.Join(os.TempDir(), "test_dav.key")
  271. caCrtPath = filepath.Join(os.TempDir(), "test_dav_ca.crt")
  272. caCRLPath = filepath.Join(os.TempDir(), "test_dav_crl.crt")
  273. err = os.WriteFile(certPath, []byte(webDavCert), os.ModePerm)
  274. if err != nil {
  275. logger.ErrorToConsole("error writing WebDAV certificate: %v", err)
  276. os.Exit(1)
  277. }
  278. err = os.WriteFile(keyPath, []byte(webDavKey), os.ModePerm)
  279. if err != nil {
  280. logger.ErrorToConsole("error writing WebDAV private key: %v", err)
  281. os.Exit(1)
  282. }
  283. err = os.WriteFile(caCrtPath, []byte(caCRT), os.ModePerm)
  284. if err != nil {
  285. logger.ErrorToConsole("error writing WebDAV CA crt: %v", err)
  286. os.Exit(1)
  287. }
  288. err = os.WriteFile(caCRLPath, []byte(caCRL), os.ModePerm)
  289. if err != nil {
  290. logger.ErrorToConsole("error writing WebDAV CRL: %v", err)
  291. os.Exit(1)
  292. }
  293. err = common.Initialize(commonConf)
  294. if err != nil {
  295. logger.WarnToConsole("error initializing common: %v", err)
  296. os.Exit(1)
  297. }
  298. err = dataprovider.Initialize(providerConf, configDir, true)
  299. if err != nil {
  300. logger.ErrorToConsole("error initializing data provider: %v", err)
  301. os.Exit(1)
  302. }
  303. httpConfig := config.GetHTTPConfig()
  304. httpConfig.Initialize(configDir) //nolint:errcheck
  305. kmsConfig := config.GetKMSConfig()
  306. err = kmsConfig.Initialize()
  307. if err != nil {
  308. logger.ErrorToConsole("error initializing kms: %v", err)
  309. os.Exit(1)
  310. }
  311. httpdConf := config.GetHTTPDConfig()
  312. httpdConf.Bindings[0].Port = 8078
  313. httpdtest.SetBaseURL("http://127.0.0.1:8078")
  314. // required to test sftpfs
  315. sftpdConf := config.GetSFTPDConfig()
  316. sftpdConf.Bindings = []sftpd.Binding{
  317. {
  318. Port: 9022,
  319. },
  320. }
  321. hostKeyPath := filepath.Join(os.TempDir(), "id_ecdsa")
  322. sftpdConf.HostKeys = []string{hostKeyPath}
  323. webDavConf := config.GetWebDAVDConfig()
  324. webDavConf.CertificateFile = certPath
  325. webDavConf.CertificateKeyFile = keyPath
  326. webDavConf.CACertificates = []string{caCrtPath}
  327. webDavConf.CARevocationLists = []string{caCRLPath}
  328. webDavConf.Bindings = []webdavd.Binding{
  329. {
  330. Port: webDavServerPort,
  331. },
  332. {
  333. Port: webDavTLSServerPort,
  334. EnableHTTPS: true,
  335. ClientAuthType: 2,
  336. },
  337. }
  338. webDavConf.Cors = webdavd.CorsConfig{
  339. Enabled: true,
  340. AllowedOrigins: []string{"*"},
  341. AllowedMethods: []string{
  342. http.MethodHead,
  343. http.MethodGet,
  344. http.MethodPost,
  345. http.MethodPut,
  346. http.MethodPatch,
  347. http.MethodDelete,
  348. },
  349. AllowedHeaders: []string{"*"},
  350. AllowCredentials: true,
  351. }
  352. status := webdavd.GetStatus()
  353. if status.IsActive {
  354. logger.ErrorToConsole("webdav server is already active")
  355. os.Exit(1)
  356. }
  357. extAuthPath = filepath.Join(homeBasePath, "extauth.sh")
  358. preLoginPath = filepath.Join(homeBasePath, "prelogin.sh")
  359. postConnectPath = filepath.Join(homeBasePath, "postconnect.sh")
  360. preDownloadPath = filepath.Join(homeBasePath, "predownload.sh")
  361. preUploadPath = filepath.Join(homeBasePath, "preupload.sh")
  362. go func() {
  363. logger.Debug(logSender, "", "initializing WebDAV server with config %+v", webDavConf)
  364. if err := webDavConf.Initialize(configDir); err != nil {
  365. logger.ErrorToConsole("could not start WebDAV server: %v", err)
  366. os.Exit(1)
  367. }
  368. }()
  369. go func() {
  370. if err := httpdConf.Initialize(configDir); err != nil {
  371. logger.ErrorToConsole("could not start HTTP server: %v", err)
  372. os.Exit(1)
  373. }
  374. }()
  375. go func() {
  376. logger.Debug(logSender, "", "initializing SFTP server with config %+v", sftpdConf)
  377. if err := sftpdConf.Initialize(configDir); err != nil {
  378. logger.ErrorToConsole("could not start SFTP server: %v", err)
  379. os.Exit(1)
  380. }
  381. }()
  382. waitTCPListening(webDavConf.Bindings[0].GetAddress())
  383. waitTCPListening(webDavConf.Bindings[1].GetAddress())
  384. waitTCPListening(httpdConf.Bindings[0].GetAddress())
  385. waitTCPListening(sftpdConf.Bindings[0].GetAddress())
  386. webdavd.ReloadCertificateMgr() //nolint:errcheck
  387. exitCode := m.Run()
  388. os.Remove(logFilePath)
  389. os.Remove(extAuthPath)
  390. os.Remove(preLoginPath)
  391. os.Remove(postConnectPath)
  392. os.Remove(preDownloadPath)
  393. os.Remove(preUploadPath)
  394. os.Remove(certPath)
  395. os.Remove(keyPath)
  396. os.Remove(caCrtPath)
  397. os.Remove(caCRLPath)
  398. os.Remove(hostKeyPath)
  399. os.Remove(hostKeyPath + ".pub")
  400. os.Exit(exitCode)
  401. }
  402. func TestInitialization(t *testing.T) {
  403. cfg := webdavd.Configuration{
  404. Bindings: []webdavd.Binding{
  405. {
  406. Port: 1234,
  407. EnableHTTPS: true,
  408. },
  409. {
  410. Port: 0,
  411. },
  412. },
  413. CertificateFile: "missing path",
  414. CertificateKeyFile: "bad path",
  415. }
  416. err := cfg.Initialize(configDir)
  417. assert.Error(t, err)
  418. cfg.Cache = config.GetWebDAVDConfig().Cache
  419. cfg.Bindings[0].Port = webDavServerPort
  420. cfg.CertificateFile = certPath
  421. cfg.CertificateKeyFile = keyPath
  422. err = cfg.Initialize(configDir)
  423. assert.Error(t, err)
  424. err = webdavd.ReloadCertificateMgr()
  425. assert.NoError(t, err)
  426. cfg.Bindings = []webdavd.Binding{
  427. {
  428. Port: 0,
  429. },
  430. }
  431. err = cfg.Initialize(configDir)
  432. assert.EqualError(t, err, common.ErrNoBinding.Error())
  433. cfg.CertificateFile = certPath
  434. cfg.CertificateKeyFile = keyPath
  435. cfg.CACertificates = []string{""}
  436. cfg.Bindings = []webdavd.Binding{
  437. {
  438. Port: 9022,
  439. ClientAuthType: 1,
  440. EnableHTTPS: true,
  441. },
  442. }
  443. err = cfg.Initialize(configDir)
  444. assert.Error(t, err)
  445. cfg.CACertificates = nil
  446. cfg.CARevocationLists = []string{""}
  447. err = cfg.Initialize(configDir)
  448. assert.Error(t, err)
  449. cfg.CARevocationLists = nil
  450. err = cfg.Initialize(configDir)
  451. assert.Error(t, err)
  452. cfg.CertificateFile = certPath
  453. cfg.CertificateKeyFile = keyPath
  454. cfg.CACertificates = []string{caCrtPath}
  455. cfg.CARevocationLists = []string{caCRLPath}
  456. cfg.Bindings[0].ProxyAllowed = []string{"not valid"}
  457. err = cfg.Initialize(configDir)
  458. if assert.Error(t, err) {
  459. assert.Contains(t, err.Error(), "is not a valid IP address")
  460. }
  461. cfg.Bindings[0].ProxyAllowed = nil
  462. err = cfg.Initialize(configDir)
  463. assert.Error(t, err)
  464. }
  465. func TestBasicHandling(t *testing.T) {
  466. u := getTestUser()
  467. u.QuotaSize = 6553600
  468. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  469. assert.NoError(t, err)
  470. u = getTestSFTPUser()
  471. u.QuotaSize = 6553600
  472. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  473. assert.NoError(t, err)
  474. for _, user := range []dataprovider.User{localUser, sftpUser} {
  475. client := getWebDavClient(user, true, nil)
  476. assert.NoError(t, checkBasicFunc(client))
  477. testFilePath := filepath.Join(homeBasePath, testFileName)
  478. testFileSize := int64(65535)
  479. expectedQuotaSize := testFileSize
  480. expectedQuotaFiles := 1
  481. err = createTestFile(testFilePath, testFileSize)
  482. assert.NoError(t, err)
  483. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  484. assert.NoError(t, err)
  485. // overwrite an existing file
  486. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  487. assert.NoError(t, err)
  488. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  489. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  490. assert.NoError(t, err)
  491. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  492. assert.NoError(t, err)
  493. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  494. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  495. err = client.Rename(testFileName, testFileName+"1", false)
  496. assert.NoError(t, err)
  497. _, err = client.Stat(testFileName)
  498. assert.Error(t, err)
  499. // the webdav client hide the error we check the quota
  500. err = client.Remove(testFileName)
  501. assert.NoError(t, err)
  502. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  503. assert.NoError(t, err)
  504. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  505. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  506. err = client.Remove(testFileName + "1")
  507. assert.NoError(t, err)
  508. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  509. assert.NoError(t, err)
  510. assert.Equal(t, expectedQuotaFiles-1, user.UsedQuotaFiles)
  511. assert.Equal(t, expectedQuotaSize-testFileSize, user.UsedQuotaSize)
  512. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  513. assert.Error(t, err)
  514. testDir := "testdir"
  515. err = client.Mkdir(testDir, os.ModePerm)
  516. assert.NoError(t, err)
  517. err = client.MkdirAll(path.Join(testDir, "sub", "sub"), os.ModePerm)
  518. assert.NoError(t, err)
  519. err = client.MkdirAll(path.Join(testDir, "sub1", "sub1"), os.ModePerm)
  520. assert.NoError(t, err)
  521. err = client.MkdirAll(path.Join(testDir, "sub2", "sub2"), os.ModePerm)
  522. assert.NoError(t, err)
  523. err = uploadFile(testFilePath, path.Join(testDir, testFileName+".txt"), testFileSize, client)
  524. assert.NoError(t, err)
  525. err = uploadFile(testFilePath, path.Join(testDir, testFileName), testFileSize, client)
  526. assert.NoError(t, err)
  527. files, err := client.ReadDir(testDir)
  528. assert.NoError(t, err)
  529. assert.Len(t, files, 5)
  530. err = client.Copy(testDir, testDir+"_copy", false)
  531. assert.NoError(t, err)
  532. err = client.RemoveAll(testDir)
  533. assert.NoError(t, err)
  534. err = os.Remove(testFilePath)
  535. assert.NoError(t, err)
  536. err = os.Remove(localDownloadPath)
  537. assert.NoError(t, err)
  538. if user.Username == defaultUsername {
  539. err = os.RemoveAll(user.GetHomeDir())
  540. assert.NoError(t, err)
  541. }
  542. }
  543. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  544. assert.NoError(t, err)
  545. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  546. assert.NoError(t, err)
  547. err = os.RemoveAll(localUser.GetHomeDir())
  548. assert.NoError(t, err)
  549. assert.Len(t, common.Connections.GetStats(), 0)
  550. status := webdavd.GetStatus()
  551. assert.True(t, status.IsActive)
  552. }
  553. func TestBasicHandlingCryptFs(t *testing.T) {
  554. u := getTestUserWithCryptFs()
  555. u.QuotaSize = 6553600
  556. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  557. assert.NoError(t, err)
  558. client := getWebDavClient(user, false, nil)
  559. assert.NoError(t, checkBasicFunc(client))
  560. testFilePath := filepath.Join(homeBasePath, testFileName)
  561. testFileSize := int64(65535)
  562. encryptedFileSize, err := getEncryptedFileSize(testFileSize)
  563. assert.NoError(t, err)
  564. expectedQuotaSize := user.UsedQuotaSize + encryptedFileSize
  565. expectedQuotaFiles := user.UsedQuotaFiles + 1
  566. err = createTestFile(testFilePath, testFileSize)
  567. assert.NoError(t, err)
  568. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  569. assert.NoError(t, err)
  570. // overwrite an existing file
  571. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  572. assert.NoError(t, err)
  573. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  574. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  575. assert.NoError(t, err)
  576. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  577. assert.NoError(t, err)
  578. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  579. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  580. files, err := client.ReadDir("/")
  581. assert.NoError(t, err)
  582. if assert.Len(t, files, 1) {
  583. assert.Equal(t, testFileSize, files[0].Size())
  584. }
  585. err = client.Remove(testFileName)
  586. assert.NoError(t, err)
  587. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  588. assert.NoError(t, err)
  589. assert.Equal(t, expectedQuotaFiles-1, user.UsedQuotaFiles)
  590. assert.Equal(t, expectedQuotaSize-encryptedFileSize, user.UsedQuotaSize)
  591. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  592. assert.Error(t, err)
  593. testDir := "testdir"
  594. err = client.Mkdir(testDir, os.ModePerm)
  595. assert.NoError(t, err)
  596. err = client.MkdirAll(path.Join(testDir, "sub", "sub"), os.ModePerm)
  597. assert.NoError(t, err)
  598. err = client.MkdirAll(path.Join(testDir, "sub1", "sub1"), os.ModePerm)
  599. assert.NoError(t, err)
  600. err = client.MkdirAll(path.Join(testDir, "sub2", "sub2"), os.ModePerm)
  601. assert.NoError(t, err)
  602. err = uploadFile(testFilePath, path.Join(testDir, testFileName+".txt"), testFileSize, client)
  603. assert.NoError(t, err)
  604. err = uploadFile(testFilePath, path.Join(testDir, testFileName), testFileSize, client)
  605. assert.NoError(t, err)
  606. files, err = client.ReadDir(testDir)
  607. assert.NoError(t, err)
  608. assert.Len(t, files, 5)
  609. for _, f := range files {
  610. if strings.HasPrefix(f.Name(), testFileName) {
  611. assert.Equal(t, testFileSize, f.Size())
  612. } else {
  613. assert.True(t, f.IsDir())
  614. }
  615. }
  616. err = os.Remove(testFilePath)
  617. assert.NoError(t, err)
  618. err = os.Remove(localDownloadPath)
  619. assert.NoError(t, err)
  620. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  621. assert.NoError(t, err)
  622. err = os.RemoveAll(user.GetHomeDir())
  623. assert.NoError(t, err)
  624. assert.Len(t, common.Connections.GetStats(), 0)
  625. }
  626. func TestLockAfterDelete(t *testing.T) {
  627. u := getTestUser()
  628. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  629. assert.NoError(t, err)
  630. client := getWebDavClient(user, false, nil)
  631. assert.NoError(t, checkBasicFunc(client))
  632. testFilePath := filepath.Join(homeBasePath, testFileName)
  633. testFileSize := int64(65535)
  634. err = createTestFile(testFilePath, testFileSize)
  635. assert.NoError(t, err)
  636. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  637. assert.NoError(t, err)
  638. lockBody := `<?xml version="1.0" encoding="utf-8" ?><d:lockinfo xmlns:d="DAV:"><d:lockscope><d:exclusive/></d:lockscope><d:locktype><d:write/></d:locktype></d:lockinfo>`
  639. req, err := http.NewRequest("LOCK", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(lockBody)))
  640. assert.NoError(t, err)
  641. req.SetBasicAuth(u.Username, u.Password)
  642. req.Header.Set("Timeout", "Second-3600")
  643. httpClient := httpclient.GetHTTPClient()
  644. resp, err := httpClient.Do(req)
  645. assert.NoError(t, err)
  646. assert.Equal(t, http.StatusOK, resp.StatusCode)
  647. response, err := io.ReadAll(resp.Body)
  648. assert.NoError(t, err)
  649. re := regexp.MustCompile(`\<D:locktoken><D:href>.*</D:href>`)
  650. lockToken := string(re.Find(response))
  651. lockToken = strings.Replace(lockToken, "<D:locktoken><D:href>", "", 1)
  652. lockToken = strings.Replace(lockToken, "</D:href>", "", 1)
  653. err = resp.Body.Close()
  654. assert.NoError(t, err)
  655. req, err = http.NewRequest(http.MethodDelete, fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), nil)
  656. assert.NoError(t, err)
  657. req.Header.Set("If", fmt.Sprintf("(%v)", lockToken))
  658. req.SetBasicAuth(u.Username, u.Password)
  659. resp, err = httpClient.Do(req)
  660. assert.NoError(t, err)
  661. assert.Equal(t, http.StatusNoContent, resp.StatusCode)
  662. err = resp.Body.Close()
  663. assert.NoError(t, err)
  664. // if we try to lock again it must succeed, the lock must be deleted with the object
  665. req, err = http.NewRequest("LOCK", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(lockBody)))
  666. assert.NoError(t, err)
  667. req.SetBasicAuth(u.Username, u.Password)
  668. resp, err = httpClient.Do(req)
  669. assert.NoError(t, err)
  670. assert.Equal(t, http.StatusCreated, resp.StatusCode)
  671. err = resp.Body.Close()
  672. assert.NoError(t, err)
  673. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  674. assert.NoError(t, err)
  675. err = os.RemoveAll(user.GetHomeDir())
  676. assert.NoError(t, err)
  677. }
  678. func TestRenameWithLock(t *testing.T) {
  679. u := getTestUser()
  680. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  681. assert.NoError(t, err)
  682. client := getWebDavClient(user, false, nil)
  683. assert.NoError(t, checkBasicFunc(client))
  684. testFilePath := filepath.Join(homeBasePath, testFileName)
  685. testFileSize := int64(65535)
  686. err = createTestFile(testFilePath, testFileSize)
  687. assert.NoError(t, err)
  688. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  689. assert.NoError(t, err)
  690. lockBody := `<?xml version="1.0" encoding="utf-8" ?><d:lockinfo xmlns:d="DAV:"><d:lockscope><d:exclusive/></d:lockscope><d:locktype><d:write/></d:locktype></d:lockinfo>`
  691. req, err := http.NewRequest("LOCK", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(lockBody)))
  692. assert.NoError(t, err)
  693. req.SetBasicAuth(u.Username, u.Password)
  694. httpClient := httpclient.GetHTTPClient()
  695. resp, err := httpClient.Do(req)
  696. assert.NoError(t, err)
  697. assert.Equal(t, http.StatusOK, resp.StatusCode)
  698. response, err := io.ReadAll(resp.Body)
  699. assert.NoError(t, err)
  700. re := regexp.MustCompile(`\<D:locktoken><D:href>.*</D:href>`)
  701. lockToken := string(re.Find(response))
  702. lockToken = strings.Replace(lockToken, "<D:locktoken><D:href>", "", 1)
  703. lockToken = strings.Replace(lockToken, "</D:href>", "", 1)
  704. err = resp.Body.Close()
  705. assert.NoError(t, err)
  706. // MOVE with a lock should succeeded
  707. req, err = http.NewRequest("MOVE", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), nil)
  708. assert.NoError(t, err)
  709. req.Header.Set("If", fmt.Sprintf("(%v)", lockToken))
  710. req.Header.Set("Overwrite", "T")
  711. req.Header.Set("Destination", path.Join("/", testFileName+"1"))
  712. req.SetBasicAuth(u.Username, u.Password)
  713. resp, err = httpClient.Do(req)
  714. assert.NoError(t, err)
  715. assert.Equal(t, http.StatusCreated, resp.StatusCode)
  716. err = resp.Body.Close()
  717. assert.NoError(t, err)
  718. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  719. assert.NoError(t, err)
  720. err = os.RemoveAll(user.GetHomeDir())
  721. assert.NoError(t, err)
  722. }
  723. func TestPropPatch(t *testing.T) {
  724. u := getTestUser()
  725. u.Username = u.Username + "1"
  726. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  727. assert.NoError(t, err)
  728. sftpUser := getTestSFTPUser()
  729. sftpUser.FsConfig.SFTPConfig.Username = localUser.Username
  730. for _, u := range []dataprovider.User{getTestUser(), getTestUserWithCryptFs(), sftpUser} {
  731. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  732. assert.NoError(t, err)
  733. client := getWebDavClient(user, true, nil)
  734. assert.NoError(t, checkBasicFunc(client), sftpUser.Username)
  735. testFilePath := filepath.Join(homeBasePath, testFileName)
  736. testFileSize := int64(65535)
  737. err = createTestFile(testFilePath, testFileSize)
  738. assert.NoError(t, err)
  739. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  740. assert.NoError(t, err)
  741. httpClient := httpclient.GetHTTPClient()
  742. 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>`
  743. req, err := http.NewRequest("PROPPATCH", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(propatchBody)))
  744. assert.NoError(t, err)
  745. req.SetBasicAuth(u.Username, u.Password)
  746. resp, err := httpClient.Do(req)
  747. assert.NoError(t, err)
  748. assert.Equal(t, 207, resp.StatusCode)
  749. err = resp.Body.Close()
  750. assert.NoError(t, err)
  751. info, err := client.Stat(testFileName)
  752. if assert.NoError(t, err) {
  753. assert.Equal(t, testFileSize, info.Size())
  754. }
  755. err = os.Remove(testFilePath)
  756. assert.NoError(t, err)
  757. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  758. assert.NoError(t, err)
  759. err = os.RemoveAll(user.GetHomeDir())
  760. assert.NoError(t, err)
  761. assert.Len(t, common.Connections.GetStats(), 0)
  762. }
  763. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  764. assert.NoError(t, err)
  765. err = os.RemoveAll(localUser.GetHomeDir())
  766. assert.NoError(t, err)
  767. }
  768. func TestLoginInvalidPwd(t *testing.T) {
  769. u := getTestUser()
  770. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  771. assert.NoError(t, err)
  772. client := getWebDavClient(user, false, nil)
  773. assert.NoError(t, checkBasicFunc(client))
  774. user.Password = "wrong"
  775. client = getWebDavClient(user, false, nil)
  776. assert.Error(t, checkBasicFunc(client))
  777. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  778. assert.NoError(t, err)
  779. }
  780. func TestLoginNonExistentUser(t *testing.T) {
  781. user := getTestUser()
  782. client := getWebDavClient(user, true, nil)
  783. assert.Error(t, checkBasicFunc(client))
  784. }
  785. func TestRateLimiter(t *testing.T) {
  786. oldConfig := config.GetCommonConfig()
  787. cfg := config.GetCommonConfig()
  788. cfg.RateLimitersConfig = []common.RateLimiterConfig{
  789. {
  790. Average: 1,
  791. Period: 1000,
  792. Burst: 3,
  793. Type: 1,
  794. Protocols: []string{common.ProtocolWebDAV},
  795. },
  796. }
  797. err := common.Initialize(cfg)
  798. assert.NoError(t, err)
  799. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  800. assert.NoError(t, err)
  801. client := getWebDavClient(user, false, nil)
  802. assert.NoError(t, checkBasicFunc(client))
  803. _, err = client.ReadDir(".")
  804. if assert.Error(t, err) {
  805. assert.Contains(t, err.Error(), "429")
  806. }
  807. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  808. assert.NoError(t, err)
  809. err = os.RemoveAll(user.GetHomeDir())
  810. assert.NoError(t, err)
  811. err = common.Initialize(oldConfig)
  812. assert.NoError(t, err)
  813. }
  814. func TestDefender(t *testing.T) {
  815. oldConfig := config.GetCommonConfig()
  816. cfg := config.GetCommonConfig()
  817. cfg.DefenderConfig.Enabled = true
  818. cfg.DefenderConfig.Threshold = 3
  819. cfg.DefenderConfig.ScoreLimitExceeded = 2
  820. err := common.Initialize(cfg)
  821. assert.NoError(t, err)
  822. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  823. assert.NoError(t, err)
  824. client := getWebDavClient(user, true, nil)
  825. assert.NoError(t, checkBasicFunc(client))
  826. for i := 0; i < 3; i++ {
  827. user.Password = "wrong_pwd"
  828. client = getWebDavClient(user, false, nil)
  829. assert.Error(t, checkBasicFunc(client))
  830. }
  831. user.Password = defaultPassword
  832. client = getWebDavClient(user, true, nil)
  833. err = checkBasicFunc(client)
  834. if assert.Error(t, err) {
  835. assert.Contains(t, err.Error(), "403")
  836. }
  837. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  838. assert.NoError(t, err)
  839. err = os.RemoveAll(user.GetHomeDir())
  840. assert.NoError(t, err)
  841. err = common.Initialize(oldConfig)
  842. assert.NoError(t, err)
  843. }
  844. func TestLoginExternalAuth(t *testing.T) {
  845. if runtime.GOOS == osWindows {
  846. t.Skip("this test is not available on Windows")
  847. }
  848. u := getTestUser()
  849. err := dataprovider.Close()
  850. assert.NoError(t, err)
  851. err = config.LoadConfig(configDir, "")
  852. assert.NoError(t, err)
  853. providerConf := config.GetProviderConf()
  854. err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, ""), os.ModePerm)
  855. assert.NoError(t, err)
  856. providerConf.ExternalAuthHook = extAuthPath
  857. providerConf.ExternalAuthScope = 0
  858. err = dataprovider.Initialize(providerConf, configDir, true)
  859. assert.NoError(t, err)
  860. client := getWebDavClient(u, false, nil)
  861. assert.NoError(t, checkBasicFunc(client))
  862. u.Username = defaultUsername + "1"
  863. client = getWebDavClient(u, false, nil)
  864. assert.Error(t, checkBasicFunc(client))
  865. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  866. assert.NoError(t, err)
  867. assert.Equal(t, defaultUsername, user.Username)
  868. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  869. assert.NoError(t, err)
  870. err = os.RemoveAll(user.GetHomeDir())
  871. assert.NoError(t, err)
  872. err = dataprovider.Close()
  873. assert.NoError(t, err)
  874. err = config.LoadConfig(configDir, "")
  875. assert.NoError(t, err)
  876. providerConf = config.GetProviderConf()
  877. err = dataprovider.Initialize(providerConf, configDir, true)
  878. assert.NoError(t, err)
  879. err = os.Remove(extAuthPath)
  880. assert.NoError(t, err)
  881. }
  882. func TestPreLoginHook(t *testing.T) {
  883. if runtime.GOOS == osWindows {
  884. t.Skip("this test is not available on Windows")
  885. }
  886. u := getTestUser()
  887. err := dataprovider.Close()
  888. assert.NoError(t, err)
  889. err = config.LoadConfig(configDir, "")
  890. assert.NoError(t, err)
  891. providerConf := config.GetProviderConf()
  892. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
  893. assert.NoError(t, err)
  894. providerConf.PreLoginHook = preLoginPath
  895. err = dataprovider.Initialize(providerConf, configDir, true)
  896. assert.NoError(t, err)
  897. _, _, err = httpdtest.GetUserByUsername(defaultUsername, http.StatusNotFound)
  898. assert.NoError(t, err)
  899. client := getWebDavClient(u, true, nil)
  900. assert.NoError(t, checkBasicFunc(client))
  901. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  902. assert.NoError(t, err)
  903. // test login with an existing user
  904. client = getWebDavClient(user, true, nil)
  905. assert.NoError(t, checkBasicFunc(client))
  906. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), os.ModePerm)
  907. assert.NoError(t, err)
  908. // update the user to remove it from the cache
  909. user.FsConfig.Provider = sdk.CryptedFilesystemProvider
  910. user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret(defaultPassword)
  911. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  912. assert.NoError(t, err)
  913. client = getWebDavClient(user, true, nil)
  914. assert.Error(t, checkBasicFunc(client))
  915. // update the user to remove it from the cache
  916. user.FsConfig.Provider = sdk.LocalFilesystemProvider
  917. user.FsConfig.CryptConfig.Passphrase = nil
  918. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  919. assert.NoError(t, err)
  920. user.Status = 0
  921. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), os.ModePerm)
  922. assert.NoError(t, err)
  923. client = getWebDavClient(user, true, nil)
  924. assert.Error(t, checkBasicFunc(client))
  925. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  926. assert.NoError(t, err)
  927. err = os.RemoveAll(user.GetHomeDir())
  928. assert.NoError(t, err)
  929. err = dataprovider.Close()
  930. assert.NoError(t, err)
  931. err = config.LoadConfig(configDir, "")
  932. assert.NoError(t, err)
  933. providerConf = config.GetProviderConf()
  934. err = dataprovider.Initialize(providerConf, configDir, true)
  935. assert.NoError(t, err)
  936. err = os.Remove(preLoginPath)
  937. assert.NoError(t, err)
  938. }
  939. func TestPreDownloadHook(t *testing.T) {
  940. if runtime.GOOS == osWindows {
  941. t.Skip("this test is not available on Windows")
  942. }
  943. oldExecuteOn := common.Config.Actions.ExecuteOn
  944. oldHook := common.Config.Actions.Hook
  945. common.Config.Actions.ExecuteOn = []string{common.OperationPreDownload}
  946. common.Config.Actions.Hook = preDownloadPath
  947. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  948. assert.NoError(t, err)
  949. err = os.WriteFile(preDownloadPath, getExitCodeScriptContent(0), os.ModePerm)
  950. assert.NoError(t, err)
  951. client := getWebDavClient(user, true, nil)
  952. assert.NoError(t, checkBasicFunc(client))
  953. testFilePath := filepath.Join(homeBasePath, testFileName)
  954. testFileSize := int64(65535)
  955. err = createTestFile(testFilePath, testFileSize)
  956. assert.NoError(t, err)
  957. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  958. assert.NoError(t, err)
  959. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  960. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  961. assert.NoError(t, err)
  962. err = os.Remove(localDownloadPath)
  963. assert.NoError(t, err)
  964. err = os.WriteFile(preDownloadPath, getExitCodeScriptContent(1), os.ModePerm)
  965. assert.NoError(t, err)
  966. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  967. assert.Error(t, err)
  968. err = os.Remove(localDownloadPath)
  969. assert.NoError(t, err)
  970. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  971. assert.NoError(t, err)
  972. err = os.RemoveAll(user.GetHomeDir())
  973. assert.NoError(t, err)
  974. assert.Len(t, common.Connections.GetStats(), 0)
  975. common.Config.Actions.ExecuteOn = []string{common.OperationPreDownload}
  976. common.Config.Actions.Hook = preDownloadPath
  977. common.Config.Actions.ExecuteOn = oldExecuteOn
  978. common.Config.Actions.Hook = oldHook
  979. }
  980. func TestPreUploadHook(t *testing.T) {
  981. if runtime.GOOS == osWindows {
  982. t.Skip("this test is not available on Windows")
  983. }
  984. oldExecuteOn := common.Config.Actions.ExecuteOn
  985. oldHook := common.Config.Actions.Hook
  986. common.Config.Actions.ExecuteOn = []string{common.OperationPreUpload}
  987. common.Config.Actions.Hook = preUploadPath
  988. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  989. assert.NoError(t, err)
  990. err = os.WriteFile(preUploadPath, getExitCodeScriptContent(0), os.ModePerm)
  991. assert.NoError(t, err)
  992. client := getWebDavClient(user, true, nil)
  993. assert.NoError(t, checkBasicFunc(client))
  994. testFilePath := filepath.Join(homeBasePath, testFileName)
  995. testFileSize := int64(65535)
  996. err = createTestFile(testFilePath, testFileSize)
  997. assert.NoError(t, err)
  998. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  999. assert.NoError(t, err)
  1000. err = os.WriteFile(preUploadPath, getExitCodeScriptContent(1), os.ModePerm)
  1001. assert.NoError(t, err)
  1002. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  1003. assert.Error(t, err)
  1004. err = uploadFile(testFilePath, testFileName+"1", testFileSize, client)
  1005. assert.Error(t, err)
  1006. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1007. assert.NoError(t, err)
  1008. err = os.RemoveAll(user.GetHomeDir())
  1009. assert.NoError(t, err)
  1010. assert.Len(t, common.Connections.GetStats(), 0)
  1011. common.Config.Actions.ExecuteOn = oldExecuteOn
  1012. common.Config.Actions.Hook = oldHook
  1013. }
  1014. func TestPostConnectHook(t *testing.T) {
  1015. if runtime.GOOS == osWindows {
  1016. t.Skip("this test is not available on Windows")
  1017. }
  1018. common.Config.PostConnectHook = postConnectPath
  1019. u := getTestUser()
  1020. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1021. assert.NoError(t, err)
  1022. err = os.WriteFile(postConnectPath, getExitCodeScriptContent(0), os.ModePerm)
  1023. assert.NoError(t, err)
  1024. client := getWebDavClient(user, false, nil)
  1025. assert.NoError(t, checkBasicFunc(client))
  1026. err = os.WriteFile(postConnectPath, getExitCodeScriptContent(1), os.ModePerm)
  1027. assert.NoError(t, err)
  1028. assert.Error(t, checkBasicFunc(client))
  1029. common.Config.PostConnectHook = "http://127.0.0.1:8078/healthz"
  1030. assert.NoError(t, checkBasicFunc(client))
  1031. common.Config.PostConnectHook = "http://127.0.0.1:8078/notfound"
  1032. assert.Error(t, checkBasicFunc(client))
  1033. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1034. assert.NoError(t, err)
  1035. err = os.RemoveAll(user.GetHomeDir())
  1036. assert.NoError(t, err)
  1037. common.Config.PostConnectHook = ""
  1038. }
  1039. func TestMaxConnections(t *testing.T) {
  1040. oldValue := common.Config.MaxTotalConnections
  1041. common.Config.MaxTotalConnections = 1
  1042. assert.Eventually(t, func() bool {
  1043. return common.Connections.GetClientConnections() == 0
  1044. }, 1000*time.Millisecond, 50*time.Millisecond)
  1045. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1046. assert.NoError(t, err)
  1047. client := getWebDavClient(user, true, nil)
  1048. assert.NoError(t, checkBasicFunc(client))
  1049. // now add a fake connection
  1050. fs := vfs.NewOsFs("id", os.TempDir(), "")
  1051. connection := &webdavd.Connection{
  1052. BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
  1053. }
  1054. common.Connections.Add(connection)
  1055. assert.Error(t, checkBasicFunc(client))
  1056. common.Connections.Remove(connection.GetID())
  1057. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1058. assert.NoError(t, err)
  1059. err = os.RemoveAll(user.GetHomeDir())
  1060. assert.NoError(t, err)
  1061. assert.Len(t, common.Connections.GetStats(), 0)
  1062. common.Config.MaxTotalConnections = oldValue
  1063. }
  1064. func TestMaxPerHostConnections(t *testing.T) {
  1065. oldValue := common.Config.MaxPerHostConnections
  1066. common.Config.MaxPerHostConnections = 1
  1067. assert.Eventually(t, func() bool {
  1068. return common.Connections.GetClientConnections() == 0
  1069. }, 1000*time.Millisecond, 50*time.Millisecond)
  1070. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1071. assert.NoError(t, err)
  1072. client := getWebDavClient(user, true, nil)
  1073. assert.NoError(t, checkBasicFunc(client))
  1074. // now add a fake connection
  1075. addrs, err := net.LookupHost("localhost")
  1076. assert.NoError(t, err)
  1077. for _, addr := range addrs {
  1078. common.Connections.AddClientConnection(addr)
  1079. }
  1080. assert.Error(t, checkBasicFunc(client))
  1081. for _, addr := range addrs {
  1082. common.Connections.RemoveClientConnection(addr)
  1083. }
  1084. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1085. assert.NoError(t, err)
  1086. err = os.RemoveAll(user.GetHomeDir())
  1087. assert.NoError(t, err)
  1088. assert.Len(t, common.Connections.GetStats(), 0)
  1089. common.Config.MaxPerHostConnections = oldValue
  1090. }
  1091. func TestMaxSessions(t *testing.T) {
  1092. u := getTestUser()
  1093. u.MaxSessions = 1
  1094. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1095. assert.NoError(t, err)
  1096. client := getWebDavClient(user, false, nil)
  1097. assert.NoError(t, checkBasicFunc(client))
  1098. // now add a fake connection
  1099. fs := vfs.NewOsFs("id", os.TempDir(), "")
  1100. connection := &webdavd.Connection{
  1101. BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
  1102. }
  1103. common.Connections.Add(connection)
  1104. assert.Error(t, checkBasicFunc(client))
  1105. common.Connections.Remove(connection.GetID())
  1106. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1107. assert.NoError(t, err)
  1108. err = os.RemoveAll(user.GetHomeDir())
  1109. assert.NoError(t, err)
  1110. assert.Len(t, common.Connections.GetStats(), 0)
  1111. }
  1112. func TestLoginWithIPilters(t *testing.T) {
  1113. u := getTestUser()
  1114. u.Filters.DeniedIP = []string{"192.167.0.0/24", "172.18.0.0/16"}
  1115. u.Filters.AllowedIP = []string{"172.19.0.0/16"}
  1116. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1117. assert.NoError(t, err)
  1118. client := getWebDavClient(user, true, nil)
  1119. assert.Error(t, checkBasicFunc(client))
  1120. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1121. assert.NoError(t, err)
  1122. err = os.RemoveAll(user.GetHomeDir())
  1123. assert.NoError(t, err)
  1124. }
  1125. func TestDownloadErrors(t *testing.T) {
  1126. u := getTestUser()
  1127. u.QuotaFiles = 1
  1128. subDir1 := "sub1"
  1129. subDir2 := "sub2"
  1130. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems}
  1131. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  1132. dataprovider.PermDelete, dataprovider.PermDownload}
  1133. // use an unknown mime to trigger content type detection
  1134. u.Filters.FilePatterns = []sdk.PatternsFilter{
  1135. {
  1136. Path: "/sub2",
  1137. AllowedPatterns: []string{},
  1138. DeniedPatterns: []string{"*.jpg", "*.zipp"},
  1139. },
  1140. }
  1141. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1142. assert.NoError(t, err)
  1143. client := getWebDavClient(user, false, nil)
  1144. testFilePath1 := filepath.Join(user.HomeDir, subDir1, "file.zipp")
  1145. testFilePath2 := filepath.Join(user.HomeDir, subDir2, "file.zipp")
  1146. testFilePath3 := filepath.Join(user.HomeDir, subDir2, "file.jpg")
  1147. err = os.MkdirAll(filepath.Dir(testFilePath1), os.ModePerm)
  1148. assert.NoError(t, err)
  1149. err = os.MkdirAll(filepath.Dir(testFilePath2), os.ModePerm)
  1150. assert.NoError(t, err)
  1151. err = os.WriteFile(testFilePath1, []byte("file1"), os.ModePerm)
  1152. assert.NoError(t, err)
  1153. err = os.WriteFile(testFilePath2, []byte("file2"), os.ModePerm)
  1154. assert.NoError(t, err)
  1155. err = os.WriteFile(testFilePath3, []byte("file3"), os.ModePerm)
  1156. assert.NoError(t, err)
  1157. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1158. err = downloadFile(path.Join("/", subDir1, "file.zipp"), localDownloadPath, 5, client)
  1159. assert.Error(t, err)
  1160. err = downloadFile(path.Join("/", subDir2, "file.zipp"), localDownloadPath, 5, client)
  1161. assert.Error(t, err)
  1162. err = downloadFile(path.Join("/", subDir2, "file.jpg"), localDownloadPath, 5, client)
  1163. assert.Error(t, err)
  1164. err = downloadFile(path.Join("missing.zip"), localDownloadPath, 5, client)
  1165. assert.Error(t, err)
  1166. err = os.Remove(localDownloadPath)
  1167. assert.NoError(t, err)
  1168. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1169. assert.NoError(t, err)
  1170. err = os.RemoveAll(user.GetHomeDir())
  1171. assert.NoError(t, err)
  1172. }
  1173. func TestUploadErrors(t *testing.T) {
  1174. u := getTestUser()
  1175. u.QuotaSize = 65535
  1176. subDir1 := "sub1"
  1177. subDir2 := "sub2"
  1178. // we need download permission to get size since PROPFIND will open the file
  1179. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems, dataprovider.PermDownload}
  1180. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  1181. dataprovider.PermDelete, dataprovider.PermDownload}
  1182. u.Filters.FilePatterns = []sdk.PatternsFilter{
  1183. {
  1184. Path: "/sub2",
  1185. AllowedPatterns: []string{},
  1186. DeniedPatterns: []string{"*.zip"},
  1187. },
  1188. }
  1189. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1190. assert.NoError(t, err)
  1191. client := getWebDavClient(user, true, nil)
  1192. testFilePath := filepath.Join(homeBasePath, testFileName)
  1193. testFileSize := user.QuotaSize
  1194. err = createTestFile(testFilePath, testFileSize)
  1195. assert.NoError(t, err)
  1196. err = client.Mkdir(subDir1, os.ModePerm)
  1197. assert.NoError(t, err)
  1198. err = client.Mkdir(subDir2, os.ModePerm)
  1199. assert.NoError(t, err)
  1200. err = uploadFile(testFilePath, path.Join(subDir1, testFileName), testFileSize, client)
  1201. assert.Error(t, err)
  1202. err = uploadFile(testFilePath, path.Join(subDir2, testFileName+".zip"), testFileSize, client)
  1203. assert.Error(t, err)
  1204. err = uploadFile(testFilePath, path.Join(subDir2, testFileName), testFileSize, client)
  1205. assert.NoError(t, err)
  1206. err = client.Rename(path.Join(subDir2, testFileName), path.Join(subDir1, testFileName), false)
  1207. assert.Error(t, err)
  1208. err = uploadFile(testFilePath, path.Join(subDir2, testFileName), testFileSize, client)
  1209. assert.Error(t, err)
  1210. err = uploadFile(testFilePath, subDir1, testFileSize, client)
  1211. assert.Error(t, err)
  1212. // overquota
  1213. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  1214. assert.Error(t, err)
  1215. err = client.Remove(path.Join(subDir2, testFileName))
  1216. assert.NoError(t, err)
  1217. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  1218. assert.NoError(t, err)
  1219. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  1220. assert.Error(t, err)
  1221. err = os.Remove(testFilePath)
  1222. assert.NoError(t, err)
  1223. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1224. assert.NoError(t, err)
  1225. err = os.RemoveAll(user.GetHomeDir())
  1226. assert.NoError(t, err)
  1227. }
  1228. func TestDeniedLoginMethod(t *testing.T) {
  1229. u := getTestUser()
  1230. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword}
  1231. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1232. assert.NoError(t, err)
  1233. client := getWebDavClient(user, true, nil)
  1234. assert.Error(t, checkBasicFunc(client))
  1235. user.Filters.DeniedLoginMethods = []string{dataprovider.SSHLoginMethodPublicKey, dataprovider.SSHLoginMethodKeyAndKeyboardInt}
  1236. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1237. assert.NoError(t, err)
  1238. client = getWebDavClient(user, true, nil)
  1239. assert.NoError(t, checkBasicFunc(client))
  1240. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1241. assert.NoError(t, err)
  1242. err = os.RemoveAll(user.GetHomeDir())
  1243. assert.NoError(t, err)
  1244. }
  1245. func TestDeniedProtocols(t *testing.T) {
  1246. u := getTestUser()
  1247. u.Filters.DeniedProtocols = []string{common.ProtocolWebDAV}
  1248. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1249. assert.NoError(t, err)
  1250. client := getWebDavClient(user, false, nil)
  1251. assert.Error(t, checkBasicFunc(client))
  1252. user.Filters.DeniedProtocols = []string{common.ProtocolSSH, common.ProtocolFTP}
  1253. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1254. assert.NoError(t, err)
  1255. client = getWebDavClient(user, false, nil)
  1256. assert.NoError(t, checkBasicFunc(client))
  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 TestQuotaLimits(t *testing.T) {
  1263. u := getTestUser()
  1264. u.QuotaFiles = 1
  1265. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1266. assert.NoError(t, err)
  1267. u = getTestSFTPUser()
  1268. u.QuotaFiles = 1
  1269. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1270. assert.NoError(t, err)
  1271. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1272. testFileSize := int64(65536)
  1273. testFilePath := filepath.Join(homeBasePath, testFileName)
  1274. err = createTestFile(testFilePath, testFileSize)
  1275. assert.NoError(t, err)
  1276. testFileSize1 := int64(131072)
  1277. testFileName1 := "test_file1.dat"
  1278. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  1279. err = createTestFile(testFilePath1, testFileSize1)
  1280. assert.NoError(t, err)
  1281. testFileSize2 := int64(32768)
  1282. testFileName2 := "test_file2.dat"
  1283. testFilePath2 := filepath.Join(homeBasePath, testFileName2)
  1284. err = createTestFile(testFilePath2, testFileSize2)
  1285. assert.NoError(t, err)
  1286. client := getWebDavClient(user, false, nil)
  1287. // test quota files
  1288. err = uploadFile(testFilePath, testFileName+".quota", testFileSize, client)
  1289. if !assert.NoError(t, err, "username: %v", user.Username) {
  1290. info, err := os.Stat(testFilePath)
  1291. if assert.NoError(t, err) {
  1292. fmt.Printf("local file size: %v\n", info.Size())
  1293. }
  1294. printLatestLogs(20)
  1295. }
  1296. err = uploadFile(testFilePath, testFileName+".quota1", testFileSize, client)
  1297. assert.Error(t, err, "username: %v", user.Username)
  1298. err = client.Rename(testFileName+".quota", testFileName, false)
  1299. assert.NoError(t, err)
  1300. files, err := client.ReadDir("/")
  1301. assert.NoError(t, err)
  1302. assert.Len(t, files, 1)
  1303. // test quota size
  1304. user.QuotaSize = testFileSize - 1
  1305. user.QuotaFiles = 0
  1306. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1307. assert.NoError(t, err)
  1308. err = uploadFile(testFilePath, testFileName+".quota", testFileSize, client)
  1309. assert.Error(t, err)
  1310. err = client.Rename(testFileName, testFileName+".quota", false)
  1311. assert.NoError(t, err)
  1312. // now test quota limits while uploading the current file, we have 1 bytes remaining
  1313. user.QuotaSize = testFileSize + 1
  1314. user.QuotaFiles = 0
  1315. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1316. assert.NoError(t, err)
  1317. err = uploadFile(testFilePath1, testFileName1, testFileSize1, client)
  1318. assert.Error(t, err)
  1319. _, err = client.Stat(testFileName1)
  1320. assert.Error(t, err)
  1321. err = client.Rename(testFileName+".quota", testFileName, false)
  1322. assert.NoError(t, err)
  1323. // overwriting an existing file will work if the resulting size is lesser or equal than the current one
  1324. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  1325. assert.NoError(t, err)
  1326. err = uploadFile(testFilePath2, testFileName, testFileSize2, client)
  1327. assert.NoError(t, err)
  1328. err = uploadFile(testFilePath1, testFileName, testFileSize1, client)
  1329. assert.Error(t, err)
  1330. err = uploadFile(testFilePath2, testFileName, testFileSize2, client)
  1331. assert.NoError(t, err)
  1332. err = os.Remove(testFilePath)
  1333. assert.NoError(t, err)
  1334. err = os.Remove(testFilePath1)
  1335. assert.NoError(t, err)
  1336. err = os.Remove(testFilePath2)
  1337. assert.NoError(t, err)
  1338. if user.Username == defaultUsername {
  1339. err = os.RemoveAll(user.GetHomeDir())
  1340. assert.NoError(t, err)
  1341. user.QuotaFiles = 0
  1342. user.QuotaSize = 0
  1343. _, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1344. assert.NoError(t, err)
  1345. }
  1346. }
  1347. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1348. assert.NoError(t, err)
  1349. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1350. assert.NoError(t, err)
  1351. err = os.RemoveAll(localUser.GetHomeDir())
  1352. assert.NoError(t, err)
  1353. }
  1354. func TestUploadMaxSize(t *testing.T) {
  1355. testFileSize := int64(65535)
  1356. u := getTestUser()
  1357. u.Filters.MaxUploadFileSize = testFileSize + 1
  1358. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1359. assert.NoError(t, err)
  1360. u = getTestSFTPUser()
  1361. u.Filters.MaxUploadFileSize = testFileSize + 1
  1362. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1363. assert.NoError(t, err)
  1364. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1365. testFilePath := filepath.Join(homeBasePath, testFileName)
  1366. err = createTestFile(testFilePath, testFileSize)
  1367. assert.NoError(t, err)
  1368. testFileSize1 := int64(131072)
  1369. testFileName1 := "test_file_dav1.dat"
  1370. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  1371. err = createTestFile(testFilePath1, testFileSize1)
  1372. assert.NoError(t, err)
  1373. client := getWebDavClient(user, false, nil)
  1374. err = uploadFile(testFilePath1, testFileName1, testFileSize1, client)
  1375. assert.Error(t, err)
  1376. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  1377. assert.NoError(t, err)
  1378. // now test overwrite an existing file with a size bigger than the allowed one
  1379. err = createTestFile(filepath.Join(user.GetHomeDir(), testFileName1), testFileSize1)
  1380. assert.NoError(t, err)
  1381. err = uploadFile(testFilePath1, testFileName1, testFileSize1, client)
  1382. assert.Error(t, err)
  1383. err = os.Remove(testFilePath)
  1384. assert.NoError(t, err)
  1385. err = os.Remove(testFilePath1)
  1386. assert.NoError(t, err)
  1387. if user.Username == defaultUsername {
  1388. err = os.RemoveAll(user.GetHomeDir())
  1389. assert.NoError(t, err)
  1390. user.Filters.MaxUploadFileSize = 65536000
  1391. _, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1392. assert.NoError(t, err)
  1393. }
  1394. }
  1395. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1396. assert.NoError(t, err)
  1397. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1398. assert.NoError(t, err)
  1399. err = os.RemoveAll(localUser.GetHomeDir())
  1400. assert.NoError(t, err)
  1401. }
  1402. func TestClientClose(t *testing.T) {
  1403. u := getTestUser()
  1404. u.UploadBandwidth = 64
  1405. u.DownloadBandwidth = 64
  1406. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1407. assert.NoError(t, err)
  1408. u = getTestSFTPUser()
  1409. u.UploadBandwidth = 64
  1410. u.DownloadBandwidth = 64
  1411. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1412. assert.NoError(t, err)
  1413. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1414. testFileSize := int64(1048576)
  1415. testFilePath := filepath.Join(homeBasePath, testFileName)
  1416. err = createTestFile(testFilePath, testFileSize)
  1417. assert.NoError(t, err)
  1418. client := getWebDavClient(user, true, nil)
  1419. assert.NoError(t, checkBasicFunc(client))
  1420. var wg sync.WaitGroup
  1421. wg.Add(1)
  1422. go func() {
  1423. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  1424. assert.Error(t, err)
  1425. wg.Done()
  1426. }()
  1427. assert.Eventually(t, func() bool {
  1428. for _, stat := range common.Connections.GetStats() {
  1429. if len(stat.Transfers) > 0 {
  1430. return true
  1431. }
  1432. }
  1433. return false
  1434. }, 1*time.Second, 50*time.Millisecond)
  1435. for _, stat := range common.Connections.GetStats() {
  1436. common.Connections.Close(stat.ConnectionID)
  1437. }
  1438. wg.Wait()
  1439. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 },
  1440. 1*time.Second, 100*time.Millisecond)
  1441. err = os.Remove(testFilePath)
  1442. assert.NoError(t, err)
  1443. testFilePath = filepath.Join(user.HomeDir, testFileName)
  1444. err = createTestFile(testFilePath, testFileSize)
  1445. assert.NoError(t, err)
  1446. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1447. wg.Add(1)
  1448. go func() {
  1449. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1450. assert.Error(t, err)
  1451. wg.Done()
  1452. }()
  1453. assert.Eventually(t, func() bool {
  1454. for _, stat := range common.Connections.GetStats() {
  1455. if len(stat.Transfers) > 0 {
  1456. return true
  1457. }
  1458. }
  1459. return false
  1460. }, 1*time.Second, 50*time.Millisecond)
  1461. for _, stat := range common.Connections.GetStats() {
  1462. common.Connections.Close(stat.ConnectionID)
  1463. }
  1464. wg.Wait()
  1465. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 },
  1466. 1*time.Second, 100*time.Millisecond)
  1467. err = os.Remove(localDownloadPath)
  1468. assert.NoError(t, err)
  1469. }
  1470. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1471. assert.NoError(t, err)
  1472. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1473. assert.NoError(t, err)
  1474. err = os.RemoveAll(localUser.GetHomeDir())
  1475. assert.NoError(t, err)
  1476. }
  1477. func TestLoginWithDatabaseCredentials(t *testing.T) {
  1478. u := getTestUser()
  1479. u.FsConfig.Provider = sdk.GCSFilesystemProvider
  1480. u.FsConfig.GCSConfig.Bucket = "test"
  1481. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret(`{ "type": "service_account" }`)
  1482. providerConf := config.GetProviderConf()
  1483. providerConf.PreferDatabaseCredentials = true
  1484. credentialsFile := filepath.Join(providerConf.CredentialsPath, fmt.Sprintf("%v_gcs_credentials.json", u.Username))
  1485. if !filepath.IsAbs(credentialsFile) {
  1486. credentialsFile = filepath.Join(configDir, credentialsFile)
  1487. }
  1488. assert.NoError(t, dataprovider.Close())
  1489. err := dataprovider.Initialize(providerConf, configDir, true)
  1490. assert.NoError(t, err)
  1491. if _, err = os.Stat(credentialsFile); err == nil {
  1492. // remove the credentials file
  1493. assert.NoError(t, os.Remove(credentialsFile))
  1494. }
  1495. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1496. assert.NoError(t, err)
  1497. assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.GCSConfig.Credentials.GetStatus())
  1498. assert.NotEmpty(t, user.FsConfig.GCSConfig.Credentials.GetPayload())
  1499. assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetAdditionalData())
  1500. assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetKey())
  1501. assert.NoFileExists(t, credentialsFile)
  1502. client := getWebDavClient(user, false, nil)
  1503. err = client.Connect()
  1504. assert.NoError(t, err)
  1505. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1506. assert.NoError(t, err)
  1507. err = os.RemoveAll(user.GetHomeDir())
  1508. assert.NoError(t, err)
  1509. assert.NoError(t, dataprovider.Close())
  1510. assert.NoError(t, config.LoadConfig(configDir, ""))
  1511. providerConf = config.GetProviderConf()
  1512. assert.NoError(t, dataprovider.Initialize(providerConf, configDir, true))
  1513. }
  1514. func TestLoginInvalidFs(t *testing.T) {
  1515. u := getTestUser()
  1516. u.FsConfig.Provider = sdk.GCSFilesystemProvider
  1517. u.FsConfig.GCSConfig.Bucket = "test"
  1518. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("invalid JSON for credentials")
  1519. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1520. assert.NoError(t, err)
  1521. providerConf := config.GetProviderConf()
  1522. credentialsFile := filepath.Join(providerConf.CredentialsPath, fmt.Sprintf("%v_gcs_credentials.json", u.Username))
  1523. if !filepath.IsAbs(credentialsFile) {
  1524. credentialsFile = filepath.Join(configDir, credentialsFile)
  1525. }
  1526. // now remove the credentials file so the filesystem creation will fail
  1527. err = os.Remove(credentialsFile)
  1528. assert.NoError(t, err)
  1529. client := getWebDavClient(user, true, nil)
  1530. assert.Error(t, checkBasicFunc(client))
  1531. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1532. assert.NoError(t, err)
  1533. err = os.RemoveAll(user.GetHomeDir())
  1534. assert.NoError(t, err)
  1535. }
  1536. func TestSFTPBuffered(t *testing.T) {
  1537. u := getTestUser()
  1538. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1539. assert.NoError(t, err)
  1540. u = getTestSFTPUser()
  1541. u.QuotaFiles = 1000
  1542. u.HomeDir = filepath.Join(os.TempDir(), u.Username)
  1543. u.FsConfig.SFTPConfig.BufferSize = 2
  1544. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1545. assert.NoError(t, err)
  1546. client := getWebDavClient(sftpUser, true, nil)
  1547. assert.NoError(t, checkBasicFunc(client))
  1548. testFilePath := filepath.Join(homeBasePath, testFileName)
  1549. testFileSize := int64(65535)
  1550. expectedQuotaSize := testFileSize
  1551. expectedQuotaFiles := 1
  1552. err = createTestFile(testFilePath, testFileSize)
  1553. assert.NoError(t, err)
  1554. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  1555. assert.NoError(t, err)
  1556. // overwrite an existing file
  1557. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  1558. assert.NoError(t, err)
  1559. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1560. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1561. assert.NoError(t, err)
  1562. user, _, err := httpdtest.GetUserByUsername(sftpUser.Username, http.StatusOK)
  1563. assert.NoError(t, err)
  1564. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  1565. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  1566. fileContent := []byte("test file contents")
  1567. err = os.WriteFile(testFilePath, fileContent, os.ModePerm)
  1568. assert.NoError(t, err)
  1569. err = uploadFile(testFilePath, testFileName, int64(len(fileContent)), client)
  1570. assert.NoError(t, err)
  1571. remotePath := fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName)
  1572. req, err := http.NewRequest(http.MethodGet, remotePath, nil)
  1573. assert.NoError(t, err)
  1574. httpClient := httpclient.GetHTTPClient()
  1575. req.SetBasicAuth(user.Username, defaultPassword)
  1576. req.Header.Set("Range", "bytes=5-")
  1577. resp, err := httpClient.Do(req)
  1578. if assert.NoError(t, err) {
  1579. defer resp.Body.Close()
  1580. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  1581. bodyBytes, err := io.ReadAll(resp.Body)
  1582. assert.NoError(t, err)
  1583. assert.Equal(t, "file contents", string(bodyBytes))
  1584. }
  1585. req.Header.Set("Range", "bytes=5-8")
  1586. resp, err = httpClient.Do(req)
  1587. if assert.NoError(t, err) {
  1588. defer resp.Body.Close()
  1589. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  1590. bodyBytes, err := io.ReadAll(resp.Body)
  1591. assert.NoError(t, err)
  1592. assert.Equal(t, "file", string(bodyBytes))
  1593. }
  1594. err = os.Remove(testFilePath)
  1595. assert.NoError(t, err)
  1596. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1597. assert.NoError(t, err)
  1598. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1599. assert.NoError(t, err)
  1600. err = os.RemoveAll(localUser.GetHomeDir())
  1601. assert.NoError(t, err)
  1602. err = os.RemoveAll(sftpUser.GetHomeDir())
  1603. assert.NoError(t, err)
  1604. }
  1605. func TestBytesRangeRequests(t *testing.T) {
  1606. u := getTestUser()
  1607. u.Username = u.Username + "1"
  1608. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1609. assert.NoError(t, err)
  1610. sftpUser := getTestSFTPUser()
  1611. sftpUser.FsConfig.SFTPConfig.Username = localUser.Username
  1612. for _, u := range []dataprovider.User{getTestUser(), getTestUserWithCryptFs(), sftpUser} {
  1613. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1614. assert.NoError(t, err)
  1615. testFileName := "test_file.txt"
  1616. testFilePath := filepath.Join(homeBasePath, testFileName)
  1617. fileContent := []byte("test file contents")
  1618. err = os.WriteFile(testFilePath, fileContent, os.ModePerm)
  1619. assert.NoError(t, err)
  1620. client := getWebDavClient(user, true, nil)
  1621. err = uploadFile(testFilePath, testFileName, int64(len(fileContent)), client)
  1622. assert.NoError(t, err)
  1623. remotePath := fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName)
  1624. req, err := http.NewRequest(http.MethodGet, remotePath, nil)
  1625. if assert.NoError(t, err) {
  1626. httpClient := httpclient.GetHTTPClient()
  1627. req.SetBasicAuth(user.Username, defaultPassword)
  1628. req.Header.Set("Range", "bytes=5-")
  1629. resp, err := httpClient.Do(req)
  1630. if assert.NoError(t, err) {
  1631. defer resp.Body.Close()
  1632. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  1633. bodyBytes, err := io.ReadAll(resp.Body)
  1634. assert.NoError(t, err)
  1635. assert.Equal(t, "file contents", string(bodyBytes))
  1636. }
  1637. req.Header.Set("Range", "bytes=5-8")
  1638. resp, err = httpClient.Do(req)
  1639. if assert.NoError(t, err) {
  1640. defer resp.Body.Close()
  1641. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  1642. bodyBytes, err := io.ReadAll(resp.Body)
  1643. assert.NoError(t, err)
  1644. assert.Equal(t, "file", string(bodyBytes))
  1645. }
  1646. }
  1647. err = os.Remove(testFilePath)
  1648. assert.NoError(t, err)
  1649. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1650. assert.NoError(t, err)
  1651. err = os.RemoveAll(user.GetHomeDir())
  1652. assert.NoError(t, err)
  1653. }
  1654. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1655. assert.NoError(t, err)
  1656. err = os.RemoveAll(localUser.GetHomeDir())
  1657. assert.NoError(t, err)
  1658. }
  1659. func TestHEAD(t *testing.T) {
  1660. u := getTestUser()
  1661. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1662. assert.NoError(t, err)
  1663. rootPath := fmt.Sprintf("http://%v", webDavServerAddr)
  1664. httpClient := httpclient.GetHTTPClient()
  1665. req, err := http.NewRequest(http.MethodHead, rootPath, nil)
  1666. if assert.NoError(t, err) {
  1667. req.SetBasicAuth(u.Username, u.Password)
  1668. resp, err := httpClient.Do(req)
  1669. if assert.NoError(t, err) {
  1670. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  1671. assert.Equal(t, "text/xml; charset=utf-8", resp.Header.Get("Content-Type"))
  1672. resp.Body.Close()
  1673. }
  1674. }
  1675. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1676. assert.NoError(t, err)
  1677. err = os.RemoveAll(user.GetHomeDir())
  1678. assert.NoError(t, err)
  1679. }
  1680. func TestGETAsPROPFIND(t *testing.T) {
  1681. u := getTestUser()
  1682. subDir1 := "/sub1"
  1683. u.Permissions[subDir1] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs}
  1684. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1685. assert.NoError(t, err)
  1686. rootPath := fmt.Sprintf("http://%v/", webDavServerAddr)
  1687. httpClient := httpclient.GetHTTPClient()
  1688. req, err := http.NewRequest(http.MethodGet, rootPath, nil)
  1689. if assert.NoError(t, err) {
  1690. req.SetBasicAuth(u.Username, u.Password)
  1691. resp, err := httpClient.Do(req)
  1692. if assert.NoError(t, err) {
  1693. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  1694. resp.Body.Close()
  1695. }
  1696. }
  1697. client := getWebDavClient(user, false, nil)
  1698. err = client.MkdirAll(path.Join(subDir1, "sub", "sub1"), os.ModePerm)
  1699. assert.NoError(t, err)
  1700. subPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, subDir1)
  1701. req, err = http.NewRequest(http.MethodGet, subPath, nil)
  1702. if assert.NoError(t, err) {
  1703. req.SetBasicAuth(u.Username, u.Password)
  1704. resp, err := httpClient.Do(req)
  1705. if assert.NoError(t, err) {
  1706. // before the performance patch we have a 500 here, now we have 207 but an empty list
  1707. //assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
  1708. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  1709. resp.Body.Close()
  1710. }
  1711. }
  1712. // we cannot stat the sub at all
  1713. subPath1 := fmt.Sprintf("http://%v/%v", webDavServerAddr, path.Join(subDir1, "sub"))
  1714. req, err = http.NewRequest(http.MethodGet, subPath1, nil)
  1715. if assert.NoError(t, err) {
  1716. req.SetBasicAuth(u.Username, u.Password)
  1717. resp, err := httpClient.Do(req)
  1718. if assert.NoError(t, err) {
  1719. // here the stat will fail, so the request will not be changed in propfind
  1720. assert.Equal(t, http.StatusForbidden, resp.StatusCode)
  1721. resp.Body.Close()
  1722. }
  1723. }
  1724. // we have no permission, we get an empty list
  1725. files, err := client.ReadDir(subDir1)
  1726. assert.NoError(t, err)
  1727. assert.Len(t, files, 0)
  1728. // if we grant the permissions the files are listed
  1729. user.Permissions[subDir1] = []string{dataprovider.PermDownload, dataprovider.PermListItems}
  1730. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1731. assert.NoError(t, err)
  1732. files, err = client.ReadDir(subDir1)
  1733. assert.NoError(t, err)
  1734. assert.Len(t, files, 1)
  1735. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1736. assert.NoError(t, err)
  1737. err = os.RemoveAll(user.GetHomeDir())
  1738. assert.NoError(t, err)
  1739. }
  1740. func TestStat(t *testing.T) {
  1741. u := getTestUser()
  1742. u.Permissions["/subdir"] = []string{dataprovider.PermUpload, dataprovider.PermListItems, dataprovider.PermDownload}
  1743. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1744. assert.NoError(t, err)
  1745. client := getWebDavClient(user, true, nil)
  1746. subDir := "subdir"
  1747. testFilePath := filepath.Join(homeBasePath, testFileName)
  1748. testFileSize := int64(65535)
  1749. err = createTestFile(testFilePath, testFileSize)
  1750. assert.NoError(t, err)
  1751. err = client.Mkdir(subDir, os.ModePerm)
  1752. assert.NoError(t, err)
  1753. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  1754. assert.NoError(t, err)
  1755. err = uploadFile(testFilePath, path.Join("/", subDir, testFileName), testFileSize, client)
  1756. assert.NoError(t, err)
  1757. user.Permissions["/subdir"] = []string{dataprovider.PermUpload, dataprovider.PermDownload}
  1758. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1759. assert.NoError(t, err)
  1760. _, err = client.Stat(testFileName)
  1761. assert.NoError(t, err)
  1762. _, err = client.Stat(path.Join("/", subDir, testFileName))
  1763. assert.Error(t, err)
  1764. err = os.Remove(testFilePath)
  1765. assert.NoError(t, err)
  1766. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1767. assert.NoError(t, err)
  1768. err = os.RemoveAll(user.GetHomeDir())
  1769. assert.NoError(t, err)
  1770. }
  1771. func TestUploadOverwriteVfolder(t *testing.T) {
  1772. u := getTestUser()
  1773. vdir := "/vdir"
  1774. mappedPath := filepath.Join(os.TempDir(), "mappedDir")
  1775. folderName := filepath.Base(mappedPath)
  1776. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1777. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1778. Name: folderName,
  1779. MappedPath: mappedPath,
  1780. },
  1781. VirtualPath: vdir,
  1782. QuotaSize: -1,
  1783. QuotaFiles: -1,
  1784. })
  1785. err := os.MkdirAll(mappedPath, os.ModePerm)
  1786. assert.NoError(t, err)
  1787. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1788. assert.NoError(t, err)
  1789. client := getWebDavClient(user, false, nil)
  1790. files, err := client.ReadDir(".")
  1791. assert.NoError(t, err)
  1792. vdirFound := false
  1793. for _, info := range files {
  1794. if info.Name() == path.Base(vdir) {
  1795. vdirFound = true
  1796. break
  1797. }
  1798. }
  1799. assert.True(t, vdirFound)
  1800. info, err := client.Stat(vdir)
  1801. if assert.NoError(t, err) {
  1802. assert.Equal(t, path.Base(vdir), info.Name())
  1803. }
  1804. testFilePath := filepath.Join(homeBasePath, testFileName)
  1805. testFileSize := int64(65535)
  1806. err = createTestFile(testFilePath, testFileSize)
  1807. assert.NoError(t, err)
  1808. err = uploadFile(testFilePath, path.Join(vdir, testFileName), testFileSize, client)
  1809. assert.NoError(t, err)
  1810. folder, _, err := httpdtest.GetFolderByName(folderName, http.StatusOK)
  1811. assert.NoError(t, err)
  1812. assert.Equal(t, testFileSize, folder.UsedQuotaSize)
  1813. assert.Equal(t, 1, folder.UsedQuotaFiles)
  1814. err = uploadFile(testFilePath, path.Join(vdir, testFileName), testFileSize, client)
  1815. assert.NoError(t, err)
  1816. folder, _, err = httpdtest.GetFolderByName(folderName, http.StatusOK)
  1817. assert.NoError(t, err)
  1818. assert.Equal(t, testFileSize, folder.UsedQuotaSize)
  1819. assert.Equal(t, 1, folder.UsedQuotaFiles)
  1820. err = os.Remove(testFilePath)
  1821. assert.NoError(t, err)
  1822. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1823. assert.NoError(t, err)
  1824. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  1825. assert.NoError(t, err)
  1826. err = os.RemoveAll(user.GetHomeDir())
  1827. assert.NoError(t, err)
  1828. err = os.RemoveAll(mappedPath)
  1829. assert.NoError(t, err)
  1830. }
  1831. func TestOsErrors(t *testing.T) {
  1832. u := getTestUser()
  1833. vdir := "/vdir"
  1834. mappedPath := filepath.Join(os.TempDir(), "mappedDir")
  1835. folderName := filepath.Base(mappedPath)
  1836. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1837. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1838. Name: folderName,
  1839. MappedPath: mappedPath,
  1840. },
  1841. VirtualPath: vdir,
  1842. QuotaSize: -1,
  1843. QuotaFiles: -1,
  1844. })
  1845. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1846. assert.NoError(t, err)
  1847. client := getWebDavClient(user, false, nil)
  1848. files, err := client.ReadDir(".")
  1849. assert.NoError(t, err)
  1850. assert.Len(t, files, 1)
  1851. info, err := client.Stat(vdir)
  1852. assert.NoError(t, err)
  1853. assert.True(t, info.IsDir())
  1854. // now remove the folder mapped to vdir. It should not appear in directory listing
  1855. err = os.RemoveAll(mappedPath)
  1856. assert.NoError(t, err)
  1857. files, err = client.ReadDir(".")
  1858. assert.NoError(t, err)
  1859. assert.Len(t, files, 0)
  1860. err = createTestFile(filepath.Join(user.GetHomeDir(), testFileName), 32768)
  1861. assert.NoError(t, err)
  1862. files, err = client.ReadDir(".")
  1863. assert.NoError(t, err)
  1864. if assert.Len(t, files, 1) {
  1865. assert.Equal(t, testFileName, files[0].Name())
  1866. }
  1867. if runtime.GOOS != osWindows {
  1868. // if the file cannot be accessed it should not appear in directory listing
  1869. err = os.Chmod(filepath.Join(user.GetHomeDir(), testFileName), 0001)
  1870. assert.NoError(t, err)
  1871. files, err = client.ReadDir(".")
  1872. assert.NoError(t, err)
  1873. assert.Len(t, files, 0)
  1874. err = os.Chmod(filepath.Join(user.GetHomeDir(), testFileName), os.ModePerm)
  1875. assert.NoError(t, err)
  1876. }
  1877. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1878. assert.NoError(t, err)
  1879. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  1880. assert.NoError(t, err)
  1881. err = os.RemoveAll(user.GetHomeDir())
  1882. assert.NoError(t, err)
  1883. err = os.RemoveAll(mappedPath)
  1884. assert.NoError(t, err)
  1885. }
  1886. func TestMiscCommands(t *testing.T) {
  1887. u := getTestUser()
  1888. u.QuotaFiles = 100
  1889. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1890. assert.NoError(t, err)
  1891. u = getTestSFTPUser()
  1892. u.QuotaFiles = 100
  1893. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1894. assert.NoError(t, err)
  1895. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1896. dir := "testDir"
  1897. client := getWebDavClient(user, true, nil)
  1898. err = client.MkdirAll(path.Join(dir, "sub1", "sub2"), os.ModePerm)
  1899. assert.NoError(t, err)
  1900. testFilePath := filepath.Join(homeBasePath, testFileName)
  1901. testFileSize := int64(65535)
  1902. err = createTestFile(testFilePath, testFileSize)
  1903. assert.NoError(t, err)
  1904. err = uploadFile(testFilePath, path.Join(dir, testFileName), testFileSize, client)
  1905. assert.NoError(t, err)
  1906. err = uploadFile(testFilePath, path.Join(dir, "sub1", testFileName), testFileSize, client)
  1907. assert.NoError(t, err)
  1908. err = uploadFile(testFilePath, path.Join(dir, "sub1", "sub2", testFileName), testFileSize, client)
  1909. assert.NoError(t, err)
  1910. err = client.Copy(dir, dir+"_copy", false)
  1911. assert.NoError(t, err)
  1912. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1913. assert.NoError(t, err)
  1914. assert.Equal(t, 6, user.UsedQuotaFiles)
  1915. assert.Equal(t, 6*testFileSize, user.UsedQuotaSize)
  1916. err = client.Copy(dir, dir+"_copy1", false)
  1917. assert.NoError(t, err)
  1918. err = client.Copy(dir+"_copy", dir+"_copy1", false)
  1919. assert.Error(t, err)
  1920. err = client.Copy(dir+"_copy", dir+"_copy1", true)
  1921. assert.NoError(t, err)
  1922. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1923. assert.NoError(t, err)
  1924. assert.Equal(t, 9, user.UsedQuotaFiles)
  1925. assert.Equal(t, 9*testFileSize, user.UsedQuotaSize)
  1926. err = client.Rename(dir+"_copy1", dir+"_copy2", false)
  1927. assert.NoError(t, err)
  1928. err = client.Remove(path.Join(dir+"_copy", testFileName))
  1929. assert.NoError(t, err)
  1930. err = client.Rename(dir+"_copy2", dir+"_copy", true)
  1931. assert.NoError(t, err)
  1932. err = client.Copy(dir+"_copy", dir+"_copy1", false)
  1933. assert.NoError(t, err)
  1934. err = client.RemoveAll(dir + "_copy1")
  1935. assert.NoError(t, err)
  1936. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1937. assert.NoError(t, err)
  1938. assert.Equal(t, 6, user.UsedQuotaFiles)
  1939. assert.Equal(t, 6*testFileSize, user.UsedQuotaSize)
  1940. err = os.Remove(testFilePath)
  1941. assert.NoError(t, err)
  1942. if user.Username == defaultUsername {
  1943. err = os.RemoveAll(user.GetHomeDir())
  1944. assert.NoError(t, err)
  1945. user.QuotaFiles = 0
  1946. _, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1947. assert.NoError(t, err)
  1948. }
  1949. }
  1950. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1951. assert.NoError(t, err)
  1952. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1953. assert.NoError(t, err)
  1954. err = os.RemoveAll(localUser.GetHomeDir())
  1955. assert.NoError(t, err)
  1956. }
  1957. func TestClientCertificateAuthRevokedCert(t *testing.T) {
  1958. u := getTestUser()
  1959. u.Username = tlsClient2Username
  1960. u.Filters.TLSUsername = sdk.TLSUsernameCN
  1961. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1962. assert.NoError(t, err)
  1963. tlsConfig := &tls.Config{
  1964. ServerName: "localhost",
  1965. InsecureSkipVerify: true, // use this for tests only
  1966. MinVersion: tls.VersionTLS12,
  1967. }
  1968. tlsCert, err := tls.X509KeyPair([]byte(client2Crt), []byte(client2Key))
  1969. assert.NoError(t, err)
  1970. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  1971. client := getWebDavClient(user, true, tlsConfig)
  1972. err = checkBasicFunc(client)
  1973. if assert.Error(t, err) {
  1974. if !strings.Contains(err.Error(), "bad certificate") && !strings.Contains(err.Error(), "broken pipe") {
  1975. t.Errorf("unexpected error: %v", err)
  1976. }
  1977. }
  1978. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1979. assert.NoError(t, err)
  1980. err = os.RemoveAll(user.GetHomeDir())
  1981. assert.NoError(t, err)
  1982. }
  1983. func TestClientCertificateAuth(t *testing.T) {
  1984. u := getTestUser()
  1985. u.Username = tlsClient1Username
  1986. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificateAndPwd}
  1987. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1988. assert.NoError(t, err)
  1989. tlsConfig := &tls.Config{
  1990. ServerName: "localhost",
  1991. InsecureSkipVerify: true, // use this for tests only
  1992. MinVersion: tls.VersionTLS12,
  1993. }
  1994. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  1995. assert.NoError(t, err)
  1996. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  1997. // TLS username is not enabled, mutual TLS should fail
  1998. resp, err := getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v/", webDavTLSServerAddr))
  1999. if assert.NoError(t, err) {
  2000. defer resp.Body.Close()
  2001. body, err := io.ReadAll(resp.Body)
  2002. assert.NoError(t, err)
  2003. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2004. }
  2005. user.Filters.TLSUsername = sdk.TLSUsernameCN
  2006. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2007. assert.NoError(t, err)
  2008. client := getWebDavClient(user, true, tlsConfig)
  2009. err = checkBasicFunc(client)
  2010. assert.NoError(t, err)
  2011. user.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificate}
  2012. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2013. assert.NoError(t, err)
  2014. client = getWebDavClient(user, true, tlsConfig)
  2015. err = checkBasicFunc(client)
  2016. assert.NoError(t, err)
  2017. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2018. assert.NoError(t, err)
  2019. err = os.RemoveAll(user.GetHomeDir())
  2020. assert.NoError(t, err)
  2021. }
  2022. func TestWrongClientCertificate(t *testing.T) {
  2023. u := getTestUser()
  2024. u.Username = tlsClient2Username
  2025. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificateAndPwd}
  2026. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2027. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2028. assert.NoError(t, err)
  2029. tlsConfig := &tls.Config{
  2030. ServerName: "localhost",
  2031. InsecureSkipVerify: true, // use this for tests only
  2032. MinVersion: tls.VersionTLS12,
  2033. }
  2034. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2035. assert.NoError(t, err)
  2036. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2037. // the certificate common name is client1 and it does not exists
  2038. resp, err := getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v/", webDavTLSServerAddr))
  2039. if assert.NoError(t, err) {
  2040. defer resp.Body.Close()
  2041. body, err := io.ReadAll(resp.Body)
  2042. assert.NoError(t, err)
  2043. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2044. }
  2045. user.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificate}
  2046. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2047. assert.NoError(t, err)
  2048. // now create client1
  2049. u = getTestUser()
  2050. u.Username = tlsClient1Username
  2051. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificate}
  2052. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2053. user1, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2054. assert.NoError(t, err)
  2055. resp, err = getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v:%v@%v/", tlsClient2Username, defaultPassword,
  2056. webDavTLSServerAddr))
  2057. if assert.NoError(t, err) {
  2058. defer resp.Body.Close()
  2059. body, err := io.ReadAll(resp.Body)
  2060. assert.NoError(t, err)
  2061. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2062. assert.Contains(t, string(body), "invalid credentials")
  2063. }
  2064. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2065. assert.NoError(t, err)
  2066. err = os.RemoveAll(user.GetHomeDir())
  2067. assert.NoError(t, err)
  2068. _, err = httpdtest.RemoveUser(user1, http.StatusOK)
  2069. assert.NoError(t, err)
  2070. err = os.RemoveAll(user1.GetHomeDir())
  2071. assert.NoError(t, err)
  2072. }
  2073. func TestClientCertificateAuthCachedUser(t *testing.T) {
  2074. u := getTestUser()
  2075. u.Username = tlsClient1Username
  2076. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2077. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificateAndPwd}
  2078. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2079. assert.NoError(t, err)
  2080. tlsConfig := &tls.Config{
  2081. ServerName: "localhost",
  2082. InsecureSkipVerify: true, // use this for tests only
  2083. MinVersion: tls.VersionTLS12,
  2084. }
  2085. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2086. assert.NoError(t, err)
  2087. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2088. client := getWebDavClient(user, true, tlsConfig)
  2089. err = checkBasicFunc(client)
  2090. assert.NoError(t, err)
  2091. // the user is now cached without a password, try a simple password login with and without TLS
  2092. client = getWebDavClient(user, true, nil)
  2093. err = checkBasicFunc(client)
  2094. assert.NoError(t, err)
  2095. client = getWebDavClient(user, false, nil)
  2096. err = checkBasicFunc(client)
  2097. assert.NoError(t, err)
  2098. // and now with a wrong password
  2099. user.Password = "wrong"
  2100. client = getWebDavClient(user, false, nil)
  2101. err = checkBasicFunc(client)
  2102. assert.Error(t, err)
  2103. // allow cert+password only
  2104. user.Password = ""
  2105. user.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificate}
  2106. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2107. assert.NoError(t, err)
  2108. client = getWebDavClient(user, true, tlsConfig)
  2109. err = checkBasicFunc(client)
  2110. assert.NoError(t, err)
  2111. // the user is now cached
  2112. client = getWebDavClient(user, true, tlsConfig)
  2113. err = checkBasicFunc(client)
  2114. assert.NoError(t, err)
  2115. // password auth should work too
  2116. client = getWebDavClient(user, false, nil)
  2117. err = checkBasicFunc(client)
  2118. assert.NoError(t, err)
  2119. client = getWebDavClient(user, true, nil)
  2120. err = checkBasicFunc(client)
  2121. assert.NoError(t, err)
  2122. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2123. assert.NoError(t, err)
  2124. err = os.RemoveAll(user.GetHomeDir())
  2125. assert.NoError(t, err)
  2126. }
  2127. func TestExternatAuthWithClientCert(t *testing.T) {
  2128. if runtime.GOOS == osWindows {
  2129. t.Skip("this test is not available on Windows")
  2130. }
  2131. u := getTestUser()
  2132. u.Username = tlsClient1Username
  2133. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2134. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificate, dataprovider.LoginMethodPassword}
  2135. err := dataprovider.Close()
  2136. assert.NoError(t, err)
  2137. err = config.LoadConfig(configDir, "")
  2138. assert.NoError(t, err)
  2139. providerConf := config.GetProviderConf()
  2140. err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, ""), os.ModePerm)
  2141. assert.NoError(t, err)
  2142. providerConf.ExternalAuthHook = extAuthPath
  2143. providerConf.ExternalAuthScope = 0
  2144. err = dataprovider.Initialize(providerConf, configDir, true)
  2145. assert.NoError(t, err)
  2146. tlsConfig := &tls.Config{
  2147. ServerName: "localhost",
  2148. InsecureSkipVerify: true, // use this for tests only
  2149. MinVersion: tls.VersionTLS12,
  2150. }
  2151. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2152. assert.NoError(t, err)
  2153. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2154. client := getWebDavClient(u, true, tlsConfig)
  2155. assert.NoError(t, checkBasicFunc(client))
  2156. resp, err := getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v:%v@%v/", tlsClient2Username, defaultPassword,
  2157. webDavTLSServerAddr))
  2158. if assert.NoError(t, err) {
  2159. defer resp.Body.Close()
  2160. body, err := io.ReadAll(resp.Body)
  2161. assert.NoError(t, err)
  2162. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2163. assert.Contains(t, string(body), "invalid credentials")
  2164. }
  2165. user, _, err := httpdtest.GetUserByUsername(tlsClient1Username, http.StatusOK)
  2166. assert.NoError(t, err)
  2167. assert.Equal(t, tlsClient1Username, user.Username)
  2168. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2169. assert.NoError(t, err)
  2170. err = os.RemoveAll(user.GetHomeDir())
  2171. assert.NoError(t, err)
  2172. err = dataprovider.Close()
  2173. assert.NoError(t, err)
  2174. err = config.LoadConfig(configDir, "")
  2175. assert.NoError(t, err)
  2176. providerConf = config.GetProviderConf()
  2177. err = dataprovider.Initialize(providerConf, configDir, true)
  2178. assert.NoError(t, err)
  2179. err = os.Remove(extAuthPath)
  2180. assert.NoError(t, err)
  2181. }
  2182. func TestPreLoginHookWithClientCert(t *testing.T) {
  2183. if runtime.GOOS == osWindows {
  2184. t.Skip("this test is not available on Windows")
  2185. }
  2186. u := getTestUser()
  2187. u.Username = tlsClient1Username
  2188. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2189. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificate, dataprovider.LoginMethodPassword}
  2190. err := dataprovider.Close()
  2191. assert.NoError(t, err)
  2192. err = config.LoadConfig(configDir, "")
  2193. assert.NoError(t, err)
  2194. providerConf := config.GetProviderConf()
  2195. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
  2196. assert.NoError(t, err)
  2197. providerConf.PreLoginHook = preLoginPath
  2198. err = dataprovider.Initialize(providerConf, configDir, true)
  2199. assert.NoError(t, err)
  2200. _, _, err = httpdtest.GetUserByUsername(tlsClient1Username, http.StatusNotFound)
  2201. assert.NoError(t, err)
  2202. tlsConfig := &tls.Config{
  2203. ServerName: "localhost",
  2204. InsecureSkipVerify: true, // use this for tests only
  2205. MinVersion: tls.VersionTLS12,
  2206. }
  2207. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2208. assert.NoError(t, err)
  2209. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2210. client := getWebDavClient(u, true, tlsConfig)
  2211. assert.NoError(t, checkBasicFunc(client))
  2212. user, _, err := httpdtest.GetUserByUsername(tlsClient1Username, http.StatusOK)
  2213. assert.NoError(t, err)
  2214. // test login with an existing user
  2215. client = getWebDavClient(user, true, tlsConfig)
  2216. assert.NoError(t, checkBasicFunc(client))
  2217. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), os.ModePerm)
  2218. assert.NoError(t, err)
  2219. // update the user to remove it from the cache
  2220. user.Password = defaultPassword
  2221. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2222. assert.NoError(t, err)
  2223. client = getWebDavClient(user, true, tlsConfig)
  2224. assert.Error(t, checkBasicFunc(client))
  2225. // update the user to remove it from the cache
  2226. user.Password = defaultPassword
  2227. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2228. assert.NoError(t, err)
  2229. user.Status = 0
  2230. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), os.ModePerm)
  2231. assert.NoError(t, err)
  2232. client = getWebDavClient(user, true, tlsConfig)
  2233. assert.Error(t, checkBasicFunc(client))
  2234. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2235. assert.NoError(t, err)
  2236. err = os.RemoveAll(user.GetHomeDir())
  2237. assert.NoError(t, err)
  2238. err = dataprovider.Close()
  2239. assert.NoError(t, err)
  2240. err = config.LoadConfig(configDir, "")
  2241. assert.NoError(t, err)
  2242. providerConf = config.GetProviderConf()
  2243. err = dataprovider.Initialize(providerConf, configDir, true)
  2244. assert.NoError(t, err)
  2245. err = os.Remove(preLoginPath)
  2246. assert.NoError(t, err)
  2247. }
  2248. func TestSFTPLoopVirtualFolders(t *testing.T) {
  2249. user1 := getTestUser()
  2250. user2 := getTestUser()
  2251. user1.Username += "1"
  2252. user2.Username += "2"
  2253. // user1 is a local account with a virtual SFTP folder to user2
  2254. // user2 has user1 as SFTP fs
  2255. user1.VirtualFolders = append(user1.VirtualFolders, vfs.VirtualFolder{
  2256. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2257. Name: "sftp",
  2258. FsConfig: vfs.Filesystem{
  2259. Provider: sdk.SFTPFilesystemProvider,
  2260. SFTPConfig: vfs.SFTPFsConfig{
  2261. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  2262. Endpoint: sftpServerAddr,
  2263. Username: user2.Username,
  2264. },
  2265. Password: kms.NewPlainSecret(defaultPassword),
  2266. },
  2267. },
  2268. },
  2269. VirtualPath: "/vdir",
  2270. })
  2271. user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
  2272. user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
  2273. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  2274. Endpoint: sftpServerAddr,
  2275. Username: user1.Username,
  2276. },
  2277. Password: kms.NewPlainSecret(defaultPassword),
  2278. }
  2279. user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
  2280. assert.NoError(t, err, string(resp))
  2281. user2, resp, err = httpdtest.AddUser(user2, http.StatusCreated)
  2282. assert.NoError(t, err, string(resp))
  2283. client := getWebDavClient(user1, true, nil)
  2284. testDir := "tdir"
  2285. err = client.Mkdir(testDir, os.ModePerm)
  2286. assert.NoError(t, err)
  2287. contents, err := client.ReadDir("/")
  2288. assert.NoError(t, err)
  2289. if assert.Len(t, contents, 1) {
  2290. assert.Equal(t, testDir, contents[0].Name())
  2291. assert.True(t, contents[0].IsDir())
  2292. }
  2293. _, err = httpdtest.RemoveUser(user1, http.StatusOK)
  2294. assert.NoError(t, err)
  2295. err = os.RemoveAll(user1.GetHomeDir())
  2296. assert.NoError(t, err)
  2297. _, err = httpdtest.RemoveUser(user2, http.StatusOK)
  2298. assert.NoError(t, err)
  2299. err = os.RemoveAll(user2.GetHomeDir())
  2300. assert.NoError(t, err)
  2301. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: "sftp"}, http.StatusOK)
  2302. assert.NoError(t, err)
  2303. }
  2304. func TestNestedVirtualFolders(t *testing.T) {
  2305. u := getTestUser()
  2306. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2307. assert.NoError(t, err)
  2308. u = getTestSFTPUser()
  2309. mappedPathCrypt := filepath.Join(os.TempDir(), "crypt")
  2310. folderNameCrypt := filepath.Base(mappedPathCrypt)
  2311. vdirCryptPath := "/vdir/crypt"
  2312. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2313. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2314. Name: folderNameCrypt,
  2315. FsConfig: vfs.Filesystem{
  2316. Provider: sdk.CryptedFilesystemProvider,
  2317. CryptConfig: vfs.CryptFsConfig{
  2318. Passphrase: kms.NewPlainSecret(defaultPassword),
  2319. },
  2320. },
  2321. MappedPath: mappedPathCrypt,
  2322. },
  2323. VirtualPath: vdirCryptPath,
  2324. })
  2325. mappedPath := filepath.Join(os.TempDir(), "local")
  2326. folderName := filepath.Base(mappedPath)
  2327. vdirPath := "/vdir/local"
  2328. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2329. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2330. Name: folderName,
  2331. MappedPath: mappedPath,
  2332. },
  2333. VirtualPath: vdirPath,
  2334. })
  2335. mappedPathNested := filepath.Join(os.TempDir(), "nested")
  2336. folderNameNested := filepath.Base(mappedPathNested)
  2337. vdirNestedPath := "/vdir/crypt/nested"
  2338. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2339. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2340. Name: folderNameNested,
  2341. MappedPath: mappedPathNested,
  2342. },
  2343. VirtualPath: vdirNestedPath,
  2344. QuotaFiles: -1,
  2345. QuotaSize: -1,
  2346. })
  2347. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2348. assert.NoError(t, err)
  2349. client := getWebDavClient(sftpUser, true, nil)
  2350. assert.NoError(t, checkBasicFunc(client))
  2351. testFilePath := filepath.Join(homeBasePath, testFileName)
  2352. testFileSize := int64(65535)
  2353. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  2354. err = createTestFile(testFilePath, testFileSize)
  2355. assert.NoError(t, err)
  2356. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  2357. assert.NoError(t, err)
  2358. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  2359. assert.NoError(t, err)
  2360. err = uploadFile(testFilePath, path.Join("/vdir", testFileName), testFileSize, client)
  2361. assert.NoError(t, err)
  2362. err = downloadFile(path.Join("/vdir", testFileName), localDownloadPath, testFileSize, client)
  2363. assert.NoError(t, err)
  2364. err = uploadFile(testFilePath, path.Join(vdirPath, testFileName), testFileSize, client)
  2365. assert.NoError(t, err)
  2366. err = downloadFile(path.Join(vdirPath, testFileName), localDownloadPath, testFileSize, client)
  2367. assert.NoError(t, err)
  2368. err = uploadFile(testFilePath, path.Join(vdirCryptPath, testFileName), testFileSize, client)
  2369. assert.NoError(t, err)
  2370. err = downloadFile(path.Join(vdirCryptPath, testFileName), localDownloadPath, testFileSize, client)
  2371. assert.NoError(t, err)
  2372. err = uploadFile(testFilePath, path.Join(vdirNestedPath, testFileName), testFileSize, client)
  2373. assert.NoError(t, err)
  2374. err = downloadFile(path.Join(vdirNestedPath, testFileName), localDownloadPath, testFileSize, client)
  2375. assert.NoError(t, err)
  2376. err = os.Remove(testFilePath)
  2377. assert.NoError(t, err)
  2378. err = os.Remove(localDownloadPath)
  2379. assert.NoError(t, err)
  2380. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  2381. assert.NoError(t, err)
  2382. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  2383. assert.NoError(t, err)
  2384. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameCrypt}, http.StatusOK)
  2385. assert.NoError(t, err)
  2386. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  2387. assert.NoError(t, err)
  2388. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameNested}, http.StatusOK)
  2389. assert.NoError(t, err)
  2390. err = os.RemoveAll(mappedPathCrypt)
  2391. assert.NoError(t, err)
  2392. err = os.RemoveAll(mappedPath)
  2393. assert.NoError(t, err)
  2394. err = os.RemoveAll(mappedPathNested)
  2395. assert.NoError(t, err)
  2396. err = os.RemoveAll(localUser.GetHomeDir())
  2397. assert.NoError(t, err)
  2398. assert.Len(t, common.Connections.GetStats(), 0)
  2399. }
  2400. func checkBasicFunc(client *gowebdav.Client) error {
  2401. err := client.Connect()
  2402. if err != nil {
  2403. return err
  2404. }
  2405. _, err = client.ReadDir("/")
  2406. return err
  2407. }
  2408. func checkFileSize(remoteDestPath string, expectedSize int64, client *gowebdav.Client) error {
  2409. info, err := client.Stat(remoteDestPath)
  2410. if err != nil {
  2411. return err
  2412. }
  2413. if info.Size() != expectedSize {
  2414. return fmt.Errorf("uploaded file size does not match, actual: %v, expected: %v", info.Size(), expectedSize)
  2415. }
  2416. return nil
  2417. }
  2418. func uploadFile(localSourcePath string, remoteDestPath string, expectedSize int64, client *gowebdav.Client) error {
  2419. srcFile, err := os.Open(localSourcePath)
  2420. if err != nil {
  2421. return err
  2422. }
  2423. defer srcFile.Close()
  2424. err = client.WriteStream(remoteDestPath, srcFile, os.ModePerm)
  2425. if err != nil {
  2426. return err
  2427. }
  2428. if expectedSize > 0 {
  2429. return checkFileSize(remoteDestPath, expectedSize, client)
  2430. /*if err != nil {
  2431. time.Sleep(1 * time.Second)
  2432. return checkFileSize(remoteDestPath, expectedSize, client)
  2433. }*/
  2434. }
  2435. return nil
  2436. }
  2437. func downloadFile(remoteSourcePath string, localDestPath string, expectedSize int64, client *gowebdav.Client) error {
  2438. downloadDest, err := os.Create(localDestPath)
  2439. if err != nil {
  2440. return err
  2441. }
  2442. defer downloadDest.Close()
  2443. reader, err := client.ReadStream(remoteSourcePath)
  2444. if err != nil {
  2445. return err
  2446. }
  2447. defer reader.Close()
  2448. written, err := io.Copy(downloadDest, reader)
  2449. if err != nil {
  2450. return err
  2451. }
  2452. if written != expectedSize {
  2453. return fmt.Errorf("downloaded file size does not match, actual: %v, expected: %v", written, expectedSize)
  2454. }
  2455. return nil
  2456. }
  2457. func getTLSHTTPClient(tlsConfig *tls.Config) *http.Client {
  2458. customTransport := http.DefaultTransport.(*http.Transport).Clone()
  2459. customTransport.TLSClientConfig = tlsConfig
  2460. return &http.Client{
  2461. Timeout: 5 * time.Second,
  2462. Transport: customTransport,
  2463. }
  2464. }
  2465. func getWebDavClient(user dataprovider.User, useTLS bool, tlsConfig *tls.Config) *gowebdav.Client {
  2466. rootPath := fmt.Sprintf("http://%v/", webDavServerAddr)
  2467. if useTLS {
  2468. rootPath = fmt.Sprintf("https://%v/", webDavTLSServerAddr)
  2469. if tlsConfig == nil {
  2470. tlsConfig = &tls.Config{
  2471. ServerName: "localhost",
  2472. InsecureSkipVerify: true, // use this for tests only
  2473. MinVersion: tls.VersionTLS12,
  2474. }
  2475. }
  2476. }
  2477. pwd := defaultPassword
  2478. if user.Password != "" {
  2479. pwd = user.Password
  2480. }
  2481. client := gowebdav.NewClient(rootPath, user.Username, pwd)
  2482. client.SetTimeout(10 * time.Second)
  2483. if tlsConfig != nil {
  2484. customTransport := http.DefaultTransport.(*http.Transport).Clone()
  2485. customTransport.TLSClientConfig = tlsConfig
  2486. client.SetTransport(customTransport)
  2487. }
  2488. return client
  2489. }
  2490. func waitTCPListening(address string) {
  2491. for {
  2492. conn, err := net.Dial("tcp", address)
  2493. if err != nil {
  2494. logger.WarnToConsole("tcp server %v not listening: %v", address, err)
  2495. time.Sleep(100 * time.Millisecond)
  2496. continue
  2497. }
  2498. logger.InfoToConsole("tcp server %v now listening", address)
  2499. conn.Close()
  2500. break
  2501. }
  2502. }
  2503. func getTestUser() dataprovider.User {
  2504. user := dataprovider.User{
  2505. BaseUser: sdk.BaseUser{
  2506. Username: defaultUsername,
  2507. Password: defaultPassword,
  2508. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  2509. Status: 1,
  2510. ExpirationDate: 0,
  2511. },
  2512. }
  2513. user.Permissions = make(map[string][]string)
  2514. user.Permissions["/"] = allPerms
  2515. return user
  2516. }
  2517. func getTestSFTPUser() dataprovider.User {
  2518. u := getTestUser()
  2519. u.Username = u.Username + "_sftp"
  2520. u.FsConfig.Provider = sdk.SFTPFilesystemProvider
  2521. u.FsConfig.SFTPConfig.Endpoint = sftpServerAddr
  2522. u.FsConfig.SFTPConfig.Username = defaultUsername
  2523. u.FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword)
  2524. return u
  2525. }
  2526. func getTestUserWithCryptFs() dataprovider.User {
  2527. user := getTestUser()
  2528. user.FsConfig.Provider = sdk.CryptedFilesystemProvider
  2529. user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret("testPassphrase")
  2530. return user
  2531. }
  2532. func getEncryptedFileSize(size int64) (int64, error) {
  2533. encSize, err := sio.EncryptedSize(uint64(size))
  2534. return int64(encSize) + 33, err
  2535. }
  2536. func getExtAuthScriptContent(user dataprovider.User, nonJSONResponse bool, username string) []byte {
  2537. extAuthContent := []byte("#!/bin/sh\n\n")
  2538. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("if test \"$SFTPGO_AUTHD_USERNAME\" = \"%v\"; then\n", user.Username))...)
  2539. if len(username) > 0 {
  2540. user.Username = username
  2541. }
  2542. u, _ := json.Marshal(user)
  2543. if nonJSONResponse {
  2544. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  2545. } else {
  2546. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  2547. }
  2548. extAuthContent = append(extAuthContent, []byte("else\n")...)
  2549. if nonJSONResponse {
  2550. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  2551. } else {
  2552. extAuthContent = append(extAuthContent, []byte("echo '{\"username\":\"\"}'\n")...)
  2553. }
  2554. extAuthContent = append(extAuthContent, []byte("fi\n")...)
  2555. return extAuthContent
  2556. }
  2557. func getPreLoginScriptContent(user dataprovider.User, nonJSONResponse bool) []byte {
  2558. content := []byte("#!/bin/sh\n\n")
  2559. if nonJSONResponse {
  2560. content = append(content, []byte("echo 'text response'\n")...)
  2561. return content
  2562. }
  2563. if len(user.Username) > 0 {
  2564. u, _ := json.Marshal(user)
  2565. content = append(content, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  2566. }
  2567. return content
  2568. }
  2569. func getExitCodeScriptContent(exitCode int) []byte {
  2570. content := []byte("#!/bin/sh\n\n")
  2571. content = append(content, []byte(fmt.Sprintf("exit %v", exitCode))...)
  2572. return content
  2573. }
  2574. func createTestFile(path string, size int64) error {
  2575. baseDir := filepath.Dir(path)
  2576. if _, err := os.Stat(baseDir); os.IsNotExist(err) {
  2577. err = os.MkdirAll(baseDir, os.ModePerm)
  2578. if err != nil {
  2579. return err
  2580. }
  2581. }
  2582. content := make([]byte, size)
  2583. _, err := rand.Read(content)
  2584. if err != nil {
  2585. return err
  2586. }
  2587. return os.WriteFile(path, content, os.ModePerm)
  2588. }
  2589. func printLatestLogs(maxNumberOfLines int) {
  2590. var lines []string
  2591. f, err := os.Open(logFilePath)
  2592. if err != nil {
  2593. return
  2594. }
  2595. defer f.Close()
  2596. scanner := bufio.NewScanner(f)
  2597. for scanner.Scan() {
  2598. lines = append(lines, scanner.Text()+"\r\n")
  2599. for len(lines) > maxNumberOfLines {
  2600. lines = lines[1:]
  2601. }
  2602. }
  2603. if scanner.Err() != nil {
  2604. logger.WarnToConsole("Unable to print latest logs: %v", scanner.Err())
  2605. return
  2606. }
  2607. for _, line := range lines {
  2608. logger.DebugToConsole(line)
  2609. }
  2610. }