mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-02-12 11:01:52 +00:00
Completed first pass with JsHint, updated windows MeshAgent.
This commit is contained in:
parent
d48f24911a
commit
562310bed1
18 changed files with 664 additions and 435 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
185
agents/modules_meshcmd/promise.js
Normal file
185
agents/modules_meshcmd/promise.js
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 Intel Corporation
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var refTable = {};
|
||||||
|
|
||||||
|
function Promise(promiseFunc)
|
||||||
|
{
|
||||||
|
this._ObjectID = 'promise';
|
||||||
|
this._internal = { promise: this, func: promiseFunc, completed: false, errors: false, completedArgs: [] };
|
||||||
|
require('events').EventEmitter.call(this._internal);
|
||||||
|
this._internal.on('_eventHook', function (eventName, eventCallback)
|
||||||
|
{
|
||||||
|
//console.log('hook', eventName, 'errors/' + this.errors + ' completed/' + this.completed);
|
||||||
|
var r = null;
|
||||||
|
|
||||||
|
if (eventName == 'resolved' && !this.errors && this.completed)
|
||||||
|
{
|
||||||
|
r = eventCallback.apply(this, this.completedArgs);
|
||||||
|
if(r!=null)
|
||||||
|
{
|
||||||
|
this.emit_returnValue('resolved', r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (eventName == 'rejected' && this.errors && this.completed)
|
||||||
|
{
|
||||||
|
eventCallback.apply(this, this.completedArgs);
|
||||||
|
}
|
||||||
|
if (eventName == 'settled' && this.completed)
|
||||||
|
{
|
||||||
|
eventCallback.apply(this, []);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._internal.resolver = function _resolver()
|
||||||
|
{
|
||||||
|
_resolver._self.errors = false;
|
||||||
|
_resolver._self.completed = true;
|
||||||
|
_resolver._self.completedArgs = [];
|
||||||
|
var args = ['resolved'];
|
||||||
|
if (this.emit_returnValue && this.emit_returnValue('resolved') != null)
|
||||||
|
{
|
||||||
|
_resolver._self.completedArgs.push(this.emit_returnValue('resolved'));
|
||||||
|
args.push(this.emit_returnValue('resolved'));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (var a in arguments)
|
||||||
|
{
|
||||||
|
_resolver._self.completedArgs.push(arguments[a]);
|
||||||
|
args.push(arguments[a]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_resolver._self.emit.apply(_resolver._self, args);
|
||||||
|
_resolver._self.emit('settled');
|
||||||
|
};
|
||||||
|
this._internal.rejector = function _rejector()
|
||||||
|
{
|
||||||
|
_rejector._self.errors = true;
|
||||||
|
_rejector._self.completed = true;
|
||||||
|
_rejector._self.completedArgs = [];
|
||||||
|
var args = ['rejected'];
|
||||||
|
for (var a in arguments)
|
||||||
|
{
|
||||||
|
_rejector._self.completedArgs.push(arguments[a]);
|
||||||
|
args.push(arguments[a]);
|
||||||
|
}
|
||||||
|
|
||||||
|
_rejector._self.emit.apply(_rejector._self, args);
|
||||||
|
_rejector._self.emit('settled');
|
||||||
|
};
|
||||||
|
this.catch = function(func)
|
||||||
|
{
|
||||||
|
this._internal.once('settled', func);
|
||||||
|
}
|
||||||
|
this.finally = function (func)
|
||||||
|
{
|
||||||
|
this._internal.once('settled', func);
|
||||||
|
};
|
||||||
|
this.then = function (resolved, rejected)
|
||||||
|
{
|
||||||
|
if (resolved) { this._internal.once('resolved', resolved); }
|
||||||
|
if (rejected) { this._internal.once('rejected', rejected); }
|
||||||
|
|
||||||
|
var retVal = new Promise(function (r, j) { });
|
||||||
|
|
||||||
|
this._internal.once('resolved', retVal._internal.resolver);
|
||||||
|
this._internal.once('rejected', retVal._internal.rejector);
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
|
||||||
|
this._internal.resolver._self = this._internal;
|
||||||
|
this._internal.rejector._self = this._internal;;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
promiseFunc.call(this, this._internal.resolver, this._internal.rejector);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this._internal.errors = true;
|
||||||
|
this._internal.completed = true;
|
||||||
|
this._internal.completedArgs = [e];
|
||||||
|
this._internal.emit('rejected', e);
|
||||||
|
this._internal.emit('settled');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this._internal.completed)
|
||||||
|
{
|
||||||
|
// Save reference of this object
|
||||||
|
refTable[this._internal._hashCode()] = this._internal;
|
||||||
|
this._internal.once('settled', function () { refTable[this._hashCode()] = null; });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.resolve = function resolve()
|
||||||
|
{
|
||||||
|
var retVal = new Promise(function (r, j) { });
|
||||||
|
var args = [];
|
||||||
|
for (var i in arguments)
|
||||||
|
{
|
||||||
|
args.push(arguments[i]);
|
||||||
|
}
|
||||||
|
retVal._internal.resolver.apply(retVal._internal, args);
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
Promise.reject = function reject() {
|
||||||
|
var retVal = new Promise(function (r, j) { });
|
||||||
|
var args = [];
|
||||||
|
for (var i in arguments) {
|
||||||
|
args.push(arguments[i]);
|
||||||
|
}
|
||||||
|
retVal._internal.rejector.apply(retVal._internal, args);
|
||||||
|
return (retVal);
|
||||||
|
};
|
||||||
|
Promise.all = function all(promiseList)
|
||||||
|
{
|
||||||
|
var ret = new Promise(function (res, rej)
|
||||||
|
{
|
||||||
|
this.__rejector = rej;
|
||||||
|
this.__resolver = res;
|
||||||
|
this.__promiseList = promiseList;
|
||||||
|
this.__done = false;
|
||||||
|
this.__count = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i in promiseList)
|
||||||
|
{
|
||||||
|
promiseList[i].then(function ()
|
||||||
|
{
|
||||||
|
// Success
|
||||||
|
if(++ret.__count == ret.__promiseList.length)
|
||||||
|
{
|
||||||
|
ret.__done = true;
|
||||||
|
ret.__resolver(ret.__promiseList);
|
||||||
|
}
|
||||||
|
}, function (arg)
|
||||||
|
{
|
||||||
|
// Failure
|
||||||
|
if(!ret.__done)
|
||||||
|
{
|
||||||
|
ret.__done = true;
|
||||||
|
ret.__rejector(arg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (promiseList.length == 0)
|
||||||
|
{
|
||||||
|
ret.__resolver(promiseList);
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Promise;
|
|
@ -109,29 +109,16 @@ function serviceManager()
|
||||||
}
|
}
|
||||||
return admin;
|
return admin;
|
||||||
};
|
};
|
||||||
|
this.getProgramFolder = function getProgramFolder() {
|
||||||
|
if (require('os').arch() == 'x64') { // 64 bit Windows
|
||||||
|
if (this.GM.PointerSize == 4) { return process.env['ProgramFiles(x86)']; } // 32 Bit App
|
||||||
|
return process.env['ProgramFiles']; // 64 bit App
|
||||||
|
}
|
||||||
|
return process.env['ProgramFiles']; // 32 bit Windows
|
||||||
|
};
|
||||||
this.getServiceFolder = function getServiceFolder()
|
this.getServiceFolder = function getServiceFolder()
|
||||||
{
|
{
|
||||||
var destinationFolder = null;
|
return this.getProgramFolder() + '\\mesh';
|
||||||
if (require('os').arch() == 'x64')
|
|
||||||
{
|
|
||||||
// 64 bit Windows
|
|
||||||
if (this.GM.PointerSize == 4)
|
|
||||||
{
|
|
||||||
// 32 Bit App
|
|
||||||
destinationFolder = process.env['ProgramFiles(x86)'];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 64 bit App
|
|
||||||
destinationFolder = process.env['ProgramFiles'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 32 bit Windows
|
|
||||||
destinationFolder = process.env['ProgramFiles'];
|
|
||||||
}
|
|
||||||
return (destinationFolder + '\\mesh');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.enumerateService = function () {
|
this.enumerateService = function () {
|
||||||
|
|
182
meshcentral.js
182
meshcentral.js
|
@ -6,23 +6,29 @@
|
||||||
* @version v0.0.1
|
* @version v0.0.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
/*xjslint node: true */
|
||||||
|
/*xjslint plusplus: true */
|
||||||
|
/*xjslint maxlen: 256 */
|
||||||
|
/*jshint node: true */
|
||||||
|
/*jshint strict: false */
|
||||||
|
/*jshint esversion: 6 */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
// If app metrics is available
|
// If app metrics is available
|
||||||
if (process.argv[2] == '--launch') { try { require('appmetrics-dash').monitor({ url: '/', title: 'MeshCentral', port: 88, host: '127.0.0.1' }); } catch (e) { } }
|
if (process.argv[2] == '--launch') { try { require('appmetrics-dash').monitor({ url: '/', title: 'MeshCentral', port: 88, host: '127.0.0.1' }); } catch (e) { } }
|
||||||
|
|
||||||
function CreateMeshCentralServer(config, args) {
|
function CreateMeshCentralServer(config, args) {
|
||||||
var obj = {};
|
var obj = {};
|
||||||
obj.db;
|
obj.db = null;
|
||||||
obj.webserver;
|
obj.webserver = null;
|
||||||
obj.redirserver;
|
obj.redirserver = null;
|
||||||
obj.mpsserver;
|
obj.mpsserver = null;
|
||||||
obj.swarmserver;
|
obj.swarmserver = null;
|
||||||
obj.mailserver;
|
obj.mailserver = null;
|
||||||
obj.amtEventHandler;
|
obj.amtEventHandler = null;
|
||||||
obj.amtScanner;
|
obj.amtScanner = null;
|
||||||
obj.meshScanner;
|
obj.meshScanner = null;
|
||||||
obj.letsencrypt;
|
obj.letsencrypt = null;
|
||||||
obj.eventsDispatch = {};
|
obj.eventsDispatch = {};
|
||||||
obj.fs = require('fs');
|
obj.fs = require('fs');
|
||||||
obj.path = require('path');
|
obj.path = require('path');
|
||||||
|
@ -78,13 +84,14 @@ function CreateMeshCentralServer(config, args) {
|
||||||
|
|
||||||
// Start the Meshcentral server
|
// Start the Meshcentral server
|
||||||
obj.Start = function () {
|
obj.Start = function () {
|
||||||
|
var i;
|
||||||
try { require('./pass').hash('test', function () { }); } catch (e) { console.log('Old version of node, must upgrade.'); return; } // TODO: Not sure if this test works or not.
|
try { require('./pass').hash('test', function () { }); } catch (e) { console.log('Old version of node, must upgrade.'); return; } // TODO: Not sure if this test works or not.
|
||||||
|
|
||||||
// Check for invalid arguments
|
// Check for invalid arguments
|
||||||
var validArguments = ['_', 'notls', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'shownodes', 'showmeshes', 'showevents', 'showpower', 'clearpower', 'showiplocations', 'help', 'exactports', 'install', 'uninstall', 'start', 'stop', 'restart', 'debug', 'filespath', 'datapath', 'noagentupdate', 'launch', 'noserverbackup', 'mongodb', 'mongodbcol', 'wanonly', 'lanonly', 'nousers', 'mpsdebug', 'mpspass', 'ciralocalfqdn', 'dbexport', 'dbimport', 'selfupdate', 'tlsoffload', 'userallowedip', 'fastcert', 'swarmport', 'swarmdebug', 'logintoken', 'logintokenkey', 'logintokengen', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify'];
|
var validArguments = ['_', 'notls', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'shownodes', 'showmeshes', 'showevents', 'showpower', 'clearpower', 'showiplocations', 'help', 'exactports', 'install', 'uninstall', 'start', 'stop', 'restart', 'debug', 'filespath', 'datapath', 'noagentupdate', 'launch', 'noserverbackup', 'mongodb', 'mongodbcol', 'wanonly', 'lanonly', 'nousers', 'mpsdebug', 'mpspass', 'ciralocalfqdn', 'dbexport', 'dbimport', 'selfupdate', 'tlsoffload', 'userallowedip', 'fastcert', 'swarmport', 'swarmdebug', 'logintoken', 'logintokenkey', 'logintokengen', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify'];
|
||||||
for (var arg in obj.args) { obj.args[arg.toLocaleLowerCase()] = obj.args[arg]; if (validArguments.indexOf(arg.toLocaleLowerCase()) == -1) { console.log('Invalid argument "' + arg + '", use --help.'); return; } }
|
for (var arg in obj.args) { obj.args[arg.toLocaleLowerCase()] = obj.args[arg]; if (validArguments.indexOf(arg.toLocaleLowerCase()) == -1) { console.log('Invalid argument "' + arg + '", use --help.'); return; } }
|
||||||
if (obj.args.mongodb == true) { console.log('Must specify: --mongodb [connectionstring] \r\nSee https://docs.mongodb.com/manual/reference/connection-string/ for MongoDB connection string.'); return; }
|
if (obj.args.mongodb == true) { console.log('Must specify: --mongodb [connectionstring] \r\nSee https://docs.mongodb.com/manual/reference/connection-string/ for MongoDB connection string.'); return; }
|
||||||
for (var i in obj.config.settings) { obj.args[i] = obj.config.settings[i]; } // Place all settings into arguments, arguments have already been placed into settings so arguments take precedence.
|
for (i in obj.config.settings) { obj.args[i] = obj.config.settings[i]; } // Place all settings into arguments, arguments have already been placed into settings so arguments take precedence.
|
||||||
|
|
||||||
if ((obj.args.help == true) || (obj.args['?'] == true)) {
|
if ((obj.args.help == true) || (obj.args['?'] == true)) {
|
||||||
console.log('MeshCentral2 Beta 2, a web-based remote computer management web portal.\r\n');
|
console.log('MeshCentral2 Beta 2, a web-based remote computer management web portal.\r\n');
|
||||||
|
@ -106,19 +113,19 @@ function CreateMeshCentralServer(config, args) {
|
||||||
console.log(' country and organization can optionaly be set.');
|
console.log(' country and organization can optionaly be set.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we need to install, start, stop, remove ourself as a background service
|
// Check if we need to install, start, stop, remove ourself as a background service
|
||||||
if ((obj.service != null) && ((obj.args.install == true) || (obj.args.uninstall == true) || (obj.args.start == true) || (obj.args.stop == true) || (obj.args.restart == true))) {
|
if ((obj.service != null) && ((obj.args.install == true) || (obj.args.uninstall == true) || (obj.args.start == true) || (obj.args.stop == true) || (obj.args.restart == true))) {
|
||||||
var env = [], xenv = ['user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'exactport', 'debug'];
|
var env = [], xenv = ['user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'exactport', 'debug'];
|
||||||
for (var i in xenv) { if (obj.args[xenv[i]] != null) { env.push({ name: 'mesh' + xenv[i], value: obj.args[xenv[i]] }); } } // Set some args as service environement variables.
|
for (i in xenv) { if (obj.args[xenv[i]] != null) { env.push({ name: 'mesh' + xenv[i], value: obj.args[xenv[i]] }); } } // Set some args as service environement variables.
|
||||||
var svc = new obj.service({ name: 'MeshCentral', description: 'MeshCentral Remote Management Server', script: obj.path.join(__dirname, 'winservice.js'), env: env, wait: 2, grow: .5 });
|
var svc = new obj.service({ name: 'MeshCentral', description: 'MeshCentral Remote Management Server', script: obj.path.join(__dirname, 'winservice.js'), env: env, wait: 2, grow: 0.5 });
|
||||||
svc.on('install', function () { console.log('MeshCentral service installed.'); svc.start(); });
|
svc.on('install', function () { console.log('MeshCentral service installed.'); svc.start(); });
|
||||||
svc.on('uninstall', function () { console.log('MeshCentral service uninstalled.'); process.exit(); });
|
svc.on('uninstall', function () { console.log('MeshCentral service uninstalled.'); process.exit(); });
|
||||||
svc.on('start', function () { console.log('MeshCentral service started.'); process.exit(); });
|
svc.on('start', function () { console.log('MeshCentral service started.'); process.exit(); });
|
||||||
svc.on('stop', function () { console.log('MeshCentral service stopped.'); if (obj.args.stop) { process.exit(); } if (obj.args.restart) { console.log('Holding 5 seconds...'); setTimeout(function () { svc.start(); }, 5000); } });
|
svc.on('stop', function () { console.log('MeshCentral service stopped.'); if (obj.args.stop) { process.exit(); } if (obj.args.restart) { console.log('Holding 5 seconds...'); setTimeout(function () { svc.start(); }, 5000); } });
|
||||||
svc.on('alreadyinstalled', function () { console.log('MeshCentral service already installed.'); process.exit(); });
|
svc.on('alreadyinstalled', function () { console.log('MeshCentral service already installed.'); process.exit(); });
|
||||||
svc.on('invalidinstallation', function () { console.log('Invalid MeshCentral service installation.'); process.exit(); });
|
svc.on('invalidinstallation', function () { console.log('Invalid MeshCentral service installation.'); process.exit(); });
|
||||||
|
|
||||||
if (obj.args.install == true) { try { svc.install(); } catch (e) { logException(e); } }
|
if (obj.args.install == true) { try { svc.install(); } catch (e) { logException(e); } }
|
||||||
if (obj.args.stop == true || obj.args.restart == true) { try { svc.stop(); } catch (e) { logException(e); } }
|
if (obj.args.stop == true || obj.args.restart == true) { try { svc.stop(); } catch (e) { logException(e); } }
|
||||||
if (obj.args.start == true || obj.args.restart == true) { try { svc.start(); } catch (e) { logException(e); } }
|
if (obj.args.start == true || obj.args.restart == true) { try { svc.start(); } catch (e) { logException(e); } }
|
||||||
|
@ -132,7 +139,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
} else {
|
} else {
|
||||||
// if "--launch" is not specified, launch the server as a child process.
|
// if "--launch" is not specified, launch the server as a child process.
|
||||||
var startLine = '';
|
var startLine = '';
|
||||||
for (var i in process.argv) {
|
for (i in process.argv) {
|
||||||
var arg = process.argv[i];
|
var arg = process.argv[i];
|
||||||
if (arg.length > 0) {
|
if (arg.length > 0) {
|
||||||
if (startLine.length > 0) startLine += ' ';
|
if (startLine.length > 0) startLine += ' ';
|
||||||
|
@ -141,7 +148,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
}
|
}
|
||||||
obj.launchChildServer(startLine);
|
obj.launchChildServer(startLine);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Launch MeshCentral as a child server and monitor it.
|
// Launch MeshCentral as a child server and monitor it.
|
||||||
obj.launchChildServer = function (startLine) {
|
obj.launchChildServer = function (startLine) {
|
||||||
|
@ -166,7 +173,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
console.log('ERROR: MeshCentral failed with critical error, check MeshErrors.txt. Restarting in 5 seconds...');
|
console.log('ERROR: MeshCentral failed with critical error, check MeshErrors.txt. Restarting in 5 seconds...');
|
||||||
setTimeout(function () { obj.launchChildServer(startLine); }, 5000);
|
setTimeout(function () { obj.launchChildServer(startLine); }, 5000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
xprocess.stdout.on('data', function (data) { if (data[data.length - 1] == '\n') { data = data.substring(0, data.length - 1); } if (data.indexOf('Updating settings folder...') >= 0) { xprocess.xrestart = 1; } else if (data.indexOf('Updating server certificates...') >= 0) { xprocess.xrestart = 1; } else if (data.indexOf('Server Ctrl-C exit...') >= 0) { xprocess.xrestart = 2; } else if (data.indexOf('Starting self upgrade...') >= 0) { xprocess.xrestart = 3; } console.log(data); });
|
xprocess.stdout.on('data', function (data) { if (data[data.length - 1] == '\n') { data = data.substring(0, data.length - 1); } if (data.indexOf('Updating settings folder...') >= 0) { xprocess.xrestart = 1; } else if (data.indexOf('Updating server certificates...') >= 0) { xprocess.xrestart = 1; } else if (data.indexOf('Server Ctrl-C exit...') >= 0) { xprocess.xrestart = 2; } else if (data.indexOf('Starting self upgrade...') >= 0) { xprocess.xrestart = 3; } console.log(data); });
|
||||||
|
@ -175,7 +182,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
if (data[data.length - 1] == '\n') { data = data.substring(0, data.length - 1); } obj.fs.appendFileSync(obj.getConfigFilePath('mesherrors.txt'), '-------- ' + new Date().toLocaleString() + ' --------\r\n\r\n' + data + '\r\n\r\n\r\n');
|
if (data[data.length - 1] == '\n') { data = data.substring(0, data.length - 1); } obj.fs.appendFileSync(obj.getConfigFilePath('mesherrors.txt'), '-------- ' + new Date().toLocaleString() + ' --------\r\n\r\n' + data + '\r\n\r\n\r\n');
|
||||||
});
|
});
|
||||||
xprocess.on('close', function (code) { if ((code != 0) && (code != 123)) { /* console.log("Exited with code " + code); */ } });
|
xprocess.on('close', function (code) { if ((code != 0) && (code != 123)) { /* console.log("Exited with code " + code); */ } });
|
||||||
}
|
};
|
||||||
|
|
||||||
// Get current and latest MeshCentral server versions using NPM
|
// Get current and latest MeshCentral server versions using NPM
|
||||||
obj.getLatestServerVersion = function (callback) {
|
obj.getLatestServerVersion = function (callback) {
|
||||||
|
@ -190,44 +197,45 @@ function CreateMeshCentralServer(config, args) {
|
||||||
if (code == 0) { try { latestVer = xprocess.data.split(' ').join('').split('\r').join('').split('\n').join(''); } catch (e) { } }
|
if (code == 0) { try { latestVer = xprocess.data.split(' ').join('').split('\r').join('').split('\n').join(''); } catch (e) { } }
|
||||||
callback(obj.currentVer, latestVer);
|
callback(obj.currentVer, latestVer);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// Initiate server self-update
|
// Initiate server self-update
|
||||||
obj.performServerUpdate = function () { console.log('Starting self upgrade...'); process.exit(200); }
|
obj.performServerUpdate = function () { console.log('Starting self upgrade...'); process.exit(200); };
|
||||||
|
|
||||||
// Initiate server self-update
|
// Initiate server self-update
|
||||||
obj.performServerCertUpdate = function () { console.log('Updating server certificates...'); process.exit(200); }
|
obj.performServerCertUpdate = function () { console.log('Updating server certificates...'); process.exit(200); };
|
||||||
|
|
||||||
obj.StartEx = function () {
|
obj.StartEx = function () {
|
||||||
|
var i;
|
||||||
//var wincmd = require('node-windows');
|
//var wincmd = require('node-windows');
|
||||||
//wincmd.list(function (svc) { console.log(svc); }, true);
|
//wincmd.list(function (svc) { console.log(svc); }, true);
|
||||||
|
|
||||||
// Write the server state
|
// Write the server state
|
||||||
obj.updateServerState('state', 'starting');
|
obj.updateServerState('state', 'starting');
|
||||||
|
|
||||||
// Look to see if data and/or file path is specified
|
// Look to see if data and/or file path is specified
|
||||||
if (obj.args.datapath) { obj.datapath = obj.args.datapath; }
|
if (obj.args.datapath) { obj.datapath = obj.args.datapath; }
|
||||||
if (obj.args.filespath) { obj.filespath = obj.args.filespath; }
|
if (obj.args.filespath) { obj.filespath = obj.args.filespath; }
|
||||||
|
|
||||||
// Read environment variables. For a subset of arguments, we allow them to be read from environment variables.
|
// Read environment variables. For a subset of arguments, we allow them to be read from environment variables.
|
||||||
var xenv = ['user', 'port', 'mpsport', 'mpsaliasport', 'redirport', 'exactport', 'debug'];
|
var xenv = ['user', 'port', 'mpsport', 'mpsaliasport', 'redirport', 'exactport', 'debug'];
|
||||||
for (var i in xenv) { if ((obj.args[xenv[i]] == null) && (process.env['mesh' + xenv[i]])) { obj.args[xenv[i]] = obj.common.toNumber(process.env['mesh' + xenv[i]]); } }
|
for (i in xenv) { if ((obj.args[xenv[i]] == null) && (process.env['mesh' + xenv[i]])) { obj.args[xenv[i]] = obj.common.toNumber(process.env['mesh' + xenv[i]]); } }
|
||||||
|
|
||||||
// Validate the domains, this is used for multi-hosting
|
// Validate the domains, this is used for multi-hosting
|
||||||
if (obj.config.domains == null) { obj.config.domains = {}; }
|
if (obj.config.domains == null) { obj.config.domains = {}; }
|
||||||
if (obj.config.domains[''] == null) { obj.config.domains[''] = {}; }
|
if (obj.config.domains[''] == null) { obj.config.domains[''] = {}; }
|
||||||
if (obj.config.domains[''].dns != null) { console.log("ERROR: Default domain can't have a DNS name."); return; }
|
if (obj.config.domains[''].dns != null) { console.log("ERROR: Default domain can't have a DNS name."); return; }
|
||||||
var xdomains = {}; for (var i in obj.config.domains) { if (!obj.config.domains[i].title) { obj.config.domains[i].title = 'MeshCentral'; } if (!obj.config.domains[i].title2) { obj.config.domains[i].title2 = '2.0 Beta 2'; } xdomains[i.toLowerCase()] = obj.config.domains[i]; } obj.config.domains = xdomains;
|
var xdomains = {}; for (i in obj.config.domains) { if (!obj.config.domains[i].title) { obj.config.domains[i].title = 'MeshCentral'; } if (!obj.config.domains[i].title2) { obj.config.domains[i].title2 = '2.0 Beta 2'; } xdomains[i.toLowerCase()] = obj.config.domains[i]; } obj.config.domains = xdomains;
|
||||||
var bannedDomains = ['public', 'private', 'images', 'scripts', 'styles', 'views']; // List of banned domains
|
var bannedDomains = ['public', 'private', 'images', 'scripts', 'styles', 'views']; // List of banned domains
|
||||||
for (var i in obj.config.domains) { for (var j in bannedDomains) { if (i == bannedDomains[j]) { console.log("ERROR: Domain '" + i + "' is not allowed domain name in ./data/config.json."); return; } } }
|
for (i in obj.config.domains) { for (var j in bannedDomains) { if (i == bannedDomains[j]) { console.log("ERROR: Domain '" + i + "' is not allowed domain name in ./data/config.json."); return; } } }
|
||||||
for (var i in obj.config.domains) {
|
for (i in obj.config.domains) {
|
||||||
if (obj.config.domains[i].dns == null) { obj.config.domains[i].url = (i == '') ? '/' : ('/' + i + '/'); } else { obj.config.domains[i].url = '/'; }
|
if (obj.config.domains[i].dns == null) { obj.config.domains[i].url = (i == '') ? '/' : ('/' + i + '/'); } else { obj.config.domains[i].url = '/'; }
|
||||||
obj.config.domains[i].id = i;
|
obj.config.domains[i].id = i;
|
||||||
if (typeof obj.config.domains[i].userallowedip == 'string') { obj.config.domains[i].userallowedip = null; if (obj.config.domains[i].userallowedip != "") { obj.config.domains[i].userallowedip = obj.config.domains[i].userallowedip.split(','); } }
|
if (typeof obj.config.domains[i].userallowedip == 'string') { obj.config.domains[i].userallowedip = null; if (obj.config.domains[i].userallowedip != "") { obj.config.domains[i].userallowedip = obj.config.domains[i].userallowedip.split(','); } }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log passed arguments into Windows Service Log
|
// Log passed arguments into Windows Service Log
|
||||||
//if (obj.servicelog != null) { var s = ''; for (var i in obj.args) { if (i != '_') { if (s.length > 0) { s += ', '; } s += i + "=" + obj.args[i]; } } logInfoEvent('MeshServer started with arguments: ' + s); }
|
//if (obj.servicelog != null) { var s = ''; for (i in obj.args) { if (i != '_') { if (s.length > 0) { s += ', '; } s += i + "=" + obj.args[i]; } } logInfoEvent('MeshServer started with arguments: ' + s); }
|
||||||
|
|
||||||
// Look at passed in arguments
|
// Look at passed in arguments
|
||||||
if ((obj.args.user != null) && (typeof obj.args.user != 'string')) { delete obj.args.user; }
|
if ((obj.args.user != null) && (typeof obj.args.user != 'string')) { delete obj.args.user; }
|
||||||
|
@ -269,12 +277,12 @@ function CreateMeshCentralServer(config, args) {
|
||||||
if (obj.args.dbimport == true) { obj.args.dbimport = obj.getConfigFilePath('meshcentral.db.json'); }
|
if (obj.args.dbimport == true) { obj.args.dbimport = obj.getConfigFilePath('meshcentral.db.json'); }
|
||||||
var json = null, json2 = "", badCharCount = 0;
|
var json = null, json2 = "", badCharCount = 0;
|
||||||
try { json = obj.fs.readFileSync(obj.args.dbimport, { encoding: 'utf8' }); } catch (e) { console.log('Invalid JSON file: ' + obj.args.dbimport + '.'); process.exit(); }
|
try { json = obj.fs.readFileSync(obj.args.dbimport, { encoding: 'utf8' }); } catch (e) { console.log('Invalid JSON file: ' + obj.args.dbimport + '.'); process.exit(); }
|
||||||
for (var i = 0; i < json.length; i++) { if (json.charCodeAt(i) >= 32) { json2 += json[i]; } else { var tt = json.charCodeAt(i); if (tt != 10 && tt != 13) { badCharCount++; } } } // Remove all bad chars
|
for (i = 0; i < json.length; i++) { if (json.charCodeAt(i) >= 32) { json2 += json[i]; } else { var tt = json.charCodeAt(i); if (tt != 10 && tt != 13) { badCharCount++; } } } // Remove all bad chars
|
||||||
if (badCharCount > 0) { console.log(badCharCount + ' invalid character(s) where removed.'); }
|
if (badCharCount > 0) { console.log(badCharCount + ' invalid character(s) where removed.'); }
|
||||||
try { json = JSON.parse(json2); } catch (e) { console.log('Invalid JSON format: ' + obj.args.dbimport + ': ' + e); process.exit(); }
|
try { json = JSON.parse(json2); } catch (e) { console.log('Invalid JSON format: ' + obj.args.dbimport + ': ' + e); process.exit(); }
|
||||||
if ((json == null) || (typeof json.length != 'number') || (json.length < 1)) { console.log('Invalid JSON format: ' + obj.args.dbimport + '.'); }
|
if ((json == null) || (typeof json.length != 'number') || (json.length < 1)) { console.log('Invalid JSON format: ' + obj.args.dbimport + '.'); }
|
||||||
for (var i in json) { if ((json[i].type == "mesh") && (json[i].links != null)) { for (var j in json[i].links) { var esc = obj.common.escapeFieldName(j); if (esc !== j) { json[i].links[esc] = json[i].links[j]; delete json[i].links[j]; } } } } // Escape MongoDB invalid field chars
|
for (i in json) { if ((json[i].type == "mesh") && (json[i].links != null)) { for (var j in json[i].links) { var esc = obj.common.escapeFieldName(j); if (esc !== j) { json[i].links[esc] = json[i].links[j]; delete json[i].links[j]; } } } } // Escape MongoDB invalid field chars
|
||||||
//for (var i in json) { if ((json[i].type == "node") && (json[i].host != null)) { json[i].rname = json[i].host; delete json[i].host; } } // DEBUG: Change host to rname
|
//for (i in json) { if ((json[i].type == "node") && (json[i].host != null)) { json[i].rname = json[i].host; delete json[i].host; } } // DEBUG: Change host to rname
|
||||||
obj.db.RemoveAll(function () { obj.db.InsertMany(json, function (err) { if (err != null) { console.log(err); } else { console.log('Imported ' + json.length + ' objects(s) from ' + obj.args.dbimport + '.'); } process.exit(); }); });
|
obj.db.RemoveAll(function () { obj.db.InsertMany(json, function (err) { if (err != null) { console.log(err); } else { console.log('Imported ' + json.length + ' objects(s) from ' + obj.args.dbimport + '.'); } process.exit(); }); });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -333,7 +341,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
obj.db.Get('dbconfig', function (err, dbconfig) {
|
obj.db.Get('dbconfig', function (err, dbconfig) {
|
||||||
if (dbconfig.length == 1) { obj.dbconfig = dbconfig[0]; } else { obj.dbconfig = { _id: 'dbconfig', version: 1 }; }
|
if (dbconfig.length == 1) { obj.dbconfig = dbconfig[0]; } else { obj.dbconfig = { _id: 'dbconfig', version: 1 }; }
|
||||||
if (obj.dbconfig.amtWsEventSecret == null) { require('crypto').randomBytes(32, function (err, buf) { obj.dbconfig.amtWsEventSecret = buf.toString('hex'); obj.db.Set(obj.dbconfig); }); }
|
if (obj.dbconfig.amtWsEventSecret == null) { require('crypto').randomBytes(32, function (err, buf) { obj.dbconfig.amtWsEventSecret = buf.toString('hex'); obj.db.Set(obj.dbconfig); }); }
|
||||||
|
|
||||||
// This is used by the user to create a username/password for a Intel AMT WSMAN event subscription
|
// This is used by the user to create a username/password for a Intel AMT WSMAN event subscription
|
||||||
if (obj.args.getwspass) {
|
if (obj.args.getwspass) {
|
||||||
if (obj.args.getwspass.length == 64) {
|
if (obj.args.getwspass.length == 64) {
|
||||||
|
@ -367,12 +375,12 @@ function CreateMeshCentralServer(config, args) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// Done starting the redirection server, go on to load the server certificates
|
// Done starting the redirection server, go on to load the server certificates
|
||||||
obj.StartEx2 = function () {
|
obj.StartEx2 = function () {
|
||||||
// Load server certificates
|
// Load server certificates
|
||||||
obj.certificateOperations = require('./certoperations.js').CertificateOperations()
|
obj.certificateOperations = require('./certoperations.js').CertificateOperations();
|
||||||
obj.certificateOperations.GetMeshServerCertificate(obj, obj.args, obj.config, function (certs) {
|
obj.certificateOperations.GetMeshServerCertificate(obj, obj.args, obj.config, function (certs) {
|
||||||
if (obj.config.letsencrypt == null) {
|
if (obj.config.letsencrypt == null) {
|
||||||
obj.StartEx3(certs); // Just use the configured certificates
|
obj.StartEx3(certs); // Just use the configured certificates
|
||||||
|
@ -387,10 +395,11 @@ function CreateMeshCentralServer(config, args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// Start the server with the given certificates
|
// Start the server with the given certificates
|
||||||
obj.StartEx3 = function (certs) {
|
obj.StartEx3 = function (certs) {
|
||||||
|
var i;
|
||||||
obj.certificates = certs;
|
obj.certificates = certs;
|
||||||
obj.certificateOperations.acceleratorStart(certs); // Set the state of the accelerators
|
obj.certificateOperations.acceleratorStart(certs); // Set the state of the accelerators
|
||||||
|
|
||||||
|
@ -398,14 +407,14 @@ function CreateMeshCentralServer(config, args) {
|
||||||
if (obj.certificates.CommonName == 'un-configured') { console.log('Server name not configured, running in LAN-only mode.'); obj.args.lanonly = true; }
|
if (obj.certificates.CommonName == 'un-configured') { console.log('Server name not configured, running in LAN-only mode.'); obj.args.lanonly = true; }
|
||||||
|
|
||||||
// Check that no sub-domains have the same DNS as the parent
|
// Check that no sub-domains have the same DNS as the parent
|
||||||
for (var i in obj.config.domains) {
|
for (i in obj.config.domains) {
|
||||||
if ((obj.config.domains[i].dns != null) && (obj.certificates.CommonName.toLowerCase() === obj.config.domains[i].dns.toLowerCase())) {
|
if ((obj.config.domains[i].dns != null) && (obj.certificates.CommonName.toLowerCase() === obj.config.domains[i].dns.toLowerCase())) {
|
||||||
console.log("ERROR: Server sub-domain can't have same DNS name as the parent."); process.exit(0); return;
|
console.log("ERROR: Server sub-domain can't have same DNS name as the parent."); process.exit(0); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the list of mesh agents and install scripts
|
// Load the list of mesh agents and install scripts
|
||||||
if (obj.args.noagentupdate == 1) { for (var i in obj.meshAgentsArchitectureNumbers) { obj.meshAgentsArchitectureNumbers[i].update = false; } }
|
if (obj.args.noagentupdate == 1) { for (i in obj.meshAgentsArchitectureNumbers) { obj.meshAgentsArchitectureNumbers[i].update = false; } }
|
||||||
obj.updateMeshAgentsTable(function () {
|
obj.updateMeshAgentsTable(function () {
|
||||||
obj.updateMeshAgentInstallScripts();
|
obj.updateMeshAgentInstallScripts();
|
||||||
|
|
||||||
|
@ -460,7 +469,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
obj.maintenanceTimer = setInterval(obj.maintenanceActions, 1000 * 60 * 60); // Run this every hour
|
obj.maintenanceTimer = setInterval(obj.maintenanceActions, 1000 * 60 * 60); // Run this every hour
|
||||||
|
|
||||||
// Dispatch an event that the server is now running
|
// Dispatch an event that the server is now running
|
||||||
obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'started', msg: 'Server started' })
|
obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'started', msg: 'Server started' });
|
||||||
|
|
||||||
// Load the login cookie encryption key from the database if allowed
|
// Load the login cookie encryption key from the database if allowed
|
||||||
if ((obj.config) && (obj.config.settings) && (obj.config.settings.allowlogintoken == true)) {
|
if ((obj.config) && (obj.config.settings) && (obj.config.settings.allowlogintoken == true)) {
|
||||||
|
@ -473,12 +482,12 @@ function CreateMeshCentralServer(config, args) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.debug(1, 'Server started');
|
//obj.debug(1, 'Server started');
|
||||||
if (obj.args.nousers == true) { obj.updateServerState('nousers', '1'); }
|
if (obj.args.nousers == true) { obj.updateServerState('nousers', '1'); }
|
||||||
obj.updateServerState('state', 'running');
|
obj.updateServerState('state', 'running');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// Perform maintenance operations (called every hour)
|
// Perform maintenance operations (called every hour)
|
||||||
obj.maintenanceActions = function () {
|
obj.maintenanceActions = function () {
|
||||||
|
@ -499,7 +508,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
|
|
||||||
// Perform other database cleanup
|
// Perform other database cleanup
|
||||||
obj.db.cleanup();
|
obj.db.cleanup();
|
||||||
}
|
};
|
||||||
|
|
||||||
// Stop the Meshcentral server
|
// Stop the Meshcentral server
|
||||||
obj.Stop = function (restoreFile) {
|
obj.Stop = function (restoreFile) {
|
||||||
|
@ -507,7 +516,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
if (!obj.db) return;
|
if (!obj.db) return;
|
||||||
|
|
||||||
// Dispatch an event saying the server is now stopping
|
// Dispatch an event saying the server is now stopping
|
||||||
obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'stopped', msg: 'Server stopped' })
|
obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'stopped', msg: 'Server stopped' });
|
||||||
|
|
||||||
// Set all nodes to power state of unknown (0)
|
// Set all nodes to power state of unknown (0)
|
||||||
var record = { type: 'power', time: Date.now(), node: '*', power: 0, s: 2 };
|
var record = { type: 'power', time: Date.now(), node: '*', power: 0, s: 2 };
|
||||||
|
@ -543,7 +552,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
zipfile.on("end", function () { setTimeout(function () { fs.unlinkSync(restoreFile); process.exit(123); }); });
|
zipfile.on("end", function () { setTimeout(function () { obj.fs.unlinkSync(restoreFile); process.exit(123); }); });
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
obj.debug(1, 'Server stopped');
|
obj.debug(1, 'Server stopped');
|
||||||
|
@ -553,25 +562,25 @@ function CreateMeshCentralServer(config, args) {
|
||||||
|
|
||||||
// Update the server state
|
// Update the server state
|
||||||
obj.updateServerState('state', 'stopped');
|
obj.updateServerState('state', 'stopped');
|
||||||
}
|
};
|
||||||
|
|
||||||
// Event Dispatch
|
// Event Dispatch
|
||||||
obj.AddEventDispatch = function (ids, target) {
|
obj.AddEventDispatch = function (ids, target) {
|
||||||
obj.debug(3, 'AddEventDispatch', ids);
|
obj.debug(3, 'AddEventDispatch', ids);
|
||||||
for (var i in ids) { var id = ids[i]; if (!obj.eventsDispatch[id]) { obj.eventsDispatch[id] = [target]; } else { obj.eventsDispatch[id].push(target); } }
|
for (var i in ids) { var id = ids[i]; if (!obj.eventsDispatch[id]) { obj.eventsDispatch[id] = [target]; } else { obj.eventsDispatch[id].push(target); } }
|
||||||
}
|
};
|
||||||
obj.RemoveEventDispatch = function (ids, target) {
|
obj.RemoveEventDispatch = function (ids, target) {
|
||||||
obj.debug(3, 'RemoveEventDispatch', id);
|
obj.debug(3, 'RemoveEventDispatch', id);
|
||||||
for (var i in ids) { var id = ids[i]; if (obj.eventsDispatch[id]) { var j = obj.eventsDispatch[id].indexOf(target); if (j >= 0) { array.splice(j, 1); } } }
|
for (var i in ids) { var id = ids[i]; if (obj.eventsDispatch[id]) { var j = obj.eventsDispatch[id].indexOf(target); if (j >= 0) { obj.eventsDispatch[id].splice(j, 1); } } }
|
||||||
}
|
};
|
||||||
obj.RemoveEventDispatchId = function (id) {
|
obj.RemoveEventDispatchId = function (id) {
|
||||||
obj.debug(3, 'RemoveEventDispatchId', id);
|
obj.debug(3, 'RemoveEventDispatchId', id);
|
||||||
if (obj.eventsDispatch[id] != null) { delete obj.eventsDispatch[id]; }
|
if (obj.eventsDispatch[id] != null) { delete obj.eventsDispatch[id]; }
|
||||||
}
|
};
|
||||||
obj.RemoveAllEventDispatch = function (target) {
|
obj.RemoveAllEventDispatch = function (target) {
|
||||||
obj.debug(3, 'RemoveAllEventDispatch');
|
obj.debug(3, 'RemoveAllEventDispatch');
|
||||||
for (var i in obj.eventsDispatch) { var j = obj.eventsDispatch[i].indexOf(target); if (j >= 0) { obj.eventsDispatch[i].splice(j, 1); } }
|
for (var i in obj.eventsDispatch) { var j = obj.eventsDispatch[i].indexOf(target); if (j >= 0) { obj.eventsDispatch[i].splice(j, 1); } }
|
||||||
}
|
};
|
||||||
obj.DispatchEvent = function (ids, source, event, fromPeerServer) {
|
obj.DispatchEvent = function (ids, source, event, fromPeerServer) {
|
||||||
// If the database is not setup, exit now.
|
// If the database is not setup, exit now.
|
||||||
if (!obj.db) return;
|
if (!obj.db) return;
|
||||||
|
@ -596,21 +605,21 @@ function CreateMeshCentralServer(config, args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((fromPeerServer == null) && (obj.multiServer != null) && ((typeof event != 'object') || (event.nopeers != 1))) { obj.multiServer.DispatchEvent(ids, source, event); }
|
if ((fromPeerServer == null) && (obj.multiServer != null) && ((typeof event != 'object') || (event.nopeers != 1))) { obj.multiServer.DispatchEvent(ids, source, event); }
|
||||||
}
|
};
|
||||||
|
|
||||||
// Get the connection state of a node
|
// Get the connection state of a node
|
||||||
obj.GetConnectivityState = function (nodeid) { return obj.connectivityByNode[nodeid]; }
|
obj.GetConnectivityState = function (nodeid) { return obj.connectivityByNode[nodeid]; };
|
||||||
|
|
||||||
// Get the routing server id for a given node and connection type, can never be self.
|
// Get the routing server id for a given node and connection type, can never be self.
|
||||||
obj.GetRoutingServerId = function (nodeid, connectType) {
|
obj.GetRoutingServerId = function (nodeid, connectType) {
|
||||||
if (obj.multiServer == null) return null;
|
if (obj.multiServer == null) return null;
|
||||||
for (serverid in obj.peerConnectivityByNode) {
|
for (var serverid in obj.peerConnectivityByNode) {
|
||||||
if (serverid == obj.serverId) continue;
|
if (serverid == obj.serverId) continue;
|
||||||
var state = obj.peerConnectivityByNode[serverid][nodeid];
|
var state = obj.peerConnectivityByNode[serverid][nodeid];
|
||||||
if ((state != null) && ((state.connectivity & connectType) != 0)) { return { serverid: serverid, meshid: state.meshid }; }
|
if ((state != null) && ((state.connectivity & connectType) != 0)) { return { serverid: serverid, meshid: state.meshid }; }
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Update the connection state of a node when in multi-server mode
|
// Update the connection state of a node when in multi-server mode
|
||||||
// Update obj.connectivityByNode using obj.peerConnectivityByNode for the list of nodes in argument
|
// Update obj.connectivityByNode using obj.peerConnectivityByNode for the list of nodes in argument
|
||||||
|
@ -618,8 +627,8 @@ function CreateMeshCentralServer(config, args) {
|
||||||
for (var nodeid in nodeids) {
|
for (var nodeid in nodeids) {
|
||||||
var meshid = null, state = null, oldConnectivity = 0, oldPowerState = 0, newConnectivity = 0, newPowerState = 0;
|
var meshid = null, state = null, oldConnectivity = 0, oldPowerState = 0, newConnectivity = 0, newPowerState = 0;
|
||||||
var oldState = obj.connectivityByNode[nodeid];
|
var oldState = obj.connectivityByNode[nodeid];
|
||||||
if (oldState != null) { meshid = oldState.meshid; oldConnectivity = oldState.connectivity; oldPowerState = oldState.powerState; }
|
if (oldState != null) { meshid = oldState.meshid; oldConnectivity = oldState.connectivity; oldPowerState = oldState.powerState; }
|
||||||
for (serverid in obj.peerConnectivityByNode) {
|
for (var serverid in obj.peerConnectivityByNode) {
|
||||||
var peerState = obj.peerConnectivityByNode[serverid][nodeid];
|
var peerState = obj.peerConnectivityByNode[serverid][nodeid];
|
||||||
if (peerState != null) {
|
if (peerState != null) {
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
|
@ -652,7 +661,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
obj.DispatchEvent(['*', meshid], obj, { action: 'nodeconnect', meshid: meshid, nodeid: nodeid, conn: newConnectivity, pwr: newPowerState, nolog: 1, nopeers: 1 });
|
obj.DispatchEvent(['*', meshid], obj, { action: 'nodeconnect', meshid: meshid, nodeid: nodeid, conn: newConnectivity, pwr: newPowerState, nolog: 1, nopeers: 1 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Set the connectivity state of a node and setup the server so that messages can be routed correctly.
|
// Set the connectivity state of a node and setup the server so that messages can be routed correctly.
|
||||||
// meshId: mesh identifier of format mesh/domain/meshidhex
|
// meshId: mesh identifier of format mesh/domain/meshidhex
|
||||||
|
@ -660,8 +669,8 @@ function CreateMeshCentralServer(config, args) {
|
||||||
// connectTime: time of connection, milliseconds elapsed since the UNIX epoch.
|
// connectTime: time of connection, milliseconds elapsed since the UNIX epoch.
|
||||||
// connectType: Bitmask, 1 = MeshAgent, 2 = Intel AMT CIRA, 4 = Intel AMT local.
|
// connectType: Bitmask, 1 = MeshAgent, 2 = Intel AMT CIRA, 4 = Intel AMT local.
|
||||||
// powerState: Value, 0 = Unknown, 1 = S0 power on, 2 = S1 Sleep, 3 = S2 Sleep, 4 = S3 Sleep, 5 = S4 Hibernate, 6 = S5 Soft-Off, 7 = Present
|
// powerState: Value, 0 = Unknown, 1 = S0 power on, 2 = S1 Sleep, 3 = S2 Sleep, 4 = S3 Sleep, 5 = S4 Hibernate, 6 = S5 Soft-Off, 7 = Present
|
||||||
var connectTypeStrings = ['', 'MeshAgent', 'Intel AMT CIRA', '', 'Intel AMT local'];
|
//var connectTypeStrings = ['', 'MeshAgent', 'Intel AMT CIRA', '', 'Intel AMT local'];
|
||||||
var powerStateStrings = ['Unknown', 'Powered', 'Sleep', 'Sleep', 'Deep Sleep', 'Hibernating', 'Soft-Off', 'Present'];
|
//var powerStateStrings = ['Unknown', 'Powered', 'Sleep', 'Sleep', 'Deep Sleep', 'Hibernating', 'Soft-Off', 'Present'];
|
||||||
obj.SetConnectivityState = function (meshid, nodeid, connectTime, connectType, powerState, serverid) {
|
obj.SetConnectivityState = function (meshid, nodeid, connectTime, connectType, powerState, serverid) {
|
||||||
//console.log('SetConnectivity for ' + nodeid.substring(0, 16) + ', Type: ' + connectTypeStrings[connectType] + ', Power: ' + powerStateStrings[powerState] + (serverid == null ? ('') : (', ServerId: ' + serverid)));
|
//console.log('SetConnectivity for ' + nodeid.substring(0, 16) + ', Type: ' + connectTypeStrings[connectType] + ', Power: ' + powerStateStrings[powerState] + (serverid == null ? ('') : (', ServerId: ' + serverid)));
|
||||||
if ((serverid == null) && (obj.multiServer != null)) { obj.multiServer.DispatchMessage({ action: 'SetConnectivityState', meshid: meshid, nodeid: nodeid, connectTime: connectTime, connectType: connectType, powerState: powerState }); }
|
if ((serverid == null) && (obj.multiServer != null)) { obj.multiServer.DispatchMessage({ action: 'SetConnectivityState', meshid: meshid, nodeid: nodeid, connectTime: connectTime, connectType: connectType, powerState: powerState }); }
|
||||||
|
@ -716,7 +725,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
|
|
||||||
// Set node power state
|
// Set node power state
|
||||||
if (connectType == 1) { state.agentPower = powerState; } else if (connectType == 2) { state.ciraPower = powerState; } else if (connectType == 4) { state.amtPower = powerState; }
|
if (connectType == 1) { state.agentPower = powerState; } else if (connectType == 2) { state.ciraPower = powerState; } else if (connectType == 4) { state.amtPower = powerState; }
|
||||||
var powerState = 0;
|
var powerState = 0, oldPowerState = state.powerState;
|
||||||
if ((state.connectivity & 1) != 0) { powerState = state.agentPower; } else if ((state.connectivity & 2) != 0) { powerState = state.ciraPower; } else if ((state.connectivity & 4) != 0) { powerState = state.amtPower; }
|
if ((state.connectivity & 1) != 0) { powerState = state.agentPower; } else if ((state.connectivity & 2) != 0) { powerState = state.ciraPower; } else if ((state.connectivity & 4) != 0) { powerState = state.amtPower; }
|
||||||
if ((state.powerState == null) || (state.powerState != powerState)) {
|
if ((state.powerState == null) || (state.powerState != powerState)) {
|
||||||
state.powerState = powerState;
|
state.powerState = powerState;
|
||||||
|
@ -731,7 +740,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
var x = {}; x[nodeid] = 1;
|
var x = {}; x[nodeid] = 1;
|
||||||
obj.UpdateConnectivityState(x);
|
obj.UpdateConnectivityState(x);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Clear the connectivity state of a node and setup the server so that messages can be routed correctly.
|
// Clear the connectivity state of a node and setup the server so that messages can be routed correctly.
|
||||||
// meshId: mesh identifier of format mesh/domain/meshidhex
|
// meshId: mesh identifier of format mesh/domain/meshidhex
|
||||||
|
@ -798,7 +807,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
var x = {}; x[nodeid] = 1;
|
var x = {}; x[nodeid] = 1;
|
||||||
obj.UpdateConnectivityState(x);
|
obj.UpdateConnectivityState(x);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Update the default mesh core
|
// Update the default mesh core
|
||||||
obj.updateMeshCoreTimer = 'notset';
|
obj.updateMeshCoreTimer = 'notset';
|
||||||
|
@ -845,9 +854,9 @@ function CreateMeshCentralServer(config, args) {
|
||||||
obj.fs.watch(obj.path.join(meshcorePath, 'meshcore.js'), function (eventType, filename) {
|
obj.fs.watch(obj.path.join(meshcorePath, 'meshcore.js'), function (eventType, filename) {
|
||||||
if (obj.updateMeshCoreTimer != null) { clearTimeout(obj.updateMeshCoreTimer); obj.updateMeshCoreTimer = null; }
|
if (obj.updateMeshCoreTimer != null) { clearTimeout(obj.updateMeshCoreTimer); obj.updateMeshCoreTimer = null; }
|
||||||
obj.updateMeshCoreTimer = setTimeout(function () { obj.updateMeshCore(); console.log('Updated meshcore.js.'); }, 5000);
|
obj.updateMeshCoreTimer = setTimeout(function () { obj.updateMeshCore(); console.log('Updated meshcore.js.'); }, 5000);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Update the default meshcmd
|
// Update the default meshcmd
|
||||||
obj.updateMeshCmdTimer = 'notset';
|
obj.updateMeshCmdTimer = 'notset';
|
||||||
|
@ -860,7 +869,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
obj.defaultMeshCmd = null; if (func != null) { func(false); } // meshcmd.js not found
|
obj.defaultMeshCmd = null; if (func != null) { func(false); } // meshcmd.js not found
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read meshcore.js and all .js files in the modules folder.
|
// Read meshcore.js and all .js files in the modules folder.
|
||||||
var moduleAdditions = 'var addedModules = [];', modulesDir = null;
|
var moduleAdditions = 'var addedModules = [];', modulesDir = null;
|
||||||
var meshCmd = obj.fs.readFileSync(obj.path.join(meshcmdPath, 'meshcmd.js')).toString().replace("'***Mesh*Cmd*Version***'", '\'' + obj.currentVer + '\'');
|
var meshCmd = obj.fs.readFileSync(obj.path.join(meshcmdPath, 'meshcmd.js')).toString().replace("'***Mesh*Cmd*Version***'", '\'' + obj.currentVer + '\'');
|
||||||
|
@ -886,9 +895,9 @@ function CreateMeshCentralServer(config, args) {
|
||||||
obj.fs.watch(obj.path.join(meshcmdPath, 'meshcmd.js'), function (eventType, filename) {
|
obj.fs.watch(obj.path.join(meshcmdPath, 'meshcmd.js'), function (eventType, filename) {
|
||||||
if (obj.updateMeshCmdTimer != null) { clearTimeout(obj.updateMeshCmdTimer); obj.updateMeshCmdTimer = null; }
|
if (obj.updateMeshCmdTimer != null) { clearTimeout(obj.updateMeshCmdTimer); obj.updateMeshCmdTimer = null; }
|
||||||
obj.updateMeshCmdTimer = setTimeout(function () { obj.updateMeshCmd(); console.log('Updated meshcmd.js.'); }, 5000);
|
obj.updateMeshCmdTimer = setTimeout(function () { obj.updateMeshCmd(); console.log('Updated meshcmd.js.'); }, 5000);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// List of possible mesh agent install scripts
|
// List of possible mesh agent install scripts
|
||||||
var meshAgentsInstallScriptList = {
|
var meshAgentsInstallScriptList = {
|
||||||
|
@ -903,7 +912,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
var stream = null;
|
var stream = null;
|
||||||
try {
|
try {
|
||||||
stream = obj.fs.createReadStream(scriptpath);
|
stream = obj.fs.createReadStream(scriptpath);
|
||||||
stream.on('data', function (data) { this.hash.update(data, 'binary') });
|
stream.on('data', function (data) { this.hash.update(data, 'binary'); });
|
||||||
stream.on('error', function (data) {
|
stream.on('error', function (data) {
|
||||||
// If there is an error reading this file, make sure this agent is not in the agent table
|
// If there is an error reading this file, make sure this agent is not in the agent table
|
||||||
if (obj.meshAgentInstallScripts[this.info.id] != null) { delete obj.meshAgentInstallScripts[this.info.id]; }
|
if (obj.meshAgentInstallScripts[this.info.id] != null) { delete obj.meshAgentInstallScripts[this.info.id]; }
|
||||||
|
@ -915,7 +924,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
obj.meshAgentInstallScripts[this.info.id].path = this.agentpath;
|
obj.meshAgentInstallScripts[this.info.id].path = this.agentpath;
|
||||||
obj.meshAgentInstallScripts[this.info.id].url = ((obj.args.notls == true) ? 'http://' : 'https://') + obj.certificates.CommonName + ':' + obj.args.port + '/meshagents?script=' + this.info.id;
|
obj.meshAgentInstallScripts[this.info.id].url = ((obj.args.notls == true) ? 'http://' : 'https://') + obj.certificates.CommonName + ':' + obj.args.port + '/meshagents?script=' + this.info.id;
|
||||||
var stats = null;
|
var stats = null;
|
||||||
try { stats = obj.fs.statSync(this.agentpath) } catch (e) { }
|
try { stats = obj.fs.statSync(this.agentpath); } catch (e) { }
|
||||||
if (stats != null) { obj.meshAgentInstallScripts[this.info.id].size = stats.size; }
|
if (stats != null) { obj.meshAgentInstallScripts[this.info.id].size = stats.size; }
|
||||||
});
|
});
|
||||||
stream.info = meshAgentsInstallScriptList[scriptid];
|
stream.info = meshAgentsInstallScriptList[scriptid];
|
||||||
|
@ -923,7 +932,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
stream.hash = obj.crypto.createHash('sha384', stream);
|
stream.hash = obj.crypto.createHash('sha384', stream);
|
||||||
} catch (e) { }
|
} catch (e) { }
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// List of possible mesh agents
|
// List of possible mesh agents
|
||||||
obj.meshAgentsArchitectureNumbers = {
|
obj.meshAgentsArchitectureNumbers = {
|
||||||
|
@ -962,10 +971,10 @@ function CreateMeshCentralServer(config, args) {
|
||||||
var archcount = 0;
|
var archcount = 0;
|
||||||
for (var archid in obj.meshAgentsArchitectureNumbers) {
|
for (var archid in obj.meshAgentsArchitectureNumbers) {
|
||||||
var agentpath = obj.path.join(__dirname, 'agents', obj.meshAgentsArchitectureNumbers[archid].localname);
|
var agentpath = obj.path.join(__dirname, 'agents', obj.meshAgentsArchitectureNumbers[archid].localname);
|
||||||
|
|
||||||
// Fetch all the agent binary information
|
// Fetch all the agent binary information
|
||||||
var stats = null;
|
var stats = null;
|
||||||
try { stats = obj.fs.statSync(agentpath) } catch (e) { }
|
try { stats = obj.fs.statSync(agentpath); } catch (e) { }
|
||||||
if ((stats != null)) {
|
if ((stats != null)) {
|
||||||
// If file exists
|
// If file exists
|
||||||
archcount++;
|
archcount++;
|
||||||
|
@ -991,7 +1000,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
}
|
}
|
||||||
if ((obj.meshAgentBinaries[3] == null) && (obj.meshAgentBinaries[10003] != null)) { obj.meshAgentBinaries[3] = obj.meshAgentBinaries[10003]; } // If only the unsigned windows binaries are present, use them.
|
if ((obj.meshAgentBinaries[3] == null) && (obj.meshAgentBinaries[10003] != null)) { obj.meshAgentBinaries[3] = obj.meshAgentBinaries[10003]; } // If only the unsigned windows binaries are present, use them.
|
||||||
if ((obj.meshAgentBinaries[4] == null) && (obj.meshAgentBinaries[10004] != null)) { obj.meshAgentBinaries[4] = obj.meshAgentBinaries[10004]; } // If only the unsigned windows binaries are present, use them.
|
if ((obj.meshAgentBinaries[4] == null) && (obj.meshAgentBinaries[10004] != null)) { obj.meshAgentBinaries[4] = obj.meshAgentBinaries[10004]; } // If only the unsigned windows binaries are present, use them.
|
||||||
}
|
};
|
||||||
|
|
||||||
// Generate a time limited user login token
|
// Generate a time limited user login token
|
||||||
obj.getLoginToken = function (userid, func) {
|
obj.getLoginToken = function (userid, func) {
|
||||||
|
@ -1016,7 +1025,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// Show the yser login token generation key
|
// Show the yser login token generation key
|
||||||
obj.showLoginTokenKey = function (func) {
|
obj.showLoginTokenKey = function (func) {
|
||||||
|
@ -1031,13 +1040,13 @@ function CreateMeshCentralServer(config, args) {
|
||||||
obj.db.Set({ _id: 'LoginCookieEncryptionKey', key: obj.loginCookieEncryptionKey.toString('hex'), time: Date.now() }, function () { func(obj.loginCookieEncryptionKey.toString('hex')); });
|
obj.db.Set({ _id: 'LoginCookieEncryptionKey', key: obj.loginCookieEncryptionKey.toString('hex'), time: Date.now() }, function () { func(obj.loginCookieEncryptionKey.toString('hex')); });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// Generate a cryptographic key used to encode and decode cookies
|
// Generate a cryptographic key used to encode and decode cookies
|
||||||
obj.generateCookieKey = function () {
|
obj.generateCookieKey = function () {
|
||||||
return new Buffer(obj.crypto.randomBytes(32), 'binary');
|
return new Buffer(obj.crypto.randomBytes(32), 'binary');
|
||||||
//return Buffer.alloc(32, 0); // Sets the key to zeros, debug only.
|
//return Buffer.alloc(32, 0); // Sets the key to zeros, debug only.
|
||||||
}
|
};
|
||||||
|
|
||||||
// Encode an object as a cookie using a key. (key must be 32 bytes long)
|
// Encode an object as a cookie using a key. (key must be 32 bytes long)
|
||||||
obj.encodeCookie = function (o, key) {
|
obj.encodeCookie = function (o, key) {
|
||||||
|
@ -1048,7 +1057,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
var crypted = Buffer.concat([cipher.update(JSON.stringify(o), 'utf8'), cipher.final()]);
|
var crypted = Buffer.concat([cipher.update(JSON.stringify(o), 'utf8'), cipher.final()]);
|
||||||
return Buffer.concat([iv, cipher.getAuthTag(), crypted]).toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
return Buffer.concat([iv, cipher.getAuthTag(), crypted]).toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
||||||
} catch (e) { return null; }
|
} catch (e) { return null; }
|
||||||
}
|
};
|
||||||
|
|
||||||
// Decode a cookie back into an object using a key. Return null if it's not a valid cookie. (key must be 32 bytes long)
|
// Decode a cookie back into an object using a key. Return null if it's not a valid cookie. (key must be 32 bytes long)
|
||||||
obj.decodeCookie = function (cookie, key, timeout) {
|
obj.decodeCookie = function (cookie, key, timeout) {
|
||||||
|
@ -1065,7 +1074,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
if ((o.dtime > (timeout * 60000)) || (o.dtime < -30000)) return null; // The cookie is only valid 120 seconds, or 30 seconds back in time (in case other server's clock is not quite right)
|
if ((o.dtime > (timeout * 60000)) || (o.dtime < -30000)) return null; // The cookie is only valid 120 seconds, or 30 seconds back in time (in case other server's clock is not quite right)
|
||||||
return o;
|
return o;
|
||||||
} catch (e) { return null; }
|
} catch (e) { return null; }
|
||||||
}
|
};
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
obj.debug = function (lvl) {
|
obj.debug = function (lvl) {
|
||||||
|
@ -1074,11 +1083,11 @@ function CreateMeshCentralServer(config, args) {
|
||||||
else if (arguments.length == 3) { console.log(arguments[1], arguments[2]); }
|
else if (arguments.length == 3) { console.log(arguments[1], arguments[2]); }
|
||||||
else if (arguments.length == 4) { console.log(arguments[1], arguments[2], arguments[3]); }
|
else if (arguments.length == 4) { console.log(arguments[1], arguments[2], arguments[3]); }
|
||||||
else if (arguments.length == 5) { console.log(arguments[1], arguments[2], arguments[3], arguments[4]); }
|
else if (arguments.length == 5) { console.log(arguments[1], arguments[2], arguments[3], arguments[4]); }
|
||||||
}
|
};
|
||||||
|
|
||||||
// Update server state. Writes a server state file.
|
// Update server state. Writes a server state file.
|
||||||
var meshServerState = {};
|
var meshServerState = {};
|
||||||
obj.updateServerState = function(name, val) {
|
obj.updateServerState = function (name, val) {
|
||||||
if ((name != null) && (val != null)) {
|
if ((name != null) && (val != null)) {
|
||||||
var changed = false;
|
var changed = false;
|
||||||
if ((name != null) && (meshServerState[name] != val)) { if ((val == null) && (meshServerState[name] != null)) { delete meshServerState[name]; changed = true; } else { if (meshServerState[name] != val) { meshServerState[name] = val; changed = true; } } }
|
if ((name != null) && (meshServerState[name] != val)) { if ((val == null) && (meshServerState[name] != null)) { delete meshServerState[name]; changed = true; } else { if (meshServerState[name] != val) { meshServerState[name] = val; changed = true; } } }
|
||||||
|
@ -1087,7 +1096,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
var r = 'time=' + Date.now() + '\r\n';
|
var r = 'time=' + Date.now() + '\r\n';
|
||||||
for (var i in meshServerState) { r += (i + '=' + meshServerState[i] + '\r\n'); }
|
for (var i in meshServerState) { r += (i + '=' + meshServerState[i] + '\r\n'); }
|
||||||
obj.fs.writeFileSync(obj.getConfigFilePath('serverstate.txt'), r);
|
obj.fs.writeFileSync(obj.getConfigFilePath('serverstate.txt'), r);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Logging funtions
|
// Logging funtions
|
||||||
function logException(e) { e += ''; logErrorEvent(e); }
|
function logException(e) { e += ''; logErrorEvent(e); }
|
||||||
|
@ -1124,7 +1133,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
}
|
}
|
||||||
//console.log('getConfigFilePath(\"' + filename + '\") = ' + obj.path.join(obj.datapath, filename));
|
//console.log('getConfigFilePath(\"' + filename + '\") = ' + obj.path.join(obj.datapath, filename));
|
||||||
return obj.path.join(obj.datapath, filename);
|
return obj.path.join(obj.datapath, filename);
|
||||||
}
|
};
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -1132,6 +1141,7 @@ function CreateMeshCentralServer(config, args) {
|
||||||
// Return the server configuration
|
// Return the server configuration
|
||||||
function getConfig() {
|
function getConfig() {
|
||||||
// Figure out the datapath location
|
// Figure out the datapath location
|
||||||
|
var i;
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var datapath = null;
|
var datapath = null;
|
||||||
|
@ -1150,7 +1160,7 @@ function getConfig() {
|
||||||
// Load and validate the configuration file
|
// Load and validate the configuration file
|
||||||
try { config = require(configFilePath); } catch (e) { console.log('ERROR: Unable to parse ' + configFilePath + '.'); return null; }
|
try { config = require(configFilePath); } catch (e) { console.log('ERROR: Unable to parse ' + configFilePath + '.'); return null; }
|
||||||
if (config.domains == null) { config.domains = {}; }
|
if (config.domains == null) { config.domains = {}; }
|
||||||
for (var i in config.domains) { if ((i.split('/').length > 1) || (i.split(' ').length > 1)) { console.log("ERROR: Error in config.json, domain names can't have spaces or /."); return null; } }
|
for (i in config.domains) { if ((i.split('/').length > 1) || (i.split(' ').length > 1)) { console.log("ERROR: Error in config.json, domain names can't have spaces or /."); return null; } }
|
||||||
} else {
|
} else {
|
||||||
// Copy the "sample-config.json" to give users a starting point
|
// Copy the "sample-config.json" to give users a starting point
|
||||||
var sampleConfigPath = path.join(__dirname, 'sample-config.json');
|
var sampleConfigPath = path.join(__dirname, 'sample-config.json');
|
||||||
|
@ -1159,7 +1169,7 @@ function getConfig() {
|
||||||
|
|
||||||
// Set the command line arguments to the config file if they are not present
|
// Set the command line arguments to the config file if they are not present
|
||||||
if (!config.settings) { config.settings = {}; }
|
if (!config.settings) { config.settings = {}; }
|
||||||
for (var i in args) { config.settings[i] = args[i]; }
|
for (i in args) { config.settings[i] = args[i]; }
|
||||||
|
|
||||||
// Lower case all keys in the config file
|
// Lower case all keys in the config file
|
||||||
require('./common.js').objKeysToLower(config);
|
require('./common.js').objKeysToLower(config);
|
||||||
|
|
22
meshrelay.js
22
meshrelay.js
|
@ -6,7 +6,12 @@
|
||||||
* @version v0.0.1
|
* @version v0.0.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
/*jslint node: true */
|
||||||
|
/*jshint node: true */
|
||||||
|
/*jshint strict:false */
|
||||||
|
/*jshint -W097 */
|
||||||
|
/*jshint esversion: 6 */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
|
module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
|
||||||
var obj = {};
|
var obj = {};
|
||||||
|
@ -23,9 +28,10 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
|
||||||
obj.close = function (arg) {
|
obj.close = function (arg) {
|
||||||
if ((arg == 1) || (arg == null)) { try { obj.ws.close(); obj.parent.parent.debug(1, 'Relay: Soft disconnect (' + obj.remoteaddr + ')'); } catch (e) { console.log(e); } } // Soft close, close the websocket
|
if ((arg == 1) || (arg == null)) { try { obj.ws.close(); obj.parent.parent.debug(1, 'Relay: Soft disconnect (' + obj.remoteaddr + ')'); } catch (e) { console.log(e); } } // Soft close, close the websocket
|
||||||
if (arg == 2) { try { obj.ws._socket._parent.end(); obj.parent.parent.debug(1, 'Relay: Hard disconnect (' + obj.remoteaddr + ')'); } catch (e) { console.log(e); } } // Hard close, close the TCP socket
|
if (arg == 2) { try { obj.ws._socket._parent.end(); obj.parent.parent.debug(1, 'Relay: Hard disconnect (' + obj.remoteaddr + ')'); } catch (e) { console.log(e); } } // Hard close, close the TCP socket
|
||||||
}
|
};
|
||||||
|
|
||||||
obj.sendAgentMessage = function (command, userid, domainid) {
|
obj.sendAgentMessage = function (command, userid, domainid) {
|
||||||
|
var rights;
|
||||||
if (command.nodeid == null) return false;
|
if (command.nodeid == null) return false;
|
||||||
var user = obj.parent.users[userid];
|
var user = obj.parent.users[userid];
|
||||||
if (user == null) return false;
|
if (user == null) return false;
|
||||||
|
@ -37,7 +43,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
|
||||||
var agent = obj.parent.wsagents[command.nodeid];
|
var agent = obj.parent.wsagents[command.nodeid];
|
||||||
if (agent != null) {
|
if (agent != null) {
|
||||||
// Check if we have permission to send a message to that node
|
// Check if we have permission to send a message to that node
|
||||||
var rights = user.links[agent.dbMeshKey];
|
rights = user.links[agent.dbMeshKey];
|
||||||
if (rights != null || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking
|
if (rights != null || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking
|
||||||
command.sessionid = ws.sessionId; // Set the session id, required for responses.
|
command.sessionid = ws.sessionId; // Set the session id, required for responses.
|
||||||
command.rights = rights.rights; // Add user rights flags to the message
|
command.rights = rights.rights; // Add user rights flags to the message
|
||||||
|
@ -50,7 +56,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
|
||||||
var routing = obj.parent.parent.GetRoutingServerId(command.nodeid, 1); // 1 = MeshAgent routing type
|
var routing = obj.parent.parent.GetRoutingServerId(command.nodeid, 1); // 1 = MeshAgent routing type
|
||||||
if (routing != null) {
|
if (routing != null) {
|
||||||
// Check if we have permission to send a message to that node
|
// Check if we have permission to send a message to that node
|
||||||
var rights = user.links[routing.meshid];
|
rights = user.links[routing.meshid];
|
||||||
if (rights != null || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking
|
if (rights != null || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking
|
||||||
command.fromSessionid = ws.sessionId; // Set the session id, required for responses.
|
command.fromSessionid = ws.sessionId; // Set the session id, required for responses.
|
||||||
command.rights = rights.rights; // Add user rights flags to the message
|
command.rights = rights.rights; // Add user rights flags to the message
|
||||||
|
@ -61,7 +67,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
if (req.query.auth == null) {
|
if (req.query.auth == null) {
|
||||||
// Use ExpressJS session, check if this session is a logged in user, at least one of the two connections will need to be authenticated.
|
// Use ExpressJS session, check if this session is a logged in user, at least one of the two connections will need to be authenticated.
|
||||||
|
@ -160,7 +166,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
|
||||||
// Wait for other relay connection
|
// Wait for other relay connection
|
||||||
ws.pause(); // Hold traffic until the other connection
|
ws.pause(); // Hold traffic until the other connection
|
||||||
parent.wsrelays[obj.id] = { peer1: obj, state: 1 };
|
parent.wsrelays[obj.id] = { peer1: obj, state: 1 };
|
||||||
obj.parent.parent.debug(1, 'Relay holding: ' + obj.id + ' (' + obj.remoteaddr + ') ' + (obj.authenticated?'Authenticated':'') );
|
obj.parent.parent.debug(1, 'Relay holding: ' + obj.id + ' (' + obj.remoteaddr + ') ' + (obj.authenticated ? 'Authenticated' : ''));
|
||||||
|
|
||||||
// Check if a peer server has this connection
|
// Check if a peer server has this connection
|
||||||
if (parent.parent.multiServer != null) {
|
if (parent.parent.multiServer != null) {
|
||||||
|
@ -213,6 +219,6 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
|
||||||
obj.id = null;
|
obj.id = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
};
|
||||||
|
|
|
@ -6,7 +6,12 @@
|
||||||
* @version v0.0.1
|
* @version v0.0.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
/*jslint node: true */
|
||||||
|
/*jshint node: true */
|
||||||
|
/*jshint strict:false */
|
||||||
|
/*jshint -W097 */
|
||||||
|
/*jshint esversion: 6 */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
// Construct a Mesh Scanner object
|
// Construct a Mesh Scanner object
|
||||||
// TODO: We need once "server4" and "server6" per interface, or change the default multicast interface as we send.
|
// TODO: We need once "server4" and "server6" per interface, or change the default multicast interface as we send.
|
||||||
|
@ -26,9 +31,10 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||||
|
|
||||||
// Get a list of IPv4 and IPv6 interface addresses
|
// Get a list of IPv4 and IPv6 interface addresses
|
||||||
function getInterfaceList() {
|
function getInterfaceList() {
|
||||||
|
var i;
|
||||||
var ipv4 = ['*'], ipv6 = ['*']; // Bind to IN_ADDR_ANY always
|
var ipv4 = ['*'], ipv6 = ['*']; // Bind to IN_ADDR_ANY always
|
||||||
var interfaces = require('os').networkInterfaces();
|
var interfaces = require('os').networkInterfaces();
|
||||||
for (var i in interfaces) {
|
for (i in interfaces) {
|
||||||
var xinterface = interfaces[i];
|
var xinterface = interfaces[i];
|
||||||
for (var j in xinterface) {
|
for (var j in xinterface) {
|
||||||
var interface2 = xinterface[j];
|
var interface2 = xinterface[j];
|
||||||
|
@ -43,11 +49,11 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||||
|
|
||||||
// Setup all IPv4 and IPv6 servers
|
// Setup all IPv4 and IPv6 servers
|
||||||
function setupServers() {
|
function setupServers() {
|
||||||
var addresses = getInterfaceList();
|
var addresses = getInterfaceList(), i, localAddress, bindOptions;
|
||||||
for (var i in obj.servers4) { obj.servers4[i].xxclear = true; }
|
for (i in obj.servers4) { obj.servers4[i].xxclear = true; }
|
||||||
for (var i in obj.servers6) { obj.servers6[i].xxclear = true; }
|
for (i in obj.servers6) { obj.servers6[i].xxclear = true; }
|
||||||
for (var i in addresses.ipv4) {
|
for (i in addresses.ipv4) {
|
||||||
var localAddress = addresses.ipv4[i];
|
localAddress = addresses.ipv4[i];
|
||||||
if (obj.servers4[localAddress] != null) {
|
if (obj.servers4[localAddress] != null) {
|
||||||
// Server already exists
|
// Server already exists
|
||||||
obj.servers4[localAddress].xxclear = false;
|
obj.servers4[localAddress].xxclear = false;
|
||||||
|
@ -59,7 +65,7 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||||
server4.xxtype = 4;
|
server4.xxtype = 4;
|
||||||
server4.xxlocal = localAddress;
|
server4.xxlocal = localAddress;
|
||||||
server4.on('error', function (err) { if (this.xxlocal == '*') { console.log("ERROR: Server port 16989 not available, check if server is running twice."); } this.close(); delete obj.servers6[this.xxlocal]; });
|
server4.on('error', function (err) { if (this.xxlocal == '*') { console.log("ERROR: Server port 16989 not available, check if server is running twice."); } this.close(); delete obj.servers6[this.xxlocal]; });
|
||||||
var bindOptions = { port: 16989, exclusive: true };
|
bindOptions = { port: 16989, exclusive: true };
|
||||||
if (server4.xxlocal != '*') { bindOptions.address = server4.xxlocal; }
|
if (server4.xxlocal != '*') { bindOptions.address = server4.xxlocal; }
|
||||||
server4.bind(bindOptions, function () {
|
server4.bind(bindOptions, function () {
|
||||||
try {
|
try {
|
||||||
|
@ -77,8 +83,8 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i in addresses.ipv6) {
|
for (i in addresses.ipv6) {
|
||||||
var localAddress = addresses.ipv6[i];
|
localAddress = addresses.ipv6[i];
|
||||||
if (obj.servers6[localAddress] != null) {
|
if (obj.servers6[localAddress] != null) {
|
||||||
// Server already exists
|
// Server already exists
|
||||||
obj.servers6[localAddress].xxclear = false;
|
obj.servers6[localAddress].xxclear = false;
|
||||||
|
@ -90,7 +96,7 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||||
server6.xxtype = 6;
|
server6.xxtype = 6;
|
||||||
server6.xxlocal = localAddress;
|
server6.xxlocal = localAddress;
|
||||||
server6.on('error', function (err) { this.close(); delete obj.servers6[this.xxlocal]; });
|
server6.on('error', function (err) { this.close(); delete obj.servers6[this.xxlocal]; });
|
||||||
var bindOptions = { port: 16989, exclusive: true };
|
bindOptions = { port: 16989, exclusive: true };
|
||||||
if (server6.xxlocal != '*') { bindOptions.address = server6.xxlocal; }
|
if (server6.xxlocal != '*') { bindOptions.address = server6.xxlocal; }
|
||||||
server6.bind(bindOptions, function () {
|
server6.bind(bindOptions, function () {
|
||||||
try {
|
try {
|
||||||
|
@ -108,14 +114,15 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i in obj.servers4) { if (obj.servers4[i].xxclear == true) { obj.servers4[i].close(); delete obj.servers4[i]; }; }
|
for (i in obj.servers4) { if (obj.servers4[i].xxclear == true) { obj.servers4[i].close(); delete obj.servers4[i]; } }
|
||||||
for (var i in obj.servers6) { if (obj.servers6[i].xxclear == true) { obj.servers6[i].close(); delete obj.servers6[i]; }; }
|
for (i in obj.servers6) { if (obj.servers6[i].xxclear == true) { obj.servers6[i].close(); delete obj.servers6[i]; } }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear all IPv4 and IPv6 servers
|
// Clear all IPv4 and IPv6 servers
|
||||||
function clearServers() {
|
function clearServers() {
|
||||||
for (var i in obj.servers4) { obj.servers4[i].close(); delete obj.servers4[i]; }
|
var i;
|
||||||
for (var i in obj.servers6) { obj.servers6[i].close(); delete obj.servers6[i]; }
|
for (i in obj.servers4) { obj.servers4[i].close(); delete obj.servers4[i]; }
|
||||||
|
for (i in obj.servers6) { obj.servers6[i].close(); delete obj.servers6[i]; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start scanning for local network Mesh Agents
|
// Start scanning for local network Mesh Agents
|
||||||
|
@ -128,27 +135,28 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||||
setupServers();
|
setupServers();
|
||||||
obj.mainTimer = setInterval(obj.performScan, periodicScanTime);
|
obj.mainTimer = setInterval(obj.performScan, periodicScanTime);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Stop scanning for local network Mesh Agents
|
// Stop scanning for local network Mesh Agents
|
||||||
obj.stop = function () {
|
obj.stop = function () {
|
||||||
if (obj.mainTimer != null) { clearInterval(obj.mainTimer); obj.mainTimer = null; }
|
if (obj.mainTimer != null) { clearInterval(obj.mainTimer); obj.mainTimer = null; }
|
||||||
clearServers();
|
clearServers();
|
||||||
}
|
};
|
||||||
|
|
||||||
// Look for all Mesh Agents that may be locally reachable, indicating the presense of this server.
|
// Look for all Mesh Agents that may be locally reachable, indicating the presense of this server.
|
||||||
obj.performScan = function (server) {
|
obj.performScan = function (server) {
|
||||||
|
var i;
|
||||||
if (server != null) {
|
if (server != null) {
|
||||||
if (server.xxtype == 4) { try { server.send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, membershipIPv4); } catch (e) { } }
|
if (server.xxtype == 4) { try { server.send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, membershipIPv4); } catch (e) { } }
|
||||||
if (server.xxtype == 6) { try { server.send(obj.multicastPacket6, 0, obj.multicastPacket6.length, 16990, membershipIPv6); } catch (e) { } }
|
if (server.xxtype == 6) { try { server.send(obj.multicastPacket6, 0, obj.multicastPacket6.length, 16990, membershipIPv6); } catch (e) { } }
|
||||||
if ((server.xxtype == 4) && (server.xxlocal == '*')) { try { server.send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, '127.0.0.1'); } catch (e) { } try { server.send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, '255.255.255.255'); } catch (e) { } }
|
if ((server.xxtype == 4) && (server.xxlocal == '*')) { try { server.send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, '127.0.0.1'); } catch (e) { } try { server.send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, '255.255.255.255'); } catch (e) { } }
|
||||||
if ((server.xxtype == 6) && (server.xxlocal == '*')) { try { server.send(obj.multicastPacket6, 0, obj.multicastPacket6.length, 16990, '::1'); } catch (e) { } }
|
if ((server.xxtype == 6) && (server.xxlocal == '*')) { try { server.send(obj.multicastPacket6, 0, obj.multicastPacket6.length, 16990, '::1'); } catch (e) { } }
|
||||||
} else {
|
} else {
|
||||||
for (var i in obj.servers4) { try { obj.servers4[i].send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, membershipIPv4); } catch (e) { } }
|
for (i in obj.servers4) { try { obj.servers4[i].send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, membershipIPv4); } catch (e) { } }
|
||||||
for (var i in obj.servers6) { try { obj.servers6[i].send(obj.multicastPacket6, 0, obj.multicastPacket6.length, 16990, membershipIPv6); } catch (e) { } }
|
for (i in obj.servers6) { try { obj.servers6[i].send(obj.multicastPacket6, 0, obj.multicastPacket6.length, 16990, membershipIPv6); } catch (e) { } }
|
||||||
setupServers(); // Check if any network interfaces where added or removed
|
setupServers(); // Check if any network interfaces where added or removed
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Called when a UDP packet is received from an agent.
|
// Called when a UDP packet is received from an agent.
|
||||||
function onUdpPacket(msg, info, server) {
|
function onUdpPacket(msg, info, server) {
|
||||||
|
@ -161,26 +169,27 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||||
|
|
||||||
// As a side job, we also send server wake-on-lan packets
|
// As a side job, we also send server wake-on-lan packets
|
||||||
obj.wakeOnLan = function (macs) {
|
obj.wakeOnLan = function (macs) {
|
||||||
for (var i in macs) {
|
var i, j;
|
||||||
|
for (i in macs) {
|
||||||
var mac = macs[i];
|
var mac = macs[i];
|
||||||
var hexpacket = 'FFFFFFFFFFFF';
|
var hexpacket = 'FFFFFFFFFFFF';
|
||||||
for (var i = 0; i < 16; i++) { hexpacket += mac; }
|
for (j = 0; j < 16; j++) { hexpacket += mac; }
|
||||||
var wakepacket = Buffer.from(hexpacket, 'hex');
|
var wakepacket = Buffer.from(hexpacket, 'hex');
|
||||||
//console.log(wakepacket.toString('hex'));
|
//console.log(wakepacket.toString('hex'));
|
||||||
|
|
||||||
// Send the wake packet 3 times with small time intervals
|
// Send the wake packet 3 times with small time intervals
|
||||||
for (var i in obj.servers4) { obj.servers4[i].send(wakepacket, 0, wakepacket.length, 7, "255.255.255.255"); obj.servers4[i].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv4); }
|
for (j in obj.servers4) { obj.servers4[j].send(wakepacket, 0, wakepacket.length, 7, "255.255.255.255"); obj.servers4[j].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv4); }
|
||||||
for (var i in obj.servers6) { obj.servers6[i].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv6); }
|
for (j in obj.servers6) { obj.servers6[j].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv6); }
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
for (var i in obj.servers4) { obj.servers4[i].send(wakepacket, 0, wakepacket.length, 7, "255.255.255.255"); obj.servers4[i].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv4); }
|
for (j in obj.servers4) { obj.servers4[j].send(wakepacket, 0, wakepacket.length, 7, "255.255.255.255"); obj.servers4[j].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv4); }
|
||||||
for (var i in obj.servers6) { obj.servers6[i].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv6); }
|
for (j in obj.servers6) { obj.servers6[j].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv6); }
|
||||||
}, 200);
|
}, 200);
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
for (var i in obj.servers4) { obj.servers4[i].send(wakepacket, 0, wakepacket.length, 7, "255.255.255.255"); obj.servers4[i].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv4); }
|
for (j in obj.servers4) { obj.servers4[j].send(wakepacket, 0, wakepacket.length, 7, "255.255.255.255"); obj.servers4[j].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv4); }
|
||||||
for (var i in obj.servers6) { obj.servers6[i].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv6); }
|
for (j in obj.servers6) { obj.servers6[j].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv6); }
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
};
|
178
meshuser.js
178
meshuser.js
|
@ -6,7 +6,12 @@
|
||||||
* @version v0.0.1
|
* @version v0.0.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
/*jslint node: true */
|
||||||
|
/*jshint node: true */
|
||||||
|
/*jshint strict:false */
|
||||||
|
/*jshint -W097 */
|
||||||
|
/*jshint esversion: 6 */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
// Construct a MeshAgent object, called upon connection
|
// Construct a MeshAgent object, called upon connection
|
||||||
module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
|
@ -27,7 +32,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
obj.close = function (arg) {
|
obj.close = function (arg) {
|
||||||
if ((arg == 1) || (arg == null)) { try { obj.ws.close(); obj.parent.parent.debug(1, 'Soft disconnect'); } catch (e) { console.log(e); } } // Soft close, close the websocket
|
if ((arg == 1) || (arg == null)) { try { obj.ws.close(); obj.parent.parent.debug(1, 'Soft disconnect'); } catch (e) { console.log(e); } } // Soft close, close the websocket
|
||||||
if (arg == 2) { try { obj.ws._socket._parent.end(); obj.parent.parent.debug(1, 'Hard disconnect'); } catch (e) { console.log(e); } } // Hard close, close the TCP socket
|
if (arg == 2) { try { obj.ws._socket._parent.end(); obj.parent.parent.debug(1, 'Hard disconnect'); } catch (e) { console.log(e); } } // Hard close, close the TCP socket
|
||||||
}
|
};
|
||||||
|
|
||||||
// Convert a mesh path array into a real path on the server side
|
// Convert a mesh path array into a real path on the server side
|
||||||
function meshPathToRealPath(meshpath, user) {
|
function meshPathToRealPath(meshpath, user) {
|
||||||
|
@ -52,22 +57,22 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
|
|
||||||
//
|
//
|
||||||
function copyFile(src, dest, func, tag) {
|
function copyFile(src, dest, func, tag) {
|
||||||
//var ss = obj.fs.createReadStream(src, { flags: 'rb' });
|
//var ss = obj.fs.createReadStream(src, { flags: 'rb' });
|
||||||
//var ds = obj.fs.createWriteStream(dest, { flags: 'wb' });
|
//var ds = obj.fs.createWriteStream(dest, { flags: 'wb' });
|
||||||
var ss = obj.fs.createReadStream(src);
|
var ss = obj.fs.createReadStream(src);
|
||||||
var ds = obj.fs.createWriteStream(dest);
|
var ds = obj.fs.createWriteStream(dest);
|
||||||
ss.fs = obj.fs;
|
ss.fs = obj.fs;
|
||||||
ss.pipe(ds);
|
ss.pipe(ds);
|
||||||
ds.ss = ss;
|
ds.ss = ss;
|
||||||
/*
|
/*
|
||||||
if (!this._copyStreams) { this._copyStreams = {}; this._copyStreamID = 0; }
|
if (!this._copyStreams) { this._copyStreams = {}; this._copyStreamID = 0; }
|
||||||
ss.id = this._copyStreamID++;
|
ss.id = this._copyStreamID++;
|
||||||
this._copyStreams[ss.id] = ss;
|
this._copyStreams[ss.id] = ss;
|
||||||
*/
|
*/
|
||||||
if (arguments.length == 3 && typeof arguments[2] === 'function') { ds.on('close', arguments[2]); }
|
if (arguments.length == 3 && typeof arguments[2] === 'function') { ds.on('close', arguments[2]); }
|
||||||
else if (arguments.length == 4 && typeof arguments[3] === 'function') { ds.on('close', arguments[3]); }
|
else if (arguments.length == 4 && typeof arguments[3] === 'function') { ds.on('close', arguments[3]); }
|
||||||
ds.on('close', function() { /*delete this.ss.fs._copyStreams[this.ss.id];*/ func(tag); });
|
ds.on('close', function () { /*delete this.ss.fs._copyStreams[this.ss.id];*/ func(tag); });
|
||||||
};
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Check if the user is logged in
|
// Check if the user is logged in
|
||||||
|
@ -83,7 +88,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
obj.parent.wssessions2[ws.sessionId] = obj.ws;
|
obj.parent.wssessions2[ws.sessionId] = obj.ws;
|
||||||
if (!obj.parent.wssessions[user._id]) { obj.parent.wssessions[user._id] = [ws]; } else { obj.parent.wssessions[user._id].push(obj.ws); }
|
if (!obj.parent.wssessions[user._id]) { obj.parent.wssessions[user._id] = [ws]; } else { obj.parent.wssessions[user._id].push(obj.ws); }
|
||||||
if (obj.parent.parent.multiServer == null) {
|
if (obj.parent.parent.multiServer == null) {
|
||||||
obj.parent.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: user.name, count: obj.parent.wssessions[user._id].length, nolog: 1, domain: obj.domain.id })
|
obj.parent.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: user.name, count: obj.parent.wssessions[user._id].length, nolog: 1, domain: obj.domain.id });
|
||||||
} else {
|
} else {
|
||||||
obj.parent.recountSessions(obj.ws.sessionId); // Recount sessions
|
obj.parent.recountSessions(obj.ws.sessionId); // Recount sessions
|
||||||
}
|
}
|
||||||
|
@ -101,14 +106,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
else { ws.send(JSON.stringify({ action: 'event', event: event })); }
|
else { ws.send(JSON.stringify({ action: 'event', event: event })); }
|
||||||
} catch (e) { }
|
} catch (e) { }
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
user.subscriptions = obj.parent.subscribe(user._id, ws); // Subscribe to events
|
user.subscriptions = obj.parent.subscribe(user._id, ws); // Subscribe to events
|
||||||
obj.ws._socket.setKeepAlive(true, 240000); // Set TCP keep alive
|
obj.ws._socket.setKeepAlive(true, 240000); // Set TCP keep alive
|
||||||
|
|
||||||
// When data is received from the web socket
|
// When data is received from the web socket
|
||||||
ws.on('message', function (msg) {
|
ws.on('message', function (msg) {
|
||||||
var command, user = obj.parent.users[req.session.userid];
|
var command, user = obj.parent.users[req.session.userid], i = 0, mesh = null, meshid = null, nodeid = null, meshlinks = null, change = 0;
|
||||||
try { command = JSON.parse(msg.toString('utf8')); } catch (e) { return; }
|
try { command = JSON.parse(msg.toString('utf8')); } catch (e) { return; }
|
||||||
if ((user == null) || (obj.common.validateString(command.action, 3, 32) == false)) return; // User must be set and action must be a string between 3 and 32 chars
|
if ((user == null) || (obj.common.validateString(command.action, 3, 32) == false)) return; // User must be set and action must be a string between 3 and 32 chars
|
||||||
|
|
||||||
|
@ -118,7 +123,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
{
|
{
|
||||||
// Request a list of all meshes this user as rights to
|
// Request a list of all meshes this user as rights to
|
||||||
var docs = [];
|
var docs = [];
|
||||||
for (var i in user.links) { if (obj.parent.meshes[i]) { docs.push(obj.parent.meshes[i]); } }
|
for (i in user.links) { if (obj.parent.meshes[i]) { docs.push(obj.parent.meshes[i]); } }
|
||||||
ws.send(JSON.stringify({ action: 'meshes', meshes: docs, tag: command.tag }));
|
ws.send(JSON.stringify({ action: 'meshes', meshes: docs, tag: command.tag }));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -127,10 +132,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
var links = [];
|
var links = [];
|
||||||
if (command.meshid == null) {
|
if (command.meshid == null) {
|
||||||
// Request a list of all meshes this user as rights to
|
// Request a list of all meshes this user as rights to
|
||||||
for (var i in user.links) { links.push(i); }
|
for (i in user.links) { links.push(i); }
|
||||||
} else {
|
} else {
|
||||||
// Request list of all nodes for one specific meshid
|
// Request list of all nodes for one specific meshid
|
||||||
var meshid = command.meshid;
|
meshid = command.meshid;
|
||||||
if (obj.common.validateString(meshid, 0, 128) == false) return;
|
if (obj.common.validateString(meshid, 0, 128) == false) return;
|
||||||
if (meshid.split('/').length == 0) { meshid = 'mesh/' + domain.id + '/' + command.meshid; }
|
if (meshid.split('/').length == 0) { meshid = 'mesh/' + domain.id + '/' + command.meshid; }
|
||||||
if (user.links[meshid] != null) { links.push(meshid); }
|
if (user.links[meshid] != null) { links.push(meshid); }
|
||||||
|
@ -139,7 +144,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
// Request a list of all nodes
|
// Request a list of all nodes
|
||||||
obj.db.GetAllTypeNoTypeFieldMeshFiltered(links, domain.id, 'node', function (err, docs) {
|
obj.db.GetAllTypeNoTypeFieldMeshFiltered(links, domain.id, 'node', function (err, docs) {
|
||||||
var r = {};
|
var r = {};
|
||||||
for (var i in docs) {
|
for (i in docs) {
|
||||||
// Add the connection state
|
// Add the connection state
|
||||||
var state = obj.parent.parent.GetConnectivityState(docs[i]._id);
|
var state = obj.parent.parent.GetConnectivityState(docs[i]._id);
|
||||||
if (state) {
|
if (state) {
|
||||||
|
@ -150,7 +155,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compress the meshid's
|
// Compress the meshid's
|
||||||
var meshid = docs[i].meshid;
|
meshid = docs[i].meshid;
|
||||||
if (!r[meshid]) { r[meshid] = []; }
|
if (!r[meshid]) { r[meshid] = []; }
|
||||||
delete docs[i].meshid;
|
delete docs[i].meshid;
|
||||||
|
|
||||||
|
@ -171,7 +176,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
obj.db.getPowerTimeline(command.nodeid, function (err, docs) {
|
obj.db.getPowerTimeline(command.nodeid, function (err, docs) {
|
||||||
if (err == null && docs.length > 0) {
|
if (err == null && docs.length > 0) {
|
||||||
var timeline = [], time = null, previousPower;
|
var timeline = [], time = null, previousPower;
|
||||||
for (var i in docs) {
|
for (i in docs) {
|
||||||
var doc = docs[i];
|
var doc = docs[i];
|
||||||
if (time == null) {
|
if (time == null) {
|
||||||
// First element
|
// First element
|
||||||
|
@ -228,14 +233,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
if (path == null) break;
|
if (path == null) break;
|
||||||
|
|
||||||
if ((command.fileop == 'createfolder') && (obj.common.IsFilenameValid(command.newfolder) == true)) { try { obj.fs.mkdirSync(path + "/" + command.newfolder); } catch (e) { } } // Create a new folder
|
if ((command.fileop == 'createfolder') && (obj.common.IsFilenameValid(command.newfolder) == true)) { try { obj.fs.mkdirSync(path + "/" + command.newfolder); } catch (e) { } } // Create a new folder
|
||||||
else if (command.fileop == 'delete') { if (obj.common.validateArray(command.delfiles, 1) == false) return; for (var i in command.delfiles) { if (obj.common.IsFilenameValid(command.delfiles[i]) == true) { var fullpath = path + "/" + command.delfiles[i]; try { obj.fs.rmdirSync(fullpath); } catch (e) { try { obj.fs.unlinkSync(fullpath); } catch (e) { } } } } } // Delete
|
else if (command.fileop == 'delete') { if (obj.common.validateArray(command.delfiles, 1) == false) return; for (i in command.delfiles) { if (obj.common.IsFilenameValid(command.delfiles[i]) == true) { var fullpath = path + "/" + command.delfiles[i]; try { obj.fs.rmdirSync(fullpath); } catch (e) { try { obj.fs.unlinkSync(fullpath); } catch (e) { } } } } } // Delete
|
||||||
else if ((command.fileop == 'rename') && (obj.common.IsFilenameValid(command.oldname) == true) && (obj.common.IsFilenameValid(command.newname) == true)) { try { obj.fs.renameSync(path + "/" + command.oldname, path + "/" + command.newname); } catch (e) { } } // Rename
|
else if ((command.fileop == 'rename') && (obj.common.IsFilenameValid(command.oldname) == true) && (obj.common.IsFilenameValid(command.newname) == true)) { try { obj.fs.renameSync(path + "/" + command.oldname, path + "/" + command.newname); } catch (e) { } } // Rename
|
||||||
else if ((command.fileop == 'copy') || (command.fileop == 'move')) {
|
else if ((command.fileop == 'copy') || (command.fileop == 'move')) {
|
||||||
if (obj.common.validateArray(command.names, 1) == false) return;
|
if (obj.common.validateArray(command.names, 1) == false) return;
|
||||||
var scpath = meshPathToRealPath(command.scpath, user); // This will also check access rights
|
var scpath = meshPathToRealPath(command.scpath, user); // This will also check access rights
|
||||||
if (scpath == null) break;
|
if (scpath == null) break;
|
||||||
// TODO: Check quota if this is a copy!!!!!!!!!!!!!!!!
|
// TODO: Check quota if this is a copy!!!!!!!!!!!!!!!!
|
||||||
for (var i in command.names) {
|
for (i in command.names) {
|
||||||
var s = obj.path.join(scpath, command.names[i]), d = obj.path.join(path, command.names[i]);
|
var s = obj.path.join(scpath, command.names[i]), d = obj.path.join(path, command.names[i]);
|
||||||
sendUpdate = false;
|
sendUpdate = false;
|
||||||
copyFile(s, d, function (op) { if (op != null) { obj.fs.unlink(op, function () { obj.parent.parent.DispatchEvent([user._id], obj, 'updatefiles'); }); } else { obj.parent.parent.DispatchEvent([user._id], obj, 'updatefiles'); } }, ((command.fileop == 'move') ? s : null));
|
copyFile(s, d, function (op) { if (op != null) { obj.fs.unlink(op, function () { obj.parent.parent.DispatchEvent([user._id], obj, 'updatefiles'); }); } else { obj.parent.parent.DispatchEvent([user._id], obj, 'updatefiles'); } }, ((command.fileop == 'move') ? s : null));
|
||||||
|
@ -319,7 +324,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
// Delete all events
|
// Delete all events
|
||||||
if (user.siteadmin != 0xFFFFFFFF) break;
|
if (user.siteadmin != 0xFFFFFFFF) break;
|
||||||
obj.db.RemoveAllEvents(domain.id);
|
obj.db.RemoveAllEvents(domain.id);
|
||||||
obj.parent.parent.DispatchEvent(['*', 'server-global'], obj, { action: 'clearevents', nolog: 1, domain: domain.id })
|
obj.parent.parent.DispatchEvent(['*', 'server-global'], obj, { action: 'clearevents', nolog: 1, domain: domain.id });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'users':
|
case 'users':
|
||||||
|
@ -327,7 +332,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
// Request a list of all users
|
// Request a list of all users
|
||||||
if ((user.siteadmin & 2) == 0) break;
|
if ((user.siteadmin & 2) == 0) break;
|
||||||
var docs = [];
|
var docs = [];
|
||||||
for (var i in obj.parent.users) {
|
for (i in obj.parent.users) {
|
||||||
if ((obj.parent.users[i].domain == domain.id) && (obj.parent.users[i].name != '~')) {
|
if ((obj.parent.users[i].domain == domain.id) && (obj.parent.users[i].name != '~')) {
|
||||||
var userinfo = obj.common.Clone(obj.parent.users[i]);
|
var userinfo = obj.common.Clone(obj.parent.users[i]);
|
||||||
delete userinfo.hash;
|
delete userinfo.hash;
|
||||||
|
@ -403,10 +408,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
if ((user.siteadmin & 2) == 0) break;
|
if ((user.siteadmin & 2) == 0) break;
|
||||||
if (obj.parent.parent.multiServer == null) {
|
if (obj.parent.parent.multiServer == null) {
|
||||||
// No peering, use simple session counting
|
// No peering, use simple session counting
|
||||||
for (var i in obj.parent.wssessions) { if (obj.parent.wssessions[i][0].domainid == domain.id) { wssessions[i] = obj.parent.wssessions[i].length; } }
|
for (i in obj.parent.wssessions) { if (obj.parent.wssessions[i][0].domainid == domain.id) { wssessions[i] = obj.parent.wssessions[i].length; } }
|
||||||
} else {
|
} else {
|
||||||
// We have peer servers, use more complex session counting
|
// We have peer servers, use more complex session counting
|
||||||
for (var userid in obj.parent.sessionsCount) { if (userid.split('/')[1] == domain.id) { wssessions[userid] = obj.parent.sessionsCount[userid]; } }
|
for (i in obj.parent.sessionsCount) { if (i.split('/')[1] == domain.id) { wssessions[i] = obj.parent.sessionsCount[i]; } }
|
||||||
}
|
}
|
||||||
ws.send(JSON.stringify({ action: 'wssessioncount', wssessions: wssessions, tag: command.tag })); // wssessions is: userid --> count
|
ws.send(JSON.stringify({ action: 'wssessioncount', wssessions: wssessions, tag: command.tag })); // wssessions is: userid --> count
|
||||||
break;
|
break;
|
||||||
|
@ -422,15 +427,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
|
|
||||||
// Remove all the mesh links to this user
|
// Remove all the mesh links to this user
|
||||||
if (deluser.links != null) {
|
if (deluser.links != null) {
|
||||||
for (var meshid in deluser.links) {
|
for (meshid in deluser.links) {
|
||||||
// Get the mesh
|
// Get the mesh
|
||||||
var mesh = obj.parent.meshes[meshid];
|
mesh = obj.parent.meshes[meshid];
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
// Remove user from the mesh
|
// Remove user from the mesh
|
||||||
if (mesh.links[deluser._id] != null) { delete mesh.links[deluser._id]; obj.parent.db.Set(mesh); }
|
if (mesh.links[deluser._id] != null) { delete mesh.links[deluser._id]; obj.parent.db.Set(mesh); }
|
||||||
// Notify mesh change
|
// Notify mesh change
|
||||||
var change = 'Removed user ' + deluser.name + ' from mesh ' + mesh.name;
|
change = 'Removed user ' + deluser.name + ' from mesh ' + mesh.name;
|
||||||
obj.parent.parent.DispatchEvent(['*', mesh._id, deluser._id, userid], obj, { etype: 'mesh', username: user.name, userid: userid, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id })
|
obj.parent.parent.DispatchEvent(['*', mesh._id, deluser._id, user._id], obj, { etype: 'mesh', username: user.name, userid: user._id, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -446,7 +451,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
|
|
||||||
obj.db.Remove(deluserid);
|
obj.db.Remove(deluserid);
|
||||||
delete obj.parent.users[deluserid];
|
delete obj.parent.users[deluserid];
|
||||||
obj.parent.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', userid: deluserid, username: deluser.name, action: 'accountremove', msg: 'Account removed', domain: domain.id })
|
obj.parent.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', userid: deluserid, username: deluser.name, action: 'accountremove', msg: 'Account removed', domain: domain.id });
|
||||||
obj.parent.parent.DispatchEvent([deluserid], obj, 'close');
|
obj.parent.parent.DispatchEvent([deluserid], obj, 'close');
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -474,7 +479,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
if (newuser2.subscriptions) { delete newuser2.subscriptions; }
|
if (newuser2.subscriptions) { delete newuser2.subscriptions; }
|
||||||
if (newuser2.salt) { delete newuser2.salt; }
|
if (newuser2.salt) { delete newuser2.salt; }
|
||||||
if (newuser2.hash) { delete newuser2.hash; }
|
if (newuser2.hash) { delete newuser2.hash; }
|
||||||
obj.parent.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: newusername, account: newuser2, action: 'accountcreate', msg: 'Account created, email is ' + command.email, domain: domain.id })
|
obj.parent.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: newusername, account: newuser2, action: 'accountcreate', msg: 'Account created, email is ' + command.email, domain: domain.id });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -483,12 +488,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
{
|
{
|
||||||
// Edit a user account, may involve changing email or administrator permissions
|
// Edit a user account, may involve changing email or administrator permissions
|
||||||
if (((user.siteadmin & 2) != 0) || (user.name == command.name)) {
|
if (((user.siteadmin & 2) != 0) || (user.name == command.name)) {
|
||||||
var chguserid = 'user/' + domain.id + '/' + command.name.toLowerCase(), chguser = obj.parent.users[chguserid], change = 0;
|
var chguserid = 'user/' + domain.id + '/' + command.name.toLowerCase(), chguser = obj.parent.users[chguserid];
|
||||||
|
change = 0;
|
||||||
if (chguser) {
|
if (chguser) {
|
||||||
if (obj.common.validateString(command.email, 1, 256) && (chguser.email != command.email)) { chguser.email = command.email; change = 1; }
|
if (obj.common.validateString(command.email, 1, 256) && (chguser.email != command.email)) { chguser.email = command.email; change = 1; }
|
||||||
if ((command.emailVerified === true || command.emailVerified === false) && (chguser.emailVerified != command.emailVerified)) { chguser.emailVerified = command.emailVerified; change = 1; }
|
if ((command.emailVerified === true || command.emailVerified === false) && (chguser.emailVerified != command.emailVerified)) { chguser.emailVerified = command.emailVerified; change = 1; }
|
||||||
if (obj.common.validateInt(command.quota, 0) && (command.quota != chguser.quota)) { chguser.quota = command.quota; if (chguser.quota == null) { delete chguser.quota; } change = 1; }
|
if (obj.common.validateInt(command.quota, 0) && (command.quota != chguser.quota)) { chguser.quota = command.quota; if (chguser.quota == null) { delete chguser.quota; } change = 1; }
|
||||||
if ((user.siteadmin == 0xFFFFFFFF) && obj.common.validateInt(command.siteadmin) && (chguser.siteadmin != command.siteadmin)) { chguser.siteadmin = command.siteadmin; change = 1 }
|
if ((user.siteadmin == 0xFFFFFFFF) && obj.common.validateInt(command.siteadmin) && (chguser.siteadmin != command.siteadmin)) { chguser.siteadmin = command.siteadmin; change = 1; }
|
||||||
if (change == 1) {
|
if (change == 1) {
|
||||||
obj.db.SetUser(chguser);
|
obj.db.SetUser(chguser);
|
||||||
obj.parent.parent.DispatchEvent([chguser._id], obj, 'resubscribe');
|
obj.parent.parent.DispatchEvent([chguser._id], obj, 'resubscribe');
|
||||||
|
@ -500,7 +506,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
delete userinfo.domain;
|
delete userinfo.domain;
|
||||||
delete userinfo.subscriptions;
|
delete userinfo.subscriptions;
|
||||||
delete userinfo.passtype;
|
delete userinfo.passtype;
|
||||||
obj.parent.parent.DispatchEvent(['*', 'server-users', user._id, chguser._id], obj, { etype: 'user', username: user.name, account: userinfo, action: 'accountchange', msg: 'Account changed: ' + command.name, domain: domain.id })
|
obj.parent.parent.DispatchEvent(['*', 'server-users', user._id, chguser._id], obj, { etype: 'user', username: user.name, account: userinfo, action: 'accountchange', msg: 'Account changed: ' + command.name, domain: domain.id });
|
||||||
}
|
}
|
||||||
if ((chguser.siteadmin) && (chguser.siteadmin != 0xFFFFFFFF) && (chguser.siteadmin & 32)) {
|
if ((chguser.siteadmin) && (chguser.siteadmin != 0xFFFFFFFF) && (chguser.siteadmin & 32)) {
|
||||||
obj.parent.parent.DispatchEvent([chguser._id], obj, 'close'); // Disconnect all this user's sessions
|
obj.parent.parent.DispatchEvent([chguser._id], obj, 'close'); // Disconnect all this user's sessions
|
||||||
|
@ -534,11 +540,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
|
|
||||||
// Get the list of sessions for this user
|
// Get the list of sessions for this user
|
||||||
var sessions = obj.parent.wssessions[command.userid];
|
var sessions = obj.parent.wssessions[command.userid];
|
||||||
if (sessions != null) { for (var i in sessions) { sessions[i].send(JSON.stringify(notification)); } }
|
if (sessions != null) { for (i in sessions) { sessions[i].send(JSON.stringify(notification)); } }
|
||||||
|
|
||||||
if (obj.parent.parent.multiServer != null) {
|
if (obj.parent.parent.multiServer != null) {
|
||||||
// TODO: Add multi-server support
|
// TODO: Add multi-server support
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case 'serverversion':
|
case 'serverversion':
|
||||||
{
|
{
|
||||||
|
@ -564,10 +571,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
if ((command.meshtype == 1) || (command.meshtype == 2)) {
|
if ((command.meshtype == 1) || (command.meshtype == 2)) {
|
||||||
// Create a type 1 agent-less Intel AMT mesh.
|
// Create a type 1 agent-less Intel AMT mesh.
|
||||||
obj.parent.crypto.randomBytes(48, function (err, buf) {
|
obj.parent.crypto.randomBytes(48, function (err, buf) {
|
||||||
var meshid = 'mesh/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
meshid = 'mesh/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
||||||
var links = {}
|
var links = {};
|
||||||
links[user._id] = { name: user.name, rights: 0xFFFFFFFF };
|
links[user._id] = { name: user.name, rights: 0xFFFFFFFF };
|
||||||
var mesh = { type: 'mesh', _id: meshid, name: command.meshname, mtype: command.meshtype, desc: command.desc, domain: domain.id, links: links };
|
mesh = { type: 'mesh', _id: meshid, name: command.meshname, mtype: command.meshtype, desc: command.desc, domain: domain.id, links: links };
|
||||||
obj.db.Set(obj.common.escapeLinksFieldName(mesh));
|
obj.db.Set(obj.common.escapeLinksFieldName(mesh));
|
||||||
obj.parent.meshes[meshid] = mesh;
|
obj.parent.meshes[meshid] = mesh;
|
||||||
obj.parent.parent.AddEventDispatch([meshid], ws);
|
obj.parent.parent.AddEventDispatch([meshid], ws);
|
||||||
|
@ -575,7 +582,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
user.links[meshid] = { rights: 0xFFFFFFFF };
|
user.links[meshid] = { rights: 0xFFFFFFFF };
|
||||||
user.subscriptions = obj.parent.subscribe(user._id, ws);
|
user.subscriptions = obj.parent.subscribe(user._id, ws);
|
||||||
obj.db.SetUser(user);
|
obj.db.SetUser(user);
|
||||||
obj.parent.parent.DispatchEvent(['*', meshid, user._id], obj, { etype: 'mesh', username: user.name, meshid: meshid, name: command.meshname, mtype: command.meshtype, desc: command.desc, action: 'createmesh', links: links, msg: 'Mesh created: ' + command.meshname, domain: domain.id })
|
obj.parent.parent.DispatchEvent(['*', meshid, user._id], obj, { etype: 'mesh', username: user.name, meshid: meshid, name: command.meshname, mtype: command.meshtype, desc: command.desc, action: 'createmesh', links: links, msg: 'Mesh created: ' + command.meshname, domain: domain.id });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -586,17 +593,17 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
if (obj.common.validateString(command.meshid, 1, 1024) == false) break; // Check the meshid
|
if (obj.common.validateString(command.meshid, 1, 1024) == false) break; // Check the meshid
|
||||||
obj.db.Get(command.meshid, function (err, meshes) {
|
obj.db.Get(command.meshid, function (err, meshes) {
|
||||||
if (meshes.length != 1) return;
|
if (meshes.length != 1) return;
|
||||||
var mesh = obj.common.unEscapeLinksFieldName(meshes[0]);
|
mesh = obj.common.unEscapeLinksFieldName(meshes[0]);
|
||||||
|
|
||||||
// Check if this user has rights to do this
|
// Check if this user has rights to do this
|
||||||
if (mesh.links[user._id] == null || mesh.links[user._id].rights != 0xFFFFFFFF) return;
|
if (mesh.links[user._id] == null || mesh.links[user._id].rights != 0xFFFFFFFF) return;
|
||||||
if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
||||||
|
|
||||||
// Fire the removal event first, because after this, the event will not route
|
// Fire the removal event first, because after this, the event will not route
|
||||||
obj.parent.parent.DispatchEvent(['*', command.meshid], obj, { etype: 'mesh', username: user.name, meshid: command.meshid, name: command.meshname, action: 'deletemesh', msg: 'Mesh deleted: ' + command.meshname, domain: domain.id })
|
obj.parent.parent.DispatchEvent(['*', command.meshid], obj, { etype: 'mesh', username: user.name, meshid: command.meshid, name: command.meshname, action: 'deletemesh', msg: 'Mesh deleted: ' + command.meshname, domain: domain.id });
|
||||||
|
|
||||||
// Remove all user links to this mesh
|
// Remove all user links to this mesh
|
||||||
for (var i in meshes) {
|
for (i in meshes) {
|
||||||
var links = meshes[i].links;
|
var links = meshes[i].links;
|
||||||
for (var j in links) {
|
for (var j in links) {
|
||||||
var xuser = obj.parent.users[j];
|
var xuser = obj.parent.users[j];
|
||||||
|
@ -608,8 +615,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
|
|
||||||
// Delete all files on the server for this mesh
|
// Delete all files on the server for this mesh
|
||||||
try {
|
try {
|
||||||
var meshpath = getServerRootFilePath(mesh);
|
var meshpath = obj.parent.getServerRootFilePath(mesh);
|
||||||
if (meshpath != null) { deleteFolderRec(meshpath); }
|
if (meshpath != null) { obj.parent.deleteFolderRec(meshpath); }
|
||||||
} catch (e) { }
|
} catch (e) { }
|
||||||
|
|
||||||
obj.parent.parent.RemoveEventDispatchId(command.meshid); // Remove all subscriptions to this mesh
|
obj.parent.parent.RemoveEventDispatchId(command.meshid); // Remove all subscriptions to this mesh
|
||||||
|
@ -622,7 +629,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
{
|
{
|
||||||
// Change the name or description of a mesh
|
// Change the name or description of a mesh
|
||||||
if (obj.common.validateString(command.meshid, 1, 1024) == false) break; // Check the meshid
|
if (obj.common.validateString(command.meshid, 1, 1024) == false) break; // Check the meshid
|
||||||
var mesh = obj.parent.meshes[command.meshid], change = '';
|
mesh = obj.parent.meshes[command.meshid];
|
||||||
|
change = '';
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
// Check if this user has rights to do this
|
// Check if this user has rights to do this
|
||||||
if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 1) == 0)) return;
|
if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 1) == 0)) return;
|
||||||
|
@ -630,7 +638,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
|
|
||||||
if ((obj.common.validateString(command.meshname, 1, 64) == true) && (command.meshname != mesh.name)) { change = 'Mesh name changed from "' + mesh.name + '" to "' + command.meshname + '"'; mesh.name = command.meshname; }
|
if ((obj.common.validateString(command.meshname, 1, 64) == true) && (command.meshname != mesh.name)) { change = 'Mesh name changed from "' + mesh.name + '" to "' + command.meshname + '"'; mesh.name = command.meshname; }
|
||||||
if ((obj.common.validateString(command.desc, 0, 1024) == true) && (command.desc != mesh.desc)) { if (change != '') change += ' and description changed'; else change += 'Mesh "' + mesh.name + '" description changed'; mesh.desc = command.desc; }
|
if ((obj.common.validateString(command.desc, 0, 1024) == true) && (command.desc != mesh.desc)) { if (change != '') change += ' and description changed'; else change += 'Mesh "' + mesh.name + '" description changed'; mesh.desc = command.desc; }
|
||||||
if (change != '') { obj.db.Set(obj.common.escapeLinksFieldName(mesh)); obj.parent.parent.DispatchEvent(['*', mesh._id, user._id], obj, { etype: 'mesh', username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id }) }
|
if (change != '') { obj.db.Set(obj.common.escapeLinksFieldName(mesh)); obj.parent.parent.DispatchEvent(['*', mesh._id, user._id], obj, { etype: 'mesh', username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id }); }
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -648,7 +656,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the mesh
|
// Get the mesh
|
||||||
var mesh = obj.parent.meshes[command.meshid], change = '';
|
mesh = obj.parent.meshes[command.meshid];
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
// Check if this user has rights to do this
|
// Check if this user has rights to do this
|
||||||
if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 2) == 0)) return;
|
if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 2) == 0)) return;
|
||||||
|
@ -665,8 +673,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
obj.db.Set(obj.common.escapeLinksFieldName(mesh));
|
obj.db.Set(obj.common.escapeLinksFieldName(mesh));
|
||||||
|
|
||||||
// Notify mesh change
|
// Notify mesh change
|
||||||
var change = 'Added user ' + newuser.name + ' to mesh ' + mesh.name;
|
obj.parent.parent.DispatchEvent(['*', mesh._id, user._id, newuserid], obj, { etype: 'mesh', username: newuser.name, userid: command.userid, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Added user ' + newuser.name + ' to mesh ' + mesh.name, domain: domain.id });
|
||||||
obj.parent.parent.DispatchEvent(['*', mesh._id, user._id, newuserid], obj, { etype: 'mesh', username: newuser.name, userid: command.userid, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id })
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -677,7 +684,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
if ((command.userid.split('/').length != 3) || (command.userid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
if ((command.userid.split('/').length != 3) || (command.userid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
||||||
|
|
||||||
// Get the mesh
|
// Get the mesh
|
||||||
var mesh = obj.parent.meshes[command.meshid];
|
mesh = obj.parent.meshes[command.meshid];
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
// Check if this user has rights to do this
|
// Check if this user has rights to do this
|
||||||
if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 2) == 0)) return;
|
if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 2) == 0)) return;
|
||||||
|
@ -701,8 +708,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
obj.db.Set(obj.common.escapeLinksFieldName(mesh));
|
obj.db.Set(obj.common.escapeLinksFieldName(mesh));
|
||||||
|
|
||||||
// Notify mesh change
|
// Notify mesh change
|
||||||
var change = 'Removed user ' + deluser.name + ' from mesh ' + mesh.name;
|
obj.parent.parent.DispatchEvent(['*', mesh._id, user._id, command.userid], obj, { etype: 'mesh', username: user.name, userid: deluser.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Removed user ' + deluser.name + ' from mesh ' + mesh.name, domain: domain.id });
|
||||||
obj.parent.parent.DispatchEvent(['*', mesh._id, user._id, command.userid], obj, { etype: 'mesh', username: user.name, userid: deluser.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -723,7 +729,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
if ((obj.parent.parent.args.wanonly == true) && (command.hostname)) { delete command.hostname; }
|
if ((obj.parent.parent.args.wanonly == true) && (command.hostname)) { delete command.hostname; }
|
||||||
|
|
||||||
// Get the mesh
|
// Get the mesh
|
||||||
var mesh = obj.parent.meshes[command.meshid];
|
mesh = obj.parent.meshes[command.meshid];
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
if (mesh.mtype != 1) return; // This operation is only allowed for mesh type 1, Intel AMT agentless mesh.
|
if (mesh.mtype != 1) return; // This operation is only allowed for mesh type 1, Intel AMT agentless mesh.
|
||||||
|
|
||||||
|
@ -733,15 +739,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
// Create a new nodeid
|
// Create a new nodeid
|
||||||
obj.parent.crypto.randomBytes(48, function (err, buf) {
|
obj.parent.crypto.randomBytes(48, function (err, buf) {
|
||||||
// create the new node
|
// create the new node
|
||||||
var nodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');;
|
nodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
||||||
var device = { type: 'node', mtype: 1, _id: nodeid, meshid: command.meshid, name: command.devicename, host: command.hostname, domain: domain.id, intelamt: { user: command.amtusername, pass: command.amtpassword, tls: command.amttls } };
|
var device = { type: 'node', mtype: 1, _id: nodeid, meshid: command.meshid, name: command.devicename, host: command.hostname, domain: domain.id, intelamt: { user: command.amtusername, pass: command.amtpassword, tls: command.amttls } };
|
||||||
obj.db.Set(device);
|
obj.db.Set(device);
|
||||||
|
|
||||||
// Event the new node
|
// Event the new node
|
||||||
var device2 = obj.common.Clone(device);
|
var device2 = obj.common.Clone(device);
|
||||||
delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
|
delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
|
||||||
var change = 'Added device ' + command.devicename + ' to mesh ' + mesh.name;
|
obj.parent.parent.DispatchEvent(['*', command.meshid], obj, { etype: 'node', username: user.name, action: 'addnode', node: device2, msg: 'Added device ' + command.devicename + ' to mesh ' + mesh.name, domain: domain.id });
|
||||||
obj.parent.parent.DispatchEvent(['*', command.meshid], obj, { etype: 'node', username: user.name, action: 'addnode', node: device2, msg: change, domain: domain.id })
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -763,8 +768,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
{
|
{
|
||||||
if (obj.common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
if (obj.common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
||||||
|
|
||||||
for (var i in command.nodeids) {
|
for (i in command.nodeids) {
|
||||||
var nodeid = command.nodeids[i];
|
nodeid = command.nodeids[i];
|
||||||
if (obj.common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
if (obj.common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
||||||
if ((nodeid.split('/').length != 3) || (nodeid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
if ((nodeid.split('/').length != 3) || (nodeid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
||||||
|
|
||||||
|
@ -774,7 +779,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
var node = nodes[0];
|
var node = nodes[0];
|
||||||
|
|
||||||
// Get the mesh for this device
|
// Get the mesh for this device
|
||||||
var mesh = obj.parent.meshes[node.meshid];
|
mesh = obj.parent.meshes[node.meshid];
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
// Check if this user has rights to do this
|
// Check if this user has rights to do this
|
||||||
if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 4) == 0)) return;
|
if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 4) == 0)) return;
|
||||||
|
@ -786,8 +791,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
obj.db.RemoveNode(node._id); // Remove all entries with node:id
|
obj.db.RemoveNode(node._id); // Remove all entries with node:id
|
||||||
|
|
||||||
// Event node deletion
|
// Event node deletion
|
||||||
var change = 'Removed device ' + node.name + ' from mesh ' + mesh.name;
|
obj.parent.parent.DispatchEvent(['*', node.meshid], obj, { etype: 'node', username: user.name, action: 'removenode', nodeid: node._id, msg: 'Removed device ' + node.name + ' from mesh ' + mesh.name, domain: domain.id });
|
||||||
obj.parent.parent.DispatchEvent(['*', node.meshid], obj, { etype: 'node', username: user.name, action: 'removenode', nodeid: node._id, msg: change, domain: domain.id })
|
|
||||||
|
|
||||||
// Disconnect all connections if needed
|
// Disconnect all connections if needed
|
||||||
var state = obj.parent.parent.GetConnectivityState(nodeid);
|
var state = obj.parent.parent.GetConnectivityState(nodeid);
|
||||||
|
@ -807,8 +811,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
// TODO: We can optimize this a lot.
|
// TODO: We can optimize this a lot.
|
||||||
// - We should get a full list of all MAC's to wake first.
|
// - We should get a full list of all MAC's to wake first.
|
||||||
// - We should try to only have one agent per subnet (using Gateway MAC) send a wake-on-lan.
|
// - We should try to only have one agent per subnet (using Gateway MAC) send a wake-on-lan.
|
||||||
for (var i in command.nodeids) {
|
for (i in command.nodeids) {
|
||||||
var nodeid = command.nodeids[i], wakeActions = 0;
|
nodeid = command.nodeids[i];
|
||||||
|
var wakeActions = 0;
|
||||||
if (obj.common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
if (obj.common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
||||||
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
||||||
// Get the device
|
// Get the device
|
||||||
|
@ -817,7 +822,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
var node = nodes[0];
|
var node = nodes[0];
|
||||||
|
|
||||||
// Get the mesh for this device
|
// Get the mesh for this device
|
||||||
var mesh = obj.parent.meshes[node.meshid];
|
mesh = obj.parent.meshes[node.meshid];
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
|
|
||||||
// Check if this user has rights to do this
|
// Check if this user has rights to do this
|
||||||
|
@ -835,10 +840,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
|
|
||||||
// Get the list of mesh this user as access to
|
// Get the list of mesh this user as access to
|
||||||
var targetMeshes = [];
|
var targetMeshes = [];
|
||||||
for (var i in user.links) { targetMeshes.push(i); }
|
for (i in user.links) { targetMeshes.push(i); }
|
||||||
|
|
||||||
// Go thru all the connected agents and send wake-on-lan on all the ones in the target mesh list
|
// Go thru all the connected agents and send wake-on-lan on all the ones in the target mesh list
|
||||||
for (var i in obj.parent.wsagents) {
|
for (i in obj.parent.wsagents) {
|
||||||
var agent = obj.parent.wsagents[i];
|
var agent = obj.parent.wsagents[i];
|
||||||
if ((targetMeshes.indexOf(agent.dbMeshKey) >= 0) && (agent.authenticated == 2)) {
|
if ((targetMeshes.indexOf(agent.dbMeshKey) >= 0) && (agent.authenticated == 2)) {
|
||||||
//console.log('Asking agent ' + agent.dbNodeKey + ' to wake ' + macs.join(','));
|
//console.log('Asking agent ' + agent.dbNodeKey + ' to wake ' + macs.join(','));
|
||||||
|
@ -862,8 +867,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
case 'poweraction':
|
case 'poweraction':
|
||||||
{
|
{
|
||||||
if (obj.common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
if (obj.common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
||||||
for (var i in command.nodeids) {
|
for (i in command.nodeids) {
|
||||||
var nodeid = command.nodeids[i], powerActions = 0;
|
nodeid = command.nodeids[i];
|
||||||
|
var powerActions = 0;
|
||||||
if (obj.common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
if (obj.common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
||||||
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
||||||
// Get the device
|
// Get the device
|
||||||
|
@ -872,7 +878,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
var node = nodes[0];
|
var node = nodes[0];
|
||||||
|
|
||||||
// Get the mesh for this device
|
// Get the mesh for this device
|
||||||
var mesh = obj.parent.meshes[node.meshid];
|
mesh = obj.parent.meshes[node.meshid];
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
|
|
||||||
// Check if this user has rights to do this
|
// Check if this user has rights to do this
|
||||||
|
@ -899,8 +905,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
if (obj.common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
if (obj.common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
||||||
if (obj.common.validateString(command.title, 1, 512) == false) break; // Check title
|
if (obj.common.validateString(command.title, 1, 512) == false) break; // Check title
|
||||||
if (obj.common.validateString(command.msg, 1, 4096) == false) break; // Check message
|
if (obj.common.validateString(command.msg, 1, 4096) == false) break; // Check message
|
||||||
for (var i in command.nodeids) {
|
for (i in command.nodeids) {
|
||||||
var nodeid = command.nodeids[i], powerActions = 0;
|
nodeid = command.nodeids[i];
|
||||||
|
var powerActions = 0;
|
||||||
if (obj.common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
if (obj.common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
||||||
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
||||||
// Get the device
|
// Get the device
|
||||||
|
@ -909,7 +916,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
var node = nodes[0];
|
var node = nodes[0];
|
||||||
|
|
||||||
// Get the mesh for this device
|
// Get the mesh for this device
|
||||||
var mesh = obj.parent.meshes[node.meshid];
|
mesh = obj.parent.meshes[node.meshid];
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
|
|
||||||
// Check if this user has rights to do this
|
// Check if this user has rights to do this
|
||||||
|
@ -940,7 +947,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
var node = nodes[0];
|
var node = nodes[0];
|
||||||
|
|
||||||
// Get the mesh for this device
|
// Get the mesh for this device
|
||||||
var mesh = obj.parent.meshes[node.meshid];
|
mesh = obj.parent.meshes[node.meshid];
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
// Check if this user has rights to do this
|
// Check if this user has rights to do this
|
||||||
if (mesh.links[user._id] == null || (mesh.links[user._id].rights == 0)) { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: command.nodeid, netif: null })); return; }
|
if (mesh.links[user._id] == null || (mesh.links[user._id].rights == 0)) { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: command.nodeid, netif: null })); return; }
|
||||||
|
@ -968,13 +975,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
var node = nodes[0];
|
var node = nodes[0];
|
||||||
|
|
||||||
// Get the mesh for this device
|
// Get the mesh for this device
|
||||||
var mesh = obj.parent.meshes[node.meshid];
|
mesh = obj.parent.meshes[node.meshid];
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
// Check if this user has rights to do this
|
// Check if this user has rights to do this
|
||||||
if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 4) == 0)) return;
|
if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 4) == 0)) return;
|
||||||
|
|
||||||
// Ready the node change event
|
// Ready the node change event
|
||||||
var changes = [], change = 0, event = { etype: 'node', username: user.name, action: 'changenode', nodeid: node._id, domain: domain.id };
|
var changes = [], event = { etype: 'node', username: user.name, action: 'changenode', nodeid: node._id, domain: domain.id };
|
||||||
|
change = 0;
|
||||||
event.msg = ": ";
|
event.msg = ": ";
|
||||||
|
|
||||||
// If we are in WAN-only mode, host is not used
|
// If we are in WAN-only mode, host is not used
|
||||||
|
@ -1041,7 +1049,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
data = obj.common.IntToStr(0) + data; // Add the 4 bytes encoding type & flags (Set to 0 for raw)
|
data = obj.common.IntToStr(0) + data; // Add the 4 bytes encoding type & flags (Set to 0 for raw)
|
||||||
obj.parent.sendMeshAgentCore(user, domain, command.nodeid, data);
|
obj.parent.sendMeshAgentCore(user, domain, command.nodeid, data);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1071,7 +1079,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
if (obj.common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
if (obj.common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
||||||
obj.db.Get(command.nodeid, function (err, nodes) { // TODO: Make a NodeRights(user) method that also does not do a db call if agent is connected (???)
|
obj.db.Get(command.nodeid, function (err, nodes) { // TODO: Make a NodeRights(user) method that also does not do a db call if agent is connected (???)
|
||||||
if (nodes.length == 1) {
|
if (nodes.length == 1) {
|
||||||
var meshlinks = user.links[nodes[0].meshid];
|
meshlinks = user.links[nodes[0].meshid];
|
||||||
if ((meshlinks) && (meshlinks.rights) && (meshlinks.rights & obj.parent.MESHRIGHT_REMOTECONTROL != 0)) {
|
if ((meshlinks) && (meshlinks.rights) && (meshlinks.rights & obj.parent.MESHRIGHT_REMOTECONTROL != 0)) {
|
||||||
// Add a user authentication cookie to a url
|
// Add a user authentication cookie to a url
|
||||||
var cookieContent = { userid: user._id, domainid: user.domain };
|
var cookieContent = { userid: user._id, domainid: user.domain };
|
||||||
|
@ -1093,7 +1101,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
||||||
|
|
||||||
// Get the mesh
|
// Get the mesh
|
||||||
var mesh = obj.parent.meshes[command.meshid];
|
mesh = obj.parent.meshes[command.meshid];
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
if (mesh.mtype != 2) return; // This operation is only allowed for mesh type 2, agent mesh
|
if (mesh.mtype != 2) return; // This operation is only allowed for mesh type 2, agent mesh
|
||||||
|
|
||||||
|
@ -1118,7 +1126,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
// Check if this user has rights on this id to set notes
|
// Check if this user has rights on this id to set notes
|
||||||
obj.db.Get(command.id, function (err, nodes) { // TODO: Make a NodeRights(user) method that also does not do a db call if agent is connected (???)
|
obj.db.Get(command.id, function (err, nodes) { // TODO: Make a NodeRights(user) method that also does not do a db call if agent is connected (???)
|
||||||
if (nodes.length == 1) {
|
if (nodes.length == 1) {
|
||||||
var meshlinks = user.links[nodes[0].meshid];
|
meshlinks = user.links[nodes[0].meshid];
|
||||||
if ((meshlinks) && (meshlinks.rights) && (meshlinks.rights & obj.parent.MESHRIGHT_SETNOTES != 0)) {
|
if ((meshlinks) && (meshlinks.rights) && (meshlinks.rights & obj.parent.MESHRIGHT_SETNOTES != 0)) {
|
||||||
// Set the id's notes
|
// Set the id's notes
|
||||||
if (obj.common.validateString(command.notes, 1) == false) {
|
if (obj.common.validateString(command.notes, 1) == false) {
|
||||||
|
@ -1131,7 +1139,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
});
|
});
|
||||||
} else if (idtype == 'mesh') {
|
} else if (idtype == 'mesh') {
|
||||||
// Get the mesh for this device
|
// Get the mesh for this device
|
||||||
var mesh = obj.parent.meshes[command.id];
|
mesh = obj.parent.meshes[command.id];
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
// Check if this user has rights to do this
|
// Check if this user has rights to do this
|
||||||
if (mesh.links[user._id] == null || (mesh.links[user._id].rights == 0)) { return; }
|
if (mesh.links[user._id] == null || (mesh.links[user._id].rights == 0)) { return; }
|
||||||
|
@ -1170,7 +1178,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
var node = nodes[0];
|
var node = nodes[0];
|
||||||
|
|
||||||
// Get the mesh for this device
|
// Get the mesh for this device
|
||||||
var mesh = obj.parent.meshes[node.meshid];
|
mesh = obj.parent.meshes[node.meshid];
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
// Check if this user has rights to do this
|
// Check if this user has rights to do this
|
||||||
if (mesh.links[user._id] == null || (mesh.links[user._id].rights == 0)) { return; }
|
if (mesh.links[user._id] == null || (mesh.links[user._id].rights == 0)) { return; }
|
||||||
|
@ -1184,7 +1192,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
});
|
});
|
||||||
} else if (idtype == 'mesh') {
|
} else if (idtype == 'mesh') {
|
||||||
// Get the mesh for this device
|
// Get the mesh for this device
|
||||||
var mesh = obj.parent.meshes[command.id];
|
mesh = obj.parent.meshes[command.id];
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
// Check if this user has rights to do this
|
// Check if this user has rights to do this
|
||||||
if (mesh.links[user._id] == null || (mesh.links[user._id].rights == 0)) { return; }
|
if (mesh.links[user._id] == null || (mesh.links[user._id].rights == 0)) { return; }
|
||||||
|
@ -1223,7 +1231,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
var user = obj.parent.users[ws.userid];
|
var user = obj.parent.users[ws.userid];
|
||||||
if (user) {
|
if (user) {
|
||||||
if (obj.parent.parent.multiServer == null) {
|
if (obj.parent.parent.multiServer == null) {
|
||||||
obj.parent.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: user.name, count: obj.parent.wssessions[ws.userid].length, nolog: 1, domain: obj.domain.id })
|
obj.parent.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: user.name, count: obj.parent.wssessions[ws.userid].length, nolog: 1, domain: obj.domain.id });
|
||||||
} else {
|
} else {
|
||||||
obj.parent.recountSessions(ws.sessionId); // Recount sessions
|
obj.parent.recountSessions(ws.sessionId); // Recount sessions
|
||||||
}
|
}
|
||||||
|
@ -1241,7 +1249,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
var httpport = ((obj.args.aliasport != null) ? obj.args.aliasport : obj.args.port);
|
var httpport = ((obj.args.aliasport != null) ? obj.args.aliasport : obj.args.port);
|
||||||
|
|
||||||
// Build server information object
|
// Build server information object
|
||||||
var serverinfo = { name: obj.parent.certificates.CommonName, mpsname: obj.parent.certificates.AmtMpsName, mpsport: mpsport, mpspass: obj.args.mpspass, port: httpport, emailcheck: obj.parent.parent.mailserver != null }
|
var serverinfo = { name: obj.parent.certificates.CommonName, mpsname: obj.parent.certificates.AmtMpsName, mpsport: mpsport, mpspass: obj.args.mpspass, port: httpport, emailcheck: obj.parent.parent.mailserver != null };
|
||||||
if (obj.args.notls == true) { serverinfo.https = false; } else { serverinfo.https = true; serverinfo.redirport = obj.args.redirport; }
|
if (obj.args.notls == true) { serverinfo.https = false; } else { serverinfo.https = true; serverinfo.redirport = obj.args.redirport; }
|
||||||
|
|
||||||
// Send server information
|
// Send server information
|
||||||
|
@ -1259,7 +1267,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
var r = {}, dir = obj.fs.readdirSync(path);
|
var r = {}, dir = obj.fs.readdirSync(path);
|
||||||
for (var i in dir) {
|
for (var i in dir) {
|
||||||
var f = { t: 3, d: 111 };
|
var f = { t: 3, d: 111 };
|
||||||
var stat = obj.fs.statSync(path + '/' + dir[i])
|
var stat = obj.fs.statSync(path + '/' + dir[i]);
|
||||||
if ((stat.mode & 0x004000) == 0) { f.s = stat.size; f.d = stat.mtime.getTime(); } else { f.t = 2; f.f = readFilesRec(path + '/' + dir[i]); }
|
if ((stat.mode & 0x004000) == 0) { f.s = stat.size; f.d = stat.mtime.getTime(); } else { f.t = 2; f.f = readFilesRec(path + '/' + dir[i]); }
|
||||||
r[dir[i]] = f;
|
r[dir[i]] = f;
|
||||||
}
|
}
|
||||||
|
@ -1316,7 +1324,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function EscapeHtml(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, '''); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
function EscapeHtml(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, '''); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
||||||
function EscapeHtmlBreaks(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, ''').replace(/\r/g, '<br />').replace(/\n/g, '').replace(/\t/g, ' '); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
//function EscapeHtmlBreaks(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, ''').replace(/\r/g, '<br />').replace(/\n/g, '').replace(/\t/g, ' '); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
};
|
|
@ -6,7 +6,12 @@
|
||||||
* @version v0.0.1
|
* @version v0.0.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
/*jslint node: true */
|
||||||
|
/*jshint node: true */
|
||||||
|
/*jshint strict:false */
|
||||||
|
/*jshint -W097 */
|
||||||
|
/*jshint esversion: 6 */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
// Construct a Mesh Multi-Server object. This is used for MeshCentral-to-MeshCentral communication.
|
// Construct a Mesh Multi-Server object. This is used for MeshCentral-to-MeshCentral communication.
|
||||||
module.exports.CreateMultiServer = function (parent, args) {
|
module.exports.CreateMultiServer = function (parent, args) {
|
||||||
|
@ -46,7 +51,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
obj.stop = function () {
|
obj.stop = function () {
|
||||||
obj.connectionState = 0;
|
obj.connectionState = 0;
|
||||||
disconnect();
|
disconnect();
|
||||||
}
|
};
|
||||||
|
|
||||||
// Make one attempt at connecting to the server
|
// Make one attempt at connecting to the server
|
||||||
function connect() {
|
function connect() {
|
||||||
|
@ -169,13 +174,13 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
if (typeof msg == 'object') { obj.ws.send(JSON.stringify(msg)); return; }
|
if (typeof msg == 'object') { obj.ws.send(JSON.stringify(msg)); return; }
|
||||||
if (typeof msg == 'string') { obj.ws.send(msg); return; }
|
if (typeof msg == 'string') { obj.ws.send(msg); return; }
|
||||||
} catch (e) { }
|
} catch (e) { }
|
||||||
}
|
};
|
||||||
|
|
||||||
// Process incoming peer server JSON data
|
// Process incoming peer server JSON data
|
||||||
function processServerData(msg) {
|
function processServerData(msg) {
|
||||||
var str = msg.toString('utf8');
|
var str = msg.toString('utf8'), command = null;
|
||||||
if (str[0] == '{') {
|
if (str[0] == '{') {
|
||||||
try { command = JSON.parse(str) } catch (e) { obj.parent.parent.debug(1, 'Unable to parse server JSON (' + obj.remoteaddr + ').'); return; } // If the command can't be parsed, ignore it.
|
try { command = JSON.parse(str); } catch (e) { obj.parent.parent.debug(1, 'Unable to parse server JSON (' + obj.remoteaddr + ').'); return; } // If the command can't be parsed, ignore it.
|
||||||
if (command.action == 'info') {
|
if (command.action == 'info') {
|
||||||
if (obj.authenticated != 3) {
|
if (obj.authenticated != 3) {
|
||||||
// We get the peer's serverid and database identifier.
|
// We get the peer's serverid and database identifier.
|
||||||
|
@ -198,7 +203,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
|
|
||||||
connect();
|
connect();
|
||||||
return obj;
|
return obj;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Create a mesh server module that received a connection to another server
|
// Create a mesh server module that received a connection to another server
|
||||||
obj.CreatePeerInServer = function (parent, ws, req) {
|
obj.CreatePeerInServer = function (parent, ws, req) {
|
||||||
|
@ -227,14 +232,14 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
if (typeof data == 'object') { obj.ws.send(JSON.stringify(data)); return; }
|
if (typeof data == 'object') { obj.ws.send(JSON.stringify(data)); return; }
|
||||||
obj.ws.send(data);
|
obj.ws.send(data);
|
||||||
} catch (e) { }
|
} catch (e) { }
|
||||||
}
|
};
|
||||||
|
|
||||||
// Disconnect this server
|
// Disconnect this server
|
||||||
obj.close = function (arg) {
|
obj.close = function (arg) {
|
||||||
if ((arg == 1) || (arg == null)) { try { obj.ws.close(); obj.parent.parent.debug(1, 'InPeer: Soft disconnect ' + obj.peerServerId + ' (' + obj.remoteaddr + ')'); } catch (e) { console.log(e); } } // Soft close, close the websocket
|
if ((arg == 1) || (arg == null)) { try { obj.ws.close(); obj.parent.parent.debug(1, 'InPeer: Soft disconnect ' + obj.peerServerId + ' (' + obj.remoteaddr + ')'); } catch (e) { console.log(e); } } // Soft close, close the websocket
|
||||||
if (arg == 2) { try { obj.ws._socket._parent.end(); obj.parent.parent.debug(1, 'InPeer: Hard disconnect ' + obj.peerServerId + ' (' + obj.remoteaddr + ')'); } catch (e) { console.log(e); } } // Hard close, close the TCP socket
|
if (arg == 2) { try { obj.ws._socket._parent.end(); obj.parent.parent.debug(1, 'InPeer: Hard disconnect ' + obj.peerServerId + ' (' + obj.remoteaddr + ')'); } catch (e) { console.log(e); } } // Hard close, close the TCP socket
|
||||||
if (obj.authenticated == 3) { obj.parent.ClearPeerServer(obj, obj.peerServerId); obj.authenticated = 0; }
|
if (obj.authenticated == 3) { obj.parent.ClearPeerServer(obj, obj.peerServerId); obj.authenticated = 0; }
|
||||||
}
|
};
|
||||||
|
|
||||||
// When data is received from the peer server web socket
|
// When data is received from the peer server web socket
|
||||||
ws.on('message', function (msg) {
|
ws.on('message', function (msg) {
|
||||||
|
@ -244,7 +249,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
if (obj.authenticated >= 2) { // We are authenticated
|
if (obj.authenticated >= 2) { // We are authenticated
|
||||||
if (msg.charCodeAt(0) == 123) { processServerData(msg); }
|
if (msg.charCodeAt(0) == 123) { processServerData(msg); }
|
||||||
if (msg.length < 2) return;
|
if (msg.length < 2) return;
|
||||||
var cmdid = obj.common.ReadShort(msg, 0);
|
//var cmdid = obj.common.ReadShort(msg, 0);
|
||||||
// Process binary commands (if any). None right now.
|
// Process binary commands (if any). None right now.
|
||||||
}
|
}
|
||||||
else if (obj.authenticated < 2) { // We are not authenticated
|
else if (obj.authenticated < 2) { // We are not authenticated
|
||||||
|
@ -259,14 +264,14 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
obj.peernonce = msg.substring(50);
|
obj.peernonce = msg.substring(50);
|
||||||
|
|
||||||
// Perform the hash signature using the server agent certificate
|
// Perform the hash signature using the server agent certificate
|
||||||
obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (signature) {
|
obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
|
||||||
// Send back our certificate + signature
|
// Send back our certificate + signature
|
||||||
obj2.send(obj2.common.ShortToStr(2) + obj.common.ShortToStr(obj2.agentCertificateAsn1.length) + obj2.agentCertificateAsn1 + signature); // Command 2, certificate + signature
|
obj2.send(obj2.common.ShortToStr(2) + obj2.common.ShortToStr(obj2.agentCertificateAsn1.length) + obj2.agentCertificateAsn1 + signature); // Command 2, certificate + signature
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check the peer server signature if we can
|
// Check the peer server signature if we can
|
||||||
if (obj.unauthsign != null) {
|
if (obj.unauthsign != null) {
|
||||||
if (processPeerSignature(obj.unauthsign) == false) { disconnect(); return; } else { completePeerServerConnection(); }
|
if (processPeerSignature(obj.unauthsign) == false) { obj.close(); return; } else { completePeerServerConnection(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cmd == 2) {
|
else if (cmd == 2) {
|
||||||
|
@ -337,9 +342,9 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
|
|
||||||
// Process incoming peer server JSON data
|
// Process incoming peer server JSON data
|
||||||
function processServerData(msg) {
|
function processServerData(msg) {
|
||||||
var str = msg.toString('utf8');
|
var str = msg.toString('utf8'), command = null;
|
||||||
if (str[0] == '{') {
|
if (str[0] == '{') {
|
||||||
try { command = JSON.parse(str) } catch (e) { obj.parent.parent.debug(1, 'Unable to parse server JSON (' + obj.remoteaddr + ').'); return; } // If the command can't be parsed, ignore it.
|
try { command = JSON.parse(str); } catch (e) { obj.parent.parent.debug(1, 'Unable to parse server JSON (' + obj.remoteaddr + ').'); return; } // If the command can't be parsed, ignore it.
|
||||||
if (command.action == 'info') {
|
if (command.action == 'info') {
|
||||||
if (obj.authenticated != 3) {
|
if (obj.authenticated != 3) {
|
||||||
// We get the peer's serverid and database identifier.
|
// We get the peer's serverid and database identifier.
|
||||||
|
@ -362,7 +367,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
};
|
||||||
|
|
||||||
// If we have no peering configuration, don't setup this object
|
// If we have no peering configuration, don't setup this object
|
||||||
if (obj.peerConfig == null) { return null; }
|
if (obj.peerConfig == null) { return null; }
|
||||||
|
@ -375,34 +380,34 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
var server = obj.peerServers[serverid];
|
var server = obj.peerServers[serverid];
|
||||||
if (server && server.peerServerKey) return server.peerServerKey;
|
if (server && server.peerServerKey) return server.peerServerKey;
|
||||||
return null;
|
return null;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Dispatch an event to all other MeshCentral2 peer servers
|
// Dispatch an event to all other MeshCentral2 peer servers
|
||||||
obj.DispatchEvent = function (ids, source, event) {
|
obj.DispatchEvent = function (ids, source, event) {
|
||||||
var busmsg = JSON.stringify({ action: 'bus', ids: ids, event: event });
|
var busmsg = JSON.stringify({ action: 'bus', ids: ids, event: event });
|
||||||
for (var serverid in obj.peerServers) { obj.peerServers[serverid].send(busmsg); }
|
for (var serverid in obj.peerServers) { obj.peerServers[serverid].send(busmsg); }
|
||||||
}
|
};
|
||||||
|
|
||||||
// Dispatch a message to other MeshCentral2 peer servers
|
// Dispatch a message to other MeshCentral2 peer servers
|
||||||
obj.DispatchMessage = function (msg) {
|
obj.DispatchMessage = function (msg) {
|
||||||
for (var serverid in obj.peerServers) { obj.peerServers[serverid].send(msg); }
|
for (var serverid in obj.peerServers) { obj.peerServers[serverid].send(msg); }
|
||||||
}
|
};
|
||||||
|
|
||||||
// Dispatch a message to other MeshCentral2 peer servers
|
// Dispatch a message to other MeshCentral2 peer servers
|
||||||
obj.DispatchMessageSingleServer = function (msg, serverid) {
|
obj.DispatchMessageSingleServer = function (msg, serverid) {
|
||||||
var server = obj.peerServers[serverid];
|
var server = obj.peerServers[serverid];
|
||||||
if (server != null) { server.send(msg); }
|
if (server != null) { server.send(msg); }
|
||||||
}
|
};
|
||||||
|
|
||||||
// Attempt to connect to all peers
|
// Attempt to connect to all peers
|
||||||
obj.ConnectToPeers = function () {
|
obj.ConnectToPeers = function () {
|
||||||
for (serverId in obj.peerConfig.servers) {
|
for (var serverId in obj.peerConfig.servers) {
|
||||||
// We will only connect to names that are larger then ours. This way, eveyone has one connection to everyone else (no cross-connections).
|
// We will only connect to names that are larger then ours. This way, eveyone has one connection to everyone else (no cross-connections).
|
||||||
if ((serverId > obj.serverid) && (obj.peerConfig.servers[serverId].url != null) && (obj.outPeerServers[serverId] == null)) {
|
if ((serverId > obj.serverid) && (obj.peerConfig.servers[serverId].url != null) && (obj.outPeerServers[serverId] == null)) {
|
||||||
obj.outPeerServers[serverId] = obj.CreatePeerOutServer(obj, serverId, obj.peerConfig.servers[serverId].url);
|
obj.outPeerServers[serverId] = obj.CreatePeerOutServer(obj, serverId, obj.peerConfig.servers[serverId].url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// We connected to a peer server, setup everything
|
// We connected to a peer server, setup everything
|
||||||
obj.SetupPeerServer = function (server, peerServerId) {
|
obj.SetupPeerServer = function (server, peerServerId) {
|
||||||
|
@ -414,7 +419,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
|
|
||||||
// Send a list of user sessions to the peer
|
// Send a list of user sessions to the peer
|
||||||
server.send(JSON.stringify({ action: 'sessionsTable', sessionsTable: Object.keys(obj.parent.webserver.wssessions2) }));
|
server.send(JSON.stringify({ action: 'sessionsTable', sessionsTable: Object.keys(obj.parent.webserver.wssessions2) }));
|
||||||
}
|
};
|
||||||
|
|
||||||
// We disconnected to a peer server, clean up everything
|
// We disconnected to a peer server, clean up everything
|
||||||
obj.ClearPeerServer = function (server, peerServerId) {
|
obj.ClearPeerServer = function (server, peerServerId) {
|
||||||
|
@ -431,10 +436,11 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
delete obj.parent.webserver.wsPeerSessions[peerServerId];
|
delete obj.parent.webserver.wsPeerSessions[peerServerId];
|
||||||
delete obj.parent.webserver.wsPeerSessions3[peerServerId];
|
delete obj.parent.webserver.wsPeerSessions3[peerServerId];
|
||||||
obj.parent.webserver.recountSessions(); // Recount all sessions
|
obj.parent.webserver.recountSessions(); // Recount all sessions
|
||||||
}
|
};
|
||||||
|
|
||||||
// Process a message coming from a peer server
|
// Process a message coming from a peer server
|
||||||
obj.ProcessPeerServerMessage = function (server, peerServerId, msg) {
|
obj.ProcessPeerServerMessage = function (server, peerServerId, msg) {
|
||||||
|
var userid, i;
|
||||||
//console.log('ProcessPeerServerMessage', peerServerId, msg);
|
//console.log('ProcessPeerServerMessage', peerServerId, msg);
|
||||||
switch (msg.action) {
|
switch (msg.action) {
|
||||||
case 'bus': {
|
case 'bus': {
|
||||||
|
@ -449,10 +455,10 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
case 'sessionsTable': {
|
case 'sessionsTable': {
|
||||||
obj.parent.webserver.wsPeerSessions[peerServerId] = msg.sessionsTable;
|
obj.parent.webserver.wsPeerSessions[peerServerId] = msg.sessionsTable;
|
||||||
var userToSession = {};
|
var userToSession = {};
|
||||||
for (var i in msg.sessionsTable) {
|
for (i in msg.sessionsTable) {
|
||||||
var sessionid = msg.sessionsTable[i];
|
var sessionid = msg.sessionsTable[i];
|
||||||
obj.parent.webserver.wsPeerSessions2[sessionid] = peerServerId;
|
obj.parent.webserver.wsPeerSessions2[sessionid] = peerServerId;
|
||||||
var userid = sessionid.split('/').slice(0, 3).join('/'); // Take the sessionid and keep only the userid partion
|
userid = sessionid.split('/').slice(0, 3).join('/'); // Take the sessionid and keep only the userid partion
|
||||||
if (userToSession[userid] == null) { userToSession[userid] = [sessionid]; } else { userToSession[userid].push(sessionid); } // UserId -> [ SessionId ]
|
if (userToSession[userid] == null) { userToSession[userid] = [sessionid]; } else { userToSession[userid].push(sessionid); } // UserId -> [ SessionId ]
|
||||||
}
|
}
|
||||||
obj.parent.webserver.wsPeerSessions3[peerServerId] = userToSession; // ServerId --> UserId --> SessionId
|
obj.parent.webserver.wsPeerSessions3[peerServerId] = userToSession; // ServerId --> UserId --> SessionId
|
||||||
|
@ -462,17 +468,17 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
case 'sessionStart': {
|
case 'sessionStart': {
|
||||||
obj.parent.webserver.wsPeerSessions[peerServerId].push(msg.sessionid);
|
obj.parent.webserver.wsPeerSessions[peerServerId].push(msg.sessionid);
|
||||||
obj.parent.webserver.wsPeerSessions2[msg.sessionid] = peerServerId;
|
obj.parent.webserver.wsPeerSessions2[msg.sessionid] = peerServerId;
|
||||||
var userid = msg.sessionid.split('/').slice(0, 3).join('/');
|
userid = msg.sessionid.split('/').slice(0, 3).join('/');
|
||||||
if (obj.parent.webserver.wsPeerSessions3[peerServerId] == null) { obj.parent.webserver.wsPeerSessions3[peerServerId] = {}; }
|
if (obj.parent.webserver.wsPeerSessions3[peerServerId] == null) { obj.parent.webserver.wsPeerSessions3[peerServerId] = {}; }
|
||||||
if (obj.parent.webserver.wsPeerSessions3[peerServerId][userid] == null) { obj.parent.webserver.wsPeerSessions3[peerServerId][userid] = [ msg.sessionid ]; } else { obj.parent.webserver.wsPeerSessions3[peerServerId][userid].push(msg.sessionid); }
|
if (obj.parent.webserver.wsPeerSessions3[peerServerId][userid] == null) { obj.parent.webserver.wsPeerSessions3[peerServerId][userid] = [msg.sessionid]; } else { obj.parent.webserver.wsPeerSessions3[peerServerId][userid].push(msg.sessionid); }
|
||||||
obj.parent.webserver.recountSessions(msg.sessionid); // Recount a specific user
|
obj.parent.webserver.recountSessions(msg.sessionid); // Recount a specific user
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'sessionEnd': {
|
case 'sessionEnd': {
|
||||||
var i = obj.parent.webserver.wsPeerSessions[peerServerId].indexOf(msg.sessionid);
|
i = obj.parent.webserver.wsPeerSessions[peerServerId].indexOf(msg.sessionid);
|
||||||
if (i >= 0) { obj.parent.webserver.wsPeerSessions[peerServerId].splice(i, 1); }
|
if (i >= 0) { obj.parent.webserver.wsPeerSessions[peerServerId].splice(i, 1); }
|
||||||
delete obj.parent.webserver.wsPeerSessions2[msg.sessionid];
|
delete obj.parent.webserver.wsPeerSessions2[msg.sessionid];
|
||||||
var userid = msg.sessionid.split('/').slice(0, 3).join('/');
|
userid = msg.sessionid.split('/').slice(0, 3).join('/');
|
||||||
if (obj.parent.webserver.wsPeerSessions3[peerServerId][userid] != null) {
|
if (obj.parent.webserver.wsPeerSessions3[peerServerId][userid] != null) {
|
||||||
i = obj.parent.webserver.wsPeerSessions3[peerServerId][userid].indexOf(msg.sessionid);
|
i = obj.parent.webserver.wsPeerSessions3[peerServerId][userid].indexOf(msg.sessionid);
|
||||||
if (i >= 0) {
|
if (i >= 0) {
|
||||||
|
@ -498,7 +504,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
// Yes, there is a waiting session, see if we must initiate.
|
// Yes, there is a waiting session, see if we must initiate.
|
||||||
if (peerServerId > obj.parent.serverId) {
|
if (peerServerId > obj.parent.serverId) {
|
||||||
// We must initiate the connection to the peer
|
// We must initiate the connection to the peer
|
||||||
var userid = null;
|
userid = null;
|
||||||
if (rsession.peer1.req.session != null) { userid = rsession.peer1.req.session.userid; }
|
if (rsession.peer1.req.session != null) { userid = rsession.peer1.req.session.userid; }
|
||||||
obj.createPeerRelay(rsession.peer1.ws, rsession.peer1.req, peerServerId, userid);
|
obj.createPeerRelay(rsession.peer1.ws, rsession.peer1.req, peerServerId, userid);
|
||||||
delete obj.parent.webserver.wsrelays[msg.id];
|
delete obj.parent.webserver.wsrelays[msg.id];
|
||||||
|
@ -509,33 +515,33 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
|
|
||||||
// Clear all relay sessions that are more than 1 minute
|
// Clear all relay sessions that are more than 1 minute
|
||||||
var oneMinuteAgo = Date.now() - 60000;
|
var oneMinuteAgo = Date.now() - 60000;
|
||||||
for (var id in obj.parent.webserver.wsPeerRelays) { if (obj.parent.webserver.wsPeerRelays[id].time < oneMinuteAgo) { delete obj.parent.webserver.wsPeerRelays[id]; } }
|
for (i in obj.parent.webserver.wsPeerRelays) { if (obj.parent.webserver.wsPeerRelays[i].time < oneMinuteAgo) { delete obj.parent.webserver.wsPeerRelays[i]; } }
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'msg': {
|
case 'msg': {
|
||||||
if (msg.sessionid != null) {
|
if (msg.sessionid != null) {
|
||||||
// Route this message to a connected user session
|
// Route this message to a connected user session
|
||||||
if (command.fromNodeid != null) { command.nodeid = command.fromNodeid; delete command.fromNodeid; }
|
if (msg.fromNodeid != null) { msg.nodeid = msg.fromNodeid; delete msg.fromNodeid; }
|
||||||
var ws = obj.parent.webserver.wssessions2[command.sessionid];
|
var ws = obj.parent.webserver.wssessions2[msg.sessionid];
|
||||||
if (ws != null) { ws.send(JSON.stringify(command)); }
|
if (ws != null) { ws.send(JSON.stringify(msg)); }
|
||||||
} else if (msg.nodeid != null) {
|
} else if (msg.nodeid != null) {
|
||||||
// Route this message to a connected agent
|
// Route this message to a connected agent
|
||||||
if (command.fromSessionid != null) { command.sessionid = command.fromSessionid; delete command.fromSessionid; }
|
if (msg.fromSessionid != null) { msg.sessionid = msg.fromSessionid; delete msg.fromSessionid; }
|
||||||
var agent = obj.parent.webserver.wsagents[msg.nodeid];
|
var agent = obj.parent.webserver.wsagents[msg.nodeid];
|
||||||
if (agent != null) { delete msg.nodeid; agent.send(JSON.stringify(msg)); } // Remove the nodeid since it's implyed and send the message to the agent
|
if (agent != null) { delete msg.nodeid; agent.send(JSON.stringify(msg)); } // Remove the nodeid since it's implyed and send the message to the agent
|
||||||
} else if (msg.meshid != null) {
|
} else if (msg.meshid != null) {
|
||||||
// Route this message to all users of this mesh
|
// Route this message to all users of this mesh
|
||||||
if (command.fromNodeid != null) { command.nodeid = command.fromNodeid; delete command.fromNodeid; }
|
if (msg.fromNodeid != null) { msg.nodeid = msg.fromNodeid; delete msg.fromNodeid; }
|
||||||
var cmdstr = JSON.stringify(command);
|
var cmdstr = JSON.stringify(msg);
|
||||||
for (var userid in obj.parent.webserver.wssessions) { // Find all connected users for this mesh and send the message
|
for (userid in obj.parent.webserver.wssessions) { // Find all connected users for this mesh and send the message
|
||||||
var user = obj.parent.webserver.users[userid];
|
var user = obj.parent.webserver.users[userid];
|
||||||
if (user) {
|
if (user) {
|
||||||
var rights = user.links[msg.meshid];
|
var rights = user.links[msg.meshid];
|
||||||
if (rights != null) { // TODO: Look at what rights are needed for message routing
|
if (rights != null) { // TODO: Look at what rights are needed for message routing
|
||||||
var sessions = obj.parent.webserver.wssessions[userid];
|
var sessions = obj.parent.webserver.wssessions[userid];
|
||||||
// Send the message to all users on this server
|
// Send the message to all users on this server
|
||||||
for (var i in sessions) { sessions[i].send(cmdstr); }
|
for (i in sessions) { sessions[i].send(cmdstr); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -543,7 +549,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Create a tunnel connection to a peer server
|
// Create a tunnel connection to a peer server
|
||||||
obj.createPeerRelay = function (ws, req, serverid, user) {
|
obj.createPeerRelay = function (ws, req, serverid, user) {
|
||||||
|
@ -558,7 +564,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
var path = req.path;
|
var path = req.path;
|
||||||
if (path[0] == '/') path = path.substring(1);
|
if (path[0] == '/') path = path.substring(1);
|
||||||
if (path.substring(path.length - 11) == '/.websocket') { path = path.substring(0, path.length - 11); }
|
if (path.substring(path.length - 11) == '/.websocket') { path = path.substring(0, path.length - 11); }
|
||||||
var queryStr = ''
|
var queryStr = '';
|
||||||
for (var i in req.query) { queryStr += ((queryStr == '') ? '?' : '&') + i + '=' + req.query[i]; }
|
for (var i in req.query) { queryStr += ((queryStr == '') ? '?' : '&') + i + '=' + req.query[i]; }
|
||||||
if (user != null) { queryStr += ((queryStr == '') ? '?' : '&') + 'auth=' + obj.parent.encodeCookie({ userid: user._id, domainid: user.domain }, cookieKey); }
|
if (user != null) { queryStr += ((queryStr == '') ? '?' : '&') + 'auth=' + obj.parent.encodeCookie({ userid: user._id, domainid: user.domain }, cookieKey); }
|
||||||
var url = obj.peerConfig.servers[serverid].url + path + queryStr;
|
var url = obj.peerConfig.servers[serverid].url + path + queryStr;
|
||||||
|
@ -566,7 +572,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
// Setup an connect the web socket
|
// Setup an connect the web socket
|
||||||
var tunnel = obj.createPeerRelayEx(ws, url, serverid);
|
var tunnel = obj.createPeerRelayEx(ws, url, serverid);
|
||||||
tunnel.connect();
|
tunnel.connect();
|
||||||
}
|
};
|
||||||
|
|
||||||
// Create a tunnel connection to a peer server
|
// Create a tunnel connection to a peer server
|
||||||
// We assume that "ws" is paused already.
|
// We assume that "ws" is paused already.
|
||||||
|
@ -610,7 +616,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
|
|
||||||
// If the web socket is closed, close the associated TCP connection.
|
// If the web socket is closed, close the associated TCP connection.
|
||||||
peerTunnel.ws1.on('close', function (req) { peerTunnel.parent.parent.debug(1, 'FTunnel disconnect ' + peerTunnel.serverid); peerTunnel.close(); });
|
peerTunnel.ws1.on('close', function (req) { peerTunnel.parent.parent.debug(1, 'FTunnel disconnect ' + peerTunnel.serverid); peerTunnel.close(); });
|
||||||
}
|
};
|
||||||
|
|
||||||
// Disconnect both sides of the tunnel
|
// Disconnect both sides of the tunnel
|
||||||
peerTunnel.close = function (arg) {
|
peerTunnel.close = function (arg) {
|
||||||
|
@ -623,11 +629,11 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||||
if (peerTunnel.ws1 != null) { try { peerTunnel.ws1.close(); peerTunnel.parent.parent.debug(1, 'FTunnel1: Soft disconnect '); } catch (e) { console.log(e); } }
|
if (peerTunnel.ws1 != null) { try { peerTunnel.ws1.close(); peerTunnel.parent.parent.debug(1, 'FTunnel1: Soft disconnect '); } catch (e) { console.log(e); } }
|
||||||
if (peerTunnel.ws2 != null) { try { peerTunnel.ws2.close(); peerTunnel.parent.parent.debug(1, 'FTunnel2: Soft disconnect '); } catch (e) { console.log(e); } }
|
if (peerTunnel.ws2 != null) { try { peerTunnel.ws2.close(); peerTunnel.parent.parent.debug(1, 'FTunnel2: Soft disconnect '); } catch (e) { console.log(e); } }
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return peerTunnel;
|
return peerTunnel;
|
||||||
}
|
};
|
||||||
|
|
||||||
setTimeout(function () { obj.ConnectToPeers(); }, 1000); // Delay this a little to make sure we are ready on our side.
|
setTimeout(function () { obj.ConnectToPeers(); }, 1000); // Delay this a little to make sure we are ready on our side.
|
||||||
return obj;
|
return obj;
|
||||||
}
|
};
|
7
pass.js
7
pass.js
|
@ -1,6 +1,11 @@
|
||||||
// check out https://github.com/tj/node-pwd
|
// check out https://github.com/tj/node-pwd
|
||||||
|
|
||||||
'use strict';
|
/*jslint node: true */
|
||||||
|
/*jshint node: true */
|
||||||
|
/*jshint strict:false */
|
||||||
|
/*jshint -W097 */
|
||||||
|
/*jshint esversion: 6 */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
// Module dependencies.
|
// Module dependencies.
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
|
|
|
@ -6,7 +6,12 @@
|
||||||
* @version v0.0.1
|
* @version v0.0.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
/*jslint node: true */
|
||||||
|
/*jshint node: true */
|
||||||
|
/*jshint strict:false */
|
||||||
|
/*jshint -W097 */
|
||||||
|
/*jshint esversion: 6 */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
// Construct a legacy Swarm Server server object
|
// Construct a legacy Swarm Server server object
|
||||||
module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
||||||
|
@ -18,7 +23,7 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
||||||
obj.legacyAgentConnections = {};
|
obj.legacyAgentConnections = {};
|
||||||
obj.migrationAgents = {};
|
obj.migrationAgents = {};
|
||||||
const common = require('./common.js');
|
const common = require('./common.js');
|
||||||
const net = require('net');
|
//const net = require('net');
|
||||||
const tls = require('tls');
|
const tls = require('tls');
|
||||||
const forge = require('node-forge');
|
const forge = require('node-forge');
|
||||||
|
|
||||||
|
@ -115,7 +120,7 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
||||||
USERAUTH2: 1031, // Authenticate a user to the swarm server (Uses SHA1 SALT)
|
USERAUTH2: 1031, // Authenticate a user to the swarm server (Uses SHA1 SALT)
|
||||||
GUESTREMOTEDESKTOP: 2001, // Guest usage: Remote Desktop
|
GUESTREMOTEDESKTOP: 2001, // Guest usage: Remote Desktop
|
||||||
GUESTWEBRTCMESH: 2002 // Guest usage: WebRTC Mesh
|
GUESTWEBRTCMESH: 2002 // Guest usage: WebRTC Mesh
|
||||||
}
|
};
|
||||||
|
|
||||||
obj.server = tls.createServer({ key: certificates.swarmserver.key, cert: certificates.swarmserver.cert, requestCert: true }, onConnection);
|
obj.server = tls.createServer({ key: certificates.swarmserver.key, cert: certificates.swarmserver.cert, requestCert: true }, onConnection);
|
||||||
obj.server.listen(args.swarmport, function () { console.log('MeshCentral Legacy Swarm Server running on ' + certificates.CommonName + ':' + args.swarmport + '.'); obj.parent.updateServerState('swarm-port', args.swarmport); }).on('error', function (err) { console.error('ERROR: MeshCentral Swarm Server server port ' + args.swarmport + ' is not available.'); if (args.exactports) { process.exit(); } });
|
obj.server.listen(args.swarmport, function () { console.log('MeshCentral Legacy Swarm Server running on ' + certificates.CommonName + ':' + args.swarmport + '.'); obj.parent.updateServerState('swarm-port', args.swarmport); }).on('error', function (err) { console.error('ERROR: MeshCentral Swarm Server server port ' + args.swarmport + ' is not available.'); if (args.exactports) { process.exit(); } });
|
||||||
|
@ -146,11 +151,11 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
||||||
socket.setEncoding('binary');
|
socket.setEncoding('binary');
|
||||||
socket.pingTimer = setInterval(function () { obj.SendCommand(socket, LegacyMeshProtocol.PING); }, 20000);
|
socket.pingTimer = setInterval(function () { obj.SendCommand(socket, LegacyMeshProtocol.PING); }, 20000);
|
||||||
Debug(1, 'SWARM:New legacy agent connection');
|
Debug(1, 'SWARM:New legacy agent connection');
|
||||||
|
|
||||||
socket.addListener("data", function (data) {
|
socket.addListener("data", function (data) {
|
||||||
if (args.swarmdebug) { var buf = new Buffer(data, "binary"); console.log('SWARM <-- (' + buf.length + '):' + buf.toString('hex')); } // Print out received bytes
|
if (args.swarmdebug) { var buf = new Buffer(data, "binary"); console.log('SWARM <-- (' + buf.length + '):' + buf.toString('hex')); } // Print out received bytes
|
||||||
socket.tag.accumulator += data;
|
socket.tag.accumulator += data;
|
||||||
|
|
||||||
// Detect if this is an HTTPS request, if it is, return a simple answer and disconnect. This is useful for debugging access to the MPS port.
|
// Detect if this is an HTTPS request, if it is, return a simple answer and disconnect. This is useful for debugging access to the MPS port.
|
||||||
if (socket.tag.first == true) {
|
if (socket.tag.first == true) {
|
||||||
if (socket.tag.accumulator.length < 3) return;
|
if (socket.tag.accumulator.length < 3) return;
|
||||||
|
@ -214,7 +219,7 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
||||||
Debug(3, 'Swarm:GETSTATE');
|
Debug(3, 'Swarm:GETSTATE');
|
||||||
if (len < 12) break;
|
if (len < 12) break;
|
||||||
var statecmd = common.ReadInt(data, 0);
|
var statecmd = common.ReadInt(data, 0);
|
||||||
var statesync = common.ReadInt(data, 4);
|
//var statesync = common.ReadInt(data, 4);
|
||||||
switch (statecmd) {
|
switch (statecmd) {
|
||||||
case 6: { // Ask for agent block
|
case 6: { // Ask for agent block
|
||||||
if (socket.tag.update != null) {
|
if (socket.tag.update != null) {
|
||||||
|
@ -247,14 +252,14 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.addListener("close", function () {
|
socket.addListener("close", function () {
|
||||||
Debug(1, 'Swarm:Connection closed');
|
Debug(1, 'Swarm:Connection closed');
|
||||||
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
|
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
|
||||||
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2);
|
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2);
|
||||||
if (socket.pingTimer != null) { clearInterval(socket.pingTimer); delete socket.pingTimer; }
|
if (socket.pingTimer != null) { clearInterval(socket.pingTimer); delete socket.pingTimer; }
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.addListener("error", function () {
|
socket.addListener("error", function () {
|
||||||
//console.log("Swarm Error: " + socket.remoteAddress);
|
//console.log("Swarm Error: " + socket.remoteAddress);
|
||||||
});
|
});
|
||||||
|
@ -311,19 +316,19 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Disconnect legacy agent connection
|
// Disconnect legacy agent connection
|
||||||
obj.close = function (socket) {
|
obj.close = function (socket) {
|
||||||
try { socket.close(); } catch (e) { }
|
try { socket.close(); } catch (e) { }
|
||||||
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
|
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
|
||||||
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2);
|
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2);
|
||||||
}
|
};
|
||||||
|
|
||||||
obj.SendCommand = function(socket, cmdid, data) {
|
obj.SendCommand = function (socket, cmdid, data) {
|
||||||
if (data == null) { data = ''; }
|
if (data == null) { data = ''; }
|
||||||
Write(socket, common.ShortToStr(cmdid) + common.ShortToStr(data.length + 4) + data);
|
Write(socket, common.ShortToStr(cmdid) + common.ShortToStr(data.length + 4) + data);
|
||||||
}
|
};
|
||||||
|
|
||||||
function Write(socket, data) {
|
function Write(socket, data) {
|
||||||
if (args.swarmdebug) {
|
if (args.swarmdebug) {
|
||||||
|
@ -335,7 +340,7 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
||||||
socket.write(new Buffer(data, "binary"));
|
socket.write(new Buffer(data, "binary"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
function Debug(lvl) {
|
function Debug(lvl) {
|
||||||
if (lvl > obj.parent.debugLevel) return;
|
if (lvl > obj.parent.debugLevel) return;
|
||||||
|
@ -348,4 +353,4 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
};
|
||||||
|
|
|
@ -2251,9 +2251,8 @@
|
||||||
var boundingBox = null;
|
var boundingBox = null;
|
||||||
for (var i in nodes) {
|
for (var i in nodes) {
|
||||||
try {
|
try {
|
||||||
var loc = map_parseNodeLoc(nodes[i]);
|
var loc = map_parseNodeLoc(nodes[i]), feature = xxmap.markersSource.getFeatureById(nodes[i]._id);
|
||||||
var feature = xxmap.markersSource.getFeatureById(nodes[i]._id);
|
if ((loc != null) && ((nodes[i].meshid == selectedMesh) || (selectedMesh == null))) { // Draw markers for devices with locations
|
||||||
if ((typeof loc == 'object') && ((nodes[i].meshid == selectedMesh) || (selectedMesh == null))) { // Draw markers for devices with locations
|
|
||||||
var lat = loc[0], lon = loc[1], type = loc[2];
|
var lat = loc[0], lon = loc[1], type = loc[2];
|
||||||
if (boundingBox == null) { boundingBox = [ lat, lon, lat, lon, 0 ]; } else { if (lat < boundingBox[0]) { boundingBox[0] = lat; } if (lon < boundingBox[1]) { boundingBox[1] = lon; } if (lat > boundingBox[2]) { boundingBox[2] = lat; } if (lon > boundingBox[3]) { boundingBox[3] = lon; } }
|
if (boundingBox == null) { boundingBox = [ lat, lon, lat, lon, 0 ]; } else { if (lat < boundingBox[0]) { boundingBox[0] = lat; } if (lon < boundingBox[1]) { boundingBox[1] = lon; } if (lat > boundingBox[2]) { boundingBox[2] = lat; } if (lon > boundingBox[3]) { boundingBox[3] = lon; } }
|
||||||
if (feature == null) { addFeature(nodes[i]); boundingBox[4] = 1; } else { updateFeature(nodes[i], feature); feature.setStyle(markerStyle(nodes[i], loc[2])); } // Update Feature
|
if (feature == null) { addFeature(nodes[i]); boundingBox[4] = 1; } else { updateFeature(nodes[i], feature); feature.setStyle(markerStyle(nodes[i], loc[2])); } // Update Feature
|
||||||
|
@ -2311,7 +2310,7 @@
|
||||||
if (node.wifiloc) { loc = node.wifiloc; t = 2; }
|
if (node.wifiloc) { loc = node.wifiloc; t = 2; }
|
||||||
if (node.gpsloc) { loc = node.gpsloc; t = 3; }
|
if (node.gpsloc) { loc = node.gpsloc; t = 3; }
|
||||||
if (node.userloc) { loc = node.userloc; t = 4; }
|
if (node.userloc) { loc = node.userloc; t = 4; }
|
||||||
if ((loc == null) || (typeof loc != 'string')) return;
|
if ((loc == null) || (typeof loc != 'string')) return null;
|
||||||
loc = loc.split(',');
|
loc = loc.split(',');
|
||||||
if (t == 1) {
|
if (t == 1) {
|
||||||
// If this is IP location, randomize the position a little.
|
// If this is IP location, randomize the position a little.
|
||||||
|
@ -2450,12 +2449,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since this is IP address location, add some fixed randomness to the location. Avoid pin pile-up.
|
// Since this is IP address location, add some fixed randomness to the location. Avoid pin pile-up.
|
||||||
var loc = map_parseNodeLoc(node); lat = loc[0]; lon = loc[1];
|
var loc = map_parseNodeLoc(node);
|
||||||
|
if (loc != null) {
|
||||||
if ((lat != feature.get('lat')) || (lon != feature.get('lon'))) { // Update lat and lon if changed
|
var lat = loc[0], lon = loc[1];
|
||||||
feature.set('lat', lat); feature.set('lon', lon);
|
if ((lat != feature.get('lat')) || (lon != feature.get('lon'))) { // Update lat and lon if changed
|
||||||
var modifiedCoordinates = ol.proj.transform([parseFloat(lon), parseFloat(lat)], 'EPSG:4326','EPSG:3857');
|
feature.set('lat', lat); feature.set('lon', lon);
|
||||||
feature.getGeometry().setCoordinates(modifiedCoordinates);
|
var modifiedCoordinates = ol.proj.transform([parseFloat(lon), parseFloat(lat)], 'EPSG:4326', 'EPSG:3857');
|
||||||
|
feature.getGeometry().setCoordinates(modifiedCoordinates);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.name != feature.get('name') ) { feature.set('name', node.name); } // Update name
|
if (node.name != feature.get('name') ) { feature.set('name', node.name); } // Update name
|
||||||
|
|
266
webserver.js
266
webserver.js
|
@ -6,7 +6,12 @@
|
||||||
* @version v0.0.1
|
* @version v0.0.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
/*jslint node: true */
|
||||||
|
/*jshint node: true */
|
||||||
|
/*jshint strict:false */
|
||||||
|
/*jshint -W097 */
|
||||||
|
/*jshint esversion: 6 */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
class SerialTunnel extends require('stream').Duplex {
|
class SerialTunnel extends require('stream').Duplex {
|
||||||
|
@ -22,9 +27,9 @@ class SerialTunnel extends require('stream').Duplex {
|
||||||
function SerialTunnel(options) {
|
function SerialTunnel(options) {
|
||||||
var obj = new require('stream').Duplex(options);
|
var obj = new require('stream').Duplex(options);
|
||||||
obj.forwardwrite = null;
|
obj.forwardwrite = null;
|
||||||
obj.updateBuffer = function (chunk) { this.push(chunk); }
|
obj.updateBuffer = function (chunk) { this.push(chunk); };
|
||||||
obj._write = function (chunk, encoding, callback) { if (obj.forwardwrite != null) { obj.forwardwrite(chunk); } else { console.err("Failed to fwd _write."); } if (callback) callback(); } // Pass data written to forward
|
obj._write = function (chunk, encoding, callback) { if (obj.forwardwrite != null) { obj.forwardwrite(chunk); } else { console.err("Failed to fwd _write."); } if (callback) callback(); }; // Pass data written to forward
|
||||||
obj._read = function(size) { } // Push nothing, anything to read should be pushed from updateBuffer()
|
obj._read = function (size) { }; // Push nothing, anything to read should be pushed from updateBuffer()
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +42,7 @@ if (!String.prototype.endsWith) { String.prototype.endsWith = function (searchSt
|
||||||
|
|
||||||
// Construct a HTTP web server object
|
// Construct a HTTP web server object
|
||||||
module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
var obj = {};
|
var obj = {}, i = 0;
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
obj.fs = require('fs');
|
obj.fs = require('fs');
|
||||||
|
@ -52,8 +57,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
obj.common = require('./common.js');
|
obj.common = require('./common.js');
|
||||||
obj.express = require('express');
|
obj.express = require('express');
|
||||||
obj.meshAgentHandler = require('./meshagent.js');
|
obj.meshAgentHandler = require('./meshagent.js');
|
||||||
obj.meshRelayHandler = require('./meshrelay.js')
|
obj.meshRelayHandler = require('./meshrelay.js');
|
||||||
obj.meshUserHandler = require('./meshuser.js')
|
obj.meshUserHandler = require('./meshuser.js');
|
||||||
obj.interceptor = require('./interceptor');
|
obj.interceptor = require('./interceptor');
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
|
@ -63,13 +68,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
obj.app = obj.express();
|
obj.app = obj.express();
|
||||||
obj.app.use(require('compression')());
|
obj.app.use(require('compression')());
|
||||||
obj.tlsServer = null;
|
obj.tlsServer = null;
|
||||||
obj.tcpServer;
|
obj.tcpServer = null;
|
||||||
obj.certificates = certificates;
|
obj.certificates = certificates;
|
||||||
obj.args = args;
|
obj.args = args;
|
||||||
obj.users = {};
|
obj.users = {};
|
||||||
obj.meshes = {};
|
obj.meshes = {};
|
||||||
obj.userAllowedIp = args.userallowedip; // List of allowed IP addresses for users
|
obj.userAllowedIp = args.userallowedip; // List of allowed IP addresses for users
|
||||||
obj.tlsSniCredentials;
|
obj.tlsSniCredentials = null;
|
||||||
obj.dnsDomains = {};
|
obj.dnsDomains = {};
|
||||||
//obj.agentConnCount = 0;
|
//obj.agentConnCount = 0;
|
||||||
|
|
||||||
|
@ -93,13 +98,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
|
|
||||||
// Setup SSPI authentication if needed
|
// Setup SSPI authentication if needed
|
||||||
if ((obj.parent.platform == 'win32') && (obj.args.nousers != true) && (obj.parent.config != null) && (obj.parent.config.domains != null)) {
|
if ((obj.parent.platform == 'win32') && (obj.args.nousers != true) && (obj.parent.config != null) && (obj.parent.config.domains != null)) {
|
||||||
for (var i in obj.parent.config.domains) { if (obj.parent.config.domains[i].auth == 'sspi') { var nodeSSPI = require('node-sspi'); obj.parent.config.domains[i].sspi = new nodeSSPI({ retrieveGroups: true, offerBasic: false }); } }
|
for (i in obj.parent.config.domains) { if (obj.parent.config.domains[i].auth == 'sspi') { var nodeSSPI = require('node-sspi'); obj.parent.config.domains[i].sspi = new nodeSSPI({ retrieveGroups: true, offerBasic: false }); } }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform hash on web certificate and agent certificate
|
// Perform hash on web certificate and agent certificate
|
||||||
obj.webCertificateHash = parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.certificates.web.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'binary' });
|
obj.webCertificateHash = parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.certificates.web.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'binary' });
|
||||||
obj.webCertificateHashs = { '': obj.webCertificateHash };
|
obj.webCertificateHashs = { '': obj.webCertificateHash };
|
||||||
for (var i in obj.parent.config.domains) { if (obj.parent.config.domains[i].dns != null) { obj.webCertificateHashs[i] = parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.parent.config.domains[i].certs.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'binary' }); } }
|
for (i in obj.parent.config.domains) { if (obj.parent.config.domains[i].dns != null) { obj.webCertificateHashs[i] = parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.parent.config.domains[i].certs.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'binary' }); } }
|
||||||
obj.webCertificateHashBase64 = new Buffer(parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.certificates.web.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'binary' }), 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
obj.webCertificateHashBase64 = new Buffer(parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.certificates.web.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'binary' }), 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
||||||
obj.agentCertificateHashHex = parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.certificates.agent.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'hex' });
|
obj.agentCertificateHashHex = parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.certificates.agent.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'hex' });
|
||||||
obj.agentCertificateHashBase64 = new Buffer(parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.certificates.agent.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'binary' }), 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
obj.agentCertificateHashBase64 = new Buffer(parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.certificates.agent.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'binary' }), 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
||||||
|
@ -130,13 +135,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
{
|
{
|
||||||
var dnscount = 0;
|
var dnscount = 0;
|
||||||
obj.tlsSniCredentials = {};
|
obj.tlsSniCredentials = {};
|
||||||
for (var i in obj.certificates.dns) { if (obj.parent.config.domains[i].dns != null) { obj.dnsDomains[obj.parent.config.domains[i].dns.toLowerCase()] = obj.parent.config.domains[i]; obj.tlsSniCredentials[obj.parent.config.domains[i].dns] = obj.tls.createSecureContext(obj.certificates.dns[i]).context; dnscount++; } }
|
for (i in obj.certificates.dns) { if (obj.parent.config.domains[i].dns != null) { obj.dnsDomains[obj.parent.config.domains[i].dns.toLowerCase()] = obj.parent.config.domains[i]; obj.tlsSniCredentials[obj.parent.config.domains[i].dns] = obj.tls.createSecureContext(obj.certificates.dns[i]).context; dnscount++; } }
|
||||||
if (dnscount > 0) { obj.tlsSniCredentials[''] = obj.tls.createSecureContext({ cert: obj.certificates.web.cert, key: obj.certificates.web.key, ca: obj.certificates.web.ca }).context; } else { obj.tlsSniCredentials = null; }
|
if (dnscount > 0) { obj.tlsSniCredentials[''] = obj.tls.createSecureContext({ cert: obj.certificates.web.cert, key: obj.certificates.web.key, ca: obj.certificates.web.ca }).context; } else { obj.tlsSniCredentials = null; }
|
||||||
}
|
}
|
||||||
function TlsSniCallback(name, cb) { var c = obj.tlsSniCredentials[name]; if (c != null) { cb(null, c); } else { cb(null, obj.tlsSniCredentials['']); } }
|
function TlsSniCallback(name, cb) { var c = obj.tlsSniCredentials[name]; if (c != null) { cb(null, c); } else { cb(null, obj.tlsSniCredentials['']); } }
|
||||||
|
|
||||||
function EscapeHtml(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, '''); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
function EscapeHtml(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, '''); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
||||||
function EscapeHtmlBreaks(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, ''').replace(/\r/g, '<br />').replace(/\n/g, '').replace(/\t/g, ' '); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
//function EscapeHtmlBreaks(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, ''').replace(/\r/g, '<br />').replace(/\n/g, '').replace(/\t/g, ' '); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
||||||
|
|
||||||
if (obj.args.notls || obj.args.tlsoffload) {
|
if (obj.args.notls || obj.args.tlsoffload) {
|
||||||
// Setup the HTTP server without TLS
|
// Setup the HTTP server without TLS
|
||||||
|
@ -172,27 +177,28 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
|
|
||||||
// Session-persisted message middleware
|
// Session-persisted message middleware
|
||||||
obj.app.use(function (req, res, next) {
|
obj.app.use(function (req, res, next) {
|
||||||
|
var err = null, msg = null, passhint = null;
|
||||||
if (req.session != null) {
|
if (req.session != null) {
|
||||||
var err = req.session.error;
|
err = req.session.error;
|
||||||
var msg = req.session.success;
|
msg = req.session.success;
|
||||||
var passhint = req.session.passhint;
|
passhint = req.session.passhint;
|
||||||
delete req.session.error;
|
delete req.session.error;
|
||||||
delete req.session.success;
|
delete req.session.success;
|
||||||
delete req.session.passhint;
|
delete req.session.passhint;
|
||||||
}
|
}
|
||||||
res.locals.message = '';
|
res.locals.message = '';
|
||||||
if (err) res.locals.message = '<p class="msg error">' + err + '</p>';
|
if (err != null) res.locals.message = '<p class="msg error">' + err + '</p>';
|
||||||
if (msg) res.locals.message = '<p class="msg success">' + msg + '</p>';
|
if (msg != null) res.locals.message = '<p class="msg success">' + msg + '</p>';
|
||||||
if (passhint) res.locals.passhint = EscapeHtml(passhint);
|
if (passhint != null) res.locals.passhint = EscapeHtml(passhint);
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fetch all users from the database, keep this in memory
|
// Fetch all users from the database, keep this in memory
|
||||||
obj.db.GetAllType('user', function (err, docs) {
|
obj.db.GetAllType('user', function (err, docs) {
|
||||||
var domainUserCount = {};
|
var domainUserCount = {}, i = 0;
|
||||||
for (var i in parent.config.domains) { domainUserCount[i] = 0; }
|
for (i in parent.config.domains) { domainUserCount[i] = 0; }
|
||||||
for (var i in docs) { var u = obj.users[docs[i]._id] = docs[i]; domainUserCount[u.domain]++; }
|
for (i in docs) { var u = obj.users[docs[i]._id] = docs[i]; domainUserCount[u.domain]++; }
|
||||||
for (var i in parent.config.domains) {
|
for (i in parent.config.domains) {
|
||||||
if (domainUserCount[i] == 0) {
|
if (domainUserCount[i] == 0) {
|
||||||
if (parent.config.domains[i].newaccounts == 0) { parent.config.domains[i].newaccounts = 2; }
|
if (parent.config.domains[i].newaccounts == 0) { parent.config.domains[i].newaccounts = 2; }
|
||||||
console.log('Server ' + ((i == '') ? '' : (i + ' ')) + 'has no users, next new account will be site administrator.');
|
console.log('Server ' + ((i == '') ? '' : (i + ' ')) + 'has no users, next new account will be site administrator.');
|
||||||
|
@ -237,7 +243,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
obj.restrict = function (req, res, next) {
|
obj.restrict = function (req, res, next) {
|
||||||
|
@ -249,7 +255,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
req.session.error = 'Access denied!';
|
req.session.error = 'Access denied!';
|
||||||
res.redirect(domain.url + 'login');
|
res.redirect(domain.url + 'login');
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Check if the source IP address is allowed for a given allowed list, return false if not
|
// Check if the source IP address is allowed for a given allowed list, return false if not
|
||||||
|
@ -287,8 +293,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
if (req.headers.host != null) { var d = obj.dnsDomains[req.headers.host.toLowerCase()]; if (d != null) return d; } // If this is a DNS name domain, return it here.
|
if (req.headers.host != null) { var d = obj.dnsDomains[req.headers.host.toLowerCase()]; if (d != null) return d; } // If this is a DNS name domain, return it here.
|
||||||
var x = req.url.split('/');
|
var x = req.url.split('/');
|
||||||
if (x.length < 2) return parent.config.domains[''];
|
if (x.length < 2) return parent.config.domains[''];
|
||||||
var d = parent.config.domains[x[1].toLowerCase()];
|
var y = parent.config.domains[x[1].toLowerCase()];
|
||||||
if ((d != null) && (d.dns == null)) return parent.config.domains[x[1].toLowerCase()];
|
if ((y != null) && (y.dns == null)) return parent.config.domains[x[1].toLowerCase()];
|
||||||
return parent.config.domains[''];
|
return parent.config.domains[''];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,8 +304,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' });
|
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' });
|
||||||
// Destroy the user's session to log them out will be re-created next request
|
// Destroy the user's session to log them out will be re-created next request
|
||||||
if (req.session.userid) {
|
if (req.session.userid) {
|
||||||
var user = obj.users[req.session.userid]
|
var user = obj.users[req.session.userid];
|
||||||
obj.parent.DispatchEvent(['*'], obj, { etype: 'user', username: user.name, action: 'logout', msg: 'Account logout', domain: domain.id })
|
obj.parent.DispatchEvent(['*'], obj, { etype: 'user', username: user.name, action: 'logout', msg: 'Account logout', domain: domain.id });
|
||||||
}
|
}
|
||||||
req.session = null;
|
req.session = null;
|
||||||
res.redirect(domain.url);
|
res.redirect(domain.url);
|
||||||
|
@ -319,35 +325,35 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
|
|
||||||
// Regenerate session when signing in to prevent fixation
|
// Regenerate session when signing in to prevent fixation
|
||||||
//req.session.regenerate(function () {
|
//req.session.regenerate(function () {
|
||||||
// Store the user's primary key in the session store to be retrieved, or in this case the entire user object
|
// Store the user's primary key in the session store to be retrieved, or in this case the entire user object
|
||||||
// req.session.success = 'Authenticated as ' + user.name + 'click to <a href="/logout">logout</a>. You may now access <a href="/restricted">/restricted</a>.';
|
// req.session.success = 'Authenticated as ' + user.name + 'click to <a href="/logout">logout</a>. You may now access <a href="/restricted">/restricted</a>.';
|
||||||
delete req.session.loginmode;
|
delete req.session.loginmode;
|
||||||
req.session.userid = userid;
|
req.session.userid = userid;
|
||||||
req.session.domainid = domain.id;
|
req.session.domainid = domain.id;
|
||||||
req.session.currentNode = '';
|
req.session.currentNode = '';
|
||||||
if (req.session.passhint) { delete req.session.passhint; }
|
if (req.session.passhint) { delete req.session.passhint; }
|
||||||
if (req.body.viewmode) { req.session.viewmode = req.body.viewmode; }
|
if (req.body.viewmode) { req.session.viewmode = req.body.viewmode; }
|
||||||
if (req.body.host) {
|
if (req.body.host) {
|
||||||
// TODO: This is a terrible search!!! FIX THIS.
|
// TODO: This is a terrible search!!! FIX THIS.
|
||||||
/*
|
/*
|
||||||
obj.db.GetAllType('node', function (err, docs) {
|
obj.db.GetAllType('node', function (err, docs) {
|
||||||
for (var i = 0; i < docs.length; i++) {
|
for (var i = 0; i < docs.length; i++) {
|
||||||
if (docs[i].name == req.body.host) {
|
if (docs[i].name == req.body.host) {
|
||||||
req.session.currentNode = docs[i]._id;
|
req.session.currentNode = docs[i]._id;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
console.log("CurrentNode: " + req.session.currentNode);
|
}
|
||||||
// This redirect happens after finding node is completed
|
console.log("CurrentNode: " + req.session.currentNode);
|
||||||
res.redirect(domain.url);
|
// This redirect happens after finding node is completed
|
||||||
});
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
res.redirect(domain.url);
|
res.redirect(domain.url);
|
||||||
}
|
});
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
res.redirect(domain.url);
|
||||||
|
}
|
||||||
//});
|
//});
|
||||||
|
|
||||||
obj.parent.DispatchEvent(['*'], obj, { etype: 'user', username: user.name, action: 'login', msg: 'Account login', domain: domain.id })
|
obj.parent.DispatchEvent(['*'], obj, { etype: 'user', username: user.name, action: 'login', msg: 'Account login', domain: domain.id });
|
||||||
} else {
|
} else {
|
||||||
delete req.session.loginmode;
|
delete req.session.loginmode;
|
||||||
if (err == 'locked') { req.session.error = '<b style=color:#8C001A>Account locked.</b>'; } else { req.session.error = '<b style=color:#8C001A>Login failed, check username and password.</b>'; }
|
if (err == 'locked') { req.session.error = '<b style=color:#8C001A>Account locked.</b>'; } else { req.session.error = '<b style=color:#8C001A>Login failed, check username and password.</b>'; }
|
||||||
|
@ -367,14 +373,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
if (domain.newaccounts == 0) { res.sendStatus(401); return; }
|
if (domain.newaccounts == 0) { res.sendStatus(401); return; }
|
||||||
if (!obj.common.validateUsername(req.body.username, 1, 64) || !obj.common.validateEmail(req.body.email, 1, 256) || !obj.common.validateString(req.body.password1, 1, 256) || !obj.common.validateString(req.body.password2, 1, 256) || (req.body.password1 != req.body.password2) || req.body.username == '~') {
|
if (!obj.common.validateUsername(req.body.username, 1, 64) || !obj.common.validateEmail(req.body.email, 1, 256) || !obj.common.validateString(req.body.password1, 1, 256) || !obj.common.validateString(req.body.password2, 1, 256) || (req.body.password1 != req.body.password2) || req.body.username == '~') {
|
||||||
req.session.loginmode = 2;
|
req.session.loginmode = 2;
|
||||||
req.session.error = '<b style=color:#8C001A>Unable to create account.</b>';;
|
req.session.error = '<b style=color:#8C001A>Unable to create account.</b>';
|
||||||
res.redirect(domain.url);
|
res.redirect(domain.url);
|
||||||
} else {
|
} else {
|
||||||
// Check if this email was already verified
|
// Check if this email was already verified
|
||||||
obj.db.GetUserWithVerifiedEmail(domain.id, req.body.email, function (err, docs) {
|
obj.db.GetUserWithVerifiedEmail(domain.id, req.body.email, function (err, docs) {
|
||||||
if (docs.length > 0) {
|
if (docs.length > 0) {
|
||||||
req.session.loginmode = 2;
|
req.session.loginmode = 2;
|
||||||
req.session.error = '<b style=color:#8C001A>Existing account with this email address.</b>';;
|
req.session.error = '<b style=color:#8C001A>Existing account with this email address.</b>';
|
||||||
res.redirect(domain.url);
|
res.redirect(domain.url);
|
||||||
} else {
|
} else {
|
||||||
// Check if there is domain.newAccountToken, check if supplied token is valid
|
// Check if there is domain.newAccountToken, check if supplied token is valid
|
||||||
|
@ -406,7 +412,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
obj.db.SetUser(user);
|
obj.db.SetUser(user);
|
||||||
if (obj.parent.mailserver != null) { obj.parent.mailserver.sendAccountCheckMail(domain, user.name, user.email); }
|
if (obj.parent.mailserver != null) { obj.parent.mailserver.sendAccountCheckMail(domain, user.name, user.email); }
|
||||||
});
|
});
|
||||||
obj.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: user.name, account: user, action: 'accountcreate', msg: 'Account created, email is ' + req.body.email, domain: domain.id })
|
obj.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: user.name, account: user, action: 'accountcreate', msg: 'Account created, email is ' + req.body.email, domain: domain.id });
|
||||||
}
|
}
|
||||||
res.redirect(domain.url);
|
res.redirect(domain.url);
|
||||||
}
|
}
|
||||||
|
@ -459,7 +465,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
} else {
|
} else {
|
||||||
obj.db.Get('user/' + cookie.u, function (err, docs) {
|
obj.db.Get('user/' + cookie.u, function (err, docs) {
|
||||||
if (docs.length == 0) {
|
if (docs.length == 0) {
|
||||||
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'ERROR: Invalid username \"' + EscapeHtml(user.name) + '\". <a href="' + domain.url + '">Go to login page</a>.' });
|
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'ERROR: Invalid username \"' + EscapeHtml(cookie.u) + '\". <a href="' + domain.url + '">Go to login page</a>.' });
|
||||||
} else {
|
} else {
|
||||||
var user = docs[0];
|
var user = docs[0];
|
||||||
if (user.email != cookie.e) {
|
if (user.email != cookie.e) {
|
||||||
|
@ -488,13 +494,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
delete userinfo.domain;
|
delete userinfo.domain;
|
||||||
delete userinfo.subscriptions;
|
delete userinfo.subscriptions;
|
||||||
delete userinfo.passtype;
|
delete userinfo.passtype;
|
||||||
obj.parent.DispatchEvent(['*', 'server-users', user._id], obj, { etype: 'user', username: userinfo.name, account: userinfo, action: 'accountchange', msg: 'Verified email of user ' + EscapeHtml(user.name) + ' (' + EscapeHtml(userinfo.email) + ')', domain: domain.id })
|
obj.parent.DispatchEvent(['*', 'server-users', user._id], obj, { etype: 'user', username: userinfo.name, account: userinfo, action: 'accountchange', msg: 'Verified email of user ' + EscapeHtml(user.name) + ' (' + EscapeHtml(userinfo.email) + ')', domain: domain.id });
|
||||||
|
|
||||||
// Send the confirmation page
|
// Send the confirmation page
|
||||||
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'Verified email <b>' + EscapeHtml(user.email) + '</b> for user account <b>' + EscapeHtml(user.name) + '</b>. <a href="' + domain.url + '">Go to login page</a>.' });
|
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: 'Verified email <b>' + EscapeHtml(user.email) + '</b> for user account <b>' + EscapeHtml(user.name) + '</b>. <a href="' + domain.url + '">Go to login page</a>.' });
|
||||||
|
|
||||||
// Send a notification
|
// Send a notification
|
||||||
obj.parent.DispatchEvent([user._id], obj, { action: 'notify', value: 'Email verified:<br /><b>' + EscapeHtml(userinfo.email) + '</b>.', nolog: 1 })
|
obj.parent.DispatchEvent([user._id], obj, { action: 'notify', value: 'Email verified:<br /><b>' + EscapeHtml(userinfo.email) + '</b>.', nolog: 1 });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -507,10 +513,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
obj.crypto.randomBytes(16, function (err, buf) {
|
obj.crypto.randomBytes(16, function (err, buf) {
|
||||||
var newpass = buf.toString('base64').split('=').join('').split('/').join('');
|
var newpass = buf.toString('base64').split('=').join('').split('/').join('');
|
||||||
require('./pass').hash(newpass, function (err, salt, hash) {
|
require('./pass').hash(newpass, function (err, salt, hash) {
|
||||||
|
var userinfo = null;
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
||||||
// Change the password
|
// Change the password
|
||||||
var userinfo = obj.users[user._id];
|
userinfo = obj.users[user._id];
|
||||||
userinfo.salt = salt;
|
userinfo.salt = salt;
|
||||||
userinfo.hash = hash;
|
userinfo.hash = hash;
|
||||||
userinfo.passchange = Date.now();
|
userinfo.passchange = Date.now();
|
||||||
|
@ -518,7 +525,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
obj.db.SetUser(userinfo);
|
obj.db.SetUser(userinfo);
|
||||||
|
|
||||||
// Event the change
|
// Event the change
|
||||||
var userinfo = obj.common.Clone(userinfo);
|
userinfo = obj.common.Clone(userinfo);
|
||||||
delete userinfo.hash;
|
delete userinfo.hash;
|
||||||
delete userinfo.passhint;
|
delete userinfo.passhint;
|
||||||
delete userinfo.salt;
|
delete userinfo.salt;
|
||||||
|
@ -526,7 +533,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
delete userinfo.domain;
|
delete userinfo.domain;
|
||||||
delete userinfo.subscriptions;
|
delete userinfo.subscriptions;
|
||||||
delete userinfo.passtype;
|
delete userinfo.passtype;
|
||||||
obj.parent.DispatchEvent(['*', 'server-users', user._id], obj, { etype: 'user', username: userinfo.name, account: userinfo, action: 'accountchange', msg: 'Password reset for user ' + EscapeHtml(user.name), domain: domain.id })
|
obj.parent.DispatchEvent(['*', 'server-users', user._id], obj, { etype: 'user', username: userinfo.name, account: userinfo, action: 'accountchange', msg: 'Password reset for user ' + EscapeHtml(user.name), domain: domain.id });
|
||||||
|
|
||||||
// Send the new password
|
// Send the new password
|
||||||
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: '<div>Password for account <b>' + EscapeHtml(user.name) + '</b> has been reset to:</div><div style=padding:14px;font-size:18px><b>' + EscapeHtml(newpass) + '</b></div>Login and go to the \"My Account\" tab to update your password. <a href="' + domain.url + '">Go to login page</a>.' });
|
res.render(obj.path.join(__dirname, 'views/message'), { title: domain.title, title2: domain.title2, title3: 'Account Verification', message: '<div>Password for account <b>' + EscapeHtml(user.name) + '</b> has been reset to:</div><div style=padding:14px;font-size:18px><b>' + EscapeHtml(newpass) + '</b></div>Login and go to the \"My Account\" tab to update your password. <a href="' + domain.url + '">Go to login page</a>.' });
|
||||||
|
@ -569,7 +576,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
if (mesh.links[escUserId] != null) { delete mesh.links[escUserId]; obj.db.Set(mesh); }
|
if (mesh.links[escUserId] != null) { delete mesh.links[escUserId]; obj.db.Set(mesh); }
|
||||||
// Notify mesh change
|
// Notify mesh change
|
||||||
var change = 'Removed user ' + user.name + ' from mesh ' + mesh.name;
|
var change = 'Removed user ' + user.name + ' from mesh ' + mesh.name;
|
||||||
obj.parent.DispatchEvent(['*', mesh._id, user._id, userid], obj, { etype: 'mesh', username: user.name, userid: userid, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id })
|
obj.parent.DispatchEvent(['*', mesh._id, user._id, userid], obj, { etype: 'mesh', username: user.name, userid: userid, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -582,7 +589,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
delete obj.users[user._id];
|
delete obj.users[user._id];
|
||||||
req.session = null;
|
req.session = null;
|
||||||
res.redirect(domain.url);
|
res.redirect(domain.url);
|
||||||
obj.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: user.name, action: 'accountremove', msg: 'Account removed', domain: domain.id })
|
obj.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: user.name, action: 'accountremove', msg: 'Account removed', domain: domain.id });
|
||||||
} else {
|
} else {
|
||||||
res.redirect(domain.url);
|
res.redirect(domain.url);
|
||||||
}
|
}
|
||||||
|
@ -609,7 +616,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
obj.db.SetUser(user);
|
obj.db.SetUser(user);
|
||||||
req.session.viewmode = 2;
|
req.session.viewmode = 2;
|
||||||
res.redirect(domain.url);
|
res.redirect(domain.url);
|
||||||
obj.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: user.name, action: 'passchange', msg: 'Account password changed: ' + user.name, domain: domain.id })
|
obj.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: user.name, action: 'passchange', msg: 'Account password changed: ' + user.name, domain: domain.id });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,11 +625,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
var domain = checkUserIpAddress(req, res);
|
var domain = checkUserIpAddress(req, res);
|
||||||
if (domain == null) return;
|
if (domain == null) return;
|
||||||
if (!obj.args) { res.sendStatus(500); return; }
|
if (!obj.args) { res.sendStatus(500); return; }
|
||||||
var domain = getDomain(req);
|
|
||||||
|
|
||||||
if ((domain.sspi != null) && ((req.query.login == null) || (obj.parent.loginCookieEncryptionKey == null))) {
|
if ((domain.sspi != null) && ((req.query.login == null) || (obj.parent.loginCookieEncryptionKey == null))) {
|
||||||
// Login using SSPI
|
// Login using SSPI
|
||||||
domain.sspi.authenticate(req, res, function (err) { if ((err != null) || (req.connection.user == null)) { res.end('Authentication Required...'); } else { handleRootRequestEx(req, res, domain); } })
|
domain.sspi.authenticate(req, res, function (err) { if ((err != null) || (req.connection.user == null)) { res.end('Authentication Required...'); } else { handleRootRequestEx(req, res, domain); } });
|
||||||
} else {
|
} else {
|
||||||
// Login using a different system
|
// Login using a different system
|
||||||
handleRootRequestEx(req, res, domain);
|
handleRootRequestEx(req, res, domain);
|
||||||
|
@ -630,7 +636,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleRootRequestEx(req, res, domain) {
|
function handleRootRequestEx(req, res, domain) {
|
||||||
var nologout = false;
|
var nologout = false, user = null, features = 0;
|
||||||
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' });
|
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' });
|
||||||
|
|
||||||
// Check if we have an incomplete domain name in the path
|
// Check if we have an incomplete domain name in the path
|
||||||
|
@ -676,15 +682,15 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
req.session.currentNode = '';
|
req.session.currentNode = '';
|
||||||
|
|
||||||
// Check if this user exists, create it if not.
|
// Check if this user exists, create it if not.
|
||||||
var user = obj.users[req.session.userid];
|
user = obj.users[req.session.userid];
|
||||||
if ((user == null) || (user.sid != req.session.usersid)) {
|
if ((user == null) || (user.sid != req.session.usersid)) {
|
||||||
// Create the domain user
|
// Create the domain user
|
||||||
var usercount = 0, user = { type: 'user', _id: req.session.userid, name: req.connection.user, domain: domain.id, sid: req.session.usersid };
|
var usercount = 0, user2 = { type: 'user', _id: req.session.userid, name: req.connection.user, domain: domain.id, sid: req.session.usersid };
|
||||||
for (var i in obj.users) { if (obj.users[i].domain == domain.id) { usercount++; } }
|
for (var i in obj.users) { if (obj.users[i].domain == domain.id) { usercount++; } }
|
||||||
if (usercount == 0) { user.siteadmin = 0xFFFFFFFF; } // If this is the first user, give the account site admin.
|
if (usercount == 0) { user2.siteadmin = 0xFFFFFFFF; } // If this is the first user, give the account site admin.
|
||||||
obj.users[req.session.userid] = user;
|
obj.users[req.session.userid] = user2;
|
||||||
obj.db.SetUser(user);
|
obj.db.SetUser(user2);
|
||||||
obj.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: req.connection.user, account: user, action: 'accountcreate', msg: 'Domain account created, user ' + req.connection.user, domain: domain.id })
|
obj.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: req.connection.user, account: user2, action: 'accountcreate', msg: 'Domain account created, user ' + req.connection.user, domain: domain.id });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -706,15 +712,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
} else if (req.query.node) {
|
} else if (req.query.node) {
|
||||||
currentNode = 'node/' + domain.id + '/' + req.query.node;
|
currentNode = 'node/' + domain.id + '/' + req.query.node;
|
||||||
}
|
}
|
||||||
var user;
|
var logoutcontrol = '';
|
||||||
var logoutcontrol;
|
if (obj.args.nousers != true) { logoutcontrol = 'Welcome ' + obj.users[req.session.userid].name + '.'; }
|
||||||
if (obj.args.nousers != true) {
|
|
||||||
user = obj.users[req.session.userid]
|
|
||||||
logoutcontrol = 'Welcome ' + user.name + '.';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Give the web page a list of supported server features
|
// Give the web page a list of supported server features
|
||||||
var features = 0;
|
features = 0;
|
||||||
if (obj.args.wanonly == true) { features += 1; } // WAN-only mode
|
if (obj.args.wanonly == true) { features += 1; } // WAN-only mode
|
||||||
if (obj.args.lanonly == true) { features += 2; } // LAN-only mode
|
if (obj.args.lanonly == true) { features += 2; } // LAN-only mode
|
||||||
if (obj.args.nousers == true) { features += 4; } // Single user mode
|
if (obj.args.nousers == true) { features += 4; } // Single user mode
|
||||||
|
@ -745,7 +747,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Send back the login application
|
// Send back the login application
|
||||||
var loginmode = req.session.loginmode, features = 0;
|
var loginmode = req.session.loginmode;
|
||||||
|
features = 0;
|
||||||
delete req.session.loginmode; // Clear this state, if the user hits refresh, we want to go back to the login page.
|
delete req.session.loginmode; // Clear this state, if the user hits refresh, we want to go back to the login page.
|
||||||
if ((parent.config != null) && (parent.config.settings != null) && (parent.config.settings.allowframing == true)) { features += 32; } // Allow site within iframe
|
if ((parent.config != null) && (parent.config.settings != null) && (parent.config.settings.allowframing == true)) { features += 32; } // Allow site within iframe
|
||||||
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
|
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
|
||||||
|
@ -900,7 +903,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
for (var i = 3; i < spliturl.length; i++) { if (obj.common.IsFilenameValid(spliturl[i]) == true) { path += '/' + spliturl[i]; filename = spliturl[i]; } else { res.sendStatus(404); return; } }
|
for (var i = 3; i < spliturl.length; i++) { if (obj.common.IsFilenameValid(spliturl[i]) == true) { path += '/' + spliturl[i]; filename = spliturl[i]; } else { res.sendStatus(404); return; } }
|
||||||
|
|
||||||
var stat = null;
|
var stat = null;
|
||||||
try { stat = obj.fs.statSync(path) } catch (e) { }
|
try { stat = obj.fs.statSync(path); } catch (e) { }
|
||||||
if ((stat != null) && ((stat.mode & 0x004000) == 0)) {
|
if ((stat != null) && ((stat.mode & 0x004000) == 0)) {
|
||||||
if (req.query.download == 1) {
|
if (req.query.download == 1) {
|
||||||
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + filename + '\"' });
|
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + filename + '\"' });
|
||||||
|
@ -923,9 +926,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
if (splitpath[1] != '') { serverpath += '-' + splitpath[1]; } // Add the domain if needed
|
if (splitpath[1] != '') { serverpath += '-' + splitpath[1]; } // Add the domain if needed
|
||||||
serverpath += ('/' + splitpath[0] + '-' + splitpath[2]);
|
serverpath += ('/' + splitpath[0] + '-' + splitpath[2]);
|
||||||
for (var i = 3; i < splitpath.length; i++) { if (obj.common.IsFilenameValid(splitpath[i]) == true) { serverpath += '/' + splitpath[i]; filename = splitpath[i]; } else { return null; } } // Check that each folder is correct
|
for (var i = 3; i < splitpath.length; i++) { if (obj.common.IsFilenameValid(splitpath[i]) == true) { serverpath += '/' + splitpath[i]; filename = splitpath[i]; } else { return null; } } // Check that each folder is correct
|
||||||
var fullpath = obj.path.resolve(obj.filespath, serverpath), quota = 0;
|
return { fullpath: obj.path.resolve(obj.filespath, serverpath), path: serverpath, name: filename, quota: obj.getQuota(objid, domain) };
|
||||||
return { fullpath: fullpath, path: serverpath, name: filename, quota: obj.getQuota(objid, domain) };
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// Return the maximum number of bytes allowed in the user account "My Files".
|
// Return the maximum number of bytes allowed in the user account "My Files".
|
||||||
obj.getQuota = function (objid, domain) {
|
obj.getQuota = function (objid, domain) {
|
||||||
|
@ -944,7 +946,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
return 1048576; // By default, the server will have a 1 meg limit on mesh accounts
|
return 1048576; // By default, the server will have a 1 meg limit on mesh accounts
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Download a file from the server
|
// Download a file from the server
|
||||||
function handleDownloadFile(req, res) {
|
function handleDownloadFile(req, res) {
|
||||||
|
@ -1014,7 +1016,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
obj.fs.mkdir(xfile.fullpath, function () {
|
obj.fs.mkdir(xfile.fullpath, function () {
|
||||||
// Write the file
|
// Write the file
|
||||||
obj.fs.writeFile(obj.path.join(xfile.fullpath, filename), filedata, function () {
|
obj.fs.writeFile(obj.path.join(xfile.fullpath, filename), filedata, function () {
|
||||||
obj.parent.DispatchEvent([user._id], obj, 'updatefiles') // Fire an event causing this user to update this files
|
obj.parent.DispatchEvent([user._id], obj, 'updatefiles'); // Fire an event causing this user to update this files
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})(xfile.fullpath, names[i], filedata);
|
})(xfile.fullpath, names[i], filedata);
|
||||||
|
@ -1027,7 +1029,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
var file = files.files[i], fpath = obj.path.join(xfile.fullpath, file.originalFilename);
|
var file = files.files[i], fpath = obj.path.join(xfile.fullpath, file.originalFilename);
|
||||||
if (obj.common.IsFilenameValid(file.originalFilename) && ((totalsize + file.size) < xfile.quota)) { // Check if quota would not be broken if we add this file
|
if (obj.common.IsFilenameValid(file.originalFilename) && ((totalsize + file.size) < xfile.quota)) { // Check if quota would not be broken if we add this file
|
||||||
obj.fs.rename(file.path, fpath, function () {
|
obj.fs.rename(file.path, fpath, function () {
|
||||||
obj.parent.DispatchEvent([user._id], obj, 'updatefiles') // Fire an event causing this user to update this files
|
obj.parent.DispatchEvent([user._id], obj, 'updatefiles'); // Fire an event causing this user to update this files
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
try { obj.fs.unlink(file.path); } catch (e) { }
|
try { obj.fs.unlink(file.path); } catch (e) { }
|
||||||
|
@ -1051,7 +1053,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
obj.parent.RemoveAllEventDispatch(target);
|
obj.parent.RemoveAllEventDispatch(target);
|
||||||
obj.parent.AddEventDispatch(subscriptions, target);
|
obj.parent.AddEventDispatch(subscriptions, target);
|
||||||
return subscriptions;
|
return subscriptions;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Handle a web socket relay request
|
// Handle a web socket relay request
|
||||||
function handleRelayWebSocket(ws, req) {
|
function handleRelayWebSocket(ws, req) {
|
||||||
|
@ -1143,13 +1145,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
// CIRA ---> TLS
|
// CIRA ---> TLS
|
||||||
Debug(3, 'Relay TLS CIRA data', data.length);
|
Debug(3, 'Relay TLS CIRA data', data.length);
|
||||||
if (data.length > 0) { try { ser.updateBuffer(Buffer.from(data, 'binary')); } catch (e) { } }
|
if (data.length > 0) { try { ser.updateBuffer(Buffer.from(data, 'binary')); } catch (e) { } }
|
||||||
}
|
};
|
||||||
|
|
||||||
// Handke CIRA tunnel state change
|
// Handke CIRA tunnel state change
|
||||||
chnl.onStateChange = function (ciraconn, state) {
|
chnl.onStateChange = function (ciraconn, state) {
|
||||||
Debug(2, 'Relay TLS CIRA state change', state);
|
Debug(2, 'Relay TLS CIRA state change', state);
|
||||||
if (state == 0) { try { ws.close(); } catch (e) { } }
|
if (state == 0) { try { ws.close(); } catch (e) { } }
|
||||||
}
|
};
|
||||||
|
|
||||||
// TLSSocket to encapsulate TLS communication, which then tunneled via SerialTunnel an then wrapped through CIRA APF
|
// TLSSocket to encapsulate TLS communication, which then tunneled via SerialTunnel an then wrapped through CIRA APF
|
||||||
var TLSSocket = require('tls').TLSSocket;
|
var TLSSocket = require('tls').TLSSocket;
|
||||||
|
@ -1199,18 +1201,18 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
ws.forwardclient.onStateChange = function (ciraconn, state) {
|
ws.forwardclient.onStateChange = function (ciraconn, state) {
|
||||||
Debug(2, 'Relay CIRA state change', state);
|
Debug(2, 'Relay CIRA state change', state);
|
||||||
if (state == 0) { try { ws.close(); } catch (e) { } }
|
if (state == 0) { try { ws.close(); } catch (e) { } }
|
||||||
}
|
};
|
||||||
|
|
||||||
ws.forwardclient.onData = function (ciraconn, data) {
|
ws.forwardclient.onData = function (ciraconn, data) {
|
||||||
Debug(4, 'Relay CIRA data', data.length);
|
Debug(4, 'Relay CIRA data', data.length);
|
||||||
if (ws.interceptor) { data = ws.interceptor.processAmtData(data); } // Run data thru interceptor
|
if (ws.interceptor) { data = ws.interceptor.processAmtData(data); } // Run data thru interceptor
|
||||||
if (data.length > 0) { try { ws.send(data); } catch (e) { } } // TODO: Add TLS support
|
if (data.length > 0) { try { ws.send(data); } catch (e) { } } // TODO: Add TLS support
|
||||||
}
|
};
|
||||||
|
|
||||||
ws.forwardclient.onSendOk = function (ciraconn) {
|
ws.forwardclient.onSendOk = function (ciraconn) {
|
||||||
// TODO: Flow control? (Dont' really need it with AMT, but would be nice)
|
// TODO: Flow control? (Dont' really need it with AMT, but would be nice)
|
||||||
//console.log('onSendOk');
|
//console.log('onSendOk');
|
||||||
}
|
};
|
||||||
|
|
||||||
// Fetch Intel AMT credentials & Setup interceptor
|
// Fetch Intel AMT credentials & Setup interceptor
|
||||||
if (req.query.p == 1) {
|
if (req.query.p == 1) {
|
||||||
|
@ -1345,7 +1347,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
var r = 0, dir;
|
var r = 0, dir;
|
||||||
try { dir = obj.fs.readdirSync(path); } catch (e) { return 0; }
|
try { dir = obj.fs.readdirSync(path); } catch (e) { return 0; }
|
||||||
for (var i in dir) {
|
for (var i in dir) {
|
||||||
var stat = obj.fs.statSync(path + '/' + dir[i])
|
var stat = obj.fs.statSync(path + '/' + dir[i]);
|
||||||
if ((stat.mode & 0x004000) == 0) { r += stat.size; } else { r += readTotalFileSize(path + '/' + dir[i]); }
|
if ((stat.mode & 0x004000) == 0) { r += stat.size; } else { r += readTotalFileSize(path + '/' + dir[i]); }
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -1359,15 +1361,15 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
if (obj.fs.lstatSync(pathx).isDirectory()) { deleteFolderRec(pathx); } else { obj.fs.unlinkSync(pathx); }
|
if (obj.fs.lstatSync(pathx).isDirectory()) { deleteFolderRec(pathx); } else { obj.fs.unlinkSync(pathx); }
|
||||||
});
|
});
|
||||||
obj.fs.rmdirSync(path);
|
obj.fs.rmdirSync(path);
|
||||||
};
|
}
|
||||||
|
|
||||||
// Handle Intel AMT events
|
// Handle Intel AMT events
|
||||||
// To subscribe, add "http://server:port/amtevents.ashx" to Intel AMT subscriptions.
|
// To subscribe, add "http://server:port/amtevents.ashx" to Intel AMT subscriptions.
|
||||||
obj.handleAmtEventRequest = function (req, res) {
|
obj.handleAmtEventRequest = function (req, res) {
|
||||||
var domain = getDomain(req);
|
var domain = getDomain(req);
|
||||||
try {
|
try {
|
||||||
if (req.headers['authorization']) {
|
if (req.headers.authorization) {
|
||||||
var authstr = req.headers['authorization'];
|
var authstr = req.headers.authorization;
|
||||||
if (authstr.substring(0, 7) == "Digest ") {
|
if (authstr.substring(0, 7) == "Digest ") {
|
||||||
var auth = obj.common.parseNameValueList(obj.common.quoteSplit(authstr.substring(7)));
|
var auth = obj.common.parseNameValueList(obj.common.quoteSplit(authstr.substring(7)));
|
||||||
if ((req.url === auth.uri) && (obj.httpAuthRealm === auth.realm) && (auth.opaque === obj.crypto.createHmac('SHA384', obj.httpAuthRandom).update(auth.nonce).digest('hex'))) {
|
if ((req.url === auth.uri) && (obj.httpAuthRealm === auth.realm) && (auth.opaque === obj.crypto.createHmac('SHA384', obj.httpAuthRandom).update(auth.nonce).digest('hex'))) {
|
||||||
|
@ -1436,7 +1438,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
res.set({ 'WWW-Authenticate': 'Digest realm="' + obj.httpAuthRealm + '", qop="auth,auth-int", nonce="' + nonce + '", opaque="' + opaque + '"' });
|
res.set({ 'WWW-Authenticate': 'Digest realm="' + obj.httpAuthRealm + '", qop="auth,auth-int", nonce="' + nonce + '", opaque="' + opaque + '"' });
|
||||||
res.sendStatus(401);
|
res.sendStatus(401);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// Handle a server backup request
|
// Handle a server backup request
|
||||||
function handleBackupRequest(req, res) {
|
function handleBackupRequest(req, res) {
|
||||||
|
@ -1541,11 +1543,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
// If the agentid is 3 or 4, check if we have a signed MeshCmd.exe
|
// If the agentid is 3 or 4, check if we have a signed MeshCmd.exe
|
||||||
if ((agentid == 3)) { // Signed Windows MeshCmd.exe x86
|
if ((agentid == 3)) { // Signed Windows MeshCmd.exe x86
|
||||||
var stats = null, meshCmdPath = obj.path.join(__dirname, 'agents', 'MeshCmd-signed.exe');
|
var stats = null, meshCmdPath = obj.path.join(__dirname, 'agents', 'MeshCmd-signed.exe');
|
||||||
try { stats = obj.fs.statSync(meshCmdPath) } catch (e) { }
|
try { stats = obj.fs.statSync(meshCmdPath); } catch (e) { }
|
||||||
if ((stats != null)) { res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshcmd' + ((req.query.meshcmd <= 3) ? '.exe' : '') }); res.sendFile(meshCmdPath); return; }
|
if ((stats != null)) { res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshcmd' + ((req.query.meshcmd <= 3) ? '.exe' : '') }); res.sendFile(meshCmdPath); return; }
|
||||||
} else if ((agentid == 4)) { // Signed Windows MeshCmd64.exe x64
|
} else if ((agentid == 4)) { // Signed Windows MeshCmd64.exe x64
|
||||||
var stats = null, meshCmd64Path = obj.path.join(__dirname, 'agents', 'MeshCmd64-signed.exe');
|
var stats = null, meshCmd64Path = obj.path.join(__dirname, 'agents', 'MeshCmd64-signed.exe');
|
||||||
try { stats = obj.fs.statSync(meshCmd64Path) } catch (e) { }
|
try { stats = obj.fs.statSync(meshCmd64Path); } catch (e) { }
|
||||||
if ((stats != null)) { res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshcmd' + ((req.query.meshcmd <= 4) ? '.exe' : '') }); res.sendFile(meshCmd64Path); return; }
|
if ((stats != null)) { res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshcmd' + ((req.query.meshcmd <= 4) ? '.exe' : '') }); res.sendFile(meshCmd64Path); return; }
|
||||||
}
|
}
|
||||||
// No signed agents, we are going to merge a new MeshCmd.
|
// No signed agents, we are going to merge a new MeshCmd.
|
||||||
|
@ -1581,7 +1583,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
serverId: obj.agentCertificateHashHex.toUpperCase(), // SHA384 of server HTTPS public key
|
serverId: obj.agentCertificateHashHex.toUpperCase(), // SHA384 of server HTTPS public key
|
||||||
serverHttpsHash: new Buffer(obj.webCertificateHash, 'binary').toString('hex').toUpperCase(), // SHA384 of server HTTPS certificate
|
serverHttpsHash: new Buffer(obj.webCertificateHash, 'binary').toString('hex').toUpperCase(), // SHA384 of server HTTPS certificate
|
||||||
debugLevel: 0
|
debugLevel: 0
|
||||||
}
|
};
|
||||||
if (user != null) { meshaction.username = user.name; }
|
if (user != null) { meshaction.username = user.name; }
|
||||||
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
|
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
|
||||||
if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; }
|
if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; }
|
||||||
|
@ -1596,7 +1598,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
serverId: obj.agentCertificateHashHex.toUpperCase(), // SHA384 of server HTTPS public key
|
serverId: obj.agentCertificateHashHex.toUpperCase(), // SHA384 of server HTTPS public key
|
||||||
serverHttpsHash: new Buffer(obj.webCertificateHash, 'binary').toString('hex').toUpperCase(), // SHA384 of server HTTPS certificate
|
serverHttpsHash: new Buffer(obj.webCertificateHash, 'binary').toString('hex').toUpperCase(), // SHA384 of server HTTPS certificate
|
||||||
debugLevel: 0
|
debugLevel: 0
|
||||||
}
|
};
|
||||||
if (user != null) { meshaction.username = user.name; }
|
if (user != null) { meshaction.username = user.name; }
|
||||||
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
|
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
|
||||||
if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; }
|
if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; }
|
||||||
|
@ -1619,7 +1621,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
response += '</table></body></html>';
|
response += '</table></body></html>';
|
||||||
res.send(response);
|
res.send(response);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Get the web server hostname. This may change if using a domain with a DNS name.
|
// Get the web server hostname. This may change if using a domain with a DNS name.
|
||||||
function getWebServerName(domain) {
|
function getWebServerName(domain) {
|
||||||
|
@ -1660,7 +1662,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
|
|
||||||
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshagent.msh' });
|
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshagent.msh' });
|
||||||
res.send(meshsettings);
|
res.send(meshsettings);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Add HTTP security headers to all responses
|
// Add HTTP security headers to all responses
|
||||||
obj.app.use(function (req, res, next) {
|
obj.app.use(function (req, res, next) {
|
||||||
|
@ -1785,7 +1787,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
// Check we have agent rights
|
// Check we have agent rights
|
||||||
var rights = user.links[agent.dbMeshKey].rights;
|
var rights = user.links[agent.dbMeshKey].rights;
|
||||||
if ((rights != null) && ((rights & MESHRIGHT_AGENTCONSOLE) != 0) && (user.siteadmin == 0xFFFFFFFF)) { agent.close(disconnectMode); }
|
if ((rights != null) && ((rights & MESHRIGHT_AGENTCONSOLE) != 0) && (user.siteadmin == 0xFFFFFFFF)) { agent.close(disconnectMode); }
|
||||||
}
|
};
|
||||||
|
|
||||||
// Send the core module to the mesh agent
|
// Send the core module to the mesh agent
|
||||||
obj.sendMeshAgentCore = function (user, domain, nodeid, core) {
|
obj.sendMeshAgentCore = function (user, domain, nodeid, core) {
|
||||||
|
@ -1815,7 +1817,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
agent.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0) + hash + core);
|
agent.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0) + hash + core);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Get the server path of a user or mesh object
|
// Get the server path of a user or mesh object
|
||||||
function getServerRootFilePath(obj) {
|
function getServerRootFilePath(obj) {
|
||||||
|
@ -1878,36 +1880,37 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
|
|
||||||
// Count sessions and event any changes
|
// Count sessions and event any changes
|
||||||
obj.recountSessions = function (changedSessionId) {
|
obj.recountSessions = function (changedSessionId) {
|
||||||
|
var userid, oldcount, newcount, x, serverid;
|
||||||
if (changedSessionId == null) {
|
if (changedSessionId == null) {
|
||||||
// Recount all sessions
|
// Recount all sessions
|
||||||
|
|
||||||
// Calculate the session count for all userid's
|
// Calculate the session count for all userid's
|
||||||
var newSessionsCount = {};
|
var newSessionsCount = {};
|
||||||
for (var userid in obj.wssessions) { newSessionsCount[userid] = obj.wssessions[userid].length; }
|
for (userid in obj.wssessions) { newSessionsCount[userid] = obj.wssessions[userid].length; }
|
||||||
for (var serverid in obj.wsPeerSessions3) {
|
for (serverid in obj.wsPeerSessions3) {
|
||||||
for (var userid in obj.wsPeerSessions3[serverid]) {
|
for (userid in obj.wsPeerSessions3[serverid]) {
|
||||||
var c = obj.wsPeerSessions3[serverid][userid].length;
|
x = obj.wsPeerSessions3[serverid][userid].length;
|
||||||
if (newSessionsCount[userid] == null) { newSessionsCount[userid] = c; } else { newSessionsCount[userid] += c; }
|
if (newSessionsCount[userid] == null) { newSessionsCount[userid] = x; } else { newSessionsCount[userid] += x; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// See what session counts have changed, event any changes
|
// See what session counts have changed, event any changes
|
||||||
for (var userid in newSessionsCount) {
|
for (userid in newSessionsCount) {
|
||||||
var newcount = newSessionsCount[userid];
|
newcount = newSessionsCount[userid];
|
||||||
var oldcount = obj.sessionsCount[userid];
|
oldcount = obj.sessionsCount[userid];
|
||||||
if (oldcount == null) { oldcount = 0; } else { delete obj.sessionsCount[userid]; }
|
if (oldcount == null) { oldcount = 0; } else { delete obj.sessionsCount[userid]; }
|
||||||
if (newcount != oldcount) {
|
if (newcount != oldcount) {
|
||||||
var x = userid.split('/');
|
x = userid.split('/');
|
||||||
obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: newcount, domain: x[1], nolog: 1, nopeers: 1 })
|
obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: newcount, domain: x[1], nolog: 1, nopeers: 1 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are any counts left in the old counts, event to zero
|
// If there are any counts left in the old counts, event to zero
|
||||||
for (var userid in obj.sessionsCount) {
|
for (userid in obj.sessionsCount) {
|
||||||
var oldcount = obj.sessionsCount[userid];
|
oldcount = obj.sessionsCount[userid];
|
||||||
if ((oldcount != null) && (oldcount != 0)) {
|
if ((oldcount != null) && (oldcount != 0)) {
|
||||||
var x = userid.split('/');
|
x = userid.split('/');
|
||||||
obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: 0, domain: x[1], nolog: 1, nopeers: 1 })
|
obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: 0, domain: x[1], nolog: 1, nopeers: 1 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1915,23 +1918,23 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
obj.sessionsCount = newSessionsCount;
|
obj.sessionsCount = newSessionsCount;
|
||||||
} else {
|
} else {
|
||||||
// Figure out the userid
|
// Figure out the userid
|
||||||
var userid = changedSessionId.split('/').slice(0, 3).join('/');
|
userid = changedSessionId.split('/').slice(0, 3).join('/');
|
||||||
|
|
||||||
// Recount only changedSessionId
|
// Recount only changedSessionId
|
||||||
var newcount = 0;
|
newcount = 0;
|
||||||
if (obj.wssessions[userid] != null) { newcount = obj.wssessions[userid].length; }
|
if (obj.wssessions[userid] != null) { newcount = obj.wssessions[userid].length; }
|
||||||
for (var serverid in obj.wsPeerSessions3) { if (obj.wsPeerSessions3[serverid][userid] != null) { newcount += obj.wsPeerSessions3[serverid][userid].length; } }
|
for (serverid in obj.wsPeerSessions3) { if (obj.wsPeerSessions3[serverid][userid] != null) { newcount += obj.wsPeerSessions3[serverid][userid].length; } }
|
||||||
var oldcount = obj.sessionsCount[userid];
|
oldcount = obj.sessionsCount[userid];
|
||||||
if (oldcount == null) { oldcount = 0; }
|
if (oldcount == null) { oldcount = 0; }
|
||||||
|
|
||||||
// If the count changed, update and event
|
// If the count changed, update and event
|
||||||
if (newcount != oldcount) {
|
if (newcount != oldcount) {
|
||||||
var x = userid.split('/');
|
x = userid.split('/');
|
||||||
obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: newcount, domain: x[1], nolog: 1, nopeers: 1 })
|
obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: newcount, domain: x[1], nolog: 1, nopeers: 1 });
|
||||||
obj.sessionsCount[userid] = newcount;
|
obj.sessionsCount[userid] = newcount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Return true if a mobile browser is detected.
|
// Return true if a mobile browser is detected.
|
||||||
// This code comes from "http://detectmobilebrowsers.com/" and was modified, This is free and unencumbered software released into the public domain. For more information, please refer to the http://unlicense.org/
|
// This code comes from "http://detectmobilebrowsers.com/" and was modified, This is free and unencumbered software released into the public domain. For more information, please refer to the http://unlicense.org/
|
||||||
|
@ -1943,5 +1946,4 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
};
|
||||||
|
|
|
@ -6,7 +6,12 @@
|
||||||
* @version v0.0.1
|
* @version v0.0.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
/*jslint node: true */
|
||||||
|
/*jshint node: true */
|
||||||
|
/*jshint strict:false */
|
||||||
|
/*jshint -W097 */
|
||||||
|
/*jshint esversion: 6 */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
// This module is only called when MeshCentral is running as a Windows service.
|
// This module is only called when MeshCentral is running as a Windows service.
|
||||||
// In this case, we don't want to start a child process, so we launch directly without arguments.
|
// In this case, we don't want to start a child process, so we launch directly without arguments.
|
||||||
|
|
Loading…
Reference in a new issue