org.ejbca.extra.caservice.processor.CertificateRequestRequestProcessor.java Source code

Java tutorial

Introduction

Here is the source code for org.ejbca.extra.caservice.processor.CertificateRequestRequestProcessor.java

Source

/*************************************************************************
 *                                                                       *
 *  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;
    }

}