Improved support for reverse-proxy certificate loading.
Ylian Saint-Hilaire committed
Oct 29, 2019 at 16:17 UTC
1f06f916102e8952c67ec8647175eba49ffd9806
6 files changed
+127
-88
certoperations.js
+1
-2
@@ -196,7 +196,6 @@ module.exports.CertificateOperations = function (parent) {
196
197
// Return the certificate of the remote HTTPS server
198
obj.loadCertificate = function (url, hostname, tag, func) {
199
- console.log('loadCertificate', url, hostname);
199
const u = require('url').parse(url);
200
if (u.protocol == 'https:') {
201
// Read the certificate from HTTPS
@@ -218,7 +217,7 @@ module.exports.CertificateOperations = function (parent) {
217
func(url, data, hostname, tag);
218
}
219
});
221
- } else { func(url, null, tag); }
220
+ } else { func(url, null, hostname, tag); }
221
};
222
223
// Check if a configuration file exists
common.js
+3
@@ -35,6 +35,9 @@ module.exports.makeFilename = function (v) { return v.split('\\').join('').split
35
// Move an element from one position in an array to a new position
36
module.exports.ArrayElementMove = function(arr, from, to) { arr.splice(to, 0, arr.splice(from, 1)[0]); };
37
38
+// Format a string with arguments, "replaces {0} and {1}..."
39
+module.exports.format = function (format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
40
+
41
// Print object for HTML
42
module.exports.ObjectToStringEx = function (x, c) {
43
var r = "", i;
meshagent.js
+8
@@ -53,6 +53,9 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
53
parent.parent.ClearConnectivityState(obj.dbMeshKey, obj.dbNodeKey, 1);
54
}
55
56
+ // Remove this agent from the list of agents with bad web certificates
57
+ if (obj.badWebCert) { delete parent.wsagentsWithBadWebCerts[obj.badWebCert]; }
58
+
59
// Get the current mesh
60
const mesh = parent.meshes[obj.dbMeshKey];
61
@@ -381,6 +384,11 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
384
} else {
385
// Check that the server hash matches our own web certificate hash (SHA384)
386
if ((getWebCertHash(domain) != msg.substring(2, 50)) && (getWebCertFullHash(domain) != msg.substring(2, 50))) {
387
+ if (parent.parent.supportsProxyCertificatesRequest !== false) {
388
+ obj.badWebCert = Buffer.from(parent.crypto.randomBytes(16), 'binary').toString('base64');
389
+ parent.wsagentsWithBadWebCerts[obj.badWebCert] = obj; // Add this agent to the list of of agents with bad web certificates.
390
+ parent.parent.updateProxyCertificates();
391
+ }
392
parent.agentStats.agentBadWebCertHashCount++;
393
console.log('Agent bad web cert hash (Agent:' + (Buffer.from(msg.substring(2, 50), 'binary').toString('hex').substring(0, 10)) + ' != Server:' + (Buffer.from(getWebCertHash(domain), 'binary').toString('hex').substring(0, 10)) + ' or ' + (new Buffer(getWebCertFullHash(domain), 'binary').toString('hex').substring(0, 10)) + '), holding connection (' + obj.remoteaddrport + ').');
394
console.log('Agent reported web cert hash:' + (Buffer.from(msg.substring(2, 50), 'binary').toString('hex')) + '.');
meshcentral.js
+102
-74
@@ -396,34 +396,34 @@ function CreateMeshCentralServer(config, args) {
396
397
// Show a list of all configuration files in the database
398
if (obj.args.dblistconfigfiles) {
399
- obj.db.GetAllType('cfile', function (err, docs) { if (err == null) { if (docs.length == 0) { console.log('No files found.'); } else { for (var i in docs) { console.log(docs[i]._id.split('/')[1] + ', ' + Buffer.from(docs[i].data, 'base64').length + ' bytes.'); } } } else { console.log('Unable to read from database.'); } process.exit(); }); return;
399
+ obj.db.GetAllType('cfile', function (err, docs) { if (err == null) { if (docs.length == 0) { console.log("No files found."); } else { for (var i in docs) { console.log(docs[i]._id.split('/')[1] + ', ' + Buffer.from(docs[i].data, 'base64').length + ' bytes.'); } } } else { console.log('Unable to read from database.'); } process.exit(); }); return;
400
}
401
402
// Display the content of a configuration file in the database
403
if (obj.args.dbshowconfigfile) {
404
- if (typeof obj.args.configkey != 'string') { console.log('Error, --configkey is required.'); process.exit(); return; }
404
+ if (typeof obj.args.configkey != 'string') { console.log("Error, --configkey is required."); process.exit(); return; }
405
obj.db.getConfigFile(obj.args.dbshowconfigfile, function (err, docs) {
406
if (err == null) {
407
- if (docs.length == 0) { console.log('File not found.'); } else {
407
+ if (docs.length == 0) { console.log("File not found."); } else {
408
var data = obj.db.decryptData(obj.args.configkey, docs[0].data);
409
- if (data == null) { console.log('Invalid config key.'); } else { console.log(data); }
409
+ if (data == null) { console.log("Invalid config key."); } else { console.log(data); }
410
}
411
- } else { console.log('Unable to read from database.'); }
411
+ } else { console.log("Unable to read from database."); }
412
process.exit();
413
}); return;
414
}
415
416
// Delete all configuration files from database
417
if (obj.args.dbdeleteconfigfiles) {
418
- console.log('Deleting all configuration files from the database...'); obj.db.RemoveAllOfType('cfile', function () { console.log('Done.'); process.exit(); });
418
+ console.log("Deleting all configuration files from the database..."); obj.db.RemoveAllOfType('cfile', function () { console.log('Done.'); process.exit(); });
419
}
420
421
// Push all relevent files from meshcentral-data into the database
422
if (obj.args.dbpushconfigfiles) {
423
- if (typeof obj.args.configkey != 'string') { console.log('Error, --configkey is required.'); process.exit(); return; }
423
+ if (typeof obj.args.configkey != 'string') { console.log("Error, --configkey is required."); process.exit(); return; }
424
if ((obj.args.dbpushconfigfiles !== true) && (typeof obj.args.dbpushconfigfiles != 'string')) {
425
- console.log('Usage: --dbpulldatafiles (path) This will import files from folder into the database');
426
- console.log(' --dbpulldatafiles This will import files from meshcentral-data into the db.');
425
+ console.log("Usage: --dbpulldatafiles (path) This will import files from folder into the database");
426
+ console.log(" --dbpulldatafiles This will import files from meshcentral-data into the db.");
427
process.exit();
428
} else {
429
if ((obj.args.dbpushconfigfiles == '*') || (obj.args.dbpushconfigfiles === true)) { obj.args.dbpushconfigfiles = obj.datapath; }
@@ -454,20 +454,20 @@ function CreateMeshCentralServer(config, args) {
454
455
// Pull all database files into meshcentral-data
456
if (obj.args.dbpullconfigfiles) {
457
- if (typeof obj.args.configkey != 'string') { console.log('Error, --configkey is required.'); process.exit(); return; }
457
+ if (typeof obj.args.configkey != 'string') { console.log("Error, --configkey is required."); process.exit(); return; }
458
if (typeof obj.args.dbpullconfigfiles != 'string') {
459
- console.log('Usage: --dbpulldatafiles (path)');
459
+ console.log("Usage: --dbpulldatafiles (path)");
460
process.exit();
461
} else {
462
obj.db.GetAllType('cfile', function (err, docs) {
463
if (err == null) {
464
if (docs.length == 0) {
465
- console.log('File not found.');
465
+ console.log("File not found.");
466
} else {
467
for (var i in docs) {
468
const file = docs[i]._id.split('/')[1], binary = obj.db.decryptData(obj.args.configkey, docs[i].data);
469
if (binary == null) {
470
- console.log('Invalid config key.');
470
+ console.log("Invalid config key.");
471
} else {
472
var fullFileName = obj.path.join(obj.args.dbpullconfigfiles, file);
473
try { obj.fs.writeFileSync(fullFileName, binary); } catch (ex) { console.log('Unable to write to ' + fullFileName); process.exit(); return; }
@@ -476,7 +476,7 @@ function CreateMeshCentralServer(config, args) {
476
}
477
}
478
} else {
479
- console.log('Unable to read from database.');
479
+ console.log("Unable to read from database.");
480
}
481
process.exit();
482
});
@@ -603,10 +603,10 @@ function CreateMeshCentralServer(config, args) {
603
var key = null;
604
if (typeof obj.args.configkey == 'string') { key = obj.args.configkey; }
605
else if (typeof obj.args.loadconfigfromdb == 'string') { key = obj.args.loadconfigfromdb; }
606
- if (key == null) { console.log('Error, --configkey is required.'); process.exit(); return; }
606
+ if (key == null) { console.log("Error, --configkey is required."); process.exit(); return; }
607
obj.db.getAllConfigFiles(key, function (configFiles) {
608
- if (configFiles == null) { console.log('Error, no configuration files found or invalid configkey.'); process.exit(); return; }
609
- if (!configFiles['config.json']) { console.log('Error, could not file config.json from database.'); process.exit(); return; }
608
+ if (configFiles == null) { console.log("Error, no configuration files found or invalid configkey."); process.exit(); return; }
609
+ if (!configFiles['config.json']) { console.log("Error, could not file config.json from database."); process.exit(); return; }
610
obj.configurationFiles = configFiles;
611
612
// Parse the new configuration file
@@ -744,9 +744,9 @@ function CreateMeshCentralServer(config, args) {
744
var adminname = obj.args.admin.split('/');
745
if (adminname.length == 1) { adminname = 'user//' + adminname[0]; }
746
else if (adminname.length == 2) { adminname = 'user/' + adminname[0] + '/' + adminname[1]; }
747
- else { console.log('Invalid administrator name.'); process.exit(); return; }
747
+ else { console.log("Invalid administrator name."); process.exit(); return; }
748
obj.db.Get(adminname, function (err, user) {
749
- if (user.length != 1) { console.log('Invalid user name.'); process.exit(); return; }
749
+ if (user.length != 1) { console.log("Invalid user name."); process.exit(); return; }
750
user[0].siteadmin = 4294967295; // 0xFFFFFFFF
751
obj.db.Set(user[0], function () {
752
if (user[0].domain == '') { console.log('User ' + user[0].name + ' set to site administrator.'); } else { console.log('User ' + user[0].name + ' of domain ' + user[0].domain + ' set to site administrator.'); }
@@ -762,9 +762,9 @@ function CreateMeshCentralServer(config, args) {
762
var adminname = obj.args.unadmin.split('/');
763
if (adminname.length == 1) { adminname = 'user//' + adminname[0]; }
764
else if (adminname.length == 2) { adminname = 'user/' + adminname[0] + '/' + adminname[1]; }
765
- else { console.log('Invalid administrator name.'); process.exit(); return; }
765
+ else { console.log("Invalid administrator name."); process.exit(); return; }
766
obj.db.Get(adminname, function (err, user) {
767
- if (user.length != 1) { console.log('Invalid user name.'); process.exit(); return; }
767
+ if (user.length != 1) { console.log("Invalid user name."); process.exit(); return; }
768
if (user[0].siteadmin) { delete user[0].siteadmin; }
769
obj.db.Set(user[0], function () {
770
if (user[0].domain == '') { console.log('User ' + user[0].name + ' is not a site administrator.'); } else { console.log('User ' + user[0].name + ' of domain ' + user[0].domain + ' is not a site administrator.'); }
@@ -793,15 +793,15 @@ function CreateMeshCentralServer(config, args) {
793
while (obj.dbconfig.amtWsEventSecret == null) { process.nextTick(); }
794
var username = buf.toString('hex');
795
var nodeid = obj.args.getwspass;
796
- var pass = obj.crypto.createHash('sha384').update(username.toLowerCase() + ":" + nodeid + ":" + obj.dbconfig.amtWsEventSecret).digest("base64").substring(0, 12).split("/").join("x").split("\\").join("x");
797
- console.log('--- Intel(r) AMT WSMAN eventing credentials ---');
798
- console.log('Username: ' + username);
799
- console.log('Password: ' + pass);
800
- console.log('Argument: ' + nodeid);
796
+ var pass = obj.crypto.createHash('sha384').update(username.toLowerCase() + ':' + nodeid + ':' + obj.dbconfig.amtWsEventSecret).digest('base64').substring(0, 12).split('/').join('x').split('\\').join('x');
797
+ console.log("--- Intel(r) AMT WSMAN eventing credentials ---");
798
+ console.log("Username: " + username);
799
+ console.log("Password: " + pass);
800
+ console.log("Argument: " + nodeid);
801
process.exit();
802
});
803
} else {
804
- console.log('Invalid NodeID.');
804
+ console.log("Invalid NodeID.");
805
process.exit();
806
}
807
return;
@@ -809,7 +809,7 @@ function CreateMeshCentralServer(config, args) {
809
810
// Start plugin manager if configuration allows this.
811
if ((obj.config) && (obj.config.settings) && (obj.config.settings.plugins != null)) {
812
- obj.pluginHandler = require("./pluginHandler.js").pluginHandler(obj);
812
+ obj.pluginHandler = require('./pluginHandler.js').pluginHandler(obj);
813
}
814
815
// Load the default meshcore and meshcmd
@@ -838,7 +838,7 @@ function CreateMeshCentralServer(config, args) {
838
if (obj.letsencrypt != null) {
839
obj.letsencrypt.getCertificate(certs, obj.StartEx3); // Use Let's Encrypt certificate
840
} else {
841
- console.log('ERROR: Unable to setup GreenLock module.');
841
+ console.log("ERROR: Unable to setup GreenLock module.");
842
obj.StartEx3(certs); // Let's Encrypt did not load, just use the configured certificates
843
}
844
}
@@ -847,50 +847,23 @@ function CreateMeshCentralServer(config, args) {
847
848
// Start the server with the given certificates, but check if we have web certificates to load
849
obj.StartEx3 = function (certs) {
850
- var i, webCertLoadCount = 0;
850
obj.certificates = certs;
851
obj.certificateOperations.acceleratorStart(certs); // Set the state of the accelerators
852
853
// Load any domain web certificates
855
- for (i in obj.config.domains) {
854
+ for (var i in obj.config.domains) {
855
// Load any Intel AMT ACM activation certificates
856
obj.certificateOperations.loadIntelAmtAcmCerts(obj.config.domains[i].amtacmactivation);
857
859
- if (obj.config.domains[i].certurl != null) {
860
- // Fix the URL and add 'https://' if needed
858
+ if (typeof obj.config.domains[i].certurl == 'string') {
859
+ obj.supportsProxyCertificatesRequest = true; // If a certurl is set, enable proxy cert requests
860
+ // Then, fix the URL and add 'https://' if needed
861
if (obj.config.domains[i].certurl.indexOf('://') < 0) { obj.config.domains[i].certurl = 'https://' + obj.config.domains[i].certurl; }
862
-
863
- // Load web certs
864
- webCertLoadCount++;
865
- var dnsname = obj.config.domains[i].dns;
866
- if ((dnsname == null) && (obj.config.settings.cert != null)) { dnsname = obj.config.settings.cert; }
867
- obj.certificateOperations.loadCertificate(obj.config.domains[i].certurl, dnsname, obj.config.domains[i], function (url, cert, xhostname, xdomain) {
868
- if (cert != null) {
869
- // Hash the entire cert
870
- var hash = obj.crypto.createHash('sha384').update(Buffer.from(cert, 'binary')).digest('hex');
871
- if (xdomain.certhash != hash) { xdomain.certkeyhash = hash; xdomain.certhash = hash; }
872
-
873
- try {
874
- // Decode a RSA certificate and hash the public key, if this is not RSA, skip this.
875
- var forgeCert = obj.certificateOperations.forge.pki.certificateFromAsn1(obj.certificateOperations.forge.asn1.fromDer(cert));
876
- xdomain.certkeyhash = obj.certificateOperations.forge.pki.getPublicKeyFingerprint(forgeCert.publicKey, { md: obj.certificateOperations.forge.md.sha384.create(), encoding: 'hex' });
877
- //console.log('V1: ' + xdomain.certkeyhash);
878
- } catch (ex) { }
879
-
880
- console.log('Loaded web certificate from \"' + url + '\", host: \"' + xhostname + '\"');
881
- console.log(' SHA384 cert hash: ' + xdomain.certhash);
882
- if (xdomain.certhash != xdomain.certkeyhash) { console.log(' SHA384 key hash: ' + xdomain.certkeyhash); }
883
- } else {
884
- console.log('Failed to load web certificate at: \"' + url + '\", host: \"' + xhostname + '\"');
885
- }
886
- webCertLoadCount--;
887
- if (webCertLoadCount == 0) { obj.StartEx4(); } // Done loading all certificates
888
- });
862
}
863
}
864
892
- // No certificate to load, start the server
893
- if (webCertLoadCount == 0) { obj.StartEx4(); }
865
+ if (obj.supportsProxyCertificatesRequest == true) { obj.updateProxyCertificates(); }
866
+ obj.StartEx4(); // Keep going
867
}
868
869
// Start the server with the given certificates
@@ -903,7 +876,7 @@ function CreateMeshCentralServer(config, args) {
876
// Write server version and run mode
877
var productionMode = (process.env.NODE_ENV && (process.env.NODE_ENV == 'production'));
878
var runmode = (obj.args.lanonly ? 2 : (obj.args.wanonly ? 1 : 0));
906
- console.log('MeshCentral v' + obj.currentVer + ', ' + (['Hybrid (LAN + WAN) mode', 'WAN mode', 'LAN mode'][runmode]) + (productionMode ? ', Production mode.' : '.'));
879
+ console.log("MeshCentral v" + obj.currentVer + ', ' + (["Hybrid (LAN + WAN) mode", "WAN mode", "LAN mode"][runmode]) + (productionMode ? ", Production mode." : '.'));
880
881
// Check that no sub-domains have the same DNS as the parent
882
for (i in obj.config.domains) {
@@ -1029,9 +1002,9 @@ function CreateMeshCentralServer(config, args) {
1002
obj.DispatchEvent(['*'], obj, { action: 'servertimelinestats', data: data }); // Event the server stats
1003
}, 300000);
1004
1032
- obj.debug('main', 'Server started');
1005
+ obj.debug('main', "Server started");
1006
if (obj.args.nousers == true) { obj.updateServerState('nousers', '1'); }
1034
- obj.updateServerState('state', 'running');
1007
+ obj.updateServerState('state', "running");
1008
1009
// Setup auto-backup defaults
1010
if (obj.config.settings.autobackup == null) { obj.config.settings.autobackup = { backupintervalhours: 24, keeplastdaysbackup: 10 }; }
@@ -1045,6 +1018,61 @@ function CreateMeshCentralServer(config, args) {
1018
});
1019
};
1020
1021
+ // Refresh any certificate hashs from the reverse proxy
1022
+ obj.pendingProxyCertificatesRequests = 0;
1023
+ obj.lastProxyCertificatesRequest = null;
1024
+ obj.supportsProxyCertificatesRequest = false;
1025
+ obj.updateProxyCertificates = function () {
1026
+ var i;
1027
+ if ((obj.pendingProxyCertificatesRequests > 0) || (obj.supportsProxyCertificatesRequest == false)) { return; }
1028
+ if ((obj.lastProxyCertificatesRequest != null) && ((Date.now() - obj.lastProxyCertificatesRequest) < 120000)) { return; } // Don't allow this call more than every 2 minutes.
1029
+ obj.lastProxyCertificatesRequest = Date.now();
1030
+
1031
+ // Load any domain web certificates
1032
+ for (i in obj.config.domains) {
1033
+ if (obj.config.domains[i].certurl != null) {
1034
+ // Load web certs
1035
+ obj.pendingProxyCertificatesRequests++;
1036
+ var dnsname = obj.config.domains[i].dns;
1037
+ if ((dnsname == null) && (obj.config.settings.cert != null)) { dnsname = obj.config.settings.cert; }
1038
+ obj.certificateOperations.loadCertificate(obj.config.domains[i].certurl, dnsname, obj.config.domains[i], function (url, cert, xhostname, xdomain) {
1039
+ obj.pendingProxyCertificatesRequests--;
1040
+ if (cert != null) {
1041
+ // Hash the entire cert
1042
+ var hash = obj.crypto.createHash('sha384').update(Buffer.from(cert, 'binary')).digest('hex');
1043
+ if (xdomain.certhash != hash) { // The certificate has changed.
1044
+ xdomain.certkeyhash = hash;
1045
+ xdomain.certhash = hash;
1046
+
1047
+ try {
1048
+ // Decode a RSA certificate and hash the public key, if this is not RSA, skip this.
1049
+ var forgeCert = obj.certificateOperations.forge.pki.certificateFromAsn1(obj.certificateOperations.forge.asn1.fromDer(cert));
1050
+ xdomain.certkeyhash = obj.certificateOperations.forge.pki.getPublicKeyFingerprint(forgeCert.publicKey, { md: obj.certificateOperations.forge.md.sha384.create(), encoding: 'hex' });
1051
+ //console.log('V1: ' + xdomain.certkeyhash);
1052
+ } catch (ex) {
1053
+ delete xdomain.certkeyhash;
1054
+ }
1055
+
1056
+ if (obj.webserver) {
1057
+ obj.webserver.webCertificateHashs[xdomain.id] = obj.webserver.webCertificateFullHashs[xdomain.id] = Buffer.from(hash, 'hex').toString('binary');
1058
+ if (xdomain.certkeyhash != null) { obj.webserver.webCertificateHashs[xdomain.id] = Buffer.from(xdomain.certkeyhash, 'hex').toString('binary'); }
1059
+
1060
+ // Disconnect all agents with bad web certificates
1061
+ for (var i in obj.webserver.wsagentsWithBadWebCerts) { obj.webserver.wsagentsWithBadWebCerts[i].close(1); }
1062
+ }
1063
+
1064
+ console.log(obj.common.format("Loaded web certificate from \"{0}\", host: \"{1}\"", url, xhostname));
1065
+ console.log(obj.common.format(" SHA384 cert hash: {0}", xdomain.certhash));
1066
+ if ((xdomain.certkeyhash != null) && (xdomain.certhash != xdomain.certkeyhash)) { console.log(obj.common.format(" SHA384 key hash: {0}", xdomain.certkeyhash)); }
1067
+ }
1068
+ } else {
1069
+ console.log(obj.common.format("Failed to load web certificate at: \"{0}\", host: \"{1}\"", url, xhostname));
1070
+ }
1071
+ });
1072
+ }
1073
+ }
1074
+ }
1075
+
1076
// Perform maintenance operations (called every hour)
1077
obj.maintenanceActions = function () {
1078
// Check for self-update that targets a specific version
@@ -1068,19 +1096,19 @@ function CreateMeshCentralServer(config, args) {
1096
if (!obj.db) return;
1097
1098
// Dispatch an event saying the server is now stopping
1071
- obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'stopped', msg: 'Server stopped' });
1099
+ obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'stopped', msg: "Server stopped" });
1100
1101
// Set all nodes to power state of unknown (0)
1102
obj.db.storePowerEvent({ time: new Date(), nodeid: '*', power: 0, s: 2 }, obj.multiServer, function () { // s:2 indicates that the server is shutting down.
1103
if (restoreFile) {
1076
- obj.debug('main', 'Server stopped, updating settings: ' + restoreFile);
1077
- console.log('Updating settings folder...');
1104
+ obj.debug('main', obj.common.format("Server stopped, updating settings: {0}", restoreFile));
1105
+ console.log("Updating settings folder...");
1106
1079
- var yauzl = require("yauzl");
1107
+ var yauzl = require('yauzl');
1108
yauzl.open(restoreFile, { lazyEntries: true }, function (err, zipfile) {
1109
if (err) throw err;
1110
zipfile.readEntry();
1083
- zipfile.on("entry", function (entry) {
1111
+ zipfile.on('entry', function (entry) {
1112
if (/\/$/.test(entry.fileName)) {
1113
// Directory file names end with '/'.
1114
// Note that entires for directories themselves are optional.
@@ -1090,22 +1118,22 @@ function CreateMeshCentralServer(config, args) {
1118
// file entry
1119
zipfile.openReadStream(entry, function (err, readStream) {
1120
if (err) throw err;
1093
- readStream.on("end", function () { zipfile.readEntry(); });
1121
+ readStream.on('end', function () { zipfile.readEntry(); });
1122
// console.log('Extracting:', obj.getConfigFilePath(entry.fileName));
1123
readStream.pipe(obj.fs.createWriteStream(obj.getConfigFilePath(entry.fileName)));
1124
});
1125
}
1126
});
1099
- zipfile.on("end", function () { setTimeout(function () { obj.fs.unlinkSync(restoreFile); process.exit(123); }); });
1127
+ zipfile.on('end', function () { setTimeout(function () { obj.fs.unlinkSync(restoreFile); process.exit(123); }); });
1128
});
1129
} else {
1102
- obj.debug('main', 'Server stopped');
1130
+ obj.debug('main', "Server stopped");
1131
process.exit(0);
1132
}
1133
});
1134
1135
// Update the server state
1108
- obj.updateServerState('state', 'stopped');
1136
+ obj.updateServerState('state', "stopped");
1137
};
1138
1139
// Event Dispatch
package.json
+1
-1
@@ -1,6 +1,6 @@
1
{
2
"name": "meshcentral",
3
- "version": "0.4.3-o",
3
+ "version": "0.4.3-p",
4
"keywords": [
5
"Remote Management",
6
"Intel AMT",
webserver.js
+12
-11
@@ -156,20 +156,21 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
156
}
157
158
// Main lists
159
- obj.wsagents = {}; // NodeId --> Agent
159
+ obj.wsagents = {}; // NodeId --> Agent
160
+ obj.wsagentsWithBadWebCerts = {}; // NodeId --> Agent
161
obj.wsagentsDisconnections = {};
162
obj.wsagentsDisconnectionsTimer = null;
163
obj.duplicateAgentsLog = {};
163
- obj.wssessions = {}; // UserId --> Array Of Sessions
164
- obj.wssessions2 = {}; // "UserId + SessionRnd" --> Session (Note that the SessionId is the UserId + / + SessionRnd)
165
- obj.wsPeerSessions = {}; // ServerId --> Array Of "UserId + SessionRnd"
166
- obj.wsPeerSessions2 = {}; // "UserId + SessionRnd" --> ServerId
167
- obj.wsPeerSessions3 = {}; // ServerId --> UserId --> [ SessionId ]
168
- obj.sessionsCount = {}; // Merged session counters, used when doing server peering. UserId --> SessionCount
169
- obj.wsrelays = {}; // Id -> Relay
170
- obj.wsPeerRelays = {}; // Id -> { ServerId, Time }
171
- var tlsSessionStore = {}; // Store TLS session information for quick resume.
172
- var tlsSessionStoreCount = 0; // Number of cached TLS session information in store.
164
+ obj.wssessions = {}; // UserId --> Array Of Sessions
165
+ obj.wssessions2 = {}; // "UserId + SessionRnd" --> Session (Note that the SessionId is the UserId + / + SessionRnd)
166
+ obj.wsPeerSessions = {}; // ServerId --> Array Of "UserId + SessionRnd"
167
+ obj.wsPeerSessions2 = {}; // "UserId + SessionRnd" --> ServerId
168
+ obj.wsPeerSessions3 = {}; // ServerId --> UserId --> [ SessionId ]
169
+ obj.sessionsCount = {}; // Merged session counters, used when doing server peering. UserId --> SessionCount
170
+ obj.wsrelays = {}; // Id -> Relay
171
+ obj.wsPeerRelays = {}; // Id -> { ServerId, Time }
172
+ var tlsSessionStore = {}; // Store TLS session information for quick resume.
173
+ var tlsSessionStoreCount = 0; // Number of cached TLS session information in store.
174
175
// Setup randoms
176
obj.crypto.randomBytes(48, function (err, buf) { obj.httpAuthRandom = buf; });