diff --git a/meshcentral-config-schema.json b/meshcentral-config-schema.json
index 946d38d3..c2922f7f 100644
--- a/meshcentral-config-schema.json
+++ b/meshcentral-config-schema.json
@@ -40,6 +40,7 @@
"agentAliasDNS": { "type": "string", "format": "hostname", "description": "When set, specified the DNS name used by agents to connect to the agent-only port." },
"agentPortTls": { "type": "boolean", "default": true, "description": "Indicates if the agent-only port must perform TLS, this should be set to false if TLS is performed in front of this server." },
"agentCoreDump": { "type": "boolean", "default": false, "description": "Automatically activates and transfers any agent crash dump files to the server in meshcentral-data/coredumps." },
+ "agentCoreDumpUsers": { "type": "array", "description": "List of non-administrator users that have access to mesh agent crash dumps." },
"exactPorts": { "type": "boolean", "default": false },
"allowLoginToken": { "type": "boolean", "default": false },
"allowFraming": { "type": "boolean", "default": false, "description": "When enabled, the MeshCentral web site can be embedded within another website's iframe." },
diff --git a/meshdesktopmultiplex.js b/meshdesktopmultiplex.js
index a0f40b0a..35a33b50 100644
--- a/meshdesktopmultiplex.js
+++ b/meshdesktopmultiplex.js
@@ -486,7 +486,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
var cmd = Buffer.alloc(10);
cmd.writeUInt16BE(5, 0); // Command 5, compression
cmd.writeUInt16BE(10, 2); // Command size, 10 bytes long
- cmd[4] = 1; // Image type, 1 = JPEN
+ cmd[4] = 1; // Image type, 1 = JPEG
cmd[5] = obj.imageCompression; // Image compression level
cmd.writeUInt16BE(obj.imageScaling, 6); // Scaling level
cmd.writeUInt16BE(obj.imageFrameRate, 8); // Frame rate timer
diff --git a/public/scripts/agent-desktop-0.0.2.js b/public/scripts/agent-desktop-0.0.2.js
index ab2b31b0..8cc36515 100644
--- a/public/scripts/agent-desktop-0.0.2.js
+++ b/public/scripts/agent-desktop-0.0.2.js
@@ -100,7 +100,7 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) {
}
obj.send = function (x) {
- if (obj.debugmode > 1) { console.log("KSend(" + x.length + "): " + rstr2hex(x)); }
+ if (obj.debugmode > 2) { console.log("KSend(" + x.length + "): " + rstr2hex(x)); }
if (obj.parent != null) { obj.parent.send(x); }
}
@@ -156,13 +156,13 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) {
}
obj.SendUnPause = function () {
- //obj.Debug("SendUnPause");
+ if (obj.debugmode > 1) { console.log("SendUnPause"); }
//obj.xxStateChange(3);
obj.send(String.fromCharCode(0x00, 0x08, 0x00, 0x05, 0x00));
}
obj.SendPause = function () {
- //obj.Debug("SendPause");
+ if (obj.debugmode > 1) { console.log("SendPause"); }
//obj.xxStateChange(2);
obj.send(String.fromCharCode(0x00, 0x08, 0x00, 0x05, 0x01));
}
@@ -196,7 +196,7 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) {
obj.ProcessBinaryCommand = function (cmd, cmdsize, view) {
var X, Y;
if ((cmd == 3) || (cmd == 4) || (cmd == 7)) { X = (view[4] << 8) + view[5]; Y = (view[6] << 8) + view[7]; }
- //console.log('CMD', cmd, cmdsize, X, Y);
+ if (obj.debugmode > 2) { console.log('CMD', cmd, cmdsize, X, Y); }
// Record the command if needed
if (obj.recordedData != null) {
@@ -250,7 +250,7 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) {
break;
case 17: // MNG_KVM_MESSAGE
var str = String.fromCharCode.apply(null, data.slice(4));
- obj.Debug("Got KVM Message: " + str);
+ console.log("Got KVM Message: " + str);
if (obj.onMessage != null) obj.onMessage(str, obj);
break;
case 65: // Alert
@@ -502,7 +502,7 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) {
if (obj.onScreenSizeChange != null) obj.onScreenSizeChange(obj, obj.ScreenWidth, obj.ScreenHeight, obj.CanvasId);
}
obj.FirstDraw = false;
- //obj.Debug("onResize: " + obj.ScreenWidth + " x " + obj.ScreenHeight);
+ if (obj.debugmode > 1) { console.log("onResize: " + obj.ScreenWidth + " x " + obj.ScreenHeight); }
}
obj.xxMouseInputGrab = false;
diff --git a/webserver.js b/webserver.js
index 7e853267..fbca1886 100644
--- a/webserver.js
+++ b/webserver.js
@@ -4265,19 +4265,92 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if (domain == null) return;
if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
if ((req.session == null) || (req.session.userid == null)) { res.sendStatus(404); return; }
+ var user = null, coreDumpsAllowed = false;
+ if (typeof req.session.userid == 'string') { user = obj.users[req.session.userid]; }
+ if (user == null) { res.sendStatus(404); return; }
+
+ // Check if this user has access to agent core dumps
+ if ((obj.parent.config.settings.agentcoredump === true) && ((user.siteadmin == 0xFFFFFFFF) || ((Array.isArray(obj.parent.config.settings.agentcoredumpusers)) && (obj.parent.config.settings.agentcoredumpusers.indexOf(user._id) >= 0)))) {
+ coreDumpsAllowed = true;
+
+ if ((req.query.dldump != null) && obj.common.IsFilenameValid(req.query.dldump)) {
+ // Download a dump file
+ var dumpFile = obj.path.join(parent.datapath, '..', 'meshcentral-coredumps', req.query.dldump);
+ if (obj.fs.existsSync(dumpFile)) {
+ res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/zip', 'Content-Disposition': 'attachment; filename="' + req.query.dldump + '' });
+ res.sendFile(dumpFile); return;
+ } else {
+ res.sendStatus(404); return;
+ }
+ }
+
+ if ((req.query.deldump != null) && obj.common.IsFilenameValid(req.query.deldump)) {
+ // Delete a dump file
+ try { obj.fs.unlinkSync(obj.path.join(parent.datapath, '..', 'meshcentral-coredumps', req.query.deldump)); } catch (ex) { console.log(ex); }
+ }
+
+ if ((req.query.dumps != null) || (req.query.deldump != null)) {
+ // Send list of agent core dumps
+ var response = '
Mesh Agents Core Dumps';
+ response += 'ID | Upload Date | Description | Current | Dump | Size | Agent | Agent SHA384 | NodeID | |
';
+
+ var coreDumpPath = obj.path.join(parent.datapath, '..', 'meshcentral-coredumps');
+ if (obj.fs.existsSync(coreDumpPath)) {
+ var files = obj.fs.readdirSync(coreDumpPath);
+ var coredumps = [];
+ for (var i in files) {
+ var file = files[i];
+ if (file.endsWith('.dmp')) {
+ var fileSplit = file.substring(0, file.length - 4).split('-');
+ if (fileSplit.length == 3) {
+ var agentid = parseInt(fileSplit[0]);
+ if ((isNaN(agentid) == false) && (obj.parent.meshAgentBinaries[agentid] != null)) {
+ var agentinfo = obj.parent.meshAgentBinaries[agentid];
+ var filestats = obj.fs.statSync(obj.path.join(parent.datapath, '..', 'meshcentral-coredumps', file));
+ coredumps.push({
+ fileSplit: fileSplit,
+ agentinfo: agentinfo,
+ filestats: filestats,
+ currentAgent: agentinfo.hashhex.startsWith(fileSplit[1].toLowerCase()),
+ downloadUrl: req.originalUrl.split('?')[0] + '?dldump=' + file + (req.query.key ? ('&key=' + req.query.key) : ''),
+ deleteUrl: req.originalUrl.split('?')[0] + '?deldump=' + file + (req.query.key ? ('&key=' + req.query.key) : ''),
+ agentUrl: req.originalUrl.split('?')[0] + '?id=' + agentinfo.id + (req.query.key ? ('&key=' + req.query.key) : ''),
+ time: new Date(filestats.ctime)
+ });
+ }
+ }
+ }
+ }
+ coredumps.sort(function (a, b) { if (a.time > b.time) return -1; if (a.time < b.time) return 1; return 0; });
+ for (var i in coredumps) {
+ var d = coredumps[i];
+ response += '' + d.agentinfo.id + ' | ' + d.time.toDateString().split(' ').join(' ') + ' | ' + d.agentinfo.desc.split(' ').join(' ') + ' | ';
+ response += '' + d.currentAgent + ' | Download | ' + d.filestats.size + ' | ';
+ if (d.currentAgent) { response += 'Download | '; } else { response += ' | '; }
+ response += '' + d.fileSplit[1].toLowerCase() + ' | ' + d.fileSplit[2] + ' | Delete |
';
+ }
+ }
+ response += '
Mesh Agents';
+ res.send(response);
+ return;
+ }
+ }
// Send a list of available mesh agents
- var response = 'Mesh Agents';
+ var response = 'Mesh Agents';
response += 'ID | Description | Link | Size | SHA384 | MeshCmd |
';
+ var originalUrl = req.originalUrl.split('?')[0];
for (var agentid in obj.parent.meshAgentBinaries) {
+ if (agentid >= 10000) continue;
var agentinfo = obj.parent.meshAgentBinaries[agentid];
- var originalUrl = req.originalUrl.split('?')[0];
- response += '' + agentinfo.id + ' | ' + agentinfo.desc + ' | ';
+ response += '
' + agentinfo.id + ' | ' + agentinfo.desc.split(' ').join(' ') + ' | ';
response += '' + agentinfo.rname + ' | ';
response += '' + agentinfo.size + ' | ' + agentinfo.hashhex + ' | ';
response += '' + agentinfo.rname.replace('agent', 'cmd') + ' |
';
}
- response += '
';
+ response += '
';
+ if (coreDumpsAllowed) { response += 'MeshAgent Crash Dumps'; }
+ response += '';
res.send(response);
}
};