MeshCentral/multiserver.js

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;
}