Improved MeshCMD server authentication.
Ylian Saint-Hilaire committed
Apr 6, 2021 at 09:22 UTC
b9b2aa55babc26041308f532206bf54387c8a1a1
7 files changed
+28
-7
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/meshcmd.js
+6
-1
@@ -70,7 +70,7 @@ function onVerifyServer(clientName, certs) {
70
if (certs == null) { certs = clientName; } // Temporary thing until we fix duktape
71
72
// If we have the serverid, used delayed server authentication
73
- if (settings.serverid != null) { settings.meshServerTlsHash = certs[certs.length - 1].fingerprint.split(':').join(''); return; }
73
+ if (settings.serverid != null) { settings.meshServerTlsHash = certs[certs.length - 1].fingerprint.replace(/:/g, ''); return; }
74
75
// Otherwise, use server HTTPS certificate hash
76
try { for (var i in certs) { if (certs[i].fingerprint.replace(/:/g, '') == settings.serverhttpshash) { return; } } } catch (e) { }
@@ -2064,6 +2064,11 @@ function OnServerWebSocket(msg, s, head) {
2064
var signDataHash = hasher.syncHash(Buffer.concat([Buffer.from(settings.serverAuthClientNonce, 'base64'), Buffer.from(settings.meshServerTlsHash, 'hex'), Buffer.from(command.nonce, 'base64')]));
2065
if (require('RSA').verify(require('RSA').TYPES.SHA384, cert, signDataHash, Buffer.from(command.signature, 'base64')) == false) { console.log("Unable to authenticate the server, invalid signature."); process.exit(1); return; }
2066
2067
+ // Switch to using HTTPS TLS certificate for authentication
2068
+ delete settings.serverid;
2069
+ settings.serverhttpshash = settings.meshServerTlsHash;
2070
+ delete settings.meshServerTlsHash;
2071
+
2072
// Figure out the 2FA token to use if any
2073
var xtoken = null;
2074
if (settings.emailtoken) { xtoken = '**email**'; }
meshcentral.js
+1
-1
@@ -3115,7 +3115,7 @@ function mainStart() {
3115
if (passport != null) { modules.push(...passport); }
3116
if (sessionRecording == true) { modules.push('image-size'); } // Need to get the remote desktop JPEG sizes to index the recodring file.
3117
if (config.letsencrypt != null) { if (nodeVersion < 8) { addServerWarning("Let's Encrypt support requires Node v8.x or higher.", !args.launch); } else { modules.push('acme-client'); } } // Add acme-client module
3118
- if (config.settings.mqtt != null) { modules.push('aedes'); } // Add MQTT Modules
3118
+ if (config.settings.mqtt != null) { modules.push('aedes@0.39.0'); } // Add MQTT Modules
3119
if (config.settings.mysql != null) { modules.push('mysql'); } // Add MySQL.
3120
//if (config.settings.mysql != null) { modules.push('@mysql/xdevapi'); } // Add MySQL, official driver (https://dev.mysql.com/doc/dev/connector-nodejs/8.0/)
3121
if (config.settings.mongodb != null) { modules.push('mongodb'); modules.push('saslprep'); } // Add MongoDB, official driver.
meshuser.js
+3
-1
@@ -5146,7 +5146,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
5146
// Get the node and the rights for this node
5147
parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) {
5148
// If this device is connected on MQTT, send a wake action.
5149
- if (rights != 0) { parent.parent.mqttbroker.publish(node._id, command.topic, command.msg); }
5149
+ if (rights != 0) {
5150
+ parent.parent.mqttbroker.publish(node._id, command.topic, command.msg);
5151
+ }
5152
});
5153
}
5154
mqttbroker.js
+5
-3
@@ -13,9 +13,9 @@ module.exports.CreateMQTTBroker = function (parent, db, args) {
13
obj.db = db;
14
obj.args = args;
15
obj.connections = {}; // NodesID --> client array
16
- const aedes = require("aedes")();
16
+ const aedes = require('aedes')();
17
obj.handle = aedes.handle;
18
- const allowedSubscriptionTopics = [ 'presence' ];
18
+ const allowedSubscriptionTopics = ['presence', 'console', 'powerAction'];
19
const denyError = new Error('denied');
20
var authError = new Error('Auth error')
21
authError.returnCode = 1
@@ -127,7 +127,9 @@ module.exports.CreateMQTTBroker = function (parent, db, args) {
127
if (typeof message == 'string') { message = Buffer.from(message); }
128
for (var i in clients) {
129
// Only publish to client that subscribe to the topic
130
- if (clients[i].subscriptions[topic] != null) { clients[i].publish({ cmd: 'publish', qos: 0, topic: topic, payload: message, retain: false }); }
130
+ if (clients[i].subscriptions[topic] != null) {
131
+ clients[i].publish({ cmd: 'publish', qos: 0, topic: topic, payload: message, retain: false }, function () { });
132
+ }
133
}
134
}
135
package.json
+13
-1
@@ -36,6 +36,9 @@
36
"sample-config-advanced.json"
37
],
38
"dependencies": {
39
+ "aedes": "^0.45.0",
40
+ "archiver": "^4.0.2",
41
+ "archiver-zip-encrypted": "^1.0.8",
42
"body-parser": "^1.19.0",
43
"cbor": "~5.2.0",
44
"compression": "^1.7.4",
@@ -44,14 +47,23 @@
47
"express": "^4.17.0",
48
"express-handlebars": "^3.1.0",
49
"express-ws": "^4.0.0",
50
+ "image-size": "^0.9.7",
51
"ipcheck": "^0.1.0",
52
+ "loadavg-windows": "^1.1.1",
53
"minimist": "^1.2.0",
54
+ "mongodb": "^3.6.5",
55
"multiparty": "^4.2.1",
56
"nedb": "^1.8.0",
57
"node-forge": "^0.10.0",
58
+ "node-rdpjs-2": "^0.3.5",
59
+ "node-windows": "^1.0.0-beta.5",
60
+ "otplib": "^10.2.3",
61
+ "saslprep": "^1.0.3",
62
+ "web-push": "^3.4.4",
63
"ws": "^6.2.1",
64
"xmldom": "^0.5.0",
54
- "yauzl": "^2.10.0"
65
+ "yauzl": "^2.10.0",
66
+ "yubikeyotp": "^0.2.0"
67
},
68
"repository": {
69
"type": "git",