webdavd_test.go 120 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366
  1. // Copyright (C) 2019-2023 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. package webdavd_test
  15. import (
  16. "bufio"
  17. "bytes"
  18. "crypto/rand"
  19. "crypto/tls"
  20. "encoding/json"
  21. "errors"
  22. "fmt"
  23. "io"
  24. "io/fs"
  25. "net"
  26. "net/http"
  27. "os"
  28. "os/exec"
  29. "path"
  30. "path/filepath"
  31. "regexp"
  32. "runtime"
  33. "strings"
  34. "sync"
  35. "testing"
  36. "time"
  37. "github.com/minio/sio"
  38. "github.com/rs/zerolog"
  39. "github.com/sftpgo/sdk"
  40. sdkkms "github.com/sftpgo/sdk/kms"
  41. "github.com/stretchr/testify/assert"
  42. "github.com/studio-b12/gowebdav"
  43. "github.com/drakkan/sftpgo/v2/internal/common"
  44. "github.com/drakkan/sftpgo/v2/internal/config"
  45. "github.com/drakkan/sftpgo/v2/internal/dataprovider"
  46. "github.com/drakkan/sftpgo/v2/internal/httpclient"
  47. "github.com/drakkan/sftpgo/v2/internal/httpdtest"
  48. "github.com/drakkan/sftpgo/v2/internal/kms"
  49. "github.com/drakkan/sftpgo/v2/internal/logger"
  50. "github.com/drakkan/sftpgo/v2/internal/sftpd"
  51. "github.com/drakkan/sftpgo/v2/internal/vfs"
  52. "github.com/drakkan/sftpgo/v2/internal/webdavd"
  53. )
  54. const (
  55. logSender = "webavdTesting"
  56. webDavServerAddr = "localhost:9090"
  57. webDavTLSServerAddr = "localhost:9443"
  58. webDavServerPort = 9090
  59. webDavTLSServerPort = 9443
  60. sftpServerAddr = "127.0.0.1:9022"
  61. defaultUsername = "test_user_dav"
  62. defaultPassword = "test_password"
  63. osWindows = "windows"
  64. webDavCert = `-----BEGIN CERTIFICATE-----
  65. MIICHTCCAaKgAwIBAgIUHnqw7QnB1Bj9oUsNpdb+ZkFPOxMwCgYIKoZIzj0EAwIw
  66. RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
  67. dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDAyMDQwOTUzMDRaFw0zMDAyMDEw
  68. OTUzMDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD
  69. VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwdjAQBgcqhkjOPQIBBgUrgQQA
  70. IgNiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVqWvrJ51t5OxV0v25NsOgR82CA
  71. NXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIVCzgWkxiz7XE4lgUwX44FCXZM
  72. 3+JeUbKjUzBRMB0GA1UdDgQWBBRhLw+/o3+Z02MI/d4tmaMui9W16jAfBgNVHSME
  73. GDAWgBRhLw+/o3+Z02MI/d4tmaMui9W16jAPBgNVHRMBAf8EBTADAQH/MAoGCCqG
  74. SM49BAMCA2kAMGYCMQDqLt2lm8mE+tGgtjDmtFgdOcI72HSbRQ74D5rYTzgST1rY
  75. /8wTi5xl8TiFUyLMUsICMQC5ViVxdXbhuG7gX6yEqSkMKZICHpO8hqFwOD/uaFVI
  76. dV4vKmHUzwK/eIx+8Ay3neE=
  77. -----END CERTIFICATE-----`
  78. webDavKey = `-----BEGIN EC PARAMETERS-----
  79. BgUrgQQAIg==
  80. -----END EC PARAMETERS-----
  81. -----BEGIN EC PRIVATE KEY-----
  82. MIGkAgEBBDCfMNsN6miEE3rVyUPwElfiJSWaR5huPCzUenZOfJT04GAcQdWvEju3
  83. UM2lmBLIXpGgBwYFK4EEACKhZANiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVq
  84. WvrJ51t5OxV0v25NsOgR82CANXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIV
  85. CzgWkxiz7XE4lgUwX44FCXZM3+JeUbI=
  86. -----END EC PRIVATE KEY-----`
  87. caCRT = `-----BEGIN CERTIFICATE-----
  88. MIIE5jCCAs6gAwIBAgIBATANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDEwhDZXJ0
  89. QXV0aDAeFw0yMjA3MDQxNTQzMTFaFw0yNDAxMDQxNTUzMDhaMBMxETAPBgNVBAMT
  90. CENlcnRBdXRoMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4eyDJkmW
  91. D4OVYo7ddgiZkd6QQdPyLcsa31Wc9jdR2/peEabyNT8jSWteS6ouY84GRlnhfFeZ
  92. mpXgbaUJu/Z8Y/8riPxwL8XF4vCScQDMywpQnVUd6E9x2/+/uaD4p/BBswgKqKPe
  93. uDcHZn7MkD4QlquUhMElDrBUi1Dv/AVHnQ6iP4vd5Jlv0F+40jdq/8Wa7yhW7Pu5
  94. iNvPwCk8HjENBKVur/re+Acif8A2TlbCsuOnVduSQNmnWH+iZmB9upyBZtUszGS0
  95. JhUwtSnwUX/JapF70Pwte/PV3RK8cJ5FjuAPNeTyJvSuMTELFSAyCeiNynFGgyhW
  96. cqbEiPu6BURLculyVkmh4dOrhTrYZv/n3UJAhyxkdYrbh3INHmTa4izvclcuwoEo
  97. lFlJp3l77D0lIi+pbtcBV6ys7reyuxUAkBNwnpt2pWfCQoi4QYKcNbHm47c2phOb
  98. QSojQ8SsNU5bnlY2MDzkKo5DPav/i4d0HpndphUpx4f8hA0KylLevDRkMz9TAH7H
  99. uDssn0CxFOGHiveEAGGbn+doHjNWM339x/cdLbK0vuieDKby8YYcBY1JML57Dl9f
  100. rs52ySnDZbMqOb9zF66mQpC2FZoAj713xSkDSnSCUekrqgck1EA1ifxAviHt+p26
  101. JwaEDL7Lk01EEdYN4csSd1fezbCqTrG8ffUCAwEAAaNFMEMwDgYDVR0PAQH/BAQD
  102. AgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFPirPBPO01zUuf7xC+ds
  103. bOOY5QvAMA0GCSqGSIb3DQEBCwUAA4ICAQBUYa+ydfTPKjTN4lXyEZgchZQ+juny
  104. aMy1xosLz6Evj0us2Bwczmy6X2Zvaw/KteFlgKaU1Ex2UkU7FfAlaH0HtwTLFMVM
  105. p9nB7ZzStvg0n8zFM29SEkOFwZ9FRonxx4sY3FdvI4QvAWyDyqgOl8+Eedg0kC4+
  106. M7hxarTFmZZ7POZl8Hio592yx3asMmSCcmb7oUCKVI98qsf9fuL+LIZSpn4fE7av
  107. AiNBcOqCZ10CRnl4VSgAW2LH4oqROYdUv+me1u1YRwh7fCF/R7VjOLuaDzv0mp/g
  108. hzG9U+Yso3WV4b28MsctwUmGTK8Zc5QaANKgmI3ulkta37wN5KjrUuescHC7MqZg
  109. vN9n60801be1EoUL83KUx57Bix95YZR02Zge0gYdYTb+E2bwaZ4GMlf7cs6qmC6A
  110. ZPLR7Tffw2J4dPTcfEx3rPZ91s3MkAdPzYYGdGlbKp8RCFnezZ7rw2z57rnT0zDr
  111. LuL3Q6ADBfothoos/EBIC5ekXb9czp8gig+nJXLC6jlqcQpCLrV88oS3+8zACmx1
  112. d6tje9uuAqPgiQGddKZj4b4BlHmAMXq0PufQsZVoyzboTewZiLVCtTR9/iF7Cepg
  113. 6EVv57p61pFhPu8lNRAi0aH/po9yt+7435FGpn2kan6k9aDIVdaqeuxxITwsqJ4R
  114. WwSa13hh6yjoDQ==
  115. -----END CERTIFICATE-----`
  116. caCRL = `-----BEGIN X509 CRL-----
  117. MIICpzCBkAIBATANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDEwhDZXJ0QXV0aBcN
  118. MjIwNzA0MTU1MzU4WhcNMjQwNzAzMTU1MzU4WjAkMCICEQDZo5Q3lhxFuDUsxGNm
  119. 794YFw0yMjA3MDQxNTUzNThaoCMwITAfBgNVHSMEGDAWgBT4qzwTztNc1Ln+8Qvn
  120. bGzjmOULwDANBgkqhkiG9w0BAQsFAAOCAgEA1lK6g8qmhyY6myx8342dDuaauY03
  121. 0iojkxpasuYcytK6XRm96YqjZK9EETxsHHViVU0vCXES60D6wJ9gw4fTWn3WxEdx
  122. nIwbGyjUGHh2y+R3uQsfvwxsdYvDsTLAnOLwOo68dAHWmMDZRmgTuGNoYFxVQRGR
  123. Cn90ZR7LPLpCScclWM8FE/W1B90x3ZE8EhJiCI/WyyTh3EgshmB7A5GoDrFZfmvR
  124. dzoTKO+F9p2XjtmgfiBE3czWQysfATmbutZUbG/ZRb89u+ZEUyPoC94mg8fhNWoX
  125. 1d5G9QAkZFHp957/5QHLq9OHNfnWXoohhebjF4VWqZH7w+RtLc8t0PIog2lX4t1o
  126. 5N/xFk9akvuoyNGg/fYuJBmN162Q0MdeYfYKDGWdXxf6fpHxVr5v2JrIx6gOwubb
  127. cIKP22ZBv/PYOeFsAZ755lTl4OTFUjU5ZJEPD6pUc1daaIqfxsxu8gDZP92FZjsB
  128. zaalMbh30n2OhagSMBzSLg5rE6WmBzlQX0ZN8YrW4l2Vq6twnnFHY+UyblRZS+d4
  129. oHBaoOaxPEkLxNZ8ulzJS4B6c4D1CXOaBEf++snVzRRUOEdX3x7TvkkrLvIsm06R
  130. ux0L1zJb9LbZ/1rhuv70z/kIlD55sqYuRqu3RpgTgZuTERU//rYIqWd03Y5Qon8i
  131. VoC6Yp9DPldQJrk=
  132. -----END X509 CRL-----`
  133. client1Crt = `-----BEGIN CERTIFICATE-----
  134. MIIEITCCAgmgAwIBAgIRAJla/m/UkZMifNwG+DxFr2MwDQYJKoZIhvcNAQELBQAw
  135. EzERMA8GA1UEAxMIQ2VydEF1dGgwHhcNMjIwNzA0MTU0MzM3WhcNMjQwMTA0MTU1
  136. MzA3WjASMRAwDgYDVQQDEwdjbGllbnQxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
  137. MIIBCgKCAQEA8xM5v+2QfdzfwnNT5cl+6oEy2fZoI2YG6L6c25rG0pr+yl1IHKdM
  138. Zcvn93uat7hlbzxeOLfJRM7+QK1lLaxuppq9p+gT+1x9eG3E4X7e0pdbjrpJGbvN
  139. ji0hwDBLDWD8mHNq/SCk9FKtGnfZqrNB5BLw2uIKjJzVGXVlsjN6geBDm2hVjTSm
  140. zMr39CfLUdtvMaZhpIPJzbH+sNfp1zKavFIpmwCd77p/z0QAiQ9NaIvzv4PZDDEE
  141. MUHzmVAU6bUjD8GToXaMbRiz694SU8aAwvvcdjGexdbHnfSAfLOl2wTPPxvePncR
  142. aa656ZeZWxY9pRCItP+v43nm7d4sAyRD4QIDAQABo3EwbzAOBgNVHQ8BAf8EBAMC
  143. A7gwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBQbwDqF
  144. aja3ifZHm6mtSeTK9IHc+zAfBgNVHSMEGDAWgBT4qzwTztNc1Ln+8QvnbGzjmOUL
  145. wDANBgkqhkiG9w0BAQsFAAOCAgEAprE/zV6u8UIH8g4Jb73wtUD/eIL3iBJ7mNYa
  146. lqwCyJrWH7/F9fcovJnF9WO1QPTeHxhoD9rlQK70GitUAeboYw611yNWDS4tDlaL
  147. sjpJKykUxBgBR7QSLZCrPtQ3fP2WvlZzLGqB28rASTLphShqTuGp4gJaxGHfbCU7
  148. mlV9QYi+InQxOICJJPebXUOwx5wYkFQWJ9qE1AK3QrWPi8QYFznJvHgkNAaMBEmI
  149. jAlggOzpveVvy8f4z3QG9o29LIwp7JvtJQs7QXL80FZK98/8US/3gONwTrBz2Imx
  150. 28ywvwCq7fpMyPgxX4sXtxphCNim+vuHcqDn2CvLS9p/6L6zzqbFNxpmMkJDLrOc
  151. YqtHE4TLWIaXpb5JNrYJgNCZyJuYDICVTbivtMacHpSwYtXQ4iuzY2nIr0+4y9i9
  152. MNpqv3W47xnvgUQa5vbTbIqo2NSY24A84mF5EyjhaNgNtDlN56+qTQ6HLZNVr6pv
  153. eUCCWnY4GkaZUEU1M8/uNtKaZKv1WA7gJxZDQHj8+R110mPtzm1C5jqg7jSjGy9C
  154. 8PhAwBqIXkVLNayFEtyZZobTxMH5qY1yFkI3sic7S9ZyXt3quY1Q1UT3liRteIm/
  155. sZHC5zEoidsHObkTeU44hqZVPkbvrfmgW01xTJjddnMPBH+yqjCCc94yCbW79j/2
  156. 7LEmxYg=
  157. -----END CERTIFICATE-----`
  158. client1Key = `-----BEGIN RSA PRIVATE KEY-----
  159. MIIEpAIBAAKCAQEA8xM5v+2QfdzfwnNT5cl+6oEy2fZoI2YG6L6c25rG0pr+yl1I
  160. HKdMZcvn93uat7hlbzxeOLfJRM7+QK1lLaxuppq9p+gT+1x9eG3E4X7e0pdbjrpJ
  161. GbvNji0hwDBLDWD8mHNq/SCk9FKtGnfZqrNB5BLw2uIKjJzVGXVlsjN6geBDm2hV
  162. jTSmzMr39CfLUdtvMaZhpIPJzbH+sNfp1zKavFIpmwCd77p/z0QAiQ9NaIvzv4PZ
  163. DDEEMUHzmVAU6bUjD8GToXaMbRiz694SU8aAwvvcdjGexdbHnfSAfLOl2wTPPxve
  164. PncRaa656ZeZWxY9pRCItP+v43nm7d4sAyRD4QIDAQABAoIBADE17zcgDWSt1s8z
  165. MgUPahZn2beu3x5rhXKRRIhhKWdx4atufy7t39WsFmZQK96OAlsmyZyJ+MFpdqf5
  166. csZwZmZsZYEcxw7Yhr5e2sEcQlg4NF0M8ce38cGa+X5DSK6IuBrVIw/kEAE2y7zU
  167. Dsk0SV63RvPJV4FoLuxcjB4rtd2c+JBduNUXQYVppz/KhsXN+9CbPbZ7wo1cB5fo
  168. Iu/VswvvW6EAxVx39zZcwSGdkss9XUktU8akx7T/pepIH6fwkm7uXSNez6GH9d1I
  169. 8qOiORk/gAtqPL1TJgConyYheWMM9RbXP/IwL0BV8U4ZVG53S8jx2XpP4OJQ+k35
  170. WYvz8JECgYEA+9OywKOG2lMiiUB1qZfmXB80PngNsz+L6xUWkrw58gSqYZIg0xyH
  171. Sfr7HBo0yn/PB0oMMWPpNfYvG8/kSMIWiVlsYz9fdsUuqIvN+Kh9VF6o2wn+gnJk
  172. sBE3KVMofcgwgLE6eMVv2MSQlBoXhGPNlCBHS1gorQdYE82dxDPBBzsCgYEA9xpm
  173. c3C9LxiVbw9ZZ5D2C+vzwIG2+ZeDwKSizM1436MAnzNQgQTMzQ20uFGNBD562VjI
  174. rHFlZYr3KCtSIw5gvCSuox0YB64Yq/WAtGZtH9JyKRz4h4juq6iM4FT7nUwM4DF9
  175. 3CUiDS8DGoqvCNpY50GvzSR5QVT1DKTZsMunh5MCgYEAyIWMq7pK0iQqtvG9/3o1
  176. 8xrhxfBgsF+kcV+MZvE8jstKRIFQY+oujCkutPTlHm3hE2PSC64L8G0Em/fRRmJO
  177. AbZUCT9YK8HdYlZYf2zix0DM4gW2RHcEV/KNYvmVn3q9rGvzLGHCqu/yVAvmuAOk
  178. mhON0Z/0W7siVjp/KtEvHisCgYA/cfTaMRkyDXLY6C0BbXPvTa7xP5z2atO2U89F
  179. HICrkxOmzKsf5VacU6eSJ8Y4T76FLcmglSD+uHaLRsw5Ggj2Zci9MswntKi7Bjb8
  180. msvr/sG3EqwxSJRXWNiLBObx1UP9EFgLfTFIB0kZuIAGmuF2xyPXXUUQ5Dpi+7S1
  181. MyUZpwKBgQDg+AIPvk41vQ4Cz2CKrQX5/uJSW4bOhgP1yk7ruIH4Djkag3ZzTnHM
  182. zA9/pLzRfz1ENc5I/WaYSh92eKw3j6tUtMJlE2AbfCpgOQtRUNs3IBmzCWrY8J01
  183. W/8bwB+KhfFxNYwvszYsvvOq51NgahYQkgThVm38UixB3PFpEf+NiQ==
  184. -----END RSA PRIVATE KEY-----`
  185. // client 2 crt is revoked
  186. client2Crt = `-----BEGIN CERTIFICATE-----
  187. MIIEITCCAgmgAwIBAgIRANmjlDeWHEW4NSzEY2bv3hgwDQYJKoZIhvcNAQELBQAw
  188. EzERMA8GA1UEAxMIQ2VydEF1dGgwHhcNMjIwNzA0MTU0MzUxWhcNMjQwMTA0MTU1
  189. MzA3WjASMRAwDgYDVQQDEwdjbGllbnQyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
  190. MIIBCgKCAQEAzNl7q7yS8MSaQs6zRbuqrsUuwEJ5ZH85vf7zHZKgOW3zNniXLOmH
  191. JdtQ3jKZQ1BCIsJFvez2GxGIMWbXaSPw4bL0J3vl5oItChsjGg34IvqcDxWuIk2a
  192. muRdMh7r1ryVs2ir2cQ5YHzI59BEpUWKQg3bD4yragdkb6BRc7lVgzCbrM1Eq758
  193. HHbaLwlsfpqOvheaum4IG113CeD/HHrw42W6g/qQWL+FHlYqV3plHZ8Bj+bhcZI5
  194. jdU4paGEzeY0a0NlnyH4gXGPjLKvPKFZHy4D6RiRlLHvHeiRyDtTu4wFkAiXxzGs
  195. E4UBbykmYUB85zgwpjaktOaoe36IM1T8CQIDAQABo3EwbzAOBgNVHQ8BAf8EBAMC
  196. A7gwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBRdYIEk
  197. gxh+vTaMpAbqaPGRKGGBpTAfBgNVHSMEGDAWgBT4qzwTztNc1Ln+8QvnbGzjmOUL
  198. wDANBgkqhkiG9w0BAQsFAAOCAgEABSR/PbPfiNZ6FOrt91/I0g6LviwICDcuXhfr
  199. re4UsWp1kxXeS3CB2G71qXv3hswN8phG2hdsij0/FBEGUTLS3FTCmLmqmcVqPj3/
  200. 677PMFDoACBKgT5iIwpnNvdD+4ROM8JFjUwy7aTWx85a5yoPFGnB+ORMfLCYjr2S
  201. D02KFvKuSXWCjXphqJ41cFGne4oeh/JMkN0RNArm7wTT8yWCGgO1k4OON8dphuTV
  202. 48Wm6I9UBSWuLk1vcIlgb/8YWVwy9rBNmjOBDGuroL6PSmfZD+e9Etii0X2znZ+t
  203. qDpXJB7V5U0DbsBCtGM/dHaFz/LCoBYX9z6th1iPUHksUTM3RzN9L24r9/28dY/a
  204. shBpn5rK3ui/2mPBpO26wX14Kl/DUkdKUV9dJllSlmwo8Z0RluY9S4xnCrna/ODH
  205. FbhWmlTSs+odCZl6Lc0nuw+WQ2HnlTVJYBSFAGfsGQQ3pzk4DC5VynnxY0UniUgD
  206. WYPR8JEYa+BpH3rIQ9jmnOKWLtyc7lFPB9ab63pQBBiwRvWo+tZ2vybqjeHPuu5N
  207. BuKvvtu3RKKdSCnIo5Rs5zw4JYCjvlx/NVk9jtpa1lIHYHilvBmCcRX5DkE/yH/x
  208. IjEKhCOQpGR6D5Kkca9xNL7zNcat3bzLn+d7Wo4m09uWi9ifPdchxed0w5d9ihx1
  209. enqNrFI=
  210. -----END CERTIFICATE-----`
  211. client2Key = `-----BEGIN RSA PRIVATE KEY-----
  212. MIIEowIBAAKCAQEAzNl7q7yS8MSaQs6zRbuqrsUuwEJ5ZH85vf7zHZKgOW3zNniX
  213. LOmHJdtQ3jKZQ1BCIsJFvez2GxGIMWbXaSPw4bL0J3vl5oItChsjGg34IvqcDxWu
  214. Ik2amuRdMh7r1ryVs2ir2cQ5YHzI59BEpUWKQg3bD4yragdkb6BRc7lVgzCbrM1E
  215. q758HHbaLwlsfpqOvheaum4IG113CeD/HHrw42W6g/qQWL+FHlYqV3plHZ8Bj+bh
  216. cZI5jdU4paGEzeY0a0NlnyH4gXGPjLKvPKFZHy4D6RiRlLHvHeiRyDtTu4wFkAiX
  217. xzGsE4UBbykmYUB85zgwpjaktOaoe36IM1T8CQIDAQABAoIBAETHMJK0udFE8VZE
  218. +EQNgn0zj0LWDtQDM2vrUc04Ebu2gtZjHr7hmZLIVBqGepbzN4FcIPZnvSnRdRzB
  219. HsoaWyIsZ3VqUAJY6q5d9iclUY7M/eDCsripvaML0Y6meyCaKNkX57sx+uG+g+Xx
  220. M1saQhVzeX17CYKMANjJxw9HxsJI0aBPyiBbILHMwfRfsJU8Ou72HH1sIQuPdH2H
  221. /c9ru8YZAno6oVq1zuC/pCis+h50U9HzTnt3/4NNS6cWG/y2YLztCvm9uGo4MTd/
  222. mA9s4cxVhvQW6gCDHgGn6zj661OL/d2rpak1eWizhZvZ8jsIN/sM87b0AJeVT4zH
  223. 6xA3egECgYEA1nI5EsCetQbFBp7tDovSp3fbitwoQtdtHtLn2u4DfvmbLrgSoq0Z
  224. L+9N13xML/l8lzWai2gI69uA3c2+y1O64LkaiSeDqbeBp9b6fKMlmwIVbklEke1w
  225. XVTIWOYTTF5/8+tUOlsgme5BhLAWnQ7+SoitzHtl5e1vEYaAGamE2DECgYEA9Is2
  226. BbTk2YCqkcsB7D9q95JbY0SZpecvTv0rLR+acz3T8JrAASdmvqdBOlPWc+0ZaEdS
  227. PcJaOEw3yxYJ33cR/nLBaR2/Uu5qQebyPALs3B2pjjTFdGvcpeFxO55fowwsfR/e
  228. 0H+HeiFj5Y4S+kFWT+3FRmJ6GUB828LJYaVhQ1kCgYEA1bdsTdYN1Vfzz89fbZnH
  229. zQLUl6UlssfDhm6mhzeh4E+eaocke1+LtIwHxfOocj9v/bp8VObPzU8rNOIxfa3q
  230. lr+jRIFO5DtwSfckGEb32W3QMeNvJQe/biRqrr5NCVU8q7kibi4XZZFfVn+vacNh
  231. hqKEoz9vpCBnCs5CqFCbhmECgYAG8qWYR+lwnI08Ey58zdh2LDxYd6x94DGh5uOB
  232. JrK2r30ECwGFht8Ob6YUyCkBpizgn5YglxMFInU7Webx6GokdpI0MFotOwTd1nfv
  233. aI3eOyGEHs+1XRMpy1vyO6+v7DqfW3ZzKgxpVeWGsiCr54tSPgkq1MVvTju96qza
  234. D17SEQKBgCKC0GjDjnt/JvujdzHuBt1sWdOtb+B6kQvA09qVmuDF/Dq36jiaHDjg
  235. XMf5HU3ThYqYn3bYypZZ8nQ7BXVh4LqGNqG29wR4v6l+dLO6odXnLzfApGD9e+d4
  236. 2tmlLP54LaN35hQxRjhT8lCN0BkrNF44+bh8frwm/kuxSd8wT2S+
  237. -----END RSA PRIVATE KEY-----`
  238. testFileName = "test_file_dav.dat"
  239. testDLFileName = "test_download_dav.dat"
  240. tlsClient1Username = "client1"
  241. tlsClient2Username = "client2"
  242. emptyPwdPlaceholder = "empty"
  243. ocMtimeHeader = "X-OC-Mtime"
  244. )
  245. var (
  246. configDir = filepath.Join(".", "..", "..")
  247. allPerms = []string{dataprovider.PermAny}
  248. homeBasePath string
  249. hookCmdPath string
  250. extAuthPath string
  251. preLoginPath string
  252. postConnectPath string
  253. preDownloadPath string
  254. preUploadPath string
  255. logFilePath string
  256. certPath string
  257. keyPath string
  258. caCrtPath string
  259. caCRLPath string
  260. )
  261. func TestMain(m *testing.M) {
  262. logFilePath = filepath.Join(configDir, "sftpgo_webdavd_test.log")
  263. logger.InitLogger(logFilePath, 5, 1, 28, false, false, zerolog.DebugLevel)
  264. os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1")
  265. os.Setenv("SFTPGO_COMMON__ALLOW_SELF_CONNECTIONS", "1")
  266. os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin")
  267. os.Setenv("SFTPGO_DEFAULT_ADMIN_PASSWORD", "password")
  268. os.Setenv("SFTPGO_WEBDAVD__CACHE__MIME_TYPES__CUSTOM_MAPPINGS__0__EXT", ".sftpgo")
  269. os.Setenv("SFTPGO_WEBDAVD__CACHE__MIME_TYPES__CUSTOM_MAPPINGS__0__MIME", "application/sftpgo")
  270. err := config.LoadConfig(configDir, "")
  271. if err != nil {
  272. logger.ErrorToConsole("error loading configuration: %v", err)
  273. os.Exit(1)
  274. }
  275. providerConf := config.GetProviderConf()
  276. logger.InfoToConsole("Starting WebDAVD tests, provider: %v", providerConf.Driver)
  277. commonConf := config.GetCommonConfig()
  278. commonConf.UploadMode = 2
  279. homeBasePath = os.TempDir()
  280. if runtime.GOOS != osWindows {
  281. commonConf.Actions.ExecuteOn = []string{"download", "upload", "rename", "delete"}
  282. commonConf.Actions.Hook = hookCmdPath
  283. hookCmdPath, err = exec.LookPath("true")
  284. if err != nil {
  285. logger.Warn(logSender, "", "unable to get hook command: %v", err)
  286. logger.WarnToConsole("unable to get hook command: %v", err)
  287. }
  288. }
  289. certPath = filepath.Join(os.TempDir(), "test_dav.crt")
  290. keyPath = filepath.Join(os.TempDir(), "test_dav.key")
  291. caCrtPath = filepath.Join(os.TempDir(), "test_dav_ca.crt")
  292. caCRLPath = filepath.Join(os.TempDir(), "test_dav_crl.crt")
  293. err = os.WriteFile(certPath, []byte(webDavCert), os.ModePerm)
  294. if err != nil {
  295. logger.ErrorToConsole("error writing WebDAV certificate: %v", err)
  296. os.Exit(1)
  297. }
  298. err = os.WriteFile(keyPath, []byte(webDavKey), os.ModePerm)
  299. if err != nil {
  300. logger.ErrorToConsole("error writing WebDAV private key: %v", err)
  301. os.Exit(1)
  302. }
  303. err = os.WriteFile(caCrtPath, []byte(caCRT), os.ModePerm)
  304. if err != nil {
  305. logger.ErrorToConsole("error writing WebDAV CA crt: %v", err)
  306. os.Exit(1)
  307. }
  308. err = os.WriteFile(caCRLPath, []byte(caCRL), os.ModePerm)
  309. if err != nil {
  310. logger.ErrorToConsole("error writing WebDAV CRL: %v", err)
  311. os.Exit(1)
  312. }
  313. err = common.Initialize(commonConf, 0)
  314. if err != nil {
  315. logger.WarnToConsole("error initializing common: %v", err)
  316. os.Exit(1)
  317. }
  318. err = dataprovider.Initialize(providerConf, configDir, true)
  319. if err != nil {
  320. logger.ErrorToConsole("error initializing data provider: %v", err)
  321. os.Exit(1)
  322. }
  323. httpConfig := config.GetHTTPConfig()
  324. httpConfig.Initialize(configDir) //nolint:errcheck
  325. kmsConfig := config.GetKMSConfig()
  326. err = kmsConfig.Initialize()
  327. if err != nil {
  328. logger.ErrorToConsole("error initializing kms: %v", err)
  329. os.Exit(1)
  330. }
  331. httpdConf := config.GetHTTPDConfig()
  332. httpdConf.Bindings[0].Port = 8078
  333. httpdtest.SetBaseURL("http://127.0.0.1:8078")
  334. // required to test sftpfs
  335. sftpdConf := config.GetSFTPDConfig()
  336. sftpdConf.Bindings = []sftpd.Binding{
  337. {
  338. Port: 9022,
  339. },
  340. }
  341. hostKeyPath := filepath.Join(os.TempDir(), "id_ecdsa")
  342. sftpdConf.HostKeys = []string{hostKeyPath}
  343. webDavConf := config.GetWebDAVDConfig()
  344. webDavConf.CACertificates = []string{caCrtPath}
  345. webDavConf.CARevocationLists = []string{caCRLPath}
  346. webDavConf.Bindings = []webdavd.Binding{
  347. {
  348. Port: webDavServerPort,
  349. },
  350. {
  351. Port: webDavTLSServerPort,
  352. EnableHTTPS: true,
  353. CertificateFile: certPath,
  354. CertificateKeyFile: keyPath,
  355. ClientAuthType: 2,
  356. },
  357. }
  358. webDavConf.Cors = webdavd.CorsConfig{
  359. Enabled: true,
  360. AllowedOrigins: []string{"*"},
  361. AllowedMethods: []string{
  362. http.MethodHead,
  363. http.MethodGet,
  364. http.MethodPost,
  365. http.MethodPut,
  366. http.MethodPatch,
  367. http.MethodDelete,
  368. },
  369. AllowedHeaders: []string{"*"},
  370. AllowCredentials: true,
  371. }
  372. status := webdavd.GetStatus()
  373. if status.IsActive {
  374. logger.ErrorToConsole("webdav server is already active")
  375. os.Exit(1)
  376. }
  377. extAuthPath = filepath.Join(homeBasePath, "extauth.sh")
  378. preLoginPath = filepath.Join(homeBasePath, "prelogin.sh")
  379. postConnectPath = filepath.Join(homeBasePath, "postconnect.sh")
  380. preDownloadPath = filepath.Join(homeBasePath, "predownload.sh")
  381. preUploadPath = filepath.Join(homeBasePath, "preupload.sh")
  382. go func() {
  383. logger.Debug(logSender, "", "initializing WebDAV server with config %+v", webDavConf)
  384. if err := webDavConf.Initialize(configDir); err != nil {
  385. logger.ErrorToConsole("could not start WebDAV server: %v", err)
  386. os.Exit(1)
  387. }
  388. }()
  389. go func() {
  390. if err := httpdConf.Initialize(configDir, 0); err != nil {
  391. logger.ErrorToConsole("could not start HTTP server: %v", err)
  392. os.Exit(1)
  393. }
  394. }()
  395. go func() {
  396. logger.Debug(logSender, "", "initializing SFTP server with config %+v", sftpdConf)
  397. if err := sftpdConf.Initialize(configDir); err != nil {
  398. logger.ErrorToConsole("could not start SFTP server: %v", err)
  399. os.Exit(1)
  400. }
  401. }()
  402. waitTCPListening(webDavConf.Bindings[0].GetAddress())
  403. waitTCPListening(webDavConf.Bindings[1].GetAddress())
  404. waitTCPListening(httpdConf.Bindings[0].GetAddress())
  405. waitTCPListening(sftpdConf.Bindings[0].GetAddress())
  406. webdavd.ReloadCertificateMgr() //nolint:errcheck
  407. exitCode := m.Run()
  408. os.Remove(logFilePath)
  409. os.Remove(extAuthPath)
  410. os.Remove(preLoginPath)
  411. os.Remove(postConnectPath)
  412. os.Remove(preDownloadPath)
  413. os.Remove(preUploadPath)
  414. os.Remove(certPath)
  415. os.Remove(keyPath)
  416. os.Remove(caCrtPath)
  417. os.Remove(caCRLPath)
  418. os.Remove(hostKeyPath)
  419. os.Remove(hostKeyPath + ".pub")
  420. os.Exit(exitCode)
  421. }
  422. func TestInitialization(t *testing.T) {
  423. cfg := webdavd.Configuration{
  424. Bindings: []webdavd.Binding{
  425. {
  426. Port: 1234,
  427. EnableHTTPS: true,
  428. },
  429. {
  430. Port: 0,
  431. },
  432. },
  433. CertificateFile: "missing path",
  434. CertificateKeyFile: "bad path",
  435. }
  436. err := cfg.Initialize(configDir)
  437. assert.Error(t, err)
  438. cfg.Cache = config.GetWebDAVDConfig().Cache
  439. cfg.Bindings[0].Port = webDavServerPort
  440. cfg.CertificateFile = certPath
  441. cfg.CertificateKeyFile = keyPath
  442. err = cfg.Initialize(configDir)
  443. assert.Error(t, err)
  444. err = webdavd.ReloadCertificateMgr()
  445. assert.NoError(t, err)
  446. cfg.Bindings = []webdavd.Binding{
  447. {
  448. Port: 0,
  449. },
  450. }
  451. err = cfg.Initialize(configDir)
  452. assert.EqualError(t, err, common.ErrNoBinding.Error())
  453. cfg.CertificateFile = certPath
  454. cfg.CertificateKeyFile = keyPath
  455. cfg.CACertificates = []string{""}
  456. cfg.Bindings = []webdavd.Binding{
  457. {
  458. Port: 9022,
  459. ClientAuthType: 1,
  460. EnableHTTPS: true,
  461. },
  462. }
  463. err = cfg.Initialize(configDir)
  464. assert.Error(t, err)
  465. cfg.CACertificates = nil
  466. cfg.CARevocationLists = []string{""}
  467. err = cfg.Initialize(configDir)
  468. assert.Error(t, err)
  469. cfg.CARevocationLists = nil
  470. err = cfg.Initialize(configDir)
  471. assert.Error(t, err)
  472. cfg.CertificateFile = certPath
  473. cfg.CertificateKeyFile = keyPath
  474. cfg.CACertificates = []string{caCrtPath}
  475. cfg.CARevocationLists = []string{caCRLPath}
  476. cfg.Bindings[0].ProxyAllowed = []string{"not valid"}
  477. err = cfg.Initialize(configDir)
  478. if assert.Error(t, err) {
  479. assert.Contains(t, err.Error(), "is not a valid IP address")
  480. }
  481. cfg.Bindings[0].ProxyAllowed = nil
  482. err = cfg.Initialize(configDir)
  483. assert.Error(t, err)
  484. }
  485. func TestBasicHandling(t *testing.T) {
  486. u := getTestUser()
  487. u.QuotaSize = 6553600
  488. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  489. assert.NoError(t, err)
  490. u = getTestSFTPUser()
  491. u.QuotaSize = 6553600
  492. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  493. assert.NoError(t, err)
  494. for _, user := range []dataprovider.User{localUser, sftpUser} {
  495. client := getWebDavClient(user, true, nil)
  496. assert.NoError(t, checkBasicFunc(client))
  497. testFilePath := filepath.Join(homeBasePath, testFileName)
  498. testFileSize := int64(65535)
  499. expectedQuotaSize := testFileSize
  500. expectedQuotaFiles := 1
  501. err = createTestFile(testFilePath, testFileSize)
  502. assert.NoError(t, err)
  503. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  504. assert.NoError(t, err)
  505. assert.Equal(t, int64(0), user.FirstUpload)
  506. assert.Equal(t, int64(0), user.FirstDownload)
  507. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  508. true, testFileSize, client)
  509. assert.NoError(t, err)
  510. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  511. assert.NoError(t, err)
  512. assert.Greater(t, user.FirstUpload, int64(0))
  513. assert.Greater(t, user.FirstDownload, int64(0)) // webdav read the mime type
  514. // overwrite an existing file
  515. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  516. true, testFileSize, client)
  517. assert.NoError(t, err)
  518. // wrong password
  519. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword+"1",
  520. true, testFileSize, client)
  521. assert.Error(t, err)
  522. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  523. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  524. assert.NoError(t, err)
  525. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  526. assert.NoError(t, err)
  527. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  528. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  529. assert.Greater(t, user.FirstUpload, int64(0))
  530. assert.Greater(t, user.FirstDownload, int64(0))
  531. err = client.Rename(testFileName, testFileName+"1", false)
  532. assert.NoError(t, err)
  533. _, err = client.Stat(testFileName)
  534. assert.Error(t, err)
  535. // the webdav client hide the error we check the quota
  536. err = client.Remove(testFileName)
  537. assert.NoError(t, err)
  538. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  539. assert.NoError(t, err)
  540. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  541. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  542. err = client.Remove(testFileName + "1")
  543. assert.NoError(t, err)
  544. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  545. assert.NoError(t, err)
  546. assert.Equal(t, expectedQuotaFiles-1, user.UsedQuotaFiles)
  547. assert.Equal(t, expectedQuotaSize-testFileSize, user.UsedQuotaSize)
  548. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  549. assert.Error(t, err)
  550. testDir := "testdir"
  551. err = client.Mkdir(testDir, os.ModePerm)
  552. assert.NoError(t, err)
  553. err = client.MkdirAll(path.Join(testDir, "sub", "sub"), os.ModePerm)
  554. assert.NoError(t, err)
  555. err = client.MkdirAll(path.Join(testDir, "sub1", "sub1"), os.ModePerm)
  556. assert.NoError(t, err)
  557. err = client.MkdirAll(path.Join(testDir, "sub2", "sub2"), os.ModePerm)
  558. assert.NoError(t, err)
  559. err = uploadFileWithRawClient(testFilePath, path.Join(testDir, testFileName+".txt"),
  560. user.Username, defaultPassword, true, testFileSize, client)
  561. assert.NoError(t, err)
  562. err = uploadFileWithRawClient(testFilePath, path.Join(testDir, testFileName),
  563. user.Username, defaultPassword, true, testFileSize, client)
  564. assert.NoError(t, err)
  565. files, err := client.ReadDir(testDir)
  566. assert.NoError(t, err)
  567. assert.Len(t, files, 5)
  568. err = client.Copy(testDir, testDir+"_copy", false)
  569. assert.NoError(t, err)
  570. err = client.RemoveAll(testDir)
  571. assert.NoError(t, err)
  572. err = os.Remove(testFilePath)
  573. assert.NoError(t, err)
  574. err = os.Remove(localDownloadPath)
  575. assert.NoError(t, err)
  576. if user.Username == defaultUsername {
  577. err = os.RemoveAll(user.GetHomeDir())
  578. assert.NoError(t, err)
  579. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  580. assert.NoError(t, err)
  581. user.Password = defaultPassword
  582. user.ID = 0
  583. user.CreatedAt = 0
  584. _, resp, err := httpdtest.AddUser(user, http.StatusCreated)
  585. assert.NoError(t, err, string(resp))
  586. }
  587. }
  588. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  589. assert.NoError(t, err)
  590. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  591. assert.NoError(t, err)
  592. err = os.RemoveAll(localUser.GetHomeDir())
  593. assert.NoError(t, err)
  594. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  595. 1*time.Second, 100*time.Millisecond)
  596. status := webdavd.GetStatus()
  597. assert.True(t, status.IsActive)
  598. }
  599. func TestBasicHandlingCryptFs(t *testing.T) {
  600. u := getTestUserWithCryptFs()
  601. u.QuotaSize = 6553600
  602. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  603. assert.NoError(t, err)
  604. client := getWebDavClient(user, false, nil)
  605. assert.NoError(t, checkBasicFunc(client))
  606. testFilePath := filepath.Join(homeBasePath, testFileName)
  607. testFileSize := int64(65535)
  608. encryptedFileSize, err := getEncryptedFileSize(testFileSize)
  609. assert.NoError(t, err)
  610. expectedQuotaSize := user.UsedQuotaSize + encryptedFileSize
  611. expectedQuotaFiles := user.UsedQuotaFiles + 1
  612. err = createTestFile(testFilePath, testFileSize)
  613. assert.NoError(t, err)
  614. err = uploadFileWithRawClient(testFilePath, testFileName,
  615. user.Username, defaultPassword, false, testFileSize, client)
  616. assert.NoError(t, err)
  617. // overwrite an existing file
  618. err = uploadFileWithRawClient(testFilePath, testFileName,
  619. user.Username, defaultPassword, false, testFileSize, client)
  620. assert.NoError(t, err)
  621. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  622. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  623. assert.NoError(t, err)
  624. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  625. assert.NoError(t, err)
  626. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  627. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  628. files, err := client.ReadDir("/")
  629. assert.NoError(t, err)
  630. if assert.Len(t, files, 1) {
  631. assert.Equal(t, testFileSize, files[0].Size())
  632. }
  633. err = client.Remove(testFileName)
  634. assert.NoError(t, err)
  635. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  636. assert.NoError(t, err)
  637. assert.Equal(t, expectedQuotaFiles-1, user.UsedQuotaFiles)
  638. assert.Equal(t, expectedQuotaSize-encryptedFileSize, user.UsedQuotaSize)
  639. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  640. assert.Error(t, err)
  641. testDir := "testdir"
  642. err = client.Mkdir(testDir, os.ModePerm)
  643. assert.NoError(t, err)
  644. err = client.MkdirAll(path.Join(testDir, "sub", "sub"), os.ModePerm)
  645. assert.NoError(t, err)
  646. err = client.MkdirAll(path.Join(testDir, "sub1", "sub1"), os.ModePerm)
  647. assert.NoError(t, err)
  648. err = client.MkdirAll(path.Join(testDir, "sub2", "sub2"), os.ModePerm)
  649. assert.NoError(t, err)
  650. err = uploadFileWithRawClient(testFilePath, path.Join(testDir, testFileName+".txt"),
  651. user.Username, defaultPassword, false, testFileSize, client)
  652. assert.NoError(t, err)
  653. err = uploadFileWithRawClient(testFilePath, path.Join(testDir, testFileName),
  654. user.Username, defaultPassword, false, testFileSize, client)
  655. assert.NoError(t, err)
  656. files, err = client.ReadDir(testDir)
  657. assert.NoError(t, err)
  658. assert.Len(t, files, 5)
  659. for _, f := range files {
  660. if strings.HasPrefix(f.Name(), testFileName) {
  661. assert.Equal(t, testFileSize, f.Size())
  662. } else {
  663. assert.True(t, f.IsDir())
  664. }
  665. }
  666. err = os.Remove(testFilePath)
  667. assert.NoError(t, err)
  668. err = os.Remove(localDownloadPath)
  669. assert.NoError(t, err)
  670. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  671. assert.NoError(t, err)
  672. err = os.RemoveAll(user.GetHomeDir())
  673. assert.NoError(t, err)
  674. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  675. 1*time.Second, 100*time.Millisecond)
  676. }
  677. func TestLoginEmptyPassword(t *testing.T) {
  678. u := getTestUser()
  679. u.Password = ""
  680. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  681. assert.NoError(t, err)
  682. user.Password = emptyPwdPlaceholder
  683. client := getWebDavClient(user, false, nil)
  684. err = checkBasicFunc(client)
  685. if assert.Error(t, err) {
  686. assert.Contains(t, err.Error(), "401")
  687. }
  688. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  689. assert.NoError(t, err)
  690. err = os.RemoveAll(user.GetHomeDir())
  691. assert.NoError(t, err)
  692. }
  693. func TestAnonymousUser(t *testing.T) {
  694. u := getTestUser()
  695. u.Password = ""
  696. u.Filters.IsAnonymous = true
  697. _, _, err := httpdtest.AddUser(u, http.StatusCreated)
  698. assert.Error(t, err)
  699. user, _, err := httpdtest.GetUserByUsername(u.Username, http.StatusOK)
  700. assert.NoError(t, err)
  701. client := getWebDavClient(user, false, nil)
  702. assert.NoError(t, checkBasicFunc(client))
  703. user.Password = emptyPwdPlaceholder
  704. client = getWebDavClient(user, false, nil)
  705. assert.NoError(t, checkBasicFunc(client))
  706. testFilePath := filepath.Join(homeBasePath, testFileName)
  707. testFileSize := int64(65535)
  708. err = createTestFile(testFilePath, testFileSize)
  709. assert.NoError(t, err)
  710. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  711. false, testFileSize, client)
  712. if assert.Error(t, err) {
  713. assert.Contains(t, err.Error(), "403")
  714. }
  715. err = client.Mkdir("testdir", os.ModePerm)
  716. if assert.Error(t, err) {
  717. assert.Contains(t, err.Error(), "403")
  718. }
  719. err = os.Remove(testFilePath)
  720. assert.NoError(t, err)
  721. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  722. assert.NoError(t, err)
  723. err = os.RemoveAll(user.GetHomeDir())
  724. assert.NoError(t, err)
  725. }
  726. func TestLockAfterDelete(t *testing.T) {
  727. u := getTestUser()
  728. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  729. assert.NoError(t, err)
  730. client := getWebDavClient(user, false, nil)
  731. assert.NoError(t, checkBasicFunc(client))
  732. testFilePath := filepath.Join(homeBasePath, testFileName)
  733. testFileSize := int64(65535)
  734. err = createTestFile(testFilePath, testFileSize)
  735. assert.NoError(t, err)
  736. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  737. false, testFileSize, client)
  738. assert.NoError(t, err)
  739. lockBody := `<?xml version="1.0" encoding="utf-8" ?><d:lockinfo xmlns:d="DAV:"><d:lockscope><d:exclusive/></d:lockscope><d:locktype><d:write/></d:locktype></d:lockinfo>`
  740. req, err := http.NewRequest("LOCK", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(lockBody)))
  741. assert.NoError(t, err)
  742. req.SetBasicAuth(u.Username, u.Password)
  743. req.Header.Set("Timeout", "Second-3600")
  744. httpClient := httpclient.GetHTTPClient()
  745. resp, err := httpClient.Do(req)
  746. assert.NoError(t, err)
  747. assert.Equal(t, http.StatusOK, resp.StatusCode)
  748. response, err := io.ReadAll(resp.Body)
  749. assert.NoError(t, err)
  750. re := regexp.MustCompile(`\<D:locktoken><D:href>.*</D:href>`)
  751. lockToken := string(re.Find(response))
  752. lockToken = strings.Replace(lockToken, "<D:locktoken><D:href>", "", 1)
  753. lockToken = strings.Replace(lockToken, "</D:href>", "", 1)
  754. err = resp.Body.Close()
  755. assert.NoError(t, err)
  756. req, err = http.NewRequest(http.MethodDelete, fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), nil)
  757. assert.NoError(t, err)
  758. req.Header.Set("If", fmt.Sprintf("(%v)", lockToken))
  759. req.SetBasicAuth(u.Username, u.Password)
  760. resp, err = httpClient.Do(req)
  761. assert.NoError(t, err)
  762. assert.Equal(t, http.StatusNoContent, resp.StatusCode)
  763. err = resp.Body.Close()
  764. assert.NoError(t, err)
  765. // if we try to lock again it must succeed, the lock must be deleted with the object
  766. req, err = http.NewRequest("LOCK", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(lockBody)))
  767. assert.NoError(t, err)
  768. req.SetBasicAuth(u.Username, u.Password)
  769. resp, err = httpClient.Do(req)
  770. assert.NoError(t, err)
  771. assert.Equal(t, http.StatusCreated, resp.StatusCode)
  772. err = resp.Body.Close()
  773. assert.NoError(t, err)
  774. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  775. assert.NoError(t, err)
  776. err = os.RemoveAll(user.GetHomeDir())
  777. assert.NoError(t, err)
  778. }
  779. func TestMtimeHeader(t *testing.T) {
  780. u := getTestUser()
  781. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  782. assert.NoError(t, err)
  783. client := getWebDavClient(user, false, nil)
  784. assert.NoError(t, checkBasicFunc(client))
  785. testFilePath := filepath.Join(homeBasePath, testFileName)
  786. testFileSize := int64(65535)
  787. err = createTestFile(testFilePath, testFileSize)
  788. assert.NoError(t, err)
  789. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  790. false, testFileSize, client, dataprovider.KeyValue{Key: ocMtimeHeader, Value: "1668879480"})
  791. assert.NoError(t, err)
  792. // check the modification time
  793. info, err := client.Stat(testFileName)
  794. if assert.NoError(t, err) {
  795. assert.Equal(t, time.Unix(1668879480, 0).UTC(), info.ModTime().UTC())
  796. }
  797. // test on overwrite
  798. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  799. false, testFileSize, client, dataprovider.KeyValue{Key: ocMtimeHeader, Value: "1667879480"})
  800. assert.NoError(t, err)
  801. info, err = client.Stat(testFileName)
  802. if assert.NoError(t, err) {
  803. assert.Equal(t, time.Unix(1667879480, 0).UTC(), info.ModTime().UTC())
  804. }
  805. // invalid time will be silently ignored and the time set to now
  806. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  807. false, testFileSize, client, dataprovider.KeyValue{Key: ocMtimeHeader, Value: "not unix time"})
  808. assert.NoError(t, err)
  809. info, err = client.Stat(testFileName)
  810. if assert.NoError(t, err) {
  811. assert.NotEqual(t, time.Unix(1667879480, 0).UTC(), info.ModTime().UTC())
  812. }
  813. req, err := http.NewRequest("MOVE", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), nil)
  814. assert.NoError(t, err)
  815. req.Header.Set("Overwrite", "T")
  816. req.Header.Set("Destination", path.Join("/", testFileName+"rename"))
  817. req.Header.Set(ocMtimeHeader, "1666779480")
  818. req.SetBasicAuth(u.Username, u.Password)
  819. httpClient := httpclient.GetHTTPClient()
  820. resp, err := httpClient.Do(req)
  821. assert.NoError(t, err)
  822. assert.Equal(t, http.StatusCreated, resp.StatusCode)
  823. err = resp.Body.Close()
  824. assert.NoError(t, err)
  825. // check the modification time
  826. info, err = client.Stat(testFileName + "rename")
  827. if assert.NoError(t, err) {
  828. assert.Equal(t, time.Unix(1666779480, 0).UTC(), info.ModTime().UTC())
  829. }
  830. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  831. assert.NoError(t, err)
  832. err = os.RemoveAll(user.GetHomeDir())
  833. assert.NoError(t, err)
  834. }
  835. func TestRenameWithLock(t *testing.T) {
  836. u := getTestUser()
  837. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  838. assert.NoError(t, err)
  839. client := getWebDavClient(user, false, nil)
  840. assert.NoError(t, checkBasicFunc(client))
  841. testFilePath := filepath.Join(homeBasePath, testFileName)
  842. testFileSize := int64(65535)
  843. err = createTestFile(testFilePath, testFileSize)
  844. assert.NoError(t, err)
  845. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  846. false, testFileSize, client)
  847. assert.NoError(t, err)
  848. lockBody := `<?xml version="1.0" encoding="utf-8" ?><d:lockinfo xmlns:d="DAV:"><d:lockscope><d:exclusive/></d:lockscope><d:locktype><d:write/></d:locktype></d:lockinfo>`
  849. req, err := http.NewRequest("LOCK", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(lockBody)))
  850. assert.NoError(t, err)
  851. req.SetBasicAuth(u.Username, u.Password)
  852. httpClient := httpclient.GetHTTPClient()
  853. resp, err := httpClient.Do(req)
  854. assert.NoError(t, err)
  855. assert.Equal(t, http.StatusOK, resp.StatusCode)
  856. response, err := io.ReadAll(resp.Body)
  857. assert.NoError(t, err)
  858. re := regexp.MustCompile(`\<D:locktoken><D:href>.*</D:href>`)
  859. lockToken := string(re.Find(response))
  860. lockToken = strings.Replace(lockToken, "<D:locktoken><D:href>", "", 1)
  861. lockToken = strings.Replace(lockToken, "</D:href>", "", 1)
  862. err = resp.Body.Close()
  863. assert.NoError(t, err)
  864. // MOVE with a lock should succeeded
  865. req, err = http.NewRequest("MOVE", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), nil)
  866. assert.NoError(t, err)
  867. req.Header.Set("If", fmt.Sprintf("(%v)", lockToken))
  868. req.Header.Set("Overwrite", "T")
  869. req.Header.Set("Destination", path.Join("/", testFileName+"1"))
  870. req.SetBasicAuth(u.Username, u.Password)
  871. resp, err = httpClient.Do(req)
  872. assert.NoError(t, err)
  873. assert.Equal(t, http.StatusCreated, resp.StatusCode)
  874. err = resp.Body.Close()
  875. assert.NoError(t, err)
  876. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  877. assert.NoError(t, err)
  878. err = os.RemoveAll(user.GetHomeDir())
  879. assert.NoError(t, err)
  880. }
  881. func TestPropPatch(t *testing.T) {
  882. u := getTestUser()
  883. u.Username = u.Username + "1"
  884. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  885. assert.NoError(t, err)
  886. sftpUser := getTestSFTPUser()
  887. sftpUser.FsConfig.SFTPConfig.Username = localUser.Username
  888. for _, u := range []dataprovider.User{getTestUser(), getTestUserWithCryptFs(), sftpUser} {
  889. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  890. assert.NoError(t, err)
  891. client := getWebDavClient(user, true, nil)
  892. assert.NoError(t, checkBasicFunc(client), sftpUser.Username)
  893. testFilePath := filepath.Join(homeBasePath, testFileName)
  894. testFileSize := int64(65535)
  895. err = createTestFile(testFilePath, testFileSize)
  896. assert.NoError(t, err)
  897. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  898. false, testFileSize, client)
  899. assert.NoError(t, err)
  900. httpClient := httpclient.GetHTTPClient()
  901. 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>`
  902. req, err := http.NewRequest("PROPPATCH", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(propatchBody)))
  903. assert.NoError(t, err)
  904. req.SetBasicAuth(u.Username, u.Password)
  905. resp, err := httpClient.Do(req)
  906. assert.NoError(t, err)
  907. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  908. err = resp.Body.Close()
  909. assert.NoError(t, err)
  910. info, err := client.Stat(testFileName)
  911. if assert.NoError(t, err) {
  912. expected, err := http.ParseTime("Wed, 04 Nov 2020 13:25:51 GMT")
  913. assert.NoError(t, err)
  914. assert.Equal(t, testFileSize, info.Size())
  915. assert.Equal(t, expected.Format(http.TimeFormat), info.ModTime().Format(http.TimeFormat))
  916. }
  917. // wrong date
  918. 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>Wid, 04 Nov 2020 13:25:51 GMT</Z:Win32LastModifiedTime><Z:Win32FileAttributes>00000000</Z:Win32FileAttributes></D:prop></D:set></D:propertyupdate>`
  919. req, err = http.NewRequest("PROPPATCH", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(propatchBody)))
  920. assert.NoError(t, err)
  921. req.SetBasicAuth(u.Username, u.Password)
  922. resp, err = httpClient.Do(req)
  923. assert.NoError(t, err)
  924. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  925. err = resp.Body.Close()
  926. assert.NoError(t, err)
  927. err = os.Remove(testFilePath)
  928. assert.NoError(t, err)
  929. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  930. assert.NoError(t, err)
  931. err = os.RemoveAll(user.GetHomeDir())
  932. assert.NoError(t, err)
  933. }
  934. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  935. assert.NoError(t, err)
  936. err = os.RemoveAll(localUser.GetHomeDir())
  937. assert.NoError(t, err)
  938. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  939. 1*time.Second, 100*time.Millisecond)
  940. }
  941. func TestLoginInvalidPwd(t *testing.T) {
  942. u := getTestUser()
  943. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  944. assert.NoError(t, err)
  945. client := getWebDavClient(user, false, nil)
  946. assert.NoError(t, checkBasicFunc(client))
  947. user.Password = "wrong"
  948. client = getWebDavClient(user, false, nil)
  949. assert.Error(t, checkBasicFunc(client))
  950. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  951. assert.NoError(t, err)
  952. }
  953. func TestLoginNonExistentUser(t *testing.T) {
  954. user := getTestUser()
  955. client := getWebDavClient(user, true, nil)
  956. assert.Error(t, checkBasicFunc(client))
  957. }
  958. func TestRateLimiter(t *testing.T) {
  959. oldConfig := config.GetCommonConfig()
  960. cfg := config.GetCommonConfig()
  961. cfg.RateLimitersConfig = []common.RateLimiterConfig{
  962. {
  963. Average: 1,
  964. Period: 1000,
  965. Burst: 3,
  966. Type: 1,
  967. Protocols: []string{common.ProtocolWebDAV},
  968. },
  969. }
  970. err := common.Initialize(cfg, 0)
  971. assert.NoError(t, err)
  972. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  973. assert.NoError(t, err)
  974. client := getWebDavClient(user, false, nil)
  975. assert.NoError(t, checkBasicFunc(client))
  976. _, err = client.ReadDir(".")
  977. if assert.Error(t, err) {
  978. assert.Contains(t, err.Error(), "429")
  979. }
  980. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  981. assert.NoError(t, err)
  982. err = os.RemoveAll(user.GetHomeDir())
  983. assert.NoError(t, err)
  984. err = common.Initialize(oldConfig, 0)
  985. assert.NoError(t, err)
  986. }
  987. func TestDefender(t *testing.T) {
  988. oldConfig := config.GetCommonConfig()
  989. cfg := config.GetCommonConfig()
  990. cfg.DefenderConfig.Enabled = true
  991. cfg.DefenderConfig.Threshold = 3
  992. cfg.DefenderConfig.ScoreLimitExceeded = 2
  993. err := common.Initialize(cfg, 0)
  994. assert.NoError(t, err)
  995. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  996. assert.NoError(t, err)
  997. client := getWebDavClient(user, true, nil)
  998. assert.NoError(t, checkBasicFunc(client))
  999. for i := 0; i < 3; i++ {
  1000. user.Password = "wrong_pwd"
  1001. client = getWebDavClient(user, false, nil)
  1002. assert.Error(t, checkBasicFunc(client))
  1003. }
  1004. user.Password = defaultPassword
  1005. client = getWebDavClient(user, true, nil)
  1006. err = checkBasicFunc(client)
  1007. if assert.Error(t, err) {
  1008. assert.Contains(t, err.Error(), "403")
  1009. }
  1010. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1011. assert.NoError(t, err)
  1012. err = os.RemoveAll(user.GetHomeDir())
  1013. assert.NoError(t, err)
  1014. err = common.Initialize(oldConfig, 0)
  1015. assert.NoError(t, err)
  1016. }
  1017. func TestLoginExternalAuth(t *testing.T) {
  1018. if runtime.GOOS == osWindows {
  1019. t.Skip("this test is not available on Windows")
  1020. }
  1021. u := getTestUser()
  1022. err := dataprovider.Close()
  1023. assert.NoError(t, err)
  1024. err = config.LoadConfig(configDir, "")
  1025. assert.NoError(t, err)
  1026. providerConf := config.GetProviderConf()
  1027. err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u), os.ModePerm)
  1028. assert.NoError(t, err)
  1029. providerConf.ExternalAuthHook = extAuthPath
  1030. providerConf.ExternalAuthScope = 0
  1031. err = dataprovider.Initialize(providerConf, configDir, true)
  1032. assert.NoError(t, err)
  1033. client := getWebDavClient(u, false, nil)
  1034. assert.NoError(t, checkBasicFunc(client))
  1035. u.Username = defaultUsername + "1"
  1036. client = getWebDavClient(u, false, nil)
  1037. assert.Error(t, checkBasicFunc(client))
  1038. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  1039. assert.NoError(t, err)
  1040. assert.Equal(t, defaultUsername, user.Username)
  1041. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1042. assert.NoError(t, err)
  1043. err = os.RemoveAll(user.GetHomeDir())
  1044. assert.NoError(t, err)
  1045. err = dataprovider.Close()
  1046. assert.NoError(t, err)
  1047. err = config.LoadConfig(configDir, "")
  1048. assert.NoError(t, err)
  1049. providerConf = config.GetProviderConf()
  1050. err = dataprovider.Initialize(providerConf, configDir, true)
  1051. assert.NoError(t, err)
  1052. err = os.Remove(extAuthPath)
  1053. assert.NoError(t, err)
  1054. }
  1055. func TestExternalAuthReturningAnonymousUser(t *testing.T) {
  1056. if runtime.GOOS == osWindows {
  1057. t.Skip("this test is not available on Windows")
  1058. }
  1059. u := getTestUser()
  1060. u.Filters.IsAnonymous = true
  1061. u.Filters.DeniedProtocols = []string{common.ProtocolSSH}
  1062. u.Password = ""
  1063. err := dataprovider.Close()
  1064. assert.NoError(t, err)
  1065. err = config.LoadConfig(configDir, "")
  1066. assert.NoError(t, err)
  1067. providerConf := config.GetProviderConf()
  1068. err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u), os.ModePerm)
  1069. assert.NoError(t, err)
  1070. providerConf.ExternalAuthHook = extAuthPath
  1071. providerConf.ExternalAuthScope = 0
  1072. err = dataprovider.Initialize(providerConf, configDir, true)
  1073. assert.NoError(t, err)
  1074. client := getWebDavClient(u, false, nil)
  1075. assert.NoError(t, checkBasicFunc(client))
  1076. testFilePath := filepath.Join(homeBasePath, testFileName)
  1077. testFileSize := int64(65535)
  1078. err = createTestFile(testFilePath, testFileSize)
  1079. assert.NoError(t, err)
  1080. err = uploadFileWithRawClient(testFilePath, testFileName, u.Username, emptyPwdPlaceholder,
  1081. false, testFileSize, client)
  1082. if assert.Error(t, err) {
  1083. assert.Contains(t, err.Error(), "403")
  1084. }
  1085. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  1086. assert.NoError(t, err)
  1087. assert.True(t, user.Filters.IsAnonymous)
  1088. assert.Equal(t, []string{dataprovider.PermListItems, dataprovider.PermDownload}, user.Permissions["/"])
  1089. assert.Equal(t, []string{common.ProtocolSSH, common.ProtocolHTTP}, user.Filters.DeniedProtocols)
  1090. assert.Equal(t, []string{dataprovider.SSHLoginMethodPublicKey, dataprovider.SSHLoginMethodPassword,
  1091. dataprovider.SSHLoginMethodKeyboardInteractive, dataprovider.SSHLoginMethodKeyAndPassword,
  1092. dataprovider.SSHLoginMethodKeyAndKeyboardInt, dataprovider.LoginMethodTLSCertificate,
  1093. dataprovider.LoginMethodTLSCertificateAndPwd}, user.Filters.DeniedLoginMethods)
  1094. u.Password = emptyPwdPlaceholder
  1095. client = getWebDavClient(user, false, nil)
  1096. assert.NoError(t, checkBasicFunc(client))
  1097. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1098. false, testFileSize, client)
  1099. if assert.Error(t, err) {
  1100. assert.Contains(t, err.Error(), "403")
  1101. }
  1102. err = client.Mkdir("testdir", os.ModePerm)
  1103. if assert.Error(t, err) {
  1104. assert.Contains(t, err.Error(), "403")
  1105. }
  1106. err = os.Remove(testFilePath)
  1107. assert.NoError(t, err)
  1108. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1109. assert.NoError(t, err)
  1110. err = os.RemoveAll(user.GetHomeDir())
  1111. assert.NoError(t, err)
  1112. err = dataprovider.Close()
  1113. assert.NoError(t, err)
  1114. err = config.LoadConfig(configDir, "")
  1115. assert.NoError(t, err)
  1116. providerConf = config.GetProviderConf()
  1117. err = dataprovider.Initialize(providerConf, configDir, true)
  1118. assert.NoError(t, err)
  1119. err = os.Remove(extAuthPath)
  1120. assert.NoError(t, err)
  1121. }
  1122. func TestExternalAuthAnonymousGroupInheritance(t *testing.T) {
  1123. if runtime.GOOS == osWindows {
  1124. t.Skip("this test is not available on Windows")
  1125. }
  1126. g := dataprovider.Group{
  1127. BaseGroup: sdk.BaseGroup{
  1128. Name: "test_group",
  1129. },
  1130. UserSettings: dataprovider.GroupUserSettings{
  1131. BaseGroupUserSettings: sdk.BaseGroupUserSettings{
  1132. Permissions: map[string][]string{
  1133. "/": allPerms,
  1134. },
  1135. Filters: sdk.BaseUserFilters{
  1136. IsAnonymous: true,
  1137. },
  1138. },
  1139. },
  1140. }
  1141. u := getTestUser()
  1142. u.Groups = []sdk.GroupMapping{
  1143. {
  1144. Name: g.Name,
  1145. Type: sdk.GroupTypePrimary,
  1146. },
  1147. }
  1148. err := dataprovider.Close()
  1149. assert.NoError(t, err)
  1150. err = config.LoadConfig(configDir, "")
  1151. assert.NoError(t, err)
  1152. providerConf := config.GetProviderConf()
  1153. err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u), os.ModePerm)
  1154. assert.NoError(t, err)
  1155. providerConf.ExternalAuthHook = extAuthPath
  1156. providerConf.ExternalAuthScope = 0
  1157. err = dataprovider.Initialize(providerConf, configDir, true)
  1158. assert.NoError(t, err)
  1159. group, _, err := httpdtest.AddGroup(g, http.StatusCreated)
  1160. assert.NoError(t, err)
  1161. u.Password = emptyPwdPlaceholder
  1162. client := getWebDavClient(u, false, nil)
  1163. assert.NoError(t, checkBasicFunc(client))
  1164. err = client.Mkdir("tdir", os.ModePerm)
  1165. if assert.Error(t, err) {
  1166. assert.Contains(t, err.Error(), "403")
  1167. }
  1168. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  1169. assert.NoError(t, err)
  1170. assert.False(t, user.Filters.IsAnonymous)
  1171. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1172. assert.NoError(t, err)
  1173. err = os.RemoveAll(user.GetHomeDir())
  1174. assert.NoError(t, err)
  1175. _, err = httpdtest.RemoveGroup(group, http.StatusOK)
  1176. assert.NoError(t, err)
  1177. err = dataprovider.Close()
  1178. assert.NoError(t, err)
  1179. err = config.LoadConfig(configDir, "")
  1180. assert.NoError(t, err)
  1181. providerConf = config.GetProviderConf()
  1182. err = dataprovider.Initialize(providerConf, configDir, true)
  1183. assert.NoError(t, err)
  1184. err = os.Remove(extAuthPath)
  1185. assert.NoError(t, err)
  1186. }
  1187. func TestPreLoginHook(t *testing.T) {
  1188. if runtime.GOOS == osWindows {
  1189. t.Skip("this test is not available on Windows")
  1190. }
  1191. u := getTestUser()
  1192. err := dataprovider.Close()
  1193. assert.NoError(t, err)
  1194. err = config.LoadConfig(configDir, "")
  1195. assert.NoError(t, err)
  1196. providerConf := config.GetProviderConf()
  1197. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
  1198. assert.NoError(t, err)
  1199. providerConf.PreLoginHook = preLoginPath
  1200. err = dataprovider.Initialize(providerConf, configDir, true)
  1201. assert.NoError(t, err)
  1202. _, _, err = httpdtest.GetUserByUsername(defaultUsername, http.StatusNotFound)
  1203. assert.NoError(t, err)
  1204. client := getWebDavClient(u, true, nil)
  1205. assert.NoError(t, checkBasicFunc(client))
  1206. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  1207. assert.NoError(t, err)
  1208. // test login with an existing user
  1209. client = getWebDavClient(user, true, nil)
  1210. assert.NoError(t, checkBasicFunc(client))
  1211. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), os.ModePerm)
  1212. assert.NoError(t, err)
  1213. // update the user to remove it from the cache
  1214. user.FsConfig.Provider = sdk.CryptedFilesystemProvider
  1215. user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret(defaultPassword)
  1216. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1217. assert.NoError(t, err)
  1218. client = getWebDavClient(user, true, nil)
  1219. assert.Error(t, checkBasicFunc(client))
  1220. // update the user to remove it from the cache
  1221. user.FsConfig.Provider = sdk.LocalFilesystemProvider
  1222. user.FsConfig.CryptConfig.Passphrase = nil
  1223. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1224. assert.NoError(t, err)
  1225. user.Status = 0
  1226. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), os.ModePerm)
  1227. assert.NoError(t, err)
  1228. client = getWebDavClient(user, true, nil)
  1229. assert.Error(t, checkBasicFunc(client))
  1230. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1231. assert.NoError(t, err)
  1232. err = os.RemoveAll(user.GetHomeDir())
  1233. assert.NoError(t, err)
  1234. err = dataprovider.Close()
  1235. assert.NoError(t, err)
  1236. err = config.LoadConfig(configDir, "")
  1237. assert.NoError(t, err)
  1238. providerConf = config.GetProviderConf()
  1239. err = dataprovider.Initialize(providerConf, configDir, true)
  1240. assert.NoError(t, err)
  1241. err = os.Remove(preLoginPath)
  1242. assert.NoError(t, err)
  1243. }
  1244. func TestPreDownloadHook(t *testing.T) {
  1245. if runtime.GOOS == osWindows {
  1246. t.Skip("this test is not available on Windows")
  1247. }
  1248. oldExecuteOn := common.Config.Actions.ExecuteOn
  1249. oldHook := common.Config.Actions.Hook
  1250. common.Config.Actions.ExecuteOn = []string{common.OperationPreDownload}
  1251. common.Config.Actions.Hook = preDownloadPath
  1252. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1253. assert.NoError(t, err)
  1254. err = os.WriteFile(preDownloadPath, getExitCodeScriptContent(0), os.ModePerm)
  1255. assert.NoError(t, err)
  1256. client := getWebDavClient(user, true, nil)
  1257. assert.NoError(t, checkBasicFunc(client))
  1258. testFilePath := filepath.Join(homeBasePath, testFileName)
  1259. testFileSize := int64(65535)
  1260. err = createTestFile(testFilePath, testFileSize)
  1261. assert.NoError(t, err)
  1262. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1263. true, testFileSize, client)
  1264. assert.NoError(t, err)
  1265. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1266. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1267. assert.NoError(t, err)
  1268. err = os.Remove(localDownloadPath)
  1269. assert.NoError(t, err)
  1270. err = os.WriteFile(preDownloadPath, getExitCodeScriptContent(1), os.ModePerm)
  1271. assert.NoError(t, err)
  1272. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1273. assert.Error(t, err)
  1274. err = os.Remove(localDownloadPath)
  1275. assert.NoError(t, err)
  1276. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1277. assert.NoError(t, err)
  1278. err = os.RemoveAll(user.GetHomeDir())
  1279. assert.NoError(t, err)
  1280. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  1281. 1*time.Second, 100*time.Millisecond)
  1282. common.Config.Actions.ExecuteOn = []string{common.OperationPreDownload}
  1283. common.Config.Actions.Hook = preDownloadPath
  1284. common.Config.Actions.ExecuteOn = oldExecuteOn
  1285. common.Config.Actions.Hook = oldHook
  1286. }
  1287. func TestPreUploadHook(t *testing.T) {
  1288. if runtime.GOOS == osWindows {
  1289. t.Skip("this test is not available on Windows")
  1290. }
  1291. oldExecuteOn := common.Config.Actions.ExecuteOn
  1292. oldHook := common.Config.Actions.Hook
  1293. common.Config.Actions.ExecuteOn = []string{common.OperationPreUpload}
  1294. common.Config.Actions.Hook = preUploadPath
  1295. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1296. assert.NoError(t, err)
  1297. err = os.WriteFile(preUploadPath, getExitCodeScriptContent(0), os.ModePerm)
  1298. assert.NoError(t, err)
  1299. client := getWebDavClient(user, true, nil)
  1300. assert.NoError(t, checkBasicFunc(client))
  1301. testFilePath := filepath.Join(homeBasePath, testFileName)
  1302. testFileSize := int64(65535)
  1303. err = createTestFile(testFilePath, testFileSize)
  1304. assert.NoError(t, err)
  1305. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1306. true, testFileSize, client)
  1307. assert.NoError(t, err)
  1308. err = os.WriteFile(preUploadPath, getExitCodeScriptContent(1), os.ModePerm)
  1309. assert.NoError(t, err)
  1310. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1311. true, testFileSize, client)
  1312. assert.Error(t, err)
  1313. err = uploadFileWithRawClient(testFilePath, testFileName+"1", user.Username, defaultPassword,
  1314. false, testFileSize, client)
  1315. assert.Error(t, err)
  1316. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1317. assert.NoError(t, err)
  1318. err = os.RemoveAll(user.GetHomeDir())
  1319. assert.NoError(t, err)
  1320. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  1321. 1*time.Second, 100*time.Millisecond)
  1322. common.Config.Actions.ExecuteOn = oldExecuteOn
  1323. common.Config.Actions.Hook = oldHook
  1324. }
  1325. func TestPostConnectHook(t *testing.T) {
  1326. if runtime.GOOS == osWindows {
  1327. t.Skip("this test is not available on Windows")
  1328. }
  1329. common.Config.PostConnectHook = postConnectPath
  1330. u := getTestUser()
  1331. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1332. assert.NoError(t, err)
  1333. err = os.WriteFile(postConnectPath, getExitCodeScriptContent(0), os.ModePerm)
  1334. assert.NoError(t, err)
  1335. client := getWebDavClient(user, false, nil)
  1336. assert.NoError(t, checkBasicFunc(client))
  1337. err = os.WriteFile(postConnectPath, getExitCodeScriptContent(1), os.ModePerm)
  1338. assert.NoError(t, err)
  1339. assert.Error(t, checkBasicFunc(client))
  1340. common.Config.PostConnectHook = "http://127.0.0.1:8078/healthz"
  1341. assert.NoError(t, checkBasicFunc(client))
  1342. common.Config.PostConnectHook = "http://127.0.0.1:8078/notfound"
  1343. assert.Error(t, checkBasicFunc(client))
  1344. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1345. assert.NoError(t, err)
  1346. err = os.RemoveAll(user.GetHomeDir())
  1347. assert.NoError(t, err)
  1348. common.Config.PostConnectHook = ""
  1349. }
  1350. func TestMaxConnections(t *testing.T) {
  1351. oldValue := common.Config.MaxTotalConnections
  1352. common.Config.MaxTotalConnections = 1
  1353. assert.Eventually(t, func() bool {
  1354. return common.Connections.GetClientConnections() == 0
  1355. }, 1000*time.Millisecond, 50*time.Millisecond)
  1356. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1357. assert.NoError(t, err)
  1358. client := getWebDavClient(user, true, nil)
  1359. assert.NoError(t, checkBasicFunc(client))
  1360. // now add a fake connection
  1361. fs := vfs.NewOsFs("id", os.TempDir(), "")
  1362. connection := &webdavd.Connection{
  1363. BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
  1364. }
  1365. err = common.Connections.Add(connection)
  1366. assert.NoError(t, err)
  1367. assert.Error(t, checkBasicFunc(client))
  1368. common.Connections.Remove(connection.GetID())
  1369. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1370. assert.NoError(t, err)
  1371. err = os.RemoveAll(user.GetHomeDir())
  1372. assert.NoError(t, err)
  1373. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  1374. 1*time.Second, 100*time.Millisecond)
  1375. common.Config.MaxTotalConnections = oldValue
  1376. }
  1377. func TestMaxPerHostConnections(t *testing.T) {
  1378. oldValue := common.Config.MaxPerHostConnections
  1379. common.Config.MaxPerHostConnections = 1
  1380. assert.Eventually(t, func() bool {
  1381. return common.Connections.GetClientConnections() == 0
  1382. }, 1000*time.Millisecond, 50*time.Millisecond)
  1383. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1384. assert.NoError(t, err)
  1385. client := getWebDavClient(user, true, nil)
  1386. assert.NoError(t, checkBasicFunc(client))
  1387. // now add a fake connection
  1388. addrs, err := net.LookupHost("localhost")
  1389. assert.NoError(t, err)
  1390. for _, addr := range addrs {
  1391. common.Connections.AddClientConnection(addr)
  1392. }
  1393. assert.Error(t, checkBasicFunc(client))
  1394. for _, addr := range addrs {
  1395. common.Connections.RemoveClientConnection(addr)
  1396. }
  1397. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1398. assert.NoError(t, err)
  1399. err = os.RemoveAll(user.GetHomeDir())
  1400. assert.NoError(t, err)
  1401. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  1402. 1*time.Second, 100*time.Millisecond)
  1403. common.Config.MaxPerHostConnections = oldValue
  1404. }
  1405. func TestMustChangePasswordRequirement(t *testing.T) {
  1406. u := getTestUser()
  1407. u.Filters.RequirePasswordChange = true
  1408. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1409. assert.NoError(t, err)
  1410. client := getWebDavClient(user, false, nil)
  1411. assert.Error(t, checkBasicFunc(client))
  1412. err = dataprovider.UpdateUserPassword(user.Username, defaultPassword, "", "", "")
  1413. assert.NoError(t, err)
  1414. client = getWebDavClient(user, false, nil)
  1415. assert.NoError(t, checkBasicFunc(client))
  1416. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1417. assert.NoError(t, err)
  1418. err = os.RemoveAll(user.GetHomeDir())
  1419. assert.NoError(t, err)
  1420. }
  1421. func TestMaxSessions(t *testing.T) {
  1422. u := getTestUser()
  1423. u.MaxSessions = 1
  1424. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1425. assert.NoError(t, err)
  1426. client := getWebDavClient(user, false, nil)
  1427. assert.NoError(t, checkBasicFunc(client))
  1428. // now add a fake connection
  1429. fs := vfs.NewOsFs("id", os.TempDir(), "")
  1430. connection := &webdavd.Connection{
  1431. BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
  1432. }
  1433. err = common.Connections.Add(connection)
  1434. assert.NoError(t, err)
  1435. assert.Error(t, checkBasicFunc(client))
  1436. common.Connections.Remove(connection.GetID())
  1437. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1438. assert.NoError(t, err)
  1439. err = os.RemoveAll(user.GetHomeDir())
  1440. assert.NoError(t, err)
  1441. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  1442. 1*time.Second, 100*time.Millisecond)
  1443. }
  1444. func TestLoginWithIPilters(t *testing.T) {
  1445. u := getTestUser()
  1446. u.Filters.DeniedIP = []string{"192.167.0.0/24", "172.18.0.0/16"}
  1447. u.Filters.AllowedIP = []string{"172.19.0.0/16"}
  1448. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1449. assert.NoError(t, err)
  1450. client := getWebDavClient(user, true, nil)
  1451. assert.Error(t, checkBasicFunc(client))
  1452. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1453. assert.NoError(t, err)
  1454. err = os.RemoveAll(user.GetHomeDir())
  1455. assert.NoError(t, err)
  1456. }
  1457. func TestDownloadErrors(t *testing.T) {
  1458. u := getTestUser()
  1459. u.QuotaFiles = 1
  1460. subDir1 := "sub1"
  1461. subDir2 := "sub2"
  1462. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems}
  1463. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  1464. dataprovider.PermDelete, dataprovider.PermDownload}
  1465. // use an unknown mime to trigger content type detection
  1466. u.Filters.FilePatterns = []sdk.PatternsFilter{
  1467. {
  1468. Path: "/sub2",
  1469. AllowedPatterns: []string{},
  1470. DeniedPatterns: []string{"*.jpg", "*.zipp"},
  1471. },
  1472. }
  1473. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1474. assert.NoError(t, err)
  1475. client := getWebDavClient(user, false, nil)
  1476. testFilePath1 := filepath.Join(user.HomeDir, subDir1, "file.zipp")
  1477. testFilePath2 := filepath.Join(user.HomeDir, subDir2, "file.zipp")
  1478. testFilePath3 := filepath.Join(user.HomeDir, subDir2, "file.jpg")
  1479. err = os.MkdirAll(filepath.Dir(testFilePath1), os.ModePerm)
  1480. assert.NoError(t, err)
  1481. err = os.MkdirAll(filepath.Dir(testFilePath2), os.ModePerm)
  1482. assert.NoError(t, err)
  1483. err = os.WriteFile(testFilePath1, []byte("file1"), os.ModePerm)
  1484. assert.NoError(t, err)
  1485. err = os.WriteFile(testFilePath2, []byte("file2"), os.ModePerm)
  1486. assert.NoError(t, err)
  1487. err = os.WriteFile(testFilePath3, []byte("file3"), os.ModePerm)
  1488. assert.NoError(t, err)
  1489. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1490. err = downloadFile(path.Join("/", subDir1, "file.zipp"), localDownloadPath, 5, client)
  1491. assert.Error(t, err)
  1492. err = downloadFile(path.Join("/", subDir2, "file.zipp"), localDownloadPath, 5, client)
  1493. assert.Error(t, err)
  1494. err = downloadFile(path.Join("/", subDir2, "file.jpg"), localDownloadPath, 5, client)
  1495. assert.Error(t, err)
  1496. err = downloadFile(path.Join("missing.zip"), localDownloadPath, 5, client)
  1497. assert.Error(t, err)
  1498. err = os.Remove(localDownloadPath)
  1499. assert.NoError(t, err)
  1500. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1501. assert.NoError(t, err)
  1502. err = os.RemoveAll(user.GetHomeDir())
  1503. assert.NoError(t, err)
  1504. }
  1505. func TestUploadErrors(t *testing.T) {
  1506. u := getTestUser()
  1507. u.QuotaSize = 65535
  1508. subDir1 := "sub1"
  1509. subDir2 := "sub2"
  1510. // we need download permission to get size since PROPFIND will open the file
  1511. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems, dataprovider.PermDownload}
  1512. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  1513. dataprovider.PermDelete, dataprovider.PermDownload}
  1514. u.Filters.FilePatterns = []sdk.PatternsFilter{
  1515. {
  1516. Path: "/sub2",
  1517. AllowedPatterns: []string{},
  1518. DeniedPatterns: []string{"*.zip"},
  1519. },
  1520. }
  1521. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1522. assert.NoError(t, err)
  1523. client := getWebDavClient(user, true, nil)
  1524. testFilePath := filepath.Join(homeBasePath, testFileName)
  1525. testFileSize := user.QuotaSize
  1526. err = createTestFile(testFilePath, testFileSize)
  1527. assert.NoError(t, err)
  1528. err = client.Mkdir(subDir1, os.ModePerm)
  1529. assert.NoError(t, err)
  1530. err = client.Mkdir(subDir2, os.ModePerm)
  1531. assert.NoError(t, err)
  1532. err = uploadFileWithRawClient(testFilePath, path.Join(subDir1, testFileName), user.Username,
  1533. defaultPassword, true, testFileSize, client)
  1534. assert.Error(t, err)
  1535. err = uploadFileWithRawClient(testFilePath, path.Join(subDir2, testFileName+".zip"), user.Username,
  1536. defaultPassword, true, testFileSize, client)
  1537. assert.Error(t, err)
  1538. err = uploadFileWithRawClient(testFilePath, path.Join(subDir2, testFileName), user.Username,
  1539. defaultPassword, true, testFileSize, client)
  1540. assert.NoError(t, err)
  1541. err = client.Rename(path.Join(subDir2, testFileName), path.Join(subDir1, testFileName), false)
  1542. assert.Error(t, err)
  1543. err = uploadFileWithRawClient(testFilePath, path.Join(subDir2, testFileName), user.Username,
  1544. defaultPassword, true, testFileSize, client)
  1545. assert.Error(t, err)
  1546. err = uploadFileWithRawClient(testFilePath, subDir1, user.Username,
  1547. defaultPassword, true, testFileSize, client)
  1548. assert.Error(t, err)
  1549. // overquota
  1550. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1551. true, testFileSize, client)
  1552. assert.Error(t, err)
  1553. err = client.Remove(path.Join(subDir2, testFileName))
  1554. assert.NoError(t, err)
  1555. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1556. true, testFileSize, client)
  1557. assert.NoError(t, err)
  1558. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1559. true, testFileSize, client)
  1560. assert.Error(t, err)
  1561. err = os.Remove(testFilePath)
  1562. assert.NoError(t, err)
  1563. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1564. assert.NoError(t, err)
  1565. err = os.RemoveAll(user.GetHomeDir())
  1566. assert.NoError(t, err)
  1567. }
  1568. func TestDeniedLoginMethod(t *testing.T) {
  1569. u := getTestUser()
  1570. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword}
  1571. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1572. assert.NoError(t, err)
  1573. client := getWebDavClient(user, true, nil)
  1574. assert.Error(t, checkBasicFunc(client))
  1575. user.Filters.DeniedLoginMethods = []string{dataprovider.SSHLoginMethodPublicKey, dataprovider.SSHLoginMethodKeyAndKeyboardInt}
  1576. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1577. assert.NoError(t, err)
  1578. client = getWebDavClient(user, true, nil)
  1579. assert.NoError(t, checkBasicFunc(client))
  1580. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1581. assert.NoError(t, err)
  1582. err = os.RemoveAll(user.GetHomeDir())
  1583. assert.NoError(t, err)
  1584. }
  1585. func TestDeniedProtocols(t *testing.T) {
  1586. u := getTestUser()
  1587. u.Filters.DeniedProtocols = []string{common.ProtocolWebDAV}
  1588. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1589. assert.NoError(t, err)
  1590. client := getWebDavClient(user, false, nil)
  1591. assert.Error(t, checkBasicFunc(client))
  1592. user.Filters.DeniedProtocols = []string{common.ProtocolSSH, common.ProtocolFTP}
  1593. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1594. assert.NoError(t, err)
  1595. client = getWebDavClient(user, false, nil)
  1596. assert.NoError(t, checkBasicFunc(client))
  1597. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1598. assert.NoError(t, err)
  1599. err = os.RemoveAll(user.GetHomeDir())
  1600. assert.NoError(t, err)
  1601. }
  1602. func TestQuotaLimits(t *testing.T) {
  1603. u := getTestUser()
  1604. u.QuotaFiles = 1
  1605. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1606. assert.NoError(t, err)
  1607. u = getTestSFTPUser()
  1608. u.QuotaFiles = 1
  1609. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1610. assert.NoError(t, err)
  1611. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1612. testFileSize := int64(65536)
  1613. testFilePath := filepath.Join(homeBasePath, testFileName)
  1614. err = createTestFile(testFilePath, testFileSize)
  1615. assert.NoError(t, err)
  1616. testFileSize1 := int64(131072)
  1617. testFileName1 := "test_file1.dat"
  1618. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  1619. err = createTestFile(testFilePath1, testFileSize1)
  1620. assert.NoError(t, err)
  1621. testFileSize2 := int64(32768)
  1622. testFileName2 := "test_file2.dat"
  1623. testFilePath2 := filepath.Join(homeBasePath, testFileName2)
  1624. err = createTestFile(testFilePath2, testFileSize2)
  1625. assert.NoError(t, err)
  1626. client := getWebDavClient(user, false, nil)
  1627. // test quota files
  1628. err = uploadFileWithRawClient(testFilePath, testFileName+".quota", user.Username, defaultPassword, false,
  1629. testFileSize, client)
  1630. if !assert.NoError(t, err, "username: %v", user.Username) {
  1631. info, err := os.Stat(testFilePath)
  1632. if assert.NoError(t, err) {
  1633. fmt.Printf("local file size: %v\n", info.Size())
  1634. }
  1635. printLatestLogs(20)
  1636. }
  1637. err = uploadFileWithRawClient(testFilePath, testFileName+".quota1", user.Username, defaultPassword,
  1638. false, testFileSize, client)
  1639. assert.Error(t, err, "username: %v", user.Username)
  1640. err = client.Rename(testFileName+".quota", testFileName, false)
  1641. assert.NoError(t, err)
  1642. files, err := client.ReadDir("/")
  1643. assert.NoError(t, err)
  1644. assert.Len(t, files, 1)
  1645. // test quota size
  1646. user.QuotaSize = testFileSize - 1
  1647. user.QuotaFiles = 0
  1648. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1649. assert.NoError(t, err)
  1650. err = uploadFileWithRawClient(testFilePath, testFileName+".quota", user.Username, defaultPassword,
  1651. false, testFileSize, client)
  1652. assert.Error(t, err)
  1653. err = client.Rename(testFileName, testFileName+".quota", false)
  1654. assert.NoError(t, err)
  1655. // now test quota limits while uploading the current file, we have 1 bytes remaining
  1656. user.QuotaSize = testFileSize + 1
  1657. user.QuotaFiles = 0
  1658. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1659. assert.NoError(t, err)
  1660. err = uploadFileWithRawClient(testFilePath1, testFileName1, user.Username, defaultPassword,
  1661. false, testFileSize1, client)
  1662. assert.Error(t, err)
  1663. _, err = client.Stat(testFileName1)
  1664. assert.Error(t, err)
  1665. err = client.Rename(testFileName+".quota", testFileName, false)
  1666. assert.NoError(t, err)
  1667. // overwriting an existing file will work if the resulting size is lesser or equal than the current one
  1668. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1669. false, testFileSize, client)
  1670. assert.NoError(t, err)
  1671. err = uploadFileWithRawClient(testFilePath2, testFileName, user.Username, defaultPassword,
  1672. false, testFileSize2, client)
  1673. assert.NoError(t, err)
  1674. err = uploadFileWithRawClient(testFilePath1, testFileName, user.Username, defaultPassword,
  1675. false, testFileSize1, client)
  1676. assert.Error(t, err)
  1677. err = uploadFileWithRawClient(testFilePath2, testFileName, user.Username, defaultPassword,
  1678. false, testFileSize2, client)
  1679. assert.NoError(t, err)
  1680. err = os.Remove(testFilePath)
  1681. assert.NoError(t, err)
  1682. err = os.Remove(testFilePath1)
  1683. assert.NoError(t, err)
  1684. err = os.Remove(testFilePath2)
  1685. assert.NoError(t, err)
  1686. if user.Username == defaultUsername {
  1687. err = os.RemoveAll(user.GetHomeDir())
  1688. assert.NoError(t, err)
  1689. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1690. assert.NoError(t, err)
  1691. user.Password = defaultPassword
  1692. user.ID = 0
  1693. user.CreatedAt = 0
  1694. user.QuotaFiles = 0
  1695. user.QuotaSize = 0
  1696. _, resp, err := httpdtest.AddUser(user, http.StatusCreated)
  1697. assert.NoError(t, err, string(resp))
  1698. }
  1699. }
  1700. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1701. assert.NoError(t, err)
  1702. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1703. assert.NoError(t, err)
  1704. err = os.RemoveAll(localUser.GetHomeDir())
  1705. assert.NoError(t, err)
  1706. }
  1707. func TestTransferQuotaLimits(t *testing.T) {
  1708. u := getTestUser()
  1709. u.DownloadDataTransfer = 1
  1710. u.UploadDataTransfer = 1
  1711. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1712. assert.NoError(t, err)
  1713. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1714. testFilePath := filepath.Join(homeBasePath, testFileName)
  1715. testFileSize := int64(550000)
  1716. err = createTestFile(testFilePath, testFileSize)
  1717. assert.NoError(t, err)
  1718. client := getWebDavClient(user, false, nil)
  1719. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1720. false, testFileSize, client)
  1721. assert.NoError(t, err)
  1722. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1723. assert.NoError(t, err)
  1724. // error while download is active
  1725. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1726. assert.Error(t, err)
  1727. // error before starting the download
  1728. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1729. assert.Error(t, err)
  1730. // error while upload is active
  1731. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1732. false, testFileSize, client)
  1733. assert.Error(t, err)
  1734. // error before starting the upload
  1735. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1736. false, testFileSize, client)
  1737. assert.Error(t, err)
  1738. err = os.Remove(localDownloadPath)
  1739. assert.NoError(t, err)
  1740. err = os.Remove(testFilePath)
  1741. assert.NoError(t, err)
  1742. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1743. assert.NoError(t, err)
  1744. err = os.RemoveAll(user.GetHomeDir())
  1745. assert.NoError(t, err)
  1746. }
  1747. func TestUploadMaxSize(t *testing.T) {
  1748. testFileSize := int64(65535)
  1749. u := getTestUser()
  1750. u.Filters.MaxUploadFileSize = testFileSize + 1
  1751. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1752. assert.NoError(t, err)
  1753. u = getTestSFTPUser()
  1754. u.Filters.MaxUploadFileSize = testFileSize + 1
  1755. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1756. assert.NoError(t, err)
  1757. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1758. testFilePath := filepath.Join(homeBasePath, testFileName)
  1759. err = createTestFile(testFilePath, testFileSize)
  1760. assert.NoError(t, err)
  1761. testFileSize1 := int64(131072)
  1762. testFileName1 := "test_file_dav1.dat"
  1763. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  1764. err = createTestFile(testFilePath1, testFileSize1)
  1765. assert.NoError(t, err)
  1766. client := getWebDavClient(user, false, nil)
  1767. err = uploadFileWithRawClient(testFilePath1, testFileName1, user.Username, defaultPassword,
  1768. false, testFileSize1, client)
  1769. assert.Error(t, err)
  1770. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1771. false, testFileSize, client)
  1772. assert.NoError(t, err)
  1773. // now test overwrite an existing file with a size bigger than the allowed one
  1774. err = createTestFile(filepath.Join(user.GetHomeDir(), testFileName1), testFileSize1)
  1775. assert.NoError(t, err)
  1776. err = uploadFileWithRawClient(testFilePath1, testFileName1, user.Username, defaultPassword,
  1777. false, testFileSize1, client)
  1778. assert.Error(t, err)
  1779. err = os.Remove(testFilePath)
  1780. assert.NoError(t, err)
  1781. err = os.Remove(testFilePath1)
  1782. assert.NoError(t, err)
  1783. if user.Username == defaultUsername {
  1784. err = os.RemoveAll(user.GetHomeDir())
  1785. assert.NoError(t, err)
  1786. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1787. assert.NoError(t, err)
  1788. user.Filters.MaxUploadFileSize = 65536000
  1789. user.Password = defaultPassword
  1790. user.ID = 0
  1791. user.CreatedAt = 0
  1792. _, resp, err := httpdtest.AddUser(user, http.StatusCreated)
  1793. assert.NoError(t, err, string(resp))
  1794. }
  1795. }
  1796. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1797. assert.NoError(t, err)
  1798. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1799. assert.NoError(t, err)
  1800. err = os.RemoveAll(localUser.GetHomeDir())
  1801. assert.NoError(t, err)
  1802. }
  1803. func TestClientClose(t *testing.T) {
  1804. u := getTestUser()
  1805. u.UploadBandwidth = 64
  1806. u.DownloadBandwidth = 64
  1807. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1808. assert.NoError(t, err)
  1809. u = getTestSFTPUser()
  1810. u.UploadBandwidth = 64
  1811. u.DownloadBandwidth = 64
  1812. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1813. assert.NoError(t, err)
  1814. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1815. testFileSize := int64(1048576)
  1816. testFilePath := filepath.Join(homeBasePath, testFileName)
  1817. err = createTestFile(testFilePath, testFileSize)
  1818. assert.NoError(t, err)
  1819. client := getWebDavClient(user, true, nil)
  1820. assert.NoError(t, checkBasicFunc(client))
  1821. var wg sync.WaitGroup
  1822. wg.Add(1)
  1823. go func() {
  1824. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1825. true, testFileSize, client)
  1826. assert.Error(t, err)
  1827. wg.Done()
  1828. }()
  1829. assert.Eventually(t, func() bool {
  1830. for _, stat := range common.Connections.GetStats("") {
  1831. if len(stat.Transfers) > 0 {
  1832. return true
  1833. }
  1834. }
  1835. return false
  1836. }, 1*time.Second, 50*time.Millisecond)
  1837. for _, stat := range common.Connections.GetStats("") {
  1838. common.Connections.Close(stat.ConnectionID, "")
  1839. }
  1840. wg.Wait()
  1841. // for the sftp user a stat is done after the failed upload and
  1842. // this triggers a new connection
  1843. for _, stat := range common.Connections.GetStats("") {
  1844. common.Connections.Close(stat.ConnectionID, "")
  1845. }
  1846. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  1847. 1*time.Second, 100*time.Millisecond)
  1848. err = os.Remove(testFilePath)
  1849. assert.NoError(t, err)
  1850. testFilePath = filepath.Join(user.HomeDir, testFileName)
  1851. err = createTestFile(testFilePath, testFileSize)
  1852. assert.NoError(t, err)
  1853. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1854. wg.Add(1)
  1855. go func() {
  1856. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1857. assert.Error(t, err)
  1858. wg.Done()
  1859. }()
  1860. assert.Eventually(t, func() bool {
  1861. for _, stat := range common.Connections.GetStats("") {
  1862. if len(stat.Transfers) > 0 {
  1863. return true
  1864. }
  1865. }
  1866. return false
  1867. }, 1*time.Second, 50*time.Millisecond)
  1868. for _, stat := range common.Connections.GetStats("") {
  1869. common.Connections.Close(stat.ConnectionID, "")
  1870. }
  1871. wg.Wait()
  1872. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  1873. 1*time.Second, 100*time.Millisecond)
  1874. err = os.Remove(localDownloadPath)
  1875. assert.NoError(t, err)
  1876. }
  1877. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1878. assert.NoError(t, err)
  1879. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1880. assert.NoError(t, err)
  1881. err = os.RemoveAll(localUser.GetHomeDir())
  1882. assert.NoError(t, err)
  1883. }
  1884. func TestLoginWithDatabaseCredentials(t *testing.T) {
  1885. u := getTestUser()
  1886. u.FsConfig.Provider = sdk.GCSFilesystemProvider
  1887. u.FsConfig.GCSConfig.Bucket = "test"
  1888. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret(`{ "type": "service_account" }`)
  1889. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1890. assert.NoError(t, err)
  1891. assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.GCSConfig.Credentials.GetStatus())
  1892. assert.NotEmpty(t, user.FsConfig.GCSConfig.Credentials.GetPayload())
  1893. assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetAdditionalData())
  1894. assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetKey())
  1895. client := getWebDavClient(user, false, nil)
  1896. err = client.Connect()
  1897. assert.NoError(t, err)
  1898. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1899. assert.NoError(t, err)
  1900. err = os.RemoveAll(user.GetHomeDir())
  1901. assert.NoError(t, err)
  1902. }
  1903. func TestLoginInvalidFs(t *testing.T) {
  1904. u := getTestUser()
  1905. u.FsConfig.Provider = sdk.GCSFilesystemProvider
  1906. u.FsConfig.GCSConfig.Bucket = "test"
  1907. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("invalid JSON for credentials")
  1908. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1909. assert.NoError(t, err)
  1910. client := getWebDavClient(user, true, nil)
  1911. assert.Error(t, checkBasicFunc(client))
  1912. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1913. assert.NoError(t, err)
  1914. err = os.RemoveAll(user.GetHomeDir())
  1915. assert.NoError(t, err)
  1916. }
  1917. func TestSFTPBuffered(t *testing.T) {
  1918. u := getTestUser()
  1919. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1920. assert.NoError(t, err)
  1921. u = getTestSFTPUser()
  1922. u.QuotaFiles = 1000
  1923. u.HomeDir = filepath.Join(os.TempDir(), u.Username)
  1924. u.FsConfig.SFTPConfig.BufferSize = 2
  1925. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1926. assert.NoError(t, err)
  1927. client := getWebDavClient(sftpUser, true, nil)
  1928. assert.NoError(t, checkBasicFunc(client))
  1929. testFilePath := filepath.Join(homeBasePath, testFileName)
  1930. testFileSize := int64(65535)
  1931. expectedQuotaSize := testFileSize
  1932. expectedQuotaFiles := 1
  1933. err = createTestFile(testFilePath, testFileSize)
  1934. assert.NoError(t, err)
  1935. err = uploadFileWithRawClient(testFilePath, testFileName, sftpUser.Username, defaultPassword,
  1936. true, testFileSize, client)
  1937. assert.NoError(t, err)
  1938. // overwrite an existing file
  1939. err = uploadFileWithRawClient(testFilePath, testFileName, sftpUser.Username, defaultPassword,
  1940. true, testFileSize, client)
  1941. assert.NoError(t, err)
  1942. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1943. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1944. assert.NoError(t, err)
  1945. user, _, err := httpdtest.GetUserByUsername(sftpUser.Username, http.StatusOK)
  1946. assert.NoError(t, err)
  1947. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  1948. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  1949. fileContent := []byte("test file contents")
  1950. err = os.WriteFile(testFilePath, fileContent, os.ModePerm)
  1951. assert.NoError(t, err)
  1952. err = uploadFileWithRawClient(testFilePath, testFileName, sftpUser.Username, defaultPassword,
  1953. true, int64(len(fileContent)), client)
  1954. assert.NoError(t, err)
  1955. remotePath := fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName)
  1956. req, err := http.NewRequest(http.MethodGet, remotePath, nil)
  1957. assert.NoError(t, err)
  1958. httpClient := httpclient.GetHTTPClient()
  1959. req.SetBasicAuth(user.Username, defaultPassword)
  1960. req.Header.Set("Range", "bytes=5-")
  1961. resp, err := httpClient.Do(req)
  1962. if assert.NoError(t, err) {
  1963. defer resp.Body.Close()
  1964. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  1965. bodyBytes, err := io.ReadAll(resp.Body)
  1966. assert.NoError(t, err)
  1967. assert.Equal(t, "file contents", string(bodyBytes))
  1968. }
  1969. req.Header.Set("Range", "bytes=5-8")
  1970. resp, err = httpClient.Do(req)
  1971. if assert.NoError(t, err) {
  1972. defer resp.Body.Close()
  1973. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  1974. bodyBytes, err := io.ReadAll(resp.Body)
  1975. assert.NoError(t, err)
  1976. assert.Equal(t, "file", string(bodyBytes))
  1977. }
  1978. err = os.Remove(testFilePath)
  1979. assert.NoError(t, err)
  1980. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1981. assert.NoError(t, err)
  1982. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1983. assert.NoError(t, err)
  1984. err = os.RemoveAll(localUser.GetHomeDir())
  1985. assert.NoError(t, err)
  1986. err = os.RemoveAll(sftpUser.GetHomeDir())
  1987. assert.NoError(t, err)
  1988. }
  1989. func TestBytesRangeRequests(t *testing.T) {
  1990. u := getTestUser()
  1991. u.Username = u.Username + "1"
  1992. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1993. assert.NoError(t, err)
  1994. sftpUser := getTestSFTPUser()
  1995. sftpUser.FsConfig.SFTPConfig.Username = localUser.Username
  1996. for _, u := range []dataprovider.User{getTestUser(), getTestUserWithCryptFs(), sftpUser} {
  1997. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1998. assert.NoError(t, err)
  1999. testFileName := "test_file.txt"
  2000. testFilePath := filepath.Join(homeBasePath, testFileName)
  2001. fileContent := []byte("test file contents")
  2002. err = os.WriteFile(testFilePath, fileContent, os.ModePerm)
  2003. assert.NoError(t, err)
  2004. client := getWebDavClient(user, true, nil)
  2005. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  2006. true, int64(len(fileContent)), client)
  2007. assert.NoError(t, err)
  2008. remotePath := fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName)
  2009. req, err := http.NewRequest(http.MethodGet, remotePath, nil)
  2010. if assert.NoError(t, err) {
  2011. httpClient := httpclient.GetHTTPClient()
  2012. req.SetBasicAuth(user.Username, defaultPassword)
  2013. req.Header.Set("Range", "bytes=5-")
  2014. resp, err := httpClient.Do(req)
  2015. if assert.NoError(t, err) {
  2016. defer resp.Body.Close()
  2017. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  2018. bodyBytes, err := io.ReadAll(resp.Body)
  2019. assert.NoError(t, err)
  2020. assert.Equal(t, "file contents", string(bodyBytes))
  2021. }
  2022. req.Header.Set("Range", "bytes=5-8")
  2023. resp, err = httpClient.Do(req)
  2024. if assert.NoError(t, err) {
  2025. defer resp.Body.Close()
  2026. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  2027. bodyBytes, err := io.ReadAll(resp.Body)
  2028. assert.NoError(t, err)
  2029. assert.Equal(t, "file", string(bodyBytes))
  2030. }
  2031. }
  2032. // seek on a missing file
  2033. remotePath = fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName+"_missing")
  2034. req, err = http.NewRequest(http.MethodGet, remotePath, nil)
  2035. if assert.NoError(t, err) {
  2036. httpClient := httpclient.GetHTTPClient()
  2037. req.SetBasicAuth(user.Username, defaultPassword)
  2038. req.Header.Set("Range", "bytes=5-")
  2039. resp, err := httpClient.Do(req)
  2040. if assert.NoError(t, err) {
  2041. defer resp.Body.Close()
  2042. assert.Equal(t, http.StatusNotFound, resp.StatusCode)
  2043. }
  2044. }
  2045. err = os.Remove(testFilePath)
  2046. assert.NoError(t, err)
  2047. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2048. assert.NoError(t, err)
  2049. err = os.RemoveAll(user.GetHomeDir())
  2050. assert.NoError(t, err)
  2051. }
  2052. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  2053. assert.NoError(t, err)
  2054. err = os.RemoveAll(localUser.GetHomeDir())
  2055. assert.NoError(t, err)
  2056. }
  2057. func TestContentTypeGET(t *testing.T) {
  2058. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  2059. assert.NoError(t, err)
  2060. testFilePath := filepath.Join(homeBasePath, testFileName)
  2061. testFileSize := int64(64)
  2062. err = createTestFile(testFilePath, testFileSize)
  2063. assert.NoError(t, err)
  2064. client := getWebDavClient(user, true, nil)
  2065. err = uploadFileWithRawClient(testFilePath, testFileName+".sftpgo", user.Username, defaultPassword,
  2066. true, testFileSize, client)
  2067. assert.NoError(t, err)
  2068. remotePath := fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName+".sftpgo")
  2069. req, err := http.NewRequest(http.MethodGet, remotePath, nil)
  2070. if assert.NoError(t, err) {
  2071. httpClient := httpclient.GetHTTPClient()
  2072. req.SetBasicAuth(user.Username, defaultPassword)
  2073. resp, err := httpClient.Do(req)
  2074. if assert.NoError(t, err) {
  2075. defer resp.Body.Close()
  2076. assert.Equal(t, http.StatusOK, resp.StatusCode)
  2077. assert.Equal(t, "application/sftpgo", resp.Header.Get("Content-Type"))
  2078. }
  2079. }
  2080. err = os.Remove(testFilePath)
  2081. assert.NoError(t, err)
  2082. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2083. assert.NoError(t, err)
  2084. err = os.RemoveAll(user.GetHomeDir())
  2085. assert.NoError(t, err)
  2086. }
  2087. func TestHEAD(t *testing.T) {
  2088. u := getTestUser()
  2089. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2090. assert.NoError(t, err)
  2091. rootPath := fmt.Sprintf("http://%v", webDavServerAddr)
  2092. httpClient := httpclient.GetHTTPClient()
  2093. req, err := http.NewRequest(http.MethodHead, rootPath, nil)
  2094. if assert.NoError(t, err) {
  2095. req.SetBasicAuth(u.Username, u.Password)
  2096. resp, err := httpClient.Do(req)
  2097. if assert.NoError(t, err) {
  2098. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  2099. assert.Equal(t, "text/xml; charset=utf-8", resp.Header.Get("Content-Type"))
  2100. resp.Body.Close()
  2101. }
  2102. }
  2103. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2104. assert.NoError(t, err)
  2105. err = os.RemoveAll(user.GetHomeDir())
  2106. assert.NoError(t, err)
  2107. }
  2108. func TestGETAsPROPFIND(t *testing.T) {
  2109. u := getTestUser()
  2110. subDir1 := "/sub1"
  2111. u.Permissions[subDir1] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs}
  2112. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2113. assert.NoError(t, err)
  2114. rootPath := fmt.Sprintf("http://%v/", webDavServerAddr)
  2115. httpClient := httpclient.GetHTTPClient()
  2116. req, err := http.NewRequest(http.MethodGet, rootPath, nil)
  2117. if assert.NoError(t, err) {
  2118. req.SetBasicAuth(u.Username, u.Password)
  2119. resp, err := httpClient.Do(req)
  2120. if assert.NoError(t, err) {
  2121. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  2122. resp.Body.Close()
  2123. }
  2124. }
  2125. client := getWebDavClient(user, false, nil)
  2126. err = client.MkdirAll(path.Join(subDir1, "sub", "sub1"), os.ModePerm)
  2127. assert.NoError(t, err)
  2128. subPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, subDir1)
  2129. req, err = http.NewRequest(http.MethodGet, subPath, nil)
  2130. if assert.NoError(t, err) {
  2131. req.SetBasicAuth(u.Username, u.Password)
  2132. resp, err := httpClient.Do(req)
  2133. if assert.NoError(t, err) {
  2134. // before the performance patch we have a 500 here, now we have 207 but an empty list
  2135. //assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
  2136. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  2137. resp.Body.Close()
  2138. }
  2139. }
  2140. // we cannot stat the sub at all
  2141. subPath1 := fmt.Sprintf("http://%v/%v", webDavServerAddr, path.Join(subDir1, "sub"))
  2142. req, err = http.NewRequest(http.MethodGet, subPath1, nil)
  2143. if assert.NoError(t, err) {
  2144. req.SetBasicAuth(u.Username, u.Password)
  2145. resp, err := httpClient.Do(req)
  2146. if assert.NoError(t, err) {
  2147. // here the stat will fail, so the request will not be changed in propfind
  2148. assert.Equal(t, http.StatusForbidden, resp.StatusCode)
  2149. resp.Body.Close()
  2150. }
  2151. }
  2152. // we have no permission, we get an empty list
  2153. files, err := client.ReadDir(subDir1)
  2154. assert.NoError(t, err)
  2155. assert.Len(t, files, 0)
  2156. // if we grant the permissions the files are listed
  2157. user.Permissions[subDir1] = []string{dataprovider.PermDownload, dataprovider.PermListItems}
  2158. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2159. assert.NoError(t, err)
  2160. files, err = client.ReadDir(subDir1)
  2161. assert.NoError(t, err)
  2162. assert.Len(t, files, 1)
  2163. // PROPFIND with infinity depth is forbidden
  2164. req, err = http.NewRequest(http.MethodGet, rootPath, nil)
  2165. if assert.NoError(t, err) {
  2166. req.SetBasicAuth(u.Username, u.Password)
  2167. req.Header.Set("Depth", "infinity")
  2168. resp, err := httpClient.Do(req)
  2169. if assert.NoError(t, err) {
  2170. assert.Equal(t, http.StatusForbidden, resp.StatusCode)
  2171. resp.Body.Close()
  2172. }
  2173. }
  2174. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2175. assert.NoError(t, err)
  2176. err = os.RemoveAll(user.GetHomeDir())
  2177. assert.NoError(t, err)
  2178. }
  2179. func TestStat(t *testing.T) {
  2180. u := getTestUser()
  2181. u.Permissions["/subdir"] = []string{dataprovider.PermUpload, dataprovider.PermListItems, dataprovider.PermDownload}
  2182. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2183. assert.NoError(t, err)
  2184. client := getWebDavClient(user, true, nil)
  2185. subDir := "subdir"
  2186. testFilePath := filepath.Join(homeBasePath, testFileName)
  2187. testFileSize := int64(65535)
  2188. err = createTestFile(testFilePath, testFileSize)
  2189. assert.NoError(t, err)
  2190. err = client.Mkdir(subDir, os.ModePerm)
  2191. assert.NoError(t, err)
  2192. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  2193. true, testFileSize, client)
  2194. assert.NoError(t, err)
  2195. err = uploadFileWithRawClient(testFilePath, path.Join("/", subDir, testFileName), user.Username,
  2196. defaultPassword, true, testFileSize, client)
  2197. assert.NoError(t, err)
  2198. user.Permissions["/subdir"] = []string{dataprovider.PermUpload, dataprovider.PermDownload}
  2199. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2200. assert.NoError(t, err)
  2201. _, err = client.Stat(testFileName)
  2202. assert.NoError(t, err)
  2203. _, err = client.Stat(path.Join("/", subDir, testFileName))
  2204. assert.Error(t, err)
  2205. err = os.Remove(testFilePath)
  2206. assert.NoError(t, err)
  2207. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2208. assert.NoError(t, err)
  2209. err = os.RemoveAll(user.GetHomeDir())
  2210. assert.NoError(t, err)
  2211. }
  2212. func TestUploadOverwriteVfolder(t *testing.T) {
  2213. u := getTestUser()
  2214. vdir := "/vdir"
  2215. mappedPath := filepath.Join(os.TempDir(), "mappedDir")
  2216. folderName := filepath.Base(mappedPath)
  2217. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2218. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2219. Name: folderName,
  2220. MappedPath: mappedPath,
  2221. },
  2222. VirtualPath: vdir,
  2223. QuotaSize: -1,
  2224. QuotaFiles: -1,
  2225. })
  2226. err := os.MkdirAll(mappedPath, os.ModePerm)
  2227. assert.NoError(t, err)
  2228. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2229. assert.NoError(t, err)
  2230. client := getWebDavClient(user, false, nil)
  2231. files, err := client.ReadDir(".")
  2232. assert.NoError(t, err)
  2233. vdirFound := false
  2234. for _, info := range files {
  2235. if info.Name() == path.Base(vdir) {
  2236. vdirFound = true
  2237. break
  2238. }
  2239. }
  2240. assert.True(t, vdirFound)
  2241. info, err := client.Stat(vdir)
  2242. if assert.NoError(t, err) {
  2243. assert.Equal(t, path.Base(vdir), info.Name())
  2244. }
  2245. testFilePath := filepath.Join(homeBasePath, testFileName)
  2246. testFileSize := int64(65535)
  2247. err = createTestFile(testFilePath, testFileSize)
  2248. assert.NoError(t, err)
  2249. err = uploadFileWithRawClient(testFilePath, path.Join(vdir, testFileName), user.Username,
  2250. defaultPassword, true, testFileSize, client)
  2251. assert.NoError(t, err)
  2252. folder, _, err := httpdtest.GetFolderByName(folderName, http.StatusOK)
  2253. assert.NoError(t, err)
  2254. assert.Equal(t, testFileSize, folder.UsedQuotaSize)
  2255. assert.Equal(t, 1, folder.UsedQuotaFiles)
  2256. err = uploadFileWithRawClient(testFilePath, path.Join(vdir, testFileName), user.Username,
  2257. defaultPassword, true, testFileSize, client)
  2258. assert.NoError(t, err)
  2259. folder, _, err = httpdtest.GetFolderByName(folderName, http.StatusOK)
  2260. assert.NoError(t, err)
  2261. assert.Equal(t, testFileSize, folder.UsedQuotaSize)
  2262. assert.Equal(t, 1, folder.UsedQuotaFiles)
  2263. err = os.Remove(testFilePath)
  2264. assert.NoError(t, err)
  2265. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2266. assert.NoError(t, err)
  2267. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  2268. assert.NoError(t, err)
  2269. err = os.RemoveAll(user.GetHomeDir())
  2270. assert.NoError(t, err)
  2271. err = os.RemoveAll(mappedPath)
  2272. assert.NoError(t, err)
  2273. }
  2274. func TestOsErrors(t *testing.T) {
  2275. u := getTestUser()
  2276. vdir := "/vdir"
  2277. mappedPath := filepath.Join(os.TempDir(), "mappedDir")
  2278. folderName := filepath.Base(mappedPath)
  2279. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2280. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2281. Name: folderName,
  2282. MappedPath: mappedPath,
  2283. },
  2284. VirtualPath: vdir,
  2285. QuotaSize: -1,
  2286. QuotaFiles: -1,
  2287. })
  2288. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2289. assert.NoError(t, err)
  2290. client := getWebDavClient(user, false, nil)
  2291. files, err := client.ReadDir(".")
  2292. assert.NoError(t, err)
  2293. assert.Len(t, files, 1)
  2294. info, err := client.Stat(vdir)
  2295. assert.NoError(t, err)
  2296. assert.True(t, info.IsDir())
  2297. // now remove the folder mapped to vdir. It still appear in directory listing
  2298. // virtual folders are automatically added
  2299. err = os.RemoveAll(mappedPath)
  2300. assert.NoError(t, err)
  2301. files, err = client.ReadDir(".")
  2302. assert.NoError(t, err)
  2303. assert.Len(t, files, 1)
  2304. err = createTestFile(filepath.Join(user.GetHomeDir(), testFileName), 32768)
  2305. assert.NoError(t, err)
  2306. files, err = client.ReadDir(".")
  2307. assert.NoError(t, err)
  2308. if assert.Len(t, files, 2) {
  2309. var names []string
  2310. for _, info := range files {
  2311. names = append(names, info.Name())
  2312. }
  2313. assert.Contains(t, names, testFileName)
  2314. assert.Contains(t, names, "vdir")
  2315. }
  2316. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2317. assert.NoError(t, err)
  2318. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  2319. assert.NoError(t, err)
  2320. err = os.RemoveAll(user.GetHomeDir())
  2321. assert.NoError(t, err)
  2322. err = os.RemoveAll(mappedPath)
  2323. assert.NoError(t, err)
  2324. }
  2325. func TestMiscCommands(t *testing.T) {
  2326. u := getTestUser()
  2327. u.QuotaFiles = 100
  2328. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2329. assert.NoError(t, err)
  2330. u = getTestSFTPUser()
  2331. u.QuotaFiles = 100
  2332. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2333. assert.NoError(t, err)
  2334. for _, user := range []dataprovider.User{localUser, sftpUser} {
  2335. dir := "testDir"
  2336. client := getWebDavClient(user, true, nil)
  2337. err = client.MkdirAll(path.Join(dir, "sub1", "sub2"), os.ModePerm)
  2338. assert.NoError(t, err)
  2339. testFilePath := filepath.Join(homeBasePath, testFileName)
  2340. testFileSize := int64(65535)
  2341. err = createTestFile(testFilePath, testFileSize)
  2342. assert.NoError(t, err)
  2343. err = uploadFileWithRawClient(testFilePath, path.Join(dir, testFileName), user.Username,
  2344. defaultPassword, true, testFileSize, client)
  2345. assert.NoError(t, err)
  2346. err = uploadFileWithRawClient(testFilePath, path.Join(dir, "sub1", testFileName), user.Username,
  2347. defaultPassword, true, testFileSize, client)
  2348. assert.NoError(t, err)
  2349. err = uploadFileWithRawClient(testFilePath, path.Join(dir, "sub1", "sub2", testFileName), user.Username,
  2350. defaultPassword, true, testFileSize, client)
  2351. assert.NoError(t, err)
  2352. err = client.Copy(dir, dir+"_copy", false)
  2353. assert.NoError(t, err)
  2354. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2355. assert.NoError(t, err)
  2356. assert.Equal(t, 6, user.UsedQuotaFiles)
  2357. assert.Equal(t, 6*testFileSize, user.UsedQuotaSize)
  2358. err = client.Copy(dir, dir+"_copy1", false)
  2359. assert.NoError(t, err)
  2360. err = client.Copy(dir+"_copy", dir+"_copy1", false)
  2361. assert.Error(t, err)
  2362. err = client.Copy(dir+"_copy", dir+"_copy1", true)
  2363. assert.NoError(t, err)
  2364. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2365. assert.NoError(t, err)
  2366. assert.Equal(t, 9, user.UsedQuotaFiles)
  2367. assert.Equal(t, 9*testFileSize, user.UsedQuotaSize)
  2368. err = client.Rename(dir+"_copy1", dir+"_copy2", false)
  2369. assert.NoError(t, err)
  2370. err = client.Remove(path.Join(dir+"_copy", testFileName))
  2371. assert.NoError(t, err)
  2372. err = client.Rename(dir+"_copy2", dir+"_copy", true)
  2373. assert.NoError(t, err)
  2374. err = client.Copy(dir+"_copy", dir+"_copy1", false)
  2375. assert.NoError(t, err)
  2376. err = client.RemoveAll(dir + "_copy1")
  2377. assert.NoError(t, err)
  2378. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2379. assert.NoError(t, err)
  2380. assert.Equal(t, 6, user.UsedQuotaFiles)
  2381. assert.Equal(t, 6*testFileSize, user.UsedQuotaSize)
  2382. err = os.Remove(testFilePath)
  2383. assert.NoError(t, err)
  2384. if user.Username == defaultUsername {
  2385. err = os.RemoveAll(user.GetHomeDir())
  2386. assert.NoError(t, err)
  2387. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2388. assert.NoError(t, err)
  2389. user.Password = defaultPassword
  2390. user.ID = 0
  2391. user.CreatedAt = 0
  2392. user.QuotaFiles = 0
  2393. _, resp, err := httpdtest.AddUser(user, http.StatusCreated)
  2394. assert.NoError(t, err, string(resp))
  2395. }
  2396. }
  2397. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  2398. assert.NoError(t, err)
  2399. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  2400. assert.NoError(t, err)
  2401. err = os.RemoveAll(localUser.GetHomeDir())
  2402. assert.NoError(t, err)
  2403. }
  2404. func TestClientCertificateAuthRevokedCert(t *testing.T) {
  2405. u := getTestUser()
  2406. u.Username = tlsClient2Username
  2407. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2408. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2409. assert.NoError(t, err)
  2410. tlsConfig := &tls.Config{
  2411. ServerName: "localhost",
  2412. InsecureSkipVerify: true, // use this for tests only
  2413. MinVersion: tls.VersionTLS12,
  2414. }
  2415. tlsCert, err := tls.X509KeyPair([]byte(client2Crt), []byte(client2Key))
  2416. assert.NoError(t, err)
  2417. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2418. client := getWebDavClient(user, true, tlsConfig)
  2419. err = checkBasicFunc(client)
  2420. if assert.Error(t, err) {
  2421. if !strings.Contains(err.Error(), "bad certificate") && !strings.Contains(err.Error(), "broken pipe") {
  2422. t.Errorf("unexpected error: %v", err)
  2423. }
  2424. }
  2425. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2426. assert.NoError(t, err)
  2427. err = os.RemoveAll(user.GetHomeDir())
  2428. assert.NoError(t, err)
  2429. }
  2430. func TestClientCertificateAuth(t *testing.T) {
  2431. u := getTestUser()
  2432. u.Username = tlsClient1Username
  2433. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificateAndPwd}
  2434. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2435. assert.NoError(t, err)
  2436. tlsConfig := &tls.Config{
  2437. ServerName: "localhost",
  2438. InsecureSkipVerify: true, // use this for tests only
  2439. MinVersion: tls.VersionTLS12,
  2440. }
  2441. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2442. assert.NoError(t, err)
  2443. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2444. // TLS username is not enabled, mutual TLS should fail
  2445. resp, err := getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v/", webDavTLSServerAddr))
  2446. if assert.NoError(t, err) {
  2447. defer resp.Body.Close()
  2448. body, err := io.ReadAll(resp.Body)
  2449. assert.NoError(t, err)
  2450. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2451. }
  2452. user.Filters.TLSUsername = sdk.TLSUsernameCN
  2453. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2454. assert.NoError(t, err)
  2455. client := getWebDavClient(user, true, tlsConfig)
  2456. err = checkBasicFunc(client)
  2457. assert.NoError(t, err)
  2458. user.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificate}
  2459. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2460. assert.NoError(t, err)
  2461. client = getWebDavClient(user, true, tlsConfig)
  2462. err = checkBasicFunc(client)
  2463. assert.NoError(t, err)
  2464. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2465. assert.NoError(t, err)
  2466. err = os.RemoveAll(user.GetHomeDir())
  2467. assert.NoError(t, err)
  2468. }
  2469. func TestWrongClientCertificate(t *testing.T) {
  2470. u := getTestUser()
  2471. u.Username = tlsClient2Username
  2472. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificateAndPwd}
  2473. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2474. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2475. assert.NoError(t, err)
  2476. tlsConfig := &tls.Config{
  2477. ServerName: "localhost",
  2478. InsecureSkipVerify: true, // use this for tests only
  2479. MinVersion: tls.VersionTLS12,
  2480. }
  2481. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2482. assert.NoError(t, err)
  2483. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2484. // the certificate common name is client1 and it does not exists
  2485. resp, err := getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v/", webDavTLSServerAddr))
  2486. if assert.NoError(t, err) {
  2487. defer resp.Body.Close()
  2488. body, err := io.ReadAll(resp.Body)
  2489. assert.NoError(t, err)
  2490. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2491. }
  2492. user.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificate}
  2493. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2494. assert.NoError(t, err)
  2495. // now create client1
  2496. u = getTestUser()
  2497. u.Username = tlsClient1Username
  2498. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificate}
  2499. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2500. user1, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2501. assert.NoError(t, err)
  2502. resp, err = getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v:%v@%v/", tlsClient2Username, defaultPassword,
  2503. webDavTLSServerAddr))
  2504. if assert.NoError(t, err) {
  2505. defer resp.Body.Close()
  2506. body, err := io.ReadAll(resp.Body)
  2507. assert.NoError(t, err)
  2508. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2509. assert.Contains(t, string(body), "invalid credentials")
  2510. }
  2511. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2512. assert.NoError(t, err)
  2513. err = os.RemoveAll(user.GetHomeDir())
  2514. assert.NoError(t, err)
  2515. _, err = httpdtest.RemoveUser(user1, http.StatusOK)
  2516. assert.NoError(t, err)
  2517. err = os.RemoveAll(user1.GetHomeDir())
  2518. assert.NoError(t, err)
  2519. }
  2520. func TestClientCertificateAuthCachedUser(t *testing.T) {
  2521. u := getTestUser()
  2522. u.Username = tlsClient1Username
  2523. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2524. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificateAndPwd}
  2525. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2526. assert.NoError(t, err)
  2527. tlsConfig := &tls.Config{
  2528. ServerName: "localhost",
  2529. InsecureSkipVerify: true, // use this for tests only
  2530. MinVersion: tls.VersionTLS12,
  2531. }
  2532. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2533. assert.NoError(t, err)
  2534. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2535. client := getWebDavClient(user, true, tlsConfig)
  2536. err = checkBasicFunc(client)
  2537. assert.NoError(t, err)
  2538. // the user is now cached without a password, try a simple password login with and without TLS
  2539. client = getWebDavClient(user, true, nil)
  2540. err = checkBasicFunc(client)
  2541. assert.NoError(t, err)
  2542. client = getWebDavClient(user, false, nil)
  2543. err = checkBasicFunc(client)
  2544. assert.NoError(t, err)
  2545. // and now with a wrong password
  2546. user.Password = "wrong"
  2547. client = getWebDavClient(user, false, nil)
  2548. err = checkBasicFunc(client)
  2549. assert.Error(t, err)
  2550. // allow cert+password only
  2551. user.Password = ""
  2552. user.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificate}
  2553. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2554. assert.NoError(t, err)
  2555. client = getWebDavClient(user, true, tlsConfig)
  2556. err = checkBasicFunc(client)
  2557. assert.NoError(t, err)
  2558. // the user is now cached
  2559. client = getWebDavClient(user, true, tlsConfig)
  2560. err = checkBasicFunc(client)
  2561. assert.NoError(t, err)
  2562. // password auth should work too
  2563. client = getWebDavClient(user, false, nil)
  2564. err = checkBasicFunc(client)
  2565. assert.NoError(t, err)
  2566. client = getWebDavClient(user, true, nil)
  2567. err = checkBasicFunc(client)
  2568. assert.NoError(t, err)
  2569. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2570. assert.NoError(t, err)
  2571. err = os.RemoveAll(user.GetHomeDir())
  2572. assert.NoError(t, err)
  2573. }
  2574. func TestExternatAuthWithClientCert(t *testing.T) {
  2575. if runtime.GOOS == osWindows {
  2576. t.Skip("this test is not available on Windows")
  2577. }
  2578. u := getTestUser()
  2579. u.Username = tlsClient1Username
  2580. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2581. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificate, dataprovider.LoginMethodPassword}
  2582. err := dataprovider.Close()
  2583. assert.NoError(t, err)
  2584. err = config.LoadConfig(configDir, "")
  2585. assert.NoError(t, err)
  2586. providerConf := config.GetProviderConf()
  2587. err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u), os.ModePerm)
  2588. assert.NoError(t, err)
  2589. providerConf.ExternalAuthHook = extAuthPath
  2590. providerConf.ExternalAuthScope = 0
  2591. err = dataprovider.Initialize(providerConf, configDir, true)
  2592. assert.NoError(t, err)
  2593. tlsConfig := &tls.Config{
  2594. ServerName: "localhost",
  2595. InsecureSkipVerify: true, // use this for tests only
  2596. MinVersion: tls.VersionTLS12,
  2597. }
  2598. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2599. assert.NoError(t, err)
  2600. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2601. client := getWebDavClient(u, true, tlsConfig)
  2602. assert.NoError(t, checkBasicFunc(client))
  2603. resp, err := getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v:%v@%v/", tlsClient2Username, defaultPassword,
  2604. webDavTLSServerAddr))
  2605. if assert.NoError(t, err) {
  2606. defer resp.Body.Close()
  2607. body, err := io.ReadAll(resp.Body)
  2608. assert.NoError(t, err)
  2609. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2610. assert.Contains(t, string(body), "invalid credentials")
  2611. }
  2612. user, _, err := httpdtest.GetUserByUsername(tlsClient1Username, http.StatusOK)
  2613. assert.NoError(t, err)
  2614. assert.Equal(t, tlsClient1Username, user.Username)
  2615. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2616. assert.NoError(t, err)
  2617. err = os.RemoveAll(user.GetHomeDir())
  2618. assert.NoError(t, err)
  2619. err = dataprovider.Close()
  2620. assert.NoError(t, err)
  2621. err = config.LoadConfig(configDir, "")
  2622. assert.NoError(t, err)
  2623. providerConf = config.GetProviderConf()
  2624. err = dataprovider.Initialize(providerConf, configDir, true)
  2625. assert.NoError(t, err)
  2626. err = os.Remove(extAuthPath)
  2627. assert.NoError(t, err)
  2628. }
  2629. func TestPreLoginHookWithClientCert(t *testing.T) {
  2630. if runtime.GOOS == osWindows {
  2631. t.Skip("this test is not available on Windows")
  2632. }
  2633. u := getTestUser()
  2634. u.Username = tlsClient1Username
  2635. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2636. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificate, dataprovider.LoginMethodPassword}
  2637. err := dataprovider.Close()
  2638. assert.NoError(t, err)
  2639. err = config.LoadConfig(configDir, "")
  2640. assert.NoError(t, err)
  2641. providerConf := config.GetProviderConf()
  2642. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
  2643. assert.NoError(t, err)
  2644. providerConf.PreLoginHook = preLoginPath
  2645. err = dataprovider.Initialize(providerConf, configDir, true)
  2646. assert.NoError(t, err)
  2647. _, _, err = httpdtest.GetUserByUsername(tlsClient1Username, http.StatusNotFound)
  2648. assert.NoError(t, err)
  2649. tlsConfig := &tls.Config{
  2650. ServerName: "localhost",
  2651. InsecureSkipVerify: true, // use this for tests only
  2652. MinVersion: tls.VersionTLS12,
  2653. }
  2654. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2655. assert.NoError(t, err)
  2656. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2657. client := getWebDavClient(u, true, tlsConfig)
  2658. assert.NoError(t, checkBasicFunc(client))
  2659. user, _, err := httpdtest.GetUserByUsername(tlsClient1Username, http.StatusOK)
  2660. assert.NoError(t, err)
  2661. // test login with an existing user
  2662. client = getWebDavClient(user, true, tlsConfig)
  2663. assert.NoError(t, checkBasicFunc(client))
  2664. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), os.ModePerm)
  2665. assert.NoError(t, err)
  2666. // update the user to remove it from the cache
  2667. user.Password = defaultPassword
  2668. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2669. assert.NoError(t, err)
  2670. client = getWebDavClient(user, true, tlsConfig)
  2671. assert.Error(t, checkBasicFunc(client))
  2672. // update the user to remove it from the cache
  2673. user.Password = defaultPassword
  2674. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2675. assert.NoError(t, err)
  2676. user.Status = 0
  2677. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), os.ModePerm)
  2678. assert.NoError(t, err)
  2679. client = getWebDavClient(user, true, tlsConfig)
  2680. assert.Error(t, checkBasicFunc(client))
  2681. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2682. assert.NoError(t, err)
  2683. err = os.RemoveAll(user.GetHomeDir())
  2684. assert.NoError(t, err)
  2685. err = dataprovider.Close()
  2686. assert.NoError(t, err)
  2687. err = config.LoadConfig(configDir, "")
  2688. assert.NoError(t, err)
  2689. providerConf = config.GetProviderConf()
  2690. err = dataprovider.Initialize(providerConf, configDir, true)
  2691. assert.NoError(t, err)
  2692. err = os.Remove(preLoginPath)
  2693. assert.NoError(t, err)
  2694. }
  2695. func TestSFTPLoopVirtualFolders(t *testing.T) {
  2696. user1 := getTestUser()
  2697. user2 := getTestUser()
  2698. user1.Username += "1"
  2699. user2.Username += "2"
  2700. // user1 is a local account with a virtual SFTP folder to user2
  2701. // user2 has user1 as SFTP fs
  2702. user1.VirtualFolders = append(user1.VirtualFolders, vfs.VirtualFolder{
  2703. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2704. Name: "sftp",
  2705. FsConfig: vfs.Filesystem{
  2706. Provider: sdk.SFTPFilesystemProvider,
  2707. SFTPConfig: vfs.SFTPFsConfig{
  2708. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  2709. Endpoint: sftpServerAddr,
  2710. Username: user2.Username,
  2711. },
  2712. Password: kms.NewPlainSecret(defaultPassword),
  2713. },
  2714. },
  2715. },
  2716. VirtualPath: "/vdir",
  2717. })
  2718. user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
  2719. user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
  2720. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  2721. Endpoint: sftpServerAddr,
  2722. Username: user1.Username,
  2723. },
  2724. Password: kms.NewPlainSecret(defaultPassword),
  2725. }
  2726. user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
  2727. assert.NoError(t, err, string(resp))
  2728. user2, resp, err = httpdtest.AddUser(user2, http.StatusCreated)
  2729. assert.NoError(t, err, string(resp))
  2730. client := getWebDavClient(user1, true, nil)
  2731. testDir := "tdir"
  2732. err = client.Mkdir(testDir, os.ModePerm)
  2733. assert.NoError(t, err)
  2734. contents, err := client.ReadDir("/")
  2735. assert.NoError(t, err)
  2736. if assert.Len(t, contents, 2) {
  2737. expected := 0
  2738. for _, info := range contents {
  2739. switch info.Name() {
  2740. case testDir, "vdir":
  2741. assert.True(t, info.IsDir())
  2742. expected++
  2743. default:
  2744. t.Errorf("unexpected file/dir %q", info.Name())
  2745. }
  2746. }
  2747. assert.Equal(t, expected, 2)
  2748. }
  2749. _, err = httpdtest.RemoveUser(user1, http.StatusOK)
  2750. assert.NoError(t, err)
  2751. err = os.RemoveAll(user1.GetHomeDir())
  2752. assert.NoError(t, err)
  2753. _, err = httpdtest.RemoveUser(user2, http.StatusOK)
  2754. assert.NoError(t, err)
  2755. err = os.RemoveAll(user2.GetHomeDir())
  2756. assert.NoError(t, err)
  2757. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: "sftp"}, http.StatusOK)
  2758. assert.NoError(t, err)
  2759. }
  2760. func TestNestedVirtualFolders(t *testing.T) {
  2761. u := getTestUser()
  2762. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2763. assert.NoError(t, err)
  2764. u = getTestSFTPUser()
  2765. mappedPathCrypt := filepath.Join(os.TempDir(), "crypt")
  2766. folderNameCrypt := filepath.Base(mappedPathCrypt)
  2767. vdirCryptPath := "/vdir/crypt"
  2768. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2769. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2770. Name: folderNameCrypt,
  2771. FsConfig: vfs.Filesystem{
  2772. Provider: sdk.CryptedFilesystemProvider,
  2773. CryptConfig: vfs.CryptFsConfig{
  2774. Passphrase: kms.NewPlainSecret(defaultPassword),
  2775. },
  2776. },
  2777. MappedPath: mappedPathCrypt,
  2778. },
  2779. VirtualPath: vdirCryptPath,
  2780. })
  2781. mappedPath := filepath.Join(os.TempDir(), "local")
  2782. folderName := filepath.Base(mappedPath)
  2783. vdirPath := "/vdir/local"
  2784. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2785. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2786. Name: folderName,
  2787. MappedPath: mappedPath,
  2788. },
  2789. VirtualPath: vdirPath,
  2790. })
  2791. mappedPathNested := filepath.Join(os.TempDir(), "nested")
  2792. folderNameNested := filepath.Base(mappedPathNested)
  2793. vdirNestedPath := "/vdir/crypt/nested"
  2794. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2795. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2796. Name: folderNameNested,
  2797. MappedPath: mappedPathNested,
  2798. },
  2799. VirtualPath: vdirNestedPath,
  2800. QuotaFiles: -1,
  2801. QuotaSize: -1,
  2802. })
  2803. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2804. assert.NoError(t, err)
  2805. client := getWebDavClient(sftpUser, true, nil)
  2806. assert.NoError(t, checkBasicFunc(client))
  2807. testFilePath := filepath.Join(homeBasePath, testFileName)
  2808. testFileSize := int64(65535)
  2809. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  2810. err = createTestFile(testFilePath, testFileSize)
  2811. assert.NoError(t, err)
  2812. err = uploadFileWithRawClient(testFilePath, testFileName, sftpUser.Username,
  2813. defaultPassword, true, testFileSize, client)
  2814. assert.NoError(t, err)
  2815. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  2816. assert.NoError(t, err)
  2817. err = uploadFileWithRawClient(testFilePath, path.Join("/vdir", testFileName), sftpUser.Username,
  2818. defaultPassword, true, testFileSize, client)
  2819. assert.NoError(t, err)
  2820. err = downloadFile(path.Join("/vdir", testFileName), localDownloadPath, testFileSize, client)
  2821. assert.NoError(t, err)
  2822. err = uploadFileWithRawClient(testFilePath, path.Join(vdirPath, testFileName), sftpUser.Username,
  2823. defaultPassword, true, testFileSize, client)
  2824. assert.NoError(t, err)
  2825. err = downloadFile(path.Join(vdirPath, testFileName), localDownloadPath, testFileSize, client)
  2826. assert.NoError(t, err)
  2827. err = uploadFileWithRawClient(testFilePath, path.Join(vdirCryptPath, testFileName), sftpUser.Username,
  2828. defaultPassword, true, testFileSize, client)
  2829. assert.NoError(t, err)
  2830. err = downloadFile(path.Join(vdirCryptPath, testFileName), localDownloadPath, testFileSize, client)
  2831. assert.NoError(t, err)
  2832. err = uploadFileWithRawClient(testFilePath, path.Join(vdirNestedPath, testFileName), sftpUser.Username,
  2833. defaultPassword, true, testFileSize, client)
  2834. assert.NoError(t, err)
  2835. err = downloadFile(path.Join(vdirNestedPath, testFileName), localDownloadPath, testFileSize, client)
  2836. assert.NoError(t, err)
  2837. err = os.Remove(testFilePath)
  2838. assert.NoError(t, err)
  2839. err = os.Remove(localDownloadPath)
  2840. assert.NoError(t, err)
  2841. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  2842. assert.NoError(t, err)
  2843. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  2844. assert.NoError(t, err)
  2845. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameCrypt}, http.StatusOK)
  2846. assert.NoError(t, err)
  2847. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  2848. assert.NoError(t, err)
  2849. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameNested}, http.StatusOK)
  2850. assert.NoError(t, err)
  2851. err = os.RemoveAll(mappedPathCrypt)
  2852. assert.NoError(t, err)
  2853. err = os.RemoveAll(mappedPath)
  2854. assert.NoError(t, err)
  2855. err = os.RemoveAll(mappedPathNested)
  2856. assert.NoError(t, err)
  2857. err = os.RemoveAll(localUser.GetHomeDir())
  2858. assert.NoError(t, err)
  2859. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  2860. 1*time.Second, 100*time.Millisecond)
  2861. }
  2862. func checkBasicFunc(client *gowebdav.Client) error {
  2863. err := client.Connect()
  2864. if err != nil {
  2865. return err
  2866. }
  2867. _, err = client.ReadDir("/")
  2868. return err
  2869. }
  2870. func checkFileSize(remoteDestPath string, expectedSize int64, client *gowebdav.Client) error {
  2871. info, err := client.Stat(remoteDestPath)
  2872. if err != nil {
  2873. return err
  2874. }
  2875. if info.Size() != expectedSize {
  2876. return fmt.Errorf("uploaded file size does not match, actual: %v, expected: %v", info.Size(), expectedSize)
  2877. }
  2878. return nil
  2879. }
  2880. func uploadFileWithRawClient(localSourcePath string, remoteDestPath string, username, password string,
  2881. useTLS bool, expectedSize int64, client *gowebdav.Client, headers ...dataprovider.KeyValue,
  2882. ) error {
  2883. srcFile, err := os.Open(localSourcePath)
  2884. if err != nil {
  2885. return err
  2886. }
  2887. defer srcFile.Close()
  2888. var tlsConfig *tls.Config
  2889. rootPath := fmt.Sprintf("http://%v/", webDavServerAddr)
  2890. if useTLS {
  2891. rootPath = fmt.Sprintf("https://%v/", webDavTLSServerAddr)
  2892. tlsConfig = &tls.Config{
  2893. ServerName: "localhost",
  2894. InsecureSkipVerify: true, // use this for tests only
  2895. MinVersion: tls.VersionTLS12,
  2896. }
  2897. }
  2898. req, err := http.NewRequest(http.MethodPut, fmt.Sprintf("%v%v", rootPath, remoteDestPath), srcFile)
  2899. if err != nil {
  2900. return err
  2901. }
  2902. req.SetBasicAuth(username, password)
  2903. for _, kv := range headers {
  2904. req.Header.Set(kv.Key, kv.Value)
  2905. }
  2906. httpClient := &http.Client{Timeout: 10 * time.Second}
  2907. if tlsConfig != nil {
  2908. customTransport := http.DefaultTransport.(*http.Transport).Clone()
  2909. customTransport.TLSClientConfig = tlsConfig
  2910. httpClient.Transport = customTransport
  2911. }
  2912. defer httpClient.CloseIdleConnections()
  2913. resp, err := httpClient.Do(req)
  2914. if err != nil {
  2915. return err
  2916. }
  2917. defer resp.Body.Close()
  2918. if resp.StatusCode != http.StatusCreated {
  2919. return fmt.Errorf("unexpected status code: %v", resp.StatusCode)
  2920. }
  2921. if expectedSize > 0 {
  2922. return checkFileSize(remoteDestPath, expectedSize, client)
  2923. }
  2924. return nil
  2925. }
  2926. // This method is buggy. I have to find time to better investigate and eventually report the issue upstream.
  2927. // For now we upload using the uploadFileWithRawClient method
  2928. /*func uploadFile(localSourcePath string, remoteDestPath string, expectedSize int64, client *gowebdav.Client) error {
  2929. srcFile, err := os.Open(localSourcePath)
  2930. if err != nil {
  2931. return err
  2932. }
  2933. defer srcFile.Close()
  2934. err = client.WriteStream(remoteDestPath, srcFile, os.ModePerm)
  2935. if err != nil {
  2936. return err
  2937. }
  2938. if expectedSize > 0 {
  2939. return checkFileSize(remoteDestPath, expectedSize, client)
  2940. }
  2941. return nil
  2942. }*/
  2943. func downloadFile(remoteSourcePath string, localDestPath string, expectedSize int64, client *gowebdav.Client) error {
  2944. downloadDest, err := os.Create(localDestPath)
  2945. if err != nil {
  2946. return err
  2947. }
  2948. defer downloadDest.Close()
  2949. reader, err := client.ReadStream(remoteSourcePath)
  2950. if err != nil {
  2951. return err
  2952. }
  2953. defer reader.Close()
  2954. written, err := io.Copy(downloadDest, reader)
  2955. if err != nil {
  2956. return err
  2957. }
  2958. if written != expectedSize {
  2959. return fmt.Errorf("downloaded file size does not match, actual: %v, expected: %v", written, expectedSize)
  2960. }
  2961. return nil
  2962. }
  2963. func getTLSHTTPClient(tlsConfig *tls.Config) *http.Client {
  2964. customTransport := http.DefaultTransport.(*http.Transport).Clone()
  2965. customTransport.TLSClientConfig = tlsConfig
  2966. return &http.Client{
  2967. Timeout: 5 * time.Second,
  2968. Transport: customTransport,
  2969. }
  2970. }
  2971. func getWebDavClient(user dataprovider.User, useTLS bool, tlsConfig *tls.Config) *gowebdav.Client {
  2972. rootPath := fmt.Sprintf("http://%v/", webDavServerAddr)
  2973. if useTLS {
  2974. rootPath = fmt.Sprintf("https://%v/", webDavTLSServerAddr)
  2975. if tlsConfig == nil {
  2976. tlsConfig = &tls.Config{
  2977. ServerName: "localhost",
  2978. InsecureSkipVerify: true, // use this for tests only
  2979. MinVersion: tls.VersionTLS12,
  2980. }
  2981. }
  2982. }
  2983. pwd := defaultPassword
  2984. if user.Password != "" {
  2985. if user.Password == emptyPwdPlaceholder {
  2986. pwd = ""
  2987. } else {
  2988. pwd = user.Password
  2989. }
  2990. }
  2991. client := gowebdav.NewClient(rootPath, user.Username, pwd)
  2992. client.SetTimeout(10 * time.Second)
  2993. if tlsConfig != nil {
  2994. customTransport := http.DefaultTransport.(*http.Transport).Clone()
  2995. customTransport.TLSClientConfig = tlsConfig
  2996. client.SetTransport(customTransport)
  2997. }
  2998. return client
  2999. }
  3000. func waitTCPListening(address string) {
  3001. for {
  3002. conn, err := net.Dial("tcp", address)
  3003. if err != nil {
  3004. logger.WarnToConsole("tcp server %v not listening: %v", address, err)
  3005. time.Sleep(100 * time.Millisecond)
  3006. continue
  3007. }
  3008. logger.InfoToConsole("tcp server %v now listening", address)
  3009. conn.Close()
  3010. break
  3011. }
  3012. }
  3013. func getTestUser() dataprovider.User {
  3014. user := dataprovider.User{
  3015. BaseUser: sdk.BaseUser{
  3016. Username: defaultUsername,
  3017. Password: defaultPassword,
  3018. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  3019. Status: 1,
  3020. ExpirationDate: 0,
  3021. },
  3022. }
  3023. user.Permissions = make(map[string][]string)
  3024. user.Permissions["/"] = allPerms
  3025. return user
  3026. }
  3027. func getTestSFTPUser() dataprovider.User {
  3028. u := getTestUser()
  3029. u.Username = u.Username + "_sftp"
  3030. u.FsConfig.Provider = sdk.SFTPFilesystemProvider
  3031. u.FsConfig.SFTPConfig.Endpoint = sftpServerAddr
  3032. u.FsConfig.SFTPConfig.Username = defaultUsername
  3033. u.FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword)
  3034. return u
  3035. }
  3036. func getTestUserWithCryptFs() dataprovider.User {
  3037. user := getTestUser()
  3038. user.FsConfig.Provider = sdk.CryptedFilesystemProvider
  3039. user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret("testPassphrase")
  3040. return user
  3041. }
  3042. func getEncryptedFileSize(size int64) (int64, error) {
  3043. encSize, err := sio.EncryptedSize(uint64(size))
  3044. return int64(encSize) + 33, err
  3045. }
  3046. func getExtAuthScriptContent(user dataprovider.User) []byte {
  3047. extAuthContent := []byte("#!/bin/sh\n\n")
  3048. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("if test \"$SFTPGO_AUTHD_USERNAME\" = \"%v\"; then\n", user.Username))...)
  3049. u, _ := json.Marshal(user)
  3050. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  3051. extAuthContent = append(extAuthContent, []byte("else\n")...)
  3052. extAuthContent = append(extAuthContent, []byte("echo '{\"username\":\"\"}'\n")...)
  3053. extAuthContent = append(extAuthContent, []byte("fi\n")...)
  3054. return extAuthContent
  3055. }
  3056. func getPreLoginScriptContent(user dataprovider.User, nonJSONResponse bool) []byte {
  3057. content := []byte("#!/bin/sh\n\n")
  3058. if nonJSONResponse {
  3059. content = append(content, []byte("echo 'text response'\n")...)
  3060. return content
  3061. }
  3062. if len(user.Username) > 0 {
  3063. u, _ := json.Marshal(user)
  3064. content = append(content, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  3065. }
  3066. return content
  3067. }
  3068. func getExitCodeScriptContent(exitCode int) []byte {
  3069. content := []byte("#!/bin/sh\n\n")
  3070. content = append(content, []byte(fmt.Sprintf("exit %v", exitCode))...)
  3071. return content
  3072. }
  3073. func createTestFile(path string, size int64) error {
  3074. baseDir := filepath.Dir(path)
  3075. if _, err := os.Stat(baseDir); errors.Is(err, fs.ErrNotExist) {
  3076. err = os.MkdirAll(baseDir, os.ModePerm)
  3077. if err != nil {
  3078. return err
  3079. }
  3080. }
  3081. content := make([]byte, size)
  3082. _, err := rand.Read(content)
  3083. if err != nil {
  3084. return err
  3085. }
  3086. err = os.WriteFile(path, content, os.ModePerm)
  3087. if err != nil {
  3088. return err
  3089. }
  3090. fi, err := os.Stat(path)
  3091. if err != nil {
  3092. return err
  3093. }
  3094. if fi.Size() != size {
  3095. return fmt.Errorf("unexpected size %v, expected %v", fi.Size(), size)
  3096. }
  3097. return nil
  3098. }
  3099. func printLatestLogs(maxNumberOfLines int) {
  3100. var lines []string
  3101. f, err := os.Open(logFilePath)
  3102. if err != nil {
  3103. return
  3104. }
  3105. defer f.Close()
  3106. scanner := bufio.NewScanner(f)
  3107. for scanner.Scan() {
  3108. lines = append(lines, scanner.Text()+"\r\n")
  3109. for len(lines) > maxNumberOfLines {
  3110. lines = lines[1:]
  3111. }
  3112. }
  3113. if scanner.Err() != nil {
  3114. logger.WarnToConsole("Unable to print latest logs: %v", scanner.Err())
  3115. return
  3116. }
  3117. for _, line := range lines {
  3118. logger.DebugToConsole(line)
  3119. }
  3120. }