[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Pki-devel] [PATCH] 807-809 Fixed PKCS #12 import for cloning.



To fix cloning issue in IPA the security_database.py has been
modified to import all certificates and keys in the PKCS #12 file
before the PKI server is started. Since the PKCS #12 generated by
IPA may not contain the certificate trust flags, the script will
also reset the trust flags on the imported certificates (i.e.
CT,C,C for CA certificate and u,u,Pu for audit certificate).

https://fedorahosted.org/pki/ticket/2424

--
Endi S. Dewata
>From d607ba3fe642b33dd0a12ae3321622898f247f5d Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata redhat com>
Date: Mon, 1 Aug 2016 22:35:32 +0200
Subject: [PATCH] Added log messages for certificate validation.

The ConfigCertApprovalCallback has been modified such that it
logs the server certificate being validated and can be configured
to ignore certain validation errors.

The ConfigurationUtils has been modified to use the
ConfigCertApprovalCallback to show and validate the server
certificate in all GET and POST operations except for the
importCertChain() in which the code needs to ignore untrusted
issuer in order to get the certificate chain via SSL.

https://fedorahosted.org/pki/ticket/2424
---
 .../csadmin/ConfigCertApprovalCallback.java        | 63 +++++++++++++++++++++-
 .../cms/servlet/csadmin/ConfigurationUtils.java    | 63 ++++++++++++----------
 2 files changed, 97 insertions(+), 29 deletions(-)

diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java
index 956c285b5e329d33af0d4f5a4211f6719767de8f..9b741af020c22c54ac9f61fc2103a2856d026fc8 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java
@@ -17,17 +17,78 @@
 // --- END COPYRIGHT BLOCK ---
 package com.netscape.cms.servlet.csadmin;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
+
 import org.mozilla.jss.crypto.X509Certificate;
 import org.mozilla.jss.ssl.SSLCertificateApprovalCallback;
 
+import com.netscape.certsrv.apps.CMS;
+
 public class ConfigCertApprovalCallback
         implements SSLCertificateApprovalCallback {
 
+    public Set<Integer> ignoredErrors = new HashSet<Integer>();
+
     public ConfigCertApprovalCallback() {
     }
 
+    public void ignoreError(int error) {
+        ignoredErrors.add(error);
+    }
+
+    public String getErrorDescription(int reason) {
+
+        // iterate through all constants in ValidityStatus
+        for (Field f : ValidityStatus.class.getDeclaredFields()) {
+            int mod = f.getModifiers();
+            if (Modifier.isPublic(mod) &&
+                Modifier.isFinal(mod) &&
+                Modifier.isStatic(mod)) {
+
+                try {
+                    int value = f.getInt(null);
+
+                    // if value matches the reason, return the name
+                    if (value == reason) {
+                        return f.getName();
+                    }
+
+                } catch (IllegalAccessException e) {
+                    return "ERROR #" + reason;
+                }
+            }
+        }
+
+        return "UNKNOWN_ERROR";
+    }
+
     public boolean approve(X509Certificate cert,
             SSLCertificateApprovalCallback.ValidityStatus status) {
-        return true;
+
+        CMS.debug("Server certificate:");
+        CMS.debug(" - subject: " + cert.getSubjectDN());
+        CMS.debug(" - issuer: " + cert.getIssuerDN());
+
+        Enumeration<?> errors = status.getReasons();
+        boolean result = true;
+
+        while (errors.hasMoreElements()) {
+            SSLCertificateApprovalCallback.ValidityItem item = (SSLCertificateApprovalCallback.ValidityItem) errors.nextElement();
+            int reason = item.getReason();
+            String description = getErrorDescription(reason);
+
+            if (ignoredErrors.contains(reason)) {
+                CMS.debug("WARNING: " + description);
+            } else {
+                CMS.debug("ERROR: " + description);
+                result = false;
+            }
+        }
+
+        return result;
     }
 }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
index ab5e4d63da1d91718ed3795c5fa144d18b5f5a99..fe65bb855a24702c2248d03059716d4246d70d0a 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
@@ -58,34 +58,6 @@ import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.xml.parsers.ParserConfigurationException;
 
-import netscape.ldap.LDAPAttribute;
-import netscape.ldap.LDAPAttributeSet;
-import netscape.ldap.LDAPConnection;
-import netscape.ldap.LDAPDN;
-import netscape.ldap.LDAPEntry;
-import netscape.ldap.LDAPException;
-import netscape.ldap.LDAPModification;
-import netscape.ldap.LDAPSearchConstraints;
-import netscape.ldap.LDAPSearchResults;
-import netscape.ldap.LDAPv3;
-import netscape.security.pkcs.ContentInfo;
-import netscape.security.pkcs.PKCS10;
-import netscape.security.pkcs.PKCS12;
-import netscape.security.pkcs.PKCS12Util;
-import netscape.security.pkcs.PKCS7;
-import netscape.security.pkcs.SignerInfo;
-import netscape.security.util.DerOutputStream;
-import netscape.security.util.ObjectIdentifier;
-import netscape.security.x509.AlgorithmId;
-import netscape.security.x509.BasicConstraintsExtension;
-import netscape.security.x509.CertificateChain;
-import netscape.security.x509.Extension;
-import netscape.security.x509.Extensions;
-import netscape.security.x509.KeyUsageExtension;
-import netscape.security.x509.X500Name;
-import netscape.security.x509.X509CertImpl;
-import netscape.security.x509.X509Key;
-
 import org.apache.commons.lang.StringUtils;
 import org.apache.velocity.context.Context;
 import org.mozilla.jss.CryptoManager;
@@ -131,6 +103,7 @@ import org.mozilla.jss.pkix.primitive.Attribute;
 import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo;
 import org.mozilla.jss.pkix.primitive.PrivateKeyInfo;
 import org.mozilla.jss.ssl.SSLCertificateApprovalCallback;
+import org.mozilla.jss.ssl.SSLCertificateApprovalCallback.ValidityStatus;
 import org.mozilla.jss.util.IncorrectPasswordException;
 import org.mozilla.jss.util.Password;
 import org.w3c.dom.Document;
@@ -180,6 +153,34 @@ import com.netscape.cmsutil.ldap.LDAPUtil;
 import com.netscape.cmsutil.util.Utils;
 import com.netscape.cmsutil.xml.XMLObject;
 
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPDN;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+import netscape.ldap.LDAPSearchConstraints;
+import netscape.ldap.LDAPSearchResults;
+import netscape.ldap.LDAPv3;
+import netscape.security.pkcs.ContentInfo;
+import netscape.security.pkcs.PKCS10;
+import netscape.security.pkcs.PKCS12;
+import netscape.security.pkcs.PKCS12Util;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.pkcs.SignerInfo;
+import netscape.security.util.DerOutputStream;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.Extension;
+import netscape.security.x509.Extensions;
+import netscape.security.x509.KeyUsageExtension;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509Key;
+
 /**
  * Utility class for functions to be used by the RESTful installer.
  *
@@ -196,6 +197,8 @@ public class ConfigurationUtils {
     public static final Long MINUS_ONE = Long.valueOf(-1);
     public static final String DBUSER = "pkidbuser";
 
+    public static ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback();
+
     public static boolean loginToken(CryptoToken token, String tokPwd) throws TokenException,
             IncorrectPasswordException {
         boolean rv = true;
@@ -229,6 +232,7 @@ public class ConfigurationUtils {
 
         CMS.debug("ConfigurationUtils: GET " + config.getServerURI() + path);
         PKIConnection connection = new PKIConnection(config);
+        if (certApprovalCallback == null) certApprovalCallback = ConfigurationUtils.certApprovalCallback;
         connection.setCallback(certApprovalCallback);
         return connection.get(path);
     }
@@ -245,6 +249,7 @@ public class ConfigurationUtils {
 
         CMS.debug("ConfigurationUtils: POST " + config.getServerURI() + path);
         PKIConnection connection = new PKIConnection(config);
+        if (certApprovalCallback == null) certApprovalCallback = ConfigurationUtils.certApprovalCallback;
         connection.setCallback(certApprovalCallback);
         return connection.post(path, content);
     }
@@ -256,6 +261,8 @@ public class ConfigurationUtils {
 
         IConfigStore cs = CMS.getConfigStore();
         ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback();
+        // Ignore untrusted issuer to get cert chain.
+        certApprovalCallback.ignoreError(ValidityStatus.UNTRUSTED_ISSUER);
         String c = get(host, port, true, serverPath, null, certApprovalCallback);
 
         if (c != null) {
-- 
2.5.5

>From 9fafe7149736be6d998e165f1d819587ee9f1d38 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata redhat com>
Date: Mon, 1 Aug 2016 22:35:32 +0200
Subject: [PATCH] Added log messages for certificate import during cloning.

To help troubleshooting cloning issues the security_databases.py
has been modified to log the content of the PKCS #12 file before
import and the NSS database after import.

https://fedorahosted.org/pki/ticket/2424
---
 .../deployment/scriptlets/security_databases.py    | 42 ++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/base/server/python/pki/server/deployment/scriptlets/security_databases.py b/base/server/python/pki/server/deployment/scriptlets/security_databases.py
index 18fc3e1efb9ebf64308f7fdf7f647c9ac973ba35..75b50e9260b2005fd3eb40b344465a9c963f8ae2 100644
--- a/base/server/python/pki/server/deployment/scriptlets/security_databases.py
+++ b/base/server/python/pki/server/deployment/scriptlets/security_databases.py
@@ -19,8 +19,12 @@
 #
 
 from __future__ import absolute_import
+from __future__ import print_function
 
 import os
+import shutil
+import subprocess
+import tempfile
 import pki.nssdb
 import pki.server
 
@@ -123,6 +127,34 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
             if not pki_clone_pkcs12_password:
                 raise Exception('Missing pki_clone_pkcs12_password property.')
 
+            print('Importing certificates from %s:' % pki_clone_pkcs12_path)
+
+            tmpdir = tempfile.mkdtemp()
+
+            try:
+                if pki_clone_pkcs12_password:
+                    pki_clone_pkcs12_password_file = os.path.join(tmpdir, 'password.txt')
+                    with open(pki_clone_pkcs12_password_file, 'w') as f:
+                        f.write(pki_clone_pkcs12_password)
+
+                cmd = [
+                    'pki',
+                    '-d', deployer.mdict['pki_database_path'],
+                    '-C', deployer.mdict['pki_shared_pfile']
+                ]
+
+                cmd.extend([
+                    'pkcs12-cert-find',
+                    '--pkcs12-file', pki_clone_pkcs12_path,
+                    '--pkcs12-password', pki_clone_pkcs12_password
+                ])
+
+                subprocess.check_call(cmd)
+
+            finally:
+                shutil.rmtree(tmpdir)
+
+            # Import certificates
             nssdb = pki.nssdb.NSSDatabase(
                 directory=deployer.mdict['pki_database_path'],
                 password_file=deployer.mdict['pki_shared_pfile'])
@@ -132,6 +164,16 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
                 pkcs12_password=pki_clone_pkcs12_password,
                 no_user_certs=True)
 
+            print('Imported certificates in %s:' % deployer.mdict['pki_database_path'])
+
+            cmd = [
+                'certutil',
+                '-L',
+                '-d', deployer.mdict['pki_database_path']
+            ]
+
+            subprocess.check_call(cmd)
+
         if len(deployer.instance.tomcat_instance_subsystems()) < 2:
 
             # Check to see if a secure connection is being used for the DS
-- 
2.5.5

>From 2cae54b97c1a315fd9c898e6ed06a45f430d980f Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata redhat com>
Date: Mon, 1 Aug 2016 22:35:32 +0200
Subject: [PATCH] Fixed PKCS #12 import for cloning.

To fix cloning issue in IPA the security_database.py has been
modified to import all certificates and keys in the PKCS #12 file
before the PKI server is started. Since the PKCS #12 generated by
IPA may not contain the certificate trust flags, the script will
also reset the trust flags on the imported certificates (i.e.
CT,C,C for CA certificate and u,u,Pu for audit certificate).

The ConfigurationUtils.restoreCertsFromP12() is now redundant and
it should be removed in the future, but for now it has been
modified to set the same trust flags on imported certificates.

The CryptoUtil.importCertificateChain() has also been modified to
set the same trust flags on imported certificates.

https://fedorahosted.org/pki/ticket/2424
---
 .../cms/servlet/csadmin/ConfigurationUtils.java    |  9 +++-
 .../deployment/scriptlets/security_databases.py    | 13 ++++-
 .../com/netscape/cmsutil/crypto/CryptoUtil.java    | 60 ++++++++++++----------
 3 files changed, 51 insertions(+), 31 deletions(-)

diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
index fe65bb855a24702c2248d03059716d4246d70d0a..905a5bb662be23297a2e24125421cb1a11064a3d 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
@@ -834,7 +834,8 @@ public class ConfigurationUtils {
             BadPaddingException, NotInitializedException, NicknameConflictException, UserCertConflictException,
             NoSuchItemOnTokenException, InvalidBERException, IOException {
 
-        // TODO: refactor into a PKCS #12 utility class
+        // TODO: The PKCS #12 file is already imported in security_database.py.
+        // This method should be removed.
 
         byte b[] = new byte[1000000];
         FileInputStream fis = new FileInputStream(p12File);
@@ -1109,10 +1110,14 @@ public class ConfigurationUtils {
                 InternalCertificate icert = (InternalCertificate) xcert;
 
                 if (isCASigningCert) {
-                    // we need to change the trust attribute to CT
+                    // set trust flags to CT,C,C
                     icert.setSSLTrust(InternalCertificate.TRUSTED_CA
                             | InternalCertificate.TRUSTED_CLIENT_CA
                             | InternalCertificate.VALID_CA);
+                    icert.setEmailTrust(InternalCertificate.TRUSTED_CA
+                            | InternalCertificate.VALID_CA);
+                    icert.setObjectSigningTrust(InternalCertificate.TRUSTED_CA
+                            | InternalCertificate.VALID_CA);
 
                 } else if (isAuditSigningCert(name)) {
                     icert.setObjectSigningTrust(InternalCertificate.USER
diff --git a/base/server/python/pki/server/deployment/scriptlets/security_databases.py b/base/server/python/pki/server/deployment/scriptlets/security_databases.py
index 75b50e9260b2005fd3eb40b344465a9c963f8ae2..1a90a32e7ec02d8d0af435596f84f35653396975 100644
--- a/base/server/python/pki/server/deployment/scriptlets/security_databases.py
+++ b/base/server/python/pki/server/deployment/scriptlets/security_databases.py
@@ -161,8 +161,17 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
 
             nssdb.import_pkcs12(
                 pkcs12_file=pki_clone_pkcs12_path,
-                pkcs12_password=pki_clone_pkcs12_password,
-                no_user_certs=True)
+                pkcs12_password=pki_clone_pkcs12_password)
+
+            # Set certificate trust flags
+            if subsystem.type == 'CA':
+                nssdb.modify_cert(
+                    nickname=deployer.mdict['pki_ca_signing_nickname'],
+                    trust_attributes='CTu,Cu,Cu')
+
+            nssdb.modify_cert(
+                nickname=deployer.mdict['pki_audit_signing_nickname'],
+                trust_attributes='u,u,Pu')
 
             print('Imported certificates in %s:' % deployer.mdict['pki_database_path'])
 
diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
index 9cabdc5cc459afc0ab2b60450d29fa14e384f58d..b02c363e2af150cb4c74d394dd00d6d8650b0c58 100644
--- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
+++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
@@ -47,33 +47,6 @@ import java.util.Random;
 import java.util.StringTokenizer;
 import java.util.Vector;
 
-import netscape.security.pkcs.PKCS10;
-import netscape.security.pkcs.PKCS10Attribute;
-import netscape.security.pkcs.PKCS10Attributes;
-import netscape.security.pkcs.PKCS7;
-import netscape.security.pkcs.PKCS9Attribute;
-import netscape.security.util.BigInt;
-import netscape.security.util.DerInputStream;
-import netscape.security.util.DerOutputStream;
-import netscape.security.util.DerValue;
-import netscape.security.util.ObjectIdentifier;
-import netscape.security.x509.AlgorithmId;
-import netscape.security.x509.CertificateAlgorithmId;
-import netscape.security.x509.CertificateChain;
-import netscape.security.x509.CertificateExtensions;
-import netscape.security.x509.CertificateIssuerName;
-import netscape.security.x509.CertificateSerialNumber;
-import netscape.security.x509.CertificateSubjectName;
-import netscape.security.x509.CertificateValidity;
-import netscape.security.x509.CertificateVersion;
-import netscape.security.x509.CertificateX509Key;
-import netscape.security.x509.Extensions;
-import netscape.security.x509.X500Name;
-import netscape.security.x509.X500Signer;
-import netscape.security.x509.X509CertImpl;
-import netscape.security.x509.X509CertInfo;
-import netscape.security.x509.X509Key;
-
 import org.mozilla.jss.CryptoManager;
 import org.mozilla.jss.CryptoManager.NotInitializedException;
 import org.mozilla.jss.NoSuchTokenException;
@@ -132,6 +105,33 @@ import org.mozilla.jss.util.Password;
 import com.netscape.cmsutil.util.Cert;
 import com.netscape.cmsutil.util.Utils;
 
+import netscape.security.pkcs.PKCS10;
+import netscape.security.pkcs.PKCS10Attribute;
+import netscape.security.pkcs.PKCS10Attributes;
+import netscape.security.pkcs.PKCS7;
+import netscape.security.pkcs.PKCS9Attribute;
+import netscape.security.util.BigInt;
+import netscape.security.util.DerInputStream;
+import netscape.security.util.DerOutputStream;
+import netscape.security.util.DerValue;
+import netscape.security.util.ObjectIdentifier;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.CertificateChain;
+import netscape.security.x509.CertificateExtensions;
+import netscape.security.x509.CertificateIssuerName;
+import netscape.security.x509.CertificateSerialNumber;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.CertificateVersion;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.Extensions;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X500Signer;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
 @SuppressWarnings("serial")
 public class CryptoUtil {
 
@@ -1164,10 +1164,16 @@ public class CryptoUtil {
         if (certchains != null) {
             cert = certchains[certchains.length - 1];
         }
+
+        // set trust flags to CT,C,C
         InternalCertificate icert = (InternalCertificate) cert;
         icert.setSSLTrust(InternalCertificate.TRUSTED_CA
                                     | InternalCertificate.TRUSTED_CLIENT_CA
                                     | InternalCertificate.VALID_CA);
+        icert.setEmailTrust(InternalCertificate.TRUSTED_CA
+                | InternalCertificate.VALID_CA);
+        icert.setObjectSigningTrust(InternalCertificate.TRUSTED_CA
+                | InternalCertificate.VALID_CA);
     }
 
     public static SEQUENCE parseCRMFMsgs(byte cert_request[])
-- 
2.5.5


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]