package org.cagrid.gaards.dorian.ca; import gov.nih.nci.cagrid.common.FaultHelper; import java.security.KeyPair; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.X509CRL; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPublicKey; import java.util.Date; import org.bouncycastle.asn1.x509.X509Name; import org.cagrid.gaards.dorian.common.Lifetime; import org.cagrid.gaards.dorian.common.LoggingObject; import org.cagrid.gaards.dorian.service.util.Utils; import org.cagrid.gaards.pki.CRLEntry; import org.cagrid.gaards.pki.CertUtil; import org.cagrid.gaards.pki.KeyUtil; /** * @author <A href="mailto:langella@bmi.osu.edu">Stephen Langella </A> * @author <A href="mailto:oster@bmi.osu.edu">Scott Oster </A> * @author <A href="mailto:hastings@bmi.osu.edu">Shannon Hastings </A> * @version $Id: ArgumentManagerTable.java,v 1.2 2004/10/15 16:35:16 langella * Exp $ */ public abstract class CertificateAuthority extends LoggingObject { private boolean initialized = false; private CertificateAuthorityProperties properties; public CertificateAuthority(CertificateAuthorityProperties properties) { this.properties = properties; } public abstract String getUserCredentialsProvider(); public abstract String getCACredentialsProvider(); public abstract String getSignatureAlgorithm(); public abstract boolean hasCACredentials() throws CertificateAuthorityFault; public abstract void setCACredentials(X509Certificate cert, PrivateKey key, String password) throws CertificateAuthorityFault; public abstract void deleteCACredentials() throws CertificateAuthorityFault; public abstract PrivateKey getPrivateKey(String password) throws CertificateAuthorityFault, NoCACredentialsFault; protected abstract java.security.cert.X509Certificate getCertificate() throws CertificateAuthorityFault; public void clearCertificateAuthority() throws CertificateAuthorityFault { deleteCACredentials(); this.initialized = false; } private synchronized void init() throws CertificateAuthorityFault { try { if (!initialized) { if (!hasCACredentials()) { if (properties.isAutoCreateCAEnabled()) { Lifetime lifetime = properties.getCreationPolicy().getLifetime(); this.createCertifcateAuthorityCredentials(properties.getCreationPolicy().getSubject(), Utils .getExpiredDate(lifetime), properties.getCreationPolicy().getKeySize()); } } initialized = true; } } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Unexpected Error, could not initialize the Dorian Certificate Authority."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } private void createCertifcateAuthorityCredentials(String dn, Date expirationDate, int keySize) throws CertificateAuthorityFault, NoCACredentialsFault { try { KeyPair pair = KeyUtil.generateRSAKeyPair(getCACredentialsProvider(), keySize); X509Certificate cacert = CertUtil.generateCACertificate(getCACredentialsProvider(), new X509Name(dn), new Date(), expirationDate, pair, getSignatureAlgorithm()); deleteCACredentials(); this.setCACredentials(cacert, pair.getPrivate(), properties.getCertificateAuthorityPassword()); } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Unexpected Error, could not create the CA credentials."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } public java.security.cert.X509Certificate getCACertificate() throws CertificateAuthorityFault, NoCACredentialsFault { return getCACertificate(true); } private java.security.cert.X509Certificate getCACertificate(boolean errorOnExpiredCredentials) throws CertificateAuthorityFault, NoCACredentialsFault { X509Certificate cert = null; init(); try { if (!hasCACredentials()) { NoCACredentialsFault fault = new NoCACredentialsFault(); fault.setFaultString("No certificate exists for the CA."); throw fault; } else { cert = getCertificate(); } } catch (NoCACredentialsFault f) { throw f; } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Unexpected Error, Error obtaining the CA private key."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } if (errorOnExpiredCredentials) { Date now = new Date(); if (now.before(cert.getNotBefore()) || (now.after(cert.getNotAfter()))) { if (properties.isAutoRenewCAEnabled()) { Lifetime lifetime = properties.getRenewalLifetime(); return renewCertifcateAuthorityCredentials(Utils.getExpiredDate(lifetime)); } else { NoCACredentialsFault fault = new NoCACredentialsFault(); fault.setFaultString("The CA certificate had expired or is not valid at this time."); throw fault; } } } return cert; } public synchronized X509Certificate signCertificate(String subject, PublicKey publicKey, Date start, Date expiration) throws CertificateAuthorityFault, NoCACredentialsFault { init(); X509Certificate cacert = getCACertificate(); Date caDate = cacert.getNotAfter(); if (start.after(caDate)) { CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Certificate start date is after the CA certificates expiration date."); throw fault; } if (expiration.after(caDate)) { CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Certificate expiration date is after the CA certificates expiration date."); throw fault; } try { // VALIDATE DN String caSubject = cacert.getSubjectDN().getName(); int caindex = caSubject.lastIndexOf(","); String caPreSub = caSubject.substring(0, caindex); if (!subject.startsWith(caPreSub)) { CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Invalid certificate subject, the subject must start with, " + caPreSub); throw fault; } X509Certificate cert = CertUtil.generateCertificate(getCACredentialsProvider(), new X509Name(subject), start, expiration, publicKey, cacert, getPrivateKey(), getSignatureAlgorithm(), properties .getPolicyOID()); return cert; } catch (CertificateAuthorityFault e) { throw e; } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Unexpected Error, could not sign certificate."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } public synchronized X509Certificate signHostCertificate(String host, PublicKey publicKey, Date start, Date expiration) throws CertificateAuthorityFault, NoCACredentialsFault { init(); X509Certificate cacert = getCACertificate(); try { String subject = Utils.getHostCertificateSubject(cacert, host); return signCertificate(subject, publicKey, start, expiration); } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Unexpected Error, could not sign host certificate."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } public synchronized X509Certificate renewCertifcateAuthorityCredentials(Date expirationDate) throws CertificateAuthorityFault, NoCACredentialsFault { init(); try { X509Certificate oldcert = getCACertificate(false); int size = ((RSAPublicKey) oldcert.getPublicKey()).getModulus().bitLength(); KeyPair pair = KeyUtil.generateRSAKeyPair(getCACredentialsProvider(), size); X509Certificate cacert = CertUtil.generateCACertificate(getCACredentialsProvider(), new X509Name(oldcert .getSubjectDN().getName()), new Date(), expirationDate, pair, getSignatureAlgorithm()); deleteCACredentials(); this.setCACredentials(cacert, pair.getPrivate(), properties.getCertificateAuthorityPassword()); return cacert; } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Unexpected Error, could renew the CA credentials."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } public X509CRL getCRL(CRLEntry[] entries) throws CertificateAuthorityFault, NoCACredentialsFault { try { init(); return CertUtil.createCRL(getCACredentialsProvider(), getCACertificate(), getPrivateKey(), entries, getCACertificate().getNotAfter(), getSignatureAlgorithm()); } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Unexpected Error, could not create the CRL."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } public PrivateKey getPrivateKey() throws CertificateAuthorityFault, NoCACredentialsFault { init(); try { if (!hasCACredentials()) { NoCACredentialsFault fault = new NoCACredentialsFault(); fault.setFaultString("No Private Key exists for the CA."); throw fault; } else { return getPrivateKey(properties.getCertificateAuthorityPassword()); } } catch (NoCACredentialsFault f) { throw f; } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Unexpected Error, Error obtaining the CA private key."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } public CertificateAuthorityProperties getProperties() { return properties; } }