webdavd_test.go 99 KB

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