Fixed meshcore agent update when used with AgentPort.

This commit is contained in:
Ylian Saint-Hilaire 2021-01-28 15:49:42 -08:00
parent a9987c5bff
commit 6f6040d742
4 changed files with 53 additions and 71 deletions

View File

@ -3993,6 +3993,10 @@ function agentUpdate_Start(updateurl, updateoptions) {
// If this value is null
var sessionid = (updateoptions != null) ? updateoptions.sessionid : null; // If this is null, messages will be broadcast. Otherwise they will be unicasted
// If the url starts with *, switch it to use the same protoco, host and port as the control channel.
updateurl = getServerTargetUrlEx(updateurl);
if (updateurl.startsWith("wss://")) { updateurl = "https://" + updateurl.substring(6); }
if (agentUpdate_Start._selfupdate != null) {
// We were already called, so we will ignore this duplicate request
if (sessionid != null) { sendConsoleText('Self update already in progress...', sessionid); }
@ -4006,7 +4010,7 @@ function agentUpdate_Start(updateurl, updateoptions) {
else {
var agentfilename = process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop(); // Local File Name, ie: MeshAgent.exe
var name = require('MeshAgent').serviceName;
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
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 {
var s = require('service-manager').manager.getService(name);
if (!s.isMe()) {
@ -4035,9 +4039,8 @@ function agentUpdate_Start(updateurl, updateoptions) {
// Check that the certificate is the one expected by the server, fail if not.
if (checkServerIdentity.servertlshash == null) {
if (require('MeshAgent').ServerInfo == null || require('MeshAgent').ServerInfo.ControlChannelCertificate == null) { return; }
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: ' + updateurl, sessionid);
sendAgentMessage('Self Update failed, because the url cannot be verified: ' + updateurl, 3);
throw new Error('BadCert');
}
if (certs[0].digest == null) { return; }
@ -4050,8 +4053,8 @@ function agentUpdate_Start(updateurl, updateoptions) {
options.checkServerIdentity.servertlshash = (updateoptions != null ? updateoptions.tlshash : null);
agentUpdate_Start._selfupdate = require('https').get(options);
agentUpdate_Start._selfupdate.on('error', function (e) {
sendConsoleText('Self Update failed, because there was a problem trying to download the update', sessionid);
sendAgentMessage('Self Update failed, because there was a problem trying to download the update', 3);
sendConsoleText('Self Update failed, because there was a problem trying to download the update from ' + updateurl, sessionid);
sendAgentMessage('Self Update failed, because there was a problem trying to download the update from ' + updateurl, 3);
agentUpdate_Start._selfupdate = null;
});
agentUpdate_Start._selfupdate.on('response', function (img) {
@ -4064,8 +4067,8 @@ function agentUpdate_Start(updateurl, updateoptions) {
}
else {
agentUpdate_Start._retryCount++;
sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + ')', sessionid);
sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + ')', 3);
sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + '), URL: ' + updateurl, sessionid);
sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + '), URL: ' + updateurl, 3);
agentUpdate_Start._selfupdate = null;
if (agentUpdate_Start._retryCount < 4) {

View File

@ -324,70 +324,62 @@ function windows_execve(name, agentfilename, sessionid) {
}
// Start a JavaScript based Agent Self-Update
function agentUpdate_Start(updateurl, updateoptions)
{
function agentUpdate_Start(updateurl, updateoptions) {
// If this value is null
var sessionid = (updateoptions != null) ? updateoptions.sessionid : null; // If this is null, messages will be broadcast. Otherwise they will be unicasted
if (agentUpdate_Start._selfupdate != null)
{
// If the url starts with *, switch it to use the same protoco, host and port as the control channel.
updateurl = getServerTargetUrlEx(updateurl);
if (updateurl.startsWith("wss://")) { updateurl = "https://" + updateurl.substring(6); }
if (agentUpdate_Start._selfupdate != null) {
// We were already called, so we will ignore this duplicate request
if (sessionid != null) { sendConsoleText('Self update already in progress...', sessionid); }
}
else
{
else {
if (agentUpdate_Start._retryCount == null) { agentUpdate_Start._retryCount = 0; }
if (require('MeshAgent').ARCHID == null && updateurl == null)
{
if (require('MeshAgent').ARCHID == null && updateurl == null) {
// 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(); // Local File Name, ie: MeshAgent.exe
var name = require('MeshAgent').serviceName;
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
{
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 {
var s = require('service-manager').manager.getService(name);
if (!s.isMe())
{
if (!s.isMe()) {
if (process.platform == 'win32') { s.close(); }
sendConsoleText('Self Update cannot continue, this agent is not an instance of (' + name + ')', sessionid);
return;
}
if (process.platform == 'win32') { s.close(); }
}
catch (zz)
{
catch (zz) {
sendConsoleText('Self Update Failed because this agent is not an instance of (' + name + ')', sessionid);
sendAgentMessage('Self Update Failed because this agent is not an instance of (' + name + ')', 3);
return;
}
if (sessionid != null) { sendConsoleText('Downloading update...', sessionid); }
if (sessionid != null) { sendConsoleText('Downloading update from: ' + updateurl, sessionid); }
var options = require('http').parseUri(updateurl != null ? updateurl : require('MeshAgent').ServerUrl);
options.protocol = 'https:';
if (updateurl == null) { options.path = ('/meshagents?id=' + require('MeshAgent').ARCHID); }
options.rejectUnauthorized = false;
options.checkServerIdentity = function checkServerIdentity(certs)
{
options.checkServerIdentity = function checkServerIdentity(certs) {
// If the tunnel certificate matches the control channel certificate, accept the connection
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { }
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { }
// Check that the certificate is the one expected by the server, fail if not.
if (checkServerIdentity.servertlshash == null)
{
if (checkServerIdentity.servertlshash == null) {
if (require('MeshAgent').ServerInfo == null || require('MeshAgent').ServerInfo.ControlChannelCertificate == null) { return; }
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: ' + updateurl, sessionid);
sendAgentMessage('Self Update failed, because the url cannot be verified: ' + updateurl, 3);
throw new Error('BadCert');
}
if (certs[0].digest == null) { return; }
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())) {
sendConsoleText('Self Update failed, because the supplied certificate does not match', sessionid);
sendAgentMessage('Self Update failed, because the supplied certificate does not match', 3);
throw new Error('BadCert')
@ -395,47 +387,38 @@ function agentUpdate_Start(updateurl, updateoptions)
}
options.checkServerIdentity.servertlshash = (updateoptions != null ? updateoptions.tlshash : null);
agentUpdate_Start._selfupdate = require('https').get(options);
agentUpdate_Start._selfupdate.on('error', function (e)
{
sendConsoleText('Self Update failed, because there was a problem trying to download the update', sessionid);
sendAgentMessage('Self Update failed, because there was a problem trying to download the update', 3);
agentUpdate_Start._selfupdate.on('error', function (e) {
sendConsoleText('Self Update failed, because there was a problem trying to download the update from ' + updateurl, sessionid);
sendAgentMessage('Self Update failed, because there was a problem trying to download the update from ' + updateurl, 3);
agentUpdate_Start._selfupdate = null;
});
agentUpdate_Start._selfupdate.on('response', function (img)
{
agentUpdate_Start._selfupdate.on('response', function (img) {
this._file = require('fs').createWriteStream(agentfilename + '.update', { flags: 'wb' });
this._filehash = require('SHA384Stream').create();
this._filehash.on('hash', function (h)
{
if (updateoptions != null && updateoptions.hash != null)
{
if (updateoptions.hash.toLowerCase() == h.toString('hex').toLowerCase())
{
this._filehash.on('hash', function (h) {
if (updateoptions != null && updateoptions.hash != null) {
if (updateoptions.hash.toLowerCase() == h.toString('hex').toLowerCase()) {
if (sessionid != null) { sendConsoleText('Download complete. HASH verified.', sessionid); }
}
else
{
else {
agentUpdate_Start._retryCount++;
sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + ')', sessionid);
sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + ')', 3);
sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + '), URL: ' + updateurl, sessionid);
sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + '), URL: ' + updateurl, 3);
agentUpdate_Start._selfupdate = null;
if (agentUpdate_Start._retryCount < 4)
{
if (agentUpdate_Start._retryCount < 4) {
// Retry the download again
sendConsoleText('Self Update will try again in 60 seconds...', sessionid);
agentUpdate_Start._timeout = setTimeout(agentUpdate_Start, 60000, updateurl, updateoptions);
}
else
{
else {
sendConsoleText('Self Update giving up, too many failures...', sessionid);
sendAgentMessage('Self Update giving up, too many failures...', 3);
}
return;
}
}
else
{
else {
sendConsoleText('Download complete. HASH=' + h.toString('hex'), sessionid);
}
@ -443,13 +426,11 @@ function agentUpdate_Start(updateurl, updateoptions)
try { require('MeshAgent').SendCommand({ action: 'agentupdatedownloaded' }); } catch (e) { }
if (sessionid != null) { sendConsoleText('Updating and restarting agent...', sessionid); }
if (process.platform == 'win32')
{
if (process.platform == 'win32') {
// Use _wexecve() equivalent to perform the update
windows_execve(name, agentfilename, sessionid);
}
else
{
else {
var m = require('fs').statSync(process.execPath).mode;
require('fs').chmodSync(process.cwd() + agentfilename + '.update', m);
@ -463,8 +444,7 @@ function agentUpdate_Start(updateurl, updateoptions)
// erase update
require('fs').unlinkSync(process.cwd() + agentfilename + '.update');
switch (process.platform)
{
switch (process.platform) {
case 'freebsd':
bsd_execv(name, agentfilename, sessionid);
break;
@ -472,14 +452,12 @@ function agentUpdate_Start(updateurl, updateoptions)
linux_execv(name, agentfilename, sessionid);
break;
default:
try
{
try {
// restart service
var s = require('service-manager').manager.getService(name);
s.restart();
}
catch (zz)
{
catch (zz) {
sendConsoleText('Self Update encountered an error trying to restart service', sessionid);
sendAgentMessage('Self Update encountered an error trying to restart service', 3);
}

View File

@ -1171,8 +1171,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// Agent update. The recovery core was loaded in the agent, send a command to update the agent
obj.agentCoreUpdateTaskId = taskid;
var url = obj.agentExeInfo.url;
if (url.startsWith('http://')) { url = url.replace('http://', 'https://') }
const url = '*' + require('url').parse(obj.agentExeInfo.url).path;
var cmd = { action: 'agentupdate', url: url, hash: obj.agentExeInfo.hashhex };
// Add the hash
@ -1483,8 +1482,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// Agent is requesting an agent update
obj.agentCoreUpdateTaskId = taskid;
var url = obj.agentExeInfo.url;
if (url.startsWith('http://')) { url = url.replace('http://', 'https://') }
const url = '*' + require('url').parse(obj.agentExeInfo.url).path;
var cmd = { action: 'agentupdate', url: url, hash: obj.agentExeInfo.hashhex, sessionid: agentUpdateFunc.sessionid };
// Add the hash

View File

@ -5513,6 +5513,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
// Setup agent to/from server file transfer handler
obj.agentapp.ws(url + 'agenttransfer.ashx', handleAgentFileTransfer); // Setup agent to/from server file transfer handler
// Setup agent downloads for meshcore updates
obj.agentapp.get(url + 'meshagents', obj.handleMeshAgentRequest);
}
// Indicates to ExpressJS that the override public folder should be used to serve static files.