diff --git a/agents/MeshCmd-signed.exe b/agents/MeshCmd-signed.exe index 2efb5bbe..85256a0a 100644 Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ diff --git a/agents/MeshCmd64-signed.exe b/agents/MeshCmd64-signed.exe index ada4dd5d..2d4ccf3a 100644 Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ diff --git a/agents/MeshService-signed.exe b/agents/MeshService-signed.exe index b27ab9fa..7dcbff2c 100644 Binary files a/agents/MeshService-signed.exe and b/agents/MeshService-signed.exe differ diff --git a/agents/MeshService.exe b/agents/MeshService.exe index ce61f6a4..acc61f2f 100644 Binary files a/agents/MeshService.exe and b/agents/MeshService.exe differ diff --git a/agents/MeshService64-signed.exe b/agents/MeshService64-signed.exe index 5a0e9060..1c209b3c 100644 Binary files a/agents/MeshService64-signed.exe and b/agents/MeshService64-signed.exe differ diff --git a/agents/MeshService64.exe b/agents/MeshService64.exe index 8e275fb8..9298d169 100644 Binary files a/agents/MeshService64.exe and b/agents/MeshService64.exe differ diff --git a/agents/meshcore.js b/agents/meshcore.js index 13863db7..0105fea1 100644 --- a/agents/meshcore.js +++ b/agents/meshcore.js @@ -1477,13 +1477,15 @@ function createMeshCore(agent) { } catch (e) { amtLmsState = -1; amtLms = null; } // Setup logged in user monitoring - /* try { var userSession = require('user-sessions'); userSession.on('changed', function onUserSessionChanged() { userSession.enumerateUsers().then(function (users) { var u = [], a = users.Active; - for (var i in a) { if (a[i].Domain) { u.push(a[i].Domain + '\\' + a[i].Username); } else { u.push(a[i].Username); } } + for (var i = 0; i < a.length; i++) { + var un = a[i].Domain ? (a[i].Domain + '\\' + a[i].Username) : (a[i].Username); + if (u.indexOf(un) == -1) { u.push(un); } // Only push users in the list once. + } obj.loggedInUsers = u; if (mesh.isControlChannelConnected) { mesh.SendCommand({ "action": "coreinfo", "users": u }); } }); @@ -1492,7 +1494,6 @@ function createMeshCore(agent) { //userSession.on('locked', function (user) { sendConsoleText('[' + (user.Domain ? user.Domain + '\\' : '') + user.Username + '] has LOCKED the desktop'); }); //userSession.on('unlocked', function (user) { sendConsoleText('[' + (user.Domain ? user.Domain + '\\' : '') + user.Username + '] has UNLOCKED the desktop'); }); } catch (ex) { } - */ } obj.stop = function () { diff --git a/meshagent.js b/meshagent.js index 8c16e4b2..4fdab39a 100644 --- a/meshagent.js +++ b/meshagent.js @@ -164,7 +164,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Send the next block to the agent obj.agentUpdate.ptr += len; //console.log("Agent update send next block", obj.agentUpdate.ptr, len); - if (len == agentUpdateBlockSize) { obj.ws.send(obj.agentUpdate.buf); } else { obj.ws.send(obj.agentUpdate.buf.slice(0, len + 4)); } // Command 14, mesh agent next data block + if (len == agentUpdateBlockSize) { obj.send(obj.agentUpdate.buf); } else { obj.send(obj.agentUpdate.buf.slice(0, len + 4)); } // Command 14, mesh agent next data block if (len < agentUpdateBlockSize) { //console.log("Agent update sent"); @@ -294,6 +294,9 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Mark when we connected to this agent obj.connectTime = Date.now(); + obj.db.Set({ _id: 'lc' + obj.dbNodeKey, type: 'lastconnect', domain: domain.id, time: obj.connectTime }); + + // See if this node exists in the database if (nodes.length == 0) { // This node does not exist, create it. device = { type: 'node', mtype: mesh.mtype, _id: obj.dbNodeKey, icon: obj.agentInfo.platformType, meshid: obj.dbMeshKey, name: obj.agentInfo.computerName, rname: obj.agentInfo.computerName, domain: domain.id, agent: { ver: obj.agentInfo.agentVersion, id: obj.agentInfo.agentId, caps: obj.agentInfo.capabilities }, host: null }; @@ -324,7 +327,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Event the node change var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id }; - if (log == 0) { event.nolog = 1; } else { event.msg = 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', '); } + if (log == 0) { event.nolog = 1; } else { event.msg = 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', '); } var device2 = obj.common.Clone(device); if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. event.node = device; @@ -450,7 +453,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { if (ws != null) { command.nodeid = obj.dbNodeKey; // Set the nodeid, required for responses. delete command.sessionid; // Remove the sessionid, since we are sending to that sessionid, so it's implyed. - ws.send(JSON.stringify(command)); + try { ws.send(JSON.stringify(command)); } catch (ex) { } } else if (obj.parent.parent.multiServer != null) { // See if we can send this to a peer server var serverid = obj.parent.wsPeerSessions2[command.sessionid]; @@ -617,7 +620,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Event the node change var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id }; - if (changes.length > 0) { event.msg = 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', '); } + if (changes.length > 0) { event.msg = 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', '); } if ((obj.agentInfo.capabilities & 0x20) || (changes.length == 0)) { event.nolog = 1; } // If this is a temporary device, don't log changes var device2 = obj.common.Clone(device); if (device2.intelamt && device2.intelamt.pass) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. @@ -652,7 +655,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { obj.db.Set(device); // Event the node change - var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Changed device ' + device.name + ' from mesh ' + mesh.name + ': ' + changes.join(', ') }; + var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', ') }; if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes var device2 = obj.common.Clone(device); if (device2.intelamt && device2.intelamt.pass) { delete device2.intelamt.pass; } // Remove the Intel AMT password before eventing this. diff --git a/meshcentral.js b/meshcentral.js index e919973a..c7d26d72 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -57,6 +57,7 @@ function CreateMeshCentralServer(config, args) { obj.currentVer = null; obj.serverKey = new Buffer(obj.crypto.randomBytes(32), 'binary'); obj.loginCookieEncryptionKey = null; + obj.serverSelfWriteAllowed = false; try { obj.currentVer = JSON.parse(obj.fs.readFileSync(obj.path.join(__dirname, 'package.json'), 'utf8')).version; } catch (e) { } // Fetch server version // Setup the default configuration and files paths @@ -491,7 +492,7 @@ function CreateMeshCentralServer(config, args) { // Perform maintenance operations (called every hour) obj.maintenanceActions = function () { // Check if we need to perform server self-update - if (obj.args.selfupdate == true) { + if ((obj.args.selfupdate == true) && (obj.serverSelfWriteAllowed == true)) { obj.db.getValueOfTheDay('performSelfUpdate', 1, function (performSelfUpdate) { if (performSelfUpdate.value > 0) { performSelfUpdate.value--; @@ -1096,7 +1097,8 @@ function CreateMeshCentralServer(config, args) { var r = 'time=' + Date.now() + '\r\n'; for (var i in meshServerState) { r += (i + '=' + meshServerState[i] + '\r\n'); } obj.fs.writeFileSync(obj.getConfigFilePath('serverstate.txt'), r); // Try to write the server state, this may fail if we don't have permission. - } catch (ex) { } // Do nothing since this is not a critical feature. + obj.serverSelfWriteAllowed = true; + } catch (ex) { obj.serverSelfWriteAllowed = false; } // Do nothing since this is not a critical feature. }; // Logging funtions diff --git a/meshuser.js b/meshuser.js index e5f27ce4..12461d98 100644 --- a/meshuser.js +++ b/meshuser.js @@ -76,7 +76,18 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { try { // Check if the user is logged in - if ((!req.session) || (!req.session.userid) || (req.session.domainid != domain.id)) { try { obj.ws.close(); } catch (e) { } return; } + if ((!req.session) || (!req.session.userid) || (req.session.domainid != domain.id)) { + // If a default user is active, setup the session here. + if (obj.args.user && obj.parent.users['user/' + domain.id + '/' + obj.args.user.toLowerCase()]) { + if (req.session && req.session.loginmode) { delete req.session.loginmode; } + req.session.userid = 'user/' + domain.id + '/' + obj.args.user.toLowerCase(); + req.session.domainid = domain.id; + req.session.currentNode = ''; + } else { + // Close the websocket connection + try { obj.ws.close(); } catch (e) { } return; + } + } req.session.ws = obj.ws; // Associate this websocket session with the web session req.session.ws.userid = req.session.userid; req.session.ws.domainid = domain.id; @@ -217,6 +228,16 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { }); break; } + case 'lastconnect': + { + if (obj.common.validateString(command.nodeid, 0, 128) == false) return; + + // Query the database for the last time this node connected + obj.db.Get('lc' + command.nodeid, function (err, docs) { + if ((docs != null) && (docs.length > 0)) { try { ws.send(JSON.stringify({ action: 'lastconnect', nodeid: command.nodeid, time: docs[0].time })); } catch (ex) { } } + }); + break; + } case 'files': { // Send the full list of server files to the browser app @@ -434,7 +455,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { // Remove user from the mesh if (mesh.links[deluser._id] != null) { delete mesh.links[deluser._id]; obj.parent.db.Set(mesh); } // Notify mesh change - change = 'Removed user ' + deluser.name + ' from mesh ' + mesh.name; + change = 'Removed user ' + deluser.name + ' from group ' + mesh.name; obj.parent.parent.DispatchEvent(['*', mesh._id, deluser._id, user._id], obj, { etype: 'mesh', username: user.name, userid: user._id, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id }); } } @@ -722,7 +743,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { obj.db.Set(obj.common.escapeLinksFieldName(mesh)); // Notify mesh change - obj.parent.parent.DispatchEvent(['*', mesh._id, user._id, command.userid], obj, { etype: 'mesh', username: user.name, userid: deluser.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Removed user ' + deluser.name + ' from mesh ' + mesh.name, domain: domain.id }); + obj.parent.parent.DispatchEvent(['*', mesh._id, user._id, command.userid], obj, { etype: 'mesh', username: user.name, userid: deluser.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Removed user ' + deluser.name + ' from group ' + mesh.name, domain: domain.id }); } } break; @@ -805,7 +826,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { obj.db.RemoveNode(node._id); // Remove all entries with node:id // Event node deletion - obj.parent.parent.DispatchEvent(['*', node.meshid], obj, { etype: 'node', username: user.name, action: 'removenode', nodeid: node._id, msg: 'Removed device ' + node.name + ' from mesh ' + mesh.name, domain: domain.id }); + obj.parent.parent.DispatchEvent(['*', node.meshid], obj, { etype: 'node', username: user.name, action: 'removenode', nodeid: node._id, msg: 'Removed device ' + node.name + ' from group ' + mesh.name, domain: domain.id }); // Disconnect all connections if needed var state = obj.parent.parent.GetConnectivityState(nodeid); @@ -1034,7 +1055,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { obj.db.Set(node); // Event the node change - event.msg = 'Changed device ' + node.name + ' from mesh ' + mesh.name + ': ' + changes.join(', '); + event.msg = 'Changed device ' + node.name + ' from group ' + mesh.name + ': ' + changes.join(', '); var node2 = obj.common.Clone(node); if (node2.intelamt && node2.intelamt.pass) delete node2.intelamt.pass; // Remove the Intel AMT password before eventing this. event.node = node2; diff --git a/package.json b/package.json index a447505e..8f6ed0ff 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.2.0-y", + "version": "0.2.1-a", "keywords": [ "Remote Management", "Intel AMT", diff --git a/views/default.handlebars b/views/default.handlebars index 028bf7b1..d1115e28 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -82,7 +82,7 @@