diff --git a/agents/MeshService.exe b/agents/MeshService.exe index 00ddfa14..a8e300f0 100644 Binary files a/agents/MeshService.exe and b/agents/MeshService.exe differ diff --git a/agents/MeshService64.exe b/agents/MeshService64.exe index 17f5dab8..ca1807de 100644 Binary files a/agents/MeshService64.exe and b/agents/MeshService64.exe differ diff --git a/agents/meshcore.js b/agents/meshcore.js index 28f5463e..dda29422 100644 --- a/agents/meshcore.js +++ b/agents/meshcore.js @@ -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; } diff --git a/certoperations.js b/certoperations.js index 6553397f..4d04bf18 100644 --- a/certoperations.js +++ b/certoperations.js @@ -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; diff --git a/meshagent.js b/meshagent.js index adc42e4a..c5f2c6b8 100644 --- a/meshagent.js +++ b/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; } diff --git a/meshcentral.js b/meshcentral.js index 6e4d4508..b0478a50 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -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; } diff --git a/meshscanner.js b/meshscanner.js index 6c0d8721..1655a8c5 100644 --- a/meshscanner.js +++ b/meshscanner.js @@ -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) { } } } diff --git a/mpsserver.js b/mpsserver.js index 518c120a..74b2d130 100644 --- a/mpsserver.js +++ b/mpsserver.js @@ -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)); } diff --git a/multiserver.js b/multiserver.js index 3bf64d08..63f469f5 100644 --- a/multiserver.js +++ b/multiserver.js @@ -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; diff --git a/webserver.js b/webserver.js index 81f02745..5d733fd2 100644 --- a/webserver.js +++ b/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 += "/";