diff --git a/agents/MeshCmd-signed.exe b/agents/MeshCmd-signed.exe index 309bab39..b708d0e0 100644 Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ diff --git a/agents/MeshCmd64-signed.exe b/agents/MeshCmd64-signed.exe index fe7c30c4..29af3c50 100644 Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ diff --git a/agents/MeshService-signed.exe b/agents/MeshService-signed.exe index 6a702c55..551c6d1f 100644 Binary files a/agents/MeshService-signed.exe and b/agents/MeshService-signed.exe differ diff --git a/agents/MeshService.exe b/agents/MeshService.exe index e730bb45..d07b0c65 100644 Binary files a/agents/MeshService.exe and b/agents/MeshService.exe differ diff --git a/agents/MeshService64-signed.exe b/agents/MeshService64-signed.exe index 42e8919e..a3467ead 100644 Binary files a/agents/MeshService64-signed.exe and b/agents/MeshService64-signed.exe differ diff --git a/agents/MeshService64.exe b/agents/MeshService64.exe index aa8a5213..31b15918 100644 Binary files a/agents/MeshService64.exe and b/agents/MeshService64.exe differ diff --git a/agents/meshagent_arm b/agents/meshagent_arm index 94d1752b..76918b81 100644 Binary files a/agents/meshagent_arm and b/agents/meshagent_arm differ diff --git a/agents/meshagent_arm-linaro b/agents/meshagent_arm-linaro index ddfe2233..c9b555cd 100644 Binary files a/agents/meshagent_arm-linaro and b/agents/meshagent_arm-linaro differ diff --git a/agents/meshagent_armhf b/agents/meshagent_armhf index d319efa6..f50b9795 100644 Binary files a/agents/meshagent_armhf and b/agents/meshagent_armhf differ diff --git a/agents/meshagent_pogo b/agents/meshagent_pogo index fd8cdb8b..382662d9 100644 Binary files a/agents/meshagent_pogo and b/agents/meshagent_pogo differ diff --git a/agents/meshagent_poky b/agents/meshagent_poky index feb9f795..f29f310e 100644 Binary files a/agents/meshagent_poky and b/agents/meshagent_poky differ diff --git a/agents/meshagent_poky64 b/agents/meshagent_poky64 index 9572e817..8910ca6e 100644 Binary files a/agents/meshagent_poky64 and b/agents/meshagent_poky64 differ diff --git a/agents/meshagent_x86 b/agents/meshagent_x86 index c6d4ed8c..a1f5c198 100644 Binary files a/agents/meshagent_x86 and b/agents/meshagent_x86 differ diff --git a/agents/meshagent_x86-64 b/agents/meshagent_x86-64 index ae120546..aedc667b 100644 Binary files a/agents/meshagent_x86-64 and b/agents/meshagent_x86-64 differ diff --git a/agents/meshagent_x86-64_nokvm b/agents/meshagent_x86-64_nokvm index 522fc4ae..9f9e9992 100644 Binary files a/agents/meshagent_x86-64_nokvm and b/agents/meshagent_x86-64_nokvm differ diff --git a/agents/meshagent_x86_nokvm b/agents/meshagent_x86_nokvm index 3ef18979..9d36da11 100644 Binary files a/agents/meshagent_x86_nokvm and b/agents/meshagent_x86_nokvm differ diff --git a/meshagent.js b/meshagent.js index b81b9580..5aefb160 100644 --- a/meshagent.js +++ b/meshagent.js @@ -266,7 +266,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Decode the certificate var certlen = obj.common.ReadShort(msg, 2); obj.unauth = {}; - try { obj.unauth.nodeid = Buffer.from(obj.forge.pki.getPublicKeyFingerprint(obj.forge.pki.certificateFromAsn1(obj.forge.asn1.fromDer(msg.substring(4, 4 + certlen))).publicKey, { md: obj.forge.md.sha384.create() }).data, 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'); } catch (e) { return; } + try { obj.unauth.nodeid = Buffer.from(obj.forge.pki.getPublicKeyFingerprint(obj.forge.pki.certificateFromAsn1(obj.forge.asn1.fromDer(msg.substring(4, 4 + certlen))).publicKey, { md: obj.forge.md.sha384.create() }).data, 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'); } catch (ex) { console.log(ex); return; } obj.unauth.nodeCertPem = '-----BEGIN CERTIFICATE-----\r\n' + Buffer.from(msg.substring(4, 4 + certlen), 'binary').toString('base64') + '\r\n-----END CERTIFICATE-----'; // Check the agent signature if we can @@ -462,13 +462,43 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Verify the agent signature function processAgentSignature(msg) { if (obj.args.ignoreagenthashcheck !== true) { - // Verify the signature. This is the fast way, without using forge. - const verify = obj.parent.crypto.createVerify('SHA384'); - verify.end(Buffer.from(getWebCertHash(obj.domain) + obj.nonce + obj.agentnonce, 'binary')); // Test using the private key hash - if (verify.verify(obj.unauth.nodeCertPem, Buffer.from(msg, 'binary')) !== true) { - const verify2 = obj.parent.crypto.createVerify('SHA384'); - verify2.end(Buffer.from(getWebCertFullHash(obj.domain) + obj.nonce + obj.agentnonce, 'binary')); // Test using the full cert hash - if (verify2.verify(obj.unauth.nodeCertPem, Buffer.from(msg, 'binary')) !== true) { return false; } + var verified = false; + + if (msg.length != 384) { + // Verify a PKCS7 signature. + var msgDer = null; + try { msgDer = obj.forge.asn1.fromDer(obj.forge.util.createBuffer(msg, 'binary')); } catch (ex) { } + if (msgDer != null) { + try { + var p7 = obj.forge.pkcs7.messageFromAsn1(msgDer); + var sig = p7.rawCapture.signature; + + // Verify with key hash + var buf = Buffer.from(getWebCertHash(obj.domain) + obj.nonce + obj.agentnonce, 'binary'); + var verifier = obj.parent.crypto.createVerify('RSA-SHA384'); + verifier.update(buf); + verified = verifier.verify(obj.unauth.nodeCertPem, sig, 'binary'); + if (verified == false) { + // Verify with full hash + buf = Buffer.from(getWebCertFullHash(obj.domain) + obj.nonce + obj.agentnonce, 'binary'); + verifier = obj.parent.crypto.createVerify('RSA-SHA384'); + verifier.update(buf); + verified = verifier.verify(obj.unauth.nodeCertPem, sig, 'binary'); + } + if (verified == false) { return false; } // Not a valid signature + } catch (ex) { }; + } + } + + if (verified == false) { + // Verify the RSA signature. This is the fast way, without using forge. + const verify = obj.parent.crypto.createVerify('SHA384'); + verify.end(Buffer.from(getWebCertHash(obj.domain) + obj.nonce + obj.agentnonce, 'binary')); // Test using the private key hash + if (verify.verify(obj.unauth.nodeCertPem, Buffer.from(msg, 'binary')) !== true) { + const verify2 = obj.parent.crypto.createVerify('SHA384'); + verify2.end(Buffer.from(getWebCertFullHash(obj.domain) + obj.nonce + obj.agentnonce, 'binary')); // Test using the full cert hash + if (verify2.verify(obj.unauth.nodeCertPem, Buffer.from(msg, 'binary')) !== true) { return false; } + } } } diff --git a/meshcentral.js b/meshcentral.js index 316930c6..21d686b5 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -90,7 +90,7 @@ function CreateMeshCentralServer(config, args) { 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', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'shownodes', 'showmeshes', 'showevents', 'showpower', 'clearpower', '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', 'swarmport', 'swarmdebug', 'logintoken', 'logintokenkey', 'logintokengen', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify', 'minifycore']; + var validArguments = ['_', 'notls', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'shownodes', 'showmeshes', 'showevents', 'showpower', 'clearpower', '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', 'swarmallowedip', 'fastcert', 'swarmport', 'swarmdebug', 'logintoken', 'logintokenkey', 'logintokengen', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify', 'minifycore']; 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; } for (i in obj.config.settings) { obj.args[i] = obj.config.settings[i]; } // Place all settings into arguments, arguments have already been placed into settings so arguments take precedence. @@ -252,6 +252,7 @@ function CreateMeshCentralServer(config, args) { if (obj.args.notls == null && obj.args.redirport == null) obj.args.redirport = 80; if (obj.args.minifycore === 0) obj.args.minifycore = false; if (typeof obj.args.userallowedip == 'string') { if (obj.args.userallowedip == '') { obj.args.userallowedip = null; } else { obj.args.userallowedip = obj.args.userallowedip.split(','); } } + if (typeof obj.args.swarmallowedip == 'string') { if (obj.args.swarmallowedip == '') { obj.args.swarmallowedip = null; } else { obj.args.swarmallowedip = obj.args.swarmallowedip.split(','); } } if (typeof obj.args.debug == 'number') obj.debugLevel = obj.args.debug; if (obj.args.debug == true) obj.debugLevel = 1; obj.db = require('./db.js').CreateDB(obj); diff --git a/package.json b/package.json index b0e84747..800fe3c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.2.5-y", + "version": "0.2.6-d", "keywords": [ "Remote Management", "Intel AMT", diff --git a/swarmserver.js b/swarmserver.js index 50fe43c7..0ad4b7d5 100644 --- a/swarmserver.js +++ b/swarmserver.js @@ -122,7 +122,7 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) { GUESTWEBRTCMESH: 2002 // Guest usage: WebRTC Mesh }; - obj.server = tls.createServer({ key: certificates.swarmserver.key, cert: certificates.swarmserver.cert, requestCert: true }, onConnection); + obj.server = tls.createServer({ key: certificates.swarmserver.key, cert: certificates.swarmserver.cert, requestCert: true, rejectUnauthorized: false }, onConnection); obj.server.listen(args.swarmport, function () { console.log('MeshCentral Legacy Swarm Server running on ' + certificates.CommonName + ':' + args.swarmport + '.'); obj.parent.updateServerState('swarm-port', args.swarmport); }).on('error', function (err) { console.error('ERROR: MeshCentral Swarm Server server port ' + args.swarmport + ' is not available.'); if (args.exactports) { process.exit(); } }); loadMigrationAgents(); @@ -147,6 +147,9 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) { // Called when a legacy agent connects to this server function onConnection(socket) { + // Check for blocked IP address + if (checkSwarmIpAddress(socket, obj.args.swarmallowedip) == false) { Debug(1, "SWARM:New blocked agent connection"); return; } + socket.tag = { first: true, clientCert: socket.getPeerCertificate(true), accumulator: "", socket: socket }; socket.setEncoding('binary'); socket.pingTimer = setInterval(function () { obj.SendCommand(socket, LegacyMeshProtocol.PING); }, 20000); @@ -349,6 +352,16 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) { } } + // Check if the source IP address is allowed for a given allowed list, return false if not + function checkSwarmIpAddress(socket, allowedIpList) { + if (allowedIpList == null) { return true; } + try { + var ip = socket.remoteAddress; + if (ip) { for (var i = 0; i < allowedIpList.length; i++) { if (require('ipcheck').match(ip, allowedIpList[i])) { return true; } } } + } catch (e) { console.log(e); } + return false; + } + // Debug function Debug(lvl) { if (lvl > obj.parent.debugLevel) return;