webdavd_test.go 95 KB

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