85 lines
3.7 KiB
JavaScript
85 lines
3.7 KiB
JavaScript
/**
|
|
* @description Meshcentral Multi-Server Support
|
|
* @author Ylian Saint-Hilaire
|
|
* @version v0.0.1
|
|
*/
|
|
|
|
// Construct a Mesh Multi-Server object. This is used for MeshCentral-to-MeshCentral communication.
|
|
module.exports.CreateMultiServer = function (parent, args) {
|
|
var obj = {};
|
|
obj.parent = parent;
|
|
obj.crypto = require('crypto');
|
|
|
|
// Generate a cryptographic key used to encode and decode cookies
|
|
obj.generateCookieKey = function () {
|
|
return new Buffer(obj.crypto.randomBytes(32), 'binary').toString('ascii');
|
|
}
|
|
|
|
// Encode an object as a cookie using a key
|
|
obj.encodeCookie = function (o, key) {
|
|
try {
|
|
if (key == undefined) { key = obj.serverKey; }
|
|
o.time = Math.floor(Date.now() / 1000); // Add the cookie creation time
|
|
var msg = JSON.stringify(o);
|
|
msg = obj.crypto.createHmac('sha256', key.substring(16)).update(msg, 'binary', 'binary').digest('binary') + msg;
|
|
var iv = new Buffer(obj.crypto.randomBytes(16), 'binary');
|
|
var cipher = obj.crypto.createCipheriv('aes-128-cbc', key.substring(0, 16), iv);
|
|
crypted = cipher.update(msg, 'binary', 'binary');
|
|
crypted += cipher.final('binary');
|
|
var total = new Buffer(iv, 'binary').toString('hex') + new Buffer(crypted, 'binary').toString('hex'); // HEX: This is not an efficient concat, but it's very compatible.
|
|
var cookie = new Buffer(total, 'hex').toString('base64');
|
|
return cookie.replace(/\+/g, '@').replace(/\//g, '$');
|
|
} catch (e) { return null; }
|
|
}
|
|
|
|
// Decode a cookie back into an object using a key. Return null if it's not a valid cookie.
|
|
obj.decodeCookie = function (cookie, key) {
|
|
try {
|
|
if (key == undefined) { key = obj.serverKey; }
|
|
cookie = new Buffer(cookie.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex'); // HEX: This is not an efficient split, but it's very compatible.
|
|
var iv = new Buffer(cookie.substring(0, 32), 'hex');
|
|
var msg = new Buffer(cookie.substring(32), 'hex');
|
|
var decipher = obj.crypto.createDecipheriv('aes-128-cbc', key.substring(0, 16), iv)
|
|
var dec = decipher.update(msg, 'binary', 'binary')
|
|
dec += decipher.final('binary');
|
|
var msg = dec.substring(32);
|
|
var hash1 = dec.substring(0, 32);
|
|
var hash2 = obj.crypto.createHmac('sha256', key.substring(16)).update(msg, 'binary', 'binary').digest('binary');
|
|
if (hash1 !== hash2) { return null; }
|
|
var o = JSON.parse(msg);
|
|
if ((o.time == null) || (o.time == undefined) || (typeof o.time != 'number')) { return null; }
|
|
o.time = o.time * 1000; // Decode the cookie creation time
|
|
o.dtime = Date.now() - o.time; // Decode how long ago the cookie was created
|
|
return o;
|
|
} catch (e) { return null; }
|
|
}
|
|
|
|
// Dispatch an event to other MeshCentral2 peer servers
|
|
obj.DispatchEvent = function (ids, source, event) {
|
|
// TODO
|
|
}
|
|
|
|
// Handle websocket requests on "/meshserver.ashx" from other MeshCentral2 peer servers.
|
|
obj.handleServerWebSocket = function (ws, req) {
|
|
Debug(1, 'MeshServer connection open.');
|
|
|
|
// Handle data from another mesh server
|
|
ws.on('message', function (msg) {
|
|
Debug(1, 'MeshServer data of length ' + msg.length);
|
|
// TODO
|
|
});
|
|
|
|
// If error, do nothing
|
|
ws.on('error', function (err) { console.log(err); });
|
|
|
|
// Another mesh server connection has closed
|
|
ws.on('close', function (req) {
|
|
Debug(1, 'MeshServer connection closed.');
|
|
// TODO
|
|
});
|
|
}
|
|
|
|
obj.serverKey = obj.generateCookieKey();
|
|
return obj;
|
|
}
|