Java tutorial
/************************************************************************* * * * EJBCA: The OpenSource Certificate Authority * * * * This software is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or any later version. * * * * See terms of license at gnu.org. * * * *************************************************************************/ package org.ejbca.extra.caservice.processor; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.security.cert.CertPath; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.util.ArrayList; import org.apache.log4j.Logger; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.X509Name; import org.bouncycastle.jce.netscape.NetscapeCertRequest; import org.ejbca.core.EjbcaException; import org.ejbca.core.model.log.Admin; import org.ejbca.core.model.ra.ExtendedInformation; import org.ejbca.core.model.ra.UserDataConstants; import org.ejbca.core.model.ra.UserDataVO; import org.ejbca.core.protocol.IResponseMessage; import org.ejbca.core.protocol.PKCS10RequestMessage; import org.ejbca.core.protocol.X509ResponseMessage; import org.ejbca.core.protocol.cmp.CrmfRequestMessage; import org.ejbca.extra.db.CertificateRequestRequest; import org.ejbca.extra.db.CertificateRequestResponse; import org.ejbca.extra.db.ExtRARequest; import org.ejbca.extra.db.ISubMessage; import org.ejbca.util.CertTools; import org.ejbca.util.RequestMessageUtils; import org.ejbca.util.passgen.IPasswordGenerator; import org.ejbca.util.passgen.PasswordGeneratorFactory; import com.novosec.pkix.asn1.cmp.CertRepMessage; import com.novosec.pkix.asn1.cmp.PKIBody; import com.novosec.pkix.asn1.cmp.PKIHeader; import com.novosec.pkix.asn1.cmp.PKIMessage; import com.novosec.pkix.asn1.crmf.CertReqMessages; /** * Process certificate signing requests. * * CertificateRequestRequest.REQUEST_TYPE_.. lists supported request types. * CertificateRequestRequest.RESPONSE_TYPE.. lists supported response type. Not all responses are available for all request types. * * @version $Id: CertificateRequestRequestProcessor.java 11793 2011-04-21 07:10:20Z netmackan $ */ public class CertificateRequestRequestProcessor extends MessageProcessor implements ISubMessageProcessor { private static final Logger log = Logger.getLogger(CertificateRequestRequestProcessor.class); private static final String MSG_UNSUPPORTED_RESPONSE_TYPE = "Unsupported response type."; private static final String MSG_UNSUPPORTED_REQUEST_TYPE = "Unsupported request type."; /** @see ISubMessageProcessor#process(Admin, ISubMessage, String) */ public ISubMessage process(Admin admin, ISubMessage submessage, String errormessage) { if (errormessage == null) { return processCertificateRequestRequest(admin, (CertificateRequestRequest) submessage); } else { return new CertificateRequestResponse(((ExtRARequest) submessage).getRequestId(), false, errormessage, null, null); } } /** * Extracts the certificate signing request type and requests a new certificate using the provided credentials. */ private CertificateRequestResponse processCertificateRequestRequest(Admin admin, CertificateRequestRequest submessage) { if (log.isDebugEnabled()) { log.debug("Processing CertificateRequestRequest"); } try { byte[] result = null; if (submessage.createOrEditUser()) { if (log.isDebugEnabled()) { log.debug("createOrEditUser == true, will use one-shot request processing."); } final UserDataVO userdatavo = getUserDataVO(admin, submessage); final String requestData = new String(submessage.getRequestData()); final int requestTypeInt = submessage.getRequestType(); final int responseTypeInt = submessage.getResponseType(); final String hardTokenSN = null; result = certificateRequestSession.processCertReq(admin, userdatavo, requestData, requestTypeInt, hardTokenSN, responseTypeInt); } else { switch (submessage.getRequestType()) { case CertificateRequestRequest.REQUEST_TYPE_PKCS10: Certificate cert = null; PKCS10RequestMessage req = RequestMessageUtils .genPKCS10RequestMessage(submessage.getRequestData()); req.setUsername(submessage.getUsername()); req.setPassword(submessage.getPassword()); IResponseMessage resp = signSession.createCertificate(admin, req, X509ResponseMessage.class, null); cert = CertTools.getCertfromByteArray(resp.getResponseMessage()); if (submessage.getResponseType() == CertificateRequestRequest.RESPONSE_TYPE_CERTIFICATE) { result = cert.getEncoded(); } else { result = signSession.createPKCS7(admin, cert, true); } break; case CertificateRequestRequest.REQUEST_TYPE_SPKAC: ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(submessage.getRequestData())); ASN1Sequence spkac = (ASN1Sequence) in.readObject(); in.close(); NetscapeCertRequest nscr = new NetscapeCertRequest(spkac); cert = signSession.createCertificate(admin, submessage.getUsername(), submessage.getPassword(), nscr.getPublicKey()); if (submessage.getResponseType() == CertificateRequestRequest.RESPONSE_TYPE_CERTIFICATE) { result = cert.getEncoded(); } else if (submessage.getResponseType() == CertificateRequestRequest.RESPONSE_TYPE_PKCS7) { result = signSession.createPKCS7(admin, cert, true); } else if (submessage .getResponseType() == CertificateRequestRequest.RESPONSE_TYPE_PKCS7WITHCHAIN) { // Read certificate chain ArrayList<Certificate> certList = new ArrayList<Certificate>(); certList.add(cert); certList.addAll( caSession.getCA(Admin.getInternalAdmin(), CertTools.getIssuerDN(cert).hashCode()) .getCertificateChain()); // Create large certificate-only PKCS7 CertificateFactory cf = CertificateFactory.getInstance("X.509"); CertPath certPath = cf .generateCertPath(new ByteArrayInputStream(CertTools.getPEMFromCerts(certList))); result = certPath.getEncoded("PKCS7"); } else { return new CertificateRequestResponse(submessage.getRequestId(), false, MSG_UNSUPPORTED_RESPONSE_TYPE, null, null); } break; case CertificateRequestRequest.REQUEST_TYPE_CRMF: // Extract request in a format that EJBCA can process CertReqMessages certReqMessages = CertReqMessages .getInstance(new ASN1InputStream(submessage.getRequestData()).readObject()); PKIMessage msg = new PKIMessage(new PKIHeader(new DERInteger(2), new GeneralName(new X509Name("CN=unused")), new GeneralName(new X509Name("CN=unused"))), new PKIBody(certReqMessages, 2)); // [2] CertReqMessages --Certification Request CrmfRequestMessage crmfReq = new CrmfRequestMessage(msg, null, true, null); crmfReq.setUsername(submessage.getUsername()); crmfReq.setPassword(submessage.getPassword()); // Request and extract certificate from response IResponseMessage response = signSession.createCertificate(admin, crmfReq, org.ejbca.core.protocol.cmp.CmpResponseMessage.class, null); ASN1InputStream ais = new ASN1InputStream( new ByteArrayInputStream(response.getResponseMessage())); CertRepMessage certRepMessage = PKIMessage.getInstance(ais.readObject()).getBody().getCp(); InputStream inStream = new ByteArrayInputStream(certRepMessage.getResponse(0) .getCertifiedKeyPair().getCertOrEncCert().getCertificate().getEncoded()); cert = CertificateFactory.getInstance("X.509").generateCertificate(inStream); inStream.close(); // Convert to the right response type if (submessage.getResponseType() == CertificateRequestRequest.RESPONSE_TYPE_CERTIFICATE) { result = cert.getEncoded(); } else if (submessage.getResponseType() == CertificateRequestRequest.RESPONSE_TYPE_PKCS7) { result = signSession.createPKCS7(admin, cert, false); } else if (submessage .getResponseType() == CertificateRequestRequest.RESPONSE_TYPE_PKCS7WITHCHAIN) { // Read certificate chain ArrayList<Certificate> certList = new ArrayList<Certificate>(); certList.add(cert); certList.addAll( caSession.getCA(Admin.getInternalAdmin(), CertTools.getIssuerDN(cert).hashCode()) .getCertificateChain()); // Create large certificate-only PKCS7 CertificateFactory cf = CertificateFactory.getInstance("X.509"); CertPath certPath = cf .generateCertPath(new ByteArrayInputStream(CertTools.getPEMFromCerts(certList))); result = certPath.getEncoded("PKCS7"); } else { return new CertificateRequestResponse(submessage.getRequestId(), false, MSG_UNSUPPORTED_RESPONSE_TYPE, null, null); } break; default: return new CertificateRequestResponse(submessage.getRequestId(), false, MSG_UNSUPPORTED_REQUEST_TYPE, null, null); } } // Return the response when we have response data (byte[]) return new CertificateRequestResponse(submessage.getRequestId(), true, null, submessage.getResponseType(), result); } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("External RA request generated an error: " + e.getMessage()); } return new CertificateRequestResponse(submessage.getRequestId(), false, "Error " + e.getMessage(), null, null); } } private UserDataVO getUserDataVO(final Admin admin, final CertificateRequestRequest submessage) throws ClassCastException, EjbcaException { final UserDataVO result = generateUserDataVO(admin, submessage); result.setStatus(UserDataConstants.STATUS_NEW); // Not yet supported: hardtokenissuerid // Not yet supported: custom start time // Not yet supported: custom end time // Not yet supported: generic Custom ExtendedInformation if (submessage.getCertificateSerialNumber() != null) { ExtendedInformation ei = result.getExtendedinformation(); if (ei == null) { ei = new ExtendedInformation(); } ei.setCertificateSerialNumber(submessage.getCertificateSerialNumber()); result.setExtendedinformation(ei); } if (submessage.getPassword() == null) { final IPasswordGenerator pwdgen = PasswordGeneratorFactory .getInstance(PasswordGeneratorFactory.PASSWORDTYPE_ALLPRINTABLE); final String pwd = pwdgen.getNewPassword(12, 12); result.setPassword(pwd); } else { result.setPassword(submessage.getPassword()); } return result; } }