webdavd_test.go 99 KB

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