mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-23 14:01:43 +03:00
First working MacOS mesh agent
This commit is contained in:
parent
cf63f78564
commit
35245805fb
Binary file not shown.
@ -631,7 +631,7 @@ function createMeshCore(agent) {
|
|||||||
this.removeAllListeners('data');
|
this.removeAllListeners('data');
|
||||||
this.on('data', onTunnelControlData);
|
this.on('data', onTunnelControlData);
|
||||||
//this.write('MeshCore Terminal Hello');
|
//this.write('MeshCore Terminal Hello');
|
||||||
if (process.platform != 'win32') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nclear\n"); }
|
if (process.platform == 'linux') { this.httprequest.process.stdin.write("stty erase ^H\nalias ls='ls --color=auto'\nclear\n"); }
|
||||||
} else if (this.httprequest.protocol == 2)
|
} else if (this.httprequest.protocol == 2)
|
||||||
{
|
{
|
||||||
// Remote desktop using native pipes
|
// Remote desktop using native pipes
|
||||||
|
@ -187,9 +187,9 @@ function serviceHost(serviceName)
|
|||||||
console.log(e);
|
console.log(e);
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
if (process.platform == 'win32')
|
if (process.platform == 'win32' || process.platform == 'darwin')
|
||||||
{
|
{
|
||||||
// Only do this on Windows, becuase Linux is async... It'll complete later
|
// Only do this on Windows/MacOS, becuase Linux is async... It'll complete later
|
||||||
console.log(this._ServiceOptions.name + ' installed');
|
console.log(this._ServiceOptions.name + ' installed');
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
@ -207,9 +207,9 @@ function serviceHost(serviceName)
|
|||||||
console.log(e);
|
console.log(e);
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
if (process.platform == 'win32')
|
if (process.platform == 'win32' || process.platform == 'darwin')
|
||||||
{
|
{
|
||||||
// Only do this on Windows, becuase Linux is async... It'll complete later
|
// Only do this on Windows/MacOS, becuase Linux is async... It'll complete later
|
||||||
console.log(this._ServiceOptions.name + ' uninstalled');
|
console.log(this._ServiceOptions.name + ' uninstalled');
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
@ -251,26 +251,22 @@ function serviceHost(serviceName)
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (process.platform == 'linux')
|
||||||
|
{
|
||||||
var moduleName = this._ServiceOptions ? this._ServiceOptions.name : process.execPath.substring(1 + process.execPath.lastIndexOf('/'));
|
var moduleName = this._ServiceOptions ? this._ServiceOptions.name : process.execPath.substring(1 + process.execPath.lastIndexOf('/'));
|
||||||
|
|
||||||
for (var i = 0; i < process.argv.length; ++i)
|
for (var i = 0; i < process.argv.length; ++i) {
|
||||||
{
|
switch (process.argv[i]) {
|
||||||
switch(process.argv[i])
|
|
||||||
{
|
|
||||||
case 'start':
|
case 'start':
|
||||||
case '-d':
|
case '-d':
|
||||||
var child = require('child_process').execFile(process.execPath, [moduleName], { type: require('child_process').SpawnTypes.DETACHED });
|
var child = require('child_process').execFile(process.execPath, [moduleName], { type: require('child_process').SpawnTypes.DETACHED });
|
||||||
var pstream = null;
|
var pstream = null;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
pstream = require('fs').createWriteStream('/var/run/' + moduleName + '.pid', { flags: 'w' });
|
pstream = require('fs').createWriteStream('/var/run/' + moduleName + '.pid', { flags: 'w' });
|
||||||
}
|
}
|
||||||
catch(e)
|
catch (e) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
if (pstream == null)
|
if (pstream == null) {
|
||||||
{
|
|
||||||
pstream = require('fs').createWriteStream('.' + moduleName + '.pid', { flags: 'w' });
|
pstream = require('fs').createWriteStream('.' + moduleName + '.pid', { flags: 'w' });
|
||||||
}
|
}
|
||||||
pstream.end(child.pid.toString());
|
pstream.end(child.pid.toString());
|
||||||
@ -281,33 +277,26 @@ function serviceHost(serviceName)
|
|||||||
case 'stop':
|
case 'stop':
|
||||||
case '-s':
|
case '-s':
|
||||||
var pid = null;
|
var pid = null;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
pid = parseInt(require('fs').readFileSync('/var/run/' + moduleName + '.pid', { flags: 'r' }));
|
pid = parseInt(require('fs').readFileSync('/var/run/' + moduleName + '.pid', { flags: 'r' }));
|
||||||
require('fs').unlinkSync('/var/run/' + moduleName + '.pid');
|
require('fs').unlinkSync('/var/run/' + moduleName + '.pid');
|
||||||
}
|
}
|
||||||
catch(e)
|
catch (e) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
if(pid == null)
|
if (pid == null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
pid = parseInt(require('fs').readFileSync('.' + moduleName + '.pid', { flags: 'r' }));
|
pid = parseInt(require('fs').readFileSync('.' + moduleName + '.pid', { flags: 'r' }));
|
||||||
require('fs').unlinkSync('.' + moduleName + '.pid');
|
require('fs').unlinkSync('.' + moduleName + '.pid');
|
||||||
}
|
}
|
||||||
catch(e)
|
catch (e) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pid)
|
if (pid) {
|
||||||
{
|
|
||||||
process.kill(pid);
|
process.kill(pid);
|
||||||
console.log(moduleName + ' stopped');
|
console.log(moduleName + ' stopped');
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
console.log(moduleName + ' not running');
|
console.log(moduleName + ' not running');
|
||||||
}
|
}
|
||||||
process.exit();
|
process.exit();
|
||||||
@ -315,56 +304,42 @@ function serviceHost(serviceName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(serviceOperation == 0)
|
if (serviceOperation == 0) {
|
||||||
{
|
|
||||||
// This is non-windows, so we need to check how this binary was started to determine if this was a service start
|
// This is non-windows, so we need to check how this binary was started to determine if this was a service start
|
||||||
|
|
||||||
// Start by checking if we were started with start/stop
|
// Start by checking if we were started with start/stop
|
||||||
var pid = null;
|
var pid = null;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
pid = parseInt(require('fs').readFileSync('/var/run/' + moduleName + '.pid', { flags: 'r' }));
|
pid = parseInt(require('fs').readFileSync('/var/run/' + moduleName + '.pid', { flags: 'r' }));
|
||||||
}
|
}
|
||||||
catch (e)
|
catch (e) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
if (pid == null)
|
if (pid == null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
pid = parseInt(require('fs').readFileSync('.' + moduleName + '.pid', { flags: 'r' }));
|
pid = parseInt(require('fs').readFileSync('.' + moduleName + '.pid', { flags: 'r' }));
|
||||||
}
|
}
|
||||||
catch (e)
|
catch (e) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid != null && pid == process.pid)
|
if (pid != null && pid == process.pid) {
|
||||||
{
|
|
||||||
this.emit('serviceStart');
|
this.emit('serviceStart');
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
// Now we need to check if we were started with systemd
|
// Now we need to check if we were started with systemd
|
||||||
if (require('process-manager').getProcessInfo(1).Name == 'systemd')
|
if (require('process-manager').getProcessInfo(1).Name == 'systemd') {
|
||||||
{
|
|
||||||
this._checkpid = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
this._checkpid = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||||
this._checkpid.result = '';
|
this._checkpid.result = '';
|
||||||
this._checkpid.parent = this;
|
this._checkpid.parent = this;
|
||||||
this._checkpid.on('exit', function onCheckPIDExit()
|
this._checkpid.on('exit', function onCheckPIDExit() {
|
||||||
{
|
|
||||||
var lines = this.result.split('\r\n');
|
var lines = this.result.split('\r\n');
|
||||||
for (i in lines)
|
for (i in lines) {
|
||||||
{
|
if (lines[i].startsWith(' Main PID:')) {
|
||||||
if(lines[i].startsWith(' Main PID:'))
|
|
||||||
{
|
|
||||||
var tokens = lines[i].split(' ');
|
var tokens = lines[i].split(' ');
|
||||||
if (parseInt(tokens[3]) == process.pid)
|
if (parseInt(tokens[3]) == process.pid) {
|
||||||
{
|
|
||||||
this.parent.emit('serviceStart');
|
this.parent.emit('serviceStart');
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
this.parent.emit('normalStart');
|
this.parent.emit('normalStart');
|
||||||
}
|
}
|
||||||
delete this.parent._checkpid;
|
delete this.parent._checkpid;
|
||||||
@ -378,13 +353,41 @@ function serviceHost(serviceName)
|
|||||||
this._checkpid.stdin.write("systemctl status " + moduleName + " | grep 'Main PID:'\n");
|
this._checkpid.stdin.write("systemctl status " + moduleName + " | grep 'Main PID:'\n");
|
||||||
this._checkpid.stdin.write('exit\n');
|
this._checkpid.stdin.write('exit\n');
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
// This isn't even a systemd platform, so this couldn't have been a service start
|
// This isn't even a systemd platform, so this couldn't have been a service start
|
||||||
this.emit('normalStart');
|
this.emit('normalStart');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if(process.platform == 'darwin')
|
||||||
|
{
|
||||||
|
// First let's fetch all the PIDs of running services
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('launchctl list\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var tokens, i;
|
||||||
|
var p = {};
|
||||||
|
for (i = 1; i < lines.length; ++i)
|
||||||
|
{
|
||||||
|
tokens = lines[i].split('\t');
|
||||||
|
if (tokens[0] && tokens[0] != '-') { p[tokens[0]] = tokens[0]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p[process.pid.toString()])
|
||||||
|
{
|
||||||
|
// We are a service!
|
||||||
|
this.emit('serviceStart');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.emit('normalStart');
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,6 +214,13 @@ function serviceManager()
|
|||||||
throw ('could not find service: ' + name);
|
throw ('could not find service: ' + name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.isAdmin = function isAdmin()
|
||||||
|
{
|
||||||
|
return (require('user-sessions').isRoot());
|
||||||
|
}
|
||||||
|
}
|
||||||
this.installService = function installService(options)
|
this.installService = function installService(options)
|
||||||
{
|
{
|
||||||
if (process.platform == 'win32')
|
if (process.platform == 'win32')
|
||||||
@ -273,6 +280,8 @@ function serviceManager()
|
|||||||
}
|
}
|
||||||
if(process.platform == 'linux')
|
if(process.platform == 'linux')
|
||||||
{
|
{
|
||||||
|
if (!this.isAdmin()) { throw ('Installing as Service, requires root'); }
|
||||||
|
|
||||||
switch (this.getServiceType())
|
switch (this.getServiceType())
|
||||||
{
|
{
|
||||||
case 'init':
|
case 'init':
|
||||||
@ -311,14 +320,70 @@ function serviceManager()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(process.platform == 'darwin')
|
||||||
|
{
|
||||||
|
if (!this.isAdmin()) { throw ('Installing as Service, requires root'); }
|
||||||
|
|
||||||
|
// Mac OS
|
||||||
|
var stdoutpath = (options.stdout ? ('<key>StandardOutPath</key>\n<string>' + options.stdout + '</string>') : '');
|
||||||
|
var autoStart = (options.startType == 'AUTO_START' ? '<true/>' : '<false/>');
|
||||||
|
var params = ' <key>ProgramArguments</key>\n';
|
||||||
|
params += ' <array>\n';
|
||||||
|
params += (' <string>/usr/local/mesh_services/' + options.name + '/' + options.name + '</string>\n');
|
||||||
|
if(options.parameters)
|
||||||
|
{
|
||||||
|
for(var itm in options.parameters)
|
||||||
|
{
|
||||||
|
params += (' <string>' + options.parameters[itm] + '</string>\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
params += ' </array>\n';
|
||||||
|
|
||||||
|
var plist = '<?xml version="1.0" encoding="UTF-8"?>\n';
|
||||||
|
plist += '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n';
|
||||||
|
plist += '<plist version="1.0">\n';
|
||||||
|
plist += ' <dict>\n';
|
||||||
|
plist += ' <key>Label</key>\n';
|
||||||
|
plist += (' <string>' + options.name + '</string>\n');
|
||||||
|
plist += (params + '\n');
|
||||||
|
plist += ' <key>WorkingDirectory</key>\n';
|
||||||
|
plist += (' <string>/usr/local/mesh_services/' + options.name + '</string>\n');
|
||||||
|
plist += (stdoutpath + '\n');
|
||||||
|
plist += ' <key>RunAtLoad</key>\n';
|
||||||
|
plist += (autoStart + '\n');
|
||||||
|
plist += ' </dict>\n';
|
||||||
|
plist += '</plist>';
|
||||||
|
|
||||||
|
if (!require('fs').existsSync('/usr/local/mesh_services')) { require('fs').mkdirSync('/usr/local/mesh_services'); }
|
||||||
|
if (!require('fs').existsSync('/Library/LaunchDaemons/' + options.name + '.plist'))
|
||||||
|
{
|
||||||
|
if (!require('fs').existsSync('/usr/local/mesh_services/' + options.name)) { require('fs').mkdirSync('/usr/local/mesh_services/' + options.name); }
|
||||||
|
if (options.binary)
|
||||||
|
{
|
||||||
|
require('fs').writeFileSync('/usr/local/mesh_services/' + options.name + '/' + options.name, options.binary);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
require('fs').copyFileSync(options.servicePath, '/usr/local/mesh_services/' + options.name + '/' + options.name);
|
||||||
|
}
|
||||||
|
require('fs').writeFileSync('/Library/LaunchDaemons/' + options.name + '.plist', plist);
|
||||||
|
var m = require('fs').statSync('/usr/local/mesh_services/' + options.name + '/' + options.name).mode;
|
||||||
|
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||||
|
require('fs').chmodSync('/usr/local/mesh_services/' + options.name + '/' + options.name, m);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw ('Service: ' + options.name + ' already exists');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.uninstallService = function uninstallService(name)
|
this.uninstallService = function uninstallService(name)
|
||||||
{
|
{
|
||||||
|
if (!this.isAdmin()) { throw ('Uninstalling a service, requires admin'); }
|
||||||
|
|
||||||
if (typeof (name) == 'object') { name = name.name; }
|
if (typeof (name) == 'object') { name = name.name; }
|
||||||
if (process.platform == 'win32')
|
if (process.platform == 'win32')
|
||||||
{
|
{
|
||||||
if (!this.isAdmin()) { throw ('Uninstalling a service, requires admin'); }
|
|
||||||
|
|
||||||
var service = this.getService(name);
|
var service = this.getService(name);
|
||||||
if (service.status.state == undefined || service.status.state == 'STOPPED')
|
if (service.status.state == undefined || service.status.state == 'STOPPED')
|
||||||
{
|
{
|
||||||
@ -388,6 +453,39 @@ function serviceManager()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(process.platform == 'darwin')
|
||||||
|
{
|
||||||
|
if (require('fs').existsSync('/Library/LaunchDaemons/' + name + '.plist'))
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.on('data', function (chunk) { });
|
||||||
|
child.stdin.write('launchctl stop ' + name + '\n');
|
||||||
|
child.stdin.write('launchctl unload /Library/LaunchDaemons/' + name + '.plist\n');
|
||||||
|
child.stdin.write('exit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('fs').unlinkSync('/usr/local/mesh_services/' + name + '/' + name);
|
||||||
|
require('fs').unlinkSync('/Library/LaunchDaemons/' + name + '.plist');
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
throw ('Error uninstalling service: ' + name + ' => ' + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('fs').rmdirSync('/usr/local/mesh_services/' + name);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw ('Service: ' + name + ' does not exist');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(process.platform == 'linux')
|
if(process.platform == 'linux')
|
||||||
{
|
{
|
||||||
|
@ -78,12 +78,20 @@ function UserSessions()
|
|||||||
this._marshal = require('_GenericMarshal');
|
this._marshal = require('_GenericMarshal');
|
||||||
this._kernel32 = this._marshal.CreateNativeProxy('Kernel32.dll');
|
this._kernel32 = this._marshal.CreateNativeProxy('Kernel32.dll');
|
||||||
this._kernel32.CreateMethod('GetLastError');
|
this._kernel32.CreateMethod('GetLastError');
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
this._wts = this._marshal.CreateNativeProxy('Wtsapi32.dll');
|
this._wts = this._marshal.CreateNativeProxy('Wtsapi32.dll');
|
||||||
this._wts.CreateMethod('WTSEnumerateSessionsA');
|
this._wts.CreateMethod('WTSEnumerateSessionsA');
|
||||||
this._wts.CreateMethod('WTSQuerySessionInformationA');
|
this._wts.CreateMethod('WTSQuerySessionInformationA');
|
||||||
this._wts.CreateMethod('WTSRegisterSessionNotification');
|
this._wts.CreateMethod('WTSRegisterSessionNotification');
|
||||||
this._wts.CreateMethod('WTSUnRegisterSessionNotification');
|
this._wts.CreateMethod('WTSUnRegisterSessionNotification');
|
||||||
this._wts.CreateMethod('WTSFreeMemory');
|
this._wts.CreateMethod('WTSFreeMemory');
|
||||||
|
}
|
||||||
|
catch(exc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
this._user32 = this._marshal.CreateNativeProxy('user32.dll');
|
this._user32 = this._marshal.CreateNativeProxy('user32.dll');
|
||||||
this._user32.CreateMethod('RegisterPowerSettingNotification');
|
this._user32.CreateMethod('RegisterPowerSettingNotification');
|
||||||
this._user32.CreateMethod('UnregisterPowerSettingNotification');
|
this._user32.CreateMethod('UnregisterPowerSettingNotification');
|
||||||
@ -203,7 +211,7 @@ function UserSessions()
|
|||||||
this.immediate = setImmediate(function (self)
|
this.immediate = setImmediate(function (self)
|
||||||
{
|
{
|
||||||
// Now that we have a window handle, we can register it to receive Windows Messages
|
// Now that we have a window handle, we can register it to receive Windows Messages
|
||||||
self.parent._wts.WTSRegisterSessionNotification(self.parent.hwnd, NOTIFY_FOR_ALL_SESSIONS);
|
if (self.parent._wts) { self.parent._wts.WTSRegisterSessionNotification(self.parent.hwnd, NOTIFY_FOR_ALL_SESSIONS); }
|
||||||
self.parent._user32.ACDC_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_ACDC_POWER_SOURCE, 0);
|
self.parent._user32.ACDC_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_ACDC_POWER_SOURCE, 0);
|
||||||
self.parent._user32.BATT_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_BATTERY_PERCENTAGE_REMAINING, 0);
|
self.parent._user32.BATT_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_BATTERY_PERCENTAGE_REMAINING, 0);
|
||||||
self.parent._user32.DISP_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_CONSOLE_DISPLAY_STATE, 0);
|
self.parent._user32.DISP_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_CONSOLE_DISPLAY_STATE, 0);
|
||||||
@ -307,6 +315,38 @@ function UserSessions()
|
|||||||
{
|
{
|
||||||
this.user_session.emit('changed');
|
this.user_session.emit('changed');
|
||||||
});
|
});
|
||||||
|
this._users = function _users()
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('awk -F: \'($3 >= 0) {printf "%s:%s\\n", $1, $3}\' /etc/passwd\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var ret = {}, tokens;
|
||||||
|
for (var ln in lines)
|
||||||
|
{
|
||||||
|
tokens = lines[ln].split(':');
|
||||||
|
if (tokens[0]) { ret[tokens[0]] = tokens[1]; }
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
this._uids = function _uids() {
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('awk -F: \'($3 >= 0) {printf "%s:%s\\n", $1, $3}\' /etc/passwd\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var ret = {}, tokens;
|
||||||
|
for (var ln in lines) {
|
||||||
|
tokens = lines[ln].split(':');
|
||||||
|
if (tokens[0]) { ret[tokens[1]] = tokens[0]; }
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
this.Self = function Self()
|
this.Self = function Self()
|
||||||
{
|
{
|
||||||
var promise = require('promise');
|
var promise = require('promise');
|
||||||
@ -501,6 +541,43 @@ function UserSessions()
|
|||||||
}
|
}
|
||||||
else if(process.platform == 'darwin')
|
else if(process.platform == 'darwin')
|
||||||
{
|
{
|
||||||
|
this._users = function ()
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/usr/bin/dscl', ['dscl', '.', 'list', '/Users', 'UniqueID']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('exit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var tokens, i;
|
||||||
|
var users = {};
|
||||||
|
|
||||||
|
for (i = 0; i < lines.length; ++i) {
|
||||||
|
tokens = lines[i].split(' ');
|
||||||
|
if (tokens[0]) { users[tokens[0]] = tokens[tokens.length - 1]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return (users);
|
||||||
|
}
|
||||||
|
this._uids = function () {
|
||||||
|
var child = require('child_process').execFile('/usr/bin/dscl', ['dscl', '.', 'list', '/Users', 'UniqueID']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('exit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var tokens, i;
|
||||||
|
var users = {};
|
||||||
|
|
||||||
|
for (i = 0; i < lines.length; ++i) {
|
||||||
|
tokens = lines[i].split(' ');
|
||||||
|
if (tokens[0]) { users[tokens[tokens.length - 1]] = tokens[0]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return (users);
|
||||||
|
}
|
||||||
this._idTable = function()
|
this._idTable = function()
|
||||||
{
|
{
|
||||||
var table = {};
|
var table = {};
|
||||||
@ -559,6 +636,48 @@ function UserSessions()
|
|||||||
if (cb) { cb.call(this, users); }
|
if (cb) { cb.call(this, users); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(process.platform == 'linux' || process.platform == 'darwin')
|
||||||
|
{
|
||||||
|
this._self = function _self()
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/usr/bin/id', ['id', '-u']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.waitExit();
|
||||||
|
return (parseInt(child.stdout.str));
|
||||||
|
}
|
||||||
|
this.isRoot = function isRoot()
|
||||||
|
{
|
||||||
|
return (this._self() == 0);
|
||||||
|
}
|
||||||
|
this.consoleUid = function consoleUid()
|
||||||
|
{
|
||||||
|
var checkstr = process.platform == 'darwin' ? 'console' : ':0';
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('who\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var tokens, i, j;
|
||||||
|
for (i in lines)
|
||||||
|
{
|
||||||
|
tokens = lines[i].split(' ');
|
||||||
|
for (j = 1; j < tokens.length; ++j)
|
||||||
|
{
|
||||||
|
if (tokens[j].length > 0 && tokens[j] == checkstr)
|
||||||
|
{
|
||||||
|
return (parseInt(this._users()[tokens[0]]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw ('nobody logged into console');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
function showActiveOnly(source)
|
function showActiveOnly(source)
|
||||||
{
|
{
|
||||||
|
@ -78,12 +78,20 @@ function UserSessions()
|
|||||||
this._marshal = require('_GenericMarshal');
|
this._marshal = require('_GenericMarshal');
|
||||||
this._kernel32 = this._marshal.CreateNativeProxy('Kernel32.dll');
|
this._kernel32 = this._marshal.CreateNativeProxy('Kernel32.dll');
|
||||||
this._kernel32.CreateMethod('GetLastError');
|
this._kernel32.CreateMethod('GetLastError');
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
this._wts = this._marshal.CreateNativeProxy('Wtsapi32.dll');
|
this._wts = this._marshal.CreateNativeProxy('Wtsapi32.dll');
|
||||||
this._wts.CreateMethod('WTSEnumerateSessionsA');
|
this._wts.CreateMethod('WTSEnumerateSessionsA');
|
||||||
this._wts.CreateMethod('WTSQuerySessionInformationA');
|
this._wts.CreateMethod('WTSQuerySessionInformationA');
|
||||||
this._wts.CreateMethod('WTSRegisterSessionNotification');
|
this._wts.CreateMethod('WTSRegisterSessionNotification');
|
||||||
this._wts.CreateMethod('WTSUnRegisterSessionNotification');
|
this._wts.CreateMethod('WTSUnRegisterSessionNotification');
|
||||||
this._wts.CreateMethod('WTSFreeMemory');
|
this._wts.CreateMethod('WTSFreeMemory');
|
||||||
|
}
|
||||||
|
catch(exc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
this._user32 = this._marshal.CreateNativeProxy('user32.dll');
|
this._user32 = this._marshal.CreateNativeProxy('user32.dll');
|
||||||
this._user32.CreateMethod('RegisterPowerSettingNotification');
|
this._user32.CreateMethod('RegisterPowerSettingNotification');
|
||||||
this._user32.CreateMethod('UnregisterPowerSettingNotification');
|
this._user32.CreateMethod('UnregisterPowerSettingNotification');
|
||||||
@ -203,7 +211,7 @@ function UserSessions()
|
|||||||
this.immediate = setImmediate(function (self)
|
this.immediate = setImmediate(function (self)
|
||||||
{
|
{
|
||||||
// Now that we have a window handle, we can register it to receive Windows Messages
|
// Now that we have a window handle, we can register it to receive Windows Messages
|
||||||
self.parent._wts.WTSRegisterSessionNotification(self.parent.hwnd, NOTIFY_FOR_ALL_SESSIONS);
|
if (self.parent._wts) { self.parent._wts.WTSRegisterSessionNotification(self.parent.hwnd, NOTIFY_FOR_ALL_SESSIONS); }
|
||||||
self.parent._user32.ACDC_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_ACDC_POWER_SOURCE, 0);
|
self.parent._user32.ACDC_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_ACDC_POWER_SOURCE, 0);
|
||||||
self.parent._user32.BATT_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_BATTERY_PERCENTAGE_REMAINING, 0);
|
self.parent._user32.BATT_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_BATTERY_PERCENTAGE_REMAINING, 0);
|
||||||
self.parent._user32.DISP_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_CONSOLE_DISPLAY_STATE, 0);
|
self.parent._user32.DISP_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_CONSOLE_DISPLAY_STATE, 0);
|
||||||
@ -307,6 +315,38 @@ function UserSessions()
|
|||||||
{
|
{
|
||||||
this.user_session.emit('changed');
|
this.user_session.emit('changed');
|
||||||
});
|
});
|
||||||
|
this._users = function _users()
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('awk -F: \'($3 >= 0) {printf "%s:%s\\n", $1, $3}\' /etc/passwd\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var ret = {}, tokens;
|
||||||
|
for (var ln in lines)
|
||||||
|
{
|
||||||
|
tokens = lines[ln].split(':');
|
||||||
|
if (tokens[0]) { ret[tokens[0]] = tokens[1]; }
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
this._uids = function _uids() {
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('awk -F: \'($3 >= 0) {printf "%s:%s\\n", $1, $3}\' /etc/passwd\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var ret = {}, tokens;
|
||||||
|
for (var ln in lines) {
|
||||||
|
tokens = lines[ln].split(':');
|
||||||
|
if (tokens[0]) { ret[tokens[1]] = tokens[0]; }
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
this.Self = function Self()
|
this.Self = function Self()
|
||||||
{
|
{
|
||||||
var promise = require('promise');
|
var promise = require('promise');
|
||||||
@ -501,6 +541,43 @@ function UserSessions()
|
|||||||
}
|
}
|
||||||
else if(process.platform == 'darwin')
|
else if(process.platform == 'darwin')
|
||||||
{
|
{
|
||||||
|
this._users = function ()
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/usr/bin/dscl', ['dscl', '.', 'list', '/Users', 'UniqueID']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('exit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var tokens, i;
|
||||||
|
var users = {};
|
||||||
|
|
||||||
|
for (i = 0; i < lines.length; ++i) {
|
||||||
|
tokens = lines[i].split(' ');
|
||||||
|
if (tokens[0]) { users[tokens[0]] = tokens[tokens.length - 1]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return (users);
|
||||||
|
}
|
||||||
|
this._uids = function () {
|
||||||
|
var child = require('child_process').execFile('/usr/bin/dscl', ['dscl', '.', 'list', '/Users', 'UniqueID']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('exit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var tokens, i;
|
||||||
|
var users = {};
|
||||||
|
|
||||||
|
for (i = 0; i < lines.length; ++i) {
|
||||||
|
tokens = lines[i].split(' ');
|
||||||
|
if (tokens[0]) { users[tokens[tokens.length - 1]] = tokens[0]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return (users);
|
||||||
|
}
|
||||||
this._idTable = function()
|
this._idTable = function()
|
||||||
{
|
{
|
||||||
var table = {};
|
var table = {};
|
||||||
@ -559,6 +636,48 @@ function UserSessions()
|
|||||||
if (cb) { cb.call(this, users); }
|
if (cb) { cb.call(this, users); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(process.platform == 'linux' || process.platform == 'darwin')
|
||||||
|
{
|
||||||
|
this._self = function _self()
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/usr/bin/id', ['id', '-u']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.waitExit();
|
||||||
|
return (parseInt(child.stdout.str));
|
||||||
|
}
|
||||||
|
this.isRoot = function isRoot()
|
||||||
|
{
|
||||||
|
return (this._self() == 0);
|
||||||
|
}
|
||||||
|
this.consoleUid = function consoleUid()
|
||||||
|
{
|
||||||
|
var checkstr = process.platform == 'darwin' ? 'console' : ':0';
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = '';
|
||||||
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
||||||
|
child.stdin.write('who\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var lines = child.stdout.str.split('\n');
|
||||||
|
var tokens, i, j;
|
||||||
|
for (i in lines)
|
||||||
|
{
|
||||||
|
tokens = lines[i].split(' ');
|
||||||
|
for (j = 1; j < tokens.length; ++j)
|
||||||
|
{
|
||||||
|
if (tokens[j].length > 0 && tokens[j] == checkstr)
|
||||||
|
{
|
||||||
|
return (parseInt(this._users()[tokens[0]]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw ('nobody logged into console');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
function showActiveOnly(source)
|
function showActiveOnly(source)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "meshcentral",
|
"name": "meshcentral",
|
||||||
"version": "0.2.3-a",
|
"version": "0.2.3-c",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Remote Management",
|
"Remote Management",
|
||||||
"Intel AMT",
|
"Intel AMT",
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1936,6 +1936,10 @@
|
|||||||
for (var i in multiDesktop) {
|
for (var i in multiDesktop) {
|
||||||
// If a device is no longer viewed, disconnect it.
|
// If a device is no longer viewed, disconnect it.
|
||||||
if (multiDesktop[i].xxdelete == true) { multiDesktop[i].Stop(); delete multiDesktop[i]; }
|
if (multiDesktop[i].xxdelete == true) { multiDesktop[i].Stop(); delete multiDesktop[i]; }
|
||||||
|
else if (debugmode && multiDesktop[i].m && multiDesktop[i].m.onScreenSizeChange) {
|
||||||
|
// Adjust screen size change (JOKO) - This is not good.
|
||||||
|
multiDesktop[i].m.onScreenSizeChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
deskAdjust();
|
deskAdjust();
|
||||||
} else {
|
} else {
|
||||||
@ -2197,7 +2201,7 @@
|
|||||||
|
|
||||||
// OSX agent install
|
// OSX agent install
|
||||||
x += "<div id=agins_osx style=display:none>To add a new computer to device group \"" + EscapeHtml(mesh.name) + "\", download the mesh agent and install it the computer to manage. This agent installer has server and mesh information embedded within it.<br /><br />";
|
x += "<div id=agins_osx style=display:none>To add a new computer to device group \"" + EscapeHtml(mesh.name) + "\", download the mesh agent and install it the computer to manage. This agent installer has server and mesh information embedded within it.<br /><br />";
|
||||||
x += addHtmlValue('Mesh Agent', '<a href="meshosxagent?id=16&meshid=' + meshid.split('/')[2] + '" target="_blank" title="64bit version of OSX Mesh Agent">OSX Agent (64bit) - TEST BUILD</a>');
|
x += addHtmlValue('Mesh Agent', '<a href="meshosxagent?id=16&meshid=' + meshid.split('/')[2] + '" target="_blank" title="64bit version of OSX Mesh Agent">OSX Agent (64bit)</a>');
|
||||||
x += "</div>";
|
x += "</div>";
|
||||||
|
|
||||||
// Windows agent uninstall
|
// Windows agent uninstall
|
||||||
|
13
webserver.js
13
webserver.js
@ -1682,12 +1682,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
// Skip all folder entries
|
// Skip all folder entries
|
||||||
zipfile.readEntry();
|
zipfile.readEntry();
|
||||||
} else {
|
} else {
|
||||||
if (entry.fileName == 'Meshcentral_MeshAgent.mpkg/Contents/distribution.dist') {
|
if (entry.fileName == 'MeshAgent.mpkg/Contents/distribution.dist') {
|
||||||
// This is a special file entry, we need to fix it.
|
// This is a special file entry, we need to fix it.
|
||||||
zipfile.openReadStream(entry, function (err, readStream) {
|
zipfile.openReadStream(entry, function (err, readStream) {
|
||||||
readStream.on("data", function (data) { if (readStream.xxdata) { readStream.xxdata += data; } else { readStream.xxdata = data; } });
|
readStream.on("data", function (data) { if (readStream.xxdata) { readStream.xxdata += data; } else { readStream.xxdata = data; } });
|
||||||
readStream.on("end", function () {
|
readStream.on("end", function () {
|
||||||
var welcomemsg = 'Welcome to the MeshCentral agent for OSX\\\n\\\nThis installer will install the mesh agent for "' + mesh.name + '" and allow the administrator to remotely monitor and control this computer over the internet. For more information, go to info.meshcentral.com.\\\n\\\nThis software is provided under Apache 2.0 license.\\\n';
|
var meshname = mesh.name.split(']').join('').split('[').join(''); // We can't have ']]' in the string since it will terminate the CDATA.
|
||||||
|
var welcomemsg = 'Welcome to the MeshCentral agent for MacOS\n\nThis installer will install the mesh agent for "' + meshname + '" and allow the administrator to remotely monitor and control this computer over the internet. For more information, go to https://www.meshcommander.com/meshcentral2.\n\nThis software is provided under Apache 2.0 license.\n';
|
||||||
var installsize = Math.floor((argentInfo.size + meshsettings.length) / 1024);
|
var installsize = Math.floor((argentInfo.size + meshsettings.length) / 1024);
|
||||||
archive.append(readStream.xxdata.toString().split('###WELCOMEMSG###').join(welcomemsg).split('###INSTALLSIZE###').join(installsize), { name: entry.fileName });
|
archive.append(readStream.xxdata.toString().split('###WELCOMEMSG###').join(welcomemsg).split('###INSTALLSIZE###').join(installsize), { name: entry.fileName });
|
||||||
zipfile.readEntry();
|
zipfile.readEntry();
|
||||||
@ -1697,15 +1698,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
// Normal file entry
|
// Normal file entry
|
||||||
zipfile.openReadStream(entry, function (err, readStream) {
|
zipfile.openReadStream(entry, function (err, readStream) {
|
||||||
if (err) { throw err; }
|
if (err) { throw err; }
|
||||||
archive.append(readStream, { name: entry.fileName });
|
var options = { name: entry.fileName };
|
||||||
|
if (entry.fileName.endsWith('postflight') || entry.fileName.endsWith('Uninstall.command')) { options.mode = 493; }
|
||||||
|
archive.append(readStream, options);
|
||||||
readStream.on('end', function () { zipfile.readEntry(); });
|
readStream.on('end', function () { zipfile.readEntry(); });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
zipfile.on("end", function () {
|
zipfile.on("end", function () {
|
||||||
archive.file(argentInfo.path, { name: "Meshcentral_MeshAgent.mpkg/Contents/Packages/meshagentosx64.pkg/Contents/meshagent_osx64.bin" });
|
archive.file(argentInfo.path, { name: "MeshAgent.mpkg/Contents/Packages/internal.pkg/Contents/meshagent_osx64.bin" });
|
||||||
archive.append(meshsettings, { name: "Meshcentral_MeshAgent.mpkg/Contents/Packages/meshagentosx64.pkg/Contents/meshagent_osx64.msh" });
|
archive.append(meshsettings, { name: "MeshAgent.mpkg/Contents/Packages/internal.pkg/Contents/meshagent_osx64.msh" });
|
||||||
archive.finalize();
|
archive.finalize();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user