[Pki-devel] [PATCH] 0052 Lightweight CAs: enrol cert via profile subsystem

Fraser Tweedale ftweedal at redhat.com
Thu Oct 8 06:44:53 UTC 2015


The attached patch fixes:

- #1624 generate lightweight CAs via profile subsystem
- #1632 ensure CA certs bear correct Authority Key Identifier

Thanks,
Fraser
-------------- next part --------------
From 3b21cc55ff915aa91f1af56fe27bdca0ffd4bb05 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal at redhat.com>
Date: Thu, 8 Oct 2015 01:09:22 -0400
Subject: [PATCH] Lightweight CAs: enrol cert via profile subsystem

Enrol new CA certs via the profile subsystem to ensure that the
usual audit events are logged and to avoid the nasty ConfigStore
hack used to generate the cert via CertUtil.

This commit also fixes an issue where the new CA certificate does
not have the correct Authority Key Identifier extension.

Fixes: https://fedorahosted.org/pki/ticket/1624
Fixes: https://fedorahosted.org/pki/ticket/1632
---
 .../src/com/netscape/ca/CertificateAuthority.java  | 66 ++++++++++++++++++----
 .../dogtagpki/server/ca/rest/AuthorityService.java |  5 ++
 .../netscape/certsrv/ca/ICertificateAuthority.java |  3 +
 .../servlet/cert/CertEnrollmentRequestFactory.java | 15 +++--
 .../cms/servlet/cert/EnrollmentProcessor.java      | 15 ++++-
 5 files changed, 88 insertions(+), 16 deletions(-)

diff --git a/base/ca/src/com/netscape/ca/CertificateAuthority.java b/base/ca/src/com/netscape/ca/CertificateAuthority.java
index 449da301f71338402ae070a3247b8e7d2c78b05c..ea4515c353e4bf3d18acc54a3729b9d98fe064ed 100644
--- a/base/ca/src/com/netscape/ca/CertificateAuthority.java
+++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java
@@ -18,15 +18,18 @@
 package com.netscape.ca;
 
 import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.PrintStream;
 import java.math.BigInteger;
 import java.security.KeyPair;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
+import java.security.Signature;
 import java.security.cert.CRLException;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateParsingException;
@@ -36,6 +39,7 @@ import java.util.Date;
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.TreeMap;
 import java.util.Vector;
@@ -51,6 +55,7 @@ import netscape.ldap.LDAPException;
 import netscape.ldap.LDAPModification;
 import netscape.ldap.LDAPModificationSet;
 import netscape.ldap.LDAPSearchResults;
+import netscape.security.pkcs.PKCS10;
 import netscape.security.util.DerOutputStream;
 import netscape.security.util.DerValue;
 import netscape.security.x509.AlgorithmId;
@@ -59,6 +64,7 @@ import netscape.security.x509.CertificateIssuerName;
 import netscape.security.x509.CertificateSubjectName;
 import netscape.security.x509.CertificateVersion;
 import netscape.security.x509.X500Name;
+import netscape.security.x509.X500Signer;
 import netscape.security.x509.X509CRLImpl;
 import netscape.security.x509.X509CertImpl;
 import netscape.security.x509.X509CertInfo;
@@ -83,6 +89,7 @@ import org.mozilla.jss.pkix.cert.Extension;
 import org.mozilla.jss.pkix.primitive.Name;
 
 import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.authority.ICertAuthority;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.EPropertyNotFound;
@@ -100,6 +107,7 @@ import com.netscape.certsrv.ca.ECAException;
 import com.netscape.certsrv.ca.ICRLIssuingPoint;
 import com.netscape.certsrv.ca.ICertificateAuthority;
 import com.netscape.certsrv.ca.IssuerUnavailableException;
+import com.netscape.certsrv.cert.CertEnrollmentRequest;
 import com.netscape.certsrv.dbs.IDBSubsystem;
 import com.netscape.certsrv.dbs.certdb.ICertRecord;
 import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
@@ -110,19 +118,26 @@ import com.netscape.certsrv.ldap.ILdapConnFactory;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.ocsp.IOCSPService;
 import com.netscape.certsrv.policy.IPolicyProcessor;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfileSubsystem;
+import com.netscape.certsrv.profile.IProfile;
 import com.netscape.certsrv.publish.ICRLPublisher;
 import com.netscape.certsrv.publish.IPublisherProcessor;
 import com.netscape.certsrv.request.ARequestNotifier;
 import com.netscape.certsrv.request.IPolicy;
+import com.netscape.certsrv.request.IRequest;
 import com.netscape.certsrv.request.IRequestListener;
 import com.netscape.certsrv.request.IRequestNotifier;
 import com.netscape.certsrv.request.IRequestQueue;
 import com.netscape.certsrv.request.IRequestScheduler;
 import com.netscape.certsrv.request.IService;
+import com.netscape.certsrv.request.RequestStatus;
 import com.netscape.certsrv.security.ISigningUnit;
 import com.netscape.certsrv.util.IStatsSubsystem;
-import com.netscape.cms.servlet.csadmin.CertUtil;
-import com.netscape.cmscore.base.PropConfigStore;
+import com.netscape.cms.servlet.cert.EnrollmentProcessor;
+import com.netscape.cms.servlet.cert.CertEnrollmentRequestFactory;
+import com.netscape.cms.servlet.processors.CAProcessor;
+import com.netscape.cmscore.base.ArgBlock;
 import com.netscape.cmscore.dbs.CRLRepository;
 import com.netscape.cmscore.dbs.CertRecord;
 import com.netscape.cmscore.dbs.CertificateRepository;
@@ -2376,6 +2391,7 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
      * @param description Optional string description of CA
      */
     public ICertificateAuthority createCA(
+            IAuthToken authToken,
             String subjectDN, AuthorityID parentAID,
             String description)
             throws EBaseException {
@@ -2385,7 +2401,7 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
                 "Parent CA \"" + parentAID + "\" does not exist");
 
         ICertificateAuthority ca = parentCA.createSubCA(
-                subjectDN, description);
+                authToken, subjectDN, description);
         caMap.put(ca.getAuthorityID(), ca);
         return ca;
     }
@@ -2406,6 +2422,7 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
      * caller's responsibility.
      */
     public ICertificateAuthority createSubCA(
+            IAuthToken authToken,
             String subjectDN, String description)
             throws EBaseException {
 
@@ -2473,20 +2490,49 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
                 PublicKey pub = keypair.getPublic();
                 X509Key x509key = CryptoUtil.convertPublicKeyToX509Key(pub);
 
+                // Create pkcs10 request
+                CMS.debug("createSubCA: creating pkcs10 request");
+                PKCS10 pkcs10 = new PKCS10(x509key);
+                Signature signature = Signature.getInstance("SHA256withRSA");
+                signature.initSign(keypair.getPrivate());
+                pkcs10.encodeAndSign(
+                    new X500Signer(signature, subjectX500Name));
+                ByteArrayOutputStream out = new ByteArrayOutputStream();
+                pkcs10.print(new PrintStream(out));
+                String pkcs10String = out.toString();
+
                 // Sign certificate
-                String algName = mSigningUnit.getDefaultAlgorithm();
-                IConfigStore cs = new PropConfigStore("cs");
-                cs.put(".profile", "caCert.profile");
-                cs.put(".dn", subjectDN);
-                cs.put(".keyalgorithm", algName);
-                X509CertImpl cert =
-                    CertUtil.createLocalCertWithCA(cs, x509key, "", "", "local", this);
+                Locale locale = Locale.getDefault();
+                String profileId = "caCACert";
+                IProfileSubsystem ps = (IProfileSubsystem)
+                    CMS.getSubsystem(IProfileSubsystem.ID);
+                IProfile profile = ps.getProfile(profileId);
+                ArgBlock argBlock = new ArgBlock();
+                argBlock.set("cert_request_type", "pkcs10");
+                argBlock.set("cert_request", pkcs10String);
+                CertEnrollmentRequest certRequest =
+                    CertEnrollmentRequestFactory.create(argBlock, profile, locale);
+                EnrollmentProcessor processor =
+                    new EnrollmentProcessor("createSubCA", locale);
+                Map<String, Object> resultMap = processor.processEnrollment(
+                    certRequest, null, authorityID, null, authToken);
+                IRequest requests[] = (IRequest[]) resultMap.get(CAProcessor.ARG_REQUESTS);
+                IRequest request = requests[0];
+                Integer result = request.getExtDataInInteger(IRequest.RESULT);
+                if (result != null && !result.equals(IRequest.RES_SUCCESS))
+                    throw new EBaseException("createSubCA: certificate request submission resulted in error: " + result);
+                RequestStatus requestStatus = request.getRequestStatus();
+                if (requestStatus != RequestStatus.COMPLETE)
+                    throw new EBaseException("createSubCA: certificate request did not complete; status: " + requestStatus);
 
                 // Add certificate to nssdb
+                X509CertImpl cert = request.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
                 cryptoManager.importCertPackage(cert.getEncoded(), nickname);
             } catch (Exception e) {
                 // something went wrong; delete just-added entry
                 conn.delete(dn);
+                CMS.debug("Error creating lightweight CA certificate");
+                CMS.debug(e);
                 throw new ECAException("Error creating lightweight CA certificate: " + e);
             }
         } catch (LDAPException e) {
diff --git a/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java b/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java
index b23a4b853252dd4e5dadef3b3ef508113e1d5337..3504b005b480b597fb0a2246a43bd848e7d6afa0 100644
--- a/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java
+++ b/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java
@@ -48,6 +48,7 @@ import com.netscape.certsrv.ca.CANotLeafException;
 import com.netscape.certsrv.ca.CATypeException;
 import com.netscape.certsrv.ca.ICertificateAuthority;
 import com.netscape.certsrv.ca.IssuerUnavailableException;
+import com.netscape.cms.realm.PKIPrincipal;
 import com.netscape.cms.servlet.base.PKIService;
 import com.netscape.cmsutil.util.Utils;
 
@@ -178,8 +179,12 @@ public class AuthorityService extends PKIService implements AuthorityResource {
             throw new BadRequestException("Bad Authority ID: " + parentAIDString);
         }
 
+        PKIPrincipal principal =
+            (PKIPrincipal) servletRequest.getUserPrincipal();
+
         try {
             ICertificateAuthority subCA = hostCA.createCA(
+                principal.getAuthToken(),
                 data.getDN(), parentAID, data.getDescription());
             return createOKResponse(readAuthorityData(subCA));
         } catch (IllegalArgumentException e) {
diff --git a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
index 96bc392294f27d57d9795c2b1b793b8cbc001fda..376654e98b0276a2c2add8b98fb30bf339165b87 100644
--- a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
+++ b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
@@ -34,6 +34,7 @@ import netscape.security.x509.X509CertInfo;
 
 import org.mozilla.jss.crypto.SignatureAlgorithm;
 
+import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.IConfigStore;
 import com.netscape.certsrv.base.ISubsystem;
@@ -562,6 +563,7 @@ public interface ICertificateAuthority extends ISubsystem {
      * Create a new sub-CA under the specified parent CA.
      */
     public ICertificateAuthority createCA(
+            IAuthToken authToken,
             String dn, AuthorityID parentAID, String desc)
         throws EBaseException;
 
@@ -572,6 +574,7 @@ public interface ICertificateAuthority extends ISubsystem {
      * caller's responsibility.
      */
     public ICertificateAuthority createSubCA(
+            IAuthToken authToken,
             String dn, String desc)
         throws EBaseException;
 
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CertEnrollmentRequestFactory.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CertEnrollmentRequestFactory.java
index d74a285f391ecf4fdbafe219d02f20e86ccf1848..2b608259fbe4994e4e3eb42604756b6814027f9b 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/CertEnrollmentRequestFactory.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CertEnrollmentRequestFactory.java
@@ -37,6 +37,17 @@ public class CertEnrollmentRequestFactory {
             throws EProfileException {
         IArgBlock params = cmsReq.getHttpParams();
 
+        CertEnrollmentRequest request = create(params, profile, locale);
+
+        HttpServletRequest httpRequest = cmsReq.getHttpReq();
+        request.setRemoteHost(httpRequest.getRemoteHost());
+        request.setRemoteAddr(httpRequest.getRemoteAddr());
+
+        return request;
+    }
+
+    public static CertEnrollmentRequest create(IArgBlock params, IProfile profile, Locale locale)
+            throws EProfileException {
         CertEnrollmentRequest request = new CertEnrollmentRequest();
         request.setProfileId(profile.getId());
 
@@ -48,10 +59,6 @@ public class CertEnrollmentRequestFactory {
             request.addInput(addInput);
         }
 
-        HttpServletRequest httpRequest = cmsReq.getHttpReq();
-        request.setRemoteHost(httpRequest.getRemoteHost());
-        request.setRemoteAddr(httpRequest.getRemoteAddr());
-
         return request;
     }
 
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
index dadd34cfe8b74ebbefa1af2d2141d5baee04755e..3e92d5948a236fd153414d5faa556b2f805a99b5 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
@@ -83,6 +83,15 @@ public class EnrollmentProcessor extends CertProcessor {
 
     }
 
+    public HashMap<String, Object> processEnrollment(
+            CertEnrollmentRequest data,
+            HttpServletRequest request,
+            AuthorityID aid,
+            AuthCredentials credentials)
+            throws EBaseException {
+        return processEnrollment(data, request, aid, credentials, null);
+    }
+
     /**
      * Process the HTTP request
      * <P>
@@ -104,7 +113,8 @@ public class EnrollmentProcessor extends CertProcessor {
             CertEnrollmentRequest data,
             HttpServletRequest request,
             AuthorityID aid,
-            AuthCredentials credentials)
+            AuthCredentials credentials,
+            IAuthToken authToken)
         throws EBaseException {
 
         try {
@@ -153,7 +163,8 @@ public class EnrollmentProcessor extends CertProcessor {
             CMS.debug("EnrollmentProcessor: set sslClientCertProvider");
 
             // before creating the request, authenticate the request
-            IAuthToken authToken = authenticate(request, null, authenticator, context, false, credentials);
+            if (authToken == null)
+                authToken = authenticate(request, null, authenticator, context, false, credentials);
 
             // authentication success, now authorize
             authorize(profileId, profile, authToken);
-- 
2.4.3



More information about the Pki-devel mailing list