Many bug fixes: Login screen, hw keys, relay domain and more.

This commit is contained in:
Ylian Saint-Hilaire 2019-05-21 14:19:32 -07:00
parent 084a6bab57
commit bbd7a96c7b
13 changed files with 69 additions and 39 deletions

View File

@ -597,14 +597,14 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// Check that the node exists
db.Get(obj.dbNodeKey, function (err, nodes) {
if (obj.agentInfo == null) { return; }
var device;
var device, mesh;
// See if this node exists in the database
if ((nodes == null) || (nodes.length == 0)) {
// This device does not exist, use the meshid given by the device
// See if this mesh exists, if it does not we may want to create it.
const mesh = getMeshAutoCreate();
mesh = getMeshAutoCreate();
// Check if the mesh exists
if (mesh == null) {
@ -647,7 +647,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
}
// See if this mesh exists, if it does not we may want to create it.
const mesh = getMeshAutoCreate();
mesh = getMeshAutoCreate();
// Check if the mesh exists
if (mesh == null) {
@ -705,6 +705,20 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
const dupAgent = parent.wsagents[obj.dbNodeKey];
parent.wsagents[obj.dbNodeKey] = obj;
if (dupAgent) {
// Record duplicate agents
if (parent.duplicateAgentsLog[obj.dbNodeKey] == null) {
if (dupAgent.remoteaddr == obj.remoteaddr) {
parent.duplicateAgentsLog[obj.dbNodeKey] = { name: device.name, group: mesh.name, ip: [obj.remoteaddr], count: 1 };
} else {
parent.duplicateAgentsLog[obj.dbNodeKey] = { name: device.name, group: mesh.name, ip: [obj.remoteaddr, dupAgent.remoteaddr], count: 1 };
}
} else {
parent.duplicateAgentsLog[obj.dbNodeKey].name = device.name;
parent.duplicateAgentsLog[obj.dbNodeKey].group = mesh.name;
parent.duplicateAgentsLog[obj.dbNodeKey].count++;
if (parent.duplicateAgentsLog[obj.dbNodeKey].ip.indexOf(obj.remoteaddr) == -1) { parent.duplicateAgentsLog[obj.dbNodeKey].ip.push(obj.remoteaddr); }
}
// Close the duplicate agent
parent.agentStats.duplicateAgentCount++;
if (obj.nodeid != null) { parent.parent.debug(1, 'Duplicate agent ' + obj.nodeid + ' (' + obj.remoteaddrport + ')'); }

View File

@ -548,7 +548,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
case 'help': {
r = 'Available commands: help, info, versions, args, resetserver, showconfig, usersessions, tasklimiter, setmaxtasks, cores,\r\n'
r += 'migrationagents, agentstats, webstats, mpsstats, swarmstats, acceleratorsstats, updatecheck, serverupdate, nodeconfig,\r\n';
r += 'heapdump, relays, autobackup.';
r += 'heapdump, relays, autobackup, dupagents.';
break;
}
case 'dupagents': {
for (var i in parent.duplicateAgentsLog) { r += JSON.stringify(parent.duplicateAgentsLog[i]) + '\r\n'; }
if (r == '') { r = 'No duplicate agents in log.'; }
break;
}
case 'agentstats': {
@ -1217,10 +1222,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
// Change a user's password
if (user.siteadmin != 0xFFFFFFFF) break;
if (common.validateString(command.userid, 1, 256) == false) break;
if (common.validateString(command.pass, 1, 256) == false) break;
if (common.validateString(command.pass, 0, 256) == false) break;
if ((command.hint != null) && (common.validateString(command.hint, 0, 256) == false)) break;
if (typeof command.removeMultiFactor != 'boolean') break;
if (common.checkPasswordRequirements(command.pass, domain.passwordrequirements) == false) break; // Password does not meet requirements
if ((command.pass != '') && (common.checkPasswordRequirements(command.pass, domain.passwordrequirements) == false)) break; // Password does not meet requirements
var chguser = parent.users[command.userid];
if (chguser) {
@ -1230,8 +1235,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
// Compute the password hash & save it
require('./pass').hash(command.pass, function (err, salt, hash, tag) {
if (!err) {
chguser.salt = salt;
chguser.hash = hash;
if (command.pass != '') { chguser.salt = salt; chguser.hash = hash; }
if ((domain.passwordrequirements != null) && (domain.passwordrequirements.hint === true) && (command.hint != null)) {
var hint = command.hint;
if (hint.length > 250) { hint = hint.substring(0, 250); }

View File

@ -1,6 +1,6 @@
{
"name": "meshcentral",
"version": "0.3.4-y",
"version": "0.3.4-z",
"keywords": [
"Remote Management",
"Intel AMT",
@ -28,13 +28,12 @@
],
"dependencies": {
"archiver": "^3.0.0",
"archiver-zip-encrypted": "^1.0.3",
"body-parser": "^1.19.0",
"cbor": "^4.1.5",
"compression": "^1.7.4",
"connect-redis": "^3.4.1",
"cookie-session": "^2.0.0-beta.3",
"express": "^4.16.4",
"express": "^4.17.0",
"express-handlebars": "^3.1.0",
"express-ws": "^4.0.0",
"ipcheck": "^0.1.0",

View File

@ -5,7 +5,7 @@
*/
// Construct a MeshServer agent direction object
var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, authCookie) {
var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, authCookie, domainUrl) {
var obj = {};
obj.m = module; // This is the inner module (Terminal or Desktop)
module.parent = obj;
@ -25,6 +25,7 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, au
obj.webchannel = null;
obj.webrtc = null;
obj.debugmode = 0;
if (domainUrl == null) { domainUrl = '/'; }
// Console Message
obj.consoleMessage = null;
@ -47,7 +48,7 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, au
obj.socket.onclose = obj.xxOnSocketClosed;
obj.xxStateChange(1);
//obj.meshserver.send({ action: 'msg', type: 'tunnel', nodeid: obj.nodeid, value: url2 });
obj.meshserver.send({ action: 'msg', type: 'tunnel', nodeid: obj.nodeid, value: "*/meshrelay.ashx?id=" + obj.tunnelid, usage: obj.protocol });
obj.meshserver.send({ action: 'msg', type: 'tunnel', nodeid: obj.nodeid, value: "*" + domainUrl + "meshrelay.ashx?id=" + obj.tunnelid, usage: obj.protocol });
//obj.debug("Agent Redir Start: " + url);
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2167,7 +2167,7 @@
desktop.contype = 2;
} else {
// Setup the Mesh Agent remote desktop
desktop = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('Desk'), serverPublicNamePort, authCookie);
desktop = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('Desk'), serverPublicNamePort, authCookie, domainUrl);
desktop.debugmode = debugmode;
desktop.m.debugmode = debugmode;
desktop.attemptWebRTC = attemptWebRTC;
@ -2468,7 +2468,7 @@
function connectFiles(e) {
if (!files) {
// Setup a mesh agent files
files = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotFiles), serverPublicNamePort, authCookie);
files = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotFiles), serverPublicNamePort, authCookie, domainUrl);
files.attemptWebRTC = attemptWebRTC;
files.onStateChanged = onFilesStateChange;
files.Start(filesNode._id);
@ -2693,7 +2693,7 @@
// Called by the html page to start a download, arguments are: path, file name and file size.
function p13downloadfile(x, y, z) {
if (xxdialogMode) return;
downloadFile = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotDownloadData), serverPublicNamePort, authCookie); // Create our websocket file transport
downloadFile = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotDownloadData), serverPublicNamePort, authCookie, domainUrl); // Create our websocket file transport
downloadFile.ctrlMsgAllowed = false;
downloadFile.onStateChanged = onFileDownloadStateChange;
downloadFile.xpath = decodeURIComponent(x);
@ -2780,7 +2780,7 @@
// Connect again
function p13uploadReconnect() {
uploadFile.ws = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotUploadData), serverPublicNamePort, authCookie);
uploadFile.ws = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotUploadData), serverPublicNamePort, authCookie, domainUrl);
uploadFile.ws.attemptWebRTC = false;
uploadFile.ws.ctrlMsgAllowed = false;
uploadFile.ws.onStateChanged = onFileUploadStateChange;

View File

@ -2485,7 +2485,7 @@
multiDesktop[nodeid] = desk;
} else if (contype == 1) {
// Setup the Mesh Agent remote desktop
desk = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('kvmid_' + shortid), serverPublicNamePort, authCookie);
desk = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('kvmid_' + shortid), serverPublicNamePort, authCookie, domainUrl);
desk.shortid = shortid;
desk.attemptWebRTC = attemptWebRTC;
desk.onStateChanged = onMultiDesktopStateChange;
@ -4464,7 +4464,7 @@
desktop.contype = 2;
} else {
// Setup the Mesh Agent remote desktop
desktop = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('Desk'), serverPublicNamePort, authCookie);
desktop = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('Desk'), serverPublicNamePort, authCookie, domainUrl);
desktop.debugmode = debugmode;
desktop.m.debugmode = debugmode;
desktop.attemptWebRTC = attemptWebRTC;
@ -4963,7 +4963,7 @@
Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
} else {
// Setup a mesh agent terminal
terminal = CreateAgentRedirect(meshserver, CreateAmtRemoteTerminal('Term'), serverPublicNamePort, authCookie);
terminal = CreateAgentRedirect(meshserver, CreateAmtRemoteTerminal('Term'), serverPublicNamePort, authCookie, domainUrl);
terminal.debugmode = debugmode;
terminal.m.debugmode = debugmode;
terminal.m.lineFeed = ([1, 2, 3, 4, 21, 22].indexOf(currentNode.agent.id) >= 0) ? '\r\n' : '\r'; // On windows, send \r\n, on Linux only \r
@ -5093,7 +5093,7 @@
function connectFiles(e) {
if (!files) {
// Setup a mesh agent files
files = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotFiles), serverPublicNamePort, authCookie);
files = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotFiles), serverPublicNamePort, authCookie, domainUrl);
files.attemptWebRTC = attemptWebRTC;
files.onStateChanged = onFilesStateChange;
files.onConsoleMessageChange = function () {
@ -5354,7 +5354,7 @@
// Called by the html page to start a download, arguments are: path, file name and file size.
function p13downloadfile(x, y, z) {
if (xxdialogMode) return;
downloadFile = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotDownloadData), serverPublicNamePort, authCookie); // Create our websocket file transport
downloadFile = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotDownloadData), serverPublicNamePort, authCookie, domainUrl); // Create our websocket file transport
downloadFile.ctrlMsgAllowed = false;
downloadFile.onStateChanged = onFileDownloadStateChange;
downloadFile.xpath = decodeURIComponent(x);
@ -5441,7 +5441,7 @@
// Connect again
function p13uploadReconnect() {
uploadFile.ws = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotUploadData), serverPublicNamePort, authCookie);
uploadFile.ws = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotUploadData), serverPublicNamePort, authCookie, domainUrl);
uploadFile.ws.attemptWebRTC = false;
uploadFile.ws.ctrlMsgAllowed = false;
uploadFile.ws.onStateChanged = onFileUploadStateChange;
@ -7235,8 +7235,8 @@
function p30showUserChangePassDialog(multiFactor) {
if (xxdialogMode) return;
var x = '';
x += addHtmlValue('Password', '<input id=p4pass1 type=password style=width:230px maxlength=256 onchange=showCreateNewAccountDialogValidate(1) onkeyup=showCreateNewAccountDialogValidate(1)></input>');
x += addHtmlValue('Password', '<input id=p4pass2 type=password style=width:230px maxlength=256 onchange=showCreateNewAccountDialogValidate(1) onkeyup=showCreateNewAccountDialogValidate(1)></input>');
x += addHtmlValue('Password', '<input id=p4pass1 type=password style=width:230px maxlength=256 onchange=showCreateNewAccountDialogValidate(1) onkeyup=p30showUserChangePassDialogValidate(1)></input>');
x += addHtmlValue('Password', '<input id=p4pass2 type=password style=width:230px maxlength=256 onchange=showCreateNewAccountDialogValidate(1) onkeyup=p30showUserChangePassDialogValidate(1)></input>');
if (features & 0x00010000) { x += addHtmlValue('Password hint', '<input id=p4hint type=text style=width:230px maxlength=256></input>'); }
if (passRequirements) {
@ -7248,8 +7248,19 @@
x += '<div><input id=p4resetNextLogin type=checkbox />Force password reset on next login.</div>';
if (multiFactor == 1) { x += '<div><input id=p4twoFactorRemove type=checkbox />Remove all 2nd factor authentication.</div>'; }
setDialogMode(2, "Change Password for " + EscapeHtml(currentUser.name), 3, p30showUserChangePassDialogEx, x, multiFactor);
showCreateNewAccountDialogValidate(1);
p30showUserChangePassDialogValidate();
Q('p4pass1').focus();
if (currentUser.passchange == -1) { Q('p4resetNextLogin').checked = true; }
}
function p30showUserChangePassDialogValidate() {
var ok = true;
if ((Q('p4pass1').value != '') || (Q('p4pass2').value != '')) {
if (Q('p4pass1').value != Q('p4pass2').value) { ok = false; } else {
if (passRequirements) { if (checkPasswordRequirements(Q('p4pass1').value, passRequirements) == false) { ok = false; } }
}
}
QE('idx_dlgOkButton', ok);
}
function p30showUserChangePassDialogEx(b, tag) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -73,8 +73,8 @@
</div>
</form>
</div>
<div id=createpanel style="position:relative;display:none">
<div style="background-color: #979797;border-radius:16px;width:260px;padding:16px;text-align:center;clear:both">
<div id=createpanel style="display:none">
<div style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;clear:both;position:relative">
<form action=createaccount method=post>
<div id=message2>
{{{message}}}
@ -188,7 +188,7 @@
</form>
</div>
<div id=resetpasswordpanel style="position:relative;background-color: #979797;border-radius:16px;width:300px;padding:16px;text-align:center;display:none">
<div id=resetpasswordpanel style="position:relative;background-color:#979797;border-radius:16px;width:300px;padding:16px;text-align:center;display:none">
<form action=resetpassword method=post>
<div id=message6>
{{{message}}}

View File

@ -70,7 +70,7 @@
</div>
</form>
</div>
<div id=createpanel style="display:none">
<div id=createpanel style="display:none;position:relative">
<form action=createaccount method=post>
<div id=message2>
{{{message}}}
@ -78,7 +78,7 @@
<div>
<b>Account Creation</b>
</div>
<div id="passwordPolicyCallout" style="display:none;"></div>
<div id="passwordPolicyCallout" style="display:none"></div>
<table>
<tr>
<td id="nuUser" align=right width=100>Username:</td>
@ -181,12 +181,12 @@
<hr /><a onclick=xgo(1) style=cursor:pointer>Back to login</a>
</form>
</div>
<div id=resetpasswordpanel style="display:none">
<div id=resetpasswordpanel style="display:none;position:relative">
<form action=resetpassword method=post>
<div id=message6>
{{{message}}}
</div>
<div id="rpasswordPolicyCallout" style="display:none;"></div>
<div id="rpasswordPolicyCallout" style="display:none"></div>
<table>
<tr>
<td id="rnuPass1" width=100 align=right>Password:</td>

View File

@ -157,6 +157,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
obj.wsagents = {}; // NodeId --> Agent
obj.wsagentsDisconnections = {};
obj.wsagentsDisconnectionsTimer = null;
obj.duplicateAgentsLog = {};
obj.wssessions = {}; // UserId --> Array Of Sessions
obj.wssessions2 = {}; // "UserId + SessionRnd" --> Session (Note that the SessionId is the UserId + / + SessionRnd)
obj.wsPeerSessions = {}; // ServerId --> Array Of "UserId + SessionRnd"
@ -599,10 +600,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
for (var i = 0; i < webAuthnKeys.length; i++) { authnOptions.keyIds.push(webAuthnKeys[i].keyId); }
req.session.u2fchallenge = authnOptions.challenge;
func(JSON.stringify(authnOptions));
return;
}
} else {
func('');
}
func('');
}
function handleLoginRequest(req, res) {