Completed first pass with JsHint, updated windows MeshAgent.
Ylian Saint-Hilaire committed
Aug 30, 2018 at 12:05 UTC
562310bed1bb8e843db3b65efeec225d25a5f955
18 files changed
+664
-435
agents/MeshCmd-signed.exe
Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ
agents/MeshCmd64-signed.exe
Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ
agents/MeshService-signed.exe
Binary files a/agents/MeshService-signed.exe and b/agents/MeshService-signed.exe differ
agents/MeshService.exe
Binary files a/agents/MeshService.exe and b/agents/MeshService.exe differ
agents/MeshService64-signed.exe
Binary files a/agents/MeshService64-signed.exe and b/agents/MeshService64-signed.exe differ
agents/MeshService64.exe
Binary files a/agents/MeshService64.exe and b/agents/MeshService64.exe differ
agents/modules_meshcmd/promise.js
new
+185
@@ -0,0 +1,185 @@
1
+/*
2
+Copyright 2018 Intel Corporation
3
+
4
+Licensed under the Apache License, Version 2.0 (the "License");
5
+you may not use this file except in compliance with the License.
6
+You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+Unless required by applicable law or agreed to in writing, software
11
+distributed under the License is distributed on an "AS IS" BASIS,
12
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+See the License for the specific language governing permissions and
14
+limitations under the License.
15
+*/
16
+
17
+var refTable = {};
18
+
19
+function Promise(promiseFunc)
20
+{
21
+ this._ObjectID = 'promise';
22
+ this._internal = { promise: this, func: promiseFunc, completed: false, errors: false, completedArgs: [] };
23
+ require('events').EventEmitter.call(this._internal);
24
+ this._internal.on('_eventHook', function (eventName, eventCallback)
25
+ {
26
+ //console.log('hook', eventName, 'errors/' + this.errors + ' completed/' + this.completed);
27
+ var r = null;
28
+
29
+ if (eventName == 'resolved' && !this.errors && this.completed)
30
+ {
31
+ r = eventCallback.apply(this, this.completedArgs);
32
+ if(r!=null)
33
+ {
34
+ this.emit_returnValue('resolved', r);
35
+ }
36
+ }
37
+ if (eventName == 'rejected' && this.errors && this.completed)
38
+ {
39
+ eventCallback.apply(this, this.completedArgs);
40
+ }
41
+ if (eventName == 'settled' && this.completed)
42
+ {
43
+ eventCallback.apply(this, []);
44
+ }
45
+ });
46
+ this._internal.resolver = function _resolver()
47
+ {
48
+ _resolver._self.errors = false;
49
+ _resolver._self.completed = true;
50
+ _resolver._self.completedArgs = [];
51
+ var args = ['resolved'];
52
+ if (this.emit_returnValue && this.emit_returnValue('resolved') != null)
53
+ {
54
+ _resolver._self.completedArgs.push(this.emit_returnValue('resolved'));
55
+ args.push(this.emit_returnValue('resolved'));
56
+ }
57
+ else
58
+ {
59
+ for (var a in arguments)
60
+ {
61
+ _resolver._self.completedArgs.push(arguments[a]);
62
+ args.push(arguments[a]);
63
+ }
64
+ }
65
+ _resolver._self.emit.apply(_resolver._self, args);
66
+ _resolver._self.emit('settled');
67
+ };
68
+ this._internal.rejector = function _rejector()
69
+ {
70
+ _rejector._self.errors = true;
71
+ _rejector._self.completed = true;
72
+ _rejector._self.completedArgs = [];
73
+ var args = ['rejected'];
74
+ for (var a in arguments)
75
+ {
76
+ _rejector._self.completedArgs.push(arguments[a]);
77
+ args.push(arguments[a]);
78
+ }
79
+
80
+ _rejector._self.emit.apply(_rejector._self, args);
81
+ _rejector._self.emit('settled');
82
+ };
83
+ this.catch = function(func)
84
+ {
85
+ this._internal.once('settled', func);
86
+ }
87
+ this.finally = function (func)
88
+ {
89
+ this._internal.once('settled', func);
90
+ };
91
+ this.then = function (resolved, rejected)
92
+ {
93
+ if (resolved) { this._internal.once('resolved', resolved); }
94
+ if (rejected) { this._internal.once('rejected', rejected); }
95
+
96
+ var retVal = new Promise(function (r, j) { });
97
+
98
+ this._internal.once('resolved', retVal._internal.resolver);
99
+ this._internal.once('rejected', retVal._internal.rejector);
100
+ return (retVal);
101
+ };
102
+
103
+ this._internal.resolver._self = this._internal;
104
+ this._internal.rejector._self = this._internal;;
105
+
106
+ try
107
+ {
108
+ promiseFunc.call(this, this._internal.resolver, this._internal.rejector);
109
+ }
110
+ catch(e)
111
+ {
112
+ this._internal.errors = true;
113
+ this._internal.completed = true;
114
+ this._internal.completedArgs = [e];
115
+ this._internal.emit('rejected', e);
116
+ this._internal.emit('settled');
117
+ }
118
+
119
+ if(!this._internal.completed)
120
+ {
121
+ // Save reference of this object
122
+ refTable[this._internal._hashCode()] = this._internal;
123
+ this._internal.once('settled', function () { refTable[this._hashCode()] = null; });
124
+ }
125
+}
126
+
127
+Promise.resolve = function resolve()
128
+{
129
+ var retVal = new Promise(function (r, j) { });
130
+ var args = [];
131
+ for (var i in arguments)
132
+ {
133
+ args.push(arguments[i]);
134
+ }
135
+ retVal._internal.resolver.apply(retVal._internal, args);
136
+ return (retVal);
137
+};
138
+Promise.reject = function reject() {
139
+ var retVal = new Promise(function (r, j) { });
140
+ var args = [];
141
+ for (var i in arguments) {
142
+ args.push(arguments[i]);
143
+ }
144
+ retVal._internal.rejector.apply(retVal._internal, args);
145
+ return (retVal);
146
+};
147
+Promise.all = function all(promiseList)
148
+{
149
+ var ret = new Promise(function (res, rej)
150
+ {
151
+ this.__rejector = rej;
152
+ this.__resolver = res;
153
+ this.__promiseList = promiseList;
154
+ this.__done = false;
155
+ this.__count = 0;
156
+ });
157
+
158
+ for (var i in promiseList)
159
+ {
160
+ promiseList[i].then(function ()
161
+ {
162
+ // Success
163
+ if(++ret.__count == ret.__promiseList.length)
164
+ {
165
+ ret.__done = true;
166
+ ret.__resolver(ret.__promiseList);
167
+ }
168
+ }, function (arg)
169
+ {
170
+ // Failure
171
+ if(!ret.__done)
172
+ {
173
+ ret.__done = true;
174
+ ret.__rejector(arg);
175
+ }
176
+ });
177
+ }
178
+ if (promiseList.length == 0)
179
+ {
180
+ ret.__resolver(promiseList);
181
+ }
182
+ return (ret);
183
+};
184
+
185
+module.exports = Promise;
\ No newline at end of file
agents/modules_meshcmd/service-manager.js
+8
-21
@@ -109,29 +109,16 @@ function serviceManager()
109
}
110
return admin;
111
};
112
+ this.getProgramFolder = function getProgramFolder() {
113
+ if (require('os').arch() == 'x64') { // 64 bit Windows
114
+ if (this.GM.PointerSize == 4) { return process.env['ProgramFiles(x86)']; } // 32 Bit App
115
+ return process.env['ProgramFiles']; // 64 bit App
116
+ }
117
+ return process.env['ProgramFiles']; // 32 bit Windows
118
+ };
119
this.getServiceFolder = function getServiceFolder()
120
{
114
- var destinationFolder = null;
115
- if (require('os').arch() == 'x64')
116
- {
117
- // 64 bit Windows
118
- if (this.GM.PointerSize == 4)
119
- {
120
- // 32 Bit App
121
- destinationFolder = process.env['ProgramFiles(x86)'];
122
- }
123
- else
124
- {
125
- // 64 bit App
126
- destinationFolder = process.env['ProgramFiles'];
127
- }
128
- }
129
- else
130
- {
131
- // 32 bit Windows
132
- destinationFolder = process.env['ProgramFiles'];
133
- }
134
- return (destinationFolder + '\\mesh');
121
+ return this.getProgramFolder() + '\\mesh';
122
};
123
124
this.enumerateService = function () {
meshcentral.js
+96
-86
@@ -6,23 +6,29 @@
6
* @version v0.0.1
7
*/
8
9
-'use strict';
9
+/*xjslint node: true */
10
+/*xjslint plusplus: true */
11
+/*xjslint maxlen: 256 */
12
+/*jshint node: true */
13
+/*jshint strict: false */
14
+/*jshint esversion: 6 */
15
+"use strict";
16
17
// If app metrics is available
18
if (process.argv[2] == '--launch') { try { require('appmetrics-dash').monitor({ url: '/', title: 'MeshCentral', port: 88, host: '127.0.0.1' }); } catch (e) { } }
19
20
function CreateMeshCentralServer(config, args) {
21
var obj = {};
16
- obj.db;
17
- obj.webserver;
18
- obj.redirserver;
19
- obj.mpsserver;
20
- obj.swarmserver;
21
- obj.mailserver;
22
- obj.amtEventHandler;
23
- obj.amtScanner;
24
- obj.meshScanner;
25
- obj.letsencrypt;
22
+ obj.db = null;
23
+ obj.webserver = null;
24
+ obj.redirserver = null;
25
+ obj.mpsserver = null;
26
+ obj.swarmserver = null;
27
+ obj.mailserver = null;
28
+ obj.amtEventHandler = null;
29
+ obj.amtScanner = null;
30
+ obj.meshScanner = null;
31
+ obj.letsencrypt = null;
32
obj.eventsDispatch = {};
33
obj.fs = require('fs');
34
obj.path = require('path');
@@ -78,13 +84,14 @@ function CreateMeshCentralServer(config, args) {
84
85
// Start the Meshcentral server
86
obj.Start = function () {
87
+ var i;
88
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.
89
90
// Check for invalid arguments
91
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'];
92
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; } }
93
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; }
87
- 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.
94
+ 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.
95
96
if ((obj.args.help == true) || (obj.args['?'] == true)) {
97
console.log('MeshCentral2 Beta 2, a web-based remote computer management web portal.\r\n');
@@ -106,19 +113,19 @@ function CreateMeshCentralServer(config, args) {
113
console.log(' country and organization can optionaly be set.');
114
return;
115
}
109
-
116
+
117
// Check if we need to install, start, stop, remove ourself as a background service
118
if ((obj.service != null) && ((obj.args.install == true) || (obj.args.uninstall == true) || (obj.args.start == true) || (obj.args.stop == true) || (obj.args.restart == true))) {
119
var env = [], xenv = ['user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'exactport', 'debug'];
113
- 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.
114
- 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 });
120
+ 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.
121
+ 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 });
122
svc.on('install', function () { console.log('MeshCentral service installed.'); svc.start(); });
123
svc.on('uninstall', function () { console.log('MeshCentral service uninstalled.'); process.exit(); });
124
svc.on('start', function () { console.log('MeshCentral service started.'); process.exit(); });
125
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); } });
126
svc.on('alreadyinstalled', function () { console.log('MeshCentral service already installed.'); process.exit(); });
127
svc.on('invalidinstallation', function () { console.log('Invalid MeshCentral service installation.'); process.exit(); });
121
-
128
+
129
if (obj.args.install == true) { try { svc.install(); } catch (e) { logException(e); } }
130
if (obj.args.stop == true || obj.args.restart == true) { try { svc.stop(); } catch (e) { logException(e); } }
131
if (obj.args.start == true || obj.args.restart == true) { try { svc.start(); } catch (e) { logException(e); } }
@@ -132,7 +139,7 @@ function CreateMeshCentralServer(config, args) {
139
} else {
140
// if "--launch" is not specified, launch the server as a child process.
141
var startLine = '';
135
- for (var i in process.argv) {
142
+ for (i in process.argv) {
143
var arg = process.argv[i];
144
if (arg.length > 0) {
145
if (startLine.length > 0) startLine += ' ';
@@ -141,7 +148,7 @@ function CreateMeshCentralServer(config, args) {
148
}
149
obj.launchChildServer(startLine);
150
}
144
- }
151
+ };
152
153
// Launch MeshCentral as a child server and monitor it.
154
obj.launchChildServer = function (startLine) {
@@ -166,7 +173,7 @@ function CreateMeshCentralServer(config, args) {
173
console.log(error);
174
console.log('ERROR: MeshCentral failed with critical error, check MeshErrors.txt. Restarting in 5 seconds...');
175
setTimeout(function () { obj.launchChildServer(startLine); }, 5000);
169
- }
176
+ }
177
}
178
});
179
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) {
182
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');
183
});
184
xprocess.on('close', function (code) { if ((code != 0) && (code != 123)) { /* console.log("Exited with code " + code); */ } });
178
- }
185
+ };
186
187
// Get current and latest MeshCentral server versions using NPM
188
obj.getLatestServerVersion = function (callback) {
@@ -190,44 +197,45 @@ function CreateMeshCentralServer(config, args) {
197
if (code == 0) { try { latestVer = xprocess.data.split(' ').join('').split('\r').join('').split('\n').join(''); } catch (e) { } }
198
callback(obj.currentVer, latestVer);
199
});
193
- }
200
+ };
201
202
// Initiate server self-update
196
- obj.performServerUpdate = function () { console.log('Starting self upgrade...'); process.exit(200); }
203
+ obj.performServerUpdate = function () { console.log('Starting self upgrade...'); process.exit(200); };
204
205
// Initiate server self-update
199
- obj.performServerCertUpdate = function () { console.log('Updating server certificates...'); process.exit(200); }
206
+ obj.performServerCertUpdate = function () { console.log('Updating server certificates...'); process.exit(200); };
207
208
obj.StartEx = function () {
209
+ var i;
210
//var wincmd = require('node-windows');
211
//wincmd.list(function (svc) { console.log(svc); }, true);
204
-
212
+
213
// Write the server state
214
obj.updateServerState('state', 'starting');
215
216
// Look to see if data and/or file path is specified
217
if (obj.args.datapath) { obj.datapath = obj.args.datapath; }
218
if (obj.args.filespath) { obj.filespath = obj.args.filespath; }
211
-
219
+
220
// Read environment variables. For a subset of arguments, we allow them to be read from environment variables.
221
var xenv = ['user', 'port', 'mpsport', 'mpsaliasport', 'redirport', 'exactport', 'debug'];
214
- 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]]); } }
215
-
222
+ 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]]); } }
223
+
224
// Validate the domains, this is used for multi-hosting
225
if (obj.config.domains == null) { obj.config.domains = {}; }
226
if (obj.config.domains[''] == null) { obj.config.domains[''] = {}; }
227
if (obj.config.domains[''].dns != null) { console.log("ERROR: Default domain can't have a DNS name."); return; }
220
- 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;
228
+ 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;
229
var bannedDomains = ['public', 'private', 'images', 'scripts', 'styles', 'views']; // List of banned domains
222
- 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; } } }
223
- for (var i in obj.config.domains) {
230
+ 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; } } }
231
+ for (i in obj.config.domains) {
232
if (obj.config.domains[i].dns == null) { obj.config.domains[i].url = (i == '') ? '/' : ('/' + i + '/'); } else { obj.config.domains[i].url = '/'; }
233
obj.config.domains[i].id = i;
234
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(','); } }
235
}
236
237
// Log passed arguments into Windows Service Log
230
- //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); }
238
+ //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); }
239
240
// Look at passed in arguments
241
if ((obj.args.user != null) && (typeof obj.args.user != 'string')) { delete obj.args.user; }
@@ -269,12 +277,12 @@ function CreateMeshCentralServer(config, args) {
277
if (obj.args.dbimport == true) { obj.args.dbimport = obj.getConfigFilePath('meshcentral.db.json'); }
278
var json = null, json2 = "", badCharCount = 0;
279
try { json = obj.fs.readFileSync(obj.args.dbimport, { encoding: 'utf8' }); } catch (e) { console.log('Invalid JSON file: ' + obj.args.dbimport + '.'); process.exit(); }
272
- 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
280
+ 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
281
if (badCharCount > 0) { console.log(badCharCount + ' invalid character(s) where removed.'); }
282
try { json = JSON.parse(json2); } catch (e) { console.log('Invalid JSON format: ' + obj.args.dbimport + ': ' + e); process.exit(); }
283
if ((json == null) || (typeof json.length != 'number') || (json.length < 1)) { console.log('Invalid JSON format: ' + obj.args.dbimport + '.'); }
276
- 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
277
- //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
284
+ 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
285
+ //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
286
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(); }); });
287
return;
288
}
@@ -333,7 +341,7 @@ function CreateMeshCentralServer(config, args) {
341
obj.db.Get('dbconfig', function (err, dbconfig) {
342
if (dbconfig.length == 1) { obj.dbconfig = dbconfig[0]; } else { obj.dbconfig = { _id: 'dbconfig', version: 1 }; }
343
if (obj.dbconfig.amtWsEventSecret == null) { require('crypto').randomBytes(32, function (err, buf) { obj.dbconfig.amtWsEventSecret = buf.toString('hex'); obj.db.Set(obj.dbconfig); }); }
336
-
344
+
345
// This is used by the user to create a username/password for a Intel AMT WSMAN event subscription
346
if (obj.args.getwspass) {
347
if (obj.args.getwspass.length == 64) {
@@ -367,12 +375,12 @@ function CreateMeshCentralServer(config, args) {
375
}
376
});
377
});
370
- }
378
+ };
379
380
// Done starting the redirection server, go on to load the server certificates
381
obj.StartEx2 = function () {
382
// Load server certificates
375
- obj.certificateOperations = require('./certoperations.js').CertificateOperations()
383
+ obj.certificateOperations = require('./certoperations.js').CertificateOperations();
384
obj.certificateOperations.GetMeshServerCertificate(obj, obj.args, obj.config, function (certs) {
385
if (obj.config.letsencrypt == null) {
386
obj.StartEx3(certs); // Just use the configured certificates
@@ -387,10 +395,11 @@ function CreateMeshCentralServer(config, args) {
395
}
396
}
397
});
390
- }
398
+ };
399
400
// Start the server with the given certificates
401
obj.StartEx3 = function (certs) {
402
+ var i;
403
obj.certificates = certs;
404
obj.certificateOperations.acceleratorStart(certs); // Set the state of the accelerators
405
@@ -398,14 +407,14 @@ function CreateMeshCentralServer(config, args) {
407
if (obj.certificates.CommonName == 'un-configured') { console.log('Server name not configured, running in LAN-only mode.'); obj.args.lanonly = true; }
408
409
// Check that no sub-domains have the same DNS as the parent
401
- for (var i in obj.config.domains) {
410
+ for (i in obj.config.domains) {
411
if ((obj.config.domains[i].dns != null) && (obj.certificates.CommonName.toLowerCase() === obj.config.domains[i].dns.toLowerCase())) {
412
console.log("ERROR: Server sub-domain can't have same DNS name as the parent."); process.exit(0); return;
413
}
414
}
415
416
// Load the list of mesh agents and install scripts
408
- if (obj.args.noagentupdate == 1) { for (var i in obj.meshAgentsArchitectureNumbers) { obj.meshAgentsArchitectureNumbers[i].update = false; } }
417
+ if (obj.args.noagentupdate == 1) { for (i in obj.meshAgentsArchitectureNumbers) { obj.meshAgentsArchitectureNumbers[i].update = false; } }
418
obj.updateMeshAgentsTable(function () {
419
obj.updateMeshAgentInstallScripts();
420
@@ -460,7 +469,7 @@ function CreateMeshCentralServer(config, args) {
469
obj.maintenanceTimer = setInterval(obj.maintenanceActions, 1000 * 60 * 60); // Run this every hour
470
471
// Dispatch an event that the server is now running
463
- obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'started', msg: 'Server started' })
472
+ obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'started', msg: 'Server started' });
473
474
// Load the login cookie encryption key from the database if allowed
475
if ((obj.config) && (obj.config.settings) && (obj.config.settings.allowlogintoken == true)) {
@@ -473,12 +482,12 @@ function CreateMeshCentralServer(config, args) {
482
});
483
}
484
476
- obj.debug(1, 'Server started');
485
+ //obj.debug(1, 'Server started');
486
if (obj.args.nousers == true) { obj.updateServerState('nousers', '1'); }
487
obj.updateServerState('state', 'running');
488
});
489
});
481
- }
490
+ };
491
492
// Perform maintenance operations (called every hour)
493
obj.maintenanceActions = function () {
@@ -499,7 +508,7 @@ function CreateMeshCentralServer(config, args) {
508
509
// Perform other database cleanup
510
obj.db.cleanup();
502
- }
511
+ };
512
513
// Stop the Meshcentral server
514
obj.Stop = function (restoreFile) {
@@ -507,7 +516,7 @@ function CreateMeshCentralServer(config, args) {
516
if (!obj.db) return;
517
518
// Dispatch an event saying the server is now stopping
510
- obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'stopped', msg: 'Server stopped' })
519
+ obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'stopped', msg: 'Server stopped' });
520
521
// Set all nodes to power state of unknown (0)
522
var record = { type: 'power', time: Date.now(), node: '*', power: 0, s: 2 };
@@ -543,7 +552,7 @@ function CreateMeshCentralServer(config, args) {
552
});
553
}
554
});
546
- zipfile.on("end", function () { setTimeout(function () { fs.unlinkSync(restoreFile); process.exit(123); }); });
555
+ zipfile.on("end", function () { setTimeout(function () { obj.fs.unlinkSync(restoreFile); process.exit(123); }); });
556
});
557
} else {
558
obj.debug(1, 'Server stopped');
@@ -553,25 +562,25 @@ function CreateMeshCentralServer(config, args) {
562
563
// Update the server state
564
obj.updateServerState('state', 'stopped');
556
- }
565
+ };
566
567
// Event Dispatch
568
obj.AddEventDispatch = function (ids, target) {
569
obj.debug(3, 'AddEventDispatch', ids);
570
for (var i in ids) { var id = ids[i]; if (!obj.eventsDispatch[id]) { obj.eventsDispatch[id] = [target]; } else { obj.eventsDispatch[id].push(target); } }
562
- }
571
+ };
572
obj.RemoveEventDispatch = function (ids, target) {
573
obj.debug(3, 'RemoveEventDispatch', id);
565
- 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); } } }
566
- }
574
+ 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); } } }
575
+ };
576
obj.RemoveEventDispatchId = function (id) {
577
obj.debug(3, 'RemoveEventDispatchId', id);
578
if (obj.eventsDispatch[id] != null) { delete obj.eventsDispatch[id]; }
570
- }
579
+ };
580
obj.RemoveAllEventDispatch = function (target) {
581
obj.debug(3, 'RemoveAllEventDispatch');
582
for (var i in obj.eventsDispatch) { var j = obj.eventsDispatch[i].indexOf(target); if (j >= 0) { obj.eventsDispatch[i].splice(j, 1); } }
574
- }
583
+ };
584
obj.DispatchEvent = function (ids, source, event, fromPeerServer) {
585
// If the database is not setup, exit now.
586
if (!obj.db) return;
@@ -596,21 +605,21 @@ function CreateMeshCentralServer(config, args) {
605
}
606
}
607
if ((fromPeerServer == null) && (obj.multiServer != null) && ((typeof event != 'object') || (event.nopeers != 1))) { obj.multiServer.DispatchEvent(ids, source, event); }
599
- }
608
+ };
609
610
// Get the connection state of a node
602
- obj.GetConnectivityState = function (nodeid) { return obj.connectivityByNode[nodeid]; }
611
+ obj.GetConnectivityState = function (nodeid) { return obj.connectivityByNode[nodeid]; };
612
613
// Get the routing server id for a given node and connection type, can never be self.
614
obj.GetRoutingServerId = function (nodeid, connectType) {
615
if (obj.multiServer == null) return null;
607
- for (serverid in obj.peerConnectivityByNode) {
616
+ for (var serverid in obj.peerConnectivityByNode) {
617
if (serverid == obj.serverId) continue;
618
var state = obj.peerConnectivityByNode[serverid][nodeid];
619
if ((state != null) && ((state.connectivity & connectType) != 0)) { return { serverid: serverid, meshid: state.meshid }; }
620
}
621
return null;
613
- }
622
+ };
623
624
// Update the connection state of a node when in multi-server mode
625
// Update obj.connectivityByNode using obj.peerConnectivityByNode for the list of nodes in argument
@@ -618,8 +627,8 @@ function CreateMeshCentralServer(config, args) {
627
for (var nodeid in nodeids) {
628
var meshid = null, state = null, oldConnectivity = 0, oldPowerState = 0, newConnectivity = 0, newPowerState = 0;
629
var oldState = obj.connectivityByNode[nodeid];
621
- if (oldState != null) { meshid = oldState.meshid; oldConnectivity = oldState.connectivity; oldPowerState = oldState.powerState; }
622
- for (serverid in obj.peerConnectivityByNode) {
630
+ if (oldState != null) { meshid = oldState.meshid; oldConnectivity = oldState.connectivity; oldPowerState = oldState.powerState; }
631
+ for (var serverid in obj.peerConnectivityByNode) {
632
var peerState = obj.peerConnectivityByNode[serverid][nodeid];
633
if (peerState != null) {
634
if (state == null) {
@@ -652,7 +661,7 @@ function CreateMeshCentralServer(config, args) {
661
obj.DispatchEvent(['*', meshid], obj, { action: 'nodeconnect', meshid: meshid, nodeid: nodeid, conn: newConnectivity, pwr: newPowerState, nolog: 1, nopeers: 1 });
662
}
663
}
655
- }
664
+ };
665
666
// Set the connectivity state of a node and setup the server so that messages can be routed correctly.
667
// meshId: mesh identifier of format mesh/domain/meshidhex
@@ -660,8 +669,8 @@ function CreateMeshCentralServer(config, args) {
669
// connectTime: time of connection, milliseconds elapsed since the UNIX epoch.
670
// connectType: Bitmask, 1 = MeshAgent, 2 = Intel AMT CIRA, 4 = Intel AMT local.
671
// 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
663
- var connectTypeStrings = ['', 'MeshAgent', 'Intel AMT CIRA', '', 'Intel AMT local'];
664
- var powerStateStrings = ['Unknown', 'Powered', 'Sleep', 'Sleep', 'Deep Sleep', 'Hibernating', 'Soft-Off', 'Present'];
672
+ //var connectTypeStrings = ['', 'MeshAgent', 'Intel AMT CIRA', '', 'Intel AMT local'];
673
+ //var powerStateStrings = ['Unknown', 'Powered', 'Sleep', 'Sleep', 'Deep Sleep', 'Hibernating', 'Soft-Off', 'Present'];
674
obj.SetConnectivityState = function (meshid, nodeid, connectTime, connectType, powerState, serverid) {
675
//console.log('SetConnectivity for ' + nodeid.substring(0, 16) + ', Type: ' + connectTypeStrings[connectType] + ', Power: ' + powerStateStrings[powerState] + (serverid == null ? ('') : (', ServerId: ' + serverid)));
676
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) {
725
726
// Set node power state
727
if (connectType == 1) { state.agentPower = powerState; } else if (connectType == 2) { state.ciraPower = powerState; } else if (connectType == 4) { state.amtPower = powerState; }
719
- var powerState = 0;
728
+ var powerState = 0, oldPowerState = state.powerState;
729
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; }
730
if ((state.powerState == null) || (state.powerState != powerState)) {
731
state.powerState = powerState;
@@ -731,7 +740,7 @@ function CreateMeshCentralServer(config, args) {
740
var x = {}; x[nodeid] = 1;
741
obj.UpdateConnectivityState(x);
742
}
734
- }
743
+ };
744
745
// Clear the connectivity state of a node and setup the server so that messages can be routed correctly.
746
// meshId: mesh identifier of format mesh/domain/meshidhex
@@ -798,7 +807,7 @@ function CreateMeshCentralServer(config, args) {
807
var x = {}; x[nodeid] = 1;
808
obj.UpdateConnectivityState(x);
809
}
801
- }
810
+ };
811
812
// Update the default mesh core
813
obj.updateMeshCoreTimer = 'notset';
@@ -845,9 +854,9 @@ function CreateMeshCentralServer(config, args) {
854
obj.fs.watch(obj.path.join(meshcorePath, 'meshcore.js'), function (eventType, filename) {
855
if (obj.updateMeshCoreTimer != null) { clearTimeout(obj.updateMeshCoreTimer); obj.updateMeshCoreTimer = null; }
856
obj.updateMeshCoreTimer = setTimeout(function () { obj.updateMeshCore(); console.log('Updated meshcore.js.'); }, 5000);
848
- })
857
+ });
858
}
850
- }
859
+ };
860
861
// Update the default meshcmd
862
obj.updateMeshCmdTimer = 'notset';
@@ -860,7 +869,7 @@ function CreateMeshCentralServer(config, args) {
869
obj.defaultMeshCmd = null; if (func != null) { func(false); } // meshcmd.js not found
870
}
871
}
863
-
872
+
873
// Read meshcore.js and all .js files in the modules folder.
874
var moduleAdditions = 'var addedModules = [];', modulesDir = null;
875
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) {
895
obj.fs.watch(obj.path.join(meshcmdPath, 'meshcmd.js'), function (eventType, filename) {
896
if (obj.updateMeshCmdTimer != null) { clearTimeout(obj.updateMeshCmdTimer); obj.updateMeshCmdTimer = null; }
897
obj.updateMeshCmdTimer = setTimeout(function () { obj.updateMeshCmd(); console.log('Updated meshcmd.js.'); }, 5000);
889
- })
898
+ });
899
}
891
- }
900
+ };
901
902
// List of possible mesh agent install scripts
903
var meshAgentsInstallScriptList = {
@@ -903,7 +912,7 @@ function CreateMeshCentralServer(config, args) {
912
var stream = null;
913
try {
914
stream = obj.fs.createReadStream(scriptpath);
906
- stream.on('data', function (data) { this.hash.update(data, 'binary') });
915
+ stream.on('data', function (data) { this.hash.update(data, 'binary'); });
916
stream.on('error', function (data) {
917
// If there is an error reading this file, make sure this agent is not in the agent table
918
if (obj.meshAgentInstallScripts[this.info.id] != null) { delete obj.meshAgentInstallScripts[this.info.id]; }
@@ -915,7 +924,7 @@ function CreateMeshCentralServer(config, args) {
924
obj.meshAgentInstallScripts[this.info.id].path = this.agentpath;
925
obj.meshAgentInstallScripts[this.info.id].url = ((obj.args.notls == true) ? 'http://' : 'https://') + obj.certificates.CommonName + ':' + obj.args.port + '/meshagents?script=' + this.info.id;
926
var stats = null;
918
- try { stats = obj.fs.statSync(this.agentpath) } catch (e) { }
927
+ try { stats = obj.fs.statSync(this.agentpath); } catch (e) { }
928
if (stats != null) { obj.meshAgentInstallScripts[this.info.id].size = stats.size; }
929
});
930
stream.info = meshAgentsInstallScriptList[scriptid];
@@ -923,7 +932,7 @@ function CreateMeshCentralServer(config, args) {
932
stream.hash = obj.crypto.createHash('sha384', stream);
933
} catch (e) { }
934
}
926
- }
935
+ };
936
937
// List of possible mesh agents
938
obj.meshAgentsArchitectureNumbers = {
@@ -962,10 +971,10 @@ function CreateMeshCentralServer(config, args) {
971
var archcount = 0;
972
for (var archid in obj.meshAgentsArchitectureNumbers) {
973
var agentpath = obj.path.join(__dirname, 'agents', obj.meshAgentsArchitectureNumbers[archid].localname);
965
-
974
+
975
// Fetch all the agent binary information
976
var stats = null;
968
- try { stats = obj.fs.statSync(agentpath) } catch (e) { }
977
+ try { stats = obj.fs.statSync(agentpath); } catch (e) { }
978
if ((stats != null)) {
979
// If file exists
980
archcount++;
@@ -991,7 +1000,7 @@ function CreateMeshCentralServer(config, args) {
1000
}
1001
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.
1002
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.
994
- }
1003
+ };
1004
1005
// Generate a time limited user login token
1006
obj.getLoginToken = function (userid, func) {
@@ -1016,7 +1025,7 @@ function CreateMeshCentralServer(config, args) {
1025
});
1026
}
1027
});
1019
- }
1028
+ };
1029
1030
// Show the yser login token generation key
1031
obj.showLoginTokenKey = function (func) {
@@ -1031,13 +1040,13 @@ function CreateMeshCentralServer(config, args) {
1040
obj.db.Set({ _id: 'LoginCookieEncryptionKey', key: obj.loginCookieEncryptionKey.toString('hex'), time: Date.now() }, function () { func(obj.loginCookieEncryptionKey.toString('hex')); });
1041
}
1042
});
1034
- }
1043
+ };
1044
1045
// Generate a cryptographic key used to encode and decode cookies
1046
obj.generateCookieKey = function () {
1047
return new Buffer(obj.crypto.randomBytes(32), 'binary');
1048
//return Buffer.alloc(32, 0); // Sets the key to zeros, debug only.
1040
- }
1049
+ };
1050
1051
// Encode an object as a cookie using a key. (key must be 32 bytes long)
1052
obj.encodeCookie = function (o, key) {
@@ -1048,7 +1057,7 @@ function CreateMeshCentralServer(config, args) {
1057
var crypted = Buffer.concat([cipher.update(JSON.stringify(o), 'utf8'), cipher.final()]);
1058
return Buffer.concat([iv, cipher.getAuthTag(), crypted]).toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
1059
} catch (e) { return null; }
1051
- }
1060
+ };
1061
1062
// 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)
1063
obj.decodeCookie = function (cookie, key, timeout) {
@@ -1065,7 +1074,7 @@ function CreateMeshCentralServer(config, args) {
1074
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)
1075
return o;
1076
} catch (e) { return null; }
1068
- }
1077
+ };
1078
1079
// Debug
1080
obj.debug = function (lvl) {
@@ -1074,11 +1083,11 @@ function CreateMeshCentralServer(config, args) {
1083
else if (arguments.length == 3) { console.log(arguments[1], arguments[2]); }
1084
else if (arguments.length == 4) { console.log(arguments[1], arguments[2], arguments[3]); }
1085
else if (arguments.length == 5) { console.log(arguments[1], arguments[2], arguments[3], arguments[4]); }
1077
- }
1086
+ };
1087
1088
// Update server state. Writes a server state file.
1089
var meshServerState = {};
1081
- obj.updateServerState = function(name, val) {
1090
+ obj.updateServerState = function (name, val) {
1091
if ((name != null) && (val != null)) {
1092
var changed = false;
1093
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) {
1096
var r = 'time=' + Date.now() + '\r\n';
1097
for (var i in meshServerState) { r += (i + '=' + meshServerState[i] + '\r\n'); }
1098
obj.fs.writeFileSync(obj.getConfigFilePath('serverstate.txt'), r);
1090
- }
1099
+ };
1100
1101
// Logging funtions
1102
function logException(e) { e += ''; logErrorEvent(e); }
@@ -1124,7 +1133,7 @@ function CreateMeshCentralServer(config, args) {
1133
}
1134
//console.log('getConfigFilePath(\"' + filename + '\") = ' + obj.path.join(obj.datapath, filename));
1135
return obj.path.join(obj.datapath, filename);
1127
- }
1136
+ };
1137
1138
return obj;
1139
}
@@ -1132,6 +1141,7 @@ function CreateMeshCentralServer(config, args) {
1141
// Return the server configuration
1142
function getConfig() {
1143
// Figure out the datapath location
1144
+ var i;
1145
var fs = require('fs');
1146
var path = require('path');
1147
var datapath = null;
@@ -1150,7 +1160,7 @@ function getConfig() {
1160
// Load and validate the configuration file
1161
try { config = require(configFilePath); } catch (e) { console.log('ERROR: Unable to parse ' + configFilePath + '.'); return null; }
1162
if (config.domains == null) { config.domains = {}; }
1153
- 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; } }
1163
+ 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; } }
1164
} else {
1165
// Copy the "sample-config.json" to give users a starting point
1166
var sampleConfigPath = path.join(__dirname, 'sample-config.json');
@@ -1159,7 +1169,7 @@ function getConfig() {
1169
1170
// Set the command line arguments to the config file if they are not present
1171
if (!config.settings) { config.settings = {}; }
1162
- for (var i in args) { config.settings[i] = args[i]; }
1172
+ for (i in args) { config.settings[i] = args[i]; }
1173
1174
// Lower case all keys in the config file
1175
require('./common.js').objKeysToLower(config);
meshrelay.js
+14
-8
@@ -6,7 +6,12 @@
6
* @version v0.0.1
7
*/
8
9
-'use strict';
9
+/*jslint node: true */
10
+/*jshint node: true */
11
+/*jshint strict:false */
12
+/*jshint -W097 */
13
+/*jshint esversion: 6 */
14
+"use strict";
15
16
module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
17
var obj = {};
@@ -23,9 +28,10 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
28
obj.close = function (arg) {
29
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
30
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
26
- }
31
+ };
32
33
obj.sendAgentMessage = function (command, userid, domainid) {
34
+ var rights;
35
if (command.nodeid == null) return false;
36
var user = obj.parent.users[userid];
37
if (user == null) return false;
@@ -37,7 +43,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
43
var agent = obj.parent.wsagents[command.nodeid];
44
if (agent != null) {
45
// Check if we have permission to send a message to that node
40
- var rights = user.links[agent.dbMeshKey];
46
+ rights = user.links[agent.dbMeshKey];
47
if (rights != null || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking
48
command.sessionid = ws.sessionId; // Set the session id, required for responses.
49
command.rights = rights.rights; // Add user rights flags to the message
@@ -50,7 +56,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
56
var routing = obj.parent.parent.GetRoutingServerId(command.nodeid, 1); // 1 = MeshAgent routing type
57
if (routing != null) {
58
// Check if we have permission to send a message to that node
53
- var rights = user.links[routing.meshid];
59
+ rights = user.links[routing.meshid];
60
if (rights != null || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking
61
command.fromSessionid = ws.sessionId; // Set the session id, required for responses.
62
command.rights = rights.rights; // Add user rights flags to the message
@@ -61,7 +67,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
67
}
68
}
69
return false;
64
- }
70
+ };
71
72
if (req.query.auth == null) {
73
// 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) {
166
// Wait for other relay connection
167
ws.pause(); // Hold traffic until the other connection
168
parent.wsrelays[obj.id] = { peer1: obj, state: 1 };
163
- obj.parent.parent.debug(1, 'Relay holding: ' + obj.id + ' (' + obj.remoteaddr + ') ' + (obj.authenticated?'Authenticated':'') );
169
+ obj.parent.parent.debug(1, 'Relay holding: ' + obj.id + ' (' + obj.remoteaddr + ') ' + (obj.authenticated ? 'Authenticated' : ''));
170
171
// Check if a peer server has this connection
172
if (parent.parent.multiServer != null) {
@@ -213,6 +219,6 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
219
obj.id = null;
220
}
221
});
216
-
222
+
223
return obj;
218
-}
224
+};
meshscanner.js
+40
-31
@@ -6,7 +6,12 @@
6
* @version v0.0.1
7
*/
8
9
-'use strict';
9
+/*jslint node: true */
10
+/*jshint node: true */
11
+/*jshint strict:false */
12
+/*jshint -W097 */
13
+/*jshint esversion: 6 */
14
+"use strict";
15
16
// Construct a Mesh Scanner object
17
// 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) {
31
32
// Get a list of IPv4 and IPv6 interface addresses
33
function getInterfaceList() {
34
+ var i;
35
var ipv4 = ['*'], ipv6 = ['*']; // Bind to IN_ADDR_ANY always
36
var interfaces = require('os').networkInterfaces();
31
- for (var i in interfaces) {
37
+ for (i in interfaces) {
38
var xinterface = interfaces[i];
39
for (var j in xinterface) {
40
var interface2 = xinterface[j];
@@ -43,11 +49,11 @@ module.exports.CreateMeshScanner = function (parent) {
49
50
// Setup all IPv4 and IPv6 servers
51
function setupServers() {
46
- var addresses = getInterfaceList();
47
- for (var i in obj.servers4) { obj.servers4[i].xxclear = true; }
48
- for (var i in obj.servers6) { obj.servers6[i].xxclear = true; }
49
- for (var i in addresses.ipv4) {
50
- var localAddress = addresses.ipv4[i];
52
+ var addresses = getInterfaceList(), i, localAddress, bindOptions;
53
+ for (i in obj.servers4) { obj.servers4[i].xxclear = true; }
54
+ for (i in obj.servers6) { obj.servers6[i].xxclear = true; }
55
+ for (i in addresses.ipv4) {
56
+ localAddress = addresses.ipv4[i];
57
if (obj.servers4[localAddress] != null) {
58
// Server already exists
59
obj.servers4[localAddress].xxclear = false;
@@ -59,7 +65,7 @@ module.exports.CreateMeshScanner = function (parent) {
65
server4.xxtype = 4;
66
server4.xxlocal = localAddress;
67
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]; });
62
- var bindOptions = { port: 16989, exclusive: true };
68
+ bindOptions = { port: 16989, exclusive: true };
69
if (server4.xxlocal != '*') { bindOptions.address = server4.xxlocal; }
70
server4.bind(bindOptions, function () {
71
try {
@@ -77,8 +83,8 @@ module.exports.CreateMeshScanner = function (parent) {
83
}
84
}
85
80
- for (var i in addresses.ipv6) {
81
- var localAddress = addresses.ipv6[i];
86
+ for (i in addresses.ipv6) {
87
+ localAddress = addresses.ipv6[i];
88
if (obj.servers6[localAddress] != null) {
89
// Server already exists
90
obj.servers6[localAddress].xxclear = false;
@@ -90,7 +96,7 @@ module.exports.CreateMeshScanner = function (parent) {
96
server6.xxtype = 6;
97
server6.xxlocal = localAddress;
98
server6.on('error', function (err) { this.close(); delete obj.servers6[this.xxlocal]; });
93
- var bindOptions = { port: 16989, exclusive: true };
99
+ bindOptions = { port: 16989, exclusive: true };
100
if (server6.xxlocal != '*') { bindOptions.address = server6.xxlocal; }
101
server6.bind(bindOptions, function () {
102
try {
@@ -108,14 +114,15 @@ module.exports.CreateMeshScanner = function (parent) {
114
}
115
}
116
111
- for (var i in obj.servers4) { if (obj.servers4[i].xxclear == true) { obj.servers4[i].close(); delete obj.servers4[i]; }; }
112
- for (var i in obj.servers6) { if (obj.servers6[i].xxclear == true) { obj.servers6[i].close(); delete obj.servers6[i]; }; }
117
+ for (i in obj.servers4) { if (obj.servers4[i].xxclear == true) { obj.servers4[i].close(); delete obj.servers4[i]; } }
118
+ for (i in obj.servers6) { if (obj.servers6[i].xxclear == true) { obj.servers6[i].close(); delete obj.servers6[i]; } }
119
}
120
121
// Clear all IPv4 and IPv6 servers
122
function clearServers() {
117
- for (var i in obj.servers4) { obj.servers4[i].close(); delete obj.servers4[i]; }
118
- for (var i in obj.servers6) { obj.servers6[i].close(); delete obj.servers6[i]; }
123
+ var i;
124
+ for (i in obj.servers4) { obj.servers4[i].close(); delete obj.servers4[i]; }
125
+ for (i in obj.servers6) { obj.servers6[i].close(); delete obj.servers6[i]; }
126
}
127
128
// Start scanning for local network Mesh Agents
@@ -128,27 +135,28 @@ module.exports.CreateMeshScanner = function (parent) {
135
setupServers();
136
obj.mainTimer = setInterval(obj.performScan, periodicScanTime);
137
return obj;
131
- }
138
+ };
139
140
// Stop scanning for local network Mesh Agents
141
obj.stop = function () {
142
if (obj.mainTimer != null) { clearInterval(obj.mainTimer); obj.mainTimer = null; }
143
clearServers();
137
- }
144
+ };
145
146
// Look for all Mesh Agents that may be locally reachable, indicating the presense of this server.
147
obj.performScan = function (server) {
148
+ var i;
149
if (server != null) {
150
if (server.xxtype == 4) { try { server.send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, membershipIPv4); } catch (e) { } }
151
if (server.xxtype == 6) { try { server.send(obj.multicastPacket6, 0, obj.multicastPacket6.length, 16990, membershipIPv6); } catch (e) { } }
152
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) { } }
153
if ((server.xxtype == 6) && (server.xxlocal == '*')) { try { server.send(obj.multicastPacket6, 0, obj.multicastPacket6.length, 16990, '::1'); } catch (e) { } }
154
} else {
147
- for (var i in obj.servers4) { try { obj.servers4[i].send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, membershipIPv4); } catch (e) { } }
148
- for (var i in obj.servers6) { try { obj.servers6[i].send(obj.multicastPacket6, 0, obj.multicastPacket6.length, 16990, membershipIPv6); } catch (e) { } }
155
+ for (i in obj.servers4) { try { obj.servers4[i].send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, membershipIPv4); } catch (e) { } }
156
+ for (i in obj.servers6) { try { obj.servers6[i].send(obj.multicastPacket6, 0, obj.multicastPacket6.length, 16990, membershipIPv6); } catch (e) { } }
157
setupServers(); // Check if any network interfaces where added or removed
158
}
151
- }
159
+ };
160
161
// Called when a UDP packet is received from an agent.
162
function onUdpPacket(msg, info, server) {
@@ -161,26 +169,27 @@ module.exports.CreateMeshScanner = function (parent) {
169
170
// As a side job, we also send server wake-on-lan packets
171
obj.wakeOnLan = function (macs) {
164
- for (var i in macs) {
172
+ var i, j;
173
+ for (i in macs) {
174
var mac = macs[i];
175
var hexpacket = 'FFFFFFFFFFFF';
167
- for (var i = 0; i < 16; i++) { hexpacket += mac; }
176
+ for (j = 0; j < 16; j++) { hexpacket += mac; }
177
var wakepacket = Buffer.from(hexpacket, 'hex');
178
//console.log(wakepacket.toString('hex'));
179
180
// Send the wake packet 3 times with small time intervals
172
- 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); }
173
- for (var i in obj.servers6) { obj.servers6[i].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv6); }
181
+ 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); }
182
+ for (j in obj.servers6) { obj.servers6[j].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv6); }
183
setTimeout(function () {
175
- 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); }
176
- for (var i in obj.servers6) { obj.servers6[i].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv6); }
184
+ 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); }
185
+ for (j in obj.servers6) { obj.servers6[j].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv6); }
186
}, 200);
187
setTimeout(function () {
179
- 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); }
180
- for (var i in obj.servers6) { obj.servers6[i].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv6); }
188
+ 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); }
189
+ for (j in obj.servers6) { obj.servers6[j].send(wakepacket, 0, wakepacket.length, 16990, membershipIPv6); }
190
}, 500);
191
}
183
- }
184
-
192
+ };
193
+
194
return obj;
186
-}
\ No newline at end of file
195
+};
\ No newline at end of file
meshuser.js
+93
-85
@@ -6,7 +6,12 @@
6
* @version v0.0.1
7
*/
8
9
-'use strict';
9
+/*jslint node: true */
10
+/*jshint node: true */
11
+/*jshint strict:false */
12
+/*jshint -W097 */
13
+/*jshint esversion: 6 */
14
+"use strict";
15
16
// Construct a MeshAgent object, called upon connection
17
module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
@@ -27,7 +32,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
32
obj.close = function (arg) {
33
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
34
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
30
- }
35
+ };
36
37
// Convert a mesh path array into a real path on the server side
38
function meshPathToRealPath(meshpath, user) {
@@ -52,22 +57,22 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
57
58
//
59
function copyFile(src, dest, func, tag) {
55
- //var ss = obj.fs.createReadStream(src, { flags: 'rb' });
60
+ //var ss = obj.fs.createReadStream(src, { flags: 'rb' });
61
//var ds = obj.fs.createWriteStream(dest, { flags: 'wb' });
62
var ss = obj.fs.createReadStream(src);
63
var ds = obj.fs.createWriteStream(dest);
64
ss.fs = obj.fs;
60
- ss.pipe(ds);
65
+ ss.pipe(ds);
66
ds.ss = ss;
67
/*
68
if (!this._copyStreams) { this._copyStreams = {}; this._copyStreamID = 0; }
69
ss.id = this._copyStreamID++;
70
this._copyStreams[ss.id] = ss;
71
*/
67
- if (arguments.length == 3 && typeof arguments[2] === 'function') { ds.on('close', arguments[2]); }
68
- else if (arguments.length == 4 && typeof arguments[3] === 'function') { ds.on('close', arguments[3]); }
69
- ds.on('close', function() { /*delete this.ss.fs._copyStreams[this.ss.id];*/ func(tag); });
70
- };
72
+ if (arguments.length == 3 && typeof arguments[2] === 'function') { ds.on('close', arguments[2]); }
73
+ else if (arguments.length == 4 && typeof arguments[3] === 'function') { ds.on('close', arguments[3]); }
74
+ ds.on('close', function () { /*delete this.ss.fs._copyStreams[this.ss.id];*/ func(tag); });
75
+ }
76
77
try {
78
// Check if the user is logged in
@@ -83,7 +88,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
88
obj.parent.wssessions2[ws.sessionId] = obj.ws;
89
if (!obj.parent.wssessions[user._id]) { obj.parent.wssessions[user._id] = [ws]; } else { obj.parent.wssessions[user._id].push(obj.ws); }
90
if (obj.parent.parent.multiServer == null) {
86
- obj.parent.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: user.name, count: obj.parent.wssessions[user._id].length, nolog: 1, domain: obj.domain.id })
91
+ obj.parent.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: user.name, count: obj.parent.wssessions[user._id].length, nolog: 1, domain: obj.domain.id });
92
} else {
93
obj.parent.recountSessions(obj.ws.sessionId); // Recount sessions
94
}
@@ -101,14 +106,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
106
else { ws.send(JSON.stringify({ action: 'event', event: event })); }
107
} catch (e) { }
108
}
104
- }
109
+ };
110
111
user.subscriptions = obj.parent.subscribe(user._id, ws); // Subscribe to events
112
obj.ws._socket.setKeepAlive(true, 240000); // Set TCP keep alive
113
114
// When data is received from the web socket
115
ws.on('message', function (msg) {
111
- var command, user = obj.parent.users[req.session.userid];
116
+ var command, user = obj.parent.users[req.session.userid], i = 0, mesh = null, meshid = null, nodeid = null, meshlinks = null, change = 0;
117
try { command = JSON.parse(msg.toString('utf8')); } catch (e) { return; }
118
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
119
@@ -118,7 +123,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
123
{
124
// Request a list of all meshes this user as rights to
125
var docs = [];
121
- for (var i in user.links) { if (obj.parent.meshes[i]) { docs.push(obj.parent.meshes[i]); } }
126
+ for (i in user.links) { if (obj.parent.meshes[i]) { docs.push(obj.parent.meshes[i]); } }
127
ws.send(JSON.stringify({ action: 'meshes', meshes: docs, tag: command.tag }));
128
break;
129
}
@@ -127,10 +132,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
132
var links = [];
133
if (command.meshid == null) {
134
// Request a list of all meshes this user as rights to
130
- for (var i in user.links) { links.push(i); }
135
+ for (i in user.links) { links.push(i); }
136
} else {
137
// Request list of all nodes for one specific meshid
133
- var meshid = command.meshid;
138
+ meshid = command.meshid;
139
if (obj.common.validateString(meshid, 0, 128) == false) return;
140
if (meshid.split('/').length == 0) { meshid = 'mesh/' + domain.id + '/' + command.meshid; }
141
if (user.links[meshid] != null) { links.push(meshid); }
@@ -139,7 +144,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
144
// Request a list of all nodes
145
obj.db.GetAllTypeNoTypeFieldMeshFiltered(links, domain.id, 'node', function (err, docs) {
146
var r = {};
142
- for (var i in docs) {
147
+ for (i in docs) {
148
// Add the connection state
149
var state = obj.parent.parent.GetConnectivityState(docs[i]._id);
150
if (state) {
@@ -150,7 +155,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
155
}
156
157
// Compress the meshid's
153
- var meshid = docs[i].meshid;
158
+ meshid = docs[i].meshid;
159
if (!r[meshid]) { r[meshid] = []; }
160
delete docs[i].meshid;
161
@@ -171,7 +176,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
176
obj.db.getPowerTimeline(command.nodeid, function (err, docs) {
177
if (err == null && docs.length > 0) {
178
var timeline = [], time = null, previousPower;
174
- for (var i in docs) {
179
+ for (i in docs) {
180
var doc = docs[i];
181
if (time == null) {
182
// First element
@@ -228,14 +233,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
233
if (path == null) break;
234
235
if ((command.fileop == 'createfolder') && (obj.common.IsFilenameValid(command.newfolder) == true)) { try { obj.fs.mkdirSync(path + "/" + command.newfolder); } catch (e) { } } // Create a new folder
231
- 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
236
+ 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
237
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
238
else if ((command.fileop == 'copy') || (command.fileop == 'move')) {
239
if (obj.common.validateArray(command.names, 1) == false) return;
240
var scpath = meshPathToRealPath(command.scpath, user); // This will also check access rights
241
if (scpath == null) break;
242
// TODO: Check quota if this is a copy!!!!!!!!!!!!!!!!
238
- for (var i in command.names) {
243
+ for (i in command.names) {
244
var s = obj.path.join(scpath, command.names[i]), d = obj.path.join(path, command.names[i]);
245
sendUpdate = false;
246
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) {
324
// Delete all events
325
if (user.siteadmin != 0xFFFFFFFF) break;
326
obj.db.RemoveAllEvents(domain.id);
322
- obj.parent.parent.DispatchEvent(['*', 'server-global'], obj, { action: 'clearevents', nolog: 1, domain: domain.id })
327
+ obj.parent.parent.DispatchEvent(['*', 'server-global'], obj, { action: 'clearevents', nolog: 1, domain: domain.id });
328
break;
329
}
330
case 'users':
@@ -327,7 +332,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
332
// Request a list of all users
333
if ((user.siteadmin & 2) == 0) break;
334
var docs = [];
330
- for (var i in obj.parent.users) {
335
+ for (i in obj.parent.users) {
336
if ((obj.parent.users[i].domain == domain.id) && (obj.parent.users[i].name != '~')) {
337
var userinfo = obj.common.Clone(obj.parent.users[i]);
338
delete userinfo.hash;
@@ -403,10 +408,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
408
if ((user.siteadmin & 2) == 0) break;
409
if (obj.parent.parent.multiServer == null) {
410
// No peering, use simple session counting
406
- for (var i in obj.parent.wssessions) { if (obj.parent.wssessions[i][0].domainid == domain.id) { wssessions[i] = obj.parent.wssessions[i].length; } }
411
+ for (i in obj.parent.wssessions) { if (obj.parent.wssessions[i][0].domainid == domain.id) { wssessions[i] = obj.parent.wssessions[i].length; } }
412
} else {
413
// We have peer servers, use more complex session counting
409
- for (var userid in obj.parent.sessionsCount) { if (userid.split('/')[1] == domain.id) { wssessions[userid] = obj.parent.sessionsCount[userid]; } }
414
+ for (i in obj.parent.sessionsCount) { if (i.split('/')[1] == domain.id) { wssessions[i] = obj.parent.sessionsCount[i]; } }
415
}
416
ws.send(JSON.stringify({ action: 'wssessioncount', wssessions: wssessions, tag: command.tag })); // wssessions is: userid --> count
417
break;
@@ -422,15 +427,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
427
428
// Remove all the mesh links to this user
429
if (deluser.links != null) {
425
- for (var meshid in deluser.links) {
430
+ for (meshid in deluser.links) {
431
// Get the mesh
427
- var mesh = obj.parent.meshes[meshid];
432
+ mesh = obj.parent.meshes[meshid];
433
if (mesh) {
434
// Remove user from the mesh
435
if (mesh.links[deluser._id] != null) { delete mesh.links[deluser._id]; obj.parent.db.Set(mesh); }
436
// Notify mesh change
432
- var change = 'Removed user ' + deluser.name + ' from mesh ' + mesh.name;
433
- 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 })
437
+ change = 'Removed user ' + deluser.name + ' from mesh ' + mesh.name;
438
+ 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 });
439
}
440
}
441
}
@@ -446,7 +451,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
451
452
obj.db.Remove(deluserid);
453
delete obj.parent.users[deluserid];
449
- obj.parent.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', userid: deluserid, username: deluser.name, action: 'accountremove', msg: 'Account removed', domain: domain.id })
454
+ obj.parent.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', userid: deluserid, username: deluser.name, action: 'accountremove', msg: 'Account removed', domain: domain.id });
455
obj.parent.parent.DispatchEvent([deluserid], obj, 'close');
456
457
break;
@@ -474,7 +479,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
479
if (newuser2.subscriptions) { delete newuser2.subscriptions; }
480
if (newuser2.salt) { delete newuser2.salt; }
481
if (newuser2.hash) { delete newuser2.hash; }
477
- 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 })
482
+ 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 });
483
});
484
}
485
break;
@@ -483,12 +488,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
488
{
489
// Edit a user account, may involve changing email or administrator permissions
490
if (((user.siteadmin & 2) != 0) || (user.name == command.name)) {
486
- var chguserid = 'user/' + domain.id + '/' + command.name.toLowerCase(), chguser = obj.parent.users[chguserid], change = 0;
491
+ var chguserid = 'user/' + domain.id + '/' + command.name.toLowerCase(), chguser = obj.parent.users[chguserid];
492
+ change = 0;
493
if (chguser) {
494
if (obj.common.validateString(command.email, 1, 256) && (chguser.email != command.email)) { chguser.email = command.email; change = 1; }
495
if ((command.emailVerified === true || command.emailVerified === false) && (chguser.emailVerified != command.emailVerified)) { chguser.emailVerified = command.emailVerified; change = 1; }
496
if (obj.common.validateInt(command.quota, 0) && (command.quota != chguser.quota)) { chguser.quota = command.quota; if (chguser.quota == null) { delete chguser.quota; } change = 1; }
491
- if ((user.siteadmin == 0xFFFFFFFF) && obj.common.validateInt(command.siteadmin) && (chguser.siteadmin != command.siteadmin)) { chguser.siteadmin = command.siteadmin; change = 1 }
497
+ if ((user.siteadmin == 0xFFFFFFFF) && obj.common.validateInt(command.siteadmin) && (chguser.siteadmin != command.siteadmin)) { chguser.siteadmin = command.siteadmin; change = 1; }
498
if (change == 1) {
499
obj.db.SetUser(chguser);
500
obj.parent.parent.DispatchEvent([chguser._id], obj, 'resubscribe');
@@ -500,7 +506,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
506
delete userinfo.domain;
507
delete userinfo.subscriptions;
508
delete userinfo.passtype;
503
- 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 })
509
+ 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 });
510
}
511
if ((chguser.siteadmin) && (chguser.siteadmin != 0xFFFFFFFF) && (chguser.siteadmin & 32)) {
512
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) {
540
541
// Get the list of sessions for this user
542
var sessions = obj.parent.wssessions[command.userid];
537
- if (sessions != null) { for (var i in sessions) { sessions[i].send(JSON.stringify(notification)); } }
543
+ if (sessions != null) { for (i in sessions) { sessions[i].send(JSON.stringify(notification)); } }
544
545
if (obj.parent.parent.multiServer != null) {
546
// TODO: Add multi-server support
547
}
548
+ break;
549
}
550
case 'serverversion':
551
{
@@ -564,10 +571,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
571
if ((command.meshtype == 1) || (command.meshtype == 2)) {
572
// Create a type 1 agent-less Intel AMT mesh.
573
obj.parent.crypto.randomBytes(48, function (err, buf) {
567
- var meshid = 'mesh/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
568
- var links = {}
574
+ meshid = 'mesh/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
575
+ var links = {};
576
links[user._id] = { name: user.name, rights: 0xFFFFFFFF };
570
- var mesh = { type: 'mesh', _id: meshid, name: command.meshname, mtype: command.meshtype, desc: command.desc, domain: domain.id, links: links };
577
+ mesh = { type: 'mesh', _id: meshid, name: command.meshname, mtype: command.meshtype, desc: command.desc, domain: domain.id, links: links };
578
obj.db.Set(obj.common.escapeLinksFieldName(mesh));
579
obj.parent.meshes[meshid] = mesh;
580
obj.parent.parent.AddEventDispatch([meshid], ws);
@@ -575,7 +582,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
582
user.links[meshid] = { rights: 0xFFFFFFFF };
583
user.subscriptions = obj.parent.subscribe(user._id, ws);
584
obj.db.SetUser(user);
578
- 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 })
585
+ 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 });
586
});
587
}
588
break;
@@ -586,17 +593,17 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
593
if (obj.common.validateString(command.meshid, 1, 1024) == false) break; // Check the meshid
594
obj.db.Get(command.meshid, function (err, meshes) {
595
if (meshes.length != 1) return;
589
- var mesh = obj.common.unEscapeLinksFieldName(meshes[0]);
596
+ mesh = obj.common.unEscapeLinksFieldName(meshes[0]);
597
598
// Check if this user has rights to do this
599
if (mesh.links[user._id] == null || mesh.links[user._id].rights != 0xFFFFFFFF) return;
600
if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
601
602
// Fire the removal event first, because after this, the event will not route
596
- 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 })
603
+ 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 });
604
605
// Remove all user links to this mesh
599
- for (var i in meshes) {
606
+ for (i in meshes) {
607
var links = meshes[i].links;
608
for (var j in links) {
609
var xuser = obj.parent.users[j];
@@ -608,8 +615,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
615
616
// Delete all files on the server for this mesh
617
try {
611
- var meshpath = getServerRootFilePath(mesh);
612
- if (meshpath != null) { deleteFolderRec(meshpath); }
618
+ var meshpath = obj.parent.getServerRootFilePath(mesh);
619
+ if (meshpath != null) { obj.parent.deleteFolderRec(meshpath); }
620
} catch (e) { }
621
622
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) {
629
{
630
// Change the name or description of a mesh
631
if (obj.common.validateString(command.meshid, 1, 1024) == false) break; // Check the meshid
625
- var mesh = obj.parent.meshes[command.meshid], change = '';
632
+ mesh = obj.parent.meshes[command.meshid];
633
+ change = '';
634
if (mesh) {
635
// Check if this user has rights to do this
636
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) {
638
639
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; }
640
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; }
633
- 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 }) }
641
+ 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 }); }
642
}
643
break;
644
}
@@ -648,7 +656,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
656
}
657
658
// Get the mesh
651
- var mesh = obj.parent.meshes[command.meshid], change = '';
659
+ mesh = obj.parent.meshes[command.meshid];
660
if (mesh) {
661
// Check if this user has rights to do this
662
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) {
673
obj.db.Set(obj.common.escapeLinksFieldName(mesh));
674
675
// Notify mesh change
668
- var change = 'Added user ' + newuser.name + ' to mesh ' + mesh.name;
669
- 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 })
676
+ 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 });
677
}
678
break;
679
}
@@ -677,7 +684,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
684
if ((command.userid.split('/').length != 3) || (command.userid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
685
686
// Get the mesh
680
- var mesh = obj.parent.meshes[command.meshid];
687
+ mesh = obj.parent.meshes[command.meshid];
688
if (mesh) {
689
// Check if this user has rights to do this
690
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) {
708
obj.db.Set(obj.common.escapeLinksFieldName(mesh));
709
710
// Notify mesh change
704
- var change = 'Removed user ' + deluser.name + ' from mesh ' + mesh.name;
705
- 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 })
711
+ 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 });
712
}
713
}
714
break;
@@ -723,7 +729,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
729
if ((obj.parent.parent.args.wanonly == true) && (command.hostname)) { delete command.hostname; }
730
731
// Get the mesh
726
- var mesh = obj.parent.meshes[command.meshid];
732
+ mesh = obj.parent.meshes[command.meshid];
733
if (mesh) {
734
if (mesh.mtype != 1) return; // This operation is only allowed for mesh type 1, Intel AMT agentless mesh.
735
@@ -733,15 +739,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
739
// Create a new nodeid
740
obj.parent.crypto.randomBytes(48, function (err, buf) {
741
// create the new node
736
- var nodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');;
742
+ nodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
743
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 } };
744
obj.db.Set(device);
745
746
// Event the new node
747
var device2 = obj.common.Clone(device);
748
delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
743
- var change = 'Added device ' + command.devicename + ' to mesh ' + mesh.name;
744
- obj.parent.parent.DispatchEvent(['*', command.meshid], obj, { etype: 'node', username: user.name, action: 'addnode', node: device2, msg: change, domain: domain.id })
749
+ 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 });
750
});
751
}
752
break;
@@ -763,8 +768,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
768
{
769
if (obj.common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
770
766
- for (var i in command.nodeids) {
767
- var nodeid = command.nodeids[i];
771
+ for (i in command.nodeids) {
772
+ nodeid = command.nodeids[i];
773
if (obj.common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
774
if ((nodeid.split('/').length != 3) || (nodeid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
775
@@ -774,7 +779,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
779
var node = nodes[0];
780
781
// Get the mesh for this device
777
- var mesh = obj.parent.meshes[node.meshid];
782
+ mesh = obj.parent.meshes[node.meshid];
783
if (mesh) {
784
// Check if this user has rights to do this
785
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) {
791
obj.db.RemoveNode(node._id); // Remove all entries with node:id
792
793
// Event node deletion
789
- var change = 'Removed device ' + node.name + ' from mesh ' + mesh.name;
790
- obj.parent.parent.DispatchEvent(['*', node.meshid], obj, { etype: 'node', username: user.name, action: 'removenode', nodeid: node._id, msg: change, domain: domain.id })
794
+ 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 });
795
796
// Disconnect all connections if needed
797
var state = obj.parent.parent.GetConnectivityState(nodeid);
@@ -807,8 +811,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
811
// TODO: We can optimize this a lot.
812
// - We should get a full list of all MAC's to wake first.
813
// - We should try to only have one agent per subnet (using Gateway MAC) send a wake-on-lan.
810
- for (var i in command.nodeids) {
811
- var nodeid = command.nodeids[i], wakeActions = 0;
814
+ for (i in command.nodeids) {
815
+ nodeid = command.nodeids[i];
816
+ var wakeActions = 0;
817
if (obj.common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
818
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
819
// Get the device
@@ -817,7 +822,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
822
var node = nodes[0];
823
824
// Get the mesh for this device
820
- var mesh = obj.parent.meshes[node.meshid];
825
+ mesh = obj.parent.meshes[node.meshid];
826
if (mesh) {
827
828
// Check if this user has rights to do this
@@ -835,10 +840,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
840
841
// Get the list of mesh this user as access to
842
var targetMeshes = [];
838
- for (var i in user.links) { targetMeshes.push(i); }
843
+ for (i in user.links) { targetMeshes.push(i); }
844
845
// Go thru all the connected agents and send wake-on-lan on all the ones in the target mesh list
841
- for (var i in obj.parent.wsagents) {
846
+ for (i in obj.parent.wsagents) {
847
var agent = obj.parent.wsagents[i];
848
if ((targetMeshes.indexOf(agent.dbMeshKey) >= 0) && (agent.authenticated == 2)) {
849
//console.log('Asking agent ' + agent.dbNodeKey + ' to wake ' + macs.join(','));
@@ -862,8 +867,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
867
case 'poweraction':
868
{
869
if (obj.common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
865
- for (var i in command.nodeids) {
866
- var nodeid = command.nodeids[i], powerActions = 0;
870
+ for (i in command.nodeids) {
871
+ nodeid = command.nodeids[i];
872
+ var powerActions = 0;
873
if (obj.common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
874
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
875
// Get the device
@@ -872,7 +878,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
878
var node = nodes[0];
879
880
// Get the mesh for this device
875
- var mesh = obj.parent.meshes[node.meshid];
881
+ mesh = obj.parent.meshes[node.meshid];
882
if (mesh) {
883
884
// Check if this user has rights to do this
@@ -899,8 +905,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
905
if (obj.common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
906
if (obj.common.validateString(command.title, 1, 512) == false) break; // Check title
907
if (obj.common.validateString(command.msg, 1, 4096) == false) break; // Check message
902
- for (var i in command.nodeids) {
903
- var nodeid = command.nodeids[i], powerActions = 0;
908
+ for (i in command.nodeids) {
909
+ nodeid = command.nodeids[i];
910
+ var powerActions = 0;
911
if (obj.common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
912
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
913
// Get the device
@@ -909,7 +916,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
916
var node = nodes[0];
917
918
// Get the mesh for this device
912
- var mesh = obj.parent.meshes[node.meshid];
919
+ mesh = obj.parent.meshes[node.meshid];
920
if (mesh) {
921
922
// Check if this user has rights to do this
@@ -940,7 +947,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
947
var node = nodes[0];
948
949
// Get the mesh for this device
943
- var mesh = obj.parent.meshes[node.meshid];
950
+ mesh = obj.parent.meshes[node.meshid];
951
if (mesh) {
952
// Check if this user has rights to do this
953
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) {
975
var node = nodes[0];
976
977
// Get the mesh for this device
971
- var mesh = obj.parent.meshes[node.meshid];
978
+ mesh = obj.parent.meshes[node.meshid];
979
if (mesh) {
980
// Check if this user has rights to do this
981
if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 4) == 0)) return;
982
983
// Ready the node change event
977
- var changes = [], change = 0, event = { etype: 'node', username: user.name, action: 'changenode', nodeid: node._id, domain: domain.id };
984
+ var changes = [], event = { etype: 'node', username: user.name, action: 'changenode', nodeid: node._id, domain: domain.id };
985
+ change = 0;
986
event.msg = ": ";
987
988
// 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) {
1049
data = obj.common.IntToStr(0) + data; // Add the 4 bytes encoding type & flags (Set to 0 for raw)
1050
obj.parent.sendMeshAgentCore(user, domain, command.nodeid, data);
1051
}
1044
- })
1052
+ });
1053
}
1054
}
1055
} else {
@@ -1071,7 +1079,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
1079
if (obj.common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
1080
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 (???)
1081
if (nodes.length == 1) {
1074
- var meshlinks = user.links[nodes[0].meshid];
1082
+ meshlinks = user.links[nodes[0].meshid];
1083
if ((meshlinks) && (meshlinks.rights) && (meshlinks.rights & obj.parent.MESHRIGHT_REMOTECONTROL != 0)) {
1084
// Add a user authentication cookie to a url
1085
var cookieContent = { userid: user._id, domainid: user.domain };
@@ -1093,7 +1101,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
1101
if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
1102
1103
// Get the mesh
1096
- var mesh = obj.parent.meshes[command.meshid];
1104
+ mesh = obj.parent.meshes[command.meshid];
1105
if (mesh) {
1106
if (mesh.mtype != 2) return; // This operation is only allowed for mesh type 2, agent mesh
1107
@@ -1118,7 +1126,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
1126
// Check if this user has rights on this id to set notes
1127
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 (???)
1128
if (nodes.length == 1) {
1121
- var meshlinks = user.links[nodes[0].meshid];
1129
+ meshlinks = user.links[nodes[0].meshid];
1130
if ((meshlinks) && (meshlinks.rights) && (meshlinks.rights & obj.parent.MESHRIGHT_SETNOTES != 0)) {
1131
// Set the id's notes
1132
if (obj.common.validateString(command.notes, 1) == false) {
@@ -1131,7 +1139,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
1139
});
1140
} else if (idtype == 'mesh') {
1141
// Get the mesh for this device
1134
- var mesh = obj.parent.meshes[command.id];
1142
+ mesh = obj.parent.meshes[command.id];
1143
if (mesh) {
1144
// Check if this user has rights to do this
1145
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) {
1178
var node = nodes[0];
1179
1180
// Get the mesh for this device
1173
- var mesh = obj.parent.meshes[node.meshid];
1181
+ mesh = obj.parent.meshes[node.meshid];
1182
if (mesh) {
1183
// Check if this user has rights to do this
1184
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) {
1192
});
1193
} else if (idtype == 'mesh') {
1194
// Get the mesh for this device
1187
- var mesh = obj.parent.meshes[command.id];
1195
+ mesh = obj.parent.meshes[command.id];
1196
if (mesh) {
1197
// Check if this user has rights to do this
1198
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) {
1231
var user = obj.parent.users[ws.userid];
1232
if (user) {
1233
if (obj.parent.parent.multiServer == null) {
1226
- obj.parent.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: user.name, count: obj.parent.wssessions[ws.userid].length, nolog: 1, domain: obj.domain.id })
1234
+ obj.parent.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: user.name, count: obj.parent.wssessions[ws.userid].length, nolog: 1, domain: obj.domain.id });
1235
} else {
1236
obj.parent.recountSessions(ws.sessionId); // Recount sessions
1237
}
@@ -1241,7 +1249,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
1249
var httpport = ((obj.args.aliasport != null) ? obj.args.aliasport : obj.args.port);
1250
1251
// Build server information object
1244
- 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 }
1252
+ 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 };
1253
if (obj.args.notls == true) { serverinfo.https = false; } else { serverinfo.https = true; serverinfo.redirport = obj.args.redirport; }
1254
1255
// Send server information
@@ -1259,7 +1267,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
1267
var r = {}, dir = obj.fs.readdirSync(path);
1268
for (var i in dir) {
1269
var f = { t: 3, d: 111 };
1262
- var stat = obj.fs.statSync(path + '/' + dir[i])
1270
+ var stat = obj.fs.statSync(path + '/' + dir[i]);
1271
if ((stat.mode & 0x004000) == 0) { f.s = stat.size; f.d = stat.mtime.getTime(); } else { f.t = 2; f.f = readFilesRec(path + '/' + dir[i]); }
1272
r[dir[i]] = f;
1273
}
@@ -1316,7 +1324,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
1324
}
1325
1326
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; }
1319
- 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; }
1327
+ //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; }
1328
1329
return obj;
1322
-}
1330
+};
\ No newline at end of file
multiserver.js
+52
-46
@@ -6,7 +6,12 @@
6
* @version v0.0.1
7
*/
8
9
-'use strict';
9
+/*jslint node: true */
10
+/*jshint node: true */
11
+/*jshint strict:false */
12
+/*jshint -W097 */
13
+/*jshint esversion: 6 */
14
+"use strict";
15
16
// Construct a Mesh Multi-Server object. This is used for MeshCentral-to-MeshCentral communication.
17
module.exports.CreateMultiServer = function (parent, args) {
@@ -46,7 +51,7 @@ module.exports.CreateMultiServer = function (parent, args) {
51
obj.stop = function () {
52
obj.connectionState = 0;
53
disconnect();
49
- }
54
+ };
55
56
// Make one attempt at connecting to the server
57
function connect() {
@@ -169,13 +174,13 @@ module.exports.CreateMultiServer = function (parent, args) {
174
if (typeof msg == 'object') { obj.ws.send(JSON.stringify(msg)); return; }
175
if (typeof msg == 'string') { obj.ws.send(msg); return; }
176
} catch (e) { }
172
- }
177
+ };
178
179
// Process incoming peer server JSON data
180
function processServerData(msg) {
176
- var str = msg.toString('utf8');
181
+ var str = msg.toString('utf8'), command = null;
182
if (str[0] == '{') {
178
- 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.
183
+ 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.
184
if (command.action == 'info') {
185
if (obj.authenticated != 3) {
186
// We get the peer's serverid and database identifier.
@@ -198,7 +203,7 @@ module.exports.CreateMultiServer = function (parent, args) {
203
204
connect();
205
return obj;
201
- }
206
+ };
207
208
// Create a mesh server module that received a connection to another server
209
obj.CreatePeerInServer = function (parent, ws, req) {
@@ -227,14 +232,14 @@ module.exports.CreateMultiServer = function (parent, args) {
232
if (typeof data == 'object') { obj.ws.send(JSON.stringify(data)); return; }
233
obj.ws.send(data);
234
} catch (e) { }
230
- }
235
+ };
236
237
// Disconnect this server
238
obj.close = function (arg) {
239
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
240
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
241
if (obj.authenticated == 3) { obj.parent.ClearPeerServer(obj, obj.peerServerId); obj.authenticated = 0; }
237
- }
242
+ };
243
244
// When data is received from the peer server web socket
245
ws.on('message', function (msg) {
@@ -244,7 +249,7 @@ module.exports.CreateMultiServer = function (parent, args) {
249
if (obj.authenticated >= 2) { // We are authenticated
250
if (msg.charCodeAt(0) == 123) { processServerData(msg); }
251
if (msg.length < 2) return;
247
- var cmdid = obj.common.ReadShort(msg, 0);
252
+ //var cmdid = obj.common.ReadShort(msg, 0);
253
// Process binary commands (if any). None right now.
254
}
255
else if (obj.authenticated < 2) { // We are not authenticated
@@ -259,14 +264,14 @@ module.exports.CreateMultiServer = function (parent, args) {
264
obj.peernonce = msg.substring(50);
265
266
// Perform the hash signature using the server agent certificate
262
- obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (signature) {
267
+ obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
268
// Send back our certificate + signature
264
- obj2.send(obj2.common.ShortToStr(2) + obj.common.ShortToStr(obj2.agentCertificateAsn1.length) + obj2.agentCertificateAsn1 + signature); // Command 2, certificate + signature
269
+ obj2.send(obj2.common.ShortToStr(2) + obj2.common.ShortToStr(obj2.agentCertificateAsn1.length) + obj2.agentCertificateAsn1 + signature); // Command 2, certificate + signature
270
});
271
272
// Check the peer server signature if we can
273
if (obj.unauthsign != null) {
269
- if (processPeerSignature(obj.unauthsign) == false) { disconnect(); return; } else { completePeerServerConnection(); }
274
+ if (processPeerSignature(obj.unauthsign) == false) { obj.close(); return; } else { completePeerServerConnection(); }
275
}
276
}
277
else if (cmd == 2) {
@@ -337,9 +342,9 @@ module.exports.CreateMultiServer = function (parent, args) {
342
343
// Process incoming peer server JSON data
344
function processServerData(msg) {
340
- var str = msg.toString('utf8');
345
+ var str = msg.toString('utf8'), command = null;
346
if (str[0] == '{') {
342
- 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.
347
+ 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.
348
if (command.action == 'info') {
349
if (obj.authenticated != 3) {
350
// We get the peer's serverid and database identifier.
@@ -362,7 +367,7 @@ module.exports.CreateMultiServer = function (parent, args) {
367
}
368
369
return obj;
365
- }
370
+ };
371
372
// If we have no peering configuration, don't setup this object
373
if (obj.peerConfig == null) { return null; }
@@ -375,34 +380,34 @@ module.exports.CreateMultiServer = function (parent, args) {
380
var server = obj.peerServers[serverid];
381
if (server && server.peerServerKey) return server.peerServerKey;
382
return null;
378
- }
383
+ };
384
385
// Dispatch an event to all other MeshCentral2 peer servers
386
obj.DispatchEvent = function (ids, source, event) {
387
var busmsg = JSON.stringify({ action: 'bus', ids: ids, event: event });
388
for (var serverid in obj.peerServers) { obj.peerServers[serverid].send(busmsg); }
384
- }
389
+ };
390
391
// Dispatch a message to other MeshCentral2 peer servers
392
obj.DispatchMessage = function (msg) {
393
for (var serverid in obj.peerServers) { obj.peerServers[serverid].send(msg); }
389
- }
394
+ };
395
396
// Dispatch a message to other MeshCentral2 peer servers
397
obj.DispatchMessageSingleServer = function (msg, serverid) {
398
var server = obj.peerServers[serverid];
399
if (server != null) { server.send(msg); }
395
- }
400
+ };
401
402
// Attempt to connect to all peers
403
obj.ConnectToPeers = function () {
399
- for (serverId in obj.peerConfig.servers) {
404
+ for (var serverId in obj.peerConfig.servers) {
405
// We will only connect to names that are larger then ours. This way, eveyone has one connection to everyone else (no cross-connections).
406
if ((serverId > obj.serverid) && (obj.peerConfig.servers[serverId].url != null) && (obj.outPeerServers[serverId] == null)) {
407
obj.outPeerServers[serverId] = obj.CreatePeerOutServer(obj, serverId, obj.peerConfig.servers[serverId].url);
408
}
409
}
405
- }
410
+ };
411
412
// We connected to a peer server, setup everything
413
obj.SetupPeerServer = function (server, peerServerId) {
@@ -414,7 +419,7 @@ module.exports.CreateMultiServer = function (parent, args) {
419
420
// Send a list of user sessions to the peer
421
server.send(JSON.stringify({ action: 'sessionsTable', sessionsTable: Object.keys(obj.parent.webserver.wssessions2) }));
417
- }
422
+ };
423
424
// We disconnected to a peer server, clean up everything
425
obj.ClearPeerServer = function (server, peerServerId) {
@@ -431,10 +436,11 @@ module.exports.CreateMultiServer = function (parent, args) {
436
delete obj.parent.webserver.wsPeerSessions[peerServerId];
437
delete obj.parent.webserver.wsPeerSessions3[peerServerId];
438
obj.parent.webserver.recountSessions(); // Recount all sessions
434
- }
439
+ };
440
441
// Process a message coming from a peer server
442
obj.ProcessPeerServerMessage = function (server, peerServerId, msg) {
443
+ var userid, i;
444
//console.log('ProcessPeerServerMessage', peerServerId, msg);
445
switch (msg.action) {
446
case 'bus': {
@@ -449,10 +455,10 @@ module.exports.CreateMultiServer = function (parent, args) {
455
case 'sessionsTable': {
456
obj.parent.webserver.wsPeerSessions[peerServerId] = msg.sessionsTable;
457
var userToSession = {};
452
- for (var i in msg.sessionsTable) {
458
+ for (i in msg.sessionsTable) {
459
var sessionid = msg.sessionsTable[i];
460
obj.parent.webserver.wsPeerSessions2[sessionid] = peerServerId;
455
- var userid = sessionid.split('/').slice(0, 3).join('/'); // Take the sessionid and keep only the userid partion
461
+ userid = sessionid.split('/').slice(0, 3).join('/'); // Take the sessionid and keep only the userid partion
462
if (userToSession[userid] == null) { userToSession[userid] = [sessionid]; } else { userToSession[userid].push(sessionid); } // UserId -> [ SessionId ]
463
}
464
obj.parent.webserver.wsPeerSessions3[peerServerId] = userToSession; // ServerId --> UserId --> SessionId
@@ -462,17 +468,17 @@ module.exports.CreateMultiServer = function (parent, args) {
468
case 'sessionStart': {
469
obj.parent.webserver.wsPeerSessions[peerServerId].push(msg.sessionid);
470
obj.parent.webserver.wsPeerSessions2[msg.sessionid] = peerServerId;
465
- var userid = msg.sessionid.split('/').slice(0, 3).join('/');
471
+ userid = msg.sessionid.split('/').slice(0, 3).join('/');
472
if (obj.parent.webserver.wsPeerSessions3[peerServerId] == null) { obj.parent.webserver.wsPeerSessions3[peerServerId] = {}; }
467
- 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); }
473
+ 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); }
474
obj.parent.webserver.recountSessions(msg.sessionid); // Recount a specific user
475
break;
476
}
477
case 'sessionEnd': {
472
- var i = obj.parent.webserver.wsPeerSessions[peerServerId].indexOf(msg.sessionid);
478
+ i = obj.parent.webserver.wsPeerSessions[peerServerId].indexOf(msg.sessionid);
479
if (i >= 0) { obj.parent.webserver.wsPeerSessions[peerServerId].splice(i, 1); }
480
delete obj.parent.webserver.wsPeerSessions2[msg.sessionid];
475
- var userid = msg.sessionid.split('/').slice(0, 3).join('/');
481
+ userid = msg.sessionid.split('/').slice(0, 3).join('/');
482
if (obj.parent.webserver.wsPeerSessions3[peerServerId][userid] != null) {
483
i = obj.parent.webserver.wsPeerSessions3[peerServerId][userid].indexOf(msg.sessionid);
484
if (i >= 0) {
@@ -498,7 +504,7 @@ module.exports.CreateMultiServer = function (parent, args) {
504
// Yes, there is a waiting session, see if we must initiate.
505
if (peerServerId > obj.parent.serverId) {
506
// We must initiate the connection to the peer
501
- var userid = null;
507
+ userid = null;
508
if (rsession.peer1.req.session != null) { userid = rsession.peer1.req.session.userid; }
509
obj.createPeerRelay(rsession.peer1.ws, rsession.peer1.req, peerServerId, userid);
510
delete obj.parent.webserver.wsrelays[msg.id];
@@ -509,33 +515,33 @@ module.exports.CreateMultiServer = function (parent, args) {
515
516
// Clear all relay sessions that are more than 1 minute
517
var oneMinuteAgo = Date.now() - 60000;
512
- for (var id in obj.parent.webserver.wsPeerRelays) { if (obj.parent.webserver.wsPeerRelays[id].time < oneMinuteAgo) { delete obj.parent.webserver.wsPeerRelays[id]; } }
518
+ for (i in obj.parent.webserver.wsPeerRelays) { if (obj.parent.webserver.wsPeerRelays[i].time < oneMinuteAgo) { delete obj.parent.webserver.wsPeerRelays[i]; } }
519
}
520
break;
521
}
522
case 'msg': {
523
if (msg.sessionid != null) {
524
// Route this message to a connected user session
519
- if (command.fromNodeid != null) { command.nodeid = command.fromNodeid; delete command.fromNodeid; }
520
- var ws = obj.parent.webserver.wssessions2[command.sessionid];
521
- if (ws != null) { ws.send(JSON.stringify(command)); }
525
+ if (msg.fromNodeid != null) { msg.nodeid = msg.fromNodeid; delete msg.fromNodeid; }
526
+ var ws = obj.parent.webserver.wssessions2[msg.sessionid];
527
+ if (ws != null) { ws.send(JSON.stringify(msg)); }
528
} else if (msg.nodeid != null) {
529
// Route this message to a connected agent
524
- if (command.fromSessionid != null) { command.sessionid = command.fromSessionid; delete command.fromSessionid; }
530
+ if (msg.fromSessionid != null) { msg.sessionid = msg.fromSessionid; delete msg.fromSessionid; }
531
var agent = obj.parent.webserver.wsagents[msg.nodeid];
532
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
533
} else if (msg.meshid != null) {
534
// Route this message to all users of this mesh
529
- if (command.fromNodeid != null) { command.nodeid = command.fromNodeid; delete command.fromNodeid; }
530
- var cmdstr = JSON.stringify(command);
531
- for (var userid in obj.parent.webserver.wssessions) { // Find all connected users for this mesh and send the message
535
+ if (msg.fromNodeid != null) { msg.nodeid = msg.fromNodeid; delete msg.fromNodeid; }
536
+ var cmdstr = JSON.stringify(msg);
537
+ for (userid in obj.parent.webserver.wssessions) { // Find all connected users for this mesh and send the message
538
var user = obj.parent.webserver.users[userid];
539
if (user) {
540
var rights = user.links[msg.meshid];
541
if (rights != null) { // TODO: Look at what rights are needed for message routing
542
var sessions = obj.parent.webserver.wssessions[userid];
543
// Send the message to all users on this server
538
- for (var i in sessions) { sessions[i].send(cmdstr); }
544
+ for (i in sessions) { sessions[i].send(cmdstr); }
545
}
546
}
547
}
@@ -543,7 +549,7 @@ module.exports.CreateMultiServer = function (parent, args) {
549
break;
550
}
551
}
546
- }
552
+ };
553
554
// Create a tunnel connection to a peer server
555
obj.createPeerRelay = function (ws, req, serverid, user) {
@@ -558,7 +564,7 @@ module.exports.CreateMultiServer = function (parent, args) {
564
var path = req.path;
565
if (path[0] == '/') path = path.substring(1);
566
if (path.substring(path.length - 11) == '/.websocket') { path = path.substring(0, path.length - 11); }
561
- var queryStr = ''
567
+ var queryStr = '';
568
for (var i in req.query) { queryStr += ((queryStr == '') ? '?' : '&') + i + '=' + req.query[i]; }
569
if (user != null) { queryStr += ((queryStr == '') ? '?' : '&') + 'auth=' + obj.parent.encodeCookie({ userid: user._id, domainid: user.domain }, cookieKey); }
570
var url = obj.peerConfig.servers[serverid].url + path + queryStr;
@@ -566,7 +572,7 @@ module.exports.CreateMultiServer = function (parent, args) {
572
// Setup an connect the web socket
573
var tunnel = obj.createPeerRelayEx(ws, url, serverid);
574
tunnel.connect();
569
- }
575
+ };
576
577
// Create a tunnel connection to a peer server
578
// We assume that "ws" is paused already.
@@ -610,7 +616,7 @@ module.exports.CreateMultiServer = function (parent, args) {
616
617
// If the web socket is closed, close the associated TCP connection.
618
peerTunnel.ws1.on('close', function (req) { peerTunnel.parent.parent.debug(1, 'FTunnel disconnect ' + peerTunnel.serverid); peerTunnel.close(); });
613
- }
619
+ };
620
621
// Disconnect both sides of the tunnel
622
peerTunnel.close = function (arg) {
@@ -623,11 +629,11 @@ module.exports.CreateMultiServer = function (parent, args) {
629
if (peerTunnel.ws1 != null) { try { peerTunnel.ws1.close(); peerTunnel.parent.parent.debug(1, 'FTunnel1: Soft disconnect '); } catch (e) { console.log(e); } }
630
if (peerTunnel.ws2 != null) { try { peerTunnel.ws2.close(); peerTunnel.parent.parent.debug(1, 'FTunnel2: Soft disconnect '); } catch (e) { console.log(e); } }
631
}
626
- }
632
+ };
633
634
return peerTunnel;
629
- }
635
+ };
636
637
setTimeout(function () { obj.ConnectToPeers(); }, 1000); // Delay this a little to make sure we are ready on our side.
638
return obj;
633
-}
639
+};
\ No newline at end of file
pass.js
+6
-1
@@ -1,6 +1,11 @@
1
// check out https://github.com/tj/node-pwd
2
3
-'use strict';
3
+/*jslint node: true */
4
+/*jshint node: true */
5
+/*jshint strict:false */
6
+/*jshint -W097 */
7
+/*jshint esversion: 6 */
8
+"use strict";
9
10
// Module dependencies.
11
const crypto = require('crypto');
swarmserver.js
+19
-14
@@ -6,7 +6,12 @@
6
* @version v0.0.1
7
*/
8
9
-'use strict';
9
+/*jslint node: true */
10
+/*jshint node: true */
11
+/*jshint strict:false */
12
+/*jshint -W097 */
13
+/*jshint esversion: 6 */
14
+"use strict";
15
16
// Construct a legacy Swarm Server server object
17
module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
@@ -18,7 +23,7 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
23
obj.legacyAgentConnections = {};
24
obj.migrationAgents = {};
25
const common = require('./common.js');
21
- const net = require('net');
26
+ //const net = require('net');
27
const tls = require('tls');
28
const forge = require('node-forge');
29
@@ -115,7 +120,7 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
120
USERAUTH2: 1031, // Authenticate a user to the swarm server (Uses SHA1 SALT)
121
GUESTREMOTEDESKTOP: 2001, // Guest usage: Remote Desktop
122
GUESTWEBRTCMESH: 2002 // Guest usage: WebRTC Mesh
118
- }
123
+ };
124
125
obj.server = tls.createServer({ key: certificates.swarmserver.key, cert: certificates.swarmserver.cert, requestCert: true }, onConnection);
126
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) {
151
socket.setEncoding('binary');
152
socket.pingTimer = setInterval(function () { obj.SendCommand(socket, LegacyMeshProtocol.PING); }, 20000);
153
Debug(1, 'SWARM:New legacy agent connection');
149
-
154
+
155
socket.addListener("data", function (data) {
156
if (args.swarmdebug) { var buf = new Buffer(data, "binary"); console.log('SWARM <-- (' + buf.length + '):' + buf.toString('hex')); } // Print out received bytes
157
socket.tag.accumulator += data;
153
-
158
+
159
// 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.
160
if (socket.tag.first == true) {
161
if (socket.tag.accumulator.length < 3) return;
@@ -214,7 +219,7 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
219
Debug(3, 'Swarm:GETSTATE');
220
if (len < 12) break;
221
var statecmd = common.ReadInt(data, 0);
217
- var statesync = common.ReadInt(data, 4);
222
+ //var statesync = common.ReadInt(data, 4);
223
switch (statecmd) {
224
case 6: { // Ask for agent block
225
if (socket.tag.update != null) {
@@ -247,14 +252,14 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
252
}
253
return len;
254
}
250
-
255
+
256
socket.addListener("close", function () {
257
Debug(1, 'Swarm:Connection closed');
258
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
259
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2);
260
if (socket.pingTimer != null) { clearInterval(socket.pingTimer); delete socket.pingTimer; }
261
});
257
-
262
+
263
socket.addListener("error", function () {
264
//console.log("Swarm Error: " + socket.remoteAddress);
265
});
@@ -311,19 +316,19 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
316
console.log(e);
317
}
318
return null;
314
- }
319
+ };
320
321
// Disconnect legacy agent connection
322
obj.close = function (socket) {
323
try { socket.close(); } catch (e) { }
324
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
325
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2);
321
- }
326
+ };
327
323
- obj.SendCommand = function(socket, cmdid, data) {
328
+ obj.SendCommand = function (socket, cmdid, data) {
329
if (data == null) { data = ''; }
330
Write(socket, common.ShortToStr(cmdid) + common.ShortToStr(data.length + 4) + data);
326
- }
331
+ };
332
333
function Write(socket, data) {
334
if (args.swarmdebug) {
@@ -335,7 +340,7 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
340
socket.write(new Buffer(data, "binary"));
341
}
342
}
338
-
343
+
344
// Debug
345
function Debug(lvl) {
346
if (lvl > obj.parent.debugLevel) return;
@@ -348,4 +353,4 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
353
}
354
355
return obj;
351
-}
356
+};
views/default.handlebars
+11
-10
@@ -2251,9 +2251,8 @@
2251
var boundingBox = null;
2252
for (var i in nodes) {
2253
try {
2254
- var loc = map_parseNodeLoc(nodes[i]);
2255
- var feature = xxmap.markersSource.getFeatureById(nodes[i]._id);
2256
- if ((typeof loc == 'object') && ((nodes[i].meshid == selectedMesh) || (selectedMesh == null))) { // Draw markers for devices with locations
2254
+ var loc = map_parseNodeLoc(nodes[i]), feature = xxmap.markersSource.getFeatureById(nodes[i]._id);
2255
+ if ((loc != null) && ((nodes[i].meshid == selectedMesh) || (selectedMesh == null))) { // Draw markers for devices with locations
2256
var lat = loc[0], lon = loc[1], type = loc[2];
2257
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; } }
2258
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 @@
2310
if (node.wifiloc) { loc = node.wifiloc; t = 2; }
2311
if (node.gpsloc) { loc = node.gpsloc; t = 3; }
2312
if (node.userloc) { loc = node.userloc; t = 4; }
2314
- if ((loc == null) || (typeof loc != 'string')) return;
2313
+ if ((loc == null) || (typeof loc != 'string')) return null;
2314
loc = loc.split(',');
2315
if (t == 1) {
2316
// If this is IP location, randomize the position a little.
@@ -2450,12 +2449,14 @@
2449
}
2450
2451
// Since this is IP address location, add some fixed randomness to the location. Avoid pin pile-up.
2453
- var loc = map_parseNodeLoc(node); lat = loc[0]; lon = loc[1];
2454
-
2455
- if ((lat != feature.get('lat')) || (lon != feature.get('lon'))) { // Update lat and lon if changed
2456
- feature.set('lat', lat); feature.set('lon', lon);
2457
- var modifiedCoordinates = ol.proj.transform([parseFloat(lon), parseFloat(lat)], 'EPSG:4326','EPSG:3857');
2458
- feature.getGeometry().setCoordinates(modifiedCoordinates);
2452
+ var loc = map_parseNodeLoc(node);
2453
+ if (loc != null) {
2454
+ var lat = loc[0], lon = loc[1];
2455
+ if ((lat != feature.get('lat')) || (lon != feature.get('lon'))) { // Update lat and lon if changed
2456
+ feature.set('lat', lat); feature.set('lon', lon);
2457
+ var modifiedCoordinates = ol.proj.transform([parseFloat(lon), parseFloat(lat)], 'EPSG:4326', 'EPSG:3857');
2458
+ feature.getGeometry().setCoordinates(modifiedCoordinates);
2459
+ }
2460
}
2461
2462
if (node.name != feature.get('name') ) { feature.set('name', node.name); } // Update name
webserver.js
+134
-132
@@ -6,7 +6,12 @@
6
* @version v0.0.1
7
*/
8
9
-'use strict';
9
+/*jslint node: true */
10
+/*jshint node: true */
11
+/*jshint strict:false */
12
+/*jshint -W097 */
13
+/*jshint esversion: 6 */
14
+"use strict";
15
16
/*
17
class SerialTunnel extends require('stream').Duplex {
@@ -22,9 +27,9 @@ class SerialTunnel extends require('stream').Duplex {
27
function SerialTunnel(options) {
28
var obj = new require('stream').Duplex(options);
29
obj.forwardwrite = null;
25
- obj.updateBuffer = function (chunk) { this.push(chunk); }
26
- 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
27
- obj._read = function(size) { } // Push nothing, anything to read should be pushed from updateBuffer()
30
+ obj.updateBuffer = function (chunk) { this.push(chunk); };
31
+ 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
32
+ obj._read = function (size) { }; // Push nothing, anything to read should be pushed from updateBuffer()
33
return obj;
34
}
35
@@ -37,7 +42,7 @@ if (!String.prototype.endsWith) { String.prototype.endsWith = function (searchSt
42
43
// Construct a HTTP web server object
44
module.exports.CreateWebServer = function (parent, db, args, certificates) {
40
- var obj = {};
45
+ var obj = {}, i = 0;
46
47
// Modules
48
obj.fs = require('fs');
@@ -52,8 +57,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
57
obj.common = require('./common.js');
58
obj.express = require('express');
59
obj.meshAgentHandler = require('./meshagent.js');
55
- obj.meshRelayHandler = require('./meshrelay.js')
56
- obj.meshUserHandler = require('./meshuser.js')
60
+ obj.meshRelayHandler = require('./meshrelay.js');
61
+ obj.meshUserHandler = require('./meshuser.js');
62
obj.interceptor = require('./interceptor');
63
64
// Variables
@@ -63,13 +68,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
68
obj.app = obj.express();
69
obj.app.use(require('compression')());
70
obj.tlsServer = null;
66
- obj.tcpServer;
71
+ obj.tcpServer = null;
72
obj.certificates = certificates;
73
obj.args = args;
74
obj.users = {};
75
obj.meshes = {};
76
obj.userAllowedIp = args.userallowedip; // List of allowed IP addresses for users
72
- obj.tlsSniCredentials;
77
+ obj.tlsSniCredentials = null;
78
obj.dnsDomains = {};
79
//obj.agentConnCount = 0;
80
@@ -93,13 +98,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
98
99
// Setup SSPI authentication if needed
100
if ((obj.parent.platform == 'win32') && (obj.args.nousers != true) && (obj.parent.config != null) && (obj.parent.config.domains != null)) {
96
- 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 }); } }
101
+ 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 }); } }
102
}
103
104
// Perform hash on web certificate and agent certificate
105
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' });
106
obj.webCertificateHashs = { '': obj.webCertificateHash };
102
- 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' }); } }
107
+ 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' }); } }
108
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, '$');
109
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' });
110
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) {
135
{
136
var dnscount = 0;
137
obj.tlsSniCredentials = {};
133
- 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++; } }
138
+ 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++; } }
139
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; }
140
}
141
function TlsSniCallback(name, cb) { var c = obj.tlsSniCredentials[name]; if (c != null) { cb(null, c); } else { cb(null, obj.tlsSniCredentials['']); } }
142
143
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; }
139
- 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; }
144
+ //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; }
145
146
if (obj.args.notls || obj.args.tlsoffload) {
147
// Setup the HTTP server without TLS
@@ -172,27 +177,28 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
177
178
// Session-persisted message middleware
179
obj.app.use(function (req, res, next) {
180
+ var err = null, msg = null, passhint = null;
181
if (req.session != null) {
176
- var err = req.session.error;
177
- var msg = req.session.success;
178
- var passhint = req.session.passhint;
182
+ err = req.session.error;
183
+ msg = req.session.success;
184
+ passhint = req.session.passhint;
185
delete req.session.error;
186
delete req.session.success;
187
delete req.session.passhint;
188
}
189
res.locals.message = '';
184
- if (err) res.locals.message = '<p class="msg error">' + err + '</p>';
185
- if (msg) res.locals.message = '<p class="msg success">' + msg + '</p>';
186
- if (passhint) res.locals.passhint = EscapeHtml(passhint);
190
+ if (err != null) res.locals.message = '<p class="msg error">' + err + '</p>';
191
+ if (msg != null) res.locals.message = '<p class="msg success">' + msg + '</p>';
192
+ if (passhint != null) res.locals.passhint = EscapeHtml(passhint);
193
next();
194
});
195
196
// Fetch all users from the database, keep this in memory
197
obj.db.GetAllType('user', function (err, docs) {
192
- var domainUserCount = {};
193
- for (var i in parent.config.domains) { domainUserCount[i] = 0; }
194
- for (var i in docs) { var u = obj.users[docs[i]._id] = docs[i]; domainUserCount[u.domain]++; }
195
- for (var i in parent.config.domains) {
198
+ var domainUserCount = {}, i = 0;
199
+ for (i in parent.config.domains) { domainUserCount[i] = 0; }
200
+ for (i in docs) { var u = obj.users[docs[i]._id] = docs[i]; domainUserCount[u.domain]++; }
201
+ for (i in parent.config.domains) {
202
if (domainUserCount[i] == 0) {
203
if (parent.config.domains[i].newaccounts == 0) { parent.config.domains[i].newaccounts = 2; }
204
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) {
243
});
244
}
245
}
240
- }
246
+ };
247
248
/*
249
obj.restrict = function (req, res, next) {
@@ -249,7 +255,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
255
req.session.error = 'Access denied!';
256
res.redirect(domain.url + 'login');
257
}
252
- }
258
+ };
259
*/
260
261
// 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) {
293
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.
294
var x = req.url.split('/');
295
if (x.length < 2) return parent.config.domains[''];
290
- var d = parent.config.domains[x[1].toLowerCase()];
291
- if ((d != null) && (d.dns == null)) return parent.config.domains[x[1].toLowerCase()];
296
+ var y = parent.config.domains[x[1].toLowerCase()];
297
+ if ((y != null) && (y.dns == null)) return parent.config.domains[x[1].toLowerCase()];
298
return parent.config.domains[''];
299
}
300
@@ -298,8 +304,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
304
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' });
305
// Destroy the user's session to log them out will be re-created next request
306
if (req.session.userid) {
301
- var user = obj.users[req.session.userid]
302
- obj.parent.DispatchEvent(['*'], obj, { etype: 'user', username: user.name, action: 'logout', msg: 'Account logout', domain: domain.id })
307
+ var user = obj.users[req.session.userid];
308
+ obj.parent.DispatchEvent(['*'], obj, { etype: 'user', username: user.name, action: 'logout', msg: 'Account logout', domain: domain.id });
309
}
310
req.session = null;
311
res.redirect(domain.url);
@@ -319,35 +325,35 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
325
326
// Regenerate session when signing in to prevent fixation
327
//req.session.regenerate(function () {
322
- // Store the user's primary key in the session store to be retrieved, or in this case the entire user object
323
- // req.session.success = 'Authenticated as ' + user.name + 'click to <a href="/logout">logout</a>. You may now access <a href="/restricted">/restricted</a>.';
324
- delete req.session.loginmode;
325
- req.session.userid = userid;
326
- req.session.domainid = domain.id;
327
- req.session.currentNode = '';
328
- if (req.session.passhint) { delete req.session.passhint; }
329
- if (req.body.viewmode) { req.session.viewmode = req.body.viewmode; }
330
- if (req.body.host) {
331
- // TODO: This is a terrible search!!! FIX THIS.
332
- /*
333
- obj.db.GetAllType('node', function (err, docs) {
334
- for (var i = 0; i < docs.length; i++) {
335
- if (docs[i].name == req.body.host) {
336
- req.session.currentNode = docs[i]._id;
337
- break;
338
- }
328
+ // Store the user's primary key in the session store to be retrieved, or in this case the entire user object
329
+ // req.session.success = 'Authenticated as ' + user.name + 'click to <a href="/logout">logout</a>. You may now access <a href="/restricted">/restricted</a>.';
330
+ delete req.session.loginmode;
331
+ req.session.userid = userid;
332
+ req.session.domainid = domain.id;
333
+ req.session.currentNode = '';
334
+ if (req.session.passhint) { delete req.session.passhint; }
335
+ if (req.body.viewmode) { req.session.viewmode = req.body.viewmode; }
336
+ if (req.body.host) {
337
+ // TODO: This is a terrible search!!! FIX THIS.
338
+ /*
339
+ obj.db.GetAllType('node', function (err, docs) {
340
+ for (var i = 0; i < docs.length; i++) {
341
+ if (docs[i].name == req.body.host) {
342
+ req.session.currentNode = docs[i]._id;
343
+ break;
344
}
340
- console.log("CurrentNode: " + req.session.currentNode);
341
- // This redirect happens after finding node is completed
342
- res.redirect(domain.url);
343
- });
344
- */
345
- } else {
345
+ }
346
+ console.log("CurrentNode: " + req.session.currentNode);
347
+ // This redirect happens after finding node is completed
348
res.redirect(domain.url);
347
- }
349
+ });
350
+ */
351
+ } else {
352
+ res.redirect(domain.url);
353
+ }
354
//});
355
350
- obj.parent.DispatchEvent(['*'], obj, { etype: 'user', username: user.name, action: 'login', msg: 'Account login', domain: domain.id })
356
+ obj.parent.DispatchEvent(['*'], obj, { etype: 'user', username: user.name, action: 'login', msg: 'Account login', domain: domain.id });
357
} else {
358
delete req.session.loginmode;
359
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) {
373
if (domain.newaccounts == 0) { res.sendStatus(401); return; }
374
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 == '~') {
375
req.session.loginmode = 2;
370
- req.session.error = '<b style=color:#8C001A>Unable to create account.</b>';;
376
+ req.session.error = '<b style=color:#8C001A>Unable to create account.</b>';
377
res.redirect(domain.url);
378
} else {
379
// Check if this email was already verified
380
obj.db.GetUserWithVerifiedEmail(domain.id, req.body.email, function (err, docs) {
381
if (docs.length > 0) {
382
req.session.loginmode = 2;
377
- req.session.error = '<b style=color:#8C001A>Existing account with this email address.</b>';;
383
+ req.session.error = '<b style=color:#8C001A>Existing account with this email address.</b>';
384
res.redirect(domain.url);
385
} else {
386
// Check if there is domain.newAccountToken, check if supplied token is valid
@@ -406,7 +412,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
412
obj.db.SetUser(user);
413
if (obj.parent.mailserver != null) { obj.parent.mailserver.sendAccountCheckMail(domain, user.name, user.email); }
414
});
409
- 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 })
415
+ 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 });
416
}
417
res.redirect(domain.url);
418
}
@@ -459,7 +465,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
465
} else {
466
obj.db.Get('user/' + cookie.u, function (err, docs) {
467
if (docs.length == 0) {
462
- 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>.' });
468
+ 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>.' });
469
} else {
470
var user = docs[0];
471
if (user.email != cookie.e) {
@@ -488,13 +494,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
494
delete userinfo.domain;
495
delete userinfo.subscriptions;
496
delete userinfo.passtype;
491
- 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 })
497
+ 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 });
498
499
// Send the confirmation page
500
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>.' });
501
502
// Send a notification
497
- obj.parent.DispatchEvent([user._id], obj, { action: 'notify', value: 'Email verified:<br /><b>' + EscapeHtml(userinfo.email) + '</b>.', nolog: 1 })
503
+ obj.parent.DispatchEvent([user._id], obj, { action: 'notify', value: 'Email verified:<br /><b>' + EscapeHtml(userinfo.email) + '</b>.', nolog: 1 });
504
}
505
});
506
}
@@ -507,10 +513,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
513
obj.crypto.randomBytes(16, function (err, buf) {
514
var newpass = buf.toString('base64').split('=').join('').split('/').join('');
515
require('./pass').hash(newpass, function (err, salt, hash) {
516
+ var userinfo = null;
517
if (err) throw err;
518
519
// Change the password
513
- var userinfo = obj.users[user._id];
520
+ userinfo = obj.users[user._id];
521
userinfo.salt = salt;
522
userinfo.hash = hash;
523
userinfo.passchange = Date.now();
@@ -518,7 +525,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
525
obj.db.SetUser(userinfo);
526
527
// Event the change
521
- var userinfo = obj.common.Clone(userinfo);
528
+ userinfo = obj.common.Clone(userinfo);
529
delete userinfo.hash;
530
delete userinfo.passhint;
531
delete userinfo.salt;
@@ -526,7 +533,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
533
delete userinfo.domain;
534
delete userinfo.subscriptions;
535
delete userinfo.passtype;
529
- 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 })
536
+ 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 });
537
538
// Send the new password
539
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) {
576
if (mesh.links[escUserId] != null) { delete mesh.links[escUserId]; obj.db.Set(mesh); }
577
// Notify mesh change
578
var change = 'Removed user ' + user.name + ' from mesh ' + mesh.name;
572
- 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 })
579
+ 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 });
580
}
581
}
582
}
@@ -582,7 +589,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
589
delete obj.users[user._id];
590
req.session = null;
591
res.redirect(domain.url);
585
- obj.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: user.name, action: 'accountremove', msg: 'Account removed', domain: domain.id })
592
+ obj.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: user.name, action: 'accountremove', msg: 'Account removed', domain: domain.id });
593
} else {
594
res.redirect(domain.url);
595
}
@@ -609,7 +616,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
616
obj.db.SetUser(user);
617
req.session.viewmode = 2;
618
res.redirect(domain.url);
612
- obj.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: user.name, action: 'passchange', msg: 'Account password changed: ' + user.name, domain: domain.id })
619
+ obj.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: user.name, action: 'passchange', msg: 'Account password changed: ' + user.name, domain: domain.id });
620
});
621
}
622
@@ -618,11 +625,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
625
var domain = checkUserIpAddress(req, res);
626
if (domain == null) return;
627
if (!obj.args) { res.sendStatus(500); return; }
621
- var domain = getDomain(req);
628
629
if ((domain.sspi != null) && ((req.query.login == null) || (obj.parent.loginCookieEncryptionKey == null))) {
630
// Login using SSPI
625
- domain.sspi.authenticate(req, res, function (err) { if ((err != null) || (req.connection.user == null)) { res.end('Authentication Required...'); } else { handleRootRequestEx(req, res, domain); } })
631
+ domain.sspi.authenticate(req, res, function (err) { if ((err != null) || (req.connection.user == null)) { res.end('Authentication Required...'); } else { handleRootRequestEx(req, res, domain); } });
632
} else {
633
// Login using a different system
634
handleRootRequestEx(req, res, domain);
@@ -630,7 +636,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
636
}
637
638
function handleRootRequestEx(req, res, domain) {
633
- var nologout = false;
639
+ var nologout = false, user = null, features = 0;
640
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' });
641
642
// Check if we have an incomplete domain name in the path
@@ -676,15 +682,15 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
682
req.session.currentNode = '';
683
684
// Check if this user exists, create it if not.
679
- var user = obj.users[req.session.userid];
685
+ user = obj.users[req.session.userid];
686
if ((user == null) || (user.sid != req.session.usersid)) {
687
// Create the domain user
682
- var usercount = 0, user = { type: 'user', _id: req.session.userid, name: req.connection.user, domain: domain.id, sid: req.session.usersid };
688
+ var usercount = 0, user2 = { type: 'user', _id: req.session.userid, name: req.connection.user, domain: domain.id, sid: req.session.usersid };
689
for (var i in obj.users) { if (obj.users[i].domain == domain.id) { usercount++; } }
684
- if (usercount == 0) { user.siteadmin = 0xFFFFFFFF; } // If this is the first user, give the account site admin.
685
- obj.users[req.session.userid] = user;
686
- obj.db.SetUser(user);
687
- 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 })
690
+ if (usercount == 0) { user2.siteadmin = 0xFFFFFFFF; } // If this is the first user, give the account site admin.
691
+ obj.users[req.session.userid] = user2;
692
+ obj.db.SetUser(user2);
693
+ 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 });
694
}
695
}
696
}
@@ -706,15 +712,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
712
} else if (req.query.node) {
713
currentNode = 'node/' + domain.id + '/' + req.query.node;
714
}
709
- var user;
710
- var logoutcontrol;
711
- if (obj.args.nousers != true) {
712
- user = obj.users[req.session.userid]
713
- logoutcontrol = 'Welcome ' + user.name + '.';
714
- }
715
+ var logoutcontrol = '';
716
+ if (obj.args.nousers != true) { logoutcontrol = 'Welcome ' + obj.users[req.session.userid].name + '.'; }
717
718
// Give the web page a list of supported server features
717
- var features = 0;
719
+ features = 0;
720
if (obj.args.wanonly == true) { features += 1; } // WAN-only mode
721
if (obj.args.lanonly == true) { features += 2; } // LAN-only mode
722
if (obj.args.nousers == true) { features += 4; } // Single user mode
@@ -745,7 +747,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
747
}
748
} else {
749
// Send back the login application
748
- var loginmode = req.session.loginmode, features = 0;
750
+ var loginmode = req.session.loginmode;
751
+ features = 0;
752
delete req.session.loginmode; // Clear this state, if the user hits refresh, we want to go back to the login page.
753
if ((parent.config != null) && (parent.config.settings != null) && (parent.config.settings.allowframing == true)) { features += 32; } // Allow site within iframe
754
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) {
903
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; } }
904
905
var stat = null;
903
- try { stat = obj.fs.statSync(path) } catch (e) { }
906
+ try { stat = obj.fs.statSync(path); } catch (e) { }
907
if ((stat != null) && ((stat.mode & 0x004000) == 0)) {
908
if (req.query.download == 1) {
909
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) {
926
if (splitpath[1] != '') { serverpath += '-' + splitpath[1]; } // Add the domain if needed
927
serverpath += ('/' + splitpath[0] + '-' + splitpath[2]);
928
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
926
- var fullpath = obj.path.resolve(obj.filespath, serverpath), quota = 0;
927
- return { fullpath: fullpath, path: serverpath, name: filename, quota: obj.getQuota(objid, domain) };
928
- }
929
+ return { fullpath: obj.path.resolve(obj.filespath, serverpath), path: serverpath, name: filename, quota: obj.getQuota(objid, domain) };
930
+ };
931
932
// Return the maximum number of bytes allowed in the user account "My Files".
933
obj.getQuota = function (objid, domain) {
@@ -944,7 +946,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
946
return 1048576; // By default, the server will have a 1 meg limit on mesh accounts
947
}
948
return 0;
947
- }
949
+ };
950
951
// Download a file from the server
952
function handleDownloadFile(req, res) {
@@ -1014,7 +1016,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1016
obj.fs.mkdir(xfile.fullpath, function () {
1017
// Write the file
1018
obj.fs.writeFile(obj.path.join(xfile.fullpath, filename), filedata, function () {
1017
- obj.parent.DispatchEvent([user._id], obj, 'updatefiles') // Fire an event causing this user to update this files
1019
+ obj.parent.DispatchEvent([user._id], obj, 'updatefiles'); // Fire an event causing this user to update this files
1020
});
1021
});
1022
})(xfile.fullpath, names[i], filedata);
@@ -1027,7 +1029,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1029
var file = files.files[i], fpath = obj.path.join(xfile.fullpath, file.originalFilename);
1030
if (obj.common.IsFilenameValid(file.originalFilename) && ((totalsize + file.size) < xfile.quota)) { // Check if quota would not be broken if we add this file
1031
obj.fs.rename(file.path, fpath, function () {
1030
- obj.parent.DispatchEvent([user._id], obj, 'updatefiles') // Fire an event causing this user to update this files
1032
+ obj.parent.DispatchEvent([user._id], obj, 'updatefiles'); // Fire an event causing this user to update this files
1033
});
1034
} else {
1035
try { obj.fs.unlink(file.path); } catch (e) { }
@@ -1051,7 +1053,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1053
obj.parent.RemoveAllEventDispatch(target);
1054
obj.parent.AddEventDispatch(subscriptions, target);
1055
return subscriptions;
1054
- }
1056
+ };
1057
1058
// Handle a web socket relay request
1059
function handleRelayWebSocket(ws, req) {
@@ -1143,13 +1145,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1145
// CIRA ---> TLS
1146
Debug(3, 'Relay TLS CIRA data', data.length);
1147
if (data.length > 0) { try { ser.updateBuffer(Buffer.from(data, 'binary')); } catch (e) { } }
1146
- }
1148
+ };
1149
1150
// Handke CIRA tunnel state change
1151
chnl.onStateChange = function (ciraconn, state) {
1152
Debug(2, 'Relay TLS CIRA state change', state);
1153
if (state == 0) { try { ws.close(); } catch (e) { } }
1152
- }
1154
+ };
1155
1156
// TLSSocket to encapsulate TLS communication, which then tunneled via SerialTunnel an then wrapped through CIRA APF
1157
var TLSSocket = require('tls').TLSSocket;
@@ -1199,18 +1201,18 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1201
ws.forwardclient.onStateChange = function (ciraconn, state) {
1202
Debug(2, 'Relay CIRA state change', state);
1203
if (state == 0) { try { ws.close(); } catch (e) { } }
1202
- }
1204
+ };
1205
1206
ws.forwardclient.onData = function (ciraconn, data) {
1207
Debug(4, 'Relay CIRA data', data.length);
1208
if (ws.interceptor) { data = ws.interceptor.processAmtData(data); } // Run data thru interceptor
1209
if (data.length > 0) { try { ws.send(data); } catch (e) { } } // TODO: Add TLS support
1208
- }
1210
+ };
1211
1212
ws.forwardclient.onSendOk = function (ciraconn) {
1213
// TODO: Flow control? (Dont' really need it with AMT, but would be nice)
1214
//console.log('onSendOk');
1213
- }
1215
+ };
1216
1217
// Fetch Intel AMT credentials & Setup interceptor
1218
if (req.query.p == 1) {
@@ -1345,7 +1347,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1347
var r = 0, dir;
1348
try { dir = obj.fs.readdirSync(path); } catch (e) { return 0; }
1349
for (var i in dir) {
1348
- var stat = obj.fs.statSync(path + '/' + dir[i])
1350
+ var stat = obj.fs.statSync(path + '/' + dir[i]);
1351
if ((stat.mode & 0x004000) == 0) { r += stat.size; } else { r += readTotalFileSize(path + '/' + dir[i]); }
1352
}
1353
return r;
@@ -1359,15 +1361,15 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1361
if (obj.fs.lstatSync(pathx).isDirectory()) { deleteFolderRec(pathx); } else { obj.fs.unlinkSync(pathx); }
1362
});
1363
obj.fs.rmdirSync(path);
1362
- };
1364
+ }
1365
1366
// Handle Intel AMT events
1367
// To subscribe, add "http://server:port/amtevents.ashx" to Intel AMT subscriptions.
1368
obj.handleAmtEventRequest = function (req, res) {
1369
var domain = getDomain(req);
1370
try {
1369
- if (req.headers['authorization']) {
1370
- var authstr = req.headers['authorization'];
1371
+ if (req.headers.authorization) {
1372
+ var authstr = req.headers.authorization;
1373
if (authstr.substring(0, 7) == "Digest ") {
1374
var auth = obj.common.parseNameValueList(obj.common.quoteSplit(authstr.substring(7)));
1375
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) {
1438
res.set({ 'WWW-Authenticate': 'Digest realm="' + obj.httpAuthRealm + '", qop="auth,auth-int", nonce="' + nonce + '", opaque="' + opaque + '"' });
1439
res.sendStatus(401);
1440
});
1439
- }
1441
+ };
1442
1443
// Handle a server backup request
1444
function handleBackupRequest(req, res) {
@@ -1541,11 +1543,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1543
// If the agentid is 3 or 4, check if we have a signed MeshCmd.exe
1544
if ((agentid == 3)) { // Signed Windows MeshCmd.exe x86
1545
var stats = null, meshCmdPath = obj.path.join(__dirname, 'agents', 'MeshCmd-signed.exe');
1544
- try { stats = obj.fs.statSync(meshCmdPath) } catch (e) { }
1546
+ try { stats = obj.fs.statSync(meshCmdPath); } catch (e) { }
1547
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; }
1548
} else if ((agentid == 4)) { // Signed Windows MeshCmd64.exe x64
1549
var stats = null, meshCmd64Path = obj.path.join(__dirname, 'agents', 'MeshCmd64-signed.exe');
1548
- try { stats = obj.fs.statSync(meshCmd64Path) } catch (e) { }
1550
+ try { stats = obj.fs.statSync(meshCmd64Path); } catch (e) { }
1551
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; }
1552
}
1553
// No signed agents, we are going to merge a new MeshCmd.
@@ -1581,7 +1583,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1583
serverId: obj.agentCertificateHashHex.toUpperCase(), // SHA384 of server HTTPS public key
1584
serverHttpsHash: new Buffer(obj.webCertificateHash, 'binary').toString('hex').toUpperCase(), // SHA384 of server HTTPS certificate
1585
debugLevel: 0
1584
- }
1586
+ };
1587
if (user != null) { meshaction.username = user.name; }
1588
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
1589
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) {
1598
serverId: obj.agentCertificateHashHex.toUpperCase(), // SHA384 of server HTTPS public key
1599
serverHttpsHash: new Buffer(obj.webCertificateHash, 'binary').toString('hex').toUpperCase(), // SHA384 of server HTTPS certificate
1600
debugLevel: 0
1599
- }
1601
+ };
1602
if (user != null) { meshaction.username = user.name; }
1603
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
1604
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) {
1621
response += '</table></body></html>';
1622
res.send(response);
1623
}
1622
- }
1624
+ };
1625
1626
// Get the web server hostname. This may change if using a domain with a DNS name.
1627
function getWebServerName(domain) {
@@ -1660,7 +1662,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1662
1663
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' });
1664
res.send(meshsettings);
1663
- }
1665
+ };
1666
1667
// Add HTTP security headers to all responses
1668
obj.app.use(function (req, res, next) {
@@ -1785,7 +1787,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1787
// Check we have agent rights
1788
var rights = user.links[agent.dbMeshKey].rights;
1789
if ((rights != null) && ((rights & MESHRIGHT_AGENTCONSOLE) != 0) && (user.siteadmin == 0xFFFFFFFF)) { agent.close(disconnectMode); }
1788
- }
1790
+ };
1791
1792
// Send the core module to the mesh agent
1793
obj.sendMeshAgentCore = function (user, domain, nodeid, core) {
@@ -1815,7 +1817,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1817
agent.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0) + hash + core);
1818
}
1819
}
1818
- }
1820
+ };
1821
1822
// Get the server path of a user or mesh object
1823
function getServerRootFilePath(obj) {
@@ -1878,36 +1880,37 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1880
1881
// Count sessions and event any changes
1882
obj.recountSessions = function (changedSessionId) {
1883
+ var userid, oldcount, newcount, x, serverid;
1884
if (changedSessionId == null) {
1885
// Recount all sessions
1886
1887
// Calculate the session count for all userid's
1888
var newSessionsCount = {};
1886
- for (var userid in obj.wssessions) { newSessionsCount[userid] = obj.wssessions[userid].length; }
1887
- for (var serverid in obj.wsPeerSessions3) {
1888
- for (var userid in obj.wsPeerSessions3[serverid]) {
1889
- var c = obj.wsPeerSessions3[serverid][userid].length;
1890
- if (newSessionsCount[userid] == null) { newSessionsCount[userid] = c; } else { newSessionsCount[userid] += c; }
1889
+ for (userid in obj.wssessions) { newSessionsCount[userid] = obj.wssessions[userid].length; }
1890
+ for (serverid in obj.wsPeerSessions3) {
1891
+ for (userid in obj.wsPeerSessions3[serverid]) {
1892
+ x = obj.wsPeerSessions3[serverid][userid].length;
1893
+ if (newSessionsCount[userid] == null) { newSessionsCount[userid] = x; } else { newSessionsCount[userid] += x; }
1894
}
1895
}
1896
1897
// See what session counts have changed, event any changes
1895
- for (var userid in newSessionsCount) {
1896
- var newcount = newSessionsCount[userid];
1897
- var oldcount = obj.sessionsCount[userid];
1898
+ for (userid in newSessionsCount) {
1899
+ newcount = newSessionsCount[userid];
1900
+ oldcount = obj.sessionsCount[userid];
1901
if (oldcount == null) { oldcount = 0; } else { delete obj.sessionsCount[userid]; }
1902
if (newcount != oldcount) {
1900
- var x = userid.split('/');
1901
- obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: newcount, domain: x[1], nolog: 1, nopeers: 1 })
1903
+ x = userid.split('/');
1904
+ obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: newcount, domain: x[1], nolog: 1, nopeers: 1 });
1905
}
1906
}
1907
1908
// If there are any counts left in the old counts, event to zero
1906
- for (var userid in obj.sessionsCount) {
1907
- var oldcount = obj.sessionsCount[userid];
1909
+ for (userid in obj.sessionsCount) {
1910
+ oldcount = obj.sessionsCount[userid];
1911
if ((oldcount != null) && (oldcount != 0)) {
1909
- var x = userid.split('/');
1910
- obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: 0, domain: x[1], nolog: 1, nopeers: 1 })
1912
+ x = userid.split('/');
1913
+ obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: 0, domain: x[1], nolog: 1, nopeers: 1 });
1914
}
1915
}
1916
@@ -1915,23 +1918,23 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1918
obj.sessionsCount = newSessionsCount;
1919
} else {
1920
// Figure out the userid
1918
- var userid = changedSessionId.split('/').slice(0, 3).join('/');
1921
+ userid = changedSessionId.split('/').slice(0, 3).join('/');
1922
1923
// Recount only changedSessionId
1921
- var newcount = 0;
1924
+ newcount = 0;
1925
if (obj.wssessions[userid] != null) { newcount = obj.wssessions[userid].length; }
1923
- for (var serverid in obj.wsPeerSessions3) { if (obj.wsPeerSessions3[serverid][userid] != null) { newcount += obj.wsPeerSessions3[serverid][userid].length; } }
1924
- var oldcount = obj.sessionsCount[userid];
1926
+ for (serverid in obj.wsPeerSessions3) { if (obj.wsPeerSessions3[serverid][userid] != null) { newcount += obj.wsPeerSessions3[serverid][userid].length; } }
1927
+ oldcount = obj.sessionsCount[userid];
1928
if (oldcount == null) { oldcount = 0; }
1929
1930
// If the count changed, update and event
1931
if (newcount != oldcount) {
1929
- var x = userid.split('/');
1930
- obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: newcount, domain: x[1], nolog: 1, nopeers: 1 })
1932
+ x = userid.split('/');
1933
+ obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: newcount, domain: x[1], nolog: 1, nopeers: 1 });
1934
obj.sessionsCount[userid] = newcount;
1935
}
1936
}
1934
- }
1937
+ };
1938
1939
// Return true if a mobile browser is detected.
1940
// 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) {
1946
}
1947
1948
return obj;
1946
-}
1947
-
1949
+};
\ No newline at end of file
winservice.js
+6
-1
@@ -6,7 +6,12 @@
6
* @version v0.0.1
7
*/
8
9
-'use strict';
9
+/*jslint node: true */
10
+/*jshint node: true */
11
+/*jshint strict:false */
12
+/*jshint -W097 */
13
+/*jshint esversion: 6 */
14
+"use strict";
15
16
// This module is only called when MeshCentral is running as a Windows service.
17
// In this case, we don't want to start a child process, so we launch directly without arguments.