// --- 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) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package com.netscape.ca; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Principal; import java.security.cert.CRLException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Date; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import netscape.security.extensions.CertInfo; import netscape.security.util.BigInt; import netscape.security.util.DerValue; import netscape.security.x509.AlgorithmId; import netscape.security.x509.BasicConstraintsExtension; import netscape.security.x509.CRLExtensions; import netscape.security.x509.CRLReasonExtension; import netscape.security.x509.CertificateAlgorithmId; import netscape.security.x509.CertificateChain; import netscape.security.x509.CertificateExtensions; import netscape.security.x509.CertificateIssuerName; import netscape.security.x509.CertificateSerialNumber; import netscape.security.x509.CertificateSubjectName; import netscape.security.x509.CertificateValidity; import netscape.security.x509.LdapV3DNStrConverter; import netscape.security.x509.PKIXExtensions; import netscape.security.x509.RevocationReason; import netscape.security.x509.RevokedCertImpl; import netscape.security.x509.SerialNumber; import netscape.security.x509.X500Name; import netscape.security.x509.X500NameAttrMap; import netscape.security.x509.X509CRLImpl; import netscape.security.x509.X509CertImpl; import netscape.security.x509.X509CertInfo; import netscape.security.x509.X509ExtensionException; import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.authority.IAuthority; import com.netscape.certsrv.authority.ICertAuthority; import com.netscape.certsrv.base.EBaseException; import com.netscape.certsrv.base.IConfigStore; import com.netscape.certsrv.base.MetaInfo; import com.netscape.certsrv.base.SessionContext; import com.netscape.certsrv.ca.ECAException; import com.netscape.certsrv.ca.ICAService; import com.netscape.certsrv.ca.ICRLIssuingPoint; import com.netscape.certsrv.ca.ICertificateAuthority; import com.netscape.certsrv.connector.IConnector; import com.netscape.certsrv.dbs.Modification; import com.netscape.certsrv.dbs.ModificationSet; import com.netscape.certsrv.dbs.certdb.ICertRecord; import com.netscape.certsrv.dbs.certdb.ICertRecordList; import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; import com.netscape.certsrv.logging.ILogger; import com.netscape.certsrv.profile.EProfileException; import com.netscape.certsrv.profile.IProfile; import com.netscape.certsrv.profile.IProfileSubsystem; import com.netscape.certsrv.request.IRequest; import com.netscape.certsrv.request.IService; import com.netscape.cmscore.base.SubsystemRegistry; import com.netscape.cmscore.connector.HttpConnector; import com.netscape.cmscore.connector.LocalConnector; import com.netscape.cmscore.connector.RemoteAuthority; import com.netscape.cmscore.crmf.CRMFParser; import com.netscape.cmscore.crmf.PKIArchiveOptionsContainer; import com.netscape.cmscore.dbs.CertRecord; import com.netscape.cmscore.dbs.CertificateRepository; import com.netscape.cmscore.dbs.RevocationInfo; import com.netscape.cmscore.util.Debug; /** * Request Service for CertificateAuthority. */ public class CAService implements ICAService, IService { public static final String CRMF_REQUEST = "CRMFRequest"; public static final String CHALLENGE_PHRASE = "challengePhrase"; public static final String SERIALNO_ARRAY = "serialNoArray"; // CCA->CLA connector protected static IConnector mCLAConnector = null; private ICertificateAuthority mCA = null; private Hashtable mServants = new Hashtable(); private IConnector mKRAConnector = null; private IConfigStore mConfig = null; private boolean mArchivalRequired = true; private Hashtable mCRLIssuingPoints = new Hashtable(); private ILogger mSignedAuditLogger = CMS.getSignedAuditLogger(); private final static String LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST = "LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST_4"; public CAService(ICertificateAuthority ca) { mCA = ca; // init services. mServants.put( IRequest.ENROLLMENT_REQUEST, new serviceIssue(this)); mServants.put( IRequest.RENEWAL_REQUEST, new serviceRenewal(this)); mServants.put( IRequest.REVOCATION_REQUEST, new serviceRevoke(this)); mServants.put( IRequest.CMCREVOKE_REQUEST, new serviceRevoke(this)); mServants.put( IRequest.REVOCATION_CHECK_CHALLENGE_REQUEST, new serviceCheckChallenge(this)); mServants.put( IRequest.GETCERTS_FOR_CHALLENGE_REQUEST, new getCertsForChallenge(this)); mServants.put( IRequest.UNREVOCATION_REQUEST, new serviceUnrevoke(this)); mServants.put( IRequest.GETCACHAIN_REQUEST, new serviceGetCAChain(this)); mServants.put( IRequest.GETCRL_REQUEST, new serviceGetCRL(this)); mServants.put( IRequest.GETREVOCATIONINFO_REQUEST, new serviceGetRevocationInfo(this)); mServants.put( IRequest.GETCERTS_REQUEST, new serviceGetCertificates(this)); mServants.put( IRequest.CLA_CERT4CRL_REQUEST, new serviceCert4Crl(this)); mServants.put( IRequest.CLA_UNCERT4CRL_REQUEST, new serviceUnCert4Crl(this)); mServants.put( IRequest.GETCERT_STATUS_REQUEST, new getCertStatus(this)); } public void init(IConfigStore config) throws EBaseException { mConfig = config; try { // MOVED TO com.netscape.certsrv.apps.CMS // java.security.Security.addProvider(new netscape.security.provider.CMS()); // java.security.Provider pr = java.security.Security.getProvider("CMS"); // if (pr != null) { // ; // } // else // Debug.trace("Something is wrong in CMS install !"); java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X.509"); Debug.trace("CertificateFactory Type : " + cf.getType()); Debug.trace("CertificateFactory Provider : " + cf.getProvider().getInfo()); } catch (java.security.cert.CertificateException e) { Debug.trace("Something is happen in install CMS provider !" + e.toString()); } } public void startup() throws EBaseException { IConfigStore kraConfig = mConfig.getSubStore("KRA"); if (kraConfig != null) { mArchivalRequired = kraConfig.getBoolean( "archivalRequired", true); mKRAConnector = getConnector(kraConfig); if (mKRAConnector != null) { if (Debug.ON) { Debug.trace("Started KRA Connector"); } mKRAConnector.start(); } } // clone ca to CLA (clone master) connector IConfigStore claConfig = mConfig.getSubStore("CLA"); if (claConfig != null) { mCLAConnector = getConnector(claConfig); if (mCLAConnector != null) { CMS.debug(CMS.getLogMessage("CMSCORE_CA_START_CONNECTOR")); if (Debug.ON) { Debug.trace("Started CLA Connector in CCA"); } mCLAConnector.start(); } } } protected ICertificateAuthority getCA() { return mCA; } public IConnector getKRAConnector() { return mKRAConnector; } public void setKRAConnector(IConnector c) { mKRAConnector = c; } public IConnector getConnector(IConfigStore config) throws EBaseException { IConnector connector = null; if (config == null || config.size() <= 0) { return null; } boolean enable = config.getBoolean("enable", true); // provide a way to register a 3rd connector into RA String extConnector = config.getString("class", null); if (extConnector != null) { try { connector = (IConnector) Class.forName(extConnector).newInstance(); // connector.start() will be called later on return connector; } catch (Exception e) { // ignore external class if error mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_LOAD_CONNECTOR", extConnector, e.toString())); } } if (!enable) return null; boolean local = config.getBoolean("local"); IAuthority authority = null; if (local) { String id = config.getString("id"); authority = (IAuthority) SubsystemRegistry.getInstance().get(id); if (authority == null) { String msg = "local authority " + id + " not found."; mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_AUTHORITY_NOT_FOUND", id)); throw new EBaseException(msg); } connector = new LocalConnector((ICertAuthority) mCA, authority); // log(ILogger.LL_INFO, "local Connector to "+id+" inited"); } else { String host = config.getString("host"); int port = config.getInteger("port"); String uri = config.getString("uri"); String nickname = config.getString("nickName", null); int resendInterval = config.getInteger("resendInterval", -1); // Inserted by beomsuk int timeout = config.getInteger("timeout", 0); // Insert end // Changed by beomsuk //RemoteAuthority remauthority = // new RemoteAuthority(host, port, uri); RemoteAuthority remauthority = new RemoteAuthority(host, port, uri, timeout); // Change end if (nickname == null) nickname = mCA.getNickname(); // Changed by beomsuk //connector = // new HttpConnector(mCA, nickname, remauthority, resendInterval); if (timeout == 0) connector = new HttpConnector((IAuthority) mCA, nickname, remauthority, resendInterval, config); else connector = new HttpConnector((IAuthority) mCA, nickname, remauthority, resendInterval, config, timeout); // Change end // log(ILogger.LL_INFO, "remote authority "+ // host+":"+port+" "+uri+" inited"); } return connector; } public boolean isProfileRequest(IRequest request) { String profileId = request.getExtDataInString("profileId"); if (profileId == null || profileId.equals("")) return false; else return true; } /** * After population of defaults, and constraint validation, * the profile request is processed here. */ public void serviceProfileRequest(IRequest request) throws EBaseException { CMS.debug("CAService: serviceProfileRequest requestId=" + request.getRequestId().toString()); String profileId = request.getExtDataInString("profileId"); if (profileId == null || profileId.equals("")) { throw new EBaseException("profileId not found"); } IProfileSubsystem ps = (IProfileSubsystem) CMS.getSubsystem("profile"); IProfile profile = null; try { profile = ps.getProfile(profileId); } catch (EProfileException e) { } if (profile == null) { throw new EProfileException("Profile not found " + profileId); } // assumed rejected request.setExtData("dbStatus", "NOT_UPDATED"); // profile.populate(request); profile.validate(request); profile.execute(request); // This function is called only from ConnectorServlet // serialize to request queue } /** * method interface for IService *
* *
* * @param msg signed audit log message */ private void audit(String msg) { // in this case, do NOT strip preceding/trailing whitespace // from passed-in String parameters if (mSignedAuditLogger == null) { return; } mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT, null, ILogger.S_SIGNED_AUDIT, ILogger.LL_SECURITY, msg); } /** * Signed Audit Log Subject ID * * This method is called to obtain the "SubjectID" for * a signed audit log message. *
* * @return id string containing the signed audit log message SubjectID */ private String auditSubjectID() { // if no signed audit object exists, bail if (mSignedAuditLogger == null) { return null; } String subjectID = null; // Initialize subjectID SessionContext auditContext = SessionContext.getExistingContext(); if (auditContext != null) { subjectID = (String) auditContext.get(SessionContext.USER_ID); if (subjectID != null) { subjectID = subjectID.trim(); } else { subjectID = ILogger.NONROLEUSER; } } else { subjectID = ILogger.UNIDENTIFIED; } return subjectID; } /** * Signed Audit Log Requester ID * * This method is called to obtain the "RequesterID" for * a signed audit log message. *
* * @return id string containing the signed audit log message RequesterID */ private String auditRequesterID() { // if no signed audit object exists, bail if (mSignedAuditLogger == null) { return null; } String requesterID = null; // Initialize requesterID SessionContext auditContext = SessionContext.getExistingContext(); if (auditContext != null) { requesterID = (String) auditContext.get(SessionContext.REQUESTER_ID); if (requesterID != null) { requesterID = requesterID.trim(); } else { requesterID = ILogger.UNIDENTIFIED; } } else { requesterID = ILogger.UNIDENTIFIED; } return requesterID; } } /// /// servant classes /// interface IServant { public boolean service(IRequest request) throws EBaseException; } class serviceIssue implements IServant { private ICertificateAuthority mCA; private CAService mService; public serviceIssue(CAService service) { mService = service; mCA = mService.getCA(); } public boolean service(IRequest request) throws EBaseException { // XXX This is ugly. should associate attributes with // request types, not policy. // XXX how do we know what to look for in request ? if (request.getExtDataInCertInfoArray(IRequest.CERT_INFO) != null) return serviceX509(request); else return false; // Don't know what it is ????? } public boolean serviceX509(IRequest request) throws EBaseException { // XXX This is ugly. should associate attributes with // request types, not policy. // XXX how do we know what to look for in request ? X509CertInfo certinfos[] = request.getExtDataInCertInfoArray(IRequest.CERT_INFO); if (certinfos == null || certinfos[0] == null) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT_REQUEST_NOT_FOUND", request.getRequestId().toString())); throw new ECAException(CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_ISSUEREQ")); } String challengePassword = request.getExtDataInString(CAService.CHALLENGE_PHRASE); X509CertImpl[] certs = new X509CertImpl[certinfos.length]; String rid = request.getRequestId().toString(); int i; for (i = 0; i < certinfos.length; i++) { try { certs[i] = mService.issueX509Cert(rid, certinfos[i]); } catch (EBaseException e) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUE_ERROR", Integer.toString(i), rid, e.toString())); throw e; } } String crmfReqId = request.getExtDataInString(IRequest.CRMF_REQID); EBaseException ex = null; for (i = 0; i < certs.length; i++) { try { mService.storeX509Cert(rid, certs[i], crmfReqId, challengePassword); } catch (EBaseException e) { e.printStackTrace(); mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_STORE_ERROR", Integer.toString(i), rid, e.toString())); ex = e; // save to throw later. break; } } if (ex != null) { for (int j = 0; j < i; j++) { // delete the stored cert records from the database. // we issue all or nothing. BigInteger serialNo = ((X509Certificate) certs[i]).getSerialNumber(); try { mCA.getCertificateRepository().deleteCertificateRecord(serialNo); } catch (EBaseException e) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_DELETE_CERT_ERROR", serialNo.toString(), e.toString())); } } throw ex; } request.setExtData(IRequest.ISSUED_CERTS, certs); return true; } } class serviceRenewal implements IServant { private ICertificateAuthority mCA; private CAService mService; public serviceRenewal(CAService service) { mService = service; mCA = mService.getCA(); } public boolean service(IRequest request) throws EBaseException { // XXX if one fails should all fail ? - can't backtrack. X509CertInfo certinfos[] = request.getExtDataInCertInfoArray(IRequest.CERT_INFO); if (certinfos == null || certinfos[0] == null) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT_REQUEST_NOT_FOUND", request.getRequestId().toString())); throw new ECAException( CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_RENEWREQ")); } X509CertImpl issuedCerts[] = new X509CertImpl[certinfos.length]; for (int j = 0; j < issuedCerts.length; j++) issuedCerts[j] = null; String svcerrors[] = new String[certinfos.length]; for (int k = 0; k < svcerrors.length; k++) svcerrors[k] = null; String rid = request.getRequestId().toString(); for (int i = 0; i < certinfos.length; i++) { try { // get old serial number. SerialNumber serialnum = null; try { CertificateSerialNumber serialno = (CertificateSerialNumber) certinfos[i].get(X509CertInfo.SERIAL_NUMBER); if (serialno == null) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_NULL_SERIAL_NUMBER")); throw new ECAException( CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_RENEWREQ")); } serialnum = (SerialNumber) serialno.get(CertificateSerialNumber.NUMBER); } catch (IOException e) { if (Debug.ON) e.printStackTrace(); mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ERROR_GET_CERT", e.toString())); throw new ECAException( CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_RENEWREQ")); } catch (CertificateException e) { if (Debug.ON) e.printStackTrace(); mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ERROR_GET_CERT", e.toString())); throw new ECAException( CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_RENEWREQ")); } if (serialnum == null) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ERROR_GET_CERT", "")); throw new ECAException( CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_RENEWREQ")); } BigInt serialnumBigInt = serialnum.getNumber(); BigInteger oldSerialNo = serialnumBigInt.toBigInteger(); // get cert record CertRecord certRecord = (CertRecord) mCA.getCertificateRepository().readCertificateRecord(oldSerialNo); if (certRecord == null) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_NOT_FROM_CA", oldSerialNo.toString())); svcerrors[i] = new ECAException( CMS.getUserMessage("CMS_CA_CANT_FIND_CERT_SERIAL", oldSerialNo.toString())).toString(); continue; } // check if cert has been revoked. String certStatus = certRecord.getStatus(); if (certStatus.equals(ICertRecord.STATUS_REVOKED) || certStatus.equals(ICertRecord.STATUS_REVOKED_EXPIRED)) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_RENEW_REVOKED", oldSerialNo.toString())); svcerrors[i] = new ECAException( CMS.getUserMessage("CMS_CA_CANNOT_RENEW_REVOKED_CERT", "0x" + oldSerialNo.toString(16))).toString(); continue; } // check if cert has already been renewed. MetaInfo metaInfo = certRecord.getMetaInfo(); if (metaInfo != null) { String renewed = (String) metaInfo.get(ICertRecord.META_RENEWED_CERT); if (renewed != null) { BigInteger serial = new BigInteger(renewed); X509CertImpl cert = (X509CertImpl) mCA.getCertificateRepository().getX509Certificate(serial); if (cert == null) { // something wrong mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_MISSING_RENEWED", serial.toString())); svcerrors[i] = new ECAException( CMS.getUserMessage("CMS_CA_ERROR_GETTING_RENEWED_CERT", oldSerialNo.toString(), serial.toString())).toString(); continue; } // get cert record CertRecord cRecord = (CertRecord) mCA.getCertificateRepository().readCertificateRecord(serial); if (cRecord == null) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_NOT_FROM_CA", serial.toString())); svcerrors[i] = new ECAException( CMS.getUserMessage("CMS_CA_CANT_FIND_CERT_SERIAL", serial.toString())).toString(); continue; } // Check renewed certificate already REVOKED or EXPIRED String status = cRecord.getStatus(); if (status.equals(ICertRecord.STATUS_REVOKED) || status.equals(ICertRecord.STATUS_REVOKED_EXPIRED)) { Debug.trace("It is already revoked or Expired !!!"); } // it is still new ... So just return this certificate to user else { Debug.trace("It is still new !!!"); issuedCerts[i] = cert; continue; } } } // issue the cert. issuedCerts[i] = mService.issueX509Cert(rid, certinfos[i], true, oldSerialNo); mService.storeX509Cert(rid, issuedCerts[i], true, oldSerialNo); } catch (ECAException e) { svcerrors[i] = e.toString(); mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CANNOT_RENEW", Integer.toString(i), request.getRequestId().toString())); } } // always set issued certs regardless of error. request.setExtData(IRequest.ISSUED_CERTS, issuedCerts); // set and throw error if any. int l; for (l = svcerrors.length - 1; l >= 0 && svcerrors[l] == null; l--) ; if (l >= 0) { request.setExtData(IRequest.SVCERRORS, svcerrors); mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_NO_RENEW", request.getRequestId().toString())); throw new ECAException(CMS.getUserMessage("CMS_CA_RENEW_FAILED")); } return true; } } class getCertsForChallenge implements IServant { private ICertificateAuthority mCA; private CAService mService; public getCertsForChallenge(CAService service) { mService = service; mCA = mService.getCA(); } public boolean service(IRequest request) throws EBaseException { BigInteger[] serialNoArray = request.getExtDataInBigIntegerArray(CAService.SERIALNO_ARRAY); X509CertImpl[] certs = new X509CertImpl[serialNoArray.length]; for (int i = 0; i < serialNoArray.length; i++) { certs[i] = mCA.getCertificateRepository().getX509Certificate(serialNoArray[i]); } request.setExtData(IRequest.OLD_CERTS, certs); return true; } } class getCertStatus implements IServant { private ICertificateAuthority mCA; private CAService mService; public getCertStatus(CAService service) { mService = service; mCA = mService.getCA(); } public boolean service(IRequest request) throws EBaseException { BigInteger serialno = request.getExtDataInBigInteger("serialNumber"); String issuerDN = request.getExtDataInString("issuerDN"); CertificateRepository certDB = (CertificateRepository) mCA.getCertificateRepository(); String status = null; if (serialno != null) { CertRecord record = null; try { record = (CertRecord) certDB.readCertificateRecord(serialno); } catch (EBaseException ee) { Debug.trace(ee.toString()); } if (record != null) { status = record.getStatus(); if (status.equals("VALID")) { X509CertImpl cacert = mCA.getCACert(); Principal p = cacert.getSubjectDN(); if (!p.toString().equals(issuerDN)) { status = "INVALIDCERTROOT"; } } } } request.setExtData(IRequest.CERT_STATUS, status); return true; } } class serviceCheckChallenge implements IServant { private ICertificateAuthority mCA; private CAService mService; private MessageDigest mSHADigest = null; public serviceCheckChallenge(CAService service) { mService = service; mCA = mService.getCA(); try { mSHADigest = MessageDigest.getInstance("SHA1"); } catch (NoSuchAlgorithmException e) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString())); } } public boolean service(IRequest request) throws EBaseException { // note: some request attributes used below are set in // authentication/ChallengePhraseAuthentication.java :( BigInteger serialno = request.getExtDataInBigInteger("serialNumber"); String pwd = request.getExtDataInString( CAService.CHALLENGE_PHRASE); CertificateRepository certDB = (CertificateRepository) mCA.getCertificateRepository(); BigInteger[] bigIntArray = null; if (serialno != null) { CertRecord record = null; try { record = (CertRecord) certDB.readCertificateRecord(serialno); } catch (EBaseException ee) { Debug.trace(ee.toString()); } if (record != null) { String status = record.getStatus(); if (status.equals("VALID")) { boolean samepwd = compareChallengePassword(record, pwd); if (samepwd) { bigIntArray = new BigInteger[1]; bigIntArray[0] = record.getSerialNumber(); } } else { bigIntArray = new BigInteger[0]; } } else bigIntArray = new BigInteger[0]; } else { String subjectName = request.getExtDataInString("subjectName"); if (subjectName != null) { String filter = "(&(x509cert.subject=" + subjectName + ")(certStatus=VALID))"; ICertRecordList list = certDB.findCertRecordsInList(filter, null, 10); int size = list.getSize(); Enumeration en = list.getCertRecords(0, size - 1); if (!en.hasMoreElements()) { bigIntArray = new BigInteger[0]; } else { Vector idv = new Vector(); while (en.hasMoreElements()) { CertRecord record = (CertRecord) en.nextElement(); boolean samepwd = compareChallengePassword(record, pwd); if (samepwd) { BigInteger id = record.getSerialNumber(); idv.addElement(id); } } bigIntArray = new BigInteger[idv.size()]; idv.copyInto(bigIntArray); } } } if (bigIntArray == null) bigIntArray = new BigInteger[0]; request.setExtData(CAService.SERIALNO_ARRAY, bigIntArray); return true; } private boolean compareChallengePassword(CertRecord record, String pwd) throws EBaseException { MetaInfo metaInfo = (MetaInfo) record.get(CertRecord.ATTR_META_INFO); if (metaInfo == null) { throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", "metaInfo")); } String hashpwd = hashPassword(pwd); // got metaInfo String challengeString = (String) metaInfo.get(CertRecord.META_CHALLENGE_PHRASE); if (!challengeString.equals(hashpwd)) { return false; } else return true; } private String hashPassword(String pwd) { String salt = "lala123"; byte[] pwdDigest = mSHADigest.digest((salt + pwd).getBytes()); String b64E = com.netscape.osutil.OSUtil.BtoA(pwdDigest); return "{SHA}" + b64E; } } class serviceRevoke implements IServant { private ICertificateAuthority mCA; private CAService mService; public serviceRevoke(CAService service) { mService = service; mCA = mService.getCA(); } public boolean service(IRequest request) throws EBaseException { boolean sendStatus = true; // XXX Need to think passing as array. // XXX every implemented according to servlet. RevokedCertImpl crlentries[] = request.getExtDataInRevokedCertArray(IRequest.CERT_INFO); if (crlentries == null || crlentries.length == 0 || crlentries[0] == null) { // XXX should this be an error ? mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRL_NOT_FOUND", request.getRequestId().toString())); throw new ECAException(CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_REVREQ")); } RevokedCertImpl revokedCerts[] = new RevokedCertImpl[crlentries.length]; String svcerrors[] = null; for (int i = 0; i < crlentries.length; i++) { try { mService.revokeCert(crlentries[i], request.getRequestId().toString()); revokedCerts[i] = crlentries[i]; } catch (ECAException e) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CANNOT_REVOKE", Integer.toString(i), request.getRequestId().toString(), e.toString())); revokedCerts[i] = null; if (svcerrors == null) { svcerrors = new String[revokedCerts.length]; } svcerrors[i] = e.toString(); } } // #605941 - request.get(IRequest.CERT_INFO) store exact same thing // request.set(IRequest.REVOKED_CERTS, revokedCerts); // if clone ca, send revoked cert records to CLA if (CAService.mCLAConnector != null) { CMS.debug(CMS.getLogMessage("CMSCORE_CA_CLONE_READ_REVOKED")); BigInteger revokedCertIds[] = new BigInteger[revokedCerts.length]; for (int i = 0; i < revokedCerts.length; i++) { revokedCertIds[i] = revokedCerts[i].getSerialNumber(); } request.deleteExtData(IRequest.CERT_INFO); request.deleteExtData(IRequest.OLD_CERTS); request.setExtData(IRequest.REVOKED_CERT_RECORDS, revokedCertIds); CMS.debug(CMS.getLogMessage("CMSCORE_CA_CLONE_READ_REVOKED_CONNECTOR")); request.setRequestType(IRequest.CLA_CERT4CRL_REQUEST); sendStatus = CAService.mCLAConnector.send(request); if (sendStatus == false) { request.setExtData(IRequest.RESULT, IRequest.RES_ERROR); request.setExtData(IRequest.ERROR, new ECAException(CMS.getUserMessage("CMS_CA_SEND_CLA_REQUEST"))); return sendStatus; } else { if (request.getExtDataInString(IRequest.ERROR) != null) { request.setExtData(IRequest.RESULT, IRequest.RES_SUCCESS); request.deleteExtData(IRequest.ERROR); } } if (request.getExtDataInString(IRequest.ERROR) != null) { return sendStatus; } } if (svcerrors != null) { request.setExtData(IRequest.SVCERRORS, svcerrors); throw new ECAException(CMS.getUserMessage("CMS_CA_REVOKE_FAILED")); } if (Debug.ON) { Debug.trace("serviceRevoke sendStatus=" + sendStatus); } return sendStatus; } } class serviceUnrevoke implements IServant { private ICertificateAuthority mCA; private CAService mService; public serviceUnrevoke(CAService service) { mService = service; mCA = mService.getCA(); } public boolean service(IRequest request) throws EBaseException { boolean sendStatus = true; BigInteger oldSerialNo[] = request.getExtDataInBigIntegerArray(IRequest.OLD_SERIALS); if (oldSerialNo == null || oldSerialNo.length < 1) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_UNREVOKE_MISSING_SERIAL")); throw new ECAException( CMS.getUserMessage("CMS_CA_MISSING_SERIAL_NUMBER")); } String svcerrors[] = null; boolean needOldCerts = false; X509CertImpl oldCerts[] = request.getExtDataInCertArray(IRequest.OLD_CERTS); if (oldCerts == null || oldCerts.length < 1) { needOldCerts = true; oldCerts = new X509CertImpl[oldSerialNo.length]; } for (int i = 0; i < oldSerialNo.length; i++) { try { if (oldSerialNo[i].compareTo(new BigInteger("0")) < 0) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_UNREVOKE_MISSING_SERIAL")); throw new ECAException( CMS.getUserMessage("CMS_CA_MISSING_SERIAL_NUMBER")); } if (needOldCerts) { CertRecord certRec = (CertRecord) mCA.getCertificateRepository().readCertificateRecord(oldSerialNo[i]); oldCerts[i] = certRec.getCertificate(); } mService.unrevokeCert(oldSerialNo[i], request.getRequestId().toString()); } catch (ECAException e) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_UNREVOKE_FAILED", oldSerialNo[i].toString(), request.getRequestId().toString())); if (svcerrors == null) { svcerrors = new String[oldSerialNo.length]; } svcerrors[i] = e.toString(); } } // if clone ca, send unrevoked cert serials to CLA if (CAService.mCLAConnector != null) { request.setRequestType(IRequest.CLA_UNCERT4CRL_REQUEST); sendStatus = CAService.mCLAConnector.send(request); if (sendStatus == false) { request.setExtData(IRequest.RESULT, IRequest.RES_ERROR); request.setExtData(IRequest.ERROR, new ECAException(CMS.getUserMessage("CMS_CA_SEND_CLA_REQUEST"))); return sendStatus; } else { if (request.getExtDataInString(IRequest.ERROR) != null) { request.setExtData(IRequest.RESULT, IRequest.RES_SUCCESS); request.deleteExtData(IRequest.ERROR); } } } if (needOldCerts) { request.setExtData(IRequest.OLD_CERTS, oldCerts); } if (svcerrors != null) { request.setExtData(IRequest.SVCERRORS, svcerrors); throw new ECAException(CMS.getUserMessage("CMS_CA_UNREVOKE_FAILED")); } return sendStatus; } } class serviceGetCAChain implements IServant { private ICertificateAuthority mCA; private CAService mService; public serviceGetCAChain(CAService service) { mService = service; mCA = mService.getCA(); } public boolean service(IRequest request) throws EBaseException { CertificateChain certChain = mCA.getCACertChain(); ByteArrayOutputStream certChainOut = new ByteArrayOutputStream(); try { certChain.encode(certChainOut); } catch (IOException e) { mCA.log(ILogger.LL_FAILURE, e.toString()); throw new EBaseException(e.toString()); } request.setExtData(IRequest.CACERTCHAIN, certChainOut.toByteArray()); return true; } } class serviceGetCRL implements IServant { private ICertificateAuthority mCA; private CAService mService; public serviceGetCRL(CAService service) { mService = service; mCA = mService.getCA(); } public boolean service(IRequest request) throws EBaseException { try { ICRLIssuingPointRecord crlRec = (ICRLIssuingPointRecord) mCA.getCRLRepository().readCRLIssuingPointRecord(ICertificateAuthority.PROP_MASTER_CRL); X509CRLImpl crl = new X509CRLImpl(crlRec.getCRL()); request.setExtData(IRequest.CRL, crl.getEncoded()); } catch (EBaseException e) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_GETCRL_FIND_CRL")); throw new ECAException( CMS.getUserMessage("CMS_CA_CRL_ISSUEPT_NOT_FOUND", e.toString())); } catch (CRLException e) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_GETCRL_INST_CRL", ICertificateAuthority.PROP_MASTER_CRL)); throw new ECAException( CMS.getUserMessage("CMS_CA_CRL_ISSUEPT_NOGOOD", ICertificateAuthority.PROP_MASTER_CRL)); } catch (X509ExtensionException e) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_GETCRL_NO_ISSUING_REC")); throw new ECAException( CMS.getUserMessage("CMS_CA_CRL_ISSUEPT_EXT_NOGOOD", ICertificateAuthority.PROP_MASTER_CRL)); } return true; } } class serviceGetRevocationInfo implements IServant { private ICertificateAuthority mCA; private CAService mService; public serviceGetRevocationInfo(CAService service) { mService = service; mCA = mService.getCA(); } public boolean service(IRequest request) throws EBaseException { Enumeration enum1 = request.getExtDataKeys(); while (enum1.hasMoreElements()) { String name = (String) enum1.nextElement(); if (name.equals(IRequest.ISSUED_CERTS)) { X509CertImpl certsToCheck[] = request.getExtDataInCertArray(IRequest.ISSUED_CERTS); CertificateRepository certDB = (CertificateRepository) mCA.getCertificateRepository(); RevocationInfo info = certDB.isCertificateRevoked(certsToCheck[0]); if (info != null) { RevokedCertImpl revokedCerts[] = new RevokedCertImpl[1]; RevokedCertImpl revokedCert = new RevokedCertImpl( certsToCheck[0].getSerialNumber(), info.getRevocationDate(), info.getCRLEntryExtensions()); revokedCerts[0] = revokedCert; request.setExtData(IRequest.REVOKED_CERTS, revokedCerts); } } } return true; } } class serviceGetCertificates implements IServant { private ICertificateAuthority mCA; private CAService mService; public serviceGetCertificates(CAService service) { mService = service; mCA = mService.getCA(); } public boolean service(IRequest request) throws EBaseException { Enumeration enum1 = request.getExtDataKeys(); while (enum1.hasMoreElements()) { String name = (String) enum1.nextElement(); if (name.equals(IRequest.CERT_FILTER)) { String filter = request.getExtDataInString(IRequest.CERT_FILTER); CertificateRepository certDB = (CertificateRepository) mCA.getCertificateRepository(); X509CertImpl[] certs = certDB.getX509Certificates(filter); if (certs != null) { request.setExtData(IRequest.OLD_CERTS, certs); } } } return true; } } class serviceCert4Crl implements IServant { private ICertificateAuthority mCA; private CAService mService; public serviceCert4Crl(CAService service) { mService = service; mCA = mService.getCA(); } public boolean service(IRequest request) throws EBaseException { // XXX Need to think passing as array. // XXX every implemented according to servlet. BigInteger revokedCertIds[] = request.getExtDataInBigIntegerArray( IRequest.REVOKED_CERT_RECORDS); if (revokedCertIds == null || revokedCertIds.length == 0) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT4CRL_NO_ENTRY", request.getRequestId().toString())); throw new ECAException(CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_CLAREQ")); } CertRecord revokedCertRecs[] = new CertRecord[revokedCertIds.length]; for (int i = 0; i < revokedCertIds.length; i++) { revokedCertRecs[i] = (CertRecord) mCA.getCertificateRepository().readCertificateRecord( revokedCertIds[i]); } if (revokedCertRecs == null || revokedCertRecs.length == 0 || revokedCertRecs[0] == null) { // XXX should this be an error ? mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT4CRL_NO_ENTRY", request.getRequestId().toString())); throw new ECAException(CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_CLAREQ")); } CertRecord recordedCerts[] = new CertRecord[revokedCertRecs.length]; String svcerrors[] = null; for (int i = 0; i < revokedCertRecs.length; i++) { try { // for CLA, record it into cert repost ((CertificateRepository) mCA.getCertificateRepository()).addRevokedCertRecord(revokedCertRecs[i]); // mService.revokeCert(crlentries[i]); recordedCerts[i] = revokedCertRecs[i]; // inform all CRLIssuingPoints about revoked certificate Hashtable hips = mService.getCRLIssuingPoints(); Enumeration eIPs = hips.elements(); while (eIPs.hasMoreElements()) { ICRLIssuingPoint ip = (ICRLIssuingPoint) eIPs.nextElement(); // form RevokedCertImpl RevokedCertImpl rci = new RevokedCertImpl(revokedCertRecs[i].getSerialNumber(), revokedCertRecs[i].getRevokedOn()); if (ip != null) { ip.addRevokedCert(revokedCertRecs[i].getSerialNumber(), rci); } } } catch (ECAException e) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT4CRL_NO_REC", Integer.toString(i), request.getRequestId().toString(), e.toString())); recordedCerts[i] = null; if (svcerrors == null) { svcerrors = new String[recordedCerts.length]; } svcerrors[i] = e.toString(); } } //need to record which gets recorded and which failed...cfu // request.set(IRequest.REVOKED_CERTS, revokedCerts); if (svcerrors != null) { request.setExtData(IRequest.SVCERRORS, svcerrors); throw new ECAException(CMS.getUserMessage("CMS_CA_CERT4CRL_FAILED")); } return true; } } class serviceUnCert4Crl implements IServant { private ICertificateAuthority mCA; private CAService mService; public serviceUnCert4Crl(CAService service) { mService = service; mCA = mService.getCA(); } public boolean service(IRequest request) throws EBaseException { BigInteger oldSerialNo[] = request.getExtDataInBigIntegerArray(IRequest.OLD_SERIALS); if (oldSerialNo == null || oldSerialNo.length < 1) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_UNREVOKE_MISSING_SERIAL")); throw new ECAException( CMS.getUserMessage("CMS_CA_MISSING_SERIAL_NUMBER")); } String svcerrors[] = null; for (int i = 0; i < oldSerialNo.length; i++) { try { mCA.getCertificateRepository().deleteCertificateRecord(oldSerialNo[i]); // inform all CRLIssuingPoints about unrevoked certificate Hashtable hips = mService.getCRLIssuingPoints(); Enumeration eIPs = hips.elements(); while (eIPs.hasMoreElements()) { ICRLIssuingPoint ip = (ICRLIssuingPoint) eIPs.nextElement(); if (ip != null) { ip.addUnrevokedCert(oldSerialNo[i]); } } } catch (EBaseException e) { mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_DELETE_CERT_ERROR", oldSerialNo[i].toString(), e.toString())); if (svcerrors == null) { svcerrors = new String[oldSerialNo.length]; } svcerrors[i] = e.toString(); } } if (svcerrors != null) { request.setExtData(IRequest.SVCERRORS, svcerrors); throw new ECAException(CMS.getUserMessage("CMS_CA_UNCERT4CRL_FAILED")); } return true; } }