From ee33bb2a90a183b9d5552c6ac193e9d8958a3974 Mon Sep 17 00:00:00 2001 From: Christina Fu Date: Thu, 25 Sep 2014 09:03:58 -0700 Subject: ticket #1110 pkispawn (configuration) does not provide CA extensions in subordinate certificate signing requests (CSR) --- .../cms/servlet/csadmin/ConfigurationUtils.java | 78 +++++++++++++++++++++- .../dogtagpki/server/rest/SystemConfigService.java | 9 +++ base/server/etc/default.cfg | 5 ++ .../python/pki/server/deployment/pkihelper.py | 25 +++++++ .../python/pki/server/deployment/pkiparser.py | 3 + 5 files changed, 119 insertions(+), 1 deletion(-) (limited to 'base/server') 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 06728e24b..f44323896 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 @@ -74,8 +74,14 @@ import netscape.security.pkcs.ContentInfo; import netscape.security.pkcs.PKCS10; 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; @@ -2680,9 +2686,11 @@ public class ConfigurationUtils { EBaseException, InvalidKeyException, NotInitializedException, TokenException, NoSuchAlgorithmException, NoSuchProviderException, CertificateException, SignatureException, IOException { + CMS.debug("ConfigurationUtils: handleCertRequest() begins"); // get public key String pubKeyType = config.getString(PCERT_PREFIX + certTag + ".keytype"); String algorithm = config.getString(PCERT_PREFIX + certTag + ".keyalgorithm"); + X509Key pubk = null; if (pubKeyType.equals("rsa")) { pubk = getRSAX509Key(config, certTag); @@ -2713,7 +2721,13 @@ public class ConfigurationUtils { String caDN = config.getString(PCERT_PREFIX + certTag + ".dn"); cert.setDN(caDN); - PKCS10 certReq = CryptoUtil.createCertificationRequest(caDN, pubk, privk, algorithm); + + Extensions exts = null; + if (certTag.equals("signing")) { + CMS.debug("handleCertRequest: certTag is siging -- about to call createBasicCAExtensions()"); + exts = createBasicCAExtensions(config); + } + PKCS10 certReq = CryptoUtil.createCertificationRequest(caDN, pubk, privk, algorithm, exts); CMS.debug("handleCertRequest: created cert request"); byte[] certReqb = certReq.toByteArray(); @@ -2727,6 +2741,68 @@ public class ConfigurationUtils { } + /* + * createBasicCAExtensions creates the basic Extensions needed for a CSR to a + * CA signing certificate + */ + private static Extensions createBasicCAExtensions(IConfigStore config) throws IOException { + Extensions exts = new Extensions(); + CMS.debug("ConfigurationUtils: createBasicCAExtensions: begins"); + + // create BasicConstraintsExtension + BasicConstraintsExtension bcExt = new BasicConstraintsExtension(true, -1); + exts.add(bcExt); + + // create KeyUsageExtension + boolean[] kuBits = new boolean[KeyUsageExtension.NBITS]; + for (int i = 0; i < kuBits.length; i++) { + kuBits[i] = false; + } + kuBits[KeyUsageExtension.DIGITAL_SIGNATURE_BIT] = true; + kuBits[KeyUsageExtension.NON_REPUDIATION_BIT] = true; + kuBits[KeyUsageExtension.KEY_CERTSIGN_BIT] = true; + kuBits[KeyUsageExtension.CRL_SIGN_BIT] = true; + KeyUsageExtension kuExt = new KeyUsageExtension(true, kuBits); + exts.add(kuExt); + + /* save this for later when we want to allow more selection for pkispawn configuration + // create NSCertTypeExtension + boolean[] nsBits = new boolean[NSCertTypeExtension.NBITS]; + for (int i = 0; i < nsBits.length; i++) { + nsBits[i] = false; + } + nsBits[NSCertTypeExtension.SSL_CA_BIT] = true; + NSCertTypeExtension nsctExt = new NSCertTypeExtension(false, nsBits); + exts.add(nsctExt); + */ + + // add a generic extension + Extension genExt = null; + try { + String oidString = config.getString(PCERT_PREFIX + "signing.ext.oid"); + String dataString = config.getString(PCERT_PREFIX + "signing.ext.data"); + boolean critical = false; + if (oidString != null && dataString != null) { + CMS.debug("ConfigurationUtils: createBasicCAExtensions: processing generic extension"); + critical = config.getBoolean("preop.cert.signing.ext.critical"); + ObjectIdentifier oid = new ObjectIdentifier(oidString); + + byte data[] = CryptoUtil.hexString2Bytes(dataString); + DerOutputStream out = new DerOutputStream(); + out.putOctetString(data); + genExt = new Extension(oid, critical, out.toByteArray()); + out.close(); + + exts.add(genExt); + CMS.debug("ConfigurationUtils: createBasicCAExtensions: generic extension added: " + oidString); + } + } catch (EBaseException e) { + CMS.debug("ConfigurationUtils: createBasicCAExtensions: generic extension not processed:" + e); + } + + return exts; + } + public static X509Key getECCX509Key(IConfigStore config, String certTag) throws EPropertyNotFound, EBaseException, InvalidKeyException { X509Key pubk = null; diff --git a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java index 96a6cf0bf..fa762774a 100644 --- a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java +++ b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java @@ -309,6 +309,14 @@ public class SystemConfigService extends PKIService implements SystemConfigResou if (systemCert.getTag().equals(tag)) { certData = systemCert; CMS.debug("Found data for '" + tag + "'"); + if (tag.equals("signing") && + certData.getReqExtOID() != null && + certData.getReqExtData() != null) { + CMS.debug("SystemConfigService:processCerts: adding request extension to config"); + cs.putString("preop.cert.signing.ext.oid", certData.getReqExtOID()); + cs.putString("preop.cert.signing.ext.data", certData.getReqExtData()); + cs.putBoolean("preop.cert.signing.ext.critical", certData.getReqExtCritical()); + } break; } } @@ -382,6 +390,7 @@ public class SystemConfigService extends PKIService implements SystemConfigResou cs.putString("preop.cert." + tag + ".signingalgorithm", signingalgorithm); cs.putString("preop.cert." + tag + ".nickname", nickname); cs.putString("preop.cert." + tag + ".dn", dn); + cs.commit(false); if (!request.getStepTwo()) { if (keytype.equals("ecc")) { diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg index 9047e6e7c..686cc59f9 100644 --- a/base/server/etc/default.cfg +++ b/base/server/etc/default.cfg @@ -347,6 +347,11 @@ pki_ca_signing_signing_algorithm=SHA256withRSA pki_ca_signing_subject_dn=cn=CA Signing Certificate,o=%(pki_security_domain_name)s pki_ca_signing_token=Internal Key Storage Token pki_external=False +pki_req_ext_add=False +# MS subca request ext data +pki_req_ext_oid=1.3.6.1.4.1.311.20.2 +pki_req_ext_critical=False +pki_req_ext_data=1E0A00530075006200430041 pki_external_csr_path=%(pki_instance_configuration_path)s/ca_signing.csr pki_external_step_two=False pki_external_ca_cert_chain_path=%(pki_instance_configuration_path)s/external_ca_chain.cert diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py index a35b8f347..b4c728a87 100644 --- a/base/server/python/pki/server/deployment/pkihelper.py +++ b/base/server/python/pki/server/deployment/pkihelper.py @@ -447,7 +447,16 @@ class ConfigurationFile: self.mdict = deployer.mdict # set useful 'boolean' object variables for this class self.clone = config.str2bool(self.mdict['pki_clone']) + # generic extension support in CSR - for external CA + self.add_req_ext = config.str2bool( + self.mdict['pki_req_ext_add']) self.external = config.str2bool(self.mdict['pki_external']) + if self.external: + # generic extension support in CSR - for external CA + if self.add_req_ext: + self.req_ext_oid = self.mdict['pki_req_ext_oid'] + self.req_ext_critical = self.mdict['pki_req_ext_critical'] + self.req_ext_data = self.mdict['pki_req_ext_data'] self.external_step_two = config.str2bool( self.mdict['pki_external_step_two']) self.skip_configuration = config.str2bool( @@ -660,6 +669,11 @@ class ConfigurationFile: # External CA (Step 1) self.confirm_data_exists("pki_external_csr_path") self.confirm_missing_file("pki_external_csr_path") + # generic extension support in CSR - for external CA + if self.add_req_ext: + self.confirm_data_exists("pki_req_ext_oid") + self.confirm_data_exists("pki_req_ext_critical") + self.confirm_data_exists("pki_req_ext_data") else: # External CA (Step 2) self.confirm_data_exists("pki_external_ca_cert_chain_path") @@ -3397,6 +3411,9 @@ class ConfigClient: self.subordinate = config.str2bool(self.mdict['pki_subordinate']) # set useful 'string' object variables for this class self.subsystem = self.mdict['pki_subsystem'] + # generic extension support in CSR - for external CA + self.add_req_ext = config.str2bool( + self.mdict['pki_req_ext_add']) def configure_pki_data(self, data): config.pki_log.info( @@ -3715,6 +3732,14 @@ class ConfigClient: cert1 = self.create_system_cert("ca_signing") cert1.signingAlgorithm = \ self.mdict['pki_ca_signing_signing_algorithm'] + # generic extension support in CSR - for external CA + if self.add_req_ext: + cert1.req_ext_oid = \ + self.mdict['pki_req_ext_oid'] + cert1.req_ext_critical = \ + self.mdict['pki_req_ext_critical'] + cert1.req_ext_data = \ + self.mdict['pki_req_ext_data'] if self.external_step_two: # External CA (Step 2) or Stand-alone PKI (Step 2) if not self.subsystem == "CA": diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py index 049ebf518..de224eb9a 100644 --- a/base/server/python/pki/server/deployment/pkiparser.py +++ b/base/server/python/pki/server/deployment/pkiparser.py @@ -569,6 +569,9 @@ class PKIConfigParser: if not 'pki_external' in self.mdict or\ not len(self.mdict['pki_external']): self.mdict['pki_external'] = "false" + if not 'pki_req_ext_add' in self.mdict or\ + not len(self.mdict['pki_req_ext_add']): + self.mdict['pki_req_ext_add'] = "false" if not 'pki_external_step_two' in self.mdict or\ not len(self.mdict['pki_external_step_two']): self.mdict['pki_external_step_two'] = "false" -- cgit