1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345 |
- // 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;
- }
- // 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 hostname[64];
- char *vpn_http_target = HTTP_VPN_TARGET2;
- bool check_hostname = true;
- // Validate arguments
- if (c == NULL)
- {
- return false;
- }
- strcpy(hostname, "");
- 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;
- 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) && (StartWith(h->Target, "/wiki")))
- {
- HttpSendRedirect(s, h->Target, hostname);
- b = true;
- }
- 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/
|