From a5d1c9dab35030c839e3a2b506bd3dfcf631ccdb Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Tue, 11 Aug 2020 11:56:27 -0500
Subject: [PATCH 1/5] Disabled AIA and cert policy extensions in ACME examples
The ACME NSS issuer has been modified to disable the AIA and
certificate policy extensions by default since they contain
non-functional URLs that might cause certbot to generate
error messages.
https://bugzilla.redhat.com/show_bug.cgi?id=1868233
---
base/acme/issuer/nss/ca_signing.conf | 9 +++++----
base/acme/issuer/nss/sslserver.conf | 9 +++++----
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/base/acme/issuer/nss/ca_signing.conf b/base/acme/issuer/nss/ca_signing.conf
index aedcd4b0e..b9a82a2d1 100644
--- a/base/acme/issuer/nss/ca_signing.conf
+++ b/base/acme/issuer/nss/ca_signing.conf
@@ -1,8 +1,9 @@
basicConstraints = critical, CA:TRUE
subjectKeyIdentifier = hash
-authorityInfoAccess = OCSP;URI:http://ocsp.example.com, caIssuers;URI:http://cert.example.com
keyUsage = critical, digitalSignature, keyCertSign, cRLSign
-certificatePolicies = 2.23.140.1.2.1, @cps_policy
-cps_policy.id = 1.3.6.1.4.1.44947.1.1.1
-cps_policy.CPS.1 = http://cps.example.com
+# authorityInfoAccess = OCSP;URI:http://ocsp.example.com, caIssuers;URI:http://cert.example.com
+
+# certificatePolicies = 2.23.140.1.2.1, @cps_policy
+# cps_policy.id = 1.3.6.1.4.1.44947.1.1.1
+# cps_policy.CPS.1 = http://cps.example.com
diff --git a/base/acme/issuer/nss/sslserver.conf b/base/acme/issuer/nss/sslserver.conf
index f9e04902b..e153c223e 100644
--- a/base/acme/issuer/nss/sslserver.conf
+++ b/base/acme/issuer/nss/sslserver.conf
@@ -1,10 +1,11 @@
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
-authorityInfoAccess = OCSP;URI:http://ocsp.example.com, caIssuers;URI:http://cert.example.com
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
-certificatePolicies = 2.23.140.1.2.1, @cps_policy
-cps_policy.id = 1.3.6.1.4.1.44947.1.1.1
-cps_policy.CPS.1 = http://cps.example.com
+# authorityInfoAccess = OCSP;URI:http://ocsp.example.com, caIssuers;URI:http://cert.example.com
+
+# certificatePolicies = 2.23.140.1.2.1, @cps_policy
+# cps_policy.id = 1.3.6.1.4.1.44947.1.1.1
+# cps_policy.CPS.1 = http://cps.example.com
--
2.26.2
From a48e731d0faab11929fd9bf3d54a0638bbf40a16 Mon Sep 17 00:00:00 2001
From: Alexander Scheel <ascheel@redhat.com>
Date: Tue, 11 Aug 2020 14:41:16 -0400
Subject: [PATCH 2/5] Start NSSCertExportCLI
Can be tested with pki nss-cert-export
Signed-off-by: Alexander Scheel <ascheel@redhat.com>
---
.../com/netscape/cmstools/nss/NSSCertCLI.java | 3 +-
.../cmstools/nss/NSSCertExportCLI.java | 128 ++++++++++++++++++
2 files changed, 130 insertions(+), 1 deletion(-)
create mode 100644 base/java-tools/src/com/netscape/cmstools/nss/NSSCertExportCLI.java
diff --git a/base/java-tools/src/com/netscape/cmstools/nss/NSSCertCLI.java b/base/java-tools/src/com/netscape/cmstools/nss/NSSCertCLI.java
index 0313ffae5..2f1f8cac5 100644
--- a/base/java-tools/src/com/netscape/cmstools/nss/NSSCertCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/nss/NSSCertCLI.java
@@ -12,8 +12,9 @@ public class NSSCertCLI extends CLI {
public NSSCertCLI(NSSCLI nssCLI) {
super("cert", "NSS certificate management commands", nssCLI);
+ addModule(new NSSCertExportCLI(this));
addModule(new NSSCertImportCLI(this));
- addModule(new NSSCertRequestCLI(this));
addModule(new NSSCertIssueCLI(this));
+ addModule(new NSSCertRequestCLI(this));
}
}
diff --git a/base/java-tools/src/com/netscape/cmstools/nss/NSSCertExportCLI.java b/base/java-tools/src/com/netscape/cmstools/nss/NSSCertExportCLI.java
new file mode 100644
index 000000000..06150fe41
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/nss/NSSCertExportCLI.java
@@ -0,0 +1,128 @@
+//
+// Copyright Red Hat, Inc.
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+//
+package com.netscape.cmstools.nss;
+
+import java.io.FileOutputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import javax.net.ssl.KeyManagerFactory;
+import java.security.cert.X509Certificate;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.io.IOUtils;
+import org.dogtagpki.cli.CommandCLI;
+import org.dogtagpki.nss.NSSDatabase;
+import org.mozilla.jss.pkcs11.PK11Cert;
+import org.mozilla.jss.netscape.security.util.Cert;
+import org.mozilla.jss.netscape.security.util.Utils;
+import org.mozilla.jss.netscape.security.x509.X509CertImpl;
+import org.mozilla.jss.provider.javax.crypto.JSSKeyManager;
+
+import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.cmstools.cli.MainCLI;
+
+public class NSSCertExportCLI extends CommandCLI {
+
+ public static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(NSSCertExportCLI.class);
+
+ public NSSCertExportCLI(NSSCertCLI nssCertCLI) {
+ super("export", "Export certificate", nssCertCLI);
+ }
+
+ public void printHelp() {
+ formatter.printHelp(getFullName() + " [OPTIONS...] nickname [path]", options);
+ }
+
+ public void createOptions() {
+ Option option = new Option(null, "format", true, "Certificate format: PEM (default), DER, RAW");
+ option.setArgName("format");
+ options.addOption(option);
+
+ option = new Option(null, "with-chain", false, "Export with certificate chain from NSS DB");
+ option.setArgName("with-chain");
+ options.addOption(option);
+ }
+
+ public void execute(CommandLine cmd) throws Exception {
+
+ String[] cmdArgs = cmd.getArgs();
+ String nickname = null;
+ String path = null;
+
+ if (cmdArgs.length < 1) {
+ throw new Exception("Missing required positional argument: nickname");
+ }
+ nickname = cmdArgs[0];
+
+ if (cmdArgs.length >= 2) {
+ path = cmdArgs[1];
+ }
+
+ String format = cmd.getOptionValue("format", "PEM").toUpperCase();
+ boolean chain = cmd.hasOption("with-chain");
+
+ if (!format.equals("PEM") && !format.equals("DER") && !format.equals("RAW")) {
+ throw new Exception("Unknown type of output format: " + format);
+ }
+
+ if (chain && format.equals("DER")) {
+ throw new Exception("Unable to write chain of DER-encoded certificates; use PEM instead.");
+ }
+
+ MainCLI mainCLI = (MainCLI) getRoot();
+ mainCLI.init();
+
+ X509Certificate[] certs;
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("NssX509", "Mozilla-JSS");
+ JSSKeyManager km = (JSSKeyManager) kmf.getKeyManagers()[0];
+
+ if (chain) {
+ certs = km.getCertificateChain(nickname);
+ } else {
+ certs = new X509Certificate[] {
+ (PK11Cert) km.getCertificate(nickname)
+ };
+ }
+
+ byte[] output = null;
+
+ if (format.equals("RAW")) {
+ StringBuffer buffer = new StringBuffer();
+ for (X509Certificate cert : certs) {
+ buffer.append(cert.toString());
+ }
+
+ output = buffer.toString().getBytes();
+ } else if (format.equals("PEM")) {
+ StringBuffer buffer = new StringBuffer();
+
+ for (X509Certificate cert : certs) {
+ byte[] encoded = cert.getEncoded();
+ buffer.append(Cert.HEADER);
+ buffer.append("\r\n");
+ buffer.append(Utils.base64encodeMultiLine(encoded));
+ buffer.append(Cert.FOOTER);
+ buffer.append("\r\n\r\n");
+ }
+
+ output = buffer.toString().getBytes();
+ } else if (format.equals("DER")) {
+ for (X509Certificate cert : certs) {
+ output = cert.getEncoded();
+ }
+ }
+
+ if (path == null) {
+ System.out.println(new String(output));
+ } else {
+ try (FileOutputStream fos = new FileOutputStream(path)) {
+ fos.write(output);
+ }
+ }
+ }
+}
--
2.26.2
From 0c6b6e916420faa583a25a12621100a35bba1b57 Mon Sep 17 00:00:00 2001
From: Alexander Scheel <ascheel@redhat.com>
Date: Tue, 11 Aug 2020 15:16:01 -0400
Subject: [PATCH 3/5] Fix export on FIPS-enabled HSMs
Signed-off-by: Alexander Scheel <ascheel@redhat.com>
---
base/common/python/pki/nssdb.py | 70 +++++++++++++++++----------------
1 file changed, 37 insertions(+), 33 deletions(-)
diff --git a/base/common/python/pki/nssdb.py b/base/common/python/pki/nssdb.py
index 599cd9895..ff2af4a40 100644
--- a/base/common/python/pki/nssdb.py
+++ b/base/common/python/pki/nssdb.py
@@ -1351,6 +1351,38 @@ class NSSDatabase(object):
epoch = datetime.datetime.utcfromtimestamp(0)
return (date - epoch).total_seconds() * 1000
+ def export_cert_from_db(self,
+ nickname,
+ output_file,
+ include_chain=False,
+ output_format=None):
+ cmd = [
+ 'pki',
+ '-d', self.directory
+ ]
+
+ if self.password_file:
+ cmd.extend(['-C', self.password_file])
+
+ if self.token:
+ cmd.extend(['--token', self.token])
+ full_name = self.token + ':' + nickname
+ else:
+ full_name = nickname
+
+ cmd.extend(['nss-cert-export'])
+
+ if include_chain:
+ cmd.extend(['--with-chain'])
+
+ if output_format:
+ cmd.extend(['--format', output_format])
+
+ cmd.extend([full_name, output_file])
+
+ logger.debug('Command: %s', ' '.join(map(str, cmd)))
+ subprocess.check_call(cmd)
+
def export_cert(self,
nickname,
pkcs12_file,
@@ -1752,39 +1784,11 @@ class NSSDatabase(object):
shutil.rmtree(tmpdir)
def extract_ca_cert(self, ca_path, nickname):
- tmpdir = tempfile.mkdtemp()
-
- try:
- p12_file = os.path.join(tmpdir, "sslserver.p12")
- password = pki.generate_password()
-
- # Build a chain containing the certificate we're trying to
- # export. OpenSSL gets confused if we don't have a key for
- # the end certificate: rh-bz#1246371
- self.export_pkcs12(p12_file, pkcs12_password=password,
- nicknames=[nickname], include_key=False,
- include_chain=True)
-
- # This command is similar to the one from server/__init__.py.
- # However, to work during the initial startup, we do not
- # specify the cacerts option! This ensures we always get
- cmd_export_ca = [
- 'openssl', 'pkcs12',
- '-in', p12_file,
- '-out', ca_path,
- '-nodes', '-nokeys',
- '-passin', 'pass:' + password
- ]
-
- # Remove CA.crt prior to starting; openssl gets annoyed otherwise.
- if os.path.exists(ca_path):
- os.remove(ca_path)
-
- res_ca = subprocess.check_output(cmd_export_ca,
- stderr=subprocess.STDOUT).decode('utf-8')
- logger.debug('Result of CA cert export: %s', res_ca)
- finally:
- shutil.rmtree(tmpdir)
+ # Build a chain containing the certificate we're trying to
+ # export. OpenSSL gets confused if we don't have a key for
+ # the end certificate: rh-bz#1246371
+ self.export_cert_from_db(nickname, ca_path, include_chain=True,
+ output_format="PEM")
@staticmethod
def __generate_key_args(key_type=None, key_size=None, curve=None):
--
2.26.2
From 2df13c4195e8e6b184294888b2c6376043047e33 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Tue, 11 Aug 2020 19:39:39 -0500
Subject: [PATCH 4/5] Fixed cert nickname in NSSDatabase.export_cert_from_db()
The NSSDatabase.export_cert_from_db() has been modified to
no longer prepend the token name to the cert nickname since
the cert nickname obtained from serverCertNick.conf already
contains the token name.
---
base/common/python/pki/nssdb.py | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/base/common/python/pki/nssdb.py b/base/common/python/pki/nssdb.py
index ff2af4a40..c7ce89336 100644
--- a/base/common/python/pki/nssdb.py
+++ b/base/common/python/pki/nssdb.py
@@ -1366,9 +1366,6 @@ class NSSDatabase(object):
if self.token:
cmd.extend(['--token', self.token])
- full_name = self.token + ':' + nickname
- else:
- full_name = nickname
cmd.extend(['nss-cert-export'])
@@ -1378,7 +1375,7 @@ class NSSDatabase(object):
if output_format:
cmd.extend(['--format', output_format])
- cmd.extend([full_name, output_file])
+ cmd.extend([nickname, output_file])
logger.debug('Command: %s', ' '.join(map(str, cmd)))
subprocess.check_call(cmd)
--
2.26.2
From eb28b09fb030fe5df2b6b4cfa16338ddd0325b30 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Tue, 11 Aug 2020 20:07:56 -0500
Subject: [PATCH 5/5] Removed blank lines in pki nss-cert-export output
The pki nss-cert-export has been modified to remove the extra
blank lines between certs and at the end of the output.
---
.../src/com/netscape/cmstools/nss/NSSCertExportCLI.java | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/base/java-tools/src/com/netscape/cmstools/nss/NSSCertExportCLI.java b/base/java-tools/src/com/netscape/cmstools/nss/NSSCertExportCLI.java
index 06150fe41..9aaf83a30 100644
--- a/base/java-tools/src/com/netscape/cmstools/nss/NSSCertExportCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/nss/NSSCertExportCLI.java
@@ -107,7 +107,7 @@ public class NSSCertExportCLI extends CommandCLI {
buffer.append("\r\n");
buffer.append(Utils.base64encodeMultiLine(encoded));
buffer.append(Cert.FOOTER);
- buffer.append("\r\n\r\n");
+ buffer.append("\r\n");
}
output = buffer.toString().getBytes();
@@ -118,7 +118,8 @@ public class NSSCertExportCLI extends CommandCLI {
}
if (path == null) {
- System.out.println(new String(output));
+ System.out.print(new String(output));
+ System.out.flush();
} else {
try (FileOutputStream fos = new FileOutputStream(path)) {
fos.write(output);
--
2.26.2