Fixed certificate generation.

This commit is contained in:
Ylian Saint-Hilaire 2017-10-18 16:28:05 -07:00
parent c848956aa4
commit 5108b344be
10 changed files with 82 additions and 64 deletions

Binary file not shown.

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

@ -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) { } }
}

View File

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

View File

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

View File

@ -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 += "/";