diff --git a/agents/MeshCentralAssistant.exe b/agents/MeshCentralAssistant.exe new file mode 100644 index 00000000..9c92d8dd Binary files /dev/null and b/agents/MeshCentralAssistant.exe differ diff --git a/agents/MeshCentralRouter.exe b/agents/MeshCentralRouter.exe index 098ebc96..6d2b50e5 100644 Binary files a/agents/MeshCentralRouter.exe and b/agents/MeshCentralRouter.exe differ diff --git a/meshcentral.js b/meshcentral.js index 9bba575f..7630a291 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -57,6 +57,7 @@ function CreateMeshCentralServer(config, args) { obj.defaultMeshCores = {}; obj.defaultMeshCoresDeflate = {}; obj.defaultMeshCoresHash = {}; + obj.meshToolsBinaries = {}; // Mesh Tools Binaries, ToolName --> { hash:(sha384 hash), size:(binary size), path:(binary path) } obj.meshAgentBinaries = {}; // Mesh Agent Binaries, Architecture type --> { hash:(sha384 hash), size:(binary size), path:(binary path) } obj.meshAgentInstallScripts = {}; // Mesh Install Scripts, Script ID -- { hash:(sha384 hash), size:(binary size), path:(binary path) } obj.multiServer = null; @@ -1296,6 +1297,9 @@ function CreateMeshCentralServer(config, args) { } } + // Load the list of MeshCentral tools + obj.updateMeshTools(); + // Load the list of mesh agents and install scripts if (obj.args.noagentupdate == 1) { for (i in obj.meshAgentsArchitectureNumbers) { obj.meshAgentsArchitectureNumbers[i].update = false; } } obj.updateMeshAgentsTable(function () { @@ -2078,6 +2082,44 @@ function CreateMeshCentralServer(config, args) { } }; + // List of possible mesh agent install scripts + var meshToolsList = { + 'MeshCentralRouter': { localname: 'MeshCentralRouter.exe', dlname: 'winrouter' }, + 'MeshCentralAssistant': { localname: 'MeshCentralAssistant.exe', dlname: 'winassistant' } + }; + + // Update the list of available mesh agents + obj.updateMeshTools = function () { + for (var toolname in meshToolsList) { + var toolpath = obj.path.join(__dirname, 'agents', meshToolsList[toolname].localname); + var stream = null; + try { + stream = obj.fs.createReadStream(toolpath); + stream.on('data', function (data) { this.hash.update(data, 'binary'); this.hashx += data.length; }); + stream.on('error', function (data) { + // If there is an error reading this file, make sure this agent is not in the agent table + if (obj.meshToolsBinaries[this.toolname] != null) { delete obj.meshToolsBinaries[this.toolname]; } + }); + stream.on('end', function () { + // Add the agent to the agent table with all information and the hash + obj.meshToolsBinaries[this.toolname] = {}; + obj.meshToolsBinaries[this.toolname].hash = this.hash.digest('hex'); + obj.meshToolsBinaries[this.toolname].hashx = this.hashx; + obj.meshToolsBinaries[this.toolname].path = this.agentpath; + obj.meshToolsBinaries[this.toolname].url = ((obj.args.notls == true) ? 'http://' : 'https://') + obj.certificates.CommonName + ':' + ((typeof obj.args.aliasport == 'number') ? obj.args.aliasport : obj.args.port) + '/meshagents?meshaction=' + this.dlname; + var stats = null; + try { stats = obj.fs.statSync(this.agentpath); } catch (e) { } + if (stats != null) { obj.meshToolsBinaries[this.toolname].size = stats.size; } + }); + stream.toolname = toolname; + stream.agentpath = toolpath; + stream.dlname = meshToolsList[toolname].dlname; + stream.hash = obj.crypto.createHash('sha384', stream); + stream.hashx = 0; + } catch (e) { } + } + }; + // List of possible mesh agent install scripts var meshAgentsInstallScriptList = { 1: { id: 1, localname: 'meshinstall-linux.sh', rname: 'meshinstall.sh', linux: true }, diff --git a/meshuser.js b/meshuser.js index 0a938e0d..0887d0d2 100644 --- a/meshuser.js +++ b/meshuser.js @@ -4999,6 +4999,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use try { ws.send(JSON.stringify({ action: 'amtsetupbin', file: Buffer.from(bin, 'binary').toString('base64') })); } catch (ex) { } break; } + case 'meshToolInfo': { + if (typeof command.name != 'string') break; + var info = parent.parent.meshToolsBinaries[command.name]; + try { ws.send(JSON.stringify({ action: 'meshToolInfo', name: command.name, hash: info.hash, size: info.size, url: info.url })); } catch (ex) { } + break; + } default: { // Unknown user action console.log('Unknown action from user ' + user.name + ': ' + command.action + '.'); diff --git a/webserver.js b/webserver.js index e692143e..8a9abf63 100644 --- a/webserver.js +++ b/webserver.js @@ -4177,7 +4177,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } else if (req.query.meshaction != null) { if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key var user = obj.users[req.session.userid]; - if (user == null) { res.sendStatus(404); return; } + if (user == null) { + var c = obj.parent.decodeCookie(req.query.auth, obj.parent.loginCookieEncryptionKey); + if ((c == null) || (c.userid == null)) { res.sendStatus(404); return; } + user = obj.users[c.userid]; + if (user == null) { res.sendStatus(404); return; } + } if ((req.query.meshaction == 'route') && (req.query.nodeid != null)) { obj.db.Get(req.query.nodeid, function (err, nodes) { if (nodes.length != 1) { res.sendStatus(401); return; } @@ -4225,6 +4230,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { setContentDispositionHeader(res, 'application/octet-stream', 'MeshCentralRouter.exe', null, 'MeshCentralRouter.exe'); try { res.sendFile(p); } catch (e) { res.sendStatus(404); } } else { res.sendStatus(404); } + } else if (req.query.meshaction == 'winassistant') { + var p = obj.path.join(__dirname, 'agents', 'MeshCentralAssistant.exe'); + if (obj.fs.existsSync(p)) { + setContentDispositionHeader(res, 'application/octet-stream', 'MeshCentralAssistant.exe', null, 'MeshCentralAssistant.exe'); + try { res.sendFile(p); } catch (e) { res.sendStatus(404); } + } else { res.sendStatus(404); } } else { res.sendStatus(401); }