sftpd_test.go 301 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045
  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. "strconv"
  24. "strings"
  25. "sync"
  26. "sync/atomic"
  27. "testing"
  28. "time"
  29. _ "github.com/go-sql-driver/mysql"
  30. _ "github.com/lib/pq"
  31. _ "github.com/mattn/go-sqlite3"
  32. "github.com/pkg/sftp"
  33. "github.com/rs/zerolog"
  34. "github.com/stretchr/testify/assert"
  35. "golang.org/x/crypto/ssh"
  36. "github.com/drakkan/sftpgo/common"
  37. "github.com/drakkan/sftpgo/config"
  38. "github.com/drakkan/sftpgo/dataprovider"
  39. "github.com/drakkan/sftpgo/httpd"
  40. "github.com/drakkan/sftpgo/logger"
  41. "github.com/drakkan/sftpgo/utils"
  42. "github.com/drakkan/sftpgo/vfs"
  43. )
  44. const (
  45. logSender = "sftpdTesting"
  46. sftpServerAddr = "127.0.0.1:2022"
  47. sftpSrvAddr2222 = "127.0.0.1:2222"
  48. defaultUsername = "test_user_sftp"
  49. defaultPassword = "test_password"
  50. testPubKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0= nicola@p1"
  51. testPubKey1 = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCd60+/j+y8f0tLftihWV1YN9RSahMI9btQMDIMqts/jeNbD8jgoogM3nhF7KxfcaMKURuD47KC4Ey6iAJUJ0sWkSNNxOcIYuvA+5MlspfZDsa8Ag76Fe1vyz72WeHMHMeh/hwFo2TeIeIXg480T1VI6mzfDrVp2GzUx0SS0dMsQBjftXkuVR8YOiOwMCAH2a//M1OrvV7d/NBk6kBN0WnuIBb2jKm15PAA7+jQQG7tzwk2HedNH3jeL5GH31xkSRwlBczRK0xsCQXehAlx6cT/e/s44iJcJTHfpPKoSk6UAhPJYe7Z1QnuoawY9P9jQaxpyeImBZxxUEowhjpj2avBxKdRGBVK8R7EL8tSOeLbhdyWe5Mwc1+foEbq9Zz5j5Kd+hn3Wm1UnsGCrXUUUoZp1jnlNl0NakCto+5KmqnT9cHxaY+ix2RLUWAZyVFlRq71OYux1UHJnEJPiEI1/tr4jFBSL46qhQZv/TfpkfVW8FLz0lErfqu0gQEZnNHr3Fc= nicola@p1"
  52. testPrivateKey = `-----BEGIN OPENSSH PRIVATE KEY-----
  53. b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
  54. NhAAAAAwEAAQAAAYEAtN449A/nY5O6cSH/9Doa8a3ISU0WZJaHydTaCLuO+dkqtNpnV5mq
  55. zFbKidXAI1eSwVctw9ReVOl1uK6aZF3lbXdOD8W9PXobR9KUUT2qBx5QC4ibfAqDKWymDA
  56. PG9ylzz64hsYBqJr7VNk9kTFEUsDmWzLabLoH42Elnp8mF/lTkWIcpVp0ly/etS08gttXo
  57. XenekJ1vRuxOYWDCEzGPU7kGc920TmM14k7IDdPoOh5+3sRUKedKeOUrVDH1f0n7QjHQsZ
  58. cbshp8tgqzf734zu8cTqNrr+6taptdEOOij1iUL/qYGfzny/hA48tO5+UFUih5W8ftp0+E
  59. NBIDkkGgk2MJ92I7QAXyMVsIABXco+mJT7pQi9tqlODGIQ3AOj0gcA3X/Ib8QX77Ih3TPi
  60. XEh77/P1XiYZOgpp2cRmNH8QbqaL9u898hDvJwIPJPuj2lIltTElH7hjBf5LQfCzrLV7BD
  61. 10rM7sl4jr+A2q8jl1Ikp+25kainBBZSbrDummT9AAAFgDU/VLk1P1S5AAAAB3NzaC1yc2
  62. EAAAGBALTeOPQP52OTunEh//Q6GvGtyElNFmSWh8nU2gi7jvnZKrTaZ1eZqsxWyonVwCNX
  63. ksFXLcPUXlTpdbiummRd5W13Tg/FvT16G0fSlFE9qgceUAuIm3wKgylspgwDxvcpc8+uIb
  64. GAaia+1TZPZExRFLA5lsy2my6B+NhJZ6fJhf5U5FiHKVadJcv3rUtPILbV6F3p3pCdb0bs
  65. TmFgwhMxj1O5BnPdtE5jNeJOyA3T6Doeft7EVCnnSnjlK1Qx9X9J+0Ix0LGXG7IafLYKs3
  66. +9+M7vHE6ja6/urWqbXRDjoo9YlC/6mBn858v4QOPLTuflBVIoeVvH7adPhDQSA5JBoJNj
  67. CfdiO0AF8jFbCAAV3KPpiU+6UIvbapTgxiENwDo9IHAN1/yG/EF++yId0z4lxIe+/z9V4m
  68. GToKadnEZjR/EG6mi/bvPfIQ7ycCDyT7o9pSJbUxJR+4YwX+S0Hws6y1ewQ9dKzO7JeI6/
  69. gNqvI5dSJKftuZGopwQWUm6w7ppk/QAAAAMBAAEAAAGAHKnC+Nq0XtGAkIFE4N18e6SAwy
  70. 0WSWaZqmCzFQM0S2AhJnweOIG/0ZZHjsRzKKauOTmppQk40dgVsejpytIek9R+aH172gxJ
  71. 2n4Cx0UwduRU5x8FFQlNc/kl722B0JWfJuB/snOZXv6LJ4o5aObIkozt2w9tVFeAqjYn2S
  72. 1UsNOfRHBXGsTYwpRDwFWP56nKo2d2wBBTHDhCy6fb2dLW1fvSi/YspueOGIlHpvlYKi2/
  73. CWqvs9xVrwcScMtiDoQYq0khhO0efLCxvg/o+W9CLMVM2ms4G1zoSUQKN0oYWWQJyW4+VI
  74. YneWO8UpN0J3ElXKi7bhgAat7dBaM1g9IrAzk153DiEFZNsPxGOgL/+YdQN7zUBx/z7EkI
  75. jyv80RV7fpUXvcq2p+qNl6UVig3VSzRrnsaJkUWu/A0u59ha7ocv6NxDIXjxpIDJme16GF
  76. quiGVBQNnYJymS/vFEbGf6bgf7iRmMCRUMG4nqLA6fPYP9uAtch+CmDfVLZC/fIdC5AAAA
  77. wQCDissV4zH6bfqgxJSuYNk8Vbb+19cF3b7gH1rVlB3zxpCAgcRgMHC+dP1z2NRx7UW9MR
  78. nye6kjpkzZZ0OigLqo7TtEq8uTglD9o6W7mRXqhy5A/ySOmqPL3ernHHQhGuoNODYAHkOU
  79. u2Rh8HXi+VLwKZcLInPOYJvcuLG4DxN8WfeVvlMHwhAOaTNNOtL4XZDHQeIPc4qHmJymmv
  80. sV7GuyQ6yW5C10uoGdxRPd90Bh4z4h2bKfZFjvEBbSBVkqrlAAAADBAN/zNtNayd/dX7Cr
  81. Nb4sZuzCh+CW4BH8GOePZWNCATwBbNXBVb5cR+dmuTqYm+Ekz0VxVQRA1TvKncluJOQpoa
  82. Xj8r0xdIgqkehnfDPMKtYVor06B9Fl1jrXtXU0Vrr6QcBWruSVyK1ZxqcmcNK/+KolVepe
  83. A6vcl/iKaG4U7su166nxLST06M2EgcSVsFJHpKn5+WAXC+X0Gx8kNjWIIb3GpiChdc0xZD
  84. mq02xZthVJrTCVw/e7gfDoB2QRsNV8HwAAAMEAzsCghZVp+0YsYg9oOrw4tEqcbEXEMhwY
  85. 0jW8JNL8Spr1Ibp5Dw6bRSk5azARjmJtnMJhJ3oeHfF0eoISqcNuQXGndGQbVM9YzzAzc1
  86. NbbCNsVroqKlChT5wyPNGS+phi2bPARBno7WSDvshTZ7dAVEP2c9MJW0XwoSevwKlhgSdt
  87. RLFFQ/5nclJSdzPBOmQouC0OBcMFSrYtMeknJ4VvueVvve5HcHFaEsaMc7ABAGaLYaBQOm
  88. iixITGvaNZh/tjAAAACW5pY29sYUBwMQE=
  89. -----END OPENSSH PRIVATE KEY-----`
  90. // test CA user key.
  91. // % ssh-keygen -f ca_user_key
  92. testCAUserKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDF5fcwZHiyixmnE6IlOZJpZhWXoh62gN+yadAA0GJ509SAEaZVLPDP8S5RsE8mUikR3wxynVshxHeqMhrkS+RlNbhSlOXDdNg94yTrq/xF8Z/PgKRInvef74k5i7bAIytza7jERzFJ/ujTEy3537T5k5EYQJ15ZQGuvzynSdv+6o99SjI4jFplyQOZ2QcYbEAmhHm5GgQlIiEFG/RlDtLksOulKZxOY3qPzP0AyQxtZJXn/5vG40aW9LTbwxCJqWlgrkFXMqAAVCbuU5YspwhiXmKt1PsldiXw23oloa4caCKN1jzbFiGuZNXEU2Ebx7JIvjQCPaUYwLjEbkRDxDqN/vmwZqBuKYiuG9Eafx+nFSQkr7QYb5b+mT+/1IFHnmeRGn38731kBqtH7tpzC/t+soRX9p2HtJM+9MYhblO2OqTSPGTlxihWUkyiRBekpAhaiHld16TsG+A3bOJHrojGcX+5g6oGarKGLAMcykL1X+rZqT993Mo6d2Z7q43MOXE= root@p1"
  93. // this is testPubKey signed using testCAUserKey.
  94. // % 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
  95. 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"
  96. // this is testPubKey signed using a CA user key different from testCAUserKey
  97. 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"
  98. // this is testPubKey signed as host certificate.
  99. // % ssh-keygen -s ca_user_key -I test_user_sftp -h -n test_user_sftp -V always:forever -z 2 /tmp/test.pub
  100. 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"
  101. // this is testPubKey signed using testCAUserKey but with source address 172.16.34.45.
  102. // % 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
  103. 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"
  104. // this is testPubKey signed using testCAUserKey but expired.
  105. // % ssh-keygen -s ca_user_key -I test_user_sftp -n test_user_sftp -V 20100101123000:20110101123000 -z 4 /tmp/test.pub
  106. 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"
  107. configDir = ".."
  108. osWindows = "windows"
  109. testFileName = "test_file_sftp.dat"
  110. testDLFileName = "test_download_sftp.dat"
  111. )
  112. var (
  113. allPerms = []string{dataprovider.PermAny}
  114. homeBasePath string
  115. scpPath string
  116. gitPath string
  117. sshPath string
  118. hookCmdPath string
  119. pubKeyPath string
  120. privateKeyPath string
  121. trustedCAUserKey string
  122. gitWrapPath string
  123. extAuthPath string
  124. keyIntAuthPath string
  125. preLoginPath string
  126. postConnectPath string
  127. checkPwdPath string
  128. logFilePath string
  129. )
  130. func TestMain(m *testing.M) {
  131. logFilePath = filepath.Join(configDir, "sftpgo_sftpd_test.log")
  132. loginBannerFileName := "login_banner"
  133. loginBannerFile := filepath.Join(configDir, loginBannerFileName)
  134. logger.InitLogger(logFilePath, 5, 1, 28, false, zerolog.DebugLevel)
  135. err := ioutil.WriteFile(loginBannerFile, []byte("simple login banner\n"), os.ModePerm)
  136. if err != nil {
  137. logger.ErrorToConsole("error creating login banner: %v", err)
  138. }
  139. err = config.LoadConfig(configDir, "")
  140. if err != nil {
  141. logger.ErrorToConsole("error loading configuration: %v", err)
  142. os.Exit(1)
  143. }
  144. providerConf := config.GetProviderConf()
  145. logger.InfoToConsole("Starting SFTPD tests, provider: %v", providerConf.Driver)
  146. commonConf := config.GetCommonConfig()
  147. // we run the test cases with UploadMode atomic and resume support. The non atomic code path
  148. // simply does not execute some code so if it works in atomic mode will
  149. // work in non atomic mode too
  150. commonConf.UploadMode = 2
  151. homeBasePath = os.TempDir()
  152. checkSystemCommands()
  153. var scriptArgs string
  154. if runtime.GOOS == osWindows {
  155. scriptArgs = "%*"
  156. } else {
  157. commonConf.Actions.ExecuteOn = []string{"download", "upload", "rename", "delete", "ssh_cmd"}
  158. commonConf.Actions.Hook = hookCmdPath
  159. scriptArgs = "$@"
  160. }
  161. common.Initialize(commonConf)
  162. err = dataprovider.Initialize(providerConf, configDir)
  163. if err != nil {
  164. logger.ErrorToConsole("error initializing data provider: %v", err)
  165. os.Exit(1)
  166. }
  167. httpConfig := config.GetHTTPConfig()
  168. httpConfig.Initialize(configDir)
  169. sftpdConf := config.GetSFTPDConfig()
  170. httpdConf := config.GetHTTPDConfig()
  171. sftpdConf.BindPort = 2022
  172. sftpdConf.KexAlgorithms = []string{"[email protected]", "ecdh-sha2-nistp256",
  173. "ecdh-sha2-nistp384"}
  174. sftpdConf.Ciphers = []string{"[email protected]", "[email protected]",
  175. "aes256-ctr"}
  176. sftpdConf.MACs = []string{"[email protected]", "hmac-sha2-256"}
  177. sftpdConf.LoginBannerFile = loginBannerFileName
  178. // we need to test all supported ssh commands
  179. sftpdConf.EnabledSSHCommands = []string{"*"}
  180. keyIntAuthPath = filepath.Join(homeBasePath, "keyintauth.sh")
  181. err = ioutil.WriteFile(keyIntAuthPath, getKeyboardInteractiveScriptContent([]string{"1", "2"}, 0, false, 1), os.ModePerm)
  182. if err != nil {
  183. logger.ErrorToConsole("error writing keyboard interactive script: %v", err)
  184. os.Exit(1)
  185. }
  186. sftpdConf.KeyboardInteractiveHook = keyIntAuthPath
  187. pubKeyPath = filepath.Join(homeBasePath, "ssh_key.pub")
  188. privateKeyPath = filepath.Join(homeBasePath, "ssh_key")
  189. trustedCAUserKey = filepath.Join(homeBasePath, "ca_user_key")
  190. gitWrapPath = filepath.Join(homeBasePath, "gitwrap.sh")
  191. extAuthPath = filepath.Join(homeBasePath, "extauth.sh")
  192. preLoginPath = filepath.Join(homeBasePath, "prelogin.sh")
  193. postConnectPath = filepath.Join(homeBasePath, "postconnect.sh")
  194. checkPwdPath = filepath.Join(homeBasePath, "checkpwd.sh")
  195. err = ioutil.WriteFile(pubKeyPath, []byte(testPubKey+"\n"), 0600)
  196. if err != nil {
  197. logger.WarnToConsole("unable to save public key to file: %v", err)
  198. }
  199. err = ioutil.WriteFile(privateKeyPath, []byte(testPrivateKey+"\n"), 0600)
  200. if err != nil {
  201. logger.WarnToConsole("unable to save private key to file: %v", err)
  202. }
  203. err = ioutil.WriteFile(gitWrapPath, []byte(fmt.Sprintf("%v -i %v -oStrictHostKeyChecking=no %v\n",
  204. sshPath, privateKeyPath, scriptArgs)), os.ModePerm)
  205. if err != nil {
  206. logger.WarnToConsole("unable to save gitwrap shell script: %v", err)
  207. }
  208. err = ioutil.WriteFile(trustedCAUserKey, []byte(testCAUserKey), 0600)
  209. if err != nil {
  210. logger.WarnToConsole("unable to save trusted CA user key: %v", err)
  211. }
  212. sftpdConf.TrustedUserCAKeys = append(sftpdConf.TrustedUserCAKeys, trustedCAUserKey)
  213. go func() {
  214. logger.Debug(logSender, "", "initializing SFTP server with config %+v", sftpdConf)
  215. if err := sftpdConf.Initialize(configDir); err != nil {
  216. logger.ErrorToConsole("could not start SFTP server: %v", err)
  217. os.Exit(1)
  218. }
  219. }()
  220. go func() {
  221. if err := httpdConf.Initialize(configDir, false); err != nil {
  222. logger.ErrorToConsole("could not start HTTP server: %v", err)
  223. os.Exit(1)
  224. }
  225. }()
  226. waitTCPListening(fmt.Sprintf("%s:%d", sftpdConf.BindAddress, sftpdConf.BindPort))
  227. waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
  228. sftpdConf.BindPort = 2222
  229. sftpdConf.PasswordAuthentication = false
  230. common.Config.ProxyProtocol = 1
  231. go func() {
  232. logger.Debug(logSender, "", "initializing SFTP server with config %+v and proxy protocol %v",
  233. sftpdConf, common.Config.ProxyProtocol)
  234. if err := sftpdConf.Initialize(configDir); err != nil {
  235. logger.ErrorToConsole("could not start SFTP server with proxy protocol 1: %v", err)
  236. os.Exit(1)
  237. }
  238. }()
  239. waitTCPListening(fmt.Sprintf("%s:%d", sftpdConf.BindAddress, sftpdConf.BindPort))
  240. sftpdConf.BindPort = 2224
  241. sftpdConf.PasswordAuthentication = true
  242. common.Config.ProxyProtocol = 2
  243. go func() {
  244. logger.Debug(logSender, "", "initializing SFTP server with config %+v and proxy protocol %v",
  245. sftpdConf, common.Config.ProxyProtocol)
  246. if err := sftpdConf.Initialize(configDir); err != nil {
  247. logger.ErrorToConsole("could not start SFTP server with proxy protocol 2: %v", err)
  248. os.Exit(1)
  249. }
  250. }()
  251. waitTCPListening(fmt.Sprintf("%s:%d", sftpdConf.BindAddress, sftpdConf.BindPort))
  252. exitCode := m.Run()
  253. os.Remove(logFilePath)
  254. os.Remove(loginBannerFile)
  255. os.Remove(pubKeyPath)
  256. os.Remove(privateKeyPath)
  257. os.Remove(trustedCAUserKey)
  258. os.Remove(gitWrapPath)
  259. os.Remove(extAuthPath)
  260. os.Remove(preLoginPath)
  261. os.Remove(postConnectPath)
  262. os.Remove(keyIntAuthPath)
  263. os.Remove(checkPwdPath)
  264. os.Exit(exitCode)
  265. }
  266. func TestInitialization(t *testing.T) {
  267. err := config.LoadConfig(configDir, "")
  268. assert.NoError(t, err)
  269. sftpdConf := config.GetSFTPDConfig()
  270. sftpdConf.BindPort = 2022
  271. sftpdConf.LoginBannerFile = "invalid_file"
  272. sftpdConf.EnabledSSHCommands = append(sftpdConf.EnabledSSHCommands, "ls")
  273. err = sftpdConf.Initialize(configDir)
  274. assert.Error(t, err)
  275. sftpdConf.KeyboardInteractiveHook = "invalid_file"
  276. err = sftpdConf.Initialize(configDir)
  277. assert.Error(t, err)
  278. sftpdConf.KeyboardInteractiveHook = filepath.Join(homeBasePath, "invalid_file")
  279. err = sftpdConf.Initialize(configDir)
  280. assert.Error(t, err)
  281. sftpdConf.BindPort = 4444
  282. common.Config.ProxyProtocol = 1
  283. common.Config.ProxyAllowed = []string{"1270.0.0.1"}
  284. err = sftpdConf.Initialize(configDir)
  285. assert.Error(t, err)
  286. sftpdConf.HostKeys = []string{"missing key"}
  287. err = sftpdConf.Initialize(configDir)
  288. assert.Error(t, err)
  289. sftpdConf.HostKeys = nil
  290. sftpdConf.TrustedUserCAKeys = []string{"missing ca key"}
  291. err = sftpdConf.Initialize(configDir)
  292. assert.Error(t, err)
  293. }
  294. func TestBasicSFTPHandling(t *testing.T) {
  295. usePubKey := false
  296. u := getTestUser(usePubKey)
  297. u.QuotaSize = 6553600
  298. user, _, err := httpd.AddUser(u, http.StatusOK)
  299. assert.NoError(t, err)
  300. err = os.RemoveAll(user.GetHomeDir())
  301. assert.NoError(t, err)
  302. client, err := getSftpClient(user, usePubKey)
  303. if assert.NoError(t, err) {
  304. defer client.Close()
  305. testFilePath := filepath.Join(homeBasePath, testFileName)
  306. testFileSize := int64(65535)
  307. expectedQuotaSize := user.UsedQuotaSize + testFileSize
  308. expectedQuotaFiles := user.UsedQuotaFiles + 1
  309. err = createTestFile(testFilePath, testFileSize)
  310. assert.NoError(t, err)
  311. err = sftpUploadFile(testFilePath, path.Join("/missing_dir", testFileName), testFileSize, client)
  312. assert.Error(t, err)
  313. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  314. assert.NoError(t, err)
  315. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  316. err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize, client)
  317. assert.NoError(t, err)
  318. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  319. assert.NoError(t, err)
  320. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  321. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  322. err = client.Remove(testFileName)
  323. assert.NoError(t, err)
  324. _, err = client.Lstat(testFileName)
  325. assert.Error(t, err)
  326. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  327. assert.NoError(t, err)
  328. assert.Equal(t, expectedQuotaFiles-1, user.UsedQuotaFiles)
  329. assert.Equal(t, expectedQuotaSize-testFileSize, user.UsedQuotaSize)
  330. err = os.Remove(testFilePath)
  331. assert.NoError(t, err)
  332. err = os.Remove(localDownloadPath)
  333. assert.NoError(t, err)
  334. }
  335. _, err = httpd.RemoveUser(user, http.StatusOK)
  336. assert.NoError(t, err)
  337. err = os.RemoveAll(user.GetHomeDir())
  338. assert.NoError(t, err)
  339. }
  340. func TestOpenReadWrite(t *testing.T) {
  341. usePubKey := false
  342. u := getTestUser(usePubKey)
  343. u.QuotaSize = 6553600
  344. user, _, err := httpd.AddUser(u, http.StatusOK)
  345. assert.NoError(t, err)
  346. client, err := getSftpClient(user, usePubKey)
  347. if assert.NoError(t, err) {
  348. defer client.Close()
  349. sftpFile, err := client.OpenFile(testFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC)
  350. if assert.NoError(t, err) {
  351. testData := []byte("test data")
  352. n, err := sftpFile.Write(testData)
  353. assert.NoError(t, err)
  354. assert.Equal(t, len(testData), n)
  355. buffer := make([]byte, 128)
  356. n, err = sftpFile.ReadAt(buffer, 1)
  357. assert.EqualError(t, err, io.EOF.Error())
  358. assert.Equal(t, len(testData)-1, n)
  359. assert.Equal(t, testData[1:], buffer[:n])
  360. err = sftpFile.Close()
  361. assert.NoError(t, err)
  362. }
  363. sftpFile, err = client.OpenFile(testFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC)
  364. if assert.NoError(t, err) {
  365. testData := []byte("new test data")
  366. n, err := sftpFile.Write(testData)
  367. assert.NoError(t, err)
  368. assert.Equal(t, len(testData), n)
  369. buffer := make([]byte, 128)
  370. n, err = sftpFile.ReadAt(buffer, 1)
  371. assert.EqualError(t, err, io.EOF.Error())
  372. assert.Equal(t, len(testData)-1, n)
  373. assert.Equal(t, testData[1:], buffer[:n])
  374. err = sftpFile.Close()
  375. assert.NoError(t, err)
  376. }
  377. }
  378. _, err = httpd.RemoveUser(user, http.StatusOK)
  379. assert.NoError(t, err)
  380. err = os.RemoveAll(user.GetHomeDir())
  381. assert.NoError(t, err)
  382. }
  383. func TestOpenReadWritePerm(t *testing.T) {
  384. usePubKey := true
  385. u := getTestUser(usePubKey)
  386. // we cannot read inside "/sub"
  387. u.Permissions["/sub"] = []string{dataprovider.PermUpload, dataprovider.PermListItems}
  388. user, _, err := httpd.AddUser(u, http.StatusOK)
  389. assert.NoError(t, err)
  390. client, err := getSftpClient(user, usePubKey)
  391. if assert.NoError(t, err) {
  392. defer client.Close()
  393. err = client.Mkdir("sub")
  394. assert.NoError(t, err)
  395. sftpFileName := path.Join("sub", "file.txt")
  396. sftpFile, err := client.OpenFile(sftpFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC)
  397. if assert.NoError(t, err) {
  398. testData := []byte("test data")
  399. n, err := sftpFile.Write(testData)
  400. assert.NoError(t, err)
  401. assert.Equal(t, len(testData), n)
  402. buffer := make([]byte, 128)
  403. _, err = sftpFile.ReadAt(buffer, 1)
  404. if assert.Error(t, err) {
  405. assert.Contains(t, strings.ToLower(err.Error()), "permission denied")
  406. }
  407. err = sftpFile.Close()
  408. assert.NoError(t, err)
  409. }
  410. }
  411. _, err = httpd.RemoveUser(user, http.StatusOK)
  412. assert.NoError(t, err)
  413. err = os.RemoveAll(user.GetHomeDir())
  414. assert.NoError(t, err)
  415. }
  416. func TestConcurrency(t *testing.T) {
  417. usePubKey := true
  418. numLogins := 50
  419. u := getTestUser(usePubKey)
  420. u.QuotaFiles = numLogins + 1
  421. user, _, err := httpd.AddUser(u, http.StatusOK)
  422. assert.NoError(t, err)
  423. var wg sync.WaitGroup
  424. testFilePath := filepath.Join(homeBasePath, testFileName)
  425. testFileSize := int64(262144)
  426. err = createTestFile(testFilePath, testFileSize)
  427. assert.NoError(t, err)
  428. closedConns := int32(0)
  429. for i := 0; i < numLogins; i++ {
  430. wg.Add(1)
  431. go func(counter int) {
  432. defer wg.Done()
  433. defer atomic.AddInt32(&closedConns, 1)
  434. client, err := getSftpClient(user, usePubKey)
  435. if assert.NoError(t, err) {
  436. defer client.Close()
  437. err = checkBasicSFTP(client)
  438. assert.NoError(t, err)
  439. err = sftpUploadFile(testFilePath, testFileName+strconv.Itoa(counter), testFileSize, client)
  440. assert.NoError(t, err)
  441. assert.Greater(t, common.Connections.GetActiveSessions(defaultUsername), 0)
  442. }
  443. }(i)
  444. }
  445. wg.Add(1)
  446. go func() {
  447. defer wg.Done()
  448. maxConns := 0
  449. maxSessions := 0
  450. for {
  451. servedReqs := atomic.LoadInt32(&closedConns)
  452. if servedReqs > 0 {
  453. stats := common.Connections.GetStats()
  454. if len(stats) > maxConns {
  455. maxConns = len(stats)
  456. }
  457. activeSessions := common.Connections.GetActiveSessions(defaultUsername)
  458. if activeSessions > maxSessions {
  459. maxSessions = activeSessions
  460. }
  461. }
  462. if servedReqs >= int32(numLogins) {
  463. break
  464. }
  465. time.Sleep(1 * time.Millisecond)
  466. }
  467. assert.Greater(t, maxConns, 0)
  468. assert.Greater(t, maxSessions, 0)
  469. }()
  470. wg.Wait()
  471. client, err := getSftpClient(user, usePubKey)
  472. if assert.NoError(t, err) {
  473. files, err := client.ReadDir(".")
  474. assert.NoError(t, err)
  475. assert.Len(t, files, numLogins)
  476. client.Close()
  477. }
  478. assert.Eventually(t, func() bool {
  479. return common.Connections.GetActiveSessions(defaultUsername) == 0
  480. }, 1*time.Second, 50*time.Millisecond)
  481. assert.Eventually(t, func() bool {
  482. return len(common.Connections.GetStats()) == 0
  483. }, 1*time.Second, 50*time.Millisecond)
  484. err = os.Remove(testFilePath)
  485. assert.NoError(t, err)
  486. _, err = httpd.RemoveUser(user, http.StatusOK)
  487. assert.NoError(t, err)
  488. err = os.RemoveAll(user.GetHomeDir())
  489. assert.NoError(t, err)
  490. }
  491. func TestProxyProtocol(t *testing.T) {
  492. usePubKey := true
  493. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  494. assert.NoError(t, err)
  495. // remove the home dir to test auto creation
  496. err = os.RemoveAll(user.HomeDir)
  497. assert.NoError(t, err)
  498. client, err := getSftpClientWithAddr(user, usePubKey, sftpSrvAddr2222)
  499. if assert.NoError(t, err) {
  500. defer client.Close()
  501. assert.NoError(t, checkBasicSFTP(client))
  502. }
  503. client, err = getSftpClientWithAddr(user, usePubKey, "127.0.0.1:2224")
  504. if !assert.Error(t, err) {
  505. client.Close()
  506. }
  507. _, err = httpd.RemoveUser(user, http.StatusOK)
  508. assert.NoError(t, err)
  509. err = os.RemoveAll(user.GetHomeDir())
  510. assert.NoError(t, err)
  511. }
  512. func TestUploadResume(t *testing.T) {
  513. usePubKey := false
  514. u := getTestUser(usePubKey)
  515. user, _, err := httpd.AddUser(u, http.StatusOK)
  516. assert.NoError(t, err)
  517. err = os.RemoveAll(user.GetHomeDir())
  518. assert.NoError(t, err)
  519. client, err := getSftpClient(user, usePubKey)
  520. if assert.NoError(t, err) {
  521. defer client.Close()
  522. testFilePath := filepath.Join(homeBasePath, testFileName)
  523. testFileSize := int64(65535)
  524. appendDataSize := int64(65535)
  525. err = createTestFile(testFilePath, testFileSize)
  526. assert.NoError(t, err)
  527. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  528. assert.NoError(t, err)
  529. err = appendToTestFile(testFilePath, appendDataSize)
  530. assert.NoError(t, err)
  531. err = sftpUploadResumeFile(testFilePath, testFileName, testFileSize+appendDataSize, false, client)
  532. assert.NoError(t, err)
  533. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  534. err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize+appendDataSize, client)
  535. assert.NoError(t, err)
  536. initialHash, err := computeHashForFile(sha256.New(), testFilePath)
  537. assert.NoError(t, err)
  538. donwloadedFileHash, err := computeHashForFile(sha256.New(), localDownloadPath)
  539. assert.NoError(t, err)
  540. assert.Equal(t, initialHash, donwloadedFileHash)
  541. err = sftpUploadResumeFile(testFilePath, testFileName, testFileSize+appendDataSize, true, client)
  542. assert.Error(t, err, "file upload resume with invalid offset must fail")
  543. err = os.Remove(testFilePath)
  544. assert.NoError(t, err)
  545. err = os.Remove(localDownloadPath)
  546. assert.NoError(t, err)
  547. }
  548. _, err = httpd.RemoveUser(user, http.StatusOK)
  549. assert.NoError(t, err)
  550. err = os.RemoveAll(user.GetHomeDir())
  551. assert.NoError(t, err)
  552. }
  553. func TestDirCommands(t *testing.T) {
  554. usePubKey := false
  555. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  556. assert.NoError(t, err)
  557. // remove the home dir to test auto creation
  558. err = os.RemoveAll(user.HomeDir)
  559. assert.NoError(t, err)
  560. client, err := getSftpClient(user, usePubKey)
  561. if assert.NoError(t, err) {
  562. defer client.Close()
  563. err = client.Mkdir("test1")
  564. assert.NoError(t, err)
  565. err = client.Rename("test1", "test")
  566. assert.NoError(t, err)
  567. // rename a missing file
  568. err = client.Rename("test1", "test2")
  569. assert.Error(t, err)
  570. _, err = client.Lstat("/test1")
  571. assert.Error(t, err, "stat for renamed dir must not succeed")
  572. err = client.PosixRename("test", "test1")
  573. assert.NoError(t, err)
  574. err = client.Remove("test1")
  575. assert.NoError(t, err)
  576. err = client.Mkdir("/test/test1")
  577. assert.Error(t, err, "recursive mkdir must fail")
  578. err = client.Mkdir("/test")
  579. assert.NoError(t, err)
  580. err = client.Mkdir("/test/test1")
  581. assert.NoError(t, err)
  582. _, err = client.ReadDir("/this/dir/does/not/exist")
  583. assert.Error(t, err, "reading a missing dir must fail")
  584. err = client.RemoveDirectory("/test/test1")
  585. assert.NoError(t, err)
  586. err = client.RemoveDirectory("/test")
  587. assert.NoError(t, err)
  588. _, err = client.Lstat("/test")
  589. assert.Error(t, err, "stat for deleted dir must not succeed")
  590. _, err = client.Stat("/test")
  591. assert.Error(t, err, "stat for deleted dir must not succeed")
  592. err = client.RemoveDirectory("/test")
  593. assert.Error(t, err, "remove missing path must fail")
  594. }
  595. _, err = httpd.RemoveUser(user, http.StatusOK)
  596. assert.NoError(t, err)
  597. err = os.RemoveAll(user.GetHomeDir())
  598. assert.NoError(t, err)
  599. }
  600. func TestRemove(t *testing.T) {
  601. usePubKey := true
  602. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  603. assert.NoError(t, err)
  604. client, err := getSftpClient(user, usePubKey)
  605. if assert.NoError(t, err) {
  606. defer client.Close()
  607. err = client.Mkdir("test")
  608. assert.NoError(t, err)
  609. err = client.Mkdir("/test/test1")
  610. assert.NoError(t, err)
  611. testFilePath := filepath.Join(homeBasePath, testFileName)
  612. testFileSize := int64(65535)
  613. err = createTestFile(testFilePath, testFileSize)
  614. assert.NoError(t, err)
  615. err = sftpUploadFile(testFilePath, path.Join("/test", testFileName), testFileSize, client)
  616. assert.NoError(t, err)
  617. err = client.Remove("/test")
  618. assert.Error(t, err, "remove non empty dir must fail")
  619. err = client.RemoveDirectory(path.Join("/test", testFileName))
  620. assert.Error(t, err, "remove a file with rmdir must fail")
  621. err = client.Remove(path.Join("/test", testFileName))
  622. assert.NoError(t, err)
  623. err = client.Remove(path.Join("/test", testFileName))
  624. assert.Error(t, err, "remove missing file must fail")
  625. err = client.Remove("/test/test1")
  626. assert.NoError(t, err)
  627. err = client.Remove("/test")
  628. assert.NoError(t, err)
  629. err = os.Remove(testFilePath)
  630. assert.NoError(t, err)
  631. }
  632. _, err = httpd.RemoveUser(user, http.StatusOK)
  633. assert.NoError(t, err)
  634. err = os.RemoveAll(user.GetHomeDir())
  635. assert.NoError(t, err)
  636. }
  637. func TestLink(t *testing.T) {
  638. usePubKey := false
  639. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  640. assert.NoError(t, err)
  641. client, err := getSftpClient(user, usePubKey)
  642. if assert.NoError(t, err) {
  643. defer client.Close()
  644. testFilePath := filepath.Join(homeBasePath, testFileName)
  645. testFileSize := int64(65535)
  646. err = createTestFile(testFilePath, testFileSize)
  647. assert.NoError(t, err)
  648. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  649. assert.NoError(t, err)
  650. err = client.Symlink(testFileName, testFileName+".link")
  651. assert.NoError(t, err)
  652. linkName, err := client.ReadLink(testFileName + ".link")
  653. assert.NoError(t, err)
  654. assert.Equal(t, path.Join("/", testFileName), linkName)
  655. err = client.Symlink(testFileName, testFileName+".link")
  656. assert.Error(t, err, "creating a symlink to an existing one must fail")
  657. err = client.Link(testFileName, testFileName+".hlink")
  658. assert.Error(t, err, "hard link is not supported and must fail")
  659. err = client.Remove(testFileName + ".link")
  660. assert.NoError(t, err)
  661. err = client.Remove(testFileName)
  662. assert.NoError(t, err)
  663. err = os.Remove(testFilePath)
  664. assert.NoError(t, err)
  665. }
  666. _, err = httpd.RemoveUser(user, http.StatusOK)
  667. assert.NoError(t, err)
  668. err = os.RemoveAll(user.GetHomeDir())
  669. assert.NoError(t, err)
  670. }
  671. func TestStat(t *testing.T) {
  672. usePubKey := false
  673. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  674. assert.NoError(t, err)
  675. client, err := getSftpClient(user, usePubKey)
  676. if assert.NoError(t, err) {
  677. defer client.Close()
  678. testFilePath := filepath.Join(homeBasePath, testFileName)
  679. testFileSize := int64(65535)
  680. err = createTestFile(testFilePath, testFileSize)
  681. assert.NoError(t, err)
  682. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  683. assert.NoError(t, err)
  684. _, err := client.Lstat(testFileName)
  685. assert.NoError(t, err)
  686. _, err = client.Stat(testFileName)
  687. assert.NoError(t, err)
  688. // mode 0666 and 0444 works on Windows too
  689. newPerm := os.FileMode(0666)
  690. err = client.Chmod(testFileName, newPerm)
  691. assert.NoError(t, err)
  692. newFi, err := client.Lstat(testFileName)
  693. assert.NoError(t, err)
  694. assert.Equal(t, newPerm, newFi.Mode().Perm())
  695. newPerm = os.FileMode(0444)
  696. err = client.Chmod(testFileName, newPerm)
  697. assert.NoError(t, err)
  698. newFi, err = client.Lstat(testFileName)
  699. if assert.NoError(t, err) {
  700. assert.Equal(t, newPerm, newFi.Mode().Perm())
  701. }
  702. _, err = client.ReadLink(testFileName)
  703. assert.Error(t, err, "readlink on a file must fail")
  704. symlinkName := testFileName + ".sym"
  705. err = client.Symlink(testFileName, symlinkName)
  706. assert.NoError(t, err)
  707. info, err := client.Lstat(symlinkName)
  708. if assert.NoError(t, err) {
  709. assert.True(t, info.Mode()&os.ModeSymlink == os.ModeSymlink)
  710. }
  711. info, err = client.Stat(symlinkName)
  712. if assert.NoError(t, err) {
  713. assert.False(t, info.Mode()&os.ModeSymlink == os.ModeSymlink)
  714. }
  715. linkName, err := client.ReadLink(symlinkName)
  716. assert.NoError(t, err)
  717. assert.Equal(t, path.Join("/", testFileName), linkName)
  718. newPerm = os.FileMode(0666)
  719. err = client.Chmod(testFileName, newPerm)
  720. assert.NoError(t, err)
  721. err = client.Truncate(testFileName, 100)
  722. assert.NoError(t, err)
  723. fi, err := client.Stat(testFileName)
  724. if assert.NoError(t, err) {
  725. assert.Equal(t, int64(100), fi.Size())
  726. }
  727. f, err := client.OpenFile(testFileName, os.O_WRONLY)
  728. if assert.NoError(t, err) {
  729. err = f.Truncate(5)
  730. assert.NoError(t, err)
  731. err = f.Close()
  732. assert.NoError(t, err)
  733. }
  734. f, err = client.OpenFile(testFileName, os.O_WRONLY)
  735. newPerm = os.FileMode(0444)
  736. if assert.NoError(t, err) {
  737. err = f.Chmod(newPerm)
  738. assert.NoError(t, err)
  739. err = f.Close()
  740. assert.NoError(t, err)
  741. }
  742. newFi, err = client.Lstat(testFileName)
  743. if assert.NoError(t, err) {
  744. assert.Equal(t, newPerm, newFi.Mode().Perm())
  745. }
  746. newPerm = os.FileMode(0666)
  747. err = client.Chmod(testFileName, newPerm)
  748. assert.NoError(t, err)
  749. err = os.Remove(testFilePath)
  750. assert.NoError(t, err)
  751. }
  752. _, err = httpd.RemoveUser(user, http.StatusOK)
  753. assert.NoError(t, err)
  754. err = os.RemoveAll(user.GetHomeDir())
  755. assert.NoError(t, err)
  756. }
  757. func TestStatChownChmod(t *testing.T) {
  758. if runtime.GOOS == osWindows {
  759. t.Skip("chown is not supported on Windows, chmod is partially supported")
  760. }
  761. usePubKey := true
  762. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  763. assert.NoError(t, err)
  764. client, err := getSftpClient(user, usePubKey)
  765. if assert.NoError(t, err) {
  766. defer client.Close()
  767. testFilePath := filepath.Join(homeBasePath, testFileName)
  768. testFileSize := int64(65535)
  769. err = createTestFile(testFilePath, testFileSize)
  770. assert.NoError(t, err)
  771. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  772. assert.NoError(t, err)
  773. err = client.Chown(testFileName, os.Getuid(), os.Getgid())
  774. assert.NoError(t, err)
  775. newPerm := os.FileMode(0600)
  776. err = client.Chmod(testFileName, newPerm)
  777. assert.NoError(t, err)
  778. newFi, err := client.Lstat(testFileName)
  779. assert.NoError(t, err)
  780. assert.Equal(t, newPerm, newFi.Mode().Perm())
  781. err = client.Remove(testFileName)
  782. assert.NoError(t, err)
  783. err = client.Chmod(testFileName, newPerm)
  784. assert.EqualError(t, err, os.ErrNotExist.Error())
  785. err = client.Chown(testFileName, os.Getuid(), os.Getgid())
  786. assert.EqualError(t, err, os.ErrNotExist.Error())
  787. err = os.Remove(testFilePath)
  788. assert.NoError(t, err)
  789. }
  790. _, err = httpd.RemoveUser(user, http.StatusOK)
  791. assert.NoError(t, err)
  792. err = os.RemoveAll(user.GetHomeDir())
  793. assert.NoError(t, err)
  794. }
  795. func TestChtimes(t *testing.T) {
  796. usePubKey := false
  797. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  798. assert.NoError(t, err)
  799. client, err := getSftpClient(user, usePubKey)
  800. if assert.NoError(t, err) {
  801. defer client.Close()
  802. testFilePath := filepath.Join(homeBasePath, testFileName)
  803. testFileSize := int64(65535)
  804. testDir := "test"
  805. err = createTestFile(testFilePath, testFileSize)
  806. assert.NoError(t, err)
  807. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  808. assert.NoError(t, err)
  809. acmodTime := time.Now()
  810. err = client.Chtimes(testFileName, acmodTime, acmodTime)
  811. assert.NoError(t, err)
  812. newFi, err := client.Lstat(testFileName)
  813. assert.NoError(t, err)
  814. diff := math.Abs(newFi.ModTime().Sub(acmodTime).Seconds())
  815. assert.LessOrEqual(t, diff, float64(1))
  816. err = client.Chtimes("invalidFile", acmodTime, acmodTime)
  817. assert.EqualError(t, err, os.ErrNotExist.Error())
  818. err = client.Mkdir(testDir)
  819. assert.NoError(t, err)
  820. err = client.Chtimes(testDir, acmodTime, acmodTime)
  821. assert.NoError(t, err)
  822. newFi, err = client.Lstat(testDir)
  823. assert.NoError(t, err)
  824. diff = math.Abs(newFi.ModTime().Sub(acmodTime).Seconds())
  825. assert.LessOrEqual(t, diff, float64(1))
  826. err = os.Remove(testFilePath)
  827. assert.NoError(t, err)
  828. }
  829. _, err = httpd.RemoveUser(user, http.StatusOK)
  830. assert.NoError(t, err)
  831. err = os.RemoveAll(user.GetHomeDir())
  832. assert.NoError(t, err)
  833. }
  834. // basic tests to verify virtual chroot, should be improved to cover more cases ...
  835. func TestEscapeHomeDir(t *testing.T) {
  836. usePubKey := true
  837. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  838. assert.NoError(t, err)
  839. client, err := getSftpClient(user, usePubKey)
  840. if assert.NoError(t, err) {
  841. defer client.Close()
  842. assert.NoError(t, checkBasicSFTP(client))
  843. testDir := "testDir" //nolint:goconst
  844. linkPath := filepath.Join(homeBasePath, defaultUsername, testDir)
  845. err = os.Symlink(homeBasePath, linkPath)
  846. assert.NoError(t, err)
  847. _, err = client.ReadDir(testDir)
  848. assert.Error(t, err, "reading a symbolic link outside home dir should not succeeded")
  849. err = os.Remove(linkPath)
  850. assert.NoError(t, err)
  851. testFilePath := filepath.Join(homeBasePath, testFileName)
  852. testFileSize := int64(65535)
  853. err = createTestFile(testFilePath, testFileSize)
  854. assert.NoError(t, err)
  855. remoteDestPath := path.Join("..", "..", testFileName)
  856. err = sftpUploadFile(testFilePath, remoteDestPath, testFileSize, client)
  857. assert.NoError(t, err)
  858. _, err = client.Lstat(testFileName)
  859. assert.NoError(t, err)
  860. err = client.Remove(testFileName)
  861. assert.NoError(t, err)
  862. linkPath = filepath.Join(homeBasePath, defaultUsername, testFileName)
  863. err = os.Symlink(homeBasePath, linkPath)
  864. assert.NoError(t, err)
  865. err = sftpDownloadFile(testFileName, testFilePath, 0, client)
  866. assert.Error(t, err, "download file outside home dir must fail")
  867. err = sftpUploadFile(testFilePath, remoteDestPath, testFileSize, client)
  868. assert.Error(t, err, "overwrite a file outside home dir must fail")
  869. err = client.Chmod(remoteDestPath, 0644)
  870. assert.Error(t, err, "setstat on a file outside home dir must fail")
  871. err = os.Remove(linkPath)
  872. assert.NoError(t, err)
  873. err = os.Remove(testFilePath)
  874. assert.NoError(t, err)
  875. }
  876. _, err = httpd.RemoveUser(user, http.StatusOK)
  877. assert.NoError(t, err)
  878. err = os.RemoveAll(user.GetHomeDir())
  879. assert.NoError(t, err)
  880. }
  881. func TestHomeSpecialChars(t *testing.T) {
  882. usePubKey := true
  883. u := getTestUser(usePubKey)
  884. u.HomeDir = filepath.Join(homeBasePath, "abc açà#&%lk")
  885. user, _, err := httpd.AddUser(u, http.StatusOK)
  886. assert.NoError(t, err)
  887. client, err := getSftpClient(user, usePubKey)
  888. if assert.NoError(t, err) {
  889. defer client.Close()
  890. assert.NoError(t, checkBasicSFTP(client))
  891. testFilePath := filepath.Join(homeBasePath, testFileName)
  892. testFileSize := int64(65535)
  893. err = createTestFile(testFilePath, testFileSize)
  894. assert.NoError(t, err)
  895. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  896. assert.NoError(t, err)
  897. files, err := client.ReadDir(".")
  898. assert.NoError(t, err)
  899. assert.Equal(t, 1, len(files))
  900. err = client.Remove(testFileName)
  901. assert.NoError(t, err)
  902. err = os.Remove(testFilePath)
  903. assert.NoError(t, err)
  904. }
  905. _, err = httpd.RemoveUser(user, http.StatusOK)
  906. assert.NoError(t, err)
  907. err = os.RemoveAll(user.GetHomeDir())
  908. assert.NoError(t, err)
  909. }
  910. func TestLogin(t *testing.T) {
  911. u := getTestUser(false)
  912. u.PublicKeys = []string{testPubKey}
  913. user, _, err := httpd.AddUser(u, http.StatusOK)
  914. assert.NoError(t, err)
  915. client, err := getSftpClient(user, false)
  916. if assert.NoError(t, err) {
  917. defer client.Close()
  918. assert.NoError(t, checkBasicSFTP(client))
  919. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  920. assert.NoError(t, err)
  921. assert.Greater(t, user.LastLogin, int64(0), "last login must be updated after a successful login: %v", user.LastLogin)
  922. }
  923. client, err = getSftpClient(user, true)
  924. if assert.NoError(t, err) {
  925. defer client.Close()
  926. assert.NoError(t, checkBasicSFTP(client))
  927. }
  928. user.Password = "invalid password"
  929. client, err = getSftpClient(user, false)
  930. if !assert.Error(t, err, "login with invalid password must fail") {
  931. client.Close()
  932. }
  933. // testPubKey1 is not authorized
  934. user.PublicKeys = []string{testPubKey1}
  935. user.Password = ""
  936. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  937. assert.NoError(t, err)
  938. client, err = getSftpClient(user, true)
  939. if !assert.Error(t, err, "login with invalid public key must fail") {
  940. defer client.Close()
  941. }
  942. // login a user with multiple public keys, only the second one is valid
  943. user.PublicKeys = []string{testPubKey1, testPubKey}
  944. user.Password = ""
  945. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  946. assert.NoError(t, err)
  947. client, err = getSftpClient(user, true)
  948. if assert.NoError(t, err) {
  949. defer client.Close()
  950. assert.NoError(t, checkBasicSFTP(client))
  951. }
  952. _, err = httpd.RemoveUser(user, http.StatusOK)
  953. assert.NoError(t, err)
  954. err = os.RemoveAll(user.GetHomeDir())
  955. assert.NoError(t, err)
  956. }
  957. func TestLoginUserCert(t *testing.T) {
  958. u := getTestUser(true)
  959. u.PublicKeys = []string{testCertValid, testCertUntrustedCA, testHostCert, testCertOtherSourceAddress, testCertExpired}
  960. user, _, err := httpd.AddUser(u, http.StatusOK)
  961. assert.NoError(t, err)
  962. // try login using a cert signed from a trusted CA
  963. signer, err := getSignerForUserCert([]byte(testCertValid))
  964. assert.NoError(t, err)
  965. client, err := getCustomAuthSftpClient(user, []ssh.AuthMethod{ssh.PublicKeys(signer)}, "")
  966. if assert.NoError(t, err) {
  967. defer client.Close()
  968. assert.NoError(t, checkBasicSFTP(client))
  969. }
  970. // try login using a cert signed from an untrusted CA
  971. signer, err = getSignerForUserCert([]byte(testCertUntrustedCA))
  972. assert.NoError(t, err)
  973. client, err = getCustomAuthSftpClient(user, []ssh.AuthMethod{ssh.PublicKeys(signer)}, "")
  974. if !assert.Error(t, err) {
  975. client.Close()
  976. }
  977. // try login using an host certificate instead of an user certificate
  978. signer, err = getSignerForUserCert([]byte(testHostCert))
  979. assert.NoError(t, err)
  980. client, err = getCustomAuthSftpClient(user, []ssh.AuthMethod{ssh.PublicKeys(signer)}, "")
  981. if !assert.Error(t, err) {
  982. client.Close()
  983. }
  984. // try login using a user certificate with an authorized source address different from localhost
  985. signer, err = getSignerForUserCert([]byte(testCertOtherSourceAddress))
  986. assert.NoError(t, err)
  987. client, err = getCustomAuthSftpClient(user, []ssh.AuthMethod{ssh.PublicKeys(signer)}, "")
  988. if !assert.Error(t, err) {
  989. client.Close()
  990. }
  991. // try login using an expired certificate
  992. signer, err = getSignerForUserCert([]byte(testCertExpired))
  993. assert.NoError(t, err)
  994. client, err = getCustomAuthSftpClient(user, []ssh.AuthMethod{ssh.PublicKeys(signer)}, "")
  995. if !assert.Error(t, err) {
  996. client.Close()
  997. }
  998. _, err = httpd.RemoveUser(user, http.StatusOK)
  999. assert.NoError(t, err)
  1000. err = os.RemoveAll(user.GetHomeDir())
  1001. assert.NoError(t, err)
  1002. // now login with a username not in the set of valid principals for the given certificate
  1003. u.Username += "1"
  1004. user, _, err = httpd.AddUser(u, http.StatusOK)
  1005. assert.NoError(t, err)
  1006. signer, err = getSignerForUserCert([]byte(testCertValid))
  1007. assert.NoError(t, err)
  1008. client, err = getCustomAuthSftpClient(user, []ssh.AuthMethod{ssh.PublicKeys(signer)}, "")
  1009. if !assert.Error(t, err) {
  1010. client.Close()
  1011. }
  1012. _, err = httpd.RemoveUser(user, http.StatusOK)
  1013. assert.NoError(t, err)
  1014. err = os.RemoveAll(user.GetHomeDir())
  1015. assert.NoError(t, err)
  1016. }
  1017. func TestMultiStepLoginKeyAndPwd(t *testing.T) {
  1018. u := getTestUser(true)
  1019. u.Password = defaultPassword
  1020. u.Filters.DeniedLoginMethods = append(u.Filters.DeniedLoginMethods, []string{
  1021. dataprovider.SSHLoginMethodKeyAndKeyboardInt,
  1022. dataprovider.SSHLoginMethodPublicKey,
  1023. dataprovider.LoginMethodPassword,
  1024. dataprovider.SSHLoginMethodKeyboardInteractive,
  1025. }...)
  1026. user, _, err := httpd.AddUser(u, http.StatusOK)
  1027. assert.NoError(t, err)
  1028. client, err := getSftpClient(user, true)
  1029. if !assert.Error(t, err, "login with public key is disallowed and must fail") {
  1030. client.Close()
  1031. }
  1032. client, err = getSftpClient(user, true)
  1033. if !assert.Error(t, err, "login with password is disallowed and must fail") {
  1034. client.Close()
  1035. }
  1036. signer, _ := ssh.ParsePrivateKey([]byte(testPrivateKey))
  1037. authMethods := []ssh.AuthMethod{
  1038. ssh.PublicKeys(signer),
  1039. ssh.Password(defaultPassword),
  1040. }
  1041. client, err = getCustomAuthSftpClient(user, authMethods, "")
  1042. if assert.NoError(t, err) {
  1043. defer client.Close()
  1044. assert.NoError(t, checkBasicSFTP(client))
  1045. }
  1046. client, err = getCustomAuthSftpClient(user, authMethods, sftpSrvAddr2222)
  1047. if !assert.Error(t, err, "password auth is disabled on port 2222, multi-step auth must fail") {
  1048. client.Close()
  1049. }
  1050. authMethods = []ssh.AuthMethod{
  1051. ssh.Password(defaultPassword),
  1052. ssh.PublicKeys(signer),
  1053. }
  1054. _, err = getCustomAuthSftpClient(user, authMethods, "")
  1055. assert.Error(t, err, "multi step auth login with wrong order must fail")
  1056. _, err = httpd.RemoveUser(user, http.StatusOK)
  1057. assert.NoError(t, err)
  1058. err = os.RemoveAll(user.GetHomeDir())
  1059. assert.NoError(t, err)
  1060. }
  1061. func TestMultiStepLoginKeyAndKeyInt(t *testing.T) {
  1062. if runtime.GOOS == osWindows {
  1063. t.Skip("this test is not available on Windows")
  1064. }
  1065. u := getTestUser(true)
  1066. u.Password = defaultPassword
  1067. u.Filters.DeniedLoginMethods = append(u.Filters.DeniedLoginMethods, []string{
  1068. dataprovider.SSHLoginMethodKeyAndPassword,
  1069. dataprovider.SSHLoginMethodPublicKey,
  1070. dataprovider.LoginMethodPassword,
  1071. dataprovider.SSHLoginMethodKeyboardInteractive,
  1072. }...)
  1073. user, _, err := httpd.AddUser(u, http.StatusOK)
  1074. assert.NoError(t, err)
  1075. err = ioutil.WriteFile(keyIntAuthPath, getKeyboardInteractiveScriptContent([]string{"1", "2"}, 0, false, 1), os.ModePerm)
  1076. assert.NoError(t, err)
  1077. client, err := getSftpClient(user, true)
  1078. if !assert.Error(t, err, "login with public key is disallowed and must fail") {
  1079. client.Close()
  1080. }
  1081. signer, _ := ssh.ParsePrivateKey([]byte(testPrivateKey))
  1082. authMethods := []ssh.AuthMethod{
  1083. ssh.PublicKeys(signer),
  1084. ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) ([]string, error) {
  1085. return []string{"1", "2"}, nil
  1086. }),
  1087. }
  1088. client, err = getCustomAuthSftpClient(user, authMethods, "")
  1089. if assert.NoError(t, err) {
  1090. defer client.Close()
  1091. assert.NoError(t, checkBasicSFTP(client))
  1092. }
  1093. client, err = getCustomAuthSftpClient(user, authMethods, sftpSrvAddr2222)
  1094. if assert.NoError(t, err) {
  1095. defer client.Close()
  1096. assert.NoError(t, checkBasicSFTP(client))
  1097. }
  1098. authMethods = []ssh.AuthMethod{
  1099. ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) ([]string, error) {
  1100. return []string{"1", "2"}, nil
  1101. }),
  1102. ssh.PublicKeys(signer),
  1103. }
  1104. _, err = getCustomAuthSftpClient(user, authMethods, "")
  1105. assert.Error(t, err, "multi step auth login with wrong order must fail")
  1106. authMethods = []ssh.AuthMethod{
  1107. ssh.PublicKeys(signer),
  1108. ssh.Password(defaultPassword),
  1109. }
  1110. _, err = getCustomAuthSftpClient(user, authMethods, "")
  1111. assert.Error(t, err, "multi step auth login with wrong method must fail")
  1112. user.Filters.DeniedLoginMethods = nil
  1113. user.Filters.DeniedLoginMethods = append(user.Filters.DeniedLoginMethods, []string{
  1114. dataprovider.SSHLoginMethodKeyAndKeyboardInt,
  1115. dataprovider.SSHLoginMethodPublicKey,
  1116. dataprovider.LoginMethodPassword,
  1117. dataprovider.SSHLoginMethodKeyboardInteractive,
  1118. }...)
  1119. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1120. assert.NoError(t, err)
  1121. _, err = getCustomAuthSftpClient(user, authMethods, sftpSrvAddr2222)
  1122. assert.Error(t, err)
  1123. client, err = getCustomAuthSftpClient(user, authMethods, "")
  1124. if assert.NoError(t, err) {
  1125. assert.NoError(t, checkBasicSFTP(client))
  1126. client.Close()
  1127. }
  1128. _, err = httpd.RemoveUser(user, http.StatusOK)
  1129. assert.NoError(t, err)
  1130. err = os.RemoveAll(user.GetHomeDir())
  1131. assert.NoError(t, err)
  1132. }
  1133. func TestMultiStepLoginCertAndPwd(t *testing.T) {
  1134. u := getTestUser(true)
  1135. u.Password = defaultPassword
  1136. u.PublicKeys = []string{testCertValid, testCertOtherSourceAddress}
  1137. u.Filters.DeniedLoginMethods = append(u.Filters.DeniedLoginMethods, []string{
  1138. dataprovider.SSHLoginMethodKeyAndKeyboardInt,
  1139. dataprovider.SSHLoginMethodPublicKey,
  1140. dataprovider.LoginMethodPassword,
  1141. dataprovider.SSHLoginMethodKeyboardInteractive,
  1142. }...)
  1143. user, _, err := httpd.AddUser(u, http.StatusOK)
  1144. assert.NoError(t, err)
  1145. signer, err := getSignerForUserCert([]byte(testCertValid))
  1146. assert.NoError(t, err)
  1147. authMethods := []ssh.AuthMethod{
  1148. ssh.PublicKeys(signer),
  1149. ssh.Password(defaultPassword),
  1150. }
  1151. client, err := getCustomAuthSftpClient(user, authMethods, "")
  1152. if assert.NoError(t, err) {
  1153. defer client.Close()
  1154. assert.NoError(t, checkBasicSFTP(client))
  1155. }
  1156. signer, err = getSignerForUserCert([]byte(testCertOtherSourceAddress))
  1157. assert.NoError(t, err)
  1158. authMethods = []ssh.AuthMethod{
  1159. ssh.PublicKeys(signer),
  1160. ssh.Password(defaultPassword),
  1161. }
  1162. client, err = getCustomAuthSftpClient(user, authMethods, "")
  1163. if !assert.Error(t, err) {
  1164. client.Close()
  1165. }
  1166. _, err = httpd.RemoveUser(user, http.StatusOK)
  1167. assert.NoError(t, err)
  1168. err = os.RemoveAll(user.GetHomeDir())
  1169. assert.NoError(t, err)
  1170. }
  1171. func TestLoginUserStatus(t *testing.T) {
  1172. usePubKey := true
  1173. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  1174. assert.NoError(t, err)
  1175. client, err := getSftpClient(user, usePubKey)
  1176. if assert.NoError(t, err) {
  1177. defer client.Close()
  1178. assert.NoError(t, checkBasicSFTP(client))
  1179. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  1180. assert.NoError(t, err)
  1181. assert.Greater(t, user.LastLogin, int64(0), "last login must be updated after a successful login: %v", user.LastLogin)
  1182. }
  1183. user.Status = 0
  1184. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1185. assert.NoError(t, err)
  1186. client, err = getSftpClient(user, usePubKey)
  1187. if !assert.Error(t, err, "login for a disabled user must fail") {
  1188. client.Close()
  1189. }
  1190. _, err = httpd.RemoveUser(user, http.StatusOK)
  1191. assert.NoError(t, err)
  1192. err = os.RemoveAll(user.GetHomeDir())
  1193. assert.NoError(t, err)
  1194. }
  1195. func TestLoginUserExpiration(t *testing.T) {
  1196. usePubKey := true
  1197. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  1198. assert.NoError(t, err)
  1199. client, err := getSftpClient(user, usePubKey)
  1200. if assert.NoError(t, err) {
  1201. defer client.Close()
  1202. assert.NoError(t, checkBasicSFTP(client))
  1203. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  1204. assert.NoError(t, err)
  1205. assert.Greater(t, user.LastLogin, int64(0), "last login must be updated after a successful login: %v", user.LastLogin)
  1206. }
  1207. user.ExpirationDate = utils.GetTimeAsMsSinceEpoch(time.Now()) - 120000
  1208. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1209. assert.NoError(t, err)
  1210. client, err = getSftpClient(user, usePubKey)
  1211. if !assert.Error(t, err, "login for an expired user must fail") {
  1212. client.Close()
  1213. }
  1214. user.ExpirationDate = utils.GetTimeAsMsSinceEpoch(time.Now()) + 120000
  1215. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1216. assert.NoError(t, err)
  1217. client, err = getSftpClient(user, usePubKey)
  1218. if assert.NoError(t, err) {
  1219. defer client.Close()
  1220. assert.NoError(t, checkBasicSFTP(client))
  1221. }
  1222. _, err = httpd.RemoveUser(user, http.StatusOK)
  1223. assert.NoError(t, err)
  1224. err = os.RemoveAll(user.GetHomeDir())
  1225. assert.NoError(t, err)
  1226. }
  1227. func TestLoginInvalidFs(t *testing.T) {
  1228. usePubKey := true
  1229. u := getTestUser(usePubKey)
  1230. u.FsConfig.Provider = 2
  1231. u.FsConfig.GCSConfig.Bucket = "test"
  1232. u.FsConfig.GCSConfig.Credentials = base64.StdEncoding.EncodeToString([]byte("invalid JSON for credentials"))
  1233. user, _, err := httpd.AddUser(u, http.StatusOK)
  1234. assert.NoError(t, err)
  1235. // now remove the credentials file so the filesystem creation will fail
  1236. providerConf := config.GetProviderConf()
  1237. credentialsFile := filepath.Join(providerConf.CredentialsPath, fmt.Sprintf("%v_gcs_credentials.json", u.Username))
  1238. if !filepath.IsAbs(credentialsFile) {
  1239. credentialsFile = filepath.Join(configDir, credentialsFile)
  1240. }
  1241. err = os.Remove(credentialsFile)
  1242. assert.NoError(t, err)
  1243. client, err := getSftpClient(user, usePubKey)
  1244. if !assert.Error(t, err, "login must fail, the user has an invalid filesystem config") {
  1245. client.Close()
  1246. }
  1247. _, err = httpd.RemoveUser(user, http.StatusOK)
  1248. assert.NoError(t, err)
  1249. err = os.RemoveAll(user.GetHomeDir())
  1250. assert.NoError(t, err)
  1251. }
  1252. func TestDeniedProtocols(t *testing.T) {
  1253. u := getTestUser(true)
  1254. u.Filters.DeniedProtocols = []string{common.ProtocolSSH}
  1255. user, _, err := httpd.AddUser(u, http.StatusOK)
  1256. assert.NoError(t, err)
  1257. client, err := getSftpClient(user, true)
  1258. if !assert.Error(t, err, "SSH protocol is disabled, authentication must fail") {
  1259. client.Close()
  1260. }
  1261. user.Filters.DeniedProtocols = []string{common.ProtocolFTP, common.ProtocolWebDAV}
  1262. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1263. assert.NoError(t, err)
  1264. client, err = getSftpClient(user, true)
  1265. if assert.NoError(t, err) {
  1266. defer client.Close()
  1267. assert.NoError(t, checkBasicSFTP(client))
  1268. }
  1269. _, err = httpd.RemoveUser(user, http.StatusOK)
  1270. assert.NoError(t, err)
  1271. err = os.RemoveAll(user.GetHomeDir())
  1272. assert.NoError(t, err)
  1273. }
  1274. func TestDeniedLoginMethods(t *testing.T) {
  1275. u := getTestUser(true)
  1276. u.Filters.DeniedLoginMethods = []string{dataprovider.SSHLoginMethodPublicKey, dataprovider.LoginMethodPassword}
  1277. user, _, err := httpd.AddUser(u, http.StatusOK)
  1278. assert.NoError(t, err)
  1279. client, err := getSftpClient(user, true)
  1280. if !assert.Error(t, err, "public key login is disabled, authentication must fail") {
  1281. client.Close()
  1282. }
  1283. user.Filters.DeniedLoginMethods = []string{dataprovider.SSHLoginMethodKeyboardInteractive, dataprovider.LoginMethodPassword}
  1284. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1285. assert.NoError(t, err)
  1286. client, err = getSftpClient(user, true)
  1287. if assert.NoError(t, err) {
  1288. defer client.Close()
  1289. assert.NoError(t, checkBasicSFTP(client))
  1290. }
  1291. user.Password = defaultPassword
  1292. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1293. assert.NoError(t, err)
  1294. client, err = getSftpClient(user, false)
  1295. if !assert.Error(t, err, "password login is disabled, authentication must fail") {
  1296. client.Close()
  1297. }
  1298. user.Filters.DeniedLoginMethods = []string{dataprovider.SSHLoginMethodKeyboardInteractive, dataprovider.SSHLoginMethodPublicKey}
  1299. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1300. assert.NoError(t, err)
  1301. client, err = getSftpClient(user, false)
  1302. if assert.NoError(t, err) {
  1303. defer client.Close()
  1304. assert.NoError(t, checkBasicSFTP(client))
  1305. }
  1306. _, err = httpd.RemoveUser(user, http.StatusOK)
  1307. assert.NoError(t, err)
  1308. err = os.RemoveAll(user.GetHomeDir())
  1309. assert.NoError(t, err)
  1310. }
  1311. func TestLoginWithIPFilters(t *testing.T) {
  1312. usePubKey := true
  1313. u := getTestUser(usePubKey)
  1314. u.Filters.DeniedIP = []string{"192.167.0.0/24", "172.18.0.0/16"}
  1315. u.Filters.AllowedIP = []string{}
  1316. user, _, err := httpd.AddUser(u, http.StatusOK)
  1317. assert.NoError(t, err)
  1318. client, err := getSftpClient(user, usePubKey)
  1319. if assert.NoError(t, err) {
  1320. defer client.Close()
  1321. assert.NoError(t, checkBasicSFTP(client))
  1322. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  1323. assert.NoError(t, err)
  1324. assert.Greater(t, user.LastLogin, int64(0), "last login must be updated after a successful login: %v", user.LastLogin)
  1325. }
  1326. user.Filters.AllowedIP = []string{"127.0.0.0/8"}
  1327. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1328. assert.NoError(t, err)
  1329. client, err = getSftpClient(user, usePubKey)
  1330. if assert.NoError(t, err) {
  1331. defer client.Close()
  1332. assert.NoError(t, checkBasicSFTP(client))
  1333. }
  1334. user.Filters.AllowedIP = []string{"172.19.0.0/16"}
  1335. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1336. assert.NoError(t, err)
  1337. client, err = getSftpClient(user, usePubKey)
  1338. if !assert.Error(t, err, "login from an not allowed IP must fail") {
  1339. client.Close()
  1340. }
  1341. _, err = httpd.RemoveUser(user, http.StatusOK)
  1342. assert.NoError(t, err)
  1343. err = os.RemoveAll(user.GetHomeDir())
  1344. assert.NoError(t, err)
  1345. }
  1346. func TestLoginAfterUserUpdateEmptyPwd(t *testing.T) {
  1347. usePubKey := false
  1348. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  1349. assert.NoError(t, err)
  1350. user.Password = ""
  1351. user.PublicKeys = []string{}
  1352. // password and public key should remain unchanged
  1353. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1354. assert.NoError(t, err)
  1355. client, err := getSftpClient(user, usePubKey)
  1356. if assert.NoError(t, err) {
  1357. defer client.Close()
  1358. assert.NoError(t, checkBasicSFTP(client))
  1359. }
  1360. _, err = httpd.RemoveUser(user, http.StatusOK)
  1361. assert.NoError(t, err)
  1362. err = os.RemoveAll(user.GetHomeDir())
  1363. assert.NoError(t, err)
  1364. }
  1365. func TestLoginAfterUserUpdateEmptyPubKey(t *testing.T) {
  1366. usePubKey := true
  1367. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  1368. assert.NoError(t, err)
  1369. user.Password = ""
  1370. user.PublicKeys = []string{}
  1371. // password and public key should remain unchanged
  1372. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1373. assert.NoError(t, err)
  1374. client, err := getSftpClient(user, usePubKey)
  1375. if assert.NoError(t, err) {
  1376. defer client.Close()
  1377. assert.NoError(t, checkBasicSFTP(client))
  1378. }
  1379. _, err = httpd.RemoveUser(user, http.StatusOK)
  1380. assert.NoError(t, err)
  1381. err = os.RemoveAll(user.GetHomeDir())
  1382. assert.NoError(t, err)
  1383. }
  1384. func TestLoginKeyboardInteractiveAuth(t *testing.T) {
  1385. if runtime.GOOS == osWindows {
  1386. t.Skip("this test is not available on Windows")
  1387. }
  1388. user, _, err := httpd.AddUser(getTestUser(false), http.StatusOK)
  1389. assert.NoError(t, err)
  1390. err = ioutil.WriteFile(keyIntAuthPath, getKeyboardInteractiveScriptContent([]string{"1", "2"}, 0, false, 1), os.ModePerm)
  1391. assert.NoError(t, err)
  1392. client, err := getKeyboardInteractiveSftpClient(user, []string{"1", "2"})
  1393. if assert.NoError(t, err) {
  1394. defer client.Close()
  1395. assert.NoError(t, checkBasicSFTP(client))
  1396. }
  1397. user.Status = 0
  1398. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1399. assert.NoError(t, err)
  1400. client, err = getKeyboardInteractiveSftpClient(user, []string{"1", "2"})
  1401. if !assert.Error(t, err, "keyboard interactive auth must fail the user is disabled") {
  1402. client.Close()
  1403. }
  1404. user.Status = 1
  1405. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1406. assert.NoError(t, err)
  1407. err = ioutil.WriteFile(keyIntAuthPath, getKeyboardInteractiveScriptContent([]string{"1", "2"}, 0, false, -1), os.ModePerm)
  1408. assert.NoError(t, err)
  1409. client, err = getKeyboardInteractiveSftpClient(user, []string{"1", "2"})
  1410. if !assert.Error(t, err, "keyboard interactive auth must fail the script returned -1") {
  1411. client.Close()
  1412. }
  1413. err = ioutil.WriteFile(keyIntAuthPath, getKeyboardInteractiveScriptContent([]string{"1", "2"}, 0, true, 1), os.ModePerm)
  1414. assert.NoError(t, err)
  1415. client, err = getKeyboardInteractiveSftpClient(user, []string{"1", "2"})
  1416. if !assert.Error(t, err, "keyboard interactive auth must fail the script returned bad json") {
  1417. client.Close()
  1418. }
  1419. err = ioutil.WriteFile(keyIntAuthPath, getKeyboardInteractiveScriptContent([]string{"1", "2"}, 5, true, 1), os.ModePerm)
  1420. assert.NoError(t, err)
  1421. client, err = getKeyboardInteractiveSftpClient(user, []string{"1", "2"})
  1422. if !assert.Error(t, err, "keyboard interactive auth must fail the script returned bad json") {
  1423. client.Close()
  1424. }
  1425. _, err = httpd.RemoveUser(user, http.StatusOK)
  1426. assert.NoError(t, err)
  1427. err = os.RemoveAll(user.GetHomeDir())
  1428. assert.NoError(t, err)
  1429. }
  1430. func TestPreLoginScript(t *testing.T) {
  1431. if runtime.GOOS == osWindows {
  1432. t.Skip("this test is not available on Windows")
  1433. }
  1434. usePubKey := true
  1435. u := getTestUser(usePubKey)
  1436. err := dataprovider.Close()
  1437. assert.NoError(t, err)
  1438. err = config.LoadConfig(configDir, "")
  1439. assert.NoError(t, err)
  1440. providerConf := config.GetProviderConf()
  1441. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
  1442. assert.NoError(t, err)
  1443. providerConf.PreLoginHook = preLoginPath
  1444. err = dataprovider.Initialize(providerConf, configDir)
  1445. assert.NoError(t, err)
  1446. user, _, err := httpd.AddUser(u, http.StatusOK)
  1447. assert.NoError(t, err)
  1448. client, err := getSftpClient(u, usePubKey)
  1449. if assert.NoError(t, err) {
  1450. defer client.Close()
  1451. assert.NoError(t, checkBasicSFTP(client))
  1452. }
  1453. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), os.ModePerm)
  1454. assert.NoError(t, err)
  1455. client, err = getSftpClient(u, usePubKey)
  1456. if !assert.Error(t, err, "pre-login script returned a non json response, login must fail") {
  1457. client.Close()
  1458. }
  1459. user.Status = 0
  1460. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), os.ModePerm)
  1461. assert.NoError(t, err)
  1462. client, err = getSftpClient(u, usePubKey)
  1463. if !assert.Error(t, err, "pre-login script returned a disabled user, login must fail") {
  1464. client.Close()
  1465. }
  1466. _, err = httpd.RemoveUser(user, http.StatusOK)
  1467. assert.NoError(t, err)
  1468. err = os.RemoveAll(user.GetHomeDir())
  1469. assert.NoError(t, err)
  1470. err = dataprovider.Close()
  1471. assert.NoError(t, err)
  1472. err = config.LoadConfig(configDir, "")
  1473. assert.NoError(t, err)
  1474. providerConf = config.GetProviderConf()
  1475. err = dataprovider.Initialize(providerConf, configDir)
  1476. assert.NoError(t, err)
  1477. err = os.Remove(preLoginPath)
  1478. assert.NoError(t, err)
  1479. }
  1480. func TestPreLoginUserCreation(t *testing.T) {
  1481. if runtime.GOOS == osWindows {
  1482. t.Skip("this test is not available on Windows")
  1483. }
  1484. usePubKey := false
  1485. u := getTestUser(usePubKey)
  1486. err := dataprovider.Close()
  1487. assert.NoError(t, err)
  1488. err = config.LoadConfig(configDir, "")
  1489. assert.NoError(t, err)
  1490. providerConf := config.GetProviderConf()
  1491. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
  1492. assert.NoError(t, err)
  1493. providerConf.PreLoginHook = preLoginPath
  1494. err = dataprovider.Initialize(providerConf, configDir)
  1495. assert.NoError(t, err)
  1496. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  1497. assert.NoError(t, err)
  1498. assert.Equal(t, 0, len(users))
  1499. client, err := getSftpClient(u, usePubKey)
  1500. if assert.NoError(t, err) {
  1501. defer client.Close()
  1502. assert.NoError(t, checkBasicSFTP(client))
  1503. }
  1504. users, _, err = httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  1505. assert.NoError(t, err)
  1506. assert.Equal(t, 1, len(users))
  1507. user := users[0]
  1508. _, err = httpd.RemoveUser(user, http.StatusOK)
  1509. assert.NoError(t, err)
  1510. err = os.RemoveAll(user.GetHomeDir())
  1511. assert.NoError(t, err)
  1512. err = dataprovider.Close()
  1513. assert.NoError(t, err)
  1514. err = config.LoadConfig(configDir, "")
  1515. assert.NoError(t, err)
  1516. providerConf = config.GetProviderConf()
  1517. err = dataprovider.Initialize(providerConf, configDir)
  1518. assert.NoError(t, err)
  1519. err = os.Remove(preLoginPath)
  1520. assert.NoError(t, err)
  1521. }
  1522. func TestPostConnectHook(t *testing.T) {
  1523. if runtime.GOOS == osWindows {
  1524. t.Skip("this test is not available on Windows")
  1525. }
  1526. common.Config.PostConnectHook = postConnectPath
  1527. usePubKey := true
  1528. u := getTestUser(usePubKey)
  1529. user, _, err := httpd.AddUser(u, http.StatusOK)
  1530. assert.NoError(t, err)
  1531. err = ioutil.WriteFile(postConnectPath, getPostConnectScriptContent(0), os.ModePerm)
  1532. assert.NoError(t, err)
  1533. client, err := getSftpClient(u, usePubKey)
  1534. if assert.NoError(t, err) {
  1535. defer client.Close()
  1536. err = checkBasicSFTP(client)
  1537. assert.NoError(t, err)
  1538. }
  1539. err = ioutil.WriteFile(postConnectPath, getPostConnectScriptContent(1), os.ModePerm)
  1540. assert.NoError(t, err)
  1541. client, err = getSftpClient(u, usePubKey)
  1542. if !assert.Error(t, err) {
  1543. client.Close()
  1544. }
  1545. common.Config.PostConnectHook = "http://127.0.0.1:8080/api/v1/version"
  1546. client, err = getSftpClient(u, usePubKey)
  1547. if assert.NoError(t, err) {
  1548. defer client.Close()
  1549. err = checkBasicSFTP(client)
  1550. assert.NoError(t, err)
  1551. }
  1552. common.Config.PostConnectHook = "http://127.0.0.1:8080/notfound"
  1553. client, err = getSftpClient(u, usePubKey)
  1554. if !assert.Error(t, err) {
  1555. client.Close()
  1556. }
  1557. _, err = httpd.RemoveUser(user, http.StatusOK)
  1558. assert.NoError(t, err)
  1559. err = os.RemoveAll(user.GetHomeDir())
  1560. assert.NoError(t, err)
  1561. common.Config.PostConnectHook = ""
  1562. }
  1563. func TestCheckPwdHook(t *testing.T) {
  1564. if runtime.GOOS == osWindows {
  1565. t.Skip("this test is not available on Windows")
  1566. }
  1567. usePubKey := false
  1568. u := getTestUser(usePubKey)
  1569. u.QuotaFiles = 1000
  1570. err := dataprovider.Close()
  1571. assert.NoError(t, err)
  1572. err = config.LoadConfig(configDir, "")
  1573. assert.NoError(t, err)
  1574. providerConf := config.GetProviderConf()
  1575. err = ioutil.WriteFile(checkPwdPath, getCheckPwdScriptsContents(2, defaultPassword), os.ModePerm)
  1576. assert.NoError(t, err)
  1577. providerConf.CheckPasswordHook = checkPwdPath
  1578. providerConf.CheckPasswordScope = 1
  1579. err = dataprovider.Initialize(providerConf, configDir)
  1580. assert.NoError(t, err)
  1581. user, _, err := httpd.AddUser(u, http.StatusOK)
  1582. assert.NoError(t, err)
  1583. client, err := getSftpClient(user, usePubKey)
  1584. if assert.NoError(t, err) {
  1585. err = checkBasicSFTP(client)
  1586. assert.NoError(t, err)
  1587. client.Close()
  1588. }
  1589. err = ioutil.WriteFile(checkPwdPath, getCheckPwdScriptsContents(0, defaultPassword), os.ModePerm)
  1590. assert.NoError(t, err)
  1591. client, err = getSftpClient(user, usePubKey)
  1592. if !assert.Error(t, err) {
  1593. client.Close()
  1594. }
  1595. err = ioutil.WriteFile(checkPwdPath, getCheckPwdScriptsContents(1, ""), os.ModePerm)
  1596. assert.NoError(t, err)
  1597. user.Password = defaultPassword + "1"
  1598. client, err = getSftpClient(user, usePubKey)
  1599. if assert.NoError(t, err) {
  1600. err = checkBasicSFTP(client)
  1601. assert.NoError(t, err)
  1602. client.Close()
  1603. }
  1604. _, err = httpd.RemoveUser(user, http.StatusOK)
  1605. assert.NoError(t, err)
  1606. err = dataprovider.Close()
  1607. assert.NoError(t, err)
  1608. providerConf.CheckPasswordScope = 6
  1609. err = dataprovider.Initialize(providerConf, configDir)
  1610. assert.NoError(t, err)
  1611. user, _, err = httpd.AddUser(u, http.StatusOK)
  1612. assert.NoError(t, err)
  1613. user.Password = defaultPassword + "1"
  1614. client, err = getSftpClient(user, usePubKey)
  1615. if !assert.Error(t, err) {
  1616. client.Close()
  1617. }
  1618. _, err = httpd.RemoveUser(user, http.StatusOK)
  1619. assert.NoError(t, err)
  1620. err = os.RemoveAll(user.GetHomeDir())
  1621. assert.NoError(t, err)
  1622. err = dataprovider.Close()
  1623. assert.NoError(t, err)
  1624. err = config.LoadConfig(configDir, "")
  1625. assert.NoError(t, err)
  1626. providerConf = config.GetProviderConf()
  1627. err = dataprovider.Initialize(providerConf, configDir)
  1628. assert.NoError(t, err)
  1629. err = os.Remove(checkPwdPath)
  1630. assert.NoError(t, err)
  1631. }
  1632. func TestLoginExternalAuthPwdAndPubKey(t *testing.T) {
  1633. if runtime.GOOS == osWindows {
  1634. t.Skip("this test is not available on Windows")
  1635. }
  1636. usePubKey := true
  1637. u := getTestUser(usePubKey)
  1638. u.QuotaFiles = 1000
  1639. err := dataprovider.Close()
  1640. assert.NoError(t, err)
  1641. err = config.LoadConfig(configDir, "")
  1642. assert.NoError(t, err)
  1643. providerConf := config.GetProviderConf()
  1644. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, ""), os.ModePerm)
  1645. assert.NoError(t, err)
  1646. providerConf.ExternalAuthHook = extAuthPath
  1647. providerConf.ExternalAuthScope = 0
  1648. err = dataprovider.Initialize(providerConf, configDir)
  1649. assert.NoError(t, err)
  1650. testFileSize := int64(65535)
  1651. client, err := getSftpClient(u, usePubKey)
  1652. if assert.NoError(t, err) {
  1653. defer client.Close()
  1654. testFilePath := filepath.Join(homeBasePath, testFileName)
  1655. err = createTestFile(testFilePath, testFileSize)
  1656. assert.NoError(t, err)
  1657. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  1658. assert.NoError(t, err)
  1659. err = os.Remove(testFilePath)
  1660. assert.NoError(t, err)
  1661. }
  1662. u.Username = defaultUsername + "1"
  1663. client, err = getSftpClient(u, usePubKey)
  1664. if !assert.Error(t, err, "external auth login with invalid user must fail") {
  1665. client.Close()
  1666. }
  1667. usePubKey = false
  1668. u = getTestUser(usePubKey)
  1669. u.PublicKeys = []string{}
  1670. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, ""), os.ModePerm)
  1671. assert.NoError(t, err)
  1672. client, err = getSftpClient(u, usePubKey)
  1673. if assert.NoError(t, err) {
  1674. defer client.Close()
  1675. assert.NoError(t, checkBasicSFTP(client))
  1676. }
  1677. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  1678. assert.NoError(t, err)
  1679. if assert.Equal(t, 1, len(users)) {
  1680. user := users[0]
  1681. assert.Equal(t, 0, len(user.PublicKeys))
  1682. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  1683. assert.Equal(t, 1, user.UsedQuotaFiles)
  1684. _, err = httpd.RemoveUser(user, http.StatusOK)
  1685. assert.NoError(t, err)
  1686. err = os.RemoveAll(user.GetHomeDir())
  1687. assert.NoError(t, err)
  1688. }
  1689. err = dataprovider.Close()
  1690. assert.NoError(t, err)
  1691. err = config.LoadConfig(configDir, "")
  1692. assert.NoError(t, err)
  1693. providerConf = config.GetProviderConf()
  1694. err = dataprovider.Initialize(providerConf, configDir)
  1695. assert.NoError(t, err)
  1696. err = os.Remove(extAuthPath)
  1697. assert.NoError(t, err)
  1698. }
  1699. func TestExternalAuthDifferentUsername(t *testing.T) {
  1700. if runtime.GOOS == osWindows {
  1701. t.Skip("this test is not available on Windows")
  1702. }
  1703. usePubKey := false
  1704. extAuthUsername := "common_user"
  1705. u := getTestUser(usePubKey)
  1706. u.QuotaFiles = 1000
  1707. err := dataprovider.Close()
  1708. assert.NoError(t, err)
  1709. err = config.LoadConfig(configDir, "")
  1710. assert.NoError(t, err)
  1711. providerConf := config.GetProviderConf()
  1712. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, extAuthUsername), os.ModePerm)
  1713. assert.NoError(t, err)
  1714. providerConf.ExternalAuthHook = extAuthPath
  1715. providerConf.ExternalAuthScope = 0
  1716. err = dataprovider.Initialize(providerConf, configDir)
  1717. assert.NoError(t, err)
  1718. // the user logins using "defaultUsername" and the external auth returns "extAuthUsername"
  1719. testFileSize := int64(65535)
  1720. client, err := getSftpClient(u, usePubKey)
  1721. if assert.NoError(t, err) {
  1722. defer client.Close()
  1723. testFilePath := filepath.Join(homeBasePath, testFileName)
  1724. err = createTestFile(testFilePath, testFileSize)
  1725. assert.NoError(t, err)
  1726. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  1727. assert.NoError(t, err)
  1728. err = os.Remove(testFilePath)
  1729. assert.NoError(t, err)
  1730. }
  1731. // logins again to test that used quota is preserved
  1732. client, err = getSftpClient(u, usePubKey)
  1733. if assert.NoError(t, err) {
  1734. defer client.Close()
  1735. err = checkBasicSFTP(client)
  1736. assert.NoError(t, err)
  1737. }
  1738. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  1739. assert.NoError(t, err)
  1740. assert.Equal(t, 0, len(users))
  1741. users, _, err = httpd.GetUsers(0, 0, extAuthUsername, http.StatusOK)
  1742. assert.NoError(t, err)
  1743. if assert.Equal(t, 1, len(users)) {
  1744. user := users[0]
  1745. assert.Equal(t, 0, len(user.PublicKeys))
  1746. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  1747. assert.Equal(t, 1, user.UsedQuotaFiles)
  1748. _, err = httpd.RemoveUser(user, http.StatusOK)
  1749. assert.NoError(t, err)
  1750. err = os.RemoveAll(user.GetHomeDir())
  1751. assert.NoError(t, err)
  1752. }
  1753. err = dataprovider.Close()
  1754. assert.NoError(t, err)
  1755. err = config.LoadConfig(configDir, "")
  1756. assert.NoError(t, err)
  1757. providerConf = config.GetProviderConf()
  1758. err = dataprovider.Initialize(providerConf, configDir)
  1759. assert.NoError(t, err)
  1760. err = os.Remove(extAuthPath)
  1761. assert.NoError(t, err)
  1762. }
  1763. func TestLoginExternalAuth(t *testing.T) {
  1764. if runtime.GOOS == osWindows {
  1765. t.Skip("this test is not available on Windows")
  1766. }
  1767. mappedPath := filepath.Join(os.TempDir(), "vdir1")
  1768. extAuthScopes := []int{1, 2}
  1769. for _, authScope := range extAuthScopes {
  1770. var usePubKey bool
  1771. if authScope == 1 {
  1772. usePubKey = false
  1773. } else {
  1774. usePubKey = true
  1775. }
  1776. u := getTestUser(usePubKey)
  1777. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1778. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1779. MappedPath: mappedPath,
  1780. },
  1781. VirtualPath: "/vpath",
  1782. QuotaFiles: 1 + authScope,
  1783. QuotaSize: 10 + int64(authScope),
  1784. })
  1785. err := dataprovider.Close()
  1786. assert.NoError(t, err)
  1787. err = config.LoadConfig(configDir, "")
  1788. assert.NoError(t, err)
  1789. providerConf := config.GetProviderConf()
  1790. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, ""), os.ModePerm)
  1791. assert.NoError(t, err)
  1792. providerConf.ExternalAuthHook = extAuthPath
  1793. providerConf.ExternalAuthScope = authScope
  1794. err = dataprovider.Initialize(providerConf, configDir)
  1795. assert.NoError(t, err)
  1796. client, err := getSftpClient(u, usePubKey)
  1797. if assert.NoError(t, err) {
  1798. defer client.Close()
  1799. assert.NoError(t, checkBasicSFTP(client))
  1800. }
  1801. u.Username = defaultUsername + "1"
  1802. client, err = getSftpClient(u, usePubKey)
  1803. if !assert.Error(t, err, "external auth login with invalid user must fail") {
  1804. client.Close()
  1805. }
  1806. usePubKey = !usePubKey
  1807. u = getTestUser(usePubKey)
  1808. client, err = getSftpClient(u, usePubKey)
  1809. if !assert.Error(t, err, "external auth login with valid user but invalid auth scope must fail") {
  1810. client.Close()
  1811. }
  1812. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  1813. assert.NoError(t, err)
  1814. if assert.Len(t, users, 1) {
  1815. user := users[0]
  1816. if assert.Len(t, user.VirtualFolders, 1) {
  1817. folder := user.VirtualFolders[0]
  1818. assert.Equal(t, mappedPath, folder.MappedPath)
  1819. assert.Equal(t, 1+authScope, folder.QuotaFiles)
  1820. assert.Equal(t, 10+int64(authScope), folder.QuotaSize)
  1821. }
  1822. _, err = httpd.RemoveUser(user, http.StatusOK)
  1823. assert.NoError(t, err)
  1824. err = os.RemoveAll(user.GetHomeDir())
  1825. assert.NoError(t, err)
  1826. }
  1827. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath}, http.StatusOK)
  1828. assert.NoError(t, err)
  1829. err = dataprovider.Close()
  1830. assert.NoError(t, err)
  1831. err = config.LoadConfig(configDir, "")
  1832. assert.NoError(t, err)
  1833. providerConf = config.GetProviderConf()
  1834. err = dataprovider.Initialize(providerConf, configDir)
  1835. assert.NoError(t, err)
  1836. err = os.Remove(extAuthPath)
  1837. assert.NoError(t, err)
  1838. }
  1839. }
  1840. func TestLoginExternalAuthInteractive(t *testing.T) {
  1841. if runtime.GOOS == osWindows {
  1842. t.Skip("this test is not available on Windows")
  1843. }
  1844. usePubKey := false
  1845. u := getTestUser(usePubKey)
  1846. err := dataprovider.Close()
  1847. assert.NoError(t, err)
  1848. err = config.LoadConfig(configDir, "")
  1849. assert.NoError(t, err)
  1850. providerConf := config.GetProviderConf()
  1851. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, ""), os.ModePerm)
  1852. assert.NoError(t, err)
  1853. providerConf.ExternalAuthHook = extAuthPath
  1854. providerConf.ExternalAuthScope = 4
  1855. err = dataprovider.Initialize(providerConf, configDir)
  1856. assert.NoError(t, err)
  1857. err = ioutil.WriteFile(keyIntAuthPath, getKeyboardInteractiveScriptContent([]string{"1", "2"}, 0, false, 1), os.ModePerm)
  1858. assert.NoError(t, err)
  1859. client, err := getKeyboardInteractiveSftpClient(u, []string{"1", "2"})
  1860. if assert.NoError(t, err) {
  1861. defer client.Close()
  1862. assert.NoError(t, checkBasicSFTP(client))
  1863. }
  1864. u.Username = defaultUsername + "1"
  1865. client, err = getKeyboardInteractiveSftpClient(u, []string{"1", "2"})
  1866. if !assert.Error(t, err, "external auth login with invalid user must fail") {
  1867. client.Close()
  1868. }
  1869. usePubKey = true
  1870. u = getTestUser(usePubKey)
  1871. client, err = getSftpClient(u, usePubKey)
  1872. if !assert.Error(t, err, "external auth login with valid user but invalid auth scope must fail") {
  1873. client.Close()
  1874. }
  1875. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  1876. assert.NoError(t, err)
  1877. assert.Equal(t, 1, len(users))
  1878. user := users[0]
  1879. _, err = httpd.RemoveUser(user, http.StatusOK)
  1880. assert.NoError(t, err)
  1881. err = os.RemoveAll(user.GetHomeDir())
  1882. assert.NoError(t, err)
  1883. err = dataprovider.Close()
  1884. assert.NoError(t, err)
  1885. err = config.LoadConfig(configDir, "")
  1886. assert.NoError(t, err)
  1887. providerConf = config.GetProviderConf()
  1888. err = dataprovider.Initialize(providerConf, configDir)
  1889. assert.NoError(t, err)
  1890. err = os.Remove(extAuthPath)
  1891. assert.NoError(t, err)
  1892. }
  1893. func TestLoginExternalAuthErrors(t *testing.T) {
  1894. if runtime.GOOS == osWindows {
  1895. t.Skip("this test is not available on Windows")
  1896. }
  1897. usePubKey := true
  1898. u := getTestUser(usePubKey)
  1899. err := dataprovider.Close()
  1900. assert.NoError(t, err)
  1901. err = config.LoadConfig(configDir, "")
  1902. assert.NoError(t, err)
  1903. providerConf := config.GetProviderConf()
  1904. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, true, ""), os.ModePerm)
  1905. assert.NoError(t, err)
  1906. providerConf.ExternalAuthHook = extAuthPath
  1907. providerConf.ExternalAuthScope = 0
  1908. err = dataprovider.Initialize(providerConf, configDir)
  1909. assert.NoError(t, err)
  1910. client, err := getSftpClient(u, usePubKey)
  1911. if !assert.Error(t, err, "login must fail, external auth returns a non json response") {
  1912. client.Close()
  1913. }
  1914. usePubKey = false
  1915. u = getTestUser(usePubKey)
  1916. client, err = getSftpClient(u, usePubKey)
  1917. if !assert.Error(t, err, "login must fail, external auth returns a non json response") {
  1918. client.Close()
  1919. }
  1920. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  1921. assert.NoError(t, err)
  1922. assert.Equal(t, 0, len(users))
  1923. err = dataprovider.Close()
  1924. assert.NoError(t, err)
  1925. err = config.LoadConfig(configDir, "")
  1926. assert.NoError(t, err)
  1927. providerConf = config.GetProviderConf()
  1928. err = dataprovider.Initialize(providerConf, configDir)
  1929. assert.NoError(t, err)
  1930. err = os.Remove(extAuthPath)
  1931. assert.NoError(t, err)
  1932. }
  1933. func TestQuotaDisabledError(t *testing.T) {
  1934. err := dataprovider.Close()
  1935. assert.NoError(t, err)
  1936. err = config.LoadConfig(configDir, "")
  1937. assert.NoError(t, err)
  1938. providerConf := config.GetProviderConf()
  1939. providerConf.TrackQuota = 0
  1940. err = dataprovider.Initialize(providerConf, configDir)
  1941. assert.NoError(t, err)
  1942. usePubKey := false
  1943. u := getTestUser(usePubKey)
  1944. u.QuotaFiles = 1
  1945. user, _, err := httpd.AddUser(u, http.StatusOK)
  1946. assert.NoError(t, err)
  1947. client, err := getSftpClient(user, usePubKey)
  1948. if assert.NoError(t, err) {
  1949. defer client.Close()
  1950. testFilePath := filepath.Join(homeBasePath, testFileName)
  1951. testFileSize := int64(65535)
  1952. err = createTestFile(testFilePath, testFileSize)
  1953. assert.NoError(t, err)
  1954. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  1955. assert.NoError(t, err)
  1956. err = sftpUploadFile(testFilePath, testFileName+"1", testFileSize, client)
  1957. assert.NoError(t, err)
  1958. err = client.Rename(testFileName+"1", testFileName+".rename")
  1959. assert.NoError(t, err)
  1960. err = os.Remove(testFilePath)
  1961. assert.NoError(t, err)
  1962. }
  1963. _, err = httpd.RemoveUser(user, http.StatusOK)
  1964. assert.NoError(t, err)
  1965. err = os.RemoveAll(user.GetHomeDir())
  1966. assert.NoError(t, err)
  1967. err = dataprovider.Close()
  1968. assert.NoError(t, err)
  1969. err = config.LoadConfig(configDir, "")
  1970. assert.NoError(t, err)
  1971. providerConf = config.GetProviderConf()
  1972. err = dataprovider.Initialize(providerConf, configDir)
  1973. assert.NoError(t, err)
  1974. }
  1975. func TestMaxSessions(t *testing.T) {
  1976. usePubKey := false
  1977. u := getTestUser(usePubKey)
  1978. u.Username += "1"
  1979. u.MaxSessions = 1
  1980. user, _, err := httpd.AddUser(u, http.StatusOK)
  1981. assert.NoError(t, err)
  1982. client, err := getSftpClient(user, usePubKey)
  1983. if assert.NoError(t, err) {
  1984. defer client.Close()
  1985. assert.NoError(t, checkBasicSFTP(client))
  1986. c, err := getSftpClient(user, usePubKey)
  1987. if !assert.Error(t, err, "max sessions exceeded, new login should not succeed") {
  1988. c.Close()
  1989. }
  1990. }
  1991. _, err = httpd.RemoveUser(user, http.StatusOK)
  1992. assert.NoError(t, err)
  1993. err = os.RemoveAll(user.GetHomeDir())
  1994. assert.NoError(t, err)
  1995. }
  1996. func TestQuotaFileReplace(t *testing.T) {
  1997. usePubKey := false
  1998. u := getTestUser(usePubKey)
  1999. u.QuotaFiles = 1000
  2000. user, _, err := httpd.AddUser(u, http.StatusOK)
  2001. assert.NoError(t, err)
  2002. err = os.RemoveAll(user.GetHomeDir())
  2003. assert.NoError(t, err)
  2004. testFileSize := int64(65535)
  2005. testFilePath := filepath.Join(homeBasePath, testFileName)
  2006. client, err := getSftpClient(user, usePubKey)
  2007. if assert.NoError(t, err) {
  2008. defer client.Close()
  2009. expectedQuotaSize := user.UsedQuotaSize + testFileSize
  2010. expectedQuotaFiles := user.UsedQuotaFiles + 1
  2011. err = createTestFile(testFilePath, testFileSize)
  2012. assert.NoError(t, err)
  2013. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2014. assert.NoError(t, err)
  2015. // now replace the same file, the quota must not change
  2016. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2017. assert.NoError(t, err)
  2018. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2019. assert.NoError(t, err)
  2020. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  2021. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  2022. // now create a symlink, replace it with a file and check the quota
  2023. // replacing a symlink is like uploading a new file
  2024. err = client.Symlink(testFileName, testFileName+".link")
  2025. assert.NoError(t, err)
  2026. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2027. assert.NoError(t, err)
  2028. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  2029. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  2030. expectedQuotaFiles = expectedQuotaFiles + 1
  2031. expectedQuotaSize = expectedQuotaSize + testFileSize
  2032. err = sftpUploadFile(testFilePath, testFileName+".link", testFileSize, client)
  2033. assert.NoError(t, err)
  2034. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2035. assert.NoError(t, err)
  2036. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  2037. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  2038. }
  2039. // now set a quota size restriction and upload the same file, upload should fail for space limit exceeded
  2040. user.QuotaSize = testFileSize*2 - 1
  2041. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  2042. assert.NoError(t, err)
  2043. client, err = getSftpClient(user, usePubKey)
  2044. if assert.NoError(t, err) {
  2045. defer client.Close()
  2046. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2047. assert.Error(t, err, "quota size exceeded, file upload must fail")
  2048. err = client.Remove(testFileName)
  2049. assert.NoError(t, err)
  2050. }
  2051. _, err = httpd.RemoveUser(user, http.StatusOK)
  2052. assert.NoError(t, err)
  2053. err = os.Remove(testFilePath)
  2054. assert.NoError(t, err)
  2055. err = os.RemoveAll(user.GetHomeDir())
  2056. assert.NoError(t, err)
  2057. }
  2058. func TestQuotaRename(t *testing.T) {
  2059. usePubKey := false
  2060. u := getTestUser(usePubKey)
  2061. u.QuotaFiles = 1000
  2062. user, _, err := httpd.AddUser(u, http.StatusOK)
  2063. assert.NoError(t, err)
  2064. err = os.RemoveAll(user.GetHomeDir())
  2065. assert.NoError(t, err)
  2066. testFileSize := int64(65535)
  2067. testFileSize1 := int64(65537)
  2068. testFileName1 := "test_file1.dat" //nolint:goconst
  2069. testFilePath := filepath.Join(homeBasePath, testFileName)
  2070. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  2071. client, err := getSftpClient(user, usePubKey)
  2072. if assert.NoError(t, err) {
  2073. defer client.Close()
  2074. err = createTestFile(testFilePath, testFileSize)
  2075. assert.NoError(t, err)
  2076. err = createTestFile(testFilePath1, testFileSize1)
  2077. assert.NoError(t, err)
  2078. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2079. assert.NoError(t, err)
  2080. err = client.Rename(testFileName, testFileName+".rename")
  2081. assert.NoError(t, err)
  2082. err = sftpUploadFile(testFilePath1, testFileName1, testFileSize1, client)
  2083. assert.NoError(t, err)
  2084. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2085. assert.NoError(t, err)
  2086. assert.Equal(t, 2, user.UsedQuotaFiles)
  2087. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  2088. err = client.Rename(testFileName1, testFileName+".rename")
  2089. assert.NoError(t, err)
  2090. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2091. assert.NoError(t, err)
  2092. assert.Equal(t, 1, user.UsedQuotaFiles)
  2093. assert.Equal(t, testFileSize1, user.UsedQuotaSize)
  2094. err = client.Symlink(testFileName+".rename", testFileName+".symlink")
  2095. assert.NoError(t, err)
  2096. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2097. assert.NoError(t, err)
  2098. // overwrite a symlink
  2099. err = client.Rename(testFileName, testFileName+".symlink")
  2100. assert.NoError(t, err)
  2101. err = client.Mkdir("testdir")
  2102. assert.NoError(t, err)
  2103. err = client.Rename("testdir", "testdir1")
  2104. assert.NoError(t, err)
  2105. err = client.Mkdir("testdir")
  2106. assert.NoError(t, err)
  2107. err = client.Rename("testdir", "testdir1")
  2108. assert.Error(t, err)
  2109. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2110. assert.NoError(t, err)
  2111. assert.Equal(t, 2, user.UsedQuotaFiles)
  2112. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  2113. testDir := "tdir"
  2114. err = client.Mkdir(testDir)
  2115. assert.NoError(t, err)
  2116. err = sftpUploadFile(testFilePath, path.Join(testDir, testFileName), testFileSize, client)
  2117. assert.NoError(t, err)
  2118. err = sftpUploadFile(testFilePath1, path.Join(testDir, testFileName1), testFileSize1, client)
  2119. assert.NoError(t, err)
  2120. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2121. assert.NoError(t, err)
  2122. assert.Equal(t, 4, user.UsedQuotaFiles)
  2123. assert.Equal(t, testFileSize*2+testFileSize1*2, user.UsedQuotaSize)
  2124. err = client.Rename(testDir, testDir+"1")
  2125. assert.NoError(t, err)
  2126. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2127. assert.NoError(t, err)
  2128. assert.Equal(t, 4, user.UsedQuotaFiles)
  2129. assert.Equal(t, testFileSize*2+testFileSize1*2, user.UsedQuotaSize)
  2130. }
  2131. _, err = httpd.RemoveUser(user, http.StatusOK)
  2132. assert.NoError(t, err)
  2133. err = os.Remove(testFilePath)
  2134. assert.NoError(t, err)
  2135. err = os.Remove(testFilePath1)
  2136. assert.NoError(t, err)
  2137. err = os.RemoveAll(user.GetHomeDir())
  2138. assert.NoError(t, err)
  2139. }
  2140. func TestQuotaScan(t *testing.T) {
  2141. usePubKey := false
  2142. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  2143. assert.NoError(t, err)
  2144. testFileSize := int64(65535)
  2145. expectedQuotaSize := user.UsedQuotaSize + testFileSize
  2146. expectedQuotaFiles := user.UsedQuotaFiles + 1
  2147. client, err := getSftpClient(user, usePubKey)
  2148. if assert.NoError(t, err) {
  2149. defer client.Close()
  2150. testFilePath := filepath.Join(homeBasePath, testFileName)
  2151. err = createTestFile(testFilePath, testFileSize)
  2152. assert.NoError(t, err)
  2153. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2154. assert.NoError(t, err)
  2155. err = os.Remove(testFilePath)
  2156. assert.NoError(t, err)
  2157. }
  2158. _, err = httpd.RemoveUser(user, http.StatusOK)
  2159. assert.NoError(t, err)
  2160. // create user with the same home dir, so there is at least an untracked file
  2161. user, _, err = httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  2162. assert.NoError(t, err)
  2163. _, err = httpd.StartQuotaScan(user, http.StatusCreated)
  2164. assert.NoError(t, err)
  2165. assert.Eventually(t, func() bool {
  2166. scans, _, err := httpd.GetQuotaScans(http.StatusOK)
  2167. if err == nil {
  2168. return len(scans) == 0
  2169. }
  2170. return false
  2171. }, 1*time.Second, 50*time.Millisecond)
  2172. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2173. assert.NoError(t, err)
  2174. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  2175. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  2176. _, err = httpd.RemoveUser(user, http.StatusOK)
  2177. assert.NoError(t, err)
  2178. err = os.RemoveAll(user.GetHomeDir())
  2179. assert.NoError(t, err)
  2180. }
  2181. func TestMultipleQuotaScans(t *testing.T) {
  2182. res := common.QuotaScans.AddUserQuotaScan(defaultUsername)
  2183. assert.True(t, res)
  2184. res = common.QuotaScans.AddUserQuotaScan(defaultUsername)
  2185. assert.False(t, res, "add quota must fail if another scan is already active")
  2186. assert.True(t, common.QuotaScans.RemoveUserQuotaScan(defaultUsername))
  2187. activeScans := common.QuotaScans.GetUsersQuotaScans()
  2188. assert.Equal(t, 0, len(activeScans))
  2189. assert.False(t, common.QuotaScans.RemoveUserQuotaScan(defaultUsername))
  2190. }
  2191. func TestQuotaLimits(t *testing.T) {
  2192. usePubKey := false
  2193. u := getTestUser(usePubKey)
  2194. u.QuotaFiles = 1
  2195. user, _, err := httpd.AddUser(u, http.StatusOK)
  2196. assert.NoError(t, err)
  2197. testFileSize := int64(65535)
  2198. testFilePath := filepath.Join(homeBasePath, testFileName)
  2199. err = createTestFile(testFilePath, testFileSize)
  2200. assert.NoError(t, err)
  2201. testFileSize1 := int64(131072)
  2202. testFileName1 := "test_file1.dat"
  2203. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  2204. err = createTestFile(testFilePath1, testFileSize1)
  2205. assert.NoError(t, err)
  2206. testFileSize2 := int64(32768)
  2207. testFileName2 := "test_file2.dat" //nolint:goconst
  2208. testFilePath2 := filepath.Join(homeBasePath, testFileName2)
  2209. err = createTestFile(testFilePath2, testFileSize2)
  2210. assert.NoError(t, err)
  2211. // test quota files
  2212. client, err := getSftpClient(user, usePubKey)
  2213. if assert.NoError(t, err) {
  2214. defer client.Close()
  2215. err = sftpUploadFile(testFilePath, testFileName+".quota", testFileSize, client)
  2216. assert.NoError(t, err)
  2217. err = sftpUploadFile(testFilePath, testFileName+".quota.1", testFileSize, client)
  2218. assert.Error(t, err, "user is over quota files, upload must fail")
  2219. // rename should work
  2220. err = client.Rename(testFileName+".quota", testFileName)
  2221. assert.NoError(t, err)
  2222. }
  2223. // test quota size
  2224. user.QuotaSize = testFileSize - 1
  2225. user.QuotaFiles = 0
  2226. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  2227. assert.NoError(t, err)
  2228. client, err = getSftpClient(user, usePubKey)
  2229. if assert.NoError(t, err) {
  2230. defer client.Close()
  2231. err = sftpUploadFile(testFilePath, testFileName+".quota.1", testFileSize, client)
  2232. assert.Error(t, err, "user is over quota size, upload must fail")
  2233. err = client.Rename(testFileName, testFileName+".quota")
  2234. assert.NoError(t, err)
  2235. err = client.Rename(testFileName+".quota", testFileName)
  2236. assert.NoError(t, err)
  2237. }
  2238. // now test quota limits while uploading the current file, we have 1 bytes remaining
  2239. user.QuotaSize = testFileSize + 1
  2240. user.QuotaFiles = 0
  2241. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  2242. assert.NoError(t, err)
  2243. client, err = getSftpClient(user, usePubKey)
  2244. if assert.NoError(t, err) {
  2245. defer client.Close()
  2246. err = sftpUploadFile(testFilePath1, testFileName1, testFileSize1, client)
  2247. assert.Error(t, err)
  2248. _, err = client.Stat(testFileName1)
  2249. assert.Error(t, err)
  2250. _, err = client.Lstat(testFileName1)
  2251. assert.Error(t, err)
  2252. // overwriting an existing file will work if the resulting size is lesser or equal than the current one
  2253. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2254. assert.NoError(t, err)
  2255. err = sftpUploadFile(testFilePath2, testFileName, testFileSize2, client)
  2256. assert.NoError(t, err)
  2257. err = sftpUploadFile(testFilePath1, testFileName, testFileSize1, client)
  2258. assert.Error(t, err)
  2259. _, err := client.Stat(testFileName)
  2260. assert.Error(t, err)
  2261. }
  2262. err = os.Remove(testFilePath)
  2263. assert.NoError(t, err)
  2264. err = os.Remove(testFilePath1)
  2265. assert.NoError(t, err)
  2266. err = os.Remove(testFilePath2)
  2267. assert.NoError(t, err)
  2268. _, err = httpd.RemoveUser(user, http.StatusOK)
  2269. assert.NoError(t, err)
  2270. err = os.RemoveAll(user.GetHomeDir())
  2271. assert.NoError(t, err)
  2272. }
  2273. func TestUploadMaxSize(t *testing.T) {
  2274. testFileSize := int64(65535)
  2275. usePubKey := false
  2276. u := getTestUser(usePubKey)
  2277. u.Filters.MaxUploadFileSize = testFileSize + 1
  2278. user, _, err := httpd.AddUser(u, http.StatusOK)
  2279. assert.NoError(t, err)
  2280. testFilePath := filepath.Join(homeBasePath, testFileName)
  2281. err = createTestFile(testFilePath, testFileSize)
  2282. assert.NoError(t, err)
  2283. testFileSize1 := int64(131072)
  2284. testFileName1 := "test_file1.dat"
  2285. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  2286. err = createTestFile(testFilePath1, testFileSize1)
  2287. assert.NoError(t, err)
  2288. client, err := getSftpClient(user, usePubKey)
  2289. if assert.NoError(t, err) {
  2290. defer client.Close()
  2291. err = sftpUploadFile(testFilePath1, testFileName1, testFileSize1, client)
  2292. assert.Error(t, err)
  2293. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2294. assert.NoError(t, err)
  2295. }
  2296. err = os.Remove(testFilePath)
  2297. assert.NoError(t, err)
  2298. err = os.Remove(testFilePath1)
  2299. assert.NoError(t, err)
  2300. _, err = httpd.RemoveUser(user, http.StatusOK)
  2301. assert.NoError(t, err)
  2302. err = os.RemoveAll(user.GetHomeDir())
  2303. assert.NoError(t, err)
  2304. }
  2305. func TestBandwidthAndConnections(t *testing.T) {
  2306. usePubKey := false
  2307. testFileSize := int64(524288)
  2308. u := getTestUser(usePubKey)
  2309. u.UploadBandwidth = 120
  2310. u.DownloadBandwidth = 100
  2311. wantedUploadElapsed := 1000 * (testFileSize / 1000) / u.UploadBandwidth
  2312. wantedDownloadElapsed := 1000 * (testFileSize / 1000) / u.DownloadBandwidth
  2313. // 100 ms tolerance
  2314. wantedUploadElapsed -= 100
  2315. wantedDownloadElapsed -= 100
  2316. user, _, err := httpd.AddUser(u, http.StatusOK)
  2317. assert.NoError(t, err)
  2318. client, err := getSftpClient(user, usePubKey)
  2319. if assert.NoError(t, err) {
  2320. defer client.Close()
  2321. testFilePath := filepath.Join(homeBasePath, testFileName)
  2322. err = createTestFile(testFilePath, testFileSize)
  2323. assert.NoError(t, err)
  2324. startTime := time.Now()
  2325. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2326. assert.NoError(t, err)
  2327. elapsed := time.Since(startTime).Nanoseconds() / 1000000
  2328. assert.GreaterOrEqual(t, elapsed, wantedUploadElapsed, "upload bandwidth throttling not respected")
  2329. startTime = time.Now()
  2330. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  2331. c := sftpDownloadNonBlocking(testFileName, localDownloadPath, testFileSize, client)
  2332. waitForActiveTransfers(t)
  2333. // wait some additional arbitrary time to wait for transfer activity to happen
  2334. // it is need to reach all the code in CheckIdleConnections
  2335. time.Sleep(100 * time.Millisecond)
  2336. err = <-c
  2337. assert.NoError(t, err)
  2338. elapsed = time.Since(startTime).Nanoseconds() / 1000000
  2339. assert.GreaterOrEqual(t, elapsed, wantedDownloadElapsed, "download bandwidth throttling not respected")
  2340. // test disconnection
  2341. c = sftpUploadNonBlocking(testFilePath, testFileName+"_partial", testFileSize, client)
  2342. waitForActiveTransfers(t)
  2343. time.Sleep(100 * time.Millisecond)
  2344. for _, stat := range common.Connections.GetStats() {
  2345. common.Connections.Close(stat.ConnectionID)
  2346. }
  2347. err = <-c
  2348. assert.Error(t, err, "connection closed while uploading: the upload must fail")
  2349. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 }, 1*time.Second, 50*time.Millisecond)
  2350. err = os.Remove(testFilePath)
  2351. assert.NoError(t, err)
  2352. err = os.Remove(localDownloadPath)
  2353. assert.NoError(t, err)
  2354. }
  2355. _, err = httpd.RemoveUser(user, http.StatusOK)
  2356. assert.NoError(t, err)
  2357. err = os.RemoveAll(user.GetHomeDir())
  2358. assert.NoError(t, err)
  2359. }
  2360. func TestExtensionsFilters(t *testing.T) {
  2361. usePubKey := true
  2362. u := getTestUser(usePubKey)
  2363. user, _, err := httpd.AddUser(u, http.StatusOK)
  2364. assert.NoError(t, err)
  2365. testFileSize := int64(131072)
  2366. testFilePath := filepath.Join(homeBasePath, testFileName)
  2367. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  2368. client, err := getSftpClient(user, usePubKey)
  2369. if assert.NoError(t, err) {
  2370. defer client.Close()
  2371. err = createTestFile(testFilePath, testFileSize)
  2372. assert.NoError(t, err)
  2373. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2374. assert.NoError(t, err)
  2375. }
  2376. user.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  2377. {
  2378. Path: "/",
  2379. AllowedExtensions: []string{".zip"},
  2380. DeniedExtensions: []string{},
  2381. },
  2382. }
  2383. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  2384. assert.NoError(t, err)
  2385. client, err = getSftpClient(user, usePubKey)
  2386. if assert.NoError(t, err) {
  2387. defer client.Close()
  2388. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2389. assert.Error(t, err)
  2390. err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize, client)
  2391. assert.Error(t, err)
  2392. err = client.Rename(testFileName, testFileName+"1")
  2393. assert.Error(t, err)
  2394. err = client.Remove(testFileName)
  2395. assert.Error(t, err)
  2396. err = client.Mkdir("dir.zip")
  2397. assert.NoError(t, err)
  2398. err = client.Rename("dir.zip", "dir1.zip")
  2399. assert.NoError(t, err)
  2400. }
  2401. _, err = httpd.RemoveUser(user, http.StatusOK)
  2402. assert.NoError(t, err)
  2403. err = os.Remove(testFilePath)
  2404. assert.NoError(t, err)
  2405. err = os.Remove(localDownloadPath)
  2406. assert.NoError(t, err)
  2407. err = os.RemoveAll(user.GetHomeDir())
  2408. assert.NoError(t, err)
  2409. }
  2410. func TestVirtualFolders(t *testing.T) {
  2411. usePubKey := true
  2412. u := getTestUser(usePubKey)
  2413. mappedPath := filepath.Join(os.TempDir(), "vdir")
  2414. vdirPath := "/vdir/subdir"
  2415. testDir := "/userDir"
  2416. testDir1 := "/userDir1"
  2417. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2418. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2419. MappedPath: mappedPath,
  2420. },
  2421. VirtualPath: vdirPath,
  2422. })
  2423. u.Permissions[testDir] = []string{dataprovider.PermCreateDirs}
  2424. u.Permissions[testDir1] = []string{dataprovider.PermCreateDirs, dataprovider.PermUpload, dataprovider.PermDelete}
  2425. u.Permissions[path.Join(testDir1, "subdir")] = []string{dataprovider.PermCreateSymlinks, dataprovider.PermUpload,
  2426. dataprovider.PermDelete}
  2427. err := os.MkdirAll(mappedPath, os.ModePerm)
  2428. assert.NoError(t, err)
  2429. user, _, err := httpd.AddUser(u, http.StatusOK)
  2430. assert.NoError(t, err)
  2431. client, err := getSftpClient(user, usePubKey)
  2432. if assert.NoError(t, err) {
  2433. defer client.Close()
  2434. testFileSize := int64(131072)
  2435. testFilePath := filepath.Join(homeBasePath, testFileName)
  2436. err = createTestFile(testFilePath, testFileSize)
  2437. assert.NoError(t, err)
  2438. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  2439. err = sftpUploadFile(testFilePath, path.Join(vdirPath, testFileName), testFileSize, client)
  2440. assert.NoError(t, err)
  2441. err = sftpDownloadFile(path.Join(vdirPath, testFileName), localDownloadPath, testFileSize, client)
  2442. assert.NoError(t, err)
  2443. err = client.Rename(vdirPath, "new_name")
  2444. assert.Error(t, err, "renaming a virtual folder must fail")
  2445. err = client.RemoveDirectory(vdirPath)
  2446. assert.Error(t, err, "removing a virtual folder must fail")
  2447. err = client.Mkdir(vdirPath)
  2448. assert.Error(t, err, "creating a virtual folder must fail")
  2449. err = client.Symlink(path.Join(vdirPath, testFileName), vdirPath)
  2450. assert.Error(t, err, "symlink to a virtual folder must fail")
  2451. err = client.Rename("/vdir", "/vdir1")
  2452. assert.Error(t, err, "renaming a directory with a virtual folder inside must fail")
  2453. err = client.RemoveDirectory("/vdir")
  2454. assert.Error(t, err, "removing a directory with a virtual folder inside must fail")
  2455. err = client.Mkdir("vdir1")
  2456. assert.NoError(t, err)
  2457. // rename empty dir /vdir1, we have permission on /
  2458. err = client.Rename("vdir1", "vdir2")
  2459. assert.NoError(t, err)
  2460. err = sftpUploadFile(testFilePath, path.Join("vdir2", testFileName), testFileSize, client)
  2461. assert.NoError(t, err)
  2462. // we don't have upload permission on testDir, we can only create dirs
  2463. err = client.Rename("vdir2", testDir)
  2464. assert.Error(t, err)
  2465. // on testDir1 only symlink aren't allowed
  2466. err = client.Rename("vdir2", testDir1)
  2467. assert.NoError(t, err)
  2468. err = client.Rename(testDir1, "vdir2")
  2469. assert.NoError(t, err)
  2470. err = client.MkdirAll(path.Join("vdir2", "subdir"))
  2471. assert.NoError(t, err)
  2472. err = sftpUploadFile(testFilePath, path.Join("vdir2", "subdir", testFileName), testFileSize, client)
  2473. assert.NoError(t, err)
  2474. err = client.Rename("vdir2", testDir1)
  2475. assert.NoError(t, err)
  2476. err = client.Rename(testDir1, "vdir2")
  2477. assert.NoError(t, err)
  2478. err = client.MkdirAll(path.Join("vdir2", "subdir", "subdir"))
  2479. assert.NoError(t, err)
  2480. err = sftpUploadFile(testFilePath, path.Join("vdir2", "subdir", "subdir", testFileName), testFileSize, client)
  2481. assert.NoError(t, err)
  2482. // we cannot create dirs inside /userDir1/subdir
  2483. err = client.Rename("vdir2", testDir1)
  2484. assert.Error(t, err)
  2485. err = client.Rename("vdir2", "vdir3")
  2486. assert.NoError(t, err)
  2487. err = client.Remove(path.Join("vdir3", "subdir", "subdir", testFileName))
  2488. assert.NoError(t, err)
  2489. err = client.RemoveDirectory(path.Join("vdir3", "subdir", "subdir"))
  2490. assert.NoError(t, err)
  2491. err = client.Rename("vdir3", testDir1)
  2492. assert.NoError(t, err)
  2493. err = client.Rename(testDir1, "vdir2")
  2494. assert.NoError(t, err)
  2495. err = client.Symlink(path.Join("vdir2", "subdir", testFileName), path.Join("vdir2", "subdir", "alink"))
  2496. assert.NoError(t, err)
  2497. err = client.Rename("vdir2", testDir1)
  2498. assert.NoError(t, err)
  2499. err = os.Remove(testFilePath)
  2500. assert.NoError(t, err)
  2501. err = os.Remove(localDownloadPath)
  2502. assert.NoError(t, err)
  2503. }
  2504. _, err = httpd.RemoveUser(user, http.StatusOK)
  2505. assert.NoError(t, err)
  2506. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath}, http.StatusOK)
  2507. assert.NoError(t, err)
  2508. err = os.RemoveAll(user.GetHomeDir())
  2509. assert.NoError(t, err)
  2510. err = os.RemoveAll(mappedPath)
  2511. assert.NoError(t, err)
  2512. }
  2513. func TestVirtualFoldersQuotaLimit(t *testing.T) {
  2514. usePubKey := false
  2515. u1 := getTestUser(usePubKey)
  2516. u1.QuotaFiles = 1
  2517. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  2518. vdirPath1 := "/vdir1" //nolint:goconst
  2519. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  2520. vdirPath2 := "/vdir2" //nolint:goconst
  2521. u1.VirtualFolders = append(u1.VirtualFolders, vfs.VirtualFolder{
  2522. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2523. MappedPath: mappedPath1,
  2524. },
  2525. VirtualPath: vdirPath1,
  2526. QuotaFiles: -1,
  2527. QuotaSize: -1,
  2528. })
  2529. u1.VirtualFolders = append(u1.VirtualFolders, vfs.VirtualFolder{
  2530. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2531. MappedPath: mappedPath2,
  2532. },
  2533. VirtualPath: vdirPath2,
  2534. QuotaFiles: 1,
  2535. QuotaSize: 0,
  2536. })
  2537. testFileSize := int64(131072)
  2538. testFilePath := filepath.Join(homeBasePath, testFileName)
  2539. err := createTestFile(testFilePath, testFileSize)
  2540. assert.NoError(t, err)
  2541. u2 := getTestUser(usePubKey)
  2542. u2.QuotaSize = testFileSize + 1
  2543. u2.VirtualFolders = append(u2.VirtualFolders, vfs.VirtualFolder{
  2544. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2545. MappedPath: mappedPath1,
  2546. },
  2547. VirtualPath: vdirPath1,
  2548. QuotaFiles: -1,
  2549. QuotaSize: -1,
  2550. })
  2551. u2.VirtualFolders = append(u2.VirtualFolders, vfs.VirtualFolder{
  2552. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2553. MappedPath: mappedPath2,
  2554. },
  2555. VirtualPath: vdirPath2,
  2556. QuotaFiles: 0,
  2557. QuotaSize: testFileSize + 1,
  2558. })
  2559. users := []dataprovider.User{u1, u2}
  2560. for _, u := range users {
  2561. err = os.MkdirAll(mappedPath1, os.ModePerm)
  2562. assert.NoError(t, err)
  2563. err = os.MkdirAll(mappedPath2, os.ModePerm)
  2564. assert.NoError(t, err)
  2565. user, _, err := httpd.AddUser(u, http.StatusOK)
  2566. assert.NoError(t, err)
  2567. client, err := getSftpClient(user, usePubKey)
  2568. if assert.NoError(t, err) {
  2569. defer client.Close()
  2570. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, testFileName), testFileSize, client)
  2571. assert.NoError(t, err)
  2572. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testFileName), testFileSize, client)
  2573. assert.NoError(t, err)
  2574. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2575. assert.Error(t, err)
  2576. _, err = client.Stat(testFileName)
  2577. assert.Error(t, err)
  2578. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, testFileName+"1"), testFileSize, client)
  2579. assert.Error(t, err)
  2580. _, err = client.Stat(path.Join(vdirPath1, testFileName+"1"))
  2581. assert.Error(t, err)
  2582. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testFileName+"1"), testFileSize, client)
  2583. assert.Error(t, err)
  2584. _, err = client.Stat(path.Join(vdirPath2, testFileName+"1"))
  2585. assert.Error(t, err)
  2586. err = client.Remove(path.Join(vdirPath1, testFileName))
  2587. assert.NoError(t, err)
  2588. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2589. assert.NoError(t, err)
  2590. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, testFileName), testFileSize, client)
  2591. assert.Error(t, err)
  2592. // now test renames
  2593. err = client.Rename(testFileName, path.Join(vdirPath1, testFileName))
  2594. assert.NoError(t, err)
  2595. err = client.Rename(path.Join(vdirPath1, testFileName), path.Join(vdirPath1, testFileName+".rename"))
  2596. assert.NoError(t, err)
  2597. err = client.Rename(path.Join(vdirPath2, testFileName), path.Join(vdirPath2, testFileName+".rename"))
  2598. assert.NoError(t, err)
  2599. err = client.Rename(path.Join(vdirPath2, testFileName+".rename"), testFileName+".rename")
  2600. assert.Error(t, err)
  2601. err = client.Rename(path.Join(vdirPath2, testFileName+".rename"), path.Join(vdirPath1, testFileName))
  2602. assert.Error(t, err)
  2603. err = client.Rename(path.Join(vdirPath1, testFileName+".rename"), path.Join(vdirPath2, testFileName))
  2604. assert.Error(t, err)
  2605. err = client.Rename(path.Join(vdirPath1, testFileName+".rename"), testFileName)
  2606. assert.Error(t, err)
  2607. }
  2608. _, err = httpd.RemoveUser(user, http.StatusOK)
  2609. assert.NoError(t, err)
  2610. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  2611. assert.NoError(t, err)
  2612. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  2613. assert.NoError(t, err)
  2614. err = os.RemoveAll(user.GetHomeDir())
  2615. assert.NoError(t, err)
  2616. err = os.RemoveAll(mappedPath1)
  2617. assert.NoError(t, err)
  2618. err = os.RemoveAll(mappedPath2)
  2619. assert.NoError(t, err)
  2620. }
  2621. err = os.Remove(testFilePath)
  2622. assert.NoError(t, err)
  2623. }
  2624. func TestTruncateQuotaLimits(t *testing.T) {
  2625. usePubKey := true
  2626. u := getTestUser(usePubKey)
  2627. u.QuotaSize = 20
  2628. mappedPath := filepath.Join(os.TempDir(), "mapped")
  2629. err := os.MkdirAll(mappedPath, os.ModePerm)
  2630. assert.NoError(t, err)
  2631. vdirPath := "/vmapped"
  2632. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2633. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2634. MappedPath: mappedPath,
  2635. },
  2636. VirtualPath: vdirPath,
  2637. QuotaFiles: 10,
  2638. })
  2639. user, _, err := httpd.AddUser(u, http.StatusOK)
  2640. assert.NoError(t, err)
  2641. client, err := getSftpClient(user, usePubKey)
  2642. if assert.NoError(t, err) {
  2643. defer client.Close()
  2644. data := []byte("test data")
  2645. f, err := client.OpenFile(testFileName, os.O_WRONLY)
  2646. if assert.NoError(t, err) {
  2647. n, err := f.Write(data)
  2648. assert.NoError(t, err)
  2649. assert.Equal(t, len(data), n)
  2650. err = f.Truncate(2)
  2651. assert.NoError(t, err)
  2652. expectedQuotaFiles := 0
  2653. expectedQuotaSize := int64(2)
  2654. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2655. assert.NoError(t, err)
  2656. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  2657. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  2658. _, err = f.Seek(expectedQuotaSize, io.SeekStart)
  2659. assert.NoError(t, err)
  2660. n, err = f.Write(data)
  2661. assert.NoError(t, err)
  2662. assert.Equal(t, len(data), n)
  2663. err = f.Truncate(5)
  2664. assert.NoError(t, err)
  2665. expectedQuotaSize = int64(5)
  2666. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2667. assert.NoError(t, err)
  2668. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  2669. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  2670. _, err = f.Seek(expectedQuotaSize, io.SeekStart)
  2671. assert.NoError(t, err)
  2672. n, err = f.Write(data)
  2673. assert.NoError(t, err)
  2674. assert.Equal(t, len(data), n)
  2675. err = f.Close()
  2676. assert.NoError(t, err)
  2677. expectedQuotaFiles = 1
  2678. expectedQuotaSize = int64(5) + int64(len(data))
  2679. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2680. assert.NoError(t, err)
  2681. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  2682. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  2683. }
  2684. // now truncate by path
  2685. err = client.Truncate(testFileName, 5)
  2686. assert.NoError(t, err)
  2687. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2688. assert.NoError(t, err)
  2689. assert.Equal(t, 1, user.UsedQuotaFiles)
  2690. assert.Equal(t, int64(5), user.UsedQuotaSize)
  2691. // now open an existing file without truncate it, quota should not change
  2692. f, err = client.OpenFile(testFileName, os.O_WRONLY)
  2693. if assert.NoError(t, err) {
  2694. err = f.Close()
  2695. assert.NoError(t, err)
  2696. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2697. assert.NoError(t, err)
  2698. assert.Equal(t, 1, user.UsedQuotaFiles)
  2699. assert.Equal(t, int64(5), user.UsedQuotaSize)
  2700. }
  2701. // open the file truncating it
  2702. f, err = client.OpenFile(testFileName, os.O_WRONLY|os.O_TRUNC)
  2703. if assert.NoError(t, err) {
  2704. err = f.Close()
  2705. assert.NoError(t, err)
  2706. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2707. assert.NoError(t, err)
  2708. assert.Equal(t, 1, user.UsedQuotaFiles)
  2709. assert.Equal(t, int64(0), user.UsedQuotaSize)
  2710. }
  2711. // now test max write size
  2712. f, err = client.OpenFile(testFileName, os.O_WRONLY)
  2713. if assert.NoError(t, err) {
  2714. n, err := f.Write(data)
  2715. assert.NoError(t, err)
  2716. assert.Equal(t, len(data), n)
  2717. err = f.Truncate(11)
  2718. assert.NoError(t, err)
  2719. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2720. assert.NoError(t, err)
  2721. assert.Equal(t, 1, user.UsedQuotaFiles)
  2722. assert.Equal(t, int64(11), user.UsedQuotaSize)
  2723. _, err = f.Seek(int64(11), io.SeekStart)
  2724. assert.NoError(t, err)
  2725. n, err = f.Write(data)
  2726. assert.NoError(t, err)
  2727. assert.Equal(t, len(data), n)
  2728. err = f.Truncate(5)
  2729. assert.NoError(t, err)
  2730. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2731. assert.NoError(t, err)
  2732. assert.Equal(t, 1, user.UsedQuotaFiles)
  2733. assert.Equal(t, int64(5), user.UsedQuotaSize)
  2734. _, err = f.Seek(int64(5), io.SeekStart)
  2735. assert.NoError(t, err)
  2736. n, err = f.Write(data)
  2737. assert.NoError(t, err)
  2738. assert.Equal(t, len(data), n)
  2739. err = f.Truncate(12)
  2740. assert.NoError(t, err)
  2741. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2742. assert.NoError(t, err)
  2743. assert.Equal(t, 1, user.UsedQuotaFiles)
  2744. assert.Equal(t, int64(12), user.UsedQuotaSize)
  2745. _, err = f.Seek(int64(12), io.SeekStart)
  2746. assert.NoError(t, err)
  2747. _, err = f.Write(data)
  2748. if assert.Error(t, err) {
  2749. assert.Contains(t, err.Error(), common.ErrQuotaExceeded.Error())
  2750. }
  2751. err = f.Close()
  2752. assert.Error(t, err)
  2753. // the file is deleted
  2754. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  2755. assert.NoError(t, err)
  2756. assert.Equal(t, 0, user.UsedQuotaFiles)
  2757. assert.Equal(t, int64(0), user.UsedQuotaSize)
  2758. }
  2759. // basic test inside a virtual folder
  2760. vfileName := path.Join(vdirPath, testFileName)
  2761. f, err = client.OpenFile(vfileName, os.O_WRONLY)
  2762. if assert.NoError(t, err) {
  2763. n, err := f.Write(data)
  2764. assert.NoError(t, err)
  2765. assert.Equal(t, len(data), n)
  2766. err = f.Truncate(2)
  2767. assert.NoError(t, err)
  2768. expectedQuotaFiles := 0
  2769. expectedQuotaSize := int64(2)
  2770. folder, _, err := httpd.GetFolders(0, 0, mappedPath, http.StatusOK)
  2771. assert.NoError(t, err)
  2772. if assert.Len(t, folder, 1) {
  2773. fold := folder[0]
  2774. assert.Equal(t, expectedQuotaSize, fold.UsedQuotaSize)
  2775. assert.Equal(t, expectedQuotaFiles, fold.UsedQuotaFiles)
  2776. }
  2777. err = f.Close()
  2778. assert.NoError(t, err)
  2779. expectedQuotaFiles = 1
  2780. folder, _, err = httpd.GetFolders(0, 0, mappedPath, http.StatusOK)
  2781. assert.NoError(t, err)
  2782. if assert.Len(t, folder, 1) {
  2783. fold := folder[0]
  2784. assert.Equal(t, expectedQuotaSize, fold.UsedQuotaSize)
  2785. assert.Equal(t, expectedQuotaFiles, fold.UsedQuotaFiles)
  2786. }
  2787. }
  2788. err = client.Truncate(vfileName, 1)
  2789. assert.NoError(t, err)
  2790. folder, _, err := httpd.GetFolders(0, 0, mappedPath, http.StatusOK)
  2791. assert.NoError(t, err)
  2792. if assert.Len(t, folder, 1) {
  2793. fold := folder[0]
  2794. assert.Equal(t, int64(1), fold.UsedQuotaSize)
  2795. assert.Equal(t, 1, fold.UsedQuotaFiles)
  2796. }
  2797. }
  2798. _, err = httpd.RemoveUser(user, http.StatusOK)
  2799. assert.NoError(t, err)
  2800. err = os.RemoveAll(user.GetHomeDir())
  2801. assert.NoError(t, err)
  2802. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath}, http.StatusOK)
  2803. assert.NoError(t, err)
  2804. err = os.RemoveAll(mappedPath)
  2805. assert.NoError(t, err)
  2806. }
  2807. func TestVirtualFoldersQuotaRenameOverwrite(t *testing.T) {
  2808. usePubKey := true
  2809. testFileSize := int64(131072)
  2810. testFilePath := filepath.Join(homeBasePath, testFileName)
  2811. testFileSize1 := int64(65537)
  2812. testFileName1 := "test_file1.dat"
  2813. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  2814. err := createTestFile(testFilePath, testFileSize)
  2815. assert.NoError(t, err)
  2816. err = createTestFile(testFilePath1, testFileSize1)
  2817. assert.NoError(t, err)
  2818. u := getTestUser(usePubKey)
  2819. u.QuotaFiles = 0
  2820. u.QuotaSize = 0
  2821. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  2822. vdirPath1 := "/vdir1"
  2823. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  2824. vdirPath2 := "/vdir2"
  2825. mappedPath3 := filepath.Join(os.TempDir(), "vdir3")
  2826. vdirPath3 := "/vdir3"
  2827. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2828. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2829. MappedPath: mappedPath1,
  2830. },
  2831. VirtualPath: vdirPath1,
  2832. QuotaFiles: 2,
  2833. QuotaSize: 0,
  2834. })
  2835. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2836. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2837. MappedPath: mappedPath2,
  2838. },
  2839. VirtualPath: vdirPath2,
  2840. QuotaFiles: 0,
  2841. QuotaSize: testFileSize + testFileSize1 + 1,
  2842. })
  2843. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2844. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2845. MappedPath: mappedPath3,
  2846. },
  2847. VirtualPath: vdirPath3,
  2848. QuotaFiles: 2,
  2849. QuotaSize: testFileSize * 2,
  2850. })
  2851. err = os.MkdirAll(mappedPath1, os.ModePerm)
  2852. assert.NoError(t, err)
  2853. err = os.MkdirAll(mappedPath2, os.ModePerm)
  2854. assert.NoError(t, err)
  2855. err = os.MkdirAll(mappedPath3, os.ModePerm)
  2856. assert.NoError(t, err)
  2857. user, _, err := httpd.AddUser(u, http.StatusOK)
  2858. assert.NoError(t, err)
  2859. client, err := getSftpClient(user, usePubKey)
  2860. if assert.NoError(t, err) {
  2861. defer client.Close()
  2862. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, testFileName), testFileSize, client)
  2863. assert.NoError(t, err)
  2864. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testFileName), testFileSize, client)
  2865. assert.NoError(t, err)
  2866. err = sftpUploadFile(testFilePath1, path.Join(vdirPath1, testFileName1), testFileSize1, client)
  2867. assert.NoError(t, err)
  2868. err = sftpUploadFile(testFilePath1, path.Join(vdirPath2, testFileName1), testFileSize1, client)
  2869. assert.NoError(t, err)
  2870. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2871. assert.NoError(t, err)
  2872. err = sftpUploadFile(testFilePath1, testFileName1, testFileSize1, client)
  2873. assert.NoError(t, err)
  2874. err = sftpUploadFile(testFilePath, path.Join(vdirPath3, testFileName), testFileSize, client)
  2875. assert.NoError(t, err)
  2876. err = sftpUploadFile(testFilePath, path.Join(vdirPath3, testFileName+"1"), testFileSize, client)
  2877. assert.NoError(t, err)
  2878. err = client.Rename(testFileName, path.Join(vdirPath1, testFileName+".rename"))
  2879. assert.Error(t, err)
  2880. // we overwrite an existing file and we have unlimited size
  2881. err = client.Rename(testFileName, path.Join(vdirPath1, testFileName))
  2882. assert.NoError(t, err)
  2883. // we have no space and we try to overwrite a bigger file with a smaller one, this should succeed
  2884. err = client.Rename(testFileName1, path.Join(vdirPath2, testFileName))
  2885. assert.NoError(t, err)
  2886. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testFileName), testFileSize, client)
  2887. assert.NoError(t, err)
  2888. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2889. assert.NoError(t, err)
  2890. // we have no space and we try to overwrite a smaller file with a bigger one, this should fail
  2891. err = client.Rename(testFileName, path.Join(vdirPath2, testFileName1))
  2892. assert.Error(t, err)
  2893. fi, err := client.Stat(path.Join(vdirPath1, testFileName1))
  2894. if assert.NoError(t, err) {
  2895. assert.Equal(t, testFileSize1, fi.Size())
  2896. }
  2897. // we are overquota inside vdir3 size 2/2 and size 262144/262144
  2898. err = client.Rename(path.Join(vdirPath1, testFileName1), path.Join(vdirPath3, testFileName1+".rename"))
  2899. assert.Error(t, err)
  2900. // we overwrite an existing file and we have enough size
  2901. err = client.Rename(path.Join(vdirPath1, testFileName1), path.Join(vdirPath3, testFileName))
  2902. assert.NoError(t, err)
  2903. testFileName2 := "test_file2.dat"
  2904. testFilePath2 := filepath.Join(homeBasePath, testFileName2)
  2905. err = createTestFile(testFilePath2, testFileSize+testFileSize1)
  2906. assert.NoError(t, err)
  2907. err = sftpUploadFile(testFilePath2, testFileName2, testFileSize+testFileSize1, client)
  2908. assert.NoError(t, err)
  2909. // we overwrite an existing file and we haven't enough size
  2910. err = client.Rename(testFileName2, path.Join(vdirPath3, testFileName))
  2911. assert.Error(t, err)
  2912. err = os.Remove(testFilePath2)
  2913. assert.NoError(t, err)
  2914. // now remove a file from vdir3, create a dir with 2 files and try to rename it in vdir3
  2915. // this will fail since the rename will result in 3 files inside vdir3 and quota limits only
  2916. // allow 2 total files there
  2917. err = client.Remove(path.Join(vdirPath3, testFileName+"1"))
  2918. assert.NoError(t, err)
  2919. aDir := "a dir"
  2920. err = client.Mkdir(aDir)
  2921. assert.NoError(t, err)
  2922. err = sftpUploadFile(testFilePath1, path.Join(aDir, testFileName1), testFileSize1, client)
  2923. assert.NoError(t, err)
  2924. err = sftpUploadFile(testFilePath1, path.Join(aDir, testFileName1+"1"), testFileSize1, client)
  2925. assert.NoError(t, err)
  2926. err = client.Rename(aDir, path.Join(vdirPath3, aDir))
  2927. assert.Error(t, err)
  2928. }
  2929. _, err = httpd.RemoveUser(user, http.StatusOK)
  2930. assert.NoError(t, err)
  2931. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  2932. assert.NoError(t, err)
  2933. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  2934. assert.NoError(t, err)
  2935. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath3}, http.StatusOK)
  2936. assert.NoError(t, err)
  2937. err = os.RemoveAll(user.GetHomeDir())
  2938. assert.NoError(t, err)
  2939. err = os.RemoveAll(mappedPath1)
  2940. assert.NoError(t, err)
  2941. err = os.RemoveAll(mappedPath2)
  2942. assert.NoError(t, err)
  2943. err = os.RemoveAll(mappedPath3)
  2944. assert.NoError(t, err)
  2945. err = os.Remove(testFilePath)
  2946. assert.NoError(t, err)
  2947. err = os.Remove(testFilePath1)
  2948. assert.NoError(t, err)
  2949. }
  2950. func TestVirtualFoldersQuotaValues(t *testing.T) {
  2951. usePubKey := false
  2952. u := getTestUser(usePubKey)
  2953. u.QuotaFiles = 100
  2954. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  2955. vdirPath1 := "/vdir1" //nolint:goconst
  2956. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  2957. vdirPath2 := "/vdir2" //nolint:goconst
  2958. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2959. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2960. MappedPath: mappedPath1,
  2961. },
  2962. VirtualPath: vdirPath1,
  2963. // quota is included in the user's one
  2964. QuotaFiles: -1,
  2965. QuotaSize: -1,
  2966. })
  2967. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2968. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2969. MappedPath: mappedPath2,
  2970. },
  2971. VirtualPath: vdirPath2,
  2972. // quota is unlimited and excluded from user's one
  2973. QuotaFiles: 0,
  2974. QuotaSize: 0,
  2975. })
  2976. err := os.MkdirAll(mappedPath1, os.ModePerm)
  2977. assert.NoError(t, err)
  2978. err = os.MkdirAll(mappedPath2, os.ModePerm)
  2979. assert.NoError(t, err)
  2980. user, _, err := httpd.AddUser(u, http.StatusOK)
  2981. assert.NoError(t, err)
  2982. client, err := getSftpClient(user, usePubKey)
  2983. if assert.NoError(t, err) {
  2984. defer client.Close()
  2985. testFileSize := int64(131072)
  2986. testFilePath := filepath.Join(homeBasePath, testFileName)
  2987. err = createTestFile(testFilePath, testFileSize)
  2988. assert.NoError(t, err)
  2989. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  2990. assert.NoError(t, err)
  2991. // we copy the same file two times to test quota update on file overwrite
  2992. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, testFileName), testFileSize, client)
  2993. assert.NoError(t, err)
  2994. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, testFileName), testFileSize, client)
  2995. assert.NoError(t, err)
  2996. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testFileName), testFileSize, client)
  2997. assert.NoError(t, err)
  2998. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testFileName), testFileSize, client)
  2999. assert.NoError(t, err)
  3000. expectedQuotaFiles := 2
  3001. expectedQuotaSize := testFileSize * 2
  3002. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3003. assert.NoError(t, err)
  3004. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  3005. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  3006. folder, _, err := httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3007. assert.NoError(t, err)
  3008. if assert.Len(t, folder, 1) {
  3009. f := folder[0]
  3010. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  3011. assert.Equal(t, 1, f.UsedQuotaFiles)
  3012. }
  3013. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3014. assert.NoError(t, err)
  3015. if assert.Len(t, folder, 1) {
  3016. f := folder[0]
  3017. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  3018. assert.Equal(t, 1, f.UsedQuotaFiles)
  3019. }
  3020. err = client.Remove(path.Join(vdirPath1, testFileName))
  3021. assert.NoError(t, err)
  3022. err = client.Remove(path.Join(vdirPath2, testFileName))
  3023. assert.NoError(t, err)
  3024. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3025. assert.NoError(t, err)
  3026. if assert.Len(t, folder, 1) {
  3027. f := folder[0]
  3028. assert.Equal(t, int64(0), f.UsedQuotaSize)
  3029. assert.Equal(t, 0, f.UsedQuotaFiles)
  3030. }
  3031. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3032. assert.NoError(t, err)
  3033. if assert.Len(t, folder, 1) {
  3034. f := folder[0]
  3035. assert.Equal(t, int64(0), f.UsedQuotaSize)
  3036. assert.Equal(t, 0, f.UsedQuotaFiles)
  3037. }
  3038. err = os.Remove(testFilePath)
  3039. assert.NoError(t, err)
  3040. }
  3041. _, err = httpd.RemoveUser(user, http.StatusOK)
  3042. assert.NoError(t, err)
  3043. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  3044. assert.NoError(t, err)
  3045. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  3046. assert.NoError(t, err)
  3047. err = os.RemoveAll(user.GetHomeDir())
  3048. assert.NoError(t, err)
  3049. err = os.RemoveAll(mappedPath1)
  3050. assert.NoError(t, err)
  3051. err = os.RemoveAll(mappedPath2)
  3052. assert.NoError(t, err)
  3053. }
  3054. func TestQuotaRenameInsideSameVirtualFolder(t *testing.T) {
  3055. usePubKey := false
  3056. u := getTestUser(usePubKey)
  3057. u.QuotaFiles = 100
  3058. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  3059. vdirPath1 := "/vdir1"
  3060. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  3061. vdirPath2 := "/vdir2"
  3062. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  3063. BaseVirtualFolder: vfs.BaseVirtualFolder{
  3064. MappedPath: mappedPath1,
  3065. },
  3066. VirtualPath: vdirPath1,
  3067. // quota is included in the user's one
  3068. QuotaFiles: -1,
  3069. QuotaSize: -1,
  3070. })
  3071. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  3072. BaseVirtualFolder: vfs.BaseVirtualFolder{
  3073. MappedPath: mappedPath2,
  3074. },
  3075. VirtualPath: vdirPath2,
  3076. // quota is unlimited and excluded from user's one
  3077. QuotaFiles: 0,
  3078. QuotaSize: 0,
  3079. })
  3080. err := os.MkdirAll(mappedPath1, os.ModePerm)
  3081. assert.NoError(t, err)
  3082. err = os.MkdirAll(mappedPath2, os.ModePerm)
  3083. assert.NoError(t, err)
  3084. user, _, err := httpd.AddUser(u, http.StatusOK)
  3085. assert.NoError(t, err)
  3086. client, err := getSftpClient(user, usePubKey)
  3087. if assert.NoError(t, err) {
  3088. defer client.Close()
  3089. testFileName1 := "test_file1.dat"
  3090. testFileSize := int64(131072)
  3091. testFileSize1 := int64(65535)
  3092. testFilePath := filepath.Join(homeBasePath, testFileName)
  3093. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  3094. dir1 := "dir1" //nolint:goconst
  3095. dir2 := "dir2" //nolint:goconst
  3096. err = createTestFile(testFilePath, testFileSize)
  3097. assert.NoError(t, err)
  3098. err = createTestFile(testFilePath1, testFileSize1)
  3099. assert.NoError(t, err)
  3100. err = client.Mkdir(path.Join(vdirPath1, dir1))
  3101. assert.NoError(t, err)
  3102. err = client.Mkdir(path.Join(vdirPath1, dir2))
  3103. assert.NoError(t, err)
  3104. err = client.Mkdir(path.Join(vdirPath2, dir1))
  3105. assert.NoError(t, err)
  3106. err = client.Mkdir(path.Join(vdirPath2, dir2))
  3107. assert.NoError(t, err)
  3108. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, dir1, testFileName), testFileSize, client)
  3109. assert.NoError(t, err)
  3110. err = sftpUploadFile(testFilePath1, path.Join(vdirPath1, dir2, testFileName1), testFileSize1, client)
  3111. assert.NoError(t, err)
  3112. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, dir1, testFileName), testFileSize, client)
  3113. assert.NoError(t, err)
  3114. err = sftpUploadFile(testFilePath1, path.Join(vdirPath2, dir2, testFileName1), testFileSize1, client)
  3115. assert.NoError(t, err)
  3116. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3117. assert.NoError(t, err)
  3118. assert.Equal(t, 2, user.UsedQuotaFiles)
  3119. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  3120. folder, _, err := httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3121. assert.NoError(t, err)
  3122. if assert.Len(t, folder, 1) {
  3123. f := folder[0]
  3124. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  3125. assert.Equal(t, 2, f.UsedQuotaFiles)
  3126. }
  3127. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3128. assert.NoError(t, err)
  3129. if assert.Len(t, folder, 1) {
  3130. f := folder[0]
  3131. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  3132. assert.Equal(t, 2, f.UsedQuotaFiles)
  3133. }
  3134. // initial files:
  3135. // - vdir1/dir1/testFileName
  3136. // - vdir1/dir2/testFileName1
  3137. // - vdir2/dir1/testFileName
  3138. // - vdir2/dir2/testFileName1
  3139. //
  3140. // rename a file inside vdir1 it is included inside user quota, so we have:
  3141. // - vdir1/dir1/testFileName.rename
  3142. // - vdir1/dir2/testFileName1
  3143. // - vdir2/dir1/testFileName
  3144. // - vdir2/dir2/testFileName1
  3145. err = client.Rename(path.Join(vdirPath1, dir1, testFileName), path.Join(vdirPath1, dir1, testFileName+".rename"))
  3146. assert.NoError(t, err)
  3147. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3148. assert.NoError(t, err)
  3149. assert.Equal(t, 2, user.UsedQuotaFiles)
  3150. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  3151. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3152. assert.NoError(t, err)
  3153. if assert.Len(t, folder, 1) {
  3154. f := folder[0]
  3155. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  3156. assert.Equal(t, 2, f.UsedQuotaFiles)
  3157. }
  3158. // rename a file inside vdir2, it isn't included inside user quota, so we have:
  3159. // - vdir1/dir1/testFileName.rename
  3160. // - vdir1/dir2/testFileName1
  3161. // - vdir2/dir1/testFileName.rename
  3162. // - vdir2/dir2/testFileName1
  3163. err = client.Rename(path.Join(vdirPath2, dir1, testFileName), path.Join(vdirPath2, dir1, testFileName+".rename"))
  3164. assert.NoError(t, err)
  3165. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3166. assert.NoError(t, err)
  3167. assert.Equal(t, 2, user.UsedQuotaFiles)
  3168. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  3169. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3170. assert.NoError(t, err)
  3171. if assert.Len(t, folder, 1) {
  3172. f := folder[0]
  3173. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  3174. assert.Equal(t, 2, f.UsedQuotaFiles)
  3175. }
  3176. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3177. assert.NoError(t, err)
  3178. if assert.Len(t, folder, 1) {
  3179. f := folder[0]
  3180. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  3181. assert.Equal(t, 2, f.UsedQuotaFiles)
  3182. }
  3183. // rename a file inside vdir2 overwriting an existing, we now have:
  3184. // - vdir1/dir1/testFileName.rename
  3185. // - vdir1/dir2/testFileName1
  3186. // - vdir2/dir1/testFileName.rename (initial testFileName1)
  3187. err = client.Rename(path.Join(vdirPath2, dir2, testFileName1), path.Join(vdirPath2, dir1, testFileName+".rename"))
  3188. assert.NoError(t, err)
  3189. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3190. assert.NoError(t, err)
  3191. assert.Equal(t, 2, user.UsedQuotaFiles)
  3192. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  3193. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3194. assert.NoError(t, err)
  3195. if assert.Len(t, folder, 1) {
  3196. f := folder[0]
  3197. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  3198. assert.Equal(t, 1, f.UsedQuotaFiles)
  3199. }
  3200. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3201. assert.NoError(t, err)
  3202. if assert.Len(t, folder, 1) {
  3203. f := folder[0]
  3204. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  3205. assert.Equal(t, 2, f.UsedQuotaFiles)
  3206. }
  3207. // rename a file inside vdir1 overwriting an existing, we now have:
  3208. // - vdir1/dir1/testFileName.rename (initial testFileName1)
  3209. // - vdir2/dir1/testFileName.rename (initial testFileName1)
  3210. err = client.Rename(path.Join(vdirPath1, dir2, testFileName1), path.Join(vdirPath1, dir1, testFileName+".rename"))
  3211. assert.NoError(t, err)
  3212. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3213. assert.NoError(t, err)
  3214. assert.Equal(t, 1, user.UsedQuotaFiles)
  3215. assert.Equal(t, testFileSize1, user.UsedQuotaSize)
  3216. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3217. assert.NoError(t, err)
  3218. if assert.Len(t, folder, 1) {
  3219. f := folder[0]
  3220. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  3221. assert.Equal(t, 1, f.UsedQuotaFiles)
  3222. }
  3223. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3224. assert.NoError(t, err)
  3225. if assert.Len(t, folder, 1) {
  3226. f := folder[0]
  3227. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  3228. assert.Equal(t, 1, f.UsedQuotaFiles)
  3229. }
  3230. // rename a directory inside the same virtual folder, quota should not change
  3231. err = client.RemoveDirectory(path.Join(vdirPath1, dir2))
  3232. assert.NoError(t, err)
  3233. err = client.RemoveDirectory(path.Join(vdirPath2, dir2))
  3234. assert.NoError(t, err)
  3235. err = client.Rename(path.Join(vdirPath1, dir1), path.Join(vdirPath1, dir2))
  3236. assert.NoError(t, err)
  3237. err = client.Rename(path.Join(vdirPath2, dir1), path.Join(vdirPath2, dir2))
  3238. assert.NoError(t, err)
  3239. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3240. assert.NoError(t, err)
  3241. assert.Equal(t, 1, user.UsedQuotaFiles)
  3242. assert.Equal(t, testFileSize1, user.UsedQuotaSize)
  3243. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3244. assert.NoError(t, err)
  3245. if assert.Len(t, folder, 1) {
  3246. f := folder[0]
  3247. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  3248. assert.Equal(t, 1, f.UsedQuotaFiles)
  3249. }
  3250. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3251. assert.NoError(t, err)
  3252. if assert.Len(t, folder, 1) {
  3253. f := folder[0]
  3254. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  3255. assert.Equal(t, 1, f.UsedQuotaFiles)
  3256. }
  3257. err = os.Remove(testFilePath)
  3258. assert.NoError(t, err)
  3259. err = os.Remove(testFilePath1)
  3260. assert.NoError(t, err)
  3261. }
  3262. _, err = httpd.RemoveUser(user, http.StatusOK)
  3263. assert.NoError(t, err)
  3264. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  3265. assert.NoError(t, err)
  3266. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  3267. assert.NoError(t, err)
  3268. err = os.RemoveAll(user.GetHomeDir())
  3269. assert.NoError(t, err)
  3270. err = os.RemoveAll(mappedPath1)
  3271. assert.NoError(t, err)
  3272. err = os.RemoveAll(mappedPath2)
  3273. assert.NoError(t, err)
  3274. }
  3275. func TestQuotaRenameBetweenVirtualFolder(t *testing.T) {
  3276. usePubKey := true
  3277. u := getTestUser(usePubKey)
  3278. u.QuotaFiles = 100
  3279. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  3280. vdirPath1 := "/vdir1"
  3281. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  3282. vdirPath2 := "/vdir2"
  3283. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  3284. BaseVirtualFolder: vfs.BaseVirtualFolder{
  3285. MappedPath: mappedPath1,
  3286. },
  3287. VirtualPath: vdirPath1,
  3288. // quota is included in the user's one
  3289. QuotaFiles: -1,
  3290. QuotaSize: -1,
  3291. })
  3292. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  3293. BaseVirtualFolder: vfs.BaseVirtualFolder{
  3294. MappedPath: mappedPath2,
  3295. },
  3296. VirtualPath: vdirPath2,
  3297. // quota is unlimited and excluded from user's one
  3298. QuotaFiles: 0,
  3299. QuotaSize: 0,
  3300. })
  3301. err := os.MkdirAll(mappedPath1, os.ModePerm)
  3302. assert.NoError(t, err)
  3303. err = os.MkdirAll(mappedPath2, os.ModePerm)
  3304. assert.NoError(t, err)
  3305. user, _, err := httpd.AddUser(u, http.StatusOK)
  3306. assert.NoError(t, err)
  3307. client, err := getSftpClient(user, usePubKey)
  3308. if assert.NoError(t, err) {
  3309. defer client.Close()
  3310. testFileName1 := "test_file1.dat"
  3311. testFileSize := int64(131072)
  3312. testFileSize1 := int64(65535)
  3313. testFilePath := filepath.Join(homeBasePath, testFileName)
  3314. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  3315. dir1 := "dir1"
  3316. dir2 := "dir2"
  3317. err = createTestFile(testFilePath, testFileSize)
  3318. assert.NoError(t, err)
  3319. err = createTestFile(testFilePath1, testFileSize1)
  3320. assert.NoError(t, err)
  3321. err = client.Mkdir(path.Join(vdirPath1, dir1))
  3322. assert.NoError(t, err)
  3323. err = client.Mkdir(path.Join(vdirPath1, dir2))
  3324. assert.NoError(t, err)
  3325. err = client.Mkdir(path.Join(vdirPath2, dir1))
  3326. assert.NoError(t, err)
  3327. err = client.Mkdir(path.Join(vdirPath2, dir2))
  3328. assert.NoError(t, err)
  3329. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, dir1, testFileName), testFileSize, client)
  3330. assert.NoError(t, err)
  3331. err = sftpUploadFile(testFilePath1, path.Join(vdirPath1, dir2, testFileName1), testFileSize1, client)
  3332. assert.NoError(t, err)
  3333. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, dir1, testFileName), testFileSize, client)
  3334. assert.NoError(t, err)
  3335. err = sftpUploadFile(testFilePath1, path.Join(vdirPath2, dir2, testFileName1), testFileSize1, client)
  3336. assert.NoError(t, err)
  3337. // initial files:
  3338. // - vdir1/dir1/testFileName
  3339. // - vdir1/dir2/testFileName1
  3340. // - vdir2/dir1/testFileName
  3341. // - vdir2/dir2/testFileName1
  3342. //
  3343. // rename a file from vdir1 to vdir2, vdir1 is included inside user quota, so we have:
  3344. // - vdir1/dir1/testFileName
  3345. // - vdir2/dir1/testFileName
  3346. // - vdir2/dir2/testFileName1
  3347. // - vdir2/dir1/testFileName1.rename
  3348. err = client.Rename(path.Join(vdirPath1, dir2, testFileName1), path.Join(vdirPath2, dir1, testFileName1+".rename"))
  3349. assert.NoError(t, err)
  3350. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3351. assert.NoError(t, err)
  3352. assert.Equal(t, 1, user.UsedQuotaFiles)
  3353. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  3354. folder, _, err := httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3355. assert.NoError(t, err)
  3356. if assert.Len(t, folder, 1) {
  3357. f := folder[0]
  3358. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  3359. assert.Equal(t, 1, f.UsedQuotaFiles)
  3360. }
  3361. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3362. assert.NoError(t, err)
  3363. if assert.Len(t, folder, 1) {
  3364. f := folder[0]
  3365. assert.Equal(t, testFileSize+testFileSize1+testFileSize1, f.UsedQuotaSize)
  3366. assert.Equal(t, 3, f.UsedQuotaFiles)
  3367. }
  3368. // rename a file from vdir2 to vdir1, vdir2 is not included inside user quota, so we have:
  3369. // - vdir1/dir1/testFileName
  3370. // - vdir1/dir2/testFileName.rename
  3371. // - vdir2/dir2/testFileName1
  3372. // - vdir2/dir1/testFileName1.rename
  3373. err = client.Rename(path.Join(vdirPath2, dir1, testFileName), path.Join(vdirPath1, dir2, testFileName+".rename"))
  3374. assert.NoError(t, err)
  3375. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3376. assert.NoError(t, err)
  3377. assert.Equal(t, 2, user.UsedQuotaFiles)
  3378. assert.Equal(t, testFileSize*2, user.UsedQuotaSize)
  3379. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3380. assert.NoError(t, err)
  3381. if assert.Len(t, folder, 1) {
  3382. f := folder[0]
  3383. assert.Equal(t, testFileSize*2, f.UsedQuotaSize)
  3384. assert.Equal(t, 2, f.UsedQuotaFiles)
  3385. }
  3386. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3387. assert.NoError(t, err)
  3388. if assert.Len(t, folder, 1) {
  3389. f := folder[0]
  3390. assert.Equal(t, testFileSize1*2, f.UsedQuotaSize)
  3391. assert.Equal(t, 2, f.UsedQuotaFiles)
  3392. }
  3393. // rename a file from vdir1 to vdir2 overwriting an existing file, vdir1 is included inside user quota, so we have:
  3394. // - vdir1/dir2/testFileName.rename
  3395. // - vdir2/dir2/testFileName1 (is the initial testFileName)
  3396. // - vdir2/dir1/testFileName1.rename
  3397. err = client.Rename(path.Join(vdirPath1, dir1, testFileName), path.Join(vdirPath2, dir2, testFileName1))
  3398. assert.NoError(t, err)
  3399. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3400. assert.NoError(t, err)
  3401. assert.Equal(t, 1, user.UsedQuotaFiles)
  3402. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  3403. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3404. assert.NoError(t, err)
  3405. if assert.Len(t, folder, 1) {
  3406. f := folder[0]
  3407. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  3408. assert.Equal(t, 1, f.UsedQuotaFiles)
  3409. }
  3410. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3411. assert.NoError(t, err)
  3412. if assert.Len(t, folder, 1) {
  3413. f := folder[0]
  3414. assert.Equal(t, testFileSize1+testFileSize, f.UsedQuotaSize)
  3415. assert.Equal(t, 2, f.UsedQuotaFiles)
  3416. }
  3417. // rename a file from vdir2 to vdir1 overwriting an existing file, vdir2 is not included inside user quota, so we have:
  3418. // - vdir1/dir2/testFileName.rename (is the initial testFileName1)
  3419. // - vdir2/dir2/testFileName1 (is the initial testFileName)
  3420. err = client.Rename(path.Join(vdirPath2, dir1, testFileName1+".rename"), path.Join(vdirPath1, dir2, testFileName+".rename"))
  3421. assert.NoError(t, err)
  3422. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3423. assert.NoError(t, err)
  3424. assert.Equal(t, 1, user.UsedQuotaFiles)
  3425. assert.Equal(t, testFileSize1, user.UsedQuotaSize)
  3426. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3427. assert.NoError(t, err)
  3428. if assert.Len(t, folder, 1) {
  3429. f := folder[0]
  3430. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  3431. assert.Equal(t, 1, f.UsedQuotaFiles)
  3432. }
  3433. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3434. assert.NoError(t, err)
  3435. if assert.Len(t, folder, 1) {
  3436. f := folder[0]
  3437. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  3438. assert.Equal(t, 1, f.UsedQuotaFiles)
  3439. }
  3440. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, dir2, testFileName), testFileSize, client)
  3441. assert.NoError(t, err)
  3442. err = sftpUploadFile(testFilePath1, path.Join(vdirPath2, dir2, testFileName), testFileSize1, client)
  3443. assert.NoError(t, err)
  3444. err = sftpUploadFile(testFilePath1, path.Join(vdirPath2, dir2, testFileName+"1.dupl"), testFileSize1, client)
  3445. assert.NoError(t, err)
  3446. err = client.RemoveDirectory(path.Join(vdirPath1, dir1))
  3447. assert.NoError(t, err)
  3448. err = client.RemoveDirectory(path.Join(vdirPath2, dir1))
  3449. assert.NoError(t, err)
  3450. // - vdir1/dir2/testFileName.rename (initial testFileName1)
  3451. // - vdir1/dir2/testFileName
  3452. // - vdir2/dir2/testFileName1 (initial testFileName)
  3453. // - vdir2/dir2/testFileName (initial testFileName1)
  3454. // - vdir2/dir2/testFileName1.dupl
  3455. // rename directories between the two virtual folders
  3456. err = client.Rename(path.Join(vdirPath2, dir2), path.Join(vdirPath1, dir1))
  3457. assert.NoError(t, err)
  3458. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3459. assert.NoError(t, err)
  3460. assert.Equal(t, 5, user.UsedQuotaFiles)
  3461. assert.Equal(t, testFileSize1*3+testFileSize*2, user.UsedQuotaSize)
  3462. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3463. assert.NoError(t, err)
  3464. if assert.Len(t, folder, 1) {
  3465. f := folder[0]
  3466. assert.Equal(t, testFileSize1*3+testFileSize*2, f.UsedQuotaSize)
  3467. assert.Equal(t, 5, f.UsedQuotaFiles)
  3468. }
  3469. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3470. assert.NoError(t, err)
  3471. if assert.Len(t, folder, 1) {
  3472. f := folder[0]
  3473. assert.Equal(t, int64(0), f.UsedQuotaSize)
  3474. assert.Equal(t, 0, f.UsedQuotaFiles)
  3475. }
  3476. // now move on vpath2
  3477. err = client.Rename(path.Join(vdirPath1, dir2), path.Join(vdirPath2, dir1))
  3478. assert.NoError(t, err)
  3479. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3480. assert.NoError(t, err)
  3481. assert.Equal(t, 3, user.UsedQuotaFiles)
  3482. assert.Equal(t, testFileSize1*2+testFileSize, user.UsedQuotaSize)
  3483. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3484. assert.NoError(t, err)
  3485. if assert.Len(t, folder, 1) {
  3486. f := folder[0]
  3487. assert.Equal(t, testFileSize1*2+testFileSize, f.UsedQuotaSize)
  3488. assert.Equal(t, 3, f.UsedQuotaFiles)
  3489. }
  3490. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3491. assert.NoError(t, err)
  3492. if assert.Len(t, folder, 1) {
  3493. f := folder[0]
  3494. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  3495. assert.Equal(t, 2, f.UsedQuotaFiles)
  3496. }
  3497. err = os.Remove(testFilePath)
  3498. assert.NoError(t, err)
  3499. err = os.Remove(testFilePath1)
  3500. assert.NoError(t, err)
  3501. }
  3502. _, err = httpd.RemoveUser(user, http.StatusOK)
  3503. assert.NoError(t, err)
  3504. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  3505. assert.NoError(t, err)
  3506. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  3507. assert.NoError(t, err)
  3508. err = os.RemoveAll(user.GetHomeDir())
  3509. assert.NoError(t, err)
  3510. err = os.RemoveAll(mappedPath1)
  3511. assert.NoError(t, err)
  3512. err = os.RemoveAll(mappedPath2)
  3513. assert.NoError(t, err)
  3514. }
  3515. func TestQuotaRenameFromVirtualFolder(t *testing.T) {
  3516. usePubKey := false
  3517. u := getTestUser(usePubKey)
  3518. u.QuotaFiles = 100
  3519. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  3520. vdirPath1 := "/vdir1"
  3521. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  3522. vdirPath2 := "/vdir2"
  3523. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  3524. BaseVirtualFolder: vfs.BaseVirtualFolder{
  3525. MappedPath: mappedPath1,
  3526. },
  3527. VirtualPath: vdirPath1,
  3528. // quota is included in the user's one
  3529. QuotaFiles: -1,
  3530. QuotaSize: -1,
  3531. })
  3532. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  3533. BaseVirtualFolder: vfs.BaseVirtualFolder{
  3534. MappedPath: mappedPath2,
  3535. },
  3536. VirtualPath: vdirPath2,
  3537. // quota is unlimited and excluded from user's one
  3538. QuotaFiles: 0,
  3539. QuotaSize: 0,
  3540. })
  3541. err := os.MkdirAll(mappedPath1, os.ModePerm)
  3542. assert.NoError(t, err)
  3543. err = os.MkdirAll(mappedPath2, os.ModePerm)
  3544. assert.NoError(t, err)
  3545. user, _, err := httpd.AddUser(u, http.StatusOK)
  3546. assert.NoError(t, err)
  3547. client, err := getSftpClient(user, usePubKey)
  3548. if assert.NoError(t, err) {
  3549. defer client.Close()
  3550. testFileName1 := "test_file1.dat"
  3551. testFileSize := int64(131072)
  3552. testFileSize1 := int64(65535)
  3553. testFilePath := filepath.Join(homeBasePath, testFileName)
  3554. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  3555. dir1 := "dir1"
  3556. dir2 := "dir2"
  3557. err = createTestFile(testFilePath, testFileSize)
  3558. assert.NoError(t, err)
  3559. err = createTestFile(testFilePath1, testFileSize1)
  3560. assert.NoError(t, err)
  3561. err = client.Mkdir(path.Join(vdirPath1, dir1))
  3562. assert.NoError(t, err)
  3563. err = client.Mkdir(path.Join(vdirPath1, dir2))
  3564. assert.NoError(t, err)
  3565. err = client.Mkdir(path.Join(vdirPath2, dir1))
  3566. assert.NoError(t, err)
  3567. err = client.Mkdir(path.Join(vdirPath2, dir2))
  3568. assert.NoError(t, err)
  3569. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, dir1, testFileName), testFileSize, client)
  3570. assert.NoError(t, err)
  3571. err = sftpUploadFile(testFilePath1, path.Join(vdirPath1, dir2, testFileName1), testFileSize1, client)
  3572. assert.NoError(t, err)
  3573. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, dir1, testFileName), testFileSize, client)
  3574. assert.NoError(t, err)
  3575. err = sftpUploadFile(testFilePath1, path.Join(vdirPath2, dir2, testFileName1), testFileSize1, client)
  3576. assert.NoError(t, err)
  3577. // initial files:
  3578. // - vdir1/dir1/testFileName
  3579. // - vdir1/dir2/testFileName1
  3580. // - vdir2/dir1/testFileName
  3581. // - vdir2/dir2/testFileName1
  3582. //
  3583. // rename a file from vdir1 to the user home dir, vdir1 is included in user quota so we have:
  3584. // - testFileName
  3585. // - vdir1/dir2/testFileName1
  3586. // - vdir2/dir1/testFileName
  3587. // - vdir2/dir2/testFileName1
  3588. err = client.Rename(path.Join(vdirPath1, dir1, testFileName), path.Join(testFileName))
  3589. assert.NoError(t, err)
  3590. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3591. assert.NoError(t, err)
  3592. assert.Equal(t, 2, user.UsedQuotaFiles)
  3593. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  3594. folder, _, err := httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3595. assert.NoError(t, err)
  3596. if assert.Len(t, folder, 1) {
  3597. f := folder[0]
  3598. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  3599. assert.Equal(t, 1, f.UsedQuotaFiles)
  3600. }
  3601. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3602. assert.NoError(t, err)
  3603. if assert.Len(t, folder, 1) {
  3604. f := folder[0]
  3605. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  3606. assert.Equal(t, 2, f.UsedQuotaFiles)
  3607. }
  3608. // rename a file from vdir2 to the user home dir, vdir2 is not included in user quota so we have:
  3609. // - testFileName
  3610. // - testFileName1
  3611. // - vdir1/dir2/testFileName1
  3612. // - vdir2/dir1/testFileName
  3613. err = client.Rename(path.Join(vdirPath2, dir2, testFileName1), path.Join(testFileName1))
  3614. assert.NoError(t, err)
  3615. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3616. assert.NoError(t, err)
  3617. assert.Equal(t, 3, user.UsedQuotaFiles)
  3618. assert.Equal(t, testFileSize+testFileSize1+testFileSize1, user.UsedQuotaSize)
  3619. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3620. assert.NoError(t, err)
  3621. if assert.Len(t, folder, 1) {
  3622. f := folder[0]
  3623. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  3624. assert.Equal(t, 1, f.UsedQuotaFiles)
  3625. }
  3626. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3627. assert.NoError(t, err)
  3628. if assert.Len(t, folder, 1) {
  3629. f := folder[0]
  3630. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  3631. assert.Equal(t, 1, f.UsedQuotaFiles)
  3632. }
  3633. // rename a file from vdir1 to the user home dir overwriting an existing file, vdir1 is included in user quota so we have:
  3634. // - testFileName (initial testFileName1)
  3635. // - testFileName1
  3636. // - vdir2/dir1/testFileName
  3637. err = client.Rename(path.Join(vdirPath1, dir2, testFileName1), path.Join(testFileName))
  3638. assert.NoError(t, err)
  3639. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3640. assert.NoError(t, err)
  3641. assert.Equal(t, 2, user.UsedQuotaFiles)
  3642. assert.Equal(t, testFileSize1+testFileSize1, user.UsedQuotaSize)
  3643. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3644. assert.NoError(t, err)
  3645. if assert.Len(t, folder, 1) {
  3646. f := folder[0]
  3647. assert.Equal(t, int64(0), f.UsedQuotaSize)
  3648. assert.Equal(t, 0, f.UsedQuotaFiles)
  3649. }
  3650. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3651. assert.NoError(t, err)
  3652. if assert.Len(t, folder, 1) {
  3653. f := folder[0]
  3654. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  3655. assert.Equal(t, 1, f.UsedQuotaFiles)
  3656. }
  3657. // rename a file from vdir2 to the user home dir overwriting an existing file, vdir2 is not included in user quota so we have:
  3658. // - testFileName (initial testFileName1)
  3659. // - testFileName1 (initial testFileName)
  3660. err = client.Rename(path.Join(vdirPath2, dir1, testFileName), path.Join(testFileName1))
  3661. assert.NoError(t, err)
  3662. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3663. assert.NoError(t, err)
  3664. assert.Equal(t, 2, user.UsedQuotaFiles)
  3665. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  3666. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3667. assert.NoError(t, err)
  3668. if assert.Len(t, folder, 1) {
  3669. f := folder[0]
  3670. assert.Equal(t, int64(0), f.UsedQuotaSize)
  3671. assert.Equal(t, 0, f.UsedQuotaFiles)
  3672. }
  3673. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3674. assert.NoError(t, err)
  3675. if assert.Len(t, folder, 1) {
  3676. f := folder[0]
  3677. assert.Equal(t, int64(0), f.UsedQuotaSize)
  3678. assert.Equal(t, 0, f.UsedQuotaFiles)
  3679. }
  3680. // dir rename
  3681. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, dir1, testFileName), testFileSize, client)
  3682. assert.NoError(t, err)
  3683. err = sftpUploadFile(testFilePath1, path.Join(vdirPath1, dir1, testFileName1), testFileSize1, client)
  3684. assert.NoError(t, err)
  3685. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, dir1, testFileName), testFileSize, client)
  3686. assert.NoError(t, err)
  3687. err = sftpUploadFile(testFilePath1, path.Join(vdirPath2, dir1, testFileName1), testFileSize1, client)
  3688. assert.NoError(t, err)
  3689. // - testFileName (initial testFileName1)
  3690. // - testFileName1 (initial testFileName)
  3691. // - vdir1/dir1/testFileName
  3692. // - vdir1/dir1/testFileName1
  3693. // - dir1/testFileName
  3694. // - dir1/testFileName1
  3695. err = client.Rename(path.Join(vdirPath2, dir1), dir1)
  3696. assert.NoError(t, err)
  3697. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3698. assert.NoError(t, err)
  3699. assert.Equal(t, 6, user.UsedQuotaFiles)
  3700. assert.Equal(t, testFileSize*3+testFileSize1*3, user.UsedQuotaSize)
  3701. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3702. assert.NoError(t, err)
  3703. if assert.Len(t, folder, 1) {
  3704. f := folder[0]
  3705. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  3706. assert.Equal(t, 2, f.UsedQuotaFiles)
  3707. }
  3708. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3709. assert.NoError(t, err)
  3710. if assert.Len(t, folder, 1) {
  3711. f := folder[0]
  3712. assert.Equal(t, int64(0), f.UsedQuotaSize)
  3713. assert.Equal(t, 0, f.UsedQuotaFiles)
  3714. }
  3715. // - testFileName (initial testFileName1)
  3716. // - testFileName1 (initial testFileName)
  3717. // - dir2/testFileName
  3718. // - dir2/testFileName1
  3719. // - dir1/testFileName
  3720. // - dir1/testFileName1
  3721. err = client.Rename(path.Join(vdirPath1, dir1), dir2)
  3722. assert.NoError(t, err)
  3723. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3724. assert.NoError(t, err)
  3725. assert.Equal(t, 6, user.UsedQuotaFiles)
  3726. assert.Equal(t, testFileSize*3+testFileSize1*3, user.UsedQuotaSize)
  3727. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3728. assert.NoError(t, err)
  3729. if assert.Len(t, folder, 1) {
  3730. f := folder[0]
  3731. assert.Equal(t, int64(0), f.UsedQuotaSize)
  3732. assert.Equal(t, 0, f.UsedQuotaFiles)
  3733. }
  3734. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3735. assert.NoError(t, err)
  3736. if assert.Len(t, folder, 1) {
  3737. f := folder[0]
  3738. assert.Equal(t, int64(0), f.UsedQuotaSize)
  3739. assert.Equal(t, 0, f.UsedQuotaFiles)
  3740. }
  3741. err = os.Remove(testFilePath)
  3742. assert.NoError(t, err)
  3743. err = os.Remove(testFilePath1)
  3744. assert.NoError(t, err)
  3745. }
  3746. _, err = httpd.RemoveUser(user, http.StatusOK)
  3747. assert.NoError(t, err)
  3748. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  3749. assert.NoError(t, err)
  3750. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  3751. assert.NoError(t, err)
  3752. err = os.RemoveAll(user.GetHomeDir())
  3753. assert.NoError(t, err)
  3754. err = os.RemoveAll(mappedPath1)
  3755. assert.NoError(t, err)
  3756. err = os.RemoveAll(mappedPath2)
  3757. assert.NoError(t, err)
  3758. }
  3759. func TestQuotaRenameToVirtualFolder(t *testing.T) {
  3760. usePubKey := true
  3761. u := getTestUser(usePubKey)
  3762. u.QuotaFiles = 100
  3763. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  3764. vdirPath1 := "/vdir1"
  3765. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  3766. vdirPath2 := "/vdir2"
  3767. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  3768. BaseVirtualFolder: vfs.BaseVirtualFolder{
  3769. MappedPath: mappedPath1,
  3770. },
  3771. VirtualPath: vdirPath1,
  3772. // quota is included in the user's one
  3773. QuotaFiles: -1,
  3774. QuotaSize: -1,
  3775. })
  3776. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  3777. BaseVirtualFolder: vfs.BaseVirtualFolder{
  3778. MappedPath: mappedPath2,
  3779. },
  3780. VirtualPath: vdirPath2,
  3781. // quota is unlimited and excluded from user's one
  3782. QuotaFiles: 0,
  3783. QuotaSize: 0,
  3784. })
  3785. err := os.MkdirAll(mappedPath1, os.ModePerm)
  3786. assert.NoError(t, err)
  3787. err = os.MkdirAll(mappedPath2, os.ModePerm)
  3788. assert.NoError(t, err)
  3789. user, _, err := httpd.AddUser(u, http.StatusOK)
  3790. assert.NoError(t, err)
  3791. client, err := getSftpClient(user, usePubKey)
  3792. if assert.NoError(t, err) {
  3793. defer client.Close()
  3794. testFileName1 := "test_file1.dat"
  3795. testFileSize := int64(131072)
  3796. testFileSize1 := int64(65535)
  3797. testFilePath := filepath.Join(homeBasePath, testFileName)
  3798. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  3799. dir1 := "dir1"
  3800. dir2 := "dir2"
  3801. err = createTestFile(testFilePath, testFileSize)
  3802. assert.NoError(t, err)
  3803. err = createTestFile(testFilePath1, testFileSize1)
  3804. assert.NoError(t, err)
  3805. err = client.Mkdir(path.Join(vdirPath1, dir1))
  3806. assert.NoError(t, err)
  3807. err = client.Mkdir(path.Join(vdirPath1, dir2))
  3808. assert.NoError(t, err)
  3809. err = client.Mkdir(path.Join(vdirPath2, dir1))
  3810. assert.NoError(t, err)
  3811. err = client.Mkdir(path.Join(vdirPath2, dir2))
  3812. assert.NoError(t, err)
  3813. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  3814. assert.NoError(t, err)
  3815. err = sftpUploadFile(testFilePath1, testFileName1, testFileSize1, client)
  3816. assert.NoError(t, err)
  3817. // initial files:
  3818. // - testFileName
  3819. // - testFileName1
  3820. //
  3821. // rename a file from user home dir to vdir1, vdir1 is included in user quota so we have:
  3822. // - testFileName
  3823. // - /vdir1/dir1/testFileName1
  3824. err = client.Rename(testFileName1, path.Join(vdirPath1, dir1, testFileName1))
  3825. assert.NoError(t, err)
  3826. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3827. assert.NoError(t, err)
  3828. assert.Equal(t, 2, user.UsedQuotaFiles)
  3829. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  3830. folder, _, err := httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3831. assert.NoError(t, err)
  3832. if assert.Len(t, folder, 1) {
  3833. f := folder[0]
  3834. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  3835. assert.Equal(t, 1, f.UsedQuotaFiles)
  3836. }
  3837. // rename a file from user home dir to vdir2, vdir2 is not included in user quota so we have:
  3838. // - /vdir2/dir1/testFileName
  3839. // - /vdir1/dir1/testFileName1
  3840. err = client.Rename(testFileName, path.Join(vdirPath2, dir1, testFileName))
  3841. assert.NoError(t, err)
  3842. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3843. assert.NoError(t, err)
  3844. assert.Equal(t, 1, user.UsedQuotaFiles)
  3845. assert.Equal(t, testFileSize1, user.UsedQuotaSize)
  3846. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3847. assert.NoError(t, err)
  3848. if assert.Len(t, folder, 1) {
  3849. f := folder[0]
  3850. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  3851. assert.Equal(t, 1, f.UsedQuotaFiles)
  3852. }
  3853. // upload two new files to the user home dir so we have:
  3854. // - testFileName
  3855. // - testFileName1
  3856. // - /vdir1/dir1/testFileName1
  3857. // - /vdir2/dir1/testFileName
  3858. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  3859. assert.NoError(t, err)
  3860. err = sftpUploadFile(testFilePath1, testFileName1, testFileSize1, client)
  3861. assert.NoError(t, err)
  3862. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3863. assert.NoError(t, err)
  3864. assert.Equal(t, 3, user.UsedQuotaFiles)
  3865. assert.Equal(t, testFileSize+testFileSize1+testFileSize1, user.UsedQuotaSize)
  3866. // rename a file from user home dir to vdir1 overwriting an existing file, vdir1 is included in user quota so we have:
  3867. // - testFileName1
  3868. // - /vdir1/dir1/testFileName1 (initial testFileName)
  3869. // - /vdir2/dir1/testFileName
  3870. err = client.Rename(testFileName, path.Join(vdirPath1, dir1, testFileName1))
  3871. assert.NoError(t, err)
  3872. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3873. assert.NoError(t, err)
  3874. assert.Equal(t, 2, user.UsedQuotaFiles)
  3875. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  3876. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3877. assert.NoError(t, err)
  3878. if assert.Len(t, folder, 1) {
  3879. f := folder[0]
  3880. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  3881. assert.Equal(t, 1, f.UsedQuotaFiles)
  3882. }
  3883. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3884. assert.NoError(t, err)
  3885. if assert.Len(t, folder, 1) {
  3886. f := folder[0]
  3887. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  3888. assert.Equal(t, 1, f.UsedQuotaFiles)
  3889. }
  3890. // rename a file from user home dir to vdir2 overwriting an existing file, vdir2 is not included in user quota so we have:
  3891. // - /vdir1/dir1/testFileName1 (initial testFileName)
  3892. // - /vdir2/dir1/testFileName (initial testFileName1)
  3893. err = client.Rename(testFileName1, path.Join(vdirPath2, dir1, testFileName))
  3894. assert.NoError(t, err)
  3895. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3896. assert.NoError(t, err)
  3897. assert.Equal(t, 1, user.UsedQuotaFiles)
  3898. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  3899. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3900. assert.NoError(t, err)
  3901. if assert.Len(t, folder, 1) {
  3902. f := folder[0]
  3903. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  3904. assert.Equal(t, 1, f.UsedQuotaFiles)
  3905. }
  3906. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3907. assert.NoError(t, err)
  3908. if assert.Len(t, folder, 1) {
  3909. f := folder[0]
  3910. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  3911. assert.Equal(t, 1, f.UsedQuotaFiles)
  3912. }
  3913. err = client.Mkdir(dir1)
  3914. assert.NoError(t, err)
  3915. err = sftpUploadFile(testFilePath, path.Join(dir1, testFileName), testFileSize, client)
  3916. assert.NoError(t, err)
  3917. err = sftpUploadFile(testFilePath1, path.Join(dir1, testFileName1), testFileSize1, client)
  3918. assert.NoError(t, err)
  3919. // - /dir1/testFileName
  3920. // - /dir1/testFileName1
  3921. // - /vdir1/dir1/testFileName1 (initial testFileName)
  3922. // - /vdir2/dir1/testFileName (initial testFileName1)
  3923. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3924. assert.NoError(t, err)
  3925. assert.Equal(t, 3, user.UsedQuotaFiles)
  3926. assert.Equal(t, testFileSize*2+testFileSize1, user.UsedQuotaSize)
  3927. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3928. assert.NoError(t, err)
  3929. if assert.Len(t, folder, 1) {
  3930. f := folder[0]
  3931. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  3932. assert.Equal(t, 1, f.UsedQuotaFiles)
  3933. }
  3934. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3935. assert.NoError(t, err)
  3936. if assert.Len(t, folder, 1) {
  3937. f := folder[0]
  3938. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  3939. assert.Equal(t, 1, f.UsedQuotaFiles)
  3940. }
  3941. // - /vdir1/adir/testFileName
  3942. // - /vdir1/adir/testFileName1
  3943. // - /vdir1/dir1/testFileName1 (initial testFileName)
  3944. // - /vdir2/dir1/testFileName (initial testFileName1)
  3945. err = client.Rename(dir1, path.Join(vdirPath1, "adir"))
  3946. assert.NoError(t, err)
  3947. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3948. assert.NoError(t, err)
  3949. assert.Equal(t, 3, user.UsedQuotaFiles)
  3950. assert.Equal(t, testFileSize*2+testFileSize1, user.UsedQuotaSize)
  3951. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3952. assert.NoError(t, err)
  3953. if assert.Len(t, folder, 1) {
  3954. f := folder[0]
  3955. assert.Equal(t, testFileSize*2+testFileSize1, f.UsedQuotaSize)
  3956. assert.Equal(t, 3, f.UsedQuotaFiles)
  3957. }
  3958. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3959. assert.NoError(t, err)
  3960. if assert.Len(t, folder, 1) {
  3961. f := folder[0]
  3962. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  3963. assert.Equal(t, 1, f.UsedQuotaFiles)
  3964. }
  3965. err = client.Mkdir(dir1)
  3966. assert.NoError(t, err)
  3967. err = sftpUploadFile(testFilePath, path.Join(dir1, testFileName), testFileSize, client)
  3968. assert.NoError(t, err)
  3969. err = sftpUploadFile(testFilePath1, path.Join(dir1, testFileName1), testFileSize1, client)
  3970. assert.NoError(t, err)
  3971. // - /vdir1/adir/testFileName
  3972. // - /vdir1/adir/testFileName1
  3973. // - /vdir1/dir1/testFileName1 (initial testFileName)
  3974. // - /vdir2/dir1/testFileName (initial testFileName1)
  3975. // - /vdir2/adir/testFileName
  3976. // - /vdir2/adir/testFileName1
  3977. err = client.Rename(dir1, path.Join(vdirPath2, "adir"))
  3978. assert.NoError(t, err)
  3979. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  3980. assert.NoError(t, err)
  3981. assert.Equal(t, 3, user.UsedQuotaFiles)
  3982. assert.Equal(t, testFileSize*2+testFileSize1, user.UsedQuotaSize)
  3983. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  3984. assert.NoError(t, err)
  3985. if assert.Len(t, folder, 1) {
  3986. f := folder[0]
  3987. assert.Equal(t, testFileSize*2+testFileSize1, f.UsedQuotaSize)
  3988. assert.Equal(t, 3, f.UsedQuotaFiles)
  3989. }
  3990. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  3991. assert.NoError(t, err)
  3992. if assert.Len(t, folder, 1) {
  3993. f := folder[0]
  3994. assert.Equal(t, testFileSize1*2+testFileSize, f.UsedQuotaSize)
  3995. assert.Equal(t, 3, f.UsedQuotaFiles)
  3996. }
  3997. err = os.Remove(testFilePath)
  3998. assert.NoError(t, err)
  3999. err = os.Remove(testFilePath1)
  4000. assert.NoError(t, err)
  4001. }
  4002. _, err = httpd.RemoveUser(user, http.StatusOK)
  4003. assert.NoError(t, err)
  4004. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  4005. assert.NoError(t, err)
  4006. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  4007. assert.NoError(t, err)
  4008. err = os.RemoveAll(user.GetHomeDir())
  4009. assert.NoError(t, err)
  4010. err = os.RemoveAll(mappedPath1)
  4011. assert.NoError(t, err)
  4012. err = os.RemoveAll(mappedPath2)
  4013. assert.NoError(t, err)
  4014. }
  4015. func TestVirtualFoldersLink(t *testing.T) {
  4016. usePubKey := true
  4017. u := getTestUser(usePubKey)
  4018. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  4019. vdirPath1 := "/vdir1"
  4020. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  4021. vdirPath2 := "/vdir2"
  4022. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  4023. BaseVirtualFolder: vfs.BaseVirtualFolder{
  4024. MappedPath: mappedPath1,
  4025. },
  4026. VirtualPath: vdirPath1,
  4027. // quota is included in the user's one
  4028. QuotaFiles: -1,
  4029. QuotaSize: -1,
  4030. })
  4031. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  4032. BaseVirtualFolder: vfs.BaseVirtualFolder{
  4033. MappedPath: mappedPath2,
  4034. },
  4035. VirtualPath: vdirPath2,
  4036. // quota is unlimited and excluded from user's one
  4037. QuotaFiles: 0,
  4038. QuotaSize: 0,
  4039. })
  4040. err := os.MkdirAll(mappedPath1, os.ModePerm)
  4041. assert.NoError(t, err)
  4042. err = os.MkdirAll(mappedPath2, os.ModePerm)
  4043. assert.NoError(t, err)
  4044. user, _, err := httpd.AddUser(u, http.StatusOK)
  4045. assert.NoError(t, err)
  4046. client, err := getSftpClient(user, usePubKey)
  4047. if assert.NoError(t, err) {
  4048. defer client.Close()
  4049. testFileSize := int64(131072)
  4050. testFilePath := filepath.Join(homeBasePath, testFileName)
  4051. testDir := "adir"
  4052. err = createTestFile(testFilePath, testFileSize)
  4053. assert.NoError(t, err)
  4054. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4055. assert.NoError(t, err)
  4056. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, testFileName), testFileSize, client)
  4057. assert.NoError(t, err)
  4058. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testFileName), testFileSize, client)
  4059. assert.NoError(t, err)
  4060. err = client.Mkdir(path.Join(vdirPath1, testDir))
  4061. assert.NoError(t, err)
  4062. err = client.Mkdir(path.Join(vdirPath2, testDir))
  4063. assert.NoError(t, err)
  4064. err = client.Symlink(testFileName, testFileName+".link")
  4065. assert.NoError(t, err)
  4066. err = client.Symlink(path.Join(vdirPath1, testFileName), path.Join(vdirPath1, testFileName+".link"))
  4067. assert.NoError(t, err)
  4068. err = client.Symlink(path.Join(vdirPath1, testFileName), path.Join(vdirPath1, testDir, testFileName+".link"))
  4069. assert.NoError(t, err)
  4070. err = client.Symlink(path.Join(vdirPath2, testFileName), path.Join(vdirPath2, testFileName+".link"))
  4071. assert.NoError(t, err)
  4072. err = client.Symlink(path.Join(vdirPath2, testFileName), path.Join(vdirPath2, testDir, testFileName+".link"))
  4073. assert.NoError(t, err)
  4074. err = client.Symlink(testFileName, path.Join(vdirPath1, testFileName+".link1"))
  4075. assert.Error(t, err)
  4076. err = client.Symlink(testFileName, path.Join(vdirPath1, testDir, testFileName+".link1"))
  4077. assert.Error(t, err)
  4078. err = client.Symlink(testFileName, path.Join(vdirPath2, testFileName+".link1"))
  4079. assert.Error(t, err)
  4080. err = client.Symlink(testFileName, path.Join(vdirPath2, testDir, testFileName+".link1"))
  4081. assert.Error(t, err)
  4082. err = client.Symlink(path.Join(vdirPath1, testFileName), testFileName+".link1")
  4083. assert.Error(t, err)
  4084. err = client.Symlink(path.Join(vdirPath2, testFileName), testFileName+".link1")
  4085. assert.Error(t, err)
  4086. err = client.Symlink(path.Join(vdirPath1, testFileName), path.Join(vdirPath2, testDir, testFileName+".link1"))
  4087. assert.Error(t, err)
  4088. err = client.Symlink(path.Join(vdirPath2, testFileName), path.Join(vdirPath1, testFileName+".link1"))
  4089. assert.Error(t, err)
  4090. err = os.Remove(testFilePath)
  4091. assert.NoError(t, err)
  4092. }
  4093. _, err = httpd.RemoveUser(user, http.StatusOK)
  4094. assert.NoError(t, err)
  4095. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  4096. assert.NoError(t, err)
  4097. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  4098. assert.NoError(t, err)
  4099. err = os.RemoveAll(user.GetHomeDir())
  4100. assert.NoError(t, err)
  4101. err = os.RemoveAll(mappedPath1)
  4102. assert.NoError(t, err)
  4103. err = os.RemoveAll(mappedPath2)
  4104. assert.NoError(t, err)
  4105. }
  4106. func TestOverlappedMappedFolders(t *testing.T) {
  4107. err := dataprovider.Close()
  4108. assert.NoError(t, err)
  4109. err = config.LoadConfig(configDir, "")
  4110. assert.NoError(t, err)
  4111. providerConf := config.GetProviderConf()
  4112. providerConf.TrackQuota = 0
  4113. err = dataprovider.Initialize(providerConf, configDir)
  4114. assert.NoError(t, err)
  4115. usePubKey := false
  4116. u := getTestUser(usePubKey)
  4117. subDir := "subdir"
  4118. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  4119. vdirPath1 := "/vdir1"
  4120. mappedPath2 := filepath.Join(os.TempDir(), "vdir1", subDir)
  4121. vdirPath2 := "/vdir2"
  4122. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  4123. BaseVirtualFolder: vfs.BaseVirtualFolder{
  4124. MappedPath: mappedPath1,
  4125. },
  4126. VirtualPath: vdirPath1,
  4127. })
  4128. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  4129. BaseVirtualFolder: vfs.BaseVirtualFolder{
  4130. MappedPath: mappedPath2,
  4131. },
  4132. VirtualPath: vdirPath2,
  4133. })
  4134. err = os.MkdirAll(mappedPath1, os.ModePerm)
  4135. assert.NoError(t, err)
  4136. err = os.MkdirAll(mappedPath2, os.ModePerm)
  4137. assert.NoError(t, err)
  4138. user, _, err := httpd.AddUser(u, http.StatusOK)
  4139. assert.NoError(t, err)
  4140. client, err := getSftpClient(user, usePubKey)
  4141. if assert.NoError(t, err) {
  4142. defer client.Close()
  4143. err = checkBasicSFTP(client)
  4144. assert.NoError(t, err)
  4145. testFileSize := int64(131072)
  4146. testFilePath := filepath.Join(homeBasePath, testFileName)
  4147. err = createTestFile(testFilePath, testFileSize)
  4148. assert.NoError(t, err)
  4149. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4150. assert.NoError(t, err)
  4151. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, testFileName), testFileSize, client)
  4152. assert.NoError(t, err)
  4153. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testFileName), testFileSize, client)
  4154. assert.NoError(t, err)
  4155. fi, err := client.Stat(path.Join(vdirPath1, subDir, testFileName))
  4156. if assert.NoError(t, err) {
  4157. assert.Equal(t, testFileSize, fi.Size())
  4158. }
  4159. err = client.Rename(path.Join(vdirPath1, subDir, testFileName), path.Join(vdirPath2, testFileName+"1"))
  4160. assert.NoError(t, err)
  4161. err = client.Rename(path.Join(vdirPath2, testFileName+"1"), path.Join(vdirPath1, subDir, testFileName))
  4162. assert.NoError(t, err)
  4163. err = client.Rename(path.Join(vdirPath1, subDir), path.Join(vdirPath2, subDir))
  4164. assert.Error(t, err)
  4165. err = client.Mkdir(subDir)
  4166. assert.NoError(t, err)
  4167. err = client.Rename(subDir, path.Join(vdirPath1, subDir))
  4168. assert.Error(t, err)
  4169. err = client.RemoveDirectory(path.Join(vdirPath1, subDir))
  4170. assert.Error(t, err)
  4171. err = client.Symlink(path.Join(vdirPath1, subDir), path.Join(vdirPath1, "adir"))
  4172. assert.Error(t, err)
  4173. err = client.Mkdir(path.Join(vdirPath1, subDir+"1"))
  4174. assert.NoError(t, err)
  4175. err = client.Symlink(path.Join(vdirPath1, subDir+"1"), path.Join(vdirPath1, subDir))
  4176. assert.Error(t, err)
  4177. err = os.Remove(testFilePath)
  4178. assert.NoError(t, err)
  4179. _, err = runSSHCommand(fmt.Sprintf("sftpgo-remove %v", path.Join(vdirPath1, subDir)), user, usePubKey)
  4180. assert.Error(t, err)
  4181. }
  4182. err = dataprovider.Close()
  4183. assert.NoError(t, err)
  4184. err = config.LoadConfig(configDir, "")
  4185. assert.NoError(t, err)
  4186. providerConf = config.GetProviderConf()
  4187. err = dataprovider.Initialize(providerConf, configDir)
  4188. assert.NoError(t, err)
  4189. if providerConf.Driver != dataprovider.MemoryDataProviderName {
  4190. client, err = getSftpClient(user, usePubKey)
  4191. if !assert.Error(t, err) {
  4192. client.Close()
  4193. }
  4194. _, err = httpd.RemoveUser(user, http.StatusOK)
  4195. assert.NoError(t, err)
  4196. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  4197. assert.NoError(t, err)
  4198. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  4199. assert.NoError(t, err)
  4200. }
  4201. _, _, err = httpd.AddUser(u, http.StatusOK)
  4202. assert.Error(t, err)
  4203. err = os.RemoveAll(user.GetHomeDir())
  4204. assert.NoError(t, err)
  4205. err = os.RemoveAll(mappedPath1)
  4206. assert.NoError(t, err)
  4207. err = os.RemoveAll(mappedPath2)
  4208. assert.NoError(t, err)
  4209. }
  4210. func TestResolveOverlappedMappedPaths(t *testing.T) {
  4211. u := getTestUser(false)
  4212. mappedPath1 := filepath.Join(os.TempDir(), "mapped1", "subdir")
  4213. vdirPath1 := "/vdir1/subdir"
  4214. mappedPath2 := filepath.Join(os.TempDir(), "mapped2")
  4215. vdirPath2 := "/vdir2/subdir"
  4216. mappedPath3 := filepath.Join(os.TempDir(), "mapped1")
  4217. vdirPath3 := "/vdir3"
  4218. mappedPath4 := filepath.Join(os.TempDir(), "mapped1", "subdir", "vdir4")
  4219. vdirPath4 := "/vdir4"
  4220. u.VirtualFolders = []vfs.VirtualFolder{
  4221. {
  4222. BaseVirtualFolder: vfs.BaseVirtualFolder{
  4223. MappedPath: mappedPath1,
  4224. },
  4225. VirtualPath: vdirPath1,
  4226. },
  4227. {
  4228. BaseVirtualFolder: vfs.BaseVirtualFolder{
  4229. MappedPath: mappedPath2,
  4230. },
  4231. VirtualPath: vdirPath2,
  4232. },
  4233. {
  4234. BaseVirtualFolder: vfs.BaseVirtualFolder{
  4235. MappedPath: mappedPath3,
  4236. },
  4237. VirtualPath: vdirPath3,
  4238. },
  4239. {
  4240. BaseVirtualFolder: vfs.BaseVirtualFolder{
  4241. MappedPath: mappedPath4,
  4242. },
  4243. VirtualPath: vdirPath4,
  4244. },
  4245. }
  4246. err := os.MkdirAll(u.GetHomeDir(), os.ModePerm)
  4247. assert.NoError(t, err)
  4248. err = os.MkdirAll(mappedPath1, os.ModePerm)
  4249. assert.NoError(t, err)
  4250. err = os.MkdirAll(mappedPath2, os.ModePerm)
  4251. assert.NoError(t, err)
  4252. err = os.MkdirAll(mappedPath3, os.ModePerm)
  4253. assert.NoError(t, err)
  4254. err = os.MkdirAll(mappedPath4, os.ModePerm)
  4255. assert.NoError(t, err)
  4256. fs := vfs.NewOsFs("", u.GetHomeDir(), u.VirtualFolders)
  4257. p, err := fs.ResolvePath("/vdir1")
  4258. assert.NoError(t, err)
  4259. assert.Equal(t, filepath.Join(u.GetHomeDir(), "vdir1"), p)
  4260. p, err = fs.ResolvePath("/vdir1/subdir")
  4261. assert.NoError(t, err)
  4262. assert.Equal(t, mappedPath1, p)
  4263. p, err = fs.ResolvePath("/vdir3/subdir/vdir4/file.txt")
  4264. assert.NoError(t, err)
  4265. assert.Equal(t, filepath.Join(mappedPath4, "file.txt"), p)
  4266. p, err = fs.ResolvePath("/vdir4/file.txt")
  4267. assert.NoError(t, err)
  4268. assert.Equal(t, filepath.Join(mappedPath4, "file.txt"), p)
  4269. assert.Equal(t, filepath.Join(mappedPath3, "subdir", "vdir4", "file.txt"), p)
  4270. assert.Equal(t, filepath.Join(mappedPath1, "vdir4", "file.txt"), p)
  4271. p, err = fs.ResolvePath("/vdir3/subdir/vdir4/../file.txt")
  4272. assert.NoError(t, err)
  4273. assert.Equal(t, filepath.Join(mappedPath3, "subdir", "file.txt"), p)
  4274. assert.Equal(t, filepath.Join(mappedPath1, "file.txt"), p)
  4275. err = os.RemoveAll(u.GetHomeDir())
  4276. assert.NoError(t, err)
  4277. err = os.RemoveAll(mappedPath4)
  4278. assert.NoError(t, err)
  4279. err = os.RemoveAll(mappedPath1)
  4280. assert.NoError(t, err)
  4281. err = os.RemoveAll(mappedPath3)
  4282. assert.NoError(t, err)
  4283. err = os.RemoveAll(mappedPath2)
  4284. assert.NoError(t, err)
  4285. }
  4286. func TestVirtualFolderQuotaScan(t *testing.T) {
  4287. mappedPath := filepath.Join(os.TempDir(), "mapped_dir")
  4288. err := os.MkdirAll(mappedPath, os.ModePerm)
  4289. assert.NoError(t, err)
  4290. testFileSize := int64(65535)
  4291. testFilePath := filepath.Join(mappedPath, testFileName)
  4292. err = createTestFile(testFilePath, testFileSize)
  4293. assert.NoError(t, err)
  4294. expectedQuotaSize := testFileSize
  4295. expectedQuotaFiles := 1
  4296. folder, _, err := httpd.AddFolder(vfs.BaseVirtualFolder{
  4297. MappedPath: mappedPath,
  4298. }, http.StatusOK)
  4299. assert.NoError(t, err)
  4300. _, err = httpd.StartFolderQuotaScan(folder, http.StatusCreated)
  4301. assert.NoError(t, err)
  4302. assert.Eventually(t, func() bool {
  4303. scans, _, err := httpd.GetFoldersQuotaScans(http.StatusOK)
  4304. if err == nil {
  4305. return len(scans) == 0
  4306. }
  4307. return false
  4308. }, 1*time.Second, 50*time.Millisecond)
  4309. folders, _, err := httpd.GetFolders(0, 0, mappedPath, http.StatusOK)
  4310. assert.NoError(t, err)
  4311. if assert.Len(t, folders, 1) {
  4312. folder = folders[0]
  4313. assert.Equal(t, expectedQuotaFiles, folder.UsedQuotaFiles)
  4314. assert.Equal(t, expectedQuotaSize, folder.UsedQuotaSize)
  4315. }
  4316. _, err = httpd.RemoveFolder(folder, http.StatusOK)
  4317. assert.NoError(t, err)
  4318. err = os.RemoveAll(mappedPath)
  4319. assert.NoError(t, err)
  4320. }
  4321. func TestVFolderMultipleQuotaScan(t *testing.T) {
  4322. folderPath := filepath.Join(os.TempDir(), "folder_path")
  4323. res := common.QuotaScans.AddVFolderQuotaScan(folderPath)
  4324. assert.True(t, res)
  4325. res = common.QuotaScans.AddVFolderQuotaScan(folderPath)
  4326. assert.False(t, res)
  4327. res = common.QuotaScans.RemoveVFolderQuotaScan(folderPath)
  4328. assert.True(t, res)
  4329. activeScans := common.QuotaScans.GetVFoldersQuotaScans()
  4330. assert.Len(t, activeScans, 0)
  4331. res = common.QuotaScans.RemoveVFolderQuotaScan(folderPath)
  4332. assert.False(t, res)
  4333. }
  4334. func TestVFolderQuotaSize(t *testing.T) {
  4335. usePubKey := false
  4336. u := getTestUser(usePubKey)
  4337. testFileSize := int64(131072)
  4338. u.QuotaFiles = 1
  4339. u.QuotaSize = testFileSize + 1
  4340. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  4341. vdirPath1 := "/vpath1"
  4342. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  4343. vdirPath2 := "/vpath2"
  4344. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  4345. BaseVirtualFolder: vfs.BaseVirtualFolder{
  4346. MappedPath: mappedPath1,
  4347. },
  4348. VirtualPath: vdirPath1,
  4349. // quota is included in the user's one
  4350. QuotaFiles: -1,
  4351. QuotaSize: -1,
  4352. })
  4353. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  4354. BaseVirtualFolder: vfs.BaseVirtualFolder{
  4355. MappedPath: mappedPath2,
  4356. },
  4357. VirtualPath: vdirPath2,
  4358. QuotaFiles: 1,
  4359. QuotaSize: testFileSize * 2,
  4360. })
  4361. err := os.MkdirAll(mappedPath1, os.ModePerm)
  4362. assert.NoError(t, err)
  4363. err = os.MkdirAll(mappedPath2, os.ModePerm)
  4364. assert.NoError(t, err)
  4365. testFilePath := filepath.Join(homeBasePath, testFileName)
  4366. err = createTestFile(testFilePath, testFileSize)
  4367. assert.NoError(t, err)
  4368. user, _, err := httpd.AddUser(u, http.StatusOK)
  4369. assert.NoError(t, err)
  4370. client, err := getSftpClient(user, usePubKey)
  4371. if assert.NoError(t, err) {
  4372. defer client.Close()
  4373. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4374. assert.NoError(t, err)
  4375. // vdir1 is included in the user quota so upload must fail
  4376. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, testFileName), testFileSize, client)
  4377. assert.Error(t, err)
  4378. // upload to vdir2 must work, it has its own quota
  4379. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testFileName), testFileSize, client)
  4380. assert.NoError(t, err)
  4381. // now vdir2 is over quota
  4382. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testFileName+".quota"), testFileSize, client)
  4383. assert.Error(t, err)
  4384. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  4385. assert.NoError(t, err)
  4386. assert.Equal(t, 1, user.UsedQuotaFiles)
  4387. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  4388. // remove a file
  4389. err = client.Remove(testFileName)
  4390. assert.NoError(t, err)
  4391. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  4392. assert.NoError(t, err)
  4393. assert.Equal(t, 0, user.UsedQuotaFiles)
  4394. assert.Equal(t, int64(0), user.UsedQuotaSize)
  4395. // upload to vdir1 must work now
  4396. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, testFileName), testFileSize, client)
  4397. assert.NoError(t, err)
  4398. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  4399. assert.NoError(t, err)
  4400. assert.Equal(t, 1, user.UsedQuotaFiles)
  4401. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  4402. folder, _, err := httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  4403. assert.NoError(t, err)
  4404. if assert.Len(t, folder, 1) {
  4405. f := folder[0]
  4406. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  4407. assert.Equal(t, 1, f.UsedQuotaFiles)
  4408. }
  4409. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  4410. assert.NoError(t, err)
  4411. if assert.Len(t, folder, 1) {
  4412. f := folder[0]
  4413. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  4414. assert.Equal(t, 1, f.UsedQuotaFiles)
  4415. }
  4416. }
  4417. // now create another user with the same shared folder but a different quota limit
  4418. u.Username = defaultUsername + "1"
  4419. u.VirtualFolders = nil
  4420. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  4421. BaseVirtualFolder: vfs.BaseVirtualFolder{
  4422. MappedPath: mappedPath2,
  4423. },
  4424. VirtualPath: vdirPath2,
  4425. QuotaFiles: 10,
  4426. QuotaSize: testFileSize*2 + 1,
  4427. })
  4428. user1, _, err := httpd.AddUser(u, http.StatusOK)
  4429. assert.NoError(t, err)
  4430. client, err = getSftpClient(user1, usePubKey)
  4431. if assert.NoError(t, err) {
  4432. defer client.Close()
  4433. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testFileName+".quota"), testFileSize, client)
  4434. assert.NoError(t, err)
  4435. // the folder is now over quota for size but not for files
  4436. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testFileName+".quota1"), testFileSize, client)
  4437. assert.Error(t, err)
  4438. }
  4439. _, err = httpd.RemoveUser(user, http.StatusOK)
  4440. assert.NoError(t, err)
  4441. _, err = httpd.RemoveUser(user1, http.StatusOK)
  4442. assert.NoError(t, err)
  4443. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  4444. assert.NoError(t, err)
  4445. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  4446. assert.NoError(t, err)
  4447. err = os.RemoveAll(user.GetHomeDir())
  4448. assert.NoError(t, err)
  4449. err = os.RemoveAll(mappedPath1)
  4450. assert.NoError(t, err)
  4451. err = os.RemoveAll(mappedPath2)
  4452. assert.NoError(t, err)
  4453. }
  4454. func TestMissingFile(t *testing.T) {
  4455. usePubKey := false
  4456. u := getTestUser(usePubKey)
  4457. user, _, err := httpd.AddUser(u, http.StatusOK)
  4458. assert.NoError(t, err)
  4459. client, err := getSftpClient(user, usePubKey)
  4460. if assert.NoError(t, err) {
  4461. defer client.Close()
  4462. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  4463. err = sftpDownloadFile("missing_file", localDownloadPath, 0, client)
  4464. assert.Error(t, err, "download missing file must fail")
  4465. err = os.Remove(localDownloadPath)
  4466. assert.NoError(t, err)
  4467. }
  4468. _, err = httpd.RemoveUser(user, http.StatusOK)
  4469. assert.NoError(t, err)
  4470. err = os.RemoveAll(user.GetHomeDir())
  4471. assert.NoError(t, err)
  4472. }
  4473. func TestOpenError(t *testing.T) {
  4474. if runtime.GOOS == osWindows {
  4475. t.Skip("this test is not available on Windows")
  4476. }
  4477. usePubKey := false
  4478. u := getTestUser(usePubKey)
  4479. user, _, err := httpd.AddUser(u, http.StatusOK)
  4480. assert.NoError(t, err)
  4481. err = os.RemoveAll(user.GetHomeDir())
  4482. assert.NoError(t, err)
  4483. client, err := getSftpClient(user, usePubKey)
  4484. if assert.NoError(t, err) {
  4485. defer client.Close()
  4486. err = os.Chmod(user.GetHomeDir(), 0001)
  4487. assert.NoError(t, err)
  4488. _, err = client.ReadDir(".")
  4489. assert.Error(t, err, "read dir must fail if we have no filesystem read permissions")
  4490. err = os.Chmod(user.GetHomeDir(), os.ModePerm)
  4491. assert.NoError(t, err)
  4492. testFileSize := int64(65535)
  4493. testFilePath := filepath.Join(user.GetHomeDir(), testFileName)
  4494. err = createTestFile(testFilePath, testFileSize)
  4495. assert.NoError(t, err)
  4496. _, err = client.Stat(testFileName)
  4497. assert.NoError(t, err)
  4498. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  4499. err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize, client)
  4500. assert.NoError(t, err)
  4501. err = os.Chmod(testFilePath, 0001)
  4502. assert.NoError(t, err)
  4503. err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize, client)
  4504. assert.Error(t, err, "file download must fail if we have no filesystem read permissions")
  4505. err = sftpUploadFile(localDownloadPath, testFileName, testFileSize, client)
  4506. assert.Error(t, err, "upload must fail if we have no filesystem write permissions")
  4507. err = client.Mkdir("test")
  4508. assert.NoError(t, err)
  4509. err = os.Chmod(user.GetHomeDir(), 0000)
  4510. assert.NoError(t, err)
  4511. _, err = client.Lstat(testFileName)
  4512. assert.Error(t, err, "file stat must fail if we have no filesystem read permissions")
  4513. err = os.Chmod(user.GetHomeDir(), os.ModePerm)
  4514. assert.NoError(t, err)
  4515. err = os.Chmod(filepath.Join(user.GetHomeDir(), "test"), 0000)
  4516. assert.NoError(t, err)
  4517. err = client.Rename(testFileName, path.Join("test", testFileName))
  4518. if assert.Error(t, err) {
  4519. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  4520. }
  4521. err = os.Chmod(filepath.Join(user.GetHomeDir(), "test"), os.ModePerm)
  4522. assert.NoError(t, err)
  4523. err = os.Remove(localDownloadPath)
  4524. assert.NoError(t, err)
  4525. }
  4526. _, err = httpd.RemoveUser(user, http.StatusOK)
  4527. assert.NoError(t, err)
  4528. err = os.RemoveAll(user.GetHomeDir())
  4529. assert.NoError(t, err)
  4530. }
  4531. func TestOverwriteDirWithFile(t *testing.T) {
  4532. usePubKey := false
  4533. u := getTestUser(usePubKey)
  4534. user, _, err := httpd.AddUser(u, http.StatusOK)
  4535. assert.NoError(t, err)
  4536. client, err := getSftpClient(user, usePubKey)
  4537. if assert.NoError(t, err) {
  4538. defer client.Close()
  4539. testFileSize := int64(65535)
  4540. testDirName := "test_dir" //nolint:goconst
  4541. testFilePath := filepath.Join(homeBasePath, testFileName)
  4542. err = createTestFile(testFilePath, testFileSize)
  4543. assert.NoError(t, err)
  4544. err = client.Mkdir(testDirName)
  4545. assert.NoError(t, err)
  4546. err = sftpUploadFile(testFilePath, testDirName, testFileSize, client)
  4547. assert.Error(t, err, "copying a file over an existing dir must fail")
  4548. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4549. assert.NoError(t, err)
  4550. err = client.Rename(testFileName, testDirName)
  4551. assert.Error(t, err, "rename a file over an existing dir must fail")
  4552. err = client.RemoveDirectory(testDirName)
  4553. assert.NoError(t, err)
  4554. err = client.Remove(testFileName)
  4555. assert.NoError(t, err)
  4556. err = os.Remove(testFilePath)
  4557. assert.NoError(t, err)
  4558. }
  4559. _, err = httpd.RemoveUser(user, http.StatusOK)
  4560. assert.NoError(t, err)
  4561. err = os.RemoveAll(user.GetHomeDir())
  4562. assert.NoError(t, err)
  4563. }
  4564. func TestHashedPasswords(t *testing.T) {
  4565. usePubKey := false
  4566. pwdMapping := make(map[string]string)
  4567. pwdMapping["$pbkdf2-sha1$150000$DveVjgYUD05R$X6ydQZdyMeOvpgND2nqGR/0GGic="] = "password" //nolint:goconst
  4568. pwdMapping["$pbkdf2-sha256$150000$E86a9YMX3zC7$R5J62hsSq+pYw00hLLPKBbcGXmq7fj5+/M0IFoYtZbo="] = "password"
  4569. pwdMapping["$pbkdf2-sha512$150000$dsu7T5R3IaVQ$1hFXPO1ntRBcoWkSLKw+s4sAP09Xtu4Ya7CyxFq64jM9zdUg8eRJVr3NcR2vQgb0W9HHvZaILHsL4Q/Vr6arCg=="] = "password"
  4570. pwdMapping["$1$b5caebda$VODr/nyhGWgZaY8sJ4x05."] = "password"
  4571. pwdMapping["$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK"] = "secret"
  4572. pwdMapping["$6$459ead56b72e44bc$uog86fUxscjt28BZxqFBE2pp2QD8P/1e98MNF75Z9xJfQvOckZnQ/1YJqiq1XeytPuDieHZvDAMoP7352ELkO1"] = "secret"
  4573. pwdMapping["$apr1$OBWLeSme$WoJbB736e7kKxMBIAqilb1"] = "password"
  4574. for pwd, clearPwd := range pwdMapping {
  4575. u := getTestUser(usePubKey)
  4576. u.Password = pwd
  4577. user, _, err := httpd.AddUser(u, http.StatusOK)
  4578. assert.NoError(t, err)
  4579. user.Password = clearPwd
  4580. client, err := getSftpClient(user, usePubKey)
  4581. if assert.NoError(t, err, "unable to login with password %#v", pwd) {
  4582. defer client.Close()
  4583. assert.NoError(t, checkBasicSFTP(client))
  4584. }
  4585. user.Password = pwd
  4586. client, err = getSftpClient(user, usePubKey)
  4587. if !assert.Error(t, err, "login with wrong password must fail") {
  4588. client.Close()
  4589. }
  4590. _, err = httpd.RemoveUser(user, http.StatusOK)
  4591. assert.NoError(t, err)
  4592. err = os.RemoveAll(user.GetHomeDir())
  4593. assert.NoError(t, err)
  4594. }
  4595. }
  4596. func TestPasswordsHashPbkdf2Sha256_389DS(t *testing.T) {
  4597. pbkdf389dsPwd := "{PBKDF2_SHA256}AAAIAMZIKG4ie44zJY4HOXI+upFR74PzWLUQV63jg+zzkbEjCK3N4qW583WF7EdcpeoOMQ4HY3aWEXB6lnXhXJixbJkU4vVSJkL6YCbU3TrD0qn1uUUVSkaIgAOtmZENitwbhYhiWfEzGyAtFqkFd75P5xhWJEog9XhQKYrR0f7S3WGGZq03JRcLJ460xpU97bE/sWRn7sshgkWzLuyrs0I+XRKmK7FJeaA9zd+1m44Y3IVmZ2YLdKATzjRHAIgpBC6i1TWOcpKJT1+feP1C9hrxH8vU9baw9thNiO8jSHaZlwb//KpJFe0ahVnG/1ubiG8cO0+CCqDqXVJR6Vr4QZxHP+4pwooW+4TP/L+HFdyA1y6z4gKfqYnBsmb3sD1R1TbxfH4btTdvgZAnBk9CmR3QASkFXxeTYsrmNd5+9IAHc6dm"
  4598. pbkdf389dsPwd = pbkdf389dsPwd[15:]
  4599. hashBytes, err := base64.StdEncoding.DecodeString(pbkdf389dsPwd)
  4600. assert.NoError(t, err)
  4601. iterBytes := hashBytes[0:4]
  4602. var iterations int32
  4603. err = binary.Read(bytes.NewBuffer(iterBytes), binary.BigEndian, &iterations)
  4604. assert.NoError(t, err)
  4605. salt := hashBytes[4:68]
  4606. targetKey := hashBytes[68:]
  4607. key := base64.StdEncoding.EncodeToString(targetKey)
  4608. pbkdf2Pwd := fmt.Sprintf("$pbkdf2-b64salt-sha256$%v$%v$%v", iterations, base64.StdEncoding.EncodeToString(salt), key)
  4609. pbkdf2ClearPwd := "password"
  4610. usePubKey := false
  4611. u := getTestUser(usePubKey)
  4612. u.Password = pbkdf2Pwd
  4613. user, _, err := httpd.AddUser(u, http.StatusOK)
  4614. assert.NoError(t, err)
  4615. user.Password = pbkdf2ClearPwd
  4616. client, err := getSftpClient(user, usePubKey)
  4617. if assert.NoError(t, err) {
  4618. defer client.Close()
  4619. assert.NoError(t, checkBasicSFTP(client))
  4620. }
  4621. user.Password = pbkdf2Pwd
  4622. client, err = getSftpClient(user, usePubKey)
  4623. if !assert.Error(t, err, "login with wrong password must fail") {
  4624. client.Close()
  4625. }
  4626. _, err = httpd.RemoveUser(user, http.StatusOK)
  4627. assert.NoError(t, err)
  4628. err = os.RemoveAll(user.GetHomeDir())
  4629. assert.NoError(t, err)
  4630. }
  4631. func TestPermList(t *testing.T) {
  4632. usePubKey := true
  4633. u := getTestUser(usePubKey)
  4634. u.Permissions["/"] = []string{dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete, dataprovider.PermRename,
  4635. dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite, dataprovider.PermChmod,
  4636. dataprovider.PermChown, dataprovider.PermChtimes}
  4637. u.Permissions["/sub"] = []string{dataprovider.PermCreateSymlinks, dataprovider.PermListItems}
  4638. user, _, err := httpd.AddUser(u, http.StatusOK)
  4639. assert.NoError(t, err)
  4640. client, err := getSftpClient(user, usePubKey)
  4641. if assert.NoError(t, err) {
  4642. defer client.Close()
  4643. _, err = client.ReadDir(".")
  4644. assert.Error(t, err, "read remote dir without permission should not succeed")
  4645. _, err = client.Stat("test_file")
  4646. assert.Error(t, err, "stat remote file without permission should not succeed")
  4647. _, err = client.Lstat("test_file")
  4648. assert.Error(t, err, "lstat remote file without permission should not succeed")
  4649. _, err = client.ReadLink("test_link")
  4650. assert.Error(t, err, "read remote link without permission on source dir should not succeed")
  4651. f, err := client.Create(testFileName)
  4652. if assert.NoError(t, err) {
  4653. _, err = f.Write([]byte("content"))
  4654. assert.NoError(t, err)
  4655. err = f.Close()
  4656. assert.NoError(t, err)
  4657. }
  4658. err = client.Mkdir("sub")
  4659. assert.NoError(t, err)
  4660. err = client.Symlink(testFileName, path.Join("/sub", testFileName))
  4661. assert.NoError(t, err)
  4662. _, err = client.ReadLink(path.Join("/sub", testFileName))
  4663. assert.Error(t, err, "read remote link without permission on targe dir should not succeed")
  4664. }
  4665. _, err = httpd.RemoveUser(user, http.StatusOK)
  4666. assert.NoError(t, err)
  4667. err = os.RemoveAll(user.GetHomeDir())
  4668. assert.NoError(t, err)
  4669. }
  4670. func TestPermDownload(t *testing.T) {
  4671. usePubKey := true
  4672. u := getTestUser(usePubKey)
  4673. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermUpload, dataprovider.PermDelete, dataprovider.PermRename,
  4674. dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite, dataprovider.PermChmod,
  4675. dataprovider.PermChown, dataprovider.PermChtimes}
  4676. user, _, err := httpd.AddUser(u, http.StatusOK)
  4677. assert.NoError(t, err)
  4678. client, err := getSftpClient(user, usePubKey)
  4679. if assert.NoError(t, err) {
  4680. defer client.Close()
  4681. testFilePath := filepath.Join(homeBasePath, testFileName)
  4682. testFileSize := int64(65535)
  4683. err = createTestFile(testFilePath, testFileSize)
  4684. assert.NoError(t, err)
  4685. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4686. assert.NoError(t, err)
  4687. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  4688. err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize, client)
  4689. assert.Error(t, err, "file download without permission should not succeed")
  4690. err = client.Remove(testFileName)
  4691. assert.NoError(t, err)
  4692. err = os.Remove(testFilePath)
  4693. assert.NoError(t, err)
  4694. err = os.Remove(localDownloadPath)
  4695. assert.NoError(t, err)
  4696. }
  4697. _, err = httpd.RemoveUser(user, http.StatusOK)
  4698. assert.NoError(t, err)
  4699. err = os.RemoveAll(user.GetHomeDir())
  4700. assert.NoError(t, err)
  4701. }
  4702. func TestPermUpload(t *testing.T) {
  4703. usePubKey := false
  4704. u := getTestUser(usePubKey)
  4705. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermDelete, dataprovider.PermRename,
  4706. dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite, dataprovider.PermChmod,
  4707. dataprovider.PermChown, dataprovider.PermChtimes}
  4708. user, _, err := httpd.AddUser(u, http.StatusOK)
  4709. assert.NoError(t, err)
  4710. client, err := getSftpClient(user, usePubKey)
  4711. if assert.NoError(t, err) {
  4712. defer client.Close()
  4713. testFilePath := filepath.Join(homeBasePath, testFileName)
  4714. testFileSize := int64(65535)
  4715. err = createTestFile(testFilePath, testFileSize)
  4716. assert.NoError(t, err)
  4717. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4718. assert.Error(t, err, "file upload without permission should not succeed")
  4719. err = os.Remove(testFilePath)
  4720. assert.NoError(t, err)
  4721. }
  4722. _, err = httpd.RemoveUser(user, http.StatusOK)
  4723. assert.NoError(t, err)
  4724. err = os.RemoveAll(user.GetHomeDir())
  4725. assert.NoError(t, err)
  4726. }
  4727. func TestPermOverwrite(t *testing.T) {
  4728. usePubKey := false
  4729. u := getTestUser(usePubKey)
  4730. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete,
  4731. dataprovider.PermRename, dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermChmod,
  4732. dataprovider.PermChown, dataprovider.PermChtimes}
  4733. user, _, err := httpd.AddUser(u, http.StatusOK)
  4734. assert.NoError(t, err)
  4735. client, err := getSftpClient(user, usePubKey)
  4736. if assert.NoError(t, err) {
  4737. defer client.Close()
  4738. testFilePath := filepath.Join(homeBasePath, testFileName)
  4739. testFileSize := int64(65535)
  4740. err = createTestFile(testFilePath, testFileSize)
  4741. assert.NoError(t, err)
  4742. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4743. assert.NoError(t, err)
  4744. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4745. assert.Error(t, err, "file overwrite without permission should not succeed")
  4746. err = os.Remove(testFilePath)
  4747. assert.NoError(t, err)
  4748. }
  4749. _, err = httpd.RemoveUser(user, http.StatusOK)
  4750. assert.NoError(t, err)
  4751. err = os.RemoveAll(user.GetHomeDir())
  4752. assert.NoError(t, err)
  4753. }
  4754. func TestPermDelete(t *testing.T) {
  4755. usePubKey := false
  4756. u := getTestUser(usePubKey)
  4757. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermRename,
  4758. dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite, dataprovider.PermChmod,
  4759. dataprovider.PermChown, dataprovider.PermChtimes}
  4760. user, _, err := httpd.AddUser(u, http.StatusOK)
  4761. assert.NoError(t, err)
  4762. client, err := getSftpClient(user, usePubKey)
  4763. if assert.NoError(t, err) {
  4764. defer client.Close()
  4765. testFilePath := filepath.Join(homeBasePath, testFileName)
  4766. testFileSize := int64(65535)
  4767. err = createTestFile(testFilePath, testFileSize)
  4768. assert.NoError(t, err)
  4769. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4770. assert.NoError(t, err)
  4771. err = client.Remove(testFileName)
  4772. assert.Error(t, err, "delete without permission should not succeed")
  4773. err = os.Remove(testFilePath)
  4774. assert.NoError(t, err)
  4775. }
  4776. _, err = httpd.RemoveUser(user, http.StatusOK)
  4777. assert.NoError(t, err)
  4778. err = os.RemoveAll(user.GetHomeDir())
  4779. assert.NoError(t, err)
  4780. }
  4781. //nolint:dupl
  4782. func TestPermRename(t *testing.T) {
  4783. usePubKey := false
  4784. u := getTestUser(usePubKey)
  4785. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload,
  4786. dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite, dataprovider.PermChmod,
  4787. dataprovider.PermChown, dataprovider.PermChtimes}
  4788. user, _, err := httpd.AddUser(u, http.StatusOK)
  4789. assert.NoError(t, err)
  4790. client, err := getSftpClient(user, usePubKey)
  4791. if assert.NoError(t, err) {
  4792. defer client.Close()
  4793. testFilePath := filepath.Join(homeBasePath, testFileName)
  4794. testFileSize := int64(65535)
  4795. err = createTestFile(testFilePath, testFileSize)
  4796. assert.NoError(t, err)
  4797. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4798. assert.NoError(t, err)
  4799. err = client.Rename(testFileName, testFileName+".rename")
  4800. if assert.Error(t, err) {
  4801. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  4802. }
  4803. _, err = client.Stat(testFileName)
  4804. assert.NoError(t, err)
  4805. err = os.Remove(testFilePath)
  4806. assert.NoError(t, err)
  4807. }
  4808. _, err = httpd.RemoveUser(user, http.StatusOK)
  4809. assert.NoError(t, err)
  4810. err = os.RemoveAll(user.GetHomeDir())
  4811. assert.NoError(t, err)
  4812. }
  4813. //nolint:dupl
  4814. func TestPermRenameOverwrite(t *testing.T) {
  4815. usePubKey := false
  4816. u := getTestUser(usePubKey)
  4817. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete,
  4818. dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermChmod, dataprovider.PermRename,
  4819. dataprovider.PermChown, dataprovider.PermChtimes}
  4820. user, _, err := httpd.AddUser(u, http.StatusOK)
  4821. assert.NoError(t, err)
  4822. client, err := getSftpClient(user, usePubKey)
  4823. if assert.NoError(t, err) {
  4824. defer client.Close()
  4825. testFilePath := filepath.Join(homeBasePath, testFileName)
  4826. testFileSize := int64(65535)
  4827. err = createTestFile(testFilePath, testFileSize)
  4828. assert.NoError(t, err)
  4829. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4830. assert.NoError(t, err)
  4831. err = client.Rename(testFileName, testFileName+".rename")
  4832. assert.NoError(t, err)
  4833. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4834. assert.NoError(t, err)
  4835. err = client.Rename(testFileName, testFileName+".rename")
  4836. if assert.Error(t, err) {
  4837. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  4838. }
  4839. err = client.Remove(testFileName)
  4840. assert.NoError(t, err)
  4841. err = os.Remove(testFilePath)
  4842. assert.NoError(t, err)
  4843. }
  4844. _, err = httpd.RemoveUser(user, http.StatusOK)
  4845. assert.NoError(t, err)
  4846. err = os.RemoveAll(user.GetHomeDir())
  4847. assert.NoError(t, err)
  4848. }
  4849. func TestPermCreateDirs(t *testing.T) {
  4850. usePubKey := false
  4851. u := getTestUser(usePubKey)
  4852. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete,
  4853. dataprovider.PermRename, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite, dataprovider.PermChmod,
  4854. dataprovider.PermChown, dataprovider.PermChtimes}
  4855. user, _, err := httpd.AddUser(u, http.StatusOK)
  4856. assert.NoError(t, err)
  4857. client, err := getSftpClient(user, usePubKey)
  4858. if assert.NoError(t, err) {
  4859. defer client.Close()
  4860. err = client.Mkdir("testdir")
  4861. assert.Error(t, err, "mkdir without permission should not succeed")
  4862. }
  4863. _, err = httpd.RemoveUser(user, http.StatusOK)
  4864. assert.NoError(t, err)
  4865. err = os.RemoveAll(user.GetHomeDir())
  4866. assert.NoError(t, err)
  4867. }
  4868. //nolint:dupl
  4869. func TestPermSymlink(t *testing.T) {
  4870. usePubKey := false
  4871. u := getTestUser(usePubKey)
  4872. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete,
  4873. dataprovider.PermRename, dataprovider.PermCreateDirs, dataprovider.PermOverwrite, dataprovider.PermChmod, dataprovider.PermChown,
  4874. dataprovider.PermChtimes}
  4875. user, _, err := httpd.AddUser(u, http.StatusOK)
  4876. assert.NoError(t, err)
  4877. client, err := getSftpClient(user, usePubKey)
  4878. if assert.NoError(t, err) {
  4879. defer client.Close()
  4880. testFilePath := filepath.Join(homeBasePath, testFileName)
  4881. testFileSize := int64(65535)
  4882. err = createTestFile(testFilePath, testFileSize)
  4883. assert.NoError(t, err)
  4884. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4885. assert.NoError(t, err)
  4886. err = client.Symlink(testFilePath, testFilePath+".symlink")
  4887. assert.Error(t, err, "symlink without permission should not succeed")
  4888. err = client.Remove(testFileName)
  4889. assert.NoError(t, err)
  4890. err = os.Remove(testFilePath)
  4891. assert.NoError(t, err)
  4892. }
  4893. _, err = httpd.RemoveUser(user, http.StatusOK)
  4894. assert.NoError(t, err)
  4895. err = os.RemoveAll(user.GetHomeDir())
  4896. assert.NoError(t, err)
  4897. }
  4898. func TestPermChmod(t *testing.T) {
  4899. usePubKey := false
  4900. u := getTestUser(usePubKey)
  4901. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete,
  4902. dataprovider.PermRename, dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite,
  4903. dataprovider.PermChown, dataprovider.PermChtimes}
  4904. user, _, err := httpd.AddUser(u, http.StatusOK)
  4905. assert.NoError(t, err)
  4906. client, err := getSftpClient(user, usePubKey)
  4907. if assert.NoError(t, err) {
  4908. defer client.Close()
  4909. testFilePath := filepath.Join(homeBasePath, testFileName)
  4910. testFileSize := int64(65535)
  4911. err = createTestFile(testFilePath, testFileSize)
  4912. assert.NoError(t, err)
  4913. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4914. assert.NoError(t, err)
  4915. err = client.Chmod(testFileName, os.ModePerm)
  4916. assert.Error(t, err, "chmod without permission should not succeed")
  4917. err = client.Remove(testFileName)
  4918. assert.NoError(t, err)
  4919. err = os.Remove(testFilePath)
  4920. assert.NoError(t, err)
  4921. }
  4922. _, err = httpd.RemoveUser(user, http.StatusOK)
  4923. assert.NoError(t, err)
  4924. err = os.RemoveAll(user.GetHomeDir())
  4925. assert.NoError(t, err)
  4926. }
  4927. //nolint:dupl
  4928. func TestPermChown(t *testing.T) {
  4929. usePubKey := false
  4930. u := getTestUser(usePubKey)
  4931. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete,
  4932. dataprovider.PermRename, dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite,
  4933. dataprovider.PermChmod, dataprovider.PermChtimes}
  4934. user, _, err := httpd.AddUser(u, http.StatusOK)
  4935. assert.NoError(t, err)
  4936. client, err := getSftpClient(user, usePubKey)
  4937. if assert.NoError(t, err) {
  4938. defer client.Close()
  4939. testFilePath := filepath.Join(homeBasePath, testFileName)
  4940. testFileSize := int64(65535)
  4941. err = createTestFile(testFilePath, testFileSize)
  4942. assert.NoError(t, err)
  4943. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4944. assert.NoError(t, err)
  4945. err = client.Chown(testFileName, os.Getuid(), os.Getgid())
  4946. assert.Error(t, err, "chown without permission should not succeed")
  4947. err = client.Remove(testFileName)
  4948. assert.NoError(t, err)
  4949. err = os.Remove(testFilePath)
  4950. assert.NoError(t, err)
  4951. }
  4952. _, err = httpd.RemoveUser(user, http.StatusOK)
  4953. assert.NoError(t, err)
  4954. err = os.RemoveAll(user.GetHomeDir())
  4955. assert.NoError(t, err)
  4956. }
  4957. //nolint:dupl
  4958. func TestPermChtimes(t *testing.T) {
  4959. usePubKey := false
  4960. u := getTestUser(usePubKey)
  4961. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDelete,
  4962. dataprovider.PermRename, dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermOverwrite,
  4963. dataprovider.PermChmod, dataprovider.PermChown}
  4964. user, _, err := httpd.AddUser(u, http.StatusOK)
  4965. assert.NoError(t, err)
  4966. client, err := getSftpClient(user, usePubKey)
  4967. if assert.NoError(t, err) {
  4968. defer client.Close()
  4969. testFilePath := filepath.Join(homeBasePath, testFileName)
  4970. testFileSize := int64(65535)
  4971. err = createTestFile(testFilePath, testFileSize)
  4972. assert.NoError(t, err)
  4973. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  4974. assert.NoError(t, err)
  4975. err = client.Chtimes(testFileName, time.Now(), time.Now())
  4976. assert.Error(t, err, "chtimes without permission should not succeed")
  4977. err = client.Remove(testFileName)
  4978. assert.NoError(t, err)
  4979. err = os.Remove(testFilePath)
  4980. assert.NoError(t, err)
  4981. }
  4982. _, err = httpd.RemoveUser(user, http.StatusOK)
  4983. assert.NoError(t, err)
  4984. err = os.RemoveAll(user.GetHomeDir())
  4985. assert.NoError(t, err)
  4986. }
  4987. func TestSubDirsUploads(t *testing.T) {
  4988. usePubKey := true
  4989. u := getTestUser(usePubKey)
  4990. u.Permissions["/"] = []string{dataprovider.PermAny}
  4991. u.Permissions["/subdir"] = []string{dataprovider.PermChtimes, dataprovider.PermDownload, dataprovider.PermOverwrite}
  4992. user, _, err := httpd.AddUser(u, http.StatusOK)
  4993. assert.NoError(t, err)
  4994. client, err := getSftpClient(user, usePubKey)
  4995. if assert.NoError(t, err) {
  4996. defer client.Close()
  4997. err = client.Mkdir("subdir")
  4998. assert.NoError(t, err)
  4999. testFileNameSub := "/subdir/test_file_dat"
  5000. testSubFile := filepath.Join(user.GetHomeDir(), "subdir", "file.dat")
  5001. testDir := "testdir"
  5002. testFilePath := filepath.Join(homeBasePath, testFileName)
  5003. testFileSize := int64(65535)
  5004. err = createTestFile(testFilePath, testFileSize)
  5005. assert.NoError(t, err)
  5006. err = createTestFile(testSubFile, testFileSize)
  5007. assert.NoError(t, err)
  5008. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  5009. assert.NoError(t, err)
  5010. err = sftpUploadFile(testFilePath, testFileNameSub, testFileSize, client)
  5011. if assert.Error(t, err) {
  5012. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5013. }
  5014. err = client.Symlink(testFileName, testFileNameSub+".link")
  5015. if assert.Error(t, err) {
  5016. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5017. }
  5018. err = client.Symlink(testFileName, testFileName+".link")
  5019. assert.NoError(t, err)
  5020. err = client.Rename(testFileName, testFileNameSub+".rename")
  5021. if assert.Error(t, err) {
  5022. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5023. }
  5024. err = client.Rename(testFileName, testFileName+".rename")
  5025. assert.NoError(t, err)
  5026. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  5027. assert.NoError(t, err)
  5028. // rename overwriting an existing file
  5029. err = client.Rename(testFileName, testFileName+".rename")
  5030. assert.NoError(t, err)
  5031. // now try to overwrite a directory
  5032. err = client.Mkdir(testDir)
  5033. assert.NoError(t, err)
  5034. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  5035. assert.NoError(t, err)
  5036. err = client.Rename(testFileName, testDir)
  5037. assert.Error(t, err)
  5038. err = client.Remove(testFileName)
  5039. assert.NoError(t, err)
  5040. err = client.Remove(testDir)
  5041. assert.NoError(t, err)
  5042. err = client.Remove(path.Join("/subdir", "file.dat"))
  5043. if assert.Error(t, err) {
  5044. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5045. }
  5046. err = client.Remove(testFileName + ".rename")
  5047. assert.NoError(t, err)
  5048. err = os.Remove(testFilePath)
  5049. assert.NoError(t, err)
  5050. }
  5051. _, err = httpd.RemoveUser(user, http.StatusOK)
  5052. assert.NoError(t, err)
  5053. err = os.RemoveAll(user.GetHomeDir())
  5054. assert.NoError(t, err)
  5055. }
  5056. func TestSubDirsOverwrite(t *testing.T) {
  5057. usePubKey := true
  5058. u := getTestUser(usePubKey)
  5059. u.Permissions["/"] = []string{dataprovider.PermAny}
  5060. u.Permissions["/subdir"] = []string{dataprovider.PermOverwrite, dataprovider.PermListItems}
  5061. user, _, err := httpd.AddUser(u, http.StatusOK)
  5062. assert.NoError(t, err)
  5063. client, err := getSftpClient(user, usePubKey)
  5064. if assert.NoError(t, err) {
  5065. defer client.Close()
  5066. testFileName := "/subdir/test_file.dat" //nolint:goconst
  5067. testFilePath := filepath.Join(homeBasePath, "test_file.dat")
  5068. testFileSFTPPath := filepath.Join(u.GetHomeDir(), "subdir", "test_file.dat")
  5069. testFileSize := int64(65535)
  5070. err = createTestFile(testFilePath, testFileSize)
  5071. assert.NoError(t, err)
  5072. err = createTestFile(testFileSFTPPath, 16384)
  5073. assert.NoError(t, err)
  5074. err = sftpUploadFile(testFilePath, testFileName+".new", testFileSize, client)
  5075. if assert.Error(t, err) {
  5076. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5077. }
  5078. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  5079. assert.NoError(t, err)
  5080. err = os.Remove(testFilePath)
  5081. assert.NoError(t, err)
  5082. }
  5083. _, err = httpd.RemoveUser(user, http.StatusOK)
  5084. assert.NoError(t, err)
  5085. err = os.RemoveAll(user.GetHomeDir())
  5086. assert.NoError(t, err)
  5087. }
  5088. func TestSubDirsDownloads(t *testing.T) {
  5089. usePubKey := true
  5090. u := getTestUser(usePubKey)
  5091. u.Permissions["/"] = []string{dataprovider.PermAny}
  5092. u.Permissions["/subdir"] = []string{dataprovider.PermChmod, dataprovider.PermUpload, dataprovider.PermListItems}
  5093. user, _, err := httpd.AddUser(u, http.StatusOK)
  5094. assert.NoError(t, err)
  5095. client, err := getSftpClient(user, usePubKey)
  5096. if assert.NoError(t, err) {
  5097. defer client.Close()
  5098. err = client.Mkdir("subdir")
  5099. assert.NoError(t, err)
  5100. testFileName := "/subdir/test_file.dat"
  5101. testFilePath := filepath.Join(homeBasePath, "test_file.dat")
  5102. testFileSize := int64(65535)
  5103. err = createTestFile(testFilePath, testFileSize)
  5104. assert.NoError(t, err)
  5105. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  5106. assert.NoError(t, err)
  5107. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  5108. err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize, client)
  5109. if assert.Error(t, err) {
  5110. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5111. }
  5112. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  5113. if assert.Error(t, err) {
  5114. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5115. }
  5116. err = client.Chtimes(testFileName, time.Now(), time.Now())
  5117. if assert.Error(t, err) {
  5118. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5119. }
  5120. err = client.Rename(testFileName, testFileName+".rename")
  5121. if assert.Error(t, err) {
  5122. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5123. }
  5124. err = client.Symlink(testFileName, testFileName+".link")
  5125. if assert.Error(t, err) {
  5126. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5127. }
  5128. err = client.Remove(testFileName)
  5129. if assert.Error(t, err) {
  5130. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5131. }
  5132. err = os.Remove(localDownloadPath)
  5133. assert.NoError(t, err)
  5134. err = os.Remove(testFilePath)
  5135. assert.NoError(t, err)
  5136. }
  5137. _, err = httpd.RemoveUser(user, http.StatusOK)
  5138. assert.NoError(t, err)
  5139. err = os.RemoveAll(user.GetHomeDir())
  5140. assert.NoError(t, err)
  5141. }
  5142. func TestPermsSubDirsSetstat(t *testing.T) {
  5143. // for setstat we check the parent dir permission if the requested path is a dir
  5144. // otherwise the path permission
  5145. usePubKey := true
  5146. u := getTestUser(usePubKey)
  5147. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermCreateDirs}
  5148. u.Permissions["/subdir"] = []string{dataprovider.PermAny}
  5149. user, _, err := httpd.AddUser(u, http.StatusOK)
  5150. assert.NoError(t, err)
  5151. client, err := getSftpClient(user, usePubKey)
  5152. if assert.NoError(t, err) {
  5153. defer client.Close()
  5154. err = client.Mkdir("subdir")
  5155. assert.NoError(t, err)
  5156. testFileName := "/subdir/test_file.dat"
  5157. testFilePath := filepath.Join(homeBasePath, "test_file.dat")
  5158. testFileSize := int64(65535)
  5159. err = createTestFile(testFilePath, testFileSize)
  5160. assert.NoError(t, err)
  5161. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  5162. assert.NoError(t, err)
  5163. err = client.Chtimes("/subdir/", time.Now(), time.Now())
  5164. if assert.Error(t, err) {
  5165. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5166. }
  5167. err = client.Chtimes("subdir/", time.Now(), time.Now())
  5168. if assert.Error(t, err) {
  5169. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5170. }
  5171. err = client.Chtimes(testFileName, time.Now(), time.Now())
  5172. assert.NoError(t, err)
  5173. err = os.Remove(testFilePath)
  5174. assert.NoError(t, err)
  5175. }
  5176. _, err = httpd.RemoveUser(user, http.StatusOK)
  5177. assert.NoError(t, err)
  5178. err = os.RemoveAll(user.GetHomeDir())
  5179. assert.NoError(t, err)
  5180. }
  5181. func TestPermsSubDirsCommands(t *testing.T) {
  5182. usePubKey := true
  5183. u := getTestUser(usePubKey)
  5184. u.Permissions["/"] = []string{dataprovider.PermAny}
  5185. u.Permissions["/subdir"] = []string{dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermCreateDirs}
  5186. u.Permissions["/subdir/otherdir"] = []string{dataprovider.PermListItems, dataprovider.PermDownload}
  5187. user, _, err := httpd.AddUser(u, http.StatusOK)
  5188. assert.NoError(t, err)
  5189. client, err := getSftpClient(user, usePubKey)
  5190. if assert.NoError(t, err) {
  5191. defer client.Close()
  5192. err = client.Mkdir("subdir")
  5193. assert.NoError(t, err)
  5194. acmodTime := time.Now()
  5195. err = client.Chtimes("/subdir", acmodTime, acmodTime)
  5196. assert.NoError(t, err)
  5197. _, err = client.Stat("/subdir")
  5198. assert.NoError(t, err)
  5199. _, err = client.ReadDir("/")
  5200. assert.NoError(t, err)
  5201. _, err = client.ReadDir("/subdir")
  5202. if assert.Error(t, err) {
  5203. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5204. }
  5205. err = client.RemoveDirectory("/subdir/dir")
  5206. if assert.Error(t, err) {
  5207. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5208. }
  5209. err = client.Mkdir("/subdir/otherdir/dir")
  5210. if assert.Error(t, err) {
  5211. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5212. }
  5213. err = client.Mkdir("/otherdir")
  5214. assert.NoError(t, err)
  5215. err = client.Mkdir("/subdir/otherdir")
  5216. assert.NoError(t, err)
  5217. err = client.Rename("/otherdir", "/subdir/otherdir/adir")
  5218. if assert.Error(t, err) {
  5219. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5220. }
  5221. err = client.Symlink("/otherdir", "/subdir/otherdir")
  5222. if assert.Error(t, err) {
  5223. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5224. }
  5225. err = client.Symlink("/otherdir", "/otherdir_link")
  5226. assert.NoError(t, err)
  5227. err = client.Rename("/otherdir", "/otherdir1")
  5228. assert.NoError(t, err)
  5229. err = client.RemoveDirectory("/otherdir1")
  5230. assert.NoError(t, err)
  5231. }
  5232. _, err = httpd.RemoveUser(user, http.StatusOK)
  5233. assert.NoError(t, err)
  5234. err = os.RemoveAll(user.GetHomeDir())
  5235. assert.NoError(t, err)
  5236. }
  5237. func TestRootDirCommands(t *testing.T) {
  5238. usePubKey := true
  5239. u := getTestUser(usePubKey)
  5240. u.Permissions["/"] = []string{dataprovider.PermAny}
  5241. u.Permissions["/subdir"] = []string{dataprovider.PermDownload, dataprovider.PermUpload}
  5242. user, _, err := httpd.AddUser(u, http.StatusOK)
  5243. assert.NoError(t, err)
  5244. client, err := getSftpClient(user, usePubKey)
  5245. if assert.NoError(t, err) {
  5246. defer client.Close()
  5247. err = client.Rename("/", "rootdir")
  5248. if assert.Error(t, err) {
  5249. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5250. }
  5251. err = client.Symlink("/", "rootdir")
  5252. if assert.Error(t, err) {
  5253. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5254. }
  5255. err = client.RemoveDirectory("/")
  5256. if assert.Error(t, err) {
  5257. assert.Contains(t, err.Error(), sftp.ErrSSHFxPermissionDenied.Error())
  5258. }
  5259. }
  5260. _, err = httpd.RemoveUser(user, http.StatusOK)
  5261. assert.NoError(t, err)
  5262. err = os.RemoveAll(user.GetHomeDir())
  5263. assert.NoError(t, err)
  5264. }
  5265. func TestRelativePaths(t *testing.T) {
  5266. user := getTestUser(true)
  5267. var path, rel string
  5268. filesystems := []vfs.Fs{vfs.NewOsFs("", user.GetHomeDir(), user.VirtualFolders)}
  5269. keyPrefix := strings.TrimPrefix(user.GetHomeDir(), "/") + "/"
  5270. s3config := vfs.S3FsConfig{
  5271. KeyPrefix: keyPrefix,
  5272. }
  5273. s3fs, _ := vfs.NewS3Fs("", user.GetHomeDir(), s3config)
  5274. gcsConfig := vfs.GCSFsConfig{
  5275. KeyPrefix: keyPrefix,
  5276. }
  5277. gcsfs, _ := vfs.NewGCSFs("", user.GetHomeDir(), gcsConfig)
  5278. if runtime.GOOS != osWindows {
  5279. filesystems = append(filesystems, s3fs, gcsfs)
  5280. }
  5281. rootPath := "/"
  5282. for _, fs := range filesystems {
  5283. path = filepath.Join(user.HomeDir, "/")
  5284. rel = fs.GetRelativePath(path)
  5285. assert.Equal(t, rootPath, rel)
  5286. path = filepath.Join(user.HomeDir, "//")
  5287. rel = fs.GetRelativePath(path)
  5288. assert.Equal(t, rootPath, rel)
  5289. path = filepath.Join(user.HomeDir, "../..")
  5290. rel = fs.GetRelativePath(path)
  5291. assert.Equal(t, rootPath, rel)
  5292. path = filepath.Join(user.HomeDir, "../../../../../")
  5293. rel = fs.GetRelativePath(path)
  5294. assert.Equal(t, rootPath, rel)
  5295. path = filepath.Join(user.HomeDir, "/..")
  5296. rel = fs.GetRelativePath(path)
  5297. assert.Equal(t, rootPath, rel)
  5298. path = filepath.Join(user.HomeDir, "/../../../..")
  5299. rel = fs.GetRelativePath(path)
  5300. assert.Equal(t, rootPath, rel)
  5301. path = filepath.Join(user.HomeDir, "")
  5302. rel = fs.GetRelativePath(path)
  5303. assert.Equal(t, rootPath, rel)
  5304. path = filepath.Join(user.HomeDir, ".")
  5305. rel = fs.GetRelativePath(path)
  5306. assert.Equal(t, rootPath, rel)
  5307. path = filepath.Join(user.HomeDir, "somedir")
  5308. rel = fs.GetRelativePath(path)
  5309. assert.Equal(t, "/somedir", rel)
  5310. path = filepath.Join(user.HomeDir, "/somedir/subdir")
  5311. rel = fs.GetRelativePath(path)
  5312. assert.Equal(t, "/somedir/subdir", rel)
  5313. }
  5314. }
  5315. func TestResolvePaths(t *testing.T) {
  5316. user := getTestUser(true)
  5317. var path, resolved string
  5318. var err error
  5319. filesystems := []vfs.Fs{vfs.NewOsFs("", user.GetHomeDir(), user.VirtualFolders)}
  5320. keyPrefix := strings.TrimPrefix(user.GetHomeDir(), "/") + "/"
  5321. s3config := vfs.S3FsConfig{
  5322. KeyPrefix: keyPrefix,
  5323. Bucket: "bucket",
  5324. Region: "us-east-1",
  5325. }
  5326. err = os.MkdirAll(user.GetHomeDir(), os.ModePerm)
  5327. assert.NoError(t, err)
  5328. s3fs, err := vfs.NewS3Fs("", user.GetHomeDir(), s3config)
  5329. assert.NoError(t, err)
  5330. gcsConfig := vfs.GCSFsConfig{
  5331. KeyPrefix: keyPrefix,
  5332. }
  5333. gcsfs, _ := vfs.NewGCSFs("", user.GetHomeDir(), gcsConfig)
  5334. if runtime.GOOS != osWindows {
  5335. filesystems = append(filesystems, s3fs, gcsfs)
  5336. }
  5337. for _, fs := range filesystems {
  5338. path = "/"
  5339. resolved, _ = fs.ResolvePath(filepath.ToSlash(path))
  5340. assert.Equal(t, fs.Join(user.GetHomeDir(), "/"), resolved)
  5341. path = "."
  5342. resolved, _ = fs.ResolvePath(filepath.ToSlash(path))
  5343. assert.Equal(t, fs.Join(user.GetHomeDir(), "/"), resolved)
  5344. path = "test/sub"
  5345. resolved, _ = fs.ResolvePath(filepath.ToSlash(path))
  5346. assert.Equal(t, fs.Join(user.GetHomeDir(), "/test/sub"), resolved)
  5347. path = "../test/sub"
  5348. resolved, err = fs.ResolvePath(filepath.ToSlash(path))
  5349. if vfs.IsLocalOsFs(fs) {
  5350. assert.Error(t, err, "Unexpected resolved path: %v for: %v, fs: %v", resolved, path, fs.Name())
  5351. } else {
  5352. assert.Equal(t, fs.Join(user.GetHomeDir(), "/test/sub"), resolved)
  5353. }
  5354. path = "../../../test/../sub"
  5355. resolved, err = fs.ResolvePath(filepath.ToSlash(path))
  5356. if vfs.IsLocalOsFs(fs) {
  5357. assert.Error(t, err, "Unexpected resolved path: %v for: %v, fs: %v", resolved, path, fs.Name())
  5358. } else {
  5359. assert.Equal(t, fs.Join(user.GetHomeDir(), "/sub"), resolved)
  5360. }
  5361. }
  5362. err = os.RemoveAll(user.GetHomeDir())
  5363. assert.NoError(t, err)
  5364. }
  5365. func TestVirtualRelativePaths(t *testing.T) {
  5366. user := getTestUser(true)
  5367. mappedPath := filepath.Join(os.TempDir(), "vdir")
  5368. vdirPath := "/vdir" //nolint:goconst
  5369. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  5370. BaseVirtualFolder: vfs.BaseVirtualFolder{
  5371. MappedPath: mappedPath,
  5372. },
  5373. VirtualPath: vdirPath,
  5374. })
  5375. err := os.MkdirAll(mappedPath, os.ModePerm)
  5376. assert.NoError(t, err)
  5377. fs := vfs.NewOsFs("", user.GetHomeDir(), user.VirtualFolders)
  5378. rel := fs.GetRelativePath(mappedPath)
  5379. assert.Equal(t, vdirPath, rel)
  5380. rel = fs.GetRelativePath(filepath.Join(mappedPath, ".."))
  5381. assert.Equal(t, "/", rel)
  5382. // path outside home and virtual dir
  5383. rel = fs.GetRelativePath(filepath.Join(mappedPath, "../vdir1"))
  5384. assert.Equal(t, "/", rel)
  5385. rel = fs.GetRelativePath(filepath.Join(mappedPath, "../vdir/file.txt"))
  5386. assert.Equal(t, "/vdir/file.txt", rel)
  5387. rel = fs.GetRelativePath(filepath.Join(user.HomeDir, "vdir1/file.txt"))
  5388. assert.Equal(t, "/vdir1/file.txt", rel)
  5389. }
  5390. func TestResolveVirtualPaths(t *testing.T) {
  5391. user := getTestUser(true)
  5392. mappedPath := filepath.Join(os.TempDir(), "vdir")
  5393. vdirPath := "/vdir"
  5394. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  5395. BaseVirtualFolder: vfs.BaseVirtualFolder{
  5396. MappedPath: mappedPath,
  5397. },
  5398. VirtualPath: vdirPath,
  5399. })
  5400. err := os.MkdirAll(mappedPath, os.ModePerm)
  5401. assert.NoError(t, err)
  5402. osFs := vfs.NewOsFs("", user.GetHomeDir(), user.VirtualFolders).(vfs.OsFs)
  5403. b, f := osFs.GetFsPaths("/vdir/a.txt")
  5404. assert.Equal(t, mappedPath, b)
  5405. assert.Equal(t, filepath.Join(mappedPath, "a.txt"), f)
  5406. b, f = osFs.GetFsPaths("/vdir/sub with space & spécial chars/a.txt")
  5407. assert.Equal(t, mappedPath, b)
  5408. assert.Equal(t, filepath.Join(mappedPath, "sub with space & spécial chars/a.txt"), f)
  5409. b, f = osFs.GetFsPaths("/vdir/../a.txt")
  5410. assert.Equal(t, user.GetHomeDir(), b)
  5411. assert.Equal(t, filepath.Join(user.GetHomeDir(), "a.txt"), f)
  5412. b, f = osFs.GetFsPaths("/vdir1/a.txt")
  5413. assert.Equal(t, user.GetHomeDir(), b)
  5414. assert.Equal(t, filepath.Join(user.GetHomeDir(), "/vdir1/a.txt"), f)
  5415. }
  5416. func TestUserPerms(t *testing.T) {
  5417. user := getTestUser(true)
  5418. user.Permissions = make(map[string][]string)
  5419. user.Permissions["/"] = []string{dataprovider.PermListItems}
  5420. user.Permissions["/p"] = []string{dataprovider.PermDelete}
  5421. user.Permissions["/p/1"] = []string{dataprovider.PermDownload, dataprovider.PermUpload}
  5422. user.Permissions["/p/2"] = []string{dataprovider.PermCreateDirs}
  5423. user.Permissions["/p/3"] = []string{dataprovider.PermChmod}
  5424. user.Permissions["/p/3/4"] = []string{dataprovider.PermChtimes}
  5425. user.Permissions["/tmp"] = []string{dataprovider.PermRename}
  5426. assert.True(t, user.HasPerm(dataprovider.PermListItems, "/"))
  5427. assert.True(t, user.HasPerm(dataprovider.PermListItems, "."))
  5428. assert.True(t, user.HasPerm(dataprovider.PermListItems, ""))
  5429. assert.True(t, user.HasPerm(dataprovider.PermListItems, "../"))
  5430. // path p and /p are the same
  5431. assert.True(t, user.HasPerm(dataprovider.PermDelete, "/p"))
  5432. assert.True(t, user.HasPerm(dataprovider.PermDownload, "/p/1"))
  5433. assert.True(t, user.HasPerm(dataprovider.PermCreateDirs, "p/2"))
  5434. assert.True(t, user.HasPerm(dataprovider.PermChmod, "/p/3"))
  5435. assert.True(t, user.HasPerm(dataprovider.PermChtimes, "p/3/4/"))
  5436. assert.True(t, user.HasPerm(dataprovider.PermChtimes, "p/3/4/../4"))
  5437. // undefined paths have permissions of the nearest path
  5438. assert.True(t, user.HasPerm(dataprovider.PermListItems, "/p34"))
  5439. assert.True(t, user.HasPerm(dataprovider.PermListItems, "/p34/p1/file.dat"))
  5440. assert.True(t, user.HasPerm(dataprovider.PermChtimes, "/p/3/4/5/6"))
  5441. assert.True(t, user.HasPerm(dataprovider.PermDownload, "/p/1/test/file.dat"))
  5442. }
  5443. func TestFilterFileExtensions(t *testing.T) {
  5444. user := getTestUser(true)
  5445. extension := dataprovider.ExtensionsFilter{
  5446. Path: "/test",
  5447. AllowedExtensions: []string{".jpg", ".png"},
  5448. DeniedExtensions: []string{".pdf"},
  5449. }
  5450. filters := dataprovider.UserFilters{
  5451. FileExtensions: []dataprovider.ExtensionsFilter{extension},
  5452. }
  5453. user.Filters = filters
  5454. assert.True(t, user.IsFileAllowed("/test/test.jPg"))
  5455. assert.False(t, user.IsFileAllowed("/test/test.pdf"))
  5456. assert.True(t, user.IsFileAllowed("/test.pDf"))
  5457. filters.FileExtensions = append(filters.FileExtensions, dataprovider.ExtensionsFilter{
  5458. Path: "/",
  5459. AllowedExtensions: []string{".zip", ".rar", ".pdf"},
  5460. DeniedExtensions: []string{".gz"},
  5461. })
  5462. user.Filters = filters
  5463. assert.False(t, user.IsFileAllowed("/test1/test.gz"))
  5464. assert.True(t, user.IsFileAllowed("/test1/test.zip"))
  5465. assert.False(t, user.IsFileAllowed("/test/sub/test.pdf"))
  5466. assert.False(t, user.IsFileAllowed("/test1/test.png"))
  5467. filters.FileExtensions = append(filters.FileExtensions, dataprovider.ExtensionsFilter{
  5468. Path: "/test/sub",
  5469. DeniedExtensions: []string{".tar"},
  5470. })
  5471. user.Filters = filters
  5472. assert.False(t, user.IsFileAllowed("/test/sub/sub/test.tar"))
  5473. assert.True(t, user.IsFileAllowed("/test/sub/test.gz"))
  5474. assert.False(t, user.IsFileAllowed("/test/test.zip"))
  5475. }
  5476. func TestUserAllowedLoginMethods(t *testing.T) {
  5477. user := getTestUser(true)
  5478. user.Filters.DeniedLoginMethods = dataprovider.ValidSSHLoginMethods
  5479. allowedMethods := user.GetAllowedLoginMethods()
  5480. assert.Equal(t, 0, len(allowedMethods))
  5481. user.Filters.DeniedLoginMethods = []string{
  5482. dataprovider.LoginMethodPassword,
  5483. dataprovider.SSHLoginMethodPublicKey,
  5484. dataprovider.SSHLoginMethodKeyboardInteractive,
  5485. }
  5486. allowedMethods = user.GetAllowedLoginMethods()
  5487. assert.Equal(t, 2, len(allowedMethods))
  5488. assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodKeyAndKeyboardInt, allowedMethods))
  5489. assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodKeyAndPassword, allowedMethods))
  5490. }
  5491. func TestUserPartialAuth(t *testing.T) {
  5492. user := getTestUser(true)
  5493. user.Filters.DeniedLoginMethods = []string{
  5494. dataprovider.LoginMethodPassword,
  5495. dataprovider.SSHLoginMethodPublicKey,
  5496. dataprovider.SSHLoginMethodKeyboardInteractive,
  5497. }
  5498. assert.False(t, user.IsPartialAuth(dataprovider.LoginMethodPassword))
  5499. assert.False(t, user.IsPartialAuth(dataprovider.SSHLoginMethodKeyboardInteractive))
  5500. assert.True(t, user.IsPartialAuth(dataprovider.SSHLoginMethodPublicKey))
  5501. user.Filters.DeniedLoginMethods = []string{
  5502. dataprovider.LoginMethodPassword,
  5503. dataprovider.SSHLoginMethodKeyboardInteractive,
  5504. }
  5505. assert.False(t, user.IsPartialAuth(dataprovider.SSHLoginMethodPublicKey))
  5506. user.Filters.DeniedLoginMethods = []string{
  5507. dataprovider.LoginMethodPassword,
  5508. dataprovider.SSHLoginMethodPublicKey,
  5509. }
  5510. assert.False(t, user.IsPartialAuth(dataprovider.SSHLoginMethodPublicKey))
  5511. }
  5512. func TestUserGetNextAuthMethods(t *testing.T) {
  5513. user := getTestUser(true)
  5514. user.Filters.DeniedLoginMethods = []string{
  5515. dataprovider.LoginMethodPassword,
  5516. dataprovider.SSHLoginMethodPublicKey,
  5517. dataprovider.SSHLoginMethodKeyboardInteractive,
  5518. }
  5519. methods := user.GetNextAuthMethods(nil, true)
  5520. assert.Equal(t, 0, len(methods))
  5521. methods = user.GetNextAuthMethods([]string{dataprovider.LoginMethodPassword}, true)
  5522. assert.Equal(t, 0, len(methods))
  5523. methods = user.GetNextAuthMethods([]string{dataprovider.SSHLoginMethodKeyboardInteractive}, true)
  5524. assert.Equal(t, 0, len(methods))
  5525. methods = user.GetNextAuthMethods([]string{
  5526. dataprovider.SSHLoginMethodPublicKey,
  5527. dataprovider.SSHLoginMethodKeyboardInteractive,
  5528. }, true)
  5529. assert.Equal(t, 0, len(methods))
  5530. methods = user.GetNextAuthMethods([]string{dataprovider.SSHLoginMethodPublicKey}, true)
  5531. assert.Equal(t, 2, len(methods))
  5532. assert.True(t, utils.IsStringInSlice(dataprovider.LoginMethodPassword, methods))
  5533. assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodKeyboardInteractive, methods))
  5534. methods = user.GetNextAuthMethods([]string{dataprovider.SSHLoginMethodPublicKey}, false)
  5535. assert.Equal(t, 1, len(methods))
  5536. assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodKeyboardInteractive, methods))
  5537. user.Filters.DeniedLoginMethods = []string{
  5538. dataprovider.LoginMethodPassword,
  5539. dataprovider.SSHLoginMethodPublicKey,
  5540. dataprovider.SSHLoginMethodKeyboardInteractive,
  5541. dataprovider.SSHLoginMethodKeyAndKeyboardInt,
  5542. }
  5543. methods = user.GetNextAuthMethods([]string{dataprovider.SSHLoginMethodPublicKey}, true)
  5544. assert.Equal(t, 1, len(methods))
  5545. assert.True(t, utils.IsStringInSlice(dataprovider.LoginMethodPassword, methods))
  5546. user.Filters.DeniedLoginMethods = []string{
  5547. dataprovider.LoginMethodPassword,
  5548. dataprovider.SSHLoginMethodPublicKey,
  5549. dataprovider.SSHLoginMethodKeyboardInteractive,
  5550. dataprovider.SSHLoginMethodKeyAndPassword,
  5551. }
  5552. methods = user.GetNextAuthMethods([]string{dataprovider.SSHLoginMethodPublicKey}, true)
  5553. assert.Equal(t, 1, len(methods))
  5554. assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodKeyboardInteractive, methods))
  5555. }
  5556. func TestUserIsLoginMethodAllowed(t *testing.T) {
  5557. user := getTestUser(true)
  5558. user.Filters.DeniedLoginMethods = []string{
  5559. dataprovider.LoginMethodPassword,
  5560. dataprovider.SSHLoginMethodPublicKey,
  5561. dataprovider.SSHLoginMethodKeyboardInteractive,
  5562. }
  5563. assert.False(t, user.IsLoginMethodAllowed(dataprovider.LoginMethodPassword, nil))
  5564. assert.False(t, user.IsLoginMethodAllowed(dataprovider.SSHLoginMethodPublicKey, nil))
  5565. assert.False(t, user.IsLoginMethodAllowed(dataprovider.SSHLoginMethodKeyboardInteractive, nil))
  5566. assert.True(t, user.IsLoginMethodAllowed(dataprovider.LoginMethodPassword, []string{dataprovider.SSHLoginMethodPublicKey}))
  5567. assert.True(t, user.IsLoginMethodAllowed(dataprovider.SSHLoginMethodKeyboardInteractive, []string{dataprovider.SSHLoginMethodPublicKey}))
  5568. assert.True(t, user.IsLoginMethodAllowed(dataprovider.SSHLoginMethodKeyAndPassword, []string{dataprovider.SSHLoginMethodPublicKey}))
  5569. user.Filters.DeniedLoginMethods = []string{
  5570. dataprovider.SSHLoginMethodPublicKey,
  5571. dataprovider.SSHLoginMethodKeyboardInteractive,
  5572. }
  5573. assert.True(t, user.IsLoginMethodAllowed(dataprovider.LoginMethodPassword, nil))
  5574. }
  5575. func TestUserEmptySubDirPerms(t *testing.T) {
  5576. user := getTestUser(true)
  5577. user.Permissions = make(map[string][]string)
  5578. user.Permissions["/emptyperms"] = []string{}
  5579. for _, p := range dataprovider.ValidPerms {
  5580. assert.False(t, user.HasPerm(p, "/emptyperms"))
  5581. }
  5582. }
  5583. func TestUserFiltersIPMaskConditions(t *testing.T) {
  5584. user := getTestUser(true)
  5585. // with no filter login must be allowed even if the remoteIP is invalid
  5586. assert.True(t, user.IsLoginFromAddrAllowed("192.168.1.5"))
  5587. assert.True(t, user.IsLoginFromAddrAllowed("invalid"))
  5588. user.Filters.DeniedIP = append(user.Filters.DeniedIP, "192.168.1.0/24")
  5589. assert.False(t, user.IsLoginFromAddrAllowed("192.168.1.5"))
  5590. assert.True(t, user.IsLoginFromAddrAllowed("192.168.2.6"))
  5591. user.Filters.AllowedIP = append(user.Filters.AllowedIP, "192.168.1.5/32")
  5592. // if the same ip/mask is both denied and allowed then login must be denied
  5593. assert.False(t, user.IsLoginFromAddrAllowed("192.168.1.5"))
  5594. assert.False(t, user.IsLoginFromAddrAllowed("192.168.3.6"))
  5595. user.Filters.DeniedIP = []string{}
  5596. assert.True(t, user.IsLoginFromAddrAllowed("192.168.1.5"))
  5597. assert.False(t, user.IsLoginFromAddrAllowed("192.168.1.6"))
  5598. user.Filters.DeniedIP = []string{"192.168.0.0/16", "172.16.0.0/16"}
  5599. user.Filters.AllowedIP = []string{}
  5600. assert.False(t, user.IsLoginFromAddrAllowed("192.168.5.255"))
  5601. assert.False(t, user.IsLoginFromAddrAllowed("172.16.1.2"))
  5602. assert.True(t, user.IsLoginFromAddrAllowed("172.18.2.1"))
  5603. user.Filters.AllowedIP = []string{"10.4.4.0/24"}
  5604. assert.False(t, user.IsLoginFromAddrAllowed("10.5.4.2"))
  5605. assert.True(t, user.IsLoginFromAddrAllowed("10.4.4.2"))
  5606. assert.True(t, user.IsLoginFromAddrAllowed("invalid"))
  5607. }
  5608. func TestGetVirtualFolderForPath(t *testing.T) {
  5609. user := getTestUser(true)
  5610. mappedPath1 := filepath.Join(os.TempDir(), "vpath1")
  5611. mappedPath2 := filepath.Join(os.TempDir(), "vpath1")
  5612. mappedPath3 := filepath.Join(os.TempDir(), "vpath3")
  5613. vdirPath := "/vdir/sub"
  5614. vSubDirPath := path.Join(vdirPath, "subdir", "subdir")
  5615. vSubDir1Path := path.Join(vSubDirPath, "subdir", "subdir")
  5616. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  5617. BaseVirtualFolder: vfs.BaseVirtualFolder{
  5618. MappedPath: mappedPath1,
  5619. },
  5620. VirtualPath: vdirPath,
  5621. })
  5622. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  5623. BaseVirtualFolder: vfs.BaseVirtualFolder{
  5624. MappedPath: mappedPath2,
  5625. },
  5626. VirtualPath: vSubDir1Path,
  5627. })
  5628. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  5629. BaseVirtualFolder: vfs.BaseVirtualFolder{
  5630. MappedPath: mappedPath3,
  5631. },
  5632. VirtualPath: vSubDirPath,
  5633. })
  5634. folder, err := user.GetVirtualFolderForPath(path.Join(vSubDirPath, "file"))
  5635. assert.NoError(t, err)
  5636. assert.Equal(t, folder.MappedPath, mappedPath3)
  5637. _, err = user.GetVirtualFolderForPath("/file")
  5638. assert.Error(t, err)
  5639. folder, err = user.GetVirtualFolderForPath(path.Join(vdirPath, "/file"))
  5640. assert.NoError(t, err)
  5641. assert.Equal(t, folder.MappedPath, mappedPath1)
  5642. folder, err = user.GetVirtualFolderForPath(path.Join(vSubDirPath+"1", "file"))
  5643. assert.NoError(t, err)
  5644. assert.Equal(t, folder.MappedPath, mappedPath1)
  5645. _, err = user.GetVirtualFolderForPath("/vdir/sub1/file")
  5646. assert.Error(t, err)
  5647. folder, err = user.GetVirtualFolderForPath(vdirPath)
  5648. assert.NoError(t, err)
  5649. }
  5650. func TestSSHCommands(t *testing.T) {
  5651. usePubKey := false
  5652. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  5653. assert.NoError(t, err)
  5654. _, err = runSSHCommand("ls", user, usePubKey)
  5655. assert.Error(t, err, "unsupported ssh command must fail")
  5656. _, err = runSSHCommand("cd", user, usePubKey)
  5657. assert.NoError(t, err)
  5658. out, err := runSSHCommand("pwd", user, usePubKey)
  5659. if assert.NoError(t, err) {
  5660. assert.Equal(t, "/\n", string(out))
  5661. }
  5662. out, err = runSSHCommand("md5sum", user, usePubKey)
  5663. assert.NoError(t, err)
  5664. // echo -n '' | md5sum
  5665. assert.Contains(t, string(out), "d41d8cd98f00b204e9800998ecf8427e")
  5666. out, err = runSSHCommand("sha1sum", user, usePubKey)
  5667. assert.NoError(t, err)
  5668. assert.Contains(t, string(out), "da39a3ee5e6b4b0d3255bfef95601890afd80709")
  5669. out, err = runSSHCommand("sha256sum", user, usePubKey)
  5670. assert.NoError(t, err)
  5671. assert.Contains(t, string(out), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
  5672. out, err = runSSHCommand("sha384sum", user, usePubKey)
  5673. assert.NoError(t, err)
  5674. assert.Contains(t, string(out), "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b")
  5675. _, err = httpd.RemoveUser(user, http.StatusOK)
  5676. assert.NoError(t, err)
  5677. }
  5678. func TestSSHFileHash(t *testing.T) {
  5679. usePubKey := true
  5680. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  5681. assert.NoError(t, err)
  5682. client, err := getSftpClient(user, usePubKey)
  5683. if assert.NoError(t, err) {
  5684. defer client.Close()
  5685. testFilePath := filepath.Join(homeBasePath, testFileName)
  5686. testFileSize := int64(65535)
  5687. err = createTestFile(testFilePath, testFileSize)
  5688. assert.NoError(t, err)
  5689. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  5690. assert.NoError(t, err)
  5691. user.Permissions = make(map[string][]string)
  5692. user.Permissions["/"] = []string{dataprovider.PermUpload}
  5693. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  5694. assert.NoError(t, err)
  5695. _, err = runSSHCommand("sha512sum "+testFileName, user, usePubKey)
  5696. assert.Error(t, err, "hash command with no list permission must fail")
  5697. user.Permissions["/"] = []string{dataprovider.PermAny}
  5698. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  5699. assert.NoError(t, err)
  5700. initialHash, err := computeHashForFile(sha512.New(), testFilePath)
  5701. assert.NoError(t, err)
  5702. out, err := runSSHCommand("sha512sum "+testFileName, user, usePubKey)
  5703. if assert.NoError(t, err) {
  5704. assert.Contains(t, string(out), initialHash)
  5705. }
  5706. _, err = runSSHCommand("sha512sum invalid_path", user, usePubKey)
  5707. assert.Error(t, err, "hash for an invalid path must fail")
  5708. err = os.Remove(testFilePath)
  5709. assert.NoError(t, err)
  5710. }
  5711. _, err = httpd.RemoveUser(user, http.StatusOK)
  5712. assert.NoError(t, err)
  5713. err = os.RemoveAll(user.GetHomeDir())
  5714. assert.NoError(t, err)
  5715. }
  5716. func TestSSHCopy(t *testing.T) {
  5717. usePubKey := true
  5718. u := getTestUser(usePubKey)
  5719. u.QuotaFiles = 100
  5720. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  5721. vdirPath1 := "/vdir1/subdir"
  5722. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  5723. vdirPath2 := "/vdir2/subdir"
  5724. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  5725. BaseVirtualFolder: vfs.BaseVirtualFolder{
  5726. MappedPath: mappedPath1,
  5727. },
  5728. VirtualPath: vdirPath1,
  5729. QuotaFiles: -1,
  5730. QuotaSize: -1,
  5731. })
  5732. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  5733. BaseVirtualFolder: vfs.BaseVirtualFolder{
  5734. MappedPath: mappedPath2,
  5735. },
  5736. VirtualPath: vdirPath2,
  5737. QuotaFiles: 100,
  5738. QuotaSize: 0,
  5739. })
  5740. u.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  5741. {
  5742. Path: "/",
  5743. DeniedExtensions: []string{".denied"},
  5744. },
  5745. }
  5746. err := os.MkdirAll(mappedPath1, os.ModePerm)
  5747. assert.NoError(t, err)
  5748. err = os.MkdirAll(mappedPath2, os.ModePerm)
  5749. assert.NoError(t, err)
  5750. user, _, err := httpd.AddUser(u, http.StatusOK)
  5751. assert.NoError(t, err)
  5752. testDir := "adir"
  5753. testDir1 := "adir1"
  5754. client, err := getSftpClient(user, usePubKey)
  5755. if assert.NoError(t, err) {
  5756. defer client.Close()
  5757. testFileSize := int64(131072)
  5758. testFilePath := filepath.Join(homeBasePath, testFileName)
  5759. testFileName1 := "test_file1.dat"
  5760. testFileSize1 := int64(65537)
  5761. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  5762. err = createTestFile(testFilePath, testFileSize)
  5763. assert.NoError(t, err)
  5764. err = createTestFile(testFilePath1, testFileSize1)
  5765. assert.NoError(t, err)
  5766. err = client.Mkdir(testDir)
  5767. assert.NoError(t, err)
  5768. err = client.Mkdir(path.Join(vdirPath1, testDir1))
  5769. assert.NoError(t, err)
  5770. err = client.Mkdir(path.Join(vdirPath2, testDir1))
  5771. assert.NoError(t, err)
  5772. err = sftpUploadFile(testFilePath, path.Join(testDir, testFileName), testFileSize, client)
  5773. assert.NoError(t, err)
  5774. err = sftpUploadFile(testFilePath1, path.Join(testDir, testFileName1), testFileSize1, client)
  5775. assert.NoError(t, err)
  5776. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, testDir1, testFileName), testFileSize, client)
  5777. assert.NoError(t, err)
  5778. err = sftpUploadFile(testFilePath1, path.Join(vdirPath1, testDir1, testFileName1), testFileSize1, client)
  5779. assert.NoError(t, err)
  5780. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testDir1, testFileName), testFileSize, client)
  5781. assert.NoError(t, err)
  5782. err = sftpUploadFile(testFilePath1, path.Join(vdirPath2, testDir1, testFileName1), testFileSize1, client)
  5783. assert.NoError(t, err)
  5784. err = client.Symlink(path.Join(testDir, testFileName), testFileName)
  5785. assert.NoError(t, err)
  5786. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  5787. assert.NoError(t, err)
  5788. assert.Equal(t, 4, user.UsedQuotaFiles)
  5789. assert.Equal(t, 2*testFileSize+2*testFileSize1, user.UsedQuotaSize)
  5790. folder, _, err := httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  5791. assert.NoError(t, err)
  5792. if assert.Len(t, folder, 1) {
  5793. f := folder[0]
  5794. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  5795. assert.Equal(t, 2, f.UsedQuotaFiles)
  5796. }
  5797. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  5798. assert.NoError(t, err)
  5799. if assert.Len(t, folder, 1) {
  5800. f := folder[0]
  5801. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  5802. assert.Equal(t, 2, f.UsedQuotaFiles)
  5803. }
  5804. _, err = client.Stat(testDir1)
  5805. assert.Error(t, err)
  5806. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v", path.Join(vdirPath1, testDir1)), user, usePubKey)
  5807. assert.Error(t, err)
  5808. _, err = runSSHCommand("sftpgo-copy", user, usePubKey)
  5809. assert.Error(t, err)
  5810. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", testFileName, testFileName+".linkcopy"), user, usePubKey)
  5811. assert.Error(t, err)
  5812. out, err := runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join(vdirPath1, testDir1), "."), user, usePubKey)
  5813. if assert.NoError(t, err) {
  5814. assert.Equal(t, "OK\n", string(out))
  5815. fi, err := client.Stat(testDir1)
  5816. if assert.NoError(t, err) {
  5817. assert.True(t, fi.IsDir())
  5818. }
  5819. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  5820. assert.NoError(t, err)
  5821. assert.Equal(t, 6, user.UsedQuotaFiles)
  5822. assert.Equal(t, 3*testFileSize+3*testFileSize1, user.UsedQuotaSize)
  5823. }
  5824. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", "missing\\ dir", "."), user, usePubKey)
  5825. assert.Error(t, err)
  5826. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join(vdirPath1, testDir1), "."), user, usePubKey)
  5827. assert.Error(t, err)
  5828. out, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join(vdirPath2, testDir1, testFileName), testFileName+".copy"),
  5829. user, usePubKey)
  5830. if assert.NoError(t, err) {
  5831. assert.Equal(t, "OK\n", string(out))
  5832. fi, err := client.Stat(testFileName + ".copy")
  5833. if assert.NoError(t, err) {
  5834. assert.True(t, fi.Mode().IsRegular())
  5835. }
  5836. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  5837. assert.NoError(t, err)
  5838. assert.Equal(t, 7, user.UsedQuotaFiles)
  5839. assert.Equal(t, 4*testFileSize+3*testFileSize1, user.UsedQuotaSize)
  5840. }
  5841. out, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join(vdirPath1, testDir1), path.Join(vdirPath2, testDir1+"copy")),
  5842. user, usePubKey)
  5843. if assert.NoError(t, err) {
  5844. assert.Equal(t, "OK\n", string(out))
  5845. fi, err := client.Stat(path.Join(vdirPath2, testDir1+"copy"))
  5846. if assert.NoError(t, err) {
  5847. assert.True(t, fi.IsDir())
  5848. }
  5849. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  5850. assert.NoError(t, err)
  5851. assert.Equal(t, 7, user.UsedQuotaFiles)
  5852. assert.Equal(t, 4*testFileSize+3*testFileSize1, user.UsedQuotaSize)
  5853. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  5854. assert.NoError(t, err)
  5855. if assert.Len(t, folder, 1) {
  5856. f := folder[0]
  5857. assert.Equal(t, testFileSize*2+testFileSize1*2, f.UsedQuotaSize)
  5858. assert.Equal(t, 4, f.UsedQuotaFiles)
  5859. }
  5860. }
  5861. out, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join(vdirPath1, testDir1), path.Join(vdirPath1, testDir1+"copy")),
  5862. user, usePubKey)
  5863. if assert.NoError(t, err) {
  5864. assert.Equal(t, "OK\n", string(out))
  5865. _, err := client.Stat(path.Join(vdirPath2, testDir1+"copy"))
  5866. assert.NoError(t, err)
  5867. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  5868. assert.NoError(t, err)
  5869. assert.Equal(t, 9, user.UsedQuotaFiles)
  5870. assert.Equal(t, 5*testFileSize+4*testFileSize1, user.UsedQuotaSize)
  5871. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  5872. assert.NoError(t, err)
  5873. if assert.Len(t, folder, 1) {
  5874. f := folder[0]
  5875. assert.Equal(t, 2*testFileSize+2*testFileSize1, f.UsedQuotaSize)
  5876. assert.Equal(t, 4, f.UsedQuotaFiles)
  5877. }
  5878. }
  5879. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join(vdirPath2, ".."), "newdir"), user, usePubKey)
  5880. assert.Error(t, err)
  5881. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join(testDir, testFileName), testFileName+".denied"), user, usePubKey)
  5882. assert.Error(t, err)
  5883. if runtime.GOOS != osWindows {
  5884. subPath := filepath.Join(mappedPath1, testDir1, "asubdir", "anothersub", "another")
  5885. err = os.MkdirAll(subPath, os.ModePerm)
  5886. assert.NoError(t, err)
  5887. err = os.Chmod(subPath, 0001)
  5888. assert.NoError(t, err)
  5889. // c.connection.fs.GetDirSize(fsSourcePath) will fail scanning subdirs
  5890. // checkRecursiveCopyPermissions will work since it will skip subdirs with no permissions
  5891. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", vdirPath1, "newdir"), user, usePubKey)
  5892. assert.Error(t, err)
  5893. err = os.Chmod(subPath, os.ModePerm)
  5894. assert.NoError(t, err)
  5895. err = os.Chmod(filepath.Join(user.GetHomeDir(), testDir1), 0555)
  5896. assert.NoError(t, err)
  5897. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join(vdirPath1, testDir1, testFileName),
  5898. path.Join(testDir1, "anewdir")), user, usePubKey)
  5899. assert.Error(t, err)
  5900. err = os.Chmod(filepath.Join(user.GetHomeDir(), testDir1), os.ModePerm)
  5901. assert.NoError(t, err)
  5902. err = os.RemoveAll(filepath.Join(user.GetHomeDir(), "vdir1"))
  5903. assert.NoError(t, err)
  5904. err = os.Chmod(user.GetHomeDir(), 0555)
  5905. assert.NoError(t, err)
  5906. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join(vdirPath2), "/vdir1"), user, usePubKey)
  5907. assert.Error(t, err)
  5908. err = os.Chmod(user.GetHomeDir(), os.ModePerm)
  5909. assert.NoError(t, err)
  5910. }
  5911. err = os.Remove(testFilePath)
  5912. assert.NoError(t, err)
  5913. err = os.Remove(testFilePath1)
  5914. assert.NoError(t, err)
  5915. }
  5916. _, err = httpd.RemoveUser(user, http.StatusOK)
  5917. assert.NoError(t, err)
  5918. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  5919. assert.NoError(t, err)
  5920. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  5921. assert.NoError(t, err)
  5922. err = os.RemoveAll(user.GetHomeDir())
  5923. assert.NoError(t, err)
  5924. err = os.RemoveAll(mappedPath1)
  5925. assert.NoError(t, err)
  5926. err = os.RemoveAll(mappedPath2)
  5927. assert.NoError(t, err)
  5928. }
  5929. func TestSSHCopyPermissions(t *testing.T) {
  5930. usePubKey := false
  5931. u := getTestUser(usePubKey)
  5932. u.Permissions["/dir1"] = []string{dataprovider.PermUpload, dataprovider.PermDownload, dataprovider.PermListItems}
  5933. u.Permissions["/dir2"] = []string{dataprovider.PermCreateDirs, dataprovider.PermUpload, dataprovider.PermDownload,
  5934. dataprovider.PermListItems}
  5935. u.Permissions["/dir3"] = []string{dataprovider.PermCreateDirs, dataprovider.PermCreateSymlinks, dataprovider.PermDownload,
  5936. dataprovider.PermListItems}
  5937. user, _, err := httpd.AddUser(u, http.StatusOK)
  5938. assert.NoError(t, err)
  5939. client, err := getSftpClient(user, usePubKey)
  5940. if assert.NoError(t, err) {
  5941. defer client.Close()
  5942. testDir := "tDir"
  5943. testFileSize := int64(131072)
  5944. testFilePath := filepath.Join(homeBasePath, testFileName)
  5945. err = createTestFile(testFilePath, testFileSize)
  5946. assert.NoError(t, err)
  5947. err = client.Mkdir(testDir)
  5948. assert.NoError(t, err)
  5949. err = sftpUploadFile(testFilePath, path.Join("/", testDir, testFileName), testFileSize, client)
  5950. assert.NoError(t, err)
  5951. // test copy file with no permission
  5952. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join("/", testDir, testFileName), path.Join("/dir3", testFileName)),
  5953. user, usePubKey)
  5954. assert.Error(t, err)
  5955. // test copy dir with no create dirs perm
  5956. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join("/", testDir), "/dir1/"), user, usePubKey)
  5957. assert.Error(t, err)
  5958. // dir2 has the needed permissions
  5959. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join("/", testDir), "/dir2/"), user, usePubKey)
  5960. assert.NoError(t, err)
  5961. info, err := client.Stat(path.Join("/dir2", testDir))
  5962. if assert.NoError(t, err) {
  5963. assert.True(t, info.IsDir())
  5964. }
  5965. info, err = client.Stat(path.Join("/dir2", testDir, testFileName))
  5966. if assert.NoError(t, err) {
  5967. assert.True(t, info.Mode().IsRegular())
  5968. }
  5969. // now create a symlink, dir2 has no create symlink permission
  5970. err = client.Symlink(path.Join("/", testDir, testFileName), path.Join("/", testDir, testFileName+".link"))
  5971. assert.NoError(t, err)
  5972. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join("/", testDir), "/dir2/sub"), user, usePubKey)
  5973. assert.Error(t, err)
  5974. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join("/", testDir), "/newdir"), user, usePubKey)
  5975. assert.NoError(t, err)
  5976. // now delete the file and copy inside /dir3
  5977. err = client.Remove(path.Join("/", testDir, testFileName))
  5978. assert.NoError(t, err)
  5979. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join("/", testDir), "/dir3"), user, usePubKey)
  5980. assert.NoError(t, err)
  5981. err = os.Remove(testFilePath)
  5982. assert.NoError(t, err)
  5983. }
  5984. _, err = httpd.RemoveUser(user, http.StatusOK)
  5985. assert.NoError(t, err)
  5986. err = os.RemoveAll(user.GetHomeDir())
  5987. assert.NoError(t, err)
  5988. }
  5989. func TestSSHCopyQuotaLimits(t *testing.T) {
  5990. usePubKey := true
  5991. testFileSize := int64(131072)
  5992. testFileSize1 := int64(65536)
  5993. testFileSize2 := int64(32768)
  5994. u := getTestUser(usePubKey)
  5995. u.QuotaFiles = 3
  5996. u.QuotaSize = testFileSize + testFileSize1 + 1
  5997. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  5998. vdirPath1 := "/vdir1"
  5999. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  6000. vdirPath2 := "/vdir2"
  6001. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  6002. BaseVirtualFolder: vfs.BaseVirtualFolder{
  6003. MappedPath: mappedPath1,
  6004. },
  6005. VirtualPath: vdirPath1,
  6006. QuotaFiles: -1,
  6007. QuotaSize: -1,
  6008. })
  6009. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  6010. BaseVirtualFolder: vfs.BaseVirtualFolder{
  6011. MappedPath: mappedPath2,
  6012. },
  6013. VirtualPath: vdirPath2,
  6014. QuotaFiles: 3,
  6015. QuotaSize: testFileSize + testFileSize1 + 1,
  6016. })
  6017. u.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  6018. {
  6019. Path: "/",
  6020. DeniedExtensions: []string{".denied"},
  6021. },
  6022. }
  6023. err := os.MkdirAll(mappedPath1, os.ModePerm)
  6024. assert.NoError(t, err)
  6025. err = os.MkdirAll(mappedPath2, os.ModePerm)
  6026. assert.NoError(t, err)
  6027. user, _, err := httpd.AddUser(u, http.StatusOK)
  6028. assert.NoError(t, err)
  6029. client, err := getSftpClient(user, usePubKey)
  6030. if assert.NoError(t, err) {
  6031. defer client.Close()
  6032. testDir := "testDir"
  6033. testFilePath := filepath.Join(homeBasePath, testFileName)
  6034. testFileName1 := "test_file1.dat"
  6035. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  6036. testFileName2 := "test_file2.dat"
  6037. testFilePath2 := filepath.Join(homeBasePath, testFileName2)
  6038. err = createTestFile(testFilePath, testFileSize)
  6039. assert.NoError(t, err)
  6040. err = createTestFile(testFilePath1, testFileSize1)
  6041. assert.NoError(t, err)
  6042. err = createTestFile(testFilePath2, testFileSize2)
  6043. assert.NoError(t, err)
  6044. err = client.Mkdir(testDir)
  6045. assert.NoError(t, err)
  6046. err = client.Mkdir(path.Join(vdirPath2, testDir))
  6047. assert.NoError(t, err)
  6048. err = sftpUploadFile(testFilePath2, path.Join(testDir, testFileName2), testFileSize2, client)
  6049. assert.NoError(t, err)
  6050. err = sftpUploadFile(testFilePath2, path.Join(testDir, testFileName2+".dupl"), testFileSize2, client)
  6051. assert.NoError(t, err)
  6052. err = sftpUploadFile(testFilePath2, path.Join(vdirPath2, testDir, testFileName2), testFileSize2, client)
  6053. assert.NoError(t, err)
  6054. err = sftpUploadFile(testFilePath2, path.Join(vdirPath2, testDir, testFileName2+".dupl"), testFileSize2, client)
  6055. assert.NoError(t, err)
  6056. // user quota: 2 files, size: 32768*2, folder2 quota: 2 files, size: 32768*2
  6057. // try to duplicate testDir, this will result in 4 file (over quota) and 32768*4 bytes (not over quota)
  6058. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", testDir, testDir+"_copy"), user, usePubKey)
  6059. assert.Error(t, err)
  6060. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join(vdirPath2, testDir),
  6061. path.Join(vdirPath2, testDir+"_copy")), user, usePubKey)
  6062. assert.Error(t, err)
  6063. _, err = runSSHCommand(fmt.Sprintf("sftpgo-remove %v", testDir), user, usePubKey)
  6064. assert.NoError(t, err)
  6065. _, err = runSSHCommand(fmt.Sprintf("sftpgo-remove %v", path.Join(vdirPath2, testDir)), user, usePubKey)
  6066. assert.NoError(t, err)
  6067. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  6068. assert.NoError(t, err)
  6069. assert.Equal(t, 0, user.UsedQuotaFiles)
  6070. assert.Equal(t, int64(0), user.UsedQuotaSize)
  6071. folder, _, err := httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  6072. assert.NoError(t, err)
  6073. if assert.Len(t, folder, 1) {
  6074. f := folder[0]
  6075. assert.Equal(t, 0, f.UsedQuotaFiles)
  6076. assert.Equal(t, int64(0), f.UsedQuotaSize)
  6077. }
  6078. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  6079. assert.NoError(t, err)
  6080. if assert.Len(t, folder, 1) {
  6081. f := folder[0]
  6082. assert.Equal(t, 0, f.UsedQuotaFiles)
  6083. assert.Equal(t, int64(0), f.UsedQuotaSize)
  6084. }
  6085. err = client.Mkdir(path.Join(vdirPath1, testDir))
  6086. assert.NoError(t, err)
  6087. err = client.Mkdir(path.Join(vdirPath2, testDir))
  6088. assert.NoError(t, err)
  6089. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, testDir, testFileName), testFileSize, client)
  6090. assert.NoError(t, err)
  6091. err = sftpUploadFile(testFilePath1, path.Join(vdirPath1, testDir, testFileName1), testFileSize1, client)
  6092. assert.NoError(t, err)
  6093. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testDir, testFileName), testFileSize, client)
  6094. assert.NoError(t, err)
  6095. err = sftpUploadFile(testFilePath1, path.Join(vdirPath2, testDir, testFileName1), testFileSize1, client)
  6096. assert.NoError(t, err)
  6097. // vdir1 is included in user quota, file limit will be exceeded
  6098. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join(vdirPath1, testDir), "/"), user, usePubKey)
  6099. assert.Error(t, err)
  6100. // vdir2 size limit will be exceeded
  6101. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join(vdirPath1, testDir, testFileName),
  6102. vdirPath2+"/"), user, usePubKey)
  6103. assert.Error(t, err)
  6104. // now decrease the limits
  6105. user.QuotaFiles = 1
  6106. user.QuotaSize = testFileSize * 10
  6107. user.VirtualFolders[1].QuotaSize = testFileSize
  6108. user.VirtualFolders[1].QuotaFiles = 10
  6109. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  6110. assert.NoError(t, err)
  6111. assert.Equal(t, 1, user.QuotaFiles)
  6112. assert.Equal(t, testFileSize*10, user.QuotaSize)
  6113. if assert.Len(t, user.VirtualFolders, 2) {
  6114. f := user.VirtualFolders[1]
  6115. assert.Equal(t, testFileSize, f.QuotaSize)
  6116. assert.Equal(t, 10, f.QuotaFiles)
  6117. }
  6118. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join(vdirPath1, testDir),
  6119. path.Join(vdirPath2, testDir+".copy")), user, usePubKey)
  6120. assert.Error(t, err)
  6121. _, err = runSSHCommand(fmt.Sprintf("sftpgo-copy %v %v", path.Join(vdirPath2, testDir),
  6122. testDir+".copy"), user, usePubKey)
  6123. assert.Error(t, err)
  6124. err = os.Remove(testFilePath)
  6125. assert.NoError(t, err)
  6126. err = os.Remove(testFilePath1)
  6127. assert.NoError(t, err)
  6128. err = os.Remove(testFilePath2)
  6129. assert.NoError(t, err)
  6130. }
  6131. _, err = httpd.RemoveUser(user, http.StatusOK)
  6132. assert.NoError(t, err)
  6133. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  6134. assert.NoError(t, err)
  6135. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  6136. assert.NoError(t, err)
  6137. err = os.RemoveAll(user.GetHomeDir())
  6138. assert.NoError(t, err)
  6139. err = os.RemoveAll(mappedPath1)
  6140. assert.NoError(t, err)
  6141. err = os.RemoveAll(mappedPath2)
  6142. assert.NoError(t, err)
  6143. }
  6144. func TestSSHRemove(t *testing.T) {
  6145. usePubKey := false
  6146. u := getTestUser(usePubKey)
  6147. u.QuotaFiles = 100
  6148. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  6149. vdirPath1 := "/vdir1/sub"
  6150. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  6151. vdirPath2 := "/vdir2/sub"
  6152. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  6153. BaseVirtualFolder: vfs.BaseVirtualFolder{
  6154. MappedPath: mappedPath1,
  6155. },
  6156. VirtualPath: vdirPath1,
  6157. QuotaFiles: -1,
  6158. QuotaSize: -1,
  6159. })
  6160. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  6161. BaseVirtualFolder: vfs.BaseVirtualFolder{
  6162. MappedPath: mappedPath2,
  6163. },
  6164. VirtualPath: vdirPath2,
  6165. QuotaFiles: 100,
  6166. QuotaSize: 0,
  6167. })
  6168. err := os.MkdirAll(mappedPath1, os.ModePerm)
  6169. assert.NoError(t, err)
  6170. err = os.MkdirAll(mappedPath2, os.ModePerm)
  6171. assert.NoError(t, err)
  6172. user, _, err := httpd.AddUser(u, http.StatusOK)
  6173. assert.NoError(t, err)
  6174. client, err := getSftpClient(user, usePubKey)
  6175. if assert.NoError(t, err) {
  6176. defer client.Close()
  6177. testFileSize := int64(131072)
  6178. testFilePath := filepath.Join(homeBasePath, testFileName)
  6179. testFileName1 := "test_file1.dat"
  6180. testFileSize1 := int64(65537)
  6181. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  6182. testDir := "testdir"
  6183. err = createTestFile(testFilePath, testFileSize)
  6184. assert.NoError(t, err)
  6185. err = createTestFile(testFilePath1, testFileSize1)
  6186. assert.NoError(t, err)
  6187. err = client.Mkdir(path.Join(vdirPath1, testDir))
  6188. assert.NoError(t, err)
  6189. err = client.Mkdir(path.Join(vdirPath2, testDir))
  6190. assert.NoError(t, err)
  6191. err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
  6192. assert.NoError(t, err)
  6193. err = sftpUploadFile(testFilePath1, testFileName1, testFileSize1, client)
  6194. assert.NoError(t, err)
  6195. err = sftpUploadFile(testFilePath, path.Join(vdirPath1, testDir, testFileName), testFileSize, client)
  6196. assert.NoError(t, err)
  6197. err = sftpUploadFile(testFilePath1, path.Join(vdirPath1, testDir, testFileName1), testFileSize1, client)
  6198. assert.NoError(t, err)
  6199. err = sftpUploadFile(testFilePath, path.Join(vdirPath2, testDir, testFileName), testFileSize, client)
  6200. assert.NoError(t, err)
  6201. err = sftpUploadFile(testFilePath1, path.Join(vdirPath2, testDir, testFileName1), testFileSize1, client)
  6202. assert.NoError(t, err)
  6203. err = client.Symlink(testFileName, testFileName+".link")
  6204. assert.NoError(t, err)
  6205. _, err = runSSHCommand(fmt.Sprintf("sftpgo-remove %v", testFileName+".link"), user, usePubKey)
  6206. assert.Error(t, err)
  6207. _, err = runSSHCommand("sftpgo-remove /vdir1", user, usePubKey)
  6208. assert.Error(t, err)
  6209. _, err = runSSHCommand("sftpgo-remove /", user, usePubKey)
  6210. assert.Error(t, err)
  6211. _, err = runSSHCommand("sftpgo-remove", user, usePubKey)
  6212. assert.Error(t, err)
  6213. out, err := runSSHCommand(fmt.Sprintf("sftpgo-remove %v", testFileName), user, usePubKey)
  6214. if assert.NoError(t, err) {
  6215. assert.Equal(t, "OK\n", string(out))
  6216. _, err := client.Stat(testFileName)
  6217. assert.Error(t, err)
  6218. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  6219. assert.NoError(t, err)
  6220. assert.Equal(t, 3, user.UsedQuotaFiles)
  6221. assert.Equal(t, testFileSize+2*testFileSize1, user.UsedQuotaSize)
  6222. }
  6223. out, err = runSSHCommand(fmt.Sprintf("sftpgo-remove %v", path.Join(vdirPath1, testDir)), user, usePubKey)
  6224. if assert.NoError(t, err) {
  6225. assert.Equal(t, "OK\n", string(out))
  6226. _, err := client.Stat(path.Join(vdirPath1, testFileName))
  6227. assert.Error(t, err)
  6228. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  6229. assert.NoError(t, err)
  6230. assert.Equal(t, 1, user.UsedQuotaFiles)
  6231. assert.Equal(t, testFileSize1, user.UsedQuotaSize)
  6232. }
  6233. _, err = runSSHCommand(fmt.Sprintf("sftpgo-remove %v", vdirPath1), user, usePubKey)
  6234. assert.Error(t, err)
  6235. _, err = runSSHCommand("sftpgo-remove /", user, usePubKey)
  6236. assert.Error(t, err)
  6237. _, err = runSSHCommand("sftpgo-remove missing_file", user, usePubKey)
  6238. assert.Error(t, err)
  6239. if runtime.GOOS != osWindows {
  6240. err = os.Chmod(filepath.Join(mappedPath2, testDir), 0555)
  6241. assert.NoError(t, err)
  6242. _, err = runSSHCommand(fmt.Sprintf("sftpgo-remove %v", path.Join(vdirPath2, testDir)), user, usePubKey)
  6243. assert.Error(t, err)
  6244. err = os.Chmod(filepath.Join(mappedPath2, testDir), 0001)
  6245. assert.NoError(t, err)
  6246. _, err = runSSHCommand(fmt.Sprintf("sftpgo-remove %v", path.Join(vdirPath2, testDir)), user, usePubKey)
  6247. assert.Error(t, err)
  6248. err = os.Chmod(filepath.Join(mappedPath2, testDir), os.ModePerm)
  6249. assert.NoError(t, err)
  6250. }
  6251. }
  6252. // test remove dir with no delete perm
  6253. user.Permissions["/"] = []string{dataprovider.PermUpload, dataprovider.PermDownload, dataprovider.PermListItems}
  6254. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  6255. assert.NoError(t, err)
  6256. client, err = getSftpClient(user, usePubKey)
  6257. if assert.NoError(t, err) {
  6258. defer client.Close()
  6259. _, err = runSSHCommand("sftpgo-remove adir", user, usePubKey)
  6260. assert.Error(t, err)
  6261. }
  6262. _, err = httpd.RemoveUser(user, http.StatusOK)
  6263. assert.NoError(t, err)
  6264. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  6265. assert.NoError(t, err)
  6266. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  6267. assert.NoError(t, err)
  6268. err = os.RemoveAll(user.GetHomeDir())
  6269. assert.NoError(t, err)
  6270. err = os.RemoveAll(mappedPath1)
  6271. assert.NoError(t, err)
  6272. err = os.RemoveAll(mappedPath2)
  6273. assert.NoError(t, err)
  6274. }
  6275. func TestBasicGitCommands(t *testing.T) {
  6276. if len(gitPath) == 0 || len(sshPath) == 0 || runtime.GOOS == osWindows {
  6277. t.Skip("git and/or ssh command not found or OS is windows, unable to execute this test")
  6278. }
  6279. usePubKey := true
  6280. u := getTestUser(usePubKey)
  6281. user, _, err := httpd.AddUser(u, http.StatusOK)
  6282. assert.NoError(t, err)
  6283. repoName := "testrepo" //nolint:goconst
  6284. clonePath := filepath.Join(homeBasePath, repoName)
  6285. err = os.RemoveAll(user.GetHomeDir())
  6286. assert.NoError(t, err)
  6287. err = os.RemoveAll(filepath.Join(homeBasePath, repoName))
  6288. assert.NoError(t, err)
  6289. out, err := initGitRepo(filepath.Join(user.HomeDir, repoName))
  6290. assert.NoError(t, err, "unexpected error, out: %v", string(out))
  6291. out, err = cloneGitRepo(homeBasePath, "/"+repoName, user.Username)
  6292. assert.NoError(t, err, "unexpected error, out: %v", string(out))
  6293. out, err = addFileToGitRepo(clonePath, 128)
  6294. assert.NoError(t, err, "unexpected error, out: %v", string(out))
  6295. user.QuotaFiles = 100000
  6296. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  6297. assert.NoError(t, err)
  6298. out, err = pushToGitRepo(clonePath)
  6299. if !assert.NoError(t, err, "unexpected error, out: %v", string(out)) {
  6300. printLatestLogs(10)
  6301. }
  6302. out, err = addFileToGitRepo(clonePath, 131072)
  6303. assert.NoError(t, err, "unexpected error, out: %v", string(out))
  6304. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  6305. assert.NoError(t, err)
  6306. user.QuotaSize = user.UsedQuotaSize + 1
  6307. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  6308. assert.NoError(t, err)
  6309. out, err = pushToGitRepo(clonePath)
  6310. assert.Error(t, err, "git push must fail if quota is exceeded, out: %v", string(out))
  6311. aDir := filepath.Join(user.GetHomeDir(), repoName, "adir")
  6312. err = os.MkdirAll(aDir, 0001)
  6313. assert.NoError(t, err)
  6314. _, err = pushToGitRepo(clonePath)
  6315. assert.Error(t, err)
  6316. err = os.Chmod(aDir, os.ModePerm)
  6317. assert.NoError(t, err)
  6318. _, err = httpd.RemoveUser(user, http.StatusOK)
  6319. assert.NoError(t, err)
  6320. err = os.RemoveAll(user.GetHomeDir())
  6321. assert.NoError(t, err)
  6322. err = os.RemoveAll(clonePath)
  6323. assert.NoError(t, err)
  6324. }
  6325. func TestGitQuotaVirtualFolders(t *testing.T) {
  6326. if len(gitPath) == 0 || len(sshPath) == 0 || runtime.GOOS == osWindows {
  6327. t.Skip("git and/or ssh command not found or OS is windows, unable to execute this test")
  6328. }
  6329. usePubKey := true
  6330. repoName := "testrepo"
  6331. u := getTestUser(usePubKey)
  6332. u.QuotaFiles = 1
  6333. u.QuotaSize = 131072
  6334. mappedPath := filepath.Join(os.TempDir(), "repo")
  6335. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  6336. BaseVirtualFolder: vfs.BaseVirtualFolder{
  6337. MappedPath: mappedPath,
  6338. },
  6339. VirtualPath: "/" + repoName,
  6340. QuotaFiles: 0,
  6341. QuotaSize: 0,
  6342. })
  6343. err := os.MkdirAll(mappedPath, os.ModePerm)
  6344. assert.NoError(t, err)
  6345. user, _, err := httpd.AddUser(u, http.StatusOK)
  6346. assert.NoError(t, err)
  6347. client, err := getSftpClient(user, usePubKey)
  6348. if assert.NoError(t, err) {
  6349. // we upload a file so the user is over quota
  6350. defer client.Close()
  6351. testFilePath := filepath.Join(homeBasePath, testFileName)
  6352. err = createTestFile(testFilePath, u.QuotaSize)
  6353. assert.NoError(t, err)
  6354. err = sftpUploadFile(testFilePath, testFileName, u.QuotaSize, client)
  6355. assert.NoError(t, err)
  6356. err = os.Remove(testFilePath)
  6357. assert.NoError(t, err)
  6358. }
  6359. clonePath := filepath.Join(homeBasePath, repoName)
  6360. err = os.RemoveAll(user.GetHomeDir())
  6361. assert.NoError(t, err)
  6362. err = os.RemoveAll(filepath.Join(homeBasePath, repoName))
  6363. assert.NoError(t, err)
  6364. out, err := initGitRepo(mappedPath)
  6365. assert.NoError(t, err, "unexpected error, out: %v", string(out))
  6366. out, err = cloneGitRepo(homeBasePath, "/"+repoName, user.Username)
  6367. assert.NoError(t, err, "unexpected error, out: %v", string(out))
  6368. out, err = addFileToGitRepo(clonePath, 128)
  6369. assert.NoError(t, err, "unexpected error, out: %v", string(out))
  6370. out, err = pushToGitRepo(clonePath)
  6371. assert.NoError(t, err, "unexpected error, out: %v", string(out))
  6372. _, err = httpd.RemoveUser(user, http.StatusOK)
  6373. assert.NoError(t, err)
  6374. err = os.RemoveAll(user.GetHomeDir())
  6375. assert.NoError(t, err)
  6376. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath}, http.StatusOK)
  6377. assert.NoError(t, err)
  6378. err = os.RemoveAll(mappedPath)
  6379. assert.NoError(t, err)
  6380. err = os.RemoveAll(clonePath)
  6381. assert.NoError(t, err)
  6382. }
  6383. func TestGitErrors(t *testing.T) {
  6384. if len(gitPath) == 0 || len(sshPath) == 0 || runtime.GOOS == osWindows {
  6385. t.Skip("git and/or ssh command not found or OS is windows, unable to execute this test")
  6386. }
  6387. usePubKey := true
  6388. u := getTestUser(usePubKey)
  6389. user, _, err := httpd.AddUser(u, http.StatusOK)
  6390. assert.NoError(t, err)
  6391. repoName := "testrepo"
  6392. clonePath := filepath.Join(homeBasePath, repoName)
  6393. err = os.RemoveAll(user.GetHomeDir())
  6394. assert.NoError(t, err)
  6395. err = os.RemoveAll(filepath.Join(homeBasePath, repoName))
  6396. assert.NoError(t, err)
  6397. out, err := cloneGitRepo(homeBasePath, "/"+repoName, user.Username)
  6398. assert.Error(t, err, "cloning a missing repo must fail, out: %v", string(out))
  6399. _, err = httpd.RemoveUser(user, http.StatusOK)
  6400. assert.NoError(t, err)
  6401. err = os.RemoveAll(user.GetHomeDir())
  6402. assert.NoError(t, err)
  6403. err = os.RemoveAll(clonePath)
  6404. assert.NoError(t, err)
  6405. }
  6406. // Start SCP tests
  6407. func TestSCPBasicHandling(t *testing.T) {
  6408. if len(scpPath) == 0 {
  6409. t.Skip("scp command not found, unable to execute this test")
  6410. }
  6411. usePubKey := true
  6412. u := getTestUser(usePubKey)
  6413. u.QuotaSize = 6553600
  6414. user, _, err := httpd.AddUser(u, http.StatusOK)
  6415. assert.NoError(t, err)
  6416. testFilePath := filepath.Join(homeBasePath, testFileName)
  6417. testFileSize := int64(131074)
  6418. expectedQuotaSize := user.UsedQuotaSize + testFileSize
  6419. expectedQuotaFiles := user.UsedQuotaFiles + 1
  6420. err = createTestFile(testFilePath, testFileSize)
  6421. assert.NoError(t, err)
  6422. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/")
  6423. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  6424. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  6425. // test to download a missing file
  6426. err = scpDownload(localPath, remoteDownPath, false, false)
  6427. assert.Error(t, err, "downloading a missing file via scp must fail")
  6428. err = scpUpload(testFilePath, remoteUpPath, false, false)
  6429. assert.NoError(t, err)
  6430. err = scpDownload(localPath, remoteDownPath, false, false)
  6431. assert.NoError(t, err)
  6432. fi, err := os.Stat(localPath)
  6433. if assert.NoError(t, err) {
  6434. assert.Equal(t, testFileSize, fi.Size())
  6435. }
  6436. err = os.Remove(localPath)
  6437. assert.NoError(t, err)
  6438. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  6439. assert.NoError(t, err)
  6440. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  6441. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  6442. assert.NoError(t, err)
  6443. _, err = httpd.RemoveUser(user, http.StatusOK)
  6444. assert.NoError(t, err)
  6445. err = os.Remove(testFilePath)
  6446. assert.NoError(t, err)
  6447. }
  6448. func TestSCPUploadFileOverwrite(t *testing.T) {
  6449. if len(scpPath) == 0 {
  6450. t.Skip("scp command not found, unable to execute this test")
  6451. }
  6452. usePubKey := true
  6453. u := getTestUser(usePubKey)
  6454. u.QuotaFiles = 1000
  6455. user, _, err := httpd.AddUser(u, http.StatusOK)
  6456. assert.NoError(t, err)
  6457. err = os.RemoveAll(user.GetHomeDir())
  6458. assert.NoError(t, err)
  6459. testFilePath := filepath.Join(homeBasePath, testFileName)
  6460. testFileSize := int64(32760)
  6461. err = createTestFile(testFilePath, testFileSize)
  6462. assert.NoError(t, err)
  6463. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  6464. err = scpUpload(testFilePath, remoteUpPath, true, false)
  6465. assert.NoError(t, err)
  6466. // test a new upload that must overwrite the existing file
  6467. err = scpUpload(testFilePath, remoteUpPath, true, false)
  6468. assert.NoError(t, err)
  6469. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  6470. assert.NoError(t, err)
  6471. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  6472. assert.Equal(t, 1, user.UsedQuotaFiles)
  6473. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  6474. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  6475. err = scpDownload(localPath, remoteDownPath, false, false)
  6476. assert.NoError(t, err)
  6477. fi, err := os.Stat(localPath)
  6478. if assert.NoError(t, err) {
  6479. assert.Equal(t, testFileSize, fi.Size())
  6480. }
  6481. // now create a simlink via SFTP, replace the symlink with a file via SCP and check quota usage
  6482. client, err := getSftpClient(user, usePubKey)
  6483. if assert.NoError(t, err) {
  6484. defer client.Close()
  6485. err = client.Symlink(testFileName, testFileName+".link")
  6486. assert.NoError(t, err)
  6487. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  6488. assert.NoError(t, err)
  6489. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  6490. assert.Equal(t, 1, user.UsedQuotaFiles)
  6491. }
  6492. err = scpUpload(testFilePath, remoteUpPath+".link", true, false)
  6493. assert.NoError(t, err)
  6494. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  6495. assert.NoError(t, err)
  6496. assert.Equal(t, testFileSize*2, user.UsedQuotaSize)
  6497. assert.Equal(t, 2, user.UsedQuotaFiles)
  6498. err = os.Remove(localPath)
  6499. assert.NoError(t, err)
  6500. err = os.Remove(testFilePath)
  6501. assert.NoError(t, err)
  6502. err = os.RemoveAll(user.GetHomeDir())
  6503. assert.NoError(t, err)
  6504. _, err = httpd.RemoveUser(user, http.StatusOK)
  6505. assert.NoError(t, err)
  6506. }
  6507. func TestSCPRecursive(t *testing.T) {
  6508. if len(scpPath) == 0 {
  6509. t.Skip("scp command not found, unable to execute this test")
  6510. }
  6511. usePubKey := true
  6512. u := getTestUser(usePubKey)
  6513. user, _, err := httpd.AddUser(u, http.StatusOK)
  6514. assert.NoError(t, err)
  6515. testBaseDirName := "test_dir"
  6516. testBaseDirPath := filepath.Join(homeBasePath, testBaseDirName)
  6517. testBaseDirDownName := "test_dir_down" //nolint:goconst
  6518. testBaseDirDownPath := filepath.Join(homeBasePath, testBaseDirDownName)
  6519. testFilePath := filepath.Join(homeBasePath, testBaseDirName, testFileName)
  6520. testFilePath1 := filepath.Join(homeBasePath, testBaseDirName, testBaseDirName, testFileName)
  6521. testFileSize := int64(131074)
  6522. err = createTestFile(testFilePath, testFileSize)
  6523. assert.NoError(t, err)
  6524. err = createTestFile(testFilePath1, testFileSize)
  6525. assert.NoError(t, err)
  6526. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testBaseDirName))
  6527. // test to download a missing dir
  6528. err = scpDownload(testBaseDirDownPath, remoteDownPath, true, true)
  6529. assert.Error(t, err, "downloading a missing dir via scp must fail")
  6530. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/")
  6531. err = scpUpload(testBaseDirPath, remoteUpPath, true, false)
  6532. assert.NoError(t, err)
  6533. // overwrite existing dir
  6534. err = scpUpload(testBaseDirPath, remoteUpPath, true, false)
  6535. assert.NoError(t, err)
  6536. err = scpDownload(testBaseDirDownPath, remoteDownPath, true, true)
  6537. assert.NoError(t, err)
  6538. // test download without passing -r
  6539. err = scpDownload(testBaseDirDownPath, remoteDownPath, true, false)
  6540. assert.Error(t, err, "recursive download without -r must fail")
  6541. fi, err := os.Stat(filepath.Join(testBaseDirDownPath, testFileName))
  6542. if assert.NoError(t, err) {
  6543. assert.Equal(t, testFileSize, fi.Size())
  6544. }
  6545. fi, err = os.Stat(filepath.Join(testBaseDirDownPath, testBaseDirName, testFileName))
  6546. if assert.NoError(t, err) {
  6547. assert.Equal(t, testFileSize, fi.Size())
  6548. }
  6549. // upload to a non existent dir
  6550. remoteUpPath = fmt.Sprintf("%[email protected]:%v", user.Username, "/non_existent_dir")
  6551. err = scpUpload(testBaseDirPath, remoteUpPath, true, false)
  6552. assert.Error(t, err, "uploading via scp to a non existent dir must fail")
  6553. err = os.RemoveAll(testBaseDirPath)
  6554. assert.NoError(t, err)
  6555. err = os.RemoveAll(testBaseDirDownPath)
  6556. assert.NoError(t, err)
  6557. err = os.RemoveAll(user.GetHomeDir())
  6558. assert.NoError(t, err)
  6559. _, err = httpd.RemoveUser(user, http.StatusOK)
  6560. assert.NoError(t, err)
  6561. }
  6562. func TestSCPExtensionsFilter(t *testing.T) {
  6563. if len(scpPath) == 0 {
  6564. t.Skip("scp command not found, unable to execute this test")
  6565. }
  6566. usePubKey := true
  6567. u := getTestUser(usePubKey)
  6568. user, _, err := httpd.AddUser(u, http.StatusOK)
  6569. assert.NoError(t, err)
  6570. testFileSize := int64(131072)
  6571. testFilePath := filepath.Join(homeBasePath, testFileName)
  6572. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  6573. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/")
  6574. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  6575. err = createTestFile(testFilePath, testFileSize)
  6576. assert.NoError(t, err)
  6577. err = scpUpload(testFilePath, remoteUpPath, false, false)
  6578. assert.NoError(t, err)
  6579. user.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  6580. {
  6581. Path: "/",
  6582. AllowedExtensions: []string{".zip"},
  6583. DeniedExtensions: []string{},
  6584. },
  6585. }
  6586. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  6587. assert.NoError(t, err)
  6588. err = scpDownload(localPath, remoteDownPath, false, false)
  6589. assert.Error(t, err, "scp download must fail")
  6590. err = scpUpload(testFilePath, remoteUpPath, false, false)
  6591. assert.Error(t, err, "scp upload must fail")
  6592. _, err = httpd.RemoveUser(user, http.StatusOK)
  6593. assert.NoError(t, err)
  6594. err = os.Remove(testFilePath)
  6595. assert.NoError(t, err)
  6596. _, err = os.Stat(localPath)
  6597. if err == nil {
  6598. err = os.Remove(localPath)
  6599. assert.NoError(t, err)
  6600. }
  6601. err = os.RemoveAll(user.GetHomeDir())
  6602. assert.NoError(t, err)
  6603. }
  6604. func TestSCPUploadMaxSize(t *testing.T) {
  6605. testFileSize := int64(65535)
  6606. usePubKey := true
  6607. u := getTestUser(usePubKey)
  6608. u.Filters.MaxUploadFileSize = testFileSize + 1
  6609. user, _, err := httpd.AddUser(u, http.StatusOK)
  6610. assert.NoError(t, err)
  6611. testFilePath := filepath.Join(homeBasePath, testFileName)
  6612. err = createTestFile(testFilePath, testFileSize)
  6613. assert.NoError(t, err)
  6614. testFileSize1 := int64(131072)
  6615. testFileName1 := "test_file1.dat"
  6616. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  6617. err = createTestFile(testFilePath1, testFileSize1)
  6618. assert.NoError(t, err)
  6619. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/")
  6620. err = scpUpload(testFilePath1, remoteUpPath, false, false)
  6621. assert.Error(t, err)
  6622. err = scpUpload(testFilePath, remoteUpPath, false, false)
  6623. assert.NoError(t, err)
  6624. err = os.Remove(testFilePath)
  6625. assert.NoError(t, err)
  6626. err = os.Remove(testFilePath1)
  6627. assert.NoError(t, err)
  6628. _, err = httpd.RemoveUser(user, http.StatusOK)
  6629. assert.NoError(t, err)
  6630. err = os.RemoveAll(user.GetHomeDir())
  6631. assert.NoError(t, err)
  6632. }
  6633. func TestSCPVirtualFolders(t *testing.T) {
  6634. if len(scpPath) == 0 {
  6635. t.Skip("scp command not found, unable to execute this test")
  6636. }
  6637. usePubKey := true
  6638. u := getTestUser(usePubKey)
  6639. mappedPath := filepath.Join(os.TempDir(), "vdir")
  6640. vdirPath := "/vdir"
  6641. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  6642. BaseVirtualFolder: vfs.BaseVirtualFolder{
  6643. MappedPath: mappedPath,
  6644. },
  6645. VirtualPath: vdirPath,
  6646. })
  6647. err := os.MkdirAll(mappedPath, os.ModePerm)
  6648. assert.NoError(t, err)
  6649. user, _, err := httpd.AddUser(u, http.StatusOK)
  6650. assert.NoError(t, err)
  6651. testBaseDirName := "test_dir"
  6652. testBaseDirPath := filepath.Join(homeBasePath, testBaseDirName)
  6653. testBaseDirDownName := "test_dir_down"
  6654. testBaseDirDownPath := filepath.Join(homeBasePath, testBaseDirDownName)
  6655. testFilePath := filepath.Join(homeBasePath, testBaseDirName, testFileName)
  6656. testFilePath1 := filepath.Join(homeBasePath, testBaseDirName, testBaseDirName, testFileName)
  6657. testFileSize := int64(131074)
  6658. err = createTestFile(testFilePath, testFileSize)
  6659. assert.NoError(t, err)
  6660. err = createTestFile(testFilePath1, testFileSize)
  6661. assert.NoError(t, err)
  6662. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, vdirPath)
  6663. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, vdirPath)
  6664. err = scpUpload(testBaseDirPath, remoteUpPath, true, false)
  6665. assert.NoError(t, err)
  6666. err = scpDownload(testBaseDirDownPath, remoteDownPath, true, true)
  6667. assert.NoError(t, err)
  6668. _, err = httpd.RemoveUser(user, http.StatusOK)
  6669. assert.NoError(t, err)
  6670. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath}, http.StatusOK)
  6671. assert.NoError(t, err)
  6672. err = os.RemoveAll(testBaseDirPath)
  6673. assert.NoError(t, err)
  6674. err = os.RemoveAll(testBaseDirDownPath)
  6675. assert.NoError(t, err)
  6676. err = os.RemoveAll(user.GetHomeDir())
  6677. assert.NoError(t, err)
  6678. err = os.RemoveAll(mappedPath)
  6679. assert.NoError(t, err)
  6680. }
  6681. func TestSCPVirtualFoldersQuota(t *testing.T) {
  6682. if len(scpPath) == 0 {
  6683. t.Skip("scp command not found, unable to execute this test")
  6684. }
  6685. usePubKey := true
  6686. u := getTestUser(usePubKey)
  6687. u.QuotaFiles = 100
  6688. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  6689. vdirPath1 := "/vdir1"
  6690. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  6691. vdirPath2 := "/vdir2"
  6692. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  6693. BaseVirtualFolder: vfs.BaseVirtualFolder{
  6694. MappedPath: mappedPath1,
  6695. },
  6696. VirtualPath: vdirPath1,
  6697. QuotaFiles: -1,
  6698. QuotaSize: -1,
  6699. })
  6700. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  6701. BaseVirtualFolder: vfs.BaseVirtualFolder{
  6702. MappedPath: mappedPath2,
  6703. },
  6704. VirtualPath: vdirPath2,
  6705. QuotaFiles: 0,
  6706. QuotaSize: 0,
  6707. })
  6708. err := os.MkdirAll(mappedPath1, os.ModePerm)
  6709. assert.NoError(t, err)
  6710. err = os.MkdirAll(mappedPath2, os.ModePerm)
  6711. assert.NoError(t, err)
  6712. user, _, err := httpd.AddUser(u, http.StatusOK)
  6713. assert.NoError(t, err)
  6714. testBaseDirName := "test_dir"
  6715. testBaseDirPath := filepath.Join(homeBasePath, testBaseDirName)
  6716. testBaseDirDownName := "test_dir_down"
  6717. testBaseDirDownPath := filepath.Join(homeBasePath, testBaseDirDownName)
  6718. testFilePath := filepath.Join(homeBasePath, testBaseDirName, testFileName)
  6719. testFilePath1 := filepath.Join(homeBasePath, testBaseDirName, testBaseDirName, testFileName)
  6720. testFileSize := int64(131074)
  6721. err = createTestFile(testFilePath, testFileSize)
  6722. assert.NoError(t, err)
  6723. err = createTestFile(testFilePath1, testFileSize)
  6724. assert.NoError(t, err)
  6725. remoteDownPath1 := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", vdirPath1))
  6726. remoteUpPath1 := fmt.Sprintf("%[email protected]:%v", user.Username, vdirPath1)
  6727. remoteDownPath2 := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", vdirPath2))
  6728. remoteUpPath2 := fmt.Sprintf("%[email protected]:%v", user.Username, vdirPath2)
  6729. // we upload two times to test overwrite
  6730. err = scpUpload(testBaseDirPath, remoteUpPath1, true, false)
  6731. assert.NoError(t, err)
  6732. err = scpDownload(testBaseDirDownPath, remoteDownPath1, true, true)
  6733. assert.NoError(t, err)
  6734. err = scpUpload(testBaseDirPath, remoteUpPath1, true, false)
  6735. assert.NoError(t, err)
  6736. err = scpDownload(testBaseDirDownPath, remoteDownPath1, true, true)
  6737. assert.NoError(t, err)
  6738. err = scpUpload(testBaseDirPath, remoteUpPath2, true, false)
  6739. assert.NoError(t, err)
  6740. err = scpDownload(testBaseDirDownPath, remoteDownPath2, true, true)
  6741. assert.NoError(t, err)
  6742. expectedQuotaFiles := 2
  6743. expectedQuotaSize := testFileSize * 2
  6744. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  6745. assert.NoError(t, err)
  6746. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  6747. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  6748. folder, _, err := httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  6749. assert.NoError(t, err)
  6750. if assert.Len(t, folder, 1) {
  6751. f := folder[0]
  6752. assert.Equal(t, expectedQuotaSize, f.UsedQuotaSize)
  6753. assert.Equal(t, expectedQuotaFiles, f.UsedQuotaFiles)
  6754. }
  6755. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  6756. assert.NoError(t, err)
  6757. if assert.Len(t, folder, 1) {
  6758. f := folder[0]
  6759. assert.Equal(t, expectedQuotaSize, f.UsedQuotaSize)
  6760. assert.Equal(t, expectedQuotaFiles, f.UsedQuotaFiles)
  6761. }
  6762. _, err = httpd.RemoveUser(user, http.StatusOK)
  6763. assert.NoError(t, err)
  6764. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  6765. assert.NoError(t, err)
  6766. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  6767. assert.NoError(t, err)
  6768. err = os.RemoveAll(testBaseDirPath)
  6769. assert.NoError(t, err)
  6770. err = os.RemoveAll(testBaseDirDownPath)
  6771. assert.NoError(t, err)
  6772. err = os.RemoveAll(user.GetHomeDir())
  6773. assert.NoError(t, err)
  6774. err = os.RemoveAll(mappedPath1)
  6775. assert.NoError(t, err)
  6776. err = os.RemoveAll(mappedPath2)
  6777. assert.NoError(t, err)
  6778. }
  6779. func TestSCPPermsSubDirs(t *testing.T) {
  6780. if len(scpPath) == 0 {
  6781. t.Skip("scp command not found, unable to execute this test")
  6782. }
  6783. usePubKey := true
  6784. u := getTestUser(usePubKey)
  6785. u.Permissions["/"] = []string{dataprovider.PermAny}
  6786. u.Permissions["/somedir"] = []string{dataprovider.PermListItems, dataprovider.PermUpload}
  6787. user, _, err := httpd.AddUser(u, http.StatusOK)
  6788. assert.NoError(t, err)
  6789. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  6790. subPath := filepath.Join(user.GetHomeDir(), "somedir")
  6791. testFileSize := int64(65535)
  6792. err = os.MkdirAll(subPath, os.ModePerm)
  6793. assert.NoError(t, err)
  6794. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/somedir")
  6795. err = scpDownload(localPath, remoteDownPath, false, true)
  6796. assert.Error(t, err, "download a dir with no permissions must fail")
  6797. err = os.Remove(subPath)
  6798. assert.NoError(t, err)
  6799. err = createTestFile(subPath, testFileSize)
  6800. assert.NoError(t, err)
  6801. err = scpDownload(localPath, remoteDownPath, false, false)
  6802. assert.NoError(t, err)
  6803. if runtime.GOOS != osWindows {
  6804. err = os.Chmod(subPath, 0001)
  6805. assert.NoError(t, err)
  6806. err = scpDownload(localPath, remoteDownPath, false, false)
  6807. assert.Error(t, err, "download a file with no system permissions must fail")
  6808. err = os.Chmod(subPath, os.ModePerm)
  6809. assert.NoError(t, err)
  6810. }
  6811. err = os.Remove(localPath)
  6812. assert.NoError(t, err)
  6813. err = os.RemoveAll(user.GetHomeDir())
  6814. assert.NoError(t, err)
  6815. _, err = httpd.RemoveUser(user, http.StatusOK)
  6816. assert.NoError(t, err)
  6817. }
  6818. func TestSCPPermCreateDirs(t *testing.T) {
  6819. if len(scpPath) == 0 {
  6820. t.Skip("scp command not found, unable to execute this test")
  6821. }
  6822. usePubKey := true
  6823. u := getTestUser(usePubKey)
  6824. u.Permissions["/"] = []string{dataprovider.PermDownload, dataprovider.PermUpload}
  6825. user, _, err := httpd.AddUser(u, http.StatusOK)
  6826. assert.NoError(t, err)
  6827. testFilePath := filepath.Join(homeBasePath, testFileName)
  6828. testFileSize := int64(32760)
  6829. testBaseDirName := "test_dir"
  6830. testBaseDirPath := filepath.Join(homeBasePath, testBaseDirName)
  6831. testFilePath1 := filepath.Join(homeBasePath, testBaseDirName, testFileName)
  6832. err = createTestFile(testFilePath, testFileSize)
  6833. assert.NoError(t, err)
  6834. err = createTestFile(testFilePath1, testFileSize)
  6835. assert.NoError(t, err)
  6836. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/tmp/")
  6837. err = scpUpload(testFilePath, remoteUpPath, true, false)
  6838. assert.Error(t, err, "scp upload must fail, the user cannot create files in a missing dir")
  6839. err = scpUpload(testBaseDirPath, remoteUpPath, true, false)
  6840. assert.Error(t, err, "scp upload must fail, the user cannot create new dirs")
  6841. err = os.Remove(testFilePath)
  6842. assert.NoError(t, err)
  6843. err = os.RemoveAll(testBaseDirPath)
  6844. assert.NoError(t, err)
  6845. err = os.RemoveAll(user.GetHomeDir())
  6846. assert.NoError(t, err)
  6847. _, err = httpd.RemoveUser(user, http.StatusOK)
  6848. assert.NoError(t, err)
  6849. }
  6850. func TestSCPPermUpload(t *testing.T) {
  6851. if len(scpPath) == 0 {
  6852. t.Skip("scp command not found, unable to execute this test")
  6853. }
  6854. usePubKey := true
  6855. u := getTestUser(usePubKey)
  6856. u.Permissions["/"] = []string{dataprovider.PermDownload, dataprovider.PermCreateDirs}
  6857. user, _, err := httpd.AddUser(u, http.StatusOK)
  6858. assert.NoError(t, err)
  6859. testFilePath := filepath.Join(homeBasePath, testFileName)
  6860. testFileSize := int64(65536)
  6861. err = createTestFile(testFilePath, testFileSize)
  6862. assert.NoError(t, err)
  6863. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/tmp")
  6864. err = scpUpload(testFilePath, remoteUpPath, true, false)
  6865. assert.Error(t, err, "scp upload must fail, the user cannot upload")
  6866. err = os.Remove(testFilePath)
  6867. assert.NoError(t, err)
  6868. err = os.RemoveAll(user.GetHomeDir())
  6869. assert.NoError(t, err)
  6870. _, err = httpd.RemoveUser(user, http.StatusOK)
  6871. assert.NoError(t, err)
  6872. }
  6873. func TestSCPPermOverwrite(t *testing.T) {
  6874. if len(scpPath) == 0 {
  6875. t.Skip("scp command not found, unable to execute this test")
  6876. }
  6877. usePubKey := true
  6878. u := getTestUser(usePubKey)
  6879. u.Permissions["/"] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs}
  6880. user, _, err := httpd.AddUser(u, http.StatusOK)
  6881. assert.NoError(t, err)
  6882. testFilePath := filepath.Join(homeBasePath, testFileName)
  6883. testFileSize := int64(65536)
  6884. err = createTestFile(testFilePath, testFileSize)
  6885. assert.NoError(t, err)
  6886. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/tmp")
  6887. err = scpUpload(testFilePath, remoteUpPath, true, false)
  6888. assert.NoError(t, err)
  6889. err = scpUpload(testFilePath, remoteUpPath, true, false)
  6890. assert.Error(t, err, "scp upload must fail, the user cannot ovewrite existing files")
  6891. err = os.Remove(testFilePath)
  6892. assert.NoError(t, err)
  6893. err = os.RemoveAll(user.GetHomeDir())
  6894. assert.NoError(t, err)
  6895. _, err = httpd.RemoveUser(user, http.StatusOK)
  6896. assert.NoError(t, err)
  6897. }
  6898. func TestSCPPermDownload(t *testing.T) {
  6899. if len(scpPath) == 0 {
  6900. t.Skip("scp command not found, unable to execute this test")
  6901. }
  6902. usePubKey := true
  6903. u := getTestUser(usePubKey)
  6904. u.Permissions["/"] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs}
  6905. user, _, err := httpd.AddUser(u, http.StatusOK)
  6906. assert.NoError(t, err)
  6907. testFilePath := filepath.Join(homeBasePath, testFileName)
  6908. testFileSize := int64(65537)
  6909. err = createTestFile(testFilePath, testFileSize)
  6910. assert.NoError(t, err)
  6911. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/")
  6912. err = scpUpload(testFilePath, remoteUpPath, true, false)
  6913. assert.NoError(t, err)
  6914. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  6915. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  6916. err = scpDownload(localPath, remoteDownPath, false, false)
  6917. assert.Error(t, err, "scp download must fail, the user cannot download")
  6918. err = os.Remove(testFilePath)
  6919. assert.NoError(t, err)
  6920. err = os.RemoveAll(user.GetHomeDir())
  6921. assert.NoError(t, err)
  6922. _, err = httpd.RemoveUser(user, http.StatusOK)
  6923. assert.NoError(t, err)
  6924. }
  6925. func TestSCPQuotaSize(t *testing.T) {
  6926. if len(scpPath) == 0 {
  6927. t.Skip("scp command not found, unable to execute this test")
  6928. }
  6929. usePubKey := true
  6930. testFileSize := int64(65535)
  6931. u := getTestUser(usePubKey)
  6932. u.QuotaFiles = 1
  6933. u.QuotaSize = testFileSize + 1
  6934. user, _, err := httpd.AddUser(u, http.StatusOK)
  6935. assert.NoError(t, err)
  6936. testFilePath := filepath.Join(homeBasePath, testFileName)
  6937. err = createTestFile(testFilePath, testFileSize)
  6938. assert.NoError(t, err)
  6939. testFileSize1 := int64(131072)
  6940. testFileName1 := "test_file1.dat"
  6941. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  6942. err = createTestFile(testFilePath1, testFileSize1)
  6943. assert.NoError(t, err)
  6944. testFileSize2 := int64(32768)
  6945. testFileName2 := "test_file2.dat"
  6946. testFilePath2 := filepath.Join(homeBasePath, testFileName2)
  6947. err = createTestFile(testFilePath2, testFileSize2)
  6948. assert.NoError(t, err)
  6949. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  6950. err = scpUpload(testFilePath, remoteUpPath, true, false)
  6951. assert.NoError(t, err)
  6952. err = scpUpload(testFilePath, remoteUpPath+".quota", true, false)
  6953. assert.Error(t, err, "user is over quota scp upload must fail")
  6954. // now test quota limits while uploading the current file, we have 1 bytes remaining
  6955. user.QuotaSize = testFileSize + 1
  6956. user.QuotaFiles = 0
  6957. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  6958. assert.NoError(t, err)
  6959. err = scpUpload(testFilePath2, remoteUpPath+".quota", true, false)
  6960. assert.Error(t, err, "user is over quota scp upload must fail")
  6961. // overwriting an existing file will work if the resulting size is lesser or equal than the current one
  6962. err = scpUpload(testFilePath1, remoteUpPath, true, false)
  6963. assert.Error(t, err)
  6964. err = scpUpload(testFilePath2, remoteUpPath, true, false)
  6965. assert.NoError(t, err)
  6966. err = scpUpload(testFilePath, remoteUpPath, true, false)
  6967. assert.NoError(t, err)
  6968. err = os.Remove(testFilePath)
  6969. assert.NoError(t, err)
  6970. err = os.Remove(testFilePath1)
  6971. assert.NoError(t, err)
  6972. err = os.Remove(testFilePath2)
  6973. assert.NoError(t, err)
  6974. err = os.RemoveAll(user.GetHomeDir())
  6975. assert.NoError(t, err)
  6976. _, err = httpd.RemoveUser(user, http.StatusOK)
  6977. assert.NoError(t, err)
  6978. }
  6979. func TestSCPEscapeHomeDir(t *testing.T) {
  6980. if len(scpPath) == 0 {
  6981. t.Skip("scp command not found, unable to execute this test")
  6982. }
  6983. usePubKey := true
  6984. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  6985. assert.NoError(t, err)
  6986. err = os.MkdirAll(user.GetHomeDir(), os.ModePerm)
  6987. assert.NoError(t, err)
  6988. testDir := "testDir"
  6989. linkPath := filepath.Join(homeBasePath, defaultUsername, testDir)
  6990. err = os.Symlink(homeBasePath, linkPath)
  6991. assert.NoError(t, err)
  6992. testFilePath := filepath.Join(homeBasePath, testFileName)
  6993. testFileSize := int64(65535)
  6994. err = createTestFile(testFilePath, testFileSize)
  6995. assert.NoError(t, err)
  6996. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join(testDir, testDir))
  6997. err = scpUpload(testFilePath, remoteUpPath, false, false)
  6998. assert.Error(t, err, "uploading to a dir with a symlink outside home dir must fail")
  6999. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testDir, testFileName))
  7000. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  7001. err = scpDownload(localPath, remoteDownPath, false, false)
  7002. assert.Error(t, err, "scp download must fail, the requested file has a symlink outside user home")
  7003. remoteDownPath = fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testDir))
  7004. err = scpDownload(homeBasePath, remoteDownPath, false, true)
  7005. assert.Error(t, err, "scp download must fail, the requested dir is a symlink outside user home")
  7006. err = os.Remove(testFilePath)
  7007. assert.NoError(t, err)
  7008. err = os.RemoveAll(user.GetHomeDir())
  7009. assert.NoError(t, err)
  7010. _, err = httpd.RemoveUser(user, http.StatusOK)
  7011. assert.NoError(t, err)
  7012. }
  7013. func TestSCPUploadPaths(t *testing.T) {
  7014. if len(scpPath) == 0 {
  7015. t.Skip("scp command not found, unable to execute this test")
  7016. }
  7017. usePubKey := true
  7018. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  7019. assert.NoError(t, err)
  7020. testFilePath := filepath.Join(homeBasePath, testFileName)
  7021. testFileSize := int64(65535)
  7022. testDirName := "testDir"
  7023. testDirPath := filepath.Join(user.GetHomeDir(), testDirName)
  7024. err = os.MkdirAll(testDirPath, os.ModePerm)
  7025. assert.NoError(t, err)
  7026. err = createTestFile(testFilePath, testFileSize)
  7027. assert.NoError(t, err)
  7028. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, testDirName)
  7029. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join(testDirName, testFileName))
  7030. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  7031. err = scpUpload(testFilePath, remoteUpPath, false, false)
  7032. assert.NoError(t, err)
  7033. err = scpDownload(localPath, remoteDownPath, false, false)
  7034. assert.NoError(t, err)
  7035. // upload a file to a missing dir
  7036. remoteUpPath = fmt.Sprintf("%[email protected]:%v", user.Username, path.Join(testDirName, testDirName, testFileName))
  7037. err = scpUpload(testFilePath, remoteUpPath, false, false)
  7038. assert.Error(t, err, "scp upload to a missing dir must fail")
  7039. err = os.RemoveAll(user.GetHomeDir())
  7040. assert.NoError(t, err)
  7041. err = os.Remove(localPath)
  7042. assert.NoError(t, err)
  7043. _, err = httpd.RemoveUser(user, http.StatusOK)
  7044. assert.NoError(t, err)
  7045. }
  7046. func TestSCPOverwriteDirWithFile(t *testing.T) {
  7047. if len(scpPath) == 0 {
  7048. t.Skip("scp command not found, unable to execute this test")
  7049. }
  7050. usePubKey := true
  7051. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  7052. assert.NoError(t, err)
  7053. testFilePath := filepath.Join(homeBasePath, testFileName)
  7054. testFileSize := int64(65535)
  7055. testDirPath := filepath.Join(user.GetHomeDir(), testFileName)
  7056. err = os.MkdirAll(testDirPath, os.ModePerm)
  7057. assert.NoError(t, err)
  7058. err = createTestFile(testFilePath, testFileSize)
  7059. assert.NoError(t, err)
  7060. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/")
  7061. err = scpUpload(testFilePath, remoteUpPath, false, false)
  7062. assert.Error(t, err, "copying a file over an existing dir must fail")
  7063. err = os.RemoveAll(user.GetHomeDir())
  7064. assert.NoError(t, err)
  7065. _, err = httpd.RemoveUser(user, http.StatusOK)
  7066. assert.NoError(t, err)
  7067. }
  7068. func TestSCPRemoteToRemote(t *testing.T) {
  7069. if len(scpPath) == 0 {
  7070. t.Skip("scp command not found, unable to execute this test")
  7071. }
  7072. if runtime.GOOS == osWindows {
  7073. t.Skip("scp between remote hosts is not supported on Windows")
  7074. }
  7075. usePubKey := true
  7076. user, _, err := httpd.AddUser(getTestUser(usePubKey), http.StatusOK)
  7077. assert.NoError(t, err)
  7078. u := getTestUser(usePubKey)
  7079. u.Username += "1"
  7080. u.HomeDir += "1"
  7081. user1, _, err := httpd.AddUser(u, http.StatusOK)
  7082. assert.NoError(t, err)
  7083. testFilePath := filepath.Join(homeBasePath, testFileName)
  7084. testFileSize := int64(65535)
  7085. err = createTestFile(testFilePath, testFileSize)
  7086. assert.NoError(t, err)
  7087. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  7088. remote1UpPath := fmt.Sprintf("%[email protected]:%v", user1.Username, path.Join("/", testFileName))
  7089. err = scpUpload(testFilePath, remoteUpPath, false, false)
  7090. assert.NoError(t, err)
  7091. err = scpUpload(remoteUpPath, remote1UpPath, false, true)
  7092. assert.NoError(t, err)
  7093. err = os.RemoveAll(user.GetHomeDir())
  7094. assert.NoError(t, err)
  7095. _, err = httpd.RemoveUser(user, http.StatusOK)
  7096. assert.NoError(t, err)
  7097. err = os.RemoveAll(user1.GetHomeDir())
  7098. assert.NoError(t, err)
  7099. _, err = httpd.RemoveUser(user1, http.StatusOK)
  7100. assert.NoError(t, err)
  7101. }
  7102. func TestSCPErrors(t *testing.T) {
  7103. if len(scpPath) == 0 {
  7104. t.Skip("scp command not found, unable to execute this test")
  7105. }
  7106. u := getTestUser(true)
  7107. user, _, err := httpd.AddUser(u, http.StatusOK)
  7108. assert.NoError(t, err)
  7109. testFileSize := int64(524288)
  7110. testFilePath := filepath.Join(homeBasePath, testFileName)
  7111. err = createTestFile(testFilePath, testFileSize)
  7112. assert.NoError(t, err)
  7113. remoteUpPath := fmt.Sprintf("%[email protected]:%v", user.Username, "/")
  7114. remoteDownPath := fmt.Sprintf("%[email protected]:%v", user.Username, path.Join("/", testFileName))
  7115. localPath := filepath.Join(homeBasePath, "scp_download.dat")
  7116. err = scpUpload(testFilePath, remoteUpPath, false, false)
  7117. assert.NoError(t, err)
  7118. user.UploadBandwidth = 512
  7119. user.DownloadBandwidth = 512
  7120. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  7121. assert.NoError(t, err)
  7122. cmd := getScpDownloadCommand(localPath, remoteDownPath, false, false)
  7123. go func() {
  7124. err := cmd.Run()
  7125. assert.Error(t, err, "SCP download must fail")
  7126. }()
  7127. waitForActiveTransfers(t)
  7128. // wait some additional arbitrary time to wait for transfer activity to happen
  7129. // it is need to reach all the code in CheckIdleConnections
  7130. time.Sleep(100 * time.Millisecond)
  7131. err = cmd.Process.Kill()
  7132. assert.NoError(t, err)
  7133. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 }, 2*time.Second, 100*time.Millisecond)
  7134. cmd = getScpUploadCommand(testFilePath, remoteUpPath, false, false)
  7135. go func() {
  7136. err := cmd.Run()
  7137. assert.Error(t, err, "SCP upload must fail")
  7138. }()
  7139. waitForActiveTransfers(t)
  7140. // wait some additional arbitrary time to wait for transfer activity to happen
  7141. // it is need to reach all the code in CheckIdleConnections
  7142. time.Sleep(100 * time.Millisecond)
  7143. err = cmd.Process.Kill()
  7144. assert.NoError(t, err)
  7145. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 }, 2*time.Second, 100*time.Millisecond)
  7146. err = os.Remove(testFilePath)
  7147. assert.NoError(t, err)
  7148. os.Remove(localPath)
  7149. err = os.RemoveAll(user.GetHomeDir())
  7150. assert.NoError(t, err)
  7151. _, err = httpd.RemoveUser(user, http.StatusOK)
  7152. assert.NoError(t, err)
  7153. }
  7154. // End SCP tests
  7155. func waitTCPListening(address string) {
  7156. for {
  7157. conn, err := net.Dial("tcp", address)
  7158. if err != nil {
  7159. logger.WarnToConsole("tcp server %v not listening: %v\n", address, err)
  7160. time.Sleep(100 * time.Millisecond)
  7161. continue
  7162. }
  7163. logger.InfoToConsole("tcp server %v now listening\n", address)
  7164. conn.Close()
  7165. break
  7166. }
  7167. }
  7168. func getTestUser(usePubKey bool) dataprovider.User {
  7169. user := dataprovider.User{
  7170. Username: defaultUsername,
  7171. Password: defaultPassword,
  7172. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  7173. Status: 1,
  7174. ExpirationDate: 0,
  7175. }
  7176. user.Permissions = make(map[string][]string)
  7177. user.Permissions["/"] = allPerms
  7178. if usePubKey {
  7179. user.PublicKeys = []string{testPubKey}
  7180. user.Password = ""
  7181. }
  7182. return user
  7183. }
  7184. func runSSHCommand(command string, user dataprovider.User, usePubKey bool) ([]byte, error) {
  7185. var sshSession *ssh.Session
  7186. var output []byte
  7187. config := &ssh.ClientConfig{
  7188. User: user.Username,
  7189. HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
  7190. return nil
  7191. },
  7192. }
  7193. if usePubKey {
  7194. key, err := ssh.ParsePrivateKey([]byte(testPrivateKey))
  7195. if err != nil {
  7196. return output, err
  7197. }
  7198. config.Auth = []ssh.AuthMethod{ssh.PublicKeys(key)}
  7199. } else {
  7200. config.Auth = []ssh.AuthMethod{ssh.Password(defaultPassword)}
  7201. }
  7202. conn, err := ssh.Dial("tcp", sftpServerAddr, config)
  7203. if err != nil {
  7204. return output, err
  7205. }
  7206. defer conn.Close()
  7207. sshSession, err = conn.NewSession()
  7208. if err != nil {
  7209. return output, err
  7210. }
  7211. var stdout, stderr bytes.Buffer
  7212. sshSession.Stdout = &stdout
  7213. sshSession.Stderr = &stderr
  7214. err = sshSession.Run(command)
  7215. if err != nil {
  7216. return nil, fmt.Errorf("failed to run command %v: %v", command, stderr.Bytes())
  7217. }
  7218. return stdout.Bytes(), err
  7219. }
  7220. func getSignerForUserCert(certBytes []byte) (ssh.Signer, error) {
  7221. signer, err := ssh.ParsePrivateKey([]byte(testPrivateKey))
  7222. if err != nil {
  7223. return nil, err
  7224. }
  7225. cert, _, _, _, err := ssh.ParseAuthorizedKey(certBytes) //nolint:dogsled
  7226. if err != nil {
  7227. return nil, err
  7228. }
  7229. return ssh.NewCertSigner(cert.(*ssh.Certificate), signer)
  7230. }
  7231. func getSftpClientWithAddr(user dataprovider.User, usePubKey bool, addr string) (*sftp.Client, error) {
  7232. var sftpClient *sftp.Client
  7233. config := &ssh.ClientConfig{
  7234. User: user.Username,
  7235. HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
  7236. return nil
  7237. },
  7238. }
  7239. if usePubKey {
  7240. signer, err := ssh.ParsePrivateKey([]byte(testPrivateKey))
  7241. if err != nil {
  7242. return nil, err
  7243. }
  7244. config.Auth = []ssh.AuthMethod{ssh.PublicKeys(signer)}
  7245. } else {
  7246. if len(user.Password) > 0 {
  7247. config.Auth = []ssh.AuthMethod{ssh.Password(user.Password)}
  7248. } else {
  7249. config.Auth = []ssh.AuthMethod{ssh.Password(defaultPassword)}
  7250. }
  7251. }
  7252. conn, err := ssh.Dial("tcp", addr, config)
  7253. if err != nil {
  7254. return sftpClient, err
  7255. }
  7256. sftpClient, err = sftp.NewClient(conn)
  7257. return sftpClient, err
  7258. }
  7259. func getSftpClient(user dataprovider.User, usePubKey bool) (*sftp.Client, error) {
  7260. return getSftpClientWithAddr(user, usePubKey, sftpServerAddr)
  7261. }
  7262. func getKeyboardInteractiveSftpClient(user dataprovider.User, answers []string) (*sftp.Client, error) {
  7263. var sftpClient *sftp.Client
  7264. config := &ssh.ClientConfig{
  7265. User: user.Username,
  7266. HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
  7267. return nil
  7268. },
  7269. Auth: []ssh.AuthMethod{
  7270. ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) ([]string, error) {
  7271. return answers, nil
  7272. }),
  7273. },
  7274. }
  7275. conn, err := ssh.Dial("tcp", sftpServerAddr, config)
  7276. if err != nil {
  7277. return sftpClient, err
  7278. }
  7279. sftpClient, err = sftp.NewClient(conn)
  7280. return sftpClient, err
  7281. }
  7282. func getCustomAuthSftpClient(user dataprovider.User, authMethods []ssh.AuthMethod, addr string) (*sftp.Client, error) {
  7283. var sftpClient *sftp.Client
  7284. config := &ssh.ClientConfig{
  7285. User: user.Username,
  7286. HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
  7287. return nil
  7288. },
  7289. Auth: authMethods,
  7290. }
  7291. var err error
  7292. var conn *ssh.Client
  7293. if len(addr) > 0 {
  7294. conn, err = ssh.Dial("tcp", addr, config)
  7295. } else {
  7296. conn, err = ssh.Dial("tcp", sftpServerAddr, config)
  7297. }
  7298. if err != nil {
  7299. return sftpClient, err
  7300. }
  7301. sftpClient, err = sftp.NewClient(conn)
  7302. return sftpClient, err
  7303. }
  7304. func createTestFile(path string, size int64) error {
  7305. baseDir := filepath.Dir(path)
  7306. if _, err := os.Stat(baseDir); os.IsNotExist(err) {
  7307. err = os.MkdirAll(baseDir, os.ModePerm)
  7308. if err != nil {
  7309. return err
  7310. }
  7311. }
  7312. content := make([]byte, size)
  7313. _, err := rand.Read(content)
  7314. if err != nil {
  7315. return err
  7316. }
  7317. return ioutil.WriteFile(path, content, os.ModePerm)
  7318. }
  7319. func appendToTestFile(path string, size int64) error {
  7320. content := make([]byte, size)
  7321. _, err := rand.Read(content)
  7322. if err != nil {
  7323. return err
  7324. }
  7325. f, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, os.ModePerm)
  7326. if err != nil {
  7327. return err
  7328. }
  7329. defer f.Close()
  7330. written, err := io.Copy(f, bytes.NewReader(content))
  7331. if err != nil {
  7332. return err
  7333. }
  7334. if written != size {
  7335. return fmt.Errorf("write error, written: %v/%v", written, size)
  7336. }
  7337. return nil
  7338. }
  7339. func checkBasicSFTP(client *sftp.Client) error {
  7340. _, err := client.Getwd()
  7341. if err != nil {
  7342. return err
  7343. }
  7344. _, err = client.ReadDir(".")
  7345. return err
  7346. }
  7347. func sftpUploadFile(localSourcePath string, remoteDestPath string, expectedSize int64, client *sftp.Client) error {
  7348. srcFile, err := os.Open(localSourcePath)
  7349. if err != nil {
  7350. return err
  7351. }
  7352. defer srcFile.Close()
  7353. destFile, err := client.Create(remoteDestPath)
  7354. if err != nil {
  7355. return err
  7356. }
  7357. _, err = io.Copy(destFile, srcFile)
  7358. if err != nil {
  7359. destFile.Close()
  7360. return err
  7361. }
  7362. // we need to close the file to trigger the close method on server
  7363. // we cannot defer closing or Lstat will fail for uploads in atomic mode
  7364. destFile.Close()
  7365. if expectedSize > 0 {
  7366. fi, err := client.Stat(remoteDestPath)
  7367. if err != nil {
  7368. return err
  7369. }
  7370. if fi.Size() != expectedSize {
  7371. return fmt.Errorf("uploaded file size does not match, actual: %v, expected: %v", fi.Size(), expectedSize)
  7372. }
  7373. }
  7374. return err
  7375. }
  7376. func sftpUploadResumeFile(localSourcePath string, remoteDestPath string, expectedSize int64, invalidOffset bool,
  7377. client *sftp.Client) error {
  7378. srcFile, err := os.Open(localSourcePath)
  7379. if err != nil {
  7380. return err
  7381. }
  7382. defer srcFile.Close()
  7383. fi, err := client.Lstat(remoteDestPath)
  7384. if err != nil {
  7385. return err
  7386. }
  7387. if !invalidOffset {
  7388. _, err = srcFile.Seek(fi.Size(), 0)
  7389. if err != nil {
  7390. return err
  7391. }
  7392. }
  7393. destFile, err := client.OpenFile(remoteDestPath, os.O_WRONLY|os.O_APPEND)
  7394. if err != nil {
  7395. return err
  7396. }
  7397. if !invalidOffset {
  7398. _, err = destFile.Seek(fi.Size(), 0)
  7399. if err != nil {
  7400. return err
  7401. }
  7402. }
  7403. _, err = io.Copy(destFile, srcFile)
  7404. if err != nil {
  7405. destFile.Close()
  7406. return err
  7407. }
  7408. // we need to close the file to trigger the close method on server
  7409. // we cannot defer closing or Lstat will fail for upload atomic mode
  7410. destFile.Close()
  7411. if expectedSize > 0 {
  7412. fi, err := client.Lstat(remoteDestPath)
  7413. if err != nil {
  7414. return err
  7415. }
  7416. if fi.Size() != expectedSize {
  7417. return fmt.Errorf("uploaded file size does not match, actual: %v, expected: %v", fi.Size(), expectedSize)
  7418. }
  7419. }
  7420. return err
  7421. }
  7422. func sftpDownloadFile(remoteSourcePath string, localDestPath string, expectedSize int64, client *sftp.Client) error {
  7423. downloadDest, err := os.Create(localDestPath)
  7424. if err != nil {
  7425. return err
  7426. }
  7427. defer downloadDest.Close()
  7428. sftpSrcFile, err := client.Open(remoteSourcePath)
  7429. if err != nil {
  7430. return err
  7431. }
  7432. defer sftpSrcFile.Close()
  7433. _, err = io.Copy(downloadDest, sftpSrcFile)
  7434. if err != nil {
  7435. return err
  7436. }
  7437. err = downloadDest.Sync()
  7438. if err != nil {
  7439. return err
  7440. }
  7441. if expectedSize > 0 {
  7442. fi, err := downloadDest.Stat()
  7443. if err != nil {
  7444. return err
  7445. }
  7446. if fi.Size() != expectedSize {
  7447. return fmt.Errorf("downloaded file size does not match, actual: %v, expected: %v", fi.Size(), expectedSize)
  7448. }
  7449. }
  7450. return err
  7451. }
  7452. func sftpUploadNonBlocking(localSourcePath string, remoteDestPath string, expectedSize int64, client *sftp.Client) <-chan error {
  7453. c := make(chan error)
  7454. go func() {
  7455. c <- sftpUploadFile(localSourcePath, remoteDestPath, expectedSize, client)
  7456. }()
  7457. return c
  7458. }
  7459. func sftpDownloadNonBlocking(remoteSourcePath string, localDestPath string, expectedSize int64, client *sftp.Client) <-chan error {
  7460. c := make(chan error)
  7461. go func() {
  7462. c <- sftpDownloadFile(remoteSourcePath, localDestPath, expectedSize, client)
  7463. }()
  7464. return c
  7465. }
  7466. func scpUpload(localPath, remotePath string, preserveTime, remoteToRemote bool) error {
  7467. cmd := getScpUploadCommand(localPath, remotePath, preserveTime, remoteToRemote)
  7468. return cmd.Run()
  7469. }
  7470. func scpDownload(localPath, remotePath string, preserveTime, recursive bool) error {
  7471. cmd := getScpDownloadCommand(localPath, remotePath, preserveTime, recursive)
  7472. return cmd.Run()
  7473. }
  7474. func getScpDownloadCommand(localPath, remotePath string, preserveTime, recursive bool) *exec.Cmd {
  7475. var args []string
  7476. if preserveTime {
  7477. args = append(args, "-p")
  7478. }
  7479. if recursive {
  7480. args = append(args, "-r")
  7481. }
  7482. args = append(args, "-P")
  7483. args = append(args, "2022")
  7484. args = append(args, "-o")
  7485. args = append(args, "StrictHostKeyChecking=no")
  7486. args = append(args, "-i")
  7487. args = append(args, privateKeyPath)
  7488. args = append(args, remotePath)
  7489. args = append(args, localPath)
  7490. return exec.Command(scpPath, args...)
  7491. }
  7492. func getScpUploadCommand(localPath, remotePath string, preserveTime, remoteToRemote bool) *exec.Cmd {
  7493. var args []string
  7494. if remoteToRemote {
  7495. args = append(args, "-3")
  7496. }
  7497. if preserveTime {
  7498. args = append(args, "-p")
  7499. }
  7500. fi, err := os.Stat(localPath)
  7501. if err == nil {
  7502. if fi.IsDir() {
  7503. args = append(args, "-r")
  7504. }
  7505. }
  7506. args = append(args, "-P")
  7507. args = append(args, "2022")
  7508. args = append(args, "-o")
  7509. args = append(args, "StrictHostKeyChecking=no")
  7510. args = append(args, "-i")
  7511. args = append(args, privateKeyPath)
  7512. args = append(args, localPath)
  7513. args = append(args, remotePath)
  7514. return exec.Command(scpPath, args...)
  7515. }
  7516. func computeHashForFile(hasher hash.Hash, path string) (string, error) {
  7517. hash := ""
  7518. f, err := os.Open(path)
  7519. if err != nil {
  7520. return hash, err
  7521. }
  7522. defer f.Close()
  7523. _, err = io.Copy(hasher, f)
  7524. if err == nil {
  7525. hash = fmt.Sprintf("%x", hasher.Sum(nil))
  7526. }
  7527. return hash, err
  7528. }
  7529. func waitForActiveTransfers(t *testing.T) {
  7530. assert.Eventually(t, func() bool {
  7531. for _, stat := range common.Connections.GetStats() {
  7532. if len(stat.Transfers) > 0 {
  7533. return true
  7534. }
  7535. }
  7536. return false
  7537. }, 1*time.Second, 50*time.Millisecond)
  7538. }
  7539. func checkSystemCommands() {
  7540. var err error
  7541. gitPath, err = exec.LookPath("git")
  7542. if err != nil {
  7543. logger.Warn(logSender, "", "unable to get git command. GIT tests will be skipped, err: %v", err)
  7544. logger.WarnToConsole("unable to get git command. GIT tests will be skipped, err: %v", err)
  7545. gitPath = ""
  7546. }
  7547. sshPath, err = exec.LookPath("ssh")
  7548. if err != nil {
  7549. logger.Warn(logSender, "", "unable to get ssh command. GIT tests will be skipped, err: %v", err)
  7550. logger.WarnToConsole("unable to get ssh command. GIT tests will be skipped, err: %v", err)
  7551. gitPath = ""
  7552. }
  7553. hookCmdPath, err = exec.LookPath("true")
  7554. if err != nil {
  7555. logger.Warn(logSender, "", "unable to get hook command: %v", err)
  7556. logger.WarnToConsole("unable to get hook command: %v", err)
  7557. }
  7558. scpPath, err = exec.LookPath("scp")
  7559. if err != nil {
  7560. logger.Warn(logSender, "", "unable to get scp command. SCP tests will be skipped, err: %v", err)
  7561. logger.WarnToConsole("unable to get scp command. SCP tests will be skipped, err: %v", err)
  7562. scpPath = ""
  7563. }
  7564. }
  7565. func initGitRepo(path string) ([]byte, error) {
  7566. err := os.MkdirAll(path, os.ModePerm)
  7567. if err != nil {
  7568. return nil, err
  7569. }
  7570. args := []string{"init", "--bare"}
  7571. cmd := exec.Command(gitPath, args...)
  7572. cmd.Dir = path
  7573. return cmd.CombinedOutput()
  7574. }
  7575. func pushToGitRepo(repoPath string) ([]byte, error) {
  7576. cmd := exec.Command(gitPath, "push")
  7577. cmd.Dir = repoPath
  7578. cmd.Env = append(os.Environ(),
  7579. fmt.Sprintf("GIT_SSH=%v", gitWrapPath))
  7580. return cmd.CombinedOutput()
  7581. }
  7582. func cloneGitRepo(basePath, remotePath, username string) ([]byte, error) {
  7583. remoteURL := fmt.Sprintf("ssh://%[email protected]:2022%v", username, remotePath)
  7584. args := []string{"clone", remoteURL}
  7585. cmd := exec.Command(gitPath, args...)
  7586. cmd.Dir = basePath
  7587. cmd.Env = append(os.Environ(),
  7588. fmt.Sprintf("GIT_SSH=%v", gitWrapPath))
  7589. return cmd.CombinedOutput()
  7590. }
  7591. func addFileToGitRepo(repoPath string, fileSize int64) ([]byte, error) {
  7592. path := filepath.Join(repoPath, "test")
  7593. err := createTestFile(path, fileSize)
  7594. if err != nil {
  7595. return []byte(""), err
  7596. }
  7597. cmd := exec.Command(gitPath, "config", "user.email", "[email protected]")
  7598. cmd.Dir = repoPath
  7599. out, err := cmd.CombinedOutput()
  7600. if err != nil {
  7601. return out, err
  7602. }
  7603. cmd = exec.Command(gitPath, "config", "user.name", "testuser")
  7604. cmd.Dir = repoPath
  7605. out, err = cmd.CombinedOutput()
  7606. if err != nil {
  7607. return out, err
  7608. }
  7609. cmd = exec.Command(gitPath, "add", "test")
  7610. cmd.Dir = repoPath
  7611. out, err = cmd.CombinedOutput()
  7612. if err != nil {
  7613. return out, err
  7614. }
  7615. cmd = exec.Command(gitPath, "commit", "-am", "test")
  7616. cmd.Dir = repoPath
  7617. return cmd.CombinedOutput()
  7618. }
  7619. func getKeyboardInteractiveScriptContent(questions []string, sleepTime int, nonJSONResponse bool, result int) []byte {
  7620. content := []byte("#!/bin/sh\n\n")
  7621. q, _ := json.Marshal(questions)
  7622. echos := []bool{}
  7623. for index := range questions {
  7624. echos = append(echos, index%2 == 0)
  7625. }
  7626. e, _ := json.Marshal(echos)
  7627. if nonJSONResponse {
  7628. content = append(content, []byte(fmt.Sprintf("echo 'questions: %v echos: %v\n", string(q), string(e)))...)
  7629. } else {
  7630. content = append(content, []byte(fmt.Sprintf("echo '{\"questions\":%v,\"echos\":%v}'\n", string(q), string(e)))...)
  7631. }
  7632. for index := range questions {
  7633. content = append(content, []byte(fmt.Sprintf("read ANSWER%v\n", index))...)
  7634. }
  7635. if sleepTime > 0 {
  7636. content = append(content, []byte(fmt.Sprintf("sleep %v\n", sleepTime))...)
  7637. }
  7638. content = append(content, []byte(fmt.Sprintf("echo '{\"auth_result\":%v}'\n", result))...)
  7639. return content
  7640. }
  7641. func getExtAuthScriptContent(user dataprovider.User, nonJSONResponse bool, username string) []byte {
  7642. extAuthContent := []byte("#!/bin/sh\n\n")
  7643. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("if test \"$SFTPGO_AUTHD_USERNAME\" = \"%v\"; then\n", user.Username))...)
  7644. if len(username) > 0 {
  7645. user.Username = username
  7646. }
  7647. u, _ := json.Marshal(user)
  7648. if nonJSONResponse {
  7649. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  7650. } else {
  7651. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  7652. }
  7653. extAuthContent = append(extAuthContent, []byte("else\n")...)
  7654. if nonJSONResponse {
  7655. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  7656. } else {
  7657. extAuthContent = append(extAuthContent, []byte("echo '{\"username\":\"\"}'\n")...)
  7658. }
  7659. extAuthContent = append(extAuthContent, []byte("fi\n")...)
  7660. return extAuthContent
  7661. }
  7662. func getPreLoginScriptContent(user dataprovider.User, nonJSONResponse bool) []byte {
  7663. content := []byte("#!/bin/sh\n\n")
  7664. if nonJSONResponse {
  7665. content = append(content, []byte("echo 'text response'\n")...)
  7666. return content
  7667. }
  7668. if len(user.Username) > 0 {
  7669. u, _ := json.Marshal(user)
  7670. content = append(content, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  7671. }
  7672. return content
  7673. }
  7674. func getPostConnectScriptContent(exitCode int) []byte {
  7675. content := []byte("#!/bin/sh\n\n")
  7676. content = append(content, []byte(fmt.Sprintf("exit %v", exitCode))...)
  7677. return content
  7678. }
  7679. func getCheckPwdScriptsContents(status int, toVerify string) []byte {
  7680. content := []byte("#!/bin/sh\n\n")
  7681. content = append(content, []byte(fmt.Sprintf("echo '{\"status\":%v,\"to_verify\":\"%v\"}'\n", status, toVerify))...)
  7682. if status > 0 {
  7683. content = append(content, []byte("exit 0")...)
  7684. } else {
  7685. content = append(content, []byte("exit 1")...)
  7686. }
  7687. return content
  7688. }
  7689. func printLatestLogs(maxNumberOfLines int) {
  7690. var lines []string
  7691. f, err := os.Open(logFilePath)
  7692. if err != nil {
  7693. return
  7694. }
  7695. defer f.Close()
  7696. scanner := bufio.NewScanner(f)
  7697. for scanner.Scan() {
  7698. lines = append(lines, scanner.Text()+"\r\n")
  7699. for len(lines) > maxNumberOfLines {
  7700. lines = lines[1:]
  7701. }
  7702. }
  7703. if scanner.Err() != nil {
  7704. logger.WarnToConsole("Unable to print latest logs: %v", scanner.Err())
  7705. return
  7706. }
  7707. for _, line := range lines {
  7708. logger.DebugToConsole(line)
  7709. }
  7710. }