mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-22 13:21:31 +03:00
Fixed certificate generation.
This commit is contained in:
parent
c848956aa4
commit
5108b344be
Binary file not shown.
Binary file not shown.
@ -385,7 +385,7 @@ function createMeshCore(agent) {
|
||||
}
|
||||
|
||||
// Tunnel callback operations
|
||||
function onTunnelUpgrade(response, s, head) { this.s = s; s.httprequest = this; s.end = onTunnelClosed; s.data = onTunnelData; }
|
||||
function onTunnelUpgrade(response, s, head) { sendConsoleText('onTunnelUpgrade'); this.s = s; s.httprequest = this; s.end = onTunnelClosed; s.data = onTunnelData; }
|
||||
function onTunnelClosed() {
|
||||
sendConsoleText("Tunnel #" + this.httprequest.index + " closed.", this.httprequest.sessionid);
|
||||
if (this.httprequest.protocol == 1) { this.httprequest.process.end(); delete this.httprequest.process; }
|
||||
|
@ -20,8 +20,8 @@ module.exports.CertificateOperations = function () {
|
||||
}
|
||||
|
||||
// Create a self-signed certificate
|
||||
obj.GenerateRootCertificate = function (addThumbPrintToName, commonName, country, organization) {
|
||||
var keys = obj.pki.rsa.generateKeyPair(3072);
|
||||
obj.GenerateRootCertificate = function (addThumbPrintToName, commonName, country, organization, strong) {
|
||||
var keys = obj.pki.rsa.generateKeyPair((strong == true) ? 3072 : 2048);
|
||||
var cert = obj.pki.createCertificate();
|
||||
cert.publicKey = keys.publicKey;
|
||||
cert.serialNumber = '' + Math.floor((Math.random() * 100000) + 1); ;
|
||||
@ -128,6 +128,7 @@ module.exports.CertificateOperations = function () {
|
||||
// Returns the web server TLS certificate and private key, if not present, create demonstration ones.
|
||||
obj.GetMeshServerCertificate = function (directory, args, func) {
|
||||
var certargs = args.cert;
|
||||
var strongCertificate = (args.fastcert ? false : true);
|
||||
// commonName, country, organization
|
||||
|
||||
// If the certificates directory does not exist, create it.
|
||||
@ -225,12 +226,23 @@ module.exports.CertificateOperations = function () {
|
||||
if (xorganizationField != null) { xorganization = xorganizationField.value; }
|
||||
if ((r.CommonName == commonName) && (xcountry == country) && (xorganization == organization) && (r.AmtMpsName == commonName)) { if (func != undefined) { func(r); } return r; } else { forceWebCertGen = 1; } // If the certificate matches what we want, keep it.
|
||||
}
|
||||
console.log('Generating certificates, may take a few minutes...');
|
||||
|
||||
//console.log('Generating certificates, may take a few minutes...');
|
||||
|
||||
// If a certificate is missing, but web certificate is present and --cert is not used, set the names to be the same as the web certificate
|
||||
if ((certargs == null) && (r.web != null)) {
|
||||
var webCertificate = obj.pki.certificateFromPem(r.web.cert);
|
||||
commonName = webCertificate.subject.getField('CN').value;
|
||||
var xcountryField = webCertificate.subject.getField('C');
|
||||
if (xcountryField != null) { country = xcountryField.value; }
|
||||
var xorganizationField = webCertificate.subject.getField('O');
|
||||
if (xorganizationField != null) { organization = xorganizationField.value; }
|
||||
}
|
||||
|
||||
var rootCertAndKey, rootCertificate, rootPrivateKey, rootName;
|
||||
if (r.root == undefined) {
|
||||
// If the root certificate does not exist, create one
|
||||
rootCertAndKey = obj.GenerateRootCertificate(true, 'MeshCentralRoot');
|
||||
console.log('Generating root certificate...');
|
||||
rootCertAndKey = obj.GenerateRootCertificate(true, 'MeshCentralRoot', null, null, strongCertificate);
|
||||
rootCertificate = obj.pki.certificateToPem(rootCertAndKey.cert);
|
||||
rootPrivateKey = obj.pki.privateKeyToPem(rootCertAndKey.key);
|
||||
obj.fs.writeFileSync(directory + '/root-cert-public.crt', rootCertificate);
|
||||
@ -246,7 +258,8 @@ module.exports.CertificateOperations = function () {
|
||||
// If the web certificate does not exist, create one
|
||||
var webCertAndKey, webCertificate, webPrivateKey;
|
||||
if ((r.web == null) || (forceWebCertGen == 1)) {
|
||||
webCertAndKey = obj.IssueWebServerCertificate(rootCertAndKey, false, commonName, country, organization, null, true);
|
||||
console.log('Generating HTTPS certificate...');
|
||||
webCertAndKey = obj.IssueWebServerCertificate(rootCertAndKey, false, commonName, country, organization, null, strongCertificate);
|
||||
webCertificate = obj.pki.certificateToPem(webCertAndKey.cert);
|
||||
webPrivateKey = obj.pki.privateKeyToPem(webCertAndKey.key);
|
||||
obj.fs.writeFileSync(directory + '/webserver-cert-public.crt', webCertificate);
|
||||
@ -258,9 +271,26 @@ module.exports.CertificateOperations = function () {
|
||||
webPrivateKey = r.web.key
|
||||
}
|
||||
|
||||
// If the mesh agent server certificate does not exist, create one
|
||||
var agentCertAndKey, agentCertificate, agentPrivateKey;
|
||||
if (r.agent == null) {
|
||||
console.log('Generating MeshAgent certificate...');
|
||||
agentCertAndKey = obj.IssueWebServerCertificate(rootCertAndKey, true, 'MeshCentralAgentServer', null, strongCertificate);
|
||||
agentCertificate = obj.pki.certificateToPem(agentCertAndKey.cert);
|
||||
agentPrivateKey = obj.pki.privateKeyToPem(agentCertAndKey.key);
|
||||
obj.fs.writeFileSync(directory + '/agentserver-cert-public.crt', agentCertificate);
|
||||
obj.fs.writeFileSync(directory + '/agentserver-cert-private.key', agentPrivateKey);
|
||||
} else {
|
||||
// Keep the mesh agent server certificate we have
|
||||
agentCertAndKey = { cert: obj.pki.certificateFromPem(r.agent.cert), key: obj.pki.privateKeyFromPem(r.agent.key) };
|
||||
agentCertificate = r.agent.cert
|
||||
agentPrivateKey = r.agent.key
|
||||
}
|
||||
|
||||
// If the Intel AMT MPS certificate does not exist, create one
|
||||
var mpsCertAndKey, mpsCertificate, mpsPrivateKey;
|
||||
if ((r.mps == null) || (forceWebCertGen == 1)) {
|
||||
console.log('Generating Intel AMT MPS certificate...');
|
||||
mpsCertAndKey = obj.IssueWebServerCertificate(rootCertAndKey, false, commonName, country, organization, null, false);
|
||||
mpsCertificate = obj.pki.certificateToPem(mpsCertAndKey.cert);
|
||||
mpsPrivateKey = obj.pki.privateKeyToPem(mpsCertAndKey.key);
|
||||
@ -276,6 +306,7 @@ module.exports.CertificateOperations = function () {
|
||||
// If the Intel AMT console certificate does not exist, create one
|
||||
var consoleCertAndKey, consoleCertificate, consolePrivateKey, amtConsoleName = 'MeshCentral';
|
||||
if (r.console == null) {
|
||||
console.log('Generating Intel AMT console certificate...');
|
||||
consoleCertAndKey = obj.IssueWebServerCertificate(rootCertAndKey, false, amtConsoleName, country, organization, { name: 'extKeyUsage', clientAuth: true, '2.16.840.1.113741.1.2.1': true, '2.16.840.1.113741.1.2.2': true, '2.16.840.1.113741.1.2.3': true }, false); // Intel AMT Remote, Agent and Activation usages
|
||||
consoleCertificate = obj.pki.certificateToPem(consoleCertAndKey.cert);
|
||||
consolePrivateKey = obj.pki.privateKeyToPem(consoleCertAndKey.key);
|
||||
@ -289,21 +320,6 @@ module.exports.CertificateOperations = function () {
|
||||
amtConsoleName = consoleCertAndKey.cert.subject.getField('CN').value;
|
||||
}
|
||||
|
||||
// If the mesh agent server certificate does not exist, create one
|
||||
var agentCertAndKey, agentCertificate, agentPrivateKey;
|
||||
if (r.agent == null) {
|
||||
agentCertAndKey = obj.IssueWebServerCertificate(rootCertAndKey, true, 'MeshCentralAgentServer', null, true);
|
||||
agentCertificate = obj.pki.certificateToPem(agentCertAndKey.cert);
|
||||
agentPrivateKey = obj.pki.privateKeyToPem(agentCertAndKey.key);
|
||||
obj.fs.writeFileSync(directory + '/agentserver-cert-public.crt', agentCertificate);
|
||||
obj.fs.writeFileSync(directory + '/agentserver-cert-private.key', agentPrivateKey);
|
||||
} else {
|
||||
// Keep the mesh agent server certificate we have
|
||||
agentCertAndKey = { cert: obj.pki.certificateFromPem(r.agent.cert), key: obj.pki.privateKeyFromPem(r.agent.key) };
|
||||
agentCertificate = r.agent.cert
|
||||
agentPrivateKey = r.agent.key
|
||||
}
|
||||
|
||||
var r = { root: { cert: rootCertificate, key: rootPrivateKey }, web: { cert: webCertificate, key: webPrivateKey }, mps: { cert: mpsCertificate, key: mpsPrivateKey }, agent: { cert: agentCertificate, key: agentPrivateKey }, console: { cert: consoleCertificate, key: consolePrivateKey }, calist: calist, CommonName: commonName, RootName: rootName, AmtConsoleName: amtConsoleName };
|
||||
if (func != undefined) { func(r); }
|
||||
return r;
|
||||
|
14
meshagent.js
14
meshagent.js
@ -151,8 +151,8 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
||||
if ((msg.length != 98) || ((obj.receivedCommands & 1) != 0)) return;
|
||||
obj.receivedCommands += 1; // Agent can't send the same command twice on the same connection ever. Block DOS attack path.
|
||||
|
||||
// Check that the server hash matches out own web certificate hash (SHA386)
|
||||
if (obj.parent.webCertificatHash != msg.substring(2, 50)) { obj.close(); return; }
|
||||
// Check that the server hash matches our own web certificate hash (SHA386)
|
||||
if (obj.parent.webCertificateHash != msg.substring(2, 50)) { console.log('Agent connected with bad web certificate hash, holding connection (' + obj.remoteaddr + ').'); return; }
|
||||
|
||||
// Use our server private key to sign the ServerHash + AgentNonce + ServerNonce
|
||||
var privateKey = obj.forge.pki.privateKeyFromPem(obj.parent.certificates.agent.key);
|
||||
@ -162,11 +162,11 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
||||
obj.agentnonce = msg.substring(50);
|
||||
|
||||
// Send back our certificate + signature
|
||||
obj.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(parent.agentCertificatAsn1.length) + parent.agentCertificatAsn1 + privateKey.sign(md)); // Command 2, certificate + signature
|
||||
obj.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(parent.agentCertificateAsn1.length) + parent.agentCertificateAsn1 + privateKey.sign(md)); // Command 2, certificate + signature
|
||||
|
||||
// Check the agent signature if we can
|
||||
if (obj.unauthsign != null) {
|
||||
if (processAgentSignature(obj.unauthsign) == false) { disonnect(); return; } else { completeAgentConnection(); }
|
||||
if (processAgentSignature(obj.unauthsign) == false) { console.log('Agent connected with bad signature, holding connection (' + obj.remoteaddr + ').'); return; } else { completeAgentConnection(); }
|
||||
}
|
||||
}
|
||||
else if (cmd == 2) {
|
||||
@ -182,7 +182,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
||||
obj.unauth.nodeid = new Buffer(obj.forge.pki.getPublicKeyFingerprint(obj.unauth.nodeCert.publicKey, { md: obj.forge.md.sha384.create() }).data, 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
||||
|
||||
// Check the agent signature if we can
|
||||
if (obj.agentnonce == null) { obj.unauthsign = msg.substring(4 + certlen); } else { if (processAgentSignature(msg.substring(4 + certlen)) == false) { console.log('Bad Agent Signature'); obj.close(); return; } }
|
||||
if (obj.agentnonce == null) { obj.unauthsign = msg.substring(4 + certlen); } else { if (processAgentSignature(msg.substring(4 + certlen)) == false) { console.log('Agent connected with bad signature, holding connection (' + obj.remoteaddr + ').'); return; } }
|
||||
completeAgentConnection();
|
||||
}
|
||||
else if (cmd == 3) {
|
||||
@ -217,7 +217,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
||||
// Start authenticate the mesh agent by sending a auth nonce & server TLS cert hash.
|
||||
// Send 384 bits SHA384 hash of TLS cert public key + 384 bits nonce
|
||||
obj.nonce = obj.forge.random.getBytesSync(48);
|
||||
obj.send(obj.common.ShortToStr(1) + parent.webCertificatHash + obj.nonce); // Command 1, hash + nonce
|
||||
obj.send(obj.common.ShortToStr(1) + parent.webCertificateHash + obj.nonce); // Command 1, hash + nonce
|
||||
|
||||
// Once we get all the information about an agent, run this to hook everything up to the server
|
||||
function completeAgentConnection() {
|
||||
@ -334,7 +334,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
||||
// Verify the agent signature
|
||||
function processAgentSignature(msg) {
|
||||
var md = obj.forge.md.sha384.create(); // TODO: Switch this to SHA384 on node instead of forge.
|
||||
md.update(obj.parent.webCertificatHash, 'binary');
|
||||
md.update(obj.parent.webCertificateHash, 'binary');
|
||||
md.update(obj.nonce, 'binary');
|
||||
md.update(obj.agentnonce, 'binary');
|
||||
if (obj.unauth.nodeCert.publicKey.verify(md.digest().bytes(), msg) == false) { return false; }
|
||||
|
@ -64,7 +64,7 @@ function CreateMeshCentralServer() {
|
||||
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.
|
||||
|
||||
// Check for invalid arguments
|
||||
var validArguments = ['_', 'notls', 'user', 'port', 'mpsport', 'redirport', 'cert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'shownodes', 'showmeshes', 'showevents', 'showpower', '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'];
|
||||
var validArguments = ['_', 'notls', 'user', 'port', 'mpsport', 'redirport', 'cert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'shownodes', 'showmeshes', 'showevents', 'showpower', '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'];
|
||||
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; } }
|
||||
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; }
|
||||
|
||||
|
@ -17,13 +17,13 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||
var periodicScanTime = (60000 * 20); // Interval between scans, 20 minutes.
|
||||
var membershipIPv4 = '239.255.255.235';
|
||||
var membershipIPv6 = 'FF02:0:0:0:0:0:0:FE';
|
||||
obj.agentCertificatHashHex = parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(parent.certificates.agent.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'hex' }).toUpperCase();
|
||||
obj.agentCertificateHashHex = parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(parent.certificates.agent.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'hex' }).toUpperCase();
|
||||
obj.error = 0;
|
||||
|
||||
// Get a list of IPv4 and IPv6 interface addresses
|
||||
function getInterfaceList() {
|
||||
var ipv4 = ['*'], ipv6 = ['*']; // Bind to IN_ADDR_ANY always
|
||||
if (parent.platform == 'win32') { // On Windows, also bind to each interface seperatly
|
||||
//if (parent.platform == 'win32') { // On Windows, also bind to each interface seperatly (TODO: REMOVE THIS AND TEST ON LINUX!!!!!!!!!!!!!!!!!!)
|
||||
var interfaces = require('os').networkInterfaces();
|
||||
for (var i in interfaces) {
|
||||
var interface = interfaces[i];
|
||||
@ -35,7 +35,7 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//}
|
||||
return { ipv4: ipv4, ipv6: ipv6 };
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||
} else {
|
||||
// Create a new IPv4 server
|
||||
try {
|
||||
var server4 = obj.dgram.createSocket("udp4");
|
||||
var server4 = obj.dgram.createSocket({ type: 'udp4', reuseAddr: true });
|
||||
server4.xxclear = false;
|
||||
server4.xxtype = 4;
|
||||
server4.xxlocal = localAddress;
|
||||
@ -64,8 +64,8 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||
this.setBroadcast(true);
|
||||
this.setMulticastTTL(128);
|
||||
this.addMembership(membershipIPv4);
|
||||
server4.on('error', function (error) { console.log('Error: ' + error); });
|
||||
server4.on('message', function (msg, info) { onUdpPacket(msg, info, server4); });
|
||||
this.on('error', function (error) { console.log('Error: ' + error); });
|
||||
this.on('message', function (msg, info) { onUdpPacket(msg, info, this); });
|
||||
obj.performScan(this);
|
||||
obj.performScan(this);
|
||||
} catch (e) { }
|
||||
@ -84,7 +84,7 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||
obj.servers6[localAddress].xxclear = false;
|
||||
} else {
|
||||
// Create a new IPv6 server
|
||||
var server6 = obj.dgram.createSocket("udp6", localAddress);
|
||||
var server6 = obj.dgram.createSocket({ type: 'udp6', reuseAddr: true });
|
||||
server6.xxclear = false;
|
||||
server6.xxtype = 6;
|
||||
server6.xxlocal = localAddress;
|
||||
@ -105,6 +105,7 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||
obj.servers6[localAddress] = server6;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i in obj.servers4) { if (obj.servers4[i].xxclear == true) { obj.servers4[i].close(); delete obj.servers4[i]; }; }
|
||||
for (var i in obj.servers6) { if (obj.servers6[i].xxclear == true) { obj.servers6[i].close(); delete obj.servers6[i]; }; }
|
||||
}
|
||||
@ -119,9 +120,9 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||
obj.start = function () {
|
||||
if (obj.server4 != null) return;
|
||||
var url = (parent.args.notls ? 'ws' : 'wss') + '://%s:' + parent.args.port + '/agent.ashx';
|
||||
obj.multicastPacket4 = Buffer.from("MeshCentral2|" + obj.agentCertificatHashHex + '|' + url, 'ascii');
|
||||
obj.multicastPacket4 = Buffer.from("MeshCentral2|" + obj.agentCertificateHashHex + '|' + url, 'ascii');
|
||||
url = (parent.args.notls ? 'ws' : 'wss') + '://[%s]:' + parent.args.port + '/agent.ashx';
|
||||
obj.multicastPacket6 = Buffer.from("MeshCentral2|" + obj.agentCertificatHashHex + '|' + url, 'ascii');
|
||||
obj.multicastPacket6 = Buffer.from("MeshCentral2|" + obj.agentCertificateHashHex + '|' + url, 'ascii');
|
||||
setupServers();
|
||||
obj.mainTimer = setInterval(obj.performScan, periodicScanTime);
|
||||
return obj;
|
||||
@ -150,7 +151,7 @@ module.exports.CreateMeshScanner = function (parent) {
|
||||
// Called when a UDP packet is received from an agent.
|
||||
function onUdpPacket(msg, info, server) {
|
||||
//console.log('Received ' + msg.length + ' bytes from ' + info.address + ':' + info.port + ', on interface: ' + server.xxlocal + '.');
|
||||
if ((msg.length == 96) && (msg.toString('ascii') == obj.agentCertificatHashHex)) {
|
||||
if ((msg.length == 96) && (msg.toString('ascii') == obj.agentCertificateHashHex)) {
|
||||
if (server.xxtype == 4) { try { server.send(obj.multicastPacket4, 0, obj.multicastPacket4.length, info.port, info.address); } catch (e) { } }
|
||||
if (server.xxtype == 6) { try { server.send(obj.multicastPacket6, 0, obj.multicastPacket6.length, info.port, info.address); } catch (e) { } }
|
||||
}
|
||||
|
@ -463,7 +463,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||
var RecipientChannel = common.ReadInt(data, 1);
|
||||
var LengthOfData = common.ReadInt(data, 5);
|
||||
if (len < (9 + LengthOfData)) return 0;
|
||||
Debug(3, 'MPS:CHANNEL_DATA', RecipientChannel, LengthOfData);
|
||||
Debug(4, 'MPS:CHANNEL_DATA', RecipientChannel, LengthOfData);
|
||||
var cirachannel = socket.tag.channels[RecipientChannel];
|
||||
if (cirachannel == undefined) { console.log("MPS Error in CHANNEL_DATA: Unable to find channelid " + RecipientChannel); return; }
|
||||
cirachannel.amtpendingcredits += LengthOfData;
|
||||
@ -553,6 +553,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||
}
|
||||
|
||||
function SendChannelWindowAdjust(socket, channelid, bytestoadd) {
|
||||
Debug(3, 'MPS:SendChannelWindowAdjust', channelid, bytestoadd);
|
||||
Write(socket, String.fromCharCode(APFProtocol.CHANNEL_WINDOW_ADJUST) + common.IntToStr(channelid) + common.IntToStr(bytestoadd));
|
||||
}
|
||||
|
||||
|
@ -32,9 +32,9 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||
obj.retryTimer = null;
|
||||
obj.retryBackoff = 0;
|
||||
obj.connectHandler = null;
|
||||
obj.webCertificatHash = obj.parent.parent.webserver.webCertificatHash;
|
||||
obj.agentCertificatHashBase64 = obj.parent.parent.webserver.agentCertificatHashBase64;
|
||||
obj.agentCertificatAsn1 = obj.parent.parent.webserver.agentCertificatAsn1;
|
||||
obj.webCertificateHash = obj.parent.parent.webserver.webCertificateHash;
|
||||
obj.agentCertificateHashBase64 = obj.parent.parent.webserver.agentCertificateHashBase64;
|
||||
obj.agentCertificateAsn1 = obj.parent.parent.webserver.agentCertificateAsn1;
|
||||
obj.peerServerId = null;
|
||||
obj.authenticated = 0;
|
||||
obj.serverCertHash = null;
|
||||
@ -99,8 +99,8 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||
md.update(obj.nonce, 'binary');
|
||||
|
||||
// Send back our certificate + signature
|
||||
agentRootCertificatAsn1 = obj.forge.asn1.toDer(obj.forge.pki.certificateToAsn1(obj.forge.pki.certificateFromPem(obj.certificates.agent.cert))).getBytes();
|
||||
obj.ws.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(agentRootCertificatAsn1.length) + agentRootCertificatAsn1 + privateKey.sign(md)); // Command 3, signature
|
||||
agentRootCertificateAsn1 = obj.forge.asn1.toDer(obj.forge.pki.certificateToAsn1(obj.forge.pki.certificateFromPem(obj.certificates.agent.cert))).getBytes();
|
||||
obj.ws.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(agentRootCertificateAsn1.length) + agentRootCertificatAsn1 + privateKey.sign(md)); // Command 3, signature
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
@ -109,7 +109,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||
try { serverCert = obj.forge.pki.certificateFromAsn1(obj.forge.asn1.fromDer(msg.substring(4, 4 + certlen))); } catch (e) { }
|
||||
if (serverCert == null) { obj.parent.parent.debug(1, 'OutPeer: Invalid server certificate.'); disconnect(); return; }
|
||||
var serverid = new Buffer(obj.forge.pki.getPublicKeyFingerprint(serverCert.publicKey, { encoding: 'binary', md: obj.forge.md.sha384.create() }), 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
||||
if (serverid !== obj.agentCertificatHashBase64) { obj.parent.parent.debug(1, 'OutPeer: Server hash mismatch.'); disconnect(); return; }
|
||||
if (serverid !== obj.agentCertificateHashBase64) { obj.parent.parent.debug(1, 'OutPeer: Server hash mismatch.'); disconnect(); return; }
|
||||
|
||||
// Server signature, verify it
|
||||
var md = obj.forge.md.sha384.create();
|
||||
@ -127,14 +127,14 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||
obj.parent.parent.debug(1, 'OutPeer ' + obj.serverid + ': Verified peer connection to ' + obj.url);
|
||||
|
||||
// Send information about our server to the peer
|
||||
if (obj.connectionState == 15) { obj.ws.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificatHashBase64 })); }
|
||||
if (obj.connectionState == 15) { obj.ws.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificateHashBase64 })); }
|
||||
//if ((obj.connectionState == 15) && (obj.connectHandler != null)) { obj.connectHandler(1); }
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
// Server confirmed authentication, we are allowed to send commands to the server
|
||||
obj.connectionState |= 8;
|
||||
if (obj.connectionState == 15) { obj.ws.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificatHashBase64 })); }
|
||||
if (obj.connectionState == 15) { obj.ws.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificateHashBase64 })); }
|
||||
//if ((obj.connectionState == 15) && (obj.connectHandler != null)) { obj.connectHandler(1); }
|
||||
break;
|
||||
}
|
||||
@ -212,9 +212,9 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||
obj.authenticated = 0;
|
||||
obj.remoteaddr = obj.ws._socket.remoteAddress;
|
||||
obj.receivedCommands = 0;
|
||||
obj.webCertificatHash = obj.parent.parent.webserver.webCertificatHash;
|
||||
obj.agentCertificatHashBase64 = obj.parent.parent.webserver.agentCertificatHashBase64;
|
||||
obj.agentCertificatAsn1 = obj.parent.parent.webserver.agentCertificatAsn1;
|
||||
obj.webCertificateHash = obj.parent.parent.webserver.webCertificateHash;
|
||||
obj.agentCertificateHashBase64 = obj.parent.parent.webserver.agentCertificateHashBase64;
|
||||
obj.agentCertificateAsn1 = obj.parent.parent.webserver.agentCertificateAsn1;
|
||||
obj.infoSent = 0;
|
||||
obj.peerServerId = null;
|
||||
obj.serverCertHash = null;
|
||||
@ -256,7 +256,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||
obj.receivedCommands += 1; // Peer server can't send the same command twice on the same connection ever. Block DOS attack path.
|
||||
|
||||
// Check that the server hash matches out own web certificate hash
|
||||
if (obj.webCertificatHash != msg.substring(2, 50)) { obj.close(); return; }
|
||||
if (obj.webCertificateHash != msg.substring(2, 50)) { obj.close(); return; }
|
||||
|
||||
// Use our server private key to sign the ServerHash + PeerNonce + ServerNonce
|
||||
var privateKey = obj.forge.pki.privateKeyFromPem(obj.parent.parent.certificates.agent.key);
|
||||
@ -266,7 +266,7 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||
obj.peernonce = msg.substring(50);
|
||||
|
||||
// Send back our certificate + signature
|
||||
obj.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.agentCertificatAsn1.length) + obj.agentCertificatAsn1 + privateKey.sign(md)); // Command 2, certificate + signature
|
||||
obj.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.agentCertificateAsn1.length) + obj.agentCertificateAsn1 + privateKey.sign(md)); // Command 2, certificate + signature
|
||||
|
||||
// Check the peer server signature if we can
|
||||
if (obj.unauthsign != null) {
|
||||
@ -307,24 +307,24 @@ module.exports.CreateMultiServer = function (parent, args) {
|
||||
// Start authenticate the peer server by sending a auth nonce & server TLS cert hash.
|
||||
// Send 384 bits SHA382 hash of TLS cert public key + 384 bits nonce
|
||||
obj.nonce = obj.forge.random.getBytesSync(48);
|
||||
obj.send(obj.common.ShortToStr(1) + obj.webCertificatHash + obj.nonce); // Command 1, hash + nonce
|
||||
obj.send(obj.common.ShortToStr(1) + obj.webCertificateHash + obj.nonce); // Command 1, hash + nonce
|
||||
|
||||
// Once we get all the information about an peer server, run this to hook everything up to the server
|
||||
function completePeerServerConnection() {
|
||||
if (obj.authenticated != 1) return;
|
||||
obj.send(obj.common.ShortToStr(4));
|
||||
obj.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificatHashBase64 }));
|
||||
obj.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificateHashBase64 }));
|
||||
obj.authenticated = 2;
|
||||
}
|
||||
|
||||
// Verify the peer server signature
|
||||
function processPeerSignature(msg) {
|
||||
var md = obj.forge.md.sha384.create(); // TODO: Switch this to SHA384 on node instead of forge.
|
||||
md.update(obj.parent.parent.webserver.webCertificatHash, 'binary');
|
||||
md.update(obj.parent.parent.webserver.webCertificateHash, 'binary');
|
||||
md.update(obj.nonce, 'binary');
|
||||
md.update(obj.peernonce, 'binary');
|
||||
if (obj.unauth.nodeCert.publicKey.verify(md.digest().bytes(), msg) == false) { return false; }
|
||||
if (obj.unauth.nodeid !== obj.agentCertificatHashBase64) { return false; }
|
||||
if (obj.unauth.nodeid !== obj.agentCertificateHashBase64) { return false; }
|
||||
|
||||
// Connection is a success, clean up
|
||||
obj.nodeid = obj.unauth.nodeid;
|
||||
|
12
webserver.js
12
webserver.js
@ -69,10 +69,10 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
|
||||
obj.userAllowedIp = args.userallowedip; // List of allowed IP addresses for users
|
||||
|
||||
// Perform hash on web certificate and agent certificate
|
||||
obj.webCertificatHash = parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(obj.certificates.web.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'binary' });
|
||||
obj.webCertificatHashBase64 = 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, '$');
|
||||
obj.agentCertificatHashBase64 = 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, '$');
|
||||
obj.agentCertificatAsn1 = parent.certificateOperations.forge.asn1.toDer(parent.certificateOperations.forge.pki.certificateToAsn1(parent.certificateOperations.forge.pki.certificateFromPem(parent.certificates.agent.cert))).getBytes();
|
||||
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' });
|
||||
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, '$');
|
||||
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, '$');
|
||||
obj.agentCertificateAsn1 = parent.certificateOperations.forge.asn1.toDer(parent.certificateOperations.forge.pki.certificateToAsn1(parent.certificateOperations.forge.pki.certificateFromPem(parent.certificates.agent.cert))).getBytes();
|
||||
|
||||
// Main lists
|
||||
obj.wsagents = {};
|
||||
@ -813,7 +813,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
|
||||
}
|
||||
|
||||
ws.forwardclient.onData = function (ciraconn, data) {
|
||||
Debug(3, 'Relay CIRA data', data.length);
|
||||
Debug(4, 'Relay CIRA data', data.length);
|
||||
if (ws.interceptor) { data = ws.interceptor.processAmtData(data); } // Run data thru interceptor
|
||||
if (data.length > 0) { try { ws.send(data); } catch (e) { } } // TODO: Add TLS support
|
||||
}
|
||||
@ -1942,7 +1942,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
|
||||
//if (domain.id != mesh.domain) { res.sendStatus(401); return; }
|
||||
|
||||
var meshidhex = new Buffer(req.query.id.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
|
||||
var serveridhex = new Buffer(obj.agentCertificatHashBase64.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
|
||||
var serveridhex = new Buffer(obj.agentCertificateHashBase64.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
|
||||
|
||||
var xdomain = domain.id;
|
||||
if (xdomain != '') xdomain += "/";
|
||||
|
Loading…
Reference in New Issue
Block a user