diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index bdd02be7d..a6aaccc55 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -4957,18 +4957,6 @@ "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" }, - "x509": { - "version": "0.2.6", - "from": "x509@>=0.2.4 <0.3.0", - "resolved": "https://registry.npmjs.org/x509/-/x509-0.2.6.tgz", - "dependencies": { - "nan": { - "version": "2.2.0", - "from": "nan@2.2.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.2.0.tgz" - } - } - }, "xml2js": { "version": "0.4.15", "from": "xml2js@0.4.15", diff --git a/package.json b/package.json index ebcf5525d..075cd0f36 100644 --- a/package.json +++ b/package.json @@ -67,8 +67,7 @@ "tldjs": "^1.6.2", "underscore": "^1.7.0", "valid-url": "^1.0.9", - "validator": "^4.9.0", - "x509": "^0.2.4" + "validator": "^4.9.0" }, "devDependencies": { "bootstrap-sass": "^3.3.3", diff --git a/src/certificates.js b/src/certificates.js index 45faaefde..c7e76529d 100644 --- a/src/certificates.js +++ b/src/certificates.js @@ -43,8 +43,7 @@ var acme = require('./cert/acme.js'), safe = require('safetydance'), settings = require('./settings.js'), user = require('./user.js'), - util = require('util'), - x509 = require('x509'); + util = require('util'); function CertificatesError(reason, errorOrMessage) { assert.strictEqual(typeof reason, 'string'); @@ -268,16 +267,6 @@ function validateCertificate(cert, key, fqdn) { if (!cert && key) return new Error('missing cert'); if (cert && !key) return new Error('missing key'); - var content; - try { - content = x509.parseCert(cert); - } catch (e) { - return new Error('invalid cert: ' + e.message); - } - - // check expiration - if (content.notAfter < new Date()) return new Error('cert expired'); - function matchesDomain(domain) { if (typeof domain !== 'string') return false; if (domain === fqdn) return true; @@ -286,8 +275,22 @@ function validateCertificate(cert, key, fqdn) { return false; } - // check domain - var domains = content.altNames.concat(content.subject.commonName); + // get commonName (http://stackoverflow.com/questions/17353122/parsing-strings-crt-files) + var result = safe.child_process.execSync('openssl x509 -noout -subject | sed -r "s|.*CN=(.*)|\\1|; s|/[^/]*=.*$||"', { encoding: 'utf8', input: cert }); + if (!result) return new Error(util.format('could not get CN')); + var commonName = result.trim(); + debug('validateCertificate: detected commonName as %s', commonName); + + // https://github.com/drwetter/testssl.sh/pull/383 + var cmd = `openssl x509 -noout -text | grep -A3 "Subject Alternative Name" | \ + grep "DNS:" | \ + sed -e "s/DNS://g" -e "s/ //g" -e "s/,/ /g" -e "s/othername://g"`; + result = safe.child_process.execSync(cmd, { encoding: 'utf8', input: cert }); + var altNames = result ? [ ] : result.trim().split(' '); // might fail if cert has no SAN + debug('validateCertificate: detected altNames as %j', altNames); + + // check altNames + var domains = altNames.concat(commonName); if (!domains.some(matchesDomain)) return new Error(util.format('cert is not valid for this domain. Expecting %s in %j', fqdn, domains)); // http://httpd.apache.org/docs/2.0/ssl/ssl_faq.html#verify @@ -295,6 +298,10 @@ function validateCertificate(cert, key, fqdn) { var keyModulus = safe.child_process.execSync('openssl rsa -noout -modulus', { encoding: 'utf8', input: key }); if (certModulus !== keyModulus) return new Error('key does not match the cert'); + // check expiration + result = safe.child_process.execSync('openssl x509 -checkend 0', { encoding: 'utf8', input: cert }); + if (!result) return new Error('cert expired'); + return null; }