Added 2FA support in MeshCMD.

This commit is contained in:
Ylian Saint-Hilaire 2020-04-03 16:06:38 -07:00
parent 49a144a42d
commit 459540f742
7 changed files with 81 additions and 18 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -153,8 +153,10 @@ function run(argv) {
if ((typeof args.cdrom) == 'string') { settings.cdrom = args.cdrom; } if ((typeof args.cdrom) == 'string') { settings.cdrom = args.cdrom; }
if ((typeof args.tag) == 'string') { settings.tag = args.tag; } if ((typeof args.tag) == 'string') { settings.tag = args.tag; }
if ((typeof args.scan) == 'string') { settings.scan = args.scan; } 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.timeout) == 'string') { settings.timeout = parseInt(args.timeout); }
if ((typeof args.uuidoutput) == 'string' || args.uuidoutput) { settings.uuidoutput = args.uuidoutput; } 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 === true) { settings.debuglevel = 1; }
if (args.debug) { try { waitForDebugger(); } catch (e) { } } if (args.debug) { try { waitForDebugger(); } catch (e) { } }
if (args.noconsole) { settings.noconsole = true; } if (args.noconsole) { settings.noconsole = true; }
@ -2048,20 +2050,80 @@ function processLmsControlData(data) {
// //
function startRouter() { 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 = net.createServer(OnTcpClientConnected);
tcpserver.on('error', function (e) { console.log("ERROR: " + JSON.stringify(e)); exit(0); return; }); tcpserver.on('error', function (e) { console.log("ERROR: " + JSON.stringify(e)); exit(0); return; });
tcpserver.listen(settings.localport, function () { try {
// We started listening. tcpserver.listen(settings.localport, function () {
if (settings.remotetarget == null) { // We started listening.
console.log('Redirecting local port ' + settings.localport + ' to remote port ' + settings.remoteport + '.'); if (settings.remotetarget == null) {
} else { console.log('Redirecting local port ' + settings.localport + ' to remote port ' + settings.remoteport + '.');
console.log('Redirecting local port ' + settings.localport + ' to ' + settings.remotetarget + ':' + settings.remoteport + '.'); } else {
} console.log('Redirecting local port ' + settings.localport + ' to ' + settings.remotetarget + ':' + settings.remoteport + '.');
console.log("Press ctrl-c to exit."); }
console.log("Press ctrl-c to exit.");
// If settings has a "cmd", run it now. // If settings has a "cmd", run it now.
//process.exec("notepad.exe"); //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. // 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"); debug(1, "Client connected");
c.on('end', function () { disconnectTunnel(this, this.websocket, "Client closed"); }); c.on('end', function () { disconnectTunnel(this, this.websocket, "Client closed"); });
c.pause(); c.pause();
var options;
try { 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; } } catch (e) { console.log("Unable to parse \"serverUrl\"."); process.exit(1); return; }
options.checkServerIdentity = onVerifyServer; options.checkServerIdentity = onVerifyServer;
options.rejectUnauthorized = false; 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('error', function () { disconnectTunnel(this.tcp, this, 'Websocket error'); });
s.on('close', function (msg) { disconnectTunnel(this.tcp, this, 'Websocket closed'); }); s.on('close', function () { disconnectTunnel(this.tcp, this, 'Websocket closed'); });
s.parent = this; s.parent = this;
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "meshcentral", "name": "meshcentral",
"version": "0.5.1-b", "version": "0.5.1-c",
"keywords": [ "keywords": [
"Remote Management", "Remote Management",
"Intel AMT", "Intel AMT",

View File

@ -3352,9 +3352,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
localPort: 1234, localPort: 1234,
remoteName: node.name, remoteName: node.name,
remoteNodeId: node._id, remoteNodeId: node._id,
remoteTarget: '', remoteTarget: null,
remotePort: 3389, remotePort: 3389,
username: '', username: user.name,
password: '', password: '',
serverId: obj.agentCertificateHashHex.toUpperCase(), // SHA384 of server HTTPS public key 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 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') { } else if (req.query.meshaction == 'generic') {
var meshaction = { var meshaction = {
username: '', username: user.name,
password: '', password: '',
serverId: obj.agentCertificateHashHex.toUpperCase(), // SHA384 of server HTTPS public key 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 serverHttpsHash: Buffer.from(obj.webCertificateHashs[domain.id], 'binary').toString('hex').toUpperCase(), // SHA384 of server HTTPS certificate