1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-09-20 10:40:39 +03:00
SoftEtherVPN/src/Cedar/Protocol.c

7913 lines
197 KiB
C
Raw Normal View History

2017-10-19 05:48:23 +03:00
// SoftEther VPN Source Code - Developer Edition Master Branch
2014-01-04 17:00:08 +04:00
// Cedar Communication Module
// Protocol.c
// SoftEther protocol related routines
#include "CedarPch.h"
static UCHAR ssl_packet_start[3] = {0x17, 0x03, 0x00};
// MIME list from https://www.freeformatter.com/mime-types-list.html
static HTTP_MIME_TYPE http_mime_types[] =
{
{".x3d", "application/vnd.hzn-3d-crossword"},
{".3gp", "video/3gpp"},
{".3g2", "video/3gpp2"},
{".mseq", "application/vnd.mseq"},
{".pwn", "application/vnd.3m.post-it-notes"},
{".plb", "application/vnd.3gpp.pic-bw-large"},
{".psb", "application/vnd.3gpp.pic-bw-small"},
{".pvb", "application/vnd.3gpp.pic-bw-var"},
{".tcap", "application/vnd.3gpp2.tcap"},
{".7z", "application/x-7z-compressed"},
{".abw", "application/x-abiword"},
{".ace", "application/x-ace-compressed"},
{".acc", "application/vnd.americandynamics.acc"},
{".acu", "application/vnd.acucobol"},
{".atc", "application/vnd.acucorp"},
{".adp", "audio/adpcm"},
{".aab", "application/x-authorware-bin"},
{".aam", "application/x-authorware-map"},
{".aas", "application/x-authorware-seg"},
{".air", "application/vnd.adobe.air-application-installer-package+zip"},
{".swf", "application/x-shockwave-flash"},
{".fxp", "application/vnd.adobe.fxp"},
{".pdf", "application/pdf"},
{".ppd", "application/vnd.cups-ppd"},
{".dir", "application/x-director"},
{".xdp", "application/vnd.adobe.xdp+xml"},
{".xfdf", "application/vnd.adobe.xfdf"},
{".aac", "audio/x-aac"},
{".ahead", "application/vnd.ahead.space"},
{".azf", "application/vnd.airzip.filesecure.azf"},
{".azs", "application/vnd.airzip.filesecure.azs"},
{".azw", "application/vnd.amazon.ebook"},
{".ami", "application/vnd.amiga.ami"},
{".apk", "application/vnd.android.package-archive"},
{".cii", "application/vnd.anser-web-certificate-issue-initiation"},
{".fti", "application/vnd.anser-web-funds-transfer-initiation"},
{".atx", "application/vnd.antix.game-component"},
{".dmg", "application/x-apple-diskimage"},
{".mpkg", "application/vnd.apple.installer+xml"},
{".aw", "application/applixware"},
{".les", "application/vnd.hhe.lesson-player"},
{".swi", "application/vnd.aristanetworks.swi"},
{".s", "text/x-asm"},
{".atomcat", "application/atomcat+xml"},
{".atomsvc", "application/atomsvc+xml"},
{".atom", "application/atom+xml"},
{".ac", "application/pkix-attr-cert"},
{".aif", "audio/x-aiff"},
{".avi", "video/x-msvideo"},
{".aep", "application/vnd.audiograph"},
{".dxf", "image/vnd.dxf"},
{".dwf", "model/vnd.dwf"},
{".par", "text/plain-bas"},
{".bcpio", "application/x-bcpio"},
{".bin", "application/octet-stream"},
{".bmp", "image/bmp"},
{".torrent", "application/x-bittorrent"},
{".cod", "application/vnd.rim.cod"},
{".mpm", "application/vnd.blueice.multipass"},
{".bmi", "application/vnd.bmi"},
{".sh", "application/x-sh"},
{".btif", "image/prs.btif"},
{".rep", "application/vnd.businessobjects"},
{".bz", "application/x-bzip"},
{".bz2", "application/x-bzip2"},
{".csh", "application/x-csh"},
{".c", "text/x-c"},
{".cdxml", "application/vnd.chemdraw+xml"},
{".css", "text/css"},
{".cdx", "chemical/x-cdx"},
{".cml", "chemical/x-cml"},
{".csml", "chemical/x-csml"},
{".cdbcmsg", "application/vnd.contact.cmsg"},
{".cla", "application/vnd.claymore"},
{".c4g", "application/vnd.clonk.c4group"},
{".sub", "image/vnd.dvb.subtitle"},
{".cdmia", "application/cdmi-capability"},
{".cdmic", "application/cdmi-container"},
{".cdmid", "application/cdmi-domain"},
{".cdmio", "application/cdmi-object"},
{".cdmiq", "application/cdmi-queue"},
{".c11amc", "application/vnd.cluetrust.cartomobile-config"},
{".c11amz", "application/vnd.cluetrust.cartomobile-config-pkg"},
{".ras", "image/x-cmu-raster"},
{".dae", "model/vnd.collada+xml"},
{".csv", "text/csv"},
{".cpt", "application/mac-compactpro"},
{".wmlc", "application/vnd.wap.wmlc"},
{".cgm", "image/cgm"},
{".ice", "x-conference/x-cooltalk"},
{".cmx", "image/x-cmx"},
{".xar", "application/vnd.xara"},
{".cmc", "application/vnd.cosmocaller"},
{".cpio", "application/x-cpio"},
{".clkx", "application/vnd.crick.clicker"},
{".clkk", "application/vnd.crick.clicker.keyboard"},
{".clkp", "application/vnd.crick.clicker.palette"},
{".clkt", "application/vnd.crick.clicker.template"},
{".clkw", "application/vnd.crick.clicker.wordbank"},
{".wbs", "application/vnd.criticaltools.wbs+xml"},
{".cryptonote", "application/vnd.rig.cryptonote"},
{".cif", "chemical/x-cif"},
{".cmdf", "chemical/x-cmdf"},
{".cu", "application/cu-seeme"},
{".cww", "application/prs.cww"},
{".curl", "text/vnd.curl"},
{".dcurl", "text/vnd.curl.dcurl"},
{".mcurl", "text/vnd.curl.mcurl"},
{".scurl", "text/vnd.curl.scurl"},
{".car", "application/vnd.curl.car"},
{".pcurl", "application/vnd.curl.pcurl"},
{".cmp", "application/vnd.yellowriver-custom-menu"},
{".dssc", "application/dssc+der"},
{".xdssc", "application/dssc+xml"},
{".deb", "application/x-debian-package"},
{".uva", "audio/vnd.dece.audio"},
{".uvi", "image/vnd.dece.graphic"},
{".uvh", "video/vnd.dece.hd"},
{".uvm", "video/vnd.dece.mobile"},
{".uvu", "video/vnd.uvvu.mp4"},
{".uvp", "video/vnd.dece.pd"},
{".uvs", "video/vnd.dece.sd"},
{".uvv", "video/vnd.dece.video"},
{".dvi", "application/x-dvi"},
{".seed", "application/vnd.fdsn.seed"},
{".dtb", "application/x-dtbook+xml"},
{".res", "application/x-dtbresource+xml"},
{".ait", "application/vnd.dvb.ait"},
{".svc", "application/vnd.dvb.service"},
{".eol", "audio/vnd.digital-winds"},
{".djvu", "image/vnd.djvu"},
{".dtd", "application/xml-dtd"},
{".mlp", "application/vnd.dolby.mlp"},
{".wad", "application/x-doom"},
{".dpg", "application/vnd.dpgraph"},
{".dra", "audio/vnd.dra"},
{".dfac", "application/vnd.dreamfactory"},
{".dts", "audio/vnd.dts"},
{".dtshd", "audio/vnd.dts.hd"},
{".dwg", "image/vnd.dwg"},
{".geo", "application/vnd.dynageo"},
{".es", "application/ecmascript"},
{".mag", "application/vnd.ecowin.chart"},
{".mmr", "image/vnd.fujixerox.edmics-mmr"},
{".rlc", "image/vnd.fujixerox.edmics-rlc"},
{".exi", "application/exi"},
{".mgz", "application/vnd.proteus.magazine"},
{".epub", "application/epub+zip"},
{".eml", "message/rfc822"},
{".nml", "application/vnd.enliven"},
{".xpr", "application/vnd.is-xpr"},
{".xif", "image/vnd.xiff"},
{".xfdl", "application/vnd.xfdl"},
{".emma", "application/emma+xml"},
{".ez2", "application/vnd.ezpix-album"},
{".ez3", "application/vnd.ezpix-package"},
{".fst", "image/vnd.fst"},
{".fvt", "video/vnd.fvt"},
{".fbs", "image/vnd.fastbidsheet"},
{".fe_launch", "application/vnd.denovo.fcselayout-link"},
{".f4v", "video/x-f4v"},
{".flv", "video/x-flv"},
{".fpx", "image/vnd.fpx"},
{".npx", "image/vnd.net-fpx"},
{".flx", "text/vnd.fmi.flexstor"},
{".fli", "video/x-fli"},
{".ftc", "application/vnd.fluxtime.clip"},
{".fdf", "application/vnd.fdf"},
{".f", "text/x-fortran"},
{".mif", "application/vnd.mif"},
{".fm", "application/vnd.framemaker"},
{".fh", "image/x-freehand"},
{".fsc", "application/vnd.fsc.weblaunch"},
{".fnc", "application/vnd.frogans.fnc"},
{".ltf", "application/vnd.frogans.ltf"},
{".ddd", "application/vnd.fujixerox.ddd"},
{".xdw", "application/vnd.fujixerox.docuworks"},
{".xbd", "application/vnd.fujixerox.docuworks.binder"},
{".oas", "application/vnd.fujitsu.oasys"},
{".oa2", "application/vnd.fujitsu.oasys2"},
{".oa3", "application/vnd.fujitsu.oasys3"},
{".fg5", "application/vnd.fujitsu.oasysgp"},
{".bh2", "application/vnd.fujitsu.oasysprs"},
{".spl", "application/x-futuresplash"},
{".fzs", "application/vnd.fuzzysheet"},
{".g3", "image/g3fax"},
{".gmx", "application/vnd.gmx"},
{".gtw", "model/vnd.gtw"},
{".txd", "application/vnd.genomatix.tuxedo"},
{".ggb", "application/vnd.geogebra.file"},
{".ggt", "application/vnd.geogebra.tool"},
{".gdl", "model/vnd.gdl"},
{".gex", "application/vnd.geometry-explorer"},
{".gxt", "application/vnd.geonext"},
{".g2w", "application/vnd.geoplan"},
{".g3w", "application/vnd.geospace"},
{".gsf", "application/x-font-ghostscript"},
{".bdf", "application/x-font-bdf"},
{".gtar", "application/x-gtar"},
{".texinfo", "application/x-texinfo"},
{".gnumeric", "application/x-gnumeric"},
{".kml", "application/vnd.google-earth.kml+xml"},
{".kmz", "application/vnd.google-earth.kmz"},
{".gqf", "application/vnd.grafeq"},
{".gif", "image/gif"},
{".gv", "text/vnd.graphviz"},
{".gac", "application/vnd.groove-account"},
{".ghf", "application/vnd.groove-help"},
{".gim", "application/vnd.groove-identity-message"},
{".grv", "application/vnd.groove-injector"},
{".gtm", "application/vnd.groove-tool-message"},
{".tpl", "application/vnd.groove-tool-template"},
{".vcg", "application/vnd.groove-vcard"},
{".h261", "video/h261"},
{".h263", "video/h263"},
{".h264", "video/h264"},
{".hpid", "application/vnd.hp-hpid"},
{".hps", "application/vnd.hp-hps"},
{".hdf", "application/x-hdf"},
{".rip", "audio/vnd.rip"},
{".hbci", "application/vnd.hbci"},
{".jlt", "application/vnd.hp-jlyt"},
{".pcl", "application/vnd.hp-pcl"},
{".hpgl", "application/vnd.hp-hpgl"},
{".hvs", "application/vnd.yamaha.hv-script"},
{".hvd", "application/vnd.yamaha.hv-dic"},
{".hvp", "application/vnd.yamaha.hv-voice"},
{".sfd-hdstx", "application/vnd.hydrostatix.sof-data"},
{".stk", "application/hyperstudio"},
{".hal", "application/vnd.hal+xml"},
{".htm", "text/html; charset=utf-8"},
{".html", "text/html; charset=utf-8"},
{".irm", "application/vnd.ibm.rights-management"},
{".sc", "application/vnd.ibm.secure-container"},
{".ics", "text/calendar"},
{".icc", "application/vnd.iccprofile"},
{".ico", "image/x-icon"},
{".igl", "application/vnd.igloader"},
{".ief", "image/ief"},
{".ivp", "application/vnd.immervision-ivp"},
{".ivu", "application/vnd.immervision-ivu"},
{".rif", "application/reginfo+xml"},
{".3dml", "text/vnd.in3d.3dml"},
{".spot", "text/vnd.in3d.spot"},
{".igs", "model/iges"},
{".i2g", "application/vnd.intergeo"},
{".cdy", "application/vnd.cinderella"},
{".xpw", "application/vnd.intercon.formnet"},
{".fcs", "application/vnd.isac.fcs"},
{".ipfix", "application/ipfix"},
{".cer", "application/pkix-cert"},
{".pki", "application/pkixcmp"},
{".crl", "application/pkix-crl"},
{".pkipath", "application/pkix-pkipath"},
{".igm", "application/vnd.insors.igm"},
{".rcprofile", "application/vnd.ipunplugged.rcprofile"},
{".irp", "application/vnd.irepository.package+xml"},
{".jad", "text/vnd.sun.j2me.app-descriptor"},
{".jar", "application/java-archive"},
{".class", "application/java-vm"},
{".jnlp", "application/x-java-jnlp-file"},
{".ser", "application/java-serialized-object"},
{".java", "text/x-java-source"},
{".js", "application/javascript"},
{".json", "application/json"},
{".joda", "application/vnd.joost.joda-archive"},
{".jpm", "video/jpm"},
{".jpg", "image/jpeg"},
{".jpeg", "image/jpeg"},
{".pjpeg", "image/pjpeg"},
{".jpgv", "video/jpeg"},
{".ktz", "application/vnd.kahootz"},
{".mmd", "application/vnd.chipnuts.karaoke-mmd"},
{".karbon", "application/vnd.kde.karbon"},
{".chrt", "application/vnd.kde.kchart"},
{".kfo", "application/vnd.kde.kformula"},
{".flw", "application/vnd.kde.kivio"},
{".kon", "application/vnd.kde.kontour"},
{".kpr", "application/vnd.kde.kpresenter"},
{".ksp", "application/vnd.kde.kspread"},
{".kwd", "application/vnd.kde.kword"},
{".htke", "application/vnd.kenameaapp"},
{".kia", "application/vnd.kidspiration"},
{".kne", "application/vnd.kinar"},
{".sse", "application/vnd.kodak-descriptor"},
{".lasxml", "application/vnd.las.las+xml"},
{".latex", "application/x-latex"},
{".lbd", "application/vnd.llamagraphics.life-balance.desktop"},
{".lbe", "application/vnd.llamagraphics.life-balance.exchange+xml"},
{".jam", "application/vnd.jam"},
{"0.123", "application/vnd.lotus-1-2-3"},
{".apr", "application/vnd.lotus-approach"},
{".pre", "application/vnd.lotus-freelance"},
{".nsf", "application/vnd.lotus-notes"},
{".org", "application/vnd.lotus-organizer"},
{".scm", "application/vnd.lotus-screencam"},
{".lwp", "application/vnd.lotus-wordpro"},
{".lvp", "audio/vnd.lucent.voice"},
{".m3u", "audio/x-mpegurl"},
{".m4v", "video/x-m4v"},
{".hqx", "application/mac-binhex40"},
{".portpkg", "application/vnd.macports.portpkg"},
{".mgp", "application/vnd.osgeo.mapguide.package"},
{".mrc", "application/marc"},
{".mrcx", "application/marcxml+xml"},
{".mxf", "application/mxf"},
{".nbp", "application/vnd.wolfram.player"},
{".ma", "application/mathematica"},
{".mathml", "application/mathml+xml"},
{".mbox", "application/mbox"},
{".mc1", "application/vnd.medcalcdata"},
{".mscml", "application/mediaservercontrol+xml"},
{".cdkey", "application/vnd.mediastation.cdkey"},
{".mwf", "application/vnd.mfer"},
{".mfm", "application/vnd.mfmp"},
{".msh", "model/mesh"},
{".mads", "application/mads+xml"},
{".mets", "application/mets+xml"},
{".mods", "application/mods+xml"},
{".meta4", "application/metalink4+xml"},
{".mcd", "application/vnd.mcd"},
{".flo", "application/vnd.micrografx.flo"},
{".igx", "application/vnd.micrografx.igx"},
{".es3", "application/vnd.eszigno3+xml"},
{".mdb", "application/x-msaccess"},
{".asf", "video/x-ms-asf"},
{".exe", "application/x-msdownload"},
{".cil", "application/vnd.ms-artgalry"},
{".cab", "application/vnd.ms-cab-compressed"},
{".ims", "application/vnd.ms-ims"},
{".application", "application/x-ms-application"},
{".clp", "application/x-msclip"},
{".mdi", "image/vnd.ms-modi"},
{".eot", "application/vnd.ms-fontobject"},
{".xls", "application/vnd.ms-excel"},
{".xlam", "application/vnd.ms-excel.addin.macroenabled.12"},
{".xlsb", "application/vnd.ms-excel.sheet.binary.macroenabled.12"},
{".xltm", "application/vnd.ms-excel.template.macroenabled.12"},
{".xlsm", "application/vnd.ms-excel.sheet.macroenabled.12"},
{".chm", "application/vnd.ms-htmlhelp"},
{".crd", "application/x-mscardfile"},
{".lrm", "application/vnd.ms-lrm"},
{".mvb", "application/x-msmediaview"},
{".mny", "application/x-msmoney"},
{".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
{".sldx", "application/vnd.openxmlformats-officedocument.presentationml.slide"},
{".ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"},
{".potx", "application/vnd.openxmlformats-officedocument.presentationml.template"},
{".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
{".xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"},
{".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
{".dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"},
{".obd", "application/x-msbinder"},
{".thmx", "application/vnd.ms-officetheme"},
{".onetoc", "application/onenote"},
{".pya", "audio/vnd.ms-playready.media.pya"},
{".pyv", "video/vnd.ms-playready.media.pyv"},
{".ppt", "application/vnd.ms-powerpoint"},
{".ppam", "application/vnd.ms-powerpoint.addin.macroenabled.12"},
{".sldm", "application/vnd.ms-powerpoint.slide.macroenabled.12"},
{".pptm", "application/vnd.ms-powerpoint.presentation.macroenabled.12"},
{".ppsm", "application/vnd.ms-powerpoint.slideshow.macroenabled.12"},
{".potm", "application/vnd.ms-powerpoint.template.macroenabled.12"},
{".mpp", "application/vnd.ms-project"},
{".pub", "application/x-mspublisher"},
{".scd", "application/x-msschedule"},
{".xap", "application/x-silverlight-app"},
{".stl", "application/vnd.ms-pki.stl"},
{".cat", "application/vnd.ms-pki.seccat"},
{".vsd", "application/vnd.visio"},
{".vsdx", "application/vnd.visio2013"},
{".wm", "video/x-ms-wm"},
{".wma", "audio/x-ms-wma"},
{".wax", "audio/x-ms-wax"},
{".wmx", "video/x-ms-wmx"},
{".wmd", "application/x-ms-wmd"},
{".wpl", "application/vnd.ms-wpl"},
{".wmz", "application/x-ms-wmz"},
{".wmv", "video/x-ms-wmv"},
{".wvx", "video/x-ms-wvx"},
{".wmf", "application/x-msmetafile"},
{".trm", "application/x-msterminal"},
{".doc", "application/msword"},
{".docm", "application/vnd.ms-word.document.macroenabled.12"},
{".dotm", "application/vnd.ms-word.template.macroenabled.12"},
{".wri", "application/x-mswrite"},
{".wps", "application/vnd.ms-works"},
{".xbap", "application/x-ms-xbap"},
{".xps", "application/vnd.ms-xpsdocument"},
{".mid", "audio/midi"},
{".mpy", "application/vnd.ibm.minipay"},
{".afp", "application/vnd.ibm.modcap"},
{".rms", "application/vnd.jcp.javame.midlet-rms"},
{".tmo", "application/vnd.tmobile-livetv"},
{".prc", "application/x-mobipocket-ebook"},
{".mbk", "application/vnd.mobius.mbk"},
{".dis", "application/vnd.mobius.dis"},
{".plc", "application/vnd.mobius.plc"},
{".mqy", "application/vnd.mobius.mqy"},
{".msl", "application/vnd.mobius.msl"},
{".txf", "application/vnd.mobius.txf"},
{".daf", "application/vnd.mobius.daf"},
{".fly", "text/vnd.fly"},
{".mpc", "application/vnd.mophun.certificate"},
{".mpn", "application/vnd.mophun.application"},
{".mj2", "video/mj2"},
{".mpga", "audio/mpeg"},
{".mxu", "video/vnd.mpegurl"},
{".mpeg", "video/mpeg"},
{".m21", "application/mp21"},
{".mp4a", "audio/mp4"},
{".mp4", "video/mp4"},
{".mp4", "application/mp4"},
{".m3u8", "application/vnd.apple.mpegurl"},
{".mus", "application/vnd.musician"},
{".msty", "application/vnd.muvee.style"},
{".mxml", "application/xv+xml"},
{".ngdat", "application/vnd.nokia.n-gage.data"},
{".n-gage", "application/vnd.nokia.n-gage.symbian.install"},
{".ncx", "application/x-dtbncx+xml"},
{".nc", "application/x-netcdf"},
{".nlu", "application/vnd.neurolanguage.nlu"},
{".dna", "application/vnd.dna"},
{".nnd", "application/vnd.noblenet-directory"},
{".nns", "application/vnd.noblenet-sealer"},
{".nnw", "application/vnd.noblenet-web"},
{".rpst", "application/vnd.nokia.radio-preset"},
{".rpss", "application/vnd.nokia.radio-presets"},
{".n3", "text/n3"},
{".edm", "application/vnd.novadigm.edm"},
{".edx", "application/vnd.novadigm.edx"},
{".ext", "application/vnd.novadigm.ext"},
{".gph", "application/vnd.flographit"},
{".ecelp4800", "audio/vnd.nuera.ecelp4800"},
{".ecelp7470", "audio/vnd.nuera.ecelp7470"},
{".ecelp9600", "audio/vnd.nuera.ecelp9600"},
{".oda", "application/oda"},
{".ogx", "application/ogg"},
{".oga", "audio/ogg"},
{".ogv", "video/ogg"},
{".dd2", "application/vnd.oma.dd2+xml"},
{".oth", "application/vnd.oasis.opendocument.text-web"},
{".opf", "application/oebps-package+xml"},
{".qbo", "application/vnd.intu.qbo"},
{".oxt", "application/vnd.openofficeorg.extension"},
{".osf", "application/vnd.yamaha.openscoreformat"},
{".weba", "audio/webm"},
{".webm", "video/webm"},
{".odc", "application/vnd.oasis.opendocument.chart"},
{".otc", "application/vnd.oasis.opendocument.chart-template"},
{".odb", "application/vnd.oasis.opendocument.database"},
{".odf", "application/vnd.oasis.opendocument.formula"},
{".odft", "application/vnd.oasis.opendocument.formula-template"},
{".odg", "application/vnd.oasis.opendocument.graphics"},
{".otg", "application/vnd.oasis.opendocument.graphics-template"},
{".odi", "application/vnd.oasis.opendocument.image"},
{".oti", "application/vnd.oasis.opendocument.image-template"},
{".odp", "application/vnd.oasis.opendocument.presentation"},
{".otp", "application/vnd.oasis.opendocument.presentation-template"},
{".ods", "application/vnd.oasis.opendocument.spreadsheet"},
{".ots", "application/vnd.oasis.opendocument.spreadsheet-template"},
{".odt", "application/vnd.oasis.opendocument.text"},
{".odm", "application/vnd.oasis.opendocument.text-master"},
{".ott", "application/vnd.oasis.opendocument.text-template"},
{".ktx", "image/ktx"},
{".sxc", "application/vnd.sun.xml.calc"},
{".stc", "application/vnd.sun.xml.calc.template"},
{".sxd", "application/vnd.sun.xml.draw"},
{".std", "application/vnd.sun.xml.draw.template"},
{".sxi", "application/vnd.sun.xml.impress"},
{".sti", "application/vnd.sun.xml.impress.template"},
{".sxm", "application/vnd.sun.xml.math"},
{".sxw", "application/vnd.sun.xml.writer"},
{".sxg", "application/vnd.sun.xml.writer.global"},
{".stw", "application/vnd.sun.xml.writer.template"},
{".otf", "application/x-font-otf"},
{".osfpvg", "application/vnd.yamaha.openscoreformat.osfpvg+xml"},
{".dp", "application/vnd.osgi.dp"},
{".pdb", "application/vnd.palm"},
{".p", "text/x-pascal"},
{".paw", "application/vnd.pawaafile"},
{".pclxl", "application/vnd.hp-pclxl"},
{".efif", "application/vnd.picsel"},
{".pcx", "image/x-pcx"},
{".psd", "image/vnd.adobe.photoshop"},
{".prf", "application/pics-rules"},
{".pic", "image/x-pict"},
{".chat", "application/x-chat"},
{".p10", "application/pkcs10"},
{".p12", "application/x-pkcs12"},
{".p7m", "application/pkcs7-mime"},
{".p7s", "application/pkcs7-signature"},
{".p7r", "application/x-pkcs7-certreqresp"},
{".p7b", "application/x-pkcs7-certificates"},
{".p8", "application/pkcs8"},
{".plf", "application/vnd.pocketlearn"},
{".pnm", "image/x-portable-anymap"},
{".pbm", "image/x-portable-bitmap"},
{".pcf", "application/x-font-pcf"},
{".pfr", "application/font-tdpfr"},
{".pgn", "application/x-chess-pgn"},
{".pgm", "image/x-portable-graymap"},
{".png", "image/png"},
{".png", "image/x-citrix-png"},
{".png", "image/x-png"},
{".ppm", "image/x-portable-pixmap"},
{".pskcxml", "application/pskc+xml"},
{".pml", "application/vnd.ctc-posml"},
{".ai", "application/postscript"},
{".pfa", "application/x-font-type1"},
{".pbd", "application/vnd.powerbuilder6"},
{".pgp", "application/pgp-encrypted"},
{".pgp", "application/pgp-signature"},
{".box", "application/vnd.previewsystems.box"},
{".ptid", "application/vnd.pvi.ptid1"},
{".pls", "application/pls+xml"},
{".str", "application/vnd.pg.format"},
{".ei6", "application/vnd.pg.osasli"},
{".dsc", "text/prs.lines.tag"},
{".psf", "application/x-font-linux-psf"},
{".qps", "application/vnd.publishare-delta-tree"},
{".wg", "application/vnd.pmi.widget"},
{".qxd", "application/vnd.quark.quarkxpress"},
{".esf", "application/vnd.epson.esf"},
{".msf", "application/vnd.epson.msf"},
{".ssf", "application/vnd.epson.ssf"},
{".qam", "application/vnd.epson.quickanime"},
{".qfx", "application/vnd.intu.qfx"},
{".qt", "video/quicktime"},
{".rar", "application/x-rar-compressed"},
{".ram", "audio/x-pn-realaudio"},
{".rmp", "audio/x-pn-realaudio-plugin"},
{".rsd", "application/rsd+xml"},
{".rm", "application/vnd.rn-realmedia"},
{".bed", "application/vnd.realvnc.bed"},
{".mxl", "application/vnd.recordare.musicxml"},
{".musicxml", "application/vnd.recordare.musicxml+xml"},
{".rnc", "application/relax-ng-compact-syntax"},
{".rdz", "application/vnd.data-vision.rdz"},
{".rdf", "application/rdf+xml"},
{".rp9", "application/vnd.cloanto.rp9"},
{".jisp", "application/vnd.jisp"},
{".rtf", "application/rtf"},
{".rtx", "text/richtext"},
{".link66", "application/vnd.route66.link66+xml"},
{".rss", "application/rss+xml"},
{".shf", "application/shf+xml"},
{".st", "application/vnd.sailingtracker.track"},
{".svg", "image/svg+xml"},
{".sus", "application/vnd.sus-calendar"},
{".sru", "application/sru+xml"},
{".setpay", "application/set-payment-initiation"},
{".setreg", "application/set-registration-initiation"},
{".sema", "application/vnd.sema"},
{".semd", "application/vnd.semd"},
{".semf", "application/vnd.semf"},
{".see", "application/vnd.seemail"},
{".snf", "application/x-font-snf"},
{".spq", "application/scvp-vp-request"},
{".spp", "application/scvp-vp-response"},
{".scq", "application/scvp-cv-request"},
{".scs", "application/scvp-cv-response"},
{".sdp", "application/sdp"},
{".etx", "text/x-setext"},
{".movie", "video/x-sgi-movie"},
{".ifm", "application/vnd.shana.informed.formdata"},
{".itp", "application/vnd.shana.informed.formtemplate"},
{".iif", "application/vnd.shana.informed.interchange"},
{".ipk", "application/vnd.shana.informed.package"},
{".tfi", "application/thraud+xml"},
{".shar", "application/x-shar"},
{".rgb", "image/x-rgb"},
{".slt", "application/vnd.epson.salt"},
{".aso", "application/vnd.accpac.simply.aso"},
{".imp", "application/vnd.accpac.simply.imp"},
{".twd", "application/vnd.simtech-mindmapper"},
{".csp", "application/vnd.commonspace"},
{".saf", "application/vnd.yamaha.smaf-audio"},
{".mmf", "application/vnd.smaf"},
{".spf", "application/vnd.yamaha.smaf-phrase"},
{".teacher", "application/vnd.smart.teacher"},
{".svd", "application/vnd.svd"},
{".rq", "application/sparql-query"},
{".srx", "application/sparql-results+xml"},
{".gram", "application/srgs"},
{".grxml", "application/srgs+xml"},
{".ssml", "application/ssml+xml"},
{".skp", "application/vnd.koan"},
{".sgml", "text/sgml"},
{".sdc", "application/vnd.stardivision.calc"},
{".sda", "application/vnd.stardivision.draw"},
{".sdd", "application/vnd.stardivision.impress"},
{".smf", "application/vnd.stardivision.math"},
{".sdw", "application/vnd.stardivision.writer"},
{".sgl", "application/vnd.stardivision.writer-global"},
{".sm", "application/vnd.stepmania.stepchart"},
{".sit", "application/x-stuffit"},
{".sitx", "application/x-stuffitx"},
{".sdkm", "application/vnd.solent.sdkm+xml"},
{".xo", "application/vnd.olpc-sugar"},
{".au", "audio/basic"},
{".wqd", "application/vnd.wqd"},
{".sis", "application/vnd.symbian.install"},
{".smi", "application/smil+xml"},
{".xsm", "application/vnd.syncml+xml"},
{".bdm", "application/vnd.syncml.dm+wbxml"},
{".xdm", "application/vnd.syncml.dm+xml"},
{".sv4cpio", "application/x-sv4cpio"},
{".sv4crc", "application/x-sv4crc"},
{".sbml", "application/sbml+xml"},
{".tsv", "text/tab-separated-values"},
{".tiff", "image/tiff"},
{".tao", "application/vnd.tao.intent-module-archive"},
{".tar", "application/x-tar"},
{".tcl", "application/x-tcl"},
{".tex", "application/x-tex"},
{".tfm", "application/x-tex-tfm"},
{".tei", "application/tei+xml"},
{".txt", "text/plain; charset=utf-8"},
{".md", "text/markdown; charset=utf-8"},
{".dxp", "application/vnd.spotfire.dxp"},
{".sfs", "application/vnd.spotfire.sfs"},
{".tsd", "application/timestamped-data"},
{".tpt", "application/vnd.trid.tpt"},
{".mxs", "application/vnd.triscape.mxs"},
{".t", "text/troff"},
{".tra", "application/vnd.trueapp"},
{".ttf", "application/x-font-ttf"},
{".ttl", "text/turtle"},
{".umj", "application/vnd.umajin"},
{".uoml", "application/vnd.uoml+xml"},
{".unityweb", "application/vnd.unity"},
{".ufd", "application/vnd.ufdl"},
{".uri", "text/uri-list"},
{".utz", "application/vnd.uiq.theme"},
{".ustar", "application/x-ustar"},
{".uu", "text/x-uuencode"},
{".vcs", "text/x-vcalendar"},
{".vcf", "text/x-vcard"},
{".vcd", "application/x-cdlink"},
{".vsf", "application/vnd.vsf"},
{".wrl", "model/vrml"},
{".vcx", "application/vnd.vcx"},
{".mts", "model/vnd.mts"},
{".vtu", "model/vnd.vtu"},
{".vis", "application/vnd.visionary"},
{".viv", "video/vnd.vivo"},
{".ccxml", "application/ccxml+xml"},
{".vxml", "application/voicexml+xml"},
{".src", "application/x-wais-source"},
{".wbxml", "application/vnd.wap.wbxml"},
{".wbmp", "image/vnd.wap.wbmp"},
{".wav", "audio/x-wav"},
{".davmount", "application/davmount+xml"},
{".woff", "application/x-font-woff"},
{".wspolicy", "application/wspolicy+xml"},
{".webp", "image/webp"},
{".wtb", "application/vnd.webturbo"},
{".wgt", "application/widget"},
{".hlp", "application/winhlp"},
{".wml", "text/vnd.wap.wml"},
{".wmls", "text/vnd.wap.wmlscript"},
{".wmlsc", "application/vnd.wap.wmlscriptc"},
{".wpd", "application/vnd.wordperfect"},
{".stf", "application/vnd.wt.stf"},
{".wsdl", "application/wsdl+xml"},
{".xbm", "image/x-xbitmap"},
{".xpm", "image/x-xpixmap"},
{".xwd", "image/x-xwindowdump"},
{".der", "application/x-x509-ca-cert"},
{".fig", "application/x-xfig"},
{".xhtml", "application/xhtml+xml"},
{".xml", "application/xml"},
{".xdf", "application/xcap-diff+xml"},
{".xenc", "application/xenc+xml"},
{".xer", "application/patch-ops-error+xml"},
{".rl", "application/resource-lists+xml"},
{".rs", "application/rls-services+xml"},
{".rld", "application/resource-lists-diff+xml"},
{".xslt", "application/xslt+xml"},
{".xop", "application/xop+xml"},
{".xpi", "application/x-xpinstall"},
{".xspf", "application/xspf+xml"},
{".xul", "application/vnd.mozilla.xul+xml"},
{".xyz", "chemical/x-xyz"},
{".yaml", "text/yaml"},
{".yang", "application/yang"},
{".yin", "application/yin+xml"},
{".zir", "application/vnd.zul"},
{".zip", "application/zip"},
{".zmm", "application/vnd.handheld-entertainment+xml"},
{".zaz", "application/vnd.zzazz.deck+xml"},
};
// Get HTTP MIME type from filename
char *GetMimeTypeFromFileName(char *filename)
{
UINT i;
UINT num = sizeof(http_mime_types) / sizeof(HTTP_MIME_TYPE);
if (filename == NULL)
{
return NULL;
}
for (i = 0;i < num;i++)
{
HTTP_MIME_TYPE *a = &http_mime_types[i];
if (EndWith(filename, a->Extension))
{
return a->MimeType;
}
}
return NULL;
}
2014-06-06 01:53:20 +04:00
// 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));
}
2014-01-04 17:00:08 +04:00
// 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);
2016-11-27 11:43:14 +03:00
StrCpy(data.SniString, sizeof(data.SniString), DDNS_SNI_VER_STRING);
recv = HttpRequestEx3(&data, NULL, UPDATE_CONNECT_TIMEOUT, UPDATE_COMM_TIMEOUT, &ret, false, NULL, NULL,
NULL, ((cert_hash != NULL && (cert_hash->Size % SHA1_SIZE) == 0) ? cert_hash->Buf : NULL),
(cert_hash != NULL ? (cert_hash->Size / SHA1_SIZE) : 0),
2014-07-11 21:06:20 +04:00
(bool *)&c->HaltFlag, 0, NULL, NULL);
2014-01-04 17:00:08 +04:00
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)
{
// Validate arguments
if (c == NULL || s == NULL)
{
return;
}
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;
2014-11-18 06:05:48 +03:00
UINT64 iphash = 0;
2014-01-04 17:00:08 +04:00
// Validate arguments
if (data == NULL)
{
return;
}
2014-11-18 06:05:48 +03:00
iphash = GetHostIPAddressListHash();
2014-01-04 17:00:08 +04:00
b = NewBuf();
GetMachineName(name, sizeof(name));
osinfo = GetOsInfo();
WriteBuf(b, name, StrLen(name));
2014-11-18 06:05:48 +03:00
WriteBufInt64(b, iphash);
2014-01-04 17:00:08 +04:00
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));
Sha0(data, b->Buf, b->Size);
2014-01-04 17:00:08 +04:00
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);
}
// 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;
// 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);
}
}
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];
UINT authtype;
POLICY *policy;
2014-11-18 06:05:48 +03:00
UINT assigned_vlan_id = 0;
2014-01-04 17:00:08 +04:00
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;
2014-07-11 21:06:20 +04:00
bool supress_return_pack_error = false;
2014-01-04 17:00:08 +04:00
IP udp_acceleration_client_ip;
UCHAR udp_acceleration_client_key[UDP_ACCELERATION_COMMON_KEY_SIZE];
UINT udp_acceleration_client_port;
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;
2014-07-11 21:06:20 +04:00
bool suppress_client_update_notification = false;
2014-01-04 17:00:08 +04:00
USER *loggedin_user_object = NULL;
FARM_MEMBER *f = NULL;
SERVER *server = NULL;
POLICY ticketed_policy;
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];
2015-10-06 14:18:00 +03:00
EAP_CLIENT *release_me_eap_client = NULL;
2014-01-04 17:00:08 +04:00
// Validate arguments
if (c == NULL)
{
return false;
}
2014-11-18 06:05:48 +03:00
GenerateMachineUniqueHash(unique2);
2014-01-04 17:00:08 +04:00
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 (c->Type == CONNECTION_TYPE_ADMIN_RPC)
{
c->Err = ERR_NO_ERROR;
}
2014-01-04 17:00:08 +04:00
if (error_detail_2 == NULL)
{
error_detail = "ServerDownloadSignature";
}
else
{
error_detail = error_detail_2;
}
2014-07-11 21:06:20 +04:00
supress_return_pack_error = true;
2014-01-04 17:00:08 +04:00
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;
}
}
// 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 = GetCedarVersionNumber();
c->ServerBuild = CEDAR_VERSION_BUILD;
2014-01-04 17:00:08 +04:00
// 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;
}
2015-01-30 16:30:34 +03:00
if (hub->ForceDisableComm)
{
Correct Spelling (#458) * spelling: accepts * spelling: account * spelling: accept * spelling: accumulate * spelling: adapter * spelling: address * spelling: additional * spelling: aggressive * spelling: adhered * spelling: allowed * spelling: ambiguous * spelling: amount * spelling: anonymous * spelling: acquisition * spelling: assemble * spelling: associated * spelling: assigns * spelling: attach * spelling: attempt * spelling: attribute * spelling: authenticate * spelling: authentication * spelling: available * spelling: bridging * spelling: cascade * spelling: cancel * spelling: check * spelling: challenge * spelling: changing * spelling: characters * spelling: cloud * spelling: compare * spelling: communication * spelling: compatible * spelling: compatibility * spelling: completion * spelling: complete * spelling: computers * spelling: configure * spelling: configuration * spelling: conformant * spelling: connection * spelling: contains * spelling: continuously * spelling: continue * spelling: convert * spelling: counters * spelling: create * spelling: created * spelling: cumulate * spelling: currently * spelling: debugging * spelling: decryption * spelling: description * spelling: default * spelling: driver * spelling: delete * spelling: destination * spelling: disabled * spelling: different * spelling: dynamically * spelling: directory * spelling: disappeared * spelling: disable * spelling: doesn't * spelling: download * spelling: dropped * spelling: enable * spelling: established * spelling: ether * spelling: except * spelling: expired * spelling: field * spelling: following * spelling: forever * spelling: firewall * spelling: first * spelling: fragment * spelling: function * spelling: gateway * spelling: identifier * spelling: identify * spelling: incoming * spelling: information * spelling: initialize * spelling: injection * spelling: inner * spelling: instead * spelling: installation * spelling: inserted * spelling: integer * spelling: interrupt * spelling: intuitive * spelling: interval * spelling: january * spelling: keybytes * spelling: know * spelling: language * spelling: length * spelling: library * spelling: listener * spelling: maintain * spelling: modified * spelling: necessary * spelling: number * spelling: obsoleted * spelling: occurred * spelling: occurring * spelling: occur * spelling: original * spelling: omittable * spelling: omit * spelling: opening * spelling: operation * spelling: packet * spelling: parameters * spelling: pointed * spelling: popupmenuopen * spelling: privilege * spelling: product * spelling: protection * spelling: promiscuous * spelling: prompt * spelling: query * spelling: random * spelling: reconnection * spelling: revocation * spelling: received * spelling: red hat * spelling: registry * spelling: release * spelling: retrieve
2018-05-17 00:47:10 +03:00
// Communication function is disabled
2015-01-30 16:30:34 +03:00
FreePack(p);
c->Err = ERR_SERVER_CANT_ACCEPT;
error_detail = "ERR_COMM_DISABLED";
ReleaseHub(hub);
goto CLEANUP;
}
2014-03-20 00:45:05 +04:00
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;
}
}
}
2014-01-04 17:00:08 +04:00
Lock(hub->lock);
{
UINT cert_size = 0;
void *cert_buf = NULL;
USER *user;
USERGROUP *group;
char plain_password[MAX_PASSWORD_LEN + 1];
2014-11-18 06:05:48 +03:00
RADIUS_LOGIN_OPTION radius_login_opt;
2014-01-04 17:00:08 +04:00
if (hub->Halt || hub->Offline)
{
// HUB is off-line
FreePack(p);
Unlock(hub->lock);
ReleaseHub(hub);
c->Err = ERR_HUB_STOPPING;
goto CLEANUP;
}
2014-11-18 06:05:48 +03:00
Zero(&radius_login_opt, sizeof(radius_login_opt));
if (hub->Option != NULL)
{
radius_login_opt.In_CheckVLanId = hub->Option->AssignVLanIdByRadiusAttribute;
2015-10-06 14:18:00 +03:00
radius_login_opt.In_DenyNoVlanId = hub->Option->DenyAllRadiusLoginWithNoVlanAssign;
2016-11-27 11:43:14 +03:00
if (hub->Option->UseHubNameAsRadiusNasId)
{
StrCpy(radius_login_opt.NasId, sizeof(radius_login_opt.NasId), hubname);
}
2014-11-18 06:05:48 +03:00
}
2014-01-04 17:00:08 +04:00
// 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;
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];
2015-10-06 14:18:00 +03:00
UINT64 ptr;
ptr = PackGetInt64(p, "release_me_eap_client");
if (ptr != 0)
{
release_me_eap_client = (EAP_CLIENT *)ptr;
}
2014-01-04 17:00:08 +04:00
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;
case AUTHTYPE_OPENVPN_CERT:
authtype_str = _UU("LH_AUTH_OPENVPN_CERT");
break;
2014-01-04 17:00:08 +04:00
}
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");
Correct Spelling (#458) * spelling: accepts * spelling: account * spelling: accept * spelling: accumulate * spelling: adapter * spelling: address * spelling: additional * spelling: aggressive * spelling: adhered * spelling: allowed * spelling: ambiguous * spelling: amount * spelling: anonymous * spelling: acquisition * spelling: assemble * spelling: associated * spelling: assigns * spelling: attach * spelling: attempt * spelling: attribute * spelling: authenticate * spelling: authentication * spelling: available * spelling: bridging * spelling: cascade * spelling: cancel * spelling: check * spelling: challenge * spelling: changing * spelling: characters * spelling: cloud * spelling: compare * spelling: communication * spelling: compatible * spelling: compatibility * spelling: completion * spelling: complete * spelling: computers * spelling: configure * spelling: configuration * spelling: conformant * spelling: connection * spelling: contains * spelling: continuously * spelling: continue * spelling: convert * spelling: counters * spelling: create * spelling: created * spelling: cumulate * spelling: currently * spelling: debugging * spelling: decryption * spelling: description * spelling: default * spelling: driver * spelling: delete * spelling: destination * spelling: disabled * spelling: different * spelling: dynamically * spelling: directory * spelling: disappeared * spelling: disable * spelling: doesn't * spelling: download * spelling: dropped * spelling: enable * spelling: established * spelling: ether * spelling: except * spelling: expired * spelling: field * spelling: following * spelling: forever * spelling: firewall * spelling: first * spelling: fragment * spelling: function * spelling: gateway * spelling: identifier * spelling: identify * spelling: incoming * spelling: information * spelling: initialize * spelling: injection * spelling: inner * spelling: instead * spelling: installation * spelling: inserted * spelling: integer * spelling: interrupt * spelling: intuitive * spelling: interval * spelling: january * spelling: keybytes * spelling: know * spelling: language * spelling: length * spelling: library * spelling: listener * spelling: maintain * spelling: modified * spelling: necessary * spelling: number * spelling: obsoleted * spelling: occurred * spelling: occurring * spelling: occur * spelling: original * spelling: omittable * spelling: omit * spelling: opening * spelling: operation * spelling: packet * spelling: parameters * spelling: pointed * spelling: popupmenuopen * spelling: privilege * spelling: product * spelling: protection * spelling: promiscuous * spelling: prompt * spelling: query * spelling: random * spelling: reconnection * spelling: revocation * spelling: received * spelling: red hat * spelling: registry * spelling: release * spelling: retrieve
2018-05-17 00:47:10 +03:00
Add(o, "anonymous");
2014-01-04 17:00:08 +04:00
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;
2014-03-20 00:45:05 +04:00
if (GetGlobalServerFlag(GSF_DISABLE_RADIUS_AUTH) != 0)
2014-01-04 17:00:08 +04:00
{
fail_ext_user_auth = true;
}
if (fail_ext_user_auth == false)
{
2014-11-18 06:05:48 +03:00
auth_ret = SamAuthUserByPlainPassword(c, hub, username, plain_password, false, mschap_v2_server_response_20, &radius_login_opt);
2014-01-04 17:00:08 +04:00
}
if (auth_ret && pol == NULL)
{
pol = SamGetUserPolicy(hub, username);
}
}
2014-03-20 00:45:05 +04:00
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)
{
2014-11-18 06:05:48 +03:00
auth_ret = SamAuthUserByPlainPassword(c, hub, username, plain_password, true, mschap_v2_server_response_20, &radius_login_opt);
2014-03-20 00:45:05 +04:00
if (auth_ret && pol == NULL)
{
pol = SamGetUserPolicy(hub, "*");
}
}
}
}
2014-01-04 17:00:08 +04:00
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:
2014-03-20 12:05:40 +04:00
if (GetGlobalServerFlag(GSF_DISABLE_CERT_AUTH) == 0)
2014-03-20 00:45:05 +04:00
{
// 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;
}
2014-01-04 17:00:08 +04:00
break;
case AUTHTYPE_OPENVPN_CERT:
// For OpenVPN; mostly same as CLIENT_AUTHTYPE_CERT, but without
// signature verification, because it was already performed during TLS handshake.
if (c->IsInProc)
{
// 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))
{
BUF *b = NewBuf();
X *x;
WriteBuf(b, cert_buf, cert_size);
x = BufToX(b, false);
if (x != NULL && x->is_compatible_bit)
{
Debug("Got to SamAuthUserByCert %s\n", username); // XXX
// Check whether the certificate is valid.
auth_ret = SamAuthUserByCert(hub, username, x);
if (auth_ret)
{
// Copy the certificate
c->ClientX = CloneX(x);
}
}
FreeX(x);
FreeBuf(b);
}
Free(cert_buf);
}
}
else
{
// OpenVPN certificate authentication cannot be used directly by external clients
Unlock(hub->lock);
ReleaseHub(hub);
FreePack(p);
c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
goto CLEANUP;
}
break;
2014-01-04 17:00:08 +04:00
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);
2014-11-18 06:05:48 +03:00
// Check the assigned VLAN ID
2015-10-06 14:18:00 +03:00
if (radius_login_opt.Out_IsRadiusLogin)
2014-11-18 06:05:48 +03:00
{
2015-10-06 14:18:00 +03:00
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;
}
}
2014-11-18 06:05:48 +03:00
}
2014-01-04 17:00:08 +04:00
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;
}
}
2014-10-03 19:09:23 +04:00
if (use_encrypt == false && c->FirstSock->IsReverseAcceptedSocket)
{
// On VPN Azure, SSL encryption is mandated.
use_encrypt = true;
}
2014-01-04 17:00:08 +04:00
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);
2014-11-18 06:05:48 +03:00
// VLAN ID
if (assigned_vlan_id != 0)
{
if (policy->VLanId == 0)
2014-11-18 06:05:48 +03:00
{
policy->VLanId = assigned_vlan_id;
2014-11-18 06:05:48 +03:00
}
}
2014-01-04 17:00:08 +04:00
// 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;
2015-02-02 12:54:00 +03:00
IPToStr(s->ClientIP, sizeof(s->ClientIP), &c->ClientIp);
2014-01-04 17:00:08 +04:00
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)
{
2015-01-30 16:30:34 +03:00
bool no_nat_t = false;
2014-01-04 17:00:08 +04:00
// Initialize the UDP acceleration function
2015-01-30 16:30:34 +03:00
s->UdpAccel = NewUdpAccel(c->Cedar, (c->FirstSock->IsRUDPSocket ? NULL : &c->FirstSock->LocalIP), false, c->FirstSock->IsRUDPSocket, no_nat_t);
2014-01-04 17:00:08 +04:00
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;
s->UseCompress = use_compress;
s->HalfConnection = half_connection;
s->Timeout = timeout;
s->QoS = qos;
s->NoReconnectToSession = no_reconnect_to_session;
s->VLanId = policy->VLanId;
2014-01-04 17:00:08 +04:00
// 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);
2014-07-11 21:06:20 +04:00
// Suppress client update notification flag
if (hub->Option != NULL)
{
suppress_client_update_notification = hub->Option->SuppressClientUpdateNotification;
}
2014-01-04 17:00:08 +04:00
}
Unlock(hub->lock);
// Send a Welcome packet to the client
p = PackWelcome(s);
2014-07-11 21:06:20 +04:00
PackAddBool(p, "suppress_client_update_notification", suppress_client_update_notification);
src/Cedar/Protocol, src/Cedar/Session: cleanup, remove unused functions, variables, resolve possible null pointer dereference found by cppcheck [src/Cedar/Protocol.c:3138] -> [src/Cedar/Protocol.c:3071]: (warning) Either the condition 's!=NULL' is redundant or there is possible null pointer dereference: s. [src/Cedar/Protocol.c:916]: (style) Variable 'save' is assigned a value that is never used. [src/Cedar/Protocol.c:6242]: (style) Variable 'size' is assigned a value that is never used. [src/Cedar/Protocol.c:778]: (style) Variable 'old_disable' is assigned a value that is never used. [src/Cedar/Protocol.c:1021]: (style) Variable 'save' is assigned a value that is never used. [src/Cedar/Protocol.c:3708]: (style) Variable 'is_vgc' is assigned a value that is never used. [src/Cedar/Protocol.c:5785]: (style) Variable 's' is assigned a value that is never used. [src/Cedar/Protocol.c:6164]: (style) The function 'SocksConnectEx' is never used. [src/Cedar/Protocol.c:907]: (style) The function 'CompareNodeInfo' is never used. [src/Cedar/Protocol.c:6968]: (style) The function 'ProxyConnect' is never used. [src/Cedar/Protocol.c:3986]: (style) The function 'SecureDelete' is never used. [src/Cedar/Protocol.c:4042]: (style) The function 'SecureEnum' is never used. [src/Cedar/Protocol.c:4127]: (style) The function 'SecureWrite' is never used. [src/Cedar/Protocol.c:6463]: (style) The function 'SocksConnect' is never used. [src/Cedar/Protocol.c:7185]: (style) The function 'TcpConnectEx2' is never used. [src/Cedar/Protocol.c:7206]: (style) The function 'TcpIpConnect' is never used.
2018-11-10 12:18:18 +03:00
if (s != NULL && s->InProcMode)
2014-01-04 17:00:08 +04:00
{
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);
}
2014-03-21 09:07:45 +04:00
tmpsize = UniStrSize(winver_msg_client) + UniStrSize(winver_msg_server) + UniStrSize(msg) + (16000 + 3000) * sizeof(wchar_t);
2014-01-04 17:00:08 +04:00
tmp = ZeroMalloc(tmpsize);
if (IsURLMsg(msg, NULL, 0) == false)
{
2014-03-20 00:45:05 +04:00
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;
2014-03-21 09:07:45 +04:00
UINT tmp2_size = 2400 * sizeof(wchar_t);
2014-03-20 00:45:05 +04:00
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
2014-03-21 09:07:45 +04:00
tmp2 = ZeroMalloc(tmp2_size);
2014-03-20 00:45:05 +04:00
UniFormat(tmp2, tmp2_size, _UU(c->ClientBuild >= 9428 ? "NATT_MSG" : "NATT_MSG2"), local_name);
UniStrCat(tmp, tmpsize, tmp2);
Free(tmp2);
}
2014-01-04 17:00:08 +04:00
{
2014-03-20 00:45:05 +04:00
if (GetGlobalServerFlag(GSF_SHOW_OSS_MSG) != 0)
2014-01-04 17:00:08 +04:00
{
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);
// 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);
2014-11-18 06:05:48 +03:00
if (s->VLanId != 0)
{
HLog(hub, "LH_VLAN_ID", s->Name, s->VLanId);
}
2014-01-04 17:00:08 +04:00
}
// 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->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;
}
// 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);
// Return a success result
p = PackError(ERR_NO_ERROR);
PackAddInt(p, "direction", direction);
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
2014-07-11 21:06:20 +04:00
if (supress_return_pack_error == false)
{
p = PackError(c->Err);
PackAddBool(p, "no_save_password", no_save_password);
HttpServerSend(c->FirstSock, p);
FreePack(p);
}
2014-01-04 17:00:08 +04:00
FreePack(HttpServerRecv(c->FirstSock));
2014-07-11 21:06:20 +04:00
2014-01-04 17:00:08 +04:00
SleepThread(25);
SLog(c->Cedar, "LS_CONNECTION_ERROR", c->Name, GetUniErrorStr(c->Err), c->Err);
2015-10-06 14:18:00 +03:00
if (release_me_eap_client != NULL)
{
ReleaseEapClient(release_me_eap_client);
}
2014-01-04 17:00:08 +04:00
return ret;
}
// Create a Node information
void CreateNodeInfo(NODE_INFO *info, CONNECTION *c)
{
SESSION *s;
OS_INFO *os;
char *product_id;
IP ip;
// 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
2018-07-30 10:03:07 +03:00
s = ClientConnectGetSocket(c, true);
2014-01-04 17:00:08 +04:00
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
2018-07-30 10:03:07 +03:00
if (StartSSLEx(s, NULL, NULL, 0, c->ServerName) == false)
2014-01-04 17:00:08 +04:00
{
// 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;
}
// 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;
2018-08-12 05:07:39 +03:00
2014-01-04 17:00:08 +04:00
// 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");
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"
);
}
// 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)
{
2016-11-27 11:43:14 +03:00
Copy(sign, ss->Signature, sizeof(ss->Signature));
2014-01-04 17:00:08 +04:00
*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
Correct Spelling (#458) * spelling: accepts * spelling: account * spelling: accept * spelling: accumulate * spelling: adapter * spelling: address * spelling: additional * spelling: aggressive * spelling: adhered * spelling: allowed * spelling: ambiguous * spelling: amount * spelling: anonymous * spelling: acquisition * spelling: assemble * spelling: associated * spelling: assigns * spelling: attach * spelling: attempt * spelling: attribute * spelling: authenticate * spelling: authentication * spelling: available * spelling: bridging * spelling: cascade * spelling: cancel * spelling: check * spelling: challenge * spelling: changing * spelling: characters * spelling: cloud * spelling: compare * spelling: communication * spelling: compatible * spelling: compatibility * spelling: completion * spelling: complete * spelling: computers * spelling: configure * spelling: configuration * spelling: conformant * spelling: connection * spelling: contains * spelling: continuously * spelling: continue * spelling: convert * spelling: counters * spelling: create * spelling: created * spelling: cumulate * spelling: currently * spelling: debugging * spelling: decryption * spelling: description * spelling: default * spelling: driver * spelling: delete * spelling: destination * spelling: disabled * spelling: different * spelling: dynamically * spelling: directory * spelling: disappeared * spelling: disable * spelling: doesn't * spelling: download * spelling: dropped * spelling: enable * spelling: established * spelling: ether * spelling: except * spelling: expired * spelling: field * spelling: following * spelling: forever * spelling: firewall * spelling: first * spelling: fragment * spelling: function * spelling: gateway * spelling: identifier * spelling: identify * spelling: incoming * spelling: information * spelling: initialize * spelling: injection * spelling: inner * spelling: instead * spelling: installation * spelling: inserted * spelling: integer * spelling: interrupt * spelling: intuitive * spelling: interval * spelling: january * spelling: keybytes * spelling: know * spelling: language * spelling: length * spelling: library * spelling: listener * spelling: maintain * spelling: modified * spelling: necessary * spelling: number * spelling: obsoleted * spelling: occurred * spelling: occurring * spelling: occur * spelling: original * spelling: omittable * spelling: omit * spelling: opening * spelling: operation * spelling: packet * spelling: parameters * spelling: pointed * spelling: popupmenuopen * spelling: privilege * spelling: product * spelling: protection * spelling: promiscuous * spelling: prompt * spelling: query * spelling: random * spelling: reconnection * spelling: revocation * spelling: received * spelling: red hat * spelling: registry * spelling: release * spelling: retrieve
2018-05-17 00:47:10 +03:00
p->Ok = p->CheckCertProc(p->Connection->Session, p->Connection, p->ServerX, &p->Expired);
2014-01-04 17:00:08 +04:00
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)
{
Correct Spelling (#458) * spelling: accepts * spelling: account * spelling: accept * spelling: accumulate * spelling: adapter * spelling: address * spelling: additional * spelling: aggressive * spelling: adhered * spelling: allowed * spelling: ambiguous * spelling: amount * spelling: anonymous * spelling: acquisition * spelling: assemble * spelling: associated * spelling: assigns * spelling: attach * spelling: attempt * spelling: attribute * spelling: authenticate * spelling: authentication * spelling: available * spelling: bridging * spelling: cascade * spelling: cancel * spelling: check * spelling: challenge * spelling: changing * spelling: characters * spelling: cloud * spelling: compare * spelling: communication * spelling: compatible * spelling: compatibility * spelling: completion * spelling: complete * spelling: computers * spelling: configure * spelling: configuration * spelling: conformant * spelling: connection * spelling: contains * spelling: continuously * spelling: continue * spelling: convert * spelling: counters * spelling: create * spelling: created * spelling: cumulate * spelling: currently * spelling: debugging * spelling: decryption * spelling: description * spelling: default * spelling: driver * spelling: delete * spelling: destination * spelling: disabled * spelling: different * spelling: dynamically * spelling: directory * spelling: disappeared * spelling: disable * spelling: doesn't * spelling: download * spelling: dropped * spelling: enable * spelling: established * spelling: ether * spelling: except * spelling: expired * spelling: field * spelling: following * spelling: forever * spelling: firewall * spelling: first * spelling: fragment * spelling: function * spelling: gateway * spelling: identifier * spelling: identify * spelling: incoming * spelling: information * spelling: initialize * spelling: injection * spelling: inner * spelling: instead * spelling: installation * spelling: inserted * spelling: integer * spelling: interrupt * spelling: intuitive * spelling: interval * spelling: january * spelling: keybytes * spelling: know * spelling: language * spelling: length * spelling: library * spelling: listener * spelling: maintain * spelling: modified * spelling: necessary * spelling: number * spelling: obsoleted * spelling: occurred * spelling: occurring * spelling: occur * spelling: original * spelling: omittable * spelling: omit * spelling: opening * spelling: operation * spelling: packet * spelling: parameters * spelling: pointed * spelling: popupmenuopen * spelling: privilege * spelling: product * spelling: protection * spelling: promiscuous * spelling: prompt * spelling: query * spelling: random * spelling: reconnection * spelling: revocation * spelling: received * spelling: red hat * spelling: registry * spelling: release * spelling: retrieve
2018-05-17 00:47:10 +03:00
*expired = p->Expired;
2014-01-04 17:00:08 +04:00
}
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];
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->Account == NULL || ! c->Session->Account->RetryOnServerCert))
2014-01-04 17:00:08 +04:00
{
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;
}
}
2014-07-11 21:06:20 +04:00
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
}
}
2014-01-04 17:00:08 +04:00
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");
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);
}
}
sess->EnableBulkOnRUDP = false;
sess->EnableHMacOnBulkOfRUDP = false;
if (s->IsRUDPSocket && s->BulkRecvKey != NULL && s->BulkSendKey != NULL)
2014-01-04 17:00:08 +04:00
{
// 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"));
#ifdef OS_UNIX
// Set TUN up if session has NicDownOnDisconnect set
if (c->Session->NicDownOnDisconnect != NULL)
{
UnixVLanSetState(c->Session->ClientOption->DeviceName, true);
}
#endif
2014-01-04 17:00:08 +04:00
// 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;
}
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_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) \
PackAddBool(p, "policy:" name, y->value == false ? 0 : 1)
2014-01-04 17:00:08 +04:00
#define PACK_ADD_POLICY_UINT(name, value) \
PackAddInt(p, "policy:" name, y->value)
#define PACK_GET_POLICY_BOOL(name, value) \
y->value = (PackGetBool(p, "policy:" name))
2014-01-04 17:00:08 +04:00
#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);
(void)HttpClientSend(c->FirstSock, p);
2014-01-04 17:00:08 +04:00
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))
{
2016-11-27 11:43:14 +03:00
p = PackLoginWithCert(o->HubName, a->Username, x, sign, x->bits / 8);
2014-01-04 17:00:08 +04:00
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);
}
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);
// 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)
{
2014-06-06 01:53:20 +04:00
IP my_ip;
Zero(&my_ip, sizeof(my_ip));
2014-01-04 17:00:08 +04:00
PackAddBool(p, "use_udp_acceleration", true);
2014-06-06 01:53:20 +04:00
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);
2014-01-04 17:00:08 +04:00
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;
2014-07-11 21:06:20 +04:00
char *vpn_http_target = HTTP_VPN_TARGET2;
2014-01-04 17:00:08 +04:00
// Validate arguments
if (c == NULL)
{
return false;
}
server = c->Cedar->Server;
s = c->FirstSock;
while (true)
{
2015-01-30 16:30:34 +03:00
bool not_found_error = false;
2014-01-04 17:00:08 +04:00
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;
if (c->IsJsonRpc)
{
c->Err = ERR_DISCONNECTED;
}
2014-01-04 17:00:08 +04:00
return false;
}
// Interpret
if (StrCmpi(h->Method, "POST") == 0)
{
// Receive the data since it's POST
data_size = GetContentLength(h);
if (server->DisableJsonRpcWebApi == false)
{
if (StrCmpi(h->Target, "/api") == 0 || StrCmpi(h->Target, "/api/") == 0)
{
c->IsJsonRpc = true;
c->Type = CONNECTION_TYPE_ADMIN_RPC;
JsonRpcProcPost(c, s, h, data_size);
FreeHttpHeader(h);
if (c->JsonRpcAuthed)
{
num = 0;
}
continue;
}
else if (StartWith(h->Target, "/admin"))
{
c->IsJsonRpc = true;
c->Type = CONNECTION_TYPE_ADMIN_RPC;
AdminWebProcPost(c, s, h, data_size, h->Target);
FreeHttpHeader(h);
if (c->JsonRpcAuthed)
{
num = 0;
}
continue;
}
}
2014-01-04 17:00:08 +04:00
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
2015-01-30 16:30:34 +03:00
if ((StrCmpi(h->Target, vpn_http_target) != 0) || not_found_error)
2014-01-04 17:00:08 +04:00
{
// 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))
2018-09-28 16:39:38 +03:00
|| ((data_size >= SizeOfWaterMark()) && Cmp(data, WaterMark, SizeOfWaterMark()) == 0))
2014-01-04 17:00:08 +04:00
{
// 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, "OPTIONS") == 0)
{
if (server->DisableJsonRpcWebApi == false)
{
if (StrCmpi(h->Target, "/api") == 0 || StrCmpi(h->Target, "/api/") == 0 || StartWith(h->Target, "/admin"))
{
c->IsJsonRpc = true;
c->Type = CONNECTION_TYPE_ADMIN_RPC;
JsonRpcProcOptions(c, s, h, h->Target);
FreeHttpHeader(h);
num = 0;
continue;
}
}
}
2014-01-04 17:00:08 +04:00
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_OTHER;
2014-01-04 17:00:08 +04:00
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
2014-07-11 21:06:20 +04:00
if (StrCmpi(h->Method, "GET") != 0 && StrCmpi(h->Method, "HEAD") != 0
&& StrCmpi(h->Method, "POST") != 0)
2014-01-04 17:00:08 +04:00
{
// 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
*error_detail_str = "HTTP_ROOT";
{
// Other than free version
HttpSendForbidden(c->FirstSock, h->Target, "");
2014-01-04 17:00:08 +04:00
}
}
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)
{
if (server->DisableJsonRpcWebApi == false)
{
if (StartWith(h->Target, "/api?") || StartWith(h->Target, "/api/") || StrCmpi(h->Target, "/api") == 0)
{
c->IsJsonRpc = true;
c->Type = CONNECTION_TYPE_ADMIN_RPC;
JsonRpcProcGet(c, s, h, h->Target);
if (c->JsonRpcAuthed)
{
num = 0;
}
FreeHttpHeader(h);
continue;
}
else if (StartWith(h->Target, "/admin"))
{
c->IsJsonRpc = true;
c->Type = CONNECTION_TYPE_ADMIN_RPC;
AdminWebProcGet(c, s, h, h->Target);
if (c->JsonRpcAuthed)
{
num = 0;
}
FreeHttpHeader(h);
continue;
}
}
}
2014-01-04 17:00:08 +04:00
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;
2014-07-11 21:06:20 +04:00
char ip_str[128];
2014-01-04 17:00:08 +04:00
// Validate arguments
if (s == NULL)
{
return false;
}
2014-07-11 21:06:20 +04:00
IPToStr(ip_str, sizeof(ip_str), &s->RemoteIP);
2014-01-04 17:00:08 +04:00
h = NewHttpHeader("POST", HTTP_VPN_TARGET2, "HTTP/1.1");
2014-07-11 21:06:20 +04:00
AddHttpValue(h, NewHttpValue("Host", ip_str));
2014-01-04 17:00:08 +04:00
AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE3));
AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
2014-07-11 21:06:20 +04:00
2014-01-04 17:00:08 +04:00
// 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
2018-07-30 10:03:07 +03:00
s = ClientConnectGetSocket(c, false);
2014-01-04 17:00:08 +04:00
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
2018-07-30 10:03:07 +03:00
if (StartSSLEx(s, x, k, 0, c->ServerName) == false)
2014-01-04 17:00:08 +04:00
{
// 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
2018-07-30 10:03:07 +03:00
SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect)
2014-01-04 17:00:08 +04:00
{
SOCK *s = NULL;
CLIENT_OPTION *o;
2018-10-30 17:11:16 +03:00
WPC_CONNECT w;
2014-01-04 17:00:08 +04:00
wchar_t tmp[MAX_SIZE];
SESSION *sess;
volatile bool *cancel_flag = NULL;
void *hWnd;
UINT nat_t_err = 0;
Correct Spelling (#458) * spelling: accepts * spelling: account * spelling: accept * spelling: accumulate * spelling: adapter * spelling: address * spelling: additional * spelling: aggressive * spelling: adhered * spelling: allowed * spelling: ambiguous * spelling: amount * spelling: anonymous * spelling: acquisition * spelling: assemble * spelling: associated * spelling: assigns * spelling: attach * spelling: attempt * spelling: attribute * spelling: authenticate * spelling: authentication * spelling: available * spelling: bridging * spelling: cascade * spelling: cancel * spelling: check * spelling: challenge * spelling: changing * spelling: characters * spelling: cloud * spelling: compare * spelling: communication * spelling: compatible * spelling: compatibility * spelling: completion * spelling: complete * spelling: computers * spelling: configure * spelling: configuration * spelling: conformant * spelling: connection * spelling: contains * spelling: continuously * spelling: continue * spelling: convert * spelling: counters * spelling: create * spelling: created * spelling: cumulate * spelling: currently * spelling: debugging * spelling: decryption * spelling: description * spelling: default * spelling: driver * spelling: delete * spelling: destination * spelling: disabled * spelling: different * spelling: dynamically * spelling: directory * spelling: disappeared * spelling: disable * spelling: doesn't * spelling: download * spelling: dropped * spelling: enable * spelling: established * spelling: ether * spelling: except * spelling: expired * spelling: field * spelling: following * spelling: forever * spelling: firewall * spelling: first * spelling: fragment * spelling: function * spelling: gateway * spelling: identifier * spelling: identify * spelling: incoming * spelling: information * spelling: initialize * spelling: injection * spelling: inner * spelling: instead * spelling: installation * spelling: inserted * spelling: integer * spelling: interrupt * spelling: intuitive * spelling: interval * spelling: january * spelling: keybytes * spelling: know * spelling: language * spelling: length * spelling: library * spelling: listener * spelling: maintain * spelling: modified * spelling: necessary * spelling: number * spelling: obsoleted * spelling: occurred * spelling: occurring * spelling: occur * spelling: original * spelling: omittable * spelling: omit * spelling: opening * spelling: operation * spelling: packet * spelling: parameters * spelling: pointed * spelling: popupmenuopen * spelling: privilege * spelling: product * spelling: protection * spelling: promiscuous * spelling: prompt * spelling: query * spelling: random * spelling: reconnection * spelling: revocation * spelling: received * spelling: red hat * spelling: registry * spelling: release * spelling: retrieve
2018-05-17 00:47:10 +03:00
bool is_additional_rudp_session = false;
2014-01-04 17:00:08 +04:00
UCHAR uc = 0;
2016-03-06 17:16:01 +03:00
IP ret_ip;
2014-01-04 17:00:08 +04:00
// Validate arguments
if (c == NULL)
{
return NULL;
}
2016-03-06 17:16:01 +03:00
Zero(&ret_ip, sizeof(IP));
2018-10-30 17:11:16 +03:00
Zero(&w, sizeof(w));
2016-03-06 17:16:01 +03:00
2014-01-04 17:00:08 +04:00
sess = c->Session;
if (sess != NULL)
{
cancel_flag = &sess->CancelConnect;
Correct Spelling (#458) * spelling: accepts * spelling: account * spelling: accept * spelling: accumulate * spelling: adapter * spelling: address * spelling: additional * spelling: aggressive * spelling: adhered * spelling: allowed * spelling: ambiguous * spelling: amount * spelling: anonymous * spelling: acquisition * spelling: assemble * spelling: associated * spelling: assigns * spelling: attach * spelling: attempt * spelling: attribute * spelling: authenticate * spelling: authentication * spelling: available * spelling: bridging * spelling: cascade * spelling: cancel * spelling: check * spelling: challenge * spelling: changing * spelling: characters * spelling: cloud * spelling: compare * spelling: communication * spelling: compatible * spelling: compatibility * spelling: completion * spelling: complete * spelling: computers * spelling: configure * spelling: configuration * spelling: conformant * spelling: connection * spelling: contains * spelling: continuously * spelling: continue * spelling: convert * spelling: counters * spelling: create * spelling: created * spelling: cumulate * spelling: currently * spelling: debugging * spelling: decryption * spelling: description * spelling: default * spelling: driver * spelling: delete * spelling: destination * spelling: disabled * spelling: different * spelling: dynamically * spelling: directory * spelling: disappeared * spelling: disable * spelling: doesn't * spelling: download * spelling: dropped * spelling: enable * spelling: established * spelling: ether * spelling: except * spelling: expired * spelling: field * spelling: following * spelling: forever * spelling: firewall * spelling: first * spelling: fragment * spelling: function * spelling: gateway * spelling: identifier * spelling: identify * spelling: incoming * spelling: information * spelling: initialize * spelling: injection * spelling: inner * spelling: instead * spelling: installation * spelling: inserted * spelling: integer * spelling: interrupt * spelling: intuitive * spelling: interval * spelling: january * spelling: keybytes * spelling: know * spelling: language * spelling: length * spelling: library * spelling: listener * spelling: maintain * spelling: modified * spelling: necessary * spelling: number * spelling: obsoleted * spelling: occurred * spelling: occurring * spelling: occur * spelling: original * spelling: omittable * spelling: omit * spelling: opening * spelling: operation * spelling: packet * spelling: parameters * spelling: pointed * spelling: popupmenuopen * spelling: privilege * spelling: product * spelling: protection * spelling: promiscuous * spelling: prompt * spelling: query * spelling: random * spelling: reconnection * spelling: revocation * spelling: received * spelling: red hat * spelling: registry * spelling: release * spelling: retrieve
2018-05-17 00:47:10 +03:00
is_additional_rudp_session = sess->IsRUDPSession;
2014-01-04 17:00:08 +04:00
}
hWnd = c->hWndForUI;
o = c->Session->ClientOption;
2016-03-06 17:16:01 +03:00
if (additional_connect)
{
if (sess != NULL)
{
Copy(&ret_ip, &sess->ServerIP_CacheForNextConnect, sizeof(IP));
}
}
2014-01-04 17:00:08 +04:00
if (c->RestoreServerNameAndPort && additional_connect)
{
// Restore to the original server name and port number
c->RestoreServerNameAndPort = false;
2016-03-06 17:16:01 +03:00
if (StrCmpi(c->ServerName, o->Hostname) != 0)
{
StrCpy(c->ServerName, sizeof(c->ServerName), o->Hostname);
Zero(&ret_ip, sizeof(IP));
}
2014-01-04 17:00:08 +04:00
c->ServerPort = o->Port;
}
2018-10-30 17:11:16 +03:00
StrCpy(w.HostName, sizeof(w.HostName), c->ServerName);
w.Port = c->ServerPort;
StrCpy(w.ProxyHostName, sizeof(w.ProxyHostName), o->ProxyName);
w.ProxyPort = o->ProxyPort;
StrCpy(w.ProxyUsername, sizeof(w.ProxyUsername), o->ProxyUsername);
StrCpy(w.ProxyPassword, sizeof(w.ProxyPassword), o->ProxyPassword);
StrCpy(w.CustomHttpHeader, sizeof(w.CustomHttpHeader), w.CustomHttpHeader);
2014-01-04 17:00:08 +04:00
switch (o->ProxyType)
{
case PROXY_DIRECT: // TCP/IP
2018-10-30 17:11:16 +03:00
UniFormat(tmp, sizeof(tmp), _UU("STATUS_4"), w.HostName);
2014-01-04 17:00:08 +04:00
PrintStatus(sess, tmp);
2018-10-30 17:11:16 +03:00
2014-01-04 17:00:08 +04:00
// 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
2018-10-30 17:11:16 +03:00
s = TcpIpConnectEx(w.HostName, w.Port,
Correct Spelling (#458) * spelling: accepts * spelling: account * spelling: accept * spelling: accumulate * spelling: adapter * spelling: address * spelling: additional * spelling: aggressive * spelling: adhered * spelling: allowed * spelling: ambiguous * spelling: amount * spelling: anonymous * spelling: acquisition * spelling: assemble * spelling: associated * spelling: assigns * spelling: attach * spelling: attempt * spelling: attribute * spelling: authenticate * spelling: authentication * spelling: available * spelling: bridging * spelling: cascade * spelling: cancel * spelling: check * spelling: challenge * spelling: changing * spelling: characters * spelling: cloud * spelling: compare * spelling: communication * spelling: compatible * spelling: compatibility * spelling: completion * spelling: complete * spelling: computers * spelling: configure * spelling: configuration * spelling: conformant * spelling: connection * spelling: contains * spelling: continuously * spelling: continue * spelling: convert * spelling: counters * spelling: create * spelling: created * spelling: cumulate * spelling: currently * spelling: debugging * spelling: decryption * spelling: description * spelling: default * spelling: driver * spelling: delete * spelling: destination * spelling: disabled * spelling: different * spelling: dynamically * spelling: directory * spelling: disappeared * spelling: disable * spelling: doesn't * spelling: download * spelling: dropped * spelling: enable * spelling: established * spelling: ether * spelling: except * spelling: expired * spelling: field * spelling: following * spelling: forever * spelling: firewall * spelling: first * spelling: fragment * spelling: function * spelling: gateway * spelling: identifier * spelling: identify * spelling: incoming * spelling: information * spelling: initialize * spelling: injection * spelling: inner * spelling: instead * spelling: installation * spelling: inserted * spelling: integer * spelling: interrupt * spelling: intuitive * spelling: interval * spelling: january * spelling: keybytes * spelling: know * spelling: language * spelling: length * spelling: library * spelling: listener * spelling: maintain * spelling: modified * spelling: necessary * spelling: number * spelling: obsoleted * spelling: occurred * spelling: occurring * spelling: occur * spelling: original * spelling: omittable * spelling: omit * spelling: opening * spelling: operation * spelling: packet * spelling: parameters * spelling: pointed * spelling: popupmenuopen * spelling: privilege * spelling: product * spelling: protection * spelling: promiscuous * spelling: prompt * spelling: query * spelling: random * spelling: reconnection * spelling: revocation * spelling: received * spelling: red hat * spelling: registry * spelling: release * spelling: retrieve
2018-05-17 00:47:10 +03:00
(bool *)cancel_flag, hWnd, &nat_t_err, (additional_connect ? (!is_additional_rudp_session) : false),
2018-07-30 10:03:07 +03:00
true, &ret_ip);
2014-01-04 17:00:08 +04:00
}
}
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
2018-10-30 17:11:16 +03:00
UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), w.HostName, w.ProxyHostName);
2014-01-04 17:00:08 +04:00
PrintStatus(sess, tmp);
// Proxy connection
s = ProxyConnectEx3(c, &w, additional_connect, (bool *)cancel_flag, hWnd, 0);
2014-01-04 17:00:08 +04:00
if (s == NULL)
{
// Connection failure
return NULL;
}
break;
2018-10-30 17:11:16 +03:00
case PROXY_SOCKS: // SOCKS4 Proxy
UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), w.HostName, w.ProxyHostName);
PrintStatus(sess, tmp);
2014-01-04 17:00:08 +04:00
2018-10-30 17:11:16 +03:00
// SOCKS4 connection
s = SocksConnectEx2(c, w.ProxyHostName, w.ProxyPort,
w.HostName, w.Port, w.ProxyUsername, additional_connect, (bool *)cancel_flag,
hWnd, 0, &ret_ip);
if (s == NULL)
{
// Connection failure
return NULL;
}
break;
2014-01-04 17:00:08 +04:00
2018-10-30 17:11:16 +03:00
case PROXY_SOCKS5: // SOCKS5 Proxy
UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), w.HostName, w.ProxyHostName);
2014-01-04 17:00:08 +04:00
PrintStatus(sess, tmp);
2018-10-30 17:11:16 +03:00
// SOCKS5 connection
s = Socks5Connect(c, &w, additional_connect, (bool *)cancel_flag, hWnd, 0, &ret_ip);
2014-01-04 17:00:08 +04:00
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))
{
2018-10-30 17:11:16 +03:00
char *hostname = o->ProxyType == PROXY_DIRECT ? w.HostName : w.ProxyHostName;
if (((s->IsRUDPSocket || s->IPv6) && IsZeroIP(&s->RemoteIP) == false && o->ProxyType == PROXY_DIRECT) || GetIP(&c->Session->ServerIP, hostname) == false)
2014-01-04 17:00:08 +04:00
{
Copy(&c->Session->ServerIP, &s->RemoteIP, sizeof(IP));
}
}
2016-03-06 17:16:01 +03:00
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);
}
}
}
2014-01-04 17:00:08 +04:00
}
return s;
}
2018-10-30 17:11:16 +03:00
// Connect via SOCKS4
2014-01-04 17:00:08 +04:00
SOCK *SocksConnectEx2(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
char *server_host_name, UINT server_port,
char *username, bool additional_connect,
2016-03-06 17:16:01 +03:00
bool *cancel_flag, void *hWnd, UINT timeout, IP *ret_ip)
2014-01-04 17:00:08 +04:00
{
SOCK *s = NULL;
IP ip;
// Validate arguments
if (c == NULL || proxy_host_name == NULL || proxy_port == 0 || server_host_name == NULL
|| server_port == 0)
{
if (c != NULL)
{
c->Err = ERR_PROXY_CONNECT_FAILED;
}
2014-01-04 17:00:08 +04:00
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
2018-07-30 10:03:07 +03:00
s = TcpConnectEx3(proxy_host_name, proxy_port, timeout, cancel_flag, hWnd, true, NULL, false, ret_ip);
2014-01-04 17:00:08 +04:00
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;
}
2018-10-30 17:11:16 +03:00
// Receive a SOCKS4 response packet
2014-01-04 17:00:08 +04:00
bool SocksRecvResponsePacket(CONNECTION *c, SOCK *s)
{
BUF *b;
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;
}
}
2018-10-30 17:11:16 +03:00
// Send a SOCKS4 request packet
2014-01-04 17:00:08 +04:00
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;
}
2018-10-30 17:11:16 +03:00
// Connect via SOCKS5 (RFC1928)
SOCK *Socks5Connect(CONNECTION *c, WPC_CONNECT *w, bool additional_connect, bool *cancel_flag, void *hWnd, UINT timeout, IP *ret_ip)
{
UCHAR tmp, recv_buf[2], *recv_buf_final;
USHORT port;
bool ret;
SOCK *s;
BUF *b;
IP ip;
// Validate arguments
if (c == NULL || w == NULL || w->Port == 0 || w->ProxyPort == 0 || IsEmptyStr(w->HostName) || IsEmptyStr(w->ProxyHostName))
{
if (c != NULL)
{
c->Err = ERR_PROXY_CONNECT_FAILED;
}
return NULL;
}
if (c->Halt)
{
// Stop
c->Err = ERR_USER_CANCEL;
return NULL;
}
// Open TCP connection to the proxy server
s = TcpConnectEx3(w->ProxyHostName, w->ProxyPort, timeout, cancel_flag, hWnd, true, NULL, false, ret_ip);
if (s == NULL)
{
// Failure
c->Err = ERR_PROXY_CONNECT_FAILED;
return NULL;
}
// Set the timeout setting
SetTimeout(s, MIN(CONNECTING_TIMEOUT_PROXY, (timeout == 0 ? INFINITE : timeout)));
if (additional_connect == false)
{
c->FirstSock = s;
}
// +----+----------+----------+
// |VER | NMETHODS | METHODS |
// +----+----------+----------+
// | 1 | 1 | 1 to 255 |
// +----+----------+----------+
//
// X'00' NO AUTHENTICATION REQUIRED
// X'01' GSSAPI
// X'02' USERNAME/PASSWORD
// X'03' to X'7F' IANA ASSIGNED
// X'80' to X'FE' RESERVED FOR PRIVATE METHODS
// X'FF' NO ACCEPTABLE METHOD
b = NewBuf();
tmp = 5;
WriteBuf(b, &tmp, sizeof(tmp)); // SOCKS version
tmp = 2;
WriteBuf(b, &tmp, sizeof(tmp)); // Number of supported methods
tmp = 0;
WriteBuf(b, &tmp, sizeof(tmp)); // No authentication
tmp = 2;
WriteBuf(b, &tmp, sizeof(tmp)); // Username/password
ret = SendAll(s, b->Buf, b->Size, false);
FreeBuf(b);
if (ret == false)
{
Debug("Socks5Connect(): [Phase 1] Failed to send initial data to the server.\n");
c->Err = ERR_DISCONNECTED;
goto failure;
}
// +----+--------+
// |VER | METHOD |
// +----+--------+
// | 1 | 1 |
// +----+--------+
if (RecvAll(s, recv_buf, sizeof(recv_buf), false) == false)
{
Debug("Socks5Connect(): [Phase 1] Failed to receive initial data response from the server.\n");
c->Err = ERR_DISCONNECTED;
goto failure;
}
if (recv_buf[0] != 5)
{
Debug("Socks5Connect(): [Phase 1] Unmatching version: %u.\n", recv_buf[0]);
c->Err = ERR_PROXY_ERROR;
goto failure;
}
// Username/password authentication (RFC1929)
if (recv_buf[1] == 2)
{
// +----+------+----------+------+----------+
// |VER | ULEN | UNAME | PLEN | PASSWD |
// +----+------+----------+------+----------+
// | 1 | 1 | 1 to 255 | 1 | 1 to 255 |
// +----+------+----------+------+----------+
b = NewBuf();
tmp = 1;
WriteBuf(b, &tmp, sizeof(tmp)); // Authentication protocol version
tmp = StrLen(w->ProxyUsername);
WriteBuf(b, &tmp, sizeof(tmp)); // Username length
WriteBuf(b, w->ProxyUsername, tmp); // Username
tmp = StrLen(w->ProxyPassword);
WriteBuf(b, &tmp, sizeof(tmp)); // Password length
WriteBuf(b, w->ProxyPassword, tmp); // Password
ret = SendAll(s, b->Buf, b->Size, false);
FreeBuf(b);
if (ret == false)
{
Debug("Socks5Connect(): [Phase 1] Failed to send authentication data to the server.\n");
c->Err = ERR_DISCONNECTED;
goto failure;
}
// +----+--------+
// |VER | STATUS |
// +----+--------+
// | 1 | 1 |
// +----+--------+
if (RecvAll(s, recv_buf, sizeof(recv_buf), false) == false)
{
Debug("Socks5Connect(): [Phase 1] Failed to receive authentication data response from the server.\n");
c->Err = ERR_DISCONNECTED;
goto failure;
}
if (recv_buf[1] != 0)
{
Debug("Socks5Connect(): [Phase 1] Authentication failure error code sent by the server: %u.\n", recv_buf[1]);
c->Err = ERR_PROXY_AUTH_FAILED;
goto failure;
}
}
// +----+-----+-------+------+----------+----------+
// |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
// +----+-----+-------+------+----------+----------+
// | 1 | 1 | X'00' | 1 | Variable | 2 |
// +----+-----+-------+------+----------+----------+
//
// VER protocol version: X'05'
// CMD
// CONNECT X'01'
// BIND X'02'
// UDP ASSOCIATE X'03'
// RSV RESERVED
// ATYP address type of following address
// IP V4 address X'01'
// DOMAINNAME X'03'
// IP V6 address X'04'
// DST.ADDR desired destination address
// DST.PORT desired destination port in network octet order
// Prepare data to send
b = NewBuf();
tmp = 5;
WriteBuf(b, &tmp, sizeof(tmp)); // SOCKS version
tmp = 1;
WriteBuf(b, &tmp, sizeof(tmp)); // Command
tmp = 0;
WriteBuf(b, &tmp, sizeof(tmp)); // Reserved byte
// Convert the hostname to an IP structure (if it's an IP address)
StrToIP(&ip, w->HostName);
// If the IP structure doesn't contain an IP address, it means that the string is an hostname
if (IsZeroIp(&ip))
{
UCHAR dest_length = StrLen(w->HostName);
tmp = 3;
WriteBuf(b, &tmp, sizeof(tmp)); // Destination type (hostname)
WriteBuf(b, &dest_length, sizeof(dest_length)); // Destination hostname length
WriteBuf(b, w->HostName, dest_length); // Destination hostname
}
else
{
if (IsIP6(&ip))
{
tmp = 4;
WriteBuf(b, &tmp, sizeof(tmp)); // Destination type (IPv6)
WriteBuf(b, ip.ipv6_addr, sizeof(ip.ipv6_addr)); // Destination IPv6 address
}
else
{
tmp = 1;
WriteBuf(b, &tmp, sizeof(tmp)); // Destination type (IPv4)
WriteBuf(b, ip.addr, sizeof(ip.addr)); // Destination IPv4 address
}
}
// Convert the port in network octet order
port = Endian16((USHORT)w->Port);
WriteBuf(b, &port, sizeof(port)); // Destination port
// Send data
ret = SendAll(s, b->Buf, b->Size, false);
FreeBuf(b);
if (ret == false)
{
Debug("Socks5Connect(): [Phase 2] Failed to send data to the server.\n");
c->Err = ERR_DISCONNECTED;
goto failure;
}
// +----+-----+-------+------+----------+----------+
// |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
// +----+-----+-------+------+----------+----------+
// | 1 | 1 | X00 | 1 | Variable | 2 |
// +----+-----+-------+------+----------+----------+
//
// VER protocol version: X05
// REP Reply field:
// X00 succeeded
// X01 general SOCKS server failure
// X02 connection not allowed by ruleset
// X03 Network unreachable
// X04 Host unreachable
// X05 Connection refused
// X06 TTL expired
// X07 Command not supported
// X08 Address type not supported
// X09 to XFF unassigned
// The packet sent by the server should always have the same size as the one we sent to it.
// However, there are some implementations which send fixed values (aside from the first 2 bytes).
// In order to support such implementations, we read the first 4 bytes in order to know the address type before trying to read the rest of the packet.
recv_buf_final = Malloc(4);
if (RecvAll(s, recv_buf_final, 4, false) == false)
{
Free(recv_buf_final);
Debug("Socks5Connect(): [Phase 2] Failed to receive response from the server.\n");
c->Err = ERR_DISCONNECTED;
goto failure;
}
// We only need the first two bytes (version and response code), but we have to read the entire packet from the socket
recv_buf[0] = recv_buf_final[0];
recv_buf[1] = recv_buf_final[1];
// We receive the rest of the packet by knowing the size according to the address type
switch (recv_buf_final[3])
{
case 1:
// IPv4
recv_buf_final = ReAlloc(recv_buf_final, 6); // 4 bytes (IPv4) + 2 bytes (port)
ret = RecvAll(s, recv_buf_final, 6, false);
break;
case 4:
// IPv6
recv_buf_final = ReAlloc(recv_buf_final, 18); // 4 bytes (IPv4) + 2 bytes (port)
ret = RecvAll(s, recv_buf_final, 18, false);
break;
case 3:
// Hostname
ret = RecvAll(s, &tmp, 1, false);
if (ret == true)
{
recv_buf_final = ReAlloc(recv_buf_final, tmp + 2); // Hostname length + 2 bytes (port)
ret = RecvAll(s, recv_buf_final, tmp + 2, false);
}
}
Free(recv_buf_final);
if (ret == false)
{
Debug("Socks5Connect(): [Phase 2] Malformed response received from the server.\n");
c->Err = ERR_DISCONNECTED;
goto failure;
}
if (recv_buf[0] != 5)
{
Debug("Socks5Connect(): [Phase 2] Unmatching version: %u.\n", recv_buf_final[0]);
c->Err = ERR_PROXY_ERROR;
goto failure;
}
if (recv_buf[1] == 0)
{
// Success
SetTimeout(s, INFINITE);
return s;
}
else
{
Debug("Socks5Connect(): [Phase 2] Connection failed with error: %u\n", recv_buf[1]);
c->Err = ERR_PROXY_ERROR;
}
failure:
if (additional_connect == false)
{
c->FirstSock = NULL;
}
Disconnect(s);
ReleaseSock(s);
return NULL;
}
2014-01-04 17:00:08 +04:00
// Connect through a proxy
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)
{
WPC_CONNECT wpc_connect;
Zero(&wpc_connect, sizeof(wpc_connect));
StrCpy(wpc_connect.ProxyHostName, sizeof(wpc_connect.ProxyHostName), proxy_host_name);
wpc_connect.ProxyPort = proxy_port;
StrCpy(wpc_connect.HostName, sizeof(wpc_connect.HostName), server_host_name);
wpc_connect.Port = server_port;
StrCpy(wpc_connect.ProxyUsername, sizeof(wpc_connect.ProxyUsername), username);
StrCpy(wpc_connect.ProxyPassword, sizeof(wpc_connect.ProxyPassword), password);
return ProxyConnectEx3(c, &wpc_connect, additional_connect, cancel_flag, hWnd, timeout);
}
SOCK *ProxyConnectEx3(CONNECTION *c, WPC_CONNECT *wpc_connect,
bool additional_connect, bool *cancel_flag, void *hWnd,
UINT timeout)
2014-01-04 17:00:08 +04:00
{
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;
2014-06-06 01:53:20 +04:00
char server_host_name_tmp[256];
UINT i, len;
2014-01-04 17:00:08 +04:00
// Validate arguments
if (c == NULL || IsEmptyStr(wpc_connect->ProxyHostName) || wpc_connect->ProxyPort == 0 || IsEmptyStr(wpc_connect->HostName) || wpc_connect->Port == 0)
2014-01-04 17:00:08 +04:00
{
if (c != NULL)
{
c->Err = ERR_PROXY_CONNECT_FAILED;
}
2014-01-04 17:00:08 +04:00
return NULL;
}
if ((IsEmptyStr(wpc_connect->ProxyUsername) || IsEmptyStr(wpc_connect->ProxyPassword)) == false)
2014-01-04 17:00:08 +04:00
{
use_auth = true;
}
if (c->Halt)
{
// Stop
c->Err = ERR_USER_CANCEL;
return NULL;
}
2014-06-06 01:53:20 +04:00
Zero(server_host_name_tmp, sizeof(server_host_name_tmp));
StrCpy(server_host_name_tmp, sizeof(server_host_name_tmp), wpc_connect->HostName);
2014-06-06 01:53:20 +04:00
len = StrLen(server_host_name_tmp);
for (i = 0;i < len;i++)
{
if (server_host_name_tmp[i] == '/')
{
server_host_name_tmp[i] = 0;
}
}
2014-01-04 17:00:08 +04:00
// Connection
s = TcpConnectEx3(wpc_connect->ProxyHostName, wpc_connect->ProxyPort, timeout, cancel_flag, hWnd, true, NULL, false, NULL);
2014-01-04 17:00:08 +04:00
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
2014-06-06 01:53:20 +04:00
if (IsStrIPv6Address(server_host_name_tmp))
2014-01-04 17:00:08 +04:00
{
IP ip;
char iptmp[MAX_PATH];
2014-06-06 01:53:20 +04:00
StrToIP(&ip, server_host_name_tmp);
2014-01-04 17:00:08 +04:00
IPToStr(iptmp, sizeof(iptmp), &ip);
Format(tmp, sizeof(tmp), "[%s]:%u", iptmp, wpc_connect->Port);
2014-01-04 17:00:08 +04:00
}
else
{
Format(tmp, sizeof(tmp), "%s:%u", server_host_name_tmp, wpc_connect->Port);
2014-01-04 17:00:08 +04:00
}
h = NewHttpHeader("CONNECT", tmp, "HTTP/1.0");
if (IsEmptyStr(wpc_connect->CustomHttpHeader) == false)
{
TOKEN_LIST *tokens = ParseToken(wpc_connect->CustomHttpHeader, "\r\n");
if (tokens != NULL)
{
for (i = 0; i < tokens->NumTokens; i++)
{
AddHttpValueStr(h, tokens->Token[i]);
}
FreeToken(tokens);
}
}
if (GetHttpValue(h, "User-Agent") == NULL)
{
AddHttpValue(h, NewHttpValue("User-Agent", (c->Cedar == NULL ? DEFAULT_USER_AGENT : c->Cedar->HttpUserAgent)));
}
if (GetHttpValue(h, "Host") == NULL)
{
AddHttpValue(h, NewHttpValue("Host", server_host_name_tmp));
}
if (GetHttpValue(h, "Content-Length") == NULL)
{
AddHttpValue(h, NewHttpValue("Content-Length", "0"));
}
if (GetHttpValue(h, "Proxy-Connection") == NULL)
{
AddHttpValue(h, NewHttpValue("Proxy-Connection", "Keep-Alive"));
}
if (GetHttpValue(h, "Pragma") == NULL)
{
AddHttpValue(h, NewHttpValue("Pragma", "no-cache"));
}
if (use_auth && GetHttpValue(h, "Proxy-Authorization") == NULL)
2014-01-04 17:00:08 +04:00
{
wchar_t tmp[MAX_SIZE];
2014-06-06 01:53:20 +04:00
UniFormat(tmp, sizeof(tmp), _UU("STATUS_3"), server_host_name_tmp);
2014-01-04 17:00:08 +04:00
// Generate the authentication string
Format(auth_tmp_str, sizeof(auth_tmp_str), "%s:%s",
wpc_connect->ProxyUsername, wpc_connect->ProxyPassword);
2014-01-04 17:00:08 +04:00
// 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
2018-07-30 10:03:07 +03:00
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, IP *ret_ip)
2014-01-04 17:00:08 +04:00
{
#ifdef OS_WIN32
if (hWnd == NULL)
{
#endif // OS_WIN32
2018-07-30 10:03:07 +03:00
return ConnectEx4(hostname, port, timeout, cancel_flag, (no_nat_t ? NULL : VPN_RUDP_SVC_NAME), nat_t_error_code, try_start_ssl, true, ret_ip);
2014-01-04 17:00:08 +04:00
#ifdef OS_WIN32
}
else
{
2018-07-30 10:03:07 +03:00
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);
2014-01-04 17:00:08 +04:00
}
#endif // OS_WIN32
}
// Connect with TCP/IP
2018-07-30 10:03:07 +03:00
SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, IP *ret_ip)
2014-01-04 17:00:08 +04:00
{
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;
}
2018-07-30 10:03:07 +03:00
s = TcpConnectEx3(hostname, port, 0, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, ret_ip);
2014-01-04 17:00:08 +04:00
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;
}
// Generate a packet of OpenVPN certificate login
PACK *PackLoginWithOpenVPNCertificate(char *hubname, char *username, X *x)
{
PACK *p;
2018-04-20 02:19:32 +03:00
char cn_username[128];
BUF *cert_buf = NULL;
// Validate arguments
if (hubname == NULL || username == NULL || x == NULL)
{
return NULL;
}
p = NewPack();
PackAddStr(p, "method", "login");
PackAddStr(p, "hubname", hubname);
if (IsEmptyStr(username))
{
if (x->subject_name == NULL)
{
FreePack(p);
return NULL;
}
UniToStr(cn_username, sizeof(cn_username), x->subject_name->CommonName);
PackAddStr(p, "username", cn_username);
}
else
{
PackAddStr(p, "username", username);
}
PackAddInt(p, "authtype", AUTHTYPE_OPENVPN_CERT);
2018-04-20 02:19:32 +03:00
cert_buf = XToBuf(x, false);
PackAddBuf(p, "cert", cert_buf);
FreeBuf(cert_buf);
return p;
}
2014-01-04 17:00:08 +04:00
// 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;
}