sftpd_test.go 173 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602
  1. package sftpd_test
  2. import (
  3. "bufio"
  4. "bytes"
  5. "crypto/rand"
  6. "crypto/sha256"
  7. "crypto/sha512"
  8. "encoding/base64"
  9. "encoding/binary"
  10. "encoding/json"
  11. "fmt"
  12. "hash"
  13. "io"
  14. "io/ioutil"
  15. "math"
  16. "net"
  17. "net/http"
  18. "os"
  19. "os/exec"
  20. "path"
  21. "path/filepath"
  22. "runtime"
  23. "strings"
  24. "testing"
  25. "time"
  26. _ "github.com/go-sql-driver/mysql"
  27. _ "github.com/lib/pq"
  28. _ "github.com/mattn/go-sqlite3"
  29. "github.com/pkg/sftp"
  30. "github.com/rs/zerolog"
  31. "github.com/stretchr/testify/assert"
  32. "golang.org/x/crypto/ssh"
  33. "github.com/drakkan/sftpgo/config"
  34. "github.com/drakkan/sftpgo/dataprovider"
  35. "github.com/drakkan/sftpgo/httpd"
  36. "github.com/drakkan/sftpgo/logger"
  37. "github.com/drakkan/sftpgo/sftpd"
  38. "github.com/drakkan/sftpgo/utils"
  39. "github.com/drakkan/sftpgo/vfs"
  40. )
  41. const (
  42. logSender = "sftpdTesting"
  43. sftpServerAddr = "127.0.0.1:2022"
  44. defaultUsername = "test_user_sftp"
  45. defaultPassword = "test_password"
  46. testPubKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0= nicola@p1"
  47. testPubKey1 = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCd60+/j+y8f0tLftihWV1YN9RSahMI9btQMDIMqts/jeNbD8jgoogM3nhF7KxfcaMKURuD47KC4Ey6iAJUJ0sWkSNNxOcIYuvA+5MlspfZDsa8Ag76Fe1vyz72WeHMHMeh/hwFo2TeIeIXg480T1VI6mzfDrVp2GzUx0SS0dMsQBjftXkuVR8YOiOwMCAH2a//M1OrvV7d/NBk6kBN0WnuIBb2jKm15PAA7+jQQG7tzwk2HedNH3jeL5GH31xkSRwlBczRK0xsCQXehAlx6cT/e/s44iJcJTHfpPKoSk6UAhPJYe7Z1QnuoawY9P9jQaxpyeImBZxxUEowhjpj2avBxKdRGBVK8R7EL8tSOeLbhdyWe5Mwc1+foEbq9Zz5j5Kd+hn3Wm1UnsGCrXUUUoZp1jnlNl0NakCto+5KmqnT9cHxaY+ix2RLUWAZyVFlRq71OYux1UHJnEJPiEI1/tr4jFBSL46qhQZv/TfpkfVW8FLz0lErfqu0gQEZnNHr3Fc= nicola@p1"
  48. testPrivateKey = `-----BEGIN OPENSSH PRIVATE KEY-----
  49. b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
  50. NhAAAAAwEAAQAAAYEAtN449A/nY5O6cSH/9Doa8a3ISU0WZJaHydTaCLuO+dkqtNpnV5mq
  51. zFbKidXAI1eSwVctw9ReVOl1uK6aZF3lbXdOD8W9PXobR9KUUT2qBx5QC4ibfAqDKWymDA
  52. PG9ylzz64hsYBqJr7VNk9kTFEUsDmWzLabLoH42Elnp8mF/lTkWIcpVp0ly/etS08gttXo
  53. XenekJ1vRuxOYWDCEzGPU7kGc920TmM14k7IDdPoOh5+3sRUKedKeOUrVDH1f0n7QjHQsZ
  54. cbshp8tgqzf734zu8cTqNrr+6taptdEOOij1iUL/qYGfzny/hA48tO5+UFUih5W8ftp0+E
  55. NBIDkkGgk2MJ92I7QAXyMVsIABXco+mJT7pQi9tqlODGIQ3AOj0gcA3X/Ib8QX77Ih3TPi
  56. XEh77/P1XiYZOgpp2cRmNH8QbqaL9u898hDvJwIPJPuj2lIltTElH7hjBf5LQfCzrLV7BD
  57. 10rM7sl4jr+A2q8jl1Ikp+25kainBBZSbrDummT9AAAFgDU/VLk1P1S5AAAAB3NzaC1yc2
  58. EAAAGBALTeOPQP52OTunEh//Q6GvGtyElNFmSWh8nU2gi7jvnZKrTaZ1eZqsxWyonVwCNX
  59. ksFXLcPUXlTpdbiummRd5W13Tg/FvT16G0fSlFE9qgceUAuIm3wKgylspgwDxvcpc8+uIb
  60. GAaia+1TZPZExRFLA5lsy2my6B+NhJZ6fJhf5U5FiHKVadJcv3rUtPILbV6F3p3pCdb0bs
  61. TmFgwhMxj1O5BnPdtE5jNeJOyA3T6Doeft7EVCnnSnjlK1Qx9X9J+0Ix0LGXG7IafLYKs3
  62. +9+M7vHE6ja6/urWqbXRDjoo9YlC/6mBn858v4QOPLTuflBVIoeVvH7adPhDQSA5JBoJNj
  63. CfdiO0AF8jFbCAAV3KPpiU+6UIvbapTgxiENwDo9IHAN1/yG/EF++yId0z4lxIe+/z9V4m
  64. GToKadnEZjR/EG6mi/bvPfIQ7ycCDyT7o9pSJbUxJR+4YwX+S0Hws6y1ewQ9dKzO7JeI6/
  65. gNqvI5dSJKftuZGopwQWUm6w7ppk/QAAAAMBAAEAAAGAHKnC+Nq0XtGAkIFE4N18e6SAwy
  66. 0WSWaZqmCzFQM0S2AhJnweOIG/0ZZHjsRzKKauOTmppQk40dgVsejpytIek9R+aH172gxJ
  67. 2n4Cx0UwduRU5x8FFQlNc/kl722B0JWfJuB/snOZXv6LJ4o5aObIkozt2w9tVFeAqjYn2S
  68. 1UsNOfRHBXGsTYwpRDwFWP56nKo2d2wBBTHDhCy6fb2dLW1fvSi/YspueOGIlHpvlYKi2/
  69. CWqvs9xVrwcScMtiDoQYq0khhO0efLCxvg/o+W9CLMVM2ms4G1zoSUQKN0oYWWQJyW4+VI
  70. YneWO8UpN0J3ElXKi7bhgAat7dBaM1g9IrAzk153DiEFZNsPxGOgL/+YdQN7zUBx/z7EkI
  71. jyv80RV7fpUXvcq2p+qNl6UVig3VSzRrnsaJkUWu/A0u59ha7ocv6NxDIXjxpIDJme16GF
  72. quiGVBQNnYJymS/vFEbGf6bgf7iRmMCRUMG4nqLA6fPYP9uAtch+CmDfVLZC/fIdC5AAAA
  73. wQCDissV4zH6bfqgxJSuYNk8Vbb+19cF3b7gH1rVlB3zxpCAgcRgMHC+dP1z2NRx7UW9MR
  74. nye6kjpkzZZ0OigLqo7TtEq8uTglD9o6W7mRXqhy5A/ySOmqPL3ernHHQhGuoNODYAHkOU
  75. u2Rh8HXi+VLwKZcLInPOYJvcuLG4DxN8WfeVvlMHwhAOaTNNOtL4XZDHQeIPc4qHmJymmv
  76. sV7GuyQ6yW5C10uoGdxRPd90Bh4z4h2bKfZFjvEBbSBVkqrlAAAADBAN/zNtNayd/dX7Cr
  77. Nb4sZuzCh+CW4BH8GOePZWNCATwBbNXBVb5cR+dmuTqYm+Ekz0VxVQRA1TvKncluJOQpoa
  78. Xj8r0xdIgqkehnfDPMKtYVor06B9Fl1jrXtXU0Vrr6QcBWruSVyK1ZxqcmcNK/+KolVepe
  79. A6vcl/iKaG4U7su166nxLST06M2EgcSVsFJHpKn5+WAXC+X0Gx8kNjWIIb3GpiChdc0xZD
  80. mq02xZthVJrTCVw/e7gfDoB2QRsNV8HwAAAMEAzsCghZVp+0YsYg9oOrw4tEqcbEXEMhwY
  81. 0jW8JNL8Spr1Ibp5Dw6bRSk5azARjmJtnMJhJ3oeHfF0eoISqcNuQXGndGQbVM9YzzAzc1
  82. NbbCNsVroqKlChT5wyPNGS+phi2bPARBno7WSDvshTZ7dAVEP2c9MJW0XwoSevwKlhgSdt
  83. RLFFQ/5nclJSdzPBOmQouC0OBcMFSrYtMeknJ4VvueVvve5HcHFaEsaMc7ABAGaLYaBQOm
  84. iixITGvaNZh/tjAAAACW5pY29sYUBwMQE=
  85. -----END OPENSSH PRIVATE KEY-----`
  86. // test CA user key.
  87. // % ssh-keygen -f ca_user_key
  88. testCAUserKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDF5fcwZHiyixmnE6IlOZJpZhWXoh62gN+yadAA0GJ509SAEaZVLPDP8S5RsE8mUikR3wxynVshxHeqMhrkS+RlNbhSlOXDdNg94yTrq/xF8Z/PgKRInvef74k5i7bAIytza7jERzFJ/ujTEy3537T5k5EYQJ15ZQGuvzynSdv+6o99SjI4jFplyQOZ2QcYbEAmhHm5GgQlIiEFG/RlDtLksOulKZxOY3qPzP0AyQxtZJXn/5vG40aW9LTbwxCJqWlgrkFXMqAAVCbuU5YspwhiXmKt1PsldiXw23oloa4caCKN1jzbFiGuZNXEU2Ebx7JIvjQCPaUYwLjEbkRDxDqN/vmwZqBuKYiuG9Eafx+nFSQkr7QYb5b+mT+/1IFHnmeRGn38731kBqtH7tpzC/t+soRX9p2HtJM+9MYhblO2OqTSPGTlxihWUkyiRBekpAhaiHld16TsG+A3bOJHrojGcX+5g6oGarKGLAMcykL1X+rZqT993Mo6d2Z7q43MOXE= root@p1"
  89. // this is testPubKey signed using testCAUserKey.
  90. // % ssh-keygen -s ca_user_key -I test_user_sftp -n test_user_sftp -V always:forever -O source-address=127.0.0.1 -z 1 /tmp/test.pub
  91. testCertValid = "[email protected] AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgm2fil1IIoTixrA2QE9tk7Vbspj/JdEY90e3K2htxYv8AAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0AAAAAAAAAAQAAAAEAAAAOdGVzdF91c2VyX3NmdHAAAAASAAAADnRlc3RfdXNlcl9zZnRwAAAAAAAAAAD//////////wAAACMAAAAOc291cmNlLWFkZHJlc3MAAAANAAAACTEyNy4wLjAuMQAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAZcAAAAHc3NoLXJzYQAAAAMBAAEAAAGBAMXl9zBkeLKLGacToiU5kmlmFZeiHraA37Jp0ADQYnnT1IARplUs8M/xLlGwTyZSKRHfDHKdWyHEd6oyGuRL5GU1uFKU5cN02D3jJOur/EXxn8+ApEie95/viTmLtsAjK3NruMRHMUn+6NMTLfnftPmTkRhAnXllAa6/PKdJ2/7qj31KMjiMWmXJA5nZBxhsQCaEebkaBCUiIQUb9GUO0uSw66UpnE5jeo/M/QDJDG1klef/m8bjRpb0tNvDEImpaWCuQVcyoABUJu5TliynCGJeYq3U+yV2JfDbeiWhrhxoIo3WPNsWIa5k1cRTYRvHski+NAI9pRjAuMRuREPEOo3++bBmoG4piK4b0Rp/H6cVJCSvtBhvlv6ZP7/UgUeeZ5EaffzvfWQGq0fu2nML+36yhFf2nYe0kz70xiFuU7Y6pNI8ZOXGKFZSTKJEF6SkCFqIeV3XpOwb4Dds4keuiMZxf7mDqgZqsoYsAxzKQvVf6tmpP33cyjp3Znurjcw5cQAAAZQAAAAMcnNhLXNoYTItNTEyAAABgMNenD7d1J9cF7JWgHA1DYpJ5+5knPtdXbbIgZAznsTxX7qOdptjeeYOuzhQ5Bwklh3fjewiJpGR1rBqbULP+6PAKeYqd7dNLH/upfKBfJweRf5pdXDpoknHaVuIhi4Uu6FeI4NkAzX9nqNKjFAflhJ+7GLGkLNb0UVZxgxr/t0rPmxc5iTg2ZRM+rk1Ij0S5RnGiKVsdAClqNA6h4TDzu5lJVdK5XvuNKBsKVRCvsVBOgJQTtRTLywQaqWR+HBfCiMj8X8EI7atDlJ6XIAlTLOO/f1sM8QPLjT0+tCHZaGFzg/lKPh3/yFQ4MvddZCptMy1Ll1xvj7cz2ynhGR4PiDfikV3YzgJU/KtL5y+ZB4jU08oPRiOP612PjwZZ+MqYOVOFCKUpMpZQs5UJHME+zNKr4LEj8M0x4YFKIciC+RsrCo4ujbJHmz61ionCadU+fmngvl3C3QjmUdgULBevODeUeIpJv4yFahNxrG1SKRTAa8VVDwJ9GdDTtmXM0mrwA== nicola@p1"
  92. // this is testPubKey signed using a CA user key different from testCAUserKey
  93. testCertUntrustedCA = "[email protected] AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg8oFPWpjYy/DowMmtOjWj7Dq20d2N/4Rxzr/c710tOOUAAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0AAAAAAAAAAAAAAAEAAAAOdGVzdF91c2VyX3NmdHAAAAASAAAADnRlc3RfdXNlcl9zZnRwAAAAAAAAAAD//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAGXAAAAB3NzaC1yc2EAAAADAQABAAABgQCqgm2gVlptULThfpRR0oCb4SAU3368ULlJaiZOUdq6b94KTfgmu4hTLs7u3a8hyZnVxrKrJ93uAVCwa/HGtgiN96CNC6JUt/QnPqTJ8LQ207RdoE9fbOe6mGwOle5z45+5JFoIi5ZZuD8JsBGodVoa92UepoMyBcNtZyl9q2GP4yT2tIYRon79dtG9AXiDYyhSgePqaObN67dn3ivMc4ZGNukK3cG07cYPic5y0wxX16wSMG3pGQDyUkAu+s4AqpnV9EWHM4PE7SYkCXE99++tUK3QALYqvGZKrLHgzmDKi6n+e14vHYUppAeGDZzwlawiY4oGP9eOW2KUfjZe2ZeL22JTFDYzH2lNV2WtUpeKRGGTSGaUblRVC9hRt6hKCT4c7qpW4kO4kPhE39JpcNPGLql7srNkw+3xXBs8xghMPtH3nOl1Rz2mxnX5tAqmPBb+KiPepnrs+pBRu7i+nCVp8az+iN87STYHy+zPtvTR+QURC8BpNraPOfXwpwM2HaMAAAGUAAAADHJzYS1zaGEyLTUxMgAAAYBnTXCL6tXUO3/Gtsm7lnH9Sulzca8FOoI4Y/4bVYhq4iUNu7Ca452m+Xr9qmCEoIyIJF0LEEcJ8jcS4rfX15e7tNNoknv7JbYXBFAbp1Y/76iqVf89FjfVcbEyH2ToAf7eyQAWzQ3gEKS8mQIkLnAwmCboUXC4GRodSIiOXiTt5Q6T02MVc8TxkhmlTA0uVLd5XgstySgE/oLBnL59lhJcwQmdhHL+m480+PaW55CtMuC36RTwk/tOyuWCDC5qMXnoveNB3yu45o3L/U4hoyJ0/5FyP5C8ahgydY0LoRZQG/mNzuraY4433rK+IfkQvZTyaDtcjhxE6hCD5F40aDDh88i6XaKAPikD6fqra6BN8PoPgLuRHzOJuqsMXBWM99s7qPgSnBbmXlekz/1jvvFiCh3zvAFTxFz2KyE4+SbDcCrhpxkNL7idw6r/ZsHaI/2+zhDcgSs5MgBwYLJEj6zUqVdp5XsF8YfC7yNZV5/qy68qY2+zXrC57SPifU2SCPE= nicola@p1"
  94. // this is testPubKey signed as host certificate.
  95. // % ssh-keygen -s ca_user_key -I test_user_sftp -h -n test_user_sftp -V always:forever -z 2 /tmp/test.pub
  96. testHostCert = "[email protected] AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg7O2LDpLO1jGTX3SSzEMILoAYJb9DdggyyaUMXUUg3L4AAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0AAAAAAAAAAgAAAAIAAAAOdGVzdF91c2VyX3NmdHAAAAASAAAADnRlc3RfdXNlcl9zZnRwAAAAAAAAAAD//////////wAAAAAAAAAAAAAAAAAAAZcAAAAHc3NoLXJzYQAAAAMBAAEAAAGBAMXl9zBkeLKLGacToiU5kmlmFZeiHraA37Jp0ADQYnnT1IARplUs8M/xLlGwTyZSKRHfDHKdWyHEd6oyGuRL5GU1uFKU5cN02D3jJOur/EXxn8+ApEie95/viTmLtsAjK3NruMRHMUn+6NMTLfnftPmTkRhAnXllAa6/PKdJ2/7qj31KMjiMWmXJA5nZBxhsQCaEebkaBCUiIQUb9GUO0uSw66UpnE5jeo/M/QDJDG1klef/m8bjRpb0tNvDEImpaWCuQVcyoABUJu5TliynCGJeYq3U+yV2JfDbeiWhrhxoIo3WPNsWIa5k1cRTYRvHski+NAI9pRjAuMRuREPEOo3++bBmoG4piK4b0Rp/H6cVJCSvtBhvlv6ZP7/UgUeeZ5EaffzvfWQGq0fu2nML+36yhFf2nYe0kz70xiFuU7Y6pNI8ZOXGKFZSTKJEF6SkCFqIeV3XpOwb4Dds4keuiMZxf7mDqgZqsoYsAxzKQvVf6tmpP33cyjp3Znurjcw5cQAAAZQAAAAMcnNhLXNoYTItNTEyAAABgHlAWMTTzNrE6pxHlkr09ZXsHgJi8U2p7eifs56DOLgklYIXVUJPEEcnzMKGdpPBnqJsvg3+PccqxgOr5L1dFuOmekQ/dGiHd1enrESiGvJOvDfm0WsuBjxEZkSNFWgC9Z2NltToMmRlhVBmb4ZRZtAmi9DAFlJ/BDV4t8ikXZ5oUsigwIeOeLkdPFx3C3x9KZIpuwuAIV4Nfmz75q1NMWY2K1hv682QCKwMYqOWSotz1vWunNmZ0yPRl9UwqAq+nqwO3AApnlrQ3MmHujWQ5tl65PyhfpI8oghhUtB6YrJIAuRXNI/S0+KewCpiYm7nbFBtv9lpecujxAeTibYBrFZ5VODEUm3sdQ/HMdTmkhi6xNgPDQVlvKFqBJAaqoO3tbhKTbEZ865tJMqhyxmZ4XY08wduvSVobrNr7s3rm42/FXLIpung+UOVXonHyeIv9zQ0iJ/bvqKQ1fOsTisZdcD0lz80ZGsjdgJt7yKfUNBnAyVbTXm048E3WsZslJIYCA== nicola@p1"
  97. // this is testPubKey signed using testCAUserKey but with source address 172.16.34.45.
  98. // % ssh-keygen -s ca_user_key -I test_user_sftp -n test_user_sftp -V always:forever -O source-address=172.16.34.45 -z 3 /tmp/test.pub
  99. testCertOtherSourceAddress = "[email protected] AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgZ4Su0250R4sQRNYJqJH9VTp9OyeYMAvqY5+lJRI4LzMAAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0AAAAAAAAAAwAAAAEAAAAOdGVzdF91c2VyX3NmdHAAAAASAAAADnRlc3RfdXNlcl9zZnRwAAAAAAAAAAD//////////wAAACYAAAAOc291cmNlLWFkZHJlc3MAAAAQAAAADDE3Mi4xNi4zNC40NQAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAZcAAAAHc3NoLXJzYQAAAAMBAAEAAAGBAMXl9zBkeLKLGacToiU5kmlmFZeiHraA37Jp0ADQYnnT1IARplUs8M/xLlGwTyZSKRHfDHKdWyHEd6oyGuRL5GU1uFKU5cN02D3jJOur/EXxn8+ApEie95/viTmLtsAjK3NruMRHMUn+6NMTLfnftPmTkRhAnXllAa6/PKdJ2/7qj31KMjiMWmXJA5nZBxhsQCaEebkaBCUiIQUb9GUO0uSw66UpnE5jeo/M/QDJDG1klef/m8bjRpb0tNvDEImpaWCuQVcyoABUJu5TliynCGJeYq3U+yV2JfDbeiWhrhxoIo3WPNsWIa5k1cRTYRvHski+NAI9pRjAuMRuREPEOo3++bBmoG4piK4b0Rp/H6cVJCSvtBhvlv6ZP7/UgUeeZ5EaffzvfWQGq0fu2nML+36yhFf2nYe0kz70xiFuU7Y6pNI8ZOXGKFZSTKJEF6SkCFqIeV3XpOwb4Dds4keuiMZxf7mDqgZqsoYsAxzKQvVf6tmpP33cyjp3Znurjcw5cQAAAZQAAAAMcnNhLXNoYTItNTEyAAABgL34Q3Li8AJIxZLU+fh4i8ehUWpm31vEvlNjXVCeP70xI+5hWuEt6E1TgKw7GCL5GeD4KehX4vVcNs+A2eOdIUZfDBZIFxn88BN8xcMlDpAMJXgvNqGttiOwcspL6X3N288djUgpCI718lLRdz8nvFqcuYBhSpBm5KL4JzH5o1o8yqv75wMJsH8CJYwGhvWi0OgWOqaLRAk3IUxq3Fbgo/nX11NgrkY/dHIZCkGBFaLJ/M5mfmt/K/5hJAVgLcSxMwB/ryyGaziB9Pv7CwZ9uwnMoRcAvyr96lqgdtLt7LNY8ktugAJ7EnBWjQn4+EJAjjRK2sCaiwpdP37ckDZgmk0OWGEL1yVy8VXgl9QBd7Mb1EVl+lhRyw8jlgBXZOGqpdDrmKCdBYGtU7ujyndLXmxZEAlqhef0yCsyZPTkYH3RhjCYs8ATrEqndEpiL59Nej5uUGQURYijJfHep08AMb4rCxvIZATVm1Ocxu48rGCGolv8jZFJzSJq84HCrVRKMw== nicola@p1"
  100. // this is testPubKey signed using testCAUserKey but expired.
  101. // % ssh-keygen -s ca_user_key -I test_user_sftp -n test_user_sftp -V 20100101123000:20110101123000 -z 4 /tmp/test.pub
  102. testCertExpired = "[email protected] AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgU3TLP5285k20fBSsdZioI78oJUpaRXFlgx5IPg6gWg8AAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0AAAAAAAAABAAAAAEAAAAOdGVzdF91c2VyX3NmdHAAAAASAAAADnRlc3RfdXNlcl9zZnRwAAAAAEs93LgAAAAATR8QOAAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAGXAAAAB3NzaC1yc2EAAAADAQABAAABgQDF5fcwZHiyixmnE6IlOZJpZhWXoh62gN+yadAA0GJ509SAEaZVLPDP8S5RsE8mUikR3wxynVshxHeqMhrkS+RlNbhSlOXDdNg94yTrq/xF8Z/PgKRInvef74k5i7bAIytza7jERzFJ/ujTEy3537T5k5EYQJ15ZQGuvzynSdv+6o99SjI4jFplyQOZ2QcYbEAmhHm5GgQlIiEFG/RlDtLksOulKZxOY3qPzP0AyQxtZJXn/5vG40aW9LTbwxCJqWlgrkFXMqAAVCbuU5YspwhiXmKt1PsldiXw23oloa4caCKN1jzbFiGuZNXEU2Ebx7JIvjQCPaUYwLjEbkRDxDqN/vmwZqBuKYiuG9Eafx+nFSQkr7QYb5b+mT+/1IFHnmeRGn38731kBqtH7tpzC/t+soRX9p2HtJM+9MYhblO2OqTSPGTlxihWUkyiRBekpAhaiHld16TsG+A3bOJHrojGcX+5g6oGarKGLAMcykL1X+rZqT993Mo6d2Z7q43MOXEAAAGUAAAADHJzYS1zaGEyLTUxMgAAAYAlH3hhj8J6xLyVpeLZjblzwDKrxp/MWiH30hQ965ExPrPRcoAZFEKVqOYdj6bp4Q19Q4Yzqdobg3aN5ym2iH0b2TlOY0mM901CAoHbNJyiLs+0KiFRoJ+30EDj/hcKusg6v8ln2yixPagAyQu3zyiWo4t1ZuO3I86xchGlptStxSdHAHPFCfpbhcnzWFZctiMqUutl82C4ROWyjOZcRzdVdWHeN5h8wnooXuvba2VkT8QPmjYYyRGuQ3Hg+ySdh8Tel4wiix1Dg5MX7Wjh4hKEx80No9UPy+0iyZMNc07lsWAtrY6NRxGM5CzB6mklscB8TzFrVSnIl9u3bquLfaCrFt/Mft5dR7Yy4jmF+zUhjia6h6giCZ91J+FZ4hV+WkBtPCvTfrGWoA1BgEB/iI2xOq/NPqJ7UXRoMXk/l0NPgRPT2JS1adegqnt4ddr6IlmPyZxaSEvXhanjKdfMlEFYO1wz7ouqpYUozQVy4KXBlzFlNwyD1hI+k4+/A6AIYeI= nicola@p1"
  103. configDir = ".."
  104. permissionErrorString = "Permission Denied"
  105. osWindows = "windows"
  106. )
  107. var (
  108. allPerms = []string{dataprovider.PermAny}
  109. homeBasePath string
  110. scpPath string
  111. gitPath string
  112. sshPath string
  113. pubKeyPath string
  114. privateKeyPath string
  115. trustedCAUserKey string
  116. gitWrapPath string
  117. extAuthPath string
  118. keyIntAuthPath string
  119. preLoginPath string
  120. logFilePath string
  121. )
  122. func TestMain(m *testing.M) {
  123. logFilePath = filepath.Join(configDir, "sftpgo_sftpd_test.log")
  124. loginBannerFileName := "login_banner"
  125. loginBannerFile := filepath.Join(configDir, loginBannerFileName)
  126. logger.InitLogger(logFilePath, 5, 1, 28, false, zerolog.DebugLevel)
  127. err := ioutil.WriteFile(loginBannerFile, []byte("simple login banner\n"), 0777)
  128. if err != nil {
  129. logger.WarnToConsole("error creating login banner: %v", err)
  130. os.Exit(1)
  131. }
  132. err = config.LoadConfig(configDir, "")
  133. if err != nil {
  134. logger.WarnToConsole("error loading configuration: %v", err)
  135. os.Exit(1)
  136. }
  137. providerConf := config.GetProviderConf()
  138. err = dataprovider.Initialize(providerConf, configDir)
  139. if err != nil {
  140. logger.WarnToConsole("error initializing data provider: %v", err)
  141. os.Exit(1)
  142. }
  143. httpConfig := config.GetHTTPConfig()
  144. httpConfig.Initialize(configDir)
  145. dataProvider := dataprovider.GetProvider()
  146. sftpdConf := config.GetSFTPDConfig()
  147. httpdConf := config.GetHTTPDConfig()
  148. sftpdConf.BindPort = 2022
  149. sftpdConf.KexAlgorithms = []string{"[email protected]", "ecdh-sha2-nistp256",
  150. "ecdh-sha2-nistp384"}
  151. sftpdConf.Ciphers = []string{"[email protected]", "[email protected]",
  152. "aes256-ctr"}
  153. sftpdConf.MACs = []string{"[email protected]", "hmac-sha2-256"}
  154. sftpdConf.LoginBannerFile = loginBannerFileName
  155. // we need to test all supported ssh commands
  156. sftpdConf.EnabledSSHCommands = []string{"*"}
  157. // we run the test cases with UploadMode atomic and resume support. The non atomic code path
  158. // simply does not execute some code so if it works in atomic mode will
  159. // work in non atomic mode too
  160. sftpdConf.UploadMode = 2
  161. homeBasePath = os.TempDir()
  162. var scriptArgs string
  163. if runtime.GOOS == osWindows {
  164. scriptArgs = "%*"
  165. } else {
  166. sftpdConf.Actions.ExecuteOn = []string{"download", "upload", "rename", "delete", "ssh_cmd"}
  167. sftpdConf.Actions.Command = "/bin/true"
  168. sftpdConf.Actions.HTTPNotificationURL = "http://127.0.0.1:8083/"
  169. scriptArgs = "$@"
  170. scpPath, err = exec.LookPath("scp")
  171. if err != nil {
  172. logger.Warn(logSender, "", "unable to get scp command. SCP tests will be skipped, err: %v", err)
  173. logger.WarnToConsole("unable to get scp command. SCP tests will be skipped, err: %v", err)
  174. scpPath = ""
  175. }
  176. }
  177. checkGitCommand()
  178. keyIntAuthPath = filepath.Join(homeBasePath, "keyintauth.sh")
  179. err = ioutil.WriteFile(keyIntAuthPath, getKeyboardInteractiveScriptContent([]string{"1", "2"}, 0, false, 1), 0755)
  180. if err != nil {
  181. logger.WarnToConsole("error writing keyboard interactive script: %v", err)
  182. os.Exit(1)
  183. }
  184. sftpdConf.KeyboardInteractiveHook = keyIntAuthPath
  185. pubKeyPath = filepath.Join(homeBasePath, "ssh_key.pub")
  186. privateKeyPath = filepath.Join(homeBasePath, "ssh_key")
  187. trustedCAUserKey = filepath.Join(homeBasePath, "ca_user_key")
  188. gitWrapPath = filepath.Join(homeBasePath, "gitwrap.sh")
  189. extAuthPath = filepath.Join(homeBasePath, "extauth.sh")
  190. preLoginPath = filepath.Join(homeBasePath, "prelogin.sh")
  191. err = ioutil.WriteFile(pubKeyPath, []byte(testPubKey+"\n"), 0600)
  192. if err != nil {
  193. logger.WarnToConsole("unable to save public key to file: %v", err)
  194. }
  195. err = ioutil.WriteFile(privateKeyPath, []byte(testPrivateKey+"\n"), 0600)
  196. if err != nil {
  197. logger.WarnToConsole("unable to save private key to file: %v", err)
  198. }
  199. err = ioutil.WriteFile(gitWrapPath, []byte(fmt.Sprintf("%v -i %v -oStrictHostKeyChecking=no %v\n",
  200. sshPath, privateKeyPath, scriptArgs)), 0755)
  201. if err != nil {
  202. logger.WarnToConsole("unable to save gitwrap shell script: %v", err)
  203. }
  204. err = ioutil.WriteFile(trustedCAUserKey, []byte(testCAUserKey), 0600)
  205. if err != nil {
  206. logger.WarnToConsole("unable to save trusted CA user key: %v", err)
  207. }
  208. sftpdConf.TrustedUserCAKeys = append(sftpdConf.TrustedUserCAKeys, trustedCAUserKey)
  209. sftpd.SetDataProvider(dataProvider)
  210. httpd.SetDataProvider(dataProvider)
  211. go func() {
  212. logger.Debug(logSender, "", "initializing SFTP server with config %+v", sftpdConf)
  213. if err := sftpdConf.Initialize(configDir); err != nil {
  214. logger.Error(logSender, "", "could not start SFTP server: %v", err)
  215. }
  216. }()
  217. go func() {
  218. if err := httpdConf.Initialize(configDir, false); err != nil {
  219. logger.Error(logSender, "", "could not start HTTP server: %v", err)
  220. }
  221. }()
  222. waitTCPListening(fmt.Sprintf("%s:%d", sftpdConf.BindAddress, sftpdConf.BindPort))
  223. waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
  224. sftpdConf.BindPort = 2222
  225. sftpdConf.ProxyProtocol = 1
  226. go func() {
  227. logger.Debug(logSender, "", "initializing SFTP server with config %+v", sftpdConf)
  228. if err := sftpdConf.Initialize(configDir); err != nil {
  229. logger.Error(logSender, "", "could not start SFTP server: %v", err)
  230. }
  231. }()
  232. waitTCPListening(fmt.Sprintf("%s:%d", sftpdConf.BindAddress, sftpdConf.BindPort))
  233. sftpdConf.BindPort = 2224
  234. sftpdConf.ProxyProtocol = 2
  235. go func() {
  236. logger.Debug(logSender, "", "initializing SFTP server with config %+v", sftpdConf)
  237. if err := sftpdConf.Initialize(configDir); err != nil {
  238. logger.Error(logSender, "", "could not start SFTP server: %v", err)
  239. }
  240. }()
  241. waitTCPListening(fmt.Sprintf("%s:%d", sftpdConf.BindAddress, sftpdConf.BindPort))
  242. exitCode := m.Run()
  243. os.Remove(logFilePath)
  244. os.Remove(loginBannerFile)
  245. os.Remove(pubKeyPath)
  246. os.Remove(privateKeyPath)
  247. os.Remove(trustedCAUserKey)
  248. os.Remove(gitWrapPath)
  249. os.Remove(extAuthPath)
  250. os.Remove(preLoginPath)
  251. os.Remove(keyIntAuthPath)
  252. os.Exit(exitCode)
  253. }
  254. func TestInitialization(t *testing.T) {
  255. err := config.LoadConfig(configDir, "")
  256. assert.NoError(t, err)
  257. sftpdConf := config.GetSFTPDConfig()
  258. sftpdConf.Umask = "invalid umask"
  259. sftpdConf.BindPort = 2022
  260. sftpdConf.LoginBannerFile = "invalid_file"
  261. sftpdConf.EnabledSSHCommands = append(sftpdConf.EnabledSSHCommands, "ls")
  262. err = sftpdConf.Initialize(configDir)
  263. assert.Error(t, err)
  264. sftpdConf.KeyboardInteractiveHook = "invalid_file"
  265. err = sftpdConf.Initialize(configDir)
  266. assert.Error(t, err)
  267. sftpdConf.KeyboardInteractiveHook = filepath.Join(homeBasePath, "invalid_file")
  268. err = sftpdConf.Initialize(configDir)
  269. assert.Error(t, err)
  270. sftpdConf.BindPort = 4444
  271. sftpdConf.ProxyProtocol = 1
  272. sftpdConf.ProxyAllowed = []string{"1270.0.0.1"}
  273. err = sftpdConf.Initialize(configDir)
  274. assert.Error(t, err)
  275. sftpdConf.HostKeys = []string{"missing file"}
  276. err = sftpdConf.Initialize(configDir)
  277. assert.Error(t, err)
  278. sftpdConf.Keys = nil
  279. sftpdConf.TrustedUserCAKeys = []string{"missing file"}
  280. err = sftpdConf.Initialize(configDir)
  281. assert.Error(t, err)
  282. }
  283. func TestBasicSFTPHandling(t *testing.T) {
  284. usePubKey := false
  285. u := getTestUser(usePubKey)
  286. u.QuotaSize = 6553600
  287. user, _, err := httpd.AddUser(u, http.StatusOK)
  288. assert.NoError(t, err)
  289. err = os.RemoveAll(user.GetHomeDir())
  290. assert.NoError(t, err)
  291. client, err := getSftpClient(user, usePubKey)
  292. if assert.NoError(t, err) {
  293. defer client.Close()
  294. testFileName := "test_file.dat" //nolint:goconst
  295. testFilePath := filepath.Join(homeBasePath, testFileName)
  296. testFileSize := int64(65535)
  297. expectedQuotaSize := user.UsedQuotaSize + testFileSize
  298. expectedQuotaFiles := user.UsedQuotaFiles + 1
  299. err = createTestFile(testFilePath, testFileSize)
  300. assert.NoError(t, err)
  301. err = sftpUploadFile(testFilePath, path.Join("/missing_dir", testFileName), testFileSize, client)
  302. assert.Error(t, err)
  303. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  304. assert.NoError(t, err)
  305. localDownloadPath := filepath.Join(homeBasePath, "test_download.dat")
  306. err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize, client)
  307. assert.NoError(t, err)
  308. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  309. assert.NoError(t, err)
  310. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  311. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  312. err = client.Remove(testFileName)
  313. assert.NoError(t, err)
  314. _, err = client.Lstat(testFileName)
  315. assert.Error(t, err)
  316. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  317. assert.NoError(t, err)
  318. assert.Equal(t, expectedQuotaFiles-1, user.UsedQuotaFiles)
  319. assert.Equal(t, expectedQuotaSize-testFileSize, user.UsedQuotaSize)
  320. err = os.Remove(testFilePath)
  321. assert.NoError(t, err)
  322. err = os.Remove(localDownloadPath)
  323. assert.NoError(t, err)
  324. }
  325. _, err = httpd.RemoveUser(user, http.StatusOK)
  326. assert.NoError(t, err)
  327. err = os.RemoveAll(user.GetHomeDir())
  328. assert.NoError(t, err)
  329. }
  330. func TestProxyProtocol(t *testing.T) {
  331. usePubKey := false
  332. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  333. assert.NoError(t, err)
  334. // remove the home dir to test auto creation
  335. err = os.RemoveAll(user.HomeDir)
  336. assert.NoError(t, err)
  337. client, err := getSftpClientWithAddr(user, usePubKey, "127.0.0.1:2222")
  338. if assert.NoError(t, err) {
  339. defer client.Close()
  340. assert.NoError(t, checkBasicSFTP(client))
  341. }
  342. client, err = getSftpClientWithAddr(user, usePubKey, "127.0.0.1:2224")
  343. if !assert.Error(t, err) {
  344. client.Close()
  345. }
  346. _, err = httpd.RemoveUser(user, http.StatusOK)
  347. assert.NoError(t, err)
  348. err = os.RemoveAll(user.GetHomeDir())
  349. assert.NoError(t, err)
  350. }
  351. func TestUploadResume(t *testing.T) {
  352. usePubKey := false
  353. u := getTestUser(usePubKey)
  354. user, _, err := httpd.AddUser(u, http.StatusOK)
  355. assert.NoError(t, err)
  356. err = os.RemoveAll(user.GetHomeDir())
  357. assert.NoError(t, err)
  358. client, err := getSftpClient(user, usePubKey)
  359. if assert.NoError(t, err) {
  360. defer client.Close()
  361. testFileName := "test_file.dat"
  362. testFilePath := filepath.Join(homeBasePath, testFileName)
  363. testFileSize := int64(65535)
  364. appendDataSize := int64(65535)
  365. err = createTestFile(testFilePath, testFileSize)
  366. assert.NoError(t, err)
  367. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  368. assert.NoError(t, err)
  369. err = appendToTestFile(testFilePath, appendDataSize)
  370. assert.NoError(t, err)
  371. err = sftpUploadResumeFile(testFilePath, testFileName, testFileSize+appendDataSize, false, client)
  372. assert.NoError(t, err)
  373. localDownloadPath := filepath.Join(homeBasePath, "test_download.dat")
  374. err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize+appendDataSize, client)
  375. assert.NoError(t, err)
  376. initialHash, err := computeHashForFile(sha256.New(), testFilePath)
  377. assert.NoError(t, err)
  378. donwloadedFileHash, err := computeHashForFile(sha256.New(), localDownloadPath)
  379. assert.NoError(t, err)
  380. assert.Equal(t, initialHash, donwloadedFileHash)
  381. err = sftpUploadResumeFile(testFilePath, testFileName, testFileSize+appendDataSize, true, client)
  382. assert.Error(t, err, "file upload resume with invalid offset must fail")
  383. err = os.Remove(testFilePath)
  384. assert.NoError(t, err)
  385. err = os.Remove(localDownloadPath)
  386. assert.NoError(t, err)
  387. }
  388. _, err = httpd.RemoveUser(user, http.StatusOK)
  389. assert.NoError(t, err)
  390. err = os.RemoveAll(user.GetHomeDir())
  391. assert.NoError(t, err)
  392. }
  393. func TestDirCommands(t *testing.T) {
  394. usePubKey := false
  395. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  396. assert.NoError(t, err)
  397. // remove the home dir to test auto creation
  398. err = os.RemoveAll(user.HomeDir)
  399. assert.NoError(t, err)
  400. client, err := getSftpClient(user, usePubKey)
  401. if assert.NoError(t, err) {
  402. defer client.Close()
  403. err = client.Mkdir("test1")
  404. assert.NoError(t, err)
  405. err = client.Rename("test1", "test")
  406. assert.NoError(t, err)
  407. _, err = client.Lstat("/test1")
  408. assert.Error(t, err, "stat for renamed dir must not succeed")
  409. err = client.PosixRename("test", "test1")
  410. assert.NoError(t, err)
  411. err = client.Remove("test1")
  412. assert.NoError(t, err)
  413. err = client.Mkdir("/test/test1")
  414. assert.Error(t, err, "recursive mkdir must fail")
  415. err = client.Mkdir("/test")
  416. assert.NoError(t, err)
  417. err = client.Mkdir("/test/test1")
  418. assert.NoError(t, err)
  419. _, err = client.ReadDir("/this/dir/does/not/exist")
  420. assert.Error(t, err, "reading a missing dir must fail")
  421. err = client.RemoveDirectory("/test/test1")
  422. assert.NoError(t, err)
  423. err = client.RemoveDirectory("/test")
  424. assert.NoError(t, err)
  425. _, err = client.Lstat("/test")
  426. assert.Error(t, err, "stat for deleted dir must not succeed")
  427. err = client.RemoveDirectory("/test")
  428. assert.Error(t, err, "remove missing path must fail")
  429. }
  430. _, err = httpd.RemoveUser(user, http.StatusOK)
  431. assert.NoError(t, err)
  432. err = os.RemoveAll(user.GetHomeDir())
  433. assert.NoError(t, err)
  434. }
  435. func TestRemove(t *testing.T) {
  436. usePubKey := true
  437. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  438. assert.NoError(t, err)
  439. client, err := getSftpClient(user, usePubKey)
  440. if assert.NoError(t, err) {
  441. defer client.Close()
  442. err = client.Mkdir("test")
  443. assert.NoError(t, err)
  444. err = client.Mkdir("/test/test1")
  445. assert.NoError(t, err)
  446. testFileName := "/test_file.dat"
  447. testFilePath := filepath.Join(homeBasePath, testFileName)
  448. testFileSize := int64(65535)
  449. err = createTestFile(testFilePath, testFileSize)
  450. assert.NoError(t, err)
  451. err = sftpUploadFile(testFilePath, path.Join("/test", testFileName), testFileSize, client)
  452. assert.NoError(t, err)
  453. err = client.Remove("/test")
  454. assert.Error(t, err, "remove non empty dir must fail")
  455. err = client.RemoveDirectory(path.Join("/test", testFileName))
  456. assert.Error(t, err, "remove a file with rmdir must fail")
  457. err = client.Remove(path.Join("/test", testFileName))
  458. assert.NoError(t, err)
  459. err = client.Remove(path.Join("/test", testFileName))
  460. assert.Error(t, err, "remove missing file must fail")
  461. err = client.Remove("/test/test1")
  462. assert.NoError(t, err)
  463. err = client.Remove("/test")
  464. assert.NoError(t, err)
  465. err = os.Remove(testFilePath)
  466. assert.NoError(t, err)
  467. }
  468. _, err = httpd.RemoveUser(user, http.StatusOK)
  469. assert.NoError(t, err)
  470. err = os.RemoveAll(user.GetHomeDir())
  471. assert.NoError(t, err)
  472. }
  473. func TestLink(t *testing.T) {
  474. usePubKey := false
  475. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  476. assert.NoError(t, err)
  477. client, err := getSftpClient(user, usePubKey)
  478. if assert.NoError(t, err) {
  479. defer client.Close()
  480. testFileName := "test_file.dat"
  481. testFilePath := filepath.Join(homeBasePath, testFileName)
  482. testFileSize := int64(65535)
  483. err = createTestFile(testFilePath, testFileSize)
  484. assert.NoError(t, err)
  485. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  486. assert.NoError(t, err)
  487. err = client.Symlink(testFileName, testFileName+".link")
  488. assert.NoError(t, err)
  489. _, err = client.ReadLink(testFileName + ".link")
  490. assert.Error(t, err, "readlink is currently not implemented so must fail")
  491. err = client.Symlink(testFileName, testFileName+".link")
  492. assert.Error(t, err, "creating a symlink to an existing one must fail")
  493. err = client.Link(testFileName, testFileName+".hlink")
  494. assert.Error(t, err, "hard link is not supported and must fail")
  495. err = client.Remove(testFileName + ".link")
  496. assert.NoError(t, err)
  497. err = client.Remove(testFileName)
  498. assert.NoError(t, err)
  499. err = os.Remove(testFilePath)
  500. assert.NoError(t, err)
  501. }
  502. _, err = httpd.RemoveUser(user, http.StatusOK)
  503. assert.NoError(t, err)
  504. err = os.RemoveAll(user.GetHomeDir())
  505. assert.NoError(t, err)
  506. }
  507. func TestStat(t *testing.T) {
  508. usePubKey := false
  509. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  510. assert.NoError(t, err)
  511. client, err := getSftpClient(user, usePubKey)
  512. if assert.NoError(t, err) {
  513. defer client.Close()
  514. testFileName := "test_file.dat"
  515. testFilePath := filepath.Join(homeBasePath, testFileName)
  516. testFileSize := int64(65535)
  517. err = createTestFile(testFilePath, testFileSize)
  518. assert.NoError(t, err)
  519. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  520. assert.NoError(t, err)
  521. _, err := client.Lstat(testFileName)
  522. assert.NoError(t, err)
  523. // mode 0666 and 0444 works on Windows too
  524. newPerm := os.FileMode(0666)
  525. err = client.Chmod(testFileName, newPerm)
  526. assert.NoError(t, err)
  527. newFi, err := client.Lstat(testFileName)
  528. assert.NoError(t, err)
  529. assert.Equal(t, newPerm, newFi.Mode().Perm())
  530. newPerm = os.FileMode(0444)
  531. err = client.Chmod(testFileName, newPerm)
  532. assert.NoError(t, err)
  533. newFi, err = client.Lstat(testFileName)
  534. assert.NoError(t, err)
  535. assert.Equal(t, newPerm, newFi.Mode().Perm())
  536. _, err = client.ReadLink(testFileName)
  537. assert.Error(t, err, "readlink is not supported and must fail")
  538. err = client.Truncate(testFileName, 0)
  539. assert.NoError(t, err)
  540. err = os.Remove(testFilePath)
  541. assert.NoError(t, err)
  542. }
  543. _, err = httpd.RemoveUser(user, http.StatusOK)
  544. assert.NoError(t, err)
  545. err = os.RemoveAll(user.GetHomeDir())
  546. assert.NoError(t, err)
  547. }
  548. func TestStatChownChmod(t *testing.T) {
  549. if runtime.GOOS == osWindows {
  550. t.Skip("chown is not supported on Windows, chmod is partially supported")
  551. }
  552. usePubKey := true
  553. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  554. assert.NoError(t, err)
  555. client, err := getSftpClient(user, usePubKey)
  556. if assert.NoError(t, err) {
  557. defer client.Close()
  558. testFileName := "test_file.dat"
  559. testFilePath := filepath.Join(homeBasePath, testFileName)
  560. testFileSize := int64(65535)
  561. err = createTestFile(testFilePath, testFileSize)
  562. assert.NoError(t, err)
  563. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  564. assert.NoError(t, err)
  565. err = client.Chown(testFileName, os.Getuid(), os.Getgid())
  566. assert.NoError(t, err)
  567. newPerm := os.FileMode(0600)
  568. err = client.Chmod(testFileName, newPerm)
  569. assert.NoError(t, err)
  570. newFi, err := client.Lstat(testFileName)
  571. assert.NoError(t, err)
  572. assert.Equal(t, newPerm, newFi.Mode().Perm())
  573. err = client.Remove(testFileName)
  574. assert.NoError(t, err)
  575. err = client.Chmod(testFileName, newPerm)
  576. assert.EqualError(t, err, os.ErrNotExist.Error())
  577. err = client.Chown(testFileName, os.Getuid(), os.Getgid())
  578. assert.EqualError(t, err, os.ErrNotExist.Error())
  579. err = os.Remove(testFilePath)
  580. assert.NoError(t, err)
  581. }
  582. _, err = httpd.RemoveUser(user, http.StatusOK)
  583. assert.NoError(t, err)
  584. err = os.RemoveAll(user.GetHomeDir())
  585. assert.NoError(t, err)
  586. }
  587. func TestChtimes(t *testing.T) {
  588. usePubKey := false
  589. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  590. assert.NoError(t, err)
  591. client, err := getSftpClient(user, usePubKey)
  592. if assert.NoError(t, err) {
  593. defer client.Close()
  594. testFileName := "test_file.dat"
  595. testFilePath := filepath.Join(homeBasePath, testFileName)
  596. testFileSize := int64(65535)
  597. testDir := "test"
  598. err = createTestFile(testFilePath, testFileSize)
  599. assert.NoError(t, err)
  600. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  601. assert.NoError(t, err)
  602. acmodTime := time.Now()
  603. err = client.Chtimes(testFileName, acmodTime, acmodTime)
  604. assert.NoError(t, err)
  605. newFi, err := client.Lstat(testFileName)
  606. assert.NoError(t, err)
  607. diff := math.Abs(newFi.ModTime().Sub(acmodTime).Seconds())
  608. assert.LessOrEqual(t, diff, float64(1))
  609. err = client.Chtimes("invalidFile", acmodTime, acmodTime)
  610. assert.EqualError(t, err, os.ErrNotExist.Error())
  611. err = client.Mkdir(testDir)
  612. assert.NoError(t, err)
  613. err = client.Chtimes(testDir, acmodTime, acmodTime)
  614. assert.NoError(t, err)
  615. newFi, err = client.Lstat(testDir)
  616. assert.NoError(t, err)
  617. diff = math.Abs(newFi.ModTime().Sub(acmodTime).Seconds())
  618. assert.LessOrEqual(t, diff, float64(1))
  619. err = os.Remove(testFilePath)
  620. assert.NoError(t, err)
  621. }
  622. _, err = httpd.RemoveUser(user, http.StatusOK)
  623. assert.NoError(t, err)
  624. err = os.RemoveAll(user.GetHomeDir())
  625. assert.NoError(t, err)
  626. }
  627. // basic tests to verify virtual chroot, should be improved to cover more cases ...
  628. func TestEscapeHomeDir(t *testing.T) {
  629. usePubKey := true
  630. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  631. assert.NoError(t, err)
  632. client, err := getSftpClient(user, usePubKey)
  633. if assert.NoError(t, err) {
  634. defer client.Close()
  635. assert.NoError(t, checkBasicSFTP(client))
  636. testDir := "testDir" //nolint:goconst
  637. linkPath := filepath.Join(homeBasePath, defaultUsername, testDir)
  638. err = os.Symlink(homeBasePath, linkPath)
  639. assert.NoError(t, err)
  640. _, err = client.ReadDir(testDir)
  641. assert.Error(t, err, "reading a symbolic link outside home dir should not succeeded")
  642. err = os.Remove(linkPath)
  643. assert.NoError(t, err)
  644. testFileName := "test_file.dat"
  645. testFilePath := filepath.Join(homeBasePath, testFileName)
  646. testFileSize := int64(65535)
  647. err = createTestFile(testFilePath, testFileSize)
  648. assert.NoError(t, err)
  649. remoteDestPath := path.Join("..", "..", testFileName)
  650. err = sftpUploadFile(testFilePath, remoteDestPath, testFileSize, client)
  651. assert.NoError(t, err)
  652. _, err = client.Lstat(testFileName)
  653. assert.NoError(t, err)
  654. err = client.Remove(testFileName)
  655. assert.NoError(t, err)
  656. linkPath = filepath.Join(homeBasePath, defaultUsername, testFileName)
  657. err = os.Symlink(homeBasePath, linkPath)
  658. assert.NoError(t, err)
  659. err = sftpDownloadFile(testFileName, testFilePath, 0, client)
  660. assert.Error(t, err, "download file outside home dir must fail")
  661. err = sftpUploadFile(testFilePath, remoteDestPath, testFileSize, client)
  662. assert.Error(t, err, "overwrite a file outside home dir must fail")
  663. err = client.Chmod(remoteDestPath, 0644)
  664. assert.Error(t, err, "setstat on a file outside home dir must fail")
  665. err = os.Remove(linkPath)
  666. assert.NoError(t, err)
  667. err = os.Remove(testFilePath)
  668. assert.NoError(t, err)
  669. }
  670. _, err = httpd.RemoveUser(user, http.StatusOK)
  671. assert.NoError(t, err)
  672. err = os.RemoveAll(user.GetHomeDir())
  673. assert.NoError(t, err)
  674. }
  675. func TestHomeSpecialChars(t *testing.T) {
  676. usePubKey := true
  677. u := getTestUser(usePubKey)
  678. u.HomeDir = filepath.Join(homeBasePath, "abc açà#&%lk")
  679. user, _, err := httpd.AddUser(u, http.StatusOK)
  680. assert.NoError(t, err)
  681. client, err := getSftpClient(user, usePubKey)
  682. if assert.NoError(t, err) {
  683. defer client.Close()
  684. assert.NoError(t, checkBasicSFTP(client))
  685. testFileName := "test_file.dat"
  686. testFilePath := filepath.Join(homeBasePath, testFileName)
  687. testFileSize := int64(65535)
  688. err = createTestFile(testFilePath, testFileSize)
  689. assert.NoError(t, err)
  690. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  691. assert.NoError(t, err)
  692. files, err := client.ReadDir(".")
  693. assert.NoError(t, err)
  694. assert.Equal(t, 1, len(files))
  695. err = client.Remove(testFileName)
  696. assert.NoError(t, err)
  697. err = os.Remove(testFilePath)
  698. assert.NoError(t, err)
  699. }
  700. _, err = httpd.RemoveUser(user, http.StatusOK)
  701. assert.NoError(t, err)
  702. err = os.RemoveAll(user.GetHomeDir())
  703. assert.NoError(t, err)
  704. }
  705. func TestLogin(t *testing.T) {
  706. u := getTestUser(false)
  707. u.PublicKeys = []string{testPubKey}
  708. user, _, err := httpd.AddUser(u, http.StatusOK)
  709. assert.NoError(t, err)
  710. client, err := getSftpClient(user, false)
  711. if assert.NoError(t, err) {
  712. defer client.Close()
  713. assert.NoError(t, checkBasicSFTP(client))
  714. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  715. assert.NoError(t, err)
  716. assert.Greater(t, user.LastLogin, int64(0), "last login must be updated after a successful login: %v", user.LastLogin)
  717. }
  718. client, err = getSftpClient(user, true)
  719. if assert.NoError(t, err) {
  720. defer client.Close()
  721. assert.NoError(t, checkBasicSFTP(client))
  722. }
  723. user.Password = "invalid password"
  724. client, err = getSftpClient(user, false)
  725. if !assert.Error(t, err, "login with invalid password must fail") {
  726. client.Close()
  727. }
  728. // testPubKey1 is not authorized
  729. user.PublicKeys = []string{testPubKey1}
  730. user.Password = ""
  731. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  732. assert.NoError(t, err)
  733. client, err = getSftpClient(user, true)
  734. if !assert.Error(t, err, "login with invalid public key must fail") {
  735. defer client.Close()
  736. }
  737. // login a user with multiple public keys, only the second one is valid
  738. user.PublicKeys = []string{testPubKey1, testPubKey}
  739. user.Password = ""
  740. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  741. assert.NoError(t, err)
  742. client, err = getSftpClient(user, true)
  743. if assert.NoError(t, err) {
  744. defer client.Close()
  745. assert.NoError(t, checkBasicSFTP(client))
  746. }
  747. _, err = httpd.RemoveUser(user, http.StatusOK)
  748. assert.NoError(t, err)
  749. err = os.RemoveAll(user.GetHomeDir())
  750. assert.NoError(t, err)
  751. }
  752. func TestLoginUserCert(t *testing.T) {
  753. u := getTestUser(true)
  754. u.PublicKeys = []string{testCertValid, testCertUntrustedCA, testHostCert, testCertOtherSourceAddress, testCertExpired}
  755. user, _, err := httpd.AddUser(u, http.StatusOK)
  756. assert.NoError(t, err)
  757. // try login using a cert signed from a trusted CA
  758. signer, err := getSignerForUserCert([]byte(testCertValid))
  759. assert.NoError(t, err)
  760. client, err := getCustomAuthSftpClient(user, []ssh.AuthMethod{ssh.PublicKeys(signer)})
  761. if assert.NoError(t, err) {
  762. defer client.Close()
  763. assert.NoError(t, checkBasicSFTP(client))
  764. }
  765. // try login using a cert signed from an untrusted CA
  766. signer, err = getSignerForUserCert([]byte(testCertUntrustedCA))
  767. assert.NoError(t, err)
  768. client, err = getCustomAuthSftpClient(user, []ssh.AuthMethod{ssh.PublicKeys(signer)})
  769. if !assert.Error(t, err) {
  770. client.Close()
  771. }
  772. // try login using an host certificate instead of an user certificate
  773. signer, err = getSignerForUserCert([]byte(testHostCert))
  774. assert.NoError(t, err)
  775. client, err = getCustomAuthSftpClient(user, []ssh.AuthMethod{ssh.PublicKeys(signer)})
  776. if !assert.Error(t, err) {
  777. client.Close()
  778. }
  779. // try login using a user certificate with an authorized source address different from localhost
  780. signer, err = getSignerForUserCert([]byte(testCertOtherSourceAddress))
  781. assert.NoError(t, err)
  782. client, err = getCustomAuthSftpClient(user, []ssh.AuthMethod{ssh.PublicKeys(signer)})
  783. if !assert.Error(t, err) {
  784. client.Close()
  785. }
  786. // try login using an expired certificate
  787. signer, err = getSignerForUserCert([]byte(testCertExpired))
  788. assert.NoError(t, err)
  789. client, err = getCustomAuthSftpClient(user, []ssh.AuthMethod{ssh.PublicKeys(signer)})
  790. if !assert.Error(t, err) {
  791. client.Close()
  792. }
  793. _, err = httpd.RemoveUser(user, http.StatusOK)
  794. assert.NoError(t, err)
  795. err = os.RemoveAll(user.GetHomeDir())
  796. assert.NoError(t, err)
  797. // now login with a username not in the set of valid principals for the given certificate
  798. u.Username += "1"
  799. user, _, err = httpd.AddUser(u, http.StatusOK)
  800. assert.NoError(t, err)
  801. signer, err = getSignerForUserCert([]byte(testCertValid))
  802. assert.NoError(t, err)
  803. client, err = getCustomAuthSftpClient(user, []ssh.AuthMethod{ssh.PublicKeys(signer)})
  804. if !assert.Error(t, err) {
  805. client.Close()
  806. }
  807. _, err = httpd.RemoveUser(user, http.StatusOK)
  808. assert.NoError(t, err)
  809. err = os.RemoveAll(user.GetHomeDir())
  810. assert.NoError(t, err)
  811. }
  812. func TestMultiStepLoginKeyAndPwd(t *testing.T) {
  813. u := getTestUser(true)
  814. u.Password = defaultPassword
  815. u.Filters.DeniedLoginMethods = append(u.Filters.DeniedLoginMethods, []string{
  816. dataprovider.SSHLoginMethodKeyAndKeyboardInt,
  817. dataprovider.SSHLoginMethodPublicKey,
  818. dataprovider.SSHLoginMethodPassword,
  819. dataprovider.SSHLoginMethodKeyboardInteractive,
  820. }...)
  821. user, _, err := httpd.AddUser(u, http.StatusOK)
  822. assert.NoError(t, err)
  823. client, err := getSftpClient(user, true)
  824. if !assert.Error(t, err, "login with public key is disallowed and must fail") {
  825. client.Close()
  826. }
  827. client, err = getSftpClient(user, true)
  828. if !assert.Error(t, err, "login with password is disallowed and must fail") {
  829. client.Close()
  830. }
  831. signer, _ := ssh.ParsePrivateKey([]byte(testPrivateKey))
  832. authMethods := []ssh.AuthMethod{
  833. ssh.PublicKeys(signer),
  834. ssh.Password(defaultPassword),
  835. }
  836. client, err = getCustomAuthSftpClient(user, authMethods)
  837. if assert.NoError(t, err) {
  838. defer client.Close()
  839. assert.NoError(t, checkBasicSFTP(client))
  840. }
  841. authMethods = []ssh.AuthMethod{
  842. ssh.Password(defaultPassword),
  843. ssh.PublicKeys(signer),
  844. }
  845. _, err = getCustomAuthSftpClient(user, authMethods)
  846. assert.Error(t, err, "multi step auth login with wrong order must fail")
  847. _, err = httpd.RemoveUser(user, http.StatusOK)
  848. assert.NoError(t, err)
  849. err = os.RemoveAll(user.GetHomeDir())
  850. assert.NoError(t, err)
  851. }
  852. func TestMultiStepLoginKeyAndKeyInt(t *testing.T) {
  853. if runtime.GOOS == osWindows {
  854. t.Skip("this test is not available on Windows")
  855. }
  856. u := getTestUser(true)
  857. u.Password = defaultPassword
  858. u.Filters.DeniedLoginMethods = append(u.Filters.DeniedLoginMethods, []string{
  859. dataprovider.SSHLoginMethodKeyAndPassword,
  860. dataprovider.SSHLoginMethodPublicKey,
  861. dataprovider.SSHLoginMethodPassword,
  862. dataprovider.SSHLoginMethodKeyboardInteractive,
  863. }...)
  864. user, _, err := httpd.AddUser(u, http.StatusOK)
  865. assert.NoError(t, err)
  866. err = ioutil.WriteFile(keyIntAuthPath, getKeyboardInteractiveScriptContent([]string{"1", "2"}, 0, false, 1), 0755)
  867. assert.NoError(t, err)
  868. client, err := getSftpClient(user, true)
  869. if !assert.Error(t, err, "login with public key is disallowed and must fail") {
  870. client.Close()
  871. }
  872. signer, _ := ssh.ParsePrivateKey([]byte(testPrivateKey))
  873. authMethods := []ssh.AuthMethod{
  874. ssh.PublicKeys(signer),
  875. ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) ([]string, error) {
  876. return []string{"1", "2"}, nil
  877. }),
  878. }
  879. client, err = getCustomAuthSftpClient(user, authMethods)
  880. if assert.NoError(t, err) {
  881. defer client.Close()
  882. assert.NoError(t, checkBasicSFTP(client))
  883. }
  884. authMethods = []ssh.AuthMethod{
  885. ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) ([]string, error) {
  886. return []string{"1", "2"}, nil
  887. }),
  888. ssh.PublicKeys(signer),
  889. }
  890. _, err = getCustomAuthSftpClient(user, authMethods)
  891. assert.Error(t, err, "multi step auth login with wrong order must fail")
  892. authMethods = []ssh.AuthMethod{
  893. ssh.PublicKeys(signer),
  894. ssh.Password(defaultPassword),
  895. }
  896. _, err = getCustomAuthSftpClient(user, authMethods)
  897. assert.Error(t, err, "multi step auth login with wrong method must fail")
  898. _, err = httpd.RemoveUser(user, http.StatusOK)
  899. assert.NoError(t, err)
  900. err = os.RemoveAll(user.GetHomeDir())
  901. assert.NoError(t, err)
  902. }
  903. func TestMultiStepLoginCertAndPwd(t *testing.T) {
  904. u := getTestUser(true)
  905. u.Password = defaultPassword
  906. u.PublicKeys = []string{testCertValid, testCertOtherSourceAddress}
  907. u.Filters.DeniedLoginMethods = append(u.Filters.DeniedLoginMethods, []string{
  908. dataprovider.SSHLoginMethodKeyAndKeyboardInt,
  909. dataprovider.SSHLoginMethodPublicKey,
  910. dataprovider.SSHLoginMethodPassword,
  911. dataprovider.SSHLoginMethodKeyboardInteractive,
  912. }...)
  913. user, _, err := httpd.AddUser(u, http.StatusOK)
  914. assert.NoError(t, err)
  915. signer, err := getSignerForUserCert([]byte(testCertValid))
  916. assert.NoError(t, err)
  917. authMethods := []ssh.AuthMethod{
  918. ssh.PublicKeys(signer),
  919. ssh.Password(defaultPassword),
  920. }
  921. client, err := getCustomAuthSftpClient(user, authMethods)
  922. if assert.NoError(t, err) {
  923. defer client.Close()
  924. assert.NoError(t, checkBasicSFTP(client))
  925. }
  926. signer, err = getSignerForUserCert([]byte(testCertOtherSourceAddress))
  927. assert.NoError(t, err)
  928. authMethods = []ssh.AuthMethod{
  929. ssh.PublicKeys(signer),
  930. ssh.Password(defaultPassword),
  931. }
  932. client, err = getCustomAuthSftpClient(user, authMethods)
  933. if !assert.Error(t, err) {
  934. client.Close()
  935. }
  936. _, err = httpd.RemoveUser(user, http.StatusOK)
  937. assert.NoError(t, err)
  938. err = os.RemoveAll(user.GetHomeDir())
  939. assert.NoError(t, err)
  940. }
  941. func TestLoginUserStatus(t *testing.T) {
  942. usePubKey := true
  943. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  944. assert.NoError(t, err)
  945. client, err := getSftpClient(user, usePubKey)
  946. if assert.NoError(t, err) {
  947. defer client.Close()
  948. assert.NoError(t, checkBasicSFTP(client))
  949. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  950. assert.NoError(t, err)
  951. assert.Greater(t, user.LastLogin, int64(0), "last login must be updated after a successful login: %v", user.LastLogin)
  952. }
  953. user.Status = 0
  954. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  955. assert.NoError(t, err)
  956. client, err = getSftpClient(user, usePubKey)
  957. if !assert.Error(t, err, "login for a disabled user must fail") {
  958. client.Close()
  959. }
  960. _, err = httpd.RemoveUser(user, http.StatusOK)
  961. assert.NoError(t, err)
  962. err = os.RemoveAll(user.GetHomeDir())
  963. assert.NoError(t, err)
  964. }
  965. func TestLoginUserExpiration(t *testing.T) {
  966. usePubKey := true
  967. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  968. assert.NoError(t, err)
  969. client, err := getSftpClient(user, usePubKey)
  970. if assert.NoError(t, err) {
  971. defer client.Close()
  972. assert.NoError(t, checkBasicSFTP(client))
  973. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  974. assert.NoError(t, err)
  975. assert.Greater(t, user.LastLogin, int64(0), "last login must be updated after a successful login: %v", user.LastLogin)
  976. }
  977. user.ExpirationDate = utils.GetTimeAsMsSinceEpoch(time.Now()) - 120000
  978. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  979. assert.NoError(t, err)
  980. client, err = getSftpClient(user, usePubKey)
  981. if !assert.Error(t, err, "login for an expired user must fail") {
  982. client.Close()
  983. }
  984. user.ExpirationDate = utils.GetTimeAsMsSinceEpoch(time.Now()) + 120000
  985. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  986. assert.NoError(t, err)
  987. client, err = getSftpClient(user, usePubKey)
  988. if assert.NoError(t, err) {
  989. defer client.Close()
  990. assert.NoError(t, checkBasicSFTP(client))
  991. }
  992. _, err = httpd.RemoveUser(user, http.StatusOK)
  993. assert.NoError(t, err)
  994. err = os.RemoveAll(user.GetHomeDir())
  995. assert.NoError(t, err)
  996. }
  997. func TestLoginInvalidFs(t *testing.T) {
  998. usePubKey := true
  999. u := getTestUser(usePubKey)
  1000. u.FsConfig.Provider = 2
  1001. u.FsConfig.GCSConfig.Bucket = "test"
  1002. u.FsConfig.GCSConfig.Credentials = base64.StdEncoding.EncodeToString([]byte("invalid JSON for credentials"))
  1003. user, _, err := httpd.AddUser(u, http.StatusOK)
  1004. assert.NoError(t, err)
  1005. // now remove the credentials file so the filesystem creation will fail
  1006. providerConf := config.GetProviderConf()
  1007. credentialsFile := filepath.Join(providerConf.CredentialsPath, fmt.Sprintf("%v_gcs_credentials.json", u.Username))
  1008. if !filepath.IsAbs(credentialsFile) {
  1009. credentialsFile = filepath.Join(configDir, credentialsFile)
  1010. }
  1011. err = os.Remove(credentialsFile)
  1012. assert.NoError(t, err)
  1013. client, err := getSftpClient(user, usePubKey)
  1014. if !assert.Error(t, err, "login must fail, the user has an invalid filesystem config") {
  1015. client.Close()
  1016. }
  1017. _, err = httpd.RemoveUser(user, http.StatusOK)
  1018. assert.NoError(t, err)
  1019. err = os.RemoveAll(user.GetHomeDir())
  1020. assert.NoError(t, err)
  1021. }
  1022. func TestDeniedLoginMethods(t *testing.T) {
  1023. u := getTestUser(true)
  1024. u.Filters.DeniedLoginMethods = []string{dataprovider.SSHLoginMethodPublicKey, dataprovider.SSHLoginMethodPassword}
  1025. user, _, err := httpd.AddUser(u, http.StatusOK)
  1026. assert.NoError(t, err)
  1027. client, err := getSftpClient(user, true)
  1028. if !assert.Error(t, err, "public key login is disabled, authentication must fail") {
  1029. client.Close()
  1030. }
  1031. user.Filters.DeniedLoginMethods = []string{dataprovider.SSHLoginMethodKeyboardInteractive, dataprovider.SSHLoginMethodPassword}
  1032. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  1033. assert.NoError(t, err)
  1034. client, err = getSftpClient(user, true)
  1035. if assert.NoError(t, err) {
  1036. defer client.Close()
  1037. assert.NoError(t, checkBasicSFTP(client))
  1038. }
  1039. user.Password = defaultPassword
  1040. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  1041. assert.NoError(t, err)
  1042. client, err = getSftpClient(user, false)
  1043. if !assert.Error(t, err, "password login is disabled, authentication must fail") {
  1044. client.Close()
  1045. }
  1046. user.Filters.DeniedLoginMethods = []string{dataprovider.SSHLoginMethodKeyboardInteractive, dataprovider.SSHLoginMethodPublicKey}
  1047. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  1048. assert.NoError(t, err)
  1049. client, err = getSftpClient(user, false)
  1050. if assert.NoError(t, err) {
  1051. defer client.Close()
  1052. assert.NoError(t, checkBasicSFTP(client))
  1053. }
  1054. _, err = httpd.RemoveUser(user, http.StatusOK)
  1055. assert.NoError(t, err)
  1056. err = os.RemoveAll(user.GetHomeDir())
  1057. assert.NoError(t, err)
  1058. }
  1059. func TestLoginWithIPFilters(t *testing.T) {
  1060. usePubKey := true
  1061. u := getTestUser(usePubKey)
  1062. u.Filters.DeniedIP = []string{"192.167.0.0/24", "172.18.0.0/16"}
  1063. u.Filters.AllowedIP = []string{}
  1064. user, _, err := httpd.AddUser(u, http.StatusOK)
  1065. assert.NoError(t, err)
  1066. client, err := getSftpClient(user, usePubKey)
  1067. if assert.NoError(t, err) {
  1068. defer client.Close()
  1069. assert.NoError(t, checkBasicSFTP(client))
  1070. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  1071. assert.NoError(t, err)
  1072. assert.Greater(t, user.LastLogin, int64(0), "last login must be updated after a successful login: %v", user.LastLogin)
  1073. }
  1074. user.Filters.AllowedIP = []string{"127.0.0.0/8"}
  1075. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  1076. assert.NoError(t, err)
  1077. client, err = getSftpClient(user, usePubKey)
  1078. if assert.NoError(t, err) {
  1079. defer client.Close()
  1080. assert.NoError(t, checkBasicSFTP(client))
  1081. }
  1082. user.Filters.AllowedIP = []string{"172.19.0.0/16"}
  1083. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  1084. assert.NoError(t, err)
  1085. client, err = getSftpClient(user, usePubKey)
  1086. if !assert.Error(t, err, "login from an not allowed IP must fail") {
  1087. client.Close()
  1088. }
  1089. _, err = httpd.RemoveUser(user, http.StatusOK)
  1090. assert.NoError(t, err)
  1091. err = os.RemoveAll(user.GetHomeDir())
  1092. assert.NoError(t, err)
  1093. }
  1094. func TestLoginAfterUserUpdateEmptyPwd(t *testing.T) {
  1095. usePubKey := false
  1096. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  1097. assert.NoError(t, err)
  1098. user.Password = ""
  1099. user.PublicKeys = []string{}
  1100. // password and public key should remain unchanged
  1101. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  1102. assert.NoError(t, err)
  1103. client, err := getSftpClient(user, usePubKey)
  1104. if assert.NoError(t, err) {
  1105. defer client.Close()
  1106. assert.NoError(t, checkBasicSFTP(client))
  1107. }
  1108. _, err = httpd.RemoveUser(user, http.StatusOK)
  1109. assert.NoError(t, err)
  1110. err = os.RemoveAll(user.GetHomeDir())
  1111. assert.NoError(t, err)
  1112. }
  1113. func TestLoginAfterUserUpdateEmptyPubKey(t *testing.T) {
  1114. usePubKey := true
  1115. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  1116. assert.NoError(t, err)
  1117. user.Password = ""
  1118. user.PublicKeys = []string{}
  1119. // password and public key should remain unchanged
  1120. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  1121. assert.NoError(t, err)
  1122. client, err := getSftpClient(user, usePubKey)
  1123. if assert.NoError(t, err) {
  1124. defer client.Close()
  1125. assert.NoError(t, checkBasicSFTP(client))
  1126. }
  1127. _, err = httpd.RemoveUser(user, http.StatusOK)
  1128. assert.NoError(t, err)
  1129. err = os.RemoveAll(user.GetHomeDir())
  1130. assert.NoError(t, err)
  1131. }
  1132. func TestLoginKeyboardInteractiveAuth(t *testing.T) {
  1133. if runtime.GOOS == osWindows {
  1134. t.Skip("this test is not available on Windows")
  1135. }
  1136. user, _, err := httpd.AddUser(getTestUser(false), http.StatusOK)
  1137. assert.NoError(t, err)
  1138. err = ioutil.WriteFile(keyIntAuthPath, getKeyboardInteractiveScriptContent([]string{"1", "2"}, 0, false, 1), 0755)
  1139. assert.NoError(t, err)
  1140. client, err := getKeyboardInteractiveSftpClient(user, []string{"1", "2"})
  1141. if assert.NoError(t, err) {
  1142. defer client.Close()
  1143. assert.NoError(t, checkBasicSFTP(client))
  1144. }
  1145. user.Status = 0
  1146. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  1147. assert.NoError(t, err)
  1148. client, err = getKeyboardInteractiveSftpClient(user, []string{"1", "2"})
  1149. if !assert.Error(t, err, "keyboard interactive auth must fail the user is disabled") {
  1150. client.Close()
  1151. }
  1152. user.Status = 1
  1153. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  1154. assert.NoError(t, err)
  1155. err = ioutil.WriteFile(keyIntAuthPath, getKeyboardInteractiveScriptContent([]string{"1", "2"}, 0, false, -1), 0755)
  1156. assert.NoError(t, err)
  1157. client, err = getKeyboardInteractiveSftpClient(user, []string{"1", "2"})
  1158. if !assert.Error(t, err, "keyboard interactive auth must fail the script returned -1") {
  1159. client.Close()
  1160. }
  1161. err = ioutil.WriteFile(keyIntAuthPath, getKeyboardInteractiveScriptContent([]string{"1", "2"}, 0, true, 1), 0755)
  1162. assert.NoError(t, err)
  1163. client, err = getKeyboardInteractiveSftpClient(user, []string{"1", "2"})
  1164. if !assert.Error(t, err, "keyboard interactive auth must fail the script returned bad json") {
  1165. client.Close()
  1166. }
  1167. err = ioutil.WriteFile(keyIntAuthPath, getKeyboardInteractiveScriptContent([]string{"1", "2"}, 5, true, 1), 0755)
  1168. assert.NoError(t, err)
  1169. client, err = getKeyboardInteractiveSftpClient(user, []string{"1", "2"})
  1170. if !assert.Error(t, err, "keyboard interactive auth must fail the script returned bad json") {
  1171. client.Close()
  1172. }
  1173. _, err = httpd.RemoveUser(user, http.StatusOK)
  1174. assert.NoError(t, err)
  1175. err = os.RemoveAll(user.GetHomeDir())
  1176. assert.NoError(t, err)
  1177. }
  1178. func TestPreLoginScript(t *testing.T) {
  1179. if runtime.GOOS == osWindows {
  1180. t.Skip("this test is not available on Windows")
  1181. }
  1182. usePubKey := true
  1183. u := getTestUser(usePubKey)
  1184. dataProvider := dataprovider.GetProvider()
  1185. err := dataprovider.Close(dataProvider)
  1186. assert.NoError(t, err)
  1187. err = config.LoadConfig(configDir, "")
  1188. assert.NoError(t, err)
  1189. providerConf := config.GetProviderConf()
  1190. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), 0755)
  1191. assert.NoError(t, err)
  1192. providerConf.PreLoginHook = preLoginPath
  1193. err = dataprovider.Initialize(providerConf, configDir)
  1194. assert.NoError(t, err)
  1195. httpd.SetDataProvider(dataprovider.GetProvider())
  1196. sftpd.SetDataProvider(dataprovider.GetProvider())
  1197. user, _, err := httpd.AddUser(u, http.StatusOK)
  1198. assert.NoError(t, err)
  1199. client, err := getSftpClient(u, usePubKey)
  1200. if assert.NoError(t, err) {
  1201. defer client.Close()
  1202. assert.NoError(t, checkBasicSFTP(client))
  1203. }
  1204. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), 0755)
  1205. assert.NoError(t, err)
  1206. client, err = getSftpClient(u, usePubKey)
  1207. if !assert.Error(t, err, "pre-login script returned a non json response, login must fail") {
  1208. client.Close()
  1209. }
  1210. user.Status = 0
  1211. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), 0755)
  1212. assert.NoError(t, err)
  1213. client, err = getSftpClient(u, usePubKey)
  1214. if !assert.Error(t, err, "pre-login script returned a disabled user, login must fail") {
  1215. client.Close()
  1216. }
  1217. _, err = httpd.RemoveUser(user, http.StatusOK)
  1218. assert.NoError(t, err)
  1219. err = os.RemoveAll(user.GetHomeDir())
  1220. assert.NoError(t, err)
  1221. dataProvider = dataprovider.GetProvider()
  1222. err = dataprovider.Close(dataProvider)
  1223. assert.NoError(t, err)
  1224. err = config.LoadConfig(configDir, "")
  1225. assert.NoError(t, err)
  1226. providerConf = config.GetProviderConf()
  1227. err = dataprovider.Initialize(providerConf, configDir)
  1228. assert.NoError(t, err)
  1229. httpd.SetDataProvider(dataprovider.GetProvider())
  1230. sftpd.SetDataProvider(dataprovider.GetProvider())
  1231. err = os.Remove(preLoginPath)
  1232. assert.NoError(t, err)
  1233. }
  1234. func TestPreLoginUserCreation(t *testing.T) {
  1235. if runtime.GOOS == osWindows {
  1236. t.Skip("this test is not available on Windows")
  1237. }
  1238. usePubKey := false
  1239. u := getTestUser(usePubKey)
  1240. dataProvider := dataprovider.GetProvider()
  1241. err := dataprovider.Close(dataProvider)
  1242. assert.NoError(t, err)
  1243. err = config.LoadConfig(configDir, "")
  1244. assert.NoError(t, err)
  1245. providerConf := config.GetProviderConf()
  1246. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), 0755)
  1247. assert.NoError(t, err)
  1248. providerConf.PreLoginHook = preLoginPath
  1249. err = dataprovider.Initialize(providerConf, configDir)
  1250. assert.NoError(t, err)
  1251. httpd.SetDataProvider(dataprovider.GetProvider())
  1252. sftpd.SetDataProvider(dataprovider.GetProvider())
  1253. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  1254. assert.NoError(t, err)
  1255. assert.Equal(t, 0, len(users))
  1256. client, err := getSftpClient(u, usePubKey)
  1257. if assert.NoError(t, err) {
  1258. defer client.Close()
  1259. assert.NoError(t, checkBasicSFTP(client))
  1260. }
  1261. users, _, err = httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  1262. assert.NoError(t, err)
  1263. assert.Equal(t, 1, len(users))
  1264. user := users[0]
  1265. err = os.RemoveAll(user.GetHomeDir())
  1266. assert.NoError(t, err)
  1267. dataProvider = dataprovider.GetProvider()
  1268. err = dataprovider.Close(dataProvider)
  1269. assert.NoError(t, err)
  1270. err = config.LoadConfig(configDir, "")
  1271. assert.NoError(t, err)
  1272. providerConf = config.GetProviderConf()
  1273. err = dataprovider.Initialize(providerConf, configDir)
  1274. assert.NoError(t, err)
  1275. httpd.SetDataProvider(dataprovider.GetProvider())
  1276. sftpd.SetDataProvider(dataprovider.GetProvider())
  1277. err = os.Remove(preLoginPath)
  1278. assert.NoError(t, err)
  1279. }
  1280. func TestLoginExternalAuthPwdAndPubKey(t *testing.T) {
  1281. if runtime.GOOS == osWindows {
  1282. t.Skip("this test is not available on Windows")
  1283. }
  1284. usePubKey := true
  1285. u := getTestUser(usePubKey)
  1286. u.QuotaFiles = 1000
  1287. dataProvider := dataprovider.GetProvider()
  1288. err := dataprovider.Close(dataProvider)
  1289. assert.NoError(t, err)
  1290. err = config.LoadConfig(configDir, "")
  1291. assert.NoError(t, err)
  1292. providerConf := config.GetProviderConf()
  1293. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, false), 0755)
  1294. assert.NoError(t, err)
  1295. providerConf.ExternalAuthHook = extAuthPath
  1296. providerConf.ExternalAuthScope = 0
  1297. err = dataprovider.Initialize(providerConf, configDir)
  1298. assert.NoError(t, err)
  1299. httpd.SetDataProvider(dataprovider.GetProvider())
  1300. sftpd.SetDataProvider(dataprovider.GetProvider())
  1301. testFileSize := int64(65535)
  1302. client, err := getSftpClient(u, usePubKey)
  1303. if assert.NoError(t, err) {
  1304. defer client.Close()
  1305. testFileName := "test_file.dat"
  1306. testFilePath := filepath.Join(homeBasePath, testFileName)
  1307. err = createTestFile(testFilePath, testFileSize)
  1308. assert.NoError(t, err)
  1309. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  1310. assert.NoError(t, err)
  1311. err = os.Remove(testFilePath)
  1312. assert.NoError(t, err)
  1313. }
  1314. u.Username = defaultUsername + "1"
  1315. client, err = getSftpClient(u, usePubKey)
  1316. if !assert.Error(t, err, "external auth login with invalid user must fail") {
  1317. client.Close()
  1318. }
  1319. usePubKey = false
  1320. u = getTestUser(usePubKey)
  1321. u.PublicKeys = []string{}
  1322. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, false), 0755)
  1323. assert.NoError(t, err)
  1324. client, err = getSftpClient(u, usePubKey)
  1325. if assert.NoError(t, err) {
  1326. defer client.Close()
  1327. assert.NoError(t, checkBasicSFTP(client))
  1328. }
  1329. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  1330. assert.NoError(t, err)
  1331. assert.Equal(t, 1, len(users))
  1332. user := users[0]
  1333. assert.Equal(t, 0, len(user.PublicKeys))
  1334. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  1335. assert.Equal(t, 1, user.UsedQuotaFiles)
  1336. _, err = httpd.RemoveUser(user, http.StatusOK)
  1337. assert.NoError(t, err)
  1338. err = os.RemoveAll(user.GetHomeDir())
  1339. assert.NoError(t, err)
  1340. dataProvider = dataprovider.GetProvider()
  1341. err = dataprovider.Close(dataProvider)
  1342. assert.NoError(t, err)
  1343. err = config.LoadConfig(configDir, "")
  1344. assert.NoError(t, err)
  1345. providerConf = config.GetProviderConf()
  1346. err = dataprovider.Initialize(providerConf, configDir)
  1347. assert.NoError(t, err)
  1348. httpd.SetDataProvider(dataprovider.GetProvider())
  1349. sftpd.SetDataProvider(dataprovider.GetProvider())
  1350. err = os.Remove(extAuthPath)
  1351. assert.NoError(t, err)
  1352. }
  1353. func TestLoginExternalAuth(t *testing.T) {
  1354. if runtime.GOOS == osWindows {
  1355. t.Skip("this test is not available on Windows")
  1356. }
  1357. extAuthScopes := []int{1, 2}
  1358. for _, authScope := range extAuthScopes {
  1359. var usePubKey bool
  1360. if authScope == 1 {
  1361. usePubKey = false
  1362. } else {
  1363. usePubKey = true
  1364. }
  1365. u := getTestUser(usePubKey)
  1366. dataProvider := dataprovider.GetProvider()
  1367. err := dataprovider.Close(dataProvider)
  1368. assert.NoError(t, err)
  1369. err = config.LoadConfig(configDir, "")
  1370. assert.NoError(t, err)
  1371. providerConf := config.GetProviderConf()
  1372. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, false), 0755)
  1373. assert.NoError(t, err)
  1374. providerConf.ExternalAuthHook = extAuthPath
  1375. providerConf.ExternalAuthScope = authScope
  1376. err = dataprovider.Initialize(providerConf, configDir)
  1377. assert.NoError(t, err)
  1378. httpd.SetDataProvider(dataprovider.GetProvider())
  1379. sftpd.SetDataProvider(dataprovider.GetProvider())
  1380. client, err := getSftpClient(u, usePubKey)
  1381. if assert.NoError(t, err) {
  1382. defer client.Close()
  1383. assert.NoError(t, checkBasicSFTP(client))
  1384. }
  1385. u.Username = defaultUsername + "1"
  1386. client, err = getSftpClient(u, usePubKey)
  1387. if !assert.Error(t, err, "external auth login with invalid user must fail") {
  1388. client.Close()
  1389. }
  1390. usePubKey = !usePubKey
  1391. u = getTestUser(usePubKey)
  1392. client, err = getSftpClient(u, usePubKey)
  1393. if !assert.Error(t, err, "external auth login with valid user but invalid auth scope must fail") {
  1394. client.Close()
  1395. }
  1396. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  1397. assert.NoError(t, err)
  1398. assert.Equal(t, 1, len(users))
  1399. user := users[0]
  1400. _, err = httpd.RemoveUser(user, http.StatusOK)
  1401. assert.NoError(t, err)
  1402. err = os.RemoveAll(user.GetHomeDir())
  1403. assert.NoError(t, err)
  1404. dataProvider = dataprovider.GetProvider()
  1405. err = dataprovider.Close(dataProvider)
  1406. assert.NoError(t, err)
  1407. err = config.LoadConfig(configDir, "")
  1408. assert.NoError(t, err)
  1409. providerConf = config.GetProviderConf()
  1410. err = dataprovider.Initialize(providerConf, configDir)
  1411. assert.NoError(t, err)
  1412. httpd.SetDataProvider(dataprovider.GetProvider())
  1413. sftpd.SetDataProvider(dataprovider.GetProvider())
  1414. err = os.Remove(extAuthPath)
  1415. assert.NoError(t, err)
  1416. }
  1417. }
  1418. func TestLoginExternalAuthInteractive(t *testing.T) {
  1419. if runtime.GOOS == osWindows {
  1420. t.Skip("this test is not available on Windows")
  1421. }
  1422. usePubKey := false
  1423. u := getTestUser(usePubKey)
  1424. dataProvider := dataprovider.GetProvider()
  1425. err := dataprovider.Close(dataProvider)
  1426. assert.NoError(t, err)
  1427. err = config.LoadConfig(configDir, "")
  1428. assert.NoError(t, err)
  1429. providerConf := config.GetProviderConf()
  1430. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, false), 0755)
  1431. assert.NoError(t, err)
  1432. providerConf.ExternalAuthHook = extAuthPath
  1433. providerConf.ExternalAuthScope = 4
  1434. err = dataprovider.Initialize(providerConf, configDir)
  1435. assert.NoError(t, err)
  1436. httpd.SetDataProvider(dataprovider.GetProvider())
  1437. sftpd.SetDataProvider(dataprovider.GetProvider())
  1438. err = ioutil.WriteFile(keyIntAuthPath, getKeyboardInteractiveScriptContent([]string{"1", "2"}, 0, false, 1), 0755)
  1439. assert.NoError(t, err)
  1440. client, err := getKeyboardInteractiveSftpClient(u, []string{"1", "2"})
  1441. if assert.NoError(t, err) {
  1442. defer client.Close()
  1443. assert.NoError(t, checkBasicSFTP(client))
  1444. }
  1445. u.Username = defaultUsername + "1"
  1446. client, err = getKeyboardInteractiveSftpClient(u, []string{"1", "2"})
  1447. if !assert.Error(t, err, "external auth login with invalid user must fail") {
  1448. client.Close()
  1449. }
  1450. usePubKey = true
  1451. u = getTestUser(usePubKey)
  1452. client, err = getSftpClient(u, usePubKey)
  1453. if !assert.Error(t, err, "external auth login with valid user but invalid auth scope must fail") {
  1454. client.Close()
  1455. }
  1456. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  1457. assert.NoError(t, err)
  1458. assert.Equal(t, 1, len(users))
  1459. user := users[0]
  1460. _, err = httpd.RemoveUser(user, http.StatusOK)
  1461. assert.NoError(t, err)
  1462. err = os.RemoveAll(user.GetHomeDir())
  1463. assert.NoError(t, err)
  1464. dataProvider = dataprovider.GetProvider()
  1465. err = dataprovider.Close(dataProvider)
  1466. assert.NoError(t, err)
  1467. err = config.LoadConfig(configDir, "")
  1468. assert.NoError(t, err)
  1469. providerConf = config.GetProviderConf()
  1470. err = dataprovider.Initialize(providerConf, configDir)
  1471. assert.NoError(t, err)
  1472. httpd.SetDataProvider(dataprovider.GetProvider())
  1473. sftpd.SetDataProvider(dataprovider.GetProvider())
  1474. err = os.Remove(extAuthPath)
  1475. assert.NoError(t, err)
  1476. }
  1477. func TestLoginExternalAuthErrors(t *testing.T) {
  1478. if runtime.GOOS == osWindows {
  1479. t.Skip("this test is not available on Windows")
  1480. }
  1481. usePubKey := true
  1482. u := getTestUser(usePubKey)
  1483. dataProvider := dataprovider.GetProvider()
  1484. err := dataprovider.Close(dataProvider)
  1485. assert.NoError(t, err)
  1486. err = config.LoadConfig(configDir, "")
  1487. assert.NoError(t, err)
  1488. providerConf := config.GetProviderConf()
  1489. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, true), 0755)
  1490. assert.NoError(t, err)
  1491. providerConf.ExternalAuthHook = extAuthPath
  1492. providerConf.ExternalAuthScope = 0
  1493. err = dataprovider.Initialize(providerConf, configDir)
  1494. assert.NoError(t, err)
  1495. httpd.SetDataProvider(dataprovider.GetProvider())
  1496. sftpd.SetDataProvider(dataprovider.GetProvider())
  1497. client, err := getSftpClient(u, usePubKey)
  1498. if !assert.Error(t, err, "login must fail, external auth returns a non json response") {
  1499. client.Close()
  1500. }
  1501. usePubKey = false
  1502. u = getTestUser(usePubKey)
  1503. client, err = getSftpClient(u, usePubKey)
  1504. if !assert.Error(t, err, "login must fail, external auth returns a non json response") {
  1505. client.Close()
  1506. }
  1507. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  1508. assert.NoError(t, err)
  1509. assert.Equal(t, 0, len(users))
  1510. dataProvider = dataprovider.GetProvider()
  1511. err = dataprovider.Close(dataProvider)
  1512. assert.NoError(t, err)
  1513. err = config.LoadConfig(configDir, "")
  1514. assert.NoError(t, err)
  1515. providerConf = config.GetProviderConf()
  1516. err = dataprovider.Initialize(providerConf, configDir)
  1517. assert.NoError(t, err)
  1518. httpd.SetDataProvider(dataprovider.GetProvider())
  1519. sftpd.SetDataProvider(dataprovider.GetProvider())
  1520. err = os.Remove(extAuthPath)
  1521. assert.NoError(t, err)
  1522. }
  1523. func TestQuotaDisabledError(t *testing.T) {
  1524. dataProvider := dataprovider.GetProvider()
  1525. err := dataprovider.Close(dataProvider)
  1526. assert.NoError(t, err)
  1527. err = config.LoadConfig(configDir, "")
  1528. assert.NoError(t, err)
  1529. providerConf := config.GetProviderConf()
  1530. providerConf.TrackQuota = 0
  1531. err = dataprovider.Initialize(providerConf, configDir)
  1532. assert.NoError(t, err)
  1533. httpd.SetDataProvider(dataprovider.GetProvider())
  1534. sftpd.SetDataProvider(dataprovider.GetProvider())
  1535. usePubKey := false
  1536. u := getTestUser(usePubKey)
  1537. u.QuotaFiles = 10
  1538. user, _, err := httpd.AddUser(u, http.StatusOK)
  1539. assert.NoError(t, err)
  1540. client, err := getSftpClient(user, usePubKey)
  1541. if assert.NoError(t, err) {
  1542. defer client.Close()
  1543. testFileName := "test_file.dat"
  1544. testFilePath := filepath.Join(homeBasePath, testFileName)
  1545. testFileSize := int64(65535)
  1546. err = createTestFile(testFilePath, testFileSize)
  1547. assert.NoError(t, err)
  1548. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  1549. assert.NoError(t, err)
  1550. err = os.Remove(testFilePath)
  1551. assert.NoError(t, err)
  1552. }
  1553. _, err = httpd.RemoveUser(user, http.StatusOK)
  1554. assert.NoError(t, err)
  1555. err = os.RemoveAll(user.GetHomeDir())
  1556. assert.NoError(t, err)
  1557. dataProvider = dataprovider.GetProvider()
  1558. err = dataprovider.Close(dataProvider)
  1559. assert.NoError(t, err)
  1560. err = config.LoadConfig(configDir, "")
  1561. assert.NoError(t, err)
  1562. providerConf = config.GetProviderConf()
  1563. err = dataprovider.Initialize(providerConf, configDir)
  1564. assert.NoError(t, err)
  1565. httpd.SetDataProvider(dataprovider.GetProvider())
  1566. sftpd.SetDataProvider(dataprovider.GetProvider())
  1567. }
  1568. func TestMaxSessions(t *testing.T) {
  1569. usePubKey := false
  1570. u := getTestUser(usePubKey)
  1571. u.Username += "1"
  1572. u.MaxSessions = 1
  1573. user, _, err := httpd.AddUser(u, http.StatusOK)
  1574. assert.NoError(t, err)
  1575. client, err := getSftpClient(user, usePubKey)
  1576. if assert.NoError(t, err) {
  1577. defer client.Close()
  1578. assert.NoError(t, checkBasicSFTP(client))
  1579. c, err := getSftpClient(user, usePubKey)
  1580. if !assert.Error(t, err, "max sessions exceeded, new login should not succeed") {
  1581. c.Close()
  1582. }
  1583. }
  1584. _, err = httpd.RemoveUser(user, http.StatusOK)
  1585. assert.NoError(t, err)
  1586. err = os.RemoveAll(user.GetHomeDir())
  1587. assert.NoError(t, err)
  1588. }
  1589. func TestQuotaFileReplace(t *testing.T) {
  1590. usePubKey := false
  1591. u := getTestUser(usePubKey)
  1592. u.QuotaFiles = 1000
  1593. user, _, err := httpd.AddUser(u, http.StatusOK)
  1594. assert.NoError(t, err)
  1595. err = os.RemoveAll(user.GetHomeDir())
  1596. assert.NoError(t, err)
  1597. testFileSize := int64(65535)
  1598. testFileName := "test_file.dat"
  1599. testFilePath := filepath.Join(homeBasePath, testFileName)
  1600. client, err := getSftpClient(user, usePubKey)
  1601. if assert.NoError(t, err) {
  1602. defer client.Close()
  1603. expectedQuotaSize := user.UsedQuotaSize + testFileSize
  1604. expectedQuotaFiles := user.UsedQuotaFiles + 1
  1605. err = createTestFile(testFilePath, testFileSize)
  1606. assert.NoError(t, err)
  1607. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  1608. assert.NoError(t, err)
  1609. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  1610. assert.NoError(t, err)
  1611. // now replace the same file, the quota must not change
  1612. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  1613. assert.NoError(t, err)
  1614. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  1615. assert.NoError(t, err)
  1616. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  1617. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  1618. }
  1619. // now set a quota size restriction and upload the same file, upload should fail for space limit exceeded
  1620. user.QuotaSize = testFileSize - 1
  1621. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  1622. assert.NoError(t, err)
  1623. client, err = getSftpClient(user, usePubKey)
  1624. if assert.NoError(t, err) {
  1625. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  1626. assert.Error(t, err, "quota size exceeded, file upload must fail")
  1627. err = client.Remove(testFileName)
  1628. assert.NoError(t, err)
  1629. }
  1630. _, err = httpd.RemoveUser(user, http.StatusOK)
  1631. assert.NoError(t, err)
  1632. err = os.Remove(testFilePath)
  1633. assert.NoError(t, err)
  1634. err = os.RemoveAll(user.GetHomeDir())
  1635. assert.NoError(t, err)
  1636. }
  1637. func TestQuotaScan(t *testing.T) {
  1638. usePubKey := false
  1639. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  1640. assert.NoError(t, err)
  1641. testFileSize := int64(65535)
  1642. expectedQuotaSize := user.UsedQuotaSize + testFileSize
  1643. expectedQuotaFiles := user.UsedQuotaFiles + 1
  1644. client, err := getSftpClient(user, usePubKey)
  1645. if assert.NoError(t, err) {
  1646. defer client.Close()
  1647. testFileName := "test_file.dat"
  1648. testFilePath := filepath.Join(homeBasePath, testFileName)
  1649. err = createTestFile(testFilePath, testFileSize)
  1650. assert.NoError(t, err)
  1651. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  1652. assert.NoError(t, err)
  1653. err = os.Remove(testFilePath)
  1654. assert.NoError(t, err)
  1655. }
  1656. _, err = httpd.RemoveUser(user, http.StatusOK)
  1657. assert.NoError(t, err)
  1658. // create user with the same home dir, so there is at least an untracked file
  1659. user, _, err = httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  1660. assert.NoError(t, err)
  1661. _, err = httpd.StartQuotaScan(user, http.StatusCreated)
  1662. assert.NoError(t, err)
  1663. err = waitQuotaScans()
  1664. assert.NoError(t, err)
  1665. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  1666. assert.NoError(t, err)
  1667. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  1668. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  1669. _, err = httpd.RemoveUser(user, http.StatusOK)
  1670. assert.NoError(t, err)
  1671. err = os.RemoveAll(user.GetHomeDir())
  1672. assert.NoError(t, err)
  1673. }
  1674. func TestMultipleQuotaScans(t *testing.T) {
  1675. res := sftpd.AddQuotaScan(defaultUsername)
  1676. assert.True(t, res)
  1677. res = sftpd.AddQuotaScan(defaultUsername)
  1678. assert.False(t, res, "add quota must fail if another scan is already active")
  1679. err := sftpd.RemoveQuotaScan(defaultUsername)
  1680. assert.NoError(t, err)
  1681. activeScans := sftpd.GetQuotaScans()
  1682. assert.Equal(t, 0, len(activeScans))
  1683. }
  1684. func TestQuotaSize(t *testing.T) {
  1685. usePubKey := false
  1686. testFileSize := int64(65535)
  1687. u := getTestUser(usePubKey)
  1688. u.QuotaFiles = 1
  1689. u.QuotaSize = testFileSize - 1
  1690. user, _, err := httpd.AddUser(u, http.StatusOK)
  1691. assert.NoError(t, err)
  1692. client, err := getSftpClient(user, usePubKey)
  1693. if assert.NoError(t, err) {
  1694. defer client.Close()
  1695. testFileName := "test_file.dat"
  1696. testFilePath := filepath.Join(homeBasePath, testFileName)
  1697. err = createTestFile(testFilePath, testFileSize)
  1698. assert.NoError(t, err)
  1699. err = sftpUploadFile(testFilePath, testFileName+".quota", testFileSize, client)
  1700. assert.NoError(t, err)
  1701. err = sftpUploadFile(testFilePath, testFileName+".quota.1", testFileSize, client)
  1702. assert.Error(t, err, "user is over quota file upload must fail")
  1703. err = client.Remove(testFileName + ".quota")
  1704. assert.NoError(t, err)
  1705. err = os.Remove(testFilePath)
  1706. assert.NoError(t, err)
  1707. }
  1708. _, err = httpd.RemoveUser(user, http.StatusOK)
  1709. assert.NoError(t, err)
  1710. err = os.RemoveAll(user.GetHomeDir())
  1711. assert.NoError(t, err)
  1712. }
  1713. func TestBandwidthAndConnections(t *testing.T) {
  1714. usePubKey := false
  1715. testFileSize := int64(131072)
  1716. u := getTestUser(usePubKey)
  1717. u.UploadBandwidth = 30
  1718. u.DownloadBandwidth = 25
  1719. wantedUploadElapsed := 1000 * (testFileSize / 1000) / u.UploadBandwidth
  1720. wantedDownloadElapsed := 1000 * (testFileSize / 1000) / u.DownloadBandwidth
  1721. // 100 ms tolerance
  1722. wantedUploadElapsed -= 100
  1723. wantedDownloadElapsed -= 100
  1724. user, _, err := httpd.AddUser(u, http.StatusOK)
  1725. assert.NoError(t, err)
  1726. client, err := getSftpClient(user, usePubKey)
  1727. if assert.NoError(t, err) {
  1728. defer client.Close()
  1729. testFileName := "test_file.dat"
  1730. testFilePath := filepath.Join(homeBasePath, testFileName)
  1731. err = createTestFile(testFilePath, testFileSize)
  1732. assert.NoError(t, err)
  1733. startTime := time.Now()
  1734. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  1735. assert.NoError(t, err)
  1736. elapsed := time.Since(startTime).Nanoseconds() / 1000000
  1737. assert.GreaterOrEqual(t, elapsed, wantedUploadElapsed, "upload bandwidth throttling not respected")
  1738. startTime = time.Now()
  1739. localDownloadPath := filepath.Join(homeBasePath, "test_download.dat")
  1740. c := sftpDownloadNonBlocking(testFileName, localDownloadPath, testFileSize, client)
  1741. waitForActiveTransfer()
  1742. // wait some additional arbitrary time to wait for transfer activity to happen
  1743. // it is need to reach all the code in CheckIdleConnections
  1744. time.Sleep(100 * time.Millisecond)
  1745. sftpd.CheckIdleConnections()
  1746. err = <-c
  1747. assert.NoError(t, err)
  1748. elapsed = time.Since(startTime).Nanoseconds() / 1000000
  1749. assert.GreaterOrEqual(t, elapsed, wantedDownloadElapsed, "download bandwidth throttling not respected")
  1750. // test disconnection
  1751. c = sftpUploadNonBlocking(testFilePath, testFileName+"_partial", testFileSize, client)
  1752. waitForActiveTransfer()
  1753. time.Sleep(100 * time.Millisecond)
  1754. sftpd.CheckIdleConnections()
  1755. stats := sftpd.GetConnectionsStats()
  1756. for _, stat := range stats {
  1757. sftpd.CloseActiveConnection(stat.ConnectionID)
  1758. }
  1759. err = <-c
  1760. assert.Error(t, err, "connection closed while uploading: the upload must fail")
  1761. waitForNoActiveTransfer()
  1762. err = os.Remove(testFilePath)
  1763. assert.NoError(t, err)
  1764. err = os.Remove(localDownloadPath)
  1765. assert.NoError(t, err)
  1766. }
  1767. _, err = httpd.RemoveUser(user, http.StatusOK)
  1768. assert.NoError(t, err)
  1769. err = os.RemoveAll(user.GetHomeDir())
  1770. assert.NoError(t, err)
  1771. }
  1772. func TestExtensionsFilters(t *testing.T) {
  1773. usePubKey := true
  1774. u := getTestUser(usePubKey)
  1775. user, _, err := httpd.AddUser(u, http.StatusOK)
  1776. assert.NoError(t, err)
  1777. testFileSize := int64(131072)
  1778. testFileName := "test_file.dat"
  1779. testFilePath := filepath.Join(homeBasePath, testFileName)
  1780. localDownloadPath := filepath.Join(homeBasePath, "test_download.dat")
  1781. client, err := getSftpClient(user, usePubKey)
  1782. if assert.NoError(t, err) {
  1783. defer client.Close()
  1784. err = createTestFile(testFilePath, testFileSize)
  1785. assert.NoError(t, err)
  1786. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  1787. assert.NoError(t, err)
  1788. }
  1789. user.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  1790. {
  1791. Path: "/",
  1792. AllowedExtensions: []string{".zip"},
  1793. DeniedExtensions: []string{},
  1794. },
  1795. }
  1796. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  1797. assert.NoError(t, err)
  1798. client, err = getSftpClient(user, usePubKey)
  1799. if assert.NoError(t, err) {
  1800. defer client.Close()
  1801. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  1802. assert.Error(t, err)
  1803. err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize, client)
  1804. assert.Error(t, err)
  1805. err = client.Rename(testFileName, testFileName+"1")
  1806. assert.Error(t, err)
  1807. err = client.Remove(testFileName)
  1808. assert.Error(t, err)
  1809. err = client.Mkdir("dir.zip")
  1810. assert.NoError(t, err)
  1811. err = client.Rename("dir.zip", "dir1.zip")
  1812. assert.NoError(t, err)
  1813. }
  1814. _, err = httpd.RemoveUser(user, http.StatusOK)
  1815. assert.NoError(t, err)
  1816. err = os.Remove(testFilePath)
  1817. assert.NoError(t, err)
  1818. err = os.Remove(localDownloadPath)
  1819. assert.NoError(t, err)
  1820. err = os.RemoveAll(user.GetHomeDir())
  1821. assert.NoError(t, err)
  1822. }
  1823. func TestVirtualFolders(t *testing.T) {
  1824. usePubKey := true
  1825. u := getTestUser(usePubKey)
  1826. mappedPath := filepath.Join(os.TempDir(), "vdir")
  1827. vdirPath := "/vdir" //nolint:goconst
  1828. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1829. VirtualPath: vdirPath,
  1830. MappedPath: mappedPath,
  1831. })
  1832. err := os.MkdirAll(mappedPath, 0777)
  1833. assert.NoError(t, err)
  1834. user, _, err := httpd.AddUser(u, http.StatusOK)
  1835. assert.NoError(t, err)
  1836. client, err := getSftpClient(user, usePubKey)
  1837. if assert.NoError(t, err) {
  1838. defer client.Close()
  1839. testFileSize := int64(131072)
  1840. testFileName := "test_file.dat"
  1841. testFilePath := filepath.Join(homeBasePath, testFileName)
  1842. err = createTestFile(testFilePath, testFileSize)
  1843. assert.NoError(t, err)
  1844. localDownloadPath := filepath.Join(homeBasePath, "test_download.dat")
  1845. err = sftpUploadFile(testFilePath, path.Join(vdirPath, testFileName), testFileSize, client)
  1846. assert.NoError(t, err)
  1847. err = sftpDownloadFile(path.Join(vdirPath, testFileName), localDownloadPath, testFileSize, client)
  1848. assert.NoError(t, err)
  1849. err = client.Rename(vdirPath, "new_name")
  1850. assert.Error(t, err, "renaming a virtual folder must fail")
  1851. err = client.RemoveDirectory(vdirPath)
  1852. assert.Error(t, err, "removing a virtual folder must fail")
  1853. err = client.Mkdir(vdirPath)
  1854. assert.Error(t, err, "creating a virtual folder must fail")
  1855. err = client.Symlink(path.Join(vdirPath, testFileName), vdirPath)
  1856. assert.Error(t, err, "symlink to a virtual folder must fail")
  1857. err = os.Remove(testFilePath)
  1858. assert.NoError(t, err)
  1859. err = os.Remove(localDownloadPath)
  1860. assert.NoError(t, err)
  1861. }
  1862. _, err = httpd.RemoveUser(user, http.StatusOK)
  1863. assert.NoError(t, err)
  1864. err = os.RemoveAll(user.GetHomeDir())
  1865. assert.NoError(t, err)
  1866. err = os.RemoveAll(mappedPath)
  1867. assert.NoError(t, err)
  1868. }
  1869. func TestVirtualFoldersQuota(t *testing.T) {
  1870. usePubKey := false
  1871. u := getTestUser(usePubKey)
  1872. u.QuotaFiles = 100
  1873. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  1874. vdirPath1 := "/vdir1"
  1875. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  1876. vdirPath2 := "/vdir2"
  1877. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1878. VirtualPath: vdirPath1,
  1879. MappedPath: mappedPath1,
  1880. })
  1881. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1882. VirtualPath: vdirPath2,
  1883. MappedPath: mappedPath2,
  1884. ExcludeFromQuota: true,
  1885. })
  1886. err := os.MkdirAll(mappedPath1, 0777)
  1887. assert.NoError(t, err)
  1888. err = os.MkdirAll(mappedPath2, 0777)
  1889. assert.NoError(t, err)
  1890. user, _, err := httpd.AddUser(u, http.StatusOK)
  1891. assert.NoError(t, err)
  1892. client, err := getSftpClient(user, usePubKey)
  1893. if assert.NoError(t, err) {
  1894. defer client.Close()
  1895. testFileName := "test_file.dat"
  1896. testFileSize := int64(131072)
  1897. testFilePath := filepath.Join(homeBasePath, testFileName)
  1898. err = createTestFile(testFilePath, testFileSize)
  1899. assert.NoError(t, err)
  1900. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  1901. assert.NoError(t, err)
  1902. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, testFileName), testFileSize, client)
  1903. assert.NoError(t, err)
  1904. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testFileName), testFileSize, client)
  1905. assert.NoError(t, err)
  1906. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testFileName), testFileSize, client)
  1907. assert.NoError(t, err)
  1908. expectedQuotaFiles := 2
  1909. expectedQuotaSize := testFileSize * 2
  1910. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  1911. assert.NoError(t, err)
  1912. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  1913. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  1914. err = client.Remove(path.Join(vdirPath2, testFileName))
  1915. assert.NoError(t, err)
  1916. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  1917. assert.NoError(t, err)
  1918. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  1919. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  1920. }
  1921. _, err = httpd.RemoveUser(user, http.StatusOK)
  1922. assert.NoError(t, err)
  1923. err = os.RemoveAll(user.GetHomeDir())
  1924. assert.NoError(t, err)
  1925. err = os.RemoveAll(mappedPath1)
  1926. assert.NoError(t, err)
  1927. err = os.RemoveAll(mappedPath2)
  1928. assert.NoError(t, err)
  1929. }
  1930. func TestMissingFile(t *testing.T) {
  1931. usePubKey := false
  1932. u := getTestUser(usePubKey)
  1933. user, _, err := httpd.AddUser(u, http.StatusOK)
  1934. assert.NoError(t, err)
  1935. client, err := getSftpClient(user, usePubKey)
  1936. if assert.NoError(t, err) {
  1937. defer client.Close()
  1938. localDownloadPath := filepath.Join(homeBasePath, "test_download.dat")
  1939. err = sftpDownloadFile("missing_file", localDownloadPath, 0, client)
  1940. assert.Error(t, err, "download missing file must fail")
  1941. err = os.Remove(localDownloadPath)
  1942. assert.NoError(t, err)
  1943. }
  1944. _, err = httpd.RemoveUser(user, http.StatusOK)
  1945. assert.NoError(t, err)
  1946. err = os.RemoveAll(user.GetHomeDir())
  1947. assert.NoError(t, err)
  1948. }
  1949. func TestOpenError(t *testing.T) {
  1950. if runtime.GOOS == osWindows {
  1951. t.Skip("this test is not available on Windows")
  1952. }
  1953. usePubKey := false
  1954. u := getTestUser(usePubKey)
  1955. user, _, err := httpd.AddUser(u, http.StatusOK)
  1956. assert.NoError(t, err)
  1957. err = os.RemoveAll(user.GetHomeDir())
  1958. assert.NoError(t, err)
  1959. client, err := getSftpClient(user, usePubKey)
  1960. if assert.NoError(t, err) {
  1961. defer client.Close()
  1962. err = os.Chmod(user.GetHomeDir(), 0001)
  1963. assert.NoError(t, err)
  1964. _, err = client.ReadDir(".")
  1965. assert.Error(t, err, "read dir must fail if we have no filesystem read permissions")
  1966. err = os.Chmod(user.GetHomeDir(), 0755)
  1967. assert.NoError(t, err)
  1968. testFileSize := int64(65535)
  1969. testFileName := "test_file.dat"
  1970. testFilePath := filepath.Join(user.GetHomeDir(), testFileName)
  1971. err = createTestFile(testFilePath, testFileSize)
  1972. assert.NoError(t, err)
  1973. _, err = client.Stat(testFileName)
  1974. assert.NoError(t, err)
  1975. localDownloadPath := filepath.Join(homeBasePath, "test_download.dat")
  1976. err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize, client)
  1977. assert.NoError(t, err)
  1978. err = os.Chmod(testFilePath, 0001)
  1979. assert.NoError(t, err)
  1980. err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize, client)
  1981. assert.Error(t, err, "file download must fail if we have no filesystem read permissions")
  1982. err = sftpUploadFile(localDownloadPath, testFileName, testFileSize, client)
  1983. assert.Error(t, err, "upload must fail if we have no filesystem write permissions")
  1984. err = client.Mkdir("test")
  1985. assert.NoError(t, err)
  1986. err = os.Chmod(user.GetHomeDir(), 0000)
  1987. assert.NoError(t, err)
  1988. _, err = client.Lstat(testFileName)
  1989. assert.Error(t, err, "file stat must fail if we have no filesystem read permissions")
  1990. err = os.Chmod(user.GetHomeDir(), 0755)
  1991. assert.NoError(t, err)
  1992. err = os.Chmod(filepath.Join(user.GetHomeDir(), "test"), 0000)
  1993. assert.NoError(t, err)
  1994. err = client.Rename(testFileName, path.Join("test", testFileName))
  1995. assert.Error(t, err)
  1996. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  1997. err = os.Chmod(filepath.Join(user.GetHomeDir(), "test"), 0755)
  1998. assert.NoError(t, err)
  1999. err = os.Remove(localDownloadPath)
  2000. assert.NoError(t, err)
  2001. }
  2002. _, err = httpd.RemoveUser(user, http.StatusOK)
  2003. assert.NoError(t, err)
  2004. err = os.RemoveAll(user.GetHomeDir())
  2005. assert.NoError(t, err)
  2006. }
  2007. func TestOverwriteDirWithFile(t *testing.T) {
  2008. usePubKey := false
  2009. u := getTestUser(usePubKey)
  2010. user, _, err := httpd.AddUser(u, http.StatusOK)
  2011. assert.NoError(t, err)
  2012. client, err := getSftpClient(user, usePubKey)
  2013. if assert.NoError(t, err) {
  2014. defer client.Close()
  2015. testFileSize := int64(65535)
  2016. testFileName := "test_file.dat"
  2017. testDirName := "test_dir" //nolint:goconst
  2018. testFilePath := filepath.Join(homeBasePath, testFileName)
  2019. err = createTestFile(testFilePath, testFileSize)
  2020. assert.NoError(t, err)
  2021. err = client.Mkdir(testDirName)
  2022. assert.NoError(t, err)
  2023. err = sftpUploadFile(testFilePath, testDirName, testFileSize, client)
  2024. assert.Error(t, err, "copying a file over an existing dir must fail")
  2025. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2026. assert.NoError(t, err)
  2027. err = client.Rename(testFileName, testDirName)
  2028. assert.Error(t, err, "rename a file over an existing dir must fail")
  2029. err = client.RemoveDirectory(testDirName)
  2030. assert.NoError(t, err)
  2031. err = client.Remove(testFileName)
  2032. assert.NoError(t, err)
  2033. err = os.Remove(testFilePath)
  2034. assert.NoError(t, err)
  2035. }
  2036. _, err = httpd.RemoveUser(user, http.StatusOK)
  2037. assert.NoError(t, err)
  2038. err = os.RemoveAll(user.GetHomeDir())
  2039. assert.NoError(t, err)
  2040. }
  2041. func TestHashedPasswords(t *testing.T) {
  2042. usePubKey := false
  2043. pwdMapping := make(map[string]string)
  2044. pwdMapping["$pbkdf2-sha1$150000$DveVjgYUD05R$X6ydQZdyMeOvpgND2nqGR/0GGic="] = "password" //nolint:goconst
  2045. pwdMapping["$pbkdf2-sha256$150000$E86a9YMX3zC7$R5J62hsSq+pYw00hLLPKBbcGXmq7fj5+/M0IFoYtZbo="] = "password"
  2046. pwdMapping["$pbkdf2-sha512$150000$dsu7T5R3IaVQ$1hFXPO1ntRBcoWkSLKw+s4sAP09Xtu4Ya7CyxFq64jM9zdUg8eRJVr3NcR2vQgb0W9HHvZaILHsL4Q/Vr6arCg=="] = "password"
  2047. pwdMapping["$1$b5caebda$VODr/nyhGWgZaY8sJ4x05."] = "password"
  2048. pwdMapping["$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK"] = "secret"
  2049. pwdMapping["$6$459ead56b72e44bc$uog86fUxscjt28BZxqFBE2pp2QD8P/1e98MNF75Z9xJfQvOckZnQ/1YJqiq1XeytPuDieHZvDAMoP7352ELkO1"] = "secret"
  2050. pwdMapping["$apr1$OBWLeSme$WoJbB736e7kKxMBIAqilb1"] = "password"
  2051. for pwd, clearPwd := range pwdMapping {
  2052. u := getTestUser(usePubKey)
  2053. u.Password = pwd
  2054. user, _, err := httpd.AddUser(u, http.StatusOK)
  2055. assert.NoError(t, err)
  2056. user.Password = clearPwd
  2057. client, err := getSftpClient(user, usePubKey)
  2058. if assert.NoError(t, err, "unable to login with password %#v", pwd) {
  2059. defer client.Close()
  2060. assert.NoError(t, checkBasicSFTP(client))
  2061. }
  2062. user.Password = pwd
  2063. client, err = getSftpClient(user, usePubKey)
  2064. if !assert.Error(t, err, "login with wrong password must fail") {
  2065. client.Close()
  2066. }
  2067. _, err = httpd.RemoveUser(user, http.StatusOK)
  2068. assert.NoError(t, err)
  2069. err = os.RemoveAll(user.GetHomeDir())
  2070. assert.NoError(t, err)
  2071. }
  2072. }
  2073. func TestPasswordsHashPbkdf2Sha256_389DS(t *testing.T) {
  2074. pbkdf389dsPwd := "{PBKDF2_SHA256}AAAIAMZIKG4ie44zJY4HOXI+upFR74PzWLUQV63jg+zzkbEjCK3N4qW583WF7EdcpeoOMQ4HY3aWEXB6lnXhXJixbJkU4vVSJkL6YCbU3TrD0qn1uUUVSkaIgAOtmZENitwbhYhiWfEzGyAtFqkFd75P5xhWJEog9XhQKYrR0f7S3WGGZq03JRcLJ460xpU97bE/sWRn7sshgkWzLuyrs0I+XRKmK7FJeaA9zd+1m44Y3IVmZ2YLdKATzjRHAIgpBC6i1TWOcpKJT1+feP1C9hrxH8vU9baw9thNiO8jSHaZlwb//KpJFe0ahVnG/1ubiG8cO0+CCqDqXVJR6Vr4QZxHP+4pwooW+4TP/L+HFdyA1y6z4gKfqYnBsmb3sD1R1TbxfH4btTdvgZAnBk9CmR3QASkFXxeTYsrmNd5+9IAHc6dm"
  2075. pbkdf389dsPwd = pbkdf389dsPwd[15:]
  2076. hashBytes, err := base64.StdEncoding.DecodeString(pbkdf389dsPwd)
  2077. assert.NoError(t, err)
  2078. iterBytes := hashBytes[0:4]
  2079. var iterations int32
  2080. err = binary.Read(bytes.NewBuffer(iterBytes), binary.BigEndian, &iterations)
  2081. assert.NoError(t, err)
  2082. salt := hashBytes[4:68]
  2083. targetKey := hashBytes[68:]
  2084. key := base64.StdEncoding.EncodeToString(targetKey)
  2085. pbkdf2Pwd := fmt.Sprintf("$pbkdf2-b64salt-sha256$%v$%v$%v", iterations, base64.StdEncoding.EncodeToString(salt), key)
  2086. pbkdf2ClearPwd := "password"
  2087. usePubKey := false
  2088. u := getTestUser(usePubKey)
  2089. u.Password = pbkdf2Pwd
  2090. user, _, err := httpd.AddUser(u, http.StatusOK)
  2091. assert.NoError(t, err)
  2092. user.Password = pbkdf2ClearPwd
  2093. client, err := getSftpClient(user, usePubKey)
  2094. if assert.NoError(t, err) {
  2095. defer client.Close()
  2096. assert.NoError(t, checkBasicSFTP(client))
  2097. }
  2098. user.Password = pbkdf2Pwd
  2099. client, err = getSftpClient(user, usePubKey)
  2100. if !assert.Error(t, err, "login with wrong password must fail") {
  2101. client.Close()
  2102. }
  2103. _, err = httpd.RemoveUser(user, http.StatusOK)
  2104. assert.NoError(t, err)
  2105. err = os.RemoveAll(user.GetHomeDir())
  2106. assert.NoError(t, err)
  2107. }
  2108. func TestPermList(t *testing.T) {
  2109. usePubKey := true
  2110. u := getTestUser(usePubKey)
  2111. u.Permissions["/"] = []string{dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete, dataprovider.PermRename,
  2112. dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite, dataprovider.PermChmod,
  2113. dataprovider.PermChown, dataprovider.PermChtimes}
  2114. user, _, err := httpd.AddUser(u, http.StatusOK)
  2115. assert.NoError(t, err)
  2116. client, err := getSftpClient(user, usePubKey)
  2117. if assert.NoError(t, err) {
  2118. defer client.Close()
  2119. _, err = client.ReadDir(".")
  2120. assert.Error(t, err, "read remote dir without permission should not succeed")
  2121. _, err = client.Stat("test_file")
  2122. assert.Error(t, err, "stat remote file without permission should not succeed")
  2123. }
  2124. _, err = httpd.RemoveUser(user, http.StatusOK)
  2125. assert.NoError(t, err)
  2126. err = os.RemoveAll(user.GetHomeDir())
  2127. assert.NoError(t, err)
  2128. }
  2129. func TestPermDownload(t *testing.T) {
  2130. usePubKey := true
  2131. u := getTestUser(usePubKey)
  2132. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermUpload, dataprovider.PermDelete, dataprovider.PermRename,
  2133. dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite, dataprovider.PermChmod,
  2134. dataprovider.PermChown, dataprovider.PermChtimes}
  2135. user, _, err := httpd.AddUser(u, http.StatusOK)
  2136. assert.NoError(t, err)
  2137. client, err := getSftpClient(user, usePubKey)
  2138. if assert.NoError(t, err) {
  2139. defer client.Close()
  2140. testFileName := "test_file.dat"
  2141. testFilePath := filepath.Join(homeBasePath, testFileName)
  2142. testFileSize := int64(65535)
  2143. err = createTestFile(testFilePath, testFileSize)
  2144. assert.NoError(t, err)
  2145. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2146. assert.NoError(t, err)
  2147. localDownloadPath := filepath.Join(homeBasePath, "test_download.dat")
  2148. err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize, client)
  2149. assert.Error(t, err, "file download without permission should not succeed")
  2150. err = client.Remove(testFileName)
  2151. assert.NoError(t, err)
  2152. err = os.Remove(testFilePath)
  2153. assert.NoError(t, err)
  2154. err = os.Remove(localDownloadPath)
  2155. assert.NoError(t, err)
  2156. }
  2157. _, err = httpd.RemoveUser(user, http.StatusOK)
  2158. assert.NoError(t, err)
  2159. err = os.RemoveAll(user.GetHomeDir())
  2160. assert.NoError(t, err)
  2161. }
  2162. func TestPermUpload(t *testing.T) {
  2163. usePubKey := false
  2164. u := getTestUser(usePubKey)
  2165. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermDelete, dataprovider.PermRename,
  2166. dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite, dataprovider.PermChmod,
  2167. dataprovider.PermChown, dataprovider.PermChtimes}
  2168. user, _, err := httpd.AddUser(u, http.StatusOK)
  2169. assert.NoError(t, err)
  2170. client, err := getSftpClient(user, usePubKey)
  2171. if assert.NoError(t, err) {
  2172. defer client.Close()
  2173. testFileName := "test_file.dat"
  2174. testFilePath := filepath.Join(homeBasePath, testFileName)
  2175. testFileSize := int64(65535)
  2176. err = createTestFile(testFilePath, testFileSize)
  2177. assert.NoError(t, err)
  2178. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2179. assert.Error(t, err, "file upload without permission should not succeed")
  2180. err = os.Remove(testFilePath)
  2181. assert.NoError(t, err)
  2182. }
  2183. _, err = httpd.RemoveUser(user, http.StatusOK)
  2184. assert.NoError(t, err)
  2185. err = os.RemoveAll(user.GetHomeDir())
  2186. assert.NoError(t, err)
  2187. }
  2188. func TestPermOverwrite(t *testing.T) {
  2189. usePubKey := false
  2190. u := getTestUser(usePubKey)
  2191. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete,
  2192. dataprovider.PermRename, dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermChmod,
  2193. dataprovider.PermChown, dataprovider.PermChtimes}
  2194. user, _, err := httpd.AddUser(u, http.StatusOK)
  2195. assert.NoError(t, err)
  2196. client, err := getSftpClient(user, usePubKey)
  2197. if assert.NoError(t, err) {
  2198. defer client.Close()
  2199. testFileName := "test_file.dat"
  2200. testFilePath := filepath.Join(homeBasePath, testFileName)
  2201. testFileSize := int64(65535)
  2202. err = createTestFile(testFilePath, testFileSize)
  2203. assert.NoError(t, err)
  2204. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2205. assert.NoError(t, err)
  2206. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2207. assert.Error(t, err, "file overwrite without permission should not succeed")
  2208. err = os.Remove(testFilePath)
  2209. assert.NoError(t, err)
  2210. }
  2211. _, err = httpd.RemoveUser(user, http.StatusOK)
  2212. assert.NoError(t, err)
  2213. err = os.RemoveAll(user.GetHomeDir())
  2214. assert.NoError(t, err)
  2215. }
  2216. func TestPermDelete(t *testing.T) {
  2217. usePubKey := false
  2218. u := getTestUser(usePubKey)
  2219. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermRename,
  2220. dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite, dataprovider.PermChmod,
  2221. dataprovider.PermChown, dataprovider.PermChtimes}
  2222. user, _, err := httpd.AddUser(u, http.StatusOK)
  2223. assert.NoError(t, err)
  2224. client, err := getSftpClient(user, usePubKey)
  2225. if assert.NoError(t, err) {
  2226. defer client.Close()
  2227. testFileName := "test_file.dat"
  2228. testFilePath := filepath.Join(homeBasePath, testFileName)
  2229. testFileSize := int64(65535)
  2230. err = createTestFile(testFilePath, testFileSize)
  2231. assert.NoError(t, err)
  2232. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2233. assert.NoError(t, err)
  2234. err = client.Remove(testFileName)
  2235. assert.Error(t, err, "delete without permission should not succeed")
  2236. err = os.Remove(testFilePath)
  2237. assert.NoError(t, err)
  2238. }
  2239. _, err = httpd.RemoveUser(user, http.StatusOK)
  2240. assert.NoError(t, err)
  2241. err = os.RemoveAll(user.GetHomeDir())
  2242. assert.NoError(t, err)
  2243. }
  2244. //nolint:dupl
  2245. func TestPermRename(t *testing.T) {
  2246. usePubKey := false
  2247. u := getTestUser(usePubKey)
  2248. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete,
  2249. dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite, dataprovider.PermChmod,
  2250. dataprovider.PermChown, dataprovider.PermChtimes}
  2251. user, _, err := httpd.AddUser(u, http.StatusOK)
  2252. assert.NoError(t, err)
  2253. client, err := getSftpClient(user, usePubKey)
  2254. if assert.NoError(t, err) {
  2255. defer client.Close()
  2256. testFileName := "test_file.dat"
  2257. testFilePath := filepath.Join(homeBasePath, testFileName)
  2258. testFileSize := int64(65535)
  2259. err = createTestFile(testFilePath, testFileSize)
  2260. assert.NoError(t, err)
  2261. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2262. assert.NoError(t, err)
  2263. err = client.Rename(testFileName, testFileName+".rename")
  2264. assert.Error(t, err, "rename without permission should not succeed")
  2265. err = client.Remove(testFileName)
  2266. assert.NoError(t, err)
  2267. err = os.Remove(testFilePath)
  2268. assert.NoError(t, err)
  2269. }
  2270. _, err = httpd.RemoveUser(user, http.StatusOK)
  2271. assert.NoError(t, err)
  2272. err = os.RemoveAll(user.GetHomeDir())
  2273. assert.NoError(t, err)
  2274. }
  2275. func TestPermCreateDirs(t *testing.T) {
  2276. usePubKey := false
  2277. u := getTestUser(usePubKey)
  2278. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete,
  2279. dataprovider.PermRename, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite, dataprovider.PermChmod,
  2280. dataprovider.PermChown, dataprovider.PermChtimes}
  2281. user, _, err := httpd.AddUser(u, http.StatusOK)
  2282. assert.NoError(t, err)
  2283. client, err := getSftpClient(user, usePubKey)
  2284. if assert.NoError(t, err) {
  2285. defer client.Close()
  2286. err = client.Mkdir("testdir")
  2287. assert.Error(t, err, "mkdir without permission should not succeed")
  2288. }
  2289. _, err = httpd.RemoveUser(user, http.StatusOK)
  2290. assert.NoError(t, err)
  2291. err = os.RemoveAll(user.GetHomeDir())
  2292. assert.NoError(t, err)
  2293. }
  2294. //nolint:dupl
  2295. func TestPermSymlink(t *testing.T) {
  2296. usePubKey := false
  2297. u := getTestUser(usePubKey)
  2298. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete,
  2299. dataprovider.PermRename, dataprovider.PermCreateDirs, dataprovider.PermOverwrite, dataprovider.PermChmod, dataprovider.PermChown,
  2300. dataprovider.PermChtimes}
  2301. user, _, err := httpd.AddUser(u, http.StatusOK)
  2302. assert.NoError(t, err)
  2303. client, err := getSftpClient(user, usePubKey)
  2304. if assert.NoError(t, err) {
  2305. defer client.Close()
  2306. testFileName := "test_file.dat"
  2307. testFilePath := filepath.Join(homeBasePath, testFileName)
  2308. testFileSize := int64(65535)
  2309. err = createTestFile(testFilePath, testFileSize)
  2310. assert.NoError(t, err)
  2311. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2312. assert.NoError(t, err)
  2313. err = client.Symlink(testFilePath, testFilePath+".symlink")
  2314. assert.Error(t, err, "symlink without permission should not succeed")
  2315. err = client.Remove(testFileName)
  2316. assert.NoError(t, err)
  2317. err = os.Remove(testFilePath)
  2318. assert.NoError(t, err)
  2319. }
  2320. _, err = httpd.RemoveUser(user, http.StatusOK)
  2321. assert.NoError(t, err)
  2322. err = os.RemoveAll(user.GetHomeDir())
  2323. assert.NoError(t, err)
  2324. }
  2325. func TestPermChmod(t *testing.T) {
  2326. usePubKey := false
  2327. u := getTestUser(usePubKey)
  2328. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete,
  2329. dataprovider.PermRename, dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite,
  2330. dataprovider.PermChown, dataprovider.PermChtimes}
  2331. user, _, err := httpd.AddUser(u, http.StatusOK)
  2332. assert.NoError(t, err)
  2333. client, err := getSftpClient(user, usePubKey)
  2334. if assert.NoError(t, err) {
  2335. defer client.Close()
  2336. testFileName := "test_file.dat"
  2337. testFilePath := filepath.Join(homeBasePath, testFileName)
  2338. testFileSize := int64(65535)
  2339. err = createTestFile(testFilePath, testFileSize)
  2340. assert.NoError(t, err)
  2341. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2342. assert.NoError(t, err)
  2343. err = client.Chmod(testFileName, 0666)
  2344. assert.Error(t, err, "chmod without permission should not succeed")
  2345. err = client.Remove(testFileName)
  2346. assert.NoError(t, err)
  2347. err = os.Remove(testFilePath)
  2348. assert.NoError(t, err)
  2349. }
  2350. _, err = httpd.RemoveUser(user, http.StatusOK)
  2351. assert.NoError(t, err)
  2352. err = os.RemoveAll(user.GetHomeDir())
  2353. assert.NoError(t, err)
  2354. }
  2355. //nolint:dupl
  2356. func TestPermChown(t *testing.T) {
  2357. usePubKey := false
  2358. u := getTestUser(usePubKey)
  2359. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete,
  2360. dataprovider.PermRename, dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite,
  2361. dataprovider.PermChmod, dataprovider.PermChtimes}
  2362. user, _, err := httpd.AddUser(u, http.StatusOK)
  2363. assert.NoError(t, err)
  2364. client, err := getSftpClient(user, usePubKey)
  2365. if assert.NoError(t, err) {
  2366. defer client.Close()
  2367. testFileName := "test_file.dat"
  2368. testFilePath := filepath.Join(homeBasePath, testFileName)
  2369. testFileSize := int64(65535)
  2370. err = createTestFile(testFilePath, testFileSize)
  2371. assert.NoError(t, err)
  2372. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2373. assert.NoError(t, err)
  2374. err = client.Chown(testFileName, os.Getuid(), os.Getgid())
  2375. assert.Error(t, err, "chown without permission should not succeed")
  2376. err = client.Remove(testFileName)
  2377. assert.NoError(t, err)
  2378. err = os.Remove(testFilePath)
  2379. assert.NoError(t, err)
  2380. }
  2381. _, err = httpd.RemoveUser(user, http.StatusOK)
  2382. assert.NoError(t, err)
  2383. err = os.RemoveAll(user.GetHomeDir())
  2384. assert.NoError(t, err)
  2385. }
  2386. //nolint:dupl
  2387. func TestPermChtimes(t *testing.T) {
  2388. usePubKey := false
  2389. u := getTestUser(usePubKey)
  2390. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete,
  2391. dataprovider.PermRename, dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite,
  2392. dataprovider.PermChmod, dataprovider.PermChown}
  2393. user, _, err := httpd.AddUser(u, http.StatusOK)
  2394. assert.NoError(t, err)
  2395. client, err := getSftpClient(user, usePubKey)
  2396. if assert.NoError(t, err) {
  2397. defer client.Close()
  2398. testFileName := "test_file.dat"
  2399. testFilePath := filepath.Join(homeBasePath, testFileName)
  2400. testFileSize := int64(65535)
  2401. err = createTestFile(testFilePath, testFileSize)
  2402. assert.NoError(t, err)
  2403. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2404. assert.NoError(t, err)
  2405. err = client.Chtimes(testFileName, time.Now(), time.Now())
  2406. assert.Error(t, err, "chtimes without permission should not succeed")
  2407. err = client.Remove(testFileName)
  2408. assert.NoError(t, err)
  2409. err = os.Remove(testFilePath)
  2410. assert.NoError(t, err)
  2411. }
  2412. _, err = httpd.RemoveUser(user, http.StatusOK)
  2413. assert.NoError(t, err)
  2414. err = os.RemoveAll(user.GetHomeDir())
  2415. assert.NoError(t, err)
  2416. }
  2417. func TestSubDirsUploads(t *testing.T) {
  2418. usePubKey := true
  2419. u := getTestUser(usePubKey)
  2420. u.Permissions["/"] = []string{dataprovider.PermAny}
  2421. u.Permissions["/subdir"] = []string{dataprovider.PermChtimes, dataprovider.PermDownload}
  2422. user, _, err := httpd.AddUser(u, http.StatusOK)
  2423. assert.NoError(t, err)
  2424. client, err := getSftpClient(user, usePubKey)
  2425. if assert.NoError(t, err) {
  2426. defer client.Close()
  2427. err = client.Mkdir("subdir")
  2428. assert.NoError(t, err)
  2429. testFileName := "test_file.dat"
  2430. testFileNameSub := "/subdir/test_file_dat"
  2431. testFilePath := filepath.Join(homeBasePath, testFileName)
  2432. testFileSize := int64(65535)
  2433. err = createTestFile(testFilePath, testFileSize)
  2434. assert.NoError(t, err)
  2435. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2436. assert.NoError(t, err)
  2437. err = sftpUploadFile(testFilePath, testFileNameSub, testFileSize, client)
  2438. if assert.Error(t, err) {
  2439. assert.Contains(t, err.Error(), permissionErrorString)
  2440. }
  2441. err = client.Symlink(testFileName, testFileNameSub+".link")
  2442. if assert.Error(t, err) {
  2443. assert.Contains(t, err.Error(), permissionErrorString)
  2444. }
  2445. err = client.Symlink(testFileName, testFileName+".link")
  2446. assert.NoError(t, err)
  2447. err = client.Rename(testFileName, testFileNameSub+".rename")
  2448. if assert.Error(t, err) {
  2449. assert.Contains(t, err.Error(), permissionErrorString)
  2450. }
  2451. err = client.Rename(testFileName, testFileName+".rename")
  2452. assert.NoError(t, err)
  2453. err = client.Remove(testFileNameSub)
  2454. if assert.Error(t, err) {
  2455. assert.Contains(t, err.Error(), permissionErrorString)
  2456. }
  2457. err = client.Remove(testFileName + ".rename")
  2458. assert.NoError(t, err)
  2459. err = os.Remove(testFilePath)
  2460. assert.NoError(t, err)
  2461. }
  2462. _, err = httpd.RemoveUser(user, http.StatusOK)
  2463. assert.NoError(t, err)
  2464. err = os.RemoveAll(user.GetHomeDir())
  2465. assert.NoError(t, err)
  2466. }
  2467. func TestSubDirsOverwrite(t *testing.T) {
  2468. usePubKey := true
  2469. u := getTestUser(usePubKey)
  2470. u.Permissions["/"] = []string{dataprovider.PermAny}
  2471. u.Permissions["/subdir"] = []string{dataprovider.PermOverwrite, dataprovider.PermListItems}
  2472. user, _, err := httpd.AddUser(u, http.StatusOK)
  2473. assert.NoError(t, err)
  2474. client, err := getSftpClient(user, usePubKey)
  2475. if assert.NoError(t, err) {
  2476. defer client.Close()
  2477. testFileName := "/subdir/test_file.dat" //nolint:goconst
  2478. testFilePath := filepath.Join(homeBasePath, "test_file.dat")
  2479. testFileSFTPPath := filepath.Join(u.GetHomeDir(), "subdir", "test_file.dat")
  2480. testFileSize := int64(65535)
  2481. err = createTestFile(testFilePath, testFileSize)
  2482. assert.NoError(t, err)
  2483. err = createTestFile(testFileSFTPPath, 16384)
  2484. assert.NoError(t, err)
  2485. err = sftpUploadFile(testFilePath, testFileName+".new", testFileSize, client)
  2486. if assert.Error(t, err) {
  2487. assert.Contains(t, err.Error(), permissionErrorString)
  2488. }
  2489. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2490. assert.NoError(t, err)
  2491. err = os.Remove(testFilePath)
  2492. assert.NoError(t, err)
  2493. }
  2494. _, err = httpd.RemoveUser(user, http.StatusOK)
  2495. assert.NoError(t, err)
  2496. err = os.RemoveAll(user.GetHomeDir())
  2497. assert.NoError(t, err)
  2498. }
  2499. func TestSubDirsDownloads(t *testing.T) {
  2500. usePubKey := true
  2501. u := getTestUser(usePubKey)
  2502. u.Permissions["/"] = []string{dataprovider.PermAny}
  2503. u.Permissions["/subdir"] = []string{dataprovider.PermChmod, dataprovider.PermUpload, dataprovider.PermListItems}
  2504. user, _, err := httpd.AddUser(u, http.StatusOK)
  2505. assert.NoError(t, err)
  2506. client, err := getSftpClient(user, usePubKey)
  2507. if assert.NoError(t, err) {
  2508. defer client.Close()
  2509. err = client.Mkdir("subdir")
  2510. assert.NoError(t, err)
  2511. testFileName := "/subdir/test_file.dat"
  2512. testFilePath := filepath.Join(homeBasePath, "test_file.dat")
  2513. testFileSize := int64(65535)
  2514. err = createTestFile(testFilePath, testFileSize)
  2515. assert.NoError(t, err)
  2516. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2517. assert.NoError(t, err)
  2518. localDownloadPath := filepath.Join(homeBasePath, "test_download.dat")
  2519. err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize, client)
  2520. if assert.Error(t, err) {
  2521. assert.Contains(t, err.Error(), permissionErrorString)
  2522. }
  2523. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2524. if assert.Error(t, err) {
  2525. assert.Contains(t, err.Error(), permissionErrorString)
  2526. }
  2527. err = client.Chtimes(testFileName, time.Now(), time.Now())
  2528. if assert.Error(t, err) {
  2529. assert.Contains(t, err.Error(), permissionErrorString)
  2530. }
  2531. err = client.Rename(testFileName, testFileName+".rename")
  2532. if assert.Error(t, err) {
  2533. assert.Contains(t, err.Error(), permissionErrorString)
  2534. }
  2535. err = client.Symlink(testFileName, testFileName+".link")
  2536. if assert.Error(t, err) {
  2537. assert.Contains(t, err.Error(), permissionErrorString)
  2538. }
  2539. err = client.Remove(testFileName)
  2540. if assert.Error(t, err) {
  2541. assert.Contains(t, err.Error(), permissionErrorString)
  2542. }
  2543. err = os.Remove(localDownloadPath)
  2544. assert.NoError(t, err)
  2545. err = os.Remove(testFilePath)
  2546. assert.NoError(t, err)
  2547. }
  2548. _, err = httpd.RemoveUser(user, http.StatusOK)
  2549. assert.NoError(t, err)
  2550. err = os.RemoveAll(user.GetHomeDir())
  2551. assert.NoError(t, err)
  2552. }
  2553. func TestPermsSubDirsSetstat(t *testing.T) {
  2554. // for setstat we check the parent dir permission if the requested path is a dir
  2555. // otherwise the path permission
  2556. usePubKey := true
  2557. u := getTestUser(usePubKey)
  2558. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermCreateDirs}
  2559. u.Permissions["/subdir"] = []string{dataprovider.PermAny}
  2560. user, _, err := httpd.AddUser(u, http.StatusOK)
  2561. assert.NoError(t, err)
  2562. client, err := getSftpClient(user, usePubKey)
  2563. if assert.NoError(t, err) {
  2564. defer client.Close()
  2565. err = client.Mkdir("subdir")
  2566. assert.NoError(t, err)
  2567. testFileName := "/subdir/test_file.dat"
  2568. testFilePath := filepath.Join(homeBasePath, "test_file.dat")
  2569. testFileSize := int64(65535)
  2570. err = createTestFile(testFilePath, testFileSize)
  2571. assert.NoError(t, err)
  2572. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2573. assert.NoError(t, err)
  2574. err = client.Chtimes("/subdir/", time.Now(), time.Now())
  2575. if assert.Error(t, err) {
  2576. assert.Contains(t, err.Error(), permissionErrorString)
  2577. }
  2578. err = client.Chtimes("subdir/", time.Now(), time.Now())
  2579. if assert.Error(t, err) {
  2580. assert.Contains(t, err.Error(), permissionErrorString)
  2581. }
  2582. err = client.Chtimes(testFileName, time.Now(), time.Now())
  2583. assert.NoError(t, err)
  2584. err = os.Remove(testFilePath)
  2585. assert.NoError(t, err)
  2586. }
  2587. _, err = httpd.RemoveUser(user, http.StatusOK)
  2588. assert.NoError(t, err)
  2589. err = os.RemoveAll(user.GetHomeDir())
  2590. assert.NoError(t, err)
  2591. }
  2592. func TestPermsSubDirsCommands(t *testing.T) {
  2593. usePubKey := true
  2594. u := getTestUser(usePubKey)
  2595. u.Permissions["/"] = []string{dataprovider.PermAny}
  2596. u.Permissions["/subdir"] = []string{dataprovider.PermDownload, dataprovider.PermUpload}
  2597. user, _, err := httpd.AddUser(u, http.StatusOK)
  2598. assert.NoError(t, err)
  2599. client, err := getSftpClient(user, usePubKey)
  2600. if assert.NoError(t, err) {
  2601. defer client.Close()
  2602. err = client.Mkdir("subdir")
  2603. assert.NoError(t, err)
  2604. acmodTime := time.Now()
  2605. err = client.Chtimes("/subdir", acmodTime, acmodTime)
  2606. assert.NoError(t, err)
  2607. _, err = client.Stat("/subdir")
  2608. assert.NoError(t, err)
  2609. _, err = client.ReadDir("/")
  2610. assert.NoError(t, err)
  2611. _, err = client.ReadDir("/subdir")
  2612. if assert.Error(t, err) {
  2613. assert.Contains(t, err.Error(), permissionErrorString)
  2614. }
  2615. err = client.RemoveDirectory("/subdir/dir")
  2616. if assert.Error(t, err) {
  2617. assert.Contains(t, err.Error(), permissionErrorString)
  2618. }
  2619. err = client.Mkdir("/subdir/dir")
  2620. if assert.Error(t, err) {
  2621. assert.Contains(t, err.Error(), permissionErrorString)
  2622. }
  2623. err = client.Mkdir("/otherdir")
  2624. assert.NoError(t, err)
  2625. err = client.Rename("/otherdir", "/subdir/otherdir")
  2626. if assert.Error(t, err) {
  2627. assert.Contains(t, err.Error(), permissionErrorString)
  2628. }
  2629. err = client.Symlink("/otherdir", "/subdir/otherdir")
  2630. if assert.Error(t, err) {
  2631. assert.Contains(t, err.Error(), permissionErrorString)
  2632. }
  2633. err = client.Symlink("/otherdir", "/otherdir_link")
  2634. assert.NoError(t, err)
  2635. err = client.Rename("/otherdir", "/otherdir1")
  2636. assert.NoError(t, err)
  2637. err = client.RemoveDirectory("/subdir")
  2638. assert.NoError(t, err)
  2639. }
  2640. _, err = httpd.RemoveUser(user, http.StatusOK)
  2641. assert.NoError(t, err)
  2642. err = os.RemoveAll(user.GetHomeDir())
  2643. assert.NoError(t, err)
  2644. }
  2645. func TestRootDirCommands(t *testing.T) {
  2646. usePubKey := true
  2647. u := getTestUser(usePubKey)
  2648. u.Permissions["/"] = []string{dataprovider.PermAny}
  2649. u.Permissions["/subdir"] = []string{dataprovider.PermDownload, dataprovider.PermUpload}
  2650. user, _, err := httpd.AddUser(u, http.StatusOK)
  2651. assert.NoError(t, err)
  2652. client, err := getSftpClient(user, usePubKey)
  2653. if assert.NoError(t, err) {
  2654. defer client.Close()
  2655. err = client.Rename("/", "rootdir")
  2656. if assert.Error(t, err) {
  2657. assert.Contains(t, err.Error(), permissionErrorString)
  2658. }
  2659. err = client.Symlink("/", "rootdir")
  2660. if assert.Error(t, err) {
  2661. assert.Contains(t, err.Error(), permissionErrorString)
  2662. }
  2663. err = client.RemoveDirectory("/")
  2664. if assert.Error(t, err) {
  2665. assert.Contains(t, err.Error(), permissionErrorString)
  2666. }
  2667. }
  2668. _, err = httpd.RemoveUser(user, http.StatusOK)
  2669. assert.NoError(t, err)
  2670. err = os.RemoveAll(user.GetHomeDir())
  2671. assert.NoError(t, err)
  2672. }
  2673. func TestRelativePaths(t *testing.T) {
  2674. user := getTestUser(true)
  2675. var path, rel string
  2676. filesystems := []vfs.Fs{vfs.NewOsFs("", user.GetHomeDir(), user.VirtualFolders)}
  2677. keyPrefix := strings.TrimPrefix(user.GetHomeDir(), "/") + "/"
  2678. s3config := vfs.S3FsConfig{
  2679. KeyPrefix: keyPrefix,
  2680. }
  2681. s3fs, _ := vfs.NewS3Fs("", user.GetHomeDir(), s3config)
  2682. gcsConfig := vfs.GCSFsConfig{
  2683. KeyPrefix: keyPrefix,
  2684. }
  2685. gcsfs, _ := vfs.NewGCSFs("", user.GetHomeDir(), gcsConfig)
  2686. if runtime.GOOS != osWindows {
  2687. filesystems = append(filesystems, s3fs, gcsfs)
  2688. }
  2689. rootPath := "/"
  2690. for _, fs := range filesystems {
  2691. path = filepath.Join(user.HomeDir, "/")
  2692. rel = fs.GetRelativePath(path)
  2693. assert.Equal(t, rootPath, rel)
  2694. path = filepath.Join(user.HomeDir, "//")
  2695. rel = fs.GetRelativePath(path)
  2696. assert.Equal(t, rootPath, rel)
  2697. path = filepath.Join(user.HomeDir, "../..")
  2698. rel = fs.GetRelativePath(path)
  2699. assert.Equal(t, rootPath, rel)
  2700. path = filepath.Join(user.HomeDir, "../../../../../")
  2701. rel = fs.GetRelativePath(path)
  2702. assert.Equal(t, rootPath, rel)
  2703. path = filepath.Join(user.HomeDir, "/..")
  2704. rel = fs.GetRelativePath(path)
  2705. assert.Equal(t, rootPath, rel)
  2706. path = filepath.Join(user.HomeDir, "/../../../..")
  2707. rel = fs.GetRelativePath(path)
  2708. assert.Equal(t, rootPath, rel)
  2709. path = filepath.Join(user.HomeDir, "")
  2710. rel = fs.GetRelativePath(path)
  2711. assert.Equal(t, rootPath, rel)
  2712. path = filepath.Join(user.HomeDir, ".")
  2713. rel = fs.GetRelativePath(path)
  2714. assert.Equal(t, rootPath, rel)
  2715. path = filepath.Join(user.HomeDir, "somedir")
  2716. rel = fs.GetRelativePath(path)
  2717. assert.Equal(t, "/somedir", rel)
  2718. path = filepath.Join(user.HomeDir, "/somedir/subdir")
  2719. rel = fs.GetRelativePath(path)
  2720. assert.Equal(t, "/somedir/subdir", rel)
  2721. }
  2722. }
  2723. func TestResolvePaths(t *testing.T) {
  2724. user := getTestUser(true)
  2725. var path, resolved string
  2726. var err error
  2727. filesystems := []vfs.Fs{vfs.NewOsFs("", user.GetHomeDir(), user.VirtualFolders)}
  2728. keyPrefix := strings.TrimPrefix(user.GetHomeDir(), "/") + "/"
  2729. s3config := vfs.S3FsConfig{
  2730. KeyPrefix: keyPrefix,
  2731. Bucket: "bucket",
  2732. Region: "us-east-1",
  2733. }
  2734. err = os.MkdirAll(user.GetHomeDir(), 0777)
  2735. assert.NoError(t, err)
  2736. s3fs, err := vfs.NewS3Fs("", user.GetHomeDir(), s3config)
  2737. assert.NoError(t, err)
  2738. gcsConfig := vfs.GCSFsConfig{
  2739. KeyPrefix: keyPrefix,
  2740. }
  2741. gcsfs, _ := vfs.NewGCSFs("", user.GetHomeDir(), gcsConfig)
  2742. if runtime.GOOS != osWindows {
  2743. filesystems = append(filesystems, s3fs, gcsfs)
  2744. }
  2745. for _, fs := range filesystems {
  2746. path = "/"
  2747. resolved, _ = fs.ResolvePath(filepath.ToSlash(path))
  2748. assert.Equal(t, fs.Join(user.GetHomeDir(), "/"), resolved)
  2749. path = "."
  2750. resolved, _ = fs.ResolvePath(filepath.ToSlash(path))
  2751. assert.Equal(t, fs.Join(user.GetHomeDir(), "/"), resolved)
  2752. path = "test/sub"
  2753. resolved, _ = fs.ResolvePath(filepath.ToSlash(path))
  2754. assert.Equal(t, fs.Join(user.GetHomeDir(), "/test/sub"), resolved)
  2755. path = "../test/sub"
  2756. resolved, err = fs.ResolvePath(filepath.ToSlash(path))
  2757. if vfs.IsLocalOsFs(fs) {
  2758. assert.Error(t, err, "Unexpected resolved path: %v for: %v, fs: %v", resolved, path, fs.Name())
  2759. } else {
  2760. assert.Equal(t, fs.Join(user.GetHomeDir(), "/test/sub"), resolved)
  2761. }
  2762. path = "../../../test/../sub"
  2763. resolved, err = fs.ResolvePath(filepath.ToSlash(path))
  2764. if vfs.IsLocalOsFs(fs) {
  2765. assert.Error(t, err, "Unexpected resolved path: %v for: %v, fs: %v", resolved, path, fs.Name())
  2766. } else {
  2767. assert.Equal(t, fs.Join(user.GetHomeDir(), "/sub"), resolved)
  2768. }
  2769. }
  2770. err = os.RemoveAll(user.GetHomeDir())
  2771. assert.NoError(t, err)
  2772. }
  2773. func TestVirtualRelativePaths(t *testing.T) {
  2774. user := getTestUser(true)
  2775. mappedPath := filepath.Join(os.TempDir(), "vdir")
  2776. vdirPath := "/vdir"
  2777. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  2778. VirtualPath: vdirPath,
  2779. MappedPath: mappedPath,
  2780. })
  2781. err := os.MkdirAll(mappedPath, 0777)
  2782. assert.NoError(t, err)
  2783. fs := vfs.NewOsFs("", user.GetHomeDir(), user.VirtualFolders)
  2784. rel := fs.GetRelativePath(mappedPath)
  2785. assert.Equal(t, vdirPath, rel)
  2786. rel = fs.GetRelativePath(filepath.Join(mappedPath, ".."))
  2787. assert.Equal(t, "/", rel)
  2788. // path outside home and virtual dir
  2789. rel = fs.GetRelativePath(filepath.Join(mappedPath, "../vdir1"))
  2790. assert.Equal(t, "/", rel)
  2791. rel = fs.GetRelativePath(filepath.Join(mappedPath, "../vdir/file.txt"))
  2792. assert.Equal(t, "/vdir/file.txt", rel)
  2793. rel = fs.GetRelativePath(filepath.Join(user.HomeDir, "vdir1/file.txt"))
  2794. assert.Equal(t, "/vdir1/file.txt", rel)
  2795. }
  2796. func TestResolveVirtualPaths(t *testing.T) {
  2797. user := getTestUser(true)
  2798. mappedPath := filepath.Join(os.TempDir(), "vdir")
  2799. vdirPath := "/vdir"
  2800. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  2801. VirtualPath: vdirPath,
  2802. MappedPath: mappedPath,
  2803. })
  2804. err := os.MkdirAll(mappedPath, 0777)
  2805. assert.NoError(t, err)
  2806. osFs := vfs.NewOsFs("", user.GetHomeDir(), user.VirtualFolders).(vfs.OsFs)
  2807. b, f := osFs.GetFsPaths("/vdir/a.txt")
  2808. assert.Equal(t, mappedPath, b)
  2809. assert.Equal(t, filepath.Join(mappedPath, "a.txt"), f)
  2810. b, f = osFs.GetFsPaths("/vdir/sub with space & spécial chars/a.txt")
  2811. assert.Equal(t, mappedPath, b)
  2812. assert.Equal(t, filepath.Join(mappedPath, "sub with space & spécial chars/a.txt"), f)
  2813. b, f = osFs.GetFsPaths("/vdir/../a.txt")
  2814. assert.Equal(t, user.GetHomeDir(), b)
  2815. assert.Equal(t, filepath.Join(user.GetHomeDir(), "a.txt"), f)
  2816. b, f = osFs.GetFsPaths("/vdir1/a.txt")
  2817. assert.Equal(t, user.GetHomeDir(), b)
  2818. assert.Equal(t, filepath.Join(user.GetHomeDir(), "/vdir1/a.txt"), f)
  2819. }
  2820. func TestVirtualFoldersExcludeQuota(t *testing.T) {
  2821. user := getTestUser(true)
  2822. mappedPath := filepath.Join(os.TempDir(), "vdir")
  2823. vdirPath := "/vdir/sub"
  2824. vSubDirPath := path.Join(vdirPath, "subdir", "subdir")
  2825. vSubDir1Path := path.Join(vSubDirPath, "subdir", "subdir")
  2826. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  2827. VirtualPath: vdirPath,
  2828. MappedPath: mappedPath,
  2829. ExcludeFromQuota: false,
  2830. })
  2831. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  2832. VirtualPath: vSubDir1Path,
  2833. MappedPath: mappedPath,
  2834. ExcludeFromQuota: false,
  2835. })
  2836. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  2837. VirtualPath: vSubDirPath,
  2838. MappedPath: mappedPath,
  2839. ExcludeFromQuota: true,
  2840. })
  2841. assert.False(t, user.IsFileExcludedFromQuota("/file"))
  2842. assert.False(t, user.IsFileExcludedFromQuota(path.Join(vdirPath, "file")))
  2843. assert.True(t, user.IsFileExcludedFromQuota(path.Join(vSubDirPath, "file")))
  2844. assert.True(t, user.IsFileExcludedFromQuota(path.Join(vSubDir1Path, "..", "file")))
  2845. assert.False(t, user.IsFileExcludedFromQuota(path.Join(vSubDir1Path, "file")))
  2846. assert.False(t, user.IsFileExcludedFromQuota(path.Join(vSubDirPath, "..", "file")))
  2847. // we check the parent dir for a file
  2848. assert.False(t, user.IsFileExcludedFromQuota(vSubDirPath))
  2849. }
  2850. func TestUserPerms(t *testing.T) {
  2851. user := getTestUser(true)
  2852. user.Permissions = make(map[string][]string)
  2853. user.Permissions["/"] = []string{dataprovider.PermListItems}
  2854. user.Permissions["/p"] = []string{dataprovider.PermDelete}
  2855. user.Permissions["/p/1"] = []string{dataprovider.PermDownload, dataprovider.PermUpload}
  2856. user.Permissions["/p/2"] = []string{dataprovider.PermCreateDirs}
  2857. user.Permissions["/p/3"] = []string{dataprovider.PermChmod}
  2858. user.Permissions["/p/3/4"] = []string{dataprovider.PermChtimes}
  2859. user.Permissions["/tmp"] = []string{dataprovider.PermRename}
  2860. assert.True(t, user.HasPerm(dataprovider.PermListItems, "/"))
  2861. assert.True(t, user.HasPerm(dataprovider.PermListItems, "."))
  2862. assert.True(t, user.HasPerm(dataprovider.PermListItems, ""))
  2863. assert.True(t, user.HasPerm(dataprovider.PermListItems, "../"))
  2864. // path p and /p are the same
  2865. assert.True(t, user.HasPerm(dataprovider.PermDelete, "/p"))
  2866. assert.True(t, user.HasPerm(dataprovider.PermDownload, "/p/1"))
  2867. assert.True(t, user.HasPerm(dataprovider.PermCreateDirs, "p/2"))
  2868. assert.True(t, user.HasPerm(dataprovider.PermChmod, "/p/3"))
  2869. assert.True(t, user.HasPerm(dataprovider.PermChtimes, "p/3/4/"))
  2870. assert.True(t, user.HasPerm(dataprovider.PermChtimes, "p/3/4/../4"))
  2871. // undefined paths have permissions of the nearest path
  2872. assert.True(t, user.HasPerm(dataprovider.PermListItems, "/p34"))
  2873. assert.True(t, user.HasPerm(dataprovider.PermListItems, "/p34/p1/file.dat"))
  2874. assert.True(t, user.HasPerm(dataprovider.PermChtimes, "/p/3/4/5/6"))
  2875. assert.True(t, user.HasPerm(dataprovider.PermDownload, "/p/1/test/file.dat"))
  2876. }
  2877. func TestFilterFileExtensions(t *testing.T) {
  2878. user := getTestUser(true)
  2879. extension := dataprovider.ExtensionsFilter{
  2880. Path: "/test",
  2881. AllowedExtensions: []string{".jpg", ".png"},
  2882. DeniedExtensions: []string{".pdf"},
  2883. }
  2884. filters := dataprovider.UserFilters{
  2885. FileExtensions: []dataprovider.ExtensionsFilter{extension},
  2886. }
  2887. user.Filters = filters
  2888. assert.True(t, user.IsFileAllowed("/test/test.jPg"))
  2889. assert.False(t, user.IsFileAllowed("/test/test.pdf"))
  2890. assert.True(t, user.IsFileAllowed("/test.pDf"))
  2891. filters.FileExtensions = append(filters.FileExtensions, dataprovider.ExtensionsFilter{
  2892. Path: "/",
  2893. AllowedExtensions: []string{".zip", ".rar", ".pdf"},
  2894. DeniedExtensions: []string{".gz"},
  2895. })
  2896. user.Filters = filters
  2897. assert.False(t, user.IsFileAllowed("/test1/test.gz"))
  2898. assert.True(t, user.IsFileAllowed("/test1/test.zip"))
  2899. assert.False(t, user.IsFileAllowed("/test/sub/test.pdf"))
  2900. assert.False(t, user.IsFileAllowed("/test1/test.png"))
  2901. filters.FileExtensions = append(filters.FileExtensions, dataprovider.ExtensionsFilter{
  2902. Path: "/test/sub",
  2903. DeniedExtensions: []string{".tar"},
  2904. })
  2905. user.Filters = filters
  2906. assert.False(t, user.IsFileAllowed("/test/sub/sub/test.tar"))
  2907. assert.True(t, user.IsFileAllowed("/test/sub/test.gz"))
  2908. assert.False(t, user.IsFileAllowed("/test/test.zip"))
  2909. }
  2910. func TestUserAllowedLoginMethods(t *testing.T) {
  2911. user := getTestUser(true)
  2912. user.Filters.DeniedLoginMethods = dataprovider.ValidSSHLoginMethods
  2913. allowedMethods := user.GetAllowedLoginMethods()
  2914. assert.Equal(t, 0, len(allowedMethods))
  2915. user.Filters.DeniedLoginMethods = []string{
  2916. dataprovider.SSHLoginMethodPassword,
  2917. dataprovider.SSHLoginMethodPublicKey,
  2918. dataprovider.SSHLoginMethodKeyboardInteractive,
  2919. }
  2920. allowedMethods = user.GetAllowedLoginMethods()
  2921. assert.Equal(t, 2, len(allowedMethods))
  2922. assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodKeyAndKeyboardInt, allowedMethods))
  2923. assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodKeyAndPassword, allowedMethods))
  2924. }
  2925. func TestUserPartialAuth(t *testing.T) {
  2926. user := getTestUser(true)
  2927. user.Filters.DeniedLoginMethods = []string{
  2928. dataprovider.SSHLoginMethodPassword,
  2929. dataprovider.SSHLoginMethodPublicKey,
  2930. dataprovider.SSHLoginMethodKeyboardInteractive,
  2931. }
  2932. assert.False(t, user.IsPartialAuth(dataprovider.SSHLoginMethodPassword))
  2933. assert.False(t, user.IsPartialAuth(dataprovider.SSHLoginMethodKeyboardInteractive))
  2934. assert.True(t, user.IsPartialAuth(dataprovider.SSHLoginMethodPublicKey))
  2935. user.Filters.DeniedLoginMethods = []string{
  2936. dataprovider.SSHLoginMethodPassword,
  2937. dataprovider.SSHLoginMethodKeyboardInteractive,
  2938. }
  2939. assert.False(t, user.IsPartialAuth(dataprovider.SSHLoginMethodPublicKey))
  2940. user.Filters.DeniedLoginMethods = []string{
  2941. dataprovider.SSHLoginMethodPassword,
  2942. dataprovider.SSHLoginMethodPublicKey,
  2943. }
  2944. assert.False(t, user.IsPartialAuth(dataprovider.SSHLoginMethodPublicKey))
  2945. }
  2946. func TestUserGetNextAuthMethods(t *testing.T) {
  2947. user := getTestUser(true)
  2948. user.Filters.DeniedLoginMethods = []string{
  2949. dataprovider.SSHLoginMethodPassword,
  2950. dataprovider.SSHLoginMethodPublicKey,
  2951. dataprovider.SSHLoginMethodKeyboardInteractive,
  2952. }
  2953. methods := user.GetNextAuthMethods(nil)
  2954. assert.Equal(t, 0, len(methods))
  2955. methods = user.GetNextAuthMethods([]string{dataprovider.SSHLoginMethodPassword})
  2956. assert.Equal(t, 0, len(methods))
  2957. methods = user.GetNextAuthMethods([]string{dataprovider.SSHLoginMethodKeyboardInteractive})
  2958. assert.Equal(t, 0, len(methods))
  2959. methods = user.GetNextAuthMethods([]string{
  2960. dataprovider.SSHLoginMethodPublicKey,
  2961. dataprovider.SSHLoginMethodKeyboardInteractive,
  2962. })
  2963. assert.Equal(t, 0, len(methods))
  2964. methods = user.GetNextAuthMethods([]string{dataprovider.SSHLoginMethodPublicKey})
  2965. assert.Equal(t, 2, len(methods))
  2966. assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodPassword, methods))
  2967. assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodKeyboardInteractive, methods))
  2968. user.Filters.DeniedLoginMethods = []string{
  2969. dataprovider.SSHLoginMethodPassword,
  2970. dataprovider.SSHLoginMethodPublicKey,
  2971. dataprovider.SSHLoginMethodKeyboardInteractive,
  2972. dataprovider.SSHLoginMethodKeyAndKeyboardInt,
  2973. }
  2974. methods = user.GetNextAuthMethods([]string{dataprovider.SSHLoginMethodPublicKey})
  2975. assert.Equal(t, 1, len(methods))
  2976. assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodPassword, methods))
  2977. user.Filters.DeniedLoginMethods = []string{
  2978. dataprovider.SSHLoginMethodPassword,
  2979. dataprovider.SSHLoginMethodPublicKey,
  2980. dataprovider.SSHLoginMethodKeyboardInteractive,
  2981. dataprovider.SSHLoginMethodKeyAndPassword,
  2982. }
  2983. methods = user.GetNextAuthMethods([]string{dataprovider.SSHLoginMethodPublicKey})
  2984. assert.Equal(t, 1, len(methods))
  2985. assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodKeyboardInteractive, methods))
  2986. }
  2987. func TestUserIsLoginMethodAllowed(t *testing.T) {
  2988. user := getTestUser(true)
  2989. user.Filters.DeniedLoginMethods = []string{
  2990. dataprovider.SSHLoginMethodPassword,
  2991. dataprovider.SSHLoginMethodPublicKey,
  2992. dataprovider.SSHLoginMethodKeyboardInteractive,
  2993. }
  2994. assert.False(t, user.IsLoginMethodAllowed(dataprovider.SSHLoginMethodPassword, nil))
  2995. assert.True(t, user.IsLoginMethodAllowed(dataprovider.SSHLoginMethodPassword, []string{dataprovider.SSHLoginMethodPublicKey}))
  2996. assert.True(t, user.IsLoginMethodAllowed(dataprovider.SSHLoginMethodKeyboardInteractive, []string{dataprovider.SSHLoginMethodPublicKey}))
  2997. user.Filters.DeniedLoginMethods = []string{
  2998. dataprovider.SSHLoginMethodPublicKey,
  2999. dataprovider.SSHLoginMethodKeyboardInteractive,
  3000. }
  3001. assert.True(t, user.IsLoginMethodAllowed(dataprovider.SSHLoginMethodPassword, nil))
  3002. }
  3003. func TestUserEmptySubDirPerms(t *testing.T) {
  3004. user := getTestUser(true)
  3005. user.Permissions = make(map[string][]string)
  3006. user.Permissions["/emptyperms"] = []string{}
  3007. for _, p := range dataprovider.ValidPerms {
  3008. assert.False(t, user.HasPerm(p, "/emptyperms"))
  3009. }
  3010. }
  3011. func TestUserFiltersIPMaskConditions(t *testing.T) {
  3012. user := getTestUser(true)
  3013. // with no filter login must be allowed even if the remoteIP is invalid
  3014. assert.True(t, user.IsLoginFromAddrAllowed("192.168.1.5"))
  3015. assert.True(t, user.IsLoginFromAddrAllowed("invalid"))
  3016. user.Filters.DeniedIP = append(user.Filters.DeniedIP, "192.168.1.0/24")
  3017. assert.False(t, user.IsLoginFromAddrAllowed("192.168.1.5"))
  3018. assert.True(t, user.IsLoginFromAddrAllowed("192.168.2.6"))
  3019. user.Filters.AllowedIP = append(user.Filters.AllowedIP, "192.168.1.5/32")
  3020. // if the same ip/mask is both denied and allowed then login must be denied
  3021. assert.False(t, user.IsLoginFromAddrAllowed("192.168.1.5"))
  3022. assert.False(t, user.IsLoginFromAddrAllowed("192.168.3.6"))
  3023. user.Filters.DeniedIP = []string{}
  3024. assert.True(t, user.IsLoginFromAddrAllowed("192.168.1.5"))
  3025. assert.False(t, user.IsLoginFromAddrAllowed("192.168.1.6"))
  3026. user.Filters.DeniedIP = []string{"192.168.0.0/16", "172.16.0.0/16"}
  3027. user.Filters.AllowedIP = []string{}
  3028. assert.False(t, user.IsLoginFromAddrAllowed("192.168.5.255"))
  3029. assert.False(t, user.IsLoginFromAddrAllowed("172.16.1.2"))
  3030. assert.True(t, user.IsLoginFromAddrAllowed("172.18.2.1"))
  3031. user.Filters.AllowedIP = []string{"10.4.4.0/24"}
  3032. assert.False(t, user.IsLoginFromAddrAllowed("10.5.4.2"))
  3033. assert.True(t, user.IsLoginFromAddrAllowed("10.4.4.2"))
  3034. assert.True(t, user.IsLoginFromAddrAllowed("invalid"))
  3035. }
  3036. func TestSSHCommands(t *testing.T) {
  3037. usePubKey := false
  3038. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  3039. assert.NoError(t, err)
  3040. _, err = runSSHCommand("ls", user, usePubKey)
  3041. assert.Error(t, err, "unsupported ssh command must fail")
  3042. _, err = runSSHCommand("cd", user, usePubKey)
  3043. assert.NoError(t, err)
  3044. out, err := runSSHCommand("pwd", user, usePubKey)
  3045. if assert.NoError(t, err) {
  3046. assert.Equal(t, "/\n", string(out))
  3047. }
  3048. out, err = runSSHCommand("md5sum", user, usePubKey)
  3049. assert.NoError(t, err)
  3050. // echo -n '' | md5sum
  3051. assert.Contains(t, string(out), "d41d8cd98f00b204e9800998ecf8427e")
  3052. out, err = runSSHCommand("sha1sum", user, usePubKey)
  3053. assert.NoError(t, err)
  3054. assert.Contains(t, string(out), "da39a3ee5e6b4b0d3255bfef95601890afd80709")
  3055. out, err = runSSHCommand("sha256sum", user, usePubKey)
  3056. assert.NoError(t, err)
  3057. assert.Contains(t, string(out), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
  3058. out, err = runSSHCommand("sha384sum", user, usePubKey)
  3059. assert.NoError(t, err)
  3060. assert.Contains(t, string(out), "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b")
  3061. _, err = httpd.RemoveUser(user, http.StatusOK)
  3062. assert.NoError(t, err)
  3063. }
  3064. func TestSSHFileHash(t *testing.T) {
  3065. usePubKey := true
  3066. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  3067. assert.NoError(t, err)
  3068. client, err := getSftpClient(user, usePubKey)
  3069. if assert.NoError(t, err) {
  3070. defer client.Close()
  3071. testFileName := "test_file.dat"
  3072. testFilePath := filepath.Join(homeBasePath, testFileName)
  3073. testFileSize := int64(65535)
  3074. err = createTestFile(testFilePath, testFileSize)
  3075. assert.NoError(t, err)
  3076. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  3077. assert.NoError(t, err)
  3078. user.Permissions = make(map[string][]string)
  3079. user.Permissions["/"] = []string{dataprovider.PermUpload}
  3080. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  3081. assert.NoError(t, err)
  3082. _, err = runSSHCommand("sha512sum "+testFileName, user, usePubKey)
  3083. assert.Error(t, err, "hash command with no list permission must fail")
  3084. user.Permissions["/"] = []string{dataprovider.PermAny}
  3085. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  3086. assert.NoError(t, err)
  3087. initialHash, err := computeHashForFile(sha512.New(), testFilePath)
  3088. assert.NoError(t, err)
  3089. out, err := runSSHCommand("sha512sum "+testFileName, user, usePubKey)
  3090. if assert.NoError(t, err) {
  3091. assert.Contains(t, string(out), initialHash)
  3092. }
  3093. _, err = runSSHCommand("sha512sum invalid_path", user, usePubKey)
  3094. assert.Error(t, err, "hash for an invalid path must fail")
  3095. err = os.Remove(testFilePath)
  3096. assert.NoError(t, err)
  3097. }
  3098. _, err = httpd.RemoveUser(user, http.StatusOK)
  3099. assert.NoError(t, err)
  3100. err = os.RemoveAll(user.GetHomeDir())
  3101. assert.NoError(t, err)
  3102. }
  3103. func TestBasicGitCommands(t *testing.T) {
  3104. if len(gitPath) == 0 || len(sshPath) == 0 || runtime.GOOS == osWindows {
  3105. t.Skip("git and/or ssh command not found or OS is windows, unable to execute this test")
  3106. }
  3107. usePubKey := true
  3108. u := getTestUser(usePubKey)
  3109. user, _, err := httpd.AddUser(u, http.StatusOK)
  3110. assert.NoError(t, err)
  3111. repoName := "testrepo"
  3112. clonePath := filepath.Join(homeBasePath, repoName)
  3113. err = os.RemoveAll(user.GetHomeDir())
  3114. assert.NoError(t, err)
  3115. err = os.RemoveAll(filepath.Join(homeBasePath, repoName))
  3116. assert.NoError(t, err)
  3117. out, err := initGitRepo(filepath.Join(user.HomeDir, repoName))
  3118. assert.NoError(t, err, "unexpected error, out: %v", string(out))
  3119. out, err = cloneGitRepo(homeBasePath, "/"+repoName, user.Username)
  3120. assert.NoError(t, err, "unexpected error, out: %v", string(out))
  3121. out, err = addFileToGitRepo(clonePath, 128)
  3122. assert.NoError(t, err, "unexpected error, out: %v", string(out))
  3123. user.QuotaFiles = 100000
  3124. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  3125. assert.NoError(t, err)
  3126. out, err = pushToGitRepo(clonePath)
  3127. if !assert.NoError(t, err, "unexpected error, out: %v", string(out)) {
  3128. printLatestLogs(10)
  3129. }
  3130. err = waitQuotaScans()
  3131. assert.NoError(t, err)
  3132. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3133. assert.NoError(t, err)
  3134. user.QuotaSize = user.UsedQuotaSize - 1
  3135. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  3136. assert.NoError(t, err)
  3137. out, err = pushToGitRepo(clonePath)
  3138. assert.Error(t, err, "git push must fail if quota is exceeded, out: %v", string(out))
  3139. _, err = httpd.RemoveUser(user, http.StatusOK)
  3140. assert.NoError(t, err)
  3141. err = os.RemoveAll(user.GetHomeDir())
  3142. assert.NoError(t, err)
  3143. err = os.RemoveAll(clonePath)
  3144. assert.NoError(t, err)
  3145. }
  3146. func TestGitErrors(t *testing.T) {
  3147. if len(gitPath) == 0 || len(sshPath) == 0 || runtime.GOOS == osWindows {
  3148. t.Skip("git and/or ssh command not found or OS is windows, unable to execute this test")
  3149. }
  3150. usePubKey := true
  3151. u := getTestUser(usePubKey)
  3152. user, _, err := httpd.AddUser(u, http.StatusOK)
  3153. assert.NoError(t, err)
  3154. repoName := "testrepo"
  3155. clonePath := filepath.Join(homeBasePath, repoName)
  3156. err = os.RemoveAll(user.GetHomeDir())
  3157. assert.NoError(t, err)
  3158. err = os.RemoveAll(filepath.Join(homeBasePath, repoName))
  3159. assert.NoError(t, err)
  3160. out, err := cloneGitRepo(homeBasePath, "/"+repoName, user.Username)
  3161. assert.Error(t, err, "cloning a missing repo must fail, out: %v", string(out))
  3162. _, err = httpd.RemoveUser(user, http.StatusOK)
  3163. assert.NoError(t, err)
  3164. err = os.RemoveAll(user.GetHomeDir())
  3165. assert.NoError(t, err)
  3166. err = os.RemoveAll(clonePath)
  3167. assert.NoError(t, err)
  3168. }
  3169. // Start SCP tests
  3170. func TestSCPBasicHandling(t *testing.T) {
  3171. if len(scpPath) == 0 {
  3172. t.Skip("scp command not found, unable to execute this test")
  3173. }
  3174. usePubKey := true
  3175. u := getTestUser(usePubKey)
  3176. u.QuotaSize = 6553600
  3177. user, _, err := httpd.AddUser(u, http.StatusOK)
  3178. assert.NoError(t, err)
  3179. testFileName := "test_file.dat"
  3180. testFilePath := filepath.Join(homeBasePath, testFileName)
  3181. testFileSize := int64(131074)
  3182. expectedQuotaSize := user.UsedQuotaSize + testFileSize
  3183. expectedQuotaFiles := user.UsedQuotaFiles + 1
  3184. err = createTestFile(testFilePath, testFileSize)
  3185. assert.NoError(t, err)
  3186. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/")
  3187. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  3188. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  3189. // test to download a missing file
  3190. err = scpDownload(localPath, remoteDownPath, false, false)
  3191. assert.Error(t, err, "downloading a missing file via scp must fail")
  3192. err = scpUpload(testFilePath, remoteUpPath, false, false)
  3193. assert.NoError(t, err)
  3194. err = scpDownload(localPath, remoteDownPath, false, false)
  3195. assert.NoError(t, err)
  3196. fi, err := os.Stat(localPath)
  3197. if assert.NoError(t, err) {
  3198. assert.Equal(t, testFileSize, fi.Size())
  3199. }
  3200. err = os.Remove(localPath)
  3201. assert.NoError(t, err)
  3202. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3203. assert.NoError(t, err)
  3204. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  3205. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  3206. assert.NoError(t, err)
  3207. _, err = httpd.RemoveUser(user, http.StatusOK)
  3208. assert.NoError(t, err)
  3209. err = os.Remove(testFilePath)
  3210. assert.NoError(t, err)
  3211. }
  3212. func TestSCPUploadFileOverwrite(t *testing.T) {
  3213. if len(scpPath) == 0 {
  3214. t.Skip("scp command not found, unable to execute this test")
  3215. }
  3216. usePubKey := true
  3217. u := getTestUser(usePubKey)
  3218. u.QuotaFiles = 1000
  3219. user, _, err := httpd.AddUser(u, http.StatusOK)
  3220. assert.NoError(t, err)
  3221. err = os.RemoveAll(user.GetHomeDir())
  3222. assert.NoError(t, err)
  3223. testFileName := "test_file.dat"
  3224. testFilePath := filepath.Join(homeBasePath, testFileName)
  3225. testFileSize := int64(32760)
  3226. err = createTestFile(testFilePath, testFileSize)
  3227. assert.NoError(t, err)
  3228. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  3229. err = scpUpload(testFilePath, remoteUpPath, true, false)
  3230. assert.NoError(t, err)
  3231. // test a new upload that must overwrite the existing file
  3232. err = scpUpload(testFilePath, remoteUpPath, true, false)
  3233. assert.NoError(t, err)
  3234. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3235. assert.NoError(t, err)
  3236. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  3237. assert.Equal(t, 1, user.UsedQuotaFiles)
  3238. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  3239. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  3240. err = scpDownload(localPath, remoteDownPath, false, false)
  3241. assert.NoError(t, err)
  3242. fi, err := os.Stat(localPath)
  3243. if assert.NoError(t, err) {
  3244. assert.Equal(t, testFileSize, fi.Size())
  3245. }
  3246. err = os.Remove(localPath)
  3247. assert.NoError(t, err)
  3248. err = os.Remove(testFilePath)
  3249. assert.NoError(t, err)
  3250. err = os.RemoveAll(user.GetHomeDir())
  3251. assert.NoError(t, err)
  3252. _, err = httpd.RemoveUser(user, http.StatusOK)
  3253. assert.NoError(t, err)
  3254. }
  3255. func TestSCPRecursive(t *testing.T) {
  3256. if len(scpPath) == 0 {
  3257. t.Skip("scp command not found, unable to execute this test")
  3258. }
  3259. usePubKey := true
  3260. u := getTestUser(usePubKey)
  3261. user, _, err := httpd.AddUser(u, http.StatusOK)
  3262. assert.NoError(t, err)
  3263. testFileName := "test_file.dat"
  3264. testBaseDirName := "test_dir"
  3265. testBaseDirPath := filepath.Join(homeBasePath, testBaseDirName)
  3266. testBaseDirDownName := "test_dir_down" //nolint:goconst
  3267. testBaseDirDownPath := filepath.Join(homeBasePath, testBaseDirDownName)
  3268. testFilePath := filepath.Join(homeBasePath, testBaseDirName, testFileName)
  3269. testFilePath1 := filepath.Join(homeBasePath, testBaseDirName, testBaseDirName, testFileName)
  3270. testFileSize := int64(131074)
  3271. err = createTestFile(testFilePath, testFileSize)
  3272. assert.NoError(t, err)
  3273. err = createTestFile(testFilePath1, testFileSize)
  3274. assert.NoError(t, err)
  3275. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testBaseDirName))
  3276. // test to download a missing dir
  3277. err = scpDownload(testBaseDirDownPath, remoteDownPath, true, true)
  3278. assert.Error(t, err, "downloading a missing dir via scp must fail")
  3279. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/")
  3280. err = scpUpload(testBaseDirPath, remoteUpPath, true, false)
  3281. assert.NoError(t, err)
  3282. // overwrite existing dir
  3283. err = scpUpload(testBaseDirPath, remoteUpPath, true, false)
  3284. assert.NoError(t, err)
  3285. err = scpDownload(testBaseDirDownPath, remoteDownPath, true, true)
  3286. assert.NoError(t, err)
  3287. // test download without passing -r
  3288. err = scpDownload(testBaseDirDownPath, remoteDownPath, true, false)
  3289. assert.Error(t, err, "recursive download without -r must fail")
  3290. fi, err := os.Stat(filepath.Join(testBaseDirDownPath, testFileName))
  3291. if assert.NoError(t, err) {
  3292. assert.Equal(t, testFileSize, fi.Size())
  3293. }
  3294. fi, err = os.Stat(filepath.Join(testBaseDirDownPath, testBaseDirName, testFileName))
  3295. if assert.NoError(t, err) {
  3296. assert.Equal(t, testFileSize, fi.Size())
  3297. }
  3298. // upload to a non existent dir
  3299. remoteUpPath = fmt.Sprintf("%[email protected]:%v", user.Username, "/non_existent_dir")
  3300. err = scpUpload(testBaseDirPath, remoteUpPath, true, false)
  3301. assert.Error(t, err, "uploading via scp to a non existent dir must fail")
  3302. err = os.RemoveAll(testBaseDirPath)
  3303. assert.NoError(t, err)
  3304. err = os.RemoveAll(testBaseDirDownPath)
  3305. assert.NoError(t, err)
  3306. err = os.RemoveAll(user.GetHomeDir())
  3307. assert.NoError(t, err)
  3308. _, err = httpd.RemoveUser(user, http.StatusOK)
  3309. assert.NoError(t, err)
  3310. }
  3311. func TestSCPExtensionsFilter(t *testing.T) {
  3312. if len(scpPath) == 0 {
  3313. t.Skip("scp command not found, unable to execute this test")
  3314. }
  3315. usePubKey := true
  3316. u := getTestUser(usePubKey)
  3317. user, _, err := httpd.AddUser(u, http.StatusOK)
  3318. assert.NoError(t, err)
  3319. testFileSize := int64(131072)
  3320. testFileName := "test_file.dat"
  3321. testFilePath := filepath.Join(homeBasePath, testFileName)
  3322. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  3323. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/")
  3324. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  3325. err = createTestFile(testFilePath, testFileSize)
  3326. assert.NoError(t, err)
  3327. err = scpUpload(testFilePath, remoteUpPath, false, false)
  3328. assert.NoError(t, err)
  3329. user.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  3330. {
  3331. Path: "/",
  3332. AllowedExtensions: []string{".zip"},
  3333. DeniedExtensions: []string{},
  3334. },
  3335. }
  3336. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  3337. assert.NoError(t, err)
  3338. err = scpDownload(localPath, remoteDownPath, false, false)
  3339. assert.Error(t, err, "scp download must fail")
  3340. err = scpUpload(testFilePath, remoteUpPath, false, false)
  3341. assert.Error(t, err, "scp upload must fail")
  3342. _, err = httpd.RemoveUser(user, http.StatusOK)
  3343. assert.NoError(t, err)
  3344. err = os.Remove(testFilePath)
  3345. assert.NoError(t, err)
  3346. _, err = os.Stat(localPath)
  3347. if err == nil {
  3348. err = os.Remove(localPath)
  3349. assert.NoError(t, err)
  3350. }
  3351. err = os.RemoveAll(user.GetHomeDir())
  3352. assert.NoError(t, err)
  3353. }
  3354. func TestSCPVirtualFolders(t *testing.T) {
  3355. if len(scpPath) == 0 {
  3356. t.Skip("scp command not found, unable to execute this test")
  3357. }
  3358. usePubKey := true
  3359. u := getTestUser(usePubKey)
  3360. mappedPath := filepath.Join(os.TempDir(), "vdir")
  3361. vdirPath := "/vdir"
  3362. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  3363. VirtualPath: vdirPath,
  3364. MappedPath: mappedPath,
  3365. })
  3366. err := os.MkdirAll(mappedPath, 0777)
  3367. assert.NoError(t, err)
  3368. user, _, err := httpd.AddUser(u, http.StatusOK)
  3369. assert.NoError(t, err)
  3370. testFileName := "test_file.dat"
  3371. testBaseDirName := "test_dir"
  3372. testBaseDirPath := filepath.Join(homeBasePath, testBaseDirName)
  3373. testBaseDirDownName := "test_dir_down"
  3374. testBaseDirDownPath := filepath.Join(homeBasePath, testBaseDirDownName)
  3375. testFilePath := filepath.Join(homeBasePath, testBaseDirName, testFileName)
  3376. testFilePath1 := filepath.Join(homeBasePath, testBaseDirName, testBaseDirName, testFileName)
  3377. testFileSize := int64(131074)
  3378. err = createTestFile(testFilePath, testFileSize)
  3379. assert.NoError(t, err)
  3380. err = createTestFile(testFilePath1, testFileSize)
  3381. assert.NoError(t, err)
  3382. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", vdirPath))
  3383. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, vdirPath)
  3384. err = scpUpload(testBaseDirPath, remoteUpPath, true, false)
  3385. assert.NoError(t, err)
  3386. err = scpDownload(testBaseDirDownPath, remoteDownPath, true, true)
  3387. assert.NoError(t, err)
  3388. _, err = httpd.RemoveUser(user, http.StatusOK)
  3389. assert.NoError(t, err)
  3390. err = os.RemoveAll(testBaseDirPath)
  3391. assert.NoError(t, err)
  3392. err = os.RemoveAll(testBaseDirDownPath)
  3393. assert.NoError(t, err)
  3394. err = os.RemoveAll(user.GetHomeDir())
  3395. assert.NoError(t, err)
  3396. err = os.RemoveAll(mappedPath)
  3397. assert.NoError(t, err)
  3398. }
  3399. func TestSCPVirtualFoldersQuota(t *testing.T) {
  3400. if len(scpPath) == 0 {
  3401. t.Skip("scp command not found, unable to execute this test")
  3402. }
  3403. usePubKey := true
  3404. u := getTestUser(usePubKey)
  3405. u.QuotaFiles = 100
  3406. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  3407. vdirPath1 := "/vdir1"
  3408. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  3409. vdirPath2 := "/vdir2"
  3410. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  3411. VirtualPath: vdirPath1,
  3412. MappedPath: mappedPath1,
  3413. })
  3414. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  3415. VirtualPath: vdirPath2,
  3416. MappedPath: mappedPath2,
  3417. ExcludeFromQuota: true,
  3418. })
  3419. err := os.MkdirAll(mappedPath1, 0777)
  3420. assert.NoError(t, err)
  3421. err = os.MkdirAll(mappedPath2, 0777)
  3422. assert.NoError(t, err)
  3423. user, _, err := httpd.AddUser(u, http.StatusOK)
  3424. assert.NoError(t, err)
  3425. testFileName := "test_file.dat"
  3426. testBaseDirName := "test_dir"
  3427. testBaseDirPath := filepath.Join(homeBasePath, testBaseDirName)
  3428. testBaseDirDownName := "test_dir_down"
  3429. testBaseDirDownPath := filepath.Join(homeBasePath, testBaseDirDownName)
  3430. testFilePath := filepath.Join(homeBasePath, testBaseDirName, testFileName)
  3431. testFilePath1 := filepath.Join(homeBasePath, testBaseDirName, testBaseDirName, testFileName)
  3432. testFileSize := int64(131074)
  3433. err = createTestFile(testFilePath, testFileSize)
  3434. assert.NoError(t, err)
  3435. err = createTestFile(testFilePath1, testFileSize)
  3436. assert.NoError(t, err)
  3437. remoteDownPath1 := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", vdirPath1))
  3438. remoteUpPath1 := fmt.Sprintf("%[email protected]:%v", user.Username, vdirPath1)
  3439. remoteDownPath2 := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", vdirPath2))
  3440. remoteUpPath2 := fmt.Sprintf("%[email protected]:%v", user.Username, vdirPath2)
  3441. err = scpUpload(testBaseDirPath, remoteUpPath1, true, false)
  3442. assert.NoError(t, err)
  3443. err = scpDownload(testBaseDirDownPath, remoteDownPath1, true, true)
  3444. assert.NoError(t, err)
  3445. err = scpUpload(testBaseDirPath, remoteUpPath2, true, false)
  3446. assert.NoError(t, err)
  3447. err = scpDownload(testBaseDirDownPath, remoteDownPath2, true, true)
  3448. assert.NoError(t, err)
  3449. expectedQuotaFiles := 2
  3450. expectedQuotaSize := testFileSize * 2
  3451. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3452. assert.NoError(t, err)
  3453. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  3454. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  3455. _, err = httpd.RemoveUser(user, http.StatusOK)
  3456. assert.NoError(t, err)
  3457. err = os.RemoveAll(testBaseDirPath)
  3458. assert.NoError(t, err)
  3459. err = os.RemoveAll(testBaseDirDownPath)
  3460. assert.NoError(t, err)
  3461. err = os.RemoveAll(user.GetHomeDir())
  3462. assert.NoError(t, err)
  3463. err = os.RemoveAll(mappedPath1)
  3464. assert.NoError(t, err)
  3465. err = os.RemoveAll(mappedPath1)
  3466. assert.NoError(t, err)
  3467. }
  3468. func TestSCPPermsSubDirs(t *testing.T) {
  3469. if len(scpPath) == 0 {
  3470. t.Skip("scp command not found, unable to execute this test")
  3471. }
  3472. usePubKey := true
  3473. u := getTestUser(usePubKey)
  3474. u.Permissions["/"] = []string{dataprovider.PermAny}
  3475. u.Permissions["/somedir"] = []string{dataprovider.PermListItems, dataprovider.PermUpload}
  3476. user, _, err := httpd.AddUser(u, http.StatusOK)
  3477. assert.NoError(t, err)
  3478. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  3479. subPath := filepath.Join(user.GetHomeDir(), "somedir")
  3480. testFileSize := int64(65535)
  3481. err = os.MkdirAll(subPath, 0777)
  3482. assert.NoError(t, err)
  3483. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/somedir")
  3484. err = scpDownload(localPath, remoteDownPath, false, true)
  3485. assert.Error(t, err, "download a dir with no permissions must fail")
  3486. err = os.Remove(subPath)
  3487. assert.NoError(t, err)
  3488. err = createTestFile(subPath, testFileSize)
  3489. assert.NoError(t, err)
  3490. err = scpDownload(localPath, remoteDownPath, false, false)
  3491. assert.NoError(t, err)
  3492. err = os.Chmod(subPath, 0001)
  3493. assert.NoError(t, err)
  3494. err = scpDownload(localPath, remoteDownPath, false, false)
  3495. assert.Error(t, err, "download a file with no system permissions must fail")
  3496. err = os.Chmod(subPath, 0755)
  3497. assert.NoError(t, err)
  3498. err = os.Remove(localPath)
  3499. assert.NoError(t, err)
  3500. err = os.RemoveAll(user.GetHomeDir())
  3501. assert.NoError(t, err)
  3502. _, err = httpd.RemoveUser(user, http.StatusOK)
  3503. assert.NoError(t, err)
  3504. }
  3505. func TestSCPPermCreateDirs(t *testing.T) {
  3506. if len(scpPath) == 0 {
  3507. t.Skip("scp command not found, unable to execute this test")
  3508. }
  3509. usePubKey := true
  3510. u := getTestUser(usePubKey)
  3511. u.Permissions["/"] = []string{dataprovider.PermDownload, dataprovider.PermUpload}
  3512. user, _, err := httpd.AddUser(u, http.StatusOK)
  3513. assert.NoError(t, err)
  3514. testFileName := "test_file.dat"
  3515. testFilePath := filepath.Join(homeBasePath, testFileName)
  3516. testFileSize := int64(32760)
  3517. testBaseDirName := "test_dir"
  3518. testBaseDirPath := filepath.Join(homeBasePath, testBaseDirName)
  3519. testFilePath1 := filepath.Join(homeBasePath, testBaseDirName, testFileName)
  3520. err = createTestFile(testFilePath, testFileSize)
  3521. assert.NoError(t, err)
  3522. err = createTestFile(testFilePath1, testFileSize)
  3523. assert.NoError(t, err)
  3524. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/tmp/")
  3525. err = scpUpload(testFilePath, remoteUpPath, true, false)
  3526. assert.Error(t, err, "scp upload must fail, the user cannot create files in a missing dir")
  3527. err = scpUpload(testBaseDirPath, remoteUpPath, true, false)
  3528. assert.Error(t, err, "scp upload must fail, the user cannot create new dirs")
  3529. err = os.Remove(testFilePath)
  3530. assert.NoError(t, err)
  3531. err = os.RemoveAll(testBaseDirPath)
  3532. assert.NoError(t, err)
  3533. err = os.RemoveAll(user.GetHomeDir())
  3534. assert.NoError(t, err)
  3535. _, err = httpd.RemoveUser(user, http.StatusOK)
  3536. assert.NoError(t, err)
  3537. }
  3538. func TestSCPPermUpload(t *testing.T) {
  3539. if len(scpPath) == 0 {
  3540. t.Skip("scp command not found, unable to execute this test")
  3541. }
  3542. usePubKey := true
  3543. u := getTestUser(usePubKey)
  3544. u.Permissions["/"] = []string{dataprovider.PermDownload, dataprovider.PermCreateDirs}
  3545. user, _, err := httpd.AddUser(u, http.StatusOK)
  3546. assert.NoError(t, err)
  3547. testFileName := "test_file.dat"
  3548. testFilePath := filepath.Join(homeBasePath, testFileName)
  3549. testFileSize := int64(65536)
  3550. err = createTestFile(testFilePath, testFileSize)
  3551. assert.NoError(t, err)
  3552. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/tmp")
  3553. err = scpUpload(testFilePath, remoteUpPath, true, false)
  3554. assert.Error(t, err, "scp upload must fail, the user cannot upload")
  3555. err = os.Remove(testFilePath)
  3556. assert.NoError(t, err)
  3557. err = os.RemoveAll(user.GetHomeDir())
  3558. assert.NoError(t, err)
  3559. _, err = httpd.RemoveUser(user, http.StatusOK)
  3560. assert.NoError(t, err)
  3561. }
  3562. func TestSCPPermOverwrite(t *testing.T) {
  3563. if len(scpPath) == 0 {
  3564. t.Skip("scp command not found, unable to execute this test")
  3565. }
  3566. usePubKey := true
  3567. u := getTestUser(usePubKey)
  3568. u.Permissions["/"] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs}
  3569. user, _, err := httpd.AddUser(u, http.StatusOK)
  3570. assert.NoError(t, err)
  3571. testFileName := "test_file.dat"
  3572. testFilePath := filepath.Join(homeBasePath, testFileName)
  3573. testFileSize := int64(65536)
  3574. err = createTestFile(testFilePath, testFileSize)
  3575. assert.NoError(t, err)
  3576. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/tmp")
  3577. err = scpUpload(testFilePath, remoteUpPath, true, false)
  3578. assert.NoError(t, err)
  3579. err = scpUpload(testFilePath, remoteUpPath, true, false)
  3580. assert.Error(t, err, "scp upload must fail, the user cannot ovewrite existing files")
  3581. err = os.Remove(testFilePath)
  3582. assert.NoError(t, err)
  3583. err = os.RemoveAll(user.GetHomeDir())
  3584. assert.NoError(t, err)
  3585. _, err = httpd.RemoveUser(user, http.StatusOK)
  3586. assert.NoError(t, err)
  3587. }
  3588. func TestSCPPermDownload(t *testing.T) {
  3589. if len(scpPath) == 0 {
  3590. t.Skip("scp command not found, unable to execute this test")
  3591. }
  3592. usePubKey := true
  3593. u := getTestUser(usePubKey)
  3594. u.Permissions["/"] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs}
  3595. user, _, err := httpd.AddUser(u, http.StatusOK)
  3596. assert.NoError(t, err)
  3597. testFileName := "test_file.dat"
  3598. testFilePath := filepath.Join(homeBasePath, testFileName)
  3599. testFileSize := int64(65537)
  3600. err = createTestFile(testFilePath, testFileSize)
  3601. assert.NoError(t, err)
  3602. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/")
  3603. err = scpUpload(testFilePath, remoteUpPath, true, false)
  3604. assert.NoError(t, err)
  3605. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  3606. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  3607. err = scpDownload(localPath, remoteDownPath, false, false)
  3608. assert.Error(t, err, "scp download must fail, the user cannot download")
  3609. err = os.Remove(testFilePath)
  3610. assert.NoError(t, err)
  3611. err = os.RemoveAll(user.GetHomeDir())
  3612. assert.NoError(t, err)
  3613. _, err = httpd.RemoveUser(user, http.StatusOK)
  3614. assert.NoError(t, err)
  3615. }
  3616. func TestSCPQuotaSize(t *testing.T) {
  3617. if len(scpPath) == 0 {
  3618. t.Skip("scp command not found, unable to execute this test")
  3619. }
  3620. usePubKey := true
  3621. testFileSize := int64(65535)
  3622. u := getTestUser(usePubKey)
  3623. u.QuotaFiles = 1
  3624. u.QuotaSize = testFileSize - 1
  3625. user, _, err := httpd.AddUser(u, http.StatusOK)
  3626. assert.NoError(t, err)
  3627. testFileName := "test_file.dat"
  3628. testFilePath := filepath.Join(homeBasePath, testFileName)
  3629. err = createTestFile(testFilePath, testFileSize)
  3630. assert.NoError(t, err)
  3631. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  3632. err = scpUpload(testFilePath, remoteUpPath, true, false)
  3633. assert.NoError(t, err)
  3634. err = scpUpload(testFilePath, remoteUpPath+".quota", true, false)
  3635. assert.Error(t, err, "user is over quota scp upload must fail")
  3636. err = os.Remove(testFilePath)
  3637. assert.NoError(t, err)
  3638. err = os.RemoveAll(user.GetHomeDir())
  3639. assert.NoError(t, err)
  3640. _, err = httpd.RemoveUser(user, http.StatusOK)
  3641. assert.NoError(t, err)
  3642. }
  3643. func TestSCPEscapeHomeDir(t *testing.T) {
  3644. if len(scpPath) == 0 {
  3645. t.Skip("scp command not found, unable to execute this test")
  3646. }
  3647. usePubKey := true
  3648. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  3649. assert.NoError(t, err)
  3650. err = os.MkdirAll(user.GetHomeDir(), 0777)
  3651. assert.NoError(t, err)
  3652. testDir := "testDir"
  3653. linkPath := filepath.Join(homeBasePath, defaultUsername, testDir)
  3654. err = os.Symlink(homeBasePath, linkPath)
  3655. assert.NoError(t, err)
  3656. testFileName := "test_file.dat"
  3657. testFilePath := filepath.Join(homeBasePath, testFileName)
  3658. testFileSize := int64(65535)
  3659. err = createTestFile(testFilePath, testFileSize)
  3660. assert.NoError(t, err)
  3661. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join(testDir, testDir))
  3662. err = scpUpload(testFilePath, remoteUpPath, false, false)
  3663. assert.Error(t, err, "uploading to a dir with a symlink outside home dir must fail")
  3664. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testDir, testFileName))
  3665. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  3666. err = scpDownload(localPath, remoteDownPath, false, false)
  3667. assert.Error(t, err, "scp download must fail, the requested file has a symlink outside user home")
  3668. remoteDownPath = fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testDir))
  3669. err = scpDownload(homeBasePath, remoteDownPath, false, true)
  3670. assert.Error(t, err, "scp download must fail, the requested dir is a symlink outside user home")
  3671. err = os.Remove(testFilePath)
  3672. assert.NoError(t, err)
  3673. err = os.RemoveAll(user.GetHomeDir())
  3674. assert.NoError(t, err)
  3675. _, err = httpd.RemoveUser(user, http.StatusOK)
  3676. assert.NoError(t, err)
  3677. }
  3678. func TestSCPUploadPaths(t *testing.T) {
  3679. if len(scpPath) == 0 {
  3680. t.Skip("scp command not found, unable to execute this test")
  3681. }
  3682. usePubKey := true
  3683. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  3684. assert.NoError(t, err)
  3685. testFileName := "test_file.dat"
  3686. testFilePath := filepath.Join(homeBasePath, testFileName)
  3687. testFileSize := int64(65535)
  3688. testDirName := "testDir"
  3689. testDirPath := filepath.Join(user.GetHomeDir(), testDirName)
  3690. err = os.MkdirAll(testDirPath, 0777)
  3691. assert.NoError(t, err)
  3692. err = createTestFile(testFilePath, testFileSize)
  3693. assert.NoError(t, err)
  3694. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, testDirName)
  3695. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join(testDirName, testFileName))
  3696. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  3697. err = scpUpload(testFilePath, remoteUpPath, false, false)
  3698. assert.NoError(t, err)
  3699. err = scpDownload(localPath, remoteDownPath, false, false)
  3700. assert.NoError(t, err)
  3701. // upload a file to a missing dir
  3702. remoteUpPath = fmt.Sprintf("%[email protected]:%v", user.Username, path.Join(testDirName, testDirName, testFileName))
  3703. err = scpUpload(testFilePath, remoteUpPath, false, false)
  3704. assert.Error(t, err, "scp upload to a missing dir must fail")
  3705. err = os.RemoveAll(user.GetHomeDir())
  3706. assert.NoError(t, err)
  3707. err = os.Remove(localPath)
  3708. assert.NoError(t, err)
  3709. _, err = httpd.RemoveUser(user, http.StatusOK)
  3710. assert.NoError(t, err)
  3711. }
  3712. func TestSCPOverwriteDirWithFile(t *testing.T) {
  3713. if len(scpPath) == 0 {
  3714. t.Skip("scp command not found, unable to execute this test")
  3715. }
  3716. usePubKey := true
  3717. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  3718. assert.NoError(t, err)
  3719. testFileName := "test_file.dat"
  3720. testFilePath := filepath.Join(homeBasePath, testFileName)
  3721. testFileSize := int64(65535)
  3722. testDirPath := filepath.Join(user.GetHomeDir(), testFileName)
  3723. err = os.MkdirAll(testDirPath, 0777)
  3724. assert.NoError(t, err)
  3725. err = createTestFile(testFilePath, testFileSize)
  3726. assert.NoError(t, err)
  3727. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/")
  3728. err = scpUpload(testFilePath, remoteUpPath, false, false)
  3729. assert.Error(t, err, "copying a file over an existing dir must fail")
  3730. err = os.RemoveAll(user.GetHomeDir())
  3731. assert.NoError(t, err)
  3732. _, err = httpd.RemoveUser(user, http.StatusOK)
  3733. assert.NoError(t, err)
  3734. }
  3735. func TestSCPRemoteToRemote(t *testing.T) {
  3736. if len(scpPath) == 0 {
  3737. t.Skip("scp command not found, unable to execute this test")
  3738. }
  3739. usePubKey := true
  3740. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  3741. assert.NoError(t, err)
  3742. u := getTestUser(usePubKey)
  3743. u.Username += "1"
  3744. u.HomeDir += "1"
  3745. user1, _, err := httpd.AddUser(u, http.StatusOK)
  3746. assert.NoError(t, err)
  3747. testFileName := "test_file.dat"
  3748. testFilePath := filepath.Join(homeBasePath, testFileName)
  3749. testFileSize := int64(65535)
  3750. err = createTestFile(testFilePath, testFileSize)
  3751. assert.NoError(t, err)
  3752. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  3753. remote1UpPath := fmt.Sprintf("%[email protected]:%v", user1.Username, path.Join("/", testFileName))
  3754. err = scpUpload(testFilePath, remoteUpPath, false, false)
  3755. assert.NoError(t, err)
  3756. err = scpUpload(remoteUpPath, remote1UpPath, false, true)
  3757. assert.NoError(t, err)
  3758. err = os.RemoveAll(user.GetHomeDir())
  3759. assert.NoError(t, err)
  3760. _, err = httpd.RemoveUser(user, http.StatusOK)
  3761. assert.NoError(t, err)
  3762. err = os.RemoveAll(user1.GetHomeDir())
  3763. assert.NoError(t, err)
  3764. _, err = httpd.RemoveUser(user1, http.StatusOK)
  3765. assert.NoError(t, err)
  3766. }
  3767. func TestSCPErrors(t *testing.T) {
  3768. if len(scpPath) == 0 {
  3769. t.Skip("scp command not found, unable to execute this test")
  3770. }
  3771. u := getTestUser(true)
  3772. user, _, err := httpd.AddUser(u, http.StatusOK)
  3773. assert.NoError(t, err)
  3774. testFileSize := int64(524288)
  3775. testFileName := "test_file.dat"
  3776. testFilePath := filepath.Join(homeBasePath, testFileName)
  3777. err = createTestFile(testFilePath, testFileSize)
  3778. assert.NoError(t, err)
  3779. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/")
  3780. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  3781. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  3782. err = scpUpload(testFilePath, remoteUpPath, false, false)
  3783. assert.NoError(t, err)
  3784. user.UploadBandwidth = 512
  3785. user.DownloadBandwidth = 512
  3786. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  3787. assert.NoError(t, err)
  3788. cmd := getScpDownloadCommand(localPath, remoteDownPath, false, false)
  3789. go func() {
  3790. err := cmd.Run()
  3791. assert.Error(t, err, "SCP download must fail")
  3792. }()
  3793. waitForActiveTransfer()
  3794. // wait some additional arbitrary time to wait for transfer activity to happen
  3795. // it is need to reach all the code in CheckIdleConnections
  3796. time.Sleep(100 * time.Millisecond)
  3797. err = cmd.Process.Kill()
  3798. assert.NoError(t, err)
  3799. waitForNoActiveTransfer()
  3800. cmd = getScpUploadCommand(testFilePath, remoteUpPath, false, false)
  3801. go func() {
  3802. err := cmd.Run()
  3803. assert.Error(t, err, "SCP upload must fail")
  3804. }()
  3805. waitForActiveTransfer()
  3806. // wait some additional arbitrary time to wait for transfer activity to happen
  3807. // it is need to reach all the code in CheckIdleConnections
  3808. time.Sleep(100 * time.Millisecond)
  3809. err = cmd.Process.Kill()
  3810. assert.NoError(t, err)
  3811. waitForNoActiveTransfer()
  3812. err = os.Remove(testFilePath)
  3813. assert.NoError(t, err)
  3814. os.Remove(localPath)
  3815. err = os.RemoveAll(user.GetHomeDir())
  3816. assert.NoError(t, err)
  3817. _, err = httpd.RemoveUser(user, http.StatusOK)
  3818. assert.NoError(t, err)
  3819. }
  3820. // End SCP tests
  3821. func waitTCPListening(address string) {
  3822. for {
  3823. conn, err := net.Dial("tcp", address)
  3824. if err != nil {
  3825. logger.WarnToConsole("tcp server %v not listening: %v\n", address, err)
  3826. time.Sleep(100 * time.Millisecond)
  3827. continue
  3828. }
  3829. logger.InfoToConsole("tcp server %v now listening\n", address)
  3830. defer conn.Close()
  3831. break
  3832. }
  3833. }
  3834. func getTestUser(usePubKey bool) dataprovider.User {
  3835. user := dataprovider.User{
  3836. Username: defaultUsername,
  3837. Password: defaultPassword,
  3838. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  3839. Status: 1,
  3840. ExpirationDate: 0,
  3841. }
  3842. user.Permissions = make(map[string][]string)
  3843. user.Permissions["/"] = allPerms
  3844. if usePubKey {
  3845. user.PublicKeys = []string{testPubKey}
  3846. user.Password = ""
  3847. }
  3848. return user
  3849. }
  3850. func runSSHCommand(command string, user dataprovider.User, usePubKey bool) ([]byte, error) {
  3851. var sshSession *ssh.Session
  3852. var output []byte
  3853. config := &ssh.ClientConfig{
  3854. User: user.Username,
  3855. HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
  3856. return nil
  3857. },
  3858. }
  3859. if usePubKey {
  3860. key, err := ssh.ParsePrivateKey([]byte(testPrivateKey))
  3861. if err != nil {
  3862. return output, err
  3863. }
  3864. config.Auth = []ssh.AuthMethod{ssh.PublicKeys(key)}
  3865. } else {
  3866. config.Auth = []ssh.AuthMethod{ssh.Password(defaultPassword)}
  3867. }
  3868. conn, err := ssh.Dial("tcp", sftpServerAddr, config)
  3869. if err != nil {
  3870. return output, err
  3871. }
  3872. defer conn.Close()
  3873. sshSession, err = conn.NewSession()
  3874. if err != nil {
  3875. return output, err
  3876. }
  3877. var stdout, stderr bytes.Buffer
  3878. sshSession.Stdout = &stdout
  3879. sshSession.Stderr = &stderr
  3880. err = sshSession.Run(command)
  3881. if err != nil {
  3882. return nil, fmt.Errorf("failed to run command %v: %v", command, stderr.Bytes())
  3883. }
  3884. return stdout.Bytes(), err
  3885. }
  3886. func getSignerForUserCert(certBytes []byte) (ssh.Signer, error) {
  3887. signer, err := ssh.ParsePrivateKey([]byte(testPrivateKey))
  3888. if err != nil {
  3889. return nil, err
  3890. }
  3891. cert, _, _, _, err := ssh.ParseAuthorizedKey(certBytes) //nolint:dogsled
  3892. if err != nil {
  3893. return nil, err
  3894. }
  3895. return ssh.NewCertSigner(cert.(*ssh.Certificate), signer)
  3896. }
  3897. func getSftpClientWithAddr(user dataprovider.User, usePubKey bool, addr string) (*sftp.Client, error) {
  3898. var sftpClient *sftp.Client
  3899. config := &ssh.ClientConfig{
  3900. User: user.Username,
  3901. HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
  3902. return nil
  3903. },
  3904. }
  3905. if usePubKey {
  3906. signer, err := ssh.ParsePrivateKey([]byte(testPrivateKey))
  3907. if err != nil {
  3908. return nil, err
  3909. }
  3910. config.Auth = []ssh.AuthMethod{ssh.PublicKeys(signer)}
  3911. } else {
  3912. if len(user.Password) > 0 {
  3913. config.Auth = []ssh.AuthMethod{ssh.Password(user.Password)}
  3914. } else {
  3915. config.Auth = []ssh.AuthMethod{ssh.Password(defaultPassword)}
  3916. }
  3917. }
  3918. conn, err := ssh.Dial("tcp", addr, config)
  3919. if err != nil {
  3920. return sftpClient, err
  3921. }
  3922. sftpClient, err = sftp.NewClient(conn)
  3923. return sftpClient, err
  3924. }
  3925. func getSftpClient(user dataprovider.User, usePubKey bool) (*sftp.Client, error) {
  3926. return getSftpClientWithAddr(user, usePubKey, sftpServerAddr)
  3927. }
  3928. func getKeyboardInteractiveSftpClient(user dataprovider.User, answers []string) (*sftp.Client, error) {
  3929. var sftpClient *sftp.Client
  3930. config := &ssh.ClientConfig{
  3931. User: user.Username,
  3932. HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
  3933. return nil
  3934. },
  3935. Auth: []ssh.AuthMethod{
  3936. ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) ([]string, error) {
  3937. return answers, nil
  3938. }),
  3939. },
  3940. }
  3941. conn, err := ssh.Dial("tcp", sftpServerAddr, config)
  3942. if err != nil {
  3943. return sftpClient, err
  3944. }
  3945. sftpClient, err = sftp.NewClient(conn)
  3946. return sftpClient, err
  3947. }
  3948. func getCustomAuthSftpClient(user dataprovider.User, authMethods []ssh.AuthMethod) (*sftp.Client, error) {
  3949. var sftpClient *sftp.Client
  3950. config := &ssh.ClientConfig{
  3951. User: user.Username,
  3952. HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
  3953. return nil
  3954. },
  3955. Auth: authMethods,
  3956. }
  3957. conn, err := ssh.Dial("tcp", sftpServerAddr, config)
  3958. if err != nil {
  3959. return sftpClient, err
  3960. }
  3961. sftpClient, err = sftp.NewClient(conn)
  3962. return sftpClient, err
  3963. }
  3964. func createTestFile(path string, size int64) error {
  3965. baseDir := filepath.Dir(path)
  3966. if _, err := os.Stat(baseDir); os.IsNotExist(err) {
  3967. err = os.MkdirAll(baseDir, 0777)
  3968. if err != nil {
  3969. return err
  3970. }
  3971. }
  3972. content := make([]byte, size)
  3973. _, err := rand.Read(content)
  3974. if err != nil {
  3975. return err
  3976. }
  3977. return ioutil.WriteFile(path, content, 0666)
  3978. }
  3979. func appendToTestFile(path string, size int64) error {
  3980. content := make([]byte, size)
  3981. _, err := rand.Read(content)
  3982. if err != nil {
  3983. return err
  3984. }
  3985. f, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0666)
  3986. if err != nil {
  3987. return err
  3988. }
  3989. defer f.Close()
  3990. written, err := io.Copy(f, bytes.NewReader(content))
  3991. if err != nil {
  3992. return err
  3993. }
  3994. if written != size {
  3995. return fmt.Errorf("write error, written: %v/%v", written, size)
  3996. }
  3997. return nil
  3998. }
  3999. func checkBasicSFTP(client *sftp.Client) error {
  4000. _, err := client.Getwd()
  4001. if err != nil {
  4002. return err
  4003. }
  4004. _, err = client.ReadDir(".")
  4005. return err
  4006. }
  4007. func sftpUploadFile(localSourcePath string, remoteDestPath string, expectedSize int64, client *sftp.Client) error {
  4008. srcFile, err := os.Open(localSourcePath)
  4009. if err != nil {
  4010. return err
  4011. }
  4012. defer srcFile.Close()
  4013. destFile, err := client.Create(remoteDestPath)
  4014. if err != nil {
  4015. return err
  4016. }
  4017. _, err = io.Copy(destFile, srcFile)
  4018. if err != nil {
  4019. destFile.Close()
  4020. return err
  4021. }
  4022. // we need to close the file to trigger the close method on server
  4023. // we cannot defer closing or Lstat will fail for uploads in atomic mode
  4024. destFile.Close()
  4025. if expectedSize > 0 {
  4026. fi, err := client.Stat(remoteDestPath)
  4027. if err != nil {
  4028. return err
  4029. }
  4030. if fi.Size() != expectedSize {
  4031. return fmt.Errorf("uploaded file size does not match, actual: %v, expected: %v", fi.Size(), expectedSize)
  4032. }
  4033. }
  4034. return err
  4035. }
  4036. func sftpUploadResumeFile(localSourcePath string, remoteDestPath string, expectedSize int64, invalidOffset bool,
  4037. client *sftp.Client) error {
  4038. srcFile, err := os.Open(localSourcePath)
  4039. if err != nil {
  4040. return err
  4041. }
  4042. defer srcFile.Close()
  4043. fi, err := client.Lstat(remoteDestPath)
  4044. if err != nil {
  4045. return err
  4046. }
  4047. if !invalidOffset {
  4048. _, err = srcFile.Seek(fi.Size(), 0)
  4049. if err != nil {
  4050. return err
  4051. }
  4052. }
  4053. destFile, err := client.OpenFile(remoteDestPath, os.O_WRONLY|os.O_APPEND)
  4054. if err != nil {
  4055. return err
  4056. }
  4057. if !invalidOffset {
  4058. _, err = destFile.Seek(fi.Size(), 0)
  4059. if err != nil {
  4060. return err
  4061. }
  4062. }
  4063. _, err = io.Copy(destFile, srcFile)
  4064. if err != nil {
  4065. destFile.Close()
  4066. return err
  4067. }
  4068. // we need to close the file to trigger the close method on server
  4069. // we cannot defer closing or Lstat will fail for upload atomic mode
  4070. destFile.Close()
  4071. if expectedSize > 0 {
  4072. fi, err := client.Lstat(remoteDestPath)
  4073. if err != nil {
  4074. return err
  4075. }
  4076. if fi.Size() != expectedSize {
  4077. return fmt.Errorf("uploaded file size does not match, actual: %v, expected: %v", fi.Size(), expectedSize)
  4078. }
  4079. }
  4080. return err
  4081. }
  4082. func sftpDownloadFile(remoteSourcePath string, localDestPath string, expectedSize int64, client *sftp.Client) error {
  4083. downloadDest, err := os.Create(localDestPath)
  4084. if err != nil {
  4085. return err
  4086. }
  4087. defer downloadDest.Close()
  4088. sftpSrcFile, err := client.Open(remoteSourcePath)
  4089. if err != nil {
  4090. return err
  4091. }
  4092. defer sftpSrcFile.Close()
  4093. _, err = io.Copy(downloadDest, sftpSrcFile)
  4094. if err != nil {
  4095. return err
  4096. }
  4097. err = downloadDest.Sync()
  4098. if err != nil {
  4099. return err
  4100. }
  4101. if expectedSize > 0 {
  4102. fi, err := downloadDest.Stat()
  4103. if err != nil {
  4104. return err
  4105. }
  4106. if fi.Size() != expectedSize {
  4107. return fmt.Errorf("downloaded file size does not match, actual: %v, expected: %v", fi.Size(), expectedSize)
  4108. }
  4109. }
  4110. return err
  4111. }
  4112. func sftpUploadNonBlocking(localSourcePath string, remoteDestPath string, expectedSize int64, client *sftp.Client) <-chan error {
  4113. c := make(chan error)
  4114. go func() {
  4115. c <- sftpUploadFile(localSourcePath, remoteDestPath, expectedSize, client)
  4116. }()
  4117. return c
  4118. }
  4119. func sftpDownloadNonBlocking(remoteSourcePath string, localDestPath string, expectedSize int64, client *sftp.Client) <-chan error {
  4120. c := make(chan error)
  4121. go func() {
  4122. c <- sftpDownloadFile(remoteSourcePath, localDestPath, expectedSize, client)
  4123. }()
  4124. return c
  4125. }
  4126. func scpUpload(localPath, remotePath string, preserveTime, remoteToRemote bool) error {
  4127. cmd := getScpUploadCommand(localPath, remotePath, preserveTime, remoteToRemote)
  4128. return cmd.Run()
  4129. }
  4130. func scpDownload(localPath, remotePath string, preserveTime, recursive bool) error {
  4131. cmd := getScpDownloadCommand(localPath, remotePath, preserveTime, recursive)
  4132. return cmd.Run()
  4133. }
  4134. func getScpDownloadCommand(localPath, remotePath string, preserveTime, recursive bool) *exec.Cmd {
  4135. var args []string
  4136. if preserveTime {
  4137. args = append(args, "-p")
  4138. }
  4139. if recursive {
  4140. args = append(args, "-r")
  4141. }
  4142. args = append(args, "-P")
  4143. args = append(args, "2022")
  4144. args = append(args, "-o")
  4145. args = append(args, "StrictHostKeyChecking=no")
  4146. args = append(args, "-i")
  4147. args = append(args, privateKeyPath)
  4148. args = append(args, remotePath)
  4149. args = append(args, localPath)
  4150. return exec.Command(scpPath, args...)
  4151. }
  4152. func getScpUploadCommand(localPath, remotePath string, preserveTime, remoteToRemote bool) *exec.Cmd {
  4153. var args []string
  4154. if remoteToRemote {
  4155. args = append(args, "-3")
  4156. }
  4157. if preserveTime {
  4158. args = append(args, "-p")
  4159. }
  4160. fi, err := os.Stat(localPath)
  4161. if err == nil {
  4162. if fi.IsDir() {
  4163. args = append(args, "-r")
  4164. }
  4165. }
  4166. args = append(args, "-P")
  4167. args = append(args, "2022")
  4168. args = append(args, "-o")
  4169. args = append(args, "StrictHostKeyChecking=no")
  4170. args = append(args, "-i")
  4171. args = append(args, privateKeyPath)
  4172. args = append(args, localPath)
  4173. args = append(args, remotePath)
  4174. return exec.Command(scpPath, args...)
  4175. }
  4176. func computeHashForFile(hasher hash.Hash, path string) (string, error) {
  4177. hash := ""
  4178. f, err := os.Open(path)
  4179. if err != nil {
  4180. return hash, err
  4181. }
  4182. defer f.Close()
  4183. _, err = io.Copy(hasher, f)
  4184. if err == nil {
  4185. hash = fmt.Sprintf("%x", hasher.Sum(nil))
  4186. }
  4187. return hash, err
  4188. }
  4189. func waitForNoActiveTransfer() {
  4190. for len(sftpd.GetConnectionsStats()) > 0 {
  4191. time.Sleep(100 * time.Millisecond)
  4192. }
  4193. }
  4194. func waitForActiveTransfer() {
  4195. stats := sftpd.GetConnectionsStats()
  4196. for len(stats) < 1 {
  4197. stats = sftpd.GetConnectionsStats()
  4198. }
  4199. activeTransferFound := false
  4200. for !activeTransferFound {
  4201. stats = sftpd.GetConnectionsStats()
  4202. if len(stats) == 0 {
  4203. break
  4204. }
  4205. for _, stat := range stats {
  4206. if len(stat.Transfers) > 0 {
  4207. activeTransferFound = true
  4208. }
  4209. }
  4210. }
  4211. }
  4212. func waitQuotaScans() error {
  4213. time.Sleep(100 * time.Millisecond)
  4214. scans, _, err := httpd.GetQuotaScans(http.StatusOK)
  4215. if err != nil {
  4216. return err
  4217. }
  4218. for len(scans) > 0 {
  4219. time.Sleep(100 * time.Millisecond)
  4220. scans, _, err = httpd.GetQuotaScans(http.StatusOK)
  4221. if err != nil {
  4222. return err
  4223. }
  4224. }
  4225. return nil
  4226. }
  4227. func checkGitCommand() {
  4228. var err error
  4229. gitPath, err = exec.LookPath("git")
  4230. if err != nil {
  4231. logger.Warn(logSender, "", "unable to get git command. GIT tests will be skipped, err: %v", err)
  4232. logger.WarnToConsole("unable to get git command. GIT tests will be skipped, err: %v", err)
  4233. gitPath = ""
  4234. }
  4235. sshPath, err = exec.LookPath("ssh")
  4236. if err != nil {
  4237. logger.Warn(logSender, "", "unable to get ssh command. GIT tests will be skipped, err: %v", err)
  4238. logger.WarnToConsole("unable to get ssh command. GIT tests will be skipped, err: %v", err)
  4239. gitPath = ""
  4240. }
  4241. }
  4242. func initGitRepo(path string) ([]byte, error) {
  4243. err := os.MkdirAll(path, 0777)
  4244. if err != nil {
  4245. return nil, err
  4246. }
  4247. args := []string{"init", "--bare"}
  4248. cmd := exec.Command(gitPath, args...)
  4249. cmd.Dir = path
  4250. return cmd.CombinedOutput()
  4251. }
  4252. func pushToGitRepo(repoPath string) ([]byte, error) {
  4253. cmd := exec.Command(gitPath, "push")
  4254. cmd.Dir = repoPath
  4255. cmd.Env = append(os.Environ(),
  4256. fmt.Sprintf("GIT_SSH=%v", gitWrapPath))
  4257. return cmd.CombinedOutput()
  4258. }
  4259. func cloneGitRepo(basePath, remotePath, username string) ([]byte, error) {
  4260. remoteURL := fmt.Sprintf("ssh://%[email protected]:2022%v", username, remotePath)
  4261. args := []string{"clone", remoteURL}
  4262. cmd := exec.Command(gitPath, args...)
  4263. cmd.Dir = basePath
  4264. cmd.Env = append(os.Environ(),
  4265. fmt.Sprintf("GIT_SSH=%v", gitWrapPath))
  4266. return cmd.CombinedOutput()
  4267. }
  4268. func addFileToGitRepo(repoPath string, fileSize int64) ([]byte, error) {
  4269. path := filepath.Join(repoPath, "test")
  4270. err := createTestFile(path, fileSize)
  4271. if err != nil {
  4272. return []byte(""), err
  4273. }
  4274. cmd := exec.Command(gitPath, "config", "user.email", "[email protected]")
  4275. cmd.Dir = repoPath
  4276. out, err := cmd.CombinedOutput()
  4277. if err != nil {
  4278. return out, err
  4279. }
  4280. cmd = exec.Command(gitPath, "config", "user.name", "testuser")
  4281. cmd.Dir = repoPath
  4282. out, err = cmd.CombinedOutput()
  4283. if err != nil {
  4284. return out, err
  4285. }
  4286. cmd = exec.Command(gitPath, "add", "test")
  4287. cmd.Dir = repoPath
  4288. out, err = cmd.CombinedOutput()
  4289. if err != nil {
  4290. return out, err
  4291. }
  4292. cmd = exec.Command(gitPath, "commit", "-am", "test")
  4293. cmd.Dir = repoPath
  4294. return cmd.CombinedOutput()
  4295. }
  4296. func getKeyboardInteractiveScriptContent(questions []string, sleepTime int, nonJSONResponse bool, result int) []byte {
  4297. content := []byte("#!/bin/sh\n\n")
  4298. q, _ := json.Marshal(questions)
  4299. echos := []bool{}
  4300. for index := range questions {
  4301. echos = append(echos, index%2 == 0)
  4302. }
  4303. e, _ := json.Marshal(echos)
  4304. if nonJSONResponse {
  4305. content = append(content, []byte(fmt.Sprintf("echo 'questions: %v echos: %v\n", string(q), string(e)))...)
  4306. } else {
  4307. content = append(content, []byte(fmt.Sprintf("echo '{\"questions\":%v,\"echos\":%v}'\n", string(q), string(e)))...)
  4308. }
  4309. for index := range questions {
  4310. content = append(content, []byte(fmt.Sprintf("read ANSWER%v\n", index))...)
  4311. }
  4312. if sleepTime > 0 {
  4313. content = append(content, []byte(fmt.Sprintf("sleep %v\n", sleepTime))...)
  4314. }
  4315. content = append(content, []byte(fmt.Sprintf("echo '{\"auth_result\":%v}'\n", result))...)
  4316. return content
  4317. }
  4318. func getExtAuthScriptContent(user dataprovider.User, nonJSONResponse bool) []byte {
  4319. extAuthContent := []byte("#!/bin/sh\n\n")
  4320. u, _ := json.Marshal(user)
  4321. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("if test \"$SFTPGO_AUTHD_USERNAME\" = \"%v\"; then\n", user.Username))...)
  4322. if nonJSONResponse {
  4323. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  4324. } else {
  4325. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  4326. }
  4327. extAuthContent = append(extAuthContent, []byte("else\n")...)
  4328. if nonJSONResponse {
  4329. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  4330. } else {
  4331. extAuthContent = append(extAuthContent, []byte("echo '{\"username\":\"\"}'\n")...)
  4332. }
  4333. extAuthContent = append(extAuthContent, []byte("fi\n")...)
  4334. return extAuthContent
  4335. }
  4336. func getPreLoginScriptContent(user dataprovider.User, nonJSONResponse bool) []byte {
  4337. content := []byte("#!/bin/sh\n\n")
  4338. if nonJSONResponse {
  4339. content = append(content, []byte("echo 'text response'\n")...)
  4340. return content
  4341. }
  4342. if len(user.Username) > 0 {
  4343. u, _ := json.Marshal(user)
  4344. content = append(content, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  4345. }
  4346. return content
  4347. }
  4348. func printLatestLogs(maxNumberOfLines int) {
  4349. var lines []string
  4350. f, err := os.Open(logFilePath)
  4351. if err != nil {
  4352. return
  4353. }
  4354. defer f.Close()
  4355. scanner := bufio.NewScanner(f)
  4356. for scanner.Scan() {
  4357. lines = append(lines, scanner.Text()+"\r\n")
  4358. for len(lines) > maxNumberOfLines {
  4359. lines = lines[1:]
  4360. }
  4361. }
  4362. if scanner.Err() != nil {
  4363. logger.WarnToConsole("Unable to print latest logs: %v", scanner.Err())
  4364. return
  4365. }
  4366. for _, line := range lines {
  4367. logger.DebugToConsole(line)
  4368. }
  4369. }