Updated agentupdate
Bryan Roe committed
Jan 14, 2021 at 23:57 UTC
562f8a6cebb41f4ee09884c29a8f052703541ae1
2 files changed
+1227
-684
agents/meshcore.js
+1199
-636
@@ -40,6 +40,7 @@ var MESHRIGHT_LIMITEVENTS = 8192;
40
var MESHRIGHT_CHATNOTIFY = 16384;
41
var MESHRIGHT_UNINSTALL = 32768;
42
var MESHRIGHT_NODESKTOP = 65536;
43
+
44
if (require('MeshAgent').ARCHID == null)
45
{
46
var id = null;
@@ -58,7 +59,8 @@ if (require('MeshAgent').ARCHID == null)
59
if (id != null) { Object.defineProperty(require('MeshAgent'), 'ARCHID', { value: id }); }
60
}
61
61
-function createMeshCore(agent) {
62
+function createMeshCore(agent)
63
+{
64
var obj = {};
65
var agentFileHttpRequests = {}; // Currently active agent HTTPS GET requests from the server.
66
var agentFileHttpPendingRequests = []; // Pending HTTPS GET requests from the server.
@@ -67,7 +69,8 @@ function createMeshCore(agent) {
69
if (process.platform == 'win32' && require('user-sessions').isRoot())
70
{
71
// Check the Agent Uninstall MetaData for correctness, as the installer may have written an incorrect value
70
- try {
72
+ try
73
+ {
74
var writtenSize = 0, actualSize = Math.floor(require('fs').statSync(process.execPath).size / 1024);
75
try { writtenSize = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MeshCentralAgent', 'EstimatedSize'); } catch (e) { }
76
if (writtenSize != actualSize) { try { require('win-registry').WriteKey(require('win-registry').HKEY.LocalMachine, 'Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MeshCentralAgent', 'EstimatedSize', actualSize); } catch (e) { } }
@@ -91,7 +94,8 @@ function createMeshCore(agent) {
94
} catch (e) { }
95
}
96
94
- if (process.platform == 'darwin' && !process.versions) {
97
+ if (process.platform == 'darwin' && !process.versions)
98
+ {
99
// This is an older MacOS Agent, so we'll need to check the service definition so that Auto-Update will function correctly
100
var child = require('child_process').execFile('/bin/sh', ['sh']);
101
child.stdout.str = '';
@@ -100,18 +104,21 @@ function createMeshCore(agent) {
104
child.stdin.write(" if(c[1]==\"dict\"){ split(a[2], d, \"</dict>\"); if(split(d[1], truval, \"<true/>\")>1) { split(truval[1], kn1, \"<key>\"); split(kn1[2], kn2, \"</key>\"); print kn2[1]; } }");
105
child.stdin.write(" else { split(c[1], ka, \"/\"); if(ka[1]==\"true\") {print \"ALWAYS\";} } }'\nexit\n");
106
child.waitExit();
103
- if (child.stdout.str.trim() == 'Crashed') {
107
+ if (child.stdout.str.trim() == 'Crashed')
108
+ {
109
child = require('child_process').execFile('/bin/sh', ['sh']);
110
child.stdout.str = '';
111
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
112
child.stdin.write("launchctl list | grep 'meshagent' | awk '{ if($3==\"meshagent\"){print $1;}}'\nexit\n");
113
child.waitExit();
114
110
- if (parseInt(child.stdout.str.trim()) == process.pid) {
115
+ if (parseInt(child.stdout.str.trim()) == process.pid)
116
+ {
117
// The currently running MeshAgent is us, so we can continue with the update
118
var plist = require('fs').readFileSync('/Library/LaunchDaemons/meshagent_osx64_LaunchDaemon.plist').toString();
119
var tokens = plist.split('<key>KeepAlive</key>');
114
- if (tokens[1].split('>')[0].split('<')[1] == 'dict') {
120
+ if (tokens[1].split('>')[0].split('<')[1] == 'dict')
121
+ {
122
var tmp = tokens[1].split('</dict>');
123
tmp.shift();
124
tokens[1] = '\n <true/>' + tmp.join('</dict>');
@@ -167,7 +174,8 @@ function createMeshCore(agent) {
174
}
175
176
// Add an Intel AMT event to the log
170
- function addAmtEvent(msg) {
177
+ function addAmtEvent(msg)
178
+ {
179
if (obj.amtevents == null) { obj.amtevents = []; }
180
var d = new Date();
181
obj.amtevents.push(zeroPad(d.getHours(), 2) + ':' + zeroPad(d.getMinutes(), 2) + ':' + zeroPad(d.getSeconds(), 2) + ', ' + msg);
@@ -182,8 +190,10 @@ function createMeshCore(agent) {
190
obj.DAIPC.IPCPATH = process.platform == 'win32' ? ('\\\\.\\pipe\\' + require('_agentNodeId')() + '-DAIPC') : (process.cwd() + '/DAIPC');
191
try { obj.DAIPC.listen({ path: obj.DAIPC.IPCPATH, writableAll: true, maxConnections: 5 }); } catch (e) { }
192
obj.DAIPC._daipc = [];
185
- obj.DAIPC.on('connection', function (c) {
186
- c._send = function (j) {
193
+ obj.DAIPC.on('connection', function (c)
194
+ {
195
+ c._send = function (j)
196
+ {
197
var data = JSON.stringify(j);
198
var packet = Buffer.alloc(data.length + 4);
199
packet.writeUInt32LE(data.length + 4, 0);
@@ -193,7 +203,8 @@ function createMeshCore(agent) {
203
this._daipc.push(c);
204
c.parent = this;
205
c.on('end', function () { removeRegisteredApp(this); });
196
- c.on('data', function (chunk) {
206
+ c.on('data', function (chunk)
207
+ {
208
if (chunk.length < 4) { this.unshift(chunk); return; }
209
var len = chunk.readUInt32LE(0);
210
if (len > 8192) { removeRegisteredApp(this); this.end(); return; }
@@ -203,8 +214,10 @@ function createMeshCore(agent) {
214
try { data = JSON.parse(data.toString()); } catch (e) { }
215
if ((data == null) || (typeof data.cmd != 'string')) return;
216
206
- try {
207
- switch (data.cmd) {
217
+ try
218
+ {
219
+ switch (data.cmd)
220
+ {
221
case 'requesthelp':
222
if (this._registered == null) return;
223
sendConsoleText('Request Help (' + this._registered + '): ' + data.value);
@@ -219,7 +232,8 @@ function createMeshCore(agent) {
232
try { mesh.SendCommand({ action: 'sessions', type: 'help', value: {} }); } catch (e) { }
233
break;
234
case 'register':
222
- if (typeof data.value == 'string') {
235
+ if (typeof data.value == 'string')
236
+ {
237
this._registered = data.value;
238
var apps = {};
239
apps[data.value] = 1;
@@ -235,12 +249,13 @@ function createMeshCore(agent) {
249
this._send(data);
250
break;
251
case 'descriptors':
238
- require('ChainViewer').getSnapshot().then(function (f) {
252
+ require('ChainViewer').getSnapshot().then(function (f)
253
+ {
254
this.tag.payload.result = f;
255
this.tag.ipc._send(this.tag.payload);
256
}).parentPromise.tag = { ipc: this, payload: data };
257
break;
243
- case 'timerinfo':
258
+ case 'timerinfo':
259
data.result = require('ChainViewer').getTimerInfo();
260
this._send(data);
261
break;
@@ -256,10 +271,11 @@ function createMeshCore(agent) {
271
this._send({ cmd: 'sessions', sessions: tunnelUserCount });
272
break;
273
case 'meshToolInfo':
259
- try { mesh.SendCommand({ action: 'meshToolInfo', name: data.name, hash: data.hash, cookie: data.cookie?true:false, pipe: true }); } catch (e) { }
274
+ try { mesh.SendCommand({ action: 'meshToolInfo', name: data.name, hash: data.hash, cookie: data.cookie ? true : false, pipe: true }); } catch (e) { }
275
break;
276
case 'console':
262
- if (debugConsole) {
277
+ if (debugConsole)
278
+ {
279
var args = splitArgs(data.value);
280
processConsoleCommand(args[0].toLowerCase(), parseArgs(args), 0, 'pipe');
281
}
@@ -271,24 +287,28 @@ function createMeshCore(agent) {
287
});
288
289
// Send current sessions to registered apps
274
- function broadcastSessionsToRegisteredApps(x) {
290
+ function broadcastSessionsToRegisteredApps(x)
291
+ {
292
broadcastToRegisteredApps({ cmd: 'sessions', sessions: tunnelUserCount });
293
}
294
295
// Send this object to all registered local applications
279
- function broadcastToRegisteredApps(x) {
296
+ function broadcastToRegisteredApps(x)
297
+ {
298
if ((obj.DAIPC == null) || (obj.DAIPC._daipc == null)) return;
299
for (var i in obj.DAIPC._daipc) { if (obj.DAIPC._daipc[i]._registered != null) { obj.DAIPC._daipc[i]._send(x); } }
300
}
301
302
// Send this object to a specific registered local applications
285
- function sendToRegisteredApp(appid, x) {
303
+ function sendToRegisteredApp(appid, x)
304
+ {
305
if ((obj.DAIPC == null) || (obj.DAIPC._daipc == null)) return;
306
for (var i in obj.DAIPC._daipc) { if (obj.DAIPC._daipc[i]._registered == appid) { obj.DAIPC._daipc[i]._send(x); } }
307
}
308
309
// Send list of registered apps to the server
291
- function updateRegisteredAppsToServer() {
310
+ function updateRegisteredAppsToServer()
311
+ {
312
if ((obj.DAIPC == null) || (obj.DAIPC._daipc == null)) return;
313
var apps = {};
314
for (var i in obj.DAIPC._daipc) { if (apps[obj.DAIPC._daipc[i]._registered] == null) { apps[obj.DAIPC._daipc[i]._registered] = 1; } else { apps[obj.DAIPC._daipc[i]._registered]++; } }
@@ -296,26 +316,32 @@ function createMeshCore(agent) {
316
}
317
318
// Remove a registered app
299
- function removeRegisteredApp(pipe) {
319
+ function removeRegisteredApp(pipe)
320
+ {
321
for (var i = obj.DAIPC._daipc.length - 1; i >= 0; i--) { if (obj.DAIPC._daipc[i] === pipe) { obj.DAIPC._daipc.splice(i, 1); } }
322
if (pipe._registered != null) updateRegisteredAppsToServer();
323
}
324
304
- function diagnosticAgent_uninstall() {
325
+ function diagnosticAgent_uninstall()
326
+ {
327
require('service-manager').manager.uninstallService('meshagentDiagnostic');
328
require('task-scheduler').delete('meshagentDiagnostic/periodicStart');
329
};
308
- function diagnosticAgent_installCheck(install) {
309
- try {
330
+ function diagnosticAgent_installCheck(install)
331
+ {
332
+ try
333
+ {
334
var diag = require('service-manager').manager.getService('meshagentDiagnostic');
335
return (diag);
336
}
313
- catch (e) {
337
+ catch (e)
338
+ {
339
}
340
if (!install) { return (null); }
341
342
var svc = null;
318
- try {
343
+ try
344
+ {
345
require('service-manager').manager.installService(
346
{
347
name: 'meshagentDiagnostic',
@@ -327,7 +353,8 @@ function createMeshCore(agent) {
353
});
354
svc = require('service-manager').manager.getService('meshagentDiagnostic');
355
}
330
- catch (e) {
356
+ catch (e)
357
+ {
358
return (null);
359
}
360
var proxyConfig = require('global-tunnel').proxyConfig;
@@ -340,9 +367,11 @@ function createMeshCore(agent) {
367
ddb.Put('MeshServer', require('MeshAgent').ServerInfo.ServerUri);
368
if (cert.root.pfx) { ddb.Put('SelfNodeCert', cert.root.pfx); }
369
if (cert.tls) { ddb.Put('SelfNodeTlsCert', cert.tls.pfx); }
343
- if (proxyConfig) {
370
+ if (proxyConfig)
371
+ {
372
ddb.Put('WebProxy', proxyConfig.host + ':' + proxyConfig.port);
345
- } else {
373
+ } else
374
+ {
375
ddb.Put('ignoreProxyFile', '1');
376
}
377
@@ -359,18 +388,24 @@ function createMeshCore(agent) {
388
}
389
390
// Monitor the file 'batterystate.txt' in the agent's folder and sends battery update when this file is changed.
362
- if ((require('fs').existsSync(process.cwd() + 'batterystate.txt')) && (require('fs').watch != null)) {
391
+ if ((require('fs').existsSync(process.cwd() + 'batterystate.txt')) && (require('fs').watch != null))
392
+ {
393
// Setup manual battery monitoring
364
- require('MeshAgent')._batteryFileWatcher = require('fs').watch(process.cwd(), function () {
394
+ require('MeshAgent')._batteryFileWatcher = require('fs').watch(process.cwd(), function ()
395
+ {
396
if (require('MeshAgent')._batteryFileTimer != null) return;
366
- require('MeshAgent')._batteryFileTimer = setTimeout(function () {
367
- try {
397
+ require('MeshAgent')._batteryFileTimer = setTimeout(function ()
398
+ {
399
+ try
400
+ {
401
require('MeshAgent')._batteryFileTimer = null;
402
var data = null;
403
try { data = require('fs').readFileSync(process.cwd() + 'batterystate.txt').toString(); } catch (e) { }
371
- if ((data != null) && (data.length < 10)) {
404
+ if ((data != null) && (data.length < 10))
405
+ {
406
data = data.split(',');
373
- if ((data.length == 2) && ((data[0] == 'ac') || (data[0] == 'dc'))) {
407
+ if ((data.length == 2) && ((data[0] == 'ac') || (data[0] == 'dc')))
408
+ {
409
var level = parseInt(data[1]);
410
if ((level >= 0) && (level <= 100)) { require('MeshAgent').SendCommand({ action: 'battery', state: data[0], level: level }); }
411
}
@@ -378,24 +413,31 @@ function createMeshCore(agent) {
413
} catch (e) { }
414
}, 1000);
415
});
381
- } else {
416
+ } else
417
+ {
418
// Setup normal battery monitoring
383
- if (require('identifiers').isBatteryPowered && require('identifiers').isBatteryPowered()) {
384
- require('MeshAgent')._battLevelChanged = function _battLevelChanged(val) {
419
+ if (require('identifiers').isBatteryPowered && require('identifiers').isBatteryPowered())
420
+ {
421
+ require('MeshAgent')._battLevelChanged = function _battLevelChanged(val)
422
+ {
423
_battLevelChanged.self._currentBatteryLevel = val;
424
_battLevelChanged.self.SendCommand({ action: 'battery', state: _battLevelChanged.self._currentPowerState, level: val });
425
};
426
require('MeshAgent')._battLevelChanged.self = require('MeshAgent');
389
- require('MeshAgent')._powerChanged = function _powerChanged(val) {
427
+ require('MeshAgent')._powerChanged = function _powerChanged(val)
428
+ {
429
_powerChanged.self._currentPowerState = (val == 'AC' ? 'ac' : 'dc');
430
_powerChanged.self.SendCommand({ action: 'battery', state: (val == 'AC' ? 'ac' : 'dc'), level: _powerChanged.self._currentBatteryLevel });
431
};
432
require('MeshAgent')._powerChanged.self = require('MeshAgent');
394
- require('MeshAgent').on('Connected', function (status) {
395
- if (status == 0) {
433
+ require('MeshAgent').on('Connected', function (status)
434
+ {
435
+ if (status == 0)
436
+ {
437
require('power-monitor').removeListener('acdc', this._powerChanged);
438
require('power-monitor').removeListener('batteryLevel', this._battLevelChanged);
398
- } else {
439
+ } else
440
+ {
441
require('power-monitor').on('acdc', this._powerChanged);
442
require('power-monitor').on('batteryLevel', this._battLevelChanged);
443
}
@@ -445,12 +487,16 @@ function createMeshCore(agent) {
487
try { require('os').name().then(function (v) { meshCoreObj.osdesc = v; meshCoreObjChanged(); }); } catch (e) { }
488
489
// Setup logged in user monitoring (THIS IS BROKEN IN WIN7)
448
- try {
490
+ try
491
+ {
492
var userSession = require('user-sessions');
450
- userSession.on('changed', function onUserSessionChanged() {
451
- userSession.enumerateUsers().then(function (users) {
493
+ userSession.on('changed', function onUserSessionChanged()
494
+ {
495
+ userSession.enumerateUsers().then(function (users)
496
+ {
497
var u = [], a = users.Active;
453
- for (var i = 0; i < a.length; i++) {
498
+ for (var i = 0; i < a.length; i++)
499
+ {
500
var un = a[i].Domain ? (a[i].Domain + '\\' + a[i].Username) : (a[i].Username);
501
if (u.indexOf(un) == -1) { u.push(un); } // Only push users in the list once.
502
}
@@ -482,9 +528,11 @@ function createMeshCore(agent) {
528
var tunnelUserCount = { terminal: {}, files: {}, tcp: {}, udp: {}, msg: {} }; // List of userid->count sessions for terminal, files and TCP/UDP routing
529
530
// Add to the server event log
485
- function MeshServerLog(msg, state) {
531
+ function MeshServerLog(msg, state)
532
+ {
533
if (typeof msg == 'string') { msg = { action: 'log', msg: msg }; } else { msg.action = 'log'; }
487
- if (state) {
534
+ if (state)
535
+ {
536
if (state.userid) { msg.userid = state.userid; }
537
if (state.username) { msg.username = state.username; }
538
if (state.sessionid) { msg.sessionid = state.sessionid; }
@@ -494,9 +542,11 @@ function createMeshCore(agent) {
542
}
543
544
// Add to the server event log, use internationalized events
497
- function MeshServerLogEx(id, args, msg, state) {
545
+ function MeshServerLogEx(id, args, msg, state)
546
+ {
547
var msg = { action: 'log', msgid: id, msgArgs: args, msg: msg };
499
- if (state) {
548
+ if (state)
549
+ {
550
if (state.userid) { msg.userid = state.userid; }
551
if (state.username) { msg.username = state.username; }
552
if (state.sessionid) { msg.sessionid = state.sessionid; }
@@ -510,13 +560,16 @@ function createMeshCore(agent) {
560
sha = require('SHA256Stream');
561
mesh = require('MeshAgent');
562
childProcess = require('child_process');
513
- if (mesh.hasKVM == 1) { // if the agent is compiled with KVM support
563
+ if (mesh.hasKVM == 1)
564
+ { // if the agent is compiled with KVM support
565
// Check if this computer supports a desktop
566
try
567
{
517
- if ((process.platform == 'win32') || (process.platform == 'darwin') || (require('monitor-info').kvm_x11_support)) {
568
+ if ((process.platform == 'win32') || (process.platform == 'darwin') || (require('monitor-info').kvm_x11_support))
569
+ {
570
meshCoreObj.caps |= 1; meshCoreObjChanged();
519
- } else if (process.platform == 'linux' || process.platform == 'freebsd') {
571
+ } else if (process.platform == 'linux' || process.platform == 'freebsd')
572
+ {
573
require('monitor-info').on('kvmSupportDetected', function (value) { meshCoreObj.caps |= 1; meshCoreObjChanged(); });
574
}
575
} catch (e) { }
@@ -536,12 +589,16 @@ function createMeshCore(agent) {
589
// Fetch the SMBios Tables
590
var SMBiosTables = null;
591
var SMBiosTablesRaw = null;
539
- try {
592
+ try
593
+ {
594
var SMBiosModule = null;
595
try { SMBiosModule = require('smbios'); } catch (e) { }
542
- if (SMBiosModule != null) {
543
- SMBiosModule.get(function (data) {
544
- if (data != null) {
596
+ if (SMBiosModule != null)
597
+ {
598
+ SMBiosModule.get(function (data)
599
+ {
600
+ if (data != null)
601
+ {
602
SMBiosTablesRaw = data;
603
SMBiosTables = require('smbios').parse(data)
604
if (mesh.isControlChannelConnected) { mesh.SendCommand({ action: 'smbios', value: SMBiosTablesRaw }); }
@@ -562,7 +619,8 @@ function createMeshCore(agent) {
619
} catch (e) { sendConsoleText("ex1: " + e); }
620
621
// Try to load up the WIFI scanner
565
- try {
622
+ try
623
+ {
624
var wifiScannerLib = require('wifi-scanner');
625
wifiScanner = new wifiScannerLib();
626
wifiScanner.on('accessPoint', function (data) { sendConsoleText("wifiScanner: " + data); });
@@ -571,28 +629,36 @@ function createMeshCore(agent) {
629
// Get our location (lat/long) using our public IP address
630
var getIpLocationDataExInProgress = false;
631
var getIpLocationDataExCounts = [0, 0];
574
- function getIpLocationDataEx(func) {
632
+ function getIpLocationDataEx(func)
633
+ {
634
if (getIpLocationDataExInProgress == true) { return false; }
576
- try {
635
+ try
636
+ {
637
getIpLocationDataExInProgress = true;
638
getIpLocationDataExCounts[0]++;
639
var options = http.parseUri("http://ipinfo.io/json");
640
options.method = 'GET';
581
- http.request(options, function (resp) {
582
- if (resp.statusCode == 200) {
641
+ http.request(options, function (resp)
642
+ {
643
+ if (resp.statusCode == 200)
644
+ {
645
var geoData = '';
646
resp.data = function (geoipdata) { geoData += geoipdata; };
585
- resp.end = function () {
647
+ resp.end = function ()
648
+ {
649
var location = null;
587
- try {
588
- if (typeof geoData == 'string') {
650
+ try
651
+ {
652
+ if (typeof geoData == 'string')
653
+ {
654
var result = JSON.parse(geoData);
655
if (result.ip && result.loc) { location = result; }
656
}
657
} catch (e) { }
658
if (func) { getIpLocationDataExCounts[1]++; func(location); }
659
}
595
- } else { func(null); }
660
+ } else
661
+ { func(null); }
662
getIpLocationDataExInProgress = false;
663
}).end();
664
return true;
@@ -601,45 +667,57 @@ function createMeshCore(agent) {
667
}
668
669
// Remove all Gateway MAC addresses for interface list. This is useful because the gateway MAC is not always populated reliably.
604
- function clearGatewayMac(str) {
670
+ function clearGatewayMac(str)
671
+ {
672
if (str == null) return null;
673
var x = JSON.parse(str);
674
for (var i in x.netif) { if (x.netif[i].gatewaymac) { delete x.netif[i].gatewaymac } }
675
return JSON.stringify(x);
676
}
677
611
- function getIpLocationData(func) {
678
+ function getIpLocationData(func)
679
+ {
680
// Get the location information for the cache if possible
681
var publicLocationInfo = db.Get('publicLocationInfo');
682
if (publicLocationInfo != null) { publicLocationInfo = JSON.parse(publicLocationInfo); }
615
- if (publicLocationInfo == null) {
683
+ if (publicLocationInfo == null)
684
+ {
685
// Nothing in the cache, fetch the data
617
- getIpLocationDataEx(function (locationData) {
618
- if (locationData != null) {
686
+ getIpLocationDataEx(function (locationData)
687
+ {
688
+ if (locationData != null)
689
+ {
690
publicLocationInfo = {};
691
publicLocationInfo.netInfoStr = lastNetworkInfo;
692
publicLocationInfo.locationData = locationData;
693
var x = db.Put('publicLocationInfo', JSON.stringify(publicLocationInfo)); // Save to database
694
if (func) func(locationData); // Report the new location
624
- } else {
695
+ } else
696
+ {
697
if (func) func(null); // Report no location
698
}
699
});
628
- } else {
700
+ } else
701
+ {
702
// Check the cache
630
- if (clearGatewayMac(publicLocationInfo.netInfoStr) == clearGatewayMac(lastNetworkInfo)) {
703
+ if (clearGatewayMac(publicLocationInfo.netInfoStr) == clearGatewayMac(lastNetworkInfo))
704
+ {
705
// Cache match
706
if (func) func(publicLocationInfo.locationData);
633
- } else {
707
+ } else
708
+ {
709
// Cache mismatch
635
- getIpLocationDataEx(function (locationData) {
636
- if (locationData != null) {
710
+ getIpLocationDataEx(function (locationData)
711
+ {
712
+ if (locationData != null)
713
+ {
714
publicLocationInfo = {};
715
publicLocationInfo.netInfoStr = lastNetworkInfo;
716
publicLocationInfo.locationData = locationData;
717
var x = db.Put('publicLocationInfo', JSON.stringify(publicLocationInfo)); // Save to database
718
if (func) func(locationData); // Report the new location
642
- } else {
719
+ } else
720
+ {
721
if (func) func(publicLocationInfo.locationData); // Can't get new location, report the old location
722
}
723
});
@@ -648,8 +726,10 @@ function createMeshCore(agent) {
726
}
727
728
// Polyfill String.endsWith
651
- if (!String.prototype.endsWith) {
652
- String.prototype.endsWith = function (searchString, position) {
729
+ if (!String.prototype.endsWith)
730
+ {
731
+ String.prototype.endsWith = function (searchString, position)
732
+ {
733
var subjectString = this.toString();
734
if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { position = subjectString.length; }
735
position -= searchString.length;
@@ -660,13 +740,17 @@ function createMeshCore(agent) {
740
741
// Polyfill path.join
742
obj.path = {
663
- join: function () {
743
+ join: function ()
744
+ {
745
var x = [];
665
- for (var i in arguments) {
746
+ for (var i in arguments)
747
+ {
748
var w = arguments[i];
667
- if (w != null) {
749
+ if (w != null)
750
+ {
751
while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); }
669
- if (i != 0) {
752
+ if (i != 0)
753
+ {
754
while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); }
755
}
756
x.push(w);
@@ -690,7 +774,8 @@ function createMeshCore(agent) {
774
function buf2rstr(buf) { var r = ''; for (var i = 0; i < buf.length; i++) { r += String.fromCharCode(buf[i]); } return r; }
775
776
// Convert a hex string to a raw string // TODO: Do this using Buffer(), will be MUCH faster
693
- function hex2rstr(d) {
777
+ function hex2rstr(d)
778
+ {
779
if (typeof d != "string" || d.length == 0) return '';
780
var r = '', m = ('' + d).match(/../g), t;
781
while (t = m.shift()) r += String.fromCharCode('0x' + t);
@@ -698,7 +783,8 @@ function createMeshCore(agent) {
783
}
784
785
// Convert an object to string with all functions
701
- function objToString(x, p, pad, ret) {
786
+ function objToString(x, p, pad, ret)
787
+ {
788
if (ret == undefined) ret = '';
789
if (p == undefined) p = 0;
790
if (x == null) { return '[null]'; }
@@ -716,21 +802,26 @@ function createMeshCore(agent) {
802
function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ret; } return r; }
803
804
// Split a string taking into account the quoats. Used for command line parsing
719
- function splitArgs(str) {
805
+ function splitArgs(str)
806
+ {
807
var myArray = [], myRegexp = /[^\s"]+|"([^"]*)"/gi;
808
do { var match = myRegexp.exec(str); if (match != null) { myArray.push(match[1] ? match[1] : match[0]); } } while (match != null);
809
return myArray;
810
}
811
812
// Parse arguments string array into an object
726
- function parseArgs(argv) {
813
+ function parseArgs(argv)
814
+ {
815
var results = { '_': [] }, current = null;
728
- for (var i = 1, len = argv.length; i < len; i++) {
816
+ for (var i = 1, len = argv.length; i < len; i++)
817
+ {
818
var x = argv[i];
730
- if (x.length > 2 && x[0] == '-' && x[1] == '-') {
819
+ if (x.length > 2 && x[0] == '-' && x[1] == '-')
820
+ {
821
if (current != null) { results[current] = true; }
822
current = x.substring(2);
733
- } else {
823
+ } else
824
+ {
825
if (current != null) { results[current] = toNumberIfNumber(x); current = null; } else { results['_'].push(toNumberIfNumber(x)); }
826
}
827
}
@@ -739,7 +830,8 @@ function createMeshCore(agent) {
830
}
831
832
// Get server target url with a custom path
742
- function getServerTargetUrl(path) {
833
+ function getServerTargetUrl(path)
834
+ {
835
var x = mesh.ServerUrl;
836
//sendConsoleText("mesh.ServerUrl: " + mesh.ServerUrl);
837
if (x == null) { return null; }
@@ -750,27 +842,35 @@ function createMeshCore(agent) {
842
}
843
844
// Get server url. If the url starts with "*/..." change it, it not use the url as is.
753
- function getServerTargetUrlEx(url) {
845
+ function getServerTargetUrlEx(url)
846
+ {
847
if (url.substring(0, 2) == '*/') { return getServerTargetUrl(url.substring(2)); }
848
return url;
849
}
850
851
// Send a wake-on-lan packet
759
- function sendWakeOnLan(hexMac) {
852
+ function sendWakeOnLan(hexMac)
853
+ {
854
hexMac = hexMac.split(':').join('');
855
var count = 0;
762
- try {
856
+ try
857
+ {
858
var interfaces = require('os').networkInterfaces();
859
var magic = 'FFFFFFFFFFFF';
860
for (var x = 1; x <= 16; ++x) { magic += hexMac; }
861
var magicbin = Buffer.from(magic, 'hex');
862
768
- for (var adapter in interfaces) {
769
- if (interfaces.hasOwnProperty(adapter)) {
770
- for (var i = 0; i < interfaces[adapter].length; ++i) {
863
+ for (var adapter in interfaces)
864
+ {
865
+ if (interfaces.hasOwnProperty(adapter))
866
+ {
867
+ for (var i = 0; i < interfaces[adapter].length; ++i)
868
+ {
869
var addr = interfaces[adapter][i];
772
- if ((addr.family == 'IPv4') && (addr.mac != '00:00:00:00:00:00')) {
773
- try {
870
+ if ((addr.family == 'IPv4') && (addr.mac != '00:00:00:00:00:00'))
871
+ {
872
+ try
873
+ {
874
var socket = require('dgram').createSocket({ type: 'udp4' });
875
socket.bind({ address: addr.address });
876
socket.setBroadcast(true);
@@ -790,14 +890,22 @@ function createMeshCore(agent) {
890
}
891
892
// Handle a mesh agent command
793
- function handleServerCommand(data) {
794
- if (typeof data == 'object') {
893
+ function handleServerCommand(data)
894
+ {
895
+ if (typeof data == 'object')
896
+ {
897
// If this is a console command, parse it and call the console handler
796
- switch (data.action) {
898
+ switch (data.action)
899
+ {
900
+ case 'agentupdate':
901
+ agentUpdate_Start(data.url, { hash: data.hash, tlshash: data.servertlshash });
902
+ break;
903
case 'msg': {
798
- switch (data.type) {
904
+ switch (data.type)
905
+ {
906
case 'console': { // Process a console command
800
- if (data.value && data.sessionid) {
907
+ if (data.value && data.sessionid)
908
+ {
909
MeshServerLogEx(17, [data.value], "Processing console command: " + data.value, data);
910
var args = splitArgs(data.value);
911
processConsoleCommand(args[0].toLowerCase(), parseArgs(args), data.rights, data.sessionid);
@@ -805,10 +913,12 @@ function createMeshCore(agent) {
913
break;
914
}
915
case 'tunnel': {
808
- if (data.value != null) { // Process a new tunnel connection request
916
+ if (data.value != null)
917
+ { // Process a new tunnel connection request
918
// Create a new tunnel object
919
var xurl = getServerTargetUrlEx(data.value);
811
- if (xurl != null) {
920
+ if (xurl != null)
921
+ {
922
xurl = xurl.split('$').join('%24').split('@').join('%40'); // Escape the $ and @ characters
923
var woptions = http.parseUri(xurl);
924
woptions.perMessageDeflate = false;
@@ -816,7 +926,8 @@ function createMeshCore(agent) {
926
927
// Perform manual server TLS certificate checking based on the certificate hash given by the server.
928
woptions.rejectUnauthorized = 0;
819
- woptions.checkServerIdentity = function checkServerIdentity(certs) {
929
+ woptions.checkServerIdentity = function checkServerIdentity(certs)
930
+ {
931
// If the tunnel certificate matches the control channel certificate, accept the connection
932
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { }
933
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { }
@@ -859,7 +970,8 @@ function createMeshCore(agent) {
970
}
971
case 'messagebox': {
972
// Display a message box
862
- if (data.title && data.msg) {
973
+ if (data.title && data.msg)
974
+ {
975
MeshServerLogEx(18, [data.title, data.msg], "Displaying message box, title=" + data.title + ", message=" + data.msg, data);
976
data.msg = data.msg.split('\r').join('\\r').split('\n').join('\\n');
977
try { require('message-box').create(data.title, data.msg, 120); } catch (e) { }
@@ -868,8 +980,10 @@ function createMeshCore(agent) {
980
}
981
case 'ps': {
982
// Return the list of running processes
871
- if (data.sessionid) {
872
- processManager.getProcesses(function (plist) {
983
+ if (data.sessionid)
984
+ {
985
+ processManager.getProcesses(function (plist)
986
+ {
987
mesh.SendCommand({ action: 'msg', type: 'ps', value: JSON.stringify(plist), sessionid: data.sessionid });
988
});
989
}
@@ -877,7 +991,8 @@ function createMeshCore(agent) {
991
}
992
case 'pskill': {
993
// Kill a process
880
- if (data.value) {
994
+ if (data.value)
995
+ {
996
MeshServerLogEx(19, [data.value], "Killing process " + data.value, data);
997
try { process.kill(data.value); } catch (e) { sendConsoleText("pskill: " + JSON.stringify(e)); }
998
}
@@ -892,7 +1007,8 @@ function createMeshCore(agent) {
1007
}
1008
case 'serviceStop': {
1009
// Stop a service
895
- try {
1010
+ try
1011
+ {
1012
var service = require('service-manager').manager.getService(data.serviceName);
1013
if (service != null) { service.stop(); }
1014
} catch (e) { }
@@ -900,7 +1016,8 @@ function createMeshCore(agent) {
1016
}
1017
case 'serviceStart': {
1018
// Start a service
903
- try {
1019
+ try
1020
+ {
1021
var service = require('service-manager').manager.getService(data.serviceName);
1022
if (service != null) { service.start(); }
1023
} catch (e) { }
@@ -908,7 +1025,8 @@ function createMeshCore(agent) {
1025
}
1026
case 'serviceRestart': {
1027
// Restart a service
911
- try {
1028
+ try
1029
+ {
1030
var service = require('service-manager').manager.getService(data.serviceName);
1031
if (service != null) { service.restart(); }
1032
} catch (e) { }
@@ -917,12 +1035,16 @@ function createMeshCore(agent) {
1035
case 'deskBackground':
1036
{
1037
// Toggle desktop background
920
- try {
921
- if (process.platform == 'win32') {
1038
+ try
1039
+ {
1040
+ if (process.platform == 'win32')
1041
+ {
1042
var stype = require('user-sessions').getProcessOwnerName(process.pid).tsid == 0 ? 1 : 0;
1043
var sid = undefined;
924
- if (stype == 1) {
925
- if (require('MeshAgent')._tsid != null) {
1044
+ if (stype == 1)
1045
+ {
1046
+ if (require('MeshAgent')._tsid != null)
1047
+ {
1048
stype = 5;
1049
sid = require('MeshAgent')._tsid;
1050
}
@@ -938,13 +1060,15 @@ function createMeshCore(agent) {
1060
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
1061
child.stderr.on('data', function () { });
1062
child.waitExit();
941
- } else {
1063
+ } else
1064
+ {
1065
var id = require('user-sessions').consoleUid();
1066
var current = require('linux-gnome-helpers').getDesktopWallpaper(id);
1067
if (current != '/dev/null') { require('MeshAgent')._wallpaper = current; }
1068
require('linux-gnome-helpers').setDesktopWallpaper(id, current != '/dev/null' ? undefined : require('MeshAgent')._wallpaper);
1069
}
947
- } catch (e) {
1070
+ } catch (e)
1071
+ {
1072
sendConsoleText(e);
1073
}
1074
break;
@@ -959,16 +1083,22 @@ function createMeshCore(agent) {
1083
case 'getclip': {
1084
// Send the load clipboard back to the user
1085
//sendConsoleText('getClip: ' + JSON.stringify(data));
962
- if (require('MeshAgent').isService) {
963
- require('clipboard').dispatchRead().then(function (str) {
964
- if (str) {
1086
+ if (require('MeshAgent').isService)
1087
+ {
1088
+ require('clipboard').dispatchRead().then(function (str)
1089
+ {
1090
+ if (str)
1091
+ {
1092
MeshServerLogEx(21, [str.length], "Getting clipboard content, " + str.length + " byte(s)", data);
1093
mesh.SendCommand({ action: 'msg', type: 'getclip', sessionid: data.sessionid, data: str, tag: data.tag });
1094
}
1095
});
969
- } else {
970
- require("clipboard").read().then(function (str) {
971
- if (str) {
1096
+ } else
1097
+ {
1098
+ require("clipboard").read().then(function (str)
1099
+ {
1100
+ if (str)
1101
+ {
1102
MeshServerLogEx(21, [str.length], "Getting clipboard content, " + str.length + " byte(s)", data);
1103
mesh.SendCommand({ action: 'msg', type: 'getclip', sessionid: data.sessionid, data: str, tag: data.tag });
1104
}
@@ -979,7 +1109,8 @@ function createMeshCore(agent) {
1109
case 'setclip': {
1110
// Set the load clipboard to a user value
1111
//sendConsoleText('setClip: ' + JSON.stringify(data));
982
- if (typeof data.data == 'string') {
1112
+ if (typeof data.data == 'string')
1113
+ {
1114
MeshServerLogEx(22, [data.data.length], "Setting clipboard content, " + data.data.length + " byte(s)", data);
1115
if (require('MeshAgent').isService) { require('clipboard').dispatchWrite(data.data); } else { require("clipboard")(data.data); } // Set the clipboard
1116
mesh.SendCommand({ action: 'msg', type: 'setclip', sessionid: data.sessionid, success: true });
@@ -1014,7 +1145,8 @@ function createMeshCore(agent) {
1145
break;
1146
}
1147
case 'acmactivate': {
1017
- if (amt != null) {
1148
+ if (amt != null)
1149
+ {
1150
MeshServerLogEx(23, null, "Attempting Intel AMT ACM mode activation", data);
1151
amt.setAcmResponse(data);
1152
}
@@ -1032,17 +1164,21 @@ function createMeshCore(agent) {
1164
1165
// data.runAsUser: 0=Agent,1=UserOrAgent,2=UserOnly
1166
var options = {};
1035
- if (data.runAsUser > 0) {
1167
+ if (data.runAsUser > 0)
1168
+ {
1169
try { options.uid = require('user-sessions').consoleUid(); } catch (e) { }
1170
options.type = require('child_process').SpawnTypes.TERM;
1171
}
1039
- if (data.runAsUser == 2) {
1172
+ if (data.runAsUser == 2)
1173
+ {
1174
if (options.uid == null) break;
1175
if (((require('user-sessions').minUid != null) && (options.uid < require('user-sessions').minUid()))) break; // This command can only run as user.
1176
}
1177
1044
- if (process.platform == 'win32') {
1045
- if (data.type == 1) {
1178
+ if (process.platform == 'win32')
1179
+ {
1180
+ if (data.type == 1)
1181
+ {
1182
// Windows command shell
1183
mesh.cmdchild = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ['cmd'], options);
1184
mesh.cmdchild.descriptorMetadata = 'UserCommandsShell';
@@ -1050,7 +1186,8 @@ function createMeshCore(agent) {
1186
mesh.cmdchild.stderr.on('data', function (c) { sendConsoleText(c.toString()); });
1187
mesh.cmdchild.stdin.write(data.cmds + '\r\nexit\r\n');
1188
mesh.cmdchild.on('exit', function () { sendConsoleText("Run commands completed."); delete mesh.cmdchild; });
1053
- } else if (data.type == 2) {
1189
+ } else if (data.type == 2)
1190
+ {
1191
// Windows Powershell
1192
mesh.cmdchild = require('child_process').execFile(process.env['windir'] + '\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', ['powershell', '-noprofile', '-nologo', '-command', '-'], options);
1193
mesh.cmdchild.descriptorMetadata = 'UserCommandsPowerShell';
@@ -1059,7 +1196,8 @@ function createMeshCore(agent) {
1196
mesh.cmdchild.stdin.write(data.cmds + '\r\nexit\r\n');
1197
mesh.cmdchild.on('exit', function () { sendConsoleText("Run commands completed."); delete mesh.cmdchild; });
1198
}
1062
- } else if (data.type == 3) {
1199
+ } else if (data.type == 3)
1200
+ {
1201
// Linux shell
1202
mesh.cmdchild = require('child_process').execFile('/bin/sh', ['sh'], options);
1203
mesh.cmdchild.descriptorMetadata = 'UserCommandsShell';
@@ -1081,7 +1219,8 @@ function createMeshCore(agent) {
1219
{
1220
}
1221
1084
- if (require('service-manager').manager.getService(agentName).isMe()) {
1222
+ if (require('service-manager').manager.getService(agentName).isMe())
1223
+ {
1224
try { diagnosticAgent_uninstall(); } catch (e) { }
1225
var js = "require('service-manager').manager.getService('" + agentName + "').stop(); require('service-manager').manager.uninstallService('" + agentName + "'); process.exit();";
1226
this.child = require('child_process').execFile(process.execPath, [process.platform == 'win32' ? (process.execPath.split('\\').pop()) : (process.execPath.split('/').pop()), '-b64exec', Buffer.from(js).toString('base64')], { type: 4, detached: true });
@@ -1089,7 +1228,8 @@ function createMeshCore(agent) {
1228
break;
1229
case 'poweraction': {
1230
// Server telling us to execute a power action
1092
- if ((mesh.ExecPowerState != undefined) && (data.actiontype)) {
1231
+ if ((mesh.ExecPowerState != undefined) && (data.actiontype))
1232
+ {
1233
var forced = 0;
1234
if (data.forced == 1) { forced = 1; }
1235
data.actiontype = parseInt(data.actiontype);
@@ -1107,7 +1247,8 @@ function createMeshCore(agent) {
1247
}
1248
case 'toast': {
1249
// Display a toast message
1110
- if (data.title && data.msg) {
1250
+ if (data.title && data.msg)
1251
+ {
1252
MeshServerLogEx(26, [data.title, data.msg], "Displaying toast message, title=" + data.title + ", message=" + data.msg, data);
1253
data.msg = data.msg.split('\r').join('\\r').split('\n').join('\\n');
1254
try { require('toaster').Toast(data.title, data.msg); } catch (e) { }
@@ -1124,7 +1265,8 @@ function createMeshCore(agent) {
1265
case 'amtconfig': {
1266
// Perform Intel AMT activation and/or configuration
1267
if ((apftunnel != null) || (amt == null) || (typeof data.user != 'string') || (typeof data.pass != 'string')) break;
1127
- amt.getMeiState(15, function (state) {
1268
+ amt.getMeiState(15, function (state)
1269
+ {
1270
if ((apftunnel != null) || (amt == null)) return;
1271
if ((state == null) || (state.ProvisioningState == null)) return;
1272
if ((state.UUID == null) || (state.UUID.length != 36)) return; // Bad UUID
@@ -1141,10 +1283,12 @@ function createMeshCore(agent) {
1283
};
1284
addAmtEvent('LMS tunnel start.');
1285
apftunnel = require('amt-apfclient')({ debug: false }, apfarg);
1144
- apftunnel.onJsonControl = function (data) {
1286
+ apftunnel.onJsonControl = function (data)
1287
+ {
1288
if (data.action == 'console') { addAmtEvent(data.msg); } // Add console message to AMT event log
1289
if (data.action == 'mestate') { amt.getMeiState(15, function (state) { apftunnel.updateMeiState(state); }); } // Update the MEI state
1147
- if (data.action == 'deactivate') { // Request CCM deactivation
1290
+ if (data.action == 'deactivate')
1291
+ { // Request CCM deactivation
1292
var amtMeiModule, amtMei;
1293
try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { if (apftunnel) apftunnel.sendMeiDeactivationState(1); return; }
1294
amtMei.on('error', function (e) { if (apftunnel) apftunnel.sendMeiDeactivationState(1); });
@@ -1164,7 +1308,8 @@ function createMeshCore(agent) {
1308
}
1309
case 'sysinfo': {
1310
// Fetch system information
1167
- getSystemInformation(function (results) {
1311
+ getSystemInformation(function (results)
1312
+ {
1313
if ((results != null) && (data.hash != results.hash)) { mesh.SendCommand({ action: 'sysinfo', sessionid: this.sessionid, data: results }); }
1314
});
1315
break;
@@ -1177,14 +1322,18 @@ function createMeshCore(agent) {
1322
}
1323
case 'coredump':
1324
// Set the current agent coredump situation.
1180
- if (data.value === true) {
1181
- if (process.platform == 'win32') {
1325
+ if (data.value === true)
1326
+ {
1327
+ if (process.platform == 'win32')
1328
+ {
1329
// TODO: This replace() below is not ideal, would be better to remove the .exe at the end instead of replace.
1330
process.coreDumpLocation = process.execPath.replace('.exe', '.dmp');
1184
- } else {
1331
+ } else
1332
+ {
1333
process.coreDumpLocation = (process.cwd() != '//') ? (process.cwd() + 'core') : null;
1334
}
1187
- } else if (data.value === false) {
1335
+ } else if (data.value === false)
1336
+ {
1337
process.coreDumpLocation = null;
1338
}
1339
break;
@@ -1193,15 +1342,18 @@ function createMeshCore(agent) {
1342
var r = { action: 'getcoredump', value: (process.coreDumpLocation != null) };
1343
var coreDumpPath = null;
1344
if (process.platform == 'win32') { coreDumpPath = process.coreDumpLocation; } else { coreDumpPath = (process.cwd() != '//') ? fs.existsSync(process.cwd() + 'core') : null; }
1196
- if ((coreDumpPath != null) && (fs.existsSync(coreDumpPath))) {
1197
- try {
1345
+ if ((coreDumpPath != null) && (fs.existsSync(coreDumpPath)))
1346
+ {
1347
+ try
1348
+ {
1349
var coredate = fs.statSync(coreDumpPath).mtime;
1350
var coretime = new Date(coredate).getTime();
1351
var agenttime = new Date(fs.statSync(process.execPath).mtime).getTime();
1352
if (coretime > agenttime) { r.exists = (db.Get('CoreDumpTime') != coredate); }
1353
} catch (ex) { }
1354
}
1204
- if (r.exists == true) {
1355
+ if (r.exists == true)
1356
+ {
1357
r.agenthashhex = getSHA384FileHash(process.execPath).toString('hex'); // Hash of current agent
1358
r.corehashhex = getSHA384FileHash(coreDumpPath).toString('hex'); // Hash of core dump file
1359
}
@@ -1222,7 +1374,8 @@ function createMeshCore(agent) {
1374
}
1375
1376
// Agent just get a file from the server and save it locally.
1225
- function serverFetchFile() {
1377
+ function serverFetchFile()
1378
+ {
1379
if ((Object.keys(agentFileHttpRequests).length > 4) || (agentFileHttpPendingRequests.length == 0)) return; // No more than 4 active HTTPS requests to the server.
1380
var data = agentFileHttpPendingRequests.shift();
1381
if ((data.overwrite !== true) && fs.existsSync(data.path)) return; // Don't overwrite an existing file.
@@ -1233,7 +1386,8 @@ function createMeshCore(agent) {
1386
1387
// Perform manual server TLS certificate checking based on the certificate hash given by the server.
1388
agentFileHttpOptions.rejectUnauthorized = 0;
1236
- agentFileHttpOptions.checkServerIdentity = function checkServerIdentity(certs) {
1389
+ agentFileHttpOptions.checkServerIdentity = function checkServerIdentity(certs)
1390
+ {
1391
// If the tunnel certificate matches the control channel certificate, accept the connection
1392
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { }
1393
try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { }
@@ -1244,9 +1398,11 @@ function createMeshCore(agent) {
1398
1399
if (agentFileHttpOptions == null) return;
1400
var agentFileHttpRequest = http.request(agentFileHttpOptions,
1247
- function (response) {
1401
+ function (response)
1402
+ {
1403
response.xparent = this;
1249
- try {
1404
+ try
1405
+ {
1406
response.xfile = fs.createWriteStream(this.xpath, { flags: 'wbN' })
1407
response.pipe(response.xfile);
1408
response.end = function () { delete agentFileHttpRequests[this.xparent.xurlpath]; delete this.xparent; serverFetchFile(); }
@@ -1269,10 +1425,13 @@ function createMeshCore(agent) {
1425
}
1426
*/
1427
1272
- function getSystemInformation(func) {
1273
- try {
1428
+ function getSystemInformation(func)
1429
+ {
1430
+ try
1431
+ {
1432
var results = { hardware: require('identifiers').get() }; // Hardware info
1275
- if (results.hardware && results.hardware.windows) {
1433
+ if (results.hardware && results.hardware.windows)
1434
+ {
1435
// Remove extra entries and things that change quickly
1436
var x = results.hardware.windows.osinfo;
1437
try { delete x.FreePhysicalMemory; } catch (e) { }
@@ -1282,7 +1441,8 @@ function createMeshCore(agent) {
1441
try { delete x.MaxProcessMemorySize; } catch (e) { }
1442
try { delete x.TotalVirtualMemorySize; } catch (e) { }
1443
try { delete x.TotalVisibleMemorySize; } catch (e) { }
1285
- try {
1444
+ try
1445
+ {
1446
if (results.hardware.windows.memory) { for (var i in results.hardware.windows.memory) { delete results.hardware.windows.memory[i].Node; } }
1447
if (results.hardware.windows.osinfo) { delete results.hardware.windows.osinfo.Node; }
1448
if (results.hardware.windows.partitions) { for (var i in results.hardware.windows.partitions) { delete results.hardware.windows.partitions[i].Node; } }
@@ -1318,35 +1478,46 @@ function createMeshCore(agent) {
1478
}
1479
1480
// Get a formated response for a given directory path
1321
- function getDirectoryInfo(reqpath) {
1481
+ function getDirectoryInfo(reqpath)
1482
+ {
1483
var response = { path: reqpath, dir: [] };
1323
- if (((reqpath == undefined) || (reqpath == '')) && (process.platform == 'win32')) {
1484
+ if (((reqpath == undefined) || (reqpath == '')) && (process.platform == 'win32'))
1485
+ {
1486
// List all the drives in the root, or the root itself
1487
var results = null;
1488
try { results = fs.readDrivesSync(); } catch (e) { } // TODO: Anyway to get drive total size and free space? Could draw a progress bar.
1327
- if (results != null) {
1328
- for (var i = 0; i < results.length; ++i) {
1489
+ if (results != null)
1490
+ {
1491
+ for (var i = 0; i < results.length; ++i)
1492
+ {
1493
var drive = { n: results[i].name, t: 1 };
1494
if (results[i].type == 'REMOVABLE') { drive.dt = 'removable'; } // TODO: See if this is USB/CDROM or something else, we can draw icons.
1495
response.dir.push(drive);
1496
}
1497
}
1334
- } else {
1498
+ } else
1499
+ {
1500
// List all the files and folders in this path
1501
if (reqpath == '') { reqpath = '/'; }
1502
var results = null, xpath = obj.path.join(reqpath, '*');
1503
//if (process.platform == "win32") { xpath = xpath.split('/').join('\\'); }
1504
try { results = fs.readdirSync(xpath); } catch (e) { }
1340
- if (results != null) {
1341
- for (var i = 0; i < results.length; ++i) {
1342
- if ((results[i] != '.') && (results[i] != '..')) {
1505
+ if (results != null)
1506
+ {
1507
+ for (var i = 0; i < results.length; ++i)
1508
+ {
1509
+ if ((results[i] != '.') && (results[i] != '..'))
1510
+ {
1511
var stat = null, p = obj.path.join(reqpath, results[i]);
1512
//if (process.platform == "win32") { p = p.split('/').join('\\'); }
1513
try { stat = fs.statSync(p); } catch (e) { } // TODO: Get file size/date
1346
- if ((stat != null) && (stat != undefined)) {
1347
- if (stat.isDirectory() == true) {
1514
+ if ((stat != null) && (stat != undefined))
1515
+ {
1516
+ if (stat.isDirectory() == true)
1517
+ {
1518
response.dir.push({ n: results[i], t: 2, d: stat.mtime });
1349
- } else {
1519
+ } else
1520
+ {
1521
response.dir.push({ n: results[i], t: 3, s: stat.size, d: stat.mtime });
1522
}
1523
}
@@ -1358,7 +1529,8 @@ function createMeshCore(agent) {
1529
}
1530
1531
// Tunnel callback operations
1361
- function onTunnelUpgrade(response, s, head) {
1532
+ function onTunnelUpgrade(response, s, head)
1533
+ {
1534
this.s = s;
1535
s.httprequest = this;
1536
s.end = onTunnelClosed;
@@ -1377,7 +1549,8 @@ function createMeshCore(agent) {
1549
1550
//sendConsoleText('onTunnelUpgrade - ' + this.tcpport + ' - ' + this.udpport);
1551
1380
- if (this.tcpport != null) {
1552
+ if (this.tcpport != null)
1553
+ {
1554
// This is a TCP relay connection, pause now and try to connect to the target.
1555
s.pause();
1556
s.data = onTcpRelayServerTunnelData;
@@ -1387,12 +1560,14 @@ function createMeshCore(agent) {
1560
s.tcprelay.peerindex = this.index;
1561
1562
// Add the TCP session to the count and update the server
1390
- if (s.httprequest.userid != null) {
1563
+ if (s.httprequest.userid != null)
1564
+ {
1565
if (tunnelUserCount.tcp[s.httprequest.userid] == null) { tunnelUserCount.tcp[s.httprequest.userid] = 1; } else { tunnelUserCount.tcp[s.httprequest.userid]++; }
1566
try { mesh.SendCommand({ action: 'sessions', type: 'tcp', value: tunnelUserCount.tcp }); } catch (e) { }
1567
broadcastSessionsToRegisteredApps();
1568
}
1395
- } if (this.udpport != null) {
1569
+ } if (this.udpport != null)
1570
+ {
1571
// This is a UDP relay connection, get the UDP socket setup. // TODO: ***************
1572
s.data = onUdpRelayServerTunnelData;
1573
s.udprelay = require('dgram').createSocket({ type: 'udp4' });
@@ -1404,34 +1579,41 @@ function createMeshCore(agent) {
1579
s.udprelay.first = true;
1580
1581
// Add the UDP session to the count and update the server
1407
- if (s.httprequest.userid != null) {
1582
+ if (s.httprequest.userid != null)
1583
+ {
1584
if (tunnelUserCount.udp[s.httprequest.userid] == null) { tunnelUserCount.udp[s.httprequest.userid] = 1; } else { tunnelUserCount.udp[s.httprequest.userid]++; }
1585
try { mesh.SendCommand({ action: 'sessions', type: 'udp', value: tunnelUserCount.tcp }); } catch (e) { }
1586
broadcastSessionsToRegisteredApps();
1587
}
1412
- } else {
1588
+ } else
1589
+ {
1590
// This is a normal connect for KVM/Terminal/Files
1591
s.data = onTunnelData;
1592
}
1593
}
1594
1595
// Called when UDP relay data is received // TODO****
1419
- function onUdpRelayTargetTunnelConnect(data) {
1596
+ function onUdpRelayTargetTunnelConnect(data)
1597
+ {
1598
var peerTunnel = tunnels[this.peerindex];
1599
peerTunnel.s.write(data);
1600
}
1601
1602
// Called when we get data from the server for a TCP relay (We have to skip the first received 'c' and pipe the rest)
1425
- function onUdpRelayServerTunnelData(data) {
1426
- if (this.udprelay.first === true) {
1603
+ function onUdpRelayServerTunnelData(data)
1604
+ {
1605
+ if (this.udprelay.first === true)
1606
+ {
1607
delete this.udprelay.first; // Skip the first 'c' that is received.
1428
- } else {
1608
+ } else
1609
+ {
1610
this.udprelay.send(data, parseInt(this.udprelay.udpport), this.udprelay.udpaddr ? this.udprelay.udpaddr : '127.0.0.1');
1611
}
1612
}
1613
1614
// Called when the TCP relay target is connected
1434
- function onTcpRelayTargetTunnelConnect() {
1615
+ function onTcpRelayTargetTunnelConnect()
1616
+ {
1617
var peerTunnel = tunnels[this.peerindex];
1618
this.pipe(peerTunnel.s); // Pipe Target --> Server
1619
peerTunnel.s.first = true;
@@ -1439,24 +1621,30 @@ function createMeshCore(agent) {
1621
}
1622
1623
// Called when we get data from the server for a TCP relay (We have to skip the first received 'c' and pipe the rest)
1442
- function onTcpRelayServerTunnelData(data) {
1443
- if (this.first == true) {
1444
- this.first = false;
1624
+ function onTcpRelayServerTunnelData(data)
1625
+ {
1626
+ if (this.first == true)
1627
+ {
1628
+ this.first = false;
1629
this.pipe(this.tcprelay, { dataTypeSkip: 1 }); // Pipe Server --> Target (don't pipe text type websocket frames)
1630
}
1631
}
1632
1449
- function onTunnelClosed() {
1633
+ function onTunnelClosed()
1634
+ {
1635
var tunnel = tunnels[this.httprequest.index];
1636
if (tunnel == null) return; // Stop duplicate calls.
1637
1638
// If this is a routing session, clean up and send the new session counts.
1454
- if (this.httprequest.userid != null) {
1455
- if (this.httprequest.tcpport != null) {
1639
+ if (this.httprequest.userid != null)
1640
+ {
1641
+ if (this.httprequest.tcpport != null)
1642
+ {
1643
if (tunnelUserCount.tcp[this.httprequest.userid] != null) { tunnelUserCount.tcp[this.httprequest.userid]--; if (tunnelUserCount.tcp[this.httprequest.userid] <= 0) { delete tunnelUserCount.tcp[this.httprequest.userid]; } }
1644
try { mesh.SendCommand({ action: 'sessions', type: 'tcp', value: tunnelUserCount.tcp }); } catch (e) { }
1645
broadcastSessionsToRegisteredApps();
1459
- } else if (this.httprequest.udpport != null) {
1646
+ } else if (this.httprequest.udpport != null)
1647
+ {
1648
if (tunnelUserCount.udp[this.httprequest.userid] != null) { tunnelUserCount.udp[this.httprequest.userid]--; if (tunnelUserCount.udp[this.httprequest.userid] <= 0) { delete tunnelUserCount.udp[this.httprequest.userid]; } }
1649
try { mesh.SendCommand({ action: 'sessions', type: 'udp', value: tunnelUserCount.udp }); } catch (e) { }
1650
broadcastSessionsToRegisteredApps();
@@ -1464,7 +1652,8 @@ function createMeshCore(agent) {
1652
}
1653
1654
// Sent tunnel statistics to the server, only send this if compression was used.
1467
- if ((this.bytesSent_uncompressed) && (this.bytesSent_uncompressed.toString() != this.bytesSent_actual.toString())) {
1655
+ if ((this.bytesSent_uncompressed) && (this.bytesSent_uncompressed.toString() != this.bytesSent_actual.toString()))
1656
+ {
1657
mesh.SendCommand({
1658
action: 'tunnelCloseStats',
1659
url: tunnel.url,
@@ -1497,7 +1686,8 @@ function createMeshCore(agent) {
1686
if (this.httprequest.downloadFile) { delete this.httprequest.downloadFile; }
1687
1688
// Clean up WebRTC
1500
- if (this.webrtc != null) {
1689
+ if (this.webrtc != null)
1690
+ {
1691
if (this.webrtc.rtcchannel) { try { this.webrtc.rtcchannel.close(); } catch (e) { } this.webrtc.rtcchannel.removeAllListeners('data'); this.webrtc.rtcchannel.removeAllListeners('end'); delete this.webrtc.rtcchannel; }
1692
if (this.webrtc.websocket) { delete this.webrtc.websocket; }
1693
try { this.webrtc.close(); } catch (e) { }
@@ -1511,17 +1701,21 @@ function createMeshCore(agent) {
1701
this.removeAllListeners('data');
1702
}
1703
function onTunnelSendOk() { /*sendConsoleText("Tunnel #" + this.index + " SendOK.", this.sessionid);*/ }
1514
- function onTunnelData(data) {
1704
+ function onTunnelData(data)
1705
+ {
1706
//console.log("OnTunnelData");
1707
//sendConsoleText('OnTunnelData, ' + data.length + ', ' + typeof data + ', ' + data);
1708
1709
// If this is upload data, save it to file
1519
- if ((this.httprequest.uploadFile) && (typeof data == 'object') && (data[0] != 123)) {
1710
+ if ((this.httprequest.uploadFile) && (typeof data == 'object') && (data[0] != 123))
1711
+ {
1712
// Save the data to file being uploaded.
1521
- if (data[0] == 0) {
1713
+ if (data[0] == 0)
1714
+ {
1715
// If data starts with zero, skip the first byte. This is used to escape binary file data from JSON.
1716
try { fs.writeSync(this.httprequest.uploadFile, data, 1, data.length - 1); } catch (e) { sendConsoleText('FileUpload Error'); this.write(Buffer.from(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
1524
- } else {
1717
+ } else
1718
+ {
1719
// If data does not start with zero, save as-is.
1720
try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { sendConsoleText('FileUpload Error'); this.write(Buffer.from(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
1721
}
@@ -1529,19 +1723,22 @@ function createMeshCore(agent) {
1723
return;
1724
}
1725
1532
- if (this.httprequest.state == 0) {
1726
+ if (this.httprequest.state == 0)
1727
+ {
1728
// Check if this is a relay connection
1729
if ((data == 'c') || (data == 'cr')) { this.httprequest.state = 1; /*sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid);*/ }
1730
}
1731
else
1732
{
1733
// Handle tunnel data
1539
- if (this.httprequest.protocol == 0) { // 1 = Terminal (admin), 2 = Desktop, 5 = Files, 6 = PowerShell (admin), 7 = Plugin Data Exchange, 8 = Terminal (user), 9 = PowerShell (user), 10 = FileTransfer
1734
+ if (this.httprequest.protocol == 0)
1735
+ { // 1 = Terminal (admin), 2 = Desktop, 5 = Files, 6 = PowerShell (admin), 7 = Plugin Data Exchange, 8 = Terminal (user), 9 = PowerShell (user), 10 = FileTransfer
1736
// Take a look at the protocol
1737
if ((data.length > 3) && (data[0] == '{')) { onTunnelControlData(data, this); return; }
1738
this.httprequest.protocol = parseInt(data);
1739
if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; }
1544
- if (this.httprequest.protocol == 10) {
1740
+ if (this.httprequest.protocol == 10)
1741
+ {
1742
//
1743
// Basic file transfer
1744
//
@@ -1549,12 +1746,14 @@ function createMeshCore(agent) {
1746
if ((process.platform != 'win32') && (this.httprequest.xoptions.file.startsWith('/') == false)) { this.httprequest.xoptions.file = '/' + this.httprequest.xoptions.file; }
1747
try { stats = require('fs').statSync(this.httprequest.xoptions.file) } catch (e) { }
1748
try { if (stats) { this.httprequest.downloadFile = fs.createReadStream(this.httprequest.xoptions.file, { flags: 'rbN' }); } } catch (e) { }
1552
- if (this.httprequest.downloadFile) {
1749
+ if (this.httprequest.downloadFile)
1750
+ {
1751
//sendConsoleText('BasicFileTransfer, ok, ' + this.httprequest.xoptions.file + ', ' + JSON.stringify(stats));
1752
this.write(JSON.stringify({ op: 'ok', size: stats.size }));
1753
this.httprequest.downloadFile.pipe(this);
1754
this.httprequest.downloadFile.end = function () { }
1557
- } else {
1755
+ } else
1756
+ {
1757
//sendConsoleText('BasicFileTransfer, cancel, ' + this.httprequest.xoptions.file);
1758
this.write(JSON.stringify({ op: 'cancel' }));
1759
}
@@ -1566,7 +1765,8 @@ function createMeshCore(agent) {
1765
//
1766
1767
// Check user access rights for terminal
1569
- if (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) || ((this.httprequest.rights != 0xFFFFFFFF) && ((this.httprequest.rights & MESHRIGHT_NOTERMINAL) != 0))) {
1768
+ if (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) || ((this.httprequest.rights != 0xFFFFFFFF) && ((this.httprequest.rights & MESHRIGHT_NOTERMINAL) != 0)))
1769
+ {
1770
// Disengage this tunnel, user does not have the rights to do this!!
1771
this.httprequest.protocol = 999999;
1772
this.httprequest.s.end();
@@ -1628,7 +1828,8 @@ function createMeshCore(agent) {
1828
{
1829
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 }));
1830
var consentMessage = this.httprequest.username + " requesting remote terminal access. Grant access?", consentTitle = 'MeshCentral';
1631
- if (this.httprequest.soptions != null) {
1831
+ if (this.httprequest.soptions != null)
1832
+ {
1833
if (this.httprequest.soptions.consentTitle != null) { consentTitle = this.httprequest.soptions.consentTitle; }
1834
if (this.httprequest.soptions.consentMsgTerminal != null) { consentMessage = this.httprequest.soptions.consentMsgTerminal.replace('{0}', this.httprequest.realname).replace('{1}', this.httprequest.username); }
1835
}
@@ -1665,7 +1866,7 @@ function createMeshCore(agent) {
1866
this.httprequest.connectionPromise.ws = this.that;
1867
1868
// Start Terminal
1668
- if(process.platform == 'win32')
1869
+ if (process.platform == 'win32')
1870
{
1871
try
1872
{
@@ -1836,7 +2037,8 @@ function createMeshCore(agent) {
2037
{
2038
// User Notifications is required
2039
var notifyMessage = this.ws.httprequest.username + " started a remote terminal session.", notifyTitle = "MeshCentral";
1839
- if (this.ws.httprequest.soptions != null) {
2040
+ if (this.ws.httprequest.soptions != null)
2041
+ {
2042
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
2043
if (this.ws.httprequest.soptions.notifyMsgTerminal != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgTerminal.replace('{0}', this.ws.httprequest.realname).replace('{1}', this.ws.httprequest.username); }
2044
}
@@ -1855,7 +2057,7 @@ function createMeshCore(agent) {
2057
// DO NOT start terminal
2058
this.that.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString(), msgid: 2 }));
2059
this.that.end();
1858
- });
2060
+ });
2061
}
2062
else if (this.httprequest.protocol == 2)
2063
{
@@ -1864,7 +2066,8 @@ function createMeshCore(agent) {
2066
//
2067
2068
// Check user access rights for desktop
1867
- if ((((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0)) || ((this.httprequest.rights != 0xFFFFFFFF) && ((this.httprequest.rights & MESHRIGHT_NODESKTOP) != 0))) {
2069
+ if ((((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0)) || ((this.httprequest.rights != 0xFFFFFFFF) && ((this.httprequest.rights & MESHRIGHT_NODESKTOP) != 0)))
2070
+ {
2071
// Disengage this tunnel, user does not have the rights to do this!!
2072
this.httprequest.protocol = 999999;
2073
this.httprequest.s.end();
@@ -1890,7 +2093,8 @@ function createMeshCore(agent) {
2093
2094
// Send a metadata update to all desktop sessions
2095
var users = {};
1893
- if (this.httprequest.desktop.kvm.tunnels != null) {
2096
+ if (this.httprequest.desktop.kvm.tunnels != null)
2097
+ {
2098
for (var i in this.httprequest.desktop.kvm.tunnels) { try { var userid = this.httprequest.desktop.kvm.tunnels[i].httprequest.userid; if (users[userid] == null) { users[userid] = 1; } else { users[userid]++; } } catch (e) { } }
2099
for (var i in this.httprequest.desktop.kvm.tunnels) { try { this.httprequest.desktop.kvm.tunnels[i].write(JSON.stringify({ ctrlChannel: '102938', type: 'metadata', users: users })); } catch (e) { } }
2100
tunnelUserCount.desktop = users;
@@ -1898,7 +2102,8 @@ function createMeshCore(agent) {
2102
broadcastSessionsToRegisteredApps();
2103
}
2104
1901
- this.end = function () {
2105
+ this.end = function ()
2106
+ {
2107
--this.desktop.kvm.connectionCount;
2108
2109
// Remove ourself from the list of remote desktop session
@@ -1907,7 +2112,8 @@ function createMeshCore(agent) {
2112
2113
// Send a metadata update to all desktop sessions
2114
var users = {};
1910
- if (this.httprequest.desktop.kvm.tunnels != null) {
2115
+ if (this.httprequest.desktop.kvm.tunnels != null)
2116
+ {
2117
for (var i in this.httprequest.desktop.kvm.tunnels) { try { var userid = this.httprequest.desktop.kvm.tunnels[i].httprequest.userid; if (users[userid] == null) { users[userid] = 1; } else { users[userid]++; } } catch (e) { } }
2118
for (var i in this.httprequest.desktop.kvm.tunnels) { try { this.httprequest.desktop.kvm.tunnels[i].write(JSON.stringify({ ctrlChannel: '102938', type: 'metadata', users: users })); } catch (e) { } }
2119
tunnelUserCount.desktop = users;
@@ -1921,7 +2127,7 @@ function createMeshCore(agent) {
2127
this.unpipe(this.httprequest.desktop.kvm);
2128
this.httprequest.desktop.kvm.unpipe(this);
2129
}
1924
- catch(e) { }
2130
+ catch (e) { }
2131
2132
// Unpipe the WebRTC channel if needed (This will also be done when the WebRTC channel ends).
2133
if (this.rtcchannel)
@@ -1931,34 +2137,41 @@ function createMeshCore(agent) {
2137
this.rtcchannel.unpipe(this.httprequest.desktop.kvm);
2138
this.httprequest.desktop.kvm.unpipe(this.rtcchannel);
2139
}
1934
- catch(e) { }
2140
+ catch (e) { }
2141
}
2142
2143
// Place wallpaper back if needed
2144
// TODO
2145
1940
- if (this.desktop.kvm.connectionCount == 0) {
2146
+ if (this.desktop.kvm.connectionCount == 0)
2147
+ {
2148
// Display a toast message. This may not be supported on all platforms.
2149
// try { require('toaster').Toast('MeshCentral', 'Remote Desktop Control Ended.'); } catch (e) { }
2150
2151
this.httprequest.desktop.kvm.end();
1945
- if (this.httprequest.desktop.kvm.connectionBar) {
2152
+ if (this.httprequest.desktop.kvm.connectionBar)
2153
+ {
2154
this.httprequest.desktop.kvm.connectionBar.removeAllListeners('close');
2155
this.httprequest.desktop.kvm.connectionBar.close();
2156
this.httprequest.desktop.kvm.connectionBar = null;
2157
}
1950
- } else {
1951
- for (var i in this.httprequest.desktop.kvm.users) {
1952
- if ((this.httprequest.desktop.kvm.users[i] == this.httprequest.username) && this.httprequest.desktop.kvm.connectionBar) {
2158
+ } else
2159
+ {
2160
+ for (var i in this.httprequest.desktop.kvm.users)
2161
+ {
2162
+ if ((this.httprequest.desktop.kvm.users[i] == this.httprequest.username) && this.httprequest.desktop.kvm.connectionBar)
2163
+ {
2164
for (var j in this.httprequest.desktop.kvm.rusers) { if (this.httprequest.desktop.kvm.rusers[j] == this.httprequest.realname) { this.httprequest.desktop.kvm.rusers.splice(j, 1); break; } }
2165
this.httprequest.desktop.kvm.users.splice(i, 1);
2166
this.httprequest.desktop.kvm.connectionBar.removeAllListeners('close');
2167
this.httprequest.desktop.kvm.connectionBar.close();
2168
this.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.httprequest.privacybartext.replace('{0}', this.httprequest.desktop.kvm.users.join(', ')).replace('{1}', this.httprequest.desktop.kvm.rusers.join(', ')), require('MeshAgent')._tsid);
2169
this.httprequest.desktop.kvm.connectionBar.httprequest = this.httprequest;
1959
- this.httprequest.desktop.kvm.connectionBar.on('close', function () {
2170
+ this.httprequest.desktop.kvm.connectionBar.on('close', function ()
2171
+ {
2172
MeshServerLogEx(29, null, "Remote Desktop Connection forcefully closed by local user (" + this.httprequest.remoteaddr + ")", this.httprequest);
1961
- for (var i in this.httprequest.desktop.kvm._pipedStreams) {
2173
+ for (var i in this.httprequest.desktop.kvm._pipedStreams)
2174
+ {
2175
this.httprequest.desktop.kvm._pipedStreams[i].end();
2176
}
2177
this.httprequest.desktop.kvm.end();
@@ -1968,22 +2181,26 @@ function createMeshCore(agent) {
2181
}
2182
}
2183
};
1971
- if (this.httprequest.desktop.kvm.hasOwnProperty('connectionCount')) {
2184
+ if (this.httprequest.desktop.kvm.hasOwnProperty('connectionCount'))
2185
+ {
2186
this.httprequest.desktop.kvm.connectionCount++;
2187
this.httprequest.desktop.kvm.rusers.push(this.httprequest.realname);
2188
this.httprequest.desktop.kvm.users.push(this.httprequest.username);
2189
this.httprequest.desktop.kvm.rusers.sort();
2190
this.httprequest.desktop.kvm.users.sort();
1977
- } else {
2191
+ } else
2192
+ {
2193
this.httprequest.desktop.kvm.connectionCount = 1;
2194
this.httprequest.desktop.kvm.rusers = [this.httprequest.realname];
2195
this.httprequest.desktop.kvm.users = [this.httprequest.username];
2196
}
2197
1983
- if ((this.httprequest.rights == 0xFFFFFFFF) || (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) != 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0))) {
2198
+ if ((this.httprequest.rights == 0xFFFFFFFF) || (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) != 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0)))
2199
+ {
2200
// If we have remote control rights, pipe the KVM input
2201
this.pipe(this.httprequest.desktop.kvm, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text. Pipe the Browser --> KVM input.
1986
- } else {
2202
+ } else
2203
+ {
2204
// We need to only pipe non-mouse & non-keyboard inputs.
2205
//sendConsoleText('Warning: No Remote Desktop Input Rights.');
2206
// TODO!!!
@@ -1996,7 +2213,8 @@ function createMeshCore(agent) {
2213
// Send a console message back using the console channel, "\n" is supported.
2214
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 }));
2215
var consentMessage = this.httprequest.realname + " requesting remote desktop access. Grant access?", consentTitle = 'MeshCentral';
1999
- if (this.httprequest.soptions != null) {
2216
+ if (this.httprequest.soptions != null)
2217
+ {
2218
if (this.httprequest.soptions.consentTitle != null) { consentTitle = this.httprequest.soptions.consentTitle; }
2219
if (this.httprequest.soptions.consentMsgDesktop != null) { consentMessage = this.httprequest.soptions.consentMsgDesktop.replace('{0}', this.httprequest.realname).replace('{1}', this.httprequest.username); }
2220
}
@@ -2004,7 +2222,7 @@ function createMeshCore(agent) {
2222
pr.ws = this;
2223
this.pause();
2224
this._consentpromise = pr;
2007
- this.prependOnceListener('end', function () { if (this._consentpromise && this._consentpromise.close) { this._consentpromise.close(); }});
2225
+ this.prependOnceListener('end', function () { if (this._consentpromise && this._consentpromise.close) { this._consentpromise.close(); } });
2226
pr.then(
2227
function ()
2228
{
@@ -2012,35 +2230,45 @@ function createMeshCore(agent) {
2230
this.ws._consentpromise = null;
2231
MeshServerLogEx(30, null, "Starting remote desktop after local user accepted (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
2232
this.ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: null, msgid: 0 }));
2015
- if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 1)) {
2233
+ if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 1))
2234
+ {
2235
// User Notifications is required
2236
var notifyMessage = this.ws.httprequest.realname + " started a remote desktop session.", notifyTitle = "MeshCentral";
2018
- if (this.ws.httprequest.soptions != null) {
2237
+ if (this.ws.httprequest.soptions != null)
2238
+ {
2239
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
2240
if (this.ws.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgDesktop.replace('{0}', this.ws.httprequest.realname).replace('{1}', this.ws.httprequest.username); }
2241
}
2242
try { require('toaster').Toast(notifyTitle, notifyMessage, tsid); } catch (e) { }
2243
}
2024
- if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 0x40)) {
2244
+ if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 0x40))
2245
+ {
2246
// Connection Bar is required
2026
- if (this.ws.httprequest.desktop.kvm.connectionBar) {
2247
+ if (this.ws.httprequest.desktop.kvm.connectionBar)
2248
+ {
2249
this.ws.httprequest.desktop.kvm.connectionBar.removeAllListeners('close');
2250
this.ws.httprequest.desktop.kvm.connectionBar.close();
2251
}
2030
- try {
2252
+ try
2253
+ {
2254
this.ws.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.ws.httprequest.privacybartext.replace('{0}', this.ws.httprequest.desktop.kvm.users.join(', ')).replace('{1}', this.ws.httprequest.desktop.kvm.rusers.join(', ')), require('MeshAgent')._tsid);
2255
MeshServerLogEx(31, null, "Remote Desktop Connection Bar Activated/Updated (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
2256
}
2034
- catch (e) {
2035
- if (process.platform != 'darwin') {
2257
+ catch (e)
2258
+ {
2259
+ if (process.platform != 'darwin')
2260
+ {
2261
MeshServerLogEx(32, null, "Remote Desktop Connection Bar Failed or Not Supported (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
2262
}
2263
}
2039
- if (this.ws.httprequest.desktop.kvm.connectionBar) {
2264
+ if (this.ws.httprequest.desktop.kvm.connectionBar)
2265
+ {
2266
this.ws.httprequest.desktop.kvm.connectionBar.httprequest = this.ws.httprequest;
2041
- this.ws.httprequest.desktop.kvm.connectionBar.on('close', function () {
2267
+ this.ws.httprequest.desktop.kvm.connectionBar.on('close', function ()
2268
+ {
2269
MeshServerLogEx(33, null, "Remote Desktop Connection forcefully closed by local user (" + this.httprequest.remoteaddr + ")", this.httprequest);
2043
- for (var i in this.httprequest.desktop.kvm._pipedStreams) {
2270
+ for (var i in this.httprequest.desktop.kvm._pipedStreams)
2271
+ {
2272
this.httprequest.desktop.kvm._pipedStreams[i].end();
2273
}
2274
this.httprequest.desktop.kvm.end();
@@ -2057,38 +2285,49 @@ function createMeshCore(agent) {
2285
MeshServerLogEx(34, null, "Failed to start remote desktop after local user rejected (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
2286
this.ws.end(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString(), msgid: 2 }));
2287
});
2060
- } else {
2288
+ } else
2289
+ {
2290
// User Consent Prompt is not required
2062
- if (this.httprequest.consent && (this.httprequest.consent & 1)) {
2291
+ if (this.httprequest.consent && (this.httprequest.consent & 1))
2292
+ {
2293
// User Notifications is required
2294
MeshServerLogEx(35, null, "Started remote desktop with toast notification (" + this.httprequest.remoteaddr + ")", this.httprequest);
2295
var notifyMessage = this.httprequest.realname + " started a remote desktop session.", notifyTitle = "MeshCentral";
2066
- if (this.httprequest.soptions != null) {
2296
+ if (this.httprequest.soptions != null)
2297
+ {
2298
if (this.httprequest.soptions.notifyTitle != null) { notifyTitle = this.httprequest.soptions.notifyTitle; }
2299
if (this.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = this.httprequest.soptions.notifyMsgDesktop.replace('{0}', this.httprequest.realname).replace('{1}', this.httprequest.username); }
2300
}
2301
try { require('toaster').Toast(notifyTitle, notifyMessage, tsid); } catch (e) { }
2071
- } else {
2302
+ } else
2303
+ {
2304
MeshServerLogEx(36, null, "Started remote desktop without notification (" + this.httprequest.remoteaddr + ")", this.httprequest);
2305
}
2074
- if (this.httprequest.consent && (this.httprequest.consent & 0x40)) {
2306
+ if (this.httprequest.consent && (this.httprequest.consent & 0x40))
2307
+ {
2308
// Connection Bar is required
2076
- if (this.httprequest.desktop.kvm.connectionBar) {
2309
+ if (this.httprequest.desktop.kvm.connectionBar)
2310
+ {
2311
this.httprequest.desktop.kvm.connectionBar.removeAllListeners('close');
2312
this.httprequest.desktop.kvm.connectionBar.close();
2313
}
2080
- try {
2314
+ try
2315
+ {
2316
this.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.httprequest.privacybartext.replace('{0}', this.httprequest.desktop.kvm.rusers.join(', ')).replace('{1}', this.httprequest.desktop.kvm.users.join(', ')), require('MeshAgent')._tsid);
2317
MeshServerLogEx(37, null, "Remote Desktop Connection Bar Activated/Updated (" + this.httprequest.remoteaddr + ")", this.httprequest);
2318
}
2084
- catch (e) {
2319
+ catch (e)
2320
+ {
2321
MeshServerLogEx(38, null, "Remote Desktop Connection Bar Failed or not Supported (" + this.httprequest.remoteaddr + ")", this.httprequest);
2322
}
2087
- if (this.httprequest.desktop.kvm.connectionBar) {
2323
+ if (this.httprequest.desktop.kvm.connectionBar)
2324
+ {
2325
this.httprequest.desktop.kvm.connectionBar.httprequest = this.httprequest;
2089
- this.httprequest.desktop.kvm.connectionBar.on('close', function () {
2326
+ this.httprequest.desktop.kvm.connectionBar.on('close', function ()
2327
+ {
2328
MeshServerLogEx(39, null, "Remote Desktop Connection forcefully closed by local user (" + this.httprequest.remoteaddr + ")", this.httprequest);
2091
- for (var i in this.httprequest.desktop.kvm._pipedStreams) {
2329
+ for (var i in this.httprequest.desktop.kvm._pipedStreams)
2330
+ {
2331
this.httprequest.desktop.kvm._pipedStreams[i].end();
2332
}
2333
this.httprequest.desktop.kvm.end();
@@ -2102,13 +2341,15 @@ function createMeshCore(agent) {
2341
this.on('data', onTunnelControlData);
2342
//this.write('MeshCore KVM Hello!1');
2343
2105
- } else if (this.httprequest.protocol == 5) {
2344
+ } else if (this.httprequest.protocol == 5)
2345
+ {
2346
//
2347
// Remote Files
2348
//
2349
2350
// Check user access rights for files
2111
- if (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) || ((this.httprequest.rights != 0xFFFFFFFF) && ((this.httprequest.rights & MESHRIGHT_NOFILES) != 0))) {
2351
+ if (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) || ((this.httprequest.rights != 0xFFFFFFFF) && ((this.httprequest.rights & MESHRIGHT_NOFILES) != 0)))
2352
+ {
2353
// Disengage this tunnel, user does not have the rights to do this!!
2354
this.httprequest.protocol = 999999;
2355
this.httprequest.s.end();
@@ -2119,15 +2360,18 @@ function createMeshCore(agent) {
2360
this.descriptorMetadata = "Remote Files";
2361
2362
// Add the files session to the count to update the server
2122
- if (this.httprequest.userid != null) {
2363
+ if (this.httprequest.userid != null)
2364
+ {
2365
if (tunnelUserCount.files[this.httprequest.userid] == null) { tunnelUserCount.files[this.httprequest.userid] = 1; } else { tunnelUserCount.files[this.httprequest.userid]++; }
2366
try { mesh.SendCommand({ action: 'sessions', type: 'files', value: tunnelUserCount.files }); } catch (e) { }
2367
broadcastSessionsToRegisteredApps();
2368
}
2369
2128
- this.end = function () {
2370
+ this.end = function ()
2371
+ {
2372
// Remove the files session from the count to update the server
2130
- if (this.httprequest.userid != null) {
2373
+ if (this.httprequest.userid != null)
2374
+ {
2375
if (tunnelUserCount.files[this.httprequest.userid] != null) { tunnelUserCount.files[this.httprequest.userid]--; if (tunnelUserCount.files[this.httprequest.userid] <= 0) { delete tunnelUserCount.files[this.httprequest.userid]; } }
2376
try { mesh.SendCommand({ action: 'sessions', type: 'files', value: tunnelUserCount.files }); } catch (e) { }
2377
broadcastSessionsToRegisteredApps();
@@ -2135,12 +2379,14 @@ function createMeshCore(agent) {
2379
};
2380
2381
// Perform notification if needed. Toast messages may not be supported on all platforms.
2138
- if (this.httprequest.consent && (this.httprequest.consent & 32)) {
2382
+ if (this.httprequest.consent && (this.httprequest.consent & 32))
2383
+ {
2384
// User Consent Prompt is required
2385
// Send a console message back using the console channel, "\n" is supported.
2386
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 }));
2387
var consentMessage = this.httprequest.realname + " requesting remote file Access. Grant access?", consentTitle = 'MeshCentral';
2143
- if (this.httprequest.soptions != null) {
2388
+ if (this.httprequest.soptions != null)
2389
+ {
2390
if (this.httprequest.soptions.consentTitle != null) { consentTitle = this.httprequest.soptions.consentTitle; }
2391
if (this.httprequest.soptions.consentMsgFiles != null) { consentMessage = this.httprequest.soptions.consentMsgFiles.replace('{0}', this.httprequest.realname).replace('{1}', this.httprequest.username); }
2392
}
@@ -2156,10 +2402,12 @@ function createMeshCore(agent) {
2402
this.ws._consentpromise = null;
2403
MeshServerLogEx(40, null, "Starting remote files after local user accepted (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
2404
this.ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: null }));
2159
- if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 4)) {
2405
+ if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 4))
2406
+ {
2407
// User Notifications is required
2408
var notifyMessage = this.ws.httprequest.realname + " started a remote file session.", notifyTitle = "MeshCentral";
2162
- if (this.ws.httprequest.soptions != null) {
2409
+ if (this.ws.httprequest.soptions != null)
2410
+ {
2411
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
2412
if (this.ws.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgFiles.replace('{0}', this.ws.httprequest.realname).replace('{1}', this.ws.httprequest.username); }
2413
}
@@ -2174,18 +2422,22 @@ function createMeshCore(agent) {
2422
MeshServerLogEx(41, null, "Failed to start remote files after local user rejected (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
2423
this.ws.end(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString(), msgid: 2 }));
2424
});
2177
- } else {
2425
+ } else
2426
+ {
2427
// User Consent Prompt is not required
2179
- if (this.httprequest.consent && (this.httprequest.consent & 4)) {
2428
+ if (this.httprequest.consent && (this.httprequest.consent & 4))
2429
+ {
2430
// User Notifications is required
2431
MeshServerLogEx(42, null, "Started remote files with toast notification (" + this.httprequest.remoteaddr + ")", this.httprequest);
2432
var notifyMessage = this.httprequest.realname + " started a remote file session.", notifyTitle = "MeshCentral";
2183
- if (this.httprequest.soptions != null) {
2433
+ if (this.httprequest.soptions != null)
2434
+ {
2435
if (this.httprequest.soptions.notifyTitle != null) { notifyTitle = this.httprequest.soptions.notifyTitle; }
2436
if (this.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = this.httprequest.soptions.notifyMsgFiles.replace('{0}', this.httprequest.realname).replace('{1}', this.httprequest.username); }
2437
}
2438
try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (e) { }
2188
- } else {
2439
+ } else
2440
+ {
2441
MeshServerLogEx(43, null, "Started remote files without notification (" + this.httprequest.remoteaddr + ")", this.httprequest);
2442
}
2443
this.resume();
@@ -2194,18 +2446,23 @@ function createMeshCore(agent) {
2446
// Setup files
2447
// NOP
2448
}
2197
- } else if (this.httprequest.protocol == 1) {
2449
+ } else if (this.httprequest.protocol == 1)
2450
+ {
2451
// Send data into terminal stdin
2452
//this.write(data); // Echo back the keys (Does not seem to be a good idea)
2200
- } else if (this.httprequest.protocol == 2) {
2453
+ } else if (this.httprequest.protocol == 2)
2454
+ {
2455
// Send data into remote desktop
2202
- if (this.httprequest.desktop.state == 0) {
2456
+ if (this.httprequest.desktop.state == 0)
2457
+ {
2458
this.write(Buffer.from(String.fromCharCode(0x11, 0xFE, 0x00, 0x00, 0x4D, 0x45, 0x53, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02)));
2459
this.httprequest.desktop.state = 1;
2205
- } else {
2460
+ } else
2461
+ {
2462
this.httprequest.desktop.write(data);
2463
}
2208
- } else if (this.httprequest.protocol == 5) {
2464
+ } else if (this.httprequest.protocol == 5)
2465
+ {
2466
// Process files commands
2467
var cmd = null;
2468
try { cmd = JSON.parse(data); } catch (e) { };
@@ -2216,7 +2473,8 @@ function createMeshCore(agent) {
2473
2474
if ((cmd.path != null) && (process.platform != 'win32') && (cmd.path[0] != '/')) { cmd.path = '/' + cmd.path; } // Add '/' to paths on non-windows
2475
//console.log(objToString(cmd, 0, ' '));
2219
- switch (cmd.action) {
2476
+ switch (cmd.action)
2477
+ {
2478
case 'ls': {
2479
/*
2480
// Close the watcher if required
@@ -2253,15 +2511,20 @@ function createMeshCore(agent) {
2511
}
2512
case 'rm': {
2513
// Delete, possibly recursive delete
2256
- for (var i in cmd.delfiles) {
2514
+ for (var i in cmd.delfiles)
2515
+ {
2516
var p = obj.path.join(cmd.path, cmd.delfiles[i]), delcount = 0;
2517
try { delcount = deleteFolderRecursive(p, cmd.rec); } catch (e) { }
2259
- if ((delcount == 1) && !cmd.rec) {
2518
+ if ((delcount == 1) && !cmd.rec)
2519
+ {
2520
MeshServerLogEx(45, [p], "Delete: \"" + p + "\"", this.httprequest);
2261
- } else {
2262
- if (cmd.rec) {
2521
+ } else
2522
+ {
2523
+ if (cmd.rec)
2524
+ {
2525
MeshServerLogEx(46, [p, delcount], "Delete recursive: \"" + p + "\", " + delcount + " element(s) removed", this.httprequest);
2264
- } else {
2526
+ } else
2527
+ {
2528
MeshServerLogEx(47, [p, delcount], "Delete: \"" + p + "\", " + delcount + " element(s) removed", this.httprequest);
2529
}
2530
}
@@ -2271,9 +2534,11 @@ function createMeshCore(agent) {
2534
case 'markcoredump': {
2535
// If we are asking for the coredump file, set the right path.
2536
var coreDumpPath = null;
2274
- if (process.platform == 'win32') {
2537
+ if (process.platform == 'win32')
2538
+ {
2539
if (fs.existsSync(process.coreDumpLocation)) { coreDumpPath = process.coreDumpLocation; }
2276
- } else {
2540
+ } else
2541
+ {
2542
if ((process.cwd() != '//') && fs.existsSync(process.cwd() + 'core')) { coreDumpPath = process.cwd() + 'core'; }
2543
}
2544
if (coreDumpPath != null) { db.Put('CoreDumpTime', require('fs').statSync(coreDumpPath).mtime); }
@@ -2305,24 +2570,30 @@ function createMeshCore(agent) {
2570
case 'download': {
2571
// Download a file
2572
var sendNextBlock = 0;
2308
- if (cmd.sub == 'start') { // Setup the download
2309
- if ((cmd.path == null) && (cmd.ask == 'coredump')) { // If we are asking for the coredump file, set the right path.
2310
- if (process.platform == 'win32') {
2573
+ if (cmd.sub == 'start')
2574
+ { // Setup the download
2575
+ if ((cmd.path == null) && (cmd.ask == 'coredump'))
2576
+ { // If we are asking for the coredump file, set the right path.
2577
+ if (process.platform == 'win32')
2578
+ {
2579
if (fs.existsSync(process.coreDumpLocation)) { cmd.path = process.coreDumpLocation; }
2312
- } else {
2580
+ } else
2581
+ {
2582
if ((process.cwd() != '//') && fs.existsSync(process.cwd() + 'core')) { cmd.path = process.cwd() + 'core'; }
2583
}
2584
}
2316
- MeshServerLogEx((cmd.ask == 'coredump')?104:49, [cmd.path], 'Download: \"' + cmd.path + '\"', this.httprequest);
2585
+ MeshServerLogEx((cmd.ask == 'coredump') ? 104 : 49, [cmd.path], 'Download: \"' + cmd.path + '\"', this.httprequest);
2586
if ((cmd.path == null) || (this.filedownload != null)) { this.write({ action: 'download', sub: 'cancel', id: this.filedownload.id }); delete this.filedownload; }
2587
this.filedownload = { id: cmd.id, path: cmd.path, ptr: 0 }
2588
try { this.filedownload.f = fs.openSync(this.filedownload.path, 'rbN'); } catch (e) { this.write({ action: 'download', sub: 'cancel', id: this.filedownload.id }); delete this.filedownload; }
2589
if (this.filedownload) { this.write({ action: 'download', sub: 'start', id: cmd.id }); }
2321
- } else if ((this.filedownload != null) && (cmd.id == this.filedownload.id)) { // Download commands
2590
+ } else if ((this.filedownload != null) && (cmd.id == this.filedownload.id))
2591
+ { // Download commands
2592
if (cmd.sub == 'startack') { sendNextBlock = ((typeof cmd.ack == 'number') ? cmd.ack : 8); } else if (cmd.sub == 'stop') { delete this.filedownload; } else if (cmd.sub == 'ack') { sendNextBlock = 1; }
2593
}
2594
// Send the next download block(s)
2325
- while (sendNextBlock > 0) {
2595
+ while (sendNextBlock > 0)
2596
+ {
2597
sendNextBlock--;
2598
var buf = Buffer.alloc(16384);
2599
var len = fs.readSync(this.filedownload.f, buf, 4, 16380, null);
@@ -2332,28 +2603,28 @@ function createMeshCore(agent) {
2603
}
2604
break;
2605
}
2335
- /*
2336
- case 'download': {
2337
- // Packet download of a file, agent to browser
2338
- if (cmd.path == undefined) break;
2339
- var filepath = cmd.name ? obj.path.join(cmd.path, cmd.name) : cmd.path;
2340
- //console.log('Download: ' + filepath);
2341
- try { this.httprequest.downloadFile = fs.openSync(filepath, 'rbN'); } catch (e) { this.write(Buffer.from(JSON.stringify({ action: 'downloaderror', reqid: cmd.reqid }))); break; }
2342
- this.httprequest.downloadFileId = cmd.reqid;
2343
- this.httprequest.downloadFilePtr = 0;
2344
- if (this.httprequest.downloadFile) { this.write(Buffer.from(JSON.stringify({ action: 'downloadstart', reqid: this.httprequest.downloadFileId }))); }
2345
- break;
2346
- }
2347
- case 'download2': {
2348
- // Stream download of a file, agent to browser
2349
- if (cmd.path == undefined) break;
2350
- var filepath = cmd.name ? obj.path.join(cmd.path, cmd.name) : cmd.path;
2351
- try { this.httprequest.downloadFile = fs.createReadStream(filepath, { flags: 'rbN' }); } catch (e) { console.log(e); }
2352
- this.httprequest.downloadFile.pipe(this);
2353
- this.httprequest.downloadFile.end = function () { }
2354
- break;
2355
- }
2356
- */
2606
+ /*
2607
+ case 'download': {
2608
+ // Packet download of a file, agent to browser
2609
+ if (cmd.path == undefined) break;
2610
+ var filepath = cmd.name ? obj.path.join(cmd.path, cmd.name) : cmd.path;
2611
+ //console.log('Download: ' + filepath);
2612
+ try { this.httprequest.downloadFile = fs.openSync(filepath, 'rbN'); } catch (e) { this.write(Buffer.from(JSON.stringify({ action: 'downloaderror', reqid: cmd.reqid }))); break; }
2613
+ this.httprequest.downloadFileId = cmd.reqid;
2614
+ this.httprequest.downloadFilePtr = 0;
2615
+ if (this.httprequest.downloadFile) { this.write(Buffer.from(JSON.stringify({ action: 'downloadstart', reqid: this.httprequest.downloadFileId }))); }
2616
+ break;
2617
+ }
2618
+ case 'download2': {
2619
+ // Stream download of a file, agent to browser
2620
+ if (cmd.path == undefined) break;
2621
+ var filepath = cmd.name ? obj.path.join(cmd.path, cmd.name) : cmd.path;
2622
+ try { this.httprequest.downloadFile = fs.createReadStream(filepath, { flags: 'rbN' }); } catch (e) { console.log(e); }
2623
+ this.httprequest.downloadFile.pipe(this);
2624
+ this.httprequest.downloadFile.end = function () { }
2625
+ break;
2626
+ }
2627
+ */
2628
case 'upload': {
2629
// Upload a file, browser to agent
2630
if (this.httprequest.uploadFile != null) { fs.closeSync(this.httprequest.uploadFile); delete this.httprequest.uploadFile; }
@@ -2368,7 +2639,8 @@ function createMeshCore(agent) {
2639
}
2640
case 'uploaddone': {
2641
// Indicates that an upload is done
2371
- if (this.httprequest.uploadFile) {
2642
+ if (this.httprequest.uploadFile)
2643
+ {
2644
fs.closeSync(this.httprequest.uploadFile);
2645
this.write(Buffer.from(JSON.stringify({ action: 'uploaddone', reqid: this.httprequest.uploadFileid }))); // Indicate that we closed the file.
2646
delete this.httprequest.uploadFile;
@@ -2379,7 +2651,8 @@ function createMeshCore(agent) {
2651
}
2652
case 'uploadcancel': {
2653
// Indicates that an upload is canceled
2382
- if (this.httprequest.uploadFile) {
2654
+ if (this.httprequest.uploadFile)
2655
+ {
2656
fs.closeSync(this.httprequest.uploadFile);
2657
fs.unlinkSync(this.httprequest.uploadFilePath);
2658
this.write(Buffer.from(JSON.stringify({ action: 'uploadcancel', reqid: this.httprequest.uploadFileid }))); // Indicate that we closed the file.
@@ -2391,7 +2664,8 @@ function createMeshCore(agent) {
2664
}
2665
case 'copy': {
2666
// Copy a bunch of files from scpath to dspath
2394
- for (var i in cmd.names) {
2667
+ for (var i in cmd.names)
2668
+ {
2669
var sc = obj.path.join(cmd.scpath, cmd.names[i]), ds = obj.path.join(cmd.dspath, cmd.names[i]);
2670
MeshServerLogEx(51, [sc, ds], 'Copy: \"' + sc + '\" to \"' + ds + '\"', this.httprequest);
2671
if (sc != ds) { try { fs.copyFileSync(sc, ds); } catch (e) { } }
@@ -2400,7 +2674,8 @@ function createMeshCore(agent) {
2674
}
2675
case 'move': {
2676
// Move a bunch of files from scpath to dspath
2403
- for (var i in cmd.names) {
2677
+ for (var i in cmd.names)
2678
+ {
2679
var sc = obj.path.join(cmd.scpath, cmd.names[i]), ds = obj.path.join(cmd.dspath, cmd.names[i]);
2680
MeshServerLogEx(52, [sc, ds], 'Move: \"' + sc + '\" to \"' + ds + '\"', this.httprequest);
2681
if (sc != ds) { try { fs.copyFileSync(sc, ds); fs.unlinkSync(sc); } catch (e) { } }
@@ -2423,7 +2698,8 @@ function createMeshCore(agent) {
2698
delete this.zipcancel;
2699
var out = require('fs').createWriteStream(ofile, { flags: 'wb' });
2700
out.xws = this;
2426
- out.on('close', function () {
2701
+ out.on('close', function ()
2702
+ {
2703
this.xws.write(Buffer.from(JSON.stringify({ action: 'dialogmessage', msg: null })));
2704
this.xws.write(Buffer.from(JSON.stringify({ action: 'refresh' })));
2705
if (this.xws.zipcancel === true) { fs.unlinkSync(this.xws.zipfile); } // Delete the complete file.
@@ -2445,14 +2721,16 @@ function createMeshCore(agent) {
2721
// Unknown action, ignore it.
2722
break;
2723
}
2448
- } else if (this.httprequest.protocol == 7) { // Plugin data exchange
2724
+ } else if (this.httprequest.protocol == 7)
2725
+ { // Plugin data exchange
2726
var cmd = null;
2727
try { cmd = JSON.parse(data); } catch (e) { };
2728
if (cmd == null) { return; }
2729
if ((cmd.ctrlChannel == '102938') || ((cmd.type == 'offer') && (cmd.sdp != null))) { onTunnelControlData(cmd, this); return; } // If this is control data, handle it now.
2730
if (cmd.action == undefined) return;
2731
2455
- switch (cmd.action) {
2732
+ switch (cmd.action)
2733
+ {
2734
case 'plugin': {
2735
try { require(cmd.plugin).consoleaction(cmd, null, null, this); } catch (e) { throw e; }
2736
break;
@@ -2468,15 +2746,21 @@ function createMeshCore(agent) {
2746
}
2747
2748
// Delete a directory with a files and directories within it
2471
- function deleteFolderRecursive(path, rec) {
2749
+ function deleteFolderRecursive(path, rec)
2750
+ {
2751
var count = 0;
2473
- if (fs.existsSync(path)) {
2474
- if (rec == true) {
2475
- fs.readdirSync(obj.path.join(path, '*')).forEach(function (file, index) {
2752
+ if (fs.existsSync(path))
2753
+ {
2754
+ if (rec == true)
2755
+ {
2756
+ fs.readdirSync(obj.path.join(path, '*')).forEach(function (file, index)
2757
+ {
2758
var curPath = obj.path.join(path, file);
2477
- if (fs.statSync(curPath).isDirectory()) { // recurse
2759
+ if (fs.statSync(curPath).isDirectory())
2760
+ { // recurse
2761
count += deleteFolderRecursive(curPath, true);
2479
- } else { // delete file
2762
+ } else
2763
+ { // delete file
2764
fs.unlinkSync(curPath);
2765
count++;
2766
}
@@ -2489,11 +2773,13 @@ function createMeshCore(agent) {
2773
};
2774
2775
// Called when receiving control data on WebRTC
2492
- function onTunnelWebRTCControlData(data) {
2776
+ function onTunnelWebRTCControlData(data)
2777
+ {
2778
if (typeof data != 'string') return;
2779
var obj;
2780
try { obj = JSON.parse(data); } catch (e) { sendConsoleText('Invalid control JSON on WebRTC: ' + data); return; }
2496
- if (obj.type == 'close') {
2781
+ if (obj.type == 'close')
2782
+ {
2783
//sendConsoleText('Tunnel #' + this.xrtc.websocket.tunnel.index + ' WebRTC control close');
2784
try { this.close(); } catch (e) { }
2785
try { this.xrtc.close(); } catch (e) { }
@@ -2501,7 +2787,8 @@ function createMeshCore(agent) {
2787
}
2788
2789
// Called when receiving control data on websocket
2504
- function onTunnelControlData(data, ws) {
2790
+ function onTunnelControlData(data, ws)
2791
+ {
2792
var obj;
2793
if (ws == null) { ws = this; }
2794
if (typeof data == 'string') { try { obj = JSON.parse(data); } catch (e) { sendConsoleText('Invalid control JSON: ' + data); return; } }
@@ -2509,12 +2796,16 @@ function createMeshCore(agent) {
2796
//sendConsoleText('onTunnelControlData(' + ws.httprequest.protocol + '): ' + JSON.stringify(data));
2797
//console.log('onTunnelControlData: ' + JSON.stringify(data));
2798
2512
- if (obj.action) {
2513
- switch (obj.action) {
2799
+ if (obj.action)
2800
+ {
2801
+ switch (obj.action)
2802
+ {
2803
case 'lock': {
2804
// Lock the current user out of the desktop
2516
- try {
2517
- if (process.platform == 'win32') {
2805
+ try
2806
+ {
2807
+ if (process.platform == 'win32')
2808
+ {
2809
MeshServerLogEx(53, null, "Locking remote user out of desktop", ws.httprequest);
2810
var child = require('child_process');
2811
child.execFile(process.env['windir'] + '\\system32\\cmd.exe', ['/c', 'RunDll32.exe user32.dll,LockWorkStation'], { type: 1 });
@@ -2529,7 +2820,8 @@ function createMeshCore(agent) {
2820
return;
2821
}
2822
2532
- switch (obj.type) {
2823
+ switch (obj.type)
2824
+ {
2825
case 'options': {
2826
// These are additional connection options passed in the control channel.
2827
//sendConsoleText('options: ' + JSON.stringify(obj));
@@ -2564,18 +2856,23 @@ function createMeshCore(agent) {
2856
break;
2857
}
2858
case 'webrtc0': { // Browser indicates we can start WebRTC switch-over.
2567
- if (ws.httprequest.protocol == 1) { // Terminal
2859
+ if (ws.httprequest.protocol == 1)
2860
+ { // Terminal
2861
// This is a terminal data stream, unpipe the terminal now and indicate to the other side that terminal data will no longer be received over WebSocket
2569
- if (process.platform == 'win32') {
2862
+ if (process.platform == 'win32')
2863
+ {
2864
ws.httprequest._term.unpipe(ws);
2571
- } else {
2865
+ } else
2866
+ {
2867
ws.httprequest.process.stdout.unpipe(ws);
2868
ws.httprequest.process.stderr.unpipe(ws);
2869
}
2575
- } else if (ws.httprequest.protocol == 2) { // Desktop
2870
+ } else if (ws.httprequest.protocol == 2)
2871
+ { // Desktop
2872
// This is a KVM data stream, unpipe the KVM now and indicate to the other side that KVM data will no longer be received over WebSocket
2873
ws.httprequest.desktop.kvm.unpipe(ws);
2578
- } else {
2874
+ } else
2875
+ {
2876
// Switch things around so all WebRTC data goes to onTunnelData().
2877
ws.rtcchannel.httprequest = ws.httprequest;
2878
ws.rtcchannel.removeAllListeners('data');
@@ -2585,17 +2882,21 @@ function createMeshCore(agent) {
2882
break;
2883
}
2884
case 'webrtc1': {
2588
- if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6)) { // Terminal
2885
+ if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6))
2886
+ { // Terminal
2887
// Switch the user input from websocket to webrtc at this point.
2590
- if (process.platform == 'win32') {
2888
+ if (process.platform == 'win32')
2889
+ {
2890
ws.unpipe(ws.httprequest._term);
2891
ws.rtcchannel.pipe(ws.httprequest._term, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
2593
- } else {
2892
+ } else
2893
+ {
2894
ws.unpipe(ws.httprequest.process.stdin);
2895
ws.rtcchannel.pipe(ws.httprequest.process.stdin, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
2896
}
2897
ws.resume(); // Resume the websocket to keep receiving control data
2598
- } else if (ws.httprequest.protocol == 2) { // Desktop
2898
+ } else if (ws.httprequest.protocol == 2)
2899
+ { // Desktop
2900
// Switch the user input from websocket to webrtc at this point.
2901
ws.unpipe(ws.httprequest.desktop.kvm);
2902
try { ws.webrtc.rtcchannel.pipe(ws.httprequest.desktop.kvm, { dataTypeSkip: 1, end: false }); } catch (e) { sendConsoleText('EX2'); } // 0 = Binary, 1 = Text.
@@ -2606,14 +2907,18 @@ function createMeshCore(agent) {
2907
}
2908
case 'webrtc2': {
2909
// Other side received websocket end of data marker, start sending data on WebRTC channel
2609
- if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6)) { // Terminal
2610
- if (process.platform == 'win32') {
2910
+ if ((ws.httprequest.protocol == 1) || (ws.httprequest.protocol == 6))
2911
+ { // Terminal
2912
+ if (process.platform == 'win32')
2913
+ {
2914
ws.httprequest._term.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
2612
- } else {
2915
+ } else
2916
+ {
2917
ws.httprequest.process.stdout.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
2918
ws.httprequest.process.stderr.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
2919
}
2616
- } else if (ws.httprequest.protocol == 2) { // Desktop
2920
+ } else if (ws.httprequest.protocol == 2)
2921
+ { // Desktop
2922
ws.httprequest.desktop.kvm.pipe(ws.webrtc.rtcchannel, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
2923
}
2924
break;
@@ -2625,7 +2930,8 @@ function createMeshCore(agent) {
2930
ws.webrtc.websocket = ws;
2931
ws.webrtc.on('connected', function () { /*sendConsoleText('Tunnel #' + this.websocket.tunnel.index + ' WebRTC connected');*/ });
2932
ws.webrtc.on('disconnected', function () { /*sendConsoleText('Tunnel #' + this.websocket.tunnel.index + ' WebRTC disconnected');*/ });
2628
- ws.webrtc.on('dataChannel', function (rtcchannel) {
2933
+ ws.webrtc.on('dataChannel', function (rtcchannel)
2934
+ {
2935
//sendConsoleText('WebRTC Datachannel open, protocol: ' + this.websocket.httprequest.protocol);
2936
rtcchannel.maxFragmentSize = 32768;
2937
rtcchannel.xrtc = this;
@@ -2633,7 +2939,8 @@ function createMeshCore(agent) {
2939
this.rtcchannel = rtcchannel;
2940
this.websocket.rtcchannel = rtcchannel;
2941
this.websocket.rtcchannel.on('data', onTunnelWebRTCControlData);
2636
- this.websocket.rtcchannel.on('end', function () {
2942
+ this.websocket.rtcchannel.on('end', function ()
2943
+ {
2944
// The WebRTC channel closed, unpipe the KVM now. This is also done when the web socket closes.
2945
//sendConsoleText('Tunnel #' + this.websocket.tunnel.index + ' WebRTC data channel closed');
2946
if (this.websocket.desktop && this.websocket.desktop.kvm)
@@ -2672,17 +2979,21 @@ function createMeshCore(agent) {
2979
var consoleHttpRequest = null;
2980
2981
// Console HTTP response
2675
- function consoleHttpResponse(response) {
2982
+ function consoleHttpResponse(response)
2983
+ {
2984
response.data = function (data) { sendConsoleText(rstr2hex(buf2rstr(data)), this.sessionid); consoleHttpRequest = null; }
2985
response.close = function () { sendConsoleText('httprequest.response.close', this.sessionid); consoleHttpRequest = null; }
2986
};
2987
2988
// Open a web browser to a specified URL on current user's desktop
2681
- function openUserDesktopUrl(url) {
2989
+ function openUserDesktopUrl(url)
2990
+ {
2991
if ((url.toLowerCase().startsWith('http://') == false) && (url.toLowerCase().startsWith('https://') == false)) { return null; }
2992
var child = null;
2684
- try {
2685
- switch (process.platform) {
2993
+ try
2994
+ {
2995
+ switch (process.platform)
2996
+ {
2997
case 'win32':
2998
var user = require('user-sessions').getUsername(require('user-sessions').consoleUid());
2999
child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ['cmd']);
@@ -2709,20 +3020,24 @@ function createMeshCore(agent) {
3020
}
3021
3022
// Process a mesh agent console command
2712
- function processConsoleCommand(cmd, args, rights, sessionid) {
2713
- try {
3023
+ function processConsoleCommand(cmd, args, rights, sessionid)
3024
+ {
3025
+ try
3026
+ {
3027
var response = null;
2715
- switch (cmd) {
3028
+ switch (cmd)
3029
+ {
3030
case 'help': { // Displays available commands
2717
- var fin = '', f = '', availcommands = 'msh,timerinfo,coreinfo,coredump,service,fdsnapshot,fdcount,startupoptions,alert,agentsize,versions,help,info,osinfo,args,print,type,dbkeys,dbget,dbset,dbcompact,eval,parseuri,httpget,nwslist,plugin,wsconnect,wssend,wsclose,notify,ls,ps,kill,netinfo,location,power,wakeonlan,setdebug,smbios,rawsmbios,toast,lock,users,openurl,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,wallpaper,agentmsg';
3031
+ var fin = '', f = '', availcommands = 'agentupdate,msh,timerinfo,coreinfo,coredump,service,fdsnapshot,fdcount,startupoptions,alert,agentsize,versions,help,info,osinfo,args,print,type,dbkeys,dbget,dbset,dbcompact,eval,parseuri,httpget,nwslist,plugin,wsconnect,wssend,wsclose,notify,ls,ps,kill,netinfo,location,power,wakeonlan,setdebug,smbios,rawsmbios,toast,lock,users,openurl,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,wallpaper,agentmsg';
3032
if (process.platform == 'win32') { availcommands += ',safemode,wpfhwacceleration,uac'; }
3033
if (amt != null) { availcommands += ',amt,amtconfig,amtevents'; }
2720
- if (process.platform != 'freebsd') { availcommands += ',vm';}
3034
+ if (process.platform != 'freebsd') { availcommands += ',vm'; }
3035
if (require('MeshAgent').maxKvmTileSize != null) { availcommands += ',kvmmode'; }
3036
try { require('zip-reader'); availcommands += ',zip,unzip'; } catch (e) { }
3037
3038
availcommands = availcommands.split(',').sort();
2725
- while (availcommands.length > 0) {
3039
+ while (availcommands.length > 0)
3040
+ {
3041
if (f.length > 90) { fin += (f + ',\r\n'); f = ''; }
3042
f += (((f != '') ? ', ' : ' ') + availcommands.shift());
3043
}
@@ -2731,93 +3046,11 @@ function createMeshCore(agent) {
3046
break;
3047
}
3048
case 'agentupdate':
2734
- if (require('MeshAgent').ARCHID == null)
2735
- {
2736
- response = 'Unable to initiate update, agent ARCHID is not defined';
2737
- break;
2738
- }
2739
- if (this._selfupdate != null)
2740
- {
2741
- response = "Self update already in progress...";
2742
- }
2743
- else
2744
- {
2745
- var agentfilename = process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop();
2746
- var name = require('MeshAgent').serviceName;
2747
- if (name == null) { name = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent'; }
2748
- try
2749
- {
2750
- var s = require('service-manager').manager.getService(name);
2751
- if (s.isMe())
2752
- {
2753
- sendConsoleText('Service check SUCCESS');
2754
- }
2755
- else
2756
- {
2757
- s.close();
2758
- throw ('not a service');
2759
- break;
2760
- }
2761
- if(process.platform=='win32') {s.close();}
2762
- }
2763
- catch (zz)
2764
- {
2765
- response = 'This is not a service instance';
2766
- break;
2767
- }
2768
- sendConsoleText('Downloading update...');
2769
- var options = require('http').parseUri(require('MeshAgent').ServerUrl);
2770
- options.protocol = 'https:';
2771
- options.path = ('/meshagents?id=' + require('MeshAgent').ARCHID);
2772
- options.rejectUnauthorized = false;
2773
- this._selfupdate = require('https').get(options);
2774
- this._selfupdate.on('response', function (img)
2775
- {
2776
- this._file = require('fs').createWriteStream(agentfilename + '.update', {flags: 'wb'});
2777
- this._filehash = require('SHA384Stream').create();
2778
- this._filehash.on('hash', function (h)
2779
- {
2780
- sendConsoleText('Download complete. HASH=' + h.toString('hex'));
2781
- if(process.platform == 'win32')
2782
- {
2783
- this.child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe',
2784
- ['/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 });
2785
- }
2786
- else
2787
- {
2788
- // remove binary
2789
- require('fs').unlinkSync(process.execPath);
2790
-
2791
- // copy update
2792
- require('fs').copyFileSync(process.cwd() + agentfilename + '.update', process.execPath);
2793
-
2794
- // erase update
2795
- require('fs').unlinkSync(process.cwd() + agentfilename + '.update');
2796
-
2797
- // add execute permissions
2798
- var m = require('fs').statSync(process.execPath).mode;
2799
- m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP | require('fs').CHMOD_MODES.S_IXOTH);
2800
- require('fs').chmodSync(process.execPath, m);
2801
-
2802
- sendConsoleText('Restarting service...');
2803
- try
2804
- {
2805
- // restart service
2806
- var s = require('service-manager').manager.getService(name);
2807
- s.restart();
2808
- }
2809
- catch(zz)
2810
- {
2811
- sendConsoleText('Error restarting service');
2812
- }
2813
- }
2814
- });
2815
- img.pipe(this._file);
2816
- img.pipe(this._filehash);
2817
- });
2818
- this._selfupdate.on('error', function (e) { sendConsoleText('Error fetching update'); });
2819
- }
2820
-
3049
+ require('MeshAgent').SendCommand({ action: 'agentupdate' });
3050
+ break;
3051
+ case 'agentupdateex':
3052
+ // Perform an direct agent update without requesting any information from the server, this should not typically be used.
3053
+ agentUpdate_Start(null, { session: sessionid });
3054
break;
3055
case 'msh':
3056
response = JSON.stringify(_MSH(), null, 2);
@@ -2850,21 +3083,26 @@ function createMeshCore(agent) {
3083
break;
3084
}
3085
case 'agentmsg': {
2853
- if (args['_'].length == 0) {
3086
+ if (args['_'].length == 0)
3087
+ {
3088
response = "Proper usage:\r\n agentmsg add \"[message]\" [iconIndex]\r\n agentmsg remove [index]\r\n agentmsg list"; // Display usage
2855
- } else {
2856
- if ((args['_'][0] == 'add') && (args['_'].length > 1)) {
3089
+ } else
3090
+ {
3091
+ if ((args['_'][0] == 'add') && (args['_'].length > 1))
3092
+ {
3093
var msgIndex = 1, iconIndex = 0;
3094
while (tunnelUserCount.msg[msgIndex] != null) { msgIndex++; }
3095
if (args['_'].length >= 3) { try { iconIndex = parseInt(args['_'][2]); } catch (e) { } }
3096
if (typeof iconIndex != 'number') { iconIndex = 0; }
3097
tunnelUserCount.msg[msgIndex] = { msg: args['_'][1], icon: iconIndex };
3098
response = 'Agent message ' + msgIndex + ' added.';
2863
- } else if ((args['_'][0] == 'remove') && (args['_'].length > 1)) {
3099
+ } else if ((args['_'][0] == 'remove') && (args['_'].length > 1))
3100
+ {
3101
var msgIndex = 0;
3102
try { msgIndex = parseInt(args['_'][1]); } catch (x) { }
3103
if (tunnelUserCount.msg[msgIndex] == null) { response = "Message not found."; } else { delete tunnelUserCount.msg[msgIndex]; response = "Message removed."; }
2867
- } else if (args['_'][0] == 'list') {
3104
+ } else if (args['_'][0] == 'list')
3105
+ {
3106
response = JSON.stringify(tunnelUserCount.msg, null, 2);
3107
}
3108
try { mesh.SendCommand({ action: 'sessions', type: 'msg', value: tunnelUserCount.msg }); } catch (x) { }
@@ -2879,9 +3117,11 @@ function createMeshCore(agent) {
3117
break;
3118
}
3119
case 'coredump':
2882
- if (args['_'].length != 1) {
3120
+ if (args['_'].length != 1)
3121
+ {
3122
response = "Proper usage: coredump on|off|status|clear"; // Display usage
2884
- } else {
3123
+ } else
3124
+ {
3125
switch (args['_'][0].toLowerCase())
3126
{
3127
case 'on':
@@ -2894,15 +3134,20 @@ function createMeshCore(agent) {
3134
break;
3135
case 'status':
3136
response = 'coredump is: ' + ((process.coreDumpLocation == null) ? 'off' : 'on');
2897
- if (process.coreDumpLocation != null) {
2898
- if (process.platform == 'win32') {
2899
- if (fs.existsSync(process.coreDumpLocation)) {
3137
+ if (process.coreDumpLocation != null)
3138
+ {
3139
+ if (process.platform == 'win32')
3140
+ {
3141
+ if (fs.existsSync(process.coreDumpLocation))
3142
+ {
3143
response += '\r\n CoreDump present at: ' + process.coreDumpLocation;
3144
response += '\r\n CoreDump Time: ' + new Date(fs.statSync(process.coreDumpLocation).mtime).getTime();
3145
response += '\r\n Agent Time : ' + new Date(fs.statSync(process.execPath).mtime).getTime();
3146
}
2904
- } else {
2905
- if ((process.cwd() != '//') && fs.existsSync(process.cwd() + 'core')) {
3147
+ } else
3148
+ {
3149
+ if ((process.cwd() != '//') && fs.existsSync(process.cwd() + 'core'))
3150
+ {
3151
response += '\r\n CoreDump present at: ' + process.cwd() + 'core';
3152
response += '\r\n CoreDump Time: ' + new Date(fs.statSync(process.cwd() + 'core').mtime).getTime();
3153
response += '\r\n Agent Time : ' + new Date(fs.statSync(process.execPath).mtime).getTime();
@@ -2932,11 +3177,11 @@ function createMeshCore(agent) {
3177
{
3178
svcname = require('MeshAgent').serviceName;
3179
}
2935
- catch(x)
3180
+ catch (x)
3181
{
3182
}
3183
var s = require('service-manager').manager.getService(svcname);
2939
- switch(args['_'][0].toLowerCase())
3184
+ switch (args['_'][0].toLowerCase())
3185
{
3186
case 'status':
3187
response = 'Service ' + (s.isRunning() ? (s.isMe() ? '[SELF]' : '[RUNNING]') : ('[NOT RUNNING]'));
@@ -2959,9 +3204,11 @@ function createMeshCore(agent) {
3204
}
3205
break;
3206
case 'zip':
2962
- if (args['_'].length == 0) {
3207
+ if (args['_'].length == 0)
3208
+ {
3209
response = "Proper usage: zip (output file name), input1 [, input n]"; // Display usage
2964
- } else {
3210
+ } else
3211
+ {
3212
var p = args['_'].join(' ').split(',');
3213
var ofile = p.shift();
3214
sendConsoleText('Writing ' + ofile + '...');
@@ -2974,16 +3221,19 @@ function createMeshCore(agent) {
3221
}
3222
break;
3223
case 'unzip':
2977
- if (args['_'].length == 0) {
3224
+ if (args['_'].length == 0)
3225
+ {
3226
response = "Proper usage: unzip input, destination"; // Display usage
2979
- } else {
3227
+ } else
3228
+ {
3229
var p = args['_'].join(' ').split(',');
3230
if (p.length != 2) { response = "Proper usage: unzip input, destination"; break; } // Display usage
3231
var prom = require('zip-reader').read(p[0]);
3232
prom._dest = p[1];
3233
prom.self = this;
3234
prom.sessionid = sessionid;
2986
- prom.then(function (zipped) {
3235
+ prom.then(function (zipped)
3236
+ {
3237
sendConsoleText('Extracting to ' + this._dest + '...', this.sessionid);
3238
zipped.extractAll(this._dest).then(function () { sendConsoleText('finished unzipping', this.sessionid); }, function (e) { sendConsoleText('Error unzipping: ' + e, this.sessionid); }).parentPromise.sessionid = this.sessionid;
3239
}, function (e) { sendConsoleText('Error unzipping: ' + e, this.sessionid); });
@@ -2991,11 +3241,13 @@ function createMeshCore(agent) {
3241
break;
3242
case 'setbattery':
3243
// require('MeshAgent').SendCommand({ action: 'battery', state: 'dc', level: 55 });
2994
- if ((args['_'].length > 0) && ((args['_'][0] == 'ac') || (args['_'][0] == 'dc'))) {
3244
+ if ((args['_'].length > 0) && ((args['_'][0] == 'ac') || (args['_'][0] == 'dc')))
3245
+ {
3246
var b = { action: 'battery', state: args['_'][0] };
3247
if (args['_'].length == 2) { b.level = parseInt(args['_'][1]); }
3248
require('MeshAgent').SendCommand(b);
2998
- } else {
3249
+ } else
3250
+ {
3251
require('MeshAgent').SendCommand({ action: 'battery' });
3252
}
3253
break;
@@ -3024,7 +3276,7 @@ function createMeshCore(agent) {
3276
}
3277
else
3278
{
3027
- switch(args['_'][0].toUpperCase())
3279
+ switch (args['_'][0].toUpperCase())
3280
{
3281
case 'GET':
3282
var secd = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System', 'PromptOnSecureDesktop');
@@ -3047,7 +3299,7 @@ function createMeshCore(agent) {
3299
require('win-registry').WriteKey(require('win-registry').HKEY.LocalMachine, 'Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System', 'PromptOnSecureDesktop', 1);
3300
response = 'UAC mode changed to: Secure Desktop';
3301
}
3050
- catch(e)
3302
+ catch (e)
3303
{
3304
response = "Unable to change UAC Mode";
3305
}
@@ -3058,9 +3310,9 @@ function createMeshCore(agent) {
3310
}
3311
}
3312
break;
3061
- case 'vm':
3062
- response = 'Virtual Machine = ' + require('identifiers').isVM();
3063
- break;
3313
+ case 'vm':
3314
+ response = 'Virtual Machine = ' + require('identifiers').isVM();
3315
+ break;
3316
case 'startupoptions':
3317
response = JSON.stringify(require('MeshAgent').getStartupOptions());
3318
break;
@@ -3071,72 +3323,81 @@ function createMeshCore(agent) {
3323
}
3324
else
3325
{
3074
- if(require('MeshAgent').maxKvmTileSize == 0)
3326
+ if (require('MeshAgent').maxKvmTileSize == 0)
3327
{
3328
response = 'KVM Mode: Full JUMBO';
3329
}
3078
- else
3330
+ else
3331
{
3332
response = 'KVM Mode: ' + (require('MeshAgent').maxKvmTileSize <= 65500 ? 'NO JUMBO' : 'Partial JUMBO');
3081
- response += (', TileLimit: ' + (require('MeshAgent').maxKvmTileSize < 1024 ? (require('MeshAgent').maxKvmTileSize + ' bytes') : (Math.round(require('MeshAgent').maxKvmTileSize/1024) + ' Kbytes')));
3333
+ response += (', TileLimit: ' + (require('MeshAgent').maxKvmTileSize < 1024 ? (require('MeshAgent').maxKvmTileSize + ' bytes') : (Math.round(require('MeshAgent').maxKvmTileSize / 1024) + ' Kbytes')));
3334
}
3335
}
3336
break;
3337
case 'alert':
3086
- if (args['_'].length == 0)
3338
+ if (args['_'].length == 0)
3339
{
3340
response = "Proper usage: alert TITLE, CAPTION [, TIMEOUT]"; // Display usage
3341
}
3342
else
3343
{
3344
var p = args['_'].join(' ').split(',');
3093
- if(p.length<2)
3345
+ if (p.length < 2)
3346
{
3347
response = "Proper usage: alert TITLE, CAPTION [, TIMEOUT]"; // Display usage
3348
}
3349
else
3350
{
3099
- this._alert = require('message-box').create(p[0], p[1], p.length==3?parseInt(p[2]):9999,1);
3351
+ this._alert = require('message-box').create(p[0], p[1], p.length == 3 ? parseInt(p[2]) : 9999, 1);
3352
}
3353
}
3354
break;
3355
case 'agentsize':
3356
var actualSize = Math.floor(require('fs').statSync(process.execPath).size / 1024);
3105
- if (process.platform == 'win32') {
3357
+ if (process.platform == 'win32')
3358
+ {
3359
// Check the Agent Uninstall MetaData for correctness, as the installer may have written an incorrect value
3360
var writtenSize = 0;
3361
try { writtenSize = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MeshCentralAgent', 'EstimatedSize'); } catch (e) { response = e; }
3109
- if (writtenSize != actualSize) {
3362
+ if (writtenSize != actualSize)
3363
+ {
3364
response = "Size updated from: " + writtenSize + " to: " + actualSize;
3365
try { require('win-registry').WriteKey(require('win-registry').HKEY.LocalMachine, 'Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MeshCentralAgent', 'EstimatedSize', actualSize); } catch (e) { response = e; }
3112
- } else { response = "Agent Size: " + actualSize + " kb"; }
3113
- } else { response = "Agent Size: " + actualSize + " kb"; }
3366
+ } else
3367
+ { response = "Agent Size: " + actualSize + " kb"; }
3368
+ } else
3369
+ { response = "Agent Size: " + actualSize + " kb"; }
3370
break;
3371
case 'versions':
3372
response = JSON.stringify(process.versions, null, ' ');
3373
break;
3374
case 'wpfhwacceleration':
3375
if (process.platform != 'win32') { throw ("wpfhwacceleration setting is only supported on Windows"); }
3120
- if (args['_'].length != 1) {
3376
+ if (args['_'].length != 1)
3377
+ {
3378
response = "Proper usage: wpfhwacceleration (ON|OFF|STATUS)"; // Display usage
3379
}
3123
- else {
3380
+ else
3381
+ {
3382
var reg = require('win-registry');
3383
var uname = require('user-sessions').getUsername(require('user-sessions').consoleUid());
3384
var key = reg.usernameToUserKey(uname);
3385
3128
- switch (args['_'][0].toUpperCase()) {
3386
+ switch (args['_'][0].toUpperCase())
3387
+ {
3388
default:
3389
response = "Proper usage: wpfhwacceleration (ON|OFF|STATUS|DEFAULT)"; // Display usage
3390
break;
3391
case 'ON':
3133
- try {
3392
+ try
3393
+ {
3394
reg.WriteKey(reg.HKEY.Users, key + '\\SOFTWARE\\Microsoft\\Avalon.Graphics', 'DisableHWAcceleration', 0);
3395
response = "OK";
3396
} catch (e) { response = "FAILED"; }
3397
break;
3398
case 'OFF':
3139
- try {
3399
+ try
3400
+ {
3401
reg.WriteKey(reg.HKEY.Users, key + '\\SOFTWARE\\Microsoft\\Avalon.Graphics', 'DisableHWAcceleration', 1);
3402
response = 'OK';
3403
} catch (e) { response = 'FAILED'; }
@@ -3154,59 +3415,76 @@ function createMeshCore(agent) {
3415
}
3416
break;
3417
case 'tsid':
3157
- if (process.platform == 'win32') {
3158
- if (args['_'].length != 1) {
3418
+ if (process.platform == 'win32')
3419
+ {
3420
+ if (args['_'].length != 1)
3421
+ {
3422
response = "TSID: " + (require('MeshAgent')._tsid == null ? "console" : require('MeshAgent')._tsid);
3160
- } else {
3423
+ } else
3424
+ {
3425
var i = parseInt(args['_'][0]);
3426
require('MeshAgent')._tsid = (isNaN(i) ? null : i);
3427
response = "TSID set to: " + (require('MeshAgent')._tsid == null ? "console" : require('MeshAgent')._tsid);
3428
}
3165
- } else { response = "TSID command only supported on Windows"; }
3429
+ } else
3430
+ { response = "TSID command only supported on Windows"; }
3431
break;
3432
case 'activeusers':
3168
- if (process.platform == 'win32') {
3433
+ if (process.platform == 'win32')
3434
+ {
3435
var p = require('user-sessions').enumerateUsers();
3436
p.sessionid = sessionid;
3171
- p.then(function (u) {
3437
+ p.then(function (u)
3438
+ {
3439
var v = [];
3173
- for (var i in u) {
3440
+ for (var i in u)
3441
+ {
3442
if (u[i].State == 'Active') { v.push({ tsid: i, type: u[i].StationName, user: u[i].Username, domain: u[i].Domain }); }
3443
}
3444
sendConsoleText(JSON.stringify(v, null, 1), this.sessionid);
3445
});
3178
- } else { response = "activeusers command only supported on Windows"; }
3446
+ } else
3447
+ { response = "activeusers command only supported on Windows"; }
3448
break;
3449
case 'wallpaper':
3181
- if (process.platform != 'win32' && !(process.platform == 'linux' && require('linux-gnome-helpers').available)) {
3450
+ if (process.platform != 'win32' && !(process.platform == 'linux' && require('linux-gnome-helpers').available))
3451
+ {
3452
response = "wallpaper command not supported on this platform";
3453
}
3184
- else {
3185
- if (args['_'].length != 1) {
3454
+ else
3455
+ {
3456
+ if (args['_'].length != 1)
3457
+ {
3458
response = 'Proper usage: wallpaper (GET|TOGGLE)'; // Display usage
3459
}
3188
- else {
3189
- switch (args['_'][0].toUpperCase()) {
3460
+ else
3461
+ {
3462
+ switch (args['_'][0].toUpperCase())
3463
+ {
3464
default:
3465
response = 'Proper usage: wallpaper (GET|TOGGLE)'; // Display usage
3466
break;
3467
case 'GET':
3468
case 'TOGGLE':
3195
- if (process.platform == 'win32') {
3469
+ if (process.platform == 'win32')
3470
+ {
3471
var id = require('user-sessions').getProcessOwnerName(process.pid).tsid == 0 ? 1 : 0;
3472
var child = require('child_process').execFile(process.execPath, [process.execPath.split('\\').pop(), '-b64exec', 'dmFyIFNQSV9HRVRERVNLV0FMTFBBUEVSID0gMHgwMDczOwp2YXIgU1BJX1NFVERFU0tXQUxMUEFQRVIgPSAweDAwMTQ7CnZhciBHTSA9IHJlcXVpcmUoJ19HZW5lcmljTWFyc2hhbCcpOwp2YXIgdXNlcjMyID0gR00uQ3JlYXRlTmF0aXZlUHJveHkoJ3VzZXIzMi5kbGwnKTsKdXNlcjMyLkNyZWF0ZU1ldGhvZCgnU3lzdGVtUGFyYW1ldGVyc0luZm9BJyk7CgppZiAocHJvY2Vzcy5hcmd2Lmxlbmd0aCA9PSAzKQp7CiAgICB2YXIgdiA9IEdNLkNyZWF0ZVZhcmlhYmxlKDEwMjQpOwogICAgdXNlcjMyLlN5c3RlbVBhcmFtZXRlcnNJbmZvQShTUElfR0VUREVTS1dBTExQQVBFUiwgdi5fc2l6ZSwgdiwgMCk7CiAgICBjb25zb2xlLmxvZyh2LlN0cmluZyk7CiAgICBwcm9jZXNzLmV4aXQoKTsKfQplbHNlCnsKICAgIHZhciBuYiA9IEdNLkNyZWF0ZVZhcmlhYmxlKHByb2Nlc3MuYXJndlszXSk7CiAgICB1c2VyMzIuU3lzdGVtUGFyYW1ldGVyc0luZm9BKFNQSV9TRVRERVNLV0FMTFBBUEVSLCBuYi5fc2l6ZSwgbmIsIDApOwogICAgcHJvY2Vzcy5leGl0KCk7Cn0='], { type: id });
3473
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
3474
child.stderr.on('data', function () { });
3475
child.waitExit();
3476
var current = child.stdout.str.trim();
3202
- if (args['_'][0].toUpperCase() == 'GET') {
3477
+ if (args['_'][0].toUpperCase() == 'GET')
3478
+ {
3479
response = current;
3480
break;
3481
}
3206
- if (current != '') {
3482
+ if (current != '')
3483
+ {
3484
require('MeshAgent')._wallpaper = current;
3485
response = 'Wallpaper cleared';
3209
- } else {
3486
+ } else
3487
+ {
3488
response = 'Wallpaper restored';
3489
}
3490
child = require('child_process').execFile(process.execPath, [process.execPath.split('\\').pop(), '-b64exec', 'dmFyIFNQSV9HRVRERVNLV0FMTFBBUEVSID0gMHgwMDczOwp2YXIgU1BJX1NFVERFU0tXQUxMUEFQRVIgPSAweDAwMTQ7CnZhciBHTSA9IHJlcXVpcmUoJ19HZW5lcmljTWFyc2hhbCcpOwp2YXIgdXNlcjMyID0gR00uQ3JlYXRlTmF0aXZlUHJveHkoJ3VzZXIzMi5kbGwnKTsKdXNlcjMyLkNyZWF0ZU1ldGhvZCgnU3lzdGVtUGFyYW1ldGVyc0luZm9BJyk7CgppZiAocHJvY2Vzcy5hcmd2Lmxlbmd0aCA9PSAzKQp7CiAgICB2YXIgdiA9IEdNLkNyZWF0ZVZhcmlhYmxlKDEwMjQpOwogICAgdXNlcjMyLlN5c3RlbVBhcmFtZXRlcnNJbmZvQShTUElfR0VUREVTS1dBTExQQVBFUiwgdi5fc2l6ZSwgdiwgMCk7CiAgICBjb25zb2xlLmxvZyh2LlN0cmluZyk7CiAgICBwcm9jZXNzLmV4aXQoKTsKfQplbHNlCnsKICAgIHZhciBuYiA9IEdNLkNyZWF0ZVZhcmlhYmxlKHByb2Nlc3MuYXJndlszXSk7CiAgICB1c2VyMzIuU3lzdGVtUGFyYW1ldGVyc0luZm9BKFNQSV9TRVRERVNLV0FMTFBBUEVSLCBuYi5fc2l6ZSwgbmIsIDApOwogICAgcHJvY2Vzcy5leGl0KCk7Cn0=', current != '' ? '""' : require('MeshAgent')._wallpaper], { type: id });
@@ -3214,17 +3492,21 @@ function createMeshCore(agent) {
3492
child.stderr.on('data', function () { });
3493
child.waitExit();
3494
}
3217
- else {
3495
+ else
3496
+ {
3497
var id = require('user-sessions').consoleUid();
3498
var current = require('linux-gnome-helpers').getDesktopWallpaper(id);
3220
- if (args['_'][0].toUpperCase() == 'GET') {
3499
+ if (args['_'][0].toUpperCase() == 'GET')
3500
+ {
3501
response = current;
3502
break;
3503
}
3224
- if (current != '/dev/null') {
3504
+ if (current != '/dev/null')
3505
+ {
3506
require('MeshAgent')._wallpaper = current;
3507
response = 'Wallpaper cleared';
3227
- } else {
3508
+ } else
3509
+ {
3510
response = 'Wallpaper restored';
3511
}
3512
require('linux-gnome-helpers').setDesktopWallpaper(id, current != '/dev/null' ? undefined : require('MeshAgent')._wallpaper);
@@ -3289,30 +3571,32 @@ function createMeshCore(agent) {
3571
}
3572
}
3573
break;
3292
- /*
3293
- case 'border':
3294
- {
3295
- if ((args['_'].length == 1) && (args['_'][0] == 'on')) {
3296
- if (meshCoreObj.users.length > 0) {
3297
- obj.borderManager.Start(meshCoreObj.users[0]);
3298
- response = 'Border blinking is on.';
3574
+ /*
3575
+ case 'border':
3576
+ {
3577
+ if ((args['_'].length == 1) && (args['_'][0] == 'on')) {
3578
+ if (meshCoreObj.users.length > 0) {
3579
+ obj.borderManager.Start(meshCoreObj.users[0]);
3580
+ response = 'Border blinking is on.';
3581
+ } else {
3582
+ response = 'Cannot turn on border blinking, no logged in users.';
3583
+ }
3584
+ } else if ((args['_'].length == 1) && (args['_'][0] == 'off')) {
3585
+ obj.borderManager.Stop();
3586
+ response = 'Border blinking is off.';
3587
} else {
3300
- response = 'Cannot turn on border blinking, no logged in users.';
3588
+ response = 'Proper usage: border "on|off"'; // Display correct command usage
3589
}
3302
- } else if ((args['_'].length == 1) && (args['_'][0] == 'off')) {
3303
- obj.borderManager.Stop();
3304
- response = 'Border blinking is off.';
3305
- } else {
3306
- response = 'Proper usage: border "on|off"'; // Display correct command usage
3590
}
3308
- }
3309
- break;
3310
- */
3591
+ break;
3592
+ */
3593
case 'av':
3312
- if (process.platform == 'win32') {
3594
+ if (process.platform == 'win32')
3595
+ {
3596
// Windows Command: "wmic /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct get /FORMAT:CSV"
3597
response = JSON.stringify(require('win-info').av(), null, 1);
3315
- } else {
3598
+ } else
3599
+ {
3600
response = 'Not supported on the platform';
3601
}
3602
break;
@@ -3320,21 +3604,27 @@ function createMeshCore(agent) {
3604
if (args['_'].length != 1) { response = 'Proper usage: log "sample text"'; } else { MeshServerLog(args['_'][0]); response = 'ok'; }
3605
break;
3606
case 'getclip':
3323
- if (require('MeshAgent').isService) {
3607
+ if (require('MeshAgent').isService)
3608
+ {
3609
require('clipboard').dispatchRead().then(function (str) { sendConsoleText(str, sessionid); });
3325
- } else {
3610
+ } else
3611
+ {
3612
require("clipboard").read().then(function (str) { sendConsoleText(str, sessionid); });
3613
}
3614
break;
3615
case 'setclip': {
3330
- if (args['_'].length != 1) {
3616
+ if (args['_'].length != 1)
3617
+ {
3618
response = 'Proper usage: setclip "sample text"';
3332
- } else {
3333
- if (require('MeshAgent').isService) {
3619
+ } else
3620
+ {
3621
+ if (require('MeshAgent').isService)
3622
+ {
3623
require('clipboard').dispatchWrite(args['_'][0]);
3624
response = 'Setting clipboard to: "' + args['_'][0] + '"';
3625
}
3337
- else {
3626
+ else
3627
+ {
3628
require("clipboard")(args['_'][0]); response = 'Setting clipboard to: "' + args['_'][0] + '"';
3629
}
3630
}
@@ -3352,10 +3642,12 @@ function createMeshCore(agent) {
3642
}
3643
case 'toast': {
3644
if (args['_'].length < 1) { response = 'Proper usage: toast "message"'; } else {
3355
- if (require('MeshAgent')._tsid == null) {
3645
+ if (require('MeshAgent')._tsid == null)
3646
+ {
3647
require('toaster').Toast('MeshCentral', args['_'][0]).then(sendConsoleText, sendConsoleText);
3648
}
3358
- else {
3649
+ else
3650
+ {
3651
require('toaster').Toast('MeshCentral', args['_'][0], require('MeshAgent')._tsid).then(sendConsoleText, sendConsoleText);
3652
}
3653
}
@@ -3367,7 +3659,8 @@ function createMeshCore(agent) {
3659
break;
3660
}
3661
case 'ps': {
3370
- processManager.getProcesses(function (plist) {
3662
+ processManager.getProcesses(function (plist)
3663
+ {
3664
var x = '';
3665
for (var i in plist) { x += i + ((plist[i].user) ? (', ' + plist[i].user) : '') + ', ' + plist[i].cmd + '\r\n'; }
3666
sendConsoleText(x, sessionid);
@@ -3375,9 +3668,11 @@ function createMeshCore(agent) {
3668
break;
3669
}
3670
case 'kill': {
3378
- if ((args['_'].length < 1)) {
3671
+ if ((args['_'].length < 1))
3672
+ {
3673
response = 'Proper usage: kill [pid]'; // Display correct command usage
3380
- } else {
3674
+ } else
3675
+ {
3676
process.kill(parseInt(args['_'][0]));
3677
response = 'Killed process ' + args['_'][0] + '.';
3678
}
@@ -3390,10 +3685,13 @@ function createMeshCore(agent) {
3685
case 'rawsmbios': {
3686
if (SMBiosTablesRaw == null) { response = 'SMBios tables not available.'; } else {
3687
response = '';
3393
- for (var i in SMBiosTablesRaw) {
3688
+ for (var i in SMBiosTablesRaw)
3689
+ {
3690
var header = false;
3395
- for (var j in SMBiosTablesRaw[i]) {
3396
- if (SMBiosTablesRaw[i][j].length > 0) {
3691
+ for (var j in SMBiosTablesRaw[i])
3692
+ {
3693
+ if (SMBiosTablesRaw[i][j].length > 0)
3694
+ {
3695
if (header == false) { response += ('Table type #' + i + ((require('smbios').smTableTypes[i] == null) ? '' : (', ' + require('smbios').smTableTypes[i]))) + '\r\n'; header = true; }
3696
response += (' ' + SMBiosTablesRaw[i][j].toString('hex')) + '\r\n';
3697
}
@@ -3403,9 +3701,11 @@ function createMeshCore(agent) {
3701
break;
3702
}
3703
case 'eval': { // Eval JavaScript
3406
- if (args['_'].length < 1) {
3704
+ if (args['_'].length < 1)
3705
+ {
3706
response = 'Proper usage: eval "JavaScript code"'; // Display correct command usage
3408
- } else {
3707
+ } else
3708
+ {
3709
response = JSON.stringify(mesh.eval(args['_'][0])); // This can only be run by trusted administrator.
3710
}
3711
break;
@@ -3420,18 +3720,22 @@ function createMeshCore(agent) {
3720
{
3721
}
3722
3423
- if (!require('service-manager').manager.getService(agentName).isMe()) {
3723
+ if (!require('service-manager').manager.getService(agentName).isMe())
3724
+ {
3725
response = 'Uininstall failed, this instance is not the service instance';
3425
- } else {
3726
+ } else
3727
+ {
3728
try { diagnosticAgent_uninstall(); } catch (e) { }
3729
var js = "require('service-manager').manager.getService('" + agentName + "').stop(); require('service-manager').manager.uninstallService('" + agentName + "'); process.exit();";
3730
this.child = require('child_process').execFile(process.execPath, [process.platform == 'win32' ? (process.execPath.split('\\').pop()) : (process.execPath.split('/').pop()), '-b64exec', Buffer.from(js).toString('base64')], { type: 4, detached: true });
3731
}
3732
break;
3733
case 'notify': { // Send a notification message to the mesh
3432
- if (args['_'].length != 1) {
3734
+ if (args['_'].length != 1)
3735
+ {
3736
response = 'Proper usage: notify "message" [--session]'; // Display correct command usage
3434
- } else {
3737
+ } else
3738
+ {
3739
var notification = { action: 'msg', type: 'notify', value: args['_'][0], tag: 'console' };
3740
if (args.session) { notification.sessionid = sessionid; } // If "--session" is specified, notify only this session, if not, the server will notify the mesh
3741
mesh.SendCommand(notification); // no sessionid or userid specified, notification will go to the entire mesh
@@ -3443,15 +3747,18 @@ function createMeshCore(agent) {
3747
// CPU & memory utilization
3748
pr = require('sysinfo').cpuUtilization();
3749
pr.sessionid = sessionid;
3446
- pr.then(function (data) {
3750
+ pr.then(function (data)
3751
+ {
3752
sendConsoleText(JSON.stringify({ cpu: data, memory: require('sysinfo').memUtilization() }, null, 1), this.sessionid);
3448
- }, function (e) {
3753
+ }, function (e)
3754
+ {
3755
sendConsoleText(e);
3756
});
3757
break;
3758
}
3759
case 'sysinfo': { // Return system information
3454
- getSystemInformation(function (results, err) {
3760
+ getSystemInformation(function (results, err)
3761
+ {
3762
if (results == null) { sendConsoleText(err, this.sessionid); } else {
3763
sendConsoleText(JSON.stringify(results, null, 1), this.sessionid);
3764
}
@@ -3459,7 +3766,7 @@ function createMeshCore(agent) {
3766
break;
3767
}
3768
case 'info': { // Return information about the agent and agent core module
3462
- response = 'Current Core: ' + meshCoreObj.value + '\r\nAgent Time: ' + Date() + '.\r\nUser Rights: 0x' + rights.toString(16) + '.\r\nPlatform: ' + process.platform + '.\r\nCapabilities: ' + meshCoreObj.caps + '.\r\nServer URL: ' + mesh.ServerUrl + '.';
3769
+ response = 'Current Core: ' + meshCoreObj.value + '\r\nAgent Time: ' + Date() + '.\r\nUser Rights: 0x' + rights.toString(16) + '.\r\nPlatform: ' + process.platform + '.\r\nCapabilities: ' + meshCoreObj.caps + '.\r\nServer URL: ' + mesh.ServerUrl + '.';
3770
if (amt != null) { response += '\r\nBuilt-in LMS: ' + ['Disabled', 'Connecting..', 'Connected'][amt.lmsstate] + '.'; }
3771
if (meshCoreObj.osdesc) { response += '\r\nOS: ' + meshCoreObj.osdesc + '.'; }
3772
response += '\r\nModules: ' + addedModules.join(', ') + '.';
@@ -3473,10 +3780,12 @@ function createMeshCore(agent) {
3780
case 'osinfo': { // Return the operating system information
3781
var i = 1;
3782
if (args['_'].length > 0) { i = parseInt(args['_'][0]); if (i > 8) { i = 8; } response = 'Calling ' + i + ' times.'; }
3476
- for (var j = 0; j < i; j++) {
3783
+ for (var j = 0; j < i; j++)
3784
+ {
3785
var pr = require('os').name();
3786
pr.sessionid = sessionid;
3479
- pr.then(function (v) {
3787
+ pr.then(function (v)
3788
+ {
3789
sendConsoleText("OS: " + v + (process.platform == 'win32' ? (require('win-virtual-terminal').supported ? ' [ConPTY: YES]' : ' [ConPTY: NO]') : ''), this.sessionid);
3790
});
3791
}
@@ -3494,9 +3803,11 @@ function createMeshCore(agent) {
3803
break;
3804
}
3805
case 'type': { // Returns the content of a file
3497
- if (args['_'].length == 0) {
3806
+ if (args['_'].length == 0)
3807
+ {
3808
response = 'Proper usage: type (filepath) [maxlength]'; // Display correct command usage
3499
- } else {
3809
+ } else
3810
+ {
3811
var max = 4096;
3812
if ((args['_'].length > 1) && (typeof args['_'][1] == 'number')) { max = args['_'][1]; }
3813
if (max > 4096) max = 4096;
@@ -3515,18 +3826,22 @@ function createMeshCore(agent) {
3826
}
3827
case 'dbget': { // Return the data store value for a given key
3828
if (db == null) { response = 'Database not accessible.'; break; }
3518
- if (args['_'].length != 1) {
3829
+ if (args['_'].length != 1)
3830
+ {
3831
response = 'Proper usage: dbget (key)'; // Display the value for a given database key
3520
- } else {
3832
+ } else
3833
+ {
3834
response = db.Get(args['_'][0]);
3835
}
3836
break;
3837
}
3838
case 'dbset': { // Set a data store key and value pair
3839
if (db == null) { response = 'Database not accessible.'; break; }
3527
- if (args['_'].length != 2) {
3840
+ if (args['_'].length != 2)
3841
+ {
3842
response = 'Proper usage: dbset (key) (value)'; // Set a database key
3529
- } else {
3843
+ } else
3844
+ {
3845
var r = db.Put(args['_'][0], args['_'][1]);
3846
response = 'Key set: ' + r;
3847
}
@@ -3539,20 +3854,27 @@ function createMeshCore(agent) {
3854
break;
3855
}
3856
case 'httpget': {
3542
- if (consoleHttpRequest != null) {
3857
+ if (consoleHttpRequest != null)
3858
+ {
3859
response = 'HTTP operation already in progress.';
3544
- } else {
3545
- if (args['_'].length != 1) {
3860
+ } else
3861
+ {
3862
+ if (args['_'].length != 1)
3863
+ {
3864
response = 'Proper usage: httpget (url)';
3547
- } else {
3865
+ } else
3866
+ {
3867
var options = http.parseUri(args['_'][0]);
3868
options.method = 'GET';
3550
- if (options == null) {
3869
+ if (options == null)
3870
+ {
3871
response = 'Invalid url.';
3552
- } else {
3872
+ } else
3873
+ {
3874
try { consoleHttpRequest = http.request(options, consoleHttpResponse); } catch (e) { response = 'Invalid HTTP GET request'; }
3875
consoleHttpRequest.sessionid = sessionid;
3555
- if (consoleHttpRequest != null) {
3876
+ if (consoleHttpRequest != null)
3877
+ {
3878
consoleHttpRequest.end();
3879
response = 'HTTPGET ' + options.protocol + '//' + options.host + ':' + options.port + options.path;
3880
}
@@ -3563,7 +3885,8 @@ function createMeshCore(agent) {
3885
}
3886
case 'wslist': { // List all web sockets
3887
response = '';
3566
- for (var i in consoleWebSockets) {
3888
+ for (var i in consoleWebSockets)
3889
+ {
3890
var httprequest = consoleWebSockets[i];
3891
response += 'Websocket #' + i + ', ' + httprequest.url + '\r\n';
3892
}
@@ -3571,16 +3894,20 @@ function createMeshCore(agent) {
3894
break;
3895
}
3896
case 'wsconnect': { // Setup a web socket
3574
- if (args['_'].length == 0) {
3897
+ if (args['_'].length == 0)
3898
+ {
3899
response = 'Proper usage: wsconnect (url)\r\nFor example: wsconnect wss://localhost:443/meshrelay.ashx?id=abc'; // Display correct command usage
3576
- } else {
3900
+ } else
3901
+ {
3902
var httprequest = null;
3578
- try {
3903
+ try
3904
+ {
3905
var options = http.parseUri(args['_'][0].split('$').join('%24').split('@').join('%40')); // Escape the $ and @ characters in the URL
3906
options.rejectUnauthorized = 0;
3907
httprequest = http.request(options);
3908
} catch (e) { response = 'Invalid HTTP websocket request'; }
3583
- if (httprequest != null) {
3909
+ if (httprequest != null)
3910
+ {
3911
httprequest.upgrade = onWebSocketUpgrade;
3912
httprequest.on('error', function (e) { sendConsoleText("ERROR: Unable to connect to: " + this.url + ", " + JSON.stringify(e)); });
3913
@@ -3596,34 +3923,43 @@ function createMeshCore(agent) {
3923
break;
3924
}
3925
case 'wssend': { // Send data on a web socket
3599
- if (args['_'].length == 0) {
3926
+ if (args['_'].length == 0)
3927
+ {
3928
response = 'Proper usage: wssend (socketnumber)\r\n'; // Display correct command usage
3601
- for (var i in consoleWebSockets) {
3929
+ for (var i in consoleWebSockets)
3930
+ {
3931
var httprequest = consoleWebSockets[i];
3932
response += 'Websocket #' + i + ', ' + httprequest.url + '\r\n';
3933
}
3605
- } else {
3934
+ } else
3935
+ {
3936
var i = parseInt(args['_'][0]);
3937
var httprequest = consoleWebSockets[i];
3608
- if (httprequest != undefined) {
3938
+ if (httprequest != undefined)
3939
+ {
3940
httprequest.s.write(args['_'][1]);
3941
response = 'ok';
3611
- } else {
3942
+ } else
3943
+ {
3944
response = 'Invalid web socket number';
3945
}
3946
}
3947
break;
3948
}
3949
case 'wsclose': { // Close a websocket
3618
- if (args['_'].length == 0) {
3950
+ if (args['_'].length == 0)
3951
+ {
3952
response = 'Proper usage: wsclose (socketnumber)'; // Display correct command usage
3620
- } else {
3953
+ } else
3954
+ {
3955
var i = parseInt(args['_'][0]);
3956
var httprequest = consoleWebSockets[i];
3623
- if (httprequest != undefined) {
3957
+ if (httprequest != undefined)
3958
+ {
3959
if (httprequest.s != null) { httprequest.s.end(); } else { httprequest.end(); }
3960
response = 'ok';
3626
- } else {
3961
+ } else
3962
+ {
3963
response = 'Invalid web socket number';
3964
}
3965
}
@@ -3641,12 +3977,15 @@ function createMeshCore(agent) {
3977
if (args['_'].length > 0) { xpath = obj.path.join(args['_'][0], '*'); }
3978
response = 'List of ' + xpath + '\r\n';
3979
var results = fs.readdirSync(xpath);
3644
- for (var i = 0; i < results.length; ++i) {
3980
+ for (var i = 0; i < results.length; ++i)
3981
+ {
3982
var stat = null, p = obj.path.join(args['_'][0], results[i]);
3983
try { stat = fs.statSync(p); } catch (e) { }
3647
- if ((stat == null) || (stat == undefined)) {
3984
+ if ((stat == null) || (stat == undefined))
3985
+ {
3986
response += (results[i] + "\r\n");
3649
- } else {
3987
+ } else
3988
+ {
3989
response += (results[i] + " " + ((stat.isDirectory()) ? "(Folder)" : "(File)") + "\r\n");
3990
}
3991
}
@@ -3662,13 +4001,16 @@ function createMeshCore(agent) {
4001
break;
4002
}
4003
case 'amt': { // Show Intel AMT status
3665
- if (amt != null) {
3666
- amt.getMeiState(9, function (state) {
4004
+ if (amt != null)
4005
+ {
4006
+ amt.getMeiState(9, function (state)
4007
+ {
4008
var resp = "Intel AMT not detected.";
4009
if (state != null) { resp = objToString(state, 0, ' ', true); }
4010
sendConsoleText(resp, sessionid);
4011
});
3671
- } else {
4012
+ } else
4013
+ {
4014
response = "Intel AMT not detected.";
4015
}
4016
break;
@@ -3679,9 +4021,11 @@ function createMeshCore(agent) {
4021
break;
4022
}
4023
case 'wakeonlan': { // Send wake-on-lan
3682
- if ((args['_'].length != 1) || (args['_'][0].length != 12)) {
4024
+ if ((args['_'].length != 1) || (args['_'][0].length != 12))
4025
+ {
4026
response = 'Proper usage: wakeonlan [mac], for example "wakeonlan 010203040506".';
3684
- } else {
4027
+ } else
4028
+ {
4029
var count = sendWakeOnLan(args['_'][0]);
4030
response = 'Sent wake-on-lan on ' + count + ' interface(s).';
4031
}
@@ -3692,12 +4036,16 @@ function createMeshCore(agent) {
4036
break;
4037
}
4038
case 'power': { // Execute a power action on this computer
3695
- if (mesh.ExecPowerState == undefined) {
4039
+ if (mesh.ExecPowerState == undefined)
4040
+ {
4041
response = 'Power command not supported on this agent.';
3697
- } else {
3698
- if ((args['_'].length == 0) || isNaN(Number(args['_'][0]))) {
4042
+ } else
4043
+ {
4044
+ if ((args['_'].length == 0) || isNaN(Number(args['_'][0])))
4045
+ {
4046
response = 'Proper usage: power (actionNumber), where actionNumber is:\r\n LOGOFF = 1\r\n SHUTDOWN = 2\r\n REBOOT = 3\r\n SLEEP = 4\r\n HIBERNATE = 5\r\n DISPLAYON = 6\r\n KEEPAWAKE = 7\r\n BEEP = 8\r\n CTRLALTDEL = 9\r\n VIBRATE = 13\r\n FLASH = 14'; // Display correct command usage
3700
- } else {
4047
+ } else
4048
+ {
4049
var r = mesh.ExecPowerState(Number(args['_'][0]), Number(args['_'][1]));
4050
response = 'Power action executed with return code: ' + r + '.';
4051
}
@@ -3705,7 +4053,8 @@ function createMeshCore(agent) {
4053
break;
4054
}
4055
case 'location': {
3708
- getIpLocationData(function (location) {
4056
+ getIpLocationData(function (location)
4057
+ {
4058
sendConsoleText(objToString({ action: 'iplocation', type: 'publicip', value: location }, 0, ' '));
4059
});
4060
break;
@@ -3715,10 +4064,12 @@ function createMeshCore(agent) {
4064
break;
4065
}
4066
case 'scanwifi': {
3718
- if (wifiScanner != null) {
4067
+ if (wifiScanner != null)
4068
+ {
4069
var wifiPresent = wifiScanner.hasWireless;
4070
if (wifiPresent) { response = "Perfoming Wifi scan..."; wifiScanner.Scan(); } else { response = "Wifi absent."; }
3721
- } else { response = "Wifi module not present."; }
4071
+ } else
4072
+ { response = "Wifi module not present."; }
4073
break;
4074
}
4075
case 'modules': {
@@ -3731,40 +4082,51 @@ function createMeshCore(agent) {
4082
break;
4083
}
4084
case 'getscript': {
3734
- if (args['_'].length != 1) {
4085
+ if (args['_'].length != 1)
4086
+ {
4087
response = "Proper usage: getscript [scriptNumber].";
3736
- } else {
4088
+ } else
4089
+ {
4090
mesh.SendCommand({ action: 'getScript', type: args['_'][0] });
4091
}
4092
break;
4093
}
4094
case 'diagnostic':
4095
{
3743
- if (!mesh.DAIPC.listening) {
4096
+ if (!mesh.DAIPC.listening)
4097
+ {
4098
response = 'Unable to bind to Diagnostic IPC, most likely because the path (' + process.cwd() + ') is not on a local file system';
4099
break;
4100
}
4101
var diag = diagnosticAgent_installCheck();
3748
- if (diag) {
3749
- if (args['_'].length == 1 && args['_'][0] == 'uninstall') {
4102
+ if (diag)
4103
+ {
4104
+ if (args['_'].length == 1 && args['_'][0] == 'uninstall')
4105
+ {
4106
diagnosticAgent_uninstall();
4107
response = 'Diagnostic Agent uninstalled';
4108
}
3753
- else {
4109
+ else
4110
+ {
4111
response = 'Diagnostic Agent installed at: ' + diag.appLocation();
4112
}
4113
}
3757
- else {
3758
- if (args['_'].length == 1 && args['_'][0] == 'install') {
4114
+ else
4115
+ {
4116
+ if (args['_'].length == 1 && args['_'][0] == 'install')
4117
+ {
4118
diag = diagnosticAgent_installCheck(true);
3760
- if (diag) {
4119
+ if (diag)
4120
+ {
4121
response = 'Diagnostic agent was installed at: ' + diag.appLocation();
4122
}
3763
- else {
4123
+ else
4124
+ {
4125
response = 'Diagnostic agent installation failed';
4126
}
4127
}
3767
- else {
4128
+ else
4129
+ {
4130
response = 'Diagnostic Agent Not installed. To install: diagnostic install';
4131
}
4132
}
@@ -3778,7 +4140,8 @@ function createMeshCore(agent) {
4140
case 'amtconfig': {
4141
if (amt == null) { response = "Intel AMT not detected."; break; }
4142
if (apftunnel != null) { response = "Intel AMT server tunnel already active"; break; }
3781
- amt.getMeiState(15, function (state) {
4143
+ amt.getMeiState(15, function (state)
4144
+ {
4145
var rx = '';
4146
if ((state == null) || (state.ProvisioningState == null)) { rx = "Intel AMT not ready for configuration."; } else {
4147
var apfarg = {
@@ -3792,15 +4155,19 @@ function createMeshCore(agent) {
4155
conntype: 2, // 0 = CIRA, 1 = Relay, 2 = LMS. The correct value is 2 since we are performing an LMS relay, other values for testing.
4156
meiState: state // MEI state will be passed to MPS server
4157
};
3795
- if ((state.UUID == null) || (state.UUID.length != 36)) {
4158
+ if ((state.UUID == null) || (state.UUID.length != 36))
4159
+ {
4160
rx = "Unable to get Intel AMT UUID";
3797
- } else {
4161
+ } else
4162
+ {
4163
addAmtEvent('User LMS tunnel start.');
4164
apftunnel = require('amt-apfclient')({ debug: false }, apfarg);
3800
- apftunnel.onJsonControl = function (data) {
4165
+ apftunnel.onJsonControl = function (data)
4166
+ {
4167
if (data.action == 'console') { addAmtEvent(data.msg); require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: data.msg }); } // Display a console message
4168
if (data.action == 'mestate') { amt.getMeiState(15, function (state) { apftunnel.updateMeiState(state); }); } // Update the MEI state
3803
- if (data.action == 'deactivate') { // Request CCM deactivation
4169
+ if (data.action == 'deactivate')
4170
+ { // Request CCM deactivation
4171
var amtMeiModule, amtMei;
4172
try { amtMeiModule = require('amt-mei'); amtMei = new amtMeiModule(); } catch (ex) { apftunnel.sendMeiDeactivationState(1); return; }
4173
amtMei.on('error', function (e) { apftunnel.sendMeiDeactivationState(1); });
@@ -3809,10 +4176,12 @@ function createMeshCore(agent) {
4176
if (data.action == 'close') { try { apftunnel.disconnect(); } catch (e) { } apftunnel = null; } // Close the CIRA-LMS connection
4177
}
4178
apftunnel.onChannelClosed = function () { addAmtEvent('User LMS tunnel closed.'); apftunnel = null; }
3812
- try {
4179
+ try
4180
+ {
4181
apftunnel.connect();
4182
rx = "Started Intel AMT configuration";
3815
- } catch (ex) {
4183
+ } catch (ex)
4184
+ {
4185
rx = JSON.stringify(ex);
4186
}
4187
}
@@ -3822,14 +4191,17 @@ function createMeshCore(agent) {
4191
break;
4192
}
4193
case 'apf': {
3825
- if (meshCoreObj.intelamt !== null) {
3826
- if (args['_'].length == 1) {
4194
+ if (meshCoreObj.intelamt !== null)
4195
+ {
4196
+ if (args['_'].length == 1)
4197
+ {
4198
var connType = -1, connTypeStr = args['_'][0].toLowerCase();
4199
if (connTypeStr == 'lms') { connType = 2; }
4200
if (connTypeStr == 'relay') { connType = 1; }
4201
if (connTypeStr == 'cira') { connType = 0; }
4202
if (connTypeStr == 'off') { connType = -2; }
3832
- if (connType >= 0) { // Connect
4203
+ if (connType >= 0)
4204
+ { // Connect
4205
var apfarg = {
4206
mpsurl: mesh.ServerUrl.replace('agent.ashx', 'apf.ashx'),
4207
mpsuser: Buffer.from(mesh.ServerInfo.MeshID, 'hex').toString('base64').substring(0, 16),
@@ -3840,52 +4212,67 @@ function createMeshCore(agent) {
4212
clientuuid: meshCoreObj.intelamt.uuid,
4213
conntype: connType // 0 = CIRA, 1 = Relay, 2 = LMS. The correct value is 2 since we are performing an LMS relay, other values for testing.
4214
};
3843
- if ((apfarg.clientuuid == null) || (apfarg.clientuuid.length != 36)) {
4215
+ if ((apfarg.clientuuid == null) || (apfarg.clientuuid.length != 36))
4216
+ {
4217
response = "Unable to get Intel AMT UUID: " + apfarg.clientuuid;
3845
- } else {
4218
+ } else
4219
+ {
4220
apftunnel = require('amt-apfclient')({ debug: false }, apfarg);
3847
- apftunnel.onJsonControl = function (data) {
4221
+ apftunnel.onJsonControl = function (data)
4222
+ {
4223
if (data.action == 'console') { require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: data.msg }); }
4224
if (data.action == 'close') { try { apftunnel.disconnect(); } catch (e) { } apftunnel = null; }
4225
}
4226
apftunnel.onChannelClosed = function () { apftunnel = null; }
3852
- try {
4227
+ try
4228
+ {
4229
apftunnel.connect();
4230
response = "Started APF tunnel";
3855
- } catch (e) {
4231
+ } catch (e)
4232
+ {
4233
response = JSON.stringify(e);
4234
}
4235
}
3859
- } else if (connType == -2) { // Disconnect
3860
- try {
4236
+ } else if (connType == -2)
4237
+ { // Disconnect
4238
+ try
4239
+ {
4240
apftunnel.disconnect();
4241
response = "Stopped APF tunnel";
3863
- } catch (e) {
4242
+ } catch (e)
4243
+ {
4244
response = JSON.stringify(e);
4245
}
4246
apftunnel = null;
3867
- } else {
4247
+ } else
4248
+ {
4249
response = "Invalid command.\r\nUse: apf lms|relay|cira|off";
4250
}
3870
- } else {
4251
+ } else
4252
+ {
4253
response = "APF tunnel is " + (apftunnel == null ? "off" : "on") + "\r\nUse: apf lms|relay|cira|off";
4254
}
3873
- } else {
4255
+ } else
4256
+ {
4257
response = "APF tunnel requires Intel AMT";
4258
}
4259
break;
4260
}
4261
case 'plugin': {
3879
- if (typeof args['_'][0] == 'string') {
3880
- try {
4262
+ if (typeof args['_'][0] == 'string')
4263
+ {
4264
+ try
4265
+ {
4266
// Pass off the action to the plugin
4267
// for plugin creators, you'll want to have a plugindir/modules_meshcore/plugin.js
4268
// to control the output / actions here.
4269
response = require(args['_'][0]).consoleaction(args, rights, sessionid, mesh);
3885
- } catch (e) {
4270
+ } catch (e)
4271
+ {
4272
response = "There was an error in the plugin (" + e + ")";
4273
}
3888
- } else {
4274
+ } else
4275
+ {
4276
response = "Proper usage: plugin [pluginName] [args].";
4277
}
4278
break;
@@ -3900,23 +4287,183 @@ function createMeshCore(agent) {
4287
}
4288
4289
// Send a mesh agent console command
3903
- function sendConsoleText(text, sessionid) {
4290
+ function sendConsoleText(text, sessionid)
4291
+ {
4292
if (typeof text == 'object') { text = JSON.stringify(text); }
4293
if (debugConsole && ((sessionid == null) || (sessionid == 'pipe'))) { broadcastToRegisteredApps({ cmd: 'console', value: text }); }
4294
if (sessionid != 'pipe') { require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: text, sessionid: sessionid }); }
4295
}
4296
4297
+ // Send a mesh agent message to server, placing a bubble/badge on the agent device
4298
+ function sendAgentMessage(msg, icon)
4299
+ {
4300
+ if (sendAgentMessage.messages == null)
4301
+ {
4302
+ sendAgentMessage.messages = {};
4303
+ sendAgentMessage.nextid = 1;
4304
+ }
4305
+ sendAgentMessage.messages[sendAgentMessage.nextid++] = { msg: msg, icon: icon };
4306
+ require('MeshAgent').SendCommand({ action: 'sessions', type: 'msg', value: sendAgentMessage.messages });
4307
+ }
4308
+
4309
+ // Start a JavaScript based Agent Self-Update
4310
+ function agentUpdate_Start(updateurl, updateoptions)
4311
+ {
4312
+ // If this value is null
4313
+ var sessionid = updateoptions != null ? updateoptions.session : null; // If this is null, messages will be broadcast. Otherwise they will be unicasted
4314
+
4315
+ if (this._selfupdate != null)
4316
+ {
4317
+ // We were already called, so we will ignore this duplicate request
4318
+ if (sessionid != null) { sendConsoleText('Self update already in progress...', sessionid); }
4319
+ }
4320
+ else
4321
+ {
4322
+ if (require('MeshAgent').ARCHID == null && updateurl == null)
4323
+ {
4324
+ // This agent doesn't have the ability to tell us which ARCHID it is, so we don't know which agent to pull
4325
+ sendConsoleText('Unable to initiate update, agent ARCHID is not defined', sessionid);
4326
+ }
4327
+ else
4328
+ {
4329
+ var agentfilename = process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop(); // Local File Name, ie: MeshAgent.exe
4330
+ var name = require('MeshAgent').serviceName;
4331
+ 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
4332
+ try
4333
+ {
4334
+ var s = require('service-manager').manager.getService(name);
4335
+ if (!s.isMe())
4336
+ {
4337
+ if (process.platform == 'win32') { s.close(); }
4338
+ sendConsoleText('Self Update cannot continue, this agent is not an instance of (' + name + ')', sessionid);
4339
+ return;
4340
+ }
4341
+ if (process.platform == 'win32') { s.close(); }
4342
+ }
4343
+ catch (zz)
4344
+ {
4345
+ sendConsoleText('Self Update Failed because this agent is not an instance of (' + name + ')', sessionid);
4346
+ sendAgentMessage('Self Update Failed because this agent is not an instance of (' + name + ')', 3);
4347
+ return;
4348
+ }
4349
+
4350
+ sendConsoleText('Downloading update...', sessionid);
4351
+ var options = require('http').parseUri(updateurl != null ? updateurl : require('MeshAgent').ServerUrl);
4352
+ options.protocol = 'https:';
4353
+ if (updateurl == null) { options.path = ('/meshagents?id=' + require('MeshAgent').ARCHID); }
4354
+ options.rejectUnauthorized = false;
4355
+ options.checkServerIdentity = function checkServerIdentity(certs)
4356
+ {
4357
+ // If the tunnel certificate matches the control channel certificate, accept the connection
4358
+ try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { }
4359
+ try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { }
4360
+
4361
+ // Check that the certificate is the one expected by the server, fail if not.
4362
+ if (checkServerIdentity.servertlshash == null)
4363
+ {
4364
+ sendConsoleText('Self Update failed, because the url cannot be verified', sessionid);
4365
+ sendAgentMessage('Self Update failed, because the url cannot be verified', 3);
4366
+ throw new Error('BadCert');
4367
+ }
4368
+ if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash.toLowerCase() != certs[0].digest.split(':').join('').toLowerCase()))
4369
+ {
4370
+ sendConsoleText('Self Update failed, because the supplied certificate does not match', sessionid);
4371
+ sendAgentMessage('Self Update failed, because the supplied certificate does not match', 3);
4372
+ throw new Error('BadCert')
4373
+ }
4374
+ }
4375
+ options.checkServerIdentity.servertlshash = (updateoptions != null ? updateoptions.tlshash : null);
4376
+ this._selfupdate = require('https').get(options);
4377
+ this._selfupdate.on('error', function (e)
4378
+ {
4379
+ sendConsoleText('Self Update failed, because there was a problem trying to download the update', sessionid);
4380
+ sendAgentMessage('Self Update failed, because there was a problem trying to download the update', 3);
4381
+ });
4382
+ this._selfupdate.on('response', function (img)
4383
+ {
4384
+ this._file = require('fs').createWriteStream(agentfilename + '.update', { flags: 'wb' });
4385
+ this._filehash = require('SHA384Stream').create();
4386
+ this._filehash.on('hash', function (h)
4387
+ {
4388
+ if (updateoptions != null && updateoptions.hash != null)
4389
+ {
4390
+ if (updateoptions.hash.toLowerCase() == h.toString('hex').toLowerCase())
4391
+ {
4392
+ sendConsoleText('Download complete. HASH verified.', sessionid);
4393
+ }
4394
+ else
4395
+ {
4396
+ sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check', sessionid);
4397
+ sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check', 3);
4398
+ return;
4399
+ }
4400
+ }
4401
+ else
4402
+ {
4403
+ sendConsoleText('Download complete. HASH=' + h.toString('hex'), sessionid);
4404
+ }
4405
+
4406
+ sendConsoleText('Updating and restarting agent...', sessionid);
4407
+ if (process.platform == 'win32')
4408
+ {
4409
+ // Use _wexecve() equivalent to perform the update
4410
+ this.child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe',
4411
+ ['/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 });
4412
+ }
4413
+ else
4414
+ {
4415
+ // remove binary
4416
+ require('fs').unlinkSync(process.execPath);
4417
+
4418
+ // copy update
4419
+ require('fs').copyFileSync(process.cwd() + agentfilename + '.update', process.execPath);
4420
+
4421
+ // erase update
4422
+ require('fs').unlinkSync(process.cwd() + agentfilename + '.update');
4423
+
4424
+ // add execute permissions
4425
+ var m = require('fs').statSync(process.execPath).mode;
4426
+ m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP | require('fs').CHMOD_MODES.S_IXOTH);
4427
+ require('fs').chmodSync(process.execPath, m);
4428
+
4429
+ sendConsoleText('Restarting service...', sessionid);
4430
+ try
4431
+ {
4432
+ // restart service
4433
+ var s = require('service-manager').manager.getService(name);
4434
+ s.restart();
4435
+ }
4436
+ catch (zz)
4437
+ {
4438
+ sendConsoleText('Self Update encountered an error trying to restart service', sessionid);
4439
+ sendAgentMessage('Self Update encountered an error trying to restart service', 3);
4440
+ }
4441
+ }
4442
+ });
4443
+ img.pipe(this._file);
4444
+ img.pipe(this._filehash);
4445
+ });
4446
+ }
4447
+ }
4448
+ }
4449
+
4450
+
4451
+
4452
+
4453
// Called before the process exits
4454
//process.exit = function (code) { console.log("Exit with code: " + code.toString()); }
4455
4456
// Called when the server connection state changes
3913
- function handleServerConnection(state) {
4457
+ function handleServerConnection(state)
4458
+ {
4459
meshServerConnectionState = state;
3915
- if (meshServerConnectionState == 0) {
4460
+ if (meshServerConnectionState == 0)
4461
+ {
4462
// Server disconnected
4463
if (selfInfoUpdateTimer != null) { clearInterval(selfInfoUpdateTimer); selfInfoUpdateTimer = null; }
4464
lastSelfInfo = null;
3919
- } else {
4465
+ } else
4466
+ {
4467
// Server connected, send mesh core information
4468
var oldNodeId = db.Get('OldNodeId');
4469
if (oldNodeId != null) { mesh.SendCommand({ action: 'mc1migration', oldnodeid: oldNodeId }); }
@@ -3931,10 +4478,11 @@ function createMeshCore(agent) {
4478
{
4479
selfInfoUpdateTimer = setInterval(sendPeriodicServerUpdate, 1200000); // 20 minutes
4480
selfInfoUpdateTimer.metadata = 'meshcore (InfoUpdate Timer)';
3934
- }
4481
+ }
4482
4483
// Send any state messages
3937
- if (Object.keys(tunnelUserCount.msg).length > 0) {
4484
+ if (Object.keys(tunnelUserCount.msg).length > 0)
4485
+ {
4486
try { mesh.SendCommand({ action: 'sessions', type: 'msg', value: tunnelUserCount.msg }); } catch (e) { }
4487
broadcastSessionsToRegisteredApps();
4488
}
@@ -3950,12 +4498,14 @@ function createMeshCore(agent) {
4498
// Update the server with the latest network interface information
4499
var sendNetworkUpdateNagleTimer = null;
4500
function sendNetworkUpdateNagle() { if (sendNetworkUpdateNagleTimer != null) { clearTimeout(sendNetworkUpdateNagleTimer); sendNetworkUpdateNagleTimer = null; } sendNetworkUpdateNagleTimer = setTimeout(sendNetworkUpdate, 5000); }
3953
- function sendNetworkUpdate(force) {
4501
+ function sendNetworkUpdate(force)
4502
+ {
4503
sendNetworkUpdateNagleTimer = null;
4504
4505
// Update the network interfaces information data
4506
var netInfo = { netif2: require('os').networkInterfaces() };
3958
- if (netInfo.netif2) {
4507
+ if (netInfo.netif2)
4508
+ {
4509
netInfo.action = 'netinfo';
4510
var netInfoStr = JSON.stringify(netInfo);
4511
if ((force == true) || (clearGatewayMac(netInfoStr) != clearGatewayMac(lastNetworkInfo))) { mesh.SendCommand(netInfo); lastNetworkInfo = netInfoStr; }
@@ -3963,14 +4513,17 @@ function createMeshCore(agent) {
4513
}
4514
4515
// Called periodically to check if we need to send updates to the server
3966
- function sendPeriodicServerUpdate(flags, force) {
4516
+ function sendPeriodicServerUpdate(flags, force)
4517
+ {
4518
if (meshServerConnectionState == 0) return; // Not connected to server, do nothing.
4519
if (!flags) { flags = 0xFFFFFFFF; }
4520
4521
// If we have a connected MEI, get Intel ME information
3971
- if ((flags & 1) && (amt != null) && (amt.state == 2)) {
4522
+ if ((flags & 1) && (amt != null) && (amt.state == 2))
4523
+ {
4524
delete meshCoreObj.intelamt;
3973
- amt.getMeiState(9, function (meinfo) {
4525
+ amt.getMeiState(9, function (meinfo)
4526
+ {
4527
meshCoreObj.intelamt = meinfo;
4528
meshCoreObj.intelamt.microlms = amt.lmsstate;
4529
meshCoreObjChanged();
@@ -3981,17 +4534,20 @@ function createMeshCore(agent) {
4534
if (flags & 2) { sendNetworkUpdateNagle(false); }
4535
4536
// Update anti-virus information
3984
- if ((flags & 4) && (process.platform == 'win32')) {
4537
+ if ((flags & 4) && (process.platform == 'win32'))
4538
+ {
4539
// Windows Command: "wmic /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct get /FORMAT:CSV"
4540
try { meshCoreObj.av = require('win-info').av(); meshCoreObjChanged(); } catch (e) { av = null; } // Antivirus
4541
//if (process.platform == 'win32') { try { meshCoreObj.pr = require('win-info').pendingReboot(); meshCoreObjChanged(); } catch (e) { meshCoreObj.pr = null; } } // Pending reboot
4542
}
4543
4544
// Send available data right now
3991
- if (force) {
4545
+ if (force)
4546
+ {
4547
meshCoreObj = sortObjRec(meshCoreObj);
4548
var x = JSON.stringify(meshCoreObj);
3994
- if (x != LastPeriodicServerUpdate) {
4549
+ if (x != LastPeriodicServerUpdate)
4550
+ {
4551
LastPeriodicServerUpdate = x;
4552
mesh.SendCommand(meshCoreObj);
4553
}
@@ -4002,11 +4558,13 @@ function createMeshCore(agent) {
4558
var LastPeriodicServerUpdate = null;
4559
var PeriodicServerUpdateNagleTimer = null;
4560
function meshCoreObjChanged() { if (PeriodicServerUpdateNagleTimer == null) { PeriodicServerUpdateNagleTimer = setTimeout(meshCoreObjChangedEx, 500); } }
4005
- function meshCoreObjChangedEx() {
4561
+ function meshCoreObjChangedEx()
4562
+ {
4563
PeriodicServerUpdateNagleTimer = null;
4564
meshCoreObj = sortObjRec(meshCoreObj);
4565
var x = JSON.stringify(meshCoreObj);
4009
- if (x != LastPeriodicServerUpdate) {
4566
+ if (x != LastPeriodicServerUpdate)
4567
+ {
4568
try { LastPeriodicServerUpdate = x; mesh.SendCommand(meshCoreObj); } catch (ex) { }
4569
}
4570
}
@@ -4015,13 +4573,15 @@ function createMeshCore(agent) {
4573
function sortObj(o) { return Object.keys(o).sort().reduce(function (result, key) { result[key] = o[key]; return result; }, {}); }
4574
4575
// Starting function
4018
- obj.start = function () {
4576
+ obj.start = function ()
4577
+ {
4578
// Setup the mesh agent event handlers
4579
mesh.AddCommandHandler(handleServerCommand);
4580
mesh.AddConnectHandler(handleServerConnection);
4581
}
4582
4024
- obj.stop = function () {
4583
+ obj.stop = function ()
4584
+ {
4585
mesh.AddCommandHandler(null);
4586
mesh.AddConnectHandler(null);
4587
}
@@ -4030,7 +4590,8 @@ function createMeshCore(agent) {
4590
function onWebSocketData(data) { sendConsoleText("Got WebSocket #" + this.httprequest.index + " data: " + data, this.httprequest.sessionid); }
4591
function onWebSocketSendOk() { sendConsoleText("WebSocket #" + this.index + " SendOK.", this.sessionid); }
4592
4033
- function onWebSocketUpgrade(response, s, head) {
4593
+ function onWebSocketUpgrade(response, s, head)
4594
+ {
4595
sendConsoleText("WebSocket #" + this.index + " connected.", this.sessionid);
4596
this.s = s;
4597
s.httprequest = this;
@@ -4044,9 +4605,11 @@ function createMeshCore(agent) {
4605
//
4606
// Startup for Duktape only. This file is not intended to run in NodeJS.
4607
//
4047
-try {
4608
+try
4609
+{
4610
mainMeshCore = createMeshCore();
4611
mainMeshCore.start(null);
4050
-} catch (e) {
4612
+} catch (e)
4613
+{
4614
require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: "uncaughtException2: " + ex });
4615
}
agents/recoverycore.js
+28
-48
@@ -49,47 +49,48 @@ function sendAgentMessage(msg, icon)
49
require('MeshAgent').SendCommand({ action: 'sessions', type: 'msg', value: sendAgentMessage.messages });
50
}
51
52
+// Start a JavaScript based Agent Self-Update
53
function agentUpdate_Start(updateurl, updateoptions)
54
{
54
- var sessionid = updateoptions != null ? updateoptions.session : null;
55
+ // If this value is null
56
+ var sessionid = updateoptions != null ? updateoptions.session : null; // If this is null, messages will be broadcast. Otherwise they will be unicasted
57
58
if (this._selfupdate != null)
59
{
60
+ // We were already called, so we will ignore this duplicate request
61
if (sessionid != null) { sendConsoleText('Self update already in progress...', sessionid); }
62
}
63
else
64
{
65
if (require('MeshAgent').ARCHID == null && updateurl == null)
66
{
64
- if (sessionid != null) { sendConsoleText('Unable to initiate update, agent ARCHID is not defined', sessionid); }
67
+ // This agent doesn't have the ability to tell us which ARCHID it is, so we don't know which agent to pull
68
+ sendConsoleText('Unable to initiate update, agent ARCHID is not defined', sessionid);
69
}
70
else
71
{
68
- var agentfilename = process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop();
72
+ var agentfilename = process.execPath.split(process.platform == 'win32' ? '\\' : '/').pop(); // Local File Name, ie: MeshAgent.exe
73
var name = require('MeshAgent').serviceName;
70
- if (name == null) { name = process.platform == 'win32' ? 'Mesh Agent' : 'meshagent'; }
74
+ 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
75
try
76
{
77
var s = require('service-manager').manager.getService(name);
78
if (!s.isMe())
79
{
80
if (process.platform == 'win32') { s.close(); }
77
- if (sessionid != null) { sendConsoleText('Service check FAILED', sessionid); }
81
+ sendConsoleText('Self Update cannot continue, this agent is not an instance of (' + name + ')', sessionid);
82
return;
83
}
84
if (process.platform == 'win32') { s.close(); }
85
}
86
catch (zz)
87
{
84
- if (sessionid != null) { sendConsoleText('Service check FAILED', sessionid); }
85
- else
86
- {
87
- sendAgentMessage('Self Update Failed, because this agent is not running as a service', 3);
88
- }
88
+ sendConsoleText('Self Update Failed because this agent is not an instance of (' + name + ')', sessionid);
89
+ sendAgentMessage('Self Update Failed because this agent is not an instance of (' + name + ')', 3);
90
return;
91
}
92
92
- if (sessionid != null) { sendConsoleText('Downloading update...', sessionid); }
93
+ sendConsoleText('Downloading update...', sessionid);
94
var options = require('http').parseUri(updateurl != null ? updateurl : require('MeshAgent').ServerUrl);
95
options.protocol = 'https:';
96
if (updateurl == null) { options.path = ('/meshagents?id=' + require('MeshAgent').ARCHID); }
@@ -103,26 +104,14 @@ function agentUpdate_Start(updateurl, updateoptions)
104
// Check that the certificate is the one expected by the server, fail if not.
105
if (checkServerIdentity.servertlshash == null)
106
{
106
- if(sessionid!=null)
107
- {
108
- sendConsoleText('Self Update failed, because the url cannot be verified', sessionid);
109
- }
110
- else
111
- {
112
- sendAgentMessage('Self Update failed, because the url cannot be verified', 3);
113
- }
107
+ sendConsoleText('Self Update failed, because the url cannot be verified', sessionid);
108
+ sendAgentMessage('Self Update failed, because the url cannot be verified', 3);
109
throw new Error('BadCert');
110
}
111
if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash.toLowerCase() != certs[0].digest.split(':').join('').toLowerCase()))
112
{
118
- if (sessionid != null)
119
- {
120
- sendConsoleText('Self Update failed, because the supplied certificate does not match', sessionid);
121
- }
122
- else
123
- {
124
- sendAgentMessage('Self Update failed, because the supplied certificate does not match', 3);
125
- }
113
+ sendConsoleText('Self Update failed, because the supplied certificate does not match', sessionid);
114
+ sendAgentMessage('Self Update failed, because the supplied certificate does not match', 3);
115
throw new Error('BadCert')
116
}
117
}
@@ -130,11 +119,8 @@ function agentUpdate_Start(updateurl, updateoptions)
119
this._selfupdate = require('https').get(options);
120
this._selfupdate.on('error', function (e)
121
{
133
- if (sessionid != null) { sendConsoleText('Error fetching update', sessionid); }
134
- else
135
- {
136
- sendAgentMessage('Self Update failed, because there was a problem trying to download the update', 3);
137
- }
122
+ sendConsoleText('Self Update failed, because there was a problem trying to download the update', sessionid);
123
+ sendAgentMessage('Self Update failed, because there was a problem trying to download the update', 3);
124
});
125
this._selfupdate.on('response', function (img)
126
{
@@ -146,26 +132,24 @@ function agentUpdate_Start(updateurl, updateoptions)
132
{
133
if (updateoptions.hash.toLowerCase() == h.toString('hex').toLowerCase())
134
{
149
- if (sessionid != null) { sendConsoleText('Download complete. HASH verified.', sessionid); }
135
+ sendConsoleText('Download complete. HASH verified.', sessionid);
136
}
137
else
138
{
153
- if (sessionid != null) { sendConsoleText('Download complete. HASH FAILED.', sessionid); }
154
- else
155
- {
156
- sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check', 3);
157
- }
139
+ sendConsoleText('Self Update FAILED because the downloaded agent FAILED hash check', sessionid);
140
+ sendAgentMessage('Self Update FAILED because the downloaded agent FAILED hash check', 3);
141
return;
142
}
143
}
144
else
145
{
163
- if (sessionid != null) { sendConsoleText('Download complete. HASH=' + h.toString('hex'), sessionid); }
146
+ sendConsoleText('Download complete. HASH=' + h.toString('hex'), sessionid);
147
}
148
166
- if (sessionid != null) { sendConsoleText('Updating and restarting agent...', sessionid); }
149
+ sendConsoleText('Updating and restarting agent...', sessionid);
150
if (process.platform == 'win32')
151
{
152
+ // Use _wexecve() equivalent to perform the update
153
this.child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe',
154
['/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 });
155
}
@@ -185,7 +169,7 @@ function agentUpdate_Start(updateurl, updateoptions)
169
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP | require('fs').CHMOD_MODES.S_IXOTH);
170
require('fs').chmodSync(process.execPath, m);
171
188
- if (sessionid != null) { sendConsoleText('Restarting service...', sessionid); }
172
+ sendConsoleText('Restarting service...', sessionid);
173
try
174
{
175
// restart service
@@ -194,11 +178,8 @@ function agentUpdate_Start(updateurl, updateoptions)
178
}
179
catch (zz)
180
{
197
- if (sessionid != null) { sendConsoleText('Error restarting service', sessionid); }
198
- else
199
- {
200
- sendAgentMessage('Self Update encountered an error trying to restart service', 3);
201
- }
181
+ sendConsoleText('Self Update encountered an error trying to restart service', sessionid);
182
+ sendAgentMessage('Self Update encountered an error trying to restart service', 3);
183
}
184
}
185
});
@@ -209,7 +190,6 @@ function agentUpdate_Start(updateurl, updateoptions)
190
}
191
}
192
212
-
193
// Return p number of spaces
194
function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ret; } return r; }
195
@@ -643,7 +623,7 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
623
var response = null;
624
switch (cmd) {
625
case 'help':
646
- response = "Available commands are: osinfo, dbkeys, dbget, dbset, dbcompact, netinfo, versions, agentupdate.";
626
+ response = "Available commands are: agentupdate, dbkeys, dbget, dbset, dbcompact, netinfo, osinfo, versions.";
627
break;
628
case 'versions':
629
response = JSON.stringify(process.versions, null, ' ');