webdavd_test.go 105 KB

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