Added new certificate for Intel AMT console authentication.

This commit is contained in:
Ylian Saint-Hilaire 2017-09-29 14:26:51 -07:00
parent 646bc67365
commit 5ced5c565e
3 changed files with 142 additions and 41 deletions

View File

@ -19,6 +19,14 @@ module.exports.CertificateOperations = function () {
return obj.pki.getPublicKeyFingerprint(publickey, { encoding: 'hex', md: obj.forge.md.sha256.create() });
}
// Return a random nonce (TODO: weak crypto)
obj.xxRandomNonceX = "abcdef0123456789";
obj.xxRandomNonce = function (length) {
var r = "";
for (var i = 0; i < length; i++) { r += obj.xxRandomNonceX.charAt(Math.floor(Math.random() * obj.xxRandomNonceX.length)); }
return r;
}
// Create a self-signed certificate
obj.GenerateRootCertificate = function (addThumbPrintToName, commonName, country, organization) {
var keys = obj.pki.rsa.generateKeyPair(2048);
@ -54,7 +62,7 @@ module.exports.CertificateOperations = function () {
}
// Issue a certificate from a root
obj.IssueWebServerCertificate = function (rootcert, addThumbPrintToName, commonName, country, organization) {
obj.IssueWebServerCertificate = function (rootcert, addThumbPrintToName, commonName, country, organization, extKeyUsage) {
var keys = obj.pki.rsa.generateKeyPair(2048);
var cert = obj.pki.createCertificate();
cert.publicKey = keys.publicKey;
@ -69,25 +77,45 @@ module.exports.CertificateOperations = function () {
if (organization != undefined) attrs.push({ name: 'organizationName', value: organization });
cert.setSubject(attrs);
cert.setIssuer(rootcert.cert.subject.attributes);
cert.setExtensions([{
name: 'basicConstraints',
cA: false
}, {
if (extKeyUsage == null) { extKeyUsage = { name: 'extKeyUsage', serverAuth: true, } } else { extKeyUsage.name = 'extKeyUsage'; }
var subjectAltName = null;
if (extKeyUsage.serverAuth == true) {
subjectAltName = {
name: 'subjectAltName',
altNames: [{
type: 6, // URI
value: 'http://' + commonName + '/'
}, {
type: 6, // URL
value: 'http://localhost/'
}]
}
}
/*
{
name: 'extKeyUsage',
serverAuth: true,
clientAuth: true,
codeSigning: true,
emailProtection: true,
timeStamping: true,
'2.16.840.1.113741.1.2.1': true
}
*/
var extensions = [{
name: 'basicConstraints',
cA: false
}, {
name: 'keyUsage',
keyCertSign: true,
digitalSignature: true,
nonRepudiation: true,
keyEncipherment: true,
dataEncipherment: true
}, {
name: 'extKeyUsage',
serverAuth: true,
clientAuth: false,
codeSigning: false,
emailProtection: false,
timeStamping: false
}, {
}, extKeyUsage, {
name: 'nsCertType',
client: false,
server: true,
@ -96,18 +124,11 @@ module.exports.CertificateOperations = function () {
sslCA: false,
emailCA: false,
objCA: false
}, {
name: 'subjectAltName',
altNames: [{
type: 6, // URI
value: 'http://' + commonName + '/'
}, {
type: 6, // URL
value: 'http://localhost/'
}]
}, {
name: 'subjectKeyIdentifier'
}]);
}]
if (subjectAltName != null) extensions.push(subjectAltName);
cert.setExtensions(extensions);
cert.sign(rootcert.key, obj.forge.md.sha256.create());
@ -155,6 +176,14 @@ module.exports.CertificateOperations = function () {
rcount++;
}
// If the bin certificate already exist, load it
if (obj.fileExists(directory + '/amtconsole-cert-public.crt') && obj.fileExists(directory + '/agentserver-cert-private.key')) {
var amtConsoleCertificate = obj.fs.readFileSync(directory + '/amtconsole-cert-public.crt', 'utf8');
var amtConsolePrivateKey = obj.fs.readFileSync(directory + '/amtconsole-cert-private.key', 'utf8');
r.console = { cert: amtConsoleCertificate, key: amtConsolePrivateKey };
rcount++;
}
// If CA certificates are present, load them
var caok, caindex = 1, calist = [];
do {
@ -177,7 +206,10 @@ module.exports.CertificateOperations = function () {
if (args.length > 2) organization = args[2];
}
if (rcount == 4) {
if (rcount == 5) {
// Fetch the Intel AMT console name
var consoleCertificate = obj.pki.certificateFromPem(r.console.cert);
r.AmtConsoleName = consoleCertificate.subject.getField('CN').value;
// Fetch the name of the server
var webCertificate = obj.pki.certificateFromPem(r.web.cert);
r.CommonName = webCertificate.subject.getField('CN').value;
@ -210,20 +242,49 @@ module.exports.CertificateOperations = function () {
// If the web certificate does not exist, create one
var webCertAndKey, webCertificate, webPrivateKey;
webCertAndKey = obj.IssueWebServerCertificate(rootCertAndKey, false, commonName, country, organization);
webCertificate = obj.pki.certificateToPem(webCertAndKey.cert);
webPrivateKey = obj.pki.privateKeyToPem(webCertAndKey.key);
obj.fs.writeFileSync(directory + '/webserver-cert-public.crt', webCertificate);
obj.fs.writeFileSync(directory + '/webserver-cert-private.key', webPrivateKey);
if (r.web == undefined) {
webCertAndKey = obj.IssueWebServerCertificate(rootCertAndKey, false, commonName, country, organization);
webCertificate = obj.pki.certificateToPem(webCertAndKey.cert);
webPrivateKey = obj.pki.privateKeyToPem(webCertAndKey.key);
obj.fs.writeFileSync(directory + '/webserver-cert-public.crt', webCertificate);
obj.fs.writeFileSync(directory + '/webserver-cert-private.key', webPrivateKey);
} else {
// Keep the console certificate we have
webCertAndKey = { cert: obj.pki.certificateFromPem(r.web.cert), key: obj.pki.privateKeyFromPem(r.web.key) };
webCertificate = r.web.cert
webPrivateKey = r.web.key
}
// If the Intel AMT MPS certificate does not exist, create one
var mpsCertAndKey, mpsCertificate, mpsPrivateKey;
mpsCertAndKey = obj.IssueWebServerCertificate(rootCertAndKey, false, commonName, country, organization);
mpsCertificate = obj.pki.certificateToPem(mpsCertAndKey.cert);
mpsPrivateKey = obj.pki.privateKeyToPem(mpsCertAndKey.key);
obj.fs.writeFileSync(directory + '/mpsserver-cert-public.crt', mpsCertificate);
obj.fs.writeFileSync(directory + '/mpsserver-cert-private.key', mpsPrivateKey);
if (r.console == undefined) {
mpsCertAndKey = obj.IssueWebServerCertificate(rootCertAndKey, false, commonName, country, organization);
mpsCertificate = obj.pki.certificateToPem(mpsCertAndKey.cert);
mpsPrivateKey = obj.pki.privateKeyToPem(mpsCertAndKey.key);
obj.fs.writeFileSync(directory + '/mpsserver-cert-public.crt', mpsCertificate);
obj.fs.writeFileSync(directory + '/mpsserver-cert-private.key', mpsPrivateKey);
} else {
// Keep the console certificate we have
mpsCertAndKey = { cert: obj.pki.certificateFromPem(r.mps.cert), key: obj.pki.privateKeyFromPem(r.mps.key) };
mpsCertificate = r.mps.cert
mpsPrivateKey = r.mps.key
}
// If the Intel AMT console certificate does not exist, create one
var consoleCertAndKey, consoleCertificate, consolePrivateKey, amtConsoleName = obj.xxRandomNonce(12);
if (r.console == undefined) {
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 }); // Intel AMT Remote, Agent and Activation usages
consoleCertificate = obj.pki.certificateToPem(consoleCertAndKey.cert);
consolePrivateKey = obj.pki.privateKeyToPem(consoleCertAndKey.key);
obj.fs.writeFileSync(directory + '/amtconsole-cert-public.crt', consoleCertificate);
obj.fs.writeFileSync(directory + '/amtconsole-cert-private.key', consolePrivateKey);
} else {
// Keep the console certificate we have
consoleCertAndKey = { cert: obj.pki.certificateFromPem(r.console.cert), key: obj.pki.privateKeyFromPem(r.console.key) };
consoleCertificate = r.console.cert
consolePrivateKey = r.console.key
}
// If the mesh agent server certificate does not exist, create one
var agentCertAndKey, agentCertificate, agentPrivateKey;
if (r.agent == undefined) {
@ -239,7 +300,7 @@ module.exports.CertificateOperations = function () {
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 }, calist: calist, CommonName: commonName, RootName: rootName };
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,3 +151,41 @@ ReferenceError: args is not defined
at InternalFieldObject.ondone (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshcentral.js:307:57)
-------- 9/29/2017, 11:50:51 AM --------
C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\node-forge\js\x509.js:2083
throw error;
^
Error: Extension ID not specified.
at _fillMissingExtensionFields (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\node-forge\js\x509.js:2081:19)
at Object.cert.setExtensions (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\node-forge\js\x509.js:983:7)
at Object.obj.IssueWebServerCertificate (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\certoperations.js:108:14)
at Object.obj.GetMeshServerCertificate (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\certoperations.js:256:33)
at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshcentral.js:286:43
at newArguments.(anonymous function) (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\executor.js:29:17)
at Cursor.execFn (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:484:12)
at callback (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\cursor.js:126:19)
at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\cursor.js:193:12
at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:329:14
-------- 9/29/2017, 2:14:26 PM --------
C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\webserver.js:866
var tlsoptions = { secureProtocol: 'TLSv1_method', ciphers: 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AES:!aNULL:!MD5:!DSS', secureOptions: obj.constants.SSL_OP_NO_SSLv2 | obj.constants.SSL_OP_NO_SSLv3 | obj.constants.SSL_OP_NO_COMPRESSION | obj.constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false, cert: obj.certificates.console.cert, key: obj.certificates.console.key };
^
TypeError: Cannot read property 'SSL_OP_NO_SSLv2' of undefined
at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\webserver.js:866:200
at newArguments.(anonymous function) (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\executor.js:29:17)
at Cursor.execFn (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:484:12)
at callback (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\cursor.js:126:19)
at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\cursor.js:193:12
at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:329:14
at Object.async.eachSeries (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:130:20)
at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:323:11
at fn (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:582:34)
at Immediate._onImmediate (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:498:34)

View File

@ -43,6 +43,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
obj.tls = require('tls');
obj.path = require('path');
obj.hash = require('./pass').hash;
obj.constants = require('constants');
obj.bodyParser = require('body-parser');
obj.session = require('express-session');
obj.exphbs = require('express-handlebars');
@ -751,7 +752,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// TLSSocket to encapsulate TLS communication, which then tunneled via SerialTunnel an then wrapped through CIRA APF
var TLSSocket = require('tls').TLSSocket;
var tlsock = new TLSSocket(ser, { secureProtocol: 'SSLv23_method', rejectUnauthorized: false }); // TLSv1_2_method
var tlsoptions = { secureProtocol: 'TLSv1_method', ciphers: 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AES:!aNULL:!MD5:!DSS', secureOptions: obj.constants.SSL_OP_NO_SSLv2 | obj.constants.SSL_OP_NO_SSLv3 | obj.constants.SSL_OP_NO_COMPRESSION | obj.constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false, cert: obj.certificates.console.cert, key: obj.certificates.console.key };
var tlsock = new TLSSocket(ser, tlsoptions); // 'TLSv1_2_method' or 'SSLv23_method'
tlsock.on('error', function (err) { Debug(1, "CIRA TLS Connection Error ", err); });
tlsock.on('secureConnect', function () { Debug(2, "CIRA Secure TLS Connection"); ws.resume(); });
@ -862,7 +864,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
ws.resume();
} else {
// If TLS is going to be used, setup a TLS socket
ws.forwardclient = obj.tls.connect(port, node.host, { secureProtocol: 'TLSv1_method', rejectUnauthorized: false }, function () {
var tlsoptions = { secureProtocol: 'TLSv1_method', ciphers: 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AES:!aNULL:!MD5:!DSS', secureOptions: obj.constants.SSL_OP_NO_SSLv2 | obj.constants.SSL_OP_NO_SSLv3 | obj.constants.SSL_OP_NO_COMPRESSION | obj.constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false, cert: obj.certificates.console.cert, key: obj.certificates.console.key };
ws.forwardclient = obj.tls.connect(port, node.host, tlsoptions, function () {
// The TLS connection method is the same as TCP, but located a bit differently.
Debug(2, 'TLS connected to ' + node.host + ':' + port + '.');
ws.forwardclient.xstate = 1;
@ -1886,7 +1889,6 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Handle a request to download a mesh agent
obj.handleMeshAgentRequest = function (req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
if (req.query.id != null) {
// Send a specific mesh agent back
var argentInfo = obj.parent.meshAgentBinaries[req.query.id];