1
0

webdavd_test.go 105 KB

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