diff options
Diffstat (limited to 'base/tps/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java')
-rw-r--r-- | base/tps/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java | 760 |
1 files changed, 760 insertions, 0 deletions
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java b/base/tps/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java new file mode 100644 index 000000000..5851d2f69 --- /dev/null +++ b/base/tps/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java @@ -0,0 +1,760 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2014 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package org.dogtagpki.server.tps.cms; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CertificateException; +import java.util.Hashtable; +import java.util.List; + +import netscape.security.x509.RevocationReason; +import netscape.security.x509.X509CertImpl; + +import org.dogtagpki.server.connector.IRemoteRequest; +import org.dogtagpki.server.tps.TPSSubsystem; +import org.dogtagpki.server.tps.engine.TPSEngine; +import org.dogtagpki.tps.main.TPSBuffer; +import org.dogtagpki.tps.main.Util; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.CryptoManager.NotInitializedException; +import org.mozilla.jss.crypto.X509Certificate; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.EPropertyNotFound; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.cmscore.connector.HttpConnector; +import com.netscape.cmsutil.http.HttpResponse; +import com.netscape.cmsutil.util.Utils; +import com.netscape.cmsutil.xml.XMLObject; + +/** + * CARemoteRequestHandler is a class representing remote requests + * offered by the Certificate Authority (CA) + * + * @author cfu + */ +public class CARemoteRequestHandler extends RemoteRequestHandler +{ + public CARemoteRequestHandler(String connID) + throws EBaseException { + if (connID == null) { + throw new EBaseException("CARemoteRequestHandler: CARemoteRequestHandler(): connID null."); + } + connid = connID; + } + + /** + * enrollCertificate enrolls a certificate in the CA + * + * @param pubKeybuf public key for enrollment + * @param uid uid for enrollment + * @param cuid token id + * + * @returns CAEnrollCertResponse + */ + public CAEnrollCertResponse enrollCertificate( + TPSBuffer pubKeybuf, + String uid, + String cuid, + String tokenType, + String keyType) + throws EBaseException { + + CMS.debug("CARemoteRequestHandler: enrollCertificate(): begins."); + if (pubKeybuf == null || uid == null || cuid == null) { + throw new EBaseException("CARemoteRequestHandler: enrollCertificate(): input parameter null."); + } + + IConfigStore conf = CMS.getConfigStore(); + String profileId = + conf.getString(TPSEngine.OP_ENROLL_PREFIX + "." + + tokenType + ".keyGen." + + keyType + ".ca.profileId"); + + TPSSubsystem subsystem = + (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); + HttpConnector conn = + (HttpConnector) subsystem.getConnectionManager().getConnector(connid); + CMS.debug("CARemoteRequestHandler: enrollCertificate(): sending request to CA"); + String encodedPubKey = null; + try { + encodedPubKey = Util.uriEncode(CMS.BtoA(pubKeybuf.toBytesArray())); + } catch (Exception e) { + CMS.debug("CARemoteRequestHandler: enrollCertificate(): uriEncode of pubkey failed: " + e); + throw new EBaseException("CARemoteRequestHandler: enrollCertificate(): uriEncode of pubkey failed: " + e); + } + HttpResponse resp = + conn.send("enrollment", + IRemoteRequest.GET_XML + "=" + + true + + "&" + IRemoteRequest.TOKEN_CUID + "=" + + cuid + + "&" + IRemoteRequest.CA_ENROLL_screenname + "=" + + uid + + "&" + IRemoteRequest.CA_ENROLL_publickey + "=" + + encodedPubKey + + "&" + IRemoteRequest.CA_ProfileId + "=" + + profileId); + + String content = resp.getContent(); + + CMS.debug("CARemoteRequestHandler: enrollCertificate(): got content = " + content); + + if (content != null && !content.equals("")) { + XMLObject xmlResponse = + getXMLparser(content); + + Hashtable<String, Object> response = + new Hashtable<String, Object>(); + + CMS.debug("CARemoteRequestHandler: enrollCertificate(): received:" + + content); + + /** + * When a value is not found in response, keep going so we know + * what else is missing + * Note: serverKeygen and !serverKeygen returns different set of + * response values so "missing" might not be bad + */ + Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND); + String value = xmlResponse.getValue(IRemoteRequest.RESPONSE_STATUS_XML); + if (value == null) { + CMS.debug("CARemoteRequestHandler: enrollCertificate(): Status not found."); + CMS.debug("CARemoteRequestHandler: enrollCertificate(): got content = " + content); + } else { + CMS.debug("CARemoteRequestHandler: enrollCertificate(): got Status = " + value); + ist = Integer.parseInt(value); + } + response.put(IRemoteRequest.RESPONSE_STATUS, ist); + + value = xmlResponse.getValue("SubjectDN"); + if (value == null) { + CMS.debug("CARemoteRequestHandler:: enrollCertificate(): response missing name-value pair for: " + + IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN); + } else { + CMS.debug("CARemoteRequestHandler:: enrollCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN = " + + value); + response.put(IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN, value); + } + + value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_Certificate_serial); + if (value == null) { + CMS.debug("CARemoteRequestHandler:: enrollCertificate(): response missing name-value pair for: " + + IRemoteRequest.CA_RESPONSE_Certificate_serial); + } else { + CMS.debug("CARemoteRequestHandler:: enrollCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_serial = 0x" + + value); + response.put(IRemoteRequest.CA_RESPONSE_Certificate_serial, value); + } + + value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_Certificate_b64); + if (value == null) { + CMS.debug("CARemoteRequestHandler:: enrollCertificate(): response missing name-value pair for: " + + IRemoteRequest.CA_RESPONSE_Certificate_b64); + } else { + try { + CMS.debug("CARemoteRequestHandler:: enrollCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_b64 = " + + value); + response.put(IRemoteRequest.CA_RESPONSE_Certificate_b64, value); + X509CertImpl newCert = new X509CertImpl(Utils.base64decode(value)); + response.put(IRemoteRequest.CA_RESPONSE_Certificate_x509, newCert); + CMS.debug("CARemoteRequestHandler: enrollCertificate(): new cert parsed successfully"); + } catch (Exception e) { + // we don't exit. Keep going. + CMS.debug("CARemoteRequestHandler: enrollCertificate(): exception:" + e); + } + } + + CMS.debug("CARemoteRequestHandler: enrollCertificate(): ends."); + return new CAEnrollCertResponse(response); + } else { + CMS.debug("CARemoteRequestHandler: enrollCertificate(): no response content"); + throw new EBaseException("CARemoteRequestHandler: enrollCertificate(): no response content."); + } + } + + /** + * retrieveCertificate retrieves a certificate by serial number + * + * @param serialno the serial number of the cert to be retrieved + * @return CARetrieveCertResponse + */ + public CARetrieveCertResponse retrieveCertificate( + BigInteger serialno) + throws EBaseException { + + CMS.debug("CARemoteRequestHandler: retrieveCertificate(): begins."); + if (serialno == null) { + throw new EBaseException("CARemoteRequestHandler: retrieveCertificate(): input parameter null."); + } + + //ToDo: I"m not sure why these are not used, let's check this out. + //It's working though. + + /* + IConfigStore conf = CMS.getConfigStore(); + String configName = "tps.connector." + connid + ".uri.getBySerial"; + String servlet = conf.getString(configName, "/ca/ee/ca/displayBySerial"); + */ + + + TPSSubsystem subsystem = + (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); + HttpConnector conn = + (HttpConnector) subsystem.getConnectionManager().getConnector(connid); + CMS.debug("CARemoteRequestHandler: retrieveCertificate(): sending request to CA"); + HttpResponse resp = + conn.send("getcert", + IRemoteRequest.GET_XML + "=" + true + + "&" + IRemoteRequest.CA_GET_CERT_B64CertOnly + "=" + true + + "&" + IRemoteRequest.CA_GET_CERT_SERIAL + "=" + serialno.toString()); + + String content = resp.getContent(); + if (content != null && !content.equals("")) { + XMLObject xmlResponse = + getXMLparser(content); + + Hashtable<String, Object> response = + new Hashtable<String, Object>(); + + CMS.debug("CARemoteRequestHandler: retrieveCertificate(): received:" + + content); + + /** + * When a value is not found in response, keep going so we know + * what else is missing + */ + Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND); + String value = xmlResponse.getValue(IRemoteRequest.RESPONSE_STATUS_XML); + if (value == null) { + CMS.debug("CARemoteRequestHandler: retrieveCertificate(): Status not found."); + CMS.debug("CARemoteRequestHandler: retrieveCertificate(): got content = " + content); + } else { + CMS.debug("CARemoteRequestHandler: retrieveCertificate(): got Status = " + value); + ist = Integer.parseInt(value); + } + response.put(IRemoteRequest.RESPONSE_STATUS, ist); + + value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_Certificate_chain_b64); + if (value == null) { + CMS.debug("CARemoteRequestHandler:: retrieveCertificate(): response missing name-value pair for: " + + IRemoteRequest.CA_RESPONSE_Certificate_chain_b64); + } else { + CMS.debug("CARemoteRequestHandler:: retrieveCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_chain_b64 = " + + value); + response.put(IRemoteRequest.CA_RESPONSE_Certificate_chain_b64, value); + try { + X509CertImpl newCert = new X509CertImpl(Utils.base64decode(value)); + response.put(IRemoteRequest.CA_RESPONSE_Certificate_x509, newCert); + CMS.debug("CARemoteRequestHandler: retrieveCertificate(): retrieved cert parsed successfully"); + } catch (CertificateException e) { + // we don't exit. Keep going. + CMS.debug("CARemoteRequestHandler: retrieveCertificate(): exception:" + e); + } + } + + CMS.debug("CARemoteRequestHandler: retrieveCertificate(): ends."); + return new CARetrieveCertResponse(response); + } else { + CMS.debug("CARemoteRequestHandler: retrieveCertificate(): no response content"); + throw new EBaseException("CARemoteRequestHandler: retrieveCertificate(): no response content."); + } + } + + /** + * renewCertificate renew a certificate by serial number + * + * @param serialno the serial number of the cert to be renewed + * @return CARenewCertResponse + */ + public CARenewCertResponse renewCertificate( + BigInteger serialno, + String tokenType, + String keyType) + throws EBaseException { + + CMS.debug("CARemoteRequestHandler: renewCertificate(): begins."); + if (serialno == null) { + throw new EBaseException("CARemoteRequestHandler: renewCertificate(): input parameter null."); + } + + IConfigStore conf = CMS.getConfigStore(); + + String profileId = + conf.getString(TPSEngine.OP_ENROLL_PREFIX + "." + + tokenType + ".renewal." + + keyType + ".ca.profileId"); + + TPSSubsystem subsystem = + (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); + HttpConnector conn = + (HttpConnector) subsystem.getConnectionManager().getConnector(connid); + CMS.debug("CARemoteRequestHandler: renewCertificate(): sending request to CA"); + HttpResponse resp = + conn.send("renewal", + IRemoteRequest.GET_XML + "=" + true + + "&" + IRemoteRequest.CA_RENEWAL + "=" + true + + "&" + IRemoteRequest.CA_RENEWAL_SerialNum + "=" + serialno.toString() + + "&" + IRemoteRequest.CA_ProfileId + "=" + profileId); + + String content = resp.getContent(); + + if (content != null && !content.equals("")) { + XMLObject xmlResponse = + getXMLparser(content); + + Hashtable<String, Object> response = + new Hashtable<String, Object>(); + + CMS.debug("CARemoteRequestHandler: renewCertificate(): received:" + + content); + + /** + * When a value is not found in response, keep going so we know + * what else is missing + * Note: serverKeygen and !serverKeygen returns different set of + * response values so "missing" might not be bad + */ + Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND); + String value = xmlResponse.getValue(IRemoteRequest.RESPONSE_STATUS_XML); + if (value == null) { + CMS.debug("CARemoteRequestHandler: renewCertificate(): Status not found."); + CMS.debug("CARemoteRequestHandler: renewCertificate(): got content = " + content); + } else { + CMS.debug("CARemoteRequestHandler: renewCertificate(): got Status = " + value); + ist = Integer.parseInt(value); + } + response.put(IRemoteRequest.RESPONSE_STATUS, ist); + + value = xmlResponse.getValue("SubjectDN"); + if (value == null) { + CMS.debug("CARemoteRequestHandler:: renewCertificate(): response missing name-value pair for: " + + IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN); + } else { + CMS.debug("CARemoteRequestHandler:: renewCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN = " + + value); + response.put(IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN, value); + } + + value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_Certificate_serial); + if (value == null) { + CMS.debug("CARemoteRequestHandler:: renewCertificate(): response missing name-value pair for: " + + IRemoteRequest.CA_RESPONSE_Certificate_serial); + } else { + CMS.debug("CARemoteRequestHandler:: renewCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_serial = 0x" + + value); + response.put(IRemoteRequest.CA_RESPONSE_Certificate_serial, value); + } + + value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_Certificate_b64); + if (value == null) { + CMS.debug("CARemoteRequestHandler:: renewCertificate(): response missing name-value pair for: " + + IRemoteRequest.CA_RESPONSE_Certificate_b64); + } else { + CMS.debug("CARemoteRequestHandler:: renewCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_b64 = " + + value); + response.put(IRemoteRequest.CA_RESPONSE_Certificate_b64, value); + try { + X509CertImpl newCert = new X509CertImpl(Utils.base64decode(value)); + response.put(IRemoteRequest.CA_RESPONSE_Certificate_x509, newCert); + CMS.debug("CARemoteRequestHandler: renewCertificate(): new cert parsed successfully"); + } catch (CertificateException e) { + // we don't exit. Keep going. + CMS.debug("CARemoteRequestHandler: renewCertificate(): exception:" + e); + } + } + + CMS.debug("CARemoteRequestHandler: renewCertificate(): ends."); + return new CARenewCertResponse(response); + } else { + CMS.debug("CARemoteRequestHandler: renewCertificate(): no response content"); + throw new EBaseException("CARemoteRequestHandler: renewCertificate(): no response content."); + } + } + + /** + * revokeCertificate provides the basic revocation of a certificate from + * the CA + * + * @param serialno serial number of the cert to revoke + * @param reason reason to revoke per definition in RevocationReason + * + * @returns CARevokeCertResponse + */ + private CARevokeCertResponse revokeCertificate( + String serialno, + RevocationReason reason) + throws EBaseException { + + CMS.debug("CARemoteRequestHandler: revokeCertificate(): begins on serial#:"+ serialno); + if (serialno == null || reason == null) { + throw new EBaseException("CARemoteRequestHandler: revokeCertificate(): input parameter null."); + } + + // IConfigStore conf = CMS.getConfigStore(); + + TPSSubsystem subsystem = + (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); + HttpConnector conn = + (HttpConnector) subsystem.getConnectionManager().getConnector(connid); + CMS.debug("CARemoteRequestHandler: revokeCertificate(): sending request to CA"); + HttpResponse resp = + conn.send("revoke", + IRemoteRequest.CA_OP + "=" + IRemoteRequest.CA_REVOKE + + "&" + IRemoteRequest.CA_REVOCATION_REASON + "=" + reason.getCode() + + "&" + IRemoteRequest.CA_REVOKE_ALL + "=(" + + IRemoteRequest.CA_REVOKE_SERIAL + "=" + serialno + ")&" + + IRemoteRequest.CA_REVOKE_COUNT + "=1"); + String content = resp.getContent(); + + CMS.debug("CARemoteRequestHandler: revokeCertificate(): got content = " + content); + if (content != null && !content.equals("")) { + Hashtable<String, Object> response = + parseResponse(content); + + /** + * When a value is not found in response, keep going so we know + * what else is missing + */ + Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND); + String value = (String) response.get(IRemoteRequest.RESPONSE_STATUS); + + CMS.debug("CARemoteRequestHandler: revokeCertificate(): got status = " + value); + ist = Integer.parseInt(value); + if (ist != 0) { + CMS.debug("CARemoteRequestHandler: revokeCertificate(): status not 0, getting error string... "); + value = (String) response.get(IRemoteRequest.RESPONSE_ERROR_STRING); + if (value == null) { + CMS.debug("CARemoteRequestHandler: revokeCertificate(): response missing name-value pair for: " + + IRemoteRequest.RESPONSE_ERROR_STRING); + } else { + CMS.debug("CARemoteRequestHandler: revokeCertificate(): got IRemoteRequest.RESPONSE_ERROR_STRING = " + + value); + response.put(IRemoteRequest.RESPONSE_ERROR_STRING, value); + } + } + response.put(IRemoteRequest.RESPONSE_STATUS, ist); + + CMS.debug("CARemoteRequestHandler: revokeCertificate(): ends."); + return new CARevokeCertResponse(response); + } else { + CMS.debug("CARemoteRequestHandler: revokeCertificate(): no response content."); + throw new EBaseException("CARemoteRequestHandler: revokeCertificate(): no response content."); + } + } + + /** + * unrevokeCertificate provides the basic unrevocation of a certificate from + * the CA + * + * @param serialno serial number of the cert to unrevoke + * + * @returns CARevokeCertResponse + */ + private CARevokeCertResponse unrevokeCertificate( + String serialno) + throws EBaseException { + + CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): begins on serial#:"+ serialno); + if (serialno == null) { + throw new EBaseException("CARemoteRequestHandler: unrevokeCertificate(): input parameter null."); + } + + TPSSubsystem subsystem = + (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); + HttpConnector conn = + (HttpConnector) subsystem.getConnectionManager().getConnector(connid); + CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): sending request to CA"); + HttpResponse resp = + conn.send("unrevoke", + IRemoteRequest.CA_UNREVOKE_SERIAL + "=" + serialno); + String content = resp.getContent(); + + CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): got content = " + content); + if (content != null && !content.equals("")) { + Hashtable<String, Object> response = + parseResponse(content); + + /** + * When a value is not found in response, keep going so we know + * what else is missing + */ + Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND); + String value = (String) response.get(IRemoteRequest.RESPONSE_STATUS); + + CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): got status = " + value); + ist = Integer.parseInt(value); + if (ist != 0) { + CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): status not 0, getting error string... "); + value = (String) response.get(IRemoteRequest.RESPONSE_ERROR_STRING); + if (value == null) { + CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): response missing name-value pair for: " + + IRemoteRequest.RESPONSE_ERROR_STRING); + } else { + CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): got IRemoteRequest.RESPONSE_ERROR_STRING = " + + value); + response.put(IRemoteRequest.RESPONSE_ERROR_STRING, value); + } + } + response.put(IRemoteRequest.RESPONSE_STATUS, ist); + + CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): ends."); + return new CARevokeCertResponse(response); + } else { + CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): no response content."); + throw new EBaseException("CARemoteRequestHandler: unrevokeCertificate(): no response content."); + } + } + + /** + * revokeFromOtherCA searches through all defined ca entries + * to find the cert's signing ca for revocation / unrevocation. + * It is called from revokeCertificate() when the cert's + * AKI does not match that of the current signing ca. + * + * @param revoke true to revoke; false to unrevoke + * @param cert cert to (un)revoke + * @param serialno parameter for the (Un)RevokeCertificate() functions + * @param reason RevocationReason for the base revokeCertificate() function + * @throws IOException + */ + @SuppressWarnings("unused") + private CARevokeCertResponse revokeFromOtherCA( + boolean revoke, // true==revoke; false==unrevoke + X509CertImpl cert, + RevocationReason reason) + throws EBaseException, IOException { + if (cert == null) { + throw new EBaseException("CARemoteRequestHandler: revokeFromOtherCA(): input parameter cert null."); + } + String certAkiString = null; + try { + certAkiString = Util.getCertAkiString(cert); + } catch (Exception e) { + throw new EBaseException("CARemoteRequestHandler: revokeFromOtherCA(): getCertAkiString failed:" + e); + } + return revokeFromOtherCA(revoke, cert.getSerialNumber().toString(), certAkiString, reason); + } + + + private CARevokeCertResponse revokeFromOtherCA( + boolean revoke, // true==revoke; false==unrevoke + String serialno, + String certAkiString, + RevocationReason reason) + throws EBaseException { + + + CMS.debug("CARemoteRequestHandler: revokeFromOtherCA: begins"); + + TPSSubsystem subsystem = + (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); + List<String> caList = + subsystem.getConnectionManager().getCAList(); + + Exception exception = null; + + for (String ca : caList) { + try { + String caSkiString = getCaSki(ca); + if (certAkiString.equals(caSkiString)) { + CMS.debug("CARemoteRequestHandler: revokeFromOtherCA() cert AKI and caCert SKI matched"); + if (revoke) { + return revokeCertificate(serialno, reason); + } else { + return unrevokeCertificate(serialno); + } + } else { // not a match then iterate to next ca in list + CMS.debug("CARemoteRequestHandler: revokeFromOtherCA() cert AKI and caCert SKI not matched"); + } + } catch (Exception e) { + // any issue then iterate to next ca in list + CMS.debug("CARemoteRequestHandler: revokeFromOtherCA() issue found, iterate to next ca in list. Exception:" + + e); + exception = e; + } + } + if (exception == null) { + throw new EBaseException("revokeFromOtherCA: signing ca not found"); + } else { + throw new EBaseException(exception.toString()); + } + } + + /** + * getCaSki returns the CA's Subject Key Identifier (ski) + * associated with the connector id. + * If the ca's ski has not been calculated, it will do so and + * save to the connector's caSKI config entry + * + * @param conn connector id + * @returns ca's ski associated with conn + */ + private String getCaSki(String conn) + throws EBaseException, IOException { + + String caSkiString = null; + if (conn == null) { + throw new EBaseException("CARemoteRequestHandler: getCaSki(): input parameter conn null."); + } + + IConfigStore conf = CMS.getConfigStore(); + + /* + * first, see if ca Subject Key Identifier (SKI) is in + * config store. If not, put it in, so we don't have to + * calculate that every time. + */ + try { + String configName = "tps.connector." + conn + ".caSKI"; + CMS.debug("CARemoteRequestHandler: getCaSki() retriving configName=" + configName); + return conf.getString(configName); + } catch (EPropertyNotFound e) { + // caSKI not yet calculated; proceed to calculate + CMS.debug("CARemoteRequestHandler: getCaSki() caSKI not yet calculated:" + e); + } catch (EBaseException e) { + throw e; + } + + try { + String caNickname = + conf.getString("tps.connector." + conn + ".caNickname"); + CMS.debug("CARemoteRequestHandler: getCaSki() Calculating caSKI...searching for ca cert in nss db:" + + caNickname); + CryptoManager cm = CryptoManager.getInstance(); + try { + X509Certificate c = cm.findCertByNickname(caNickname); + X509CertImpl caCert = new X509CertImpl(c.getEncoded()); + // now retrieve caSKI and store in config + caSkiString = Util.getCertSkiString(caCert); + CMS.debug("CARemoteRequestHandler: getCaSki() caSKI calculated. Saving it."); + conf.putString("tps.connector." + conn + ".caSKI", caSkiString); + conf.commit(false); + } catch (IOException e) { + throw e; + } catch (Exception et) { + /* ca cert not found in nss db; no match needed */ + CMS.debug("CARemoteRequestHandler: getCaSki() caSKI calculation failure." + et); + throw new EBaseException("CARemoteRequestHandler: getCaSki(): skip match."); + } + } catch (EBaseException e) { + /* + * if it gets here, that means config is missing both: + * 1. tps.connector.ca<n>.caSKI + * 2. tps.connector.ca<n>.caNickname + * now assume default of just using the issuing ca and + * no search performed + */ + CMS.debug("CARemoteRequestHandler: getCaSki() caSKI calculation failure." + e); + throw e; + } catch (NotInitializedException e) { + CMS.debug("CARemoteRequestHandler: getCaSki() caSKI calculation failure." + e); + throw new EBaseException("CARemoteRequestHandler: getCaSki(): skip match.:" + e); + } + + return caSkiString; + } + + + + /** + * revokeCertificate() supports revocation routing by providing + * CA discovery. When needed, it searchs through all listed ca + * entries to find the cert's signing ca for revocation. + * + * Note: in the configuration, the ca signing cert of each ca + * id must be imported into the db and have its nickname present. + * e.g. tps.connector.ca1.caNickname=CA1nickname + * + * See design: + * http://pki.fedoraproject.org/wiki/TPS_-_Revocation_Routing + * + * @param revoke true to revoke; false to unrevoke + * @param serialno serial number for the (Un)RevokeCertificate() functions + * @param reason RevocationReason for the base revokeCertificate() function + */ + public CARevokeCertResponse revokeCertificate( + boolean revoke, // true==revoke; false==unrevoke + X509CertImpl cert, + RevocationReason reason) + throws EBaseException { + if (cert == null) { + throw new EBaseException("CARemoteRequestHandler: revokeCertificate(): input parameter cert null."); + } + String certAkiString = null; + try { + certAkiString = Util.getCertAkiString(cert); + } catch (IOException e) { + throw new EBaseException("CARemoteRequestHandler: revokeCertificate(): getCertAkiString failed:" + e); + } + + return revokeCertificate(revoke, cert.getSerialNumber().toString(), certAkiString, reason); + } + + public CARevokeCertResponse revokeCertificate( + boolean revoke, // true==revoke; false==unrevoke + String serialno, + String certAkiString, + RevocationReason reason) + throws EBaseException { + + CMS.debug("CARemoteRequestHandler: revokeCertificate() begins with CA discovery"); + + if (revoke == true && reason == null) { + throw new EBaseException("CARemoteRequestHandler: revokeCertificate(): input parameter reason null."); + } + + boolean skipMatch = false; + + String caSkiString = null; + + try { + caSkiString = getCaSki(connid); + } catch (Exception e) { + CMS.debug("CARemoteRequestHandler: revokeCertificate() exception:" + e); + skipMatch = true; + } + if (!skipMatch) { + /* now compare cert's AKI to the ca's SKI + * if matched, continue, + * if not, search in the ca list + */ + CMS.debug("CARemoteRequestHandler: revokeCertificate() cert AKI and caCert SKI matching begins"); + if (certAkiString.equals(caSkiString)) { + CMS.debug("CARemoteRequestHandler: revokeCertificate() cert AKI and caCert SKI matched"); + if (revoke) { + return revokeCertificate(serialno, reason); + } else { + return unrevokeCertificate(serialno); + } + } else { + CMS.debug("CARemoteRequestHandler: revokeCertificate() cert AKI and caCert SKI of the designated issuing ca do not match...calling revokeFromOtherCA to search for another ca"); + return revokeFromOtherCA(revoke, serialno, certAkiString, reason); + } + } else { + if (revoke) { + return revokeCertificate(serialno, reason); + } else { + return unrevokeCertificate(serialno); + } + } + } +} |