webdavd_test.go 126 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552
  1. // Copyright (C) 2019 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. QXV0aDAeFw0yNDAxMTAxODEyMDRaFw0zNDAxMTAxODIxNTRaMBMxETAPBgNVBAMT
  91. CENlcnRBdXRoMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7WHW216m
  92. fi4uF8cx6HWf8wvAxaEWgCHTOi2MwFIzOrOtuT7xb64rkpdzx1aWetSiCrEyc3D1
  93. v03k0Akvlz1gtnDtO64+MA8bqlTnCydZJY4cCTvDOBUYZgtMqHZzpE6xRrqQ84zh
  94. yzjKQ5bR0st+XGfIkuhjSuf2n/ZPS37fge9j6AKzn/2uEVt33qmO85WtN3RzbSqL
  95. CdOJ6cQ216j3la1C5+NWvzIKC7t6NE1bBGI4+tRj7B5P5MeamkkogwbExUjdHp3U
  96. 4yasvoGcCHUQDoa4Dej1faywz6JlwB6rTV4ys4aZDe67V/Q8iB2May1k7zBz1Ztb
  97. KF5Em3xewP1LqPEowF1uc4KtPGcP4bxdaIpSpmObcn8AIfH6smLQrn0C3cs7CYfo
  98. NlFuTbwzENUhjz0X6EsoM4w4c87lO+dRNR7YpHLqR/BJTbbyXUB0imne1u00fuzb
  99. S7OtweiA9w7DRCkr2gU4lmHe7l0T+SA9pxIeVLb78x7ivdyXSF5LVQJ1JvhhWu6i
  100. M6GQdLHat/0fpRFUbEe34RQSDJ2eOBifMJqvsvpBP8d2jcRZVUVrSXGc2mAGuGOY
  101. /tmnCJGW8Fd+sgpCVAqM0pxCM+apqrvJYUqqQZ2ZxugCXULtRWJ9p4C9zUl40HEy
  102. OQ+AaiiwFll/doXELglcJdNg8AZPGhugfxMCAwEAAaNFMEMwDgYDVR0PAQH/BAQD
  103. AgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFNoJhIvDZQrEf/VQbWuu
  104. XgNnt2m5MA0GCSqGSIb3DQEBCwUAA4ICAQCYhT5SRqk19hGrQ09hVSZOzynXAa5F
  105. sYkEWJzFyLg9azhnTPE1bFM18FScnkd+dal6mt+bQiJvdh24NaVkDghVB7GkmXki
  106. pAiZwEDHMqtbhiPxY8LtSeCBAz5JqXVU2Q0TpAgNSH4W7FbGWNThhxcJVOoIrXKE
  107. jbzhwl1Etcaf0DBKWliUbdlxQQs65DLy+rNBYtOeK0pzhzn1vpehUlJ4eTFzP9KX
  108. y2Mksuq9AspPbqnqpWW645MdTxMb5T57MCrY3GDKw63z5z3kz88LWJF3nOxZmgQy
  109. WFUhbLmZm7x6N5eiu6Wk8/B4yJ/n5UArD4cEP1i7nqu+mbbM/SZlq1wnGpg/sbRV
  110. oUF+a7pRcSbfxEttle4pLFhS+ErKatjGcNEab2OlU3bX5UoBs+TYodnCWGKOuBKV
  111. L/CYc65QyeYZ+JiwYn9wC8YkzOnnVIQjiCEkLgSL30h9dxpnTZDLrdAA8ItelDn5
  112. DvjuQq58CGDsaVqpSobiSC1DMXYWot4Ets1wwovUNEq1l0MERB+2olE+JU/8E23E
  113. eL1/aA7Kw/JibkWz1IyzClpFDKXf6kR2onJyxerdwUL+is7tqYFLysiHxZDL1bli
  114. SXbW8hMa5gvo0IilFP9Rznn8PplIfCsvBDVv6xsRr5nTAFtwKaMBVgznE2ghs69w
  115. kK8u1YiiVenmoQ==
  116. -----END CERTIFICATE-----`
  117. caCRL = `-----BEGIN X509 CRL-----
  118. MIICpzCBkAIBATANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDEwhDZXJ0QXV0aBcN
  119. MjQwMTEwMTgyMjU4WhcNMjYwMTA5MTgyMjU4WjAkMCICEQDOaeHbjY4pEj8WBmqg
  120. ZuRRFw0yNDAxMTAxODIyNThaoCMwITAfBgNVHSMEGDAWgBTaCYSLw2UKxH/1UG1r
  121. rl4DZ7dpuTANBgkqhkiG9w0BAQsFAAOCAgEAZzZ4aBqCcAJigR9e/mqKpJa4B6FV
  122. +jZmnWXolGeUuVkjdiG9w614x7mB2S768iioJyALejjCZjqsp6ydxtn0epQw4199
  123. XSfPIxA9lxc7w79GLe0v3ztojvxDPh5V1+lwPzGf9i8AsGqb2BrcBqgxDeatndnE
  124. jF+18bY1saXOBpukNLjtRScUXzy5YcSuO6mwz4548v+1ebpF7W4Yh+yh0zldJKcF
  125. DouuirZWujJwTwxxfJ+2+yP7GAuefXUOhYs/1y9ylvUgvKFqSyokv6OaVgTooKYD
  126. MSADzmNcbRvwyAC5oL2yJTVVoTFeP6fXl/BdFH3sO/hlKXGy4Wh1AjcVE6T0CSJ4
  127. iYFX3gLFh6dbP9IQWMlIM5DKtAKSjmgOywEaWii3e4M0NFSf/Cy17p2E5/jXSLlE
  128. ypDileK0aALkx2twGWwogh6sY1dQ6R3GpKSRPD2muQxVOG6wXvuJce0E9WLx1Ud4
  129. hVUdUEMlKUvm77/15U5awarH2cCJQxzS/GMeIintQiG7hUlgRzRdmWVe3vOOvt94
  130. cp8+ZUH/QSDOo41ATTHpFeC/XqF5E2G/ahXqra+O5my52V/FP0bSJnkorJ8apy67
  131. sn6DFbkqX9khTXGtacczh2PcqVjcQjBniYl2sPO3qIrrrY3tic96tMnM/u3JRdcn
  132. w7bXJGfJcIMrrKs=
  133. -----END X509 CRL-----`
  134. client1Crt = `-----BEGIN CERTIFICATE-----
  135. MIIEITCCAgmgAwIBAgIRAJr32nHRlhyPiS7IfZ/ZWYowDQYJKoZIhvcNAQELBQAw
  136. EzERMA8GA1UEAxMIQ2VydEF1dGgwHhcNMjQwMTEwMTgxMjM3WhcNMzQwMTEwMTgy
  137. MTUzWjASMRAwDgYDVQQDEwdjbGllbnQxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
  138. MIIBCgKCAQEAtuQFiqvdjd8WLxP0FgPDyDEJ1/uJ+Aoj6QllNV7svWxwW+kiJ3X6
  139. HUVNWhhCsNfly4pGW4erF4fZzmesElGx1PoWgQCWZKsa/N08bznelWgdmkyi85xE
  140. OkTj6e/cTWHFSOBURNJaXkGHZ0ROSh7qu0Ld+eqNo3k9W+NqZaqYvs2K7MLWeYl7
  141. Qie8Ctuq5Qaz/jm0XwR2PFBROVQSaCPCukancPQ21ftqHPhAbjxoxvvN5QP4ZdRf
  142. XlH/LDLhlFnJzPZdHnVy9xisSPPRfFApJiwyfjRYdtslpJOcNgP6oPlpX/dybbhO
  143. c9FEUgj/Q90Je8EfioBYFYsqVD6/dFv9SwIDAQABo3EwbzAOBgNVHQ8BAf8EBAMC
  144. A7gwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBRUh5Xo
  145. Gzjh6iReaPSOgGatqOw9bDAfBgNVHSMEGDAWgBTaCYSLw2UKxH/1UG1rrl4DZ7dp
  146. uTANBgkqhkiG9w0BAQsFAAOCAgEAyAK7cOTWqjyLgFM0kyyx1fNPvm2GwKep3MuU
  147. OrSnLuWjoxzb7WcbKNVMlnvnmSUAWuErxsY0PUJNfcuqWiGmEp4d/SWfWPigG6DC
  148. sDej35BlSfX8FCufYrfC74VNk4yBS2LVYmIqcpqUrfay0I2oZA8+ToLEpdUvEv2I
  149. l59eOhJO2jsC3JbOyZZmK2Kv7d94fR+1tg2Rq1Wbnmc9AZKq7KDReAlIJh4u2KHb
  150. BbtF79idusMwZyP777tqSQ4THBMa+VAEc2UrzdZqTIAwqlKQOvO2fRz2P+ARR+Tz
  151. MYJMdCdmPZ9qAc8U1OcFBG6qDDltO8wf/Nu/PsSI5LGCIhIuPPIuKfm0rRfTqCG7
  152. QPQPWjRoXtGGhwjdIuWbX9fIB+c+NpAEKHgLtV+Rxj8s5IVxqG9a5TtU9VkfVXJz
  153. J20naoz/G+vDsVINpd3kH0ziNvdrKfGRM5UgtnUOPCXB22fVmkIsMH2knI10CKK+
  154. offI56NTkLRu00xvg98/wdukhkwIAxg6PQI/BHY5mdvoacEHHHdOhMq+GSAh7DDX
  155. G8+HdbABM1ExkPnZLat15q706ztiuUpQv1C2DI8YviUVkMqCslj4cD4F8EFPo4kr
  156. kvme0Cuc9Qlf7N5rjdV3cjwavhFx44dyXj9aesft2Q1okPiIqbGNpcjHcIRlj4Au
  157. MU3Bo0A=
  158. -----END CERTIFICATE-----`
  159. client1Key = `-----BEGIN RSA PRIVATE KEY-----
  160. MIIEpAIBAAKCAQEAtuQFiqvdjd8WLxP0FgPDyDEJ1/uJ+Aoj6QllNV7svWxwW+ki
  161. J3X6HUVNWhhCsNfly4pGW4erF4fZzmesElGx1PoWgQCWZKsa/N08bznelWgdmkyi
  162. 85xEOkTj6e/cTWHFSOBURNJaXkGHZ0ROSh7qu0Ld+eqNo3k9W+NqZaqYvs2K7MLW
  163. eYl7Qie8Ctuq5Qaz/jm0XwR2PFBROVQSaCPCukancPQ21ftqHPhAbjxoxvvN5QP4
  164. ZdRfXlH/LDLhlFnJzPZdHnVy9xisSPPRfFApJiwyfjRYdtslpJOcNgP6oPlpX/dy
  165. bbhOc9FEUgj/Q90Je8EfioBYFYsqVD6/dFv9SwIDAQABAoIBAFjSHK7gENVZxphO
  166. hHg8k9ShnDo8eyDvK8l9Op3U3/yOsXKxolivvyx//7UFmz3vXDahjNHe7YScAXdw
  167. eezbqBXa7xrvghqZzp2HhFYwMJ0210mcdncBKVFzK4ztZHxgQ0PFTqet0R19jZjl
  168. X3A325/eNZeuBeOied4qb/24AD6JGc6A0J55f5/QUQtdwYwrL15iC/KZXDL90PPJ
  169. CFJyrSzcXvOMEvOfXIFxhDVKRCppyIYXG7c80gtNC37I6rxxMNQ4mxjwUI2IVhxL
  170. j+nZDu0JgRZ4NaGjOq2e79QxUVm/GG3z25XgmBFBrXkEVV+sCZE1VDyj6kQfv9FU
  171. NhOrwGECgYEAzq47r/HwXifuGYBV/mvInFw3BNLrKry+iUZrJ4ms4g+LfOi0BAgf
  172. sXsWXulpBo2YgYjFdO8G66f69GlB4B7iLscpABXbRtpDZEnchQpaF36/+4g3i8gB
  173. Z29XHNDB8+7t4wbXvlSnLv1tZWey2fS4hPosc2YlvS87DMmnJMJqhs8CgYEA4oiB
  174. LGQP6VNdX0Uigmh5fL1g1k95eC8GP1ylczCcIwsb2OkAq0MT7SHRXOlg3leEq4+g
  175. mCHk1NdjkSYxDL2ZeTKTS/gy4p1jlcDa6Ilwi4pVvatNvu4o80EYWxRNNb1mAn67
  176. T8TN9lzc6mEi+LepQM3nYJ3F+ZWTKgxH8uoJwMUCgYEArpumE1vbjUBAuEyi2eGn
  177. RunlFW83fBCfDAxw5KM8anNlja5uvuU6GU/6s06QCxg+2lh5MPPrLdXpfukZ3UVa
  178. Itjg+5B7gx1MSALaiY8YU7cibFdFThM3lHIM72wyH2ogkWcrh0GvSFSUQlJcWCSW
  179. asmMGiYXBgBL697FFZomMyMCgYEAkAnp0JcDQwHd4gDsk2zoqnckBsDb5J5J46n+
  180. DYNAFEww9bgZ08u/9MzG+cPu8xFE621U2MbcYLVfuuBE2ewIlPaij/COMmeO9Z59
  181. 0tPpOuDH6eTtd1SptxqR6P+8pEn8feOlKHBj4Z1kXqdK/EiTlwAVeep4Al2oCFls
  182. ujkz4F0CgYAe8vHnVFHlWi16zAqZx4ZZZhNuqPtgFkvPg9LfyNTA4dz7F9xgtUaY
  183. nXBPyCe/8NtgBfT79HkPiG3TM0xRZY9UZgsJKFtqAu5u4ManuWDnsZI9RK2QTLHe
  184. yEbH5r3Dg3n9k/3GbjXFIWdU9UaYsdnSKHHtMw9ZODc14LaAogEQug==
  185. -----END RSA PRIVATE KEY-----`
  186. // client 2 crt is revoked
  187. client2Crt = `-----BEGIN CERTIFICATE-----
  188. MIIEITCCAgmgAwIBAgIRAM5p4duNjikSPxYGaqBm5FEwDQYJKoZIhvcNAQELBQAw
  189. EzERMA8GA1UEAxMIQ2VydEF1dGgwHhcNMjQwMTEwMTgxMjUyWhcNMzQwMTEwMTgy
  190. MTUzWjASMRAwDgYDVQQDEwdjbGllbnQyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
  191. MIIBCgKCAQEApNYpNZVmXZtAObpRRIuP2o/7z04H2E161vKZvJ3LSLlUTImVjm/b
  192. Qe6DTNCUVLnzQuanmUlu2rUnN3lDSfYoBcJWbvC3y1OCPRkCjDV6KiYMA9TPkZua
  193. eq6y3+bFFfEmyumsVEe0bSuzNHXCOIBT7PqYMdovECcwBh/RZCA5mqO5omEKh4LQ
  194. cr6+sVVkvD3nsyx0Alz/kTLFqc0mVflmpJq+0BpdetHRg4n5vy/I/08jZ81PQAmT
  195. A0kyl0Jh132JBGFdA8eyugPPP8n5edU4f3HXV/nR7XLwBrpSt8KgEg8cwfAu4Ic0
  196. 6tGzB0CH8lSGtU0tH2/cOlDuguDD7VvokQIDAQABo3EwbzAOBgNVHQ8BAf8EBAMC
  197. A7gwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBR5mf0f
  198. Zjf8ZCGXqU2+45th7VkkLDAfBgNVHSMEGDAWgBTaCYSLw2UKxH/1UG1rrl4DZ7dp
  199. uTANBgkqhkiG9w0BAQsFAAOCAgEARhFxNAouwbpEfN1M90+ao5rwyxEewerSoCCz
  200. PQzeUZ66MA/FkS/tFUGgGGG+wERN+WLbe1cN6q/XFr0FSMLuUxLXDNV02oUL/FnY
  201. xcyNLaZUZ0pP7sA+Hmx2AdTA6baIwQbyIY9RLAaz6hzo1YbI8yeis645F1bxgL2D
  202. EP5kXa3Obv0tqWByMZtrmJPv3p0W5GJKXVDn51GR/E5KI7pliZX2e0LmMX9mxfPB
  203. 4sXFUggMHXxWMMSAmXPVsxC2KX6gMnajO7JUraTwuGm+6V371FzEX+UKXHI+xSvO
  204. 78TseTIYsBGLjeiA8UjkKlD3T9qsQm2mb2PlKyqjvIm4i2ilM0E2w4JZmd45b925
  205. 7q/QLV3NZ/zZMi6AMyULu28DWKfAx3RLKwnHWSFcR4lVkxQrbDhEUMhAhLAX+2+e
  206. qc7qZm3dTabi7ZJiiOvYK/yNgFHa/XtZp5uKPB5tigPIa+34hbZF7s2/ty5X3O1N
  207. f5Ardz7KNsxJjZIt6HvB28E/PPOvBqCKJc1Y08J9JbZi8p6QS1uarGoR7l7rT1Hv
  208. /ZXkNTw2bw1VpcWdzDBLLVHYNnJmS14189LVk11PcJJpSmubwCqg+ZZULdgtVr3S
  209. ANas2dgMPVwXhnAalgkcc+lb2QqaEz06axfbRGBsgnyqR5/koKCg1Hr0+vThHSsR
  210. E0+r2+4=
  211. -----END CERTIFICATE-----`
  212. client2Key = `-----BEGIN RSA PRIVATE KEY-----
  213. MIIEowIBAAKCAQEApNYpNZVmXZtAObpRRIuP2o/7z04H2E161vKZvJ3LSLlUTImV
  214. jm/bQe6DTNCUVLnzQuanmUlu2rUnN3lDSfYoBcJWbvC3y1OCPRkCjDV6KiYMA9TP
  215. kZuaeq6y3+bFFfEmyumsVEe0bSuzNHXCOIBT7PqYMdovECcwBh/RZCA5mqO5omEK
  216. h4LQcr6+sVVkvD3nsyx0Alz/kTLFqc0mVflmpJq+0BpdetHRg4n5vy/I/08jZ81P
  217. QAmTA0kyl0Jh132JBGFdA8eyugPPP8n5edU4f3HXV/nR7XLwBrpSt8KgEg8cwfAu
  218. 4Ic06tGzB0CH8lSGtU0tH2/cOlDuguDD7VvokQIDAQABAoIBAQCMnEeg9uXQmdvq
  219. op4qi6bV+ZcDWvvkLwvHikFMnYpIaheYBpF2ZMKzdmO4xgCSWeFCQ4Hah8KxfHCM
  220. qLuWvw2bBBE5J8yQ/JaPyeLbec7RX41GQ2YhPoxDdP0PdErREdpWo4imiFhH/Ewt
  221. Rvq7ufRdpdLoS8dzzwnvX3r+H2MkHoC/QANW2AOuVoZK5qyCH5N8yEAAbWKaQaeL
  222. VBhAYEVKbAkWEtXw7bYXzxRR7WIM3f45v3ncRusDIG+Hf75ZjatoH0lF1gHQNofO
  223. qkCVZVzjkLFuzDic2KZqsNORglNs4J6t5Dahb9v3hnoK963YMnVSUjFvqQ+/RZZy
  224. VILFShilAoGBANucwZU61eJ0tLKBYEwmRY/K7Gu1MvvcYJIOoX8/BL3zNmNO0CLl
  225. NiABtNt9WOVwZxDsxJXdo1zvMtAegNqS6W11R1VAZbL6mQ/krScbLDE6JKA5DmA7
  226. 4nNi1gJOW1ziAfdBAfhe4cLbQOb94xkOK5xM1YpO0xgDJLwrZbehDMmPAoGBAMAl
  227. /owPDAvcXz7JFynT0ieYVc64MSFiwGYJcsmxSAnbEgQ+TR5FtkHYe91OSqauZcCd
  228. aoKXQNyrYKIhyounRPFTdYQrlx6KtEs7LU9wOxuphhpJtGjRnhmA7IqvX703wNvu
  229. khrEavn86G5boH8R80371SrN0Rh9UeAlQGuNBdvfAoGAEAmokW9Ug08miwqrr6Pz
  230. 3IZjMZJwALidTM1IufQuMnj6ddIhnQrEIx48yPKkdUz6GeBQkuk2rujA+zXfDxc/
  231. eMDhzrX/N0zZtLFse7ieR5IJbrH7/MciyG5lVpHGVkgjAJ18uVikgAhm+vd7iC7i
  232. vG1YAtuyysQgAKXircBTIL0CgYAHeTLWVbt9NpwJwB6DhPaWjalAug9HIiUjktiB
  233. GcEYiQnBWn77X3DATOA8clAa/Yt9m2HKJIHkU1IV3ESZe+8Fh955PozJJlHu3yVb
  234. Ap157PUHTriSnxyMF2Sb3EhX/rQkmbnbCqqygHC14iBy8MrKzLG00X6BelZV5n0D
  235. 8d85dwKBgGWY2nsaemPH/TiTVF6kW1IKSQoIyJChkngc+Xj/2aCCkkmAEn8eqncl
  236. RKjnkiEZeG4+G91Xu7+HmcBLwV86k5I+tXK9O1Okomr6Zry8oqVcxU5TB6VRS+rA
  237. ubwF00Drdvk2+kDZfxIM137nBiy7wgCJi2Ksm5ihN3dUF6Q0oNPl
  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) //nolint:goconst
  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. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  637. 1*time.Second, 100*time.Millisecond)
  638. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  639. assert.NoError(t, err)
  640. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  641. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  642. files, err := client.ReadDir("/")
  643. assert.NoError(t, err)
  644. if assert.Len(t, files, 1) {
  645. assert.Equal(t, testFileSize, files[0].Size())
  646. }
  647. err = client.Remove(testFileName)
  648. assert.NoError(t, err)
  649. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  650. assert.NoError(t, err)
  651. assert.Equal(t, expectedQuotaFiles-1, user.UsedQuotaFiles)
  652. assert.Equal(t, expectedQuotaSize-encryptedFileSize, user.UsedQuotaSize)
  653. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  654. assert.Error(t, err)
  655. testDir := "testdir"
  656. err = client.Mkdir(testDir, os.ModePerm)
  657. assert.NoError(t, err)
  658. err = client.MkdirAll(path.Join(testDir, "sub", "sub"), os.ModePerm)
  659. assert.NoError(t, err)
  660. err = client.MkdirAll(path.Join(testDir, "sub1", "sub1"), os.ModePerm)
  661. assert.NoError(t, err)
  662. err = client.MkdirAll(path.Join(testDir, "sub2", "sub2"), os.ModePerm)
  663. assert.NoError(t, err)
  664. err = uploadFileWithRawClient(testFilePath, path.Join(testDir, testFileName+".txt"),
  665. user.Username, defaultPassword, false, testFileSize, client)
  666. assert.NoError(t, err)
  667. err = uploadFileWithRawClient(testFilePath, path.Join(testDir, testFileName),
  668. user.Username, defaultPassword, false, testFileSize, client)
  669. assert.NoError(t, err)
  670. files, err = client.ReadDir(testDir)
  671. assert.NoError(t, err)
  672. assert.Len(t, files, 5)
  673. for _, f := range files {
  674. if strings.HasPrefix(f.Name(), testFileName) {
  675. assert.Equal(t, testFileSize, f.Size())
  676. } else {
  677. assert.True(t, f.IsDir())
  678. }
  679. }
  680. err = os.Remove(testFilePath)
  681. assert.NoError(t, err)
  682. err = os.Remove(localDownloadPath)
  683. assert.NoError(t, err)
  684. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  685. assert.NoError(t, err)
  686. err = os.RemoveAll(user.GetHomeDir())
  687. assert.NoError(t, err)
  688. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  689. 1*time.Second, 100*time.Millisecond)
  690. }
  691. func TestBufferedUser(t *testing.T) {
  692. u := getTestUser()
  693. u.FsConfig.OSConfig = sdk.OSFsConfig{
  694. WriteBufferSize: 2,
  695. ReadBufferSize: 1,
  696. }
  697. vdirPath := "/crypted"
  698. mappedPath := filepath.Join(os.TempDir(), util.GenerateUniqueID())
  699. folderName := filepath.Base(mappedPath)
  700. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  701. BaseVirtualFolder: vfs.BaseVirtualFolder{
  702. Name: folderName,
  703. },
  704. VirtualPath: vdirPath,
  705. QuotaFiles: -1,
  706. QuotaSize: -1,
  707. })
  708. f := vfs.BaseVirtualFolder{
  709. Name: folderName,
  710. MappedPath: mappedPath,
  711. FsConfig: vfs.Filesystem{
  712. Provider: sdk.CryptedFilesystemProvider,
  713. CryptConfig: vfs.CryptFsConfig{
  714. OSFsConfig: sdk.OSFsConfig{
  715. WriteBufferSize: 3,
  716. ReadBufferSize: 2,
  717. },
  718. Passphrase: kms.NewPlainSecret(defaultPassword),
  719. },
  720. },
  721. }
  722. _, _, err := httpdtest.AddFolder(f, http.StatusCreated)
  723. assert.NoError(t, err)
  724. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  725. assert.NoError(t, err)
  726. client := getWebDavClient(user, false, nil)
  727. assert.NoError(t, checkBasicFunc(client))
  728. testFilePath := filepath.Join(homeBasePath, testFileName)
  729. testFileSize := int64(65535)
  730. err = createTestFile(testFilePath, testFileSize)
  731. assert.NoError(t, err)
  732. err = uploadFileWithRawClient(testFilePath, testFileName,
  733. user.Username, defaultPassword, false, testFileSize, client)
  734. assert.NoError(t, err)
  735. err = uploadFileWithRawClient(testFilePath, path.Join(vdirPath, testFileName),
  736. user.Username, defaultPassword, false, testFileSize, client)
  737. assert.NoError(t, err)
  738. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  739. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  740. assert.NoError(t, err)
  741. err = downloadFile(path.Join(vdirPath, testFileName), localDownloadPath, testFileSize, client)
  742. assert.NoError(t, err)
  743. err = os.Remove(testFilePath)
  744. assert.NoError(t, err)
  745. err = os.Remove(localDownloadPath)
  746. assert.NoError(t, err)
  747. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  748. assert.NoError(t, err)
  749. err = os.RemoveAll(user.GetHomeDir())
  750. assert.NoError(t, err)
  751. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  752. assert.NoError(t, err)
  753. err = os.RemoveAll(mappedPath)
  754. assert.NoError(t, err)
  755. }
  756. func TestLoginEmptyPassword(t *testing.T) {
  757. u := getTestUser()
  758. u.Password = ""
  759. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  760. assert.NoError(t, err)
  761. user.Password = emptyPwdPlaceholder
  762. client := getWebDavClient(user, false, nil)
  763. err = checkBasicFunc(client)
  764. if assert.Error(t, err) {
  765. assert.Contains(t, err.Error(), "401")
  766. }
  767. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  768. assert.NoError(t, err)
  769. err = os.RemoveAll(user.GetHomeDir())
  770. assert.NoError(t, err)
  771. }
  772. func TestAnonymousUser(t *testing.T) {
  773. u := getTestUser()
  774. u.Password = ""
  775. u.Filters.IsAnonymous = true
  776. _, _, err := httpdtest.AddUser(u, http.StatusCreated)
  777. assert.Error(t, err)
  778. user, _, err := httpdtest.GetUserByUsername(u.Username, http.StatusOK)
  779. assert.NoError(t, err)
  780. client := getWebDavClient(user, false, nil)
  781. assert.NoError(t, checkBasicFunc(client))
  782. user.Password = emptyPwdPlaceholder
  783. client = getWebDavClient(user, false, nil)
  784. assert.NoError(t, checkBasicFunc(client))
  785. testFilePath := filepath.Join(homeBasePath, testFileName)
  786. testFileSize := int64(65535)
  787. err = createTestFile(testFilePath, testFileSize)
  788. assert.NoError(t, err)
  789. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  790. false, testFileSize, client)
  791. if assert.Error(t, err) {
  792. assert.Contains(t, err.Error(), "403")
  793. }
  794. err = client.Mkdir("testdir", os.ModePerm)
  795. if assert.Error(t, err) {
  796. assert.Contains(t, err.Error(), "403")
  797. }
  798. err = os.Remove(testFilePath)
  799. assert.NoError(t, err)
  800. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  801. assert.NoError(t, err)
  802. err = os.RemoveAll(user.GetHomeDir())
  803. assert.NoError(t, err)
  804. }
  805. func TestLockAfterDelete(t *testing.T) {
  806. u := getTestUser()
  807. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  808. assert.NoError(t, err)
  809. client := getWebDavClient(user, false, nil)
  810. assert.NoError(t, checkBasicFunc(client))
  811. testFilePath := filepath.Join(homeBasePath, testFileName)
  812. testFileSize := int64(65535)
  813. err = createTestFile(testFilePath, testFileSize)
  814. assert.NoError(t, err)
  815. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  816. false, testFileSize, client)
  817. assert.NoError(t, err)
  818. 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>`
  819. req, err := http.NewRequest("LOCK", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(lockBody)))
  820. assert.NoError(t, err)
  821. req.SetBasicAuth(u.Username, u.Password)
  822. req.Header.Set("Timeout", "Second-3600")
  823. httpClient := httpclient.GetHTTPClient()
  824. resp, err := httpClient.Do(req)
  825. assert.NoError(t, err)
  826. assert.Equal(t, http.StatusOK, resp.StatusCode)
  827. response, err := io.ReadAll(resp.Body)
  828. assert.NoError(t, err)
  829. re := regexp.MustCompile(`\<D:locktoken><D:href>.*</D:href>`)
  830. lockToken := string(re.Find(response))
  831. lockToken = strings.Replace(lockToken, "<D:locktoken><D:href>", "", 1)
  832. lockToken = strings.Replace(lockToken, "</D:href>", "", 1)
  833. err = resp.Body.Close()
  834. assert.NoError(t, err)
  835. req, err = http.NewRequest(http.MethodDelete, fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), nil)
  836. assert.NoError(t, err)
  837. req.Header.Set("If", fmt.Sprintf("(%v)", lockToken))
  838. req.SetBasicAuth(u.Username, u.Password)
  839. resp, err = httpClient.Do(req)
  840. assert.NoError(t, err)
  841. assert.Equal(t, http.StatusNoContent, resp.StatusCode)
  842. err = resp.Body.Close()
  843. assert.NoError(t, err)
  844. // if we try to lock again it must succeed, the lock must be deleted with the object
  845. req, err = http.NewRequest("LOCK", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(lockBody)))
  846. assert.NoError(t, err)
  847. req.SetBasicAuth(u.Username, u.Password)
  848. resp, err = httpClient.Do(req)
  849. assert.NoError(t, err)
  850. assert.Equal(t, http.StatusCreated, resp.StatusCode)
  851. err = resp.Body.Close()
  852. assert.NoError(t, err)
  853. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  854. assert.NoError(t, err)
  855. err = os.RemoveAll(user.GetHomeDir())
  856. assert.NoError(t, err)
  857. }
  858. func TestMtimeHeader(t *testing.T) {
  859. u := getTestUser()
  860. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  861. assert.NoError(t, err)
  862. client := getWebDavClient(user, false, nil)
  863. assert.NoError(t, checkBasicFunc(client))
  864. testFilePath := filepath.Join(homeBasePath, testFileName)
  865. testFileSize := int64(65535)
  866. err = createTestFile(testFilePath, testFileSize)
  867. assert.NoError(t, err)
  868. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  869. false, testFileSize, client, dataprovider.KeyValue{Key: ocMtimeHeader, Value: "1668879480"})
  870. assert.NoError(t, err)
  871. // check the modification time
  872. info, err := client.Stat(testFileName)
  873. if assert.NoError(t, err) {
  874. assert.Equal(t, time.Unix(1668879480, 0).UTC(), info.ModTime().UTC())
  875. }
  876. // test on overwrite
  877. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  878. false, testFileSize, client, dataprovider.KeyValue{Key: ocMtimeHeader, Value: "1667879480"})
  879. assert.NoError(t, err)
  880. info, err = client.Stat(testFileName)
  881. if assert.NoError(t, err) {
  882. assert.Equal(t, time.Unix(1667879480, 0).UTC(), info.ModTime().UTC())
  883. }
  884. // invalid time will be silently ignored and the time set to now
  885. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  886. false, testFileSize, client, dataprovider.KeyValue{Key: ocMtimeHeader, Value: "not unix time"})
  887. assert.NoError(t, err)
  888. info, err = client.Stat(testFileName)
  889. if assert.NoError(t, err) {
  890. assert.NotEqual(t, time.Unix(1667879480, 0).UTC(), info.ModTime().UTC())
  891. }
  892. req, err := http.NewRequest("MOVE", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), nil)
  893. assert.NoError(t, err)
  894. req.Header.Set("Overwrite", "T")
  895. req.Header.Set("Destination", path.Join("/", testFileName+"rename"))
  896. req.Header.Set(ocMtimeHeader, "1666779480")
  897. req.SetBasicAuth(u.Username, u.Password)
  898. httpClient := httpclient.GetHTTPClient()
  899. resp, err := httpClient.Do(req)
  900. assert.NoError(t, err)
  901. assert.Equal(t, http.StatusCreated, resp.StatusCode)
  902. err = resp.Body.Close()
  903. assert.NoError(t, err)
  904. // check the modification time
  905. info, err = client.Stat(testFileName + "rename")
  906. if assert.NoError(t, err) {
  907. assert.Equal(t, time.Unix(1666779480, 0).UTC(), info.ModTime().UTC())
  908. }
  909. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  910. assert.NoError(t, err)
  911. err = os.RemoveAll(user.GetHomeDir())
  912. assert.NoError(t, err)
  913. }
  914. func TestRenameWithLock(t *testing.T) {
  915. u := getTestUser()
  916. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  917. assert.NoError(t, err)
  918. client := getWebDavClient(user, false, nil)
  919. assert.NoError(t, checkBasicFunc(client))
  920. testFilePath := filepath.Join(homeBasePath, testFileName)
  921. testFileSize := int64(65535)
  922. err = createTestFile(testFilePath, testFileSize)
  923. assert.NoError(t, err)
  924. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  925. false, testFileSize, client)
  926. assert.NoError(t, err)
  927. 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>`
  928. req, err := http.NewRequest("LOCK", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(lockBody)))
  929. assert.NoError(t, err)
  930. req.SetBasicAuth(u.Username, u.Password)
  931. httpClient := httpclient.GetHTTPClient()
  932. resp, err := httpClient.Do(req)
  933. assert.NoError(t, err)
  934. assert.Equal(t, http.StatusOK, resp.StatusCode)
  935. response, err := io.ReadAll(resp.Body)
  936. assert.NoError(t, err)
  937. re := regexp.MustCompile(`\<D:locktoken><D:href>.*</D:href>`)
  938. lockToken := string(re.Find(response))
  939. lockToken = strings.Replace(lockToken, "<D:locktoken><D:href>", "", 1)
  940. lockToken = strings.Replace(lockToken, "</D:href>", "", 1)
  941. err = resp.Body.Close()
  942. assert.NoError(t, err)
  943. // MOVE with a lock should succeeded
  944. req, err = http.NewRequest("MOVE", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), nil)
  945. assert.NoError(t, err)
  946. req.Header.Set("If", fmt.Sprintf("(%v)", lockToken))
  947. req.Header.Set("Overwrite", "T")
  948. req.Header.Set("Destination", path.Join("/", testFileName+"1"))
  949. req.SetBasicAuth(u.Username, u.Password)
  950. resp, err = httpClient.Do(req)
  951. assert.NoError(t, err)
  952. assert.Equal(t, http.StatusCreated, resp.StatusCode)
  953. err = resp.Body.Close()
  954. assert.NoError(t, err)
  955. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  956. assert.NoError(t, err)
  957. err = os.RemoveAll(user.GetHomeDir())
  958. assert.NoError(t, err)
  959. }
  960. func TestPropPatch(t *testing.T) {
  961. u := getTestUser()
  962. u.Username = u.Username + "1"
  963. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  964. assert.NoError(t, err)
  965. sftpUser := getTestSFTPUser()
  966. sftpUser.FsConfig.SFTPConfig.Username = localUser.Username
  967. for _, u := range []dataprovider.User{getTestUser(), getTestUserWithCryptFs(), sftpUser} {
  968. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  969. assert.NoError(t, err)
  970. client := getWebDavClient(user, true, nil)
  971. assert.NoError(t, checkBasicFunc(client), sftpUser.Username)
  972. testFilePath := filepath.Join(homeBasePath, testFileName)
  973. testFileSize := int64(65535)
  974. err = createTestFile(testFilePath, testFileSize)
  975. assert.NoError(t, err)
  976. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  977. false, testFileSize, client)
  978. assert.NoError(t, err)
  979. httpClient := httpclient.GetHTTPClient()
  980. 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>`
  981. req, err := http.NewRequest("PROPPATCH", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(propatchBody)))
  982. assert.NoError(t, err)
  983. req.SetBasicAuth(u.Username, u.Password)
  984. resp, err := httpClient.Do(req)
  985. assert.NoError(t, err)
  986. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  987. err = resp.Body.Close()
  988. assert.NoError(t, err)
  989. info, err := client.Stat(testFileName)
  990. if assert.NoError(t, err) {
  991. expected, err := http.ParseTime("Wed, 04 Nov 2020 13:25:51 GMT")
  992. assert.NoError(t, err)
  993. assert.Equal(t, testFileSize, info.Size())
  994. assert.Equal(t, expected.Format(http.TimeFormat), info.ModTime().Format(http.TimeFormat))
  995. }
  996. // wrong date
  997. 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>`
  998. req, err = http.NewRequest("PROPPATCH", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(propatchBody)))
  999. assert.NoError(t, err)
  1000. req.SetBasicAuth(u.Username, u.Password)
  1001. resp, err = httpClient.Do(req)
  1002. assert.NoError(t, err)
  1003. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  1004. err = resp.Body.Close()
  1005. assert.NoError(t, err)
  1006. err = os.Remove(testFilePath)
  1007. assert.NoError(t, err)
  1008. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1009. assert.NoError(t, err)
  1010. err = os.RemoveAll(user.GetHomeDir())
  1011. assert.NoError(t, err)
  1012. }
  1013. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1014. assert.NoError(t, err)
  1015. err = os.RemoveAll(localUser.GetHomeDir())
  1016. assert.NoError(t, err)
  1017. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  1018. 1*time.Second, 100*time.Millisecond)
  1019. }
  1020. func TestLoginInvalidPwd(t *testing.T) {
  1021. u := getTestUser()
  1022. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1023. assert.NoError(t, err)
  1024. client := getWebDavClient(user, false, nil)
  1025. assert.NoError(t, checkBasicFunc(client))
  1026. user.Password = "wrong"
  1027. client = getWebDavClient(user, false, nil)
  1028. assert.Error(t, checkBasicFunc(client))
  1029. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1030. assert.NoError(t, err)
  1031. }
  1032. func TestLoginNonExistentUser(t *testing.T) {
  1033. user := getTestUser()
  1034. client := getWebDavClient(user, true, nil)
  1035. assert.Error(t, checkBasicFunc(client))
  1036. }
  1037. func TestRateLimiter(t *testing.T) {
  1038. oldConfig := config.GetCommonConfig()
  1039. cfg := config.GetCommonConfig()
  1040. cfg.RateLimitersConfig = []common.RateLimiterConfig{
  1041. {
  1042. Average: 1,
  1043. Period: 1000,
  1044. Burst: 3,
  1045. Type: 1,
  1046. Protocols: []string{common.ProtocolWebDAV},
  1047. },
  1048. }
  1049. err := common.Initialize(cfg, 0)
  1050. assert.NoError(t, err)
  1051. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1052. assert.NoError(t, err)
  1053. client := getWebDavClient(user, false, nil)
  1054. assert.NoError(t, checkBasicFunc(client))
  1055. _, err = client.ReadDir(".")
  1056. if assert.Error(t, err) {
  1057. assert.Contains(t, err.Error(), "429")
  1058. }
  1059. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1060. assert.NoError(t, err)
  1061. err = os.RemoveAll(user.GetHomeDir())
  1062. assert.NoError(t, err)
  1063. err = common.Initialize(oldConfig, 0)
  1064. assert.NoError(t, err)
  1065. }
  1066. func TestDefender(t *testing.T) {
  1067. oldConfig := config.GetCommonConfig()
  1068. cfg := config.GetCommonConfig()
  1069. cfg.DefenderConfig.Enabled = true
  1070. cfg.DefenderConfig.Threshold = 3
  1071. cfg.DefenderConfig.ScoreLimitExceeded = 2
  1072. cfg.DefenderConfig.ScoreValid = 1
  1073. err := common.Initialize(cfg, 0)
  1074. assert.NoError(t, err)
  1075. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1076. assert.NoError(t, err)
  1077. client := getWebDavClient(user, true, nil)
  1078. assert.NoError(t, checkBasicFunc(client))
  1079. user.Password = "wrong_pwd"
  1080. client = getWebDavClient(user, false, nil)
  1081. assert.Error(t, checkBasicFunc(client))
  1082. hosts, _, err := httpdtest.GetDefenderHosts(http.StatusOK)
  1083. assert.NoError(t, err)
  1084. if assert.Len(t, hosts, 1) {
  1085. host := hosts[0]
  1086. assert.Empty(t, host.GetBanTime())
  1087. assert.Equal(t, 1, host.Score)
  1088. }
  1089. for i := 0; i < 2; i++ {
  1090. client = getWebDavClient(user, false, nil)
  1091. assert.Error(t, checkBasicFunc(client))
  1092. }
  1093. user.Password = defaultPassword
  1094. client = getWebDavClient(user, true, nil)
  1095. err = checkBasicFunc(client)
  1096. if assert.Error(t, err) {
  1097. assert.Contains(t, err.Error(), "403")
  1098. }
  1099. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1100. assert.NoError(t, err)
  1101. err = os.RemoveAll(user.GetHomeDir())
  1102. assert.NoError(t, err)
  1103. err = common.Initialize(oldConfig, 0)
  1104. assert.NoError(t, err)
  1105. }
  1106. func TestLoginExternalAuth(t *testing.T) {
  1107. if runtime.GOOS == osWindows {
  1108. t.Skip("this test is not available on Windows")
  1109. }
  1110. u := getTestUser()
  1111. err := dataprovider.Close()
  1112. assert.NoError(t, err)
  1113. err = config.LoadConfig(configDir, "")
  1114. assert.NoError(t, err)
  1115. providerConf := config.GetProviderConf()
  1116. err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u, ""), os.ModePerm)
  1117. assert.NoError(t, err)
  1118. providerConf.ExternalAuthHook = extAuthPath
  1119. providerConf.ExternalAuthScope = 0
  1120. err = dataprovider.Initialize(providerConf, configDir, true)
  1121. assert.NoError(t, err)
  1122. client := getWebDavClient(u, false, nil)
  1123. assert.NoError(t, checkBasicFunc(client))
  1124. u.Username = defaultUsername + "1"
  1125. client = getWebDavClient(u, false, nil)
  1126. assert.Error(t, checkBasicFunc(client))
  1127. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  1128. assert.NoError(t, err)
  1129. assert.Equal(t, defaultUsername, user.Username)
  1130. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1131. assert.NoError(t, err)
  1132. err = os.RemoveAll(user.GetHomeDir())
  1133. assert.NoError(t, err)
  1134. err = dataprovider.Close()
  1135. assert.NoError(t, err)
  1136. err = config.LoadConfig(configDir, "")
  1137. assert.NoError(t, err)
  1138. providerConf = config.GetProviderConf()
  1139. err = dataprovider.Initialize(providerConf, configDir, true)
  1140. assert.NoError(t, err)
  1141. err = os.Remove(extAuthPath)
  1142. assert.NoError(t, err)
  1143. }
  1144. func TestExternalAuthPasswordChange(t *testing.T) {
  1145. if runtime.GOOS == osWindows {
  1146. t.Skip("this test is not available on Windows")
  1147. }
  1148. u := getTestUser()
  1149. err := dataprovider.Close()
  1150. assert.NoError(t, err)
  1151. err = config.LoadConfig(configDir, "")
  1152. assert.NoError(t, err)
  1153. providerConf := config.GetProviderConf()
  1154. err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u, defaultPassword), os.ModePerm)
  1155. assert.NoError(t, err)
  1156. providerConf.ExternalAuthHook = extAuthPath
  1157. providerConf.ExternalAuthScope = 0
  1158. err = dataprovider.Initialize(providerConf, configDir, true)
  1159. assert.NoError(t, err)
  1160. client := getWebDavClient(u, false, nil)
  1161. assert.NoError(t, checkBasicFunc(client))
  1162. u.Username = defaultUsername + "1"
  1163. client = getWebDavClient(u, false, nil)
  1164. assert.Error(t, checkBasicFunc(client))
  1165. err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u, defaultPassword+"1"), os.ModePerm)
  1166. assert.NoError(t, err)
  1167. client = getWebDavClient(u, false, nil)
  1168. assert.Error(t, checkBasicFunc(client))
  1169. u.Password = defaultPassword + "1"
  1170. client = getWebDavClient(u, false, nil)
  1171. assert.NoError(t, checkBasicFunc(client))
  1172. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  1173. assert.NoError(t, err)
  1174. assert.Equal(t, defaultUsername, user.Username)
  1175. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1176. assert.NoError(t, err)
  1177. err = os.RemoveAll(user.GetHomeDir())
  1178. assert.NoError(t, err)
  1179. user, _, err = httpdtest.GetUserByUsername(defaultUsername+"1", http.StatusOK)
  1180. assert.NoError(t, err)
  1181. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1182. assert.NoError(t, err)
  1183. err = dataprovider.Close()
  1184. assert.NoError(t, err)
  1185. err = config.LoadConfig(configDir, "")
  1186. assert.NoError(t, err)
  1187. providerConf = config.GetProviderConf()
  1188. err = dataprovider.Initialize(providerConf, configDir, true)
  1189. assert.NoError(t, err)
  1190. err = os.Remove(extAuthPath)
  1191. assert.NoError(t, err)
  1192. }
  1193. func TestExternalAuthReturningAnonymousUser(t *testing.T) {
  1194. if runtime.GOOS == osWindows {
  1195. t.Skip("this test is not available on Windows")
  1196. }
  1197. u := getTestUser()
  1198. u.Filters.IsAnonymous = true
  1199. u.Filters.DeniedProtocols = []string{common.ProtocolSSH}
  1200. u.Password = ""
  1201. err := dataprovider.Close()
  1202. assert.NoError(t, err)
  1203. err = config.LoadConfig(configDir, "")
  1204. assert.NoError(t, err)
  1205. providerConf := config.GetProviderConf()
  1206. err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u, ""), os.ModePerm)
  1207. assert.NoError(t, err)
  1208. providerConf.ExternalAuthHook = extAuthPath
  1209. providerConf.ExternalAuthScope = 0
  1210. err = dataprovider.Initialize(providerConf, configDir, true)
  1211. assert.NoError(t, err)
  1212. client := getWebDavClient(u, false, nil)
  1213. assert.NoError(t, checkBasicFunc(client))
  1214. testFilePath := filepath.Join(homeBasePath, testFileName)
  1215. testFileSize := int64(65535)
  1216. err = createTestFile(testFilePath, testFileSize)
  1217. assert.NoError(t, err)
  1218. err = uploadFileWithRawClient(testFilePath, testFileName, u.Username, emptyPwdPlaceholder,
  1219. false, testFileSize, client)
  1220. if assert.Error(t, err) {
  1221. assert.Contains(t, err.Error(), "403")
  1222. }
  1223. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  1224. assert.NoError(t, err)
  1225. assert.True(t, user.Filters.IsAnonymous)
  1226. assert.Equal(t, []string{dataprovider.PermListItems, dataprovider.PermDownload}, user.Permissions["/"])
  1227. assert.Equal(t, []string{common.ProtocolSSH, common.ProtocolHTTP}, user.Filters.DeniedProtocols)
  1228. assert.Equal(t, []string{dataprovider.SSHLoginMethodPublicKey, dataprovider.SSHLoginMethodPassword,
  1229. dataprovider.SSHLoginMethodKeyboardInteractive, dataprovider.SSHLoginMethodKeyAndPassword,
  1230. dataprovider.SSHLoginMethodKeyAndKeyboardInt, dataprovider.LoginMethodTLSCertificate,
  1231. dataprovider.LoginMethodTLSCertificateAndPwd}, user.Filters.DeniedLoginMethods)
  1232. u.Password = emptyPwdPlaceholder
  1233. client = getWebDavClient(user, false, nil)
  1234. assert.NoError(t, checkBasicFunc(client))
  1235. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1236. false, testFileSize, client)
  1237. if assert.Error(t, err) {
  1238. assert.Contains(t, err.Error(), "403")
  1239. }
  1240. err = client.Mkdir("testdir", os.ModePerm)
  1241. if assert.Error(t, err) {
  1242. assert.Contains(t, err.Error(), "403")
  1243. }
  1244. err = os.Remove(testFilePath)
  1245. assert.NoError(t, err)
  1246. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1247. assert.NoError(t, err)
  1248. err = os.RemoveAll(user.GetHomeDir())
  1249. assert.NoError(t, err)
  1250. err = dataprovider.Close()
  1251. assert.NoError(t, err)
  1252. err = config.LoadConfig(configDir, "")
  1253. assert.NoError(t, err)
  1254. providerConf = config.GetProviderConf()
  1255. err = dataprovider.Initialize(providerConf, configDir, true)
  1256. assert.NoError(t, err)
  1257. err = os.Remove(extAuthPath)
  1258. assert.NoError(t, err)
  1259. }
  1260. func TestExternalAuthAnonymousGroupInheritance(t *testing.T) {
  1261. if runtime.GOOS == osWindows {
  1262. t.Skip("this test is not available on Windows")
  1263. }
  1264. g := dataprovider.Group{
  1265. BaseGroup: sdk.BaseGroup{
  1266. Name: "test_group",
  1267. },
  1268. UserSettings: dataprovider.GroupUserSettings{
  1269. BaseGroupUserSettings: sdk.BaseGroupUserSettings{
  1270. Permissions: map[string][]string{
  1271. "/": allPerms,
  1272. },
  1273. Filters: sdk.BaseUserFilters{
  1274. IsAnonymous: true,
  1275. },
  1276. },
  1277. },
  1278. }
  1279. u := getTestUser()
  1280. u.Groups = []sdk.GroupMapping{
  1281. {
  1282. Name: g.Name,
  1283. Type: sdk.GroupTypePrimary,
  1284. },
  1285. }
  1286. err := dataprovider.Close()
  1287. assert.NoError(t, err)
  1288. err = config.LoadConfig(configDir, "")
  1289. assert.NoError(t, err)
  1290. providerConf := config.GetProviderConf()
  1291. err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u, ""), os.ModePerm)
  1292. assert.NoError(t, err)
  1293. providerConf.ExternalAuthHook = extAuthPath
  1294. providerConf.ExternalAuthScope = 0
  1295. err = dataprovider.Initialize(providerConf, configDir, true)
  1296. assert.NoError(t, err)
  1297. group, _, err := httpdtest.AddGroup(g, http.StatusCreated)
  1298. assert.NoError(t, err)
  1299. u.Password = emptyPwdPlaceholder
  1300. client := getWebDavClient(u, false, nil)
  1301. assert.NoError(t, checkBasicFunc(client))
  1302. err = client.Mkdir("tdir", os.ModePerm)
  1303. if assert.Error(t, err) {
  1304. assert.Contains(t, err.Error(), "403")
  1305. }
  1306. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  1307. assert.NoError(t, err)
  1308. assert.False(t, user.Filters.IsAnonymous)
  1309. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1310. assert.NoError(t, err)
  1311. err = os.RemoveAll(user.GetHomeDir())
  1312. assert.NoError(t, err)
  1313. _, err = httpdtest.RemoveGroup(group, http.StatusOK)
  1314. assert.NoError(t, err)
  1315. err = dataprovider.Close()
  1316. assert.NoError(t, err)
  1317. err = config.LoadConfig(configDir, "")
  1318. assert.NoError(t, err)
  1319. providerConf = config.GetProviderConf()
  1320. err = dataprovider.Initialize(providerConf, configDir, true)
  1321. assert.NoError(t, err)
  1322. err = os.Remove(extAuthPath)
  1323. assert.NoError(t, err)
  1324. }
  1325. func TestPreLoginHook(t *testing.T) {
  1326. if runtime.GOOS == osWindows {
  1327. t.Skip("this test is not available on Windows")
  1328. }
  1329. u := getTestUser()
  1330. err := dataprovider.Close()
  1331. assert.NoError(t, err)
  1332. err = config.LoadConfig(configDir, "")
  1333. assert.NoError(t, err)
  1334. providerConf := config.GetProviderConf()
  1335. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
  1336. assert.NoError(t, err)
  1337. providerConf.PreLoginHook = preLoginPath
  1338. err = dataprovider.Initialize(providerConf, configDir, true)
  1339. assert.NoError(t, err)
  1340. _, _, err = httpdtest.GetUserByUsername(defaultUsername, http.StatusNotFound)
  1341. assert.NoError(t, err)
  1342. client := getWebDavClient(u, true, nil)
  1343. assert.NoError(t, checkBasicFunc(client))
  1344. user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
  1345. assert.NoError(t, err)
  1346. // test login with an existing user
  1347. client = getWebDavClient(user, true, nil)
  1348. assert.NoError(t, checkBasicFunc(client))
  1349. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), os.ModePerm)
  1350. assert.NoError(t, err)
  1351. // update the user to remove it from the cache
  1352. user.FsConfig.Provider = sdk.CryptedFilesystemProvider
  1353. user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret(defaultPassword)
  1354. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1355. assert.NoError(t, err)
  1356. client = getWebDavClient(user, true, nil)
  1357. assert.Error(t, checkBasicFunc(client))
  1358. // update the user to remove it from the cache
  1359. user.FsConfig.Provider = sdk.LocalFilesystemProvider
  1360. user.FsConfig.CryptConfig.Passphrase = nil
  1361. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1362. assert.NoError(t, err)
  1363. user.Status = 0
  1364. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), os.ModePerm)
  1365. assert.NoError(t, err)
  1366. client = getWebDavClient(user, true, nil)
  1367. assert.Error(t, checkBasicFunc(client))
  1368. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1369. assert.NoError(t, err)
  1370. err = os.RemoveAll(user.GetHomeDir())
  1371. assert.NoError(t, err)
  1372. err = dataprovider.Close()
  1373. assert.NoError(t, err)
  1374. err = config.LoadConfig(configDir, "")
  1375. assert.NoError(t, err)
  1376. providerConf = config.GetProviderConf()
  1377. err = dataprovider.Initialize(providerConf, configDir, true)
  1378. assert.NoError(t, err)
  1379. err = os.Remove(preLoginPath)
  1380. assert.NoError(t, err)
  1381. }
  1382. func TestPreDownloadHook(t *testing.T) {
  1383. if runtime.GOOS == osWindows {
  1384. t.Skip("this test is not available on Windows")
  1385. }
  1386. oldExecuteOn := common.Config.Actions.ExecuteOn
  1387. oldHook := common.Config.Actions.Hook
  1388. common.Config.Actions.ExecuteOn = []string{common.OperationPreDownload}
  1389. common.Config.Actions.Hook = preDownloadPath
  1390. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1391. assert.NoError(t, err)
  1392. err = os.WriteFile(preDownloadPath, getExitCodeScriptContent(0), os.ModePerm)
  1393. assert.NoError(t, err)
  1394. client := getWebDavClient(user, true, nil)
  1395. assert.NoError(t, checkBasicFunc(client))
  1396. testFilePath := filepath.Join(homeBasePath, testFileName)
  1397. testFileSize := int64(65535)
  1398. err = createTestFile(testFilePath, testFileSize)
  1399. assert.NoError(t, err)
  1400. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1401. true, testFileSize, client)
  1402. assert.NoError(t, err)
  1403. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1404. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1405. assert.NoError(t, err)
  1406. err = os.Remove(localDownloadPath)
  1407. assert.NoError(t, err)
  1408. err = os.WriteFile(preDownloadPath, getExitCodeScriptContent(1), os.ModePerm)
  1409. assert.NoError(t, err)
  1410. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1411. assert.Error(t, err)
  1412. err = os.Remove(localDownloadPath)
  1413. assert.NoError(t, err)
  1414. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1415. assert.NoError(t, err)
  1416. err = os.RemoveAll(user.GetHomeDir())
  1417. assert.NoError(t, err)
  1418. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  1419. 1*time.Second, 100*time.Millisecond)
  1420. common.Config.Actions.ExecuteOn = []string{common.OperationPreDownload}
  1421. common.Config.Actions.Hook = preDownloadPath
  1422. common.Config.Actions.ExecuteOn = oldExecuteOn
  1423. common.Config.Actions.Hook = oldHook
  1424. }
  1425. func TestPreUploadHook(t *testing.T) {
  1426. if runtime.GOOS == osWindows {
  1427. t.Skip("this test is not available on Windows")
  1428. }
  1429. oldExecuteOn := common.Config.Actions.ExecuteOn
  1430. oldHook := common.Config.Actions.Hook
  1431. common.Config.Actions.ExecuteOn = []string{common.OperationPreUpload}
  1432. common.Config.Actions.Hook = preUploadPath
  1433. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1434. assert.NoError(t, err)
  1435. err = os.WriteFile(preUploadPath, getExitCodeScriptContent(0), os.ModePerm)
  1436. assert.NoError(t, err)
  1437. client := getWebDavClient(user, true, nil)
  1438. assert.NoError(t, checkBasicFunc(client))
  1439. testFilePath := filepath.Join(homeBasePath, testFileName)
  1440. testFileSize := int64(65535)
  1441. err = createTestFile(testFilePath, testFileSize)
  1442. assert.NoError(t, err)
  1443. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1444. true, testFileSize, client)
  1445. assert.NoError(t, err)
  1446. err = os.WriteFile(preUploadPath, getExitCodeScriptContent(1), os.ModePerm)
  1447. assert.NoError(t, err)
  1448. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1449. true, testFileSize, client)
  1450. assert.Error(t, err)
  1451. err = uploadFileWithRawClient(testFilePath, testFileName+"1", user.Username, defaultPassword,
  1452. false, testFileSize, client)
  1453. assert.Error(t, err)
  1454. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1455. assert.NoError(t, err)
  1456. err = os.RemoveAll(user.GetHomeDir())
  1457. assert.NoError(t, err)
  1458. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  1459. 1*time.Second, 100*time.Millisecond)
  1460. common.Config.Actions.ExecuteOn = oldExecuteOn
  1461. common.Config.Actions.Hook = oldHook
  1462. }
  1463. func TestPostConnectHook(t *testing.T) {
  1464. if runtime.GOOS == osWindows {
  1465. t.Skip("this test is not available on Windows")
  1466. }
  1467. common.Config.PostConnectHook = postConnectPath
  1468. u := getTestUser()
  1469. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1470. assert.NoError(t, err)
  1471. err = os.WriteFile(postConnectPath, getExitCodeScriptContent(0), os.ModePerm)
  1472. assert.NoError(t, err)
  1473. client := getWebDavClient(user, false, nil)
  1474. assert.NoError(t, checkBasicFunc(client))
  1475. err = os.WriteFile(postConnectPath, getExitCodeScriptContent(1), os.ModePerm)
  1476. assert.NoError(t, err)
  1477. assert.Error(t, checkBasicFunc(client))
  1478. common.Config.PostConnectHook = "http://127.0.0.1:8078/healthz"
  1479. assert.NoError(t, checkBasicFunc(client))
  1480. common.Config.PostConnectHook = "http://127.0.0.1:8078/notfound"
  1481. assert.Error(t, checkBasicFunc(client))
  1482. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1483. assert.NoError(t, err)
  1484. err = os.RemoveAll(user.GetHomeDir())
  1485. assert.NoError(t, err)
  1486. common.Config.PostConnectHook = ""
  1487. }
  1488. func TestMaxConnections(t *testing.T) {
  1489. oldValue := common.Config.MaxTotalConnections
  1490. common.Config.MaxTotalConnections = 1
  1491. assert.Eventually(t, func() bool {
  1492. return common.Connections.GetClientConnections() == 0
  1493. }, 1000*time.Millisecond, 50*time.Millisecond)
  1494. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1495. assert.NoError(t, err)
  1496. client := getWebDavClient(user, true, nil)
  1497. assert.NoError(t, checkBasicFunc(client))
  1498. // now add a fake connection
  1499. fs := vfs.NewOsFs("id", os.TempDir(), "", nil)
  1500. connection := &webdavd.Connection{
  1501. BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
  1502. }
  1503. err = common.Connections.Add(connection)
  1504. assert.NoError(t, err)
  1505. assert.Error(t, checkBasicFunc(client))
  1506. common.Connections.Remove(connection.GetID())
  1507. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1508. assert.NoError(t, err)
  1509. err = os.RemoveAll(user.GetHomeDir())
  1510. assert.NoError(t, err)
  1511. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  1512. 1*time.Second, 100*time.Millisecond)
  1513. common.Config.MaxTotalConnections = oldValue
  1514. }
  1515. func TestMaxPerHostConnections(t *testing.T) {
  1516. oldValue := common.Config.MaxPerHostConnections
  1517. common.Config.MaxPerHostConnections = 1
  1518. assert.Eventually(t, func() bool {
  1519. return common.Connections.GetClientConnections() == 0
  1520. }, 1000*time.Millisecond, 50*time.Millisecond)
  1521. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  1522. assert.NoError(t, err)
  1523. client := getWebDavClient(user, true, nil)
  1524. assert.NoError(t, checkBasicFunc(client))
  1525. // now add a fake connection
  1526. addrs, err := net.LookupHost("localhost")
  1527. assert.NoError(t, err)
  1528. for _, addr := range addrs {
  1529. common.Connections.AddClientConnection(addr)
  1530. }
  1531. assert.Error(t, checkBasicFunc(client))
  1532. for _, addr := range addrs {
  1533. common.Connections.RemoveClientConnection(addr)
  1534. }
  1535. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1536. assert.NoError(t, err)
  1537. err = os.RemoveAll(user.GetHomeDir())
  1538. assert.NoError(t, err)
  1539. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  1540. 1*time.Second, 100*time.Millisecond)
  1541. common.Config.MaxPerHostConnections = oldValue
  1542. }
  1543. func TestMustChangePasswordRequirement(t *testing.T) {
  1544. u := getTestUser()
  1545. u.Filters.RequirePasswordChange = true
  1546. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1547. assert.NoError(t, err)
  1548. client := getWebDavClient(user, false, nil)
  1549. assert.Error(t, checkBasicFunc(client))
  1550. err = dataprovider.UpdateUserPassword(user.Username, defaultPassword, "", "", "")
  1551. assert.NoError(t, err)
  1552. client = getWebDavClient(user, false, nil)
  1553. assert.NoError(t, checkBasicFunc(client))
  1554. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1555. assert.NoError(t, err)
  1556. err = os.RemoveAll(user.GetHomeDir())
  1557. assert.NoError(t, err)
  1558. }
  1559. func TestMaxSessions(t *testing.T) {
  1560. u := getTestUser()
  1561. u.MaxSessions = 1
  1562. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1563. assert.NoError(t, err)
  1564. client := getWebDavClient(user, false, nil)
  1565. assert.NoError(t, checkBasicFunc(client))
  1566. // now add a fake connection
  1567. fs := vfs.NewOsFs("id", os.TempDir(), "", nil)
  1568. connection := &webdavd.Connection{
  1569. BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
  1570. }
  1571. err = common.Connections.Add(connection)
  1572. assert.NoError(t, err)
  1573. assert.Error(t, checkBasicFunc(client))
  1574. common.Connections.Remove(connection.GetID())
  1575. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1576. assert.NoError(t, err)
  1577. err = os.RemoveAll(user.GetHomeDir())
  1578. assert.NoError(t, err)
  1579. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  1580. 1*time.Second, 100*time.Millisecond)
  1581. }
  1582. func TestLoginWithIPilters(t *testing.T) {
  1583. u := getTestUser()
  1584. u.Filters.DeniedIP = []string{"192.167.0.0/24", "172.18.0.0/16"}
  1585. u.Filters.AllowedIP = []string{"172.19.0.0/16"}
  1586. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1587. assert.NoError(t, err)
  1588. client := getWebDavClient(user, true, nil)
  1589. assert.Error(t, checkBasicFunc(client))
  1590. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1591. assert.NoError(t, err)
  1592. err = os.RemoveAll(user.GetHomeDir())
  1593. assert.NoError(t, err)
  1594. }
  1595. func TestDownloadErrors(t *testing.T) {
  1596. u := getTestUser()
  1597. u.QuotaFiles = 1
  1598. subDir1 := "sub1"
  1599. subDir2 := "sub2"
  1600. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems}
  1601. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  1602. dataprovider.PermDelete, dataprovider.PermDownload}
  1603. // use an unknown mime to trigger content type detection
  1604. u.Filters.FilePatterns = []sdk.PatternsFilter{
  1605. {
  1606. Path: "/sub2",
  1607. AllowedPatterns: []string{},
  1608. DeniedPatterns: []string{"*.jpg", "*.zipp"},
  1609. },
  1610. }
  1611. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1612. assert.NoError(t, err)
  1613. client := getWebDavClient(user, false, nil)
  1614. testFilePath1 := filepath.Join(user.HomeDir, subDir1, "file.zipp")
  1615. testFilePath2 := filepath.Join(user.HomeDir, subDir2, "file.zipp")
  1616. testFilePath3 := filepath.Join(user.HomeDir, subDir2, "file.jpg")
  1617. err = os.MkdirAll(filepath.Dir(testFilePath1), os.ModePerm)
  1618. assert.NoError(t, err)
  1619. err = os.MkdirAll(filepath.Dir(testFilePath2), os.ModePerm)
  1620. assert.NoError(t, err)
  1621. err = os.WriteFile(testFilePath1, []byte("file1"), os.ModePerm)
  1622. assert.NoError(t, err)
  1623. err = os.WriteFile(testFilePath2, []byte("file2"), os.ModePerm)
  1624. assert.NoError(t, err)
  1625. err = os.WriteFile(testFilePath3, []byte("file3"), os.ModePerm)
  1626. assert.NoError(t, err)
  1627. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1628. err = downloadFile(path.Join("/", subDir1, "file.zipp"), localDownloadPath, 5, client)
  1629. assert.Error(t, err)
  1630. err = downloadFile(path.Join("/", subDir2, "file.zipp"), localDownloadPath, 5, client)
  1631. assert.Error(t, err)
  1632. err = downloadFile(path.Join("/", subDir2, "file.jpg"), localDownloadPath, 5, client)
  1633. assert.Error(t, err)
  1634. err = downloadFile(path.Join("missing.zip"), localDownloadPath, 5, client)
  1635. assert.Error(t, err)
  1636. err = os.Remove(localDownloadPath)
  1637. assert.NoError(t, err)
  1638. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1639. assert.NoError(t, err)
  1640. err = os.RemoveAll(user.GetHomeDir())
  1641. assert.NoError(t, err)
  1642. }
  1643. func TestUploadErrors(t *testing.T) {
  1644. u := getTestUser()
  1645. u.QuotaSize = 65535
  1646. subDir1 := "sub1"
  1647. subDir2 := "sub2"
  1648. // we need download permission to get size since PROPFIND will open the file
  1649. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems, dataprovider.PermDownload}
  1650. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  1651. dataprovider.PermDelete, dataprovider.PermDownload}
  1652. u.Filters.FilePatterns = []sdk.PatternsFilter{
  1653. {
  1654. Path: "/sub2",
  1655. AllowedPatterns: []string{},
  1656. DeniedPatterns: []string{"*.zip"},
  1657. },
  1658. }
  1659. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1660. assert.NoError(t, err)
  1661. client := getWebDavClient(user, true, nil)
  1662. testFilePath := filepath.Join(homeBasePath, testFileName)
  1663. testFileSize := user.QuotaSize
  1664. err = createTestFile(testFilePath, testFileSize)
  1665. assert.NoError(t, err)
  1666. err = client.Mkdir(subDir1, os.ModePerm)
  1667. assert.NoError(t, err)
  1668. err = client.Mkdir(subDir2, os.ModePerm)
  1669. assert.NoError(t, err)
  1670. err = uploadFileWithRawClient(testFilePath, path.Join(subDir1, testFileName), user.Username,
  1671. defaultPassword, true, testFileSize, client)
  1672. assert.Error(t, err)
  1673. err = uploadFileWithRawClient(testFilePath, path.Join(subDir2, testFileName+".zip"), user.Username,
  1674. defaultPassword, true, testFileSize, client)
  1675. assert.Error(t, err)
  1676. err = uploadFileWithRawClient(testFilePath, path.Join(subDir2, testFileName), user.Username,
  1677. defaultPassword, true, testFileSize, client)
  1678. assert.NoError(t, err)
  1679. err = client.Rename(path.Join(subDir2, testFileName), path.Join(subDir1, testFileName), false)
  1680. assert.Error(t, err)
  1681. err = uploadFileWithRawClient(testFilePath, path.Join(subDir2, testFileName), user.Username,
  1682. defaultPassword, true, testFileSize, client)
  1683. assert.Error(t, err)
  1684. err = uploadFileWithRawClient(testFilePath, subDir1, user.Username,
  1685. defaultPassword, true, testFileSize, client)
  1686. assert.Error(t, err)
  1687. // overquota
  1688. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1689. true, testFileSize, client)
  1690. assert.Error(t, err)
  1691. err = client.Remove(path.Join(subDir2, testFileName))
  1692. assert.NoError(t, err)
  1693. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1694. true, testFileSize, client)
  1695. assert.NoError(t, err)
  1696. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1697. true, testFileSize, client)
  1698. assert.Error(t, err)
  1699. err = os.Remove(testFilePath)
  1700. assert.NoError(t, err)
  1701. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1702. assert.NoError(t, err)
  1703. err = os.RemoveAll(user.GetHomeDir())
  1704. assert.NoError(t, err)
  1705. }
  1706. func TestDeniedLoginMethod(t *testing.T) {
  1707. u := getTestUser()
  1708. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword}
  1709. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1710. assert.NoError(t, err)
  1711. client := getWebDavClient(user, true, nil)
  1712. assert.Error(t, checkBasicFunc(client))
  1713. user.Filters.DeniedLoginMethods = []string{dataprovider.SSHLoginMethodPublicKey, dataprovider.SSHLoginMethodKeyAndKeyboardInt}
  1714. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1715. assert.NoError(t, err)
  1716. client = getWebDavClient(user, true, nil)
  1717. assert.NoError(t, checkBasicFunc(client))
  1718. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1719. assert.NoError(t, err)
  1720. err = os.RemoveAll(user.GetHomeDir())
  1721. assert.NoError(t, err)
  1722. }
  1723. func TestDeniedProtocols(t *testing.T) {
  1724. u := getTestUser()
  1725. u.Filters.DeniedProtocols = []string{common.ProtocolWebDAV}
  1726. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1727. assert.NoError(t, err)
  1728. client := getWebDavClient(user, false, nil)
  1729. assert.Error(t, checkBasicFunc(client))
  1730. user.Filters.DeniedProtocols = []string{common.ProtocolSSH, common.ProtocolFTP}
  1731. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1732. assert.NoError(t, err)
  1733. client = getWebDavClient(user, false, nil)
  1734. assert.NoError(t, checkBasicFunc(client))
  1735. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1736. assert.NoError(t, err)
  1737. err = os.RemoveAll(user.GetHomeDir())
  1738. assert.NoError(t, err)
  1739. }
  1740. func TestQuotaLimits(t *testing.T) {
  1741. u := getTestUser()
  1742. u.QuotaFiles = 1
  1743. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1744. assert.NoError(t, err)
  1745. u = getTestSFTPUser()
  1746. u.QuotaFiles = 1
  1747. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1748. assert.NoError(t, err)
  1749. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1750. testFileSize := int64(65536)
  1751. testFilePath := filepath.Join(homeBasePath, testFileName)
  1752. err = createTestFile(testFilePath, testFileSize)
  1753. assert.NoError(t, err)
  1754. testFileSize1 := int64(131072)
  1755. testFileName1 := "test_file1.dat"
  1756. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  1757. err = createTestFile(testFilePath1, testFileSize1)
  1758. assert.NoError(t, err)
  1759. testFileSize2 := int64(32768)
  1760. testFileName2 := "test_file2.dat"
  1761. testFilePath2 := filepath.Join(homeBasePath, testFileName2)
  1762. err = createTestFile(testFilePath2, testFileSize2)
  1763. assert.NoError(t, err)
  1764. client := getWebDavClient(user, false, nil)
  1765. // test quota files
  1766. err = uploadFileWithRawClient(testFilePath, testFileName+".quota", user.Username, defaultPassword, false, //nolint:goconst
  1767. testFileSize, client)
  1768. if !assert.NoError(t, err, "username: %v", user.Username) {
  1769. info, err := os.Stat(testFilePath)
  1770. if assert.NoError(t, err) {
  1771. fmt.Printf("local file size: %v\n", info.Size())
  1772. }
  1773. printLatestLogs(20)
  1774. }
  1775. err = uploadFileWithRawClient(testFilePath, testFileName+".quota1", user.Username, defaultPassword,
  1776. false, testFileSize, client)
  1777. assert.Error(t, err, "username: %v", user.Username)
  1778. err = client.Rename(testFileName+".quota", testFileName, false)
  1779. assert.NoError(t, err)
  1780. files, err := client.ReadDir("/")
  1781. assert.NoError(t, err)
  1782. assert.Len(t, files, 1)
  1783. // test quota size
  1784. user.QuotaSize = testFileSize - 1
  1785. user.QuotaFiles = 0
  1786. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1787. assert.NoError(t, err)
  1788. err = uploadFileWithRawClient(testFilePath, testFileName+".quota", user.Username, defaultPassword,
  1789. false, testFileSize, client)
  1790. assert.Error(t, err)
  1791. err = client.Rename(testFileName, testFileName+".quota", false)
  1792. assert.NoError(t, err)
  1793. // now test quota limits while uploading the current file, we have 1 bytes remaining
  1794. user.QuotaSize = testFileSize + 1
  1795. user.QuotaFiles = 0
  1796. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  1797. assert.NoError(t, err)
  1798. err = uploadFileWithRawClient(testFilePath1, testFileName1, user.Username, defaultPassword,
  1799. false, testFileSize1, client)
  1800. assert.Error(t, err)
  1801. _, err = client.Stat(testFileName1)
  1802. assert.Error(t, err)
  1803. err = client.Rename(testFileName+".quota", testFileName, false)
  1804. assert.NoError(t, err)
  1805. // overwriting an existing file will work if the resulting size is lesser or equal than the current one
  1806. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1807. false, testFileSize, client)
  1808. assert.NoError(t, err)
  1809. err = uploadFileWithRawClient(testFilePath2, testFileName, user.Username, defaultPassword,
  1810. false, testFileSize2, client)
  1811. assert.NoError(t, err)
  1812. err = uploadFileWithRawClient(testFilePath1, testFileName, user.Username, defaultPassword,
  1813. false, testFileSize1, client)
  1814. assert.Error(t, err)
  1815. err = uploadFileWithRawClient(testFilePath2, testFileName, user.Username, defaultPassword,
  1816. false, testFileSize2, client)
  1817. assert.NoError(t, err)
  1818. err = os.Remove(testFilePath)
  1819. assert.NoError(t, err)
  1820. err = os.Remove(testFilePath1)
  1821. assert.NoError(t, err)
  1822. err = os.Remove(testFilePath2)
  1823. assert.NoError(t, err)
  1824. if user.Username == defaultUsername {
  1825. err = os.RemoveAll(user.GetHomeDir())
  1826. assert.NoError(t, err)
  1827. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1828. assert.NoError(t, err)
  1829. user.Password = defaultPassword
  1830. user.ID = 0
  1831. user.CreatedAt = 0
  1832. user.QuotaFiles = 0
  1833. user.QuotaSize = 0
  1834. _, resp, err := httpdtest.AddUser(user, http.StatusCreated)
  1835. assert.NoError(t, err, string(resp))
  1836. }
  1837. }
  1838. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1839. assert.NoError(t, err)
  1840. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1841. assert.NoError(t, err)
  1842. err = os.RemoveAll(localUser.GetHomeDir())
  1843. assert.NoError(t, err)
  1844. }
  1845. func TestTransferQuotaLimits(t *testing.T) {
  1846. u := getTestUser()
  1847. u.DownloadDataTransfer = 1
  1848. u.UploadDataTransfer = 1
  1849. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1850. assert.NoError(t, err)
  1851. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1852. testFilePath := filepath.Join(homeBasePath, testFileName)
  1853. testFileSize := int64(550000)
  1854. err = createTestFile(testFilePath, testFileSize)
  1855. assert.NoError(t, err)
  1856. client := getWebDavClient(user, false, nil)
  1857. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1858. false, testFileSize, client)
  1859. assert.NoError(t, err)
  1860. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1861. assert.NoError(t, err)
  1862. // error while download is active
  1863. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1864. assert.Error(t, err)
  1865. // error before starting the download
  1866. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1867. assert.Error(t, err)
  1868. // error while upload is active
  1869. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1870. false, testFileSize, client)
  1871. assert.Error(t, err)
  1872. // error before starting the upload
  1873. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1874. false, testFileSize, client)
  1875. assert.Error(t, err)
  1876. err = os.Remove(localDownloadPath)
  1877. assert.NoError(t, err)
  1878. err = os.Remove(testFilePath)
  1879. assert.NoError(t, err)
  1880. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1881. assert.NoError(t, err)
  1882. err = os.RemoveAll(user.GetHomeDir())
  1883. assert.NoError(t, err)
  1884. }
  1885. func TestUploadMaxSize(t *testing.T) {
  1886. testFileSize := int64(65535)
  1887. u := getTestUser()
  1888. u.Filters.MaxUploadFileSize = testFileSize + 1
  1889. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1890. assert.NoError(t, err)
  1891. u = getTestSFTPUser()
  1892. u.Filters.MaxUploadFileSize = testFileSize + 1
  1893. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1894. assert.NoError(t, err)
  1895. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1896. testFilePath := filepath.Join(homeBasePath, testFileName)
  1897. err = createTestFile(testFilePath, testFileSize)
  1898. assert.NoError(t, err)
  1899. testFileSize1 := int64(131072)
  1900. testFileName1 := "test_file_dav1.dat"
  1901. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  1902. err = createTestFile(testFilePath1, testFileSize1)
  1903. assert.NoError(t, err)
  1904. client := getWebDavClient(user, false, nil)
  1905. err = uploadFileWithRawClient(testFilePath1, testFileName1, user.Username, defaultPassword,
  1906. false, testFileSize1, client)
  1907. assert.Error(t, err)
  1908. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1909. false, testFileSize, client)
  1910. assert.NoError(t, err)
  1911. // now test overwrite an existing file with a size bigger than the allowed one
  1912. err = createTestFile(filepath.Join(user.GetHomeDir(), testFileName1), testFileSize1)
  1913. assert.NoError(t, err)
  1914. err = uploadFileWithRawClient(testFilePath1, testFileName1, user.Username, defaultPassword,
  1915. false, testFileSize1, client)
  1916. assert.Error(t, err)
  1917. err = os.Remove(testFilePath)
  1918. assert.NoError(t, err)
  1919. err = os.Remove(testFilePath1)
  1920. assert.NoError(t, err)
  1921. if user.Username == defaultUsername {
  1922. err = os.RemoveAll(user.GetHomeDir())
  1923. assert.NoError(t, err)
  1924. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1925. assert.NoError(t, err)
  1926. user.Filters.MaxUploadFileSize = 65536000
  1927. user.Password = defaultPassword
  1928. user.ID = 0
  1929. user.CreatedAt = 0
  1930. _, resp, err := httpdtest.AddUser(user, http.StatusCreated)
  1931. assert.NoError(t, err, string(resp))
  1932. }
  1933. }
  1934. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1935. assert.NoError(t, err)
  1936. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1937. assert.NoError(t, err)
  1938. err = os.RemoveAll(localUser.GetHomeDir())
  1939. assert.NoError(t, err)
  1940. }
  1941. func TestClientClose(t *testing.T) {
  1942. u := getTestUser()
  1943. u.UploadBandwidth = 64
  1944. u.DownloadBandwidth = 64
  1945. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1946. assert.NoError(t, err)
  1947. u = getTestSFTPUser()
  1948. u.UploadBandwidth = 64
  1949. u.DownloadBandwidth = 64
  1950. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1951. assert.NoError(t, err)
  1952. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1953. testFileSize := int64(1048576)
  1954. testFilePath := filepath.Join(homeBasePath, testFileName)
  1955. err = createTestFile(testFilePath, testFileSize)
  1956. assert.NoError(t, err)
  1957. client := getWebDavClient(user, true, nil)
  1958. assert.NoError(t, checkBasicFunc(client))
  1959. var wg sync.WaitGroup
  1960. wg.Add(1)
  1961. go func() {
  1962. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  1963. true, testFileSize, client)
  1964. assert.Error(t, err)
  1965. wg.Done()
  1966. }()
  1967. assert.Eventually(t, func() bool {
  1968. for _, stat := range common.Connections.GetStats("") {
  1969. if len(stat.Transfers) > 0 {
  1970. return true
  1971. }
  1972. }
  1973. return false
  1974. }, 1*time.Second, 50*time.Millisecond)
  1975. for _, stat := range common.Connections.GetStats("") {
  1976. common.Connections.Close(stat.ConnectionID, "")
  1977. }
  1978. wg.Wait()
  1979. // for the sftp user a stat is done after the failed upload and
  1980. // this triggers a new connection
  1981. for _, stat := range common.Connections.GetStats("") {
  1982. common.Connections.Close(stat.ConnectionID, "")
  1983. }
  1984. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  1985. 1*time.Second, 100*time.Millisecond)
  1986. err = os.Remove(testFilePath)
  1987. assert.NoError(t, err)
  1988. testFilePath = filepath.Join(user.HomeDir, testFileName)
  1989. err = createTestFile(testFilePath, testFileSize)
  1990. assert.NoError(t, err)
  1991. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  1992. wg.Add(1)
  1993. go func() {
  1994. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  1995. assert.Error(t, err)
  1996. wg.Done()
  1997. }()
  1998. assert.Eventually(t, func() bool {
  1999. for _, stat := range common.Connections.GetStats("") {
  2000. if len(stat.Transfers) > 0 {
  2001. return true
  2002. }
  2003. }
  2004. return false
  2005. }, 1*time.Second, 50*time.Millisecond)
  2006. for _, stat := range common.Connections.GetStats("") {
  2007. common.Connections.Close(stat.ConnectionID, "")
  2008. }
  2009. wg.Wait()
  2010. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  2011. 1*time.Second, 100*time.Millisecond)
  2012. err = os.Remove(localDownloadPath)
  2013. assert.NoError(t, err)
  2014. }
  2015. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  2016. assert.NoError(t, err)
  2017. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  2018. assert.NoError(t, err)
  2019. err = os.RemoveAll(localUser.GetHomeDir())
  2020. assert.NoError(t, err)
  2021. }
  2022. func TestLoginWithDatabaseCredentials(t *testing.T) {
  2023. u := getTestUser()
  2024. u.FsConfig.Provider = sdk.GCSFilesystemProvider
  2025. u.FsConfig.GCSConfig.Bucket = "test"
  2026. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret(`{ "type": "service_account" }`)
  2027. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2028. assert.NoError(t, err)
  2029. assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.GCSConfig.Credentials.GetStatus())
  2030. assert.NotEmpty(t, user.FsConfig.GCSConfig.Credentials.GetPayload())
  2031. assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetAdditionalData())
  2032. assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetKey())
  2033. client := getWebDavClient(user, false, nil)
  2034. err = client.Connect()
  2035. assert.NoError(t, err)
  2036. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2037. assert.NoError(t, err)
  2038. err = os.RemoveAll(user.GetHomeDir())
  2039. assert.NoError(t, err)
  2040. }
  2041. func TestLoginInvalidFs(t *testing.T) {
  2042. u := getTestUser()
  2043. u.FsConfig.Provider = sdk.GCSFilesystemProvider
  2044. u.FsConfig.GCSConfig.Bucket = "test"
  2045. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("invalid JSON for credentials")
  2046. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2047. assert.NoError(t, err)
  2048. client := getWebDavClient(user, true, nil)
  2049. assert.Error(t, checkBasicFunc(client))
  2050. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2051. assert.NoError(t, err)
  2052. err = os.RemoveAll(user.GetHomeDir())
  2053. assert.NoError(t, err)
  2054. }
  2055. func TestSFTPBuffered(t *testing.T) {
  2056. u := getTestUser()
  2057. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2058. assert.NoError(t, err)
  2059. u = getTestSFTPUser()
  2060. u.QuotaFiles = 1000
  2061. u.HomeDir = filepath.Join(os.TempDir(), u.Username)
  2062. u.FsConfig.SFTPConfig.BufferSize = 2
  2063. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2064. assert.NoError(t, err)
  2065. client := getWebDavClient(sftpUser, true, nil)
  2066. assert.NoError(t, checkBasicFunc(client))
  2067. testFilePath := filepath.Join(homeBasePath, testFileName)
  2068. testFileSize := int64(65535)
  2069. expectedQuotaSize := testFileSize
  2070. expectedQuotaFiles := 1
  2071. err = createTestFile(testFilePath, testFileSize)
  2072. assert.NoError(t, err)
  2073. err = uploadFileWithRawClient(testFilePath, testFileName, sftpUser.Username, defaultPassword,
  2074. true, testFileSize, client)
  2075. assert.NoError(t, err)
  2076. // overwrite an existing file
  2077. err = uploadFileWithRawClient(testFilePath, testFileName, sftpUser.Username, defaultPassword,
  2078. true, testFileSize, client)
  2079. assert.NoError(t, err)
  2080. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  2081. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  2082. assert.NoError(t, err)
  2083. user, _, err := httpdtest.GetUserByUsername(sftpUser.Username, http.StatusOK)
  2084. assert.NoError(t, err)
  2085. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  2086. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  2087. fileContent := []byte("test file contents")
  2088. err = os.WriteFile(testFilePath, fileContent, os.ModePerm)
  2089. assert.NoError(t, err)
  2090. err = uploadFileWithRawClient(testFilePath, testFileName, sftpUser.Username, defaultPassword,
  2091. true, int64(len(fileContent)), client)
  2092. assert.NoError(t, err)
  2093. remotePath := fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName)
  2094. req, err := http.NewRequest(http.MethodGet, remotePath, nil)
  2095. assert.NoError(t, err)
  2096. httpClient := httpclient.GetHTTPClient()
  2097. req.SetBasicAuth(user.Username, defaultPassword)
  2098. req.Header.Set("Range", "bytes=5-")
  2099. resp, err := httpClient.Do(req)
  2100. if assert.NoError(t, err) {
  2101. defer resp.Body.Close()
  2102. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  2103. bodyBytes, err := io.ReadAll(resp.Body)
  2104. assert.NoError(t, err)
  2105. assert.Equal(t, "file contents", string(bodyBytes))
  2106. }
  2107. req.Header.Set("Range", "bytes=5-8")
  2108. resp, err = httpClient.Do(req)
  2109. if assert.NoError(t, err) {
  2110. defer resp.Body.Close()
  2111. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  2112. bodyBytes, err := io.ReadAll(resp.Body)
  2113. assert.NoError(t, err)
  2114. assert.Equal(t, "file", string(bodyBytes))
  2115. }
  2116. err = os.Remove(testFilePath)
  2117. assert.NoError(t, err)
  2118. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  2119. assert.NoError(t, err)
  2120. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  2121. assert.NoError(t, err)
  2122. err = os.RemoveAll(localUser.GetHomeDir())
  2123. assert.NoError(t, err)
  2124. err = os.RemoveAll(sftpUser.GetHomeDir())
  2125. assert.NoError(t, err)
  2126. }
  2127. func TestBytesRangeRequests(t *testing.T) {
  2128. u := getTestUser()
  2129. u.Username = u.Username + "1"
  2130. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2131. assert.NoError(t, err)
  2132. sftpUser := getTestSFTPUser()
  2133. sftpUser.FsConfig.SFTPConfig.Username = localUser.Username
  2134. for _, u := range []dataprovider.User{getTestUser(), getTestUserWithCryptFs(), sftpUser} {
  2135. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2136. assert.NoError(t, err)
  2137. testFileName := "test_file.txt"
  2138. testFilePath := filepath.Join(homeBasePath, testFileName)
  2139. fileContent := []byte("test file contents")
  2140. err = os.WriteFile(testFilePath, fileContent, os.ModePerm)
  2141. assert.NoError(t, err)
  2142. client := getWebDavClient(user, true, nil)
  2143. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  2144. true, int64(len(fileContent)), client)
  2145. assert.NoError(t, err)
  2146. remotePath := fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName)
  2147. req, err := http.NewRequest(http.MethodGet, remotePath, nil)
  2148. if assert.NoError(t, err) {
  2149. httpClient := httpclient.GetHTTPClient()
  2150. req.SetBasicAuth(user.Username, defaultPassword)
  2151. req.Header.Set("Range", "bytes=5-")
  2152. resp, err := httpClient.Do(req)
  2153. if assert.NoError(t, err) {
  2154. defer resp.Body.Close()
  2155. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  2156. bodyBytes, err := io.ReadAll(resp.Body)
  2157. assert.NoError(t, err)
  2158. assert.Equal(t, "file contents", string(bodyBytes))
  2159. }
  2160. req.Header.Set("Range", "bytes=5-8")
  2161. resp, err = httpClient.Do(req)
  2162. if assert.NoError(t, err) {
  2163. defer resp.Body.Close()
  2164. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  2165. bodyBytes, err := io.ReadAll(resp.Body)
  2166. assert.NoError(t, err)
  2167. assert.Equal(t, "file", string(bodyBytes))
  2168. }
  2169. }
  2170. // seek on a missing file
  2171. remotePath = fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName+"_missing")
  2172. req, err = http.NewRequest(http.MethodGet, remotePath, nil)
  2173. if assert.NoError(t, err) {
  2174. httpClient := httpclient.GetHTTPClient()
  2175. req.SetBasicAuth(user.Username, defaultPassword)
  2176. req.Header.Set("Range", "bytes=5-")
  2177. resp, err := httpClient.Do(req)
  2178. if assert.NoError(t, err) {
  2179. defer resp.Body.Close()
  2180. assert.Equal(t, http.StatusNotFound, resp.StatusCode)
  2181. }
  2182. }
  2183. err = os.Remove(testFilePath)
  2184. assert.NoError(t, err)
  2185. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2186. assert.NoError(t, err)
  2187. err = os.RemoveAll(user.GetHomeDir())
  2188. assert.NoError(t, err)
  2189. }
  2190. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  2191. assert.NoError(t, err)
  2192. err = os.RemoveAll(localUser.GetHomeDir())
  2193. assert.NoError(t, err)
  2194. }
  2195. func TestContentTypeGET(t *testing.T) {
  2196. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  2197. assert.NoError(t, err)
  2198. testFilePath := filepath.Join(homeBasePath, testFileName)
  2199. testFileSize := int64(64)
  2200. err = createTestFile(testFilePath, testFileSize)
  2201. assert.NoError(t, err)
  2202. client := getWebDavClient(user, true, nil)
  2203. err = uploadFileWithRawClient(testFilePath, testFileName+".sftpgo", user.Username, defaultPassword,
  2204. true, testFileSize, client)
  2205. assert.NoError(t, err)
  2206. remotePath := fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName+".sftpgo")
  2207. req, err := http.NewRequest(http.MethodGet, remotePath, nil)
  2208. if assert.NoError(t, err) {
  2209. httpClient := httpclient.GetHTTPClient()
  2210. req.SetBasicAuth(user.Username, defaultPassword)
  2211. resp, err := httpClient.Do(req)
  2212. if assert.NoError(t, err) {
  2213. defer resp.Body.Close()
  2214. assert.Equal(t, http.StatusOK, resp.StatusCode)
  2215. assert.Equal(t, "application/sftpgo", resp.Header.Get("Content-Type"))
  2216. }
  2217. }
  2218. err = os.Remove(testFilePath)
  2219. assert.NoError(t, err)
  2220. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2221. assert.NoError(t, err)
  2222. err = os.RemoveAll(user.GetHomeDir())
  2223. assert.NoError(t, err)
  2224. }
  2225. func TestHEAD(t *testing.T) {
  2226. u := getTestUser()
  2227. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2228. assert.NoError(t, err)
  2229. rootPath := fmt.Sprintf("http://%v", webDavServerAddr)
  2230. httpClient := httpclient.GetHTTPClient()
  2231. req, err := http.NewRequest(http.MethodHead, rootPath, nil)
  2232. if assert.NoError(t, err) {
  2233. req.SetBasicAuth(u.Username, u.Password)
  2234. resp, err := httpClient.Do(req)
  2235. if assert.NoError(t, err) {
  2236. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  2237. assert.Equal(t, "text/xml; charset=utf-8", resp.Header.Get("Content-Type"))
  2238. resp.Body.Close()
  2239. }
  2240. }
  2241. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2242. assert.NoError(t, err)
  2243. err = os.RemoveAll(user.GetHomeDir())
  2244. assert.NoError(t, err)
  2245. }
  2246. func TestGETAsPROPFIND(t *testing.T) {
  2247. u := getTestUser()
  2248. subDir1 := "/sub1"
  2249. u.Permissions[subDir1] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs}
  2250. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2251. assert.NoError(t, err)
  2252. rootPath := fmt.Sprintf("http://%v/", webDavServerAddr)
  2253. httpClient := httpclient.GetHTTPClient()
  2254. req, err := http.NewRequest(http.MethodGet, rootPath, nil)
  2255. if assert.NoError(t, err) {
  2256. req.SetBasicAuth(u.Username, u.Password)
  2257. resp, err := httpClient.Do(req)
  2258. if assert.NoError(t, err) {
  2259. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  2260. resp.Body.Close()
  2261. }
  2262. }
  2263. client := getWebDavClient(user, false, nil)
  2264. err = client.MkdirAll(path.Join(subDir1, "sub", "sub1"), os.ModePerm)
  2265. assert.NoError(t, err)
  2266. subPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, subDir1)
  2267. req, err = http.NewRequest(http.MethodGet, subPath, nil)
  2268. if assert.NoError(t, err) {
  2269. req.SetBasicAuth(u.Username, u.Password)
  2270. resp, err := httpClient.Do(req)
  2271. if assert.NoError(t, err) {
  2272. // before the performance patch we have a 500 here, now we have 207 but an empty list
  2273. //assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
  2274. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  2275. resp.Body.Close()
  2276. }
  2277. }
  2278. // we cannot stat the sub at all
  2279. subPath1 := fmt.Sprintf("http://%v/%v", webDavServerAddr, path.Join(subDir1, "sub"))
  2280. req, err = http.NewRequest(http.MethodGet, subPath1, nil)
  2281. if assert.NoError(t, err) {
  2282. req.SetBasicAuth(u.Username, u.Password)
  2283. resp, err := httpClient.Do(req)
  2284. if assert.NoError(t, err) {
  2285. // here the stat will fail, so the request will not be changed in propfind
  2286. assert.Equal(t, http.StatusForbidden, resp.StatusCode)
  2287. resp.Body.Close()
  2288. }
  2289. }
  2290. // we have no permission, we get an empty list
  2291. files, err := client.ReadDir(subDir1)
  2292. assert.NoError(t, err)
  2293. assert.Len(t, files, 0)
  2294. // if we grant the permissions the files are listed
  2295. user.Permissions[subDir1] = []string{dataprovider.PermDownload, dataprovider.PermListItems}
  2296. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2297. assert.NoError(t, err)
  2298. files, err = client.ReadDir(subDir1)
  2299. assert.NoError(t, err)
  2300. assert.Len(t, files, 1)
  2301. // PROPFIND with infinity depth is forbidden
  2302. req, err = http.NewRequest(http.MethodGet, rootPath, nil)
  2303. if assert.NoError(t, err) {
  2304. req.SetBasicAuth(u.Username, u.Password)
  2305. req.Header.Set("Depth", "infinity")
  2306. resp, err := httpClient.Do(req)
  2307. if assert.NoError(t, err) {
  2308. assert.Equal(t, http.StatusForbidden, resp.StatusCode)
  2309. resp.Body.Close()
  2310. }
  2311. }
  2312. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2313. assert.NoError(t, err)
  2314. err = os.RemoveAll(user.GetHomeDir())
  2315. assert.NoError(t, err)
  2316. }
  2317. func TestStat(t *testing.T) {
  2318. u := getTestUser()
  2319. u.Permissions["/subdir"] = []string{dataprovider.PermUpload, dataprovider.PermListItems, dataprovider.PermDownload}
  2320. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2321. assert.NoError(t, err)
  2322. client := getWebDavClient(user, true, nil)
  2323. subDir := "subdir"
  2324. testFilePath := filepath.Join(homeBasePath, testFileName)
  2325. testFileSize := int64(65535)
  2326. err = createTestFile(testFilePath, testFileSize)
  2327. assert.NoError(t, err)
  2328. err = client.Mkdir(subDir, os.ModePerm)
  2329. assert.NoError(t, err)
  2330. err = uploadFileWithRawClient(testFilePath, testFileName, user.Username, defaultPassword,
  2331. true, testFileSize, client)
  2332. assert.NoError(t, err)
  2333. err = uploadFileWithRawClient(testFilePath, path.Join("/", subDir, testFileName), user.Username,
  2334. defaultPassword, true, testFileSize, client)
  2335. assert.NoError(t, err)
  2336. user.Permissions["/subdir"] = []string{dataprovider.PermUpload, dataprovider.PermDownload}
  2337. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2338. assert.NoError(t, err)
  2339. _, err = client.Stat(testFileName)
  2340. assert.NoError(t, err)
  2341. _, err = client.Stat(path.Join("/", subDir, testFileName))
  2342. assert.Error(t, err)
  2343. err = os.Remove(testFilePath)
  2344. assert.NoError(t, err)
  2345. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2346. assert.NoError(t, err)
  2347. err = os.RemoveAll(user.GetHomeDir())
  2348. assert.NoError(t, err)
  2349. }
  2350. func TestUploadOverwriteVfolder(t *testing.T) {
  2351. u := getTestUser()
  2352. vdir := "/vdir"
  2353. mappedPath := filepath.Join(os.TempDir(), "mappedDir")
  2354. folderName := filepath.Base(mappedPath)
  2355. f := vfs.BaseVirtualFolder{
  2356. Name: folderName,
  2357. MappedPath: mappedPath,
  2358. }
  2359. _, _, err := httpdtest.AddFolder(f, http.StatusCreated)
  2360. assert.NoError(t, err)
  2361. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2362. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2363. Name: folderName,
  2364. },
  2365. VirtualPath: vdir,
  2366. QuotaSize: -1,
  2367. QuotaFiles: -1,
  2368. })
  2369. err = os.MkdirAll(mappedPath, os.ModePerm)
  2370. assert.NoError(t, err)
  2371. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2372. assert.NoError(t, err)
  2373. client := getWebDavClient(user, false, nil)
  2374. files, err := client.ReadDir(".")
  2375. assert.NoError(t, err)
  2376. vdirFound := false
  2377. for _, info := range files {
  2378. if info.Name() == path.Base(vdir) {
  2379. vdirFound = true
  2380. break
  2381. }
  2382. }
  2383. assert.True(t, vdirFound)
  2384. info, err := client.Stat(vdir)
  2385. if assert.NoError(t, err) {
  2386. assert.Equal(t, path.Base(vdir), info.Name())
  2387. }
  2388. testFilePath := filepath.Join(homeBasePath, testFileName)
  2389. testFileSize := int64(65535)
  2390. err = createTestFile(testFilePath, testFileSize)
  2391. assert.NoError(t, err)
  2392. err = uploadFileWithRawClient(testFilePath, path.Join(vdir, testFileName), user.Username,
  2393. defaultPassword, true, testFileSize, client)
  2394. assert.NoError(t, err)
  2395. folder, _, err := httpdtest.GetFolderByName(folderName, http.StatusOK)
  2396. assert.NoError(t, err)
  2397. assert.Equal(t, testFileSize, folder.UsedQuotaSize)
  2398. assert.Equal(t, 1, folder.UsedQuotaFiles)
  2399. err = uploadFileWithRawClient(testFilePath, path.Join(vdir, testFileName), user.Username,
  2400. defaultPassword, true, testFileSize, client)
  2401. assert.NoError(t, err)
  2402. folder, _, err = httpdtest.GetFolderByName(folderName, http.StatusOK)
  2403. assert.NoError(t, err)
  2404. assert.Equal(t, testFileSize, folder.UsedQuotaSize)
  2405. assert.Equal(t, 1, folder.UsedQuotaFiles)
  2406. err = os.Remove(testFilePath)
  2407. assert.NoError(t, err)
  2408. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2409. assert.NoError(t, err)
  2410. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  2411. assert.NoError(t, err)
  2412. err = os.RemoveAll(user.GetHomeDir())
  2413. assert.NoError(t, err)
  2414. err = os.RemoveAll(mappedPath)
  2415. assert.NoError(t, err)
  2416. }
  2417. func TestOsErrors(t *testing.T) {
  2418. u := getTestUser()
  2419. vdir := "/vdir"
  2420. mappedPath := filepath.Join(os.TempDir(), "mappedDir")
  2421. folderName := filepath.Base(mappedPath)
  2422. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2423. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2424. Name: folderName,
  2425. },
  2426. VirtualPath: vdir,
  2427. QuotaSize: -1,
  2428. QuotaFiles: -1,
  2429. })
  2430. f := vfs.BaseVirtualFolder{
  2431. Name: folderName,
  2432. MappedPath: mappedPath,
  2433. }
  2434. _, _, err := httpdtest.AddFolder(f, http.StatusCreated)
  2435. assert.NoError(t, err)
  2436. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2437. assert.NoError(t, err)
  2438. client := getWebDavClient(user, false, nil)
  2439. files, err := client.ReadDir(".")
  2440. assert.NoError(t, err)
  2441. assert.Len(t, files, 1)
  2442. info, err := client.Stat(vdir)
  2443. assert.NoError(t, err)
  2444. assert.True(t, info.IsDir())
  2445. // now remove the folder mapped to vdir. It still appear in directory listing
  2446. // virtual folders are automatically added
  2447. err = os.RemoveAll(mappedPath)
  2448. assert.NoError(t, err)
  2449. files, err = client.ReadDir(".")
  2450. assert.NoError(t, err)
  2451. assert.Len(t, files, 1)
  2452. err = createTestFile(filepath.Join(user.GetHomeDir(), testFileName), 32768)
  2453. assert.NoError(t, err)
  2454. files, err = client.ReadDir(".")
  2455. assert.NoError(t, err)
  2456. if assert.Len(t, files, 2) {
  2457. var names []string
  2458. for _, info := range files {
  2459. names = append(names, info.Name())
  2460. }
  2461. assert.Contains(t, names, testFileName)
  2462. assert.Contains(t, names, "vdir")
  2463. }
  2464. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2465. assert.NoError(t, err)
  2466. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  2467. assert.NoError(t, err)
  2468. err = os.RemoveAll(user.GetHomeDir())
  2469. assert.NoError(t, err)
  2470. err = os.RemoveAll(mappedPath)
  2471. assert.NoError(t, err)
  2472. }
  2473. func TestMiscCommands(t *testing.T) {
  2474. u := getTestUser()
  2475. u.QuotaFiles = 100
  2476. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2477. assert.NoError(t, err)
  2478. u = getTestSFTPUser()
  2479. u.QuotaFiles = 100
  2480. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2481. assert.NoError(t, err)
  2482. for _, user := range []dataprovider.User{localUser, sftpUser} {
  2483. dir := "testDir"
  2484. client := getWebDavClient(user, true, nil)
  2485. err = client.MkdirAll(path.Join(dir, "sub1", "sub2"), os.ModePerm)
  2486. assert.NoError(t, err)
  2487. testFilePath := filepath.Join(homeBasePath, testFileName)
  2488. testFileSize := int64(65535)
  2489. err = createTestFile(testFilePath, testFileSize)
  2490. assert.NoError(t, err)
  2491. err = uploadFileWithRawClient(testFilePath, path.Join(dir, testFileName), user.Username,
  2492. defaultPassword, true, testFileSize, client)
  2493. assert.NoError(t, err)
  2494. err = uploadFileWithRawClient(testFilePath, path.Join(dir, "sub1", testFileName), user.Username,
  2495. defaultPassword, true, testFileSize, client)
  2496. assert.NoError(t, err)
  2497. err = uploadFileWithRawClient(testFilePath, path.Join(dir, "sub1", "sub2", testFileName), user.Username,
  2498. defaultPassword, true, testFileSize, client)
  2499. assert.NoError(t, err)
  2500. err = client.Copy(dir, dir+"_copy", false)
  2501. assert.NoError(t, err)
  2502. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2503. assert.NoError(t, err)
  2504. assert.Equal(t, 6, user.UsedQuotaFiles)
  2505. assert.Equal(t, 6*testFileSize, user.UsedQuotaSize)
  2506. err = client.Copy(dir, dir+"_copy1", false) //nolint:goconst
  2507. assert.NoError(t, err)
  2508. err = client.Copy(dir+"_copy", dir+"_copy1", false)
  2509. assert.Error(t, err)
  2510. err = client.Copy(dir+"_copy", dir+"_copy1", true)
  2511. assert.NoError(t, err)
  2512. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2513. assert.NoError(t, err)
  2514. assert.Equal(t, 9, user.UsedQuotaFiles)
  2515. assert.Equal(t, 9*testFileSize, user.UsedQuotaSize)
  2516. err = client.Rename(dir+"_copy1", dir+"_copy2", false)
  2517. assert.NoError(t, err)
  2518. err = client.Remove(path.Join(dir+"_copy", testFileName))
  2519. assert.NoError(t, err)
  2520. err = client.Rename(dir+"_copy2", dir+"_copy", true)
  2521. assert.NoError(t, err)
  2522. err = client.Copy(dir+"_copy", dir+"_copy1", false)
  2523. assert.NoError(t, err)
  2524. err = client.RemoveAll(dir + "_copy1")
  2525. assert.NoError(t, err)
  2526. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2527. assert.NoError(t, err)
  2528. assert.Equal(t, 6, user.UsedQuotaFiles)
  2529. assert.Equal(t, 6*testFileSize, user.UsedQuotaSize)
  2530. err = os.Remove(testFilePath)
  2531. assert.NoError(t, err)
  2532. if user.Username == defaultUsername {
  2533. err = os.RemoveAll(user.GetHomeDir())
  2534. assert.NoError(t, err)
  2535. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2536. assert.NoError(t, err)
  2537. user.Password = defaultPassword
  2538. user.ID = 0
  2539. user.CreatedAt = 0
  2540. user.QuotaFiles = 0
  2541. _, resp, err := httpdtest.AddUser(user, http.StatusCreated)
  2542. assert.NoError(t, err, string(resp))
  2543. }
  2544. }
  2545. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  2546. assert.NoError(t, err)
  2547. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  2548. assert.NoError(t, err)
  2549. err = os.RemoveAll(localUser.GetHomeDir())
  2550. assert.NoError(t, err)
  2551. }
  2552. func TestClientCertificateAuthRevokedCert(t *testing.T) {
  2553. u := getTestUser()
  2554. u.Username = tlsClient2Username
  2555. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2556. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2557. assert.NoError(t, err)
  2558. tlsConfig := &tls.Config{
  2559. ServerName: "localhost",
  2560. InsecureSkipVerify: true, // use this for tests only
  2561. MinVersion: tls.VersionTLS12,
  2562. }
  2563. tlsCert, err := tls.X509KeyPair([]byte(client2Crt), []byte(client2Key))
  2564. assert.NoError(t, err)
  2565. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2566. client := getWebDavClient(user, true, tlsConfig)
  2567. err = checkBasicFunc(client)
  2568. if assert.Error(t, err) {
  2569. if !strings.Contains(err.Error(), "bad certificate") && !strings.Contains(err.Error(), "broken pipe") {
  2570. t.Errorf("unexpected error: %v", err)
  2571. }
  2572. }
  2573. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2574. assert.NoError(t, err)
  2575. err = os.RemoveAll(user.GetHomeDir())
  2576. assert.NoError(t, err)
  2577. }
  2578. func TestClientCertificateAuth(t *testing.T) {
  2579. u := getTestUser()
  2580. u.Username = tlsClient1Username
  2581. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificateAndPwd}
  2582. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2583. assert.NoError(t, err)
  2584. tlsConfig := &tls.Config{
  2585. ServerName: "localhost",
  2586. InsecureSkipVerify: true, // use this for tests only
  2587. MinVersion: tls.VersionTLS12,
  2588. }
  2589. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2590. assert.NoError(t, err)
  2591. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2592. // TLS username is not enabled, mutual TLS should fail
  2593. resp, err := getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v/", webDavTLSServerAddr))
  2594. if assert.NoError(t, err) {
  2595. defer resp.Body.Close()
  2596. body, err := io.ReadAll(resp.Body)
  2597. assert.NoError(t, err)
  2598. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2599. }
  2600. user.Filters.TLSUsername = sdk.TLSUsernameCN
  2601. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2602. assert.NoError(t, err)
  2603. client := getWebDavClient(user, true, tlsConfig)
  2604. err = checkBasicFunc(client)
  2605. assert.NoError(t, err)
  2606. user.Filters.TLSUsername = sdk.TLSUsernameNone
  2607. user.Filters.TLSCerts = []string{client1Crt}
  2608. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2609. assert.NoError(t, err)
  2610. client = getWebDavClient(user, true, tlsConfig)
  2611. err = checkBasicFunc(client)
  2612. assert.NoError(t, err)
  2613. user.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificate}
  2614. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2615. assert.NoError(t, err)
  2616. client = getWebDavClient(user, true, tlsConfig)
  2617. err = checkBasicFunc(client)
  2618. assert.NoError(t, err)
  2619. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2620. assert.NoError(t, err)
  2621. err = os.RemoveAll(user.GetHomeDir())
  2622. assert.NoError(t, err)
  2623. }
  2624. func TestWrongClientCertificate(t *testing.T) {
  2625. u := getTestUser()
  2626. u.Username = tlsClient2Username
  2627. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificateAndPwd}
  2628. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2629. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2630. assert.NoError(t, err)
  2631. tlsConfig := &tls.Config{
  2632. ServerName: "localhost",
  2633. InsecureSkipVerify: true, // use this for tests only
  2634. MinVersion: tls.VersionTLS12,
  2635. }
  2636. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2637. assert.NoError(t, err)
  2638. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2639. // the certificate common name is client1 and it does not exists
  2640. resp, err := getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v/", webDavTLSServerAddr))
  2641. if assert.NoError(t, err) {
  2642. defer resp.Body.Close()
  2643. body, err := io.ReadAll(resp.Body)
  2644. assert.NoError(t, err)
  2645. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2646. }
  2647. user.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificate}
  2648. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2649. assert.NoError(t, err)
  2650. // now create client1
  2651. u = getTestUser()
  2652. u.Username = tlsClient1Username
  2653. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword, dataprovider.LoginMethodTLSCertificate}
  2654. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2655. user1, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2656. assert.NoError(t, err)
  2657. resp, err = getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v:%v@%v/", tlsClient2Username, defaultPassword,
  2658. webDavTLSServerAddr))
  2659. if assert.NoError(t, err) {
  2660. defer resp.Body.Close()
  2661. body, err := io.ReadAll(resp.Body)
  2662. assert.NoError(t, err)
  2663. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2664. assert.Contains(t, string(body), "invalid credentials")
  2665. }
  2666. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2667. assert.NoError(t, err)
  2668. err = os.RemoveAll(user.GetHomeDir())
  2669. assert.NoError(t, err)
  2670. _, err = httpdtest.RemoveUser(user1, http.StatusOK)
  2671. assert.NoError(t, err)
  2672. err = os.RemoveAll(user1.GetHomeDir())
  2673. assert.NoError(t, err)
  2674. }
  2675. func TestClientCertificateAuthCachedUser(t *testing.T) {
  2676. u := getTestUser()
  2677. u.Username = tlsClient1Username
  2678. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2679. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificateAndPwd}
  2680. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2681. assert.NoError(t, err)
  2682. tlsConfig := &tls.Config{
  2683. ServerName: "localhost",
  2684. InsecureSkipVerify: true, // use this for tests only
  2685. MinVersion: tls.VersionTLS12,
  2686. }
  2687. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2688. assert.NoError(t, err)
  2689. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2690. client := getWebDavClient(user, true, tlsConfig)
  2691. err = checkBasicFunc(client)
  2692. assert.NoError(t, err)
  2693. // the user is now cached without a password, try a simple password login with and without TLS
  2694. client = getWebDavClient(user, true, nil)
  2695. err = checkBasicFunc(client)
  2696. assert.NoError(t, err)
  2697. client = getWebDavClient(user, false, nil)
  2698. err = checkBasicFunc(client)
  2699. assert.NoError(t, err)
  2700. // and now with a wrong password
  2701. user.Password = "wrong"
  2702. client = getWebDavClient(user, false, nil)
  2703. err = checkBasicFunc(client)
  2704. assert.Error(t, err)
  2705. // allow cert+password only
  2706. user.Password = ""
  2707. user.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificate}
  2708. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2709. assert.NoError(t, err)
  2710. client = getWebDavClient(user, true, tlsConfig)
  2711. err = checkBasicFunc(client)
  2712. assert.NoError(t, err)
  2713. // the user is now cached
  2714. client = getWebDavClient(user, true, tlsConfig)
  2715. err = checkBasicFunc(client)
  2716. assert.NoError(t, err)
  2717. // password auth should work too
  2718. client = getWebDavClient(user, false, nil)
  2719. err = checkBasicFunc(client)
  2720. assert.NoError(t, err)
  2721. client = getWebDavClient(user, true, nil)
  2722. err = checkBasicFunc(client)
  2723. assert.NoError(t, err)
  2724. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2725. assert.NoError(t, err)
  2726. err = os.RemoveAll(user.GetHomeDir())
  2727. assert.NoError(t, err)
  2728. }
  2729. func TestExternatAuthWithClientCert(t *testing.T) {
  2730. if runtime.GOOS == osWindows {
  2731. t.Skip("this test is not available on Windows")
  2732. }
  2733. u := getTestUser()
  2734. u.Username = tlsClient1Username
  2735. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2736. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificate, dataprovider.LoginMethodPassword}
  2737. err := dataprovider.Close()
  2738. assert.NoError(t, err)
  2739. err = config.LoadConfig(configDir, "")
  2740. assert.NoError(t, err)
  2741. providerConf := config.GetProviderConf()
  2742. err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u, ""), os.ModePerm)
  2743. assert.NoError(t, err)
  2744. providerConf.ExternalAuthHook = extAuthPath
  2745. providerConf.ExternalAuthScope = 0
  2746. err = dataprovider.Initialize(providerConf, configDir, true)
  2747. assert.NoError(t, err)
  2748. tlsConfig := &tls.Config{
  2749. ServerName: "localhost",
  2750. InsecureSkipVerify: true, // use this for tests only
  2751. MinVersion: tls.VersionTLS12,
  2752. }
  2753. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2754. assert.NoError(t, err)
  2755. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2756. client := getWebDavClient(u, true, tlsConfig)
  2757. assert.NoError(t, checkBasicFunc(client))
  2758. resp, err := getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v:%v@%v/", tlsClient2Username, defaultPassword,
  2759. webDavTLSServerAddr))
  2760. if assert.NoError(t, err) {
  2761. defer resp.Body.Close()
  2762. body, err := io.ReadAll(resp.Body)
  2763. assert.NoError(t, err)
  2764. assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, string(body))
  2765. assert.Contains(t, string(body), "invalid credentials")
  2766. }
  2767. user, _, err := httpdtest.GetUserByUsername(tlsClient1Username, http.StatusOK)
  2768. assert.NoError(t, err)
  2769. assert.Equal(t, tlsClient1Username, user.Username)
  2770. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2771. assert.NoError(t, err)
  2772. err = os.RemoveAll(user.GetHomeDir())
  2773. assert.NoError(t, err)
  2774. err = dataprovider.Close()
  2775. assert.NoError(t, err)
  2776. err = config.LoadConfig(configDir, "")
  2777. assert.NoError(t, err)
  2778. providerConf = config.GetProviderConf()
  2779. err = dataprovider.Initialize(providerConf, configDir, true)
  2780. assert.NoError(t, err)
  2781. err = os.Remove(extAuthPath)
  2782. assert.NoError(t, err)
  2783. }
  2784. func TestPreLoginHookWithClientCert(t *testing.T) {
  2785. if runtime.GOOS == osWindows {
  2786. t.Skip("this test is not available on Windows")
  2787. }
  2788. u := getTestUser()
  2789. u.Username = tlsClient1Username
  2790. u.Filters.TLSUsername = sdk.TLSUsernameCN
  2791. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodTLSCertificate, dataprovider.LoginMethodPassword}
  2792. err := dataprovider.Close()
  2793. assert.NoError(t, err)
  2794. err = config.LoadConfig(configDir, "")
  2795. assert.NoError(t, err)
  2796. providerConf := config.GetProviderConf()
  2797. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
  2798. assert.NoError(t, err)
  2799. providerConf.PreLoginHook = preLoginPath
  2800. err = dataprovider.Initialize(providerConf, configDir, true)
  2801. assert.NoError(t, err)
  2802. _, _, err = httpdtest.GetUserByUsername(tlsClient1Username, http.StatusNotFound)
  2803. assert.NoError(t, err)
  2804. tlsConfig := &tls.Config{
  2805. ServerName: "localhost",
  2806. InsecureSkipVerify: true, // use this for tests only
  2807. MinVersion: tls.VersionTLS12,
  2808. }
  2809. tlsCert, err := tls.X509KeyPair([]byte(client1Crt), []byte(client1Key))
  2810. assert.NoError(t, err)
  2811. tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
  2812. client := getWebDavClient(u, true, tlsConfig)
  2813. assert.NoError(t, checkBasicFunc(client))
  2814. user, _, err := httpdtest.GetUserByUsername(tlsClient1Username, http.StatusOK)
  2815. assert.NoError(t, err)
  2816. // test login with an existing user
  2817. client = getWebDavClient(user, true, tlsConfig)
  2818. assert.NoError(t, checkBasicFunc(client))
  2819. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), os.ModePerm)
  2820. assert.NoError(t, err)
  2821. // update the user to remove it from the cache
  2822. user.Password = defaultPassword
  2823. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2824. assert.NoError(t, err)
  2825. client = getWebDavClient(user, true, tlsConfig)
  2826. assert.Error(t, checkBasicFunc(client))
  2827. // update the user to remove it from the cache
  2828. user.Password = defaultPassword
  2829. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2830. assert.NoError(t, err)
  2831. user.Status = 0
  2832. err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), os.ModePerm)
  2833. assert.NoError(t, err)
  2834. client = getWebDavClient(user, true, tlsConfig)
  2835. assert.Error(t, checkBasicFunc(client))
  2836. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2837. assert.NoError(t, err)
  2838. err = os.RemoveAll(user.GetHomeDir())
  2839. assert.NoError(t, err)
  2840. err = dataprovider.Close()
  2841. assert.NoError(t, err)
  2842. err = config.LoadConfig(configDir, "")
  2843. assert.NoError(t, err)
  2844. providerConf = config.GetProviderConf()
  2845. err = dataprovider.Initialize(providerConf, configDir, true)
  2846. assert.NoError(t, err)
  2847. err = os.Remove(preLoginPath)
  2848. assert.NoError(t, err)
  2849. }
  2850. func TestSFTPLoopVirtualFolders(t *testing.T) {
  2851. user1 := getTestUser()
  2852. user2 := getTestUser()
  2853. user1.Username += "1"
  2854. user2.Username += "2"
  2855. // user1 is a local account with a virtual SFTP folder to user2
  2856. // user2 has user1 as SFTP fs
  2857. folderName := "sftp"
  2858. user1.VirtualFolders = append(user1.VirtualFolders, vfs.VirtualFolder{
  2859. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2860. Name: folderName,
  2861. },
  2862. VirtualPath: "/vdir",
  2863. })
  2864. user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
  2865. user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
  2866. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  2867. Endpoint: sftpServerAddr,
  2868. Username: user1.Username,
  2869. },
  2870. Password: kms.NewPlainSecret(defaultPassword),
  2871. }
  2872. f := vfs.BaseVirtualFolder{
  2873. Name: folderName,
  2874. FsConfig: vfs.Filesystem{
  2875. Provider: sdk.SFTPFilesystemProvider,
  2876. SFTPConfig: vfs.SFTPFsConfig{
  2877. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  2878. Endpoint: sftpServerAddr,
  2879. Username: user2.Username,
  2880. },
  2881. Password: kms.NewPlainSecret(defaultPassword),
  2882. },
  2883. },
  2884. }
  2885. _, _, err := httpdtest.AddFolder(f, http.StatusCreated)
  2886. assert.NoError(t, err)
  2887. user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
  2888. assert.NoError(t, err, string(resp))
  2889. user2, resp, err = httpdtest.AddUser(user2, http.StatusCreated)
  2890. assert.NoError(t, err, string(resp))
  2891. client := getWebDavClient(user1, true, nil)
  2892. testDir := "tdir"
  2893. err = client.Mkdir(testDir, os.ModePerm)
  2894. assert.NoError(t, err)
  2895. contents, err := client.ReadDir("/")
  2896. assert.NoError(t, err)
  2897. if assert.Len(t, contents, 2) {
  2898. expected := 0
  2899. for _, info := range contents {
  2900. switch info.Name() {
  2901. case testDir, "vdir":
  2902. assert.True(t, info.IsDir())
  2903. expected++
  2904. default:
  2905. t.Errorf("unexpected file/dir %q", info.Name())
  2906. }
  2907. }
  2908. assert.Equal(t, expected, 2)
  2909. }
  2910. _, err = httpdtest.RemoveUser(user1, http.StatusOK)
  2911. assert.NoError(t, err)
  2912. err = os.RemoveAll(user1.GetHomeDir())
  2913. assert.NoError(t, err)
  2914. _, err = httpdtest.RemoveUser(user2, http.StatusOK)
  2915. assert.NoError(t, err)
  2916. err = os.RemoveAll(user2.GetHomeDir())
  2917. assert.NoError(t, err)
  2918. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  2919. assert.NoError(t, err)
  2920. }
  2921. func TestNestedVirtualFolders(t *testing.T) {
  2922. u := getTestUser()
  2923. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2924. assert.NoError(t, err)
  2925. u = getTestSFTPUser()
  2926. mappedPathCrypt := filepath.Join(os.TempDir(), "crypt")
  2927. folderNameCrypt := filepath.Base(mappedPathCrypt)
  2928. vdirCryptPath := "/vdir/crypt"
  2929. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2930. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2931. Name: folderNameCrypt,
  2932. },
  2933. VirtualPath: vdirCryptPath,
  2934. })
  2935. mappedPath := filepath.Join(os.TempDir(), "local")
  2936. folderName := filepath.Base(mappedPath)
  2937. vdirPath := "/vdir/local"
  2938. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2939. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2940. Name: folderName,
  2941. },
  2942. VirtualPath: vdirPath,
  2943. })
  2944. mappedPathNested := filepath.Join(os.TempDir(), "nested")
  2945. folderNameNested := filepath.Base(mappedPathNested)
  2946. vdirNestedPath := "/vdir/crypt/nested"
  2947. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2948. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2949. Name: folderNameNested,
  2950. },
  2951. VirtualPath: vdirNestedPath,
  2952. QuotaFiles: -1,
  2953. QuotaSize: -1,
  2954. })
  2955. f1 := vfs.BaseVirtualFolder{
  2956. Name: folderNameCrypt,
  2957. FsConfig: vfs.Filesystem{
  2958. Provider: sdk.CryptedFilesystemProvider,
  2959. CryptConfig: vfs.CryptFsConfig{
  2960. Passphrase: kms.NewPlainSecret(defaultPassword),
  2961. },
  2962. },
  2963. MappedPath: mappedPathCrypt,
  2964. }
  2965. _, _, err = httpdtest.AddFolder(f1, http.StatusCreated)
  2966. assert.NoError(t, err)
  2967. f2 := vfs.BaseVirtualFolder{
  2968. Name: folderName,
  2969. MappedPath: mappedPath,
  2970. }
  2971. _, _, err = httpdtest.AddFolder(f2, http.StatusCreated)
  2972. assert.NoError(t, err)
  2973. f3 := vfs.BaseVirtualFolder{
  2974. Name: folderNameNested,
  2975. MappedPath: mappedPathNested,
  2976. }
  2977. _, _, err = httpdtest.AddFolder(f3, http.StatusCreated)
  2978. assert.NoError(t, err)
  2979. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2980. assert.NoError(t, err)
  2981. client := getWebDavClient(sftpUser, true, nil)
  2982. assert.NoError(t, checkBasicFunc(client))
  2983. testFilePath := filepath.Join(homeBasePath, testFileName)
  2984. testFileSize := int64(65535)
  2985. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  2986. err = createTestFile(testFilePath, testFileSize)
  2987. assert.NoError(t, err)
  2988. err = uploadFileWithRawClient(testFilePath, testFileName, sftpUser.Username,
  2989. defaultPassword, true, testFileSize, client)
  2990. assert.NoError(t, err)
  2991. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  2992. assert.NoError(t, err)
  2993. err = uploadFileWithRawClient(testFilePath, path.Join("/vdir", testFileName), sftpUser.Username,
  2994. defaultPassword, true, testFileSize, client)
  2995. assert.NoError(t, err)
  2996. err = downloadFile(path.Join("/vdir", testFileName), localDownloadPath, testFileSize, client)
  2997. assert.NoError(t, err)
  2998. err = uploadFileWithRawClient(testFilePath, path.Join(vdirPath, testFileName), sftpUser.Username,
  2999. defaultPassword, true, testFileSize, client)
  3000. assert.NoError(t, err)
  3001. err = downloadFile(path.Join(vdirPath, testFileName), localDownloadPath, testFileSize, client)
  3002. assert.NoError(t, err)
  3003. err = uploadFileWithRawClient(testFilePath, path.Join(vdirCryptPath, testFileName), sftpUser.Username,
  3004. defaultPassword, true, testFileSize, client)
  3005. assert.NoError(t, err)
  3006. err = downloadFile(path.Join(vdirCryptPath, testFileName), localDownloadPath, testFileSize, client)
  3007. assert.NoError(t, err)
  3008. err = uploadFileWithRawClient(testFilePath, path.Join(vdirNestedPath, testFileName), sftpUser.Username,
  3009. defaultPassword, true, testFileSize, client)
  3010. assert.NoError(t, err)
  3011. err = downloadFile(path.Join(vdirNestedPath, testFileName), localDownloadPath, testFileSize, client)
  3012. assert.NoError(t, err)
  3013. err = os.Remove(testFilePath)
  3014. assert.NoError(t, err)
  3015. err = os.Remove(localDownloadPath)
  3016. assert.NoError(t, err)
  3017. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  3018. assert.NoError(t, err)
  3019. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  3020. assert.NoError(t, err)
  3021. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameCrypt}, http.StatusOK)
  3022. assert.NoError(t, err)
  3023. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  3024. assert.NoError(t, err)
  3025. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameNested}, http.StatusOK)
  3026. assert.NoError(t, err)
  3027. err = os.RemoveAll(mappedPathCrypt)
  3028. assert.NoError(t, err)
  3029. err = os.RemoveAll(mappedPath)
  3030. assert.NoError(t, err)
  3031. err = os.RemoveAll(mappedPathNested)
  3032. assert.NoError(t, err)
  3033. err = os.RemoveAll(localUser.GetHomeDir())
  3034. assert.NoError(t, err)
  3035. assert.Eventually(t, func() bool { return len(common.Connections.GetStats("")) == 0 },
  3036. 1*time.Second, 100*time.Millisecond)
  3037. }
  3038. func checkBasicFunc(client *gowebdav.Client) error {
  3039. err := client.Connect()
  3040. if err != nil {
  3041. return err
  3042. }
  3043. _, err = client.ReadDir("/")
  3044. return err
  3045. }
  3046. func checkFileSize(remoteDestPath string, expectedSize int64, client *gowebdav.Client) error {
  3047. info, err := client.Stat(remoteDestPath)
  3048. if err != nil {
  3049. return err
  3050. }
  3051. if info.Size() != expectedSize {
  3052. return fmt.Errorf("uploaded file size does not match, actual: %v, expected: %v", info.Size(), expectedSize)
  3053. }
  3054. return nil
  3055. }
  3056. func uploadFileWithRawClient(localSourcePath string, remoteDestPath string, username, password string,
  3057. useTLS bool, expectedSize int64, client *gowebdav.Client, headers ...dataprovider.KeyValue,
  3058. ) error {
  3059. srcFile, err := os.Open(localSourcePath)
  3060. if err != nil {
  3061. return err
  3062. }
  3063. defer srcFile.Close()
  3064. var tlsConfig *tls.Config
  3065. rootPath := fmt.Sprintf("http://%v/", webDavServerAddr)
  3066. if useTLS {
  3067. rootPath = fmt.Sprintf("https://%v/", webDavTLSServerAddr)
  3068. tlsConfig = &tls.Config{
  3069. ServerName: "localhost",
  3070. InsecureSkipVerify: true, // use this for tests only
  3071. MinVersion: tls.VersionTLS12,
  3072. }
  3073. }
  3074. req, err := http.NewRequest(http.MethodPut, fmt.Sprintf("%v%v", rootPath, remoteDestPath), srcFile)
  3075. if err != nil {
  3076. return err
  3077. }
  3078. req.SetBasicAuth(username, password)
  3079. for _, kv := range headers {
  3080. req.Header.Set(kv.Key, kv.Value)
  3081. }
  3082. httpClient := &http.Client{Timeout: 10 * time.Second}
  3083. if tlsConfig != nil {
  3084. customTransport := http.DefaultTransport.(*http.Transport).Clone()
  3085. customTransport.TLSClientConfig = tlsConfig
  3086. httpClient.Transport = customTransport
  3087. }
  3088. defer httpClient.CloseIdleConnections()
  3089. resp, err := httpClient.Do(req)
  3090. if err != nil {
  3091. return err
  3092. }
  3093. defer resp.Body.Close()
  3094. if resp.StatusCode != http.StatusCreated {
  3095. return fmt.Errorf("unexpected status code: %v", resp.StatusCode)
  3096. }
  3097. if expectedSize > 0 {
  3098. return checkFileSize(remoteDestPath, expectedSize, client)
  3099. }
  3100. return nil
  3101. }
  3102. // This method is buggy. I have to find time to better investigate and eventually report the issue upstream.
  3103. // For now we upload using the uploadFileWithRawClient method
  3104. /*func uploadFile(localSourcePath string, remoteDestPath string, expectedSize int64, client *gowebdav.Client) error {
  3105. srcFile, err := os.Open(localSourcePath)
  3106. if err != nil {
  3107. return err
  3108. }
  3109. defer srcFile.Close()
  3110. err = client.WriteStream(remoteDestPath, srcFile, os.ModePerm)
  3111. if err != nil {
  3112. return err
  3113. }
  3114. if expectedSize > 0 {
  3115. return checkFileSize(remoteDestPath, expectedSize, client)
  3116. }
  3117. return nil
  3118. }*/
  3119. func downloadFile(remoteSourcePath string, localDestPath string, expectedSize int64, client *gowebdav.Client) error {
  3120. downloadDest, err := os.Create(localDestPath)
  3121. if err != nil {
  3122. return err
  3123. }
  3124. defer downloadDest.Close()
  3125. reader, err := client.ReadStream(remoteSourcePath)
  3126. if err != nil {
  3127. return err
  3128. }
  3129. defer reader.Close()
  3130. written, err := io.Copy(downloadDest, reader)
  3131. if err != nil {
  3132. return err
  3133. }
  3134. if written != expectedSize {
  3135. return fmt.Errorf("downloaded file size does not match, actual: %v, expected: %v", written, expectedSize)
  3136. }
  3137. return nil
  3138. }
  3139. func getTLSHTTPClient(tlsConfig *tls.Config) *http.Client {
  3140. customTransport := http.DefaultTransport.(*http.Transport).Clone()
  3141. customTransport.TLSClientConfig = tlsConfig
  3142. return &http.Client{
  3143. Timeout: 5 * time.Second,
  3144. Transport: customTransport,
  3145. }
  3146. }
  3147. func getWebDavClient(user dataprovider.User, useTLS bool, tlsConfig *tls.Config) *gowebdav.Client {
  3148. rootPath := fmt.Sprintf("http://%v/", webDavServerAddr)
  3149. if useTLS {
  3150. rootPath = fmt.Sprintf("https://%v/", webDavTLSServerAddr)
  3151. if tlsConfig == nil {
  3152. tlsConfig = &tls.Config{
  3153. ServerName: "localhost",
  3154. InsecureSkipVerify: true, // use this for tests only
  3155. MinVersion: tls.VersionTLS12,
  3156. }
  3157. }
  3158. }
  3159. pwd := defaultPassword
  3160. if user.Password != "" {
  3161. if user.Password == emptyPwdPlaceholder {
  3162. pwd = ""
  3163. } else {
  3164. pwd = user.Password
  3165. }
  3166. }
  3167. client := gowebdav.NewClient(rootPath, user.Username, pwd)
  3168. client.SetTimeout(10 * time.Second)
  3169. if tlsConfig != nil {
  3170. customTransport := http.DefaultTransport.(*http.Transport).Clone()
  3171. customTransport.TLSClientConfig = tlsConfig
  3172. client.SetTransport(customTransport)
  3173. }
  3174. return client
  3175. }
  3176. func waitTCPListening(address string) {
  3177. for {
  3178. conn, err := net.Dial("tcp", address)
  3179. if err != nil {
  3180. logger.WarnToConsole("tcp server %v not listening: %v", address, err)
  3181. time.Sleep(100 * time.Millisecond)
  3182. continue
  3183. }
  3184. logger.InfoToConsole("tcp server %v now listening", address)
  3185. conn.Close()
  3186. break
  3187. }
  3188. }
  3189. func getTestUser() dataprovider.User {
  3190. user := dataprovider.User{
  3191. BaseUser: sdk.BaseUser{
  3192. Username: defaultUsername,
  3193. Password: defaultPassword,
  3194. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  3195. Status: 1,
  3196. ExpirationDate: 0,
  3197. },
  3198. }
  3199. user.Permissions = make(map[string][]string)
  3200. user.Permissions["/"] = allPerms
  3201. return user
  3202. }
  3203. func getTestSFTPUser() dataprovider.User {
  3204. u := getTestUser()
  3205. u.Username = u.Username + "_sftp"
  3206. u.FsConfig.Provider = sdk.SFTPFilesystemProvider
  3207. u.FsConfig.SFTPConfig.Endpoint = sftpServerAddr
  3208. u.FsConfig.SFTPConfig.Username = defaultUsername
  3209. u.FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword)
  3210. return u
  3211. }
  3212. func getTestUserWithCryptFs() dataprovider.User {
  3213. user := getTestUser()
  3214. user.FsConfig.Provider = sdk.CryptedFilesystemProvider
  3215. user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret("testPassphrase")
  3216. return user
  3217. }
  3218. func getEncryptedFileSize(size int64) (int64, error) {
  3219. encSize, err := sio.EncryptedSize(uint64(size))
  3220. return int64(encSize) + 33, err
  3221. }
  3222. func getExtAuthScriptContent(user dataprovider.User, password string) []byte {
  3223. extAuthContent := []byte("#!/bin/sh\n\n")
  3224. if password != "" {
  3225. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("if test \"$SFTPGO_AUTHD_USERNAME\" = \"%s\" -a \"$SFTPGO_AUTHD_PASSWORD\" = \"%s\"; then\n", user.Username, password))...)
  3226. } else {
  3227. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("if test \"$SFTPGO_AUTHD_USERNAME\" = \"%s\"; then\n", user.Username))...)
  3228. }
  3229. u, _ := json.Marshal(user)
  3230. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("echo '%s'\n", string(u)))...)
  3231. extAuthContent = append(extAuthContent, []byte("else\n")...)
  3232. extAuthContent = append(extAuthContent, []byte("echo '{\"username\":\"\"}'\n")...)
  3233. extAuthContent = append(extAuthContent, []byte("fi\n")...)
  3234. return extAuthContent
  3235. }
  3236. func getPreLoginScriptContent(user dataprovider.User, nonJSONResponse bool) []byte {
  3237. content := []byte("#!/bin/sh\n\n")
  3238. if nonJSONResponse {
  3239. content = append(content, []byte("echo 'text response'\n")...)
  3240. return content
  3241. }
  3242. if len(user.Username) > 0 {
  3243. u, _ := json.Marshal(user)
  3244. content = append(content, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  3245. }
  3246. return content
  3247. }
  3248. func getExitCodeScriptContent(exitCode int) []byte {
  3249. content := []byte("#!/bin/sh\n\n")
  3250. content = append(content, []byte(fmt.Sprintf("exit %v", exitCode))...)
  3251. return content
  3252. }
  3253. func createTestFile(path string, size int64) error {
  3254. baseDir := filepath.Dir(path)
  3255. if _, err := os.Stat(baseDir); errors.Is(err, fs.ErrNotExist) {
  3256. err = os.MkdirAll(baseDir, os.ModePerm)
  3257. if err != nil {
  3258. return err
  3259. }
  3260. }
  3261. content := make([]byte, size)
  3262. _, err := rand.Read(content)
  3263. if err != nil {
  3264. return err
  3265. }
  3266. err = os.WriteFile(path, content, os.ModePerm)
  3267. if err != nil {
  3268. return err
  3269. }
  3270. fi, err := os.Stat(path)
  3271. if err != nil {
  3272. return err
  3273. }
  3274. if fi.Size() != size {
  3275. return fmt.Errorf("unexpected size %v, expected %v", fi.Size(), size)
  3276. }
  3277. return nil
  3278. }
  3279. func printLatestLogs(maxNumberOfLines int) {
  3280. var lines []string
  3281. f, err := os.Open(logFilePath)
  3282. if err != nil {
  3283. return
  3284. }
  3285. defer f.Close()
  3286. scanner := bufio.NewScanner(f)
  3287. for scanner.Scan() {
  3288. lines = append(lines, scanner.Text()+"\r\n")
  3289. for len(lines) > maxNumberOfLines {
  3290. lines = lines[1:]
  3291. }
  3292. }
  3293. if scanner.Err() != nil {
  3294. logger.WarnToConsole("Unable to print latest logs: %v", scanner.Err())
  3295. return
  3296. }
  3297. for _, line := range lines {
  3298. logger.DebugToConsole("%s", line)
  3299. }
  3300. }