webdavd_test.go 125 KB

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