diff --git a/meshuser.js b/meshuser.js
index 2182fbed..b0f954bb 100644
--- a/meshuser.js
+++ b/meshuser.js
@@ -470,7 +470,26 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
switch (cmd) {
case 'help': {
- r = 'Available commands: help, args, resetserver, showconfig, usersessions, tasklimiter, setmaxtasks, cores, migrationagents, swarmstats.';
+ r = 'Available commands: help, info, versions, args, resetserver, showconfig, usersessions, tasklimiter, setmaxtasks, cores, migrationagents, swarmstats, nodeconfig.';
+ break;
+ }
+ case 'info': {
+ var info = process.memoryUsage();
+ try { info.platform = process.platform; } catch (ex) { }
+ try { info.arch = process.arch; } catch (ex) { }
+ try { info.pid = process.pid; } catch (ex) { }
+ try { info.uptime = process.uptime(); } catch (ex) { }
+ try { info.version = process.version; } catch (ex) { }
+ try { info.cpuUsage = process.cpuUsage(); } catch (ex) { }
+ r = JSON.stringify(info, null, 4);
+ break;
+ }
+ case 'nodeconfig': {
+ r = JSON.stringify(process.config, null, 4);
+ break;
+ }
+ case 'versions': {
+ r = JSON.stringify(process.versions, null, 4);
break;
}
case 'args': {
diff --git a/package.json b/package.json
index f61821b6..bd36b848 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "meshcentral",
- "version": "0.2.9-p",
+ "version": "0.2.9-q",
"keywords": [
"Remote Management",
"Intel AMT",
diff --git a/swarmserver.js b/swarmserver.js
index beb268ae..80e24d4d 100644
--- a/swarmserver.js
+++ b/swarmserver.js
@@ -146,6 +146,162 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
}
}
+ function onData(data) {
+ if (this.relaySocket) { var ps = this; try { this.relaySocket.write(data, 'binary', function () { ps.resume(); }); } catch (ex) { } return; }
+ if (args.swarmdebug) { var buf = Buffer.from(data, "binary"); console.log('SWARM <-- (' + buf.length + '):' + buf.toString('hex')); } // Print out received bytes
+ obj.stats.bytesIn += data.length;
+ this.tag.accumulator += data;
+
+ // Detect if this is an HTTPS request, if it is, return a simple answer and disconnect. This is useful for debugging access to the MPS port.
+ if (this.tag.first == true) {
+ if (this.tag.accumulator.length < 3) return;
+ if ((this.tag.accumulator.substring(0, 3) == 'GET') || (this.tag.accumulator.substring(0, 3) == 'POS')) {
+ obj.stats.httpGetRequest++;
+ /*console.log("Swarm Connection, HTTP GET detected: " + socket.remoteAddress);*/
+ //socket.write('HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n
MeshCentral2 legacy swarm server.
MeshCentral1 mesh agents should connect here for updates.');
+ //socket.end();
+
+ // Relay this connection to the main TLS port
+ this.pause();
+ var relaySocket = tls.connect(obj.args.port, { rejectUnauthorized: false }, function () { this.write(this.parentSocket.tag.accumulator); this.parentSocket.resume(); });
+ relaySocket.on('data', function (data) { try { var rs = this; this.pause(); this.parentSocket.write(data, 'binary', function () { rs.resume(); }); } catch (ex) { } });
+ relaySocket.on('error', function (err) { try { this.parentSocket.end(); } catch (ex) { } });
+ relaySocket.on('end', function () { try { this.parentSocket.end(); } catch (ex) { } });
+ this.relaySocket = relaySocket;
+ relaySocket.parentSocket = this;
+ return;
+ }
+ this.tag.first = false;
+ }
+
+ // A client certificate is required
+ if ((this.tag.clientCert == null) || (this.tag.clientCert.subject == null)) {
+ /*console.log("Swarm Connection, no client cert: " + socket.remoteAddress);*/
+ this.write('HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nMeshCentral2 legacy swarm server.\r\nNo client certificate given.');
+ this.end();
+ return;
+ }
+
+ try {
+ // Parse all of the agent binary command data we can
+ var l = 0;
+ do { l = ProcessCommand(this); if (l > 0) { this.tag.accumulator = this.tag.accumulator.substring(l); } } while (l > 0);
+ if (l < 0) { this.end(); }
+ } catch (e) {
+ console.log(e);
+ }
+ }
+
+ // Process one AFP command
+ function ProcessCommand(socket) {
+ if (socket.tag.accumulator.length < 4) return 0;
+ var cmd = common.ReadShort(socket.tag.accumulator, 0);
+ var len = common.ReadShort(socket.tag.accumulator, 2);
+ if (len > socket.tag.accumulator.length) return 0;
+ var data = socket.tag.accumulator.substring(4, len);
+ //console.log('Swarm: Cmd=' + cmd + ', Len=' + len + '.');
+
+ switch (cmd) {
+ case LegacyMeshProtocol.NODEPUSH: {
+ Debug(3, 'Swarm:NODEPUSH');
+ var nodeblock = obj.decodeNodeBlock(data);
+ if ((nodeblock != null) && (nodeblock.agenttype != null) && (nodeblock.agentversion != null)) {
+ if (socket.pingTimer == null) { socket.pingTimer = setInterval(function () { obj.SendCommand(socket, LegacyMeshProtocol.PING); }, 20000); }
+ Debug(3, 'Swarm:NODEPUSH:' + JSON.stringify(nodeblock));
+
+ // Check if this agent is asking of updates over and over again.
+ var actionCount = obj.agentActionCount[nodeblock.nodeidhex];
+ if (actionCount == null) { actionCount = 0; }
+ if (actionCount > 2) {
+ // Already tried to update this agent two times, something is not right.
+ //console.log('SWARM: ' + actionCount + ' update actions on ' + nodeblock.nodeidhex + ', holding.');
+ } else {
+ // Figure out what is the next agent version we need.
+ var nextAgentVersion = 0;
+ if (nodeblock.agentversion < 201) { nextAgentVersion = 201; } // If less then 201, move to transitional MC1 agent.
+ if (nodeblock.agentversion == 201) { nextAgentVersion = 202; } // If at 201, move to first MC2 agent.
+
+ // See if we need to start the agent update
+ if ((nextAgentVersion > 0) && (obj.migrationAgents[nodeblock.agenttype] != null) && (obj.migrationAgents[nodeblock.agenttype][nextAgentVersion] != null)) {
+ // Start the update
+ socket.tag.update = obj.migrationAgents[nodeblock.agenttype][nextAgentVersion];
+ socket.tag.updatePtr = 0;
+ //console.log('Performing legacy agent update from ' + nodeblock.agentversion + '.' + nodeblock.agenttype + ' to ' + socket.tag.update.ver + '.' + socket.tag.update.arch + ' on ' + nodeblock.agentname + '.');
+
+ // Update stats
+ if (obj.stats.pushedAgents[nodeblock.agenttype] == null) { obj.stats.pushedAgents[nodeblock.agenttype] = {}; }
+ if (obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion] == null) { obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion] = 0; } else { obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion]++; }
+
+ // Start the agent download using the task limiter so not to flood the server. Low priority task
+ obj.parent.taskLimiter.launch(function (socket, taskid, taskLimiterQueue) {
+ if (socket.xclosed == 1) {
+ // Socket is closed, do nothing
+ obj.parent.taskLimiter.completed(taskid); // Indicate this task complete
+ } else {
+ // Start the agent update
+ socket.tag.taskid = taskid;
+ obj.SendCommand(socket, LegacyMeshProtocol.GETSTATE, common.IntToStr(5) + common.IntToStr(0)); // agent.SendQuery(5, 0); // Start the agent download
+ }
+ }, socket, 2);
+ } else {
+ //console.log('No legacy agent update for ' + nodeblock.agentversion + '.' + nodeblock.agenttype + ' on ' + nodeblock.agentname + '.');
+ }
+ }
+
+ // Mark this agent
+ obj.agentActionCount[nodeblock.nodeidhex] = ++actionCount;
+ }
+ break;
+ }
+ case LegacyMeshProtocol.AMTPROVISIONING: {
+ Debug(3, 'Swarm:AMTPROVISIONING');
+ obj.SendCommand(socket, LegacyMeshProtocol.AMTPROVISIONING, common.ShortToStr(1));
+ break;
+ }
+ case LegacyMeshProtocol.GETSTATE: {
+ Debug(3, 'Swarm:GETSTATE');
+ if (len < 12) break;
+ var statecmd = common.ReadInt(data, 0);
+ //var statesync = common.ReadInt(data, 4);
+ switch (statecmd) {
+ case 6: { // Ask for agent block
+ if (socket.tag.update != null) {
+ // Send an agent block
+ var l = Math.min(socket.tag.update.binary.length - socket.tag.updatePtr, 16384);
+ obj.SendCommand(socket, LegacyMeshProtocol.GETSTATE, common.IntToStr(6) + common.IntToStr(socket.tag.updatePtr) + socket.tag.update.binary.toString('binary', socket.tag.updatePtr, socket.tag.updatePtr + l)); // agent.SendQuery(6, AgentFileLen + AgentBlock);
+ Debug(3, 'Swarm:Sending agent block, ptr = ' + socket.tag.updatePtr + ', len = ' + l);
+
+ socket.tag.updatePtr += l;
+ if (socket.tag.updatePtr >= socket.tag.update.binary.length) {
+ // Send end-of-transfer
+ obj.SendCommand(socket, LegacyMeshProtocol.GETSTATE, common.IntToStr(7) + common.IntToStr(socket.tag.update.binary.length)); //agent.SendQuery(7, AgentFileLen);
+ Debug(3, 'Swarm:Sending end of agent, ptr = ' + socket.tag.updatePtr);
+ obj.parent.taskLimiter.completed(socket.tag.taskid); // Indicate this task complete
+ delete socket.tag.taskid;
+ delete socket.tag.update;
+ delete socket.tag.updatePtr;
+ }
+ }
+ break;
+ }
+ default: {
+ // All other state commands from the legacy agent must be ignored.
+ break;
+ }
+ }
+ break;
+ }
+ case LegacyMeshProtocol.APPSUBSCRIBERS: {
+ Debug(3, 'Swarm:APPSUBSCRIBERS');
+ break;
+ }
+ default: {
+ Debug(1, 'Swarm:Unknown command: ' + cmd + ' of len ' + len + '.');
+ }
+ }
+ return len;
+ }
+
// Called when a legacy agent connects to this server
function onConnection(socket) {
// Check for blocked IP address
@@ -153,164 +309,20 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
obj.stats.connectCount++;
socket.tag = { first: true, clientCert: socket.getPeerCertificate(true), accumulator: "", socket: socket };
- socket.setEncoding('binary');
- socket.pingTimer = setInterval(function () { obj.SendCommand(socket, LegacyMeshProtocol.PING); }, 20000);
+ //socket.pingTimer = setInterval(function () { obj.SendCommand(socket, LegacyMeshProtocol.PING); }, 20000);
Debug(1, 'SWARM:New legacy agent connection');
if ((socket.tag.clientCert == null) || (socket.tag.clientCert.subject == null)) { obj.stats.noCertConnectCount++; } else { obj.stats.clientCertConnectCount++; }
- socket.addListener("data", function (data) {
- if (args.swarmdebug) { var buf = Buffer.from(data, "binary"); console.log('SWARM <-- (' + buf.length + '):' + buf.toString('hex')); } // Print out received bytes
- obj.stats.bytesIn += data.length;
- socket.tag.accumulator += data;
-
- // Detect if this is an HTTPS request, if it is, return a simple answer and disconnect. This is useful for debugging access to the MPS port.
- if (socket.tag.first == true) {
- if (socket.tag.accumulator.length < 3) return;
- if (socket.tag.accumulator.substring(0, 3) == 'GET') {
- obj.stats.httpGetRequest++;
- /*console.log("Swarm Connection, HTTP GET detected: " + socket.remoteAddress);*/
- socket.write('HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\nMeshCentral2 legacy swarm server.
MeshCentral1 mesh agents should connect here for updates.');
- socket.end();
- return;
- }
- socket.tag.first = false;
- }
-
- // A client certificate is required
- if ((socket.tag.clientCert == null) || (socket.tag.clientCert.subject == null)) {
- /*console.log("Swarm Connection, no client cert: " + socket.remoteAddress);*/
- socket.write('HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nMeshCentral2 legacy swarm server.\r\nNo client certificate given.');
- socket.end();
- return;
- }
-
- try {
- // Parse all of the agent binary command data we can
- var l = 0;
- do { l = ProcessCommand(socket); if (l > 0) { socket.tag.accumulator = socket.tag.accumulator.substring(l); } } while (l > 0);
- if (l < 0) { socket.end(); }
- } catch (e) {
- console.log(e);
- }
- });
-
- // Process one AFP command
- function ProcessCommand(socket) {
- if (socket.tag.accumulator.length < 4) return 0;
- var cmd = common.ReadShort(socket.tag.accumulator, 0);
- var len = common.ReadShort(socket.tag.accumulator, 2);
- if (len > socket.tag.accumulator.length) return 0;
- var data = socket.tag.accumulator.substring(4, len);
- //console.log('Swarm: Cmd=' + cmd + ', Len=' + len + '.');
-
- switch (cmd) {
- case LegacyMeshProtocol.NODEPUSH: {
- Debug(3, 'Swarm:NODEPUSH');
- var nodeblock = obj.decodeNodeBlock(data);
- if ((nodeblock != null) && (nodeblock.agenttype != null) && (nodeblock.agentversion != null)) {
- Debug(3, 'Swarm:NODEPUSH:' + JSON.stringify(nodeblock));
-
- // Check if this agent is asking of updates over and over again.
- var actionCount = obj.agentActionCount[nodeblock.nodeidhex];
- if (actionCount == null) { actionCount = 0; }
- if (actionCount > 2) {
- // Already tried to update this agent two times, something is not right.
- //console.log('SWARM: ' + actionCount + ' update actions on ' + nodeblock.nodeidhex + ', holding.');
- } else {
- // Figure out what is the next agent version we need.
- var nextAgentVersion = 0;
- if (nodeblock.agentversion < 201) { nextAgentVersion = 201; } // If less then 201, move to transitional MC1 agent.
- if (nodeblock.agentversion == 201) { nextAgentVersion = 202; } // If at 201, move to first MC2 agent.
-
- // See if we need to start the agent update
- if ((nextAgentVersion > 0) && (obj.migrationAgents[nodeblock.agenttype] != null) && (obj.migrationAgents[nodeblock.agenttype][nextAgentVersion] != null)) {
- // Start the update
- socket.tag.update = obj.migrationAgents[nodeblock.agenttype][nextAgentVersion];
- socket.tag.updatePtr = 0;
- //console.log('Performing legacy agent update from ' + nodeblock.agentversion + '.' + nodeblock.agenttype + ' to ' + socket.tag.update.ver + '.' + socket.tag.update.arch + ' on ' + nodeblock.agentname + '.');
-
- // Update stats
- if (obj.stats.pushedAgents[nodeblock.agenttype] == null) { obj.stats.pushedAgents[nodeblock.agenttype] = {}; }
- if (obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion] == null) { obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion] = 0; } else { obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion]++; }
-
- // Start the agent download using the task limiter so not to flood the server. Low priority task
- obj.parent.taskLimiter.launch(function (socket, taskid, taskLimiterQueue) {
- if (socket.xclosed == 1) {
- // Socket is closed, do nothing
- obj.parent.taskLimiter.completed(taskid); // Indicate this task complete
- } else {
- // Start the agent update
- socket.tag.taskid = taskid;
- obj.SendCommand(socket, LegacyMeshProtocol.GETSTATE, common.IntToStr(5) + common.IntToStr(0)); // agent.SendQuery(5, 0); // Start the agent download
- }
- }, socket, 2);
- } else {
- //console.log('No legacy agent update for ' + nodeblock.agentversion + '.' + nodeblock.agenttype + ' on ' + nodeblock.agentname + '.');
- }
- }
-
- // Mark this agent
- obj.agentActionCount[nodeblock.nodeidhex] = ++actionCount;
- }
- break;
- }
- case LegacyMeshProtocol.AMTPROVISIONING: {
- Debug(3, 'Swarm:AMTPROVISIONING');
- obj.SendCommand(socket, LegacyMeshProtocol.AMTPROVISIONING, common.ShortToStr(1));
- break;
- }
- case LegacyMeshProtocol.GETSTATE: {
- Debug(3, 'Swarm:GETSTATE');
- if (len < 12) break;
- var statecmd = common.ReadInt(data, 0);
- //var statesync = common.ReadInt(data, 4);
- switch (statecmd) {
- case 6: { // Ask for agent block
- if (socket.tag.update != null) {
- // Send an agent block
- var l = Math.min(socket.tag.update.binary.length - socket.tag.updatePtr, 16384);
- obj.SendCommand(socket, LegacyMeshProtocol.GETSTATE, common.IntToStr(6) + common.IntToStr(socket.tag.updatePtr) + socket.tag.update.binary.toString('binary', socket.tag.updatePtr, socket.tag.updatePtr + l)); // agent.SendQuery(6, AgentFileLen + AgentBlock);
- Debug(3, 'Swarm:Sending agent block, ptr = ' + socket.tag.updatePtr + ', len = ' + l);
-
- socket.tag.updatePtr += l;
- if (socket.tag.updatePtr >= socket.tag.update.binary.length) {
- // Send end-of-transfer
- obj.SendCommand(socket, LegacyMeshProtocol.GETSTATE, common.IntToStr(7) + common.IntToStr(socket.tag.update.binary.length)); //agent.SendQuery(7, AgentFileLen);
- Debug(3, 'Swarm:Sending end of agent, ptr = ' + socket.tag.updatePtr);
- obj.parent.taskLimiter.completed(socket.tag.taskid); // Indicate this task complete
- delete socket.tag.taskid;
- delete socket.tag.update;
- delete socket.tag.updatePtr;
- }
- }
- break;
- }
- default: {
- // All other state commands from the legacy agent must be ignored.
- break;
- }
- }
- break;
- }
- case LegacyMeshProtocol.APPSUBSCRIBERS: {
- Debug(3, 'Swarm:APPSUBSCRIBERS');
- break;
- }
- default: {
- Debug(1, 'Swarm:Unknown command: ' + cmd + ' of len ' + len + '.');
- }
- }
- return len;
- }
-
+ socket.addListener("data", onData);
socket.addListener("close", function () {
obj.stats.onclose++;
Debug(1, 'Swarm:Connection closed');
- if (socket.pingTimer != null) { clearInterval(socket.pingTimer); delete socket.pingTimer; }
- if (socket.tag && (typeof socket.tag.taskid == 'number')) {
- obj.parent.taskLimiter.completed(socket.tag.taskid); // Indicate this task complete
- delete socket.tag.taskid;
+ if (this.relaySocket) { try { this.relaySocket.end(); delete this.relaySocket; } catch (ex) { } }
+ if (this.pingTimer != null) { clearInterval(this.pingTimer); delete this.pingTimer; }
+ if (this.tag && (typeof this.tag.taskid == 'number')) {
+ obj.parent.taskLimiter.completed(this.tag.taskid); // Indicate this task complete
+ delete this.tag.taskid;
}
});
diff --git a/views/default-min.handlebars b/views/default-min.handlebars
index a78be275..fee51405 100644
--- a/views/default-min.handlebars
+++ b/views/default-min.handlebars
@@ -1 +1 @@
- MeshCentral ↔
My Devices | My Account | My Events | My Files | My Users | My Server | |
General | Desktop | Terminal | Files | Events | Intel® AMT | Console | |
Server disconnected, click to reconnect.
My Account
Device Groups (
New )
My Files
These files are shared publicly, click "link" to get public url.
✓
✗
My Server
Server actions
Server Statistics
Intel® AMT Redirection port or KVM feature is disabled, click here to enable it.
Remote computer is not powered on, click here to issue a power command.
Intel® AMT Redirection port or KVM feature is disabled, click here to enable it.
Remote computer is not powered on, click here to issue a power command.
Show
General -
Events -
Show
File Selection
Agent Remote Desktop
Scaling
Frame rate
Intel® AMT Hardware KVM
Image Encoding
\ No newline at end of file
+ MeshCentral ↔
My Devices | My Account | My Events | My Files | My Users | My Server | |
General | Desktop | Terminal | Files | Events | Intel® AMT | Console | |
Server disconnected, click to reconnect.
My Account
Device Groups (
New )
My Files
These files are shared publicly, click "link" to get public url.
✓
✗
My Server
Server actions
Server Statistics
Intel® AMT Redirection port or KVM feature is disabled, click here to enable it.
Remote computer is not powered on, click here to issue a power command.
Intel® AMT Redirection port or KVM feature is disabled, click here to enable it.
Remote computer is not powered on, click here to issue a power command.
Show
General -
Events -
Show
File Selection
Agent Remote Desktop
Scaling
Frame rate
Intel® AMT Hardware KVM
Image Encoding
\ No newline at end of file
diff --git a/views/default.handlebars b/views/default.handlebars
index 66f372f9..a6aa01c6 100644
--- a/views/default.handlebars
+++ b/views/default.handlebars
@@ -3494,7 +3494,7 @@
else if ((node.intelamt.ver == null) || (node.intelamt.state == null)) { str += 'Unknown Version & State'; }
else {
str += provisioningStates[node.intelamt.state];
- if (node.intelamt.flags) { if (node.intelamt.flags & 2) { str += ' CCM'; } else if (node.intelamt.flags & 4) { str += ' ACM'; } }
+ if ((node.intelamt.state == 2) && node.intelamt.flags) { if (node.intelamt.flags & 2) { str += ' CCM'; } else if (node.intelamt.flags & 4) { str += ' ACM'; } }
str += (', v' + node.intelamt.ver);
}
diff --git a/webserver.js b/webserver.js
index 098e3146..30bed838 100644
--- a/webserver.js
+++ b/webserver.js
@@ -313,7 +313,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
// Destroy the user's session to log them out will be re-created next request
if (req.session.userid) {
var user = obj.users[req.session.userid];
- obj.parent.DispatchEvent(['*'], obj, { etype: 'user', username: user.name, action: 'logout', msg: 'Account logout', domain: domain.id });
+ if (user != null) { obj.parent.DispatchEvent(['*'], obj, { etype: 'user', username: user.name, action: 'logout', msg: 'Account logout', domain: domain.id }); }
}
req.session = null;
res.redirect(domain.url);