From 459540f7427e734d0d283793d1b333ff920abe06 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Fri, 3 Apr 2020 16:06:38 -0700 Subject: [PATCH] Added 2FA support in MeshCMD. --- agents/MeshCmd-signed.exe | Bin 4630928 -> 4634192 bytes agents/MeshCmd64-signed.exe | Bin 4247440 -> 4250704 bytes agents/MeshService-signed.exe | Bin 3625632 -> 3625632 bytes agents/MeshService64-signed.exe | Bin 3242144 -> 3242144 bytes agents/meshcmd.js | 91 +++++++++++++++++++++++++++----- package.json | 2 +- webserver.js | 6 +-- 7 files changed, 81 insertions(+), 18 deletions(-) diff --git a/agents/MeshCmd-signed.exe b/agents/MeshCmd-signed.exe index 9e30bdd88fa035afe9727d7e4e741cf0f1ee3050..bebc660103786e0344430919ba170173816543c3 100644 GIT binary patch delta 3339 zcma);3se->8OK>f5O9%)ycSk3OJHGvP_=4IE5=&HcnlER8eh?RjPDxisn66$d_|;bznR?yjJD03^E=Gm`M!I< z$N%2Thi5msp8js5Ys+GVYgb|8QpFh8_APatie;S&30GhM;06o?+yM_@5a0=T0p7r1 zKneH&LjYgE5AX*9fT2Jj5CjARAwVdg0>XfBKn)B7h64zQ05m`(@CFbCL<3qN28ac8 zKpYScBmjCK5l8}(ffQf_kP4&$>A*-}6fhdd05X9rAR8D1j0MI4oLf4j7lJ1-5fz9OFQVdV#MAHEXhDhrQOLrTGAxpV z!%Iezp|xBIN+HK1iZvmlnKqUq(M*Y`ibiItl14_3=V_yej67|kS&^YE0xID-D_GG; zkXEp-S4r{65pbq`MC7Z{Li?)}kYr%vrSN;}A<%p!J%)!-y-;Cc#2BrW7R)?tp{n(i zV4kmy)t7M$8>2OHtjKc~#~_MB+Oalp&eozhJng9=08a=fhq-1d@w6}^D5kH>QuU=Z zgo?8|e|M7}01( zF%DZjC5QIXRFavI5@@6~S~!8$W0VW=U9%iiDs?jkCXQqLN!hk zSXMTWyCR940g>A6x&jDwgwsy$cuEN@$BN*PjYQr?%hUO3h}dvVUf-5LvMn^674;g( z2`6_NRO`NW0Jz*S;|UFAyiO;P{r{k$pw^+BS<1t zw$|H4iA;@hK-p)Jgy=Xy zWR(Wu4~q#;Rqxl{n%T`IW$iQAjly{66um}{k^WY`Jk8QoIZ~2zA!DU^Y`rsDZGFu~ z{y!yhR;VT(r6)gDF&|DIyI4SBy}A6X zg!TU;;a55iij?{j_Fwx02J1Cs6waSR_^LDx%{l}torpBgbG%-I{U(uW%uOLY6asGf znh3*9^NGR3dmW@>$RyuteZCH_@SmKq^0haegOc#Xe0(yP{M4)OuESyoITr5;fr#oi z82oT|qQM8>4aHSh53o6W+iYhp`@nMJJjwoX2z&NCV3?kMVg0LZm z9NKzFMd}pF{x`K3{y3Uc;UB`t#864y(v8}8+d0JBIxn0oa>pyeNccZPLk`AcBS~+3 zPeaD`jkUtq9?sSH34ZVqxg_b*O84BBD;b+^Tu~nL&7Cl+rOSQkiN?uo^_BINNxJ-w z+rrVbyL+y!34c83+PP7wS*^{Dq|!f0c}34%CbU)T^T+Le+jEuPzr8ZM>96y9dTviV zIc}{tvwzru6$?J|(X5K{t{alr5{dt|ovf?fdXL)qY-i4nfK_!_yN+Ht6x~>}xq7O_ zYHKfhw)5e7zG$BR@54hr{hizU=Eb@$>tKd%oE1GA|K;tDmht|dr=vIbPX0$$L;8!Z z_&*=_z8c3Jn{c4*c*rARe}2REFU&pP{@wVive4-I1dBa>78%By}T}b|LTlHm*#hWeWRqKSwC*k z%t_}jwoba3zwDb0&6`ggxp*;s@1A*;rk>h+@lE;H^vAzox(i(cYcaKh{AX=SN?Lkq z`mCf#cTZjY#QJASg{NC`klWB*d0%R0b~3Zte|%Q9cFb)aZenoT)*HCI{QL;@oqvDst6mbmD5{A#Ubvt_lh^hrV(F^$mel5^fz8<|^@M81 z@^b#vh`Gk@Aj9_Eezm)=pFY+dT(>Rz7ex=t(|n>%`HedK;?m5Uzd8Npj3YOR#@l5f zwilbOyC2+f_4O@0Uxv}?wQv8!zXj}Y&&zA2~ z1{D6NYP7X|wB`a{9^8G3TmJl)8$42)4^3Su&eg8_;JrHogqB^8AEZufIBD2r`JuXP zPVP?g=~ZX%huzv{E4X~jx~`$)<1;T3c7|L~`@H933qQMdx96^L#kpTyIGIwkreV`} TIZbJP*$?hBAy1FFxVZcWHKnv^ delta 1256 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 diff --git a/agents/MeshService-signed.exe b/agents/MeshService-signed.exe index a060f346b990aaa71cd73bf05a1b80a3ded6ab83..3da3e59e6da8a775ee274b0bd2a87f91f86204f9 100644 GIT binary patch delta 518 zcmZ3m^e*E9Al}fx$gJ_#yt$dNy_pe&nShuXh*^M`6^Pk@m>q~YfS41Axqz4(h-A*fLIWSg@9NXh(&-{6o|!uSR9BYfLIcUrGQu(h-H9S7Kr75SRRNKfLIZT zm4H|oh*f}C6^PY1W>_oV&gLf0$3)aahN@A|2< zzZ#;lMQRDJ%imb;KL4!8W#!$dD{oJ1+IOYk*7MuU&Hkq@-RZejqRi~HGG$NasvGRO zix?v+X57sG@YQO|IoYzJ^fMyCYQpO!eK~S!Spy{B)^B66_Bx?$$o#6_^p|;OYCVIV zRWZ|j@gnXlhtr?!_jE~q&{3XYZT8_;$Z5Y%?fFd%0=wJNgqKF1%vrgDU*_)QKO40A z9K-x{?q2v;Xr9r|z}4b0b)REFd-}9zO>>tYns@W}-^AqR<7G2;HgTFhDbwYVyV8(d kY{}^o*aAO@{#j0P04`p8x;= delta 518 zcmZ3m^e*E9Al}fx$lM`o(cH|~-pmNXOhC*G#4JF}3dC$c%nrmHK+FlmTtLhX#5_RE z3&eat%n!r@Kr9HvLO?7G#3Dc}3dCYSEDppHKr9KwQa~&X#4zt^_vuNU`&mG=#Og8`D$L5~7s8Px;`Ljt>NLEeDjcqNKk!6lo z;^bm{&t8r!?ChqO0Pc0QF%92;UQ1Z!P!|e3g53X)^KY8V8+V2LpZtKV4{>&53`t5k!wBSm; kIAhn@Tk2Y(Og<@pa-8p!Pc{)d`u_L)S#g}6p$rfJ0NCZnq5uE@ diff --git a/agents/MeshService64-signed.exe b/agents/MeshService64-signed.exe index b743709157c2cb815bdf92e5bac7a69e751796f1..981ba47f43c8e096b1764f588f21f04ad1026256 100644 GIT binary patch delta 494 zcmZ4R@hIa0Al}fx$ozJ>VRJKMdov>lGXXI(5VHU=D-g2*F*^`*05K;Ja{)0o5c2>r zFA(zqF+UIs0I?tt3jwh(5Q_k@C=iPQu{aP*0I?(xO98Po5X%6uED*~9u{;nf0I?zv zD*>@G5UT*ODiEsyu{scI0I?57e9|;mVVg}HFGMG3mhsM?*?Rczf~#_C!hYz)wr;zcDQEk@^>@b^u~|uS z4PSH@yp_|{4V_o1R(_(WA*P|Dp6lq}c^Y$nMx4~opRxU+-|X(D13Oit*3O>4A%NpF z=ZxdZwim8V7x6OstEH?Q?)^utyy@^iStawv-*J3vCe<_d7z?+$sejybwD#fhZ{PbZ zOBDAPSVwLM{ix@@&%h)7uiVP)$wdODlVZ4Do(R7ushb_Np!VNh2A(9Hx{k!=^*4={ zpNqVZBUQ9a_9z+jF5 z)w1@@OgDSWL|E!o&Os3-`j0D3;6Hv@hiT+e5G<26JN}aA8Q`iG>g0JS)mqf zT%P^x#PVWkp`^r#aTa-AnR7q2@8&Yke9EJCS^V9kdY%R6Q>QYwJ-oDKqw?2I55?SM z>HmvjVixpr*et)r-`*UGtjH(KlC`BrO+ndbVLLS6bfZWNWTF6+VH@m(43a zD)!xzwmQfPtcN+!>003MSzR>^x diff --git a/agents/meshcmd.js b/agents/meshcmd.js index 753fcdea..17f04751 100644 --- a/agents/meshcmd.js +++ b/agents/meshcmd.js @@ -153,8 +153,10 @@ function run(argv) { if ((typeof args.cdrom) == 'string') { settings.cdrom = args.cdrom; } if ((typeof args.tag) == 'string') { settings.tag = args.tag; } if ((typeof args.scan) == 'string') { settings.scan = args.scan; } + if ((typeof args.token) == 'string') { settings.token = args.token; } if ((typeof args.timeout) == 'string') { settings.timeout = parseInt(args.timeout); } if ((typeof args.uuidoutput) == 'string' || args.uuidoutput) { settings.uuidoutput = args.uuidoutput; } + if (args.emailtoken) { settings.emailtoken = true; } if (args.debug === true) { settings.debuglevel = 1; } if (args.debug) { try { waitForDebugger(); } catch (e) { } } if (args.noconsole) { settings.noconsole = true; } @@ -2048,20 +2050,80 @@ function processLmsControlData(data) { // function startRouter() { + // Start by requesting a login token, this is needed because of 2FA and check that we have correct credentials from the start + var options; + try { + var url = settings.serverurl.split('meshrelay.ashx').join('control.ashx') + '?user=' + settings.username + '&pass=' + settings.password; + if (settings.emailtoken) { url += '&token=**email**'; } else if (settings.token != null) { url += '&token=' + settings.token; } + options = http.parseUri(url); + } catch (e) { console.log("Unable to parse \"serverUrl\"."); process.exit(1); return; } + options.checkServerIdentity = onVerifyServer; + options.rejectUnauthorized = false; + settings.websocket = http.request(options); + settings.websocket.upgrade = OnServerWebSocket; + settings.websocket.on('error', function (e) { console.log("ERROR: " + JSON.stringify(e)); }); + settings.websocket.end(); +} + +function OnServerWebSocket(msg, s, head) { + settings.webchannel = s; + s.on('data', function (msg) { + var command = JSON.parse(msg); + switch (command.action) { + case 'close': { + if (command.cause == 'noauth') { + if (command.msg == 'tokenrequired') { + if (command.email2fasent === true) { + console.log("Login token email sent."); + } else if (command.email2fa === true) { + console.log("Login token required, use --token [token], or --emailtoken get a token."); + } else { + console.log("Login token required, use --token [token]."); + } + } else { console.log("Invalid username or password."); } + } else { console.log("Server disconnected: " + command.msg); } + process.exit(1); + return; + } + case 'serverinfo': { + s.write("{\"action\":\"authcookie\"}"); // Ask for our first authentication cookie + break; + } + case 'authcookie': { + if (settings.acookie == null) { + settings.acookie = command.cookie; + settings.rcookie = command.rcookie; + settings.renewCookieTimer = setInterval(function () { settings.webchannel.write("{\"action\":\"authcookie\"}"); }, 600000); // Ask for new cookie every 10 minutes + startRouterEx(); + } else { + settings.acookie = command.cookie; + settings.rcookie = command.rcookie; + } + break; + } + } + }); + s.on('error', function () { console.log("Server connection error."); process.exit(1); return; }); + s.on('close', function () { console.log("Server closed the connection."); process.exit(1); return; }); +} + +function startRouterEx() { tcpserver = net.createServer(OnTcpClientConnected); tcpserver.on('error', function (e) { console.log("ERROR: " + JSON.stringify(e)); exit(0); return; }); - tcpserver.listen(settings.localport, function () { - // We started listening. - if (settings.remotetarget == null) { - console.log('Redirecting local port ' + settings.localport + ' to remote port ' + settings.remoteport + '.'); - } else { - console.log('Redirecting local port ' + settings.localport + ' to ' + settings.remotetarget + ':' + settings.remoteport + '.'); - } - console.log("Press ctrl-c to exit."); + try { + tcpserver.listen(settings.localport, function () { + // We started listening. + if (settings.remotetarget == null) { + console.log('Redirecting local port ' + settings.localport + ' to remote port ' + settings.remoteport + '.'); + } else { + console.log('Redirecting local port ' + settings.localport + ' to ' + settings.remotetarget + ':' + settings.remoteport + '.'); + } + console.log("Press ctrl-c to exit."); - // If settings has a "cmd", run it now. - //process.exec("notepad.exe"); - }); + // If settings has a "cmd", run it now. + //process.exec("notepad.exe"); + }); + } catch (ex) { console.log("Unable to bind to local TCP port " + settings.localport + "."); exit(1); return; } } // Called when a TCP connect is received on the local port. Launch a tunnel. @@ -2071,8 +2133,9 @@ function OnTcpClientConnected(c) { debug(1, "Client connected"); c.on('end', function () { disconnectTunnel(this, this.websocket, "Client closed"); }); c.pause(); + var options; try { - options = http.parseUri(settings.serverurl + '?user=' + settings.username + '&pass=' + settings.password + '&nodeid=' + settings.remotenodeid + '&tcpport=' + settings.remoteport + (settings.remotetarget == null ? '' : '&tcpaddr=' + settings.remotetarget)); + options = http.parseUri(settings.serverurl + '?auth=' + settings.acookie + '&nodeid=' + settings.remotenodeid + '&tcpport=' + settings.remoteport + (settings.remotetarget == null ? '' : '&tcpaddr=' + settings.remotetarget)); } catch (e) { console.log("Unable to parse \"serverUrl\"."); process.exit(1); return; } options.checkServerIdentity = onVerifyServer; options.rejectUnauthorized = false; @@ -2106,8 +2169,8 @@ function OnWebSocket(msg, s, head) { } } }); - s.on('error', function (msg) { disconnectTunnel(this.tcp, this, 'Websocket error'); }); - s.on('close', function (msg) { disconnectTunnel(this.tcp, this, 'Websocket closed'); }); + s.on('error', function () { disconnectTunnel(this.tcp, this, 'Websocket error'); }); + s.on('close', function () { disconnectTunnel(this.tcp, this, 'Websocket closed'); }); s.parent = this; } diff --git a/package.json b/package.json index 04bc41d4..1dc7f058 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.5.1-b", + "version": "0.5.1-c", "keywords": [ "Remote Management", "Intel AMT", diff --git a/webserver.js b/webserver.js index be635567..2f4aed50 100644 --- a/webserver.js +++ b/webserver.js @@ -3352,9 +3352,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { localPort: 1234, remoteName: node.name, remoteNodeId: node._id, - remoteTarget: '', + remoteTarget: null, remotePort: 3389, - username: '', + username: user.name, password: '', serverId: obj.agentCertificateHashHex.toUpperCase(), // SHA384 of server HTTPS public key serverHttpsHash: Buffer.from(obj.webCertificateHashs[domain.id], 'binary').toString('hex').toUpperCase(), // SHA384 of server HTTPS certificate @@ -3368,7 +3368,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { }); } else if (req.query.meshaction == 'generic') { var meshaction = { - username: '', + username: user.name, password: '', serverId: obj.agentCertificateHashHex.toUpperCase(), // SHA384 of server HTTPS public key serverHttpsHash: Buffer.from(obj.webCertificateHashs[domain.id], 'binary').toString('hex').toUpperCase(), // SHA384 of server HTTPS certificate