From de80661037eccbfaafe0a1e5333faa201f796a57 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Wed, 7 Jul 2021 15:49:18 -0700 Subject: [PATCH 1/2] First version of Intel AMT RPE support in MeshCMD. --- agents/MeshCmd-signed.exe | Bin 4175072 -> 4185344 bytes agents/MeshCmd64-signed.exe | Bin 3789536 -> 3799808 bytes agents/meshcmd.js | 153 ++++++++++++++++++++++++++++++++++ agents/modules_meshcmd/amt.js | 1 + 4 files changed, 154 insertions(+) diff --git a/agents/MeshCmd-signed.exe b/agents/MeshCmd-signed.exe index db912e6db5ce4a2250ba7ba2f7019a9e6af5644b..539c87a8fd11c0c8f840b7c89696fe777507c54f 100644 GIT binary patch delta 7031 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 d9`1IilEQb~>gme*_NzBeex0dMf4^#h delta 1313 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 8) & 0xFF, (v >> 16) & 0xFF, (v >> 24) & 0xFF); } +function ShortToStrX(v) { return String.fromCharCode(v & 0xFF, (v >> 8) & 0xFF); } + // // Intel AMT feature configuration action // diff --git a/agents/modules_meshcmd/amt.js b/agents/modules_meshcmd/amt.js index 22124358..e99e54a6 100644 --- a/agents/modules_meshcmd/amt.js +++ b/agents/modules_meshcmd/amt.js @@ -300,6 +300,7 @@ function AmtStackCreateService(wsmanStack) { obj.CIM_AccountManagementService_CreateAccount = function (System, AccountTemplate, callback_func) { obj.Exec("CIM_AccountManagementService", "CreateAccount", { "System": System, "AccountTemplate": AccountTemplate }, callback_func); } obj.CIM_BootConfigSetting_ChangeBootOrder = function (Source, callback_func) { obj.Exec("CIM_BootConfigSetting", "ChangeBootOrder", { "Source": Source }, callback_func); } obj.CIM_BootService_SetBootConfigRole = function (BootConfigSetting, Role, callback_func) { obj.Exec("CIM_BootService", "SetBootConfigRole", { "BootConfigSetting": BootConfigSetting, "Role": Role }, callback_func, 0, 1); } + obj.CIM_BootService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec('CIM_BootService', 'RequestStateChange', { 'RequestedState': RequestedState, 'TimeoutPeriod': TimeoutPeriod }, callback_func, 0, 1); } obj.CIM_Card_ConnectorPower = function (Connector, PoweredOn, callback_func) { obj.Exec("CIM_Card", "ConnectorPower", { "Connector": Connector, "PoweredOn": PoweredOn }, callback_func); } obj.CIM_Card_IsCompatible = function (ElementToCheck, callback_func) { obj.Exec("CIM_Card", "IsCompatible", { "ElementToCheck": ElementToCheck }, callback_func); } obj.CIM_Chassis_IsCompatible = function (ElementToCheck, callback_func) { obj.Exec("CIM_Chassis", "IsCompatible", { "ElementToCheck": ElementToCheck }, callback_func); } From 591d73cf64866b4571f0892e5c1633643ea5ba3e Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Wed, 7 Jul 2021 19:22:18 -0700 Subject: [PATCH 2/2] Refactor for #2868 --- meshuser.js | 1192 ++++++++++++++++++++++++++++----------------------- 1 file changed, 646 insertions(+), 546 deletions(-) diff --git a/meshuser.js b/meshuser.js index a03e333f..385ab73f 100644 --- a/meshuser.js +++ b/meshuser.js @@ -911,552 +911,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use const cmd = cmdargs[0].toLowerCase(); cmdargs = parseArgs(cmdargs); - switch (cmd) { - case 'help': { - var fin = '', f = '', availcommands = 'help,maintenance,info,versions,resetserver,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,agentissues,webstats,trafficstats,trafficdelta,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats,dbcounters,sms,amtacm,certhashes,watchdog,amtmanager,amtpasswords,certexpire,email'; - if (parent.parent.config.settings.heapdump === true) { availcommands += ',heapdump'; } - availcommands = availcommands.split(',').sort(); - while (availcommands.length > 0) { if (f.length > 80) { fin += (f + ',\r\n'); f = ''; } f += (((f != '') ? ', ' : ' ') + availcommands.shift()); } - if (f != '') { fin += f; } - if (cmdargs['_'].length == 0) { - r = 'Available commands: \r\n' + fin + '\r\nType help for details.'; - } else { - var cmd2 = cmdargs['_'][0].toLowerCase(); - switch (cmd2) { - case 'info': { r = "info: Returns the most immidiatly useful information about this server, including MeshCentral and NodeJS versions. This is often information required to file a bug."; break; } - case 'versions': { r = "versions: Returns all internal versions for NodeJS running this server."; break; } - case 'resetserver': { r = "resetserver: Causes the server to reset, this is sometimes useful is the config.json file was changed."; break; } - case 'usersessions': { r = "usersessions: Returns a list of active sessions grouped by user."; break; } - case 'closeusersessions': { r = "closeusersessions: Disconnects all sessions for a specified user."; break; } - case 'tasklimiter': { r = "tasklimiter: Returns the internal status of the tasklimiter. This is a system used to smooth out work done by the server. It's used by, for example, agent updates so that not all agents are updated at the same time."; break; } - case 'serverupdate': { r = "serverupdate: Updates server to latest version. Optional version argument to install specific version. Example: serverupdate 0.8.49"; break; } - default: { r = 'No help information about this command.'; break; } - } - } - break; - } - case 'certexpire': { - const now = Date.now(); - for (var i in parent.webCertificateExpire) { - const domainName = (i == '') ? '[Default]' : i; - r += domainName + ', expires in ' + Math.floor((parent.webCertificateExpire[i] - now) / 86400000) + ' day(s)\r\n'; - } - break; - } - case 'webpush': { - if (parent.parent.webpush == null) { - r = "Web push not supported."; - } else { - if (cmdargs['_'].length != 1) { - r = "Usage: WebPush \"Message\""; - } else { - const pushSubscription = { "endpoint": "https://updates.push.services.mozilla.com/wpush/v2/gAAAAABgIkO9hjXHWhMPiuk-ppNRw7r_pUZitddwCEK4ykdzeIxOIjFnYhIt_nr-qUca2mpZziwQsSEhYTUCiuYrhWnVDRweMtiUj16yJJq8V5jneaEaUYjEIe5jp3DOMNpoTm1aHgX74gCR8uTXSITcM97bNi-hRxcQ4f6Ie4WSAmoXpd89B_g", "keys": { "auth": "UB2sbLVK7ALnSHw5P1dahg", "p256dh": "BIoRbcNSxBuTjN39CCCUCHo1f4NxBJ1YDdu_k4MbPW_q3NK1_RufnydUzLPDp8ibBVItSI72-s48QJvOjQ_S8Ok" } } - parent.parent.webpush.sendNotification(pushSubscription, cmdargs['_'][0]).then( - function (value) { try { ws.send(JSON.stringify({ action: 'OK', value: r, tag: command.tag })); } catch (ex) { } }, - function (error) { try { ws.send(JSON.stringify({ action: 'Error', value: r, tag: command.tag })); } catch (ex) { } } - ); - } - } - break; - } - case 'amtmanager': { - if (parent.parent.amtManager == null) { r = 'Intel AMT Manager not active.'; } else { r = parent.parent.amtManager.getStatusString(); } - break; - } - case 'certhashes': { - r += 'AgentCertHash: ' + parent.agentCertificateHashHex; - for (var i in parent.webCertificateHashs) { r += '\r\nwebCertificateHash (' + i + '): ' + common.rstr2hex(parent.webCertificateHashs[i]); } - for (var i in parent.webCertificateFullHashs) { r += '\r\nwebCertificateFullHash (' + i + '): ' + common.rstr2hex(parent.webCertificateFullHashs[i]); } - r += '\r\ndefaultWebCertificateHash: ' + common.rstr2hex(parent.defaultWebCertificateHash); - r += '\r\ndefaultWebCertificateFullHash: ' + common.rstr2hex(parent.defaultWebCertificateFullHash); - break; - } - case 'amtacm': { - if ((domain.amtacmactivation == null) || (domain.amtacmactivation.acmmatch == null) || (domain.amtacmactivation.acmmatch.length == 0)) { - r = 'No Intel AMT activation certificates.'; - } else { - if (domain.amtacmactivation.log != null) { r += '--- Activation Log ---\r\nFile : ' + domain.amtacmactivation.log + '\r\n'; } - for (var i in domain.amtacmactivation.acmmatch) { - var acmcert = domain.amtacmactivation.acmmatch[i]; - r += '--- Activation Certificate ' + (parseInt(i) + 1) + ' ---\r\nName : ' + acmcert.cn + '\r\nSHA1 : ' + acmcert.sha1 + '\r\nSHA256: ' + acmcert.sha256 + '\r\n'; - } - } - break; - } - case 'heapdump': { - // Heapdump support, see example at: - // https://www.arbazsiddiqui.me/a-practical-guide-to-memory-leaks-in-nodejs/ - if (parent.parent.config.settings.heapdump === true) { - var dumpFileName = parent.path.join(parent.parent.datapath, `heapDump-${Date.now()}.heapsnapshot`); - try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Generating dump file at: " + dumpFileName, tag: command.tag })); } catch (ex) { } - require('heapdump').writeSnapshot(dumpFileName, (err, filename) => { - try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Done.", tag: command.tag })); } catch (ex) { } - }); - } else { - r = "Heapdump not supported, add \"heapdump\":true to settings section of config.json."; - } - break; - } - case 'sms': { - if (parent.parent.smsserver == null) { - r = "No SMS gateway in use."; - } else { - if (cmdargs['_'].length != 2) { - r = "Usage: SMS \"PhoneNumber\" \"Message\"."; - } else { - parent.parent.smsserver.sendSMS(cmdargs['_'][0], cmdargs['_'][1], function (status, msg) { - if (typeof msg == 'string') { - try { ws.send(JSON.stringify({ action: 'serverconsole', value: status ? ('Success: ' + msg) : ('Failed: ' + msg), tag: command.tag })); } catch (ex) { } - } else { - try { ws.send(JSON.stringify({ action: 'serverconsole', value: status ? 'Success' : 'Failed', tag: command.tag })); } catch (ex) { } - } - }); - } - } - break; - } - case 'email': { - if (domain.mailserver == null) { - r = "No email service enabled."; - } else { - if (cmdargs['_'].length != 3) { - r = "Usage: email \"user@sample.com\" \"Subject\" \"Message\"."; - } else { - domain.mailserver.sendMail(cmdargs['_'][0], cmdargs['_'][1], cmdargs['_'][2]); - r = "Done."; - } - } - break; - } - case 'le': { - if (parent.parent.letsencrypt == null) { - r = "Let's Encrypt not in use."; - } else { - r = JSON.stringify(parent.parent.letsencrypt.getStats(), null, 4); - } - break; - } - case 'lecheck': { - if (parent.parent.letsencrypt == null) { - r = "Let's Encrypt not in use."; - } else { - r = ["CertOK", "Request:NoCert", "Request:Expire", "Request:MissingNames"][parent.parent.letsencrypt.checkRenewCertificate()]; - } - break; - } - case 'leevents': { - if (parent.parent.letsencrypt == null) { - r = "Let's Encrypt not in use."; - } else { - r = parent.parent.letsencrypt.events.join('\r\n'); - } - break; - } - case 'badlogins': { - if (parent.parent.config.settings.maxinvalidlogin == false) { - r = 'Bad login filter is disabled.'; - } else { - if (cmdargs['_'] == 'reset') { - // Reset bad login table - parent.badLoginTable = {}; - parent.badLoginTableLastClean = 0; - r = 'Done.' - } else if (cmdargs['_'] == '') { - // Show current bad login table - if (typeof parent.parent.config.settings.maxinvalidlogin.coolofftime == 'number') { - r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s), " + parent.parent.config.settings.maxinvalidlogin.coolofftime + " minute(s) cooloff.\r\n"; - } else { - r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s).\r\n"; - } - var badLoginCount = 0; - parent.cleanBadLoginTable(); - for (var i in parent.badLoginTable) { - badLoginCount++; - if (typeof parent.badLoginTable[i] == 'number') { - r += "Cooloff for " + Math.floor((parent.badLoginTable[i] - Date.now()) / 60000) + " minute(s)\r\n"; - } else { - if (parent.badLoginTable[i].length > 1) { - r += (i + ' - ' + parent.badLoginTable[i].length + " records\r\n"); - } else { - r += (i + ' - ' + parent.badLoginTable[i].length + " record\r\n"); - } - } - } - if (badLoginCount == 0) { r += 'No bad logins.'; } - } else { - r = 'Usage: badlogin [reset]'; - } - } - break; - } - case 'dispatchtable': { - r = ''; - for (var i in parent.parent.eventsDispatch) { r += (i + ', ' + parent.parent.eventsDispatch[i].length + '\r\n'); } - 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': { - var stats = parent.getAgentStats(); - for (var i in stats) { - if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); } - } - break; - } - case 'agentissues': { - var stats = parent.getAgentIssues(); - if (stats.length == 0) { - r = "No agent issues."; - } else { - for (var i in stats) { r += stats[i].join(', ') + '\r\n'; } - } - break; - } - case 'webstats': { - var stats = parent.getStats(); - for (var i in stats) { - if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); } - } - break; - } - case 'trafficstats': { - var stats = parent.getTrafficStats(); - for (var i in stats) { - if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); } - } - break; - } - case 'trafficdelta': { - const stats = parent.getTrafficDelta(obj.trafficStats); - obj.trafficStats = stats.current; - for (var i in stats.delta) { - if (typeof stats.delta[i] == 'object') { r += (i + ': ' + JSON.stringify(stats.delta[i]) + '\r\n'); } else { r += (i + ': ' + stats.delta[i] + '\r\n'); } - } - break; - } - case 'watchdog': { - if (parent.parent.watchdog == null) { - r = 'Server watchdog not active.'; - } else { - r = 'Server watchdog active.\r\n'; - if (parent.parent.watchdogmaxtime != null) { r += 'Largest timeout was ' + parent.parent.watchdogmax + 'ms on ' + parent.parent.watchdogmaxtime + '\r\n'; } - for (var i in parent.parent.watchdogtable) { r += parent.parent.watchdogtable[i] + '\r\n'; } - } - break; - } - case 'acceleratorsstats': { - var stats = parent.parent.certificateOperations.getAcceleratorStats(); - for (var i in stats) { - if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); } - } - break; - } - case 'mpsstats': { - if (parent.parent.mpsserver == null) { - r = 'MPS not enabled.'; - } else { - var stats = parent.parent.mpsserver.getStats(); - for (var i in stats) { - if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); } - } - } - break; - } - case 'mps': { // List all MPS connections and types. - if (parent.parent.mpsserver == null) { - r = 'MPS not enabled.'; - } else { - const connectionTypes = ['CIRA', 'Relay', 'LMS']; - for (var nodeid in parent.parent.mpsserver.ciraConnections) { - r += nodeid; - var connections = parent.parent.mpsserver.ciraConnections[nodeid]; - for (var i in connections) { r += ', ' + connectionTypes[connections[i].tag.connType]; } - r += '\r\n'; - } - if (r == '') { r = 'MPS has not connections.'; } - } - break; - } - case 'dbstats': { - parent.parent.db.getStats(function (stats) { - var r2 = ''; - for (var i in stats) { r2 += (i + ': ' + stats[i] + '\r\n'); } - try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { } - }); - break; - } - case 'dbcounters': { - try { ws.send(JSON.stringify({ action: 'serverconsole', value: JSON.stringify(parent.parent.db.dbCounters, null, 2), tag: command.tag })); } catch (ex) { } - break; - } - case 'serverupdate': { - r = 'Performing server update...'; - var version = null; - - if (cmdargs['_'].length > 0) { - version = cmdargs['_'][0]; - - // This call is SLOW. We only want to validate version if we have to - if (version != 'stable' && version != 'latest') { - parent.parent.getServerVersions((data) => { - var versions = JSON.parse(data); - - if (versions.includes(version)) { - if (parent.parent.performServerUpdate(version) == false) { - try { - ws.send(JSON.stringify({ action: 'serverconsole', - value: 'Server self-update not possible.'})); - } catch (ex) { } - } - } else { - try { - ws.send(JSON.stringify({ action: 'serverconsole', - value: 'Invalid version. Aborting update'})); - } catch (ex) { } - } - }); - } else { - if (parent.parent.performServerUpdate(version) == false) { - r = 'Server self-update not possible.'; - } - } - } else { - if (parent.parent.performServerUpdate(version) == false) { - r = 'Server self-update not possible.'; - } - } - - break; - } - case 'print': { - console.log(cmdargs['_'][0]); - break; - } - case 'amtpasswords': { - if (parent.parent.amtPasswords == null) { - r = "No Intel AMT password table." - } else { - for (var i in parent.parent.amtPasswords) { r += (i + ' - ' + parent.parent.amtPasswords[i].join(', ') + '\r\n'); } - } - break; - } - case 'updatecheck': { - parent.parent.getServerTags(function (tags, error) { - var r2 = ''; - if (error != null) { r2 += 'Exception: ' + error + '\r\n'; } - else { for (var i in tags) { r2 += i + ': ' + tags[i] + '\r\n'; } } - try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { } - }); - r = "Checking server update..."; - break; - } - case 'maintenance': { - var arg = null, changed = false; - if ((cmdargs['_'] != null) && (cmdargs['_'][0] != null)) { arg = cmdargs['_'][0].toLowerCase(); } - if (arg == 'enabled') { parent.parent.config.settings.maintenancemode = 1; changed = true; } - else if (arg == 'disabled') { delete parent.parent.config.settings.maintenancemode; changed = true; } - r = 'Maintenance mode: ' + ((parent.parent.config.settings.maintenancemode == null) ? 'Disabled' : 'Enabled'); - if (changed == false) { r += '\r\nTo change type: maintenance [enabled|disabled]'; } - break; - } - case 'info': { - var info = process.memoryUsage(); - info.dbType = ['None', 'NeDB', 'MongoJS', 'MongoDB'][parent.db.databaseType]; - try { if (parent.parent.multiServer != null) { info.serverId = parent.parent.multiServer.serverid; } } catch (ex) { } - if (parent.db.databaseType == 3) { info.dbChangeStream = parent.db.changeStream; } - if (parent.parent.pluginHandler != null) { info.plugins = []; for (var i in parent.parent.pluginHandler.plugins) { info.plugins.push(i); } } - try { info.nodeVersion = process.version; } catch (ex) { } - try { info.meshVersion = parent.parent.currentVer; } catch (ex) { } - 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.cpuUsage = process.cpuUsage(); } catch (ex) { } - try { info.warnings = parent.parent.getServerWarnings(); } catch (ex) { } - try { info.database = ["Unknown", "NeDB", "MongoJS", "MongoDB", "MariaDB", "MySQL"][parent.parent.db.databaseType]; } catch (ex) { } - try { info.productionMode = ((process.env.NODE_ENV != null) && (process.env.NODE_ENV == 'production')); } catch (ex) { } - try { info.allDevGroupManagers = parent.parent.config.settings.managealldevicegroups; } 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': { - r = cmd + ': ' + JSON.stringify(cmdargs); - break; - } - case 'usersessions': { - var userSessionCount = 0; - var filter = null; - var arg = cmdargs['_'][0]; - if (typeof arg == 'string') { if (arg.indexOf('/') >= 0) { filter = arg; } else { filter = ('user/' + domain.id + '/' + arg); } } - for (var i in parent.wssessions) { - if ((filter == null) || (filter == i)) { - userSessionCount++; - r += (i + ', ' + parent.wssessions[i].length + ' session' + ((parent.wssessions[i].length > 1) ? 's' : '') + '.\r\n'); - for (var j in parent.wssessions[i]) { - r += ' ' + parent.wssessions[i][j].clientIp + ' --> ' + parent.wssessions[i][j].sessionId + '\r\n'; - } - } - } - if (userSessionCount == 0) { r = 'None.'; } - break; - } - case 'closeusersessions': { - var userSessionCount = 0; - var filter = null; - var arg = cmdargs['_'][0]; - if (typeof arg == 'string') { if (arg.indexOf('/') >= 0) { filter = arg; } else { filter = ('user/' + domain.id + '/' + arg); } } - if (filter == null) { - r += "Usage: closeusersessions "; - } else { - r += "Closing user sessions for: " + filter + '\r\n'; - for (var i in parent.wssessions) { - if (filter == i) { - userSessionCount++; - for (var j in parent.wssessions[i]) { - parent.wssessions[i][j].send(JSON.stringify({ action: 'stopped', msg: "Administrator forced disconnection" })); - parent.wssessions[i][j].close(); - } - } - } - if (userSessionCount < 2) { r += 'Disconnected ' + userSessionCount + ' session.'; } else { r += 'Disconnected ' + userSessionCount + ' sessions.'; }; - } - break; - } - case 'resetserver': { - console.log("Server restart..."); - process.exit(0); - break; - } - case 'tasklimiter': { - if (parent.parent.taskLimiter != null) { - //var obj = { maxTasks: maxTasks, maxTaskTime: (maxTaskTime * 1000), nextTaskId: 0, currentCount: 0, current: {}, pending: [[], [], []], timer: null }; - const tl = parent.parent.taskLimiter; - r += 'MaxTasks: ' + tl.maxTasks + ', NextTaskId: ' + tl.nextTaskId + '\r\n'; - r += 'MaxTaskTime: ' + (tl.maxTaskTime / 1000) + ' seconds, Timer: ' + (tl.timer != null) + '\r\n'; - var c = []; - for (var i in tl.current) { c.push(i); } - r += 'Current (' + tl.currentCount + '): [' + c.join(', ') + ']\r\n'; - r += 'Pending (High/Med/Low): ' + tl.pending[0].length + ', ' + tl.pending[1].length + ', ' + tl.pending[2].length + '\r\n'; - } - break; - } - case 'setmaxtasks': { - if ((cmdargs["_"].length != 1) || (parseInt(cmdargs["_"][0]) < 1) || (parseInt(cmdargs["_"][0]) > 1000)) { - r = 'Usage: setmaxtasks [1 to 1000]'; - } else { - parent.parent.taskLimiter.maxTasks = parseInt(cmdargs["_"][0]); - r = 'MaxTasks set to ' + parent.parent.taskLimiter.maxTasks + '.'; - } - break; - } - case 'cores': { - if (parent.parent.defaultMeshCores != null) { for (var i in parent.parent.defaultMeshCores) { r += i + ': ' + parent.parent.defaultMeshCores[i].length + ' bytes\r\n'; } } - break; - } - case 'showpaths': { - r = 'Parent: ' + parent.parent.parentpath + '\r\n'; - r += 'Data: ' + parent.parent.datapath + '\r\n'; - r += 'Files: ' + parent.parent.filespath + '\r\n'; - r += 'Backup: ' + parent.parent.backuppath + '\r\n'; - r += 'Record: ' + parent.parent.recordpath + '\r\n'; - r += 'WebPublic: ' + parent.parent.webPublicPath + '\r\n'; - r += 'WebViews: ' + parent.parent.webViewsPath + '\r\n'; - if (parent.parent.webViewsOverridePath) { r += 'XWebPublic: ' + parent.parent.webViewsOverridePath + '\r\n'; } - if (parent.parent.webViewsOverridePath) { r += 'XWebViews: ' + parent.parent.webPublicOverridePath + '\r\n'; } - break; - } - case 'migrationagents': { - if (parent.parent.swarmserver == null) { - r = 'Swarm server not running.'; - } else { - for (var i in parent.parent.swarmserver.migrationAgents) { - var arch = parent.parent.swarmserver.migrationAgents[i]; - for (var j in arch) { var agent = arch[j]; r += 'Arch ' + agent.arch + ', Ver ' + agent.ver + ', Size ' + ((agent.binary == null) ? 0 : agent.binary.length) + '
'; } - } - } - break; - } - case 'swarmstats': { - if (parent.parent.swarmserver == null) { - r = 'Swarm server not running.'; - } else { - for (var i in parent.parent.swarmserver.stats) { - if (typeof parent.parent.swarmserver.stats[i] == 'object') { - r += i + ': ' + JSON.stringify(parent.parent.swarmserver.stats[i]) + '\r\n'; - } else { - r += i + ': ' + parent.parent.swarmserver.stats[i] + '\r\n'; - } - } - } - break; - } - case 'heapdump': { - var heapdump = null; - try { heapdump = require('heapdump'); } catch (ex) { } - if (heapdump == null) { - r = 'Heapdump module not installed, run "npm install heapdump".'; - } else { - heapdump.writeSnapshot(function (err, filename) { - if (err != null) { - try { ws.send(JSON.stringify({ action: 'serverconsole', value: 'Unable to write heapdump: ' + err })); } catch (ex) { } - } else { - try { ws.send(JSON.stringify({ action: 'serverconsole', value: 'Wrote heapdump at ' + filename })); } catch (ex) { } - } - }); - } - break; - } - case 'relays': { - for (var i in parent.wsrelays) { - r += 'id: ' + i + ', ' + ((parent.wsrelays[i].state == 2) ? 'connected' : 'pending'); - if (parent.wsrelays[i].peer1 != null) { - r += ', ' + cleanRemoteAddr(parent.wsrelays[i].peer1.req.clientIp); - if (parent.wsrelays[i].peer1.user) { r += ' (User:' + parent.wsrelays[i].peer1.user.name + ')' } - } - if (parent.wsrelays[i].peer2 != null) { - r += ' to ' + cleanRemoteAddr(parent.wsrelays[i].peer2.req.clientIp); - if (parent.wsrelays[i].peer2.user) { r += ' (User:' + parent.wsrelays[i].peer2.user.name + ')' } - } - r += '\r\n'; - } - if (r == '') { r = 'No relays.'; } - break; - } - case 'autobackup': { - var backupResult = parent.db.performBackup(function (msg) { - try { ws.send(JSON.stringify({ action: 'serverconsole', value: msg, tag: command.tag })); } catch (ex) { } - }); - if (backupResult == 0) { r = 'Starting auto-backup...'; } else { r = 'Backup alreay in progress.'; } - break; - } - case 'backupconfig': { - r = parent.db.getBackupConfig(); - break; - } - case 'firebase': { - if (parent.parent.firebase == null) { - r = "Firebase push messaging not supported"; - } else { - r = JSON.stringify(parent.parent.firebase.stats, null, 2); - } - break; - } - default: { // This is an unknown command, return an error message - r = 'Unknown command \"' + cmd + '\", type \"help\" for list of available commands.'; - break; - } - } + var cmdData = serverUserCommand[cmd]; + if (cmdData != null) { r = cmdData[0](cmdargs); } else { r = 'Unknown command \"' + cmd + '\", type \"help\" for list of available commands.'; } if (r != '') { try { ws.send(JSON.stringify({ action: 'serverconsole', value: r, tag: command.tag })); } catch (ex) { } } break; @@ -6078,6 +5534,650 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } } + const serverUserCommand = { + 'acceleratorsstats': [serverUserCommandAcceleratorsStats, "Show data on work being offloaded to other CPU's"], + 'agentissues': [serverUserCommandAgentIssues, ""], + 'agentstats': [serverUserCommandAgentStats, ""], + 'amtacm': [serverUserCommandAmtAcm, ""], + 'amtmanager': [serverUserCommandAmtManager, ""], + 'amtpasswords': [serverUserCommandAmtPasswords, ""], + 'args': [serverUserCommandArgs, ""], + 'autobackup': [serverUserCommandAutoBackup, ""], + 'backupconfig': [serverUserCommandBackupConfig, ""], + 'badlogins': [serverUserCommandBadLogins, ""], + 'certexpire': [serverUserCommandCertExpire, ""], + 'certhashes': [serverUserCommandCertHashes, ""], + 'closeusersessions': [serverUserCommandCloseUserSessions, "Disconnects all sessions for a specified user."], + 'cores': [serverUserCommandCores, ""], + 'dbcounters': [serverUserCommandDbCounters, ""], + 'dbstats': [serverUserCommandDbStats, ""], + 'dispatchtable': [serverUserCommandDispatchTable, ""], + 'dupagents': [serverUserCommandDupAgents, ""], + 'email': [serverUserCommandEmail, ""], + 'firebase': [serverUserCommandFirebase, ""], + 'heapdump': [serverUserCommandHeapDump, ""], + 'heapdump2': [serverUserCommandHeapDump2, ""], + 'help': [serverUserCommandHelp, ""], + 'info': [serverUserCommandInfo, "Returns the most immidiatly useful information about this server, including MeshCentral and NodeJS versions. This is often information required to file a bug."], + 'le': [serverUserCommandLe, ""], + 'lecheck': [serverUserCommandLeCheck, ""], + 'leevents': [serverUserCommandLeEvents, ""], + 'maintenance': [serverUserCommandMaintenance, ""], + 'migrationagents': [serverUserCommandMigrationAgents, ""], + 'mps': [serverUserCommandMps, ""], + 'mpsstats': [serverUserCommandMpsStats, ""], + 'nodeconfig': [serverUserCommandNodeConfig, ""], + 'print': [serverUserCommandPrint, ""], + 'relays': [serverUserCommandRelays, ""], + 'resetserver': [serverUserCommandResetServer, "Causes the server to reset, this is sometimes useful is the config.json file was changed."], + 'serverupdate': [serverUserCommandServerUpdate, "Updates server to latest version. Optional version argument to install specific version. Example: serverupdate 0.8.49"], + 'setmaxtasks': [serverUserCommandSetMaxTasks, ""], + 'showpaths': [serverUserCommandShowPaths, ""], + 'sms': [serverUserCommandSMS, ""], + 'swarmstats': [serverUserCommandSwarmStats, ""], + 'tasklimiter': [serverUserCommandTaslkLimiter, "Returns the internal status of the tasklimiter. This is a system used to smooth out work done by the server. It's used by, for example, agent updates so that not all agents are updated at the same time."], + 'trafficdelta': [serverUserCommandTrafficDelta, ""], + 'trafficstats': [serverUserCommandTrafficStats, ""], + 'updatecheck': [serverUserCommandUpdateCheck, ""], + 'usersessions': [serverUserCommandUserSessions, "Returns a list of active sessions grouped by user."], + 'versions': [serverUserCommandVersions, "Returns all internal versions for NodeJS running this server."], + 'watchdog': [serverUserCommandWatchdog, ""], + 'webpush': [serverUserCommandWebPush, ""], + 'webstats': [serverUserCommandWebStats, ""] + } + + function serverUserCommandHelp(cmdargs) { + var r, fin = '', f = '', availcommands = []; + for (var i in serverUserCommand) { availcommands.push(i); } + availcommands = availcommands.sort(); + while (availcommands.length > 0) { if (f.length > 80) { fin += (f + ',\r\n'); f = ''; } f += (((f != '') ? ', ' : ' ') + availcommands.shift()); } + if (f != '') { fin += f; } + if (cmdargs['_'].length == 0) { + r = 'Available commands: \r\n' + fin + '\r\nType help for details.'; + } else { + var cmd2 = cmdargs['_'][0].toLowerCase(); + var cmddata = serverUserCommand[cmd2]; + if (cmddata) { if (cmddata[1] == '') { r = "No help available for this command."; } else { r = cmddata[1]; } } else { r = "This command does not exist."; } + } + return r; + } + + function serverUserCommandCertExpire(cmdargs) { + var r = ''; + const now = Date.now(); + for (var i in parent.webCertificateExpire) { + const domainName = (i == '') ? '[Default]' : i; + r += domainName + ', expires in ' + Math.floor((parent.webCertificateExpire[i] - now) / 86400000) + ' day(s)\r\n'; + } + return r; + } + + function serverUserCommandWebPush(cmdargs) { + if (parent.parent.webpush == null) { + r = "Web push not supported."; + } else { + if (cmdargs['_'].length != 1) { + r = "Usage: WebPush \"Message\""; + } else { + const pushSubscription = { "endpoint": "https://updates.push.services.mozilla.com/wpush/v2/gAAAAABgIkO9hjXHWhMPiuk-ppNRw7r_pUZitddwCEK4ykdzeIxOIjFnYhIt_nr-qUca2mpZziwQsSEhYTUCiuYrhWnVDRweMtiUj16yJJq8V5jneaEaUYjEIe5jp3DOMNpoTm1aHgX74gCR8uTXSITcM97bNi-hRxcQ4f6Ie4WSAmoXpd89B_g", "keys": { "auth": "UB2sbLVK7ALnSHw5P1dahg", "p256dh": "BIoRbcNSxBuTjN39CCCUCHo1f4NxBJ1YDdu_k4MbPW_q3NK1_RufnydUzLPDp8ibBVItSI72-s48QJvOjQ_S8Ok" } } + parent.parent.webpush.sendNotification(pushSubscription, cmdargs['_'][0]).then( + function (value) { try { ws.send(JSON.stringify({ action: 'OK', value: r, tag: command.tag })); } catch (ex) { } }, + function (error) { try { ws.send(JSON.stringify({ action: 'Error', value: r, tag: command.tag })); } catch (ex) { } } + ); + } + } + return r; + } + + function serverUserCommandAmtManager(cmdargs) { + if (parent.parent.amtManager == null) { return 'Intel AMT Manager not active.'; } + return parent.parent.amtManager.getStatusString(); + } + + function serverUserCommandCertHashes(cmdargs) { + var r = 'AgentCertHash: ' + parent.agentCertificateHashHex; + for (var i in parent.webCertificateHashs) { r += '\r\nwebCertificateHash (' + i + '): ' + common.rstr2hex(parent.webCertificateHashs[i]); } + for (var i in parent.webCertificateFullHashs) { r += '\r\nwebCertificateFullHash (' + i + '): ' + common.rstr2hex(parent.webCertificateFullHashs[i]); } + r += '\r\ndefaultWebCertificateHash: ' + common.rstr2hex(parent.defaultWebCertificateHash); + r += '\r\ndefaultWebCertificateFullHash: ' + common.rstr2hex(parent.defaultWebCertificateFullHash); + return r; + } + + function serverUserCommandAmtAcm(cmdargs) { + var r = ''; + if ((domain.amtacmactivation == null) || (domain.amtacmactivation.acmmatch == null) || (domain.amtacmactivation.acmmatch.length == 0)) { + r = 'No Intel AMT activation certificates.'; + } else { + if (domain.amtacmactivation.log != null) { r += '--- Activation Log ---\r\nFile : ' + domain.amtacmactivation.log + '\r\n'; } + for (var i in domain.amtacmactivation.acmmatch) { + var acmcert = domain.amtacmactivation.acmmatch[i]; + r += '--- Activation Certificate ' + (parseInt(i) + 1) + ' ---\r\nName : ' + acmcert.cn + '\r\nSHA1 : ' + acmcert.sha1 + '\r\nSHA256: ' + acmcert.sha256 + '\r\n'; + } + } + return r; + } + + function serverUserCommandHeapDump(cmdargs) { + var r = ''; + // Heapdump support, see example at: + // https://www.arbazsiddiqui.me/a-practical-guide-to-memory-leaks-in-nodejs/ + if (parent.parent.config.settings.heapdump === true) { + var dumpFileName = parent.path.join(parent.parent.datapath, `heapDump-${Date.now()}.heapsnapshot`); + try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Generating dump file at: " + dumpFileName, tag: command.tag })); } catch (ex) { } + require('heapdump').writeSnapshot(dumpFileName, (err, filename) => { + try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Done.", tag: command.tag })); } catch (ex) { } + }); + } else { + r = "Heapdump not supported, add \"heapdump\":true to settings section of config.json."; + } + return r; + } + + function serverUserCommandHeapDump2(cmdargs) { + var r = ''; + var heapdump = null; + try { heapdump = require('heapdump'); } catch (ex) { } + if (heapdump == null) { + r = 'Heapdump module not installed, run "npm install heapdump".'; + } else { + heapdump.writeSnapshot(function (err, filename) { + if (err != null) { + try { ws.send(JSON.stringify({ action: 'serverconsole', value: 'Unable to write heapdump: ' + err })); } catch (ex) { } + } else { + try { ws.send(JSON.stringify({ action: 'serverconsole', value: 'Wrote heapdump at ' + filename })); } catch (ex) { } + } + }); + } + break; + } + + function serverUserCommandSMS(cmdargs) { + var r = ''; + if (parent.parent.smsserver == null) { + r = "No SMS gateway in use."; + } else { + if (cmdargs['_'].length != 2) { + r = "Usage: SMS \"PhoneNumber\" \"Message\"."; + } else { + parent.parent.smsserver.sendSMS(cmdargs['_'][0], cmdargs['_'][1], function (status, msg) { + if (typeof msg == 'string') { + try { ws.send(JSON.stringify({ action: 'serverconsole', value: status ? ('Success: ' + msg) : ('Failed: ' + msg), tag: command.tag })); } catch (ex) { } + } else { + try { ws.send(JSON.stringify({ action: 'serverconsole', value: status ? 'Success' : 'Failed', tag: command.tag })); } catch (ex) { } + } + }); + } + } + return r; + } + + function serverUserCommandEmail(cmdargs) { + var r = ''; + if (domain.mailserver == null) { + r = "No email service enabled."; + } else { + if (cmdargs['_'].length != 3) { + r = "Usage: email \"user@sample.com\" \"Subject\" \"Message\"."; + } else { + domain.mailserver.sendMail(cmdargs['_'][0], cmdargs['_'][1], cmdargs['_'][2]); + r = "Done."; + } + } + return r; + } + + function serverUserCommandLe(cmdargs) { + if (parent.parent.letsencrypt == null) { return "Let's Encrypt not in use."; } + return JSON.stringify(parent.parent.letsencrypt.getStats(), null, 4); + } + + function serverUserCommandLeCheck(cmdargs) { + if (parent.parent.letsencrypt == null) { return "Let's Encrypt not in use."; } + return ["CertOK", "Request:NoCert", "Request:Expire", "Request:MissingNames"][parent.parent.letsencrypt.checkRenewCertificate()]; + } + + function serverUserCommandLeEvents(cmdargs) { + if (parent.parent.letsencrypt == null) { return "Let's Encrypt not in use."; } + return parent.parent.letsencrypt.events.join('\r\n'); + } + + function serverUserCommandBadLogins(cmdargs) { + var r = ''; + if (parent.parent.config.settings.maxinvalidlogin == false) { + r = 'Bad login filter is disabled.'; + } else { + if (cmdargs['_'] == 'reset') { + // Reset bad login table + parent.badLoginTable = {}; + parent.badLoginTableLastClean = 0; + r = 'Done.' + } else if (cmdargs['_'] == '') { + // Show current bad login table + if (typeof parent.parent.config.settings.maxinvalidlogin.coolofftime == 'number') { + r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s), " + parent.parent.config.settings.maxinvalidlogin.coolofftime + " minute(s) cooloff.\r\n"; + } else { + r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s).\r\n"; + } + var badLoginCount = 0; + parent.cleanBadLoginTable(); + for (var i in parent.badLoginTable) { + badLoginCount++; + if (typeof parent.badLoginTable[i] == 'number') { + r += "Cooloff for " + Math.floor((parent.badLoginTable[i] - Date.now()) / 60000) + " minute(s)\r\n"; + } else { + if (parent.badLoginTable[i].length > 1) { + r += (i + ' - ' + parent.badLoginTable[i].length + " records\r\n"); + } else { + r += (i + ' - ' + parent.badLoginTable[i].length + " record\r\n"); + } + } + } + if (badLoginCount == 0) { r += 'No bad logins.'; } + } else { + r = 'Usage: badlogin [reset]'; + } + } + return r; + } + + function serverUserCommandDispatchTable(cmdargs) { + var r = ''; + for (var i in parent.parent.eventsDispatch) { r += (i + ', ' + parent.parent.eventsDispatch[i].length + '\r\n'); } + return r; + } + + function serverUserCommandDupAgents(cmdargs) { + var r = ''; + for (var i in parent.duplicateAgentsLog) { r += JSON.stringify(parent.duplicateAgentsLog[i]) + '\r\n'; } + if (r == '') { r = 'No duplicate agents in log.'; } + return r; + } + + function serverUserCommandAgentStats(cmdargs) { + var r = '', stats = parent.getAgentStats(); + for (var i in stats) { + if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); } + } + return r; + } + + function serverUserCommandAgentIssues(cmdargs) { + var r = '', stats = parent.getAgentIssues(); + if (stats.length == 0) { + r = "No agent issues."; + } else { + for (var i in stats) { r += stats[i].join(', ') + '\r\n'; } + } + return r; + } + + function serverUserCommandWebStats(cmdargs) { + var r = '', stats = parent.getStats(); + for (var i in stats) { + if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); } + } + return r; + } + + function serverUserCommandTrafficStats(cmdargs) { + var r = ''; + var stats = parent.getTrafficStats(); + for (var i in stats) { + if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); } + } + return r; + } + + function serverUserCommandTrafficDelta(cmdargs) { + var r = ''; + const stats = parent.getTrafficDelta(obj.trafficStats); + obj.trafficStats = stats.current; + for (var i in stats.delta) { + if (typeof stats.delta[i] == 'object') { r += (i + ': ' + JSON.stringify(stats.delta[i]) + '\r\n'); } else { r += (i + ': ' + stats.delta[i] + '\r\n'); } + } + return r; + } + + function serverUserCommandWatchdog(cmdargs) { + var r = ''; + if (parent.parent.watchdog == null) { + r = 'Server watchdog not active.'; + } else { + r = 'Server watchdog active.\r\n'; + if (parent.parent.watchdogmaxtime != null) { r += 'Largest timeout was ' + parent.parent.watchdogmax + 'ms on ' + parent.parent.watchdogmaxtime + '\r\n'; } + for (var i in parent.parent.watchdogtable) { r += parent.parent.watchdogtable[i] + '\r\n'; } + } + return r; + } + + function serverUserCommandAcceleratorsStats(cmdargs) { + var r = '', stats = parent.parent.certificateOperations.getAcceleratorStats(); + for (var i in stats) { + if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); } + } + return r; + } + + function serverUserCommandMpsStats(cmdargs) { + var r = ''; + if (parent.parent.mpsserver == null) { + r = 'MPS not enabled.'; + } else { + var stats = parent.parent.mpsserver.getStats(); + for (var i in stats) { + if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); } + } + } + return r; + } + + // List all MPS connections and types. + function serverUserCommandMps(cmdargs) { + var r = ''; + if (parent.parent.mpsserver == null) { + r = 'MPS not enabled.'; + } else { + const connectionTypes = ['CIRA', 'Relay', 'LMS']; + for (var nodeid in parent.parent.mpsserver.ciraConnections) { + r += nodeid; + var connections = parent.parent.mpsserver.ciraConnections[nodeid]; + for (var i in connections) { r += ', ' + connectionTypes[connections[i].tag.connType]; } + r += '\r\n'; + } + if (r == '') { r = 'MPS has not connections.'; } + } + return r; + } + + function serverUserCommandDbStats(cmdargs) { + parent.parent.db.getStats(function (stats) { + var r2 = ''; + for (var i in stats) { r2 += (i + ': ' + stats[i] + '\r\n'); } + try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { } + }); + } + + function serverUserCommandDbCounters(cmdargs) { + try { ws.send(JSON.stringify({ action: 'serverconsole', value: JSON.stringify(parent.parent.db.dbCounters, null, 2), tag: command.tag })); } catch (ex) { } + } + + function serverUserCommandServerUpdate(cmdargs) { + var r = 'Performing server update...'; + var version = null; + if (cmdargs['_'].length > 0) { + version = cmdargs['_'][0]; + + // This call is SLOW. We only want to validate version if we have to + if (version != 'stable' && version != 'latest') { + parent.parent.getServerVersions((data) => { + var versions = JSON.parse(data); + + if (versions.includes(version)) { + if (parent.parent.performServerUpdate(version) == false) { + try { + ws.send(JSON.stringify({ + action: 'serverconsole', + value: 'Server self-update not possible.' + })); + } catch (ex) { } + } + } else { + try { + ws.send(JSON.stringify({ + action: 'serverconsole', + value: 'Invalid version. Aborting update' + })); + } catch (ex) { } + } + }); + } else { + if (parent.parent.performServerUpdate(version) == false) { + r = 'Server self-update not possible.'; + } + } + } else { + if (parent.parent.performServerUpdate(version) == false) { + r = 'Server self-update not possible.'; + } + } + return r; + } + + function serverUserCommandPrint(cmdargs) { + console.log(cmdargs['_'][0]); + } + + function serverUserCommandAmtPasswords(cmdargs) { + var r = ''; + if (parent.parent.amtPasswords == null) { + r = "No Intel AMT password table." + } else { + for (var i in parent.parent.amtPasswords) { r += (i + ' - ' + parent.parent.amtPasswords[i].join(', ') + '\r\n'); } + } + return r; + } + + function serverUserCommandUpdateCheck(cmdargs) { + parent.parent.getServerTags(function (tags, error) { + var r2 = ''; + if (error != null) { r2 += 'Exception: ' + error + '\r\n'; } + else { for (var i in tags) { r2 += i + ': ' + tags[i] + '\r\n'; } } + try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { } + }); + return "Checking server update..."; + } + + function serverUserCommandMaintenance(cmdargs) { + var arg = null, changed = false, r = ''; + if ((cmdargs['_'] != null) && (cmdargs['_'][0] != null)) { arg = cmdargs['_'][0].toLowerCase(); } + if (arg == 'enabled') { parent.parent.config.settings.maintenancemode = 1; changed = true; } + else if (arg == 'disabled') { delete parent.parent.config.settings.maintenancemode; changed = true; } + r = 'Maintenance mode: ' + ((parent.parent.config.settings.maintenancemode == null) ? 'Disabled' : 'Enabled'); + if (changed == false) { r += '\r\nTo change type: maintenance [enabled|disabled]'; } + return r; + } + + function serverUserCommandInfo(cmdargs) { + var info = process.memoryUsage(); + info.dbType = ['None', 'NeDB', 'MongoJS', 'MongoDB'][parent.db.databaseType]; + try { if (parent.parent.multiServer != null) { info.serverId = parent.parent.multiServer.serverid; } } catch (ex) { } + if (parent.db.databaseType == 3) { info.dbChangeStream = parent.db.changeStream; } + if (parent.parent.pluginHandler != null) { info.plugins = []; for (var i in parent.parent.pluginHandler.plugins) { info.plugins.push(i); } } + try { info.nodeVersion = process.version; } catch (ex) { } + try { info.meshVersion = parent.parent.currentVer; } catch (ex) { } + 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.cpuUsage = process.cpuUsage(); } catch (ex) { } + try { info.warnings = parent.parent.getServerWarnings(); } catch (ex) { } + try { info.database = ["Unknown", "NeDB", "MongoJS", "MongoDB", "MariaDB", "MySQL"][parent.parent.db.databaseType]; } catch (ex) { } + try { info.productionMode = ((process.env.NODE_ENV != null) && (process.env.NODE_ENV == 'production')); } catch (ex) { } + try { info.allDevGroupManagers = parent.parent.config.settings.managealldevicegroups; } catch (ex) { } + return JSON.stringify(info, null, 4); + } + + function serverUserCommandNodeConfig(cmdargs) { + return JSON.stringify(process.config, null, 4); + } + + function serverUserCommandVersions(cmdargs) { + return JSON.stringify(process.versions, null, 4); + } + + function serverUserCommandArgs(cmdargs) { + return cmd + ': ' + JSON.stringify(cmdargs); + } + + function serverUserCommandUserSessions(cmdargs) { + var r = ''; + var userSessionCount = 0; + var filter = null; + var arg = cmdargs['_'][0]; + if (typeof arg == 'string') { if (arg.indexOf('/') >= 0) { filter = arg; } else { filter = ('user/' + domain.id + '/' + arg); } } + for (var i in parent.wssessions) { + if ((filter == null) || (filter == i)) { + userSessionCount++; + r += (i + ', ' + parent.wssessions[i].length + ' session' + ((parent.wssessions[i].length > 1) ? 's' : '') + '.\r\n'); + for (var j in parent.wssessions[i]) { + r += ' ' + parent.wssessions[i][j].clientIp + ' --> ' + parent.wssessions[i][j].sessionId + '\r\n'; + } + } + } + if (userSessionCount == 0) { r = 'None.'; } + break; + } + + function serverUserCommandCloseUserSessions(cmdargs) { + var r = ''; + var userSessionCount = 0; + var filter = null; + var arg = cmdargs['_'][0]; + if (typeof arg == 'string') { if (arg.indexOf('/') >= 0) { filter = arg; } else { filter = ('user/' + domain.id + '/' + arg); } } + if (filter == null) { + r += "Usage: closeusersessions "; + } else { + r += "Closing user sessions for: " + filter + '\r\n'; + for (var i in parent.wssessions) { + if (filter == i) { + userSessionCount++; + for (var j in parent.wssessions[i]) { + parent.wssessions[i][j].send(JSON.stringify({ action: 'stopped', msg: "Administrator forced disconnection" })); + parent.wssessions[i][j].close(); + } + } + } + if (userSessionCount < 2) { r += 'Disconnected ' + userSessionCount + ' session.'; } else { r += 'Disconnected ' + userSessionCount + ' sessions.'; }; + } + break; + } + + function serverUserCommandResetServer(cmdargs) { + var r = ''; + console.log("Server restart..."); + process.exit(0); + break; + } + + function serverUserCommandTaslkLimiter(cmdargs) { + var r = ''; + if (parent.parent.taskLimiter != null) { + //var obj = { maxTasks: maxTasks, maxTaskTime: (maxTaskTime * 1000), nextTaskId: 0, currentCount: 0, current: {}, pending: [[], [], []], timer: null }; + const tl = parent.parent.taskLimiter; + r += 'MaxTasks: ' + tl.maxTasks + ', NextTaskId: ' + tl.nextTaskId + '\r\n'; + r += 'MaxTaskTime: ' + (tl.maxTaskTime / 1000) + ' seconds, Timer: ' + (tl.timer != null) + '\r\n'; + var c = []; + for (var i in tl.current) { c.push(i); } + r += 'Current (' + tl.currentCount + '): [' + c.join(', ') + ']\r\n'; + r += 'Pending (High/Med/Low): ' + tl.pending[0].length + ', ' + tl.pending[1].length + ', ' + tl.pending[2].length + '\r\n'; + } + break; + } + + function serverUserCommandSetMaxTasks(cmdargs) { + var r = ''; + if ((cmdargs["_"].length != 1) || (parseInt(cmdargs["_"][0]) < 1) || (parseInt(cmdargs["_"][0]) > 1000)) { + r = 'Usage: setmaxtasks [1 to 1000]'; + } else { + parent.parent.taskLimiter.maxTasks = parseInt(cmdargs["_"][0]); + r = 'MaxTasks set to ' + parent.parent.taskLimiter.maxTasks + '.'; + } + break; + } + + function serverUserCommandCores(cmdargs) { + var r = ''; + if (parent.parent.defaultMeshCores != null) { for (var i in parent.parent.defaultMeshCores) { r += i + ': ' + parent.parent.defaultMeshCores[i].length + ' bytes\r\n'; } } + break; + } + + function serverUserCommandShowPaths(cmdargs) { + var r = ''; + r = 'Parent: ' + parent.parent.parentpath + '\r\n'; + r += 'Data: ' + parent.parent.datapath + '\r\n'; + r += 'Files: ' + parent.parent.filespath + '\r\n'; + r += 'Backup: ' + parent.parent.backuppath + '\r\n'; + r += 'Record: ' + parent.parent.recordpath + '\r\n'; + r += 'WebPublic: ' + parent.parent.webPublicPath + '\r\n'; + r += 'WebViews: ' + parent.parent.webViewsPath + '\r\n'; + if (parent.parent.webViewsOverridePath) { r += 'XWebPublic: ' + parent.parent.webViewsOverridePath + '\r\n'; } + if (parent.parent.webViewsOverridePath) { r += 'XWebViews: ' + parent.parent.webPublicOverridePath + '\r\n'; } + break; + } + + function serverUserCommandMigrationAgents(cmdargs) { + var r = ''; + if (parent.parent.swarmserver == null) { + r = 'Swarm server not running.'; + } else { + for (var i in parent.parent.swarmserver.migrationAgents) { + var arch = parent.parent.swarmserver.migrationAgents[i]; + for (var j in arch) { var agent = arch[j]; r += 'Arch ' + agent.arch + ', Ver ' + agent.ver + ', Size ' + ((agent.binary == null) ? 0 : agent.binary.length) + '
'; } + } + } + break; + } + + function serverUserCommandSwarmStats(cmdargs) { + var r = ''; + if (parent.parent.swarmserver == null) { + r = 'Swarm server not running.'; + } else { + for (var i in parent.parent.swarmserver.stats) { + if (typeof parent.parent.swarmserver.stats[i] == 'object') { + r += i + ': ' + JSON.stringify(parent.parent.swarmserver.stats[i]) + '\r\n'; + } else { + r += i + ': ' + parent.parent.swarmserver.stats[i] + '\r\n'; + } + } + } + break; + } + + function serverUserCommandRelays(cmdargs) { + var r = ''; + for (var i in parent.wsrelays) { + r += 'id: ' + i + ', ' + ((parent.wsrelays[i].state == 2) ? 'connected' : 'pending'); + if (parent.wsrelays[i].peer1 != null) { + r += ', ' + cleanRemoteAddr(parent.wsrelays[i].peer1.req.clientIp); + if (parent.wsrelays[i].peer1.user) { r += ' (User:' + parent.wsrelays[i].peer1.user.name + ')' } + } + if (parent.wsrelays[i].peer2 != null) { + r += ' to ' + cleanRemoteAddr(parent.wsrelays[i].peer2.req.clientIp); + if (parent.wsrelays[i].peer2.user) { r += ' (User:' + parent.wsrelays[i].peer2.user.name + ')' } + } + r += '\r\n'; + } + if (r == '') { r = 'No relays.'; } + break; + } + + function serverUserCommandAutoBackup(cmdargs) { + var r = ''; + var backupResult = parent.db.performBackup(function (msg) { + try { ws.send(JSON.stringify({ action: 'serverconsole', value: msg, tag: command.tag })); } catch (ex) { } + }); + if (backupResult == 0) { r = 'Starting auto-backup...'; } else { r = 'Backup alreay in progress.'; } + break; + } + + function serverUserCommandBackupConfig(cmdargs) { + var r = ''; + r = parent.db.getBackupConfig(); + break; + } + + function serverUserCommandFirebase(cmdargs) { + var r = ''; + if (parent.parent.firebase == null) { + r = "Firebase push messaging not supported"; + } else { + r = JSON.stringify(parent.parent.firebase.stats, null, 2); + } + break; + } + + function csvClean(s) { return '\"' + s.split('\"').join('').split(',').join('').split('\r').join('').split('\n').join('') + '\"'; } // Return detailed information about an array of nodeid's