From 8b2a2b12a343634b0eb0e9162bd26c9cf4445f0d Mon Sep 17 00:00:00 2001 From: John Knox Date: Mon, 18 Jun 2018 03:32:10 -0700 Subject: [PATCH] Add LibreSSL support (and other openssl implementations) Summary: Common Name extraction by regex was failing on LibreSSL. Now using RFC2253 to unamiguously format distinguished name subject strings. Reviewed By: emilsjolander Differential Revision: D8452825 fbshipit-source-id: a18d4162a7aed3b5bd8c2996ff3832877dac90db --- src/utils/CertificateProvider.js | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/utils/CertificateProvider.js b/src/utils/CertificateProvider.js index c109ba0e6..bbf61d818 100644 --- a/src/utils/CertificateProvider.js +++ b/src/utils/CertificateProvider.js @@ -34,6 +34,12 @@ const appNotDebuggableRegex = /debuggable/; const allowedAppNameRegex = /^[a-zA-Z0-9.\-]+$/; const allowedAppDirectoryRegex = /^\/[ a-zA-Z0-9.\-\/]+$/; const logTag = 'CertificateProvider'; +/* + * RFC2253 specifies the unamiguous x509 subject format. + * However, even when specifying this, different openssl implementations + * wrap it differently, e.g "subject=X" vs "subject= X". + */ +const x509SubjectCNRegex = /[=,]\s*CN=([^,]*)(,.*)?$/; export type SecureServerConfig = {| key: Buffer, @@ -286,20 +292,23 @@ export default class CertificateProvider { extractAppNameFromCSR(csr: string): Promise { const csrFile = this.writeToTempFile(csr); - return openssl('req', {in: csrFile, noout: true, subject: true}) + return openssl('req', { + in: csrFile, + noout: true, + subject: true, + nameopt: true, + RFC2253: false, + }) .then(subject => { fs.unlink(csrFile); return subject; }) .then(subject => { - return subject - .split('/') - .filter(part => { - return part.startsWith('CN='); - }) - .map(part => { - return part.split('=')[1].trim(); - })[0]; + const matches = subject.trim().match(x509SubjectCNRegex); + if (!matches || matches.length < 2) { + throw new Error(`Cannot extract CN from ${subject}`); + } + return matches[1]; }) .then(appName => { if (!appName.match(allowedAppNameRegex)) {