| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343 |
- // SoftEther VPN Source Code
- // Cedar Communication Module
- //
- // SoftEther VPN Server, Client and Bridge are free software under GPLv2.
- //
- // Copyright (c) 2012-2016 Daiyuu Nobori.
- // Copyright (c) 2012-2016 SoftEther VPN Project, University of Tsukuba, Japan.
- // Copyright (c) 2012-2016 SoftEther Corporation.
- //
- // All Rights Reserved.
- //
- // http://www.softether.org/
- //
- // Author: Daiyuu Nobori
- // Comments: Tetsuo Sugiyama, Ph.D.
- //
- // This program is free software; you can redistribute it and/or
- // modify it under the terms of the GNU General Public License
- // version 2 as published by the Free Software Foundation.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License version 2
- // along with this program; if not, write to the Free Software
- // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- // THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
- // AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
- //
- //
- // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
- // UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
- // MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
- // SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
- // SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
- // CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
- // DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
- // MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
- // SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
- // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
- // EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
- // JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
- // AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
- // THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
- //
- // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS
- // YOU HAVE A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY
- // CRIMINAL LAWS OR CIVIL RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS
- // SOFTWARE IN OTHER COUNTRIES IS COMPLETELY AT YOUR OWN RISK. THE
- // SOFTETHER VPN PROJECT HAS DEVELOPED AND DISTRIBUTED THIS SOFTWARE TO
- // COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING CIVIL RIGHTS INCLUDING
- // PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER COUNTRIES' LAWS OR
- // CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES. WE HAVE
- // NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
- // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+
- // COUNTRIES AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE
- // WORLD, WITH DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY
- // COUNTRIES' LAWS, REGULATIONS AND CIVIL RIGHTS TO MAKE THE SOFTWARE
- // COMPLY WITH ALL COUNTRIES' LAWS BY THE PROJECT. EVEN IF YOU WILL BE
- // SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A PUBLIC SERVANT IN YOUR
- // COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE LIABLE TO
- // RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
- // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT
- // JUST A STATEMENT FOR WARNING AND DISCLAIMER.
- //
- //
- // SOURCE CODE CONTRIBUTION
- // ------------------------
- //
- // Your contribution to SoftEther VPN Project is much appreciated.
- // Please send patches to us through GitHub.
- // Read the SoftEther VPN Patch Acceptance Policy in advance:
- // http://www.softether.org/5-download/src/9.patch
- //
- //
- // DEAR SECURITY EXPERTS
- // ---------------------
- //
- // If you find a bug or a security vulnerability please kindly inform us
- // about the problem immediately so that we can fix the security problem
- // to protect a lot of users around the world as soon as possible.
- //
- // Our e-mail address for security reports is:
- // softether-vpn-security [at] softether.org
- //
- // Please note that the above e-mail address is not a technical support
- // inquiry address. If you need technical assistance, please visit
- // http://www.softether.org/ and ask your question on the users forum.
- //
- // Thank you for your cooperation.
- //
- //
- // NO MEMORY OR RESOURCE LEAKS
- // ---------------------------
- //
- // The memory-leaks and resource-leaks verification under the stress
- // test has been passed before release this source code.
- // Protocol.c
- // SoftEther protocol related routines
- #include "CedarPch.h"
- static UCHAR ssl_packet_start[3] = {0x17, 0x03, 0x00};
- // Download and save intermediate certificates if necessary
- bool DownloadAndSaveIntermediateCertificatesIfNecessary(X *x)
- {
- LIST *o;
- bool ret = false;
- // Validate arguments
- if (x == NULL)
- {
- return false;
- }
- if (x->root_cert)
- {
- return true;
- }
- o = NewCertList(true);
- ret = TryGetRootCertChain(o, x, true, NULL);
- FreeCertList(o);
- return ret;
- }
- // Attempt to fetch the full chain of the specified cert
- bool TryGetRootCertChain(LIST *o, X *x, bool auto_save, X **found_root_x)
- {
- bool ret = false;
- LIST *chain = NULL;
- LIST *current_chain_dir = NULL;
- // Validate arguments
- if (o == NULL || x == NULL)
- {
- return false;
- }
- chain = NewCertList(false);
- ret = TryGetParentCertFromCertList(o, x, chain);
- if (ret)
- {
- UINT i;
- DIRLIST *dir;
- wchar_t dirname[MAX_SIZE];
- wchar_t exedir[MAX_SIZE];
- GetExeDirW(exedir, sizeof(exedir));
- CombinePathW(dirname, sizeof(dirname), exedir, L"chain_certs");
- MakeDirExW(dirname);
- if (auto_save)
- {
- // delete the current auto_save files
- dir = EnumDirW(dirname);
- if (dir != NULL)
- {
- for (i = 0;i < dir->NumFiles;i++)
- {
- DIRENT *e = dir->File[i];
- if (e->Folder == false)
- {
- if (UniStartWith(e->FileNameW, AUTO_DOWNLOAD_CERTS_PREFIX))
- {
- wchar_t tmp[MAX_SIZE];
- CombinePathW(tmp, sizeof(tmp), dirname, e->FileNameW);
- FileDeleteW(tmp);
- }
- }
- }
- FreeDir(dir);
- }
- }
- current_chain_dir = NewCertList(false);
- AddAllChainCertsToCertList(current_chain_dir);
- for (i = 0;i < LIST_NUM(chain);i++)
- {
- wchar_t tmp[MAX_SIZE];
- X *xx = LIST_DATA(chain, i);
- GetAllNameFromName(tmp, sizeof(tmp), xx->subject_name);
- Debug("depth = %u, subject = %S\n", i, tmp);
- if (auto_save && CompareX(x, xx) == false && IsXInCertList(current_chain_dir, xx) == false)
- {
- wchar_t fn[MAX_PATH];
- char hex_a[128];
- wchar_t hex[128];
- UCHAR hash[SHA1_SIZE];
- wchar_t tmp[MAX_SIZE];
- BUF *b;
- GetXDigest(xx, hash, true);
- BinToStr(hex_a, sizeof(hex_a), hash, SHA1_SIZE);
- StrToUni(hex, sizeof(hex), hex_a);
- UniStrCpy(fn, sizeof(fn), AUTO_DOWNLOAD_CERTS_PREFIX);
- UniStrCat(fn, sizeof(fn), hex);
- UniStrCat(fn, sizeof(fn), L".cer");
- CombinePathW(tmp, sizeof(tmp), dirname, fn);
- b = XToBuf(xx, true);
- DumpBufW(b, tmp);
- FreeBuf(b);
- }
- if (xx->root_cert)
- {
- if (found_root_x != NULL)
- {
- *found_root_x = CloneX(xx);
- }
- }
- }
- }
- FreeCertList(chain);
- FreeCertList(current_chain_dir);
- return ret;
- }
- // Try get the parent cert
- bool TryGetParentCertFromCertList(LIST *o, X *x, LIST *found_chain)
- {
- bool ret = false;
- X *r;
- bool do_free = false;
- // Validate arguments
- if (o == NULL || x == NULL || found_chain == NULL)
- {
- return false;
- }
- if (LIST_NUM(found_chain) >= FIND_CERT_CHAIN_MAX_DEPTH)
- {
- return false;
- }
- Add(found_chain, CloneX(x));
- if (x->root_cert)
- {
- return true;
- }
- r = FindCertIssuerFromCertList(o, x);
- if (r == NULL)
- {
- if (IsEmptyStr(x->issuer_url) == false)
- {
- r = DownloadCert(x->issuer_url);
- if (CheckXEx(x, r, true, true) && CompareX(x, r) == false)
- {
- // found
- do_free = true;
- }
- else
- {
- // invalid
- FreeX(r);
- r = NULL;
- }
- }
- }
- if (r != NULL)
- {
- ret = TryGetParentCertFromCertList(o, r, found_chain);
- }
- if (do_free)
- {
- FreeX(r);
- }
- return ret;
- }
- // Find the issuer of the cert from the cert list
- X *FindCertIssuerFromCertList(LIST *o, X *x)
- {
- UINT i;
- // Validate arguments
- if (o == NULL || x == NULL)
- {
- return NULL;
- }
- if (x->root_cert)
- {
- return NULL;
- }
- for (i = 0;i < LIST_NUM(o);i++)
- {
- X *xx = LIST_DATA(o, i);
- if (CheckXEx(x, xx, true, true))
- {
- if (CompareX(x, xx) == false)
- {
- return xx;
- }
- }
- }
- return NULL;
- }
- // Download a cert by using HTTP
- X *DownloadCert(char *url)
- {
- BUF *b;
- URL_DATA url_data;
- X *ret = NULL;
- // Validate arguments
- if (IsEmptyStr(url))
- {
- return NULL;
- }
- Debug("Trying to download a cert from %s ...\n", url);
- if (ParseUrl(&url_data, url, false, NULL) == false)
- {
- Debug("Download failed.\n");
- return NULL;
- }
- b = HttpRequestEx(&url_data, NULL, CERT_HTTP_DOWNLOAD_TIMEOUT, CERT_HTTP_DOWNLOAD_TIMEOUT,
- NULL, false, NULL, NULL, NULL, NULL, NULL, CERT_HTTP_DOWNLOAD_MAXSIZE);
- if (b == NULL)
- {
- Debug("Download failed.\n");
- return NULL;
- }
- ret = BufToX(b, IsBase64(b));
- FreeBuf(b);
- Debug("Download ok.\n");
- return ret;
- }
- // New cert list
- LIST *NewCertList(bool load_root_and_chain)
- {
- LIST *o;
- o = NewList(NULL);
- if (load_root_and_chain)
- {
- AddAllRootCertsToCertList(o);
- AddAllChainCertsToCertList(o);
- }
- return o;
- }
- // Free cert list
- void FreeCertList(LIST *o)
- {
- UINT i;
- // Validate arguments
- if (o == NULL)
- {
- return;
- }
- for (i = 0;i < LIST_NUM(o);i++)
- {
- X *x = LIST_DATA(o, i);
- FreeX(x);
- }
- ReleaseList(o);
- }
- // Check whether the cert is in the cert list
- bool IsXInCertList(LIST *o, X *x)
- {
- UINT i;
- // Validate arguments
- if (o == NULL || x == NULL)
- {
- return false;
- }
- for (i = 0;i < LIST_NUM(o);i++)
- {
- X *xx = LIST_DATA(o, i);
- if (CompareX(x, xx))
- {
- return true;
- }
- }
- return false;
- }
- // Add a cert to the cert list
- void AddXToCertList(LIST *o, X *x)
- {
- // Validate arguments
- if (o == NULL || x == NULL)
- {
- return;
- }
- if (IsXInCertList(o, x))
- {
- return;
- }
- if (CheckXDateNow(x) == false)
- {
- return;
- }
- Add(o, CloneX(x));
- }
- // Add all chain certs to the cert list
- void AddAllChainCertsToCertList(LIST *o)
- {
- wchar_t dirname[MAX_SIZE];
- wchar_t exedir[MAX_SIZE];
- DIRLIST *dir;
- // Validate arguments
- if (o == NULL)
- {
- return;
- }
- GetExeDirW(exedir, sizeof(exedir));
- CombinePathW(dirname, sizeof(dirname), exedir, L"chain_certs");
- MakeDirExW(dirname);
- dir = EnumDirW(dirname);
- if (dir != NULL)
- {
- UINT i;
- for (i = 0;i < dir->NumFiles;i++)
- {
- DIRENT *e = dir->File[i];
- if (e->Folder == false)
- {
- wchar_t tmp[MAX_SIZE];
- X *x;
- CombinePathW(tmp, sizeof(tmp), dirname, e->FileNameW);
- x = FileToXW(tmp);
- if (x != NULL)
- {
- AddXToCertList(o, x);
- FreeX(x);
- }
- }
- }
- FreeDir(dir);
- }
- }
- // Add all root certs to the cert list
- void AddAllRootCertsToCertList(LIST *o)
- {
- BUF *buf;
- PACK *p;
- UINT num_ok = 0, num_error = 0;
- // Validate arguments
- if (o == NULL)
- {
- return;
- }
- buf = ReadDump(ROOT_CERTS_FILENAME);
- if (buf == NULL)
- {
- return;
- }
- p = BufToPack(buf);
- if (p != NULL)
- {
- UINT num = PackGetIndexCount(p, "cert");
- UINT i;
- for (i = 0;i < num;i++)
- {
- bool ok = false;
- BUF *b = PackGetBufEx(p, "cert", i);
- if (b != NULL)
- {
- X *x = BufToX(b, false);
- if (x != NULL)
- {
- AddXToCertList(o, x);
- ok = true;
- FreeX(x);
- }
- FreeBuf(b);
- }
- if (ok)
- {
- num_ok++;
- }
- else
- {
- num_error++;
- }
- }
- FreePack(p);
- }
- FreeBuf(buf);
- Debug("AddAllRootCertsToCertList: ok=%u error=%u total_list_len=%u\n", num_ok, num_error, LIST_NUM(o));
- }
- // Convert the date of YYYYMMDD format to a number
- UINT64 ShortStrToDate64(char *str)
- {
- UINT v;
- SYSTEMTIME st;
- // Validate arguments
- if (str == NULL)
- {
- return 0;
- }
- v = ToInt(str);
- Zero(&st, sizeof(st));
- st.wYear = (v % 100000000) / 10000;
- st.wMonth = (v % 10000) / 100;
- st.wDay = v % 100;
- return SystemToUINT64(&st);
- }
- // Handle the response that is returned from the server in the update client
- void UpdateClientThreadProcessResults(UPDATE_CLIENT *c, BUF *b)
- {
- bool exit = false;
- // Validate arguments
- if (c == NULL || b == NULL)
- {
- return;
- }
- SeekBufToBegin(b);
- while (true)
- {
- char *line = CfgReadNextLine(b);
- if (line == NULL)
- {
- break;
- }
- Trim(line);
- if (StartWith(line, "#") == false && IsEmptyStr(line) == false)
- {
- TOKEN_LIST *t = ParseTokenWithNullStr(line, " \t");
- if (t != NULL)
- {
- if (t->NumTokens >= 5)
- {
- if (StrCmpi(t->Token[0], c->FamilyName) == 0)
- {
- // Match
- UINT64 date = ShortStrToDate64(t->Token[1]);
- if (date != 0)
- {
- UINT build = ToInt(t->Token[2]);
- if (build != 0)
- {
- if (build > c->MyBuild && build > c->LatestBuild && build > c->Setting.LatestIgnoreBuild)
- {
- c->Callback(c, build, date, t->Token[3], t->Token[4], &c->HaltFlag, c->Param);
- c->LatestBuild = build;
- exit = true;
- }
- }
- }
- }
- }
- FreeToken(t);
- }
- }
- Free(line);
- if (exit)
- {
- break;
- }
- }
- }
- // Update client main process
- void UpdateClientThreadMain(UPDATE_CLIENT *c)
- {
- char url[MAX_SIZE];
- char id[MAX_SIZE];
- URL_DATA data;
- BUF *cert_hash;
- UINT ret = 0;
- BUF *recv;
- // Validate arguments
- if (c == NULL)
- {
- return;
- }
- // Generate the URL
- Format(url, sizeof(url), IsUseAlternativeHostname() ? UPDATE_SERVER_URL_CHINA : UPDATE_SERVER_URL_GLOBAL, c->FamilyName, c->SoftwareName, c->MyBuild, c->MyLanguage);
- if (IsEmptyStr(c->ClientId) == false)
- {
- Format(id, sizeof(id), "&id=%s", c->ClientId);
- StrCat(url, sizeof(url), id);
- }
- // Get a text file at this URL
- if (ParseUrl(&data, url, false, NULL) == false)
- {
- return;
- }
- cert_hash = StrToBin(UPDATE_SERVER_CERT_HASH);
- recv = HttpRequestEx2(&data, NULL, UPDATE_CONNECT_TIMEOUT, UPDATE_COMM_TIMEOUT, &ret, false, NULL, NULL,
- NULL, ((cert_hash != NULL && cert_hash->Size == SHA1_SIZE) ? cert_hash->Buf : NULL),
- (bool *)&c->HaltFlag, 0, NULL, NULL);
- FreeBuf(cert_hash);
- if (recv != NULL)
- {
- UpdateClientThreadProcessResults(c, recv);
- FreeBuf(recv);
- }
- }
- // Update client main thread
- void UpdateClientThreadProc(THREAD *thread, void *param)
- {
- UPDATE_CLIENT *c = (UPDATE_CLIENT *)param;
- bool first_loop = true;
- // Validate arguments
- if (thread == NULL || param == NULL)
- {
- return;
- }
- while (true)
- {
- // Termination check
- if (c->HaltFlag)
- {
- break;
- }
- if (first_loop == false)
- {
- // Wait for the foreground
- if (c->IsForegroundCb != NULL)
- {
- while (true)
- {
- if (c->HaltFlag)
- {
- break;
- }
- if (c->IsForegroundCb(c, c->Param))
- {
- break;
- }
- Wait(c->HaltEvent, 1000);
- }
- }
- }
- first_loop = false;
- if (c->HaltFlag)
- {
- break;
- }
- if (c->Setting.DisableCheck == false)
- {
- UpdateClientThreadMain(c);
- }
- // Wait until the next attempt
- Wait(c->HaltEvent, GenRandInterval(UPDATE_CHECK_INTERVAL_MIN, UPDATE_CHECK_INTERVAL_MAX));
- }
- }
- // Update the configuration of the update client
- void SetUpdateClientSetting(UPDATE_CLIENT *c, UPDATE_CLIENT_SETTING *s)
- {
- bool old_disable;
- // Validate arguments
- if (c == NULL || s == NULL)
- {
- return;
- }
- old_disable = c->Setting.DisableCheck;
- Copy(&c->Setting, s, sizeof(UPDATE_CLIENT_SETTING));
- Set(c->HaltEvent);
- }
- // Start the update client
- UPDATE_CLIENT *NewUpdateClient(UPDATE_NOTIFY_PROC *cb, UPDATE_ISFOREGROUND_PROC *isforeground_cb, void *param, char *family_name, char *software_name, wchar_t *software_title, UINT my_build, UINT64 my_date, char *my_lang, UPDATE_CLIENT_SETTING *current_setting, char *client_id)
- {
- UPDATE_CLIENT *c;
- // Validate arguments
- if (family_name == NULL || software_title == NULL || software_name == NULL || my_build == 0 ||
- my_lang == NULL || current_setting == NULL || cb == NULL)
- {
- return NULL;
- }
- c = ZeroMalloc(sizeof(UPDATE_CLIENT));
- c->Callback = cb;
- c->IsForegroundCb = isforeground_cb;
- StrCpy(c->ClientId, sizeof(c->ClientId), client_id);
- StrCpy(c->FamilyName, sizeof(c->FamilyName), family_name);
- StrCpy(c->SoftwareName, sizeof(c->SoftwareName), software_name);
- UniStrCpy(c->SoftwareTitle, sizeof(c->SoftwareTitle), software_title);
- c->MyBuild = my_build;
- c->MyDate = my_date;
- StrCpy(c->MyLanguage, sizeof(c->MyLanguage), my_lang);
- Copy(&c->Setting, current_setting, sizeof(c->Setting));
- c->Param = param;
- c->HaltEvent = NewEvent();
- // Create a thread
- c->Thread = NewThread(UpdateClientThreadProc, c);
- return c;
- }
- // Terminate the update client
- void FreeUpdateClient(UPDATE_CLIENT *c)
- {
- // Validate arguments
- if (c == NULL)
- {
- return;
- }
- // Thread stop
- c->HaltFlag = true;
- Set(c->HaltEvent);
- // Wait for thread termination
- WaitThread(c->Thread, INFINITE);
- ReleaseThread(c->Thread);
- ReleaseEvent(c->HaltEvent);
- Free(c);
- }
- // Generate unique IDs for each machine
- void GenerateMachineUniqueHash(void *data)
- {
- BUF *b;
- char name[64];
- OS_INFO *osinfo;
- UINT64 iphash = 0;
- // Validate arguments
- if (data == NULL)
- {
- return;
- }
- iphash = GetHostIPAddressListHash();
- b = NewBuf();
- GetMachineName(name, sizeof(name));
- osinfo = GetOsInfo();
- WriteBuf(b, name, StrLen(name));
- WriteBufInt64(b, iphash);
- WriteBuf(b, &osinfo->OsType, sizeof(osinfo->OsType));
- WriteBuf(b, osinfo->KernelName, StrLen(osinfo->KernelName));
- WriteBuf(b, osinfo->KernelVersion, StrLen(osinfo->KernelVersion));
- WriteBuf(b, osinfo->OsProductName, StrLen(osinfo->OsProductName));
- WriteBuf(b, &osinfo->OsServicePack, sizeof(osinfo->OsServicePack));
- WriteBuf(b, osinfo->OsSystemName, StrLen(osinfo->OsSystemName));
- WriteBuf(b, osinfo->OsVendorName, StrLen(osinfo->OsVendorName));
- WriteBuf(b, osinfo->OsVersion, StrLen(osinfo->OsVersion));
- Hash(data, b->Buf, b->Size, true);
- FreeBuf(b);
- }
- // Convert a node information to a string
- void NodeInfoToStr(wchar_t *str, UINT size, NODE_INFO *info)
- {
- char client_ip[128], server_ip[128], proxy_ip[128], unique_id[128];
- // Validate arguments
- if (str == NULL || info == NULL)
- {
- return;
- }
- IPToStr4or6(client_ip, sizeof(client_ip), info->ClientIpAddress, info->ClientIpAddress6);
- IPToStr4or6(server_ip, sizeof(server_ip), info->ServerIpAddress, info->ServerIpAddress6);
- IPToStr4or6(proxy_ip, sizeof(proxy_ip), info->ProxyIpAddress, info->ProxyIpAddress6);
- BinToStr(unique_id, sizeof(unique_id), info->UniqueId, sizeof(info->UniqueId));
- UniFormat(str, size, _UU("LS_NODE_INFO_TAG"), info->ClientProductName,
- Endian32(info->ClientProductVer), Endian32(info->ClientProductBuild),
- info->ServerProductName, Endian32(info->ServerProductVer), Endian32(info->ServerProductBuild),
- info->ClientOsName, info->ClientOsVer, info->ClientOsProductId,
- info->ClientHostname, client_ip, Endian32(info->ClientPort),
- info->ServerHostname, server_ip, Endian32(info->ServerPort),
- info->ProxyHostname, proxy_ip, Endian32(info->ProxyPort),
- info->HubName, unique_id);
- }
- // Comparison of node information
- bool CompareNodeInfo(NODE_INFO *a, NODE_INFO *b)
- {
- // Validate arguments
- if (a == NULL || b == NULL)
- {
- return false;
- }
- if (StrCmp(a->ClientProductName, b->ClientProductName) != 0)
- {
- return false;
- }
- if (a->ClientProductVer != b->ClientProductVer)
- {
- return false;
- }
- if (a->ClientProductBuild != b->ClientProductBuild)
- {
- return false;
- }
- if (StrCmp(a->ServerProductName, b->ServerProductName) != 0)
- {
- return false;
- }
- if (a->ServerProductVer != b->ServerProductVer)
- {
- return false;
- }
- if (a->ServerProductBuild != b->ServerProductBuild)
- {
- return false;
- }
- if (StrCmp(a->ClientOsName, b->ClientOsName) != 0)
- {
- return false;
- }
- if (StrCmp(a->ClientOsVer, b->ClientOsVer) != 0)
- {
- return false;
- }
- if (StrCmp(a->ClientOsProductId, b->ClientOsProductId) != 0)
- {
- return false;
- }
- if (StrCmp(a->ClientHostname, b->ClientHostname) != 0)
- {
- return false;
- }
- if (a->ClientIpAddress != b->ClientIpAddress)
- {
- return false;
- }
- if (StrCmp(a->ServerHostname, b->ServerHostname) != 0)
- {
- return false;
- }
- if (a->ServerIpAddress != b->ServerIpAddress)
- {
- return false;
- }
- if (a->ServerPort != b->ServerPort)
- {
- return false;
- }
- if (StrCmp(a->ProxyHostname, b->ProxyHostname) != 0)
- {
- return false;
- }
- if (a->ProxyIpAddress != b->ProxyIpAddress)
- {
- return false;
- }
- if (a->ProxyPort != b->ProxyPort)
- {
- return false;
- }
- if (StrCmp(a->HubName, b->HubName) != 0)
- {
- return false;
- }
- if (Cmp(a->UniqueId, b->UniqueId, 16) != 0)
- {
- return false;
- }
- return true;
- }
- // Accept the password change
- UINT ChangePasswordAccept(CONNECTION *c, PACK *p)
- {
- CEDAR *cedar;
- UCHAR random[SHA1_SIZE];
- char hubname[MAX_HUBNAME_LEN + 1];
- char username[MAX_USERNAME_LEN + 1];
- UCHAR secure_old_password[SHA1_SIZE];
- UCHAR new_password[SHA1_SIZE];
- UCHAR new_password_ntlm[SHA1_SIZE];
- UCHAR check_secure_old_password[SHA1_SIZE];
- UINT ret = ERR_NO_ERROR;
- HUB *hub;
- bool save = false;
- // Validate arguments
- if (c == NULL || p == NULL)
- {
- return ERR_INTERNAL_ERROR;
- }
- Copy(random, c->Random, SHA1_SIZE);
- if (PackGetStr(p, "hubname", hubname, sizeof(hubname)) == false ||
- PackGetStr(p, "username", username, sizeof(username)) == false ||
- PackGetData2(p, "secure_old_password", secure_old_password, sizeof(secure_old_password)) == false ||
- PackGetData2(p, "new_password", new_password, sizeof(new_password)) == false)
- {
- return ERR_PROTOCOL_ERROR;
- }
- if (PackGetData2(p, "new_password_ntlm", new_password_ntlm, MD5_SIZE) == false)
- {
- Zero(new_password_ntlm, sizeof(new_password_ntlm));
- }
- cedar = c->Cedar;
- LockHubList(cedar);
- {
- hub = GetHub(cedar, hubname);
- }
- UnlockHubList(cedar);
- if (hub == NULL)
- {
- ret = ERR_HUB_NOT_FOUND;
- }
- else
- {
- char tmp[MAX_SIZE];
- if (GetHubAdminOption(hub, "deny_change_user_password") != 0)
- {
- ReleaseHub(hub);
- return ERR_NOT_ENOUGH_RIGHT;
- }
- IPToStr(tmp, sizeof(tmp), &c->FirstSock->RemoteIP);
- HLog(hub, "LH_CHANGE_PASSWORD_1", c->Name, tmp);
- AcLock(hub);
- {
- USER *u = AcGetUser(hub, username);
- if (u == NULL)
- {
- HLog(hub, "LH_CHANGE_PASSWORD_2", c->Name, username);
- ret = ERR_OLD_PASSWORD_WRONG;
- }
- else
- {
- Lock(u->lock);
- {
- if (u->AuthType != AUTHTYPE_PASSWORD)
- {
- // Not a password authentication
- HLog(hub, "LH_CHANGE_PASSWORD_3", c->Name, username);
- ret = ERR_USER_AUTHTYPE_NOT_PASSWORD;
- }
- else
- {
- bool fix_password = false;
- if (u->Policy != NULL)
- {
- fix_password = u->Policy->FixPassword;
- }
- else
- {
- if (u->Group != NULL)
- {
- if (u->Group->Policy != NULL)
- {
- fix_password = u->Group->Policy->FixPassword;
- }
- }
- }
- if (fix_password == false)
- {
- // Confirmation of the old password
- AUTHPASSWORD *pw = (AUTHPASSWORD *)u->AuthData;
- SecurePassword(check_secure_old_password, pw->HashedKey, random);
- if (Cmp(check_secure_old_password, secure_old_password, SHA1_SIZE) != 0)
- {
- // Old password is incorrect
- ret = ERR_OLD_PASSWORD_WRONG;
- HLog(hub, "LH_CHANGE_PASSWORD_4", c->Name, username);
- }
- else
- {
- // Write a new password
- if (Cmp(pw->HashedKey, new_password, SHA1_SIZE) != 0 || IsZero(pw->NtLmSecureHash, MD5_SIZE))
- {
- Copy(pw->HashedKey, new_password, SHA1_SIZE);
- Copy(pw->NtLmSecureHash, new_password_ntlm, MD5_SIZE);
- }
- HLog(hub, "LH_CHANGE_PASSWORD_5", c->Name, username);
- save = true;
- }
- }
- else
- {
- // Password change is prohibited
- ret = ERR_NOT_ENOUGH_RIGHT;
- }
- }
- }
- Unlock(u->lock);
- ReleaseUser(u);
- }
- }
- AcUnlock(hub);
- ReleaseHub(hub);
- }
- return ret;
- }
- // Change the password
- UINT ChangePassword(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, char *username, char *old_pass, char *new_pass)
- {
- UINT ret = ERR_NO_ERROR;
- UCHAR old_password[SHA1_SIZE];
- UCHAR secure_old_password[SHA1_SIZE];
- UCHAR new_password[SHA1_SIZE];
- UCHAR new_password_ntlm[MD5_SIZE];
- SOCK *sock;
- SESSION *s;
- // Validate arguments
- if (cedar == NULL || o == NULL || hubname == NULL || username == NULL || old_pass == NULL || new_pass == NULL)
- {
- return ERR_INTERNAL_ERROR;
- }
- // Create a session
- s = NewRpcSessionEx(cedar, o, &ret, NULL);
- if (s != NULL)
- {
- PACK *p = NewPack();
- sock = s->Connection->FirstSock;
- HashPassword(old_password, username, old_pass);
- SecurePassword(secure_old_password, old_password, s->Connection->Random);
- HashPassword(new_password, username, new_pass);
- GenerateNtPasswordHash(new_password_ntlm, new_pass);
- PackAddClientVersion(p, s->Connection);
- PackAddStr(p, "method", "password");
- PackAddStr(p, "hubname", hubname);
- PackAddStr(p, "username", username);
- PackAddData(p, "secure_old_password", secure_old_password, SHA1_SIZE);
- PackAddData(p, "new_password", new_password, SHA1_SIZE);
- PackAddData(p, "new_password_ntlm", new_password_ntlm, MD5_SIZE);
- if (HttpClientSend(sock, p))
- {
- PACK *p = HttpClientRecv(sock);
- if (p == NULL)
- {
- ret = ERR_DISCONNECTED;
- }
- else
- {
- ret = GetErrorFromPack(p);
- }
- FreePack(p);
- }
- else
- {
- ret = ERR_DISCONNECTED;
- }
- FreePack(p);
- ReleaseSession(s);
- }
- return ret;
- }
- // Enumerate HUBs
- TOKEN_LIST *EnumHub(SESSION *s)
- {
- SOCK *sock;
- TOKEN_LIST *ret;
- PACK *p;
- UINT num;
- UINT i;
- // Validate arguments
- if (s == NULL || s->Connection == NULL)
- {
- return NULL;
- }
- sock = s->Connection->FirstSock;
- if (sock == NULL)
- {
- return NULL;
- }
- // Set the Timeout
- SetTimeout(sock, 10000);
- p = NewPack();
- PackAddStr(p, "method", "enum_hub");
- PackAddClientVersion(p, s->Connection);
- if (HttpClientSend(sock, p) == false)
- {
- FreePack(p);
- return NULL;
- }
- FreePack(p);
- p = HttpClientRecv(sock);
- if (p == NULL)
- {
- return NULL;
- }
- num = PackGetInt(p, "NumHub");
- ret = ZeroMalloc(sizeof(TOKEN_LIST));
- ret->NumTokens = num;
- ret->Token = ZeroMalloc(sizeof(char *) * num);
- for (i = 0;i < num;i++)
- {
- char tmp[MAX_SIZE];
- if (PackGetStrEx(p, "HubName", tmp, sizeof(tmp), i))
- {
- ret->Token[i] = CopyStr(tmp);
- }
- }
- FreePack(p);
- return ret;
- }
- // Server accepts a connection from client
- bool ServerAccept(CONNECTION *c)
- {
- bool ret = false;
- UINT err;
- PACK *p;
- char username_real[MAX_SIZE];
- char method[MAX_SIZE];
- char hubname[MAX_SIZE];
- char username[MAX_SIZE];
- char groupname[MAX_SIZE];
- UCHAR session_key[SHA1_SIZE];
- UCHAR ticket[SHA1_SIZE];
- RC4_KEY_PAIR key_pair;
- UINT authtype;
- POLICY *policy;
- UINT assigned_vlan_id = 0;
- HUB *hub;
- SESSION *s = NULL;
- UINT64 user_expires = 0;
- bool use_encrypt;
- bool use_compress;
- bool half_connection;
- UINT adjust_mss;
- bool use_udp_acceleration_client;
- bool support_hmac_on_udp_acceleration_client = false;
- bool support_udp_accel_fast_disconnect_detect;
- bool use_hmac_on_udp_acceleration = false;
- bool supress_return_pack_error = false;
- IP udp_acceleration_client_ip;
- UCHAR udp_acceleration_client_key[UDP_ACCELERATION_COMMON_KEY_SIZE];
- UINT udp_acceleration_client_port;
- bool use_fast_rc4;
- bool admin_mode = false;
- UINT direction;
- UINT max_connection;
- UINT timeout;
- bool no_reconnect_to_session = false;
- bool farm_controller = false;
- bool farm_member = false;
- bool farm_mode = false;
- bool require_bridge_routing_mode;
- bool require_monitor_mode;
- bool support_bulk_on_rudp = false;
- bool support_hmac_on_bulk_of_rudp = false;
- bool support_udp_recovery = false;
- bool enable_bulk_on_rudp = false;
- bool enable_udp_recovery = false;
- bool enable_hmac_on_bulk_of_rudp = false;
- bool use_client_license = false, use_bridge_license = false;
- bool local_host_session = false;
- char sessionname[MAX_SESSION_NAME_LEN + 1];
- bool is_server_or_bridge = false;
- bool qos = false;
- bool cluster_dynamic_secure_nat = false;
- bool no_save_password = false;
- NODE_INFO node;
- wchar_t *msg = NULL;
- bool suppress_client_update_notification = false;
- USER *loggedin_user_object = NULL;
- FARM_MEMBER *f = NULL;
- SERVER *server = NULL;
- POLICY ticketed_policy;
- UINT64 timestamp;
- UCHAR unique[SHA1_SIZE], unique2[SHA1_SIZE];
- CEDAR *cedar;
- RPC_WINVER winver;
- UINT client_id;
- bool no_more_users_in_server = false;
- UCHAR mschap_v2_server_response_20[20];
- UINT ms_chap_error = 0;
- bool is_empty_password = false;
- char *error_detail = NULL;
- char *error_detail_2 = NULL;
- char ctoken_hash_str[64];
- EAP_CLIENT *release_me_eap_client = NULL;
- // Validate arguments
- if (c == NULL)
- {
- return false;
- }
- GenerateMachineUniqueHash(unique2);
- Zero(ctoken_hash_str, sizeof(ctoken_hash_str));
- Zero(mschap_v2_server_response_20, sizeof(mschap_v2_server_response_20));
- Zero(&udp_acceleration_client_ip, sizeof(udp_acceleration_client_ip));
- udp_acceleration_client_port = 0;
- Zero(udp_acceleration_client_key, sizeof(udp_acceleration_client_key));
- Zero(&winver, sizeof(winver));
- StrCpy(groupname, sizeof(groupname), "");
- StrCpy(sessionname, sizeof(sessionname), "");
- if (IsZero(c->CToken_Hash, SHA1_SIZE) == false)
- {
- BinToStr(ctoken_hash_str, sizeof(ctoken_hash_str), c->CToken_Hash, SHA1_SIZE);
- }
- cedar = c->Cedar;
- // Get the license status
- no_more_users_in_server = SiTooManyUserObjectsInServer(cedar->Server, true);
- c->Status = CONNECTION_STATUS_NEGOTIATION;
- if (c->Cedar->Server != NULL)
- {
- SERVER *s = c->Cedar->Server;
- server = s;
- if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
- {
- farm_member = true;
- farm_mode = true;
- }
- if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
- {
- farm_controller = true;
- farm_mode = true;
- }
- }
- // Receive the signature
- Debug("Downloading Signature...\n");
- error_detail_2 = NULL;
- if (ServerDownloadSignature(c, &error_detail_2) == false)
- {
- if (error_detail_2 == NULL)
- {
- error_detail = "ServerDownloadSignature";
- }
- else
- {
- error_detail = error_detail_2;
- }
- supress_return_pack_error = true;
- goto CLEANUP;
- }
- // Send a Hello packet
- Debug("Uploading Hello...\n");
- if (ServerUploadHello(c) == false)
- {
- error_detail = "ServerUploadHello";
- goto CLEANUP;
- }
- // Receive the authentication data
- Debug("Auth...\n");
- p = HttpServerRecv(c->FirstSock);
- if (p == NULL)
- {
- // The connection disconnected
- c->Err = ERR_DISCONNECTED;
- error_detail = "RecvAuth1";
- goto CLEANUP;
- }
- if (err = GetErrorFromPack(p))
- {
- // An error has occured
- FreePack(p);
- c->Err = err;
- error_detail = "RecvAuth2";
- goto CLEANUP;
- }
- // Get the method
- if (GetMethodFromPack(p, method, sizeof(method)) == false)
- {
- // Protocol error
- FreePack(p);
- c->Err = ERR_PROTOCOL_ERROR;
- error_detail = "GetMethodFromPack";
- goto CLEANUP;
- }
- // Brand string for the connection limit
- {
- char tmp[20];
- char *branded_ctos = _SS("BRANDED_C_TO_S");
- PackGetStr(p, "branded_ctos", tmp, sizeof(tmp));
- if(StrCmpi(method, "login") == 0 && StrLen(branded_ctos) > 0 && StrCmpi(branded_ctos, tmp) != 0)
- {
- FreePack(p);
- c->Err = ERR_BRANDED_C_TO_S;
- goto CLEANUP;
- }
- }
- // Time inspection
- timestamp = PackGetInt64(p, "timestamp");
- if (timestamp != 0)
- {
- UINT64 now = SystemTime64();
- UINT64 abs;
- if (now >= timestamp)
- {
- abs = now - timestamp;
- }
- else
- {
- abs = timestamp - now;
- }
- if (abs > ALLOW_TIMESTAMP_DIFF)
- {
- // Time difference is too large
- FreePack(p);
- c->Err = ERR_BAD_CLOCK;
- error_detail = "ERR_BAD_CLOCK";
- goto CLEANUP;
- }
- }
- // Get the client version
- PackGetStr(p, "client_str", c->ClientStr, sizeof(c->ClientStr));
- c->ClientVer = PackGetInt(p, "client_ver");
- c->ClientBuild = PackGetInt(p, "client_build");
- if (SearchStrEx(c->ClientStr, "server", 0, false) != INFINITE ||
- SearchStrEx(c->ClientStr, "bridge", 0, false) != INFINITE)
- {
- is_server_or_bridge = true;
- }
- // Get the client Windows version
- InRpcWinVer(&winver, p);
- DecrementNoSsl(c->Cedar, &c->FirstSock->RemoteIP, 2);
- if (StrCmpi(method, "login") == 0)
- {
- bool auth_ret = false;
- Debug("Login...\n");
- c->Status = CONNECTION_STATUS_USERAUTH;
- c->Type = CONNECTION_TYPE_LOGIN;
- if (no_more_users_in_server)
- {
- // There are many users than are allowed in the VPN Server
- FreePack(p);
- c->Err = ERR_TOO_MANY_USER;
- error_detail = "ERR_TOO_MANY_USER";
- goto CLEANUP;
- }
- // Such as the client name
- if (PackGetStr(p, "hello", c->ClientStr, sizeof(c->ClientStr)) == false)
- {
- StrCpy(c->ClientStr, sizeof(c->ClientStr), "Unknown");
- }
- c->ServerVer = CEDAR_VER;
- c->ServerBuild = CEDAR_BUILD;
- // Get the NODE_INFO
- Zero(&node, sizeof(node));
- InRpcNodeInfo(&node, p);
- // Protocol
- c->Protocol = GetProtocolFromPack(p);
- if (c->Protocol == CONNECTION_UDP)
- {
- // Release the structure of the TCP connection
- if (c->Tcp)
- {
- ReleaseList(c->Tcp->TcpSockList);
- Free(c->Tcp);
- }
- }
- if (GetServerCapsBool(c->Cedar->Server, "b_vpn_client_connect") == false)
- {
- // VPN client is unable to connect
- FreePack(p);
- c->Err = ERR_NOT_SUPPORTED;
- goto CLEANUP;
- }
- // Login
- if (GetHubnameAndUsernameFromPack(p, username, sizeof(username), hubname, sizeof(hubname)) == false)
- {
- // Protocol error
- FreePack(p);
- c->Err = ERR_PROTOCOL_ERROR;
- error_detail = "GetHubnameAndUsernameFromPack";
- goto CLEANUP;
- }
- if (farm_member)
- {
- bool ok = false;
- UINT authtype;
- authtype = GetAuthTypeFromPack(p);
- if (StrCmpi(username, ADMINISTRATOR_USERNAME) == 0 &&
- authtype == AUTHTYPE_PASSWORD)
- {
- ok = true;
- }
- if (authtype == AUTHTYPE_TICKET)
- {
- ok = true;
- }
- if (ok == false)
- {
- // Logging on directly to server farm members by
- // non-Administrators are prohibited
- FreePack(p);
- SLog(c->Cedar, "LS_FARMMEMBER_NOT_ADMIN", c->Name, hubname, ADMINISTRATOR_USERNAME, username);
- c->Err = ERR_ACCESS_DENIED;
- goto CLEANUP;
- }
- }
- Debug("Username = %s, HubName = %s\n", username, hubname);
- LockHubList(c->Cedar);
- {
- hub = GetHub(c->Cedar, hubname);
- }
- UnlockHubList(c->Cedar);
- if (hub == NULL)
- {
- // The HUB does not exist
- FreePack(p);
- c->Err = ERR_HUB_NOT_FOUND;
- SLog(c->Cedar, "LS_HUB_NOT_FOUND", c->Name, hubname);
- error_detail = "ERR_HUB_NOT_FOUND";
- goto CLEANUP;
- }
- if (hub->ForceDisableComm)
- {
- // Commnunication function is disabled
- FreePack(p);
- c->Err = ERR_SERVER_CANT_ACCEPT;
- error_detail = "ERR_COMM_DISABLED";
- ReleaseHub(hub);
- goto CLEANUP;
- }
- if (GetGlobalServerFlag(GSF_DISABLE_AC) == 0)
- {
- if (hub->HubDb != NULL && c->FirstSock != NULL)
- {
- IP ip;
- Copy(&ip, &c->FirstSock->RemoteIP, sizeof(IP));
- if (IsIpDeniedByAcList(&ip, hub->HubDb->AcList))
- {
- char ip_str[64];
- // Access denied
- ReleaseHub(hub);
- hub = NULL;
- FreePack(p);
- c->Err = ERR_IP_ADDRESS_DENIED;
- IPToStr(ip_str, sizeof(ip_str), &ip);
- SLog(c->Cedar, "LS_IP_DENIED", c->Name, ip_str);
- goto CLEANUP;
- }
- }
- }
- Lock(hub->lock);
- {
- UINT cert_size = 0;
- void *cert_buf = NULL;
- USER *user;
- USERGROUP *group;
- char plain_password[MAX_PASSWORD_LEN + 1];
- RADIUS_LOGIN_OPTION radius_login_opt;
- if (hub->Halt || hub->Offline)
- {
- // HUB is off-line
- FreePack(p);
- Unlock(hub->lock);
- ReleaseHub(hub);
- c->Err = ERR_HUB_STOPPING;
- goto CLEANUP;
- }
- Zero(&radius_login_opt, sizeof(radius_login_opt));
- if (hub->Option != NULL)
- {
- radius_login_opt.In_CheckVLanId = hub->Option->AssignVLanIdByRadiusAttribute;
- radius_login_opt.In_DenyNoVlanId = hub->Option->DenyAllRadiusLoginWithNoVlanAssign;
- if (hub->Option->UseHubNameAsRadiusNasId == true)
- {
- StrCpy(radius_login_opt.NasId, sizeof(radius_login_opt.NasId), hubname);
- }
- }
- // Get the various flags
- use_encrypt = PackGetInt(p, "use_encrypt") == 0 ? false : true;
- use_compress = PackGetInt(p, "use_compress") == 0 ? false : true;
- max_connection = PackGetInt(p, "max_connection");
- half_connection = PackGetInt(p, "half_connection") == 0 ? false : true;
- use_fast_rc4 = PackGetInt(p, "use_fast_rc4") == 0 ? false : true;
- qos = PackGetInt(p, "qos") ? true : false;
- client_id = PackGetInt(p, "client_id");
- adjust_mss = PackGetInt(p, "adjust_mss");
- use_udp_acceleration_client = PackGetBool(p, "use_udp_acceleration");
- support_hmac_on_udp_acceleration_client = PackGetBool(p, "support_hmac_on_udp_acceleration");
- support_udp_accel_fast_disconnect_detect = PackGetBool(p, "support_udp_accel_fast_disconnect_detect");
- support_bulk_on_rudp = PackGetBool(p, "support_bulk_on_rudp");
- support_hmac_on_bulk_of_rudp = PackGetBool(p, "support_hmac_on_bulk_of_rudp");
- support_udp_recovery = PackGetBool(p, "support_udp_recovery");
- if (c->IsInProc)
- {
- char tmp[MAX_SIZE];
- UINT64 ptr;
- ptr = PackGetInt64(p, "release_me_eap_client");
- if (ptr != 0)
- {
- release_me_eap_client = (EAP_CLIENT *)ptr;
- }
- PackGetStr(p, "inproc_postfix", c->InProcPrefix, sizeof(c->InProcPrefix));
- Zero(tmp, sizeof(tmp));
- PackGetStr(p, "inproc_cryptname", tmp, sizeof(tmp));
- if (c->FirstSock != NULL)
- {
- if (IsEmptyStr(c->InProcPrefix) == false)
- {
- Format(c->FirstSock->UnderlayProtocol, sizeof(c->FirstSock->UnderlayProtocol),
- SOCK_UNDERLAY_INPROC_EX, c->InProcPrefix);
- }
- }
- if (c->CipherName != NULL)
- {
- Free(c->CipherName);
- }
- c->CipherName = NULL;
- if (IsEmptyStr(tmp) == false)
- {
- c->CipherName = CopyStr(tmp);
- use_encrypt = true;
- }
- use_udp_acceleration_client = false;
- }
- else
- {
- if (c->CipherName != NULL)
- {
- Free(c->CipherName);
- }
- c->CipherName = NULL;
- if (c->FirstSock != NULL && IsEmptyStr(c->FirstSock->CipherName) == false)
- {
- c->CipherName = CopyStr(c->FirstSock->CipherName);
- }
- }
- if (support_bulk_on_rudp && c->FirstSock != NULL && c->FirstSock->IsRUDPSocket &&
- c->FirstSock->BulkRecvKey != NULL && c->FirstSock->BulkSendKey != NULL)
- {
- // RAllow UDP bulk transfer if the client side supports
- // in the case of using R-UDP Socket
- enable_bulk_on_rudp = true;
- enable_hmac_on_bulk_of_rudp = support_hmac_on_bulk_of_rudp;
- }
- if (support_udp_recovery && c->FirstSock != NULL && c->FirstSock->IsRUDPSocket)
- {
- // Allow UDP recovery
- enable_udp_recovery = true;
- }
- if (use_udp_acceleration_client)
- {
- // Get the parameters for the UDP acceleration function
- if (PackGetIp(p, "udp_acceleration_client_ip", &udp_acceleration_client_ip) == false ||
- PackGetData2(p, "udp_acceleration_client_key", udp_acceleration_client_key, UDP_ACCELERATION_COMMON_KEY_SIZE) == false)
- {
- use_udp_acceleration_client = false;
- }
- else
- {
- if (IsZeroIp(&udp_acceleration_client_ip))
- {
- Copy(&udp_acceleration_client_ip, &c->FirstSock->RemoteIP, sizeof(IP));
- }
- udp_acceleration_client_port = PackGetInt(p, "udp_acceleration_client_port");
- if (udp_acceleration_client_port == 0)
- {
- use_udp_acceleration_client = false;
- }
- }
- use_hmac_on_udp_acceleration = support_hmac_on_udp_acceleration_client;
- }
- Debug("use_udp_acceleration_client = %u\n", use_udp_acceleration_client);
- Debug("use_hmac_on_udp_acceleration = %u\n", use_hmac_on_udp_acceleration);
- // Request mode
- require_bridge_routing_mode = PackGetBool(p, "require_bridge_routing_mode");
- require_monitor_mode = PackGetBool(p, "require_monitor_mode");
- if (require_monitor_mode)
- {
- qos = false;
- }
- if (is_server_or_bridge)
- {
- require_bridge_routing_mode = true;
- }
- // Client unique ID
- Zero(unique, sizeof(unique));
- if (PackGetDataSize(p, "unique_id") == SHA1_SIZE)
- {
- PackGetData(p, "unique_id", unique);
- }
- // Get the authentication method
- authtype = GetAuthTypeFromPack(p);
- if (1)
- {
- // Log
- char ip1[64], ip2[64], verstr[64];
- wchar_t *authtype_str = _UU("LH_AUTH_UNKNOWN");
- switch (authtype)
- {
- case CLIENT_AUTHTYPE_ANONYMOUS:
- authtype_str = _UU("LH_AUTH_ANONYMOUS");
- break;
- case CLIENT_AUTHTYPE_PASSWORD:
- authtype_str = _UU("LH_AUTH_PASSWORD");
- break;
- case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
- authtype_str = _UU("LH_AUTH_PLAIN_PASSWORD");
- break;
- case CLIENT_AUTHTYPE_CERT:
- authtype_str = _UU("LH_AUTH_CERT");
- break;
- case AUTHTYPE_TICKET:
- authtype_str = _UU("LH_AUTH_TICKET");
- break;
- }
- IPToStr(ip1, sizeof(ip1), &c->FirstSock->RemoteIP);
- IPToStr(ip2, sizeof(ip2), &c->FirstSock->LocalIP);
- Format(verstr, sizeof(verstr), "%u.%02u", c->ClientVer / 100, c->ClientVer % 100);
- HLog(hub, "LH_CONNECT_CLIENT", c->Name, ip1, c->FirstSock->RemoteHostname, c->FirstSock->RemotePort,
- c->ClientStr, verstr, c->ClientBuild, authtype_str, username);
- }
- // Attempt an anonymous authentication first
- auth_ret = SamAuthUserByAnonymous(hub, username);
- if (auth_ret)
- {
- if (c->IsInProc)
- {
- IPC_MSCHAP_V2_AUTHINFO mschap;
- char password_tmp[MAX_SIZE];
- Zero(&mschap, sizeof(mschap));
- Zero(password_tmp, sizeof(password_tmp));
- PackGetStr(p, "plain_password", password_tmp, sizeof(password_tmp));
- if (ParseAndExtractMsChapV2InfoFromPassword(&mschap, password_tmp))
- {
- // Because the server don't know the NTLM hashed password, the bet to the possibility of
- // the same character to the user name and empty, search a password of different
- // versions of the upper and lower case characters in the case of anonymous authentication.
- // Returns the MS-CHAPv2 response by using the password if there is a match.
- // Fail the authentication if no match is found.
- // (Because, if return a false MS-CHAPv2 Response, PPP client cause an error)
- LIST *o = NewListFast(NULL);
- char tmp1[MAX_SIZE];
- char tmp2[MAX_SIZE];
- char tmp3[MAX_SIZE];
- char tmp4[MAX_SIZE];
- char *response_pw;
- char psk[MAX_SIZE];
- ParseNtUsername(mschap.MsChapV2_PPPUsername, tmp1, sizeof(tmp1), tmp2, sizeof(tmp2), false);
- ParseNtUsername(mschap.MsChapV2_PPPUsername, tmp3, sizeof(tmp3), tmp4, sizeof(tmp4), true);
- Add(o, "");
- Add(o, "-");
- Add(o, ".");
- Add(o, "*");
- Add(o, "?");
- Add(o, " ");
- Add(o, "p");
- Add(o, "guest");
- Add(o, "anony");
- Add(o, "anonymouse");
- Add(o, "password");
- Add(o, "passwd");
- Add(o, "pass");
- Add(o, "pw");
- Add(o, mschap.MsChapV2_PPPUsername);
- Add(o, tmp1);
- Add(o, tmp2);
- Add(o, tmp3);
- Add(o, tmp4);
- Zero(psk, sizeof(psk));
- if (c->Cedar->Server != NULL)
- {
- SERVER *s = c->Cedar->Server;
- if (s->IPsecServer != NULL)
- {
- StrCpy(psk, sizeof(psk), s->IPsecServer->Services.IPsec_Secret);
- Add(o, psk);
- }
- }
- response_pw = MsChapV2DoBruteForce(&mschap, o);
- ReleaseList(o);
- if (response_pw != NULL)
- {
- UCHAR challenge8[8];
- UCHAR nt_hash[16];
- UCHAR nt_hash_hash[16];
- GenerateNtPasswordHash(nt_hash, response_pw);
- GenerateNtPasswordHashHash(nt_hash_hash, nt_hash);
- MsChapV2_GenerateChallenge8(challenge8, mschap.MsChapV2_ClientChallenge, mschap.MsChapV2_ServerChallenge,
- mschap.MsChapV2_PPPUsername);
- MsChapV2Server_GenerateResponse(mschap_v2_server_response_20, nt_hash_hash,
- mschap.MsChapV2_ClientResponse, challenge8);
- Free(response_pw);
- }
- else
- {
- auth_ret = false;
- }
- }
- }
- if (auth_ret)
- {
- // User authentication success by anonymous authentication
- HLog(hub, "LH_AUTH_OK", c->Name, username);
- is_empty_password = true;
- }
- }
- if (auth_ret == false)
- {
- // Attempt other authentication methods if anonymous authentication fails
- switch (authtype)
- {
- case CLIENT_AUTHTYPE_ANONYMOUS:
- // Anonymous authentication (this have been already attempted)
- break;
- case AUTHTYPE_TICKET:
- // Ticket authentication
- if (PackGetDataSize(p, "ticket") == SHA1_SIZE)
- {
- PackGetData(p, "ticket", ticket);
- auth_ret = SiCheckTicket(hub, ticket, username, sizeof(username), username_real, sizeof(username_real),
- &ticketed_policy, sessionname, sizeof(sessionname), groupname, sizeof(groupname));
- }
- break;
- case CLIENT_AUTHTYPE_PASSWORD:
- // Password authentication
- if (PackGetDataSize(p, "secure_password") == SHA1_SIZE)
- {
- POLICY *pol = NULL;
- UCHAR secure_password[SHA1_SIZE];
- Zero(secure_password, sizeof(secure_password));
- if (PackGetDataSize(p, "secure_password") == SHA1_SIZE)
- {
- PackGetData(p, "secure_password", secure_password);
- }
- auth_ret = SamAuthUserByPassword(hub, username, c->Random, secure_password, NULL, NULL, NULL);
- pol = SamGetUserPolicy(hub, username);
- if (pol != NULL)
- {
- no_save_password = pol->NoSavePassword;
- Free(pol);
- }
- if(auth_ret){
- // Check whether the password was empty
- UCHAR hashed_empty_password[SHA1_SIZE];
- UCHAR secure_empty_password[SHA1_SIZE];
- HashPassword(hashed_empty_password, username, "");
- SecurePassword(secure_empty_password, hashed_empty_password, c->Random);
- if(Cmp(secure_password, secure_empty_password, SHA1_SIZE)==0){
- is_empty_password = true;
- }
- }
- }
- break;
- case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
- {
- POLICY *pol = NULL;
- // Plaintext password authentication
- Zero(plain_password, sizeof(plain_password));
- PackGetStr(p, "plain_password", plain_password, sizeof(plain_password));
- if (c->IsInProc == false && StartWith(plain_password, IPC_PASSWORD_MSCHAPV2_TAG))
- {
- // Do not allow the MS-CHAPv2 authentication other than IPC sessions
- Zero(plain_password, sizeof(plain_password));
- }
- if (auth_ret == false)
- {
- // Attempt a password authentication of normal user
- UCHAR secure_password[SHA1_SIZE];
- UCHAR hash_password[SHA1_SIZE];
- bool is_mschap = StartWith(plain_password, IPC_PASSWORD_MSCHAPV2_TAG);
- HashPassword(hash_password, username, plain_password);
- SecurePassword(secure_password, hash_password, c->Random);
- if (is_mschap == false)
- {
- auth_ret = SamAuthUserByPassword(hub, username, c->Random, secure_password, NULL, NULL, NULL);
- }
- else
- {
- auth_ret = SamAuthUserByPassword(hub, username, c->Random, secure_password,
- plain_password, mschap_v2_server_response_20, &ms_chap_error);
- }
- if (auth_ret && pol == NULL)
- {
- pol = SamGetUserPolicy(hub, username);
- }
- }
- if (auth_ret == false)
- {
- // Attempt external authentication registered users
- bool fail_ext_user_auth = false;
- if (GetGlobalServerFlag(GSF_DISABLE_RADIUS_AUTH) != 0)
- {
- fail_ext_user_auth = true;
- }
- if (fail_ext_user_auth == false)
- {
- auth_ret = SamAuthUserByPlainPassword(c, hub, username, plain_password, false, mschap_v2_server_response_20, &radius_login_opt);
- }
- if (auth_ret && pol == NULL)
- {
- pol = SamGetUserPolicy(hub, username);
- }
- }
- if (auth_ret == false)
- {
- // Attempt external authentication asterisk user
- bool b = false;
- bool fail_ext_user_auth = false;
- if (GetGlobalServerFlag(GSF_DISABLE_RADIUS_AUTH) != 0)
- {
- fail_ext_user_auth = true;
- }
- if (fail_ext_user_auth == false)
- {
- AcLock(hub);
- {
- b = AcIsUser(hub, "*");
- }
- AcUnlock(hub);
- // If there is asterisk user, log on as the user
- if (b)
- {
- auth_ret = SamAuthUserByPlainPassword(c, hub, username, plain_password, true, mschap_v2_server_response_20, &radius_login_opt);
- if (auth_ret && pol == NULL)
- {
- pol = SamGetUserPolicy(hub, "*");
- }
- }
- }
- }
- if (pol != NULL)
- {
- no_save_password = pol->NoSavePassword;
- Free(pol);
- }
- if(auth_ret){
- // Check whether the password was empty
- if(IsEmptyStr(plain_password)){
- is_empty_password = true;
- }
- }
- }
- break;
- case CLIENT_AUTHTYPE_CERT:
- if (GetGlobalServerFlag(GSF_DISABLE_CERT_AUTH) == 0)
- {
- // Certificate authentication
- cert_size = PackGetDataSize(p, "cert");
- if (cert_size >= 1 && cert_size <= 100000)
- {
- cert_buf = ZeroMalloc(cert_size);
- if (PackGetData(p, "cert", cert_buf))
- {
- UCHAR sign[4096 / 8];
- UINT sign_size = PackGetDataSize(p, "sign");
- if (sign_size <= sizeof(sign) && sign_size >= 1)
- {
- if (PackGetData(p, "sign", sign))
- {
- BUF *b = NewBuf();
- X *x;
- WriteBuf(b, cert_buf, cert_size);
- x = BufToX(b, false);
- if (x != NULL && x->is_compatible_bit &&
- sign_size == (x->bits / 8))
- {
- K *k = GetKFromX(x);
- // Verify the signature received from the client
- if (RsaVerifyEx(c->Random, SHA1_SIZE, sign, k, x->bits))
- {
- // Confirmed that the client has had this certificate
- // certainly because the signature matched.
- // Check whether the certificate is valid.
- auth_ret = SamAuthUserByCert(hub, username, x);
- if (auth_ret)
- {
- // Copy the certificate
- c->ClientX = CloneX(x);
- }
- }
- else
- {
- // Authentication failure
- }
- FreeK(k);
- }
- FreeX(x);
- FreeBuf(b);
- }
- }
- }
- Free(cert_buf);
- }
- }
- else
- {
- // Certificate authentication is not supported in the open source version
- HLog(hub, "LH_AUTH_CERT_NOT_SUPPORT_ON_OPEN_SOURCE", c->Name, username);
- Unlock(hub->lock);
- ReleaseHub(hub);
- FreePack(p);
- c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
- goto CLEANUP;
- }
- break;
- default:
- // Unknown authentication method
- Unlock(hub->lock);
- ReleaseHub(hub);
- FreePack(p);
- c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
- error_detail = "ERR_AUTHTYPE_NOT_SUPPORTED";
- goto CLEANUP;
- }
- if (auth_ret == false)
- {
- // Authentication failure
- HLog(hub, "LH_AUTH_NG", c->Name, username);
- }
- else
- {
- // Authentication success
- HLog(hub, "LH_AUTH_OK", c->Name, username);
- }
- }
- if (auth_ret == false)
- {
- // Authentication failure
- Unlock(hub->lock);
- ReleaseHub(hub);
- FreePack(p);
- c->Err = ERR_AUTH_FAILED;
- if (ms_chap_error != 0)
- {
- c->Err = ms_chap_error;
- }
- error_detail = "ERR_AUTH_FAILED";
- goto CLEANUP;
- }
- else
- {
- if(is_empty_password)
- {
- SOCK *s = c->FirstSock;
- if (s != NULL && s->RemoteIP.addr[0] != 127)
- {
- if(StrCmpi(username, ADMINISTRATOR_USERNAME) == 0 ||
- GetHubAdminOption(hub, "deny_empty_password") != 0)
- {
- // When the password is empty, remote connection is not acceptable
- HLog(hub, "LH_LOCAL_ONLY", c->Name, username);
- Unlock(hub->lock);
- ReleaseHub(hub);
- FreePack(p);
- c->Err = ERR_NULL_PASSWORD_LOCAL_ONLY;
- error_detail = "ERR_NULL_PASSWORD_LOCAL_ONLY";
- goto CLEANUP;
- }
- }
- }
- }
- policy = NULL;
- // Authentication success
- FreePack(p);
- // Check the assigned VLAN ID
- if (radius_login_opt.Out_IsRadiusLogin)
- {
- if (radius_login_opt.In_CheckVLanId)
- {
- if (radius_login_opt.Out_VLanId != 0)
- {
- assigned_vlan_id = radius_login_opt.Out_VLanId;
- }
- if (radius_login_opt.In_DenyNoVlanId && assigned_vlan_id == 0 || assigned_vlan_id >= 4096)
- {
- // Deny this session
- Unlock(hub->lock);
- ReleaseHub(hub);
- c->Err = ERR_ACCESS_DENIED;
- error_detail = "In_DenyNoVlanId";
- goto CLEANUP;
- }
- }
- }
- if (StrCmpi(username, ADMINISTRATOR_USERNAME) != 0)
- {
- // Get the policy
- if (farm_member == false)
- {
- // In the case of not a farm member
- user = AcGetUser(hub, username);
- if (user == NULL)
- {
- user = AcGetUser(hub, "*");
- if (user == NULL)
- {
- // User acquisition failure
- Unlock(hub->lock);
- ReleaseHub(hub);
- c->Err = ERR_ACCESS_DENIED;
- error_detail = "AcGetUser";
- goto CLEANUP;
- }
- }
- policy = NULL;
- Lock(user->lock);
- {
- // Get the expiration date
- user_expires = user->ExpireTime;
- StrCpy(username_real, sizeof(username_real), user->Name);
- group = user->Group;
- if (group != NULL)
- {
- AddRef(group->ref);
- Lock(group->lock);
- {
- // Get the group name
- StrCpy(groupname, sizeof(groupname), group->Name);
- }
- Unlock(group->lock);
- }
- if (user->Policy != NULL)
- {
- policy = ClonePolicy(user->Policy);
- }
- else
- {
- if (group)
- {
- Lock(group->lock);
- {
- if (group->Policy != NULL)
- {
- policy = ClonePolicy(group->Policy);
- }
- }
- Unlock(group->lock);
- }
- }
- if (group != NULL)
- {
- ReleaseGroup(group);
- }
- }
- Unlock(user->lock);
- loggedin_user_object = user;
- }
- else
- {
- // In the case of farm member
- policy = ClonePolicy(&ticketed_policy);
- }
- }
- else
- {
- // Administrator mode
- admin_mode = true;
- StrCpy(username_real, sizeof(username_real), ADMINISTRATOR_USERNAME);
- policy = ClonePolicy(GetDefaultPolicy());
- policy->NoBroadcastLimiter = true;
- policy->MonitorPort = true;
- }
- if (policy == NULL)
- {
- // Use the default policy
- policy = ClonePolicy(GetDefaultPolicy());
- }
- if (policy->MaxConnection == 0)
- {
- policy->MaxConnection = MAX_TCP_CONNECTION;
- }
- if (policy->TimeOut == 0)
- {
- policy->TimeOut = 20;
- }
- if (qos)
- {
- // VoIP / QoS
- if (policy->NoQoS)
- {
- // Policy does not allow QoS
- qos = false;
- }
- if (GetServerCapsBool(c->Cedar->Server, "b_support_qos") == false)
- {
- // Server does not support QoS
- qos = false;
- policy->NoQoS = true;
- }
- if (GetHubAdminOption(hub, "deny_qos") != 0)
- {
- // It is prohibited in the management options
- qos = false;
- policy->NoQoS = true;
- }
- }
- if (GetHubAdminOption(hub, "max_bitrates_download") != 0)
- {
- if (policy->MaxDownload == 0)
- {
- policy->MaxDownload = GetHubAdminOption(hub, "max_bitrates_download");
- }
- else
- {
- UINT r = GetHubAdminOption(hub, "max_bitrates_download");
- policy->MaxDownload = MIN(policy->MaxDownload, r);
- }
- }
- if (GetHubAdminOption(hub, "max_bitrates_upload") != 0)
- {
- if (policy->MaxUpload == 0)
- {
- policy->MaxUpload = GetHubAdminOption(hub, "max_bitrates_upload");
- }
- else
- {
- UINT r = GetHubAdminOption(hub, "max_bitrates_upload");
- policy->MaxUpload = MIN(policy->MaxUpload, r);
- }
- }
- if (GetHubAdminOption(hub, "deny_bridge") != 0)
- {
- policy->NoBridge = true;
- }
- if (GetHubAdminOption(hub, "deny_routing") != 0)
- {
- policy->NoRouting = true;
- }
- if (c->IsInProc)
- {
- policy->NoBridge = false;
- policy->NoRouting = false;
- }
- if (hub->Option->ClientMinimumRequiredBuild > c->ClientBuild &&
- InStrEx(c->ClientStr, "client", false))
- {
- // Build number of the client is too small
- HLog(hub, "LH_CLIENT_VERSION_OLD", c->Name, c->ClientBuild, hub->Option->ClientMinimumRequiredBuild);
- Unlock(hub->lock);
- ReleaseHub(hub);
- c->Err = ERR_VERSION_INVALID;
- Free(policy);
- error_detail = "ERR_VERSION_INVALID";
- goto CLEANUP;
- }
- if (hub->Option->RequiredClientId != 0 &&
- hub->Option->RequiredClientId != client_id &&
- InStrEx(c->ClientStr, "client", false))
- {
- // Build number of the client is too small
- HLog(hub, "LH_CLIENT_ID_REQUIRED", c->Name, client_id, hub->Option->RequiredClientId);
- Unlock(hub->lock);
- ReleaseHub(hub);
- c->Err = ERR_CLIENT_ID_REQUIRED;
- error_detail = "ERR_CLIENT_ID_REQUIRED";
- Free(policy);
- goto CLEANUP;
- }
- if ((policy->NoSavePassword) || (policy->AutoDisconnect != 0))
- {
- if (c->ClientBuild < 6560 && InStrEx(c->ClientStr, "client", false))
- {
- // If NoSavePassword policy is specified,
- // only supported client can connect
- HLog(hub, "LH_CLIENT_VERSION_OLD", c->Name, c->ClientBuild, 6560);
- Unlock(hub->lock);
- ReleaseHub(hub);
- c->Err = ERR_VERSION_INVALID;
- error_detail = "ERR_VERSION_INVALID";
- Free(policy);
- goto CLEANUP;
- }
- }
- if (user_expires != 0 && user_expires <= SystemTime64())
- {
- // User expired
- HLog(hub, "LH_USER_EXPIRES", c->Name, username);
- Unlock(hub->lock);
- ReleaseHub(hub);
- c->Err = ERR_ACCESS_DENIED;
- error_detail = "LH_USER_EXPIRES";
- Free(policy);
- goto CLEANUP;
- }
- if (policy->Access == false)
- {
- // Access is denied
- HLog(hub, "LH_POLICY_ACCESS_NG", c->Name, username);
- Unlock(hub->lock);
- ReleaseHub(hub);
- error_detail = "LH_POLICY_ACCESS_NG";
- c->Err = ERR_ACCESS_DENIED;
- Free(policy);
- goto CLEANUP;
- }
- // Determine the contents of the policy by comparing to
- // option presented by client or deny the connection.
- // Confirm the connectivity in the monitor-mode first
- if (require_monitor_mode && policy->MonitorPort == false)
- {
- // Can not connect in the monitor port mode
- HLog(hub, "LH_POLICY_MONITOR_MODE", c->Name);
- Unlock(hub->lock);
- ReleaseHub(hub);
- c->Err = ERR_MONITOR_MODE_DENIED;
- Free(policy);
- error_detail = "ERR_MONITOR_MODE_DENIED";
- goto CLEANUP;
- }
- if (policy->MonitorPort)
- {
- if (require_monitor_mode == false)
- {
- policy->MonitorPort = false;
- }
- }
- if (policy->MonitorPort)
- {
- qos = false;
- }
- // Determine whether it can be connected by a bridge / routing mode next
- if (require_bridge_routing_mode &&
- (policy->NoBridge && policy->NoRouting))
- {
- // Can not be connected by a bridge / routing mode
- HLog(hub, "LH_POLICY_BRIDGE_MODE", c->Name);
- Unlock(hub->lock);
- ReleaseHub(hub);
- c->Err = ERR_BRIDGE_MODE_DENIED;
- error_detail = "ERR_BRIDGE_MODE_DENIED";
- Free(policy);
- goto CLEANUP;
- }
- if (require_bridge_routing_mode == false)
- {
- policy->NoBridge = true;
- policy->NoRouting = true;
- }
- if (Cmp(unique, unique2, SHA1_SIZE) == 0)
- {
- // It's a localhost session
- local_host_session = true;
- }
- if (local_host_session == false)
- {
- // Make further judgment whether localhost session
- SOCK *s = c->FirstSock;
- if (s != NULL)
- {
- if (IsIPMyHost(&s->RemoteIP))
- {
- // It's a localhost session
- local_host_session = true;
- }
- }
- }
- if (local_host_session)
- {
- // Permit routing or bridging in the case of localhost session
- policy->NoBridge = false;
- policy->NoRouting = false;
- }
- if (local_host_session == false)
- {
- if (policy->NoBridge == false || policy->NoRouting == false)
- {
- use_bridge_license = true;
- }
- else
- {
- use_client_license = true;
- }
- }
- if (server != NULL && server->ServerType != SERVER_TYPE_FARM_MEMBER &&
- policy != NULL)
- {
- if (GetServerCapsBool(hub->Cedar->Server, "b_support_limit_multilogin"))
- {
- // Check if the number of concurrent multiple logins limit is specified in the policy
- RPC_ENUM_SESSION t;
- UINT i, num;
- UINT max_logins = policy->MultiLogins;
- UINT ao = GetHubAdminOption(hub, "max_multilogins_per_user");
- if (ao != 0)
- {
- if (max_logins != 0)
- {
- max_logins = MIN(max_logins, ao);
- }
- else
- {
- max_logins = ao;
- }
- }
- if (max_logins != 0)
- {
- Zero(&t, sizeof(t));
- StrCpy(t.HubName, sizeof(t.HubName), hub->Name);
- Unlock(hub->lock);
- SiEnumSessionMain(server, &t);
- Lock(hub->lock);
- num = 0;
- for (i = 0;i < t.NumSession;i++)
- {
- RPC_ENUM_SESSION_ITEM *e = &t.Sessions[i];
- if (e->BridgeMode == false && e->Layer3Mode == false && e->LinkMode == false && e->CurrentNumTcp != 0)
- {
- if (StrCmpi(e->Username, username) == 0 &&
- (IsZero(e->UniqueId, 16) || Cmp(e->UniqueId, node.UniqueId, 16) != 0))
- {
- num++;
- }
- }
- }
- FreeRpcEnumSession(&t);
- if (num >= max_logins)
- {
- // Can not connect any more
- Unlock(hub->lock);
- // Dump a detailed error log
- HLog(hub, "LH_TOO_MANY_MULTILOGINS",
- c->Name,
- username, max_logins, num);
- ReleaseHub(hub);
- c->Err = ERR_TOO_MANY_USER_SESSION;
- Free(policy);
- goto CLEANUP;
- }
- }
- }
- }
- if (loggedin_user_object != NULL)
- {
- // Update the user information
- Lock(loggedin_user_object->lock);
- {
- loggedin_user_object->LastLoginTime = SystemTime64();
- }
- Unlock(loggedin_user_object->lock);
- }
- // Update the number of log-ins
- hub->LastCommTime = hub->LastLoginTime = SystemTime64();
- if (farm_controller)
- {
- wchar_t *msg = GetHubMsg(hub);
- Unlock(hub->lock);
- Lock(cedar->CedarSuperLock);
- // In the case of farm controller, choose a farm members to host this HUB
- LockList(server->FarmMemberList);
- {
- HLog(hub, "LH_FARM_SELECT_1", c->Name);
- f = SiGetHubHostingMember(server, hub, admin_mode, c);
- if (f == NULL)
- {
- // Failed in the selection
- HLog(hub, "LH_FARM_SELECT_2", c->Name);
- UnlockList(server->FarmMemberList);
- Unlock(cedar->CedarSuperLock);
- ReleaseHub(hub);
- c->Err = ERR_COULD_NOT_HOST_HUB_ON_FARM;
- Free(policy);
- Free(msg);
- goto CLEANUP;
- }
- else
- {
- if (f->Me == false)
- {
- UCHAR ticket[SHA1_SIZE];
- PACK *p;
- BUF *b;
- UINT i;
- SLog(c->Cedar, "LH_FARM_SELECT_4", c->Name, f->hostname);
- // Create a session on the selected server farm member
- Rand(ticket, sizeof(ticket));
- SiCallCreateTicket(server, f, hub->Name,
- username, username_real, policy, ticket, Inc(hub->SessionCounter), groupname);
- p = NewPack();
- PackAddInt(p, "Redirect", 1);
- PackAddIp32(p, "Ip", f->Ip);
- for (i = 0;i < f->NumPort;i++)
- {
- PackAddIntEx(p, "Port", f->Ports[i], i, f->NumPort);
- }
- PackAddData(p, "Ticket", ticket, sizeof(ticket));
- if (true)
- {
- char *utf = CopyUniToUtf(msg);
- PackAddData(p, "Msg", utf, StrLen(utf));
- Free(utf);
- }
- b = XToBuf(f->ServerCert, false);
- PackAddBuf(p, "Cert", b);
- FreeBuf(b);
- UnlockList(server->FarmMemberList);
- Unlock(cedar->CedarSuperLock);
- ReleaseHub(hub);
- HttpServerSend(c->FirstSock, p);
- FreePack(p);
- c->Err = 0;
- Free(policy);
- FreePack(HttpServerRecv(c->FirstSock));
- Free(msg);
- goto CLEANUP;
- }
- else
- {
- HLog(hub, "LH_FARM_SELECT_3", c->Name);
- // Continue the process because myself was selected
- UnlockList(server->FarmMemberList);
- Unlock(cedar->CedarSuperLock);
- f->Point = SiGetPoint(server);
- Lock(hub->lock);
- Free(msg);
- }
- }
- }
- }
- if (admin_mode == false)
- {
- // Check the maximum number of connections of the HUB
- if (hub->Option->MaxSession != 0 &&
- hub->Option->MaxSession <= Count(hub->NumSessions))
- {
- // Can not connect any more
- Unlock(hub->lock);
- HLog(hub, "LH_MAX_SESSION", c->Name, hub->Option->MaxSession);
- ReleaseHub(hub);
- c->Err = ERR_HUB_IS_BUSY;
- Free(policy);
- error_detail = "ERR_HUB_IS_BUSY";
- goto CLEANUP;
- }
- }
- if (use_encrypt == false && c->FirstSock->IsReverseAcceptedSocket)
- {
- // On VPN Azure, SSL encryption is mandated.
- use_encrypt = true;
- }
- if (use_client_license || use_bridge_license)
- {
- // Examine whether not to conflict with the limit of simultaneous connections
- // number of sessions defined by the Virtual HUB management options
- if (
- (GetHubAdminOption(hub, "max_sessions") != 0 &&
- (Count(hub->NumSessionsClient) + Count(hub->NumSessionsBridge)) >= GetHubAdminOption(hub, "max_sessions"))
- ||
- (hub->Option->MaxSession != 0 &&
- (Count(hub->NumSessionsClient) + Count(hub->NumSessionsBridge)) >= hub->Option->MaxSession))
- {
- // Can not connect any more
- Unlock(hub->lock);
- HLog(hub, "LH_MAX_SESSION", c->Name, GetHubAdminOption(hub, "max_sessions"));
- ReleaseHub(hub);
- c->Err = ERR_HUB_IS_BUSY;
- Free(policy);
- goto CLEANUP;
- }
- }
- if (use_client_license)
- {
- // Examine whether not to conflict with the limit of simultaneous connections
- // number of sessions(client) defined by the Virtual HUB management options
- if (((GetHubAdminOption(hub, "max_sessions_client_bridge_apply") != 0
- ) &&
- Count(hub->NumSessionsClient) >= GetHubAdminOption(hub, "max_sessions_client") && hub->Cedar->Server != NULL && hub->Cedar->Server->ServerType != SERVER_TYPE_FARM_MEMBER)
- ||
- (hub->FarmMember_MaxSessionClientBridgeApply &&
- Count(hub->NumSessionsClient) >= hub->FarmMember_MaxSessionClient))
- {
- // Can not connect any more
- Unlock(hub->lock);
- HLog(hub, "LH_MAX_SESSION_CLIENT", c->Name, GetHubAdminOption(hub, "max_sessions_client"));
- ReleaseHub(hub);
- c->Err = ERR_HUB_IS_BUSY;
- Free(policy);
- goto CLEANUP;
- }
- }
- if (use_bridge_license)
- {
- // Examine whether not to conflict with the limit of simultaneous connections
- // number of sessions(bridge) defined by the Virtual HUB management options
- if (((GetHubAdminOption(hub, "max_sessions_client_bridge_apply") != 0
- ) &&
- Count(hub->NumSessionsBridge) >= GetHubAdminOption(hub, "max_sessions_bridge") && hub->Cedar->Server != NULL && hub->Cedar->Server->ServerType != SERVER_TYPE_FARM_MEMBER)
- ||
- (hub->FarmMember_MaxSessionClientBridgeApply &&
- Count(hub->NumSessionsBridge) >= hub->FarmMember_MaxSessionBridge))
- {
- // Can not connect any more
- Unlock(hub->lock);
- HLog(hub, "LH_MAX_SESSION_BRIDGE", c->Name, GetHubAdminOption(hub, "max_sessions_bridge"));
- ReleaseHub(hub);
- c->Err = ERR_HUB_IS_BUSY;
- Free(policy);
- goto CLEANUP;
- }
- }
- if (Count(hub->Cedar->CurrentSessions) >= GetServerCapsInt(hub->Cedar->Server, "i_max_sessions"))
- {
- // Can not connect any more
- Unlock(hub->lock);
- HLog(hub, "LH_MAX_SESSION_2", c->Name, GetServerCapsInt(hub->Cedar->Server, "i_max_sessions"));
- ReleaseHub(hub);
- c->Err = ERR_HUB_IS_BUSY;
- Free(policy);
- goto CLEANUP;
- }
- // Increment the current number of connections
- Inc(hub->NumSessions);
- if (use_bridge_license)
- {
- Inc(hub->NumSessionsBridge);
- }
- if (use_client_license)
- {
- Inc(hub->NumSessionsClient);
- }
- Inc(hub->Cedar->CurrentSessions);
- // Calculate the time-out period
- timeout = policy->TimeOut * 1000; // Convert milliseconds to seconds
- if (timeout == 0)
- {
- timeout = TIMEOUT_DEFAULT;
- }
- timeout = MIN(timeout, TIMEOUT_MAX);
- timeout = MAX(timeout, TIMEOUT_MIN);
- // Update the max_connection according to the policy
- max_connection = MIN(max_connection, policy->MaxConnection);
- max_connection = MIN(max_connection, MAX_TCP_CONNECTION);
- max_connection = MAX(max_connection, 1);
- if (c->FirstSock->IsRUDPSocket)
- {
- // In the case of TCP-over-UDP
- half_connection = false;
- // Disable the QoS
- qos = false;
- if (enable_udp_recovery == false)
- {
- // Disable the session reconnection feature
- no_reconnect_to_session = true;
- max_connection = 1;
- }
- else
- {
- // If the UDP recovery is enabled, permit the session re-connection feature (for 2)
- no_reconnect_to_session = false;
- max_connection = NUM_TCP_CONNECTION_FOR_UDP_RECOVERY;
- }
- }
- if (half_connection)
- {
- // Number of connections should be more than 2 in the case of Half Connection
- max_connection = MAX(max_connection, 2);
- }
- if (qos)
- {
- // Number of connections is set to 2 or more when using the VoIP / QoS
- max_connection = MAX(max_connection, 2);
- if (half_connection)
- {
- max_connection = MAX(max_connection, 4);
- }
- }
- c->Status = CONNECTION_STATUS_ESTABLISHED;
- // Remove the connection from Cedar
- DelConnection(c->Cedar, c);
- // VLAN ID
- if (assigned_vlan_id != 0)
- {
- if (policy != NULL)
- {
- if (policy->VLanId == 0)
- {
- policy->VLanId = assigned_vlan_id;
- }
- }
- }
- // Create a Session
- StrLower(username);
- s = NewServerSessionEx(c->Cedar, c, hub, username, policy, c->IsInProc);
- s->EnableUdpRecovery = enable_udp_recovery;
- s->LocalHostSession = local_host_session;
- s->NormalClient = true;
- IPToStr(s->ClientIP, sizeof(s->ClientIP), &c->ClientIp);
- if (c->FirstSock->IsRUDPSocket)
- {
- // R-UDP session
- s->IsRUDPSession = true;
- s->RUdpMss = c->FirstSock->RUDP_OptimizedMss;
- Debug("Optimized MSS Value for R-UDP: %u\n", s->RUdpMss);
- }
- if (enable_bulk_on_rudp)
- {
- // Allow bulk transfer on R-UDP
- s->EnableBulkOnRUDP = true;
- s->EnableHMacOnBulkOfRUDP = enable_hmac_on_bulk_of_rudp;
- }
- s->IsAzureSession = c->FirstSock->IsReverseAcceptedSocket;
- StrCpy(s->UnderlayProtocol, sizeof(s->UnderlayProtocol), c->FirstSock->UnderlayProtocol);
- if (server != NULL)
- {
- s->NoSendSignature = server->NoSendSignature;
- }
- if (c->IsInProc)
- {
- s->NoSendSignature = true;
- }
- if (c->IsInProc && StrCmpi(c->InProcPrefix, OPENVPN_IPC_POSTFIX_L3) == 0)
- {
- // OpenVPN L3 session
- s->IsOpenVPNL3Session = true;
- }
- if (c->IsInProc && StrCmpi(c->InProcPrefix, OPENVPN_IPC_POSTFIX_L2) == 0)
- {
- // OpenVPN L2 session
- s->IsOpenVPNL2Session = true;
- }
- // Determine whether the use of UDP acceleration mode
- if (use_udp_acceleration_client)
- {
- s->UseUdpAcceleration = true;
- s->UdpAccelFastDisconnectDetect = support_udp_accel_fast_disconnect_detect;
- }
- if (hub->Option != NULL && hub->Option->DisableUdpAcceleration)
- {
- s->UseUdpAcceleration = false;
- }
- if (IsZeroIP(&c->FirstSock->Reverse_MyServerGlobalIp) == false &&
- CmpIpAddr(&c->FirstSock->Reverse_MyServerGlobalIp, &c->FirstSock->RemoteIP) == 0)
- {
- // Disable forcibly the UDP acceleration mode if VPN Server and VPN Client
- // are in same LAN in the case of using VPN Azure.
- // (Or this may cause infinite loop of packet)
- s->UseUdpAcceleration = false;
- }
- if (s->UseUdpAcceleration)
- {
- s->UseHMacOnUdpAcceleration = use_hmac_on_udp_acceleration;
- }
- Debug("UseUdpAcceleration = %u\n", s->UseUdpAcceleration);
- Debug("UseHMacOnUdpAcceleration = %u\n", s->UseHMacOnUdpAcceleration);
- if (s->UseUdpAcceleration)
- {
- bool no_nat_t = false;
- // Initialize the UDP acceleration function
- s->UdpAccel = NewUdpAccel(c->Cedar, (c->FirstSock->IsRUDPSocket ? NULL : &c->FirstSock->LocalIP), false, c->FirstSock->IsRUDPSocket, no_nat_t);
- if (s->UdpAccel == NULL)
- {
- s->UseUdpAcceleration = false;
- Debug("NewUdpAccel Failed.\n");
- }
- else
- {
- if (UdpAccelInitServer(s->UdpAccel, udp_acceleration_client_key, &udp_acceleration_client_ip, udp_acceleration_client_port,
- &c->FirstSock->RemoteIP) == false)
- {
- Debug("UdpAccelInitServer Failed.\n");
- s->UseUdpAcceleration = false;
- }
- s->UdpAccel->FastDetect = s->UdpAccelFastDisconnectDetect;
- if (use_encrypt == false)
- {
- s->UdpAccel->PlainTextMode = true;
- }
- s->UdpAccel->UseHMac = s->UseHMacOnUdpAcceleration;
- }
- }
- s->UseClientLicense = use_client_license;
- s->UseBridgeLicense = use_bridge_license;
- s->AdjustMss = adjust_mss;
- if (s->AdjustMss != 0)
- {
- Debug("AdjustMSS: %u\n", s->AdjustMss);
- }
- s->IsBridgeMode = (policy->NoBridge == false) || (policy->NoRouting == false);
- s->IsMonitorMode = policy->MonitorPort;
- // Decide whether IPv6 session
- s->IPv6Session = false;
- if (node.ClientIpAddress == 0)
- {
- s->IPv6Session = true;
- }
- if (use_bridge_license)
- {
- Inc(s->Cedar->AssignedBridgeLicense);
- }
- if (use_client_license)
- {
- Inc(s->Cedar->AssignedClientLicense);
- }
- if (server != NULL)
- {
- // Update the total allocation of the number of licenses for Server structure
- if (server->ServerType == SERVER_TYPE_STANDALONE)
- {
- // Update only stand-alone mode
- // (Periodically poll in the cluster controller mode)
- server->CurrentAssignedClientLicense = Count(s->Cedar->AssignedClientLicense);
- server->CurrentAssignedBridgeLicense = Count(s->Cedar->AssignedBridgeLicense);
- }
- }
- if (StrLen(sessionname) != 0)
- {
- // Specify the session name
- Free(s->Name);
- s->Name = CopyStr(sessionname);
- }
- {
- char ip[128];
- IPToStr(ip, sizeof(ip), &c->FirstSock->RemoteIP);
- HLog(hub, "LH_NEW_SESSION", c->Name, s->Name, ip, c->FirstSock->RemotePort,
- c->FirstSock->UnderlayProtocol);
- }
- c->Session = s;
- s->AdministratorMode = admin_mode;
- StrCpy(s->UserNameReal, sizeof(s->UserNameReal), username_real);
- StrCpy(s->GroupName, sizeof(s->GroupName), groupname);
- // Get the session key
- Copy(session_key, s->SessionKey, SHA1_SIZE);
- // Set the parameters
- s->MaxConnection = max_connection;
- s->UseEncrypt = use_encrypt;
- if (s->UseEncrypt && use_fast_rc4)
- {
- s->UseFastRC4 = use_fast_rc4;
- }
- s->UseCompress = use_compress;
- s->HalfConnection = half_connection;
- s->Timeout = timeout;
- s->QoS = qos;
- s->NoReconnectToSession = no_reconnect_to_session;
- if (policy != NULL)
- {
- s->VLanId = policy->VLanId;
- }
- // User name
- s->Username = CopyStr(username);
- HLog(hub, "LH_SET_SESSION", s->Name, s->MaxConnection,
- s->UseEncrypt ? _UU("L_YES") : _UU("L_NO"),
- s->UseCompress ? _UU("L_YES") : _UU("L_NO"),
- s->HalfConnection ? _UU("L_YES") : _UU("L_NO"),
- s->Timeout / 1000);
- msg = GetHubMsg(hub);
- // Suppress client update notification flag
- if (hub->Option != NULL)
- {
- suppress_client_update_notification = hub->Option->SuppressClientUpdateNotification;
- }
- }
- Unlock(hub->lock);
- // Send a Welcome packet to the client
- p = PackWelcome(s);
- PackAddBool(p, "suppress_client_update_notification", suppress_client_update_notification);
- if (s->InProcMode)
- {
- if (IsZero(mschap_v2_server_response_20, sizeof(mschap_v2_server_response_20)) == false)
- {
- // MS-CHAPv2 Response
- PackAddData(p, "IpcMsChapV2ServerResponse", mschap_v2_server_response_20, sizeof(mschap_v2_server_response_20));
- }
- }
- if (true)
- {
- // A message to be displayed in the VPN Client (Will not be displayed if the VPN Gate Virtual HUB)
- char *utf;
- wchar_t winver_msg_client[3800];
- wchar_t winver_msg_server[3800];
- UINT tmpsize;
- wchar_t *tmp;
- RPC_WINVER server_winver;
- GetWinVer(&server_winver);
- Zero(winver_msg_client, sizeof(winver_msg_client));
- Zero(winver_msg_server, sizeof(winver_msg_server));
- if (IsSupportedWinVer(&winver) == false)
- {
- SYSTEMTIME st;
- LocalTime(&st);
- UniFormat(winver_msg_client, sizeof(winver_msg_client), _UU("WINVER_ERROR_FORMAT"),
- _UU("WINVER_ERROR_PC_LOCAL"),
- winver.Title,
- _UU("WINVER_ERROR_VPNSERVER"),
- SUPPORTED_WINDOWS_LIST,
- _UU("WINVER_ERROR_PC_LOCAL"),
- _UU("WINVER_ERROR_VPNSERVER"),
- _UU("WINVER_ERROR_VPNSERVER"),
- _UU("WINVER_ERROR_VPNSERVER"),
- st.wYear, st.wMonth);
- }
- if (IsSupportedWinVer(&server_winver) == false)
- {
- SYSTEMTIME st;
- LocalTime(&st);
- UniFormat(winver_msg_server, sizeof(winver_msg_server), _UU("WINVER_ERROR_FORMAT"),
- _UU("WINVER_ERROR_PC_REMOTE"),
- server_winver.Title,
- _UU("WINVER_ERROR_VPNSERVER"),
- SUPPORTED_WINDOWS_LIST,
- _UU("WINVER_ERROR_PC_REMOTE"),
- _UU("WINVER_ERROR_VPNSERVER"),
- _UU("WINVER_ERROR_VPNSERVER"),
- _UU("WINVER_ERROR_VPNSERVER"),
- st.wYear, st.wMonth);
- }
- tmpsize = UniStrSize(winver_msg_client) + UniStrSize(winver_msg_server) + UniStrSize(msg) + (16000 + 3000) * sizeof(wchar_t);
- tmp = ZeroMalloc(tmpsize);
- if (IsURLMsg(msg, NULL, 0) == false)
- {
- if (s != NULL && s->IsRUDPSession && c != NULL && StrCmpi(hub->Name, VG_HUBNAME) != 0)
- {
- // Show the warning message if the connection is made by NAT-T
- wchar_t *tmp2;
- UINT tmp2_size = 2400 * sizeof(wchar_t);
- char local_name[128];
- wchar_t local_name_2[128];
- char local_name_3[128];
- Zero(local_name, sizeof(local_name));
- Zero(local_name_2, sizeof(local_name_2));
- Zero(local_name_3, sizeof(local_name_3));
- GetMachineName(local_name, sizeof(local_name));
- #ifdef OS_WIN32
- MsGetComputerNameFullEx(local_name_2, sizeof(local_name_2), true);
- UniToStr(local_name_3, sizeof(local_name_3), local_name_2);
- if (IsEmptyStr(local_name_3) == false)
- {
- StrCpy(local_name, sizeof(local_name), local_name_3);
- }
- #endif // OS_WIN32
- tmp2 = ZeroMalloc(tmp2_size);
- UniFormat(tmp2, tmp2_size, _UU(c->ClientBuild >= 9428 ? "NATT_MSG" : "NATT_MSG2"), local_name);
- UniStrCat(tmp, tmpsize, tmp2);
- Free(tmp2);
- }
- {
- if (GetGlobalServerFlag(GSF_SHOW_OSS_MSG) != 0)
- {
- UniStrCat(tmp, tmpsize, _UU("OSS_MSG"));
- }
- }
- {
- UniStrCat(tmp, tmpsize, winver_msg_client);
- UniStrCat(tmp, tmpsize, winver_msg_server);
- }
- }
- UniStrCat(tmp, tmpsize, msg);
-
- utf = CopyUniToUtf(tmp);
- PackAddData(p, "Msg", utf, StrLen(utf));
- Free(tmp);
- Free(utf);
- }
- Free(msg);
- if (s->UseFastRC4)
- {
- // Generate a RC4 key pair
- GenerateRC4KeyPair(&key_pair);
- // Add to Welcome packet
- PackAddData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey, sizeof(key_pair.ClientToServerKey));
- PackAddData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey, sizeof(key_pair.ServerToClientKey));
- {
- char key1[64], key2[64];
- BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
- BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
- Debug(
- "Client to Server Key: %s\n"
- "Server to Client Key: %s\n",
- key1, key2);
- }
- }
- // Brand string for the connection limit
- {
- char *branded_cfroms = _SS("BRANDED_C_FROM_S");
- if(StrLen(branded_cfroms) > 0)
- {
- PackAddStr(p, "branded_cfroms", branded_cfroms);
- }
- }
- HttpServerSend(c->FirstSock, p);
- FreePack(p);
- // Receive a signature
- Copy(&c->Session->NodeInfo, &node, sizeof(NODE_INFO));
- {
- wchar_t tmp[MAX_SIZE * 2];
- NodeInfoToStr(tmp, sizeof(tmp), &s->NodeInfo);
- HLog(hub, "LH_NODE_INFO", s->Name, tmp);
- if (s->VLanId != 0)
- {
- HLog(hub, "LH_VLAN_ID", s->Name, s->VLanId);
- }
- }
- // Shift the connection to the tunneling mode
- StartTunnelingMode(c);
- // Processing of half-connection mode
- if (s->HalfConnection)
- {
- // The direction of the first socket is client to server
- TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
- ts->Direction = TCP_CLIENT_TO_SERVER;
- }
- if (s->UseFastRC4)
- {
- // Set the RC4 key information to the first TCP connection
- TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
- Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
- InitTcpSockRc4Key(ts, true);
- }
- if (s->UseEncrypt && s->UseFastRC4 == false)
- {
- s->UseSSLDataEncryption = true;
- }
- else
- {
- s->UseSSLDataEncryption = false;
- }
- if (s->Hub->Type == HUB_TYPE_FARM_DYNAMIC && s->Cedar->Server != NULL && s->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
- {
- if (s->Hub->BeingOffline == false)
- {
- // Start the SecureNAT on the dynamic Virtual HUB
- EnableSecureNATEx(s->Hub, false, true);
- cluster_dynamic_secure_nat = true;
- }
- }
- if (s->LocalHostSession)
- {
- // Update the local MAC address list
- RefreshLocalMacAddressList();
- }
- // Discard the user list cache
- DeleteAllUserListCache(hub->UserList);
- // Main routine of the session
- Debug("SessionMain()\n");
- s->NumLoginIncrementUserObject = loggedin_user_object;
- s->NumLoginIncrementHubObject = s->Hub;
- s->NumLoginIncrementTick = Tick64() + (UINT64)NUM_LOGIN_INCREMENT_INTERVAL;
- SessionMain(s);
- // Discard the user list cache
- DeleteAllUserListCache(hub->UserList);
- // Decrement the current number of connections
- Lock(s->Hub->lock);
- {
- if (use_bridge_license)
- {
- Dec(hub->NumSessionsBridge);
- }
- if (use_client_license)
- {
- Dec(hub->NumSessionsClient);
- }
- Dec(s->Hub->NumSessions);
- Dec(s->Hub->Cedar->CurrentSessions);
- // Decrement the number of licenses
- if (use_bridge_license)
- {
- Dec(s->Cedar->AssignedBridgeLicense);
- }
- if (use_client_license)
- {
- Dec(s->Cedar->AssignedClientLicense);
- }
- if (server != NULL)
- {
- // Update the total allocation of the number of licenses for Server structure
- if (server->ServerType == SERVER_TYPE_STANDALONE)
- {
- // Update only stand-alone mode
- // (Periodically polled in the cluster controller mode)
- server->CurrentAssignedClientLicense = Count(s->Cedar->AssignedClientLicense);
- server->CurrentAssignedBridgeLicense = Count(s->Cedar->AssignedBridgeLicense);
- }
- }
- }
- Unlock(s->Hub->lock);
- PrintSessionTotalDataSize(s);
- HLog(s->Hub, "LH_END_SESSION", s->Name, s->TotalSendSizeReal, s->TotalRecvSizeReal);
- if (cluster_dynamic_secure_nat && s->Hub->BeingOffline == false)
- {
- // Stop the SecureNAT on the dynamic Virtual HUB
- EnableSecureNATEx(s->Hub, false, true);
- }
- if (s->UdpAccel != NULL)
- {
- // Release the UDP acceleration
- FreeUdpAccel(s->UdpAccel);
- s->UdpAccel = NULL;
- }
- ReleaseSession(s);
- ret = true;
- c->Err = ERR_SESSION_REMOVED;
- ReleaseHub(hub);
- goto CLEANUP;
- }
- else if (StrCmpi(method, "additional_connect") == 0)
- {
- SOCK *sock;
- TCPSOCK *ts;
- UINT dummy;
- c->Type = CONNECTION_TYPE_ADDITIONAL;
- // Additional connection
- // Read the session key
- if (GetSessionKeyFromPack(p, session_key, &dummy) == false)
- {
- FreePack(p);
- c->Err = ERR_PROTOCOL_ERROR;
- goto CLEANUP;
- }
- FreePack(p);
- // Get the session from the session key
- s = GetSessionFromKey(c->Cedar, session_key);
- if (s == NULL || s->Halt || s->NoReconnectToSession)
- {
- // Session can not be found, or re-connection is prohibited
- Debug("Session Not Found.\n");
- c->Err = ERR_SESSION_TIMEOUT;
- goto CLEANUP;
- }
- // Session is found
- Debug("Session Found: %s\n", s->Name);
- // Check the protocol of session
- c->Err = 0;
- Lock(s->lock);
- {
- if (s->Connection->Protocol != CONNECTION_TCP)
- {
- c->Err = ERR_INVALID_PROTOCOL;
- }
- }
- Unlock(s->lock);
- // Check the current number of connections of the session
- Lock(s->Connection->lock);
- if (c->Err == 0)
- {
- if (Count(s->Connection->CurrentNumConnection) > s->MaxConnection)
- {
- c->Err = ERR_TOO_MANY_CONNECTION;
- }
- }
- if (c->Err != 0)
- {
- Unlock(s->Connection->lock);
- if (c->Err == ERR_TOO_MANY_CONNECTION)
- {
- Debug("Session TOO MANY CONNECTIONS !!: %u\n",
- Count(s->Connection->CurrentNumConnection));
- }
- else
- {
- Debug("Session Invalid Protocol.\n");
- }
- ReleaseSession(s);
- goto CLEANUP;
- }
- // Generate a high-speed RC4 encryption key
- if (s->UseFastRC4)
- {
- GenerateRC4KeyPair(&key_pair);
- }
- // Add the socket of this connection to the connection list of the session (TCP)
- sock = c->FirstSock;
- ts = NewTcpSock(sock);
- SetTimeout(sock, CONNECTING_TIMEOUT);
- direction = TCP_BOTH;
- LockList(s->Connection->Tcp->TcpSockList);
- {
- if (s->HalfConnection)
- {
- // In half-connection, directions of the TCP connections are automatically
- // adjusted by examining all current direction of the TCP connections
- UINT i, c2s, s2c;
- c2s = s2c = 0;
- for (i = 0;i < LIST_NUM(s->Connection->Tcp->TcpSockList);i++)
- {
- TCPSOCK *ts = (TCPSOCK *)LIST_DATA(s->Connection->Tcp->TcpSockList, i);
- if (ts->Direction == TCP_SERVER_TO_CLIENT)
- {
- s2c++;
- }
- else
- {
- c2s++;
- }
- }
- if (s2c > c2s)
- {
- direction = TCP_CLIENT_TO_SERVER;
- }
- else
- {
- direction = TCP_SERVER_TO_CLIENT;
- }
- Debug("%u/%u\n", s2c, c2s);
- ts->Direction = direction;
- }
- }
- UnlockList(s->Connection->Tcp->TcpSockList);
- if (s->UseFastRC4)
- {
- // Set the RC4 key information
- Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
- InitTcpSockRc4Key(ts, true);
- }
- // Return a success result
- p = PackError(ERR_NO_ERROR);
- PackAddInt(p, "direction", direction);
- if (s->UseFastRC4)
- {
- // Add a RC4 key information
- PackAddData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey, sizeof(key_pair.ClientToServerKey));
- PackAddData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey, sizeof(key_pair.ServerToClientKey));
- {
- char key1[64], key2[64];
- BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
- BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
- Debug(
- "Client to Server Key: %s\n"
- "Server to Client Key: %s\n",
- key1, key2);
- }
- }
- HttpServerSend(c->FirstSock, p);
- FreePack(p);
- SetTimeout(sock, INFINITE);
- LockList(s->Connection->Tcp->TcpSockList);
- {
- Add(s->Connection->Tcp->TcpSockList, ts);
- }
- UnlockList(s->Connection->Tcp->TcpSockList);
- // Increment the number of connections
- Inc(s->Connection->CurrentNumConnection);
- Debug("TCP Connection Incremented: %u\n", Count(s->Connection->CurrentNumConnection));
- // Issue the Cancel of session
- Cancel(s->Cancel1);
- Unlock(s->Connection->lock);
- c->flag1 = true;
- ReleaseSession(s);
- return true;
- }
- else if (StrCmpi(method, "enum_hub") == 0)
- {
- // Enumerate the Virtual HUB
- UINT i, num;
- LIST *o;
- o = NewListFast(NULL);
- c->Type = CONNECTION_TYPE_ENUM_HUB;
- FreePack(p);
- p = NewPack();
- LockList(c->Cedar->HubList);
- {
- num = LIST_NUM(c->Cedar->HubList);
- for (i = 0;i < num;i++)
- {
- HUB *h = LIST_DATA(c->Cedar->HubList, i);
- if (h->Option != NULL && h->Option->NoEnum == false)
- {
- Insert(o, CopyStr(h->Name));
- }
- }
- }
- UnlockList(c->Cedar->HubList);
- num = LIST_NUM(o);
- for (i = 0;i < num;i++)
- {
- char *name = LIST_DATA(o, i);
- PackAddStrEx(p, "HubName", name, i, num);
- Free(name);
- }
- ReleaseList(o);
- PackAddInt(p, "NumHub", num);
- HttpServerSend(c->FirstSock, p);
- FreePack(p);
- FreePack(HttpServerRecv(c->FirstSock));
- c->Err = 0;
- SLog(c->Cedar, "LS_ENUM_HUB", c->Name, num);
- error_detail = "enum_hub";
- goto CLEANUP;
- }
- else if (StrCmpi(method, "farm_connect") == 0)
- {
- // Server farm connection request
- CEDAR *cedar = c->Cedar;
- c->Type = CONNECTION_TYPE_FARM_RPC;
- c->Err = 0;
- if (c->Cedar->Server == NULL)
- {
- // Unsupported
- c->Err = ERR_NOT_FARM_CONTROLLER;
- }
- else
- {
- SERVER *s = c->Cedar->Server;
- if (s->ServerType != SERVER_TYPE_FARM_CONTROLLER || s->FarmControllerInited == false)
- {
- // Not a farm controller
- SLog(c->Cedar, "LS_FARM_ACCEPT_1", c->Name);
- c->Err = ERR_NOT_FARM_CONTROLLER;
- }
- else
- {
- UCHAR check_secure_password[SHA1_SIZE];
- UCHAR secure_password[SHA1_SIZE];
- // User authentication
- SecurePassword(check_secure_password, s->HashedPassword, c->Random);
- if (PackGetDataSize(p, "SecurePassword") == sizeof(secure_password))
- {
- PackGetData(p, "SecurePassword", secure_password);
- }
- else
- {
- Zero(secure_password, sizeof(secure_password));
- }
- if (Cmp(secure_password, check_secure_password, SHA1_SIZE) != 0)
- {
- // Password is different
- SLog(c->Cedar, "LS_FARM_ACCEPT_2", c->Name);
- c->Err = ERR_ACCESS_DENIED;
- }
- else
- {
- // Get the certificate
- BUF *b;
- X *server_x;
- SLog(c->Cedar, "LS_FARM_ACCEPT_3", c->Name);
- b = PackGetBuf(p, "ServerCert");
- if (b == NULL)
- {
- c->Err = ERR_PROTOCOL_ERROR;
- }
- else
- {
- server_x = BufToX(b, false);
- FreeBuf(b);
- if (server_x == NULL)
- {
- c->Err = ERR_PROTOCOL_ERROR;
- }
- else
- {
- UINT ip;
- UINT point;
- char hostname[MAX_SIZE];
- #ifdef OS_WIN32
- MsSetThreadPriorityRealtime();
- #endif // OS_WIN32
- SetTimeout(c->FirstSock, SERVER_CONTROL_TCP_TIMEOUT);
- ip = PackGetIp32(p, "PublicIp");
- point = PackGetInt(p, "Point");
- if (PackGetStr(p, "HostName", hostname, sizeof(hostname)))
- {
- UINT num_port = PackGetIndexCount(p, "PublicPort");
- if (num_port >= 1 && num_port <= MAX_PUBLIC_PORT_NUM)
- {
- UINT *ports = ZeroMalloc(sizeof(UINT) * num_port);
- UINT i;
- for (i = 0;i < num_port;i++)
- {
- ports[i] = PackGetIntEx(p, "PublicPort", i);
- }
- SiFarmServ(s, c->FirstSock, server_x, ip, num_port, ports, hostname, point,
- PackGetInt(p, "Weight"), PackGetInt(p, "MaxSessions"));
- Free(ports);
- }
- }
- FreeX(server_x);
- }
- }
- }
- }
- }
- FreePack(p);
- goto CLEANUP;
- }
- else if (StrCmpi(method, "admin") == 0 && c->Cedar->Server != NULL)
- {
- UINT err;
- // Administrative RPC connection request
- c->Type = CONNECTION_TYPE_ADMIN_RPC;
- err = AdminAccept(c, p);
- FreePack(p);
- if (err != ERR_NO_ERROR)
- {
- PACK *p = PackError(err);
- HttpServerSend(c->FirstSock, p);
- FreePack(p);
- }
- error_detail = "admin_rpc";
- goto CLEANUP;
- }
- else if (StrCmpi(method, "password") == 0)
- {
- UINT err;
- // Password change request
- c->Type = CONNECTION_TYPE_PASSWORD;
- err = ChangePasswordAccept(c, p);
- FreePack(p);
- p = PackError(err);
- HttpServerSend(c->FirstSock, p);
- FreePack(p);
- error_detail = "change_password";
- goto CLEANUP;
- }
- else
- {
- // Unknown method
- FreePack(p);
- c->Err = ERR_PROTOCOL_ERROR;
- error_detail = "unknown_method";
- goto CLEANUP;
- }
- CLEANUP:
- // Release the user object
- if (loggedin_user_object != NULL)
- {
- ReleaseUser(loggedin_user_object);
- }
- // Error packet transmission
- if (supress_return_pack_error == false)
- {
- p = PackError(c->Err);
- PackAddBool(p, "no_save_password", no_save_password);
- HttpServerSend(c->FirstSock, p);
- FreePack(p);
- }
- FreePack(HttpServerRecv(c->FirstSock));
- SleepThread(25);
- SLog(c->Cedar, "LS_CONNECTION_ERROR", c->Name, GetUniErrorStr(c->Err), c->Err);
- if (release_me_eap_client != NULL)
- {
- ReleaseEapClient(release_me_eap_client);
- }
- return ret;
- }
- // Create a Node information
- void CreateNodeInfo(NODE_INFO *info, CONNECTION *c)
- {
- SESSION *s;
- OS_INFO *os;
- char *product_id;
- IP ip;
- bool is_vgc = false;
- // Validate arguments
- if (c == NULL)
- {
- return;
- }
- s = c->Session;
- os = GetOsInfo();
- Zero(info, sizeof(NODE_INFO));
- // Client product name
- StrCpy(info->ClientProductName, sizeof(info->ClientProductName), c->ClientStr);
- // Client version
- info->ClientProductVer = Endian32(c->ClientVer);
- // Client build number
- info->ClientProductBuild = Endian32(c->ClientBuild);
- // Server product name
- StrCpy(info->ServerProductName, sizeof(info->ServerProductName), c->ServerStr);
- // Server version
- info->ServerProductVer = Endian32(c->ServerVer);
- // Server build number
- info->ServerProductBuild = Endian32(c->ServerBuild);
- // Client OS name
- StrCpy(info->ClientOsName, sizeof(info->ClientOsName), os->OsProductName);
- // Client OS version
- StrCpy(info->ClientOsVer, sizeof(info->ClientOsVer), os->OsVersion);
- // Client OS Product ID
- product_id = OSGetProductId();
- StrCpy(info->ClientOsProductId, sizeof(info->ClientOsProductId), product_id);
- Free(product_id);
- // Client host name
- #ifndef OS_WIN32
- GetMachineName(info->ClientHostname, sizeof(info->ClientHostname));
- #else // OS_WIN32
- if (true)
- {
- wchar_t namew[256];
- char namea[256];
- Zero(namew, sizeof(namew));
- MsGetComputerNameFullEx(namew, sizeof(namew), true);
- Zero(namea, sizeof(namea));
- UniToStr(namea, sizeof(namea), namew);
- if (IsEmptyStr(namea))
- {
- GetMachineName(namea, sizeof(namea));
- }
- StrCpy(info->ClientHostname, sizeof(info->ClientHostname), namea);
- }
- #endif // OS_WIN32
- // Client IP address
- if (IsIP6(&c->FirstSock->LocalIP) == false)
- {
- info->ClientIpAddress = IPToUINT(&c->FirstSock->LocalIP);
- }
- else
- {
- Copy(info->ClientIpAddress6, c->FirstSock->LocalIP.ipv6_addr, sizeof(info->ClientIpAddress6));
- }
- // Client port number
- info->ClientPort = Endian32(c->FirstSock->LocalPort);
- // Server host name
- StrCpy(info->ServerHostname, sizeof(info->ServerHostname), c->ServerName);
- // Server IP address
- if (GetIP(&ip, info->ServerHostname))
- {
- if (IsIP6(&ip) == false)
- {
- info->ServerIpAddress = IPToUINT(&ip);
- }
- else
- {
- Copy(info->ServerIpAddress6, ip.ipv6_addr, sizeof(info->ServerIpAddress6));
- }
- }
- // Server port number
- info->ServerPort = Endian32(c->ServerPort);
- if (s->ClientOption->ProxyType == PROXY_SOCKS || s->ClientOption->ProxyType == PROXY_HTTP)
- {
- // Proxy host name
- StrCpy(info->ProxyHostname, sizeof(info->ProxyHostname), s->ClientOption->ProxyName);
- // Proxy Server IP Address
- if (IsIP6(&c->FirstSock->RemoteIP) == false)
- {
- info->ProxyIpAddress = IPToUINT(&c->FirstSock->RemoteIP);
- }
- else
- {
- Copy(&info->ProxyIpAddress6, c->FirstSock->RemoteIP.ipv6_addr, sizeof(info->ProxyIpAddress6));
- }
- info->ProxyPort = Endian32(c->FirstSock->RemotePort);
- }
- // HUB name
- StrCpy(info->HubName, sizeof(info->HubName), s->ClientOption->HubName);
- // Unique ID
- Copy(info->UniqueId, c->Cedar->UniqueId, sizeof(info->UniqueId));
- }
- // Connect a socket additionally
- SOCK *ClientAdditionalConnectToServer(CONNECTION *c)
- {
- SOCK *s;
- // Validate arguments
- if (c == NULL)
- {
- return NULL;
- }
- // Socket connection
- s = ClientConnectGetSocket(c, true, (c->DontUseTls1 ? false : true));
- if (s == NULL)
- {
- // Connection failure
- return NULL;
- }
- // Add the socket to the list
- LockList(c->ConnectingSocks);
- {
- Add(c->ConnectingSocks, s);
- AddRef(s->ref);
- }
- UnlockList(c->ConnectingSocks);
- if (c->Session->Halt)
- {
- // Stop
- Disconnect(s);
- LockList(c->ConnectingSocks);
- {
- if (Delete(c->ConnectingSocks, s))
- {
- ReleaseSock(s);
- }
- }
- UnlockList(c->ConnectingSocks);
- ReleaseSock(s);
- return NULL;
- }
- // Time-out
- SetTimeout(s, CONNECTING_TIMEOUT);
- // Start the SSL communication
- if (StartSSLEx(s, NULL, NULL, (c->DontUseTls1 ? false : true), 0, c->ServerName) == false)
- {
- // SSL communication failure
- Disconnect(s);
- LockList(c->ConnectingSocks);
- {
- if (Delete(c->ConnectingSocks, s))
- {
- ReleaseSock(s);
- }
- }
- UnlockList(c->ConnectingSocks);
- ReleaseSock(s);
- return NULL;
- }
- // Check the certificate
- if (CompareX(s->RemoteX, c->ServerX) == false)
- {
- // The certificate is invalid
- Disconnect(s);
- c->Session->SessionTimeOuted = true;
- }
- return s;
- }
- // Remove the key and certificate in the secure device
- UINT SecureDelete(UINT device_id, char *pin, char *cert_name, char *key_name)
- {
- SECURE *sec;
- // Validate arguments
- if (pin == NULL || device_id == 0)
- {
- return ERR_INTERNAL_ERROR;
- }
- // Open the device
- sec = OpenSec(device_id);
- if (sec == NULL)
- {
- return ERR_SECURE_DEVICE_OPEN_FAILED;
- }
- // Open the session
- if (OpenSecSession(sec, 0) == false)
- {
- CloseSec(sec);
- return ERR_SECURE_DEVICE_OPEN_FAILED;
- }
- // Login
- if (LoginSec(sec, pin) == false)
- {
- CloseSecSession(sec);
- CloseSec(sec);
- return ERR_SECURE_PIN_LOGIN_FAILED;
- }
- // Delete the certificate
- if (cert_name != NULL)
- {
- DeleteSecCert(sec, cert_name);
- }
- // Delete the Private key
- if (key_name != NULL)
- {
- DeleteSecKey(sec, key_name);
- }
- // Log out
- LogoutSec(sec);
- // Close the session
- CloseSecSession(sec);
- // Close the device
- CloseSec(sec);
- return ERR_NO_ERROR;
- }
- // Enumerate certificates and keys in the secure device
- UINT SecureEnum(UINT device_id, char *pin, TOKEN_LIST **cert_list, TOKEN_LIST **key_list)
- {
- SECURE *sec;
- LIST *o;
- LIST *cert_name_list, *key_name_list;
- // Validate arguments
- if (pin == NULL || device_id == 0 || cert_list == NULL || key_list == NULL)
- {
- return ERR_INTERNAL_ERROR;
- }
- // Open the device
- sec = OpenSec(device_id);
- if (sec == NULL)
- {
- return ERR_SECURE_DEVICE_OPEN_FAILED;
- }
- // Open the session
- if (OpenSecSession(sec, 0) == false)
- {
- CloseSec(sec);
- return ERR_SECURE_DEVICE_OPEN_FAILED;
- }
- // Login
- if (LoginSec(sec, pin) == false)
- {
- CloseSecSession(sec);
- CloseSec(sec);
- return ERR_SECURE_PIN_LOGIN_FAILED;
- }
- // Enumerate objects
- if ((o = EnumSecObject(sec)) != NULL)
- {
- UINT i;
- cert_name_list = NewList(CompareStr);
- key_name_list = NewList(CompareStr);
- for (i = 0;i < LIST_NUM(o);i++)
- {
- SEC_OBJ *obj = LIST_DATA(o, i);
- if (obj->Type == SEC_X)
- {
- Add(cert_name_list, CopyStr(obj->Name));
- }
- else if (obj->Type == SEC_K)
- {
- Add(key_name_list, CopyStr(obj->Name));
- }
- }
- Sort(cert_name_list);
- Sort(key_name_list);
- *cert_list = ListToTokenList(cert_name_list);
- *key_list = ListToTokenList(key_name_list);
- // Release the memory
- FreeStrList(cert_name_list);
- FreeStrList(key_name_list);
- FreeEnumSecObject(o);
- }
- else
- {
- *cert_list = NullToken();
- *key_list = NullToken();
- }
- // Log out
- LogoutSec(sec);
- // Close the session
- CloseSecSession(sec);
- // Close the device
- CloseSec(sec);
- return ERR_NO_ERROR;
- }
- // Record the certificate and key to secure device
- UINT SecureWrite(UINT device_id, char *cert_name, X *x, char *key_name, K *k, char *pin)
- {
- SECURE *sec;
- bool failed;
- // Validate arguments
- if (pin == NULL || device_id == 0 || cert_name == NULL || x == NULL || key_name == NULL || k == NULL)
- {
- return ERR_INTERNAL_ERROR;
- }
- // Open the device
- sec = OpenSec(device_id);
- if (sec == NULL)
- {
- return ERR_SECURE_DEVICE_OPEN_FAILED;
- }
- // Open the session
- if (OpenSecSession(sec, 0) == false)
- {
- CloseSec(sec);
- return ERR_SECURE_DEVICE_OPEN_FAILED;
- }
- // Login
- if (LoginSec(sec, pin) == false)
- {
- CloseSecSession(sec);
- CloseSec(sec);
- return ERR_SECURE_PIN_LOGIN_FAILED;
- }
- // Registration
- failed = false;
- // Register the certificate
- if (WriteSecCert(sec, true, cert_name, x) == false)
- {
- failed = true;
- }
- // Register the private key
- if (WriteSecKey(sec, true, key_name, k) == false)
- {
- failed = true;
- }
- // Log out
- LogoutSec(sec);
- // Close the session
- CloseSecSession(sec);
- // Close the device
- CloseSec(sec);
- if (failed == false)
- {
- // Success
- return ERR_NO_ERROR;
- }
- else
- {
- // Failure
- return ERR_SECURE_CANT_WRITE;
- }
- }
- // Attempt to sign by the secure device
- UINT SecureSign(SECURE_SIGN *sign, UINT device_id, char *pin)
- {
- SECURE *sec;
- X *x;
- // Validate arguments
- if (sign == false || pin == NULL || device_id == 0)
- {
- return ERR_INTERNAL_ERROR;
- }
- // Open the device
- sec = OpenSec(device_id);
- if (sec == NULL)
- {
- return ERR_SECURE_DEVICE_OPEN_FAILED;
- }
- // Open the session
- if (OpenSecSession(sec, 0) == false)
- {
- CloseSec(sec);
- return ERR_SECURE_DEVICE_OPEN_FAILED;
- }
- // Login
- if (LoginSec(sec, pin) == false)
- {
- CloseSecSession(sec);
- CloseSec(sec);
- return ERR_SECURE_PIN_LOGIN_FAILED;
- }
- // Read the certificate
- x = ReadSecCert(sec, sign->SecurePublicCertName);
- if (x == NULL)
- {
- LogoutSec(sec);
- CloseSecSession(sec);
- CloseSec(sec);
- return ERR_SECURE_NO_CERT;
- }
- // Sign by the private key
- if (SignSec(sec, sign->SecurePrivateKeyName, sign->Signature, sign->Random, SHA1_SIZE) == false)
- {
- // Signing failure
- FreeX(x);
- LogoutSec(sec);
- CloseSecSession(sec);
- CloseSec(sec);
- return ERR_SECURE_NO_PRIVATE_KEY;
- }
- // Convert the certificate to buffer
- sign->ClientCert = x;
- // Log out
- LogoutSec(sec);
- // Close the session
- CloseSecSession(sec);
- // Close the device
- CloseSec(sec);
- // Success
- return ERR_NO_ERROR;
- }
- // Client connects to the server additionally
- bool ClientAdditionalConnect(CONNECTION *c, THREAD *t)
- {
- SOCK *s;
- PACK *p;
- TCPSOCK *ts;
- UINT err;
- UINT direction;
- RC4_KEY_PAIR key_pair;
- // Validate arguments
- if (c == NULL)
- {
- return false;
- }
- // Socket connection to the server
- s = ClientAdditionalConnectToServer(c);
- if (s == NULL)
- {
- // Failed to connect socket
- return false;
- }
- if (c->Halt)
- {
- goto CLEANUP;
- }
- // Send a signature
- Debug("Uploading Signature...\n");
- if (ClientUploadSignature(s) == false)
- {
- goto CLEANUP;
- }
- if (c->Halt)
- {
- // Stop
- goto CLEANUP;
- }
- // Receive a Hello packet
- Debug("Downloading Hello...\n");
- if (ClientDownloadHello(c, s) == false)
- {
- goto CLEANUP;
- }
- if (c->Halt)
- {
- // Stop
- goto CLEANUP;
- }
- // Send a authentication data for the additional connection
- if (ClientUploadAuth2(c, s) == false)
- {
- // Disconnected
- goto CLEANUP;
- }
- // Receive a response
- p = HttpClientRecv(s);
- if (p == NULL)
- {
- // Disconnected
- goto CLEANUP;
- }
- err = GetErrorFromPack(p);
- direction = PackGetInt(p, "direction");
- if (c->Session->UseFastRC4)
- {
- // Get the RC4 key information
- if (PackGetDataSize(p, "rc4_key_client_to_server") == 16)
- {
- PackGetData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey);
- }
- if (PackGetDataSize(p, "rc4_key_server_to_client") == 16)
- {
- PackGetData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey);
- }
- {
- char key1[64], key2[64];
- BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
- BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
- Debug(
- "Client to Server Key: %s\n"
- "Server to Client Key: %s\n",
- key1, key2);
- }
- }
- FreePack(p);
- p = NULL;
- if (err != 0)
- {
- // Error has occurred
- Debug("Additional Connect Error: %u\n", err);
- if (err == ERR_SESSION_TIMEOUT || err == ERR_INVALID_PROTOCOL)
- {
- // We shall re-connection because it is a fatal error
- c->Session->SessionTimeOuted = true;
- }
- goto CLEANUP;
- }
- Debug("Additional Connect Succeed!\n");
- // Success the additional connection
- // Add to the TcpSockList of the connection
- ts = NewTcpSock(s);
- if (c->ServerMode == false)
- {
- if (c->Session->ClientOption->ConnectionDisconnectSpan != 0)
- {
- ts->DisconnectTick = Tick64() + c->Session->ClientOption->ConnectionDisconnectSpan * (UINT64)1000;
- }
- }
- LockList(c->Tcp->TcpSockList);
- {
- ts->Direction = direction;
- Add(c->Tcp->TcpSockList, ts);
- }
- UnlockList(c->Tcp->TcpSockList);
- Debug("TCP Connection Incremented: %u\n", Count(c->CurrentNumConnection));
- if (c->Session->HalfConnection)
- {
- Debug("New Half Connection: %s\n",
- direction == TCP_SERVER_TO_CLIENT ? "TCP_SERVER_TO_CLIENT" : "TCP_CLIENT_TO_SERVER"
- );
- }
- if (c->Session->UseFastRC4)
- {
- // Set the RC4 encryption key
- Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
- InitTcpSockRc4Key(ts, false);
- }
- // Issue the Cancel to the session
- Cancel(c->Session->Cancel1);
- // Remove the socket from the socket list of connected
- LockList(c->ConnectingSocks);
- {
- if (Delete(c->ConnectingSocks, s))
- {
- ReleaseSock(s);
- }
- }
- UnlockList(c->ConnectingSocks);
- ReleaseSock(s);
- return true;
- CLEANUP:
- // Disconnection process
- Disconnect(s);
- LockList(c->ConnectingSocks);
- {
- if (Delete(c->ConnectingSocks, s))
- {
- ReleaseSock(s);
- }
- }
- UnlockList(c->ConnectingSocks);
- ReleaseSock(s);
- return false;
- }
- // Secure device signing thread
- void ClientSecureSignThread(THREAD *thread, void *param)
- {
- SECURE_SIGN_THREAD_PROC *p = (SECURE_SIGN_THREAD_PROC *)param;
- // Validate arguments
- if (thread == NULL || param == NULL)
- {
- return;
- }
- NoticeThreadInit(thread);
- p->Ok = p->SecureSignProc(p->Connection->Session, p->Connection, p->SecureSign);
- p->UserFinished = true;
- }
- // Signing with the secure device
- bool ClientSecureSign(CONNECTION *c, UCHAR *sign, UCHAR *random, X **x)
- {
- SECURE_SIGN_THREAD_PROC *p;
- SECURE_SIGN *ss;
- SESSION *s;
- CLIENT_OPTION *o;
- CLIENT_AUTH *a;
- THREAD *thread;
- UINT64 start;
- bool ret;
- // Validate arguments
- if (c == NULL || sign == NULL || random == NULL || x == NULL)
- {
- return false;
- }
- s = c->Session;
- o = s->ClientOption;
- a = s->ClientAuth;
- p = ZeroMalloc(sizeof(SECURE_SIGN_THREAD_PROC));
- p->Connection = c;
- ss = p->SecureSign = ZeroMallocEx(sizeof(SECURE_SIGN), true);
- StrCpy(ss->SecurePrivateKeyName, sizeof(ss->SecurePrivateKeyName),
- a->SecurePrivateKeyName);
- StrCpy(ss->SecurePublicCertName, sizeof(ss->SecurePublicCertName),
- a->SecurePublicCertName);
- ss->UseSecureDeviceId = c->Cedar->Client->UseSecureDeviceId;
- Copy(ss->Random, random, SHA1_SIZE);
- #ifdef OS_WIN32
- ss->BitmapId = CmGetSecureBitmapId(c->ServerName);
- #endif // OS_WIN32
- p->SecureSignProc = a->SecureSignProc;
- // Create a thread
- thread = NewThread(ClientSecureSignThread, p);
- WaitThreadInit(thread);
- // Poll every 0.5 seconds until signing is completed or canceled
- start = Tick64();
- while (true)
- {
- if ((Tick64() - start) > CONNECTING_POOLING_SPAN)
- {
- // Send a NOOP periodically for disconnection prevention
- start = Tick64();
- ClientUploadNoop(c);
- }
- if (p->UserFinished)
- {
- // User selected
- break;
- }
- WaitThread(thread, 500);
- }
- ReleaseThread(thread);
- ret = p->Ok;
- if (ret)
- {
- Copy(sign, ss->Signature, 128);
- *x = ss->ClientCert;
- }
- Free(p->SecureSign);
- Free(p);
- return ret;
- }
- // Server certificate confirmation thread
- void ClientCheckServerCertThread(THREAD *thread, void *param)
- {
- CHECK_CERT_THREAD_PROC *p = (CHECK_CERT_THREAD_PROC *)param;
- // Validate arguments
- if (thread == NULL || param == NULL)
- {
- return;
- }
- // Notify the completion of initialization
- NoticeThreadInit(thread);
- // Query for the selection to the user
- p->Ok = p->CheckCertProc(p->Connection->Session, p->Connection, p->ServerX, &p->Exipred);
- p->UserSelected = true;
- }
- // Client verify the certificate of the server
- bool ClientCheckServerCert(CONNECTION *c, bool *expired)
- {
- CLIENT_AUTH *auth;
- X *x;
- CHECK_CERT_THREAD_PROC *p;
- THREAD *thread;
- CEDAR *cedar;
- bool ret;
- UINT64 start;
- // Validate arguments
- if (c == NULL)
- {
- return false;
- }
- if (expired != NULL)
- {
- *expired = false;
- }
- auth = c->Session->ClientAuth;
- cedar = c->Cedar;
- if (auth->CheckCertProc == NULL && c->Session->LinkModeClient == false)
- {
- // No checking function
- return true;
- }
- if (c->Session->LinkModeClient && c->Session->Link->CheckServerCert == false)
- {
- // It's in cascade connection mode, but do not check the server certificate
- return true;
- }
- if (c->UseTicket)
- {
- // Check the certificate of the redirected VPN server
- if (CompareX(c->FirstSock->RemoteX, c->ServerX) == false)
- {
- return false;
- }
- else
- {
- return true;
- }
- }
- x = CloneX(c->FirstSock->RemoteX);
- if (x == NULL)
- {
- // Strange error occurs
- return false;
- }
- if (CheckXDateNow(x))
- {
- // Check whether it is signed by the root certificate to trust
- if (c->Session->LinkModeClient == false)
- {
- // Normal VPN Client mode
- if (CheckSignatureByCa(cedar, x))
- {
- // This certificate can be trusted because it is signed
- FreeX(x);
- return true;
- }
- }
- else
- {
- // Cascade connection mode
- if (CheckSignatureByCaLinkMode(c->Session, x))
- {
- // This certificate can be trusted because it is signed
- FreeX(x);
- return true;
- }
- }
- }
- if (c->Session->LinkModeClient)
- {
- if (CheckXDateNow(x))
- {
- Lock(c->Session->Link->lock);
- {
- if (c->Session->Link->ServerCert != NULL)
- {
- if (CompareX(c->Session->Link->ServerCert, x))
- {
- Unlock(c->Session->Link->lock);
- // Exactly match the certificate that is registered in the cascade configuration
- FreeX(x);
- return true;
- }
- }
- }
- Unlock(c->Session->Link->lock);
- }
- else
- {
- if (expired != NULL)
- {
- *expired = true;
- }
- }
- // Verification failure at this point in the case of cascade connection mode
- FreeX(x);
- return false;
- }
- p = ZeroMalloc(sizeof(CHECK_CERT_THREAD_PROC));
- p->ServerX = x;
- p->CheckCertProc = auth->CheckCertProc;
- p->Connection = c;
- // Create a thread
- thread = NewThread(ClientCheckServerCertThread, p);
- WaitThreadInit(thread);
- // Poll at 0.5-second intervals until the user selects whether the connection
- start = Tick64();
- while (true)
- {
- if ((Tick64() - start) > CONNECTING_POOLING_SPAN)
- {
- // Send a NOOP periodically for disconnection prevention
- start = Tick64();
- ClientUploadNoop(c);
- }
- if (p->UserSelected)
- {
- // User-selected
- break;
- }
- WaitThread(thread, 500);
- }
- if (expired != NULL)
- {
- *expired = p->Exipred;
- }
- ret = p->Ok;
- FreeX(p->ServerX);
- Free(p);
- ReleaseThread(thread);
- return ret;
- }
- // Client connects to the server
- bool ClientConnect(CONNECTION *c)
- {
- bool ret = false;
- bool ok = false;
- UINT err;
- SOCK *s;
- PACK *p = NULL;
- UINT session_key_32;
- SESSION *sess;
- char session_name[MAX_SESSION_NAME_LEN + 1];
- char connection_name[MAX_CONNECTION_NAME_LEN + 1];
- UCHAR session_key[SHA1_SIZE];
- RC4_KEY_PAIR key_pair;
- POLICY *policy;
- bool expired = false;
- IP server_ip;
- // Validate arguments
- if (c == NULL)
- {
- return false;
- }
- sess = c->Session;
- PrintStatus(sess, L"init");
- PrintStatus(sess, _UU("STATUS_1"));
- REDIRECTED:
- // [Connecting]
- c->Status = CONNECTION_STATUS_CONNECTING;
- c->Session->ClientStatus = CLIENT_STATUS_CONNECTING;
- s = ClientConnectToServer(c);
- if (s == NULL)
- {
- PrintStatus(sess, L"free");
- return false;
- }
- Copy(&server_ip, &s->RemoteIP, sizeof(IP));
- if (c->Halt)
- {
- // Stop
- c->Err = ERR_USER_CANCEL;
- goto CLEANUP;
- }
- // [Negotiating]
- c->Session->ClientStatus = CLIENT_STATUS_NEGOTIATION;
- // Initialize the UDP acceleration function
- if (sess->ClientOption != NULL && sess->ClientOption->NoUdpAcceleration == false)
- {
- if (sess->ClientOption->ProxyType == PROXY_DIRECT)
- {
- if (s->Type == SOCK_TCP)
- {
- if (sess->UdpAccel == NULL)
- {
- bool no_nat_t = false;
- if (sess->ClientOption->PortUDP != 0)
- {
- // There is no need for NAT-T treatment on my part if the UDP port on the other end is known beforehand
- no_nat_t = true;
- }
- sess->UdpAccel = NewUdpAccel(c->Cedar, &s->LocalIP, true, true, no_nat_t);
- }
- }
- }
- }
- // Send a signature
- Debug("Uploading Signature...\n");
- if (ClientUploadSignature(s) == false)
- {
- c->Err = ERR_DISCONNECTED;
- goto CLEANUP;
- }
- if (c->Halt)
- {
- // Stop
- c->Err = ERR_USER_CANCEL;
- goto CLEANUP;
- }
- PrintStatus(sess, _UU("STATUS_5"));
- // Receive a Hello packet
- Debug("Downloading Hello...\n");
- if (ClientDownloadHello(c, s) == false)
- {
- goto CLEANUP;
- }
- if (c->Session->ClientOption != NULL && c->Session->ClientOption->FromAdminPack)
- {
- if (IsAdminPackSupportedServerProduct(c->ServerStr) == false)
- {
- c->Err = ERR_NOT_ADMINPACK_SERVER;
- goto CLEANUP;
- }
- }
- if (c->Halt)
- {
- // Stop
- c->Err = ERR_USER_CANCEL;
- goto CLEANUP;
- }
- Debug("Server Version : %u\n"
- "Server String : %s\n"
- "Server Build : %u\n"
- "Client Version : %u\n"
- "Client String : %s\n"
- "Client Build : %u\n",
- c->ServerVer, c->ServerStr, c->ServerBuild,
- c->ClientVer, c->ClientStr, c->ClientBuild);
- // During user authentication
- c->Session->ClientStatus = CLIENT_STATUS_AUTH;
- // Verify the server certificate by the client
- if (ClientCheckServerCert(c, &expired) == false)
- {
- if (expired == false)
- {
- c->Err = ERR_CERT_NOT_TRUSTED;
- }
- else
- {
- c->Err = ERR_SERVER_CERT_EXPIRES;
- }
- if (c->Session->LinkModeClient == false && c->Err == ERR_CERT_NOT_TRUSTED)
- {
- c->Session->ForceStopFlag = true;
- }
- goto CLEANUP;
- }
- PrintStatus(sess, _UU("STATUS_6"));
- // Send the authentication data
- if (ClientUploadAuth(c) == false)
- {
- goto CLEANUP;
- }
- if (c->Halt)
- {
- // Stop
- c->Err = ERR_USER_CANCEL;
- goto CLEANUP;
- }
- // Receive a Welcome packet
- p = HttpClientRecv(s);
- if (p == NULL)
- {
- c->Err = ERR_DISCONNECTED;
- goto CLEANUP;
- }
- // Error checking
- err = GetErrorFromPack(p);
- if (err != 0)
- {
- // An error has occured
- c->Err = err;
- c->ClientConnectError_NoSavePassword = PackGetBool(p, "no_save_password");
- goto CLEANUP;
- }
- // Branding string check for the connection limit
- {
- char tmp[20];
- char *branded_cfroms = _SS("BRANDED_C_FROM_S");
- PackGetStr(p, "branded_cfroms", tmp, sizeof(tmp));
- if(StrLen(branded_cfroms) > 0 && StrCmpi(branded_cfroms, tmp) != 0)
- {
- c->Err = ERR_BRANDED_C_FROM_S;
- goto CLEANUP;
- }
- }
- if (c->Cedar->Server == NULL)
- {
- // Suppress client notification flag
- if (PackIsValueExists(p, "suppress_client_update_notification"))
- {
- bool suppress_client_update_notification = PackGetBool(p, "suppress_client_update_notification");
- #ifdef OS_WIN32
- MsRegWriteIntEx2(REG_LOCAL_MACHINE, PROTO_SUPPRESS_CLIENT_UPDATE_NOTIFICATION_REGKEY, PROTO_SUPPRESS_CLIENT_UPDATE_NOTIFICATION_REGVALUE,
- (suppress_client_update_notification ? 1 : 0), false, true);
- #endif // OS_WIN32
- }
- }
- if (true)
- {
- // Message retrieval
- UINT utf_size;
- char *utf;
- wchar_t *msg;
- utf_size = PackGetDataSize(p, "Msg");
- utf = ZeroMalloc(utf_size + 8);
- PackGetData(p, "Msg", utf);
- msg = CopyUtfToUni(utf);
- if (IsEmptyUniStr(msg) == false)
- {
- if (c->Session->Client_Message != NULL)
- {
- Free(c->Session->Client_Message);
- }
- c->Session->Client_Message = msg;
- }
- else
- {
- Free(msg);
- }
- Free(utf);
- }
- if (PackGetInt(p, "Redirect") != 0)
- {
- UINT i;
- UINT ip;
- UINT num_port;
- UINT *ports;
- UINT use_port = 0;
- UINT current_port = c->ServerPort;
- UCHAR ticket[SHA1_SIZE];
- X *server_cert;
- BUF *b;
- // Redirect mode
- PrintStatus(sess, _UU("STATUS_8"));
- ip = PackGetIp32(p, "Ip");
- num_port = MAX(MIN(PackGetIndexCount(p, "Port"), MAX_PUBLIC_PORT_NUM), 1);
- ports = ZeroMalloc(sizeof(UINT) * num_port);
- for (i = 0;i < num_port;i++)
- {
- ports[i] = PackGetIntEx(p, "Port", i);
- }
- // Select a port number
- for (i = 0;i < num_port;i++)
- {
- if (ports[i] == current_port)
- {
- use_port = current_port;
- }
- }
- if (use_port == 0)
- {
- use_port = ports[0];
- }
- Free(ports);
- if (PackGetDataSize(p, "Ticket") == SHA1_SIZE)
- {
- PackGetData(p, "Ticket", ticket);
- }
- b = PackGetBuf(p, "Cert");
- if (b != NULL)
- {
- server_cert = BufToX(b, false);
- FreeBuf(b);
- }
- if (c->ServerX != NULL)
- {
- FreeX(c->ServerX);
- }
- c->ServerX = server_cert;
- IPToStr32(c->ServerName, sizeof(c->ServerName), ip);
- c->ServerPort = use_port;
- c->UseTicket = true;
- Copy(c->Ticket, ticket, SHA1_SIZE);
- FreePack(p);
- p = NewPack();
- HttpClientSend(s, p);
- FreePack(p);
- p = NULL;
- c->FirstSock = NULL;
- Disconnect(s);
- ReleaseSock(s);
- s = NULL;
- goto REDIRECTED;
- }
- PrintStatus(sess, _UU("STATUS_7"));
- // Parse the Welcome packet
- if (ParseWelcomeFromPack(p, session_name, sizeof(session_name),
- connection_name, sizeof(connection_name), &policy) == false)
- {
- // Parsing failure
- c->Err = ERR_PROTOCOL_ERROR;
- goto CLEANUP;
- }
- // Get the session key
- if (GetSessionKeyFromPack(p, session_key, &session_key_32) == false)
- {
- // Acquisition failure
- Free(policy);
- policy = NULL;
- c->Err = ERR_PROTOCOL_ERROR;
- goto CLEANUP;
- }
- Copy(c->Session->SessionKey, session_key, SHA1_SIZE);
- c->Session->SessionKey32 = session_key_32;
- // Save the contents of the Welcome packet
- Debug("session_name: %s, connection_name: %s\n",
- session_name, connection_name);
- Lock(c->Session->lock);
- {
- // Deploy and update connection parameters
- sess->EnableUdpRecovery = PackGetBool(p, "enable_udp_recovery");
- c->Session->MaxConnection = PackGetInt(p, "max_connection");
- if (sess->EnableUdpRecovery == false)
- {
- c->Session->MaxConnection = MIN(c->Session->MaxConnection, c->Session->ClientOption->MaxConnection);
- }
- c->Session->MaxConnection = MIN(c->Session->MaxConnection, MAX_TCP_CONNECTION);
- c->Session->MaxConnection = MAX(c->Session->MaxConnection, 1);
- c->Session->UseCompress = PackGetInt(p, "use_compress") == 0 ? false : true;
- c->Session->UseEncrypt = PackGetInt(p, "use_encrypt") == 0 ? false : true;
- c->Session->NoSendSignature = PackGetBool(p, "no_send_signature");
- if (c->Session->UseEncrypt)
- {
- c->Session->UseFastRC4 = PackGetInt(p, "use_fast_rc4") == 0 ? false : true;
- }
- c->Session->HalfConnection = PackGetInt(p, "half_connection") == 0 ? false : true;
- c->Session->IsAzureSession = PackGetInt(p, "is_azure_session") == 0 ? false : true;
- c->Session->Timeout = PackGetInt(p, "timeout");
- c->Session->QoS = PackGetInt(p, "qos") == 0 ? false : true;
- if (c->Session->QoS)
- {
- c->Session->MaxConnection = MAX(c->Session->MaxConnection, (UINT)(c->Session->HalfConnection ? 4 : 2));
- }
- c->Session->VLanId = PackGetInt(p, "vlan_id");
- // R-UDP Session ?
- c->Session->IsRUDPSession = s->IsRUDPSocket;
- ZeroIP4(&c->Session->AzureRealServerGlobalIp);
- if (c->Session->IsAzureSession)
- {
- // Disable the life parameter of the connection in the case of VPN Azure relayed session
- c->Session->ClientOption->ConnectionDisconnectSpan = 0;
- // Get the AzureRealServerGlobalIp the case of VPN Azure relayed
- PackGetIp(p, "azure_real_server_global_ip", &c->Session->AzureRealServerGlobalIp);
- }
- if (c->Session->IsRUDPSession)
- {
- // Disable the life parameter of the connection in the case of R-UDP session
- c->Session->ClientOption->ConnectionDisconnectSpan = 0;
- // Disable QoS, etc. in the case of R-UDP session
- c->Session->QoS = false;
- c->Session->HalfConnection = false;
- if (c->Session->EnableUdpRecovery == false)
- {
- // Set the number of connection to 1 if UDP recovery is not supported
- c->Session->MaxConnection = 1;
- }
- }
- // Physical communication protocol
- StrCpy(c->Session->UnderlayProtocol, sizeof(c->Session->UnderlayProtocol), s->UnderlayProtocol);
- if (c->Session->IsAzureSession)
- {
- StrCpy(c->Session->UnderlayProtocol, sizeof(c->Session->UnderlayProtocol), SOCK_UNDERLAY_AZURE);
- }
- if (c->Protocol == CONNECTION_UDP)
- {
- // In the case of UDP protocol, receive the key from the server
- if (PackGetDataSize(p, "udp_send_key") == sizeof(c->Session->UdpSendKey))
- {
- PackGetData(p, "udp_send_key", c->Session->UdpSendKey);
- }
- if (PackGetDataSize(p, "udp_recv_key") == sizeof(c->Session->UdpRecvKey))
- {
- PackGetData(p, "udp_recv_key", c->Session->UdpRecvKey);
- }
- }
- if (c->Session->UseFastRC4)
- {
- // Get the RC4 key information
- if (PackGetDataSize(p, "rc4_key_client_to_server") == 16)
- {
- PackGetData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey);
- }
- if (PackGetDataSize(p, "rc4_key_server_to_client") == 16)
- {
- PackGetData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey);
- }
- {
- char key1[64], key2[64];
- BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
- BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
- Debug(
- "Client to Server Key: %s\n"
- "Server to Client Key: %s\n",
- key1, key2);
- }
- }
- sess->EnableBulkOnRUDP = false;
- sess->EnableHMacOnBulkOfRUDP = false;
- if (s != NULL && s->IsRUDPSocket && s->BulkRecvKey != NULL && s->BulkSendKey != NULL)
- {
- // Bulk transfer on R-UDP
- if (PackGetBool(p, "enable_bulk_on_rudp"))
- {
- // Receive the key
- UCHAR key_send[SHA1_SIZE];
- UCHAR key_recv[SHA1_SIZE];
- if (PackGetData2(p, "bulk_on_rudp_send_key", key_send, SHA1_SIZE) &&
- PackGetData2(p, "bulk_on_rudp_recv_key", key_recv, SHA1_SIZE))
- {
- sess->EnableBulkOnRUDP = true;
- Copy(s->BulkSendKey->Data, key_send, SHA1_SIZE);
- Copy(s->BulkRecvKey->Data, key_recv, SHA1_SIZE);
- }
- }
- sess->EnableHMacOnBulkOfRUDP = PackGetBool(p, "enable_hmac_on_bulk_of_rudp");
- }
- Debug("EnableBulkOnRUDP = %u\n", sess->EnableBulkOnRUDP);
- Debug("EnableHMacOnBulkOfRUDP = %u\n", sess->EnableHMacOnBulkOfRUDP);
- Debug("EnableUdpRecovery = %u\n", sess->EnableUdpRecovery);
- sess->UseUdpAcceleration = false;
- sess->IsUsingUdpAcceleration = false;
- sess->UseHMacOnUdpAcceleration = false;
- if (sess->UdpAccel != NULL)
- {
- sess->UdpAccel->UseHMac = false;
- sess->UdpAccelFastDisconnectDetect = false;
- if (PackGetBool(p, "use_udp_acceleration"))
- {
- IP udp_acceleration_server_ip;
- sess->UdpAccelFastDisconnectDetect = PackGetBool(p, "udp_accel_fast_disconnect_detect");
- if (PackGetIp(p, "udp_acceleration_server_ip", &udp_acceleration_server_ip))
- {
- UINT udp_acceleration_server_port = PackGetInt(p, "udp_acceleration_server_port");
- if (IsZeroIp(&udp_acceleration_server_ip))
- {
- Copy(&udp_acceleration_server_ip, &s->RemoteIP, sizeof(IP));
- }
- if (udp_acceleration_server_port != 0)
- {
- UCHAR udp_acceleration_server_key[UDP_ACCELERATION_COMMON_KEY_SIZE];
- if (PackGetData2(p, "udp_acceleration_server_key", udp_acceleration_server_key, UDP_ACCELERATION_COMMON_KEY_SIZE))
- {
- UINT server_cookie = PackGetInt(p, "udp_acceleration_server_cookie");
- UINT client_cookie = PackGetInt(p, "udp_acceleration_client_cookie");
- bool encryption = PackGetBool(p, "udp_acceleration_use_encryption");
- if (server_cookie != 0 && client_cookie != 0)
- {
- IP remote_ip;
- Copy(&remote_ip, &s->RemoteIP, sizeof(IP));
- if (IsZeroIp(&c->Session->AzureRealServerGlobalIp) == false)
- {
- Copy(&remote_ip, &c->Session->AzureRealServerGlobalIp, sizeof(IP));
- }
- if (UdpAccelInitClient(sess->UdpAccel, udp_acceleration_server_key,
- &udp_acceleration_server_ip, udp_acceleration_server_port,
- server_cookie, client_cookie, &remote_ip) == false)
- {
- Debug("UdpAccelInitClient failed.\n");
- }
- else
- {
- sess->UseUdpAcceleration = true;
- sess->UdpAccel->FastDetect = sess->UdpAccelFastDisconnectDetect;
- sess->UdpAccel->PlainTextMode = !encryption;
- sess->UseHMacOnUdpAcceleration = PackGetBool(p, "use_hmac_on_udp_acceleration");
- if (sess->UseHMacOnUdpAcceleration)
- {
- sess->UdpAccel->UseHMac = true;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- Unlock(c->Session->lock);
- Debug("UseUdpAcceleration = %u\n", sess->UseUdpAcceleration);
- if (sess->UseUdpAcceleration == false)
- {
- if (sess->UdpAccel != NULL)
- {
- FreeUdpAccel(sess->UdpAccel);
- sess->UdpAccel = NULL;
- }
- }
- Lock(c->lock);
- {
- if (c->Name != NULL)
- {
- Free(c->Name);
- }
- c->Name = CopyStr(connection_name);
- // Save the name of a cryptographic algorithm
- if (c->CipherName != NULL)
- {
- Free(c->CipherName);
- }
- c->CipherName = CopyStr(c->FirstSock->CipherName);
- }
- Unlock(c->lock);
- Lock(c->Session->lock);
- {
- if (c->Session->Name != NULL)
- {
- Free(c->Session->Name);
- }
- c->Session->Name = CopyStr(session_name);
- c->Session->Policy = policy;
- }
- Unlock(c->Session->lock);
- // Discard the Welcome packet
- FreePack(p);
- p = NULL;
- // Connection establishment
- c->Session->ClientStatus = CLIENT_STATUS_ESTABLISHED;
- // Save the server certificate
- if (c->ServerX == NULL)
- {
- c->ServerX = CloneX(c->FirstSock->RemoteX);
- }
- PrintStatus(sess, _UU("STATUS_9"));
- // Shift the connection to the tunneling mode
- StartTunnelingMode(c);
- s = NULL;
- if (c->Session->HalfConnection)
- {
- // Processing in the case of half-connection
- TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
- ts->Direction = TCP_CLIENT_TO_SERVER;
- }
- if (c->Session->UseFastRC4)
- {
- // Set the high-speed RC4 encryption key
- TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
- Copy(&ts->Rc4KeyPair, &key_pair, sizeof(key_pair));
- InitTcpSockRc4Key(ts, false);
- }
- // SSL encryption flag
- if (c->Session->UseEncrypt && c->Session->UseFastRC4 == false)
- {
- c->Session->UseSSLDataEncryption = true;
- }
- else
- {
- c->Session->UseSSLDataEncryption = false;
- }
- PrintStatus(sess, L"free");
- CLog(c->Cedar->Client, "LC_CONNECT_2", c->Session->ClientOption->AccountName,
- session_name);
- if (c->Session->LinkModeClient && c->Session->Link != NULL)
- {
- HLog(c->Session->Link->Hub, "LH_CONNECT_2", c->Session->ClientOption->AccountName, session_name);
- }
- // Main routine of the session
- SessionMain(c->Session);
- ok = true;
- if (c->Err == ERR_USER_CANCEL)
- {
- ret = true;
- }
- CLEANUP:
- c->FirstSock = NULL;
- if (sess->UdpAccel != NULL)
- {
- FreeUdpAccel(sess->UdpAccel);
- sess->UdpAccel = NULL;
- }
- if (p != NULL)
- {
- FreePack(p);
- }
- Disconnect(s);
- ReleaseSock(s);
- Debug("Error: %u\n", c->Err);
- if (ok == false)
- {
- PrintStatus(sess, L"free");
- }
- return ret;
- }
- // Parse the Welcome packet
- bool ParseWelcomeFromPack(PACK *p, char *session_name, UINT session_name_size,
- char *connection_name, UINT connection_name_size,
- POLICY **policy)
- {
- // Validate arguments
- if (p == NULL || session_name == NULL || connection_name == NULL || policy == NULL)
- {
- return false;
- }
- // Session name
- if (PackGetStr(p, "session_name", session_name, session_name_size) == false)
- {
- return false;
- }
- // Connection name
- if (PackGetStr(p, "connection_name", connection_name, connection_name_size) == false)
- {
- return false;
- }
- // Policy
- *policy = PackGetPolicy(p);
- if (*policy == NULL)
- {
- return false;
- }
- return true;
- }
- // Generate the Welcome packet
- PACK *PackWelcome(SESSION *s)
- {
- PACK *p;
- // Validate arguments
- if (s == NULL)
- {
- return NULL;
- }
- p = NewPack();
- // Session name
- PackAddStr(p, "session_name", s->Name);
- // Connection name
- PackAddStr(p, "connection_name", s->Connection->Name);
- // Parameters
- PackAddInt(p, "max_connection", s->MaxConnection);
- PackAddInt(p, "use_encrypt", s->UseEncrypt == false ? 0 : 1);
- PackAddInt(p, "use_fast_rc4", s->UseFastRC4 == false ? 0 : 1);
- PackAddInt(p, "use_compress", s->UseCompress == false ? 0 : 1);
- PackAddInt(p, "half_connection", s->HalfConnection == false ? 0 : 1);
- PackAddInt(p, "timeout", s->Timeout);
- PackAddInt(p, "qos", s->QoS ? 1 : 0);
- PackAddInt(p, "is_azure_session", s->IsAzureSession);
- // Session key
- PackAddData(p, "session_key", s->SessionKey, SHA1_SIZE);
- PackAddInt(p, "session_key_32", s->SessionKey32);
- // Policy
- PackAddPolicy(p, s->Policy);
- // VLAN ID
- PackAddInt(p, "vlan_id", s->VLanId);
- if (s->Connection->Protocol == CONNECTION_UDP)
- {
- // In the case of UDP protocol, generate 2 pairs of key
- Rand(s->UdpSendKey, sizeof(s->UdpSendKey));
- Rand(s->UdpRecvKey, sizeof(s->UdpRecvKey));
- // Send to client by exchanging 2 keys
- PackAddData(p, "udp_send_key", s->UdpRecvKey, sizeof(s->UdpRecvKey));
- PackAddData(p, "udp_recv_key", s->UdpSendKey, sizeof(s->UdpSendKey));
- }
- // no_send_signature
- if (s->NoSendSignature)
- {
- PackAddBool(p, "no_send_signature", true);
- }
- if (s->InProcMode)
- {
- // MAC address for IPC
- PackAddData(p, "IpcMacAddress", s->IpcMacAddress, 6);
- // Virtual HUB name
- PackAddStr(p, "IpcHubName", s->Hub->Name);
- }
- if (s->UdpAccel != NULL)
- {
- // UDP acceleration function
- PackAddBool(p, "use_udp_acceleration", true);
- PackAddIp(p, "udp_acceleration_server_ip", &s->UdpAccel->MyIp);
- PackAddInt(p, "udp_acceleration_server_port", s->UdpAccel->MyPort);
- PackAddData(p, "udp_acceleration_server_key", s->UdpAccel->MyKey, UDP_ACCELERATION_COMMON_KEY_SIZE);
- PackAddInt(p, "udp_acceleration_server_cookie", s->UdpAccel->MyCookie);
- PackAddInt(p, "udp_acceleration_client_cookie", s->UdpAccel->YourCookie);
- PackAddBool(p, "udp_acceleration_use_encryption", !s->UdpAccel->PlainTextMode);
- PackAddBool(p, "use_hmac_on_udp_acceleration", s->UdpAccel->UseHMac);
- PackAddBool(p, "udp_accel_fast_disconnect_detect", s->UdpAccelFastDisconnectDetect);
- }
- if (s->EnableBulkOnRUDP)
- {
- // Allow bulk transfer on R-UDP
- PackAddBool(p, "enable_bulk_on_rudp", true);
- PackAddBool(p, "enable_hmac_on_bulk_of_rudp", s->EnableHMacOnBulkOfRUDP);
- PackAddData(p, "bulk_on_rudp_send_key", s->Connection->FirstSock->BulkRecvKey->Data, SHA1_SIZE);
- PackAddData(p, "bulk_on_rudp_recv_key", s->Connection->FirstSock->BulkSendKey->Data, SHA1_SIZE);
- }
- if (s->IsAzureSession)
- {
- if (s->Connection != NULL && s->Connection->FirstSock != NULL)
- {
- SOCK *sock = s->Connection->FirstSock;
- PackAddIp(p, "azure_real_server_global_ip", &sock->Reverse_MyServerGlobalIp);
- }
- }
- PackAddBool(p, "enable_udp_recovery", s->EnableUdpRecovery);
- return p;
- }
- #define PACK_ADD_POLICY_BOOL(name, value) \
- PackAddInt(p, "policy:" name, y->value == false ? 0 : 1)
- #define PACK_ADD_POLICY_UINT(name, value) \
- PackAddInt(p, "policy:" name, y->value)
- #define PACK_GET_POLICY_BOOL(name, value) \
- y->value = (PackGetInt(p, "policy:" name) == 0 ? false : true)
- #define PACK_GET_POLICY_UINT(name, value) \
- y->value = PackGetInt(p, "policy:" name)
- // Get a PACK from the session key
- bool GetSessionKeyFromPack(PACK *p, UCHAR *session_key, UINT *session_key_32)
- {
- // Validate arguments
- if (p == NULL || session_key == NULL || session_key_32 == NULL)
- {
- return false;
- }
- if (PackGetDataSize(p, "session_key") != SHA1_SIZE)
- {
- return false;
- }
- if (PackGetData(p, "session_key", session_key) == false)
- {
- return false;
- }
- *session_key_32 = PackGetInt(p, "session_key_32");
- return true;
- }
- // Get the policy from the PACK
- POLICY *PackGetPolicy(PACK *p)
- {
- POLICY *y;
- // Validate arguments
- if (p == NULL)
- {
- return NULL;
- }
- y = ZeroMalloc(sizeof(POLICY));
- // Bool value
- // Ver 2
- PACK_GET_POLICY_BOOL("Access", Access);
- PACK_GET_POLICY_BOOL("DHCPFilter", DHCPFilter);
- PACK_GET_POLICY_BOOL("DHCPNoServer", DHCPNoServer);
- PACK_GET_POLICY_BOOL("DHCPForce", DHCPForce);
- PACK_GET_POLICY_BOOL("NoBridge", NoBridge);
- PACK_GET_POLICY_BOOL("NoRouting", NoRouting);
- PACK_GET_POLICY_BOOL("PrivacyFilter", PrivacyFilter);
- PACK_GET_POLICY_BOOL("NoServer", NoServer);
- PACK_GET_POLICY_BOOL("CheckMac", CheckMac);
- PACK_GET_POLICY_BOOL("CheckIP", CheckIP);
- PACK_GET_POLICY_BOOL("ArpDhcpOnly", ArpDhcpOnly);
- PACK_GET_POLICY_BOOL("MonitorPort", MonitorPort);
- PACK_GET_POLICY_BOOL("NoBroadcastLimiter", NoBroadcastLimiter);
- PACK_GET_POLICY_BOOL("FixPassword", FixPassword);
- PACK_GET_POLICY_BOOL("NoQoS", NoQoS);
- // Ver 3
- PACK_GET_POLICY_BOOL("RSandRAFilter", RSandRAFilter);
- PACK_GET_POLICY_BOOL("RAFilter", RAFilter);
- PACK_GET_POLICY_BOOL("DHCPv6Filter", DHCPv6Filter);
- PACK_GET_POLICY_BOOL("DHCPv6NoServer", DHCPv6NoServer);
- PACK_GET_POLICY_BOOL("NoRoutingV6", NoRoutingV6);
- PACK_GET_POLICY_BOOL("CheckIPv6", CheckIPv6);
- PACK_GET_POLICY_BOOL("NoServerV6", NoServerV6);
- PACK_GET_POLICY_BOOL("NoSavePassword", NoSavePassword);
- PACK_GET_POLICY_BOOL("FilterIPv4", FilterIPv4);
- PACK_GET_POLICY_BOOL("FilterIPv6", FilterIPv6);
- PACK_GET_POLICY_BOOL("FilterNonIP", FilterNonIP);
- PACK_GET_POLICY_BOOL("NoIPv6DefaultRouterInRA", NoIPv6DefaultRouterInRA);
- PACK_GET_POLICY_BOOL("NoIPv6DefaultRouterInRAWhenIPv6", NoIPv6DefaultRouterInRAWhenIPv6);
- // UINT value
- // Ver 2
- PACK_GET_POLICY_UINT("MaxConnection", MaxConnection);
- PACK_GET_POLICY_UINT("TimeOut", TimeOut);
- PACK_GET_POLICY_UINT("MaxMac", MaxMac);
- PACK_GET_POLICY_UINT("MaxIP", MaxIP);
- PACK_GET_POLICY_UINT("MaxUpload", MaxUpload);
- PACK_GET_POLICY_UINT("MaxDownload", MaxDownload);
- PACK_GET_POLICY_UINT("MultiLogins", MultiLogins);
- // Ver 3
- PACK_GET_POLICY_UINT("MaxIPv6", MaxIPv6);
- PACK_GET_POLICY_UINT("AutoDisconnect", AutoDisconnect);
- PACK_GET_POLICY_UINT("VLanId", VLanId);
- // Ver 3 flag
- PACK_GET_POLICY_BOOL("Ver3", Ver3);
- return y;
- }
- // Insert the policy into the PACK
- void PackAddPolicy(PACK *p, POLICY *y)
- {
- // Validate arguments
- if (p == NULL || y == NULL)
- {
- return;
- }
- // Bool value
- // Ver 2
- PACK_ADD_POLICY_BOOL("Access", Access);
- PACK_ADD_POLICY_BOOL("DHCPFilter", DHCPFilter);
- PACK_ADD_POLICY_BOOL("DHCPNoServer", DHCPNoServer);
- PACK_ADD_POLICY_BOOL("DHCPForce", DHCPForce);
- PACK_ADD_POLICY_BOOL("NoBridge", NoBridge);
- PACK_ADD_POLICY_BOOL("NoRouting", NoRouting);
- PACK_ADD_POLICY_BOOL("PrivacyFilter", PrivacyFilter);
- PACK_ADD_POLICY_BOOL("NoServer", NoServer);
- PACK_ADD_POLICY_BOOL("CheckMac", CheckMac);
- PACK_ADD_POLICY_BOOL("CheckIP", CheckIP);
- PACK_ADD_POLICY_BOOL("ArpDhcpOnly", ArpDhcpOnly);
- PACK_ADD_POLICY_BOOL("MonitorPort", MonitorPort);
- PACK_ADD_POLICY_BOOL("NoBroadcastLimiter", NoBroadcastLimiter);
- PACK_ADD_POLICY_BOOL("FixPassword", FixPassword);
- PACK_ADD_POLICY_BOOL("NoQoS", NoQoS);
- // Ver 3
- PACK_ADD_POLICY_BOOL("RSandRAFilter", RSandRAFilter);
- PACK_ADD_POLICY_BOOL("RAFilter", RAFilter);
- PACK_ADD_POLICY_BOOL("DHCPv6Filter", DHCPv6Filter);
- PACK_ADD_POLICY_BOOL("DHCPv6NoServer", DHCPv6NoServer);
- PACK_ADD_POLICY_BOOL("NoRoutingV6", NoRoutingV6);
- PACK_ADD_POLICY_BOOL("CheckIPv6", CheckIPv6);
- PACK_ADD_POLICY_BOOL("NoServerV6", NoServerV6);
- PACK_ADD_POLICY_BOOL("NoSavePassword", NoSavePassword);
- PACK_ADD_POLICY_BOOL("FilterIPv4", FilterIPv4);
- PACK_ADD_POLICY_BOOL("FilterIPv6", FilterIPv6);
- PACK_ADD_POLICY_BOOL("FilterNonIP", FilterNonIP);
- PACK_ADD_POLICY_BOOL("NoIPv6DefaultRouterInRA", NoIPv6DefaultRouterInRA);
- PACK_ADD_POLICY_BOOL("NoIPv6DefaultRouterInRAWhenIPv6", NoIPv6DefaultRouterInRAWhenIPv6);
- // UINT value
- // Ver 2
- PACK_ADD_POLICY_UINT("MaxConnection", MaxConnection);
- PACK_ADD_POLICY_UINT("TimeOut", TimeOut);
- PACK_ADD_POLICY_UINT("MaxMac", MaxMac);
- PACK_ADD_POLICY_UINT("MaxIP", MaxIP);
- PACK_ADD_POLICY_UINT("MaxUpload", MaxUpload);
- PACK_ADD_POLICY_UINT("MaxDownload", MaxDownload);
- PACK_ADD_POLICY_UINT("MultiLogins", MultiLogins);
- // Ver 3
- PACK_ADD_POLICY_UINT("MaxIPv6", MaxIPv6);
- PACK_ADD_POLICY_UINT("AutoDisconnect", AutoDisconnect);
- PACK_ADD_POLICY_UINT("VLanId", VLanId);
- // Ver 3 flag
- PackAddBool(p, "policy:Ver3", true);
- }
- // Upload the authentication data for the additional connection
- bool ClientUploadAuth2(CONNECTION *c, SOCK *s)
- {
- PACK *p = NULL;
- // Validate arguments
- if (c == NULL)
- {
- return false;
- }
- p = PackAdditionalConnect(c->Session->SessionKey);
- PackAddClientVersion(p, c);
- if (HttpClientSend(s, p) == false)
- {
- FreePack(p);
- return false;
- }
- FreePack(p);
- return true;
- }
- // Send a NOOP
- void ClientUploadNoop(CONNECTION *c)
- {
- PACK *p;
- // Validate arguments
- if (c == NULL)
- {
- return;
- }
- p = PackError(0);
- PackAddInt(p, "noop", 1);
- HttpClientSend(c->FirstSock, p);
- FreePack(p);
- p = HttpClientRecv(c->FirstSock);
- if (p != NULL)
- {
- FreePack(p);
- }
- }
- // Add client version information to the PACK
- void PackAddClientVersion(PACK *p, CONNECTION *c)
- {
- // Validate arguments
- if (p == NULL || c == NULL)
- {
- return;
- }
- PackAddStr(p, "client_str", c->ClientStr);
- PackAddInt(p, "client_ver", c->ClientVer);
- PackAddInt(p, "client_build", c->ClientBuild);
- }
- // Upload the certificate data for the new connection
- bool ClientUploadAuth(CONNECTION *c)
- {
- PACK *p = NULL;
- CLIENT_AUTH *a;
- CLIENT_OPTION *o;
- X *x;
- bool ret;
- NODE_INFO info;
- UCHAR secure_password[SHA1_SIZE];
- UCHAR sign[4096 / 8];
- UCHAR unique[SHA1_SIZE];
- RPC_WINVER v;
- // Validate arguments
- if (c == NULL)
- {
- return false;
- }
- Zero(sign, sizeof(sign));
- a = c->Session->ClientAuth;
- o = c->Session->ClientOption;
- if (c->UseTicket == false)
- {
- switch (a->AuthType)
- {
- case CLIENT_AUTHTYPE_ANONYMOUS:
- // Anonymous authentication
- p = PackLoginWithAnonymous(o->HubName, a->Username);
- break;
- case CLIENT_AUTHTYPE_PASSWORD:
- // Password authentication
- SecurePassword(secure_password, a->HashedPassword, c->Random);
- p = PackLoginWithPassword(o->HubName, a->Username, secure_password);
- break;
- case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
- // Plaintext password authentication
- p = PackLoginWithPlainPassword(o->HubName, a->Username, a->PlainPassword);
- break;
- case CLIENT_AUTHTYPE_CERT:
- // Certificate authentication
- if (a->ClientX != NULL && a->ClientX->is_compatible_bit &&
- a->ClientX->bits != 0 && (a->ClientX->bits / 8) <= sizeof(sign))
- {
- if (RsaSignEx(sign, c->Random, SHA1_SIZE, a->ClientK, a->ClientX->bits))
- {
- p = PackLoginWithCert(o->HubName, a->Username, a->ClientX, sign, a->ClientX->bits / 8);
- c->ClientX = CloneX(a->ClientX);
- }
- }
- break;
- case CLIENT_AUTHTYPE_SECURE:
- // Authentication by secure device
- if (ClientSecureSign(c, sign, c->Random, &x))
- {
- p = PackLoginWithCert(o->HubName, a->Username, x, sign, 128);
- c->ClientX = CloneX(x);
- FreeX(x);
- }
- else
- {
- c->Err = ERR_SECURE_DEVICE_OPEN_FAILED;
- c->Session->ForceStopFlag = true;
- }
- break;
- }
- }
- else
- {
- // Ticket
- p = NewPack();
- PackAddStr(p, "method", "login");
- PackAddStr(p, "hubname", o->HubName);
- PackAddStr(p, "username", a->Username);
- PackAddInt(p, "authtype", AUTHTYPE_TICKET);
- PackAddData(p, "ticket", c->Ticket, SHA1_SIZE);
- }
- // Current time
- PackAddInt64(p, "timestamp", SystemTime64());
- if (p == NULL)
- {
- // Error
- if (c->Err != ERR_SECURE_DEVICE_OPEN_FAILED)
- {
- c->Err = ERR_PROTOCOL_ERROR;
- }
- return false;
- }
- PackAddClientVersion(p, c);
- // Protocol
- PackAddInt(p, "protocol", c->Protocol);
- // Version, etc.
- PackAddStr(p, "hello", c->ClientStr);
- PackAddInt(p, "version", c->ClientVer);
- PackAddInt(p, "build", c->ClientBuild);
- PackAddInt(p, "client_id", c->Cedar->ClientId);
- // The maximum number of connections
- PackAddInt(p, "max_connection", o->MaxConnection);
- // Flag to use of cryptography
- PackAddInt(p, "use_encrypt", o->UseEncrypt == false ? 0 : 1);
- // Fast encryption using flag
- // PackAddInt(p, "use_fast_rc4", o->UseFastRC4 == false ? 0 : 1);
- // Data compression flag
- PackAddInt(p, "use_compress", o->UseCompress == false ? 0 : 1);
- // Half connection flag
- PackAddInt(p, "half_connection", o->HalfConnection == false ? 0 : 1);
- // Bridge / routing mode flag
- PackAddBool(p, "require_bridge_routing_mode", o->RequireBridgeRoutingMode);
- // Monitor mode flag
- PackAddBool(p, "require_monitor_mode", o->RequireMonitorMode);
- // VoIP / QoS flag
- PackAddBool(p, "qos", o->DisableQoS ? false : true);
- // Bulk transfer support
- PackAddBool(p, "support_bulk_on_rudp", true);
- PackAddBool(p, "support_hmac_on_bulk_of_rudp", true);
- // UDP recovery support
- PackAddBool(p, "support_udp_recovery", true);
- // Unique ID
- GenerateMachineUniqueHash(unique);
- PackAddData(p, "unique_id", unique, SHA1_SIZE);
- // UDP acceleration function using flag
- if (o->NoUdpAcceleration == false && c->Session->UdpAccel != NULL)
- {
- IP my_ip;
- Zero(&my_ip, sizeof(my_ip));
- PackAddBool(p, "use_udp_acceleration", true);
- Copy(&my_ip, &c->Session->UdpAccel->MyIp, sizeof(IP));
- if (IsLocalHostIP(&my_ip))
- {
- if (IsIP4(&my_ip))
- {
- ZeroIP4(&my_ip);
- }
- else
- {
- ZeroIP6(&my_ip);
- }
- }
- PackAddIp(p, "udp_acceleration_client_ip", &my_ip);
- PackAddInt(p, "udp_acceleration_client_port", c->Session->UdpAccel->MyPort);
- PackAddData(p, "udp_acceleration_client_key", c->Session->UdpAccel->MyKey, UDP_ACCELERATION_COMMON_KEY_SIZE);
- PackAddBool(p, "support_hmac_on_udp_acceleration", true);
- PackAddBool(p, "support_udp_accel_fast_disconnect_detect", true);
- }
- // Brand string for the connection limit
- {
- char *branded_ctos = _SS("BRANDED_C_TO_S");
- if(StrLen(branded_ctos) > 0)
- {
- PackAddStr(p, "branded_ctos", branded_ctos);
- }
- }
- // Node information
- CreateNodeInfo(&info, c);
- OutRpcNodeInfo(p, &info);
- // OS information
- GetWinVer(&v);
- OutRpcWinVer(p, &v);
- ret = HttpClientSend(c->FirstSock, p);
- if (ret == false)
- {
- c->Err = ERR_DISCONNECTED;
- }
- FreePack(p);
- return ret;
- }
- // Upload the Hello packet
- bool ServerUploadHello(CONNECTION *c)
- {
- PACK *p;
- // Validate arguments
- if (c == NULL)
- {
- return false;
- }
- // Random number generation
- Rand(c->Random, SHA1_SIZE);
- p = PackHello(c->Random, c->ServerVer, c->ServerBuild, c->ServerStr);
- if (HttpServerSend(c->FirstSock, p) == false)
- {
- FreePack(p);
- c->Err = ERR_DISCONNECTED;
- return false;
- }
- FreePack(p);
- return true;
- }
- // Download the Hello packet
- bool ClientDownloadHello(CONNECTION *c, SOCK *s)
- {
- PACK *p;
- UINT err;
- UCHAR random[SHA1_SIZE];
- // Validate arguments
- if (c == NULL)
- {
- return false;
- }
- // Data reception
- p = HttpClientRecv(s);
- if (p == NULL)
- {
- c->Err = ERR_SERVER_IS_NOT_VPN;
- return false;
- }
- if (err = GetErrorFromPack(p))
- {
- // An error has occured
- c->Err = err;
- FreePack(p);
- return false;
- }
- // Packet interpretation
- if (GetHello(p, random, &c->ServerVer, &c->ServerBuild, c->ServerStr, sizeof(c->ServerStr)) == false)
- {
- c->Err = ERR_SERVER_IS_NOT_VPN;
- FreePack(p);
- return false;
- }
- if (c->FirstSock == s)
- {
- Copy(c->Random, random, SHA1_SIZE);
- }
- FreePack(p);
- return true;
- }
- // Download the signature
- bool ServerDownloadSignature(CONNECTION *c, char **error_detail_str)
- {
- HTTP_HEADER *h;
- UCHAR *data;
- UINT data_size;
- SOCK *s;
- UINT num = 0, max = 19;
- SERVER *server;
- char *vpn_http_target = HTTP_VPN_TARGET2;
- bool check_hostname = false;
- // Validate arguments
- if (c == NULL)
- {
- return false;
- }
- server = c->Cedar->Server;
- s = c->FirstSock;
- while (true)
- {
- bool not_found_error = false;
- num++;
- if (num > max)
- {
- // Disconnect
- Disconnect(s);
- c->Err = ERR_CLIENT_IS_NOT_VPN;
- *error_detail_str = "HTTP_TOO_MANY_REQUEST";
- return false;
- }
- // Receive a header
- h = RecvHttpHeader(s);
- if (h == NULL)
- {
- c->Err = ERR_CLIENT_IS_NOT_VPN;
- return false;
- }
- if (check_hostname && (StrCmpi(h->Version, "HTTP/1.1") == 0 || StrCmpi(h->Version, "HTTP/1.2") == 0))
- {
- HTTP_VALUE *v;
- char hostname[64];
- Zero(hostname, sizeof(hostname));
- v = GetHttpValue(h, "Host");
- if (v != NULL)
- {
- StrCpy(hostname, sizeof(hostname), v->Data);
- }
- if (IsEmptyStr(hostname))
- {
- // Invalid hostname
- HttpSendInvalidHostname(s, h->Target);
- FreeHttpHeader(h);
- c->Err = ERR_CLIENT_IS_NOT_VPN;
- *error_detail_str = "Invalid_hostname";
- return false;
- }
- }
- // Interpret
- if (StrCmpi(h->Method, "POST") == 0)
- {
- // Receive the data since it's POST
- data_size = GetContentLength(h);
- if ((data_size > MAX_WATERMARK_SIZE || data_size < SizeOfWaterMark()) && (data_size != StrLen(HTTP_VPN_TARGET_POSTDATA)))
- {
- // Data is too large
- HttpSendForbidden(s, h->Target, NULL);
- FreeHttpHeader(h);
- c->Err = ERR_CLIENT_IS_NOT_VPN;
- *error_detail_str = "POST_Recv_TooLong";
- return false;
- }
- data = Malloc(data_size);
- if (RecvAll(s, data, data_size, s->SecureMode) == false)
- {
- // Data reception failure
- Free(data);
- FreeHttpHeader(h);
- c->Err = ERR_DISCONNECTED;
- *error_detail_str = "POST_Recv_Failed";
- return false;
- }
- // Check the Target
- if ((StrCmpi(h->Target, vpn_http_target) != 0) || not_found_error)
- {
- // Target is invalid
- HttpSendNotFound(s, h->Target);
- Free(data);
- FreeHttpHeader(h);
- *error_detail_str = "POST_Target_Wrong";
- }
- else
- {
- // Compare posted data with the WaterMark
- if ((data_size == StrLen(HTTP_VPN_TARGET_POSTDATA) && (Cmp(data, HTTP_VPN_TARGET_POSTDATA, data_size) == 0))
- || (Cmp(data, WaterMark, SizeOfWaterMark()) == 0))
- {
- // Check the WaterMark
- Free(data);
- FreeHttpHeader(h);
- return true;
- }
- else
- {
- // WaterMark is incorrect
- HttpSendForbidden(s, h->Target, NULL);
- FreeHttpHeader(h);
- *error_detail_str = "POST_WaterMark_Error";
- }
- }
- }
- else if (StrCmpi(h->Method, "SSTP_DUPLEX_POST") == 0 && (server->DisableSSTPServer == false || s->IsReverseAcceptedSocket
- ) &&
- GetServerCapsBool(server, "b_support_sstp") && GetNoSstp() == false)
- {
- // SSTP client is connected
- c->WasSstp = true;
- if (StrCmpi(h->Target, SSTP_URI) == 0)
- {
- bool sstp_ret;
- // Accept the SSTP connection
- c->Type = CONNECTION_TYPE_SSTP;
- sstp_ret = AcceptSstp(c);
- c->Err = ERR_DISCONNECTED;
- FreeHttpHeader(h);
- if (sstp_ret)
- {
- *error_detail_str = "";
- }
- else
- {
- *error_detail_str = "SSTP_ABORT";
- }
- return false;
- }
- else
- {
- // URI is invalid
- HttpSendNotFound(s, h->Target);
- *error_detail_str = "SSTP_URL_WRONG";
- }
- FreeHttpHeader(h);
- }
- else
- {
- // This should not be a VPN client, but interpret a bit more
- if (StrCmpi(h->Method, "GET") != 0 && StrCmpi(h->Method, "HEAD") != 0
- && StrCmpi(h->Method, "POST") != 0)
- {
- // Unsupported method calls
- HttpSendNotImplemented(s, h->Method, h->Target, h->Version);
- *error_detail_str = "HTTP_BAD_METHOD";
- }
- else
- {
- if (StrCmpi(h->Target, "/") == 0)
- {
- // Root directory
- SERVER *s = c->Cedar->Server;
- bool is_free = false;
- *error_detail_str = "HTTP_ROOT";
- {
- if (is_free == false)
- {
- // Other than free version
- HttpSendForbidden(c->FirstSock, h->Target, "");
- }
- else
- {
- // Free version
- BUF *b = ReadDump("|free.htm");
- if (b != NULL)
- {
- char *src = ZeroMalloc(b->Size + 1);
- UINT dst_size = b->Size * 2 + 64;
- char *dst = ZeroMalloc(dst_size);
- char host[MAX_PATH];
- char portstr[64];
- GetMachineName(host, sizeof(host));
- ToStr(portstr, c->FirstSock->LocalPort);
- Copy(src, b->Buf, b->Size);
- ReplaceStrEx(dst, dst_size, src,
- "$HOST$", host, false);
- ReplaceStrEx(dst, dst_size, dst,
- "$PORT$", portstr, false);
- FreeHttpHeader(h);
- h = NewHttpHeader("HTTP/1.1", "202", "OK");
- AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE4));
- AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
- AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
- PostHttp(c->FirstSock, h, dst, StrLen(dst));
- Free(src);
- Free(dst);
- FreeBuf(b);
- }
- }
- }
- }
- else
- {
- bool b = false;
- // Show the WebUI if the configuration allow to use the WebUI
- if (c->Cedar->Server != NULL && c->Cedar->Server->UseWebUI)
- {
- WU_WEBPAGE *page;
- // Show the WebUI
- page = WuGetPage(h->Target, c->Cedar->WebUI);
- if (page != NULL)
- {
- PostHttp(s, page->header, page->data, page->size);
- b = true;
- WuFreeWebPage(page);
- }
- }
- if (c->FirstSock->RemoteIP.addr[0] == 127)
- {
- if (StrCmpi(h->Target, HTTP_SAITAMA) == 0)
- {
- // Saitama (joke)
- FreeHttpHeader(h);
- h = NewHttpHeader("HTTP/1.1", "202", "OK");
- AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE3));
- AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
- AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
- PostHttp(s, h, Saitama, SizeOfSaitama());
- b = true;
- }
- else if (StartWith(h->Target, HTTP_PICTURES))
- {
- BUF *buf;
- // Lots of photos
- buf = ReadDump("|Pictures.mht");
- if (buf != NULL)
- {
- FreeHttpHeader(h);
- h = NewHttpHeader("HTTP/1.1", "202", "OK");
- AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE5));
- AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
- AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
- PostHttp(s, h, buf->Buf, buf->Size);
- b = true;
- FreeBuf(buf);
- }
- }
- }
- if (b == false)
- {
- // Not Found
- HttpSendNotFound(s, h->Target);
- *error_detail_str = "HTTP_NOT_FOUND";
- }
- }
- }
- FreeHttpHeader(h);
- }
- }
- }
- // Upload a signature
- bool ClientUploadSignature(SOCK *s)
- {
- HTTP_HEADER *h;
- UINT water_size, rand_size;
- UCHAR *water;
- char ip_str[128];
- // Validate arguments
- if (s == NULL)
- {
- return false;
- }
- IPToStr(ip_str, sizeof(ip_str), &s->RemoteIP);
- h = NewHttpHeader("POST", HTTP_VPN_TARGET2, "HTTP/1.1");
- AddHttpValue(h, NewHttpValue("Host", ip_str));
- AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE3));
- AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
- // Generate a watermark
- rand_size = Rand32() % (HTTP_PACK_RAND_SIZE_MAX * 2);
- water_size = SizeOfWaterMark() + rand_size;
- water = Malloc(water_size);
- Copy(water, WaterMark, SizeOfWaterMark());
- Rand(&water[SizeOfWaterMark()], rand_size);
- // Upload the watermark data
- if (PostHttp(s, h, water, water_size) == false)
- {
- Free(water);
- FreeHttpHeader(h);
- return false;
- }
- Free(water);
- FreeHttpHeader(h);
- return true;
- }
- // Establish a connection to the server
- SOCK *ClientConnectToServer(CONNECTION *c)
- {
- SOCK *s = NULL;
- X *x = NULL;
- K *k = NULL;
- // Validate arguments
- if (c == NULL)
- {
- return NULL;
- }
- if (c->Halt)
- {
- c->Err = ERR_USER_CANCEL;
- return NULL;
- }
- // Get the socket by connecting
- s = ClientConnectGetSocket(c, false, (c->DontUseTls1 ? false : true));
- if (s == NULL)
- {
- // Connection failure
- return NULL;
- }
- c->FirstSock = s;
- if (c->Halt)
- {
- c->Err = ERR_USER_CANCEL;
- ReleaseSock(s);
- c->FirstSock = NULL;
- return NULL;
- }
- // Time-out
- SetTimeout(s, CONNECTING_TIMEOUT);
- // Start the SSL communication
- if (StartSSLEx(s, x, k, (c->DontUseTls1 ? false : true), 0, c->ServerName) == false)
- {
- // SSL communication start failure
- Disconnect(s);
- ReleaseSock(s);
- c->FirstSock = NULL;
- c->Err = ERR_SERVER_IS_NOT_VPN;
- return NULL;
- }
- if (s->RemoteX == NULL)
- {
- // SSL communication start failure
- Disconnect(s);
- ReleaseSock(s);
- c->FirstSock = NULL;
- c->Err = ERR_SERVER_IS_NOT_VPN;
- return NULL;
- }
- return s;
- }
- // Return a socket by connecting to the server
- SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect, bool no_tls)
- {
- SOCK *s = NULL;
- CLIENT_OPTION *o;
- char *host_for_direct_connection;
- UINT port_for_direct_connection;
- wchar_t tmp[MAX_SIZE];
- SESSION *sess;
- volatile bool *cancel_flag = NULL;
- void *hWnd;
- UINT nat_t_err = 0;
- bool is_additonal_rudp_session = false;
- UCHAR uc = 0;
- IP ret_ip;
- // Validate arguments
- if (c == NULL)
- {
- return NULL;
- }
- Zero(&ret_ip, sizeof(IP));
- sess = c->Session;
- if (sess != NULL)
- {
- cancel_flag = &sess->CancelConnect;
- is_additonal_rudp_session = sess->IsRUDPSession;
- }
- hWnd = c->hWndForUI;
- o = c->Session->ClientOption;
- if (additional_connect)
- {
- if (sess != NULL)
- {
- Copy(&ret_ip, &sess->ServerIP_CacheForNextConnect, sizeof(IP));
- }
- }
- if (c->RestoreServerNameAndPort && additional_connect)
- {
- // Restore to the original server name and port number
- c->RestoreServerNameAndPort = false;
- if (StrCmpi(c->ServerName, o->Hostname) != 0)
- {
- StrCpy(c->ServerName, sizeof(c->ServerName), o->Hostname);
- Zero(&ret_ip, sizeof(IP));
- }
- c->ServerPort = o->Port;
- }
- host_for_direct_connection = c->ServerName;
- port_for_direct_connection = c->ServerPort;
- switch (o->ProxyType)
- {
- case PROXY_DIRECT: // TCP/IP
- UniFormat(tmp, sizeof(tmp), _UU("STATUS_4"), c->ServerName);
- PrintStatus(sess, tmp);
- // Production job
- if (o->PortUDP == 0)
- {
- {
- // If additional_connect == false, enable trying to NAT-T connection
- // If additional_connect == true, follow the IsRUDPSession setting in this session
- s = TcpIpConnectEx(host_for_direct_connection, port_for_direct_connection,
- (bool *)cancel_flag, hWnd, &nat_t_err, (additional_connect ? (!is_additonal_rudp_session) : false),
- true, no_tls, &ret_ip);
- }
- }
- else
- {
- // Mode to connect with R-UDP directly without using NAT-T server when using UDP
- IP ip;
- Zero(&ip, sizeof(ip));
- StrToIP(&ip, o->Hostname);
- s = NewRUDPClientDirect(VPN_RUDP_SVC_NAME, &ip, o->PortUDP, &nat_t_err,
- TIMEOUT_TCP_PORT_CHECK, (bool *)cancel_flag, NULL, NULL, 0, false);
- if (s != NULL)
- {
- StrCpy(s->UnderlayProtocol, sizeof(s->UnderlayProtocol), SOCK_UNDERLAY_NAT_T);
- }
- }
- if (s == NULL)
- {
- // Connection failure
- if (nat_t_err != RUDP_ERROR_NAT_T_TWO_OR_MORE)
- {
- c->Err = ERR_CONNECT_FAILED;
- }
- else
- {
- c->Err = ERR_NAT_T_TWO_OR_MORE;
- }
- return NULL;
- }
- break;
- case PROXY_HTTP: // HTTP Proxy
- host_for_direct_connection = o->ProxyName;
- port_for_direct_connection = o->ProxyPort;
- UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), c->ServerName, o->ProxyName);
- PrintStatus(sess, tmp);
- // Proxy connection
- s = ProxyConnectEx(c, host_for_direct_connection, port_for_direct_connection,
- c->ServerName, c->ServerPort, o->ProxyUsername, o->ProxyPassword,
- additional_connect, (bool *)cancel_flag, hWnd);
- if (s == NULL)
- {
- // Connection failure
- return NULL;
- }
- break;
- case PROXY_SOCKS: // SOCKS Proxy
- host_for_direct_connection = o->ProxyName;
- port_for_direct_connection = o->ProxyPort;
- UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), c->ServerName, o->ProxyName);
- PrintStatus(sess, tmp);
- // SOCKS connection
- s = SocksConnectEx2(c, host_for_direct_connection, port_for_direct_connection,
- c->ServerName, c->ServerPort, o->ProxyUsername,
- additional_connect, (bool *)cancel_flag, hWnd, 0, &ret_ip);
- if (s == NULL)
- {
- // Connection failure
- return NULL;
- }
- break;
- }
- if (s == NULL)
- {
- // Connection failure
- c->Err = ERR_CONNECT_FAILED;
- }
- else
- {
- // Success to connect
- // Keep a note of the IP address
- if (additional_connect == false || IsZeroIP(&s->RemoteIP))
- {
- if (((s->IsRUDPSocket || s->IPv6) && IsZeroIP(&s->RemoteIP) == false && o->ProxyType == PROXY_DIRECT) || GetIP(&c->Session->ServerIP, host_for_direct_connection) == false)
- {
- Copy(&c->Session->ServerIP, &s->RemoteIP, sizeof(IP));
- }
- }
- if (IsZeroIP(&ret_ip) == false)
- {
- if (c->Session != NULL)
- {
- if (additional_connect == false)
- {
- Copy(&c->Session->ServerIP_CacheForNextConnect, &ret_ip, sizeof(IP));
- Debug("Saved ServerIP_CacheForNextConnect: %s = %r\n", c->ServerName, &ret_ip);
- }
- }
- }
- }
- return s;
- }
- // Connect via SOCKS
- SOCK *SocksConnect(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
- char *server_host_name, UINT server_port,
- char *username, bool additional_connect)
- {
- return SocksConnectEx(c, proxy_host_name, proxy_port,
- server_host_name, server_port, username, additional_connect, NULL, NULL);
- }
- SOCK *SocksConnectEx(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
- char *server_host_name, UINT server_port,
- char *username, bool additional_connect,
- bool *cancel_flag, void *hWnd)
- {
- return SocksConnectEx2(c, proxy_host_name, proxy_port,
- server_host_name, server_port, username, additional_connect, cancel_flag,
- hWnd, 0, NULL);
- }
- SOCK *SocksConnectEx2(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
- char *server_host_name, UINT server_port,
- char *username, bool additional_connect,
- bool *cancel_flag, void *hWnd, UINT timeout, IP *ret_ip)
- {
- SOCK *s = NULL;
- IP ip;
- // Validate arguments
- if (c == NULL || proxy_host_name == NULL || proxy_port == 0 || server_host_name == NULL
- || server_port == 0)
- {
- c->Err = ERR_PROXY_CONNECT_FAILED;
- return NULL;
- }
- // Get the IP address of the destination server
- if (GetIP(&ip, server_host_name) == false)
- {
- // Failure
- c->Err = ERR_CONNECT_FAILED;
- return NULL;
- }
- if (c->Halt)
- {
- // Stop
- c->Err = ERR_USER_CANCEL;
- return NULL;
- }
- // Connection
- s = TcpConnectEx3(proxy_host_name, proxy_port, timeout, cancel_flag, hWnd, true, NULL, false, false, ret_ip);
- if (s == NULL)
- {
- // Failure
- c->Err = ERR_PROXY_CONNECT_FAILED;
- return NULL;
- }
- // Timeout setting
- SetTimeout(s, MIN(CONNECTING_TIMEOUT_PROXY, (timeout == 0 ? INFINITE : timeout)));
- if (additional_connect == false)
- {
- c->FirstSock = s;
- }
- // Request packet transmission
- if (SocksSendRequestPacket(c, s, server_port, &ip, username) == false)
- {
- // Failure
- if (additional_connect == false)
- {
- c->FirstSock = NULL;
- }
- Disconnect(s);
- ReleaseSock(s);
- return NULL;
- }
- // Receive a response packet
- if (SocksRecvResponsePacket(c, s) == false)
- {
- // Failure
- if (additional_connect == false)
- {
- c->FirstSock = NULL;
- }
- Disconnect(s);
- ReleaseSock(s);
- return NULL;
- }
- SetTimeout(s, INFINITE);
- return s;
- }
- // Receive a SOCKS response packet
- bool SocksRecvResponsePacket(CONNECTION *c, SOCK *s)
- {
- BUF *b;
- UINT size = 8;
- UCHAR tmp[8];
- UCHAR vn, cd;
- // Validate arguments
- if (c == NULL || s == NULL)
- {
- return false;
- }
- if (RecvAll(s, tmp, sizeof(tmp), false) == false)
- {
- c->Err = ERR_DISCONNECTED;
- return false;
- }
- b = NewBuf();
- WriteBuf(b, tmp, sizeof(tmp));
- SeekBuf(b, 0, 0);
- ReadBuf(b, &vn, 1);
- ReadBuf(b, &cd, 1);
- FreeBuf(b);
- if (vn != 0)
- {
- c->Err = ERR_PROXY_ERROR;
- return false;
- }
- switch (cd)
- {
- case 90:
- // Success
- return true;
- case 93:
- // Authentication failure
- c->Err = ERR_PROXY_AUTH_FAILED;
- return false;
- default:
- // Connection to the server failure
- c->Err = ERR_CONNECT_FAILED;
- return false;
- }
- }
- // Send a SOCKS request packet
- bool SocksSendRequestPacket(CONNECTION *c, SOCK *s, UINT dest_port, IP *dest_ip, char *userid)
- {
- BUF *b;
- UCHAR vn, cd;
- USHORT port;
- UINT ip;
- bool ret;
- // Validate arguments
- if (s == NULL || dest_port == 0 || dest_ip == NULL || c == NULL)
- {
- return false;
- }
- if (userid == NULL)
- {
- userid = "";
- }
- b = NewBuf();
- vn = 4;
- cd = 1;
- WriteBuf(b, &vn, 1);
- WriteBuf(b, &cd, 1);
- port = Endian16((USHORT)dest_port);
- ip = IPToUINT(dest_ip);
- WriteBuf(b, &port, 2);
- WriteBuf(b, &ip, 4);
- WriteBuf(b, userid, StrLen(userid) + 1);
- ret = SendAll(s, b->Buf, b->Size, false);
- if (ret == false)
- {
- c->Err = ERR_DISCONNECTED;
- }
- FreeBuf(b);
- return ret;
- }
- // Connect through a proxy
- SOCK *ProxyConnect(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
- char *server_host_name, UINT server_port,
- char *username, char *password, bool additional_connect)
- {
- return ProxyConnectEx(c, proxy_host_name, proxy_port,
- server_host_name, server_port, username, password, additional_connect, NULL, NULL);
- }
- SOCK *ProxyConnectEx(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
- char *server_host_name, UINT server_port,
- char *username, char *password, bool additional_connect,
- bool *cancel_flag, void *hWnd)
- {
- return ProxyConnectEx2(c, proxy_host_name, proxy_port,
- server_host_name, server_port, username, password, additional_connect,
- cancel_flag, hWnd, 0);
- }
- SOCK *ProxyConnectEx2(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
- char *server_host_name, UINT server_port,
- char *username, char *password, bool additional_connect,
- bool *cancel_flag, void *hWnd, UINT timeout)
- {
- SOCK *s = NULL;
- bool use_auth = false;
- char tmp[MAX_SIZE];
- char auth_tmp_str[MAX_SIZE], auth_b64_str[MAX_SIZE * 2];
- char basic_str[MAX_SIZE * 2];
- UINT http_error_code;
- HTTP_HEADER *h;
- char server_host_name_tmp[256];
- UINT i, len;
- // Validate arguments
- if (c == NULL || proxy_host_name == NULL || proxy_port == 0 || server_host_name == NULL ||
- server_port == 0)
- {
- c->Err = ERR_PROXY_CONNECT_FAILED;
- return NULL;
- }
- if (username != NULL && password != NULL &&
- (StrLen(username) != 0 || StrLen(password) != 0))
- {
- use_auth = true;
- }
- if (c->Halt)
- {
- // Stop
- c->Err = ERR_USER_CANCEL;
- return NULL;
- }
- Zero(server_host_name_tmp, sizeof(server_host_name_tmp));
- StrCpy(server_host_name_tmp, sizeof(server_host_name_tmp), server_host_name);
- len = StrLen(server_host_name_tmp);
- for (i = 0;i < len;i++)
- {
- if (server_host_name_tmp[i] == '/')
- {
- server_host_name_tmp[i] = 0;
- }
- }
- // Connection
- s = TcpConnectEx3(proxy_host_name, proxy_port, timeout, cancel_flag, hWnd, true, NULL, false, false, NULL);
- if (s == NULL)
- {
- // Failure
- c->Err = ERR_PROXY_CONNECT_FAILED;
- return NULL;
- }
- // Timeout setting
- SetTimeout(s, MIN(CONNECTING_TIMEOUT_PROXY, (timeout == 0 ? INFINITE : timeout)));
- if (additional_connect == false)
- {
- c->FirstSock = s;
- }
- // HTTP header generation
- if (IsStrIPv6Address(server_host_name_tmp))
- {
- IP ip;
- char iptmp[MAX_PATH];
- StrToIP(&ip, server_host_name_tmp);
- IPToStr(iptmp, sizeof(iptmp), &ip);
- Format(tmp, sizeof(tmp), "[%s]:%u", iptmp, server_port);
- }
- else
- {
- Format(tmp, sizeof(tmp), "%s:%u", server_host_name_tmp, server_port);
- }
- h = NewHttpHeader("CONNECT", tmp, "HTTP/1.0");
- AddHttpValue(h, NewHttpValue("User-Agent", (c->Cedar == NULL ? DEFAULT_USER_AGENT : c->Cedar->HttpUserAgent)));
- AddHttpValue(h, NewHttpValue("Host", server_host_name_tmp));
- AddHttpValue(h, NewHttpValue("Content-Length", "0"));
- AddHttpValue(h, NewHttpValue("Proxy-Connection", "Keep-Alive"));
- AddHttpValue(h, NewHttpValue("Pragma", "no-cache"));
- if (use_auth)
- {
- wchar_t tmp[MAX_SIZE];
- UniFormat(tmp, sizeof(tmp), _UU("STATUS_3"), server_host_name_tmp);
- // Generate the authentication string
- Format(auth_tmp_str, sizeof(auth_tmp_str), "%s:%s",
- username, password);
- // Base64 encode
- Zero(auth_b64_str, sizeof(auth_b64_str));
- Encode64(auth_b64_str, auth_tmp_str);
- Format(basic_str, sizeof(basic_str), "Basic %s", auth_b64_str);
- AddHttpValue(h, NewHttpValue("Proxy-Authorization", basic_str));
- }
- // Transmission
- if (SendHttpHeader(s, h) == false)
- {
- // Failure
- if (additional_connect == false)
- {
- c->FirstSock = NULL;
- }
- FreeHttpHeader(h);
- Disconnect(s);
- ReleaseSock(s);
- c->Err = ERR_PROXY_ERROR;
- return NULL;
- }
- FreeHttpHeader(h);
- if (c->Halt)
- {
- // Stop
- if (additional_connect == false)
- {
- c->FirstSock = NULL;
- }
- Disconnect(s);
- ReleaseSock(s);
- c->Err = ERR_USER_CANCEL;
- return NULL;
- }
- // Receive the results
- h = RecvHttpHeader(s);
- if (h == NULL)
- {
- // Failure
- if (additional_connect == false)
- {
- c->FirstSock = NULL;
- }
- FreeHttpHeader(h);
- Disconnect(s);
- ReleaseSock(s);
- c->Err = ERR_PROXY_ERROR;
- return NULL;
- }
- http_error_code = 0;
- if (StrLen(h->Method) == 8)
- {
- if (Cmp(h->Method, "HTTP/1.", 7) == 0)
- {
- http_error_code = ToInt(h->Target);
- }
- }
- FreeHttpHeader(h);
- // Check the code
- switch (http_error_code)
- {
- case 401:
- case 403:
- case 407:
- // Authentication failure
- if (additional_connect == false)
- {
- c->FirstSock = NULL;
- }
- Disconnect(s);
- ReleaseSock(s);
- c->Err = ERR_PROXY_AUTH_FAILED;
- return NULL;
- default:
- if ((http_error_code / 100) == 2)
- {
- // Success
- SetTimeout(s, INFINITE);
- return s;
- }
- else
- {
- // Receive an unknown result
- if (additional_connect == false)
- {
- c->FirstSock = NULL;
- }
- Disconnect(s);
- ReleaseSock(s);
- c->Err = ERR_PROXY_ERROR;
- return NULL;
- }
- }
- }
- // TCP connection function
- SOCK *TcpConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool try_start_ssl, bool ssl_no_tls)
- {
- return TcpConnectEx3(hostname, port, timeout, cancel_flag, hWnd, false, NULL, try_start_ssl, ssl_no_tls, NULL);
- }
- SOCK *TcpConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, bool ssl_no_tls, IP *ret_ip)
- {
- #ifdef OS_WIN32
- if (hWnd == NULL)
- {
- #endif // OS_WIN32
- return ConnectEx4(hostname, port, timeout, cancel_flag, (no_nat_t ? NULL : VPN_RUDP_SVC_NAME), nat_t_error_code, try_start_ssl, ssl_no_tls, true, ret_ip);
- #ifdef OS_WIN32
- }
- else
- {
- return WinConnectEx3((HWND)hWnd, hostname, port, timeout, 0, NULL, NULL, nat_t_error_code, (no_nat_t ? NULL : VPN_RUDP_SVC_NAME), try_start_ssl, ssl_no_tls);
- }
- #endif // OS_WIN32
- }
- // Connect with TCP/IP
- SOCK *TcpIpConnect(char *hostname, UINT port, bool try_start_ssl, bool ssl_no_tls)
- {
- return TcpIpConnectEx(hostname, port, NULL, NULL, NULL, false, try_start_ssl, ssl_no_tls, NULL);
- }
- SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, bool ssl_no_tls, IP *ret_ip)
- {
- SOCK *s = NULL;
- UINT dummy_int = 0;
- // Validate arguments
- if (nat_t_error_code == NULL)
- {
- nat_t_error_code = &dummy_int;
- }
- *nat_t_error_code = 0;
- if (hostname == NULL || port == 0)
- {
- return NULL;
- }
- s = TcpConnectEx3(hostname, port, 0, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, ssl_no_tls, ret_ip);
- if (s == NULL)
- {
- return NULL;
- }
- return s;
- }
- // Protocol routine initialization
- void InitProtocol()
- {
- }
- // Release the protocol routine
- void FreeProtocol()
- {
- }
- // Create a Hello packet
- PACK *PackHello(void *random, UINT ver, UINT build, char *server_str)
- {
- PACK *p;
- // Validate arguments
- if (random == NULL || server_str == NULL)
- {
- return NULL;
- }
- p = NewPack();
- PackAddStr(p, "hello", server_str);
- PackAddInt(p, "version", ver);
- PackAddInt(p, "build", build);
- PackAddData(p, "random", random, SHA1_SIZE);
- return p;
- }
- // Interpret the Hello packet
- bool GetHello(PACK *p, void *random, UINT *ver, UINT *build, char *server_str, UINT server_str_size)
- {
- // Validate arguments
- if (p == NULL || random == NULL || ver == NULL || server_str == NULL)
- {
- return false;
- }
- if (PackGetStr(p, "hello", server_str, server_str_size) == false)
- {
- return false;
- }
- *ver = PackGetInt(p, "version");
- *build = PackGetInt(p, "build");
- if (PackGetDataSize(p, "random") != SHA1_SIZE)
- {
- return false;
- }
- if (PackGetData(p, "random", random) == false)
- {
- return false;
- }
- return true;
- }
- // Get the authentication method from PACK
- UINT GetAuthTypeFromPack(PACK *p)
- {
- // Validate arguments
- if (p == NULL)
- {
- return 0;
- }
- return PackGetInt(p, "authtype");
- }
- // Get the HUB name and the user name from the PACK
- bool GetHubnameAndUsernameFromPack(PACK *p, char *username, UINT username_size,
- char *hubname, UINT hubname_size)
- {
- // Validate arguments
- if (p == NULL || username == NULL || hubname == NULL)
- {
- return false;
- }
- if (PackGetStr(p, "username", username, username_size) == false)
- {
- return false;
- }
- if (PackGetStr(p, "hubname", hubname, hubname_size) == false)
- {
- return false;
- }
- return true;
- }
- // Get the protocol from PACK
- UINT GetProtocolFromPack(PACK *p)
- {
- // Validate arguments
- if (p == NULL)
- {
- return 0;
- }
- #if 0
- return PackGetInt(p, "protocol");
- #else
- // Limit to the TCP protocol in the current version
- return CONNECTION_TCP;
- #endif
- }
- // Get the method from the PACK
- bool GetMethodFromPack(PACK *p, char *method, UINT size)
- {
- // Validate arguments
- if (p == NULL || method == NULL || size == 0)
- {
- return false;
- }
- return PackGetStr(p, "method", method, size);
- }
- // Generate a packet of certificate authentication login
- PACK *PackLoginWithCert(char *hubname, char *username, X *x, void *sign, UINT sign_size)
- {
- PACK *p;
- BUF *b;
- // Validate arguments
- if (hubname == NULL || username == NULL)
- {
- return NULL;
- }
- p = NewPack();
- PackAddStr(p, "method", "login");
- PackAddStr(p, "hubname", hubname);
- PackAddStr(p, "username", username);
- PackAddInt(p, "authtype", CLIENT_AUTHTYPE_CERT);
- // Certificate
- b = XToBuf(x, false);
- PackAddData(p, "cert", b->Buf, b->Size);
- FreeBuf(b);
- // Signature data
- PackAddData(p, "sign", sign, sign_size);
- return p;
- }
- // Generate a packet of plain text password authentication login
- PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_password)
- {
- PACK *p;
- // Validate arguments
- if (hubname == NULL || username == NULL)
- {
- return NULL;
- }
- p = NewPack();
- PackAddStr(p, "method", "login");
- PackAddStr(p, "hubname", hubname);
- PackAddStr(p, "username", username);
- PackAddInt(p, "authtype", CLIENT_AUTHTYPE_PLAIN_PASSWORD);
- PackAddStr(p, "plain_password", plain_password);
- return p;
- }
- // Create a packet of password authentication login
- PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password)
- {
- PACK *p;
- // Validate arguments
- if (hubname == NULL || username == NULL)
- {
- return NULL;
- }
- p = NewPack();
- PackAddStr(p, "method", "login");
- PackAddStr(p, "hubname", hubname);
- PackAddStr(p, "username", username);
- PackAddInt(p, "authtype", CLIENT_AUTHTYPE_PASSWORD);
- PackAddData(p, "secure_password", secure_password, SHA1_SIZE);
- return p;
- }
- // Create a packet for anonymous login
- PACK *PackLoginWithAnonymous(char *hubname, char *username)
- {
- PACK *p;
- // Validate arguments
- if (hubname == NULL || username == NULL)
- {
- return NULL;
- }
- p = NewPack();
- PackAddStr(p, "method", "login");
- PackAddStr(p, "hubname", hubname);
- PackAddStr(p, "username", username);
- PackAddInt(p, "authtype", CLIENT_AUTHTYPE_ANONYMOUS);
- return p;
- }
- // Create a packet for the additional connection
- PACK *PackAdditionalConnect(UCHAR *session_key)
- {
- PACK *p;
- // Validate arguments
- if (session_key == NULL)
- {
- return NULL;
- }
- p = NewPack();
- PackAddStr(p, "method", "additional_connect");
- PackAddData(p, "session_key", session_key, SHA1_SIZE);
- return p;
- }
- // Generate a RC4 key pair
- void GenerateRC4KeyPair(RC4_KEY_PAIR *k)
- {
- // Validate arguments
- if (k == NULL)
- {
- return;
- }
- Rand(k->ClientToServerKey, sizeof(k->ClientToServerKey));
- Rand(k->ServerToClientKey, sizeof(k->ServerToClientKey));
- }
- // Developed by SoftEther VPN Project at University of Tsukuba in Japan.
- // Department of Computer Science has dozens of overly-enthusiastic geeks.
- // Join us: http://www.tsukuba.ac.jp/english/admission/
|