This commit is contained in:
Ylian Saint-Hilaire 2021-01-15 17:05:41 -08:00
commit de2905ffcb
2 changed files with 1227 additions and 684 deletions

File diff suppressed because it is too large Load Diff

View File

@ -49,47 +49,48 @@ function sendAgentMessage(msg, icon)
require('MeshAgent').SendCommand({ action: 'sessions', type: 'msg', value: sendAgentMessage.messages }); require('MeshAgent').SendCommand({ action: 'sessions', type: 'msg', value: sendAgentMessage.messages });
} }
// Start a JavaScript based Agent Self-Update
function agentUpdate_Start(updateurl, updateoptions) function agentUpdate_Start(updateurl, updateoptions)
{ {
var sessionid = updateoptions != null ? updateoptions.session : null; // If this value is null
var sessionid = updateoptions != null ? updateoptions.session : null; // If this is null, messages will be broadcast. Otherwise they will be unicasted
if (this._selfupdate != null) if (this._selfupdate != null)
{ {
// We were already called, so we will ignore this duplicate request
if (sessionid != null) { sendConsoleText('Self update already in progress...', sessionid); } if (sessionid != null) { sendConsoleText('Self update already in progress...', sessionid); }
} }
else else
{ {
if (require('MeshAgent').ARCHID == null && updateurl == null) if (require('MeshAgent').ARCHID == null && updateurl == null)
{ {
if (sessionid != null) { sendConsoleText('Unable to initiate update, agent ARCHID is not defined', sessionid); } // This agent doesn't have the ability to tell us which ARCHID it is, so we don't know which agent to pull
sendConsoleText('Unable to initiate update, agent ARCHID is not defined', sessionid);
} }
else else
{ {
var agentfilename = process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop(); var agentfilename = process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop(); // Local File Name, ie: MeshAgent.exe
var name = require('MeshAgent').serviceName; var name = require('MeshAgent').serviceName;
if (name == null) { name = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent'; } if (name == null) { name = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent'; } // This is an older agent that doesn't expose the service name, so use the default
try try
{ {
var s = require('service-manager').manager.getService(name); var s = require('service-manager').manager.getService(name);
if (!s.isMe()) if (!s.isMe())
{ {
if (process.platform == 'win32') { s.close(); } if (process.platform == 'win32') { s.close(); }
if (sessionid != null) { sendConsoleText('Service check FAILED', sessionid); } sendConsoleText('Self Update cannot continue, this agent is not an instance of (' + name + ')', sessionid);
return; return;
} }
if (process.platform == 'win32') { s.close(); } if (process.platform == 'win32') { s.close(); }
} }
catch (zz) catch (zz)
{ {
if (sessionid != null) { sendConsoleText('Service check FAILED', sessionid); } sendConsoleText('Self Update Failed because this agent is not an instance of (' + name + ')', sessionid);
else sendAgentMessage('Self Update Failed because this agent is not an instance of (' + name + ')', 3);
{
sendAgentMessage('Self Update Failed, because this agent is not running as a service', 3);
}
return; return;
} }
if (sessionid != null) { sendConsoleText('Downloading update...', sessionid); } sendConsoleText('Downloading update...', sessionid);
var options = require('http').parseUri(updateurl != null ? updateurl : require('MeshAgent').ServerUrl); var options = require('http').parseUri(updateurl != null ? updateurl : require('MeshAgent').ServerUrl);
options.protocol = 'https:'; options.protocol = 'https:';
if (updateurl == null) { options.path = ('/meshagents?id=' + require('MeshAgent').ARCHID); } if (updateurl == null) { options.path = ('/meshagents?id=' + require('MeshAgent').ARCHID); }
@ -103,26 +104,14 @@ function agentUpdate_Start(updateurl, updateoptions)
// Check that the certificate is the one expected by the server, fail if not. // Check that the certificate is the one expected by the server, fail if not.
if (checkServerIdentity.servertlshash == null) if (checkServerIdentity.servertlshash == null)
{ {
if(sessionid!=null) sendConsoleText('Self Update failed, because the url cannot be verified', sessionid);
{ sendAgentMessage('Self Update failed, because the url cannot be verified', 3);
sendConsoleText('Self Update failed, because the url cannot be verified', sessionid);
}
else
{
sendAgentMessage('Self Update failed, because the url cannot be verified', 3);
}
throw new Error('BadCert'); throw new Error('BadCert');
} }
if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash.toLowerCase() != certs[0].digest.split(':').join('').toLowerCase())) if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash.toLowerCase() != certs[0].digest.split(':').join('').toLowerCase()))
{ {
if (sessionid != null) sendConsoleText('Self Update failed, because the supplied certificate does not match', sessionid);
{ sendAgentMessage('Self Update failed, because the supplied certificate does not match', 3);
sendConsoleText('Self Update failed, because the supplied certificate does not match', sessionid);
}
else
{
sendAgentMessage('Self Update failed, because the supplied certificate does not match', 3);
}
throw new Error('BadCert') throw new Error('BadCert')
} }
} }
@ -130,11 +119,8 @@ function agentUpdate_Start(updateurl, updateoptions)
this._selfupdate = require('https').get(options); this._selfupdate = require('https').get(options);
this._selfupdate.on('error', function (e) this._selfupdate.on('error', function (e)
{ {
if (sessionid != null) { sendConsoleText('Error fetching update', sessionid); } sendConsoleText('Self Update failed, because there was a problem trying to download the update', sessionid);
else sendAgentMessage('Self Update failed, because there was a problem trying to download the update', 3);
{
sendAgentMessage('Self Update failed, because there was a problem trying to download the update', 3);
}
}); });
this._selfupdate.on('response', function (img) this._selfupdate.on('response', function (img)
{ {
@ -146,26 +132,24 @@ function agentUpdate_Start(updateurl, updateoptions)
{ {
if (updateoptions.hash.toLowerCase() == h.toString('hex').toLowerCase()) if (updateoptions.hash.toLowerCase() == h.toString('hex').toLowerCase())
{ {
if (sessionid != null) { sendConsoleText('Download complete. HASH verified.', sessionid); } sendConsoleText('Download complete. HASH verified.', sessionid);
} }
else else
{ {
if (sessionid != null) { sendConsoleText('Download complete. HASH FAILED.', sessionid); } sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check', sessionid);
else sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check', 3);
{
sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check', 3);
}
return; return;
} }
} }
else else
{ {
if (sessionid != null) { sendConsoleText('Download complete. HASH=' + h.toString('hex'), sessionid); } sendConsoleText('Download complete. HASH=' + h.toString('hex'), sessionid);
} }
if (sessionid != null) { sendConsoleText('Updating and restarting agent...', sessionid); } sendConsoleText('Updating and restarting agent...', sessionid);
if (process.platform == 'win32') if (process.platform == 'win32')
{ {
// Use _wexecve() equivalent to perform the update
this.child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', this.child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe',
['/C wmic service "' + name + '" call stopservice && copy "' + process.cwd() + agentfilename + '.update" "' + process.execPath + '" && wmic service "' + name + '" call startservice && erase "' + process.cwd() + agentfilename + '.update"'], { type: 4 | 0x8000 }); ['/C wmic service "' + name + '" call stopservice && copy "' + process.cwd() + agentfilename + '.update" "' + process.execPath + '" && wmic service "' + name + '" call startservice && erase "' + process.cwd() + agentfilename + '.update"'], { type: 4 | 0x8000 });
} }
@ -185,7 +169,7 @@ function agentUpdate_Start(updateurl, updateoptions)
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP | require('fs').CHMOD_MODES.S_IXOTH); m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP | require('fs').CHMOD_MODES.S_IXOTH);
require('fs').chmodSync(process.execPath, m); require('fs').chmodSync(process.execPath, m);
if (sessionid != null) { sendConsoleText('Restarting service...', sessionid); } sendConsoleText('Restarting service...', sessionid);
try try
{ {
// restart service // restart service
@ -194,11 +178,8 @@ function agentUpdate_Start(updateurl, updateoptions)
} }
catch (zz) catch (zz)
{ {
if (sessionid != null) { sendConsoleText('Error restarting service', sessionid); } sendConsoleText('Self Update encountered an error trying to restart service', sessionid);
else sendAgentMessage('Self Update encountered an error trying to restart service', 3);
{
sendAgentMessage('Self Update encountered an error trying to restart service', 3);
}
} }
} }
}); });
@ -209,7 +190,6 @@ function agentUpdate_Start(updateurl, updateoptions)
} }
} }
// Return p number of spaces // Return p number of spaces
function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ret; } return r; } function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ret; } return r; }
@ -643,7 +623,7 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
var response = null; var response = null;
switch (cmd) { switch (cmd) {
case 'help': case 'help':
response = "Available commands are: osinfo, dbkeys, dbget, dbset, dbcompact, netinfo, versions, agentupdate."; response = "Available commands are: agentupdate, dbkeys, dbget, dbset, dbcompact, netinfo, osinfo, versions.";
break; break;
case 'versions': case 'versions':
response = JSON.stringify(process.versions, null, ' '); response = JSON.stringify(process.versions, null, ' ');