synced recoverycore.js changes with meshcore.js
Bryan Roe committed
Jan 18, 2021 at 19:04 UTC
d8dc375d223a0a4bb775b6199f5beac907d6dcd0
1 file changed
+207
-39
agents/meshcore.js
+207
-39
@@ -3726,13 +3726,150 @@ function createMeshCore(agent) {
3726
require('MeshAgent').SendCommand({ action: 'sessions', type: 'msg', value: sendAgentMessage.messages });
3727
}
3728
3729
- function windows_execve(name, agentfilename, sessionid) {
3729
+ function linux_execv(name, agentfilename, sessionid)
3730
+ {
3731
+ var libs = require('monitor-info').getLibInfo('libc');
3732
+ var libc = null;
3733
+
3734
+ while (libs.length > 0)
3735
+ {
3736
+ try
3737
+ {
3738
+ libc = require('_GenericMarshal').CreateNativeProxy(libs.pop().path);
3739
+ break;
3740
+ }
3741
+ catch (e)
3742
+ {
3743
+ libc = null;
3744
+ continue;
3745
+ }
3746
+ }
3747
+ if (libc != null)
3748
+ {
3749
+ try
3750
+ {
3751
+ libc.CreateMethod('execv');
3752
+ }
3753
+ catch (e)
3754
+ {
3755
+ libc = null;
3756
+ }
3757
+ }
3758
+
3759
+ if (libc == null)
3760
+ {
3761
+ // Couldn't find libc.so, fallback to using service manager to restart agent
3762
+ if (sessionid != null) { sendConsoleText('Restarting service via service-manager...', sessionid) }
3763
+ try
3764
+ {
3765
+ // restart service
3766
+ var s = require('service-manager').manager.getService(name);
3767
+ s.restart();
3768
+ }
3769
+ catch (zz)
3770
+ {
3771
+ sendConsoleText('Self Update encountered an error trying to restart service', sessionid);
3772
+ sendAgentMessage('Self Update encountered an error trying to restart service', 3);
3773
+ }
3774
+ return;
3775
+ }
3776
+
3777
+ if (sessionid != null) { sendConsoleText('Restarting service via execv()...', sessionid) }
3778
+
3779
+ var i;
3780
+ var args;
3781
+ var argarr = [];
3782
+ var path = require('_GenericMarshal').CreateVariable(process.execPath);
3783
+
3784
+ if (require('MeshAgent').getStartupOptions != null)
3785
+ {
3786
+ var options = require('MeshAgent').getStartupOptions();
3787
+ for (i in options)
3788
+ {
3789
+ argarr.push('--' + i + '="' + options[i] + '"');
3790
+ }
3791
+ }
3792
+
3793
+ args = require('_GenericMarshal').CreateVariable((1 + argarr.length) * require('_GenericMarshal').PointerSize);
3794
+ for (i = 0; i < argarr.length; ++i)
3795
+ {
3796
+ var arg = require('_GenericMarshal').CreateVariable(argarr[i]);
3797
+ arg.pointerBuffer().copy(args.toBuffer(), i * require('_GenericMarshal').PointerSize);
3798
+ }
3799
+
3800
+ libc.execv(path, args);
3801
+ if (sessionid != null) { sendConsoleText('Self Update failed because execv() failed', sessionid) }
3802
+ sendAgentMessage('Self Update failed because execv() failed', 3);
3803
+ }
3804
+
3805
+ function bsd_execv(name, agentfilename, sessionid)
3806
+ {
3807
+ var child = require('child_process').execFile('/bin/sh', ['sh']);
3808
+ child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
3809
+ child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
3810
+ child.stdin.write("cat /usr/lib/libc.so | awk '");
3811
+ child.stdin.write('{');
3812
+ child.stdin.write(' a=split($0, tok, "(");');
3813
+ child.stdin.write(' if(a>1)');
3814
+ child.stdin.write(' {');
3815
+ child.stdin.write(' split(tok[2], b, ")");');
3816
+ child.stdin.write(' split(b[1], c, " ");');
3817
+ child.stdin.write(' print c[1];');
3818
+ child.stdin.write(' }');
3819
+ child.stdin.write("}'\nexit\n");
3820
+ child.waitExit();
3821
+ if (child.stdout.str.trim() == '')
3822
+ {
3823
+ if (sessionid != null) { sendConsoleText('Self Update failed because cannot find libc.so', sessionid) }
3824
+ sendAgentMessage('Self Update failed because cannot find libc.so', 3);
3825
+ return;
3826
+ }
3827
+
3828
+ var libc = null;
3829
+ try
3830
+ {
3831
+ libc = require('_GenericMarshal').CreateNativeProxy(child.stdout.str.trim());
3832
+ libc.CreateMethod('execv');
3833
+ }
3834
+ catch (e)
3835
+ {
3836
+ if (sessionid != null) { sendConsoleText('Self Update failed: ' + e.toString(), sessionid) }
3837
+ sendAgentMessage('Self Update failed: ' + e.toString(), 3);
3838
+ return;
3839
+ }
3840
+
3841
+ var i;
3842
+ var path = require('_GenericMarshal').CreateVariable(process.execPath);
3843
+ var argarr = [];
3844
+ var args;
3845
+ var options = require('MeshAgent').getStartupOptions();
3846
+ for (i in options)
3847
+ {
3848
+ argarr.push('--' + i + '="' + options[i] + '"');
3849
+ }
3850
+ args = require('_GenericMarshal').CreateVariable((1 + argarr.length) * require('_GenericMarshal').PointerSize);
3851
+ for (i = 0; i < argarr.length; ++i)
3852
+ {
3853
+ var arg = require('_GenericMarshal').CreateVariable(argarr[i]);
3854
+ arg.pointerBuffer().copy(args.toBuffer(), i * require('_GenericMarshal').PointerSize);
3855
+ }
3856
+
3857
+ if (sessionid != null) { sendConsoleText('Restarting service via service-manager', sessionid) }
3858
+ libc.execv(path, args);
3859
+ if (sessionid != null) { sendConsoleText('Self Update failed because execv() failed', sessionid) }
3860
+ sendAgentMessage('Self Update failed because execv() failed', 3);
3861
+ }
3862
+
3863
+ function windows_execve(name, agentfilename, sessionid)
3864
+ {
3865
var libc;
3731
- try {
3866
+ try
3867
+ {
3868
libc = require('_GenericMarshal').CreateNativeProxy('msvcrt.dll');
3869
libc.CreateMethod('_wexecve');
3870
}
3735
- catch (xx) {
3871
+ catch (xx)
3872
+ {
3873
sendConsoleText('Self Update failed because msvcrt.dll is missing', sessionid);
3874
sendAgentMessage('Self Update failed because msvcrt.dll is missing', 3);
3875
return;
@@ -3750,33 +3887,41 @@ function createMeshCore(agent) {
3887
}
3888
3889
// Start a JavaScript based Agent Self-Update
3753
- function agentUpdate_Start(updateurl, updateoptions) {
3890
+ function agentUpdate_Start(updateurl, updateoptions)
3891
+ {
3892
// If this value is null
3893
var sessionid = (updateoptions != null) ? updateoptions.sessionid : null; // If this is null, messages will be broadcast. Otherwise they will be unicasted
3894
3757
- if (this._selfupdate != null) {
3895
+ if (this._selfupdate != null)
3896
+ {
3897
// We were already called, so we will ignore this duplicate request
3898
if (sessionid != null) { sendConsoleText('Self update already in progress...', sessionid); }
3899
}
3761
- else {
3762
- if (require('MeshAgent').ARCHID == null && updateurl == null) {
3900
+ else
3901
+ {
3902
+ if (require('MeshAgent').ARCHID == null && updateurl == null)
3903
+ {
3904
// This agent doesn't have the ability to tell us which ARCHID it is, so we don't know which agent to pull
3905
sendConsoleText('Unable to initiate update, agent ARCHID is not defined', sessionid);
3906
}
3766
- else {
3907
+ else
3908
+ {
3909
var agentfilename = process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop(); // Local File Name, ie: MeshAgent.exe
3910
var name = require('MeshAgent').serviceName;
3911
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
3770
- try {
3912
+ try
3913
+ {
3914
var s = require('service-manager').manager.getService(name);
3772
- if (!s.isMe()) {
3915
+ if (!s.isMe())
3916
+ {
3917
if (process.platform == 'win32') { s.close(); }
3918
sendConsoleText('Self Update cannot continue, this agent is not an instance of (' + name + ')', sessionid);
3919
return;
3920
}
3921
if (process.platform == 'win32') { s.close(); }
3922
}
3779
- catch (zz) {
3923
+ catch (zz)
3924
+ {
3925
sendConsoleText('Self Update Failed because this agent is not an instance of (' + name + ')', sessionid);
3926
sendAgentMessage('Self Update Failed because this agent is not an instance of (' + name + ')', 3);
3927
return;
@@ -3787,13 +3932,15 @@ function createMeshCore(agent) {
3932
options.protocol = 'https:';
3933
if (updateurl == null) { options.path = ('/meshagents?id=' + require('MeshAgent').ARCHID); }
3934
options.rejectUnauthorized = false;
3790
- options.checkServerIdentity = function checkServerIdentity(certs) {
3935
+ options.checkServerIdentity = function checkServerIdentity(certs)
3936
+ {
3937
// If the tunnel certificate matches the control channel certificate, accept the connection
3938
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { }
3939
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { }
3940
3941
// Check that the certificate is the one expected by the server, fail if not.
3796
- if (checkServerIdentity.servertlshash == null) {
3942
+ if (checkServerIdentity.servertlshash == null)
3943
+ {
3944
if (require('MeshAgent').ServerInfo == null || require('MeshAgent').ServerInfo.ControlChannelCertificate == null) { return; }
3945
3946
sendConsoleText('Self Update failed, because the url cannot be verified', sessionid);
@@ -3801,7 +3948,8 @@ function createMeshCore(agent) {
3948
throw new Error('BadCert');
3949
}
3950
if (certs[0].digest == null) { return; }
3804
- if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash.toLowerCase() != certs[0].digest.split(':').join('').toLowerCase())) {
3951
+ if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash.toLowerCase() != certs[0].digest.split(':').join('').toLowerCase()))
3952
+ {
3953
sendConsoleText('Self Update failed, because the supplied certificate does not match', sessionid);
3954
sendAgentMessage('Self Update failed, because the supplied certificate does not match', 3);
3955
throw new Error('BadCert')
@@ -3809,60 +3957,80 @@ function createMeshCore(agent) {
3957
}
3958
options.checkServerIdentity.servertlshash = (updateoptions != null ? updateoptions.tlshash : null);
3959
this._selfupdate = require('https').get(options);
3812
- this._selfupdate.on('error', function (e) {
3960
+ this._selfupdate.on('error', function (e)
3961
+ {
3962
sendConsoleText('Self Update failed, because there was a problem trying to download the update', sessionid);
3963
sendAgentMessage('Self Update failed, because there was a problem trying to download the update', 3);
3964
});
3816
- this._selfupdate.on('response', function (img) {
3965
+ this._selfupdate.on('response', function (img)
3966
+ {
3967
this._file = require('fs').createWriteStream(agentfilename + '.update', { flags: 'wb' });
3968
this._filehash = require('SHA384Stream').create();
3819
- this._filehash.on('hash', function (h) {
3820
- if (updateoptions != null && updateoptions.hash != null) {
3821
- if (updateoptions.hash.toLowerCase() == h.toString('hex').toLowerCase()) {
3969
+ this._filehash.on('hash', function (h)
3970
+ {
3971
+ if (updateoptions != null && updateoptions.hash != null)
3972
+ {
3973
+ if (updateoptions.hash.toLowerCase() == h.toString('hex').toLowerCase())
3974
+ {
3975
if (sessionid != null) { sendConsoleText('Download complete. HASH verified.', sessionid); }
3976
}
3824
- else {
3977
+ else
3978
+ {
3979
sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check', sessionid);
3980
sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check', 3);
3981
return;
3982
}
3983
}
3830
- else {
3831
- if (sessionid != null) { sendConsoleText('Download complete. HASH=' + h.toString('hex'), sessionid); }
3984
+ else
3985
+ {
3986
+ sendConsoleText('Download complete. HASH=' + h.toString('hex'), sessionid);
3987
}
3988
3989
// Send an indication to the server that we got the update download correctly.
3835
- try { mesh.SendCommand({ action: 'agentupdatedownloaded' }); } catch (e) { }
3990
+ try { require('MeshAgent').SendCommand({ action: 'agentupdatedownloaded' }); } catch (e) { }
3991
3992
if (sessionid != null) { sendConsoleText('Updating and restarting agent...', sessionid); }
3838
- if (process.platform == 'win32') {
3993
+ if (process.platform == 'win32')
3994
+ {
3995
// Use _wexecve() equivalent to perform the update
3996
windows_execve(name, agentfilename, sessionid);
3997
}
3842
- else {
3998
+ else
3999
+ {
4000
+ var m = require('fs').statSync(process.execPath).mode;
4001
+ require('fs').chmodSync(process.cwd() + agentfilename + '.update', m);
4002
+
4003
// remove binary
4004
require('fs').unlinkSync(process.execPath);
4005
4006
// copy update
4007
require('fs').copyFileSync(process.cwd() + agentfilename + '.update', process.execPath);
4008
+ require('fs').chmodSync(process.execPath, m);
4009
4010
// erase update
4011
require('fs').unlinkSync(process.cwd() + agentfilename + '.update');
4012
3852
- // add execute permissions
3853
- var m = require('fs').statSync(process.execPath).mode;
3854
- m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP | require('fs').CHMOD_MODES.S_IXOTH);
3855
- require('fs').chmodSync(process.execPath, m);
3856
-
3857
- if (sessionid != null) { sendConsoleText('Restarting service...', sessionid); }
3858
- try {
3859
- // restart service
3860
- var s = require('service-manager').manager.getService(name);
3861
- s.restart();
3862
- }
3863
- catch (zz) {
3864
- sendConsoleText('Self Update encountered an error trying to restart service', sessionid);
3865
- sendAgentMessage('Self Update encountered an error trying to restart service', 3);
4013
+ switch (process.platform)
4014
+ {
4015
+ case 'freebsd':
4016
+ bsd_execv(name, agentfilename, sessionid);
4017
+ break;
4018
+ case 'linux':
4019
+ linux_execv(name, agentfilename, sessionid);
4020
+ break;
4021
+ default:
4022
+ try
4023
+ {
4024
+ // restart service
4025
+ var s = require('service-manager').manager.getService(name);
4026
+ s.restart();
4027
+ }
4028
+ catch (zz)
4029
+ {
4030
+ sendConsoleText('Self Update encountered an error trying to restart service', sessionid);
4031
+ sendAgentMessage('Self Update encountered an error trying to restart service', 3);
4032
+ }
4033
+ break;
4034
}
4035
}
4036
});