webdavd_test.go 106 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999
  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. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  550. assert.NoError(t, err)
  551. user.Password = defaultPassword
  552. user.ID = 0
  553. user.CreatedAt = 0
  554. _, resp, err := httpdtest.AddUser(user, http.StatusCreated)
  555. assert.NoError(t, err, string(resp))
  556. }
  557. }
  558. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  559. assert.NoError(t, err)
  560. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  561. assert.NoError(t, err)
  562. err = os.RemoveAll(localUser.GetHomeDir())
  563. assert.NoError(t, err)
  564. assert.Len(t, common.Connections.GetStats(), 0)
  565. status := webdavd.GetStatus()
  566. assert.True(t, status.IsActive)
  567. }
  568. func TestBasicHandlingCryptFs(t *testing.T) {
  569. u := getTestUserWithCryptFs()
  570. u.QuotaSize = 6553600
  571. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  572. assert.NoError(t, err)
  573. client := getWebDavClient(user, false, nil)
  574. assert.NoError(t, checkBasicFunc(client))
  575. testFilePath := filepath.Join(homeBasePath, testFileName)
  576. testFileSize := int64(65535)
  577. encryptedFileSize, err := getEncryptedFileSize(testFileSize)
  578. assert.NoError(t, err)
  579. expectedQuotaSize := user.UsedQuotaSize + encryptedFileSize
  580. expectedQuotaFiles := user.UsedQuotaFiles + 1
  581. err = createTestFile(testFilePath, testFileSize)
  582. assert.NoError(t, err)
  583. err = uploadFileWithRawClient(testFilePath, testFileName,
  584. user.Username, defaultPassword, false, testFileSize, client)
  585. assert.NoError(t, err)
  586. // overwrite an existing file
  587. err = uploadFileWithRawClient(testFilePath, testFileName,
  588. user.Username, defaultPassword, false, testFileSize, client)
  589. assert.NoError(t, err)
  590. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  591. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  592. assert.NoError(t, err)
  593. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  594. assert.NoError(t, err)
  595. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  596. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  597. files, err := client.ReadDir("/")
  598. assert.NoError(t, err)
  599. if assert.Len(t, files, 1) {
  600. assert.Equal(t, testFileSize, files[0].Size())
  601. }
  602. err = client.Remove(testFileName)
  603. assert.NoError(t, err)
  604. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  605. assert.NoError(t, err)
  606. assert.Equal(t, expectedQuotaFiles-1, user.UsedQuotaFiles)
  607. assert.Equal(t, expectedQuotaSize-encryptedFileSize, user.UsedQuotaSize)
  608. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  609. assert.Error(t, err)
  610. testDir := "testdir"
  611. err = client.Mkdir(testDir, os.ModePerm)
  612. assert.NoError(t, err)
  613. err = client.MkdirAll(path.Join(testDir, "sub", "sub"), os.ModePerm)
  614. assert.NoError(t, err)
  615. err = client.MkdirAll(path.Join(testDir, "sub1", "sub1"), os.ModePerm)
  616. assert.NoError(t, err)
  617. err = client.MkdirAll(path.Join(testDir, "sub2", "sub2"), os.ModePerm)
  618. assert.NoError(t, err)
  619. err = uploadFileWithRawClient(testFilePath, path.Join(testDir, testFileName+".txt"),
  620. user.Username, defaultPassword, false, testFileSize, client)
  621. assert.NoError(t, err)
  622. err = uploadFileWithRawClient(testFilePath, path.Join(testDir, testFileName),
  623. user.Username, defaultPassword, false, testFileSize, client)
  624. assert.NoError(t, err)
  625. files, err = client.ReadDir(testDir)
  626. assert.NoError(t, err)
  627. assert.Len(t, files, 5)
  628. for _, f := range files {
  629. if strings.HasPrefix(f.Name(), testFileName) {
  630. assert.Equal(t, testFileSize, f.Size())
  631. } else {
  632. assert.True(t, f.IsDir())
  633. }
  634. }
  635. err = os.Remove(testFilePath)
  636. assert.NoError(t, err)
  637. err = os.Remove(localDownloadPath)
  638. assert.NoError(t, err)
  639. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  640. assert.NoError(t, err)
  641. err = os.RemoveAll(user.GetHomeDir())
  642. assert.NoError(t, err)
  643. assert.Len(t, common.Connections.GetStats(), 0)
  644. }
  645. func TestLockAfterDelete(t *testing.T) {
  646. u := getTestUser()
  647. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  648. assert.NoError(t, err)
  649. client := getWebDavClient(user, false, nil)
  650. assert.NoError(t, checkBasicFunc(client))
  651. testFilePath := filepath.Join(homeBasePath, testFileName)
  652. testFileSize := int64(65535)
  653. err = createTestFile(testFilePath, testFileSize)
  654. assert.NoError(t, err)
  655. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  656. false, testFileSize, client)
  657. assert.NoError(t, err)
  658. 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>`
  659. req, err := http.NewRequest("LOCK", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(lockBody)))
  660. assert.NoError(t, err)
  661. req.SetBasicAuth(u.Username, u.Password)
  662. req.Header.Set("Timeout", "Second-3600")
  663. httpClient := httpclient.GetHTTPClient()
  664. resp, err := httpClient.Do(req)
  665. assert.NoError(t, err)
  666. assert.Equal(t, http.StatusOK, resp.StatusCode)
  667. response, err := io.ReadAll(resp.Body)
  668. assert.NoError(t, err)
  669. re := regexp.MustCompile(`\<D:locktoken><D:href>.*</D:href>`)
  670. lockToken := string(re.Find(response))
  671. lockToken = strings.Replace(lockToken, "<D:locktoken><D:href>", "", 1)
  672. lockToken = strings.Replace(lockToken, "</D:href>", "", 1)
  673. err = resp.Body.Close()
  674. assert.NoError(t, err)
  675. req, err = http.NewRequest(http.MethodDelete, fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), nil)
  676. assert.NoError(t, err)
  677. req.Header.Set("If", fmt.Sprintf("(%v)", lockToken))
  678. req.SetBasicAuth(u.Username, u.Password)
  679. resp, err = httpClient.Do(req)
  680. assert.NoError(t, err)
  681. assert.Equal(t, http.StatusNoContent, resp.StatusCode)
  682. err = resp.Body.Close()
  683. assert.NoError(t, err)
  684. // if we try to lock again it must succeed, the lock must be deleted with the object
  685. req, err = http.NewRequest("LOCK", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(lockBody)))
  686. assert.NoError(t, err)
  687. req.SetBasicAuth(u.Username, u.Password)
  688. resp, err = httpClient.Do(req)
  689. assert.NoError(t, err)
  690. assert.Equal(t, http.StatusCreated, resp.StatusCode)
  691. err = resp.Body.Close()
  692. assert.NoError(t, err)
  693. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  694. assert.NoError(t, err)
  695. err = os.RemoveAll(user.GetHomeDir())
  696. assert.NoError(t, err)
  697. }
  698. func TestRenameWithLock(t *testing.T) {
  699. u := getTestUser()
  700. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  701. assert.NoError(t, err)
  702. client := getWebDavClient(user, false, nil)
  703. assert.NoError(t, checkBasicFunc(client))
  704. testFilePath := filepath.Join(homeBasePath, testFileName)
  705. testFileSize := int64(65535)
  706. err = createTestFile(testFilePath, testFileSize)
  707. assert.NoError(t, err)
  708. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  709. false, testFileSize, client)
  710. assert.NoError(t, err)
  711. 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>`
  712. req, err := http.NewRequest("LOCK", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(lockBody)))
  713. assert.NoError(t, err)
  714. req.SetBasicAuth(u.Username, u.Password)
  715. httpClient := httpclient.GetHTTPClient()
  716. resp, err := httpClient.Do(req)
  717. assert.NoError(t, err)
  718. assert.Equal(t, http.StatusOK, resp.StatusCode)
  719. response, err := io.ReadAll(resp.Body)
  720. assert.NoError(t, err)
  721. re := regexp.MustCompile(`\<D:locktoken><D:href>.*</D:href>`)
  722. lockToken := string(re.Find(response))
  723. lockToken = strings.Replace(lockToken, "<D:locktoken><D:href>", "", 1)
  724. lockToken = strings.Replace(lockToken, "</D:href>", "", 1)
  725. err = resp.Body.Close()
  726. assert.NoError(t, err)
  727. // MOVE with a lock should succeeded
  728. req, err = http.NewRequest("MOVE", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), nil)
  729. assert.NoError(t, err)
  730. req.Header.Set("If", fmt.Sprintf("(%v)", lockToken))
  731. req.Header.Set("Overwrite", "T")
  732. req.Header.Set("Destination", path.Join("/", testFileName+"1"))
  733. req.SetBasicAuth(u.Username, u.Password)
  734. resp, err = httpClient.Do(req)
  735. assert.NoError(t, err)
  736. assert.Equal(t, http.StatusCreated, resp.StatusCode)
  737. err = resp.Body.Close()
  738. assert.NoError(t, err)
  739. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  740. assert.NoError(t, err)
  741. err = os.RemoveAll(user.GetHomeDir())
  742. assert.NoError(t, err)
  743. }
  744. func TestPropPatch(t *testing.T) {
  745. u := getTestUser()
  746. u.Username = u.Username + "1"
  747. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  748. assert.NoError(t, err)
  749. sftpUser := getTestSFTPUser()
  750. sftpUser.FsConfig.SFTPConfig.Username = localUser.Username
  751. for _, u := range []dataprovider.User{getTestUser(), getTestUserWithCryptFs(), sftpUser} {
  752. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  753. assert.NoError(t, err)
  754. client := getWebDavClient(user, true, nil)
  755. assert.NoError(t, checkBasicFunc(client), sftpUser.Username)
  756. testFilePath := filepath.Join(homeBasePath, testFileName)
  757. testFileSize := int64(65535)
  758. err = createTestFile(testFilePath, testFileSize)
  759. assert.NoError(t, err)
  760. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  761. false, testFileSize, client)
  762. assert.NoError(t, err)
  763. httpClient := httpclient.GetHTTPClient()
  764. 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>`
  765. req, err := http.NewRequest("PROPPATCH", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(propatchBody)))
  766. assert.NoError(t, err)
  767. req.SetBasicAuth(u.Username, u.Password)
  768. resp, err := httpClient.Do(req)
  769. assert.NoError(t, err)
  770. assert.Equal(t, 207, resp.StatusCode)
  771. err = resp.Body.Close()
  772. assert.NoError(t, err)
  773. info, err := client.Stat(testFileName)
  774. if assert.NoError(t, err) {
  775. assert.Equal(t, testFileSize, info.Size())
  776. }
  777. err = os.Remove(testFilePath)
  778. assert.NoError(t, err)
  779. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  780. assert.NoError(t, err)
  781. err = os.RemoveAll(user.GetHomeDir())
  782. assert.NoError(t, err)
  783. assert.Len(t, common.Connections.GetStats(), 0)
  784. }
  785. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  786. assert.NoError(t, err)
  787. err = os.RemoveAll(localUser.GetHomeDir())
  788. assert.NoError(t, err)
  789. }
  790. func TestLoginInvalidPwd(t *testing.T) {
  791. u := getTestUser()
  792. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  793. assert.NoError(t, err)
  794. client := getWebDavClient(user, false, nil)
  795. assert.NoError(t, checkBasicFunc(client))
  796. user.Password = "wrong"
  797. client = getWebDavClient(user, false, nil)
  798. assert.Error(t, checkBasicFunc(client))
  799. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  800. assert.NoError(t, err)
  801. }
  802. func TestLoginNonExistentUser(t *testing.T) {
  803. user := getTestUser()
  804. client := getWebDavClient(user, true, nil)
  805. assert.Error(t, checkBasicFunc(client))
  806. }
  807. func TestRateLimiter(t *testing.T) {
  808. oldConfig := config.GetCommonConfig()
  809. cfg := config.GetCommonConfig()
  810. cfg.RateLimitersConfig = []common.RateLimiterConfig{
  811. {
  812. Average: 1,
  813. Period: 1000,
  814. Burst: 3,
  815. Type: 1,
  816. Protocols: []string{common.ProtocolWebDAV},
  817. },
  818. }
  819. err := common.Initialize(cfg, 0)
  820. assert.NoError(t, err)
  821. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  822. assert.NoError(t, err)
  823. client := getWebDavClient(user, false, nil)
  824. assert.NoError(t, checkBasicFunc(client))
  825. _, err = client.ReadDir(".")
  826. if assert.Error(t, err) {
  827. assert.Contains(t, err.Error(), "429")
  828. }
  829. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  830. assert.NoError(t, err)
  831. err = os.RemoveAll(user.GetHomeDir())
  832. assert.NoError(t, err)
  833. err = common.Initialize(oldConfig, 0)
  834. assert.NoError(t, err)
  835. }
  836. func TestDefender(t *testing.T) {
  837. oldConfig := config.GetCommonConfig()
  838. cfg := config.GetCommonConfig()
  839. cfg.DefenderConfig.Enabled = true
  840. cfg.DefenderConfig.Threshold = 3
  841. cfg.DefenderConfig.ScoreLimitExceeded = 2
  842. err := common.Initialize(cfg, 0)
  843. assert.NoError(t, err)
  844. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  845. assert.NoError(t, err)
  846. client := getWebDavClient(user, true, nil)
  847. assert.NoError(t, checkBasicFunc(client))
  848. for i := 0; i < 3; i++ {
  849. user.Password = "wrong_pwd"
  850. client = getWebDavClient(user, false, nil)
  851. assert.Error(t, checkBasicFunc(client))
  852. }
  853. user.Password = defaultPassword
  854. client = getWebDavClient(user, true, nil)
  855. err = checkBasicFunc(client)
  856. if assert.Error(t, err) {
  857. assert.Contains(t, err.Error(), "403")
  858. }
  859. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  860. assert.NoError(t, err)
  861. err = os.RemoveAll(user.GetHomeDir())
  862. assert.NoError(t, err)
  863. err = common.Initialize(oldConfig, 0)
  864. assert.NoError(t, err)
  865. }
  866. func TestLoginExternalAuth(t *testing.T) {
  867. if runtime.GOOS == osWindows {
  868. t.Skip("this test is not available on Windows")
  869. }
  870. u := getTestUser()
  871. err := dataprovider.Close()
  872. assert.NoError(t, err)
  873. err = config.LoadConfig(configDir, "")
  874. assert.NoError(t, err)
  875. providerConf := config.GetProviderConf()
  876. err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, ""), os.ModePerm)
  877. assert.NoError(t, err)
  878. providerConf.ExternalAuthHook = extAuthPath
  879. providerConf.ExternalAuthScope = 0
  880. err = dataprovider.Initialize(providerConf, configDir, true)
  881. assert.NoError(t, err)
  882. client := getWebDavClient(u, false, nil)
  883. assert.NoError(t, checkBasicFunc(client))
  884. u.Username = defaultUsername + "1"
  885. client = getWebDavClient(u, false, nil)
  886. assert.Error(t, checkBasicFunc(client))
  887. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  888. assert.NoError(t, err)
  889. assert.Equal(t, defaultUsername, user.Username)
  890. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  891. assert.NoError(t, err)
  892. err = os.RemoveAll(user.GetHomeDir())
  893. assert.NoError(t, err)
  894. err = dataprovider.Close()
  895. assert.NoError(t, err)
  896. err = config.LoadConfig(configDir, "")
  897. assert.NoError(t, err)
  898. providerConf = config.GetProviderConf()
  899. err = dataprovider.Initialize(providerConf, configDir, true)
  900. assert.NoError(t, err)
  901. err = os.Remove(extAuthPath)
  902. assert.NoError(t, err)
  903. }
  904. func TestPreLoginHook(t *testing.T) {
  905. if runtime.GOOS == osWindows {
  906. t.Skip("this test is not available on Windows")
  907. }
  908. u := getTestUser()
  909. err := dataprovider.Close()
  910. assert.NoError(t, err)
  911. err = config.LoadConfig(configDir, "")
  912. assert.NoError(t, err)
  913. providerConf := config.GetProviderConf()
  914. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
  915. assert.NoError(t, err)
  916. providerConf.PreLoginHook = preLoginPath
  917. err = dataprovider.Initialize(providerConf, configDir, true)
  918. assert.NoError(t, err)
  919. _, _, err = httpdtest.GetUserByUsername(defaultUsername, http.StatusNotFound)
  920. assert.NoError(t, err)
  921. client := getWebDavClient(u, true, nil)
  922. assert.NoError(t, checkBasicFunc(client))
  923. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  924. assert.NoError(t, err)
  925. // test login with an existing user
  926. client = getWebDavClient(user, true, nil)
  927. assert.NoError(t, checkBasicFunc(client))
  928. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), os.ModePerm)
  929. assert.NoError(t, err)
  930. // update the user to remove it from the cache
  931. user.FsConfig.Provider = sdk.CryptedFilesystemProvider
  932. user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret(defaultPassword)
  933. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  934. assert.NoError(t, err)
  935. client = getWebDavClient(user, true, nil)
  936. assert.Error(t, checkBasicFunc(client))
  937. // update the user to remove it from the cache
  938. user.FsConfig.Provider = sdk.LocalFilesystemProvider
  939. user.FsConfig.CryptConfig.Passphrase = nil
  940. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  941. assert.NoError(t, err)
  942. user.Status = 0
  943. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), os.ModePerm)
  944. assert.NoError(t, err)
  945. client = getWebDavClient(user, true, nil)
  946. assert.Error(t, checkBasicFunc(client))
  947. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  948. assert.NoError(t, err)
  949. err = os.RemoveAll(user.GetHomeDir())
  950. assert.NoError(t, err)
  951. err = dataprovider.Close()
  952. assert.NoError(t, err)
  953. err = config.LoadConfig(configDir, "")
  954. assert.NoError(t, err)
  955. providerConf = config.GetProviderConf()
  956. err = dataprovider.Initialize(providerConf, configDir, true)
  957. assert.NoError(t, err)
  958. err = os.Remove(preLoginPath)
  959. assert.NoError(t, err)
  960. }
  961. func TestPreDownloadHook(t *testing.T) {
  962. if runtime.GOOS == osWindows {
  963. t.Skip("this test is not available on Windows")
  964. }
  965. oldExecuteOn := common.Config.Actions.ExecuteOn
  966. oldHook := common.Config.Actions.Hook
  967. common.Config.Actions.ExecuteOn = []string{common.OperationPreDownload}
  968. common.Config.Actions.Hook = preDownloadPath
  969. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  970. assert.NoError(t, err)
  971. err = os.WriteFile(preDownloadPath, getExitCodeScriptContent(0), os.ModePerm)
  972. assert.NoError(t, err)
  973. client := getWebDavClient(user, true, nil)
  974. assert.NoError(t, checkBasicFunc(client))
  975. testFilePath := filepath.Join(homeBasePath, testFileName)
  976. testFileSize := int64(65535)
  977. err = createTestFile(testFilePath, testFileSize)
  978. assert.NoError(t, err)
  979. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  980. true, testFileSize, client)
  981. assert.NoError(t, err)
  982. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  983. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  984. assert.NoError(t, err)
  985. err = os.Remove(localDownloadPath)
  986. assert.NoError(t, err)
  987. err = os.WriteFile(preDownloadPath, getExitCodeScriptContent(1), os.ModePerm)
  988. assert.NoError(t, err)
  989. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  990. assert.Error(t, err)
  991. err = os.Remove(localDownloadPath)
  992. assert.NoError(t, err)
  993. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  994. assert.NoError(t, err)
  995. err = os.RemoveAll(user.GetHomeDir())
  996. assert.NoError(t, err)
  997. assert.Len(t, common.Connections.GetStats(), 0)
  998. common.Config.Actions.ExecuteOn = []string{common.OperationPreDownload}
  999. common.Config.Actions.Hook = preDownloadPath
  1000. common.Config.Actions.ExecuteOn = oldExecuteOn
  1001. common.Config.Actions.Hook = oldHook
  1002. }
  1003. func TestPreUploadHook(t *testing.T) {
  1004. if runtime.GOOS == osWindows {
  1005. t.Skip("this test is not available on Windows")
  1006. }
  1007. oldExecuteOn := common.Config.Actions.ExecuteOn
  1008. oldHook := common.Config.Actions.Hook
  1009. common.Config.Actions.ExecuteOn = []string{common.OperationPreUpload}
  1010. common.Config.Actions.Hook = preUploadPath
  1011. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1012. assert.NoError(t, err)
  1013. err = os.WriteFile(preUploadPath, getExitCodeScriptContent(0), os.ModePerm)
  1014. assert.NoError(t, err)
  1015. client := getWebDavClient(user, true, nil)
  1016. assert.NoError(t, checkBasicFunc(client))
  1017. testFilePath := filepath.Join(homeBasePath, testFileName)
  1018. testFileSize := int64(65535)
  1019. err = createTestFile(testFilePath, testFileSize)
  1020. assert.NoError(t, err)
  1021. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1022. true, testFileSize, client)
  1023. assert.NoError(t, err)
  1024. err = os.WriteFile(preUploadPath, getExitCodeScriptContent(1), os.ModePerm)
  1025. assert.NoError(t, err)
  1026. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1027. true, testFileSize, client)
  1028. assert.Error(t, err)
  1029. err = uploadFileWithRawClient(testFilePath, testFileName+"1", user.Username, defaultPassword,
  1030. false, testFileSize, client)
  1031. assert.Error(t, err)
  1032. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1033. assert.NoError(t, err)
  1034. err = os.RemoveAll(user.GetHomeDir())
  1035. assert.NoError(t, err)
  1036. assert.Len(t, common.Connections.GetStats(), 0)
  1037. common.Config.Actions.ExecuteOn = oldExecuteOn
  1038. common.Config.Actions.Hook = oldHook
  1039. }
  1040. func TestPostConnectHook(t *testing.T) {
  1041. if runtime.GOOS == osWindows {
  1042. t.Skip("this test is not available on Windows")
  1043. }
  1044. common.Config.PostConnectHook = postConnectPath
  1045. u := getTestUser()
  1046. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1047. assert.NoError(t, err)
  1048. err = os.WriteFile(postConnectPath, getExitCodeScriptContent(0), os.ModePerm)
  1049. assert.NoError(t, err)
  1050. client := getWebDavClient(user, false, nil)
  1051. assert.NoError(t, checkBasicFunc(client))
  1052. err = os.WriteFile(postConnectPath, getExitCodeScriptContent(1), os.ModePerm)
  1053. assert.NoError(t, err)
  1054. assert.Error(t, checkBasicFunc(client))
  1055. common.Config.PostConnectHook = "http://127.0.0.1:8078/healthz"
  1056. assert.NoError(t, checkBasicFunc(client))
  1057. common.Config.PostConnectHook = "http://127.0.0.1:8078/notfound"
  1058. assert.Error(t, checkBasicFunc(client))
  1059. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1060. assert.NoError(t, err)
  1061. err = os.RemoveAll(user.GetHomeDir())
  1062. assert.NoError(t, err)
  1063. common.Config.PostConnectHook = ""
  1064. }
  1065. func TestMaxConnections(t *testing.T) {
  1066. oldValue := common.Config.MaxTotalConnections
  1067. common.Config.MaxTotalConnections = 1
  1068. assert.Eventually(t, func() bool {
  1069. return common.Connections.GetClientConnections() == 0
  1070. }, 1000*time.Millisecond, 50*time.Millisecond)
  1071. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1072. assert.NoError(t, err)
  1073. client := getWebDavClient(user, true, nil)
  1074. assert.NoError(t, checkBasicFunc(client))
  1075. // now add a fake connection
  1076. fs := vfs.NewOsFs("id", os.TempDir(), "")
  1077. connection := &webdavd.Connection{
  1078. BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
  1079. }
  1080. common.Connections.Add(connection)
  1081. assert.Error(t, checkBasicFunc(client))
  1082. common.Connections.Remove(connection.GetID())
  1083. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1084. assert.NoError(t, err)
  1085. err = os.RemoveAll(user.GetHomeDir())
  1086. assert.NoError(t, err)
  1087. assert.Len(t, common.Connections.GetStats(), 0)
  1088. common.Config.MaxTotalConnections = oldValue
  1089. }
  1090. func TestMaxPerHostConnections(t *testing.T) {
  1091. oldValue := common.Config.MaxPerHostConnections
  1092. common.Config.MaxPerHostConnections = 1
  1093. assert.Eventually(t, func() bool {
  1094. return common.Connections.GetClientConnections() == 0
  1095. }, 1000*time.Millisecond, 50*time.Millisecond)
  1096. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1097. assert.NoError(t, err)
  1098. client := getWebDavClient(user, true, nil)
  1099. assert.NoError(t, checkBasicFunc(client))
  1100. // now add a fake connection
  1101. addrs, err := net.LookupHost("localhost")
  1102. assert.NoError(t, err)
  1103. for _, addr := range addrs {
  1104. common.Connections.AddClientConnection(addr)
  1105. }
  1106. assert.Error(t, checkBasicFunc(client))
  1107. for _, addr := range addrs {
  1108. common.Connections.RemoveClientConnection(addr)
  1109. }
  1110. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1111. assert.NoError(t, err)
  1112. err = os.RemoveAll(user.GetHomeDir())
  1113. assert.NoError(t, err)
  1114. assert.Len(t, common.Connections.GetStats(), 0)
  1115. common.Config.MaxPerHostConnections = oldValue
  1116. }
  1117. func TestMaxSessions(t *testing.T) {
  1118. u := getTestUser()
  1119. u.MaxSessions = 1
  1120. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1121. assert.NoError(t, err)
  1122. client := getWebDavClient(user, false, nil)
  1123. assert.NoError(t, checkBasicFunc(client))
  1124. // now add a fake connection
  1125. fs := vfs.NewOsFs("id", os.TempDir(), "")
  1126. connection := &webdavd.Connection{
  1127. BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
  1128. }
  1129. common.Connections.Add(connection)
  1130. assert.Error(t, checkBasicFunc(client))
  1131. common.Connections.Remove(connection.GetID())
  1132. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1133. assert.NoError(t, err)
  1134. err = os.RemoveAll(user.GetHomeDir())
  1135. assert.NoError(t, err)
  1136. assert.Len(t, common.Connections.GetStats(), 0)
  1137. }
  1138. func TestLoginWithIPilters(t *testing.T) {
  1139. u := getTestUser()
  1140. u.Filters.DeniedIP = []string{"192.167.0.0/24", "172.18.0.0/16"}
  1141. u.Filters.AllowedIP = []string{"172.19.0.0/16"}
  1142. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1143. assert.NoError(t, err)
  1144. client := getWebDavClient(user, true, nil)
  1145. assert.Error(t, checkBasicFunc(client))
  1146. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1147. assert.NoError(t, err)
  1148. err = os.RemoveAll(user.GetHomeDir())
  1149. assert.NoError(t, err)
  1150. }
  1151. func TestDownloadErrors(t *testing.T) {
  1152. u := getTestUser()
  1153. u.QuotaFiles = 1
  1154. subDir1 := "sub1"
  1155. subDir2 := "sub2"
  1156. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems}
  1157. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  1158. dataprovider.PermDelete, dataprovider.PermDownload}
  1159. // use an unknown mime to trigger content type detection
  1160. u.Filters.FilePatterns = []sdk.PatternsFilter{
  1161. {
  1162. Path: "/sub2",
  1163. AllowedPatterns: []string{},
  1164. DeniedPatterns: []string{"*.jpg", "*.zipp"},
  1165. },
  1166. }
  1167. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1168. assert.NoError(t, err)
  1169. client := getWebDavClient(user, false, nil)
  1170. testFilePath1 := filepath.Join(user.HomeDir, subDir1, "file.zipp")
  1171. testFilePath2 := filepath.Join(user.HomeDir, subDir2, "file.zipp")
  1172. testFilePath3 := filepath.Join(user.HomeDir, subDir2, "file.jpg")
  1173. err = os.MkdirAll(filepath.Dir(testFilePath1), os.ModePerm)
  1174. assert.NoError(t, err)
  1175. err = os.MkdirAll(filepath.Dir(testFilePath2), os.ModePerm)
  1176. assert.NoError(t, err)
  1177. err = os.WriteFile(testFilePath1, []byte("file1"), os.ModePerm)
  1178. assert.NoError(t, err)
  1179. err = os.WriteFile(testFilePath2, []byte("file2"), os.ModePerm)
  1180. assert.NoError(t, err)
  1181. err = os.WriteFile(testFilePath3, []byte("file3"), os.ModePerm)
  1182. assert.NoError(t, err)
  1183. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1184. err = downloadFile(path.Join("/", subDir1, "file.zipp"), localDownloadPath, 5, client)
  1185. assert.Error(t, err)
  1186. err = downloadFile(path.Join("/", subDir2, "file.zipp"), localDownloadPath, 5, client)
  1187. assert.Error(t, err)
  1188. err = downloadFile(path.Join("/", subDir2, "file.jpg"), localDownloadPath, 5, client)
  1189. assert.Error(t, err)
  1190. err = downloadFile(path.Join("missing.zip"), localDownloadPath, 5, client)
  1191. assert.Error(t, err)
  1192. err = os.Remove(localDownloadPath)
  1193. assert.NoError(t, err)
  1194. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1195. assert.NoError(t, err)
  1196. err = os.RemoveAll(user.GetHomeDir())
  1197. assert.NoError(t, err)
  1198. }
  1199. func TestUploadErrors(t *testing.T) {
  1200. u := getTestUser()
  1201. u.QuotaSize = 65535
  1202. subDir1 := "sub1"
  1203. subDir2 := "sub2"
  1204. // we need download permission to get size since PROPFIND will open the file
  1205. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems, dataprovider.PermDownload}
  1206. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  1207. dataprovider.PermDelete, dataprovider.PermDownload}
  1208. u.Filters.FilePatterns = []sdk.PatternsFilter{
  1209. {
  1210. Path: "/sub2",
  1211. AllowedPatterns: []string{},
  1212. DeniedPatterns: []string{"*.zip"},
  1213. },
  1214. }
  1215. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1216. assert.NoError(t, err)
  1217. client := getWebDavClient(user, true, nil)
  1218. testFilePath := filepath.Join(homeBasePath, testFileName)
  1219. testFileSize := user.QuotaSize
  1220. err = createTestFile(testFilePath, testFileSize)
  1221. assert.NoError(t, err)
  1222. err = client.Mkdir(subDir1, os.ModePerm)
  1223. assert.NoError(t, err)
  1224. err = client.Mkdir(subDir2, os.ModePerm)
  1225. assert.NoError(t, err)
  1226. err = uploadFileWithRawClient(testFilePath, path.Join(subDir1, testFileName), user.Username,
  1227. defaultPassword, true, testFileSize, client)
  1228. assert.Error(t, err)
  1229. err = uploadFileWithRawClient(testFilePath, path.Join(subDir2, testFileName+".zip"), user.Username,
  1230. defaultPassword, true, testFileSize, client)
  1231. assert.Error(t, err)
  1232. err = uploadFileWithRawClient(testFilePath, path.Join(subDir2, testFileName), user.Username,
  1233. defaultPassword, true, testFileSize, client)
  1234. assert.NoError(t, err)
  1235. err = client.Rename(path.Join(subDir2, testFileName), path.Join(subDir1, testFileName), false)
  1236. assert.Error(t, err)
  1237. err = uploadFileWithRawClient(testFilePath, path.Join(subDir2, testFileName), user.Username,
  1238. defaultPassword, true, testFileSize, client)
  1239. assert.Error(t, err)
  1240. err = uploadFileWithRawClient(testFilePath, subDir1, user.Username,
  1241. defaultPassword, true, testFileSize, client)
  1242. assert.Error(t, err)
  1243. // overquota
  1244. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1245. true, testFileSize, client)
  1246. assert.Error(t, err)
  1247. err = client.Remove(path.Join(subDir2, testFileName))
  1248. assert.NoError(t, err)
  1249. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1250. true, testFileSize, client)
  1251. assert.NoError(t, err)
  1252. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1253. true, testFileSize, client)
  1254. assert.Error(t, err)
  1255. err = os.Remove(testFilePath)
  1256. assert.NoError(t, err)
  1257. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1258. assert.NoError(t, err)
  1259. err = os.RemoveAll(user.GetHomeDir())
  1260. assert.NoError(t, err)
  1261. }
  1262. func TestDeniedLoginMethod(t *testing.T) {
  1263. u := getTestUser()
  1264. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword}
  1265. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1266. assert.NoError(t, err)
  1267. client := getWebDavClient(user, true, nil)
  1268. assert.Error(t, checkBasicFunc(client))
  1269. user.Filters.DeniedLoginMethods = []string{dataprovider.SSHLoginMethodPublicKey, dataprovider.SSHLoginMethodKeyAndKeyboardInt}
  1270. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1271. assert.NoError(t, err)
  1272. client = getWebDavClient(user, true, nil)
  1273. assert.NoError(t, checkBasicFunc(client))
  1274. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1275. assert.NoError(t, err)
  1276. err = os.RemoveAll(user.GetHomeDir())
  1277. assert.NoError(t, err)
  1278. }
  1279. func TestDeniedProtocols(t *testing.T) {
  1280. u := getTestUser()
  1281. u.Filters.DeniedProtocols = []string{common.ProtocolWebDAV}
  1282. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1283. assert.NoError(t, err)
  1284. client := getWebDavClient(user, false, nil)
  1285. assert.Error(t, checkBasicFunc(client))
  1286. user.Filters.DeniedProtocols = []string{common.ProtocolSSH, common.ProtocolFTP}
  1287. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1288. assert.NoError(t, err)
  1289. client = getWebDavClient(user, false, nil)
  1290. assert.NoError(t, checkBasicFunc(client))
  1291. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1292. assert.NoError(t, err)
  1293. err = os.RemoveAll(user.GetHomeDir())
  1294. assert.NoError(t, err)
  1295. }
  1296. func TestQuotaLimits(t *testing.T) {
  1297. u := getTestUser()
  1298. u.QuotaFiles = 1
  1299. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1300. assert.NoError(t, err)
  1301. u = getTestSFTPUser()
  1302. u.QuotaFiles = 1
  1303. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1304. assert.NoError(t, err)
  1305. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1306. testFileSize := int64(65536)
  1307. testFilePath := filepath.Join(homeBasePath, testFileName)
  1308. err = createTestFile(testFilePath, testFileSize)
  1309. assert.NoError(t, err)
  1310. testFileSize1 := int64(131072)
  1311. testFileName1 := "test_file1.dat"
  1312. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  1313. err = createTestFile(testFilePath1, testFileSize1)
  1314. assert.NoError(t, err)
  1315. testFileSize2 := int64(32768)
  1316. testFileName2 := "test_file2.dat"
  1317. testFilePath2 := filepath.Join(homeBasePath, testFileName2)
  1318. err = createTestFile(testFilePath2, testFileSize2)
  1319. assert.NoError(t, err)
  1320. client := getWebDavClient(user, false, nil)
  1321. // test quota files
  1322. err = uploadFileWithRawClient(testFilePath, testFileName+".quota", user.Username, defaultPassword, false,
  1323. testFileSize, client)
  1324. if !assert.NoError(t, err, "username: %v", user.Username) {
  1325. info, err := os.Stat(testFilePath)
  1326. if assert.NoError(t, err) {
  1327. fmt.Printf("local file size: %v\n", info.Size())
  1328. }
  1329. printLatestLogs(20)
  1330. }
  1331. err = uploadFileWithRawClient(testFilePath, testFileName+".quota1", user.Username, defaultPassword,
  1332. false, testFileSize, client)
  1333. assert.Error(t, err, "username: %v", user.Username)
  1334. err = client.Rename(testFileName+".quota", testFileName, false)
  1335. assert.NoError(t, err)
  1336. files, err := client.ReadDir("/")
  1337. assert.NoError(t, err)
  1338. assert.Len(t, files, 1)
  1339. // test quota size
  1340. user.QuotaSize = testFileSize - 1
  1341. user.QuotaFiles = 0
  1342. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1343. assert.NoError(t, err)
  1344. err = uploadFileWithRawClient(testFilePath, testFileName+".quota", user.Username, defaultPassword,
  1345. false, testFileSize, client)
  1346. assert.Error(t, err)
  1347. err = client.Rename(testFileName, testFileName+".quota", false)
  1348. assert.NoError(t, err)
  1349. // now test quota limits while uploading the current file, we have 1 bytes remaining
  1350. user.QuotaSize = testFileSize + 1
  1351. user.QuotaFiles = 0
  1352. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1353. assert.NoError(t, err)
  1354. err = uploadFileWithRawClient(testFilePath1, testFileName1, user.Username, defaultPassword,
  1355. false, testFileSize1, client)
  1356. assert.Error(t, err)
  1357. _, err = client.Stat(testFileName1)
  1358. assert.Error(t, err)
  1359. err = client.Rename(testFileName+".quota", testFileName, false)
  1360. assert.NoError(t, err)
  1361. // overwriting an existing file will work if the resulting size is lesser or equal than the current one
  1362. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1363. false, testFileSize, client)
  1364. assert.NoError(t, err)
  1365. err = uploadFileWithRawClient(testFilePath2, testFileName, user.Username, defaultPassword,
  1366. false, testFileSize2, client)
  1367. assert.NoError(t, err)
  1368. err = uploadFileWithRawClient(testFilePath1, testFileName, user.Username, defaultPassword,
  1369. false, testFileSize1, client)
  1370. assert.Error(t, err)
  1371. err = uploadFileWithRawClient(testFilePath2, testFileName, user.Username, defaultPassword,
  1372. false, testFileSize2, client)
  1373. assert.NoError(t, err)
  1374. err = os.Remove(testFilePath)
  1375. assert.NoError(t, err)
  1376. err = os.Remove(testFilePath1)
  1377. assert.NoError(t, err)
  1378. err = os.Remove(testFilePath2)
  1379. assert.NoError(t, err)
  1380. if user.Username == defaultUsername {
  1381. err = os.RemoveAll(user.GetHomeDir())
  1382. assert.NoError(t, err)
  1383. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1384. assert.NoError(t, err)
  1385. user.Password = defaultPassword
  1386. user.ID = 0
  1387. user.CreatedAt = 0
  1388. user.QuotaFiles = 0
  1389. user.QuotaSize = 0
  1390. _, resp, err := httpdtest.AddUser(user, http.StatusCreated)
  1391. assert.NoError(t, err, string(resp))
  1392. }
  1393. }
  1394. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1395. assert.NoError(t, err)
  1396. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1397. assert.NoError(t, err)
  1398. err = os.RemoveAll(localUser.GetHomeDir())
  1399. assert.NoError(t, err)
  1400. }
  1401. func TestTransferQuotaLimits(t *testing.T) {
  1402. u := getTestUser()
  1403. u.DownloadDataTransfer = 1
  1404. u.UploadDataTransfer = 1
  1405. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1406. assert.NoError(t, err)
  1407. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1408. testFilePath := filepath.Join(homeBasePath, testFileName)
  1409. testFileSize := int64(550000)
  1410. err = createTestFile(testFilePath, testFileSize)
  1411. assert.NoError(t, err)
  1412. client := getWebDavClient(user, false, nil)
  1413. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1414. false, testFileSize, client)
  1415. assert.NoError(t, err)
  1416. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1417. assert.NoError(t, err)
  1418. // error while download is active
  1419. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1420. assert.Error(t, err)
  1421. // error before starting the download
  1422. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1423. assert.Error(t, err)
  1424. // error while upload is active
  1425. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1426. false, testFileSize, client)
  1427. assert.Error(t, err)
  1428. // error before starting the upload
  1429. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1430. false, testFileSize, client)
  1431. assert.Error(t, err)
  1432. err = os.Remove(localDownloadPath)
  1433. assert.NoError(t, err)
  1434. err = os.Remove(testFilePath)
  1435. assert.NoError(t, err)
  1436. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1437. assert.NoError(t, err)
  1438. err = os.RemoveAll(user.GetHomeDir())
  1439. assert.NoError(t, err)
  1440. }
  1441. func TestUploadMaxSize(t *testing.T) {
  1442. testFileSize := int64(65535)
  1443. u := getTestUser()
  1444. u.Filters.MaxUploadFileSize = testFileSize + 1
  1445. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1446. assert.NoError(t, err)
  1447. u = getTestSFTPUser()
  1448. u.Filters.MaxUploadFileSize = testFileSize + 1
  1449. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1450. assert.NoError(t, err)
  1451. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1452. testFilePath := filepath.Join(homeBasePath, testFileName)
  1453. err = createTestFile(testFilePath, testFileSize)
  1454. assert.NoError(t, err)
  1455. testFileSize1 := int64(131072)
  1456. testFileName1 := "test_file_dav1.dat"
  1457. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  1458. err = createTestFile(testFilePath1, testFileSize1)
  1459. assert.NoError(t, err)
  1460. client := getWebDavClient(user, false, nil)
  1461. err = uploadFileWithRawClient(testFilePath1, testFileName1, user.Username, defaultPassword,
  1462. false, testFileSize1, client)
  1463. assert.Error(t, err)
  1464. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1465. false, testFileSize, client)
  1466. assert.NoError(t, err)
  1467. // now test overwrite an existing file with a size bigger than the allowed one
  1468. err = createTestFile(filepath.Join(user.GetHomeDir(), testFileName1), testFileSize1)
  1469. assert.NoError(t, err)
  1470. err = uploadFileWithRawClient(testFilePath1, testFileName1, user.Username, defaultPassword,
  1471. false, testFileSize1, client)
  1472. assert.Error(t, err)
  1473. err = os.Remove(testFilePath)
  1474. assert.NoError(t, err)
  1475. err = os.Remove(testFilePath1)
  1476. assert.NoError(t, err)
  1477. if user.Username == defaultUsername {
  1478. err = os.RemoveAll(user.GetHomeDir())
  1479. assert.NoError(t, err)
  1480. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1481. assert.NoError(t, err)
  1482. user.Filters.MaxUploadFileSize = 65536000
  1483. user.Password = defaultPassword
  1484. user.ID = 0
  1485. user.CreatedAt = 0
  1486. _, resp, err := httpdtest.AddUser(user, http.StatusCreated)
  1487. assert.NoError(t, err, string(resp))
  1488. }
  1489. }
  1490. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1491. assert.NoError(t, err)
  1492. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1493. assert.NoError(t, err)
  1494. err = os.RemoveAll(localUser.GetHomeDir())
  1495. assert.NoError(t, err)
  1496. }
  1497. func TestClientClose(t *testing.T) {
  1498. u := getTestUser()
  1499. u.UploadBandwidth = 64
  1500. u.DownloadBandwidth = 64
  1501. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1502. assert.NoError(t, err)
  1503. u = getTestSFTPUser()
  1504. u.UploadBandwidth = 64
  1505. u.DownloadBandwidth = 64
  1506. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1507. assert.NoError(t, err)
  1508. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1509. testFileSize := int64(1048576)
  1510. testFilePath := filepath.Join(homeBasePath, testFileName)
  1511. err = createTestFile(testFilePath, testFileSize)
  1512. assert.NoError(t, err)
  1513. client := getWebDavClient(user, true, nil)
  1514. assert.NoError(t, checkBasicFunc(client))
  1515. var wg sync.WaitGroup
  1516. wg.Add(1)
  1517. go func() {
  1518. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1519. true, testFileSize, client)
  1520. assert.Error(t, err)
  1521. wg.Done()
  1522. }()
  1523. assert.Eventually(t, func() bool {
  1524. for _, stat := range common.Connections.GetStats() {
  1525. if len(stat.Transfers) > 0 {
  1526. return true
  1527. }
  1528. }
  1529. return false
  1530. }, 1*time.Second, 50*time.Millisecond)
  1531. for _, stat := range common.Connections.GetStats() {
  1532. common.Connections.Close(stat.ConnectionID)
  1533. }
  1534. wg.Wait()
  1535. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 },
  1536. 1*time.Second, 100*time.Millisecond)
  1537. err = os.Remove(testFilePath)
  1538. assert.NoError(t, err)
  1539. testFilePath = filepath.Join(user.HomeDir, testFileName)
  1540. err = createTestFile(testFilePath, testFileSize)
  1541. assert.NoError(t, err)
  1542. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1543. wg.Add(1)
  1544. go func() {
  1545. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1546. assert.Error(t, err)
  1547. wg.Done()
  1548. }()
  1549. assert.Eventually(t, func() bool {
  1550. for _, stat := range common.Connections.GetStats() {
  1551. if len(stat.Transfers) > 0 {
  1552. return true
  1553. }
  1554. }
  1555. return false
  1556. }, 1*time.Second, 50*time.Millisecond)
  1557. for _, stat := range common.Connections.GetStats() {
  1558. common.Connections.Close(stat.ConnectionID)
  1559. }
  1560. wg.Wait()
  1561. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 },
  1562. 1*time.Second, 100*time.Millisecond)
  1563. err = os.Remove(localDownloadPath)
  1564. assert.NoError(t, err)
  1565. }
  1566. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1567. assert.NoError(t, err)
  1568. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1569. assert.NoError(t, err)
  1570. err = os.RemoveAll(localUser.GetHomeDir())
  1571. assert.NoError(t, err)
  1572. }
  1573. func TestLoginWithDatabaseCredentials(t *testing.T) {
  1574. u := getTestUser()
  1575. u.FsConfig.Provider = sdk.GCSFilesystemProvider
  1576. u.FsConfig.GCSConfig.Bucket = "test"
  1577. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret(`{ "type": "service_account" }`)
  1578. providerConf := config.GetProviderConf()
  1579. providerConf.PreferDatabaseCredentials = true
  1580. credentialsFile := filepath.Join(providerConf.CredentialsPath, fmt.Sprintf("%v_gcs_credentials.json", u.Username))
  1581. if !filepath.IsAbs(credentialsFile) {
  1582. credentialsFile = filepath.Join(configDir, credentialsFile)
  1583. }
  1584. assert.NoError(t, dataprovider.Close())
  1585. err := dataprovider.Initialize(providerConf, configDir, true)
  1586. assert.NoError(t, err)
  1587. if _, err = os.Stat(credentialsFile); err == nil {
  1588. // remove the credentials file
  1589. assert.NoError(t, os.Remove(credentialsFile))
  1590. }
  1591. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1592. assert.NoError(t, err)
  1593. assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.GCSConfig.Credentials.GetStatus())
  1594. assert.NotEmpty(t, user.FsConfig.GCSConfig.Credentials.GetPayload())
  1595. assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetAdditionalData())
  1596. assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetKey())
  1597. assert.NoFileExists(t, credentialsFile)
  1598. client := getWebDavClient(user, false, nil)
  1599. err = client.Connect()
  1600. assert.NoError(t, err)
  1601. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1602. assert.NoError(t, err)
  1603. err = os.RemoveAll(user.GetHomeDir())
  1604. assert.NoError(t, err)
  1605. assert.NoError(t, dataprovider.Close())
  1606. assert.NoError(t, config.LoadConfig(configDir, ""))
  1607. providerConf = config.GetProviderConf()
  1608. assert.NoError(t, dataprovider.Initialize(providerConf, configDir, true))
  1609. }
  1610. func TestLoginInvalidFs(t *testing.T) {
  1611. u := getTestUser()
  1612. u.FsConfig.Provider = sdk.GCSFilesystemProvider
  1613. u.FsConfig.GCSConfig.Bucket = "test"
  1614. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("invalid JSON for credentials")
  1615. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1616. assert.NoError(t, err)
  1617. providerConf := config.GetProviderConf()
  1618. credentialsFile := filepath.Join(providerConf.CredentialsPath, fmt.Sprintf("%v_gcs_credentials.json", u.Username))
  1619. if !filepath.IsAbs(credentialsFile) {
  1620. credentialsFile = filepath.Join(configDir, credentialsFile)
  1621. }
  1622. // now remove the credentials file so the filesystem creation will fail
  1623. err = os.Remove(credentialsFile)
  1624. assert.NoError(t, err)
  1625. client := getWebDavClient(user, true, nil)
  1626. assert.Error(t, checkBasicFunc(client))
  1627. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1628. assert.NoError(t, err)
  1629. err = os.RemoveAll(user.GetHomeDir())
  1630. assert.NoError(t, err)
  1631. }
  1632. func TestSFTPBuffered(t *testing.T) {
  1633. u := getTestUser()
  1634. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1635. assert.NoError(t, err)
  1636. u = getTestSFTPUser()
  1637. u.QuotaFiles = 1000
  1638. u.HomeDir = filepath.Join(os.TempDir(), u.Username)
  1639. u.FsConfig.SFTPConfig.BufferSize = 2
  1640. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1641. assert.NoError(t, err)
  1642. client := getWebDavClient(sftpUser, true, nil)
  1643. assert.NoError(t, checkBasicFunc(client))
  1644. testFilePath := filepath.Join(homeBasePath, testFileName)
  1645. testFileSize := int64(65535)
  1646. expectedQuotaSize := testFileSize
  1647. expectedQuotaFiles := 1
  1648. err = createTestFile(testFilePath, testFileSize)
  1649. assert.NoError(t, err)
  1650. err = uploadFileWithRawClient(testFilePath, testFileName, sftpUser.Username, defaultPassword,
  1651. true, testFileSize, client)
  1652. assert.NoError(t, err)
  1653. // overwrite an existing file
  1654. err = uploadFileWithRawClient(testFilePath, testFileName, sftpUser.Username, defaultPassword,
  1655. true, testFileSize, client)
  1656. assert.NoError(t, err)
  1657. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1658. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1659. assert.NoError(t, err)
  1660. user, _, err := httpdtest.GetUserByUsername(sftpUser.Username, http.StatusOK)
  1661. assert.NoError(t, err)
  1662. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  1663. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  1664. fileContent := []byte("test file contents")
  1665. err = os.WriteFile(testFilePath, fileContent, os.ModePerm)
  1666. assert.NoError(t, err)
  1667. err = uploadFileWithRawClient(testFilePath, testFileName, sftpUser.Username, defaultPassword,
  1668. true, int64(len(fileContent)), client)
  1669. assert.NoError(t, err)
  1670. remotePath := fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName)
  1671. req, err := http.NewRequest(http.MethodGet, remotePath, nil)
  1672. assert.NoError(t, err)
  1673. httpClient := httpclient.GetHTTPClient()
  1674. req.SetBasicAuth(user.Username, defaultPassword)
  1675. req.Header.Set("Range", "bytes=5-")
  1676. resp, err := httpClient.Do(req)
  1677. if assert.NoError(t, err) {
  1678. defer resp.Body.Close()
  1679. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  1680. bodyBytes, err := io.ReadAll(resp.Body)
  1681. assert.NoError(t, err)
  1682. assert.Equal(t, "file contents", string(bodyBytes))
  1683. }
  1684. req.Header.Set("Range", "bytes=5-8")
  1685. resp, err = httpClient.Do(req)
  1686. if assert.NoError(t, err) {
  1687. defer resp.Body.Close()
  1688. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  1689. bodyBytes, err := io.ReadAll(resp.Body)
  1690. assert.NoError(t, err)
  1691. assert.Equal(t, "file", string(bodyBytes))
  1692. }
  1693. err = os.Remove(testFilePath)
  1694. assert.NoError(t, err)
  1695. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1696. assert.NoError(t, err)
  1697. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1698. assert.NoError(t, err)
  1699. err = os.RemoveAll(localUser.GetHomeDir())
  1700. assert.NoError(t, err)
  1701. err = os.RemoveAll(sftpUser.GetHomeDir())
  1702. assert.NoError(t, err)
  1703. }
  1704. func TestBytesRangeRequests(t *testing.T) {
  1705. u := getTestUser()
  1706. u.Username = u.Username + "1"
  1707. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1708. assert.NoError(t, err)
  1709. sftpUser := getTestSFTPUser()
  1710. sftpUser.FsConfig.SFTPConfig.Username = localUser.Username
  1711. for _, u := range []dataprovider.User{getTestUser(), getTestUserWithCryptFs(), sftpUser} {
  1712. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1713. assert.NoError(t, err)
  1714. testFileName := "test_file.txt"
  1715. testFilePath := filepath.Join(homeBasePath, testFileName)
  1716. fileContent := []byte("test file contents")
  1717. err = os.WriteFile(testFilePath, fileContent, os.ModePerm)
  1718. assert.NoError(t, err)
  1719. client := getWebDavClient(user, true, nil)
  1720. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1721. true, int64(len(fileContent)), client)
  1722. assert.NoError(t, err)
  1723. remotePath := fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName)
  1724. req, err := http.NewRequest(http.MethodGet, remotePath, nil)
  1725. if assert.NoError(t, err) {
  1726. httpClient := httpclient.GetHTTPClient()
  1727. req.SetBasicAuth(user.Username, defaultPassword)
  1728. req.Header.Set("Range", "bytes=5-")
  1729. resp, err := httpClient.Do(req)
  1730. if assert.NoError(t, err) {
  1731. defer resp.Body.Close()
  1732. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  1733. bodyBytes, err := io.ReadAll(resp.Body)
  1734. assert.NoError(t, err)
  1735. assert.Equal(t, "file contents", string(bodyBytes))
  1736. }
  1737. req.Header.Set("Range", "bytes=5-8")
  1738. resp, err = httpClient.Do(req)
  1739. if assert.NoError(t, err) {
  1740. defer resp.Body.Close()
  1741. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  1742. bodyBytes, err := io.ReadAll(resp.Body)
  1743. assert.NoError(t, err)
  1744. assert.Equal(t, "file", string(bodyBytes))
  1745. }
  1746. }
  1747. err = os.Remove(testFilePath)
  1748. assert.NoError(t, err)
  1749. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1750. assert.NoError(t, err)
  1751. err = os.RemoveAll(user.GetHomeDir())
  1752. assert.NoError(t, err)
  1753. }
  1754. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1755. assert.NoError(t, err)
  1756. err = os.RemoveAll(localUser.GetHomeDir())
  1757. assert.NoError(t, err)
  1758. }
  1759. func TestHEAD(t *testing.T) {
  1760. u := getTestUser()
  1761. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1762. assert.NoError(t, err)
  1763. rootPath := fmt.Sprintf("http://%v", webDavServerAddr)
  1764. httpClient := httpclient.GetHTTPClient()
  1765. req, err := http.NewRequest(http.MethodHead, rootPath, nil)
  1766. if assert.NoError(t, err) {
  1767. req.SetBasicAuth(u.Username, u.Password)
  1768. resp, err := httpClient.Do(req)
  1769. if assert.NoError(t, err) {
  1770. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  1771. assert.Equal(t, "text/xml; charset=utf-8", resp.Header.Get("Content-Type"))
  1772. resp.Body.Close()
  1773. }
  1774. }
  1775. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1776. assert.NoError(t, err)
  1777. err = os.RemoveAll(user.GetHomeDir())
  1778. assert.NoError(t, err)
  1779. }
  1780. func TestGETAsPROPFIND(t *testing.T) {
  1781. u := getTestUser()
  1782. subDir1 := "/sub1"
  1783. u.Permissions[subDir1] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs}
  1784. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1785. assert.NoError(t, err)
  1786. rootPath := fmt.Sprintf("http://%v/", webDavServerAddr)
  1787. httpClient := httpclient.GetHTTPClient()
  1788. req, err := http.NewRequest(http.MethodGet, rootPath, nil)
  1789. if assert.NoError(t, err) {
  1790. req.SetBasicAuth(u.Username, u.Password)
  1791. resp, err := httpClient.Do(req)
  1792. if assert.NoError(t, err) {
  1793. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  1794. resp.Body.Close()
  1795. }
  1796. }
  1797. client := getWebDavClient(user, false, nil)
  1798. err = client.MkdirAll(path.Join(subDir1, "sub", "sub1"), os.ModePerm)
  1799. assert.NoError(t, err)
  1800. subPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, subDir1)
  1801. req, err = http.NewRequest(http.MethodGet, subPath, nil)
  1802. if assert.NoError(t, err) {
  1803. req.SetBasicAuth(u.Username, u.Password)
  1804. resp, err := httpClient.Do(req)
  1805. if assert.NoError(t, err) {
  1806. // before the performance patch we have a 500 here, now we have 207 but an empty list
  1807. //assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
  1808. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  1809. resp.Body.Close()
  1810. }
  1811. }
  1812. // we cannot stat the sub at all
  1813. subPath1 := fmt.Sprintf("http://%v/%v", webDavServerAddr, path.Join(subDir1, "sub"))
  1814. req, err = http.NewRequest(http.MethodGet, subPath1, nil)
  1815. if assert.NoError(t, err) {
  1816. req.SetBasicAuth(u.Username, u.Password)
  1817. resp, err := httpClient.Do(req)
  1818. if assert.NoError(t, err) {
  1819. // here the stat will fail, so the request will not be changed in propfind
  1820. assert.Equal(t, http.StatusForbidden, resp.StatusCode)
  1821. resp.Body.Close()
  1822. }
  1823. }
  1824. // we have no permission, we get an empty list
  1825. files, err := client.ReadDir(subDir1)
  1826. assert.NoError(t, err)
  1827. assert.Len(t, files, 0)
  1828. // if we grant the permissions the files are listed
  1829. user.Permissions[subDir1] = []string{dataprovider.PermDownload, dataprovider.PermListItems}
  1830. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1831. assert.NoError(t, err)
  1832. files, err = client.ReadDir(subDir1)
  1833. assert.NoError(t, err)
  1834. assert.Len(t, files, 1)
  1835. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1836. assert.NoError(t, err)
  1837. err = os.RemoveAll(user.GetHomeDir())
  1838. assert.NoError(t, err)
  1839. }
  1840. func TestStat(t *testing.T) {
  1841. u := getTestUser()
  1842. u.Permissions["/subdir"] = []string{dataprovider.PermUpload, dataprovider.PermListItems, dataprovider.PermDownload}
  1843. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1844. assert.NoError(t, err)
  1845. client := getWebDavClient(user, true, nil)
  1846. subDir := "subdir"
  1847. testFilePath := filepath.Join(homeBasePath, testFileName)
  1848. testFileSize := int64(65535)
  1849. err = createTestFile(testFilePath, testFileSize)
  1850. assert.NoError(t, err)
  1851. err = client.Mkdir(subDir, os.ModePerm)
  1852. assert.NoError(t, err)
  1853. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1854. true, testFileSize, client)
  1855. assert.NoError(t, err)
  1856. err = uploadFileWithRawClient(testFilePath, path.Join("/", subDir, testFileName), user.Username,
  1857. defaultPassword, true, testFileSize, client)
  1858. assert.NoError(t, err)
  1859. user.Permissions["/subdir"] = []string{dataprovider.PermUpload, dataprovider.PermDownload}
  1860. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1861. assert.NoError(t, err)
  1862. _, err = client.Stat(testFileName)
  1863. assert.NoError(t, err)
  1864. _, err = client.Stat(path.Join("/", subDir, testFileName))
  1865. assert.Error(t, err)
  1866. err = os.Remove(testFilePath)
  1867. assert.NoError(t, err)
  1868. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1869. assert.NoError(t, err)
  1870. err = os.RemoveAll(user.GetHomeDir())
  1871. assert.NoError(t, err)
  1872. }
  1873. func TestUploadOverwriteVfolder(t *testing.T) {
  1874. u := getTestUser()
  1875. vdir := "/vdir"
  1876. mappedPath := filepath.Join(os.TempDir(), "mappedDir")
  1877. folderName := filepath.Base(mappedPath)
  1878. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1879. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1880. Name: folderName,
  1881. MappedPath: mappedPath,
  1882. },
  1883. VirtualPath: vdir,
  1884. QuotaSize: -1,
  1885. QuotaFiles: -1,
  1886. })
  1887. err := os.MkdirAll(mappedPath, os.ModePerm)
  1888. assert.NoError(t, err)
  1889. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1890. assert.NoError(t, err)
  1891. client := getWebDavClient(user, false, nil)
  1892. files, err := client.ReadDir(".")
  1893. assert.NoError(t, err)
  1894. vdirFound := false
  1895. for _, info := range files {
  1896. if info.Name() == path.Base(vdir) {
  1897. vdirFound = true
  1898. break
  1899. }
  1900. }
  1901. assert.True(t, vdirFound)
  1902. info, err := client.Stat(vdir)
  1903. if assert.NoError(t, err) {
  1904. assert.Equal(t, path.Base(vdir), info.Name())
  1905. }
  1906. testFilePath := filepath.Join(homeBasePath, testFileName)
  1907. testFileSize := int64(65535)
  1908. err = createTestFile(testFilePath, testFileSize)
  1909. assert.NoError(t, err)
  1910. err = uploadFileWithRawClient(testFilePath, path.Join(vdir, testFileName), user.Username,
  1911. defaultPassword, true, testFileSize, client)
  1912. assert.NoError(t, err)
  1913. folder, _, err := httpdtest.GetFolderByName(folderName, http.StatusOK)
  1914. assert.NoError(t, err)
  1915. assert.Equal(t, testFileSize, folder.UsedQuotaSize)
  1916. assert.Equal(t, 1, folder.UsedQuotaFiles)
  1917. err = uploadFileWithRawClient(testFilePath, path.Join(vdir, testFileName), user.Username,
  1918. defaultPassword, true, testFileSize, client)
  1919. assert.NoError(t, err)
  1920. folder, _, err = httpdtest.GetFolderByName(folderName, http.StatusOK)
  1921. assert.NoError(t, err)
  1922. assert.Equal(t, testFileSize, folder.UsedQuotaSize)
  1923. assert.Equal(t, 1, folder.UsedQuotaFiles)
  1924. err = os.Remove(testFilePath)
  1925. assert.NoError(t, err)
  1926. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1927. assert.NoError(t, err)
  1928. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  1929. assert.NoError(t, err)
  1930. err = os.RemoveAll(user.GetHomeDir())
  1931. assert.NoError(t, err)
  1932. err = os.RemoveAll(mappedPath)
  1933. assert.NoError(t, err)
  1934. }
  1935. func TestOsErrors(t *testing.T) {
  1936. u := getTestUser()
  1937. vdir := "/vdir"
  1938. mappedPath := filepath.Join(os.TempDir(), "mappedDir")
  1939. folderName := filepath.Base(mappedPath)
  1940. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1941. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1942. Name: folderName,
  1943. MappedPath: mappedPath,
  1944. },
  1945. VirtualPath: vdir,
  1946. QuotaSize: -1,
  1947. QuotaFiles: -1,
  1948. })
  1949. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1950. assert.NoError(t, err)
  1951. client := getWebDavClient(user, false, nil)
  1952. files, err := client.ReadDir(".")
  1953. assert.NoError(t, err)
  1954. assert.Len(t, files, 1)
  1955. info, err := client.Stat(vdir)
  1956. assert.NoError(t, err)
  1957. assert.True(t, info.IsDir())
  1958. // now remove the folder mapped to vdir. It should not appear in directory listing
  1959. err = os.RemoveAll(mappedPath)
  1960. assert.NoError(t, err)
  1961. files, err = client.ReadDir(".")
  1962. assert.NoError(t, err)
  1963. assert.Len(t, files, 0)
  1964. err = createTestFile(filepath.Join(user.GetHomeDir(), testFileName), 32768)
  1965. assert.NoError(t, err)
  1966. files, err = client.ReadDir(".")
  1967. assert.NoError(t, err)
  1968. if assert.Len(t, files, 1) {
  1969. assert.Equal(t, testFileName, files[0].Name())
  1970. }
  1971. if runtime.GOOS != osWindows {
  1972. // if the file cannot be accessed it should not appear in directory listing
  1973. err = os.Chmod(filepath.Join(user.GetHomeDir(), testFileName), 0001)
  1974. assert.NoError(t, err)
  1975. files, err = client.ReadDir(".")
  1976. assert.NoError(t, err)
  1977. assert.Len(t, files, 0)
  1978. err = os.Chmod(filepath.Join(user.GetHomeDir(), testFileName), os.ModePerm)
  1979. assert.NoError(t, err)
  1980. }
  1981. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1982. assert.NoError(t, err)
  1983. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  1984. assert.NoError(t, err)
  1985. err = os.RemoveAll(user.GetHomeDir())
  1986. assert.NoError(t, err)
  1987. err = os.RemoveAll(mappedPath)
  1988. assert.NoError(t, err)
  1989. }
  1990. func TestMiscCommands(t *testing.T) {
  1991. u := getTestUser()
  1992. u.QuotaFiles = 100
  1993. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1994. assert.NoError(t, err)
  1995. u = getTestSFTPUser()
  1996. u.QuotaFiles = 100
  1997. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1998. assert.NoError(t, err)
  1999. for _, user := range []dataprovider.User{localUser, sftpUser} {
  2000. dir := "testDir"
  2001. client := getWebDavClient(user, true, nil)
  2002. err = client.MkdirAll(path.Join(dir, "sub1", "sub2"), os.ModePerm)
  2003. assert.NoError(t, err)
  2004. testFilePath := filepath.Join(homeBasePath, testFileName)
  2005. testFileSize := int64(65535)
  2006. err = createTestFile(testFilePath, testFileSize)
  2007. assert.NoError(t, err)
  2008. err = uploadFileWithRawClient(testFilePath, path.Join(dir, testFileName), user.Username,
  2009. defaultPassword, true, testFileSize, client)
  2010. assert.NoError(t, err)
  2011. err = uploadFileWithRawClient(testFilePath, path.Join(dir, "sub1", testFileName), user.Username,
  2012. defaultPassword, true, testFileSize, client)
  2013. assert.NoError(t, err)
  2014. err = uploadFileWithRawClient(testFilePath, path.Join(dir, "sub1", "sub2", testFileName), user.Username,
  2015. defaultPassword, true, testFileSize, client)
  2016. assert.NoError(t, err)
  2017. err = client.Copy(dir, dir+"_copy", false)
  2018. assert.NoError(t, err)
  2019. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2020. assert.NoError(t, err)
  2021. assert.Equal(t, 6, user.UsedQuotaFiles)
  2022. assert.Equal(t, 6*testFileSize, user.UsedQuotaSize)
  2023. err = client.Copy(dir, dir+"_copy1", false)
  2024. assert.NoError(t, err)
  2025. err = client.Copy(dir+"_copy", dir+"_copy1", false)
  2026. assert.Error(t, err)
  2027. err = client.Copy(dir+"_copy", dir+"_copy1", true)
  2028. assert.NoError(t, err)
  2029. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2030. assert.NoError(t, err)
  2031. assert.Equal(t, 9, user.UsedQuotaFiles)
  2032. assert.Equal(t, 9*testFileSize, user.UsedQuotaSize)
  2033. err = client.Rename(dir+"_copy1", dir+"_copy2", false)
  2034. assert.NoError(t, err)
  2035. err = client.Remove(path.Join(dir+"_copy", testFileName))
  2036. assert.NoError(t, err)
  2037. err = client.Rename(dir+"_copy2", dir+"_copy", true)
  2038. assert.NoError(t, err)
  2039. err = client.Copy(dir+"_copy", dir+"_copy1", false)
  2040. assert.NoError(t, err)
  2041. err = client.RemoveAll(dir + "_copy1")
  2042. assert.NoError(t, err)
  2043. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2044. assert.NoError(t, err)
  2045. assert.Equal(t, 6, user.UsedQuotaFiles)
  2046. assert.Equal(t, 6*testFileSize, user.UsedQuotaSize)
  2047. err = os.Remove(testFilePath)
  2048. assert.NoError(t, err)
  2049. if user.Username == defaultUsername {
  2050. err = os.RemoveAll(user.GetHomeDir())
  2051. assert.NoError(t, err)
  2052. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2053. assert.NoError(t, err)
  2054. user.Password = defaultPassword
  2055. user.ID = 0
  2056. user.CreatedAt = 0
  2057. user.QuotaFiles = 0
  2058. _, resp, err := httpdtest.AddUser(user, http.StatusCreated)
  2059. assert.NoError(t, err, string(resp))
  2060. }
  2061. }
  2062. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  2063. assert.NoError(t, err)
  2064. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  2065. assert.NoError(t, err)
  2066. err = os.RemoveAll(localUser.GetHomeDir())
  2067. assert.NoError(t, err)
  2068. }
  2069. func TestClientCertificateAuthRevokedCert(t *testing.T) {
  2070. u := getTestUser()
  2071. u.Username = tlsClient2Username
  2072. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2073. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2074. assert.NoError(t, err)
  2075. tlsConfig := &tls.Config{
  2076. ServerName: "localhost",
  2077. InsecureSkipVerify: true, // use this for tests only
  2078. MinVersion: tls.VersionTLS12,
  2079. }
  2080. tlsCert, err := tls.X509KeyPair([]byte(client2Crt), []byte(client2Key))
  2081. assert.NoError(t, err)
  2082. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2083. client := getWebDavClient(user, true, tlsConfig)
  2084. err = checkBasicFunc(client)
  2085. if assert.Error(t, err) {
  2086. if !strings.Contains(err.Error(), "bad certificate") && !strings.Contains(err.Error(), "broken pipe") {
  2087. t.Errorf("unexpected error: %v", err)
  2088. }
  2089. }
  2090. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2091. assert.NoError(t, err)
  2092. err = os.RemoveAll(user.GetHomeDir())
  2093. assert.NoError(t, err)
  2094. }
  2095. func TestClientCertificateAuth(t *testing.T) {
  2096. u := getTestUser()
  2097. u.Username = tlsClient1Username
  2098. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificateAndPwd}
  2099. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2100. assert.NoError(t, err)
  2101. tlsConfig := &tls.Config{
  2102. ServerName: "localhost",
  2103. InsecureSkipVerify: true, // use this for tests only
  2104. MinVersion: tls.VersionTLS12,
  2105. }
  2106. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2107. assert.NoError(t, err)
  2108. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2109. // TLS username is not enabled, mutual TLS should fail
  2110. resp, err := getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v/", webDavTLSServerAddr))
  2111. if assert.NoError(t, err) {
  2112. defer resp.Body.Close()
  2113. body, err := io.ReadAll(resp.Body)
  2114. assert.NoError(t, err)
  2115. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2116. }
  2117. user.Filters.TLSUsername = sdk.TLSUsernameCN
  2118. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2119. assert.NoError(t, err)
  2120. client := getWebDavClient(user, true, tlsConfig)
  2121. err = checkBasicFunc(client)
  2122. assert.NoError(t, err)
  2123. user.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificate}
  2124. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2125. assert.NoError(t, err)
  2126. client = getWebDavClient(user, true, tlsConfig)
  2127. err = checkBasicFunc(client)
  2128. assert.NoError(t, err)
  2129. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2130. assert.NoError(t, err)
  2131. err = os.RemoveAll(user.GetHomeDir())
  2132. assert.NoError(t, err)
  2133. }
  2134. func TestWrongClientCertificate(t *testing.T) {
  2135. u := getTestUser()
  2136. u.Username = tlsClient2Username
  2137. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificateAndPwd}
  2138. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2139. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2140. assert.NoError(t, err)
  2141. tlsConfig := &tls.Config{
  2142. ServerName: "localhost",
  2143. InsecureSkipVerify: true, // use this for tests only
  2144. MinVersion: tls.VersionTLS12,
  2145. }
  2146. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2147. assert.NoError(t, err)
  2148. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2149. // the certificate common name is client1 and it does not exists
  2150. resp, err := getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v/", webDavTLSServerAddr))
  2151. if assert.NoError(t, err) {
  2152. defer resp.Body.Close()
  2153. body, err := io.ReadAll(resp.Body)
  2154. assert.NoError(t, err)
  2155. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2156. }
  2157. user.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificate}
  2158. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2159. assert.NoError(t, err)
  2160. // now create client1
  2161. u = getTestUser()
  2162. u.Username = tlsClient1Username
  2163. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificate}
  2164. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2165. user1, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2166. assert.NoError(t, err)
  2167. resp, err = getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v:%v@%v/", tlsClient2Username, defaultPassword,
  2168. webDavTLSServerAddr))
  2169. if assert.NoError(t, err) {
  2170. defer resp.Body.Close()
  2171. body, err := io.ReadAll(resp.Body)
  2172. assert.NoError(t, err)
  2173. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2174. assert.Contains(t, string(body), "invalid credentials")
  2175. }
  2176. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2177. assert.NoError(t, err)
  2178. err = os.RemoveAll(user.GetHomeDir())
  2179. assert.NoError(t, err)
  2180. _, err = httpdtest.RemoveUser(user1, http.StatusOK)
  2181. assert.NoError(t, err)
  2182. err = os.RemoveAll(user1.GetHomeDir())
  2183. assert.NoError(t, err)
  2184. }
  2185. func TestClientCertificateAuthCachedUser(t *testing.T) {
  2186. u := getTestUser()
  2187. u.Username = tlsClient1Username
  2188. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2189. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificateAndPwd}
  2190. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2191. assert.NoError(t, err)
  2192. tlsConfig := &tls.Config{
  2193. ServerName: "localhost",
  2194. InsecureSkipVerify: true, // use this for tests only
  2195. MinVersion: tls.VersionTLS12,
  2196. }
  2197. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2198. assert.NoError(t, err)
  2199. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2200. client := getWebDavClient(user, true, tlsConfig)
  2201. err = checkBasicFunc(client)
  2202. assert.NoError(t, err)
  2203. // the user is now cached without a password, try a simple password login with and without TLS
  2204. client = getWebDavClient(user, true, nil)
  2205. err = checkBasicFunc(client)
  2206. assert.NoError(t, err)
  2207. client = getWebDavClient(user, false, nil)
  2208. err = checkBasicFunc(client)
  2209. assert.NoError(t, err)
  2210. // and now with a wrong password
  2211. user.Password = "wrong"
  2212. client = getWebDavClient(user, false, nil)
  2213. err = checkBasicFunc(client)
  2214. assert.Error(t, err)
  2215. // allow cert+password only
  2216. user.Password = ""
  2217. user.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificate}
  2218. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2219. assert.NoError(t, err)
  2220. client = getWebDavClient(user, true, tlsConfig)
  2221. err = checkBasicFunc(client)
  2222. assert.NoError(t, err)
  2223. // the user is now cached
  2224. client = getWebDavClient(user, true, tlsConfig)
  2225. err = checkBasicFunc(client)
  2226. assert.NoError(t, err)
  2227. // password auth should work too
  2228. client = getWebDavClient(user, false, nil)
  2229. err = checkBasicFunc(client)
  2230. assert.NoError(t, err)
  2231. client = getWebDavClient(user, true, nil)
  2232. err = checkBasicFunc(client)
  2233. assert.NoError(t, err)
  2234. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2235. assert.NoError(t, err)
  2236. err = os.RemoveAll(user.GetHomeDir())
  2237. assert.NoError(t, err)
  2238. }
  2239. func TestExternatAuthWithClientCert(t *testing.T) {
  2240. if runtime.GOOS == osWindows {
  2241. t.Skip("this test is not available on Windows")
  2242. }
  2243. u := getTestUser()
  2244. u.Username = tlsClient1Username
  2245. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2246. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificate, dataprovider.LoginMethodPassword}
  2247. err := dataprovider.Close()
  2248. assert.NoError(t, err)
  2249. err = config.LoadConfig(configDir, "")
  2250. assert.NoError(t, err)
  2251. providerConf := config.GetProviderConf()
  2252. err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, ""), os.ModePerm)
  2253. assert.NoError(t, err)
  2254. providerConf.ExternalAuthHook = extAuthPath
  2255. providerConf.ExternalAuthScope = 0
  2256. err = dataprovider.Initialize(providerConf, configDir, true)
  2257. assert.NoError(t, err)
  2258. tlsConfig := &tls.Config{
  2259. ServerName: "localhost",
  2260. InsecureSkipVerify: true, // use this for tests only
  2261. MinVersion: tls.VersionTLS12,
  2262. }
  2263. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2264. assert.NoError(t, err)
  2265. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2266. client := getWebDavClient(u, true, tlsConfig)
  2267. assert.NoError(t, checkBasicFunc(client))
  2268. resp, err := getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v:%v@%v/", tlsClient2Username, defaultPassword,
  2269. webDavTLSServerAddr))
  2270. if assert.NoError(t, err) {
  2271. defer resp.Body.Close()
  2272. body, err := io.ReadAll(resp.Body)
  2273. assert.NoError(t, err)
  2274. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2275. assert.Contains(t, string(body), "invalid credentials")
  2276. }
  2277. user, _, err := httpdtest.GetUserByUsername(tlsClient1Username, http.StatusOK)
  2278. assert.NoError(t, err)
  2279. assert.Equal(t, tlsClient1Username, user.Username)
  2280. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2281. assert.NoError(t, err)
  2282. err = os.RemoveAll(user.GetHomeDir())
  2283. assert.NoError(t, err)
  2284. err = dataprovider.Close()
  2285. assert.NoError(t, err)
  2286. err = config.LoadConfig(configDir, "")
  2287. assert.NoError(t, err)
  2288. providerConf = config.GetProviderConf()
  2289. err = dataprovider.Initialize(providerConf, configDir, true)
  2290. assert.NoError(t, err)
  2291. err = os.Remove(extAuthPath)
  2292. assert.NoError(t, err)
  2293. }
  2294. func TestPreLoginHookWithClientCert(t *testing.T) {
  2295. if runtime.GOOS == osWindows {
  2296. t.Skip("this test is not available on Windows")
  2297. }
  2298. u := getTestUser()
  2299. u.Username = tlsClient1Username
  2300. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2301. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificate, dataprovider.LoginMethodPassword}
  2302. err := dataprovider.Close()
  2303. assert.NoError(t, err)
  2304. err = config.LoadConfig(configDir, "")
  2305. assert.NoError(t, err)
  2306. providerConf := config.GetProviderConf()
  2307. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
  2308. assert.NoError(t, err)
  2309. providerConf.PreLoginHook = preLoginPath
  2310. err = dataprovider.Initialize(providerConf, configDir, true)
  2311. assert.NoError(t, err)
  2312. _, _, err = httpdtest.GetUserByUsername(tlsClient1Username, http.StatusNotFound)
  2313. assert.NoError(t, err)
  2314. tlsConfig := &tls.Config{
  2315. ServerName: "localhost",
  2316. InsecureSkipVerify: true, // use this for tests only
  2317. MinVersion: tls.VersionTLS12,
  2318. }
  2319. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2320. assert.NoError(t, err)
  2321. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2322. client := getWebDavClient(u, true, tlsConfig)
  2323. assert.NoError(t, checkBasicFunc(client))
  2324. user, _, err := httpdtest.GetUserByUsername(tlsClient1Username, http.StatusOK)
  2325. assert.NoError(t, err)
  2326. // test login with an existing user
  2327. client = getWebDavClient(user, true, tlsConfig)
  2328. assert.NoError(t, checkBasicFunc(client))
  2329. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), os.ModePerm)
  2330. assert.NoError(t, err)
  2331. // update the user to remove it from the cache
  2332. user.Password = defaultPassword
  2333. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2334. assert.NoError(t, err)
  2335. client = getWebDavClient(user, true, tlsConfig)
  2336. assert.Error(t, checkBasicFunc(client))
  2337. // update the user to remove it from the cache
  2338. user.Password = defaultPassword
  2339. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2340. assert.NoError(t, err)
  2341. user.Status = 0
  2342. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), os.ModePerm)
  2343. assert.NoError(t, err)
  2344. client = getWebDavClient(user, true, tlsConfig)
  2345. assert.Error(t, checkBasicFunc(client))
  2346. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2347. assert.NoError(t, err)
  2348. err = os.RemoveAll(user.GetHomeDir())
  2349. assert.NoError(t, err)
  2350. err = dataprovider.Close()
  2351. assert.NoError(t, err)
  2352. err = config.LoadConfig(configDir, "")
  2353. assert.NoError(t, err)
  2354. providerConf = config.GetProviderConf()
  2355. err = dataprovider.Initialize(providerConf, configDir, true)
  2356. assert.NoError(t, err)
  2357. err = os.Remove(preLoginPath)
  2358. assert.NoError(t, err)
  2359. }
  2360. func TestSFTPLoopVirtualFolders(t *testing.T) {
  2361. user1 := getTestUser()
  2362. user2 := getTestUser()
  2363. user1.Username += "1"
  2364. user2.Username += "2"
  2365. // user1 is a local account with a virtual SFTP folder to user2
  2366. // user2 has user1 as SFTP fs
  2367. user1.VirtualFolders = append(user1.VirtualFolders, vfs.VirtualFolder{
  2368. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2369. Name: "sftp",
  2370. FsConfig: vfs.Filesystem{
  2371. Provider: sdk.SFTPFilesystemProvider,
  2372. SFTPConfig: vfs.SFTPFsConfig{
  2373. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  2374. Endpoint: sftpServerAddr,
  2375. Username: user2.Username,
  2376. },
  2377. Password: kms.NewPlainSecret(defaultPassword),
  2378. },
  2379. },
  2380. },
  2381. VirtualPath: "/vdir",
  2382. })
  2383. user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
  2384. user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
  2385. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  2386. Endpoint: sftpServerAddr,
  2387. Username: user1.Username,
  2388. },
  2389. Password: kms.NewPlainSecret(defaultPassword),
  2390. }
  2391. user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
  2392. assert.NoError(t, err, string(resp))
  2393. user2, resp, err = httpdtest.AddUser(user2, http.StatusCreated)
  2394. assert.NoError(t, err, string(resp))
  2395. client := getWebDavClient(user1, true, nil)
  2396. testDir := "tdir"
  2397. err = client.Mkdir(testDir, os.ModePerm)
  2398. assert.NoError(t, err)
  2399. contents, err := client.ReadDir("/")
  2400. assert.NoError(t, err)
  2401. if assert.Len(t, contents, 1) {
  2402. assert.Equal(t, testDir, contents[0].Name())
  2403. assert.True(t, contents[0].IsDir())
  2404. }
  2405. _, err = httpdtest.RemoveUser(user1, http.StatusOK)
  2406. assert.NoError(t, err)
  2407. err = os.RemoveAll(user1.GetHomeDir())
  2408. assert.NoError(t, err)
  2409. _, err = httpdtest.RemoveUser(user2, http.StatusOK)
  2410. assert.NoError(t, err)
  2411. err = os.RemoveAll(user2.GetHomeDir())
  2412. assert.NoError(t, err)
  2413. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: "sftp"}, http.StatusOK)
  2414. assert.NoError(t, err)
  2415. }
  2416. func TestNestedVirtualFolders(t *testing.T) {
  2417. u := getTestUser()
  2418. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2419. assert.NoError(t, err)
  2420. u = getTestSFTPUser()
  2421. mappedPathCrypt := filepath.Join(os.TempDir(), "crypt")
  2422. folderNameCrypt := filepath.Base(mappedPathCrypt)
  2423. vdirCryptPath := "/vdir/crypt"
  2424. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2425. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2426. Name: folderNameCrypt,
  2427. FsConfig: vfs.Filesystem{
  2428. Provider: sdk.CryptedFilesystemProvider,
  2429. CryptConfig: vfs.CryptFsConfig{
  2430. Passphrase: kms.NewPlainSecret(defaultPassword),
  2431. },
  2432. },
  2433. MappedPath: mappedPathCrypt,
  2434. },
  2435. VirtualPath: vdirCryptPath,
  2436. })
  2437. mappedPath := filepath.Join(os.TempDir(), "local")
  2438. folderName := filepath.Base(mappedPath)
  2439. vdirPath := "/vdir/local"
  2440. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2441. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2442. Name: folderName,
  2443. MappedPath: mappedPath,
  2444. },
  2445. VirtualPath: vdirPath,
  2446. })
  2447. mappedPathNested := filepath.Join(os.TempDir(), "nested")
  2448. folderNameNested := filepath.Base(mappedPathNested)
  2449. vdirNestedPath := "/vdir/crypt/nested"
  2450. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2451. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2452. Name: folderNameNested,
  2453. MappedPath: mappedPathNested,
  2454. },
  2455. VirtualPath: vdirNestedPath,
  2456. QuotaFiles: -1,
  2457. QuotaSize: -1,
  2458. })
  2459. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2460. assert.NoError(t, err)
  2461. client := getWebDavClient(sftpUser, true, nil)
  2462. assert.NoError(t, checkBasicFunc(client))
  2463. testFilePath := filepath.Join(homeBasePath, testFileName)
  2464. testFileSize := int64(65535)
  2465. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  2466. err = createTestFile(testFilePath, testFileSize)
  2467. assert.NoError(t, err)
  2468. err = uploadFileWithRawClient(testFilePath, testFileName, sftpUser.Username,
  2469. defaultPassword, true, testFileSize, client)
  2470. assert.NoError(t, err)
  2471. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  2472. assert.NoError(t, err)
  2473. err = uploadFileWithRawClient(testFilePath, path.Join("/vdir", testFileName), sftpUser.Username,
  2474. defaultPassword, true, testFileSize, client)
  2475. assert.NoError(t, err)
  2476. err = downloadFile(path.Join("/vdir", testFileName), localDownloadPath, testFileSize, client)
  2477. assert.NoError(t, err)
  2478. err = uploadFileWithRawClient(testFilePath, path.Join(vdirPath, testFileName), sftpUser.Username,
  2479. defaultPassword, true, testFileSize, client)
  2480. assert.NoError(t, err)
  2481. err = downloadFile(path.Join(vdirPath, testFileName), localDownloadPath, testFileSize, client)
  2482. assert.NoError(t, err)
  2483. err = uploadFileWithRawClient(testFilePath, path.Join(vdirCryptPath, testFileName), sftpUser.Username,
  2484. defaultPassword, true, testFileSize, client)
  2485. assert.NoError(t, err)
  2486. err = downloadFile(path.Join(vdirCryptPath, testFileName), localDownloadPath, testFileSize, client)
  2487. assert.NoError(t, err)
  2488. err = uploadFileWithRawClient(testFilePath, path.Join(vdirNestedPath, testFileName), sftpUser.Username,
  2489. defaultPassword, true, testFileSize, client)
  2490. assert.NoError(t, err)
  2491. err = downloadFile(path.Join(vdirNestedPath, testFileName), localDownloadPath, testFileSize, client)
  2492. assert.NoError(t, err)
  2493. err = os.Remove(testFilePath)
  2494. assert.NoError(t, err)
  2495. err = os.Remove(localDownloadPath)
  2496. assert.NoError(t, err)
  2497. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  2498. assert.NoError(t, err)
  2499. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  2500. assert.NoError(t, err)
  2501. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameCrypt}, http.StatusOK)
  2502. assert.NoError(t, err)
  2503. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  2504. assert.NoError(t, err)
  2505. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameNested}, http.StatusOK)
  2506. assert.NoError(t, err)
  2507. err = os.RemoveAll(mappedPathCrypt)
  2508. assert.NoError(t, err)
  2509. err = os.RemoveAll(mappedPath)
  2510. assert.NoError(t, err)
  2511. err = os.RemoveAll(mappedPathNested)
  2512. assert.NoError(t, err)
  2513. err = os.RemoveAll(localUser.GetHomeDir())
  2514. assert.NoError(t, err)
  2515. assert.Len(t, common.Connections.GetStats(), 0)
  2516. }
  2517. func checkBasicFunc(client *gowebdav.Client) error {
  2518. err := client.Connect()
  2519. if err != nil {
  2520. return err
  2521. }
  2522. _, err = client.ReadDir("/")
  2523. return err
  2524. }
  2525. func checkFileSize(remoteDestPath string, expectedSize int64, client *gowebdav.Client) error {
  2526. info, err := client.Stat(remoteDestPath)
  2527. if err != nil {
  2528. return err
  2529. }
  2530. if info.Size() != expectedSize {
  2531. return fmt.Errorf("uploaded file size does not match, actual: %v, expected: %v", info.Size(), expectedSize)
  2532. }
  2533. return nil
  2534. }
  2535. func uploadFileWithRawClient(localSourcePath string, remoteDestPath string, username, password string,
  2536. useTLS bool, expectedSize int64, client *gowebdav.Client,
  2537. ) error {
  2538. srcFile, err := os.Open(localSourcePath)
  2539. if err != nil {
  2540. return err
  2541. }
  2542. defer srcFile.Close()
  2543. var tlsConfig *tls.Config
  2544. rootPath := fmt.Sprintf("http://%v/", webDavServerAddr)
  2545. if useTLS {
  2546. rootPath = fmt.Sprintf("https://%v/", webDavTLSServerAddr)
  2547. tlsConfig = &tls.Config{
  2548. ServerName: "localhost",
  2549. InsecureSkipVerify: true, // use this for tests only
  2550. MinVersion: tls.VersionTLS12,
  2551. }
  2552. }
  2553. req, err := http.NewRequest(http.MethodPut, fmt.Sprintf("%v%v", rootPath, remoteDestPath), srcFile)
  2554. if err != nil {
  2555. return err
  2556. }
  2557. req.SetBasicAuth(username, password)
  2558. httpClient := &http.Client{Timeout: 10 * time.Second}
  2559. if tlsConfig != nil {
  2560. customTransport := http.DefaultTransport.(*http.Transport).Clone()
  2561. customTransport.TLSClientConfig = tlsConfig
  2562. httpClient.Transport = customTransport
  2563. }
  2564. defer httpClient.CloseIdleConnections()
  2565. resp, err := httpClient.Do(req)
  2566. if err != nil {
  2567. return err
  2568. }
  2569. defer resp.Body.Close()
  2570. if resp.StatusCode != http.StatusCreated {
  2571. return fmt.Errorf("unexpected status code: %v", resp.StatusCode)
  2572. }
  2573. if expectedSize > 0 {
  2574. return checkFileSize(remoteDestPath, expectedSize, client)
  2575. }
  2576. return nil
  2577. }
  2578. // This method is buggy. I have to find time to better investigate and eventually report the issue upstream.
  2579. // For now we upload using the uploadFileWithRawClient method
  2580. /*func uploadFile(localSourcePath string, remoteDestPath string, expectedSize int64, client *gowebdav.Client) error {
  2581. srcFile, err := os.Open(localSourcePath)
  2582. if err != nil {
  2583. return err
  2584. }
  2585. defer srcFile.Close()
  2586. err = client.WriteStream(remoteDestPath, srcFile, os.ModePerm)
  2587. if err != nil {
  2588. return err
  2589. }
  2590. if expectedSize > 0 {
  2591. return checkFileSize(remoteDestPath, expectedSize, client)
  2592. }
  2593. return nil
  2594. }*/
  2595. func downloadFile(remoteSourcePath string, localDestPath string, expectedSize int64, client *gowebdav.Client) error {
  2596. downloadDest, err := os.Create(localDestPath)
  2597. if err != nil {
  2598. return err
  2599. }
  2600. defer downloadDest.Close()
  2601. reader, err := client.ReadStream(remoteSourcePath)
  2602. if err != nil {
  2603. return err
  2604. }
  2605. defer reader.Close()
  2606. written, err := io.Copy(downloadDest, reader)
  2607. if err != nil {
  2608. return err
  2609. }
  2610. if written != expectedSize {
  2611. return fmt.Errorf("downloaded file size does not match, actual: %v, expected: %v", written, expectedSize)
  2612. }
  2613. return nil
  2614. }
  2615. func getTLSHTTPClient(tlsConfig *tls.Config) *http.Client {
  2616. customTransport := http.DefaultTransport.(*http.Transport).Clone()
  2617. customTransport.TLSClientConfig = tlsConfig
  2618. return &http.Client{
  2619. Timeout: 5 * time.Second,
  2620. Transport: customTransport,
  2621. }
  2622. }
  2623. func getWebDavClient(user dataprovider.User, useTLS bool, tlsConfig *tls.Config) *gowebdav.Client {
  2624. rootPath := fmt.Sprintf("http://%v/", webDavServerAddr)
  2625. if useTLS {
  2626. rootPath = fmt.Sprintf("https://%v/", webDavTLSServerAddr)
  2627. if tlsConfig == nil {
  2628. tlsConfig = &tls.Config{
  2629. ServerName: "localhost",
  2630. InsecureSkipVerify: true, // use this for tests only
  2631. MinVersion: tls.VersionTLS12,
  2632. }
  2633. }
  2634. }
  2635. pwd := defaultPassword
  2636. if user.Password != "" {
  2637. pwd = user.Password
  2638. }
  2639. client := gowebdav.NewClient(rootPath, user.Username, pwd)
  2640. client.SetTimeout(10 * time.Second)
  2641. if tlsConfig != nil {
  2642. customTransport := http.DefaultTransport.(*http.Transport).Clone()
  2643. customTransport.TLSClientConfig = tlsConfig
  2644. client.SetTransport(customTransport)
  2645. }
  2646. return client
  2647. }
  2648. func waitTCPListening(address string) {
  2649. for {
  2650. conn, err := net.Dial("tcp", address)
  2651. if err != nil {
  2652. logger.WarnToConsole("tcp server %v not listening: %v", address, err)
  2653. time.Sleep(100 * time.Millisecond)
  2654. continue
  2655. }
  2656. logger.InfoToConsole("tcp server %v now listening", address)
  2657. conn.Close()
  2658. break
  2659. }
  2660. }
  2661. func getTestUser() dataprovider.User {
  2662. user := dataprovider.User{
  2663. BaseUser: sdk.BaseUser{
  2664. Username: defaultUsername,
  2665. Password: defaultPassword,
  2666. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  2667. Status: 1,
  2668. ExpirationDate: 0,
  2669. },
  2670. }
  2671. user.Permissions = make(map[string][]string)
  2672. user.Permissions["/"] = allPerms
  2673. return user
  2674. }
  2675. func getTestSFTPUser() dataprovider.User {
  2676. u := getTestUser()
  2677. u.Username = u.Username + "_sftp"
  2678. u.FsConfig.Provider = sdk.SFTPFilesystemProvider
  2679. u.FsConfig.SFTPConfig.Endpoint = sftpServerAddr
  2680. u.FsConfig.SFTPConfig.Username = defaultUsername
  2681. u.FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword)
  2682. return u
  2683. }
  2684. func getTestUserWithCryptFs() dataprovider.User {
  2685. user := getTestUser()
  2686. user.FsConfig.Provider = sdk.CryptedFilesystemProvider
  2687. user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret("testPassphrase")
  2688. return user
  2689. }
  2690. func getEncryptedFileSize(size int64) (int64, error) {
  2691. encSize, err := sio.EncryptedSize(uint64(size))
  2692. return int64(encSize) + 33, err
  2693. }
  2694. func getExtAuthScriptContent(user dataprovider.User, nonJSONResponse bool, username string) []byte {
  2695. extAuthContent := []byte("#!/bin/sh\n\n")
  2696. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("if test \"$SFTPGO_AUTHD_USERNAME\" = \"%v\"; then\n", user.Username))...)
  2697. if len(username) > 0 {
  2698. user.Username = username
  2699. }
  2700. u, _ := json.Marshal(user)
  2701. if nonJSONResponse {
  2702. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  2703. } else {
  2704. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  2705. }
  2706. extAuthContent = append(extAuthContent, []byte("else\n")...)
  2707. if nonJSONResponse {
  2708. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  2709. } else {
  2710. extAuthContent = append(extAuthContent, []byte("echo '{\"username\":\"\"}'\n")...)
  2711. }
  2712. extAuthContent = append(extAuthContent, []byte("fi\n")...)
  2713. return extAuthContent
  2714. }
  2715. func getPreLoginScriptContent(user dataprovider.User, nonJSONResponse bool) []byte {
  2716. content := []byte("#!/bin/sh\n\n")
  2717. if nonJSONResponse {
  2718. content = append(content, []byte("echo 'text response'\n")...)
  2719. return content
  2720. }
  2721. if len(user.Username) > 0 {
  2722. u, _ := json.Marshal(user)
  2723. content = append(content, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  2724. }
  2725. return content
  2726. }
  2727. func getExitCodeScriptContent(exitCode int) []byte {
  2728. content := []byte("#!/bin/sh\n\n")
  2729. content = append(content, []byte(fmt.Sprintf("exit %v", exitCode))...)
  2730. return content
  2731. }
  2732. func createTestFile(path string, size int64) error {
  2733. baseDir := filepath.Dir(path)
  2734. if _, err := os.Stat(baseDir); os.IsNotExist(err) {
  2735. err = os.MkdirAll(baseDir, os.ModePerm)
  2736. if err != nil {
  2737. return err
  2738. }
  2739. }
  2740. content := make([]byte, size)
  2741. _, err := rand.Read(content)
  2742. if err != nil {
  2743. return err
  2744. }
  2745. err = os.WriteFile(path, content, os.ModePerm)
  2746. if err != nil {
  2747. return err
  2748. }
  2749. fi, err := os.Stat(path)
  2750. if err != nil {
  2751. return err
  2752. }
  2753. if fi.Size() != size {
  2754. return fmt.Errorf("unexpected size %v, expected %v", fi.Size(), size)
  2755. }
  2756. return nil
  2757. }
  2758. func printLatestLogs(maxNumberOfLines int) {
  2759. var lines []string
  2760. f, err := os.Open(logFilePath)
  2761. if err != nil {
  2762. return
  2763. }
  2764. defer f.Close()
  2765. scanner := bufio.NewScanner(f)
  2766. for scanner.Scan() {
  2767. lines = append(lines, scanner.Text()+"\r\n")
  2768. for len(lines) > maxNumberOfLines {
  2769. lines = lines[1:]
  2770. }
  2771. }
  2772. if scanner.Err() != nil {
  2773. logger.WarnToConsole("Unable to print latest logs: %v", scanner.Err())
  2774. return
  2775. }
  2776. for _, line := range lines {
  2777. logger.DebugToConsole(line)
  2778. }
  2779. }