From 468f1e73e15a86861ee65ebe929527600ce37942 Mon Sep 17 00:00:00 2001 From: Fraser Tweedale Date: Thu, 31 Mar 2016 15:37:51 +1100 Subject: [PATCH 91/96] Lightweight CAs: extract LDAP commit/delete methods LDAP code to add, modify and delete authority entries exists in multiple places. Extract these methods to remove this duplication and provide a cleaner basis for upcoming implementation of replication handling. Part of: https://fedorahosted.org/pki/ticket/1625 --- .../src/com/netscape/ca/CertificateAuthority.java | 210 +++++++++++---------- 1 file changed, 115 insertions(+), 95 deletions(-) diff --git a/base/ca/src/com/netscape/ca/CertificateAuthority.java b/base/ca/src/com/netscape/ca/CertificateAuthority.java index 798b310668332bf58e2a656cf948065f0cf25d96..814e7e9297de5899ff2de3345d8ca1fee4f9350c 100644 --- a/base/ca/src/com/netscape/ca/CertificateAuthority.java +++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java @@ -2551,74 +2551,70 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori attrSet.add(new LDAPAttribute("description", description)); LDAPEntry ldapEntry = new LDAPEntry(dn, attrSet); - // connect to database - LDAPConnection conn = dbFactory.getConn(); + commitAuthority(aid, ldapEntry); try { - // add entry to database - conn.add(ldapEntry); + // Generate signing key + CryptoManager cryptoManager = CryptoManager.getInstance(); + // TODO read PROP_TOKEN_NAME config + CryptoToken token = cryptoManager.getInternalKeyStorageToken(); + // TODO algorithm parameter + KeyPairGenerator gen = token.getKeyPairGenerator(KeyPairAlgorithm.RSA); + gen.initialize(2048); + KeyPair keypair = gen.genKeyPair(); + 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 + 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 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 + CMS.debug("Error creating lightweight CA certificate"); + CMS.debug(e); try { - // Generate signing key - CryptoManager cryptoManager = CryptoManager.getInstance(); - // TODO read PROP_TOKEN_NAME config - CryptoToken token = cryptoManager.getInternalKeyStorageToken(); - // TODO algorithm parameter - KeyPairGenerator gen = token.getKeyPairGenerator(KeyPairAlgorithm.RSA); - gen.initialize(2048); - KeyPair keypair = gen.genKeyPair(); - 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 - 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 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); + deleteAuthorityEntry(aid); + } catch (ELdapException e2) { + // we are about to throw ECAException, so just + // log this error. + CMS.debug("Error deleting new authority entry after failure during certificate generation: " + e2); } - } catch (LDAPException e) { - throw new EBaseException("Error adding authority entry to database: " + e); - } finally { - dbFactory.returnConn(conn); + throw new ECAException("Error creating lightweight CA certificate: " + e); } return new CertificateAuthority( @@ -2664,22 +2660,45 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori LDAPAttributeSet attrSet = new LDAPAttributeSet(attrs); LDAPEntry ldapEntry = new LDAPEntry(dn, attrSet); - // connect to database - LDAPConnection conn = dbFactory.getConn(); - - try { - conn.add(ldapEntry); - } catch (LDAPException e) { - throw new ELdapException("Error adding host authority entry to database: " + e); - } finally { - dbFactory.returnConn(conn); - } + commitAuthority(aid, ldapEntry); this.authorityID = aid; this.authorityDescription = desc; return aid; } + private void commitAuthority(AuthorityID aid, LDAPEntry entry) + throws ELdapException { + LDAPConnection conn = dbFactory.getConn(); + synchronized (hostCA) { + try { + conn.add(entry); + } catch (LDAPException e) { + throw new ELdapException("commitAuthority: failed to add entry", e); + } finally { + dbFactory.returnConn(conn); + } + } + } + + /** + * Modify _this_ authority with the given modification set. + */ + private void commitModifyAuthority(LDAPModificationSet mods) + throws ELdapException { + String dn = "cn=" + authorityID.toString() + "," + authorityBaseDN(); + LDAPConnection conn = dbFactory.getConn(); + synchronized (hostCA) { + try { + conn.modify(dn, mods); + } catch (LDAPException e) { + throw new ELdapException("commitAuthority: failed to add entry", e); + } finally { + dbFactory.returnConn(conn); + } + } + } + /** * Update lightweight authority attributes. * @@ -2727,17 +2746,7 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori } if (mods.size() > 0) { - String dn = "cn=" + authorityID.toString() + "," + authorityBaseDN(); - - // connect to database - LDAPConnection conn = dbFactory.getConn(); - try { - conn.modify(dn, mods); - } catch (LDAPException e) { - throw new EBaseException("Error adding authority entry to database: " + e); - } finally { - dbFactory.returnConn(conn); - } + commitModifyAuthority(mods); // update was successful; update CA's state authorityEnabled = nextEnabled; @@ -2745,7 +2754,7 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori } } - public void deleteAuthority() throws EBaseException { + public synchronized void deleteAuthority() throws EBaseException { if (isHostAuthority()) throw new CATypeException("Cannot delete the host CA"); @@ -2763,19 +2772,10 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori if (hasSubCAs) throw new CANotLeafException("CA with sub-CAs cannot be deleted (delete sub-CAs first)"); - caMap.remove(authorityID); shutdown(); // delete ldap entry - LDAPConnection conn = dbFactory.getConn(); - String dn = "cn=" + authorityID.toString() + "," + authorityBaseDN(); - try { - conn.delete(dn); - } catch (LDAPException e) { - throw new ELdapException("Error deleting authority entry '" + dn + "': " + e); - } finally { - dbFactory.returnConn(conn); - } + deleteAuthorityEntry(authorityID); CryptoManager cryptoManager; try { @@ -2812,4 +2812,24 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori } } + private void deleteAuthorityEntry(AuthorityID aid) throws ELdapException { + String dn = "cn=" + aid.toString() + "," + authorityBaseDN(); + LDAPConnection conn = dbFactory.getConn(); + synchronized (hostCA) { + try { + conn.delete(dn); + } catch (LDAPException e) { + throw new ELdapException("Error deleting authority entry: " + dn, e); + } finally { + dbFactory.returnConn(conn); + } + + forgetAuthority(aid); + } + } + + private void forgetAuthority(AuthorityID aid) { + caMap.remove(aid); + } + } -- 2.5.5