Fixed meshcore agent update when used with AgentPort.
Ylian Saint-Hilaire committed
Jan 28, 2021 at 15:49 UTC
6f6040d74255cc96217794968fc686f1f162a3ed
4 files changed
+53
-71
agents/meshcore.js
+11
-8
@@ -3993,6 +3993,10 @@ function agentUpdate_Start(updateurl, updateoptions) {
3993
// If this value is null
3994
var sessionid = (updateoptions != null) ? updateoptions.sessionid : null; // If this is null, messages will be broadcast. Otherwise they will be unicasted
3995
3996
+ // If the url starts with *, switch it to use the same protoco, host and port as the control channel.
3997
+ updateurl = getServerTargetUrlEx(updateurl);
3998
+ if (updateurl.startsWith("wss://")) { updateurl = "https://" + updateurl.substring(6); }
3999
+
4000
if (agentUpdate_Start._selfupdate != null) {
4001
// We were already called, so we will ignore this duplicate request
4002
if (sessionid != null) { sendConsoleText('Self update already in progress...', sessionid); }
@@ -4006,7 +4010,7 @@ function agentUpdate_Start(updateurl, updateoptions) {
4010
else {
4011
var agentfilename = process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop(); // Local File Name, ie: MeshAgent.exe
4012
var name = require('MeshAgent').serviceName;
4009
- 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
4013
+ 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
4014
try {
4015
var s = require('service-manager').manager.getService(name);
4016
if (!s.isMe()) {
@@ -4035,9 +4039,8 @@ function agentUpdate_Start(updateurl, updateoptions) {
4039
// Check that the certificate is the one expected by the server, fail if not.
4040
if (checkServerIdentity.servertlshash == null) {
4041
if (require('MeshAgent').ServerInfo == null || require('MeshAgent').ServerInfo.ControlChannelCertificate == null) { return; }
4038
-
4039
- sendConsoleText('Self Update failed, because the url cannot be verified', sessionid);
4040
- sendAgentMessage('Self Update failed, because the url cannot be verified', 3);
4042
+ sendConsoleText('Self Update failed, because the url cannot be verified: ' + updateurl, sessionid);
4043
+ sendAgentMessage('Self Update failed, because the url cannot be verified: ' + updateurl, 3);
4044
throw new Error('BadCert');
4045
}
4046
if (certs[0].digest == null) { return; }
@@ -4050,8 +4053,8 @@ function agentUpdate_Start(updateurl, updateoptions) {
4053
options.checkServerIdentity.servertlshash = (updateoptions != null ? updateoptions.tlshash : null);
4054
agentUpdate_Start._selfupdate = require('https').get(options);
4055
agentUpdate_Start._selfupdate.on('error', function (e) {
4053
- sendConsoleText('Self Update failed, because there was a problem trying to download the update', sessionid);
4054
- sendAgentMessage('Self Update failed, because there was a problem trying to download the update', 3);
4056
+ sendConsoleText('Self Update failed, because there was a problem trying to download the update from ' + updateurl, sessionid);
4057
+ sendAgentMessage('Self Update failed, because there was a problem trying to download the update from ' + updateurl, 3);
4058
agentUpdate_Start._selfupdate = null;
4059
});
4060
agentUpdate_Start._selfupdate.on('response', function (img) {
@@ -4064,8 +4067,8 @@ function agentUpdate_Start(updateurl, updateoptions) {
4067
}
4068
else {
4069
agentUpdate_Start._retryCount++;
4067
- sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + ')', sessionid);
4068
- sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + ')', 3);
4070
+ sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + '), URL: ' + updateurl, sessionid);
4071
+ sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + '), URL: ' + updateurl, 3);
4072
agentUpdate_Start._selfupdate = null;
4073
4074
if (agentUpdate_Start._retryCount < 4) {
agents/recoverycore.js
+37
-59
@@ -324,70 +324,62 @@ function windows_execve(name, agentfilename, sessionid) {
324
}
325
326
// Start a JavaScript based Agent Self-Update
327
-function agentUpdate_Start(updateurl, updateoptions)
328
-{
327
+function agentUpdate_Start(updateurl, updateoptions) {
328
// If this value is null
329
var sessionid = (updateoptions != null) ? updateoptions.sessionid : null; // If this is null, messages will be broadcast. Otherwise they will be unicasted
330
332
- if (agentUpdate_Start._selfupdate != null)
333
- {
331
+ // If the url starts with *, switch it to use the same protoco, host and port as the control channel.
332
+ updateurl = getServerTargetUrlEx(updateurl);
333
+ if (updateurl.startsWith("wss://")) { updateurl = "https://" + updateurl.substring(6); }
334
+
335
+ if (agentUpdate_Start._selfupdate != null) {
336
// We were already called, so we will ignore this duplicate request
337
if (sessionid != null) { sendConsoleText('Self update already in progress...', sessionid); }
338
}
337
- else
338
- {
339
+ else {
340
if (agentUpdate_Start._retryCount == null) { agentUpdate_Start._retryCount = 0; }
340
- if (require('MeshAgent').ARCHID == null && updateurl == null)
341
- {
341
+ if (require('MeshAgent').ARCHID == null && updateurl == null) {
342
// This agent doesn't have the ability to tell us which ARCHID it is, so we don't know which agent to pull
343
sendConsoleText('Unable to initiate update, agent ARCHID is not defined', sessionid);
344
}
345
- else
346
- {
345
+ else {
346
var agentfilename = process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop(); // Local File Name, ie: MeshAgent.exe
347
var name = require('MeshAgent').serviceName;
349
- 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
350
- try
351
- {
348
+ 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
349
+ try {
350
var s = require('service-manager').manager.getService(name);
353
- if (!s.isMe())
354
- {
351
+ if (!s.isMe()) {
352
if (process.platform == 'win32') { s.close(); }
353
sendConsoleText('Self Update cannot continue, this agent is not an instance of (' + name + ')', sessionid);
354
return;
355
}
356
if (process.platform == 'win32') { s.close(); }
357
}
361
- catch (zz)
362
- {
358
+ catch (zz) {
359
sendConsoleText('Self Update Failed because this agent is not an instance of (' + name + ')', sessionid);
360
sendAgentMessage('Self Update Failed because this agent is not an instance of (' + name + ')', 3);
361
return;
362
}
363
368
- if (sessionid != null) { sendConsoleText('Downloading update...', sessionid); }
364
+ if (sessionid != null) { sendConsoleText('Downloading update from: ' + updateurl, sessionid); }
365
var options = require('http').parseUri(updateurl != null ? updateurl : require('MeshAgent').ServerUrl);
366
options.protocol = 'https:';
367
if (updateurl == null) { options.path = ('/meshagents?id=' + require('MeshAgent').ARCHID); }
368
options.rejectUnauthorized = false;
373
- options.checkServerIdentity = function checkServerIdentity(certs)
374
- {
369
+ options.checkServerIdentity = function checkServerIdentity(certs) {
370
// If the tunnel certificate matches the control channel certificate, accept the connection
371
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { }
372
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { }
373
374
// Check that the certificate is the one expected by the server, fail if not.
380
- if (checkServerIdentity.servertlshash == null)
381
- {
375
+ if (checkServerIdentity.servertlshash == null) {
376
if (require('MeshAgent').ServerInfo == null || require('MeshAgent').ServerInfo.ControlChannelCertificate == null) { return; }
383
-
384
- sendConsoleText('Self Update failed, because the url cannot be verified', sessionid);
385
- sendAgentMessage('Self Update failed, because the url cannot be verified', 3);
377
+ sendConsoleText('Self Update failed, because the url cannot be verified: ' + updateurl, sessionid);
378
+ sendAgentMessage('Self Update failed, because the url cannot be verified: ' + updateurl, 3);
379
throw new Error('BadCert');
380
}
381
if (certs[0].digest == null) { return; }
389
- if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash.toLowerCase() != certs[0].digest.split(':').join('').toLowerCase()))
390
- {
382
+ if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash.toLowerCase() != certs[0].digest.split(':').join('').toLowerCase())) {
383
sendConsoleText('Self Update failed, because the supplied certificate does not match', sessionid);
384
sendAgentMessage('Self Update failed, because the supplied certificate does not match', 3);
385
throw new Error('BadCert')
@@ -395,47 +387,38 @@ function agentUpdate_Start(updateurl, updateoptions)
387
}
388
options.checkServerIdentity.servertlshash = (updateoptions != null ? updateoptions.tlshash : null);
389
agentUpdate_Start._selfupdate = require('https').get(options);
398
- agentUpdate_Start._selfupdate.on('error', function (e)
399
- {
400
- sendConsoleText('Self Update failed, because there was a problem trying to download the update', sessionid);
401
- sendAgentMessage('Self Update failed, because there was a problem trying to download the update', 3);
390
+ agentUpdate_Start._selfupdate.on('error', function (e) {
391
+ sendConsoleText('Self Update failed, because there was a problem trying to download the update from ' + updateurl, sessionid);
392
+ sendAgentMessage('Self Update failed, because there was a problem trying to download the update from ' + updateurl, 3);
393
agentUpdate_Start._selfupdate = null;
394
});
404
- agentUpdate_Start._selfupdate.on('response', function (img)
405
- {
395
+ agentUpdate_Start._selfupdate.on('response', function (img) {
396
this._file = require('fs').createWriteStream(agentfilename + '.update', { flags: 'wb' });
397
this._filehash = require('SHA384Stream').create();
408
- this._filehash.on('hash', function (h)
409
- {
410
- if (updateoptions != null && updateoptions.hash != null)
411
- {
412
- if (updateoptions.hash.toLowerCase() == h.toString('hex').toLowerCase())
413
- {
398
+ this._filehash.on('hash', function (h) {
399
+ if (updateoptions != null && updateoptions.hash != null) {
400
+ if (updateoptions.hash.toLowerCase() == h.toString('hex').toLowerCase()) {
401
if (sessionid != null) { sendConsoleText('Download complete. HASH verified.', sessionid); }
402
}
416
- else
417
- {
403
+ else {
404
agentUpdate_Start._retryCount++;
419
- sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + ')', sessionid);
420
- sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + ')', 3);
405
+ sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + '), URL: ' + updateurl, sessionid);
406
+ sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check (' + agentUpdate_Start._retryCount + '), URL: ' + updateurl, 3);
407
agentUpdate_Start._selfupdate = null;
408
423
- if (agentUpdate_Start._retryCount < 4)
424
- {
409
+ if (agentUpdate_Start._retryCount < 4) {
410
// Retry the download again
411
sendConsoleText('Self Update will try again in 60 seconds...', sessionid);
412
agentUpdate_Start._timeout = setTimeout(agentUpdate_Start, 60000, updateurl, updateoptions);
413
}
429
- else
430
- {
414
+ else {
415
sendConsoleText('Self Update giving up, too many failures...', sessionid);
416
sendAgentMessage('Self Update giving up, too many failures...', 3);
417
}
418
return;
419
}
420
}
437
- else
438
- {
421
+ else {
422
sendConsoleText('Download complete. HASH=' + h.toString('hex'), sessionid);
423
}
424
@@ -443,13 +426,11 @@ function agentUpdate_Start(updateurl, updateoptions)
426
try { require('MeshAgent').SendCommand({ action: 'agentupdatedownloaded' }); } catch (e) { }
427
428
if (sessionid != null) { sendConsoleText('Updating and restarting agent...', sessionid); }
446
- if (process.platform == 'win32')
447
- {
429
+ if (process.platform == 'win32') {
430
// Use _wexecve() equivalent to perform the update
431
windows_execve(name, agentfilename, sessionid);
432
}
451
- else
452
- {
433
+ else {
434
var m = require('fs').statSync(process.execPath).mode;
435
require('fs').chmodSync(process.cwd() + agentfilename + '.update', m);
436
@@ -463,8 +444,7 @@ function agentUpdate_Start(updateurl, updateoptions)
444
// erase update
445
require('fs').unlinkSync(process.cwd() + agentfilename + '.update');
446
466
- switch (process.platform)
467
- {
447
+ switch (process.platform) {
448
case 'freebsd':
449
bsd_execv(name, agentfilename, sessionid);
450
break;
@@ -472,14 +452,12 @@ function agentUpdate_Start(updateurl, updateoptions)
452
linux_execv(name, agentfilename, sessionid);
453
break;
454
default:
475
- try
476
- {
455
+ try {
456
// restart service
457
var s = require('service-manager').manager.getService(name);
458
s.restart();
459
}
481
- catch (zz)
482
- {
460
+ catch (zz) {
461
sendConsoleText('Self Update encountered an error trying to restart service', sessionid);
462
sendAgentMessage('Self Update encountered an error trying to restart service', 3);
463
}
meshagent.js
+2
-4
@@ -1171,8 +1171,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
1171
1172
// Agent update. The recovery core was loaded in the agent, send a command to update the agent
1173
obj.agentCoreUpdateTaskId = taskid;
1174
- var url = obj.agentExeInfo.url;
1175
- if (url.startsWith('http://')) { url = url.replace('http://', 'https://') }
1174
+ const url = '*' + require('url').parse(obj.agentExeInfo.url).path;
1175
var cmd = { action: 'agentupdate', url: url, hash: obj.agentExeInfo.hashhex };
1176
1177
// Add the hash
@@ -1483,8 +1482,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
1482
1483
// Agent is requesting an agent update
1484
obj.agentCoreUpdateTaskId = taskid;
1486
- var url = obj.agentExeInfo.url;
1487
- if (url.startsWith('http://')) { url = url.replace('http://', 'https://') }
1485
+ const url = '*' + require('url').parse(obj.agentExeInfo.url).path;
1486
var cmd = { action: 'agentupdate', url: url, hash: obj.agentExeInfo.hashhex, sessionid: agentUpdateFunc.sessionid };
1487
1488
// Add the hash
webserver.js
+3
@@ -5513,6 +5513,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
5513
5514
// Setup agent to/from server file transfer handler
5515
obj.agentapp.ws(url + 'agenttransfer.ashx', handleAgentFileTransfer); // Setup agent to/from server file transfer handler
5516
+
5517
+ // Setup agent downloads for meshcore updates
5518
+ obj.agentapp.get(url + 'meshagents', obj.handleMeshAgentRequest);
5519
}
5520
5521
// Indicates to ExpressJS that the override public folder should be used to serve static files.