From 0a62aa8ae395b37ace74f12d1dbedd4fbe64281c Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Wed, 5 Jun 2019 15:24:07 -0700 Subject: [PATCH] Added support fo domain MaxDevices limit --- db.js | 4 +- meshagent.js | 226 +++++++++++++++++++---------------- mpsserver.js | 107 ++++++++++++++--- package.json | 2 +- sample-config.json | 1 + views/default-min.handlebars | 10 +- views/default.handlebars | 10 +- webserver.js | 3 +- 8 files changed, 229 insertions(+), 134 deletions(-) diff --git a/db.js b/db.js index 1122868c..63f03d7b 100644 --- a/db.js +++ b/db.js @@ -549,7 +549,7 @@ module.exports.CreateDB = function (parent, func) { // TODO: Starting in MongoDB 4.0.3, you should use countDocuments() instead of count() that is deprecated. We should detect MongoDB version and switch. // https://docs.mongodb.com/manual/reference/method/db.collection.countDocuments/ //obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.countDocuments({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max)); }); } } - obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.count({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max)); }); } } + obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.count({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max), count); }); } } // Database actions on the events collection obj.GetAllEvents = function (func) { obj.eventsfile.find({}).toArray(func); }; @@ -638,7 +638,7 @@ module.exports.CreateDB = function (parent, func) { obj.dispose = function () { for (var x in obj) { if (obj[x].close) { obj[x].close(); } delete obj[x]; } }; obj.getLocalAmtNodes = function (func) { obj.file.find({ type: 'node', host: { $exists: true, $ne: null }, intelamt: { $exists: true } }, func); }; obj.getAmtUuidNode = function (meshid, uuid, func) { obj.file.find({ type: 'node', meshid: meshid, 'intelamt.uuid': uuid }, func); }; - obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.count({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max)); }); } } + obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.count({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max), count); }); } } // Database actions on the events collection obj.GetAllEvents = function (func) { obj.eventsfile.find({}, func); }; diff --git a/meshagent.js b/meshagent.js index 6c6e8df1..6bab1968 100644 --- a/meshagent.js +++ b/meshagent.js @@ -616,40 +616,21 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { 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. - mesh = getMeshAutoCreate(); - - // Check if the mesh exists - if (mesh == null) { - // If we disconnect, the agent will just reconnect. We need to log this or tell agent to connect in a few hours. - parent.agentStats.invalidDomainMeshCount++; - console.log('Agent connected with invalid domain/mesh, holding connection (' + obj.remoteaddrport + ', ' + obj.dbMeshKey + ').'); - return; - } - - // Check if the mesh is the right type - if (mesh.mtype != 2) { - // If we disconnect, the agent will just reconnect. We need to log this or tell agent to connect in a few hours. - parent.agentStats.invalidMeshTypeCount++; - console.log('Agent connected with invalid mesh type, holding connection (' + obj.remoteaddrport + ').'); - return; - } - - // Mark when this device connected - obj.connectTime = Date.now(); - db.Set({ _id: 'lc' + obj.dbNodeKey, type: 'lastconnect', domain: domain.id, time: obj.connectTime, addr: obj.remoteaddrport }); - - // 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 }; - db.Set(device); - - // Event the new node - if (obj.agentInfo.capabilities & 0x20) { - // This is a temporary agent, don't log. - parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, domain: domain.id, nolog: 1 }); + // Check if we already have too many devices for this domain + if (domain.limits && (typeof domain.limits.maxdevices == 'number')) { + db.isMaxType(domain.limits.maxdevices, 'node', domain.id, function (ismax, count) { + if (ismax == true) { + // Too many devices in this domain. + parent.agentStats.maxDomainDevicesReached++; + } else { + // We are under the limit, create the new device. + completeAgentConnection2(); + } + }); } else { - parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, msg: ('Added device ' + obj.agentInfo.computerName + ' to mesh ' + mesh.name), domain: domain.id }); + completeAgentConnection2(); } + return; } else { device = nodes[0]; @@ -715,78 +696,121 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { } } - // Check if this agent is already connected - 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 + ')'); } - dupAgent.close(3); - } else { - // Indicate the agent is connected - parent.parent.SetConnectivityState(obj.dbMeshKey, obj.dbNodeKey, obj.connectTime, 1, 1); - } - - // We are done, ready to communicate with this agent - delete obj.pendingCompleteAgentConnection; - obj.authenticated = 2; - - // Check how many times this agent disconnected in the last few minutes. - const disconnectCount = parent.wsagentsDisconnections[obj.nodeid]; - if (disconnectCount > 6) { - console.log('Agent in big trouble: NodeId=' + obj.nodeid + ', IP=' + obj.remoteaddrport + ', Agent=' + obj.agentInfo.agentId + '.'); - // TODO: Log or do something to recover? - return; - } - - // Command 4, inform mesh agent that it's authenticated. - obj.send(common.ShortToStr(4)); - - if (disconnectCount > 4) { - // Too many disconnections, this agent has issues. Just clear the core. - obj.send(common.ShortToStr(10) + common.ShortToStr(0)); - //console.log('Agent in trouble: NodeId=' + obj.nodeid + ', IP=' + obj.remoteaddrport + ', Agent=' + obj.agentInfo.agentId + '.'); - // TODO: Log or do something to recover? - return; - } - - // Not sure why, but in rare cases, obj.agentInfo is undefined here. - if ((obj.agentInfo == null) || (typeof obj.agentInfo.capabilities != 'number')) { return; } // This is an odd case. - - // Check if we need to make an native update check - obj.agentExeInfo = parent.parent.meshAgentBinaries[obj.agentInfo.agentId]; - const corename = parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].core; - if (corename == null) { obj.send(common.ShortToStr(10) + common.ShortToStr(0)); } // MeshCommand_CoreModule, ask mesh agent to clear the core - - if ((obj.agentExeInfo != null) && (obj.agentExeInfo.update == true)) { - // Ask the agent for it's executable binary hash - obj.send(common.ShortToStr(12) + common.ShortToStr(0)); - } else { - // Check the mesh core, if the agent is capable of running one - if (((obj.agentInfo.capabilities & 16) != 0) && (corename != null)) { - obj.send(common.ShortToStr(11) + common.ShortToStr(0)); // Command 11, ask for mesh core hash. - } else { - agentCoreIsStable(); // No updates needed, agent is ready to go. - } - } + completeAgentConnection3(); }); } + function completeAgentConnection2(device) { + // See if this mesh exists, if it does not we may want to create it. + var mesh = getMeshAutoCreate(); + + // Check if the mesh exists + if (mesh == null) { + // If we disconnect, the agent will just reconnect. We need to log this or tell agent to connect in a few hours. + parent.agentStats.invalidDomainMeshCount++; + console.log('Agent connected with invalid domain/mesh, holding connection (' + obj.remoteaddrport + ', ' + obj.dbMeshKey + ').'); + return; + } + + // Check if the mesh is the right type + if (mesh.mtype != 2) { + // If we disconnect, the agent will just reconnect. We need to log this or tell agent to connect in a few hours. + parent.agentStats.invalidMeshTypeCount++; + console.log('Agent connected with invalid mesh type, holding connection (' + obj.remoteaddrport + ').'); + return; + } + + // Mark when this device connected + obj.connectTime = Date.now(); + db.Set({ _id: 'lc' + obj.dbNodeKey, type: 'lastconnect', domain: domain.id, time: obj.connectTime, addr: obj.remoteaddrport }); + + // This node does not exist, create it. + var 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 }; + db.Set(device); + + // Event the new node + if (obj.agentInfo.capabilities & 0x20) { + // This is a temporary agent, don't log. + parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, domain: domain.id, nolog: 1 }); + } else { + parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, msg: ('Added device ' + obj.agentInfo.computerName + ' to mesh ' + mesh.name), domain: domain.id }); + } + + completeAgentConnection3(); + } + + function completeAgentConnection3() { + // Check if this agent is already connected + 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 + ')'); } + dupAgent.close(3); + } else { + // Indicate the agent is connected + parent.parent.SetConnectivityState(obj.dbMeshKey, obj.dbNodeKey, obj.connectTime, 1, 1); + } + + // We are done, ready to communicate with this agent + delete obj.pendingCompleteAgentConnection; + obj.authenticated = 2; + + // Check how many times this agent disconnected in the last few minutes. + const disconnectCount = parent.wsagentsDisconnections[obj.nodeid]; + if (disconnectCount > 6) { + console.log('Agent in big trouble: NodeId=' + obj.nodeid + ', IP=' + obj.remoteaddrport + ', Agent=' + obj.agentInfo.agentId + '.'); + // TODO: Log or do something to recover? + return; + } + + // Command 4, inform mesh agent that it's authenticated. + obj.send(common.ShortToStr(4)); + + if (disconnectCount > 4) { + // Too many disconnections, this agent has issues. Just clear the core. + obj.send(common.ShortToStr(10) + common.ShortToStr(0)); + //console.log('Agent in trouble: NodeId=' + obj.nodeid + ', IP=' + obj.remoteaddrport + ', Agent=' + obj.agentInfo.agentId + '.'); + // TODO: Log or do something to recover? + return; + } + + // Not sure why, but in rare cases, obj.agentInfo is undefined here. + if ((obj.agentInfo == null) || (typeof obj.agentInfo.capabilities != 'number')) { return; } // This is an odd case. + + // Check if we need to make an native update check + obj.agentExeInfo = parent.parent.meshAgentBinaries[obj.agentInfo.agentId]; + const corename = parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].core; + if (corename == null) { obj.send(common.ShortToStr(10) + common.ShortToStr(0)); } // MeshCommand_CoreModule, ask mesh agent to clear the core + + if ((obj.agentExeInfo != null) && (obj.agentExeInfo.update == true)) { + // Ask the agent for it's executable binary hash + obj.send(common.ShortToStr(12) + common.ShortToStr(0)); + } else { + // Check the mesh core, if the agent is capable of running one + if (((obj.agentInfo.capabilities & 16) != 0) && (corename != null)) { + obj.send(common.ShortToStr(11) + common.ShortToStr(0)); // Command 11, ask for mesh core hash. + } else { + agentCoreIsStable(); // No updates needed, agent is ready to go. + } + } + } + // Take a basic Intel AMT policy and add all server information to it, making it ready to send to this agent. function completeIntelAmtPolicy(amtPolicy) { if (amtPolicy == null) return null; diff --git a/mpsserver.js b/mpsserver.js index 712da5a4..a2bfaf61 100644 --- a/mpsserver.js +++ b/mpsserver.js @@ -128,6 +128,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { var disconnectCommandCount = 0; var socketClosedCount = 0; var socketErrorCount = 0; + var maxDomainDevicesReached = 0; // Return statistics about this MPS server obj.getStats = function () { @@ -153,7 +154,8 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { channelCloseCount: channelCloseCount, disconnectCommandCount: disconnectCommandCount, socketClosedCount: socketClosedCount, - socketErrorCount: socketErrorCount + socketErrorCount: socketErrorCount, + maxDomainDevicesReached : maxDomainDevicesReached }; } @@ -189,6 +191,11 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { var xx = socket.tag.clientCert.subject.O.split('/'); if (xx.length == 1) { meshid = xx[0]; } else { domainid = xx[0].toLowerCase(); meshid = xx[1]; } + // Check the incoming domain + var domain = obj.parent.config.domains[domainid]; + if (domain == null) { console.log('CIRA connection for invalid domain. meshid: ' + meshid); socket.end(); return; } + + socket.tag.domain = domain; socket.tag.domainid = domainid; socket.tag.meshid = 'mesh/' + domainid + '/' + meshid; socket.tag.nodeid = 'node/' + domainid + '/' + require('crypto').createHash('sha384').update(common.hex2rstr(socket.tag.clientCert.modulus, 'binary')).digest('base64').replace(/\+/g, '@').replace(/\//g, '$'); @@ -203,16 +210,45 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { obj.db.Get(socket.tag.nodeid, function (err, nodes) { if ((nodes == null) || (nodes.length !== 1)) { if (mesh.mtype == 1) { - // Node is not in the database, add it. Credentials will be empty until added by the user. - var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: domainid, intelamt: { user: '', pass: '', tls: 0, state: 2 } }; - obj.db.Set(device); + // Check if we already have too many devices for this domain + if (domain.limits && (typeof domain.limits.maxdevices == 'number')) { + db.isMaxType(domain.limits.maxdevices, 'node', domain.id, function (ismax, count) { + if (ismax == true) { + // Too many devices in this domain. + maxDomainDevicesReached++; + console.log('Too many devices on this domain to accept the CIRA connection. meshid: ' + socket.tag.meshid); + socket.end(); + } else { + // We are under the limit, create the new device. + // Node is not in the database, add it. Credentials will be empty until added by the user. + var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: domainid, intelamt: { user: '', pass: '', tls: 0, state: 2 } }; + obj.db.Set(device); - // Event the new node - addedTlsDeviceCount++; - var device2 = common.Clone(device); - if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. - var change = 'CIRA added device ' + socket.tag.name + ' to mesh ' + mesh.name; - obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: domainid }); + // Event the new node + addedTlsDeviceCount++; + var device2 = common.Clone(device); + if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. + var change = 'CIRA added device ' + socket.tag.name + ' to mesh ' + mesh.name; + obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: domainid }); + + // Add the connection to the MPS connection list + obj.ciraConnections[socket.tag.nodeid] = socket; + obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 2, 7); // TODO: Right now report power state as "present" (7) until we can poll. + } + }); + return; + } else { + // Node is not in the database, add it. Credentials will be empty until added by the user. + var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: domainid, intelamt: { user: '', pass: '', tls: 0, state: 2 } }; + obj.db.Set(device); + + // Event the new node + addedTlsDeviceCount++; + var device2 = common.Clone(device); + if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. + var change = 'CIRA added device ' + socket.tag.name + ' to mesh ' + mesh.name; + obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: domainid }); + } } else { // New CIRA connection for unknown node, disconnect. unknownTlsNodeCount++; @@ -312,6 +348,9 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { // Intel AMT GUID (socket.tag.SystemId) will be used as NodeID var systemid = socket.tag.SystemId.split('-').join(''); var nodeid = Buffer.from(systemid + systemid + systemid, 'hex').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'); + var domain = obj.parent.config.domains[mesh.domain]; + socket.tag.domain = domain; + socket.tag.domainid = mesh.domain; socket.tag.name = ''; socket.tag.nodeid = 'node/' + mesh.domain + '/' + nodeid; // Turn 16bit systemid guid into 48bit nodeid that is base64 encoded socket.tag.meshid = mesh._id; @@ -319,16 +358,46 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { obj.db.Get(socket.tag.nodeid, function (err, nodes) { if ((nodes == null) || (nodes.length !== 1)) { - // Node is not in the database, add it. Credentials will be empty until added by the user. - var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } }; - obj.db.Set(device); + // Check if we already have too many devices for this domain + if (domain.limits && (typeof domain.limits.maxdevices == 'number')) { + db.isMaxType(domain.limits.maxdevices, 'node', mesh.domain, function (ismax, count) { + if (ismax == true) { + // Too many devices in this domain. + maxDomainDevicesReached++; + console.log('Too many devices on this domain to accept the CIRA connection. meshid: ' + socket.tag.meshid); + socket.end(); + } else { + // We are under the limit, create the new device. + // Node is not in the database, add it. Credentials will be empty until added by the user. + var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } }; + obj.db.Set(device); - // Event the new node - addedDeviceCount++; - var device2 = common.Clone(device); - if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. - var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name; - obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain }); + // Event the new node + addedDeviceCount++; + var device2 = common.Clone(device); + if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. + var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name; + obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain }); + + // Add the connection to the MPS connection list + obj.ciraConnections[socket.tag.nodeid] = socket; + obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 2, 7); // TODO: Right now report power state as "present" (7) until we can poll. + SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection + } + }); + return; + } else { + // Node is not in the database, add it. Credentials will be empty until added by the user. + var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } }; + obj.db.Set(device); + + // Event the new node + addedDeviceCount++; + var device2 = common.Clone(device); + if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. + var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name; + obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain }); + } } else { // Node is already present var node = nodes[0]; diff --git a/package.json b/package.json index 43e335fe..2cd696aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.3.5-z", + "version": "0.3.6-a", "keywords": [ "Remote Management", "Intel AMT", diff --git a/sample-config.json b/sample-config.json index 207f5e44..ce551563 100644 --- a/sample-config.json +++ b/sample-config.json @@ -72,6 +72,7 @@ "__UserConsentFlags__" : "Set to: 1 for desktop, 2 for terminal, 3 for files, 7 for all", "_UserConsentFlags" : 7, "_Limits": { + "_MaxDevices": 100, "_MaxUserAccounts": 100, "_MaxUserSessions": 100, "_MaxAgentSessions": 100, diff --git a/views/default-min.handlebars b/views/default-min.handlebars index 77100b80..dcffb776 100644 --- a/views/default-min.handlebars +++ b/views/default-min.handlebars @@ -10189,7 +10189,7 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this function addDeviceAttribute(name, value) { return '' + name + '' + value + ''; } - function editDeviceAmtSettings(nodeid, func) { + function editDeviceAmtSettings(nodeid, func, arg) { if (xxdialogMode) return; var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid); if ((meshrights & 4) == 0) return; @@ -10197,7 +10197,7 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this x += addHtmlValue('Password', ''); x += addHtmlValue('Security', ''); if ((node.intelamt.user != null) && (node.intelamt.user != '')) { buttons = 7; } - setDialogMode(2, "Edit Intel® AMT credentials", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func }); + setDialogMode(2, "Edit Intel® AMT credentials", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func, arg: arg }); if ((node.intelamt.user != null) && (node.intelamt.user != '')) { Q('dp10username').value = node.intelamt.user; } else { Q('dp10username').value = 'admin'; } Q('dp10tls').value = node.intelamt.tls; validateDeviceAmtSettings(); @@ -10220,7 +10220,7 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: amtuser, pass: amtpass, tls: Q('dp10tls').value } }); tag.node.intelamt.user = amtuser; tag.node.intelamt.tls = Q('dp10tls').value; - if (tag.func) { setTimeout(tag.func, 300); } + if (tag.func) { setTimeout(function () { tag.func(null, tag.arg); }, 300); } } } @@ -10519,7 +10519,7 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this desktopNode = currentNode; if (contype == 2) { // Setup the Intel AMT remote desktop - if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop); return; } + if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop, 2); return; } desktop = CreateAmtRedirect(CreateAmtRemoteDesktop('Desk'), authCookie); desktop.debugmode = debugmode; desktop.onStateChanged = onDesktopStateChange; @@ -11111,7 +11111,7 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this if (!terminal) { if (contype == 2) { // Setup the Intel AMT terminal - if ((terminalNode.intelamt.user == null) || (terminalNode.intelamt.user == '')) { editDeviceAmtSettings(terminalNode._id, connectTerminal); return; } + if ((terminalNode.intelamt.user == null) || (terminalNode.intelamt.user == '')) { editDeviceAmtSettings(terminalNode._id, connectTerminal, 2); return; } var termoptions = {}; if (Q('termSizeList').value == 2) { termoptions.width = 100; termoptions.height = 30; } terminal = CreateAmtRedirect(CreateAmtRemoteTerminal('Term', termoptions), authCookie); diff --git a/views/default.handlebars b/views/default.handlebars index 5d2ee2bf..ef754224 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -4141,7 +4141,7 @@ function addDeviceAttribute(name, value) { return '' + name + '' + value + ''; } - function editDeviceAmtSettings(nodeid, func) { + function editDeviceAmtSettings(nodeid, func, arg) { if (xxdialogMode) return; var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid); if ((meshrights & 4) == 0) return; @@ -4149,7 +4149,7 @@ x += addHtmlValue('Password', ''); x += addHtmlValue('Security', ''); if ((node.intelamt.user != null) && (node.intelamt.user != '')) { buttons = 7; } - setDialogMode(2, "Edit Intel® AMT credentials", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func }); + setDialogMode(2, "Edit Intel® AMT credentials", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func, arg: arg }); if ((node.intelamt.user != null) && (node.intelamt.user != '')) { Q('dp10username').value = node.intelamt.user; } else { Q('dp10username').value = 'admin'; } Q('dp10tls').value = node.intelamt.tls; validateDeviceAmtSettings(); @@ -4172,7 +4172,7 @@ meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: amtuser, pass: amtpass, tls: Q('dp10tls').value } }); tag.node.intelamt.user = amtuser; tag.node.intelamt.tls = Q('dp10tls').value; - if (tag.func) { setTimeout(tag.func, 300); } + if (tag.func) { setTimeout(function () { tag.func(null, tag.arg); }, 300); } } } @@ -4471,7 +4471,7 @@ desktopNode = currentNode; if (contype == 2) { // Setup the Intel AMT remote desktop - if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop); return; } + if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop, 2); return; } desktop = CreateAmtRedirect(CreateAmtRemoteDesktop('Desk'), authCookie); desktop.debugmode = debugmode; desktop.onStateChanged = onDesktopStateChange; @@ -5063,7 +5063,7 @@ if (!terminal) { if (contype == 2) { // Setup the Intel AMT terminal - if ((terminalNode.intelamt.user == null) || (terminalNode.intelamt.user == '')) { editDeviceAmtSettings(terminalNode._id, connectTerminal); return; } + if ((terminalNode.intelamt.user == null) || (terminalNode.intelamt.user == '')) { editDeviceAmtSettings(terminalNode._id, connectTerminal, 2); return; } var termoptions = {}; if (Q('termSizeList').value == 2) { termoptions.width = 100; termoptions.height = 30; } terminal = CreateAmtRedirect(CreateAmtRemoteTerminal('Term', termoptions), authCookie); diff --git a/webserver.js b/webserver.js index 6cdef490..bcba5579 100644 --- a/webserver.js +++ b/webserver.js @@ -261,7 +261,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { invalidMeshTypeCount: 0, invalidDomainMesh2Count: 0, invalidMeshType2Count: 0, - duplicateAgentCount: 0 + duplicateAgentCount: 0, + maxDomainDevicesReached: 0 } obj.getAgentStats = function () { return obj.agentStats; }