Example usage for org.bouncycastle.asn1.ocsp RevokedInfo RevokedInfo

List of usage examples for org.bouncycastle.asn1.ocsp RevokedInfo RevokedInfo

Introduction

In this page you can find the example usage for org.bouncycastle.asn1.ocsp RevokedInfo RevokedInfo.

Prototype

public RevokedInfo(ASN1GeneralizedTime revocationTime, CRLReason revocationReason) 

Source Link

Usage

From source file:org.cesecore.certificates.ocsp.OcspResponseGeneratorSessionBean.java

License:Open Source License

@Override
public OcspResponseInformation getOcspResponse(final byte[] request,
        final X509Certificate[] requestCertificates, String remoteAddress, String remoteHost,
        StringBuffer requestUrl, final AuditLogger auditLogger, final TransactionLogger transactionLogger)
        throws MalformedRequestException, OCSPException {
    //Check parameters
    if (auditLogger == null) {
        throw new InvalidParameterException(
                "Illegal to pass a null audit logger to OcspResponseSession.getOcspResponse");
    }/* w  w  w  . java  2 s. c  om*/
    if (transactionLogger == null) {
        throw new InvalidParameterException(
                "Illegal to pass a null transaction logger to OcspResponseSession.getOcspResponse");
    }
    // Validate byte array.
    if (request.length > MAX_REQUEST_SIZE) {
        final String msg = intres.getLocalizedMessage("request.toolarge", MAX_REQUEST_SIZE, request.length);
        throw new MalformedRequestException(msg);
    }
    byte[] respBytes = null;
    final Date startTime = new Date();
    OCSPResp ocspResponse = null;
    // Start logging process time after we have received the request
    if (transactionLogger.isEnabled()) {
        transactionLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
    }
    if (auditLogger.isEnabled()) {
        auditLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
        auditLogger.paramPut(AuditLogger.OCSPREQUEST, new String(Hex.encode(request)));
    }
    OCSPReq req;
    long maxAge = OcspConfiguration.getMaxAge(CertificateProfileConstants.CERTPROFILE_NO_PROFILE);
    OCSPRespBuilder responseGenerator = new OCSPRespBuilder();
    try {
        req = translateRequestFromByteArray(request, remoteAddress, transactionLogger);
        // Get the certificate status requests that are inside this OCSP req
        Req[] ocspRequests = req.getRequestList();
        if (ocspRequests.length <= 0) {
            String infoMsg = intres.getLocalizedMessage("ocsp.errornoreqentities");
            log.info(infoMsg);
            throw new MalformedRequestException(infoMsg);
        }
        final int maxRequests = 100;
        if (ocspRequests.length > maxRequests) {
            String infoMsg = intres.getLocalizedMessage("ocsp.errortoomanyreqentities", maxRequests);
            log.info(infoMsg);
            throw new MalformedRequestException(infoMsg);
        }
        if (log.isDebugEnabled()) {
            log.debug("The OCSP request contains " + ocspRequests.length + " simpleRequests.");
        }
        if (transactionLogger.isEnabled()) {
            transactionLogger.paramPut(TransactionLogger.NUM_CERT_ID, ocspRequests.length);
            transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.SUCCESSFUL);
        }
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.SUCCESSFUL);
        }
        OcspSigningCacheEntry ocspSigningCacheEntry = null;
        long nextUpdate = OcspConfiguration
                .getUntilNextUpdate(CertificateProfileConstants.CERTPROFILE_NO_PROFILE);
        // Add standard response extensions
        Map<ASN1ObjectIdentifier, Extension> responseExtensions = getStandardResponseExtensions(req);
        // Look for extension OIDs
        final Collection<String> extensionOids = OcspConfiguration.getExtensionOids();
        // Look over the status requests
        List<OCSPResponseItem> responseList = new ArrayList<OCSPResponseItem>();
        boolean addExtendedRevokedExtension = false;
        Date producedAt = null;
        for (Req ocspRequest : ocspRequests) {
            CertificateID certId = ocspRequest.getCertID();
            ASN1ObjectIdentifier certIdhash = certId.getHashAlgOID();
            if (!OIWObjectIdentifiers.idSHA1.equals(certIdhash)
                    && !NISTObjectIdentifiers.id_sha256.equals(certIdhash)) {
                throw new InvalidAlgorithmException(
                        "CertID with SHA1 and SHA256 are supported, not: " + certIdhash.getId());
            }
            if (transactionLogger.isEnabled()) {
                transactionLogger.paramPut(TransactionLogger.SERIAL_NOHEX,
                        certId.getSerialNumber().toByteArray());
                transactionLogger.paramPut(TransactionLogger.DIGEST_ALGOR, certId.getHashAlgOID().toString());
                transactionLogger.paramPut(TransactionLogger.ISSUER_NAME_HASH, certId.getIssuerNameHash());
                transactionLogger.paramPut(TransactionLogger.ISSUER_KEY, certId.getIssuerKeyHash());
            }
            if (auditLogger.isEnabled()) {
                auditLogger.paramPut(AuditLogger.ISSUER_KEY, certId.getIssuerKeyHash());
                auditLogger.paramPut(AuditLogger.SERIAL_NOHEX, certId.getSerialNumber().toByteArray());
                auditLogger.paramPut(AuditLogger.ISSUER_NAME_HASH, certId.getIssuerNameHash());
            }
            byte[] hashbytes = certId.getIssuerNameHash();
            String hash = null;
            if (hashbytes != null) {
                hash = new String(Hex.encode(hashbytes));
            }
            String infoMsg = intres.getLocalizedMessage("ocsp.inforeceivedrequest",
                    certId.getSerialNumber().toString(16), hash, remoteAddress);
            log.info(infoMsg);
            // Locate the CA which gave out the certificate
            ocspSigningCacheEntry = OcspSigningCache.INSTANCE.getEntry(certId);
            if (ocspSigningCacheEntry == null) {
                //Could it be that we haven't updated the OCSP Signing Cache?
                ocspSigningCacheEntry = findAndAddMissingCacheEntry(certId);
            }
            if (ocspSigningCacheEntry != null) {
                if (transactionLogger.isEnabled()) {
                    // This will be the issuer DN of the signing certificate, whether an OCSP responder or an internal CA  
                    String issuerNameDn = CertTools
                            .getIssuerDN(ocspSigningCacheEntry.getFullCertificateChain().get(0));
                    transactionLogger.paramPut(TransactionLogger.ISSUER_NAME_DN, issuerNameDn);
                }
            } else {
                /*
                 * if the certId was issued by an unknown CA 
                 * 
                 * The algorithm here: 
                 * We will sign the response with the CA that issued the last certificate(certId) in the request. If the issuing CA is not available on 
                 * this server, we sign the response with the default responderId (from params in web.xml). We have to look up the ca-certificate for 
                 * each certId in the request though, as we will check for revocation on the ca-cert as well when checking for revocation on the certId.
                 */
                // We could not find certificate for this request so get certificate for default responder
                ocspSigningCacheEntry = OcspSigningCache.INSTANCE.getDefaultEntry();
                if (ocspSigningCacheEntry != null) {
                    String errMsg = intres.getLocalizedMessage("ocsp.errorfindcacertusedefault",
                            new String(Hex.encode(certId.getIssuerNameHash())));
                    log.info(errMsg);
                    // If we can not find the CA, answer UnknowStatus
                    responseList.add(new OCSPResponseItem(certId, new UnknownStatus(), nextUpdate));
                    if (transactionLogger.isEnabled()) {
                        transactionLogger.paramPut(TransactionLogger.CERT_STATUS,
                                OCSPResponseItem.OCSP_UNKNOWN);
                        transactionLogger.writeln();
                    }
                    continue;
                } else {
                    GlobalOcspConfiguration ocspConfiguration = (GlobalOcspConfiguration) globalConfigurationSession
                            .getCachedConfiguration(GlobalOcspConfiguration.OCSP_CONFIGURATION_ID);
                    String defaultResponder = ocspConfiguration.getOcspDefaultResponderReference();
                    String errMsg = intres.getLocalizedMessage("ocsp.errorfindcacert",
                            new String(Hex.encode(certId.getIssuerNameHash())), defaultResponder);
                    log.error(errMsg);
                    // If we are responding to multiple requests, the last found ocspSigningCacheEntry will be used in the end
                    // so even if there are not any one now, it might be later when it is time to sign the responses.
                    // Since we only will sign the entire response once if there is at least one valid ocspSigningCacheEntry
                    // we might as well include the unknown requests.
                    responseList.add(new OCSPResponseItem(certId, new UnknownStatus(), nextUpdate));
                    continue;
                }
            }

            final org.bouncycastle.cert.ocsp.CertificateStatus certStatus;
            // Check if the cacert (or the default responderid) is revoked
            X509Certificate caCertificate = ocspSigningCacheEntry.getIssuerCaCertificate();
            final CertificateStatus signerIssuerCertStatus = ocspSigningCacheEntry
                    .getIssuerCaCertificateStatus();
            final String caCertificateSubjectDn = CertTools.getSubjectDN(caCertificate);
            CertificateStatusHolder certificateStatusHolder = null;
            if (signerIssuerCertStatus.equals(CertificateStatus.REVOKED)) {
                /*
                 * According to chapter 2.7 in RFC2560:
                 * 
                 * 2.7 CA Key Compromise If an OCSP responder knows that a particular CA's private key has been compromised, it MAY return the revoked
                 * state for all certificates issued by that CA.
                 */
                // If we've ended up here it's because the signer issuer certificate was revoked. 
                certStatus = new RevokedStatus(
                        new RevokedInfo(new ASN1GeneralizedTime(signerIssuerCertStatus.revocationDate),
                                CRLReason.lookup(signerIssuerCertStatus.revocationReason)));
                infoMsg = intres.getLocalizedMessage("ocsp.signcertissuerrevoked",
                        CertTools.getSerialNumberAsString(caCertificate),
                        CertTools.getSubjectDN(caCertificate));
                log.info(infoMsg);
                responseList.add(new OCSPResponseItem(certId, certStatus, nextUpdate));
                if (transactionLogger.isEnabled()) {
                    transactionLogger.paramPut(TransactionLogger.CERT_STATUS, OCSPResponseItem.OCSP_REVOKED);
                    transactionLogger.writeln();
                }
            } else {
                /**
                 * Here is the actual check for the status of the sought certificate (easy to miss). Here we grab just the status if there aren't
                 * any OIDs defined (default case), but if there are we'll probably need the certificate as well. If that's the case, we'll grab
                 * the certificate in the same transaction.
                 */
                final CertificateStatus status;
                if (extensionOids.isEmpty()) {
                    status = certificateStoreSession.getStatus(caCertificateSubjectDn,
                            certId.getSerialNumber());
                } else {
                    certificateStatusHolder = certificateStoreSession
                            .getCertificateAndStatus(caCertificateSubjectDn, certId.getSerialNumber());
                    status = certificateStatusHolder.getCertificateStatus();
                }
                // If we have an OcspKeyBinding configured for this request, we override the default value
                if (ocspSigningCacheEntry.isUsingSeparateOcspSigningCertificate()) {
                    nextUpdate = ocspSigningCacheEntry.getOcspKeyBinding().getUntilNextUpdate() * 1000L;
                }
                // If we have an explicit value configured for this certificate profile, we override the the current value with this value
                if (status.certificateProfileId != CertificateProfileConstants.CERTPROFILE_NO_PROFILE
                        && OcspConfiguration.isUntilNextUpdateConfigured(status.certificateProfileId)) {
                    nextUpdate = OcspConfiguration.getUntilNextUpdate(status.certificateProfileId);
                }
                // If we have an OcspKeyBinding configured for this request, we override the default value
                if (ocspSigningCacheEntry.isUsingSeparateOcspSigningCertificate()) {
                    maxAge = ocspSigningCacheEntry.getOcspKeyBinding().getMaxAge() * 1000L;
                }
                // If we have an explicit value configured for this certificate profile, we override the the current value with this value
                if (status.certificateProfileId != CertificateProfileConstants.CERTPROFILE_NO_PROFILE
                        && OcspConfiguration.isMaxAgeConfigured(status.certificateProfileId)) {
                    maxAge = OcspConfiguration.getMaxAge(status.certificateProfileId);
                }

                final String sStatus;
                boolean addArchiveCutoff = false;
                if (status.equals(CertificateStatus.NOT_AVAILABLE)) {
                    // No revocation info available for this cert, handle it
                    if (log.isDebugEnabled()) {
                        log.debug("Unable to find revocation information for certificate with serial '"
                                + certId.getSerialNumber().toString(16) + "'" + " from issuer '"
                                + caCertificateSubjectDn + "'");
                    }
                    /* 
                     * If we do not treat non existing certificates as good or revoked
                     * OR
                     * we don't actually handle requests for the CA issuing the certificate asked about
                     * then we return unknown 
                     * */
                    if (OcspConfigurationCache.INSTANCE.isNonExistingGood(requestUrl,
                            ocspSigningCacheEntry.getOcspKeyBinding())
                            && OcspSigningCache.INSTANCE.getEntry(certId) != null) {
                        sStatus = "good";
                        certStatus = null; // null means "good" in OCSP
                        if (transactionLogger.isEnabled()) {
                            transactionLogger.paramPut(TransactionLogger.CERT_STATUS,
                                    OCSPResponseItem.OCSP_GOOD);
                        }
                    } else if (OcspConfigurationCache.INSTANCE.isNonExistingRevoked(requestUrl,
                            ocspSigningCacheEntry.getOcspKeyBinding())
                            && OcspSigningCache.INSTANCE.getEntry(certId) != null) {
                        sStatus = "revoked";
                        certStatus = new RevokedStatus(new RevokedInfo(new ASN1GeneralizedTime(new Date(0)),
                                CRLReason.lookup(CRLReason.certificateHold)));
                        if (transactionLogger.isEnabled()) {
                            transactionLogger.paramPut(TransactionLogger.CERT_STATUS,
                                    OCSPResponseItem.OCSP_REVOKED);
                        }
                        addExtendedRevokedExtension = true;
                    } else {
                        sStatus = "unknown";
                        certStatus = new UnknownStatus();
                        if (transactionLogger.isEnabled()) {
                            transactionLogger.paramPut(TransactionLogger.CERT_STATUS,
                                    OCSPResponseItem.OCSP_UNKNOWN);
                        }
                    }
                } else if (status.equals(CertificateStatus.REVOKED)) {
                    // Revocation info available for this cert, handle it
                    sStatus = "revoked";
                    certStatus = new RevokedStatus(
                            new RevokedInfo(new ASN1GeneralizedTime(status.revocationDate),
                                    CRLReason.lookup(status.revocationReason)));
                    if (transactionLogger.isEnabled()) {
                        transactionLogger.paramPut(TransactionLogger.CERT_STATUS,
                                OCSPResponseItem.OCSP_REVOKED);
                    }
                    // If we have an explicit value configured for this certificate profile, we override the the current value with this value
                    if (status.certificateProfileId != CertificateProfileConstants.CERTPROFILE_NO_PROFILE
                            && OcspConfiguration
                                    .isRevokedUntilNextUpdateConfigured(status.certificateProfileId)) {
                        nextUpdate = OcspConfiguration.getRevokedUntilNextUpdate(status.certificateProfileId);
                    }
                    // If we have an explicit value configured for this certificate profile, we override the the current value with this value
                    if (status.certificateProfileId != CertificateProfileConstants.CERTPROFILE_NO_PROFILE
                            && OcspConfiguration.isRevokedMaxAgeConfigured(status.certificateProfileId)) {
                        maxAge = OcspConfiguration.getRevokedMaxAge(status.certificateProfileId);
                    }
                } else {
                    sStatus = "good";
                    certStatus = null;
                    if (transactionLogger.isEnabled()) {
                        transactionLogger.paramPut(TransactionLogger.CERT_STATUS, OCSPResponseItem.OCSP_GOOD);
                    }
                    addArchiveCutoff = checkAddArchiveCuttoff(caCertificateSubjectDn, certId);
                }

                if (log.isDebugEnabled()) {
                    log.debug("Set nextUpdate=" + nextUpdate + ", and maxAge=" + maxAge
                            + " for certificateProfileId=" + status.certificateProfileId);
                }

                infoMsg = intres.getLocalizedMessage("ocsp.infoaddedstatusinfo", sStatus,
                        certId.getSerialNumber().toString(16), caCertificateSubjectDn);
                log.info(infoMsg);
                OCSPResponseItem respItem = new OCSPResponseItem(certId, certStatus, nextUpdate);
                if (addArchiveCutoff) {
                    addArchiveCutoff(respItem);
                    producedAt = new Date();
                }
                responseList.add(respItem);
                if (transactionLogger.isEnabled()) {
                    transactionLogger.writeln();
                }
            }
            for (String oidstr : extensionOids) {
                boolean useAlways = false;
                if (oidstr.startsWith("*")) {
                    oidstr = oidstr.substring(1, oidstr.length());
                    useAlways = true;
                }
                ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(oidstr);
                Extension extension = null;
                if (!useAlways) {
                    // Only check if extension exists if we are not already bound to use it
                    if (req.hasExtensions()) {
                        extension = req.getExtension(oid);
                    }
                }
                //If found, or if it should be used anyway
                if (useAlways || extension != null) {
                    // We found an extension, call the extension class
                    if (log.isDebugEnabled()) {
                        log.debug("Found OCSP extension oid: " + oidstr);
                    }
                    OCSPExtension extObj = OcspExtensionsCache.INSTANCE.getExtensions().get(oidstr);
                    if (extObj != null) {
                        // Find the certificate from the certId
                        if (certificateStatusHolder != null
                                && certificateStatusHolder.getCertificate() != null) {
                            X509Certificate cert = (X509Certificate) certificateStatusHolder.getCertificate();
                            // Call the OCSP extension
                            Map<ASN1ObjectIdentifier, Extension> retext = extObj.process(requestCertificates,
                                    remoteAddress, remoteHost, cert, certStatus);
                            if (retext != null) {
                                // Add the returned X509Extensions to the responseExtension we will add to the basic OCSP response
                                responseExtensions.putAll(retext);
                            } else {
                                String errMsg = intres.getLocalizedMessage("ocsp.errorprocessextension",
                                        extObj.getClass().getName(),
                                        Integer.valueOf(extObj.getLastErrorCode()));
                                log.error(errMsg);
                            }
                        }
                    }
                }
            }
        }
        if (addExtendedRevokedExtension) {
            // id-pkix-ocsp-extended-revoke OBJECT IDENTIFIER ::= {id-pkix-ocsp 9}
            final ASN1ObjectIdentifier extendedRevokedOID = new ASN1ObjectIdentifier(
                    OCSPObjectIdentifiers.id_pkix_ocsp + ".9");
            try {
                responseExtensions.put(extendedRevokedOID,
                        new Extension(extendedRevokedOID, false, DERNull.INSTANCE.getEncoded()));
            } catch (IOException e) {
                throw new IllegalStateException("Could not get encodig from DERNull.", e);
            }
        }
        if (ocspSigningCacheEntry != null) {
            // Add responseExtensions
            Extensions exts = new Extensions(responseExtensions.values().toArray(new Extension[0]));
            // generate the signed response object
            BasicOCSPResp basicresp = signOcspResponse(req, responseList, exts, ocspSigningCacheEntry,
                    producedAt);
            ocspResponse = responseGenerator.build(OCSPRespBuilder.SUCCESSFUL, basicresp);
            if (auditLogger.isEnabled()) {
                auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.SUCCESSFUL);
            }
            if (transactionLogger.isEnabled()) {
                transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.SUCCESSFUL);
            }
        } else {
            // Only unknown CAs in requests and no default responder's cert, return an unsigned response
            if (log.isDebugEnabled()) {
                log.debug(intres.getLocalizedMessage("ocsp.errornocacreateresp"));
            }
            ocspResponse = responseGenerator.build(OCSPRespBuilder.UNAUTHORIZED, null);
            if (auditLogger.isEnabled()) {
                auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.UNAUTHORIZED);
            }
            if (transactionLogger.isEnabled()) {
                transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.UNAUTHORIZED);
            }
        }
    } catch (SignRequestException e) {
        if (transactionLogger.isEnabled()) {
            transactionLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
        }
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
        }
        String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
        log.info(errMsg); // No need to log the full exception here
        // RFC 2560: responseBytes are not set on error.
        ocspResponse = responseGenerator.build(OCSPRespBuilder.SIG_REQUIRED, null);
        if (transactionLogger.isEnabled()) {
            transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.SIG_REQUIRED);
            transactionLogger.writeln();
        }
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.SIG_REQUIRED);
        }
    } catch (SignRequestSignatureException e) {
        if (transactionLogger.isEnabled()) {
            transactionLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
        }
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
        }
        String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
        log.info(errMsg); // No need to log the full exception here
        // RFC 2560: responseBytes are not set on error.
        ocspResponse = responseGenerator.build(OCSPRespBuilder.UNAUTHORIZED, null);
        if (transactionLogger.isEnabled()) {
            transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.UNAUTHORIZED);
            transactionLogger.writeln();
        }
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.UNAUTHORIZED);
        }
    } catch (InvalidAlgorithmException e) {
        if (transactionLogger.isEnabled()) {
            transactionLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
        }
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
        }
        String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
        log.info(errMsg); // No need to log the full exception here
        // RFC 2560: responseBytes are not set on error.
        ocspResponse = responseGenerator.build(OCSPRespBuilder.MALFORMED_REQUEST, null);
        if (transactionLogger.isEnabled()) {
            transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.MALFORMED_REQUEST);
            transactionLogger.writeln();
        }
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.MALFORMED_REQUEST);
        }
    } catch (NoSuchAlgorithmException e) {
        ocspResponse = processDefaultError(responseGenerator, transactionLogger, auditLogger, e);
    } catch (CertificateException e) {
        ocspResponse = processDefaultError(responseGenerator, transactionLogger, auditLogger, e);
    } catch (CryptoTokenOfflineException e) {
        ocspResponse = processDefaultError(responseGenerator, transactionLogger, auditLogger, e);
    }
    try {
        respBytes = ocspResponse.getEncoded();
        if (auditLogger.isEnabled()) {
            auditLogger.paramPut(AuditLogger.OCSPRESPONSE, new String(Hex.encode(respBytes)));
            auditLogger.writeln();
            auditLogger.flush();
        }
        if (transactionLogger.isEnabled()) {
            transactionLogger.flush();
        }
        if (OcspConfiguration.getLogSafer()) {
            // See if the Errorhandler has found any problems
            if (hasErrorHandlerFailedSince(startTime)) {
                log.info("ProbableErrorhandler reported error, cannot answer request");
                // RFC 2560: responseBytes are not set on error.
                ocspResponse = responseGenerator.build(OCSPRespBuilder.INTERNAL_ERROR, null);

            }
            // See if the Appender has reported any problems
            if (!CanLogCache.INSTANCE.canLog()) {
                log.info("SaferDailyRollingFileAppender reported error, cannot answer request");
                // RFC 2560: responseBytes are not set on error.
                ocspResponse = responseGenerator.build(OCSPRespBuilder.INTERNAL_ERROR, null);
            }
        }
    } catch (IOException e) {
        log.error("Unexpected IOException caught.", e);
        if (transactionLogger.isEnabled()) {
            transactionLogger.flush();
        }
        if (auditLogger.isEnabled()) {
            auditLogger.flush();
        }
    }
    return new OcspResponseInformation(ocspResponse, maxAge);
}

From source file:org.cesecore.certificates.ocsp.CanLogCache.java

License:Open Source License

public byte[] getOcspResponse(AuthenticationToken authenticationToken, byte[] request,
        X509Certificate[] requestCertificates, String remoteAddress, String remoteHost)
        throws AuthorizationDeniedException, MalformedRequestException {
    initiateIfNecessary();/*from   w w w .  j  av a2s .  c o  m*/

    // Validate byte array.
    if (request.length > MAX_REQUEST_SIZE) {
        final String msg = intres.getLocalizedMessage("request.toolarge", MAX_REQUEST_SIZE, request.length);
        throw new MalformedRequestException(msg);
    }

    byte[] respBytes = null;

    final Date startTime = new Date();

    OCSPResp ocspResponse = null;

    int localTransactionId = TransactionCounter.INSTANCE.getTransactionNumber();
    // Create the transaction logger for this transaction.
    TransactionLogger transactionLogger = new TransactionLogger(localTransactionId,
            GuidHolder.INSTANCE.getGlobalUid(), remoteAddress);
    // Create the audit logger for this transaction.
    AuditLogger auditLogger = new AuditLogger("", localTransactionId, GuidHolder.INSTANCE.getGlobalUid(),
            remoteAddress);

    // Start logging process time after we have received the request
    transactionLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
    auditLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
    auditLogger.paramPut(AuditLogger.OCSPREQUEST, new String(Hex.encode(request)));

    OCSPReq req;

    OCSPRespGenerator responseGenerator = new OCSPRespGenerator();

    try {
        try {
            req = translateRequestFromByteArray(request, remoteAddress, transactionLogger);

            // Get the certificate status requests that are inside this OCSP req
            Req[] ocspRequests = req.getRequestList();

            if (ocspRequests.length <= 0) {
                String infoMsg = intres.getLocalizedMessage("ocsp.errornoreqentities");
                log.info(infoMsg);
                throw new MalformedRequestException(infoMsg);
            }
            int maxRequests = 100;
            if (ocspRequests.length > maxRequests) {
                String infoMsg = intres.getLocalizedMessage("ocsp.errortoomanyreqentities", maxRequests);
                log.info(infoMsg);
                throw new MalformedRequestException(infoMsg);
            }

            if (log.isDebugEnabled()) {
                log.debug("The OCSP request contains " + ocspRequests.length + " simpleRequests.");
            }

            transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespGenerator.SUCCESSFUL);
            auditLogger.paramPut(AuditLogger.STATUS, OCSPRespGenerator.SUCCESSFUL);

            CryptoTokenAndChain signerTokenAndChain = null;

            long maxAge = OcspConfiguration.getMaxAge(CertificateProfileConstants.CERTPROFILE_NO_PROFILE);
            long nextUpdate = OcspConfiguration
                    .getUntilNextUpdate(CertificateProfileConstants.CERTPROFILE_NO_PROFILE);

            // Add standard response extensions
            Hashtable<DERObjectIdentifier, X509Extension> responseExtensions = getStandardResponseExtensions(
                    req);

            // Look for extension OIDs
            final Collection<String> extensionOids = OcspConfiguration.getExtensionOids();

            // Look over the status requests
            List<OCSPResponseItem> responseList = new ArrayList<OCSPResponseItem>();
            for (Req ocspRequest : ocspRequests) {
                CertificateID certId = ocspRequest.getCertID();

                transactionLogger.paramPut(TransactionLogger.SERIAL_NOHEX,
                        certId.getSerialNumber().toByteArray());
                // TODO:find text version of this or find out if it should be something else
                transactionLogger.paramPut(TransactionLogger.DIGEST_ALGOR, certId.getHashAlgOID());
                transactionLogger.paramPut(TransactionLogger.ISSUER_NAME_HASH, certId.getIssuerNameHash());
                transactionLogger.paramPut(TransactionLogger.ISSUER_KEY, certId.getIssuerKeyHash());
                auditLogger.paramPut(AuditLogger.ISSUER_KEY, certId.getIssuerKeyHash());
                auditLogger.paramPut(AuditLogger.SERIAL_NOHEX, certId.getSerialNumber().toByteArray());
                auditLogger.paramPut(AuditLogger.ISSUER_NAME_HASH, certId.getIssuerNameHash());

                byte[] hashbytes = certId.getIssuerNameHash();
                String hash = null;
                if (hashbytes != null) {
                    hash = new String(Hex.encode(hashbytes));
                }
                String infoMsg = intres.getLocalizedMessage("ocsp.inforeceivedrequest",
                        certId.getSerialNumber().toString(16), hash, remoteAddress);
                log.info(infoMsg);

                // Locate the CA which gave out the certificate
                signerTokenAndChain = getTokenAndChainCache().get(certId);
                /*
                 * if the certId was issued by an unknown CA 
                 * 
                 * The algorithm here: 
                 * We will sign the response with the CA that issued the last certificate(certId) in the request. If the issuing CA is not available on 
                 * this server, we sign the response with the default responderId (from params in web.xml). We have to look up the ca-certificate for 
                 * each certId in the request though, as we will check for revocation on the ca-cert as well when checking for revocation on the certId.
                 */

                if (signerTokenAndChain != null) {
                    transactionLogger.paramPut(TransactionLogger.ISSUER_NAME_DN,
                            signerTokenAndChain.getCaCertificate().getSubjectDN().getName());
                } else {
                    // We could not find certificate for this request so get certificate for default responder
                    signerTokenAndChain = getTokenAndChainCache().getForDefaultResponder();
                    if (signerTokenAndChain != null) {
                        String errMsg = intres.getLocalizedMessage("ocsp.errorfindcacertusedefault",
                                new String(Hex.encode(certId.getIssuerNameHash())));
                        log.info(errMsg);
                        // If we can not find the CA, answer UnknowStatus
                        responseList.add(new OCSPResponseItem(certId, new UnknownStatus(), nextUpdate));
                        transactionLogger.paramPut(TransactionLogger.CERT_STATUS,
                                OCSPResponseItem.OCSP_UNKNOWN);
                        transactionLogger.writeln();
                        continue;
                    } else {
                        String errMsg = intres.getLocalizedMessage("ocsp.errorfindcacert",
                                new String(Hex.encode(certId.getIssuerNameHash())),
                                OcspConfiguration.getDefaultResponderId());
                        log.error(errMsg);
                        continue;
                    }
                }

                /*
                 * Implement logic according to chapter 2.7 in RFC2560
                 * 
                 * 2.7 CA Key Compromise If an OCSP responder knows that a particular CA's private key has been compromised, it MAY return the revoked
                 * state for all certificates issued by that CA.
                 */
                final org.bouncycastle.ocsp.CertificateStatus certStatus;
                transactionLogger.paramPut(TransactionLogger.CERT_STATUS, OCSPResponseItem.OCSP_GOOD); // it seems to be correct

                // Check if the cacert (or the default responderid) is revoked
                final CertificateStatus signerIssuerCertStatus = certificateStoreSession.getStatus(
                        CertTools.getSubjectDN(signerTokenAndChain.getCaCertificate()),
                        CertTools.getSerialNumber(signerTokenAndChain.getCaCertificate()));

                String subjectDn = signerTokenAndChain.getCaCertificate().getSubjectDN().getName();
                if (!signerIssuerCertStatus.equals(CertificateStatus.REVOKED)) {

                    // Check if cert is revoked
                    final CertificateStatus status = certificateStoreSession.getStatus(subjectDn,
                            certId.getSerialNumber());

                    /* If we have different maxAge and untilNextUpdate for different certificate profiles, we have to fetch these
                     values now that we have fetched the certificate status, that includes certificate profile.*/
                    nextUpdate = OcspConfiguration.getUntilNextUpdate(status.certificateProfileId);
                    maxAge = OcspConfiguration.getMaxAge(status.certificateProfileId);
                    if (log.isDebugEnabled()) {
                        log.debug("Set nextUpdate=" + nextUpdate + ", and maxAge=" + maxAge
                                + " for certificateProfileId=" + status.certificateProfileId);
                    }

                    final String sStatus;
                    if (status.equals(CertificateStatus.NOT_AVAILABLE)) {
                        // No revocation info available for this cert, handle it
                        if (log.isDebugEnabled()) {
                            log.debug("Unable to find revocation information for certificate with serial '"
                                    + certId.getSerialNumber().toString(16) + "'" + " from issuer '" + subjectDn
                                    + "'");
                        }
                        /* 
                         * If we do not treat non existing certificates as good
                         * OR
                         * we don't actually handle requests for the CA issuing the certificate asked about
                         * then we return unknown 
                         * */
                        if ((!OcspConfiguration.getNonExistingIsGood())
                                || (getTokenAndChainCache().get(certId) == null)) {
                            sStatus = "unknown";
                            certStatus = new UnknownStatus();

                        } else {
                            sStatus = "good";
                            certStatus = null; // null means "good" in OCSP

                        }
                    } else if (status.equals(CertificateStatus.REVOKED)) {
                        // Revocation info available for this cert, handle it
                        sStatus = "revoked";
                        certStatus = new RevokedStatus(
                                new RevokedInfo(new DERGeneralizedTime(status.revocationDate),
                                        new CRLReason(status.revocationReason)));
                    } else {
                        sStatus = "good";
                        certStatus = null;

                    }
                    infoMsg = intres.getLocalizedMessage("ocsp.infoaddedstatusinfo", sStatus,
                            certId.getSerialNumber().toString(16), subjectDn);
                    log.info(infoMsg);
                    responseList.add(new OCSPResponseItem(certId, certStatus, nextUpdate));

                } else {
                    certStatus = new RevokedStatus(
                            new RevokedInfo(new DERGeneralizedTime(signerIssuerCertStatus.revocationDate),
                                    new CRLReason(signerIssuerCertStatus.revocationReason)));
                    infoMsg = intres.getLocalizedMessage("ocsp.infoaddedstatusinfo", "revoked",
                            certId.getSerialNumber().toString(16), subjectDn);
                    log.info(infoMsg);
                    responseList.add(new OCSPResponseItem(certId, certStatus, nextUpdate));

                }
                for (String oidstr : extensionOids) {
                    DERObjectIdentifier oid = new DERObjectIdentifier(oidstr);
                    X509Extensions reqexts = req.getRequestExtensions();
                    if (reqexts != null) {
                        X509Extension ext = reqexts.getExtension(oid);
                        if (null != ext) {
                            // We found an extension, call the extension class
                            if (log.isDebugEnabled()) {
                                log.debug("Found OCSP extension oid: " + oidstr);
                            }
                            OCSPExtension extObj = OcspExtensionsCache.INSTANCE.getExtensions().get(oidstr);
                            if (extObj != null) {
                                // Find the certificate from the certId
                                X509Certificate cert = null;
                                cert = (X509Certificate) certificateStoreSession
                                        .findCertificateByIssuerAndSerno(subjectDn, certId.getSerialNumber());
                                if (cert != null) {
                                    // Call the OCSP extension
                                    Map<DERObjectIdentifier, X509Extension> retext = extObj.process(
                                            requestCertificates, remoteAddress, remoteHost, cert, certStatus);
                                    if (retext != null) {
                                        // Add the returned X509Extensions to the responseExtension we will add to the basic OCSP response
                                        responseExtensions.putAll(retext);
                                    } else {
                                        String errMsg = intres.getLocalizedMessage("ocsp.errorprocessextension",
                                                extObj.getClass().getName(),
                                                Integer.valueOf(extObj.getLastErrorCode()));
                                        log.error(errMsg);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (signerTokenAndChain != null) {
                // Add responseExtensions
                X509Extensions exts = new X509Extensions(responseExtensions);
                // generate the signed response object

                final X509Certificate[] signerChain = signerTokenAndChain.getChain();
                final PrivateKey privateKey = signerTokenAndChain.getPrivateKey();
                final String privateKeyProvider = signerTokenAndChain.getSignProviderName();
                BasicOCSPResp basicresp = signOcspResponse(req, responseList, exts, signerChain, privateKey,
                        privateKeyProvider);
                ocspResponse = responseGenerator.generate(OCSPRespGenerator.SUCCESSFUL, basicresp);
                auditLogger.paramPut(AuditLogger.STATUS, OCSPRespGenerator.SUCCESSFUL);
                transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespGenerator.SUCCESSFUL);
            } else {
                // Only unknown CAs in requests and no default responder's cert
                String errMsg = intres.getLocalizedMessage("ocsp.errornocacreateresp");
                log.error(errMsg);
                throw new OcspFailureException(errMsg);
            }
        } catch (MalformedRequestException e) {
            transactionLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
            auditLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
            String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
            log.info(errMsg);
            if (log.isDebugEnabled()) {
                log.debug(errMsg, e);
            }
            ocspResponse = responseGenerator.generate(OCSPRespGenerator.MALFORMED_REQUEST, null); // RFC 2560: responseBytes are not set on error.
            transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespGenerator.MALFORMED_REQUEST);
            transactionLogger.writeln();
            auditLogger.paramPut(AuditLogger.STATUS, OCSPRespGenerator.MALFORMED_REQUEST);
        } catch (SignRequestException e) {
            transactionLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
            auditLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
            String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
            log.info(errMsg); // No need to log the full exception here
            ocspResponse = responseGenerator.generate(OCSPRespGenerator.SIG_REQUIRED, null); // RFC 2560: responseBytes are not set on error.
            transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespGenerator.SIG_REQUIRED);
            transactionLogger.writeln();
            auditLogger.paramPut(AuditLogger.STATUS, OCSPRespGenerator.SIG_REQUIRED);
        } catch (SignRequestSignatureException e) {
            transactionLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
            auditLogger.paramPut(PatternLogger.PROCESS_TIME, PatternLogger.PROCESS_TIME);
            String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
            log.info(errMsg); // No need to log the full exception here
            ocspResponse = responseGenerator.generate(OCSPRespGenerator.UNAUTHORIZED, null); // RFC 2560: responseBytes are not set on error.
            transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespGenerator.UNAUTHORIZED);
            transactionLogger.writeln();
            auditLogger.paramPut(AuditLogger.STATUS, OCSPRespGenerator.UNAUTHORIZED);
        } catch (NoSuchAlgorithmException e) {
            ocspResponse = processDefaultError(responseGenerator, transactionLogger, auditLogger, e);
        } catch (CertificateException e) {
            ocspResponse = processDefaultError(responseGenerator, transactionLogger, auditLogger, e);
        } catch (ExtendedCAServiceNotActiveException e) {
            ocspResponse = processDefaultError(responseGenerator, transactionLogger, auditLogger, e);
        } catch (IllegalExtendedCAServiceRequestException e) {
            ocspResponse = processDefaultError(responseGenerator, transactionLogger, auditLogger, e);
        } catch (ExtendedCAServiceRequestException e) {
            ocspResponse = processDefaultError(responseGenerator, transactionLogger, auditLogger, e);
        } catch (CADoesntExistsException e) {
            ocspResponse = processDefaultError(responseGenerator, transactionLogger, auditLogger, e);
        } catch (IllegalCryptoTokenException e) {
            ocspResponse = processDefaultError(responseGenerator, transactionLogger, auditLogger, e);
        } catch (CryptoTokenOfflineException e) {
            ocspResponse = processDefaultError(responseGenerator, transactionLogger, auditLogger, e);
        }

        try {
            respBytes = ocspResponse.getEncoded();
            auditLogger.paramPut(AuditLogger.OCSPRESPONSE, new String(Hex.encode(respBytes)));
            auditLogger.writeln();
            auditLogger.flush();
            transactionLogger.flush();
            if (OcspConfiguration.getLogSafer()) {
                // See if the Errorhandler has found any problems
                if (hasErrorHandlerFailedSince(startTime)) {
                    log.info("ProbableErrorhandler reported error, cannot answer request");
                    ocspResponse = responseGenerator.generate(OCSPRespGenerator.INTERNAL_ERROR, null); // RFC 2560: responseBytes are not set on
                                                                                                       // error.
                    respBytes = ocspResponse.getEncoded();
                }
                // See if the Appender has reported any problems
                if (!CanLogCache.INSTANCE.canLog()) {
                    log.info("SaferDailyRollingFileAppender reported error, cannot answer request");
                    ocspResponse = responseGenerator.generate(OCSPRespGenerator.INTERNAL_ERROR, null); // RFC 2560: responseBytes are not set on
                                                                                                       // error.
                    respBytes = ocspResponse.getEncoded();
                }
            }
        } catch (IOException e) {
            log.error("", e);
            transactionLogger.flush();
            auditLogger.flush();
        }
    } catch (OCSPException e) {
        throw new OcspFailureException("OCSP response generation failed", e);
    }

    return respBytes;

}

From source file:org.ejbca.ui.web.protocol.OCSPServletBase.java

License:Open Source License

/** Performs service of the actual OCSP request, which is contained in reqBytes. 
 *  // w w  w .  ja va 2 s  . c o m
 *  @param reqBytes the binary OCSP request bytes. This parameter must already have been checked for max or min size. 
 */
public void serviceOCSP(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException {
    if (m_log.isTraceEnabled()) {
        m_log.trace(">service()");
    }
    final int localTransactionID;
    synchronized (this) {
        this.mTransactionID += 1;
        localTransactionID = this.mTransactionID;
    }
    final IPatternLogger transactionLogger;
    final IPatternLogger auditLogger;
    final Date startTime = new Date();
    if (this.mDoTransactionLog) {
        transactionLogger = this.transactionLogger.getPatternLogger();
    } else {
        transactionLogger = new DummyPatternLogger(); // Ignores everything
    }
    if (this.mDoAuditLog) {
        auditLogger = this.auditLogger.getPatternLogger();
    } else {
        auditLogger = new DummyPatternLogger(); // Ignores everything
    }
    final String remoteAddress = request.getRemoteAddr();
    auditLogger.paramPut(IAuditLogger.OCSPREQUEST, ""); // No request bytes yet
    auditLogger.paramPut(IPatternLogger.LOG_ID, new Integer(localTransactionID));
    auditLogger.paramPut(IPatternLogger.SESSION_ID, this.m_SessionID);
    auditLogger.paramPut(IOCSPLogger.CLIENT_IP, remoteAddress);
    transactionLogger.paramPut(IPatternLogger.LOG_ID, new Integer(localTransactionID));
    transactionLogger.paramPut(IPatternLogger.SESSION_ID, this.m_SessionID);
    transactionLogger.paramPut(IOCSPLogger.CLIENT_IP, remoteAddress);

    try {
        // Read configuration values affecting the response, these can be dynamically updated from properties files in file system
        // Read default values here for each request since may take a millisecond to read the value
        // These values can be changed depending on if there are different configurations for different certificate profiles
        // In that case it is updated once we have read the certificate status of the certificate searched for.
        long maxAge = OcspConfiguration.getMaxAge(SecConst.CERTPROFILE_NO_PROFILE);
        long nextUpdate = OcspConfiguration.getUntilNextUpdate(SecConst.CERTPROFILE_NO_PROFILE);

        OCSPResp ocspresp = null;
        OCSPRespGenerator res = new OCSPRespGenerator();
        X509Certificate cacert = null; // CA-certificate used to sign response
        try {
            byte[] reqBytes = checkAndGetRequestBytes(request);
            // Start logging process time after we have received the request
            transactionLogger.paramPut(IPatternLogger.PROCESS_TIME, IPatternLogger.PROCESS_TIME);
            auditLogger.paramPut(IPatternLogger.PROCESS_TIME, IPatternLogger.PROCESS_TIME);
            auditLogger.paramPut(IAuditLogger.OCSPREQUEST, new String(Hex.encode(reqBytes)));
            OCSPReq req = null;
            try {
                req = new OCSPReq(reqBytes);
            } catch (Exception e) {
                // When not being able to parse the request, we want to send a MalformedRequest back
                throw new MalformedRequestException(e);
            }
            if (req.getRequestorName() == null) {
                m_log.debug("Requestorname is null");
            } else {
                if (m_log.isDebugEnabled()) {
                    m_log.debug("Requestorname is: " + req.getRequestorName().toString());
                }
                transactionLogger.paramPut(ITransactionLogger.REQ_NAME, req.getRequestorName().toString());
            }
            // Make sure our signature keys are updated
            loadPrivateKeys(this.data.m_adm, null);

            /**
             * check the signature if contained in request.
             * if the request does not contain a signature
             * and the servlet is configured in the way 
             * the a signature is required we send back
             * 'sigRequired' response.
             */
            if (m_log.isDebugEnabled()) {
                m_log.debug("Incoming OCSP request is signed : " + req.isSigned());
            }
            if (req.isSigned()) {
                X509Certificate signercert = OCSPUtil.checkRequestSignature(request.getRemoteAddr(), req,
                        this.data.m_caCertCache);
                String signercertIssuerName = CertTools.getIssuerDN(signercert);
                BigInteger signercertSerNo = CertTools.getSerialNumber(signercert);
                String signercertSubjectName = CertTools.getSubjectDN(signercert);
                transactionLogger.paramPut(ITransactionLogger.SIGN_ISSUER_NAME_DN, signercertIssuerName);
                transactionLogger.paramPut(ITransactionLogger.SIGN_SERIAL_NO,
                        signercert.getSerialNumber().toByteArray());
                transactionLogger.paramPut(ITransactionLogger.SIGN_SUBJECT_NAME, signercertSubjectName);
                transactionLogger.paramPut(IPatternLogger.REPLY_TIME, ITransactionLogger.REPLY_TIME);
                if (OcspConfiguration.getEnforceRequestSigning()) {
                    // If it verifies OK, check if it is revoked
                    final CertificateStatus status = this.data.certificateStoreSession.getStatus(
                            CertTools.getIssuerDN(signercert), CertTools.getSerialNumber(signercert));
                    // If rci == null it means the certificate does not exist in database, we then treat it as ok,
                    // because it may be so that only revoked certificates is in the (external) OCSP database.
                    if (status.equals(CertificateStatus.REVOKED)) {
                        String serno = signercertSerNo.toString(16);
                        String infoMsg = intres.getLocalizedMessage("ocsp.infosigner.revoked",
                                signercertSubjectName, signercertIssuerName, serno);
                        m_log.info(infoMsg);
                        throw new SignRequestSignatureException(infoMsg);
                    }

                    if (m_reqRestrictSignatures) {
                        loadTrustDir();
                        if (m_reqRestrictMethod == OcspConfiguration.RESTRICTONSIGNER) {
                            if (!OCSPUtil.checkCertInList(signercert, mTrustedReqSigSigners)) {
                                String infoMsg = intres.getLocalizedMessage("ocsp.infosigner.notallowed",
                                        signercertSubjectName, signercertIssuerName,
                                        signercertSerNo.toString(16));
                                m_log.info(infoMsg);
                                throw new SignRequestSignatureException(infoMsg);
                            }
                        } else if (m_reqRestrictMethod == OcspConfiguration.RESTRICTONISSUER) {
                            X509Certificate signerca = this.data.m_caCertCache
                                    .findLatestBySubjectDN(HashID.getFromDN(signercertIssuerName));
                            if ((signerca == null)
                                    || (!OCSPUtil.checkCertInList(signerca, mTrustedReqSigIssuers))) {
                                String infoMsg = intres.getLocalizedMessage("ocsp.infosigner.notallowed",
                                        signercertSubjectName, signercertIssuerName,
                                        signercertSerNo.toString(16));
                                m_log.info(infoMsg);
                                throw new SignRequestSignatureException(infoMsg);
                            }
                        } else {
                            throw new Exception("m_reqRestrictMethod=" + m_reqRestrictMethod); // there must be an internal error. We do not want to send a response, just to be safe.
                        }
                    }
                }
            } else {
                if (OcspConfiguration.getEnforceRequestSigning()) {
                    // Signature required
                    throw new SignRequestException("Signature required");
                }
            }

            // Get the certificate status requests that are inside this OCSP req
            Req[] requests = req.getRequestList();
            transactionLogger.paramPut(ITransactionLogger.NUM_CERT_ID, requests.length);
            if (requests.length <= 0) {
                String infoMsg = intres.getLocalizedMessage("ocsp.errornoreqentities");
                m_log.info(infoMsg);
                {
                    // All this just so we can create an error response
                    cacert = this.data.m_caCertCache
                            .findLatestBySubjectDN(HashID.getFromDN(this.data.m_defaultResponderId));
                }
                throw new MalformedRequestException(infoMsg);
            }
            int maxRequests = 100;
            if (requests.length > maxRequests) {
                String infoMsg = intres.getLocalizedMessage("ocsp.errortoomanyreqentities", maxRequests);
                m_log.info(infoMsg);
                {
                    // All this just so we can create an error response
                    cacert = this.data.m_caCertCache
                            .findLatestBySubjectDN(HashID.getFromDN(this.data.m_defaultResponderId));
                }
                throw new MalformedRequestException(infoMsg);
            }

            if (m_log.isDebugEnabled()) {
                m_log.debug("The OCSP request contains " + requests.length + " simpleRequests.");
            }

            // Add standard response extensions
            Hashtable responseExtensions = OCSPUtil.getStandardResponseExtensions(req);
            transactionLogger.paramPut(ITransactionLogger.STATUS, OCSPRespGenerator.SUCCESSFUL);
            auditLogger.paramPut(IAuditLogger.STATUS, OCSPRespGenerator.SUCCESSFUL);
            // Look over the status requests
            ArrayList responseList = new ArrayList();
            for (int i = 0; i < requests.length; i++) {
                CertificateID certId = requests[i].getCertID();
                // now some Logging
                transactionLogger.paramPut(ITransactionLogger.SERIAL_NOHEX,
                        certId.getSerialNumber().toByteArray());
                transactionLogger.paramPut(ITransactionLogger.DIGEST_ALGOR, certId.getHashAlgOID()); //todo, find text version of this or find out if it should be something else               
                transactionLogger.paramPut(ITransactionLogger.ISSUER_NAME_HASH, certId.getIssuerNameHash());
                transactionLogger.paramPut(ITransactionLogger.ISSUER_KEY, certId.getIssuerKeyHash());
                auditLogger.paramPut(IAuditLogger.ISSUER_KEY, certId.getIssuerKeyHash());
                auditLogger.paramPut(IAuditLogger.SERIAL_NOHEX, certId.getSerialNumber().toByteArray());
                auditLogger.paramPut(IAuditLogger.ISSUER_NAME_HASH, certId.getIssuerNameHash());
                byte[] hashbytes = certId.getIssuerNameHash();
                String hash = null;
                if (hashbytes != null) {
                    hash = new String(Hex.encode(hashbytes));
                }
                String infoMsg = intres.getLocalizedMessage("ocsp.inforeceivedrequest",
                        certId.getSerialNumber().toString(16), hash, request.getRemoteAddr());
                m_log.info(infoMsg);
                boolean unknownCA = false;
                // if the certId was issued by an unknown CA
                // The algorithm here:
                // We will sign the response with the CA that issued the first 
                // certificate(certId) in the request. If the issuing CA is not available
                // on this server, we sign the response with the default responderId (from params in web.xml).
                // We have to look up the ca-certificate for each certId in the request though, as we will check
                // for revocation on the ca-cert as well when checking for revocation on the certId. 
                cacert = this.data.m_caCertCache.findByOcspHash(certId); // Get the issuer of certId
                if (cacert == null) {
                    // We could not find certificate for this request so get certificate for default responder
                    cacert = this.data.m_caCertCache
                            .findLatestBySubjectDN(HashID.getFromDN(this.data.m_defaultResponderId));
                    unknownCA = true;
                }
                if (cacert == null) {
                    String errMsg = intres.getLocalizedMessage("ocsp.errorfindcacert",
                            new String(Hex.encode(certId.getIssuerNameHash())), this.data.m_defaultResponderId);
                    m_log.error(errMsg);
                    continue;
                }
                if (unknownCA == true) {
                    String errMsg = intres.getLocalizedMessage("ocsp.errorfindcacertusedefault",
                            new String(Hex.encode(certId.getIssuerNameHash())));
                    m_log.info(errMsg);
                    // If we can not find the CA, answer UnknowStatus
                    responseList.add(new OCSPResponseItem(certId, new UnknownStatus(), nextUpdate));
                    transactionLogger.paramPut(ITransactionLogger.CERT_STATUS, OCSPUnidResponse.OCSP_UNKNOWN);
                    transactionLogger.writeln();
                    continue;
                } else {
                    transactionLogger.paramPut(ITransactionLogger.ISSUER_NAME_DN,
                            cacert.getSubjectDN().getName());
                }
                /*
                 * Implement logic according to
                 * chapter 2.7 in RFC2560
                 * 
                 * 2.7  CA Key Compromise
                 *   If an OCSP responder knows that a particular CA's private key has
                 *   been compromised, it MAY return the revoked state for all
                 *   certificates issued by that CA.
                 */
                final org.bouncycastle.ocsp.CertificateStatus certStatus;
                transactionLogger.paramPut(ITransactionLogger.CERT_STATUS, OCSPUnidResponse.OCSP_GOOD); // it seems to be correct
                // Check if the cacert (or the default responderid) is revoked
                final CertificateStatus cacertStatus = this.data.certificateStoreSession
                        .getStatus(CertTools.getIssuerDN(cacert), CertTools.getSerialNumber(cacert));
                if (!cacertStatus.equals(CertificateStatus.REVOKED)) {
                    // Check if cert is revoked
                    final CertificateStatus status = this.data.certificateStoreSession
                            .getStatus(cacert.getSubjectDN().getName(), certId.getSerialNumber());
                    // If we have different maxAge and untilNextUpdate for different certificate profiles, we have to fetch these
                    // values now that we have fetched the certificate status, that includes certificate profile.
                    nextUpdate = OcspConfiguration.getUntilNextUpdate(status.certificateProfileId);
                    maxAge = OcspConfiguration.getMaxAge(status.certificateProfileId);
                    if (m_log.isDebugEnabled()) {
                        m_log.debug("Set nextUpdate=" + nextUpdate + ", and maxAge=" + maxAge
                                + " for certificateProfileId=" + status.certificateProfileId);
                    }

                    final String sStatus;
                    if (status.equals(CertificateStatus.NOT_AVAILABLE)) {
                        // No revocation info available for this cert, handle it
                        if (m_log.isDebugEnabled()) {
                            m_log.debug("Unable to find revocation information for certificate with serial '"
                                    + certId.getSerialNumber().toString(16) + "'" + " from issuer '"
                                    + cacert.getSubjectDN().getName() + "'");
                        }
                        // If we do not treat non existing certificates as good 
                        // OR
                        // we don't actually handle requests for the CA issuing the certificate asked about
                        // then we return unknown
                        if (!nonExistingIsGood(request.getRequestURL())
                                || this.data.m_caCertCache.findByOcspHash(certId) == null) {
                            sStatus = "unknown";
                            certStatus = new UnknownStatus();
                            transactionLogger.paramPut(ITransactionLogger.CERT_STATUS,
                                    OCSPUnidResponse.OCSP_UNKNOWN);
                        } else {
                            sStatus = "good";
                            certStatus = null; // null means "good" in OCSP
                            transactionLogger.paramPut(ITransactionLogger.CERT_STATUS,
                                    OCSPUnidResponse.OCSP_GOOD);
                        }
                    } else if (status.equals(CertificateStatus.REVOKED)) {
                        // Revocation info available for this cert, handle it
                        sStatus = "revoked";
                        certStatus = new RevokedStatus(
                                new RevokedInfo(new DERGeneralizedTime(status.revocationDate),
                                        new CRLReason(status.revocationReason)));
                        transactionLogger.paramPut(ITransactionLogger.CERT_STATUS,
                                OCSPUnidResponse.OCSP_REVOKED); //1 = revoked
                    } else {
                        sStatus = "good";
                        certStatus = null;
                        transactionLogger.paramPut(ITransactionLogger.CERT_STATUS, OCSPUnidResponse.OCSP_GOOD);
                    }
                    infoMsg = intres.getLocalizedMessage("ocsp.infoaddedstatusinfo", sStatus,
                            certId.getSerialNumber().toString(16), cacert.getSubjectDN().getName());
                    m_log.info(infoMsg);
                    responseList.add(new OCSPResponseItem(certId, certStatus, nextUpdate));
                    transactionLogger.writeln();
                } else {
                    certStatus = new RevokedStatus(
                            new RevokedInfo(new DERGeneralizedTime(cacertStatus.revocationDate),
                                    new CRLReason(cacertStatus.revocationReason)));
                    infoMsg = intres.getLocalizedMessage("ocsp.infoaddedstatusinfo", "revoked",
                            certId.getSerialNumber().toString(16), cacert.getSubjectDN().getName());
                    m_log.info(infoMsg);
                    responseList.add(new OCSPResponseItem(certId, certStatus, nextUpdate));
                    transactionLogger.paramPut(ITransactionLogger.CERT_STATUS, OCSPUnidResponse.OCSP_REVOKED);
                    transactionLogger.writeln();
                }
                // Look for extension OIDs
                Iterator iter = m_extensionOids.iterator();
                while (iter.hasNext()) {
                    String oidstr = (String) iter.next();
                    DERObjectIdentifier oid = new DERObjectIdentifier(oidstr);
                    X509Extensions reqexts = req.getRequestExtensions();
                    if (reqexts != null) {
                        X509Extension ext = reqexts.getExtension(oid);
                        if (null != ext) {
                            // We found an extension, call the extenstion class
                            if (m_log.isDebugEnabled()) {
                                m_log.debug("Found OCSP extension oid: " + oidstr);
                            }
                            IOCSPExtension extObj = (IOCSPExtension) m_extensionMap.get(oidstr);
                            if (extObj != null) {
                                // Find the certificate from the certId
                                X509Certificate cert = null;
                                cert = (X509Certificate) this.data.certificateStoreSession
                                        .findCertificateByIssuerAndSerno(this.data.m_adm,
                                                cacert.getSubjectDN().getName(), certId.getSerialNumber());
                                if (cert != null) {
                                    // Call the OCSP extension
                                    Hashtable retext = extObj.process(request, cert, certStatus);
                                    if (retext != null) {
                                        // Add the returned X509Extensions to the responseExtension we will add to the basic OCSP response
                                        responseExtensions.putAll(retext);
                                    } else {
                                        String errMsg = intres.getLocalizedMessage("ocsp.errorprocessextension",
                                                extObj.getClass().getName(),
                                                new Integer(extObj.getLastErrorCode()));
                                        m_log.error(errMsg);
                                    }
                                }
                            }
                        }
                    }
                }
            } // end of huge for loop
            if (cacert != null) {
                // Add responseExtensions
                X509Extensions exts = new X509Extensions(responseExtensions);
                // generate the signed response object
                BasicOCSPResp basicresp = signOCSPResponse(req, responseList, exts, cacert);
                ocspresp = res.generate(OCSPRespGenerator.SUCCESSFUL, basicresp);
                auditLogger.paramPut(IAuditLogger.STATUS, OCSPRespGenerator.SUCCESSFUL);
                transactionLogger.paramPut(ITransactionLogger.STATUS, OCSPRespGenerator.SUCCESSFUL);
            } else {
                // Only unknown CAs in requests and no default reponders cert 
                String errMsg = intres.getLocalizedMessage("ocsp.errornocacreateresp");
                m_log.error(errMsg);
                throw new ServletException(errMsg);
            }
        } catch (MalformedRequestException e) {
            transactionLogger.paramPut(IPatternLogger.PROCESS_TIME, IPatternLogger.PROCESS_TIME);
            auditLogger.paramPut(IPatternLogger.PROCESS_TIME, IPatternLogger.PROCESS_TIME);
            String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
            m_log.info(errMsg);
            if (m_log.isDebugEnabled()) {
                m_log.debug(errMsg, e);
            }
            ocspresp = res.generate(OCSPRespGenerator.MALFORMED_REQUEST, null); // RFC 2560: responseBytes are not set on error.
            transactionLogger.paramPut(ITransactionLogger.STATUS, OCSPRespGenerator.MALFORMED_REQUEST);
            transactionLogger.writeln();
            auditLogger.paramPut(IAuditLogger.STATUS, OCSPRespGenerator.MALFORMED_REQUEST);
        } catch (SignRequestException e) {
            transactionLogger.paramPut(IPatternLogger.PROCESS_TIME, IPatternLogger.PROCESS_TIME);
            auditLogger.paramPut(IPatternLogger.PROCESS_TIME, IPatternLogger.PROCESS_TIME);
            String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
            m_log.info(errMsg); // No need to log the full exception here
            ocspresp = res.generate(OCSPRespGenerator.SIG_REQUIRED, null); // RFC 2560: responseBytes are not set on error.
            transactionLogger.paramPut(ITransactionLogger.STATUS, OCSPRespGenerator.SIG_REQUIRED);
            transactionLogger.writeln();
            auditLogger.paramPut(IAuditLogger.STATUS, OCSPRespGenerator.SIG_REQUIRED);
        } catch (SignRequestSignatureException e) {
            transactionLogger.paramPut(IPatternLogger.PROCESS_TIME, IPatternLogger.PROCESS_TIME);
            auditLogger.paramPut(IPatternLogger.PROCESS_TIME, IPatternLogger.PROCESS_TIME);
            String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
            m_log.info(errMsg); // No need to log the full exception here
            ocspresp = res.generate(OCSPRespGenerator.UNAUTHORIZED, null); // RFC 2560: responseBytes are not set on error.
            transactionLogger.paramPut(ITransactionLogger.STATUS, OCSPRespGenerator.UNAUTHORIZED);
            transactionLogger.writeln();
            auditLogger.paramPut(IAuditLogger.STATUS, OCSPRespGenerator.UNAUTHORIZED);
        } catch (InvalidKeyException e) {
            transactionLogger.paramPut(IPatternLogger.PROCESS_TIME, IPatternLogger.PROCESS_TIME);
            auditLogger.paramPut(IPatternLogger.PROCESS_TIME, IPatternLogger.PROCESS_TIME);
            String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
            m_log.info(errMsg, e);
            ocspresp = res.generate(OCSPRespGenerator.UNAUTHORIZED, null); // RFC 2560: responseBytes are not set on error.
            transactionLogger.paramPut(ITransactionLogger.STATUS, OCSPRespGenerator.UNAUTHORIZED);
            transactionLogger.writeln();
            auditLogger.paramPut(IAuditLogger.STATUS, OCSPRespGenerator.UNAUTHORIZED);
        } catch (Throwable e) {
            transactionLogger.paramPut(IPatternLogger.PROCESS_TIME, IPatternLogger.PROCESS_TIME);
            auditLogger.paramPut(IPatternLogger.PROCESS_TIME, IPatternLogger.PROCESS_TIME);
            String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
            m_log.error(errMsg, e);
            ocspresp = res.generate(OCSPRespGenerator.INTERNAL_ERROR, null); // RFC 2560: responseBytes are not set on error.
            transactionLogger.paramPut(ITransactionLogger.STATUS, OCSPRespGenerator.INTERNAL_ERROR);
            transactionLogger.writeln();
            auditLogger.paramPut(IAuditLogger.STATUS, OCSPRespGenerator.INTERNAL_ERROR);
        }
        byte[] respBytes = ocspresp.getEncoded();
        auditLogger.paramPut(IAuditLogger.OCSPRESPONSE, new String(Hex.encode(respBytes)));
        auditLogger.writeln();
        auditLogger.flush();
        transactionLogger.flush();
        if (mDoSaferLogging) {
            // See if the Errorhandler has found any problems
            if (hasErrorHandlerFailedSince(startTime)) {
                m_log.info("ProbableErrorhandler reported error, cannot answer request");
                ocspresp = res.generate(OCSPRespGenerator.INTERNAL_ERROR, null); // RFC 2560: responseBytes are not set on error.
                respBytes = ocspresp.getEncoded();
            }
            // See if the Appender has reported any problems
            if (!canlog) {
                m_log.info("SaferDailyRollingFileAppender reported error, cannot answer request");
                ocspresp = res.generate(OCSPRespGenerator.INTERNAL_ERROR, null); // RFC 2560: responseBytes are not set on error.
                respBytes = ocspresp.getEncoded();
            }
        }
        response.setContentType("application/ocsp-response");
        //response.setHeader("Content-transfer-encoding", "binary");
        response.setContentLength(respBytes.length);
        addRfc5019CacheHeaders(request, response, ocspresp, maxAge);
        response.getOutputStream().write(respBytes);
        response.getOutputStream().flush();
    } catch (OCSPException e) {
        String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage());
        m_log.error(errMsg, e);
        throw new ServletException(e);
    } catch (Exception e) {
        m_log.error("", e);
        transactionLogger.flush();
        auditLogger.flush();
    }
    if (m_log.isTraceEnabled()) {
        m_log.trace("<service()");
    }
}

From source file:org.jruby.ext.openssl.OCSPBasicResponse.java

License:Common Public License

@JRubyMethod(name = "add_status", rest = true)
public OCSPBasicResponse add_status(final ThreadContext context, IRubyObject[] args) {
    Ruby runtime = context.getRuntime();
    Arity.checkArgumentCount(runtime, args, 7, 7);

    IRubyObject certificateId = args[0];
    IRubyObject status = args[1];/*from  w w  w. j  a  va 2s.  co  m*/
    IRubyObject reason = args[2];
    IRubyObject revocation_time = args[3];
    IRubyObject this_update = args[4];
    IRubyObject next_update = args[5];
    IRubyObject extensions = args[6];

    CertStatus certStatus = null;
    switch (RubyFixnum.fix2int((RubyFixnum) status)) {
    case 0:
        certStatus = new CertStatus();
        break;
    case 1:
        ASN1GeneralizedTime revTime = rubyIntOrTimeToGenTime(revocation_time);
        RevokedInfo revokedInfo = new RevokedInfo(revTime,
                CRLReason.lookup(RubyFixnum.fix2int((RubyFixnum) reason)));
        certStatus = new CertStatus(revokedInfo);
        break;
    case 2:
        certStatus = new CertStatus(2, DERNull.INSTANCE);
        break;
    default:
        break;
    }

    ASN1GeneralizedTime thisUpdate = rubyIntOrTimeToGenTime(this_update);
    ASN1GeneralizedTime nextUpdate = rubyIntOrTimeToGenTime(next_update);
    Extensions singleExtensions = convertRubyExtensions(extensions);
    CertID certID = ((OCSPCertificateId) certificateId).getCertID();

    SingleResponse ocspSingleResp = new SingleResponse(certID, certStatus, thisUpdate, nextUpdate,
            singleExtensions);
    OCSPSingleResponse rubySingleResp = new OCSPSingleResponse(runtime);
    try {
        rubySingleResp.initialize(context, RubyString.newString(runtime, ocspSingleResp.getEncoded()));
        singleResponses.add(rubySingleResp);
    } catch (IOException e) {
        throw newOCSPError(runtime, e);
    }

    return this;
}

From source file:org.xipki.ocsp.server.impl.OcspServer.java

License:Open Source License

public OcspRespWithCacheInfo answer(final Responder responder, final OCSPReq request,
        final AuditEvent auditEvent, final boolean viaGet) {
    ResponderOption responderOption = responder.getResponderOption();
    RequestOption requestOption = responder.getRequestOption();
    ResponseOption responseOption = responder.getResponseOption();
    ResponderSigner signer = responder.getSigner();
    AuditOption auditOption = responder.getAuditOption();
    CertprofileOption certprofileOption = responder.getCertprofileOption();

    int version = request.getVersionNumber();
    if (requestOption.isVersionAllowed(version) == false) {
        String message = "invalid request version " + version;
        LOG.warn(message);/*from  www .ja  va  2s  .co  m*/
        if (auditEvent != null) {
            fillAuditEvent(auditEvent, AuditLevel.INFO, AuditStatus.FAILED, message);
        }
        return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest);
    }

    try {
        OcspRespWithCacheInfo resp = checkSignature(request, requestOption, auditEvent);
        if (resp != null) {
            return resp;
        }

        boolean couldCacheInfo = viaGet;

        List<Extension> responseExtensions = new ArrayList<>(2);

        Req[] requestList = request.getRequestList();
        int n = requestList.length;

        Set<ASN1ObjectIdentifier> criticalExtensionOIDs = new HashSet<>();
        Set<?> tmp = request.getCriticalExtensionOIDs();
        if (tmp != null) {
            for (Object oid : tmp) {
                criticalExtensionOIDs.add((ASN1ObjectIdentifier) oid);
            }
        }

        RespID respID = new RespID(signer.getResponderId());
        BasicOCSPRespBuilder basicOcspBuilder = new BasicOCSPRespBuilder(respID);
        ASN1ObjectIdentifier extensionType = OCSPObjectIdentifiers.id_pkix_ocsp_nonce;
        criticalExtensionOIDs.remove(extensionType);
        Extension nonceExtn = request.getExtension(extensionType);
        if (nonceExtn != null) {
            byte[] nonce = nonceExtn.getExtnValue().getOctets();
            int len = nonce.length;
            int min = requestOption.getNonceMinLen();
            int max = requestOption.getNonceMaxLen();

            if (len < min || len > max) {
                LOG.warn("length of nonce {} not within [{},{}]", new Object[] { len, min, max });
                if (auditEvent != null) {
                    StringBuilder sb = new StringBuilder();
                    sb.append("length of nonce ").append(len);
                    sb.append(" not within [").append(min).append(", ").append(max);
                    fillAuditEvent(auditEvent, AuditLevel.INFO, AuditStatus.FAILED, sb.toString());
                }
                return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest);
            }

            couldCacheInfo = false;
            responseExtensions.add(nonceExtn);
        } else if (requestOption.isNonceRequired()) {
            String message = "nonce required, but is not present in the request";
            LOG.warn(message);
            if (auditEvent != null) {
                fillAuditEvent(auditEvent, AuditLevel.INFO, AuditStatus.FAILED, message);
            }
            return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest);
        }

        boolean includeExtendedRevokeExtension = false;

        long cacheThisUpdate = 0;
        long cacheNextUpdate = Long.MAX_VALUE;
        for (int i = 0; i < n; i++) {
            AuditChildEvent childAuditEvent = null;
            if (auditEvent != null) {
                childAuditEvent = new AuditChildEvent();
                auditEvent.addChildAuditEvent(childAuditEvent);
            }

            Req req = requestList[i];
            CertificateID certID = req.getCertID();
            String certIdHashAlgo = certID.getHashAlgOID().getId();
            HashAlgoType reqHashAlgo = HashAlgoType.getHashAlgoType(certIdHashAlgo);
            if (reqHashAlgo == null) {
                LOG.warn("unknown CertID.hashAlgorithm {}", certIdHashAlgo);
                if (childAuditEvent != null) {
                    fillAuditEvent(childAuditEvent, AuditLevel.INFO, AuditStatus.FAILED,
                            "unknown CertID.hashAlgorithm " + certIdHashAlgo);
                }
                return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest);
            } else if (requestOption.allows(reqHashAlgo) == false) {
                LOG.warn("CertID.hashAlgorithm {} not allowed", certIdHashAlgo);
                if (childAuditEvent != null) {
                    fillAuditEvent(childAuditEvent, AuditLevel.INFO, AuditStatus.FAILED,
                            "CertID.hashAlgorithm " + certIdHashAlgo + " not allowed");
                }
                return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest);
            }

            CertStatusInfo certStatusInfo = null;
            CertStatusStore answeredStore = null;
            boolean exceptionOccurs = false;

            for (CertStatusStore store : responder.getStores()) {
                try {
                    certStatusInfo = store.getCertStatus(reqHashAlgo, certID.getIssuerNameHash(),
                            certID.getIssuerKeyHash(), certID.getSerialNumber(),
                            responseOption.isIncludeCerthash(), responseOption.getCertHashAlgo(),
                            certprofileOption);
                    if (certStatusInfo.getCertStatus() != CertStatus.ISSUER_UNKNOWN) {
                        answeredStore = store;
                        break;
                    }
                } catch (CertStatusStoreException e) {
                    exceptionOccurs = true;
                    final String message = "getCertStatus() of CertStatusStore " + store.getName();
                    if (LOG.isErrorEnabled()) {
                        LOG.error(LogUtil.buildExceptionLogFormat(message), e.getClass().getName(),
                                e.getMessage());
                    }
                    LOG.debug(message, e);
                }
            }

            if (certStatusInfo == null) {
                if (childAuditEvent != null) {
                    fillAuditEvent(childAuditEvent, AuditLevel.ERROR, AuditStatus.FAILED,
                            "no CertStatusStore can answer the request");
                }
                if (exceptionOccurs) {
                    return createUnsuccessfullOCSPResp(OcspResponseStatus.tryLater);
                } else {
                    certStatusInfo = CertStatusInfo.getIssuerUnknownCertStatusInfo(new Date(), null);
                }
            } else if (answeredStore != null) {
                if (responderOption.isInheritCaRevocation()) {
                    CertRevocationInfo caRevInfo = answeredStore.getCARevocationInfo(reqHashAlgo,
                            certID.getIssuerNameHash(), certID.getIssuerKeyHash());
                    if (caRevInfo != null) {
                        CertStatus certStatus = certStatusInfo.getCertStatus();
                        boolean replaced = false;
                        if (certStatus == CertStatus.GOOD || certStatus == CertStatus.UNKNOWN) {
                            replaced = true;
                        } else if (certStatus == CertStatus.REVOKED) {
                            if (certStatusInfo.getRevocationInfo().getRevocationTime()
                                    .after(caRevInfo.getRevocationTime())) {
                                replaced = true;
                            }
                        }

                        if (replaced) {
                            CertRevocationInfo newRevInfo;
                            if (caRevInfo.getReason() == CRLReason.CA_COMPROMISE) {
                                newRevInfo = caRevInfo;
                            } else {
                                newRevInfo = new CertRevocationInfo(CRLReason.CA_COMPROMISE,
                                        caRevInfo.getRevocationTime(), caRevInfo.getInvalidityTime());
                            }
                            certStatusInfo = CertStatusInfo.getRevokedCertStatusInfo(newRevInfo,
                                    certStatusInfo.getCertHashAlgo(), certStatusInfo.getCertHash(),
                                    certStatusInfo.getThisUpdate(), certStatusInfo.getNextUpdate(),
                                    certStatusInfo.getCertprofile());
                        }
                    }
                }
            }

            if (childAuditEvent != null) {
                String certprofile = certStatusInfo.getCertprofile();
                String auditCertType;
                if (certprofile != null) {
                    auditCertType = auditOption.getCertprofileMapping().get(certprofile);
                    if (auditCertType == null) {
                        auditCertType = certprofile;
                    }
                } else {
                    auditCertType = "UNKNOWN";
                }

                childAuditEvent.addEventData(new AuditEventData("certType", auditCertType));
            }

            // certStatusInfo could not be null in any case, since at least one store is configured
            Date thisUpdate = certStatusInfo.getThisUpdate();
            if (thisUpdate == null) {
                thisUpdate = new Date();
            }
            Date nextUpdate = certStatusInfo.getNextUpdate();

            List<Extension> extensions = new LinkedList<>();
            boolean unknownAsRevoked = false;
            CertificateStatus bcCertStatus = null;
            switch (certStatusInfo.getCertStatus()) {
            case GOOD:
                bcCertStatus = null;
                break;

            case ISSUER_UNKNOWN:
                couldCacheInfo = false;
                bcCertStatus = new UnknownStatus();
                break;

            case UNKNOWN:
            case IGNORE:
                couldCacheInfo = false;
                if (responderOption.getMode() == OCSPMode.RFC2560) {
                    bcCertStatus = new UnknownStatus();
                } else// (ocspMode == OCSPMode.RFC6960)
                {
                    unknownAsRevoked = true;
                    includeExtendedRevokeExtension = true;
                    bcCertStatus = new RevokedStatus(new Date(0L), CRLReason.CERTIFICATE_HOLD.getCode());
                }
                break;
            case REVOKED:
                CertRevocationInfo revInfo = certStatusInfo.getRevocationInfo();
                ASN1GeneralizedTime revTime = new ASN1GeneralizedTime(revInfo.getRevocationTime());
                org.bouncycastle.asn1.x509.CRLReason _reason = null;
                if (responseOption.isIncludeRevReason()) {
                    _reason = org.bouncycastle.asn1.x509.CRLReason.lookup(revInfo.getReason().getCode());
                }
                RevokedInfo _revInfo = new RevokedInfo(revTime, _reason);
                bcCertStatus = new RevokedStatus(_revInfo);

                Date invalidityDate = revInfo.getInvalidityTime();
                if (responseOption.isIncludeInvalidityDate() && invalidityDate != null
                        && invalidityDate.equals(revTime) == false) {
                    Extension extension = new Extension(Extension.invalidityDate, false,
                            new ASN1GeneralizedTime(invalidityDate).getEncoded());
                    extensions.add(extension);
                }
                break;
            }

            byte[] certHash = certStatusInfo.getCertHash();
            if (certHash != null) {
                ASN1ObjectIdentifier hashAlgoOid = new ASN1ObjectIdentifier(
                        certStatusInfo.getCertHashAlgo().getOid());
                AlgorithmIdentifier aId = new AlgorithmIdentifier(hashAlgoOid, DERNull.INSTANCE);
                CertHash bcCertHash = new CertHash(aId, certHash);

                byte[] encodedCertHash;
                try {
                    encodedCertHash = bcCertHash.getEncoded();
                } catch (IOException e) {
                    final String message = "answer() bcCertHash.getEncoded";
                    if (LOG.isErrorEnabled()) {
                        LOG.error(LogUtil.buildExceptionLogFormat(message), e.getClass().getName(),
                                e.getMessage());
                    }
                    LOG.debug(message, e);
                    if (childAuditEvent != null) {
                        fillAuditEvent(childAuditEvent, AuditLevel.ERROR, AuditStatus.FAILED,
                                "CertHash.getEncoded() with IOException");
                    }
                    return createUnsuccessfullOCSPResp(OcspResponseStatus.internalError);
                }

                Extension extension = new Extension(ISISMTTObjectIdentifiers.id_isismtt_at_certHash, false,
                        encodedCertHash);

                extensions.add(extension);
            }

            if (certStatusInfo.getArchiveCutOff() != null) {
                Extension extension = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_archive_cutoff, false,
                        new ASN1GeneralizedTime(certStatusInfo.getArchiveCutOff()).getEncoded());
                extensions.add(extension);
            }

            String certStatusText;
            if (bcCertStatus instanceof UnknownStatus) {
                certStatusText = "unknown";
            } else if (bcCertStatus instanceof RevokedStatus) {
                certStatusText = unknownAsRevoked ? "unknown_as_revoked" : "revoked";
            } else if (bcCertStatus == null) {
                certStatusText = "good";
            } else {
                certStatusText = "should-not-happen";
            }

            if (childAuditEvent != null) {
                childAuditEvent.setLevel(AuditLevel.INFO);
                childAuditEvent.setStatus(AuditStatus.SUCCESSFUL);
                childAuditEvent.addEventData(new AuditEventData("certStatus", certStatusText));
            }

            if (LOG.isDebugEnabled()) {
                StringBuilder sb = new StringBuilder();
                sb.append("certHashAlgo: ").append(certID.getHashAlgOID().getId()).append(", ");

                String hexCertHash = null;
                if (certHash != null) {
                    hexCertHash = Hex.toHexString(certHash).toUpperCase();
                }

                sb.append("issuerKeyHash: ").append(Hex.toHexString(certID.getIssuerKeyHash()).toUpperCase())
                        .append(", ");
                sb.append("issuerNameHash: ").append(Hex.toHexString(certID.getIssuerNameHash()).toUpperCase())
                        .append(", ");
                sb.append("serialNumber: ").append(certID.getSerialNumber()).append(", ");
                sb.append("certStatus: ").append(certStatusText).append(", ");
                sb.append("thisUpdate: ").append(thisUpdate).append(", ");
                sb.append("nextUpdate: ").append(nextUpdate).append(", ");
                sb.append("certHash: ").append(hexCertHash);
                LOG.debug(sb.toString());
            }

            basicOcspBuilder.addResponse(certID, bcCertStatus, thisUpdate, nextUpdate,
                    CollectionUtil.isEmpty(extensions) ? null
                            : new Extensions(extensions.toArray(new Extension[0])));
            cacheThisUpdate = Math.max(cacheThisUpdate, thisUpdate.getTime());
            if (nextUpdate != null) {
                cacheNextUpdate = Math.min(cacheNextUpdate, nextUpdate.getTime());
            }
        }

        if (includeExtendedRevokeExtension) {
            responseExtensions.add(new Extension(ObjectIdentifiers.id_pkix_ocsp_extendedRevoke, true,
                    DERNull.INSTANCE.getEncoded()));
        }

        if (CollectionUtil.isNotEmpty(responseExtensions)) {
            basicOcspBuilder
                    .setResponseExtensions(new Extensions(responseExtensions.toArray(new Extension[0])));
        }

        ConcurrentContentSigner concurrentSigner = null;
        if (responderOption.getMode() != OCSPMode.RFC2560) {
            extensionType = ObjectIdentifiers.id_pkix_ocsp_prefSigAlgs;
            criticalExtensionOIDs.remove(extensionType);
            Extension ext = request.getExtension(extensionType);
            if (ext != null) {
                ASN1Sequence preferredSigAlgs = ASN1Sequence.getInstance(ext.getParsedValue());
                concurrentSigner = signer.getSignerForPreferredSigAlgs(preferredSigAlgs);
            }
        }

        if (CollectionUtil.isNotEmpty(criticalExtensionOIDs)) {
            return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest);
        }

        if (concurrentSigner == null) {
            concurrentSigner = signer.getFirstSigner();
        }

        ContentSigner singleSigner;
        try {
            singleSigner = concurrentSigner.borrowContentSigner();
        } catch (NoIdleSignerException e) {
            return createUnsuccessfullOCSPResp(OcspResponseStatus.tryLater);
        }

        X509CertificateHolder[] certsInResp;
        EmbedCertsMode certsMode = responseOption.getEmbedCertsMode();
        if (certsMode == null || certsMode == EmbedCertsMode.SIGNER) {
            certsInResp = new X509CertificateHolder[] { signer.getBcCertificate() };
        } else if (certsMode == EmbedCertsMode.SIGNER_AND_CA) {
            certsInResp = signer.getBcCertificateChain();
        } else {
            // NONE
            certsInResp = null;
        }

        BasicOCSPResp basicOcspResp;
        try {
            basicOcspResp = basicOcspBuilder.build(singleSigner, certsInResp, new Date());
        } catch (OCSPException e) {
            final String message = "answer() basicOcspBuilder.build";
            if (LOG.isErrorEnabled()) {
                LOG.error(LogUtil.buildExceptionLogFormat(message), e.getClass().getName(), e.getMessage());
            }
            LOG.debug(message, e);
            if (auditEvent != null) {
                fillAuditEvent(auditEvent, AuditLevel.ERROR, AuditStatus.FAILED,
                        "BasicOCSPRespBuilder.build() with OCSPException");
            }
            return createUnsuccessfullOCSPResp(OcspResponseStatus.internalError);
        } finally {
            concurrentSigner.returnContentSigner(singleSigner);
        }

        OCSPRespBuilder ocspRespBuilder = new OCSPRespBuilder();
        try {
            OCSPResp ocspResp = ocspRespBuilder.build(OcspResponseStatus.successfull.getStatus(),
                    basicOcspResp);

            if (couldCacheInfo) {
                ResponseCacheInfo cacheInfo = new ResponseCacheInfo(cacheThisUpdate);
                if (cacheNextUpdate != Long.MAX_VALUE) {
                    cacheInfo.setNextUpdate(cacheNextUpdate);
                }
                return new OcspRespWithCacheInfo(ocspResp, cacheInfo);
            } else {
                return new OcspRespWithCacheInfo(ocspResp, null);
            }
        } catch (OCSPException e) {
            final String message = "answer() ocspRespBuilder.build";
            if (LOG.isErrorEnabled()) {
                LOG.error(LogUtil.buildExceptionLogFormat(message), e.getClass().getName(), e.getMessage());
            }
            LOG.debug(message, e);
            if (auditEvent != null) {
                fillAuditEvent(auditEvent, AuditLevel.ERROR, AuditStatus.FAILED,
                        "OCSPRespBuilder.build() with OCSPException");
            }
            return createUnsuccessfullOCSPResp(OcspResponseStatus.internalError);
        }

    } catch (Throwable t) {
        final String message = "Throwable";
        if (LOG.isErrorEnabled()) {
            LOG.error(LogUtil.buildExceptionLogFormat(message), t.getClass().getName(), t.getMessage());
        }
        LOG.debug(message, t);

        if (auditEvent != null) {
            fillAuditEvent(auditEvent, AuditLevel.ERROR, AuditStatus.FAILED, "internal error");
        }

        return createUnsuccessfullOCSPResp(OcspResponseStatus.internalError);
    }
}

From source file:org.xipki.pki.ocsp.server.impl.OcspServer.java

License:Open Source License

private OcspRespWithCacheInfo processCertReq(Req req, BasicOCSPRespBuilder builder, Responder responder,
        RequestOption reqOpt, ResponseOption repOpt, OcspRespControl repControl, AuditEvent event)
        throws IOException {
    CertificateID certId = req.getCertID();
    String certIdHashAlgo = certId.getHashAlgOID().getId();
    HashAlgoType reqHashAlgo = HashAlgoType.getHashAlgoType(certIdHashAlgo);
    if (reqHashAlgo == null) {
        LOG.warn("unknown CertID.hashAlgorithm {}", certIdHashAlgo);
        if (event != null) {
            fillAuditEvent(event, AuditLevel.INFO, AuditStatus.FAILED,
                    "unknown CertID.hashAlgorithm " + certIdHashAlgo);
        }//from   ww w. j  a va2  s  . c om
        return createUnsuccessfulOcspResp(OcspResponseStatus.malformedRequest);
    } else if (!reqOpt.allows(reqHashAlgo)) {
        LOG.warn("CertID.hashAlgorithm {} not allowed", certIdHashAlgo);
        if (event != null) {
            fillAuditEvent(event, AuditLevel.INFO, AuditStatus.FAILED,
                    "not allowed CertID.hashAlgorithm " + certIdHashAlgo);
        }
        return createUnsuccessfulOcspResp(OcspResponseStatus.malformedRequest);
    }

    if (event != null) {
        event.addEventData(OcspAuditConstants.NAME_serial, certId.getSerialNumber());
    }

    CertStatusInfo certStatusInfo = null;
    OcspStore answeredStore = null;
    boolean exceptionOccurs = false;

    Date now = new Date();
    for (OcspStore store : responder.getStores()) {
        try {
            certStatusInfo = store.getCertStatus(now, reqHashAlgo, certId.getIssuerNameHash(),
                    certId.getIssuerKeyHash(), certId.getSerialNumber(), repOpt.isIncludeCerthash(),
                    repOpt.getCertHashAlgo(), responder.getCertprofileOption());
            if (certStatusInfo != null && certStatusInfo.getCertStatus() != CertStatus.ISSUER_UNKNOWN) {
                answeredStore = store;
                break;
            }
        } catch (OcspStoreException ex) {
            exceptionOccurs = true;
            LogUtil.error(LOG, ex, "getCertStatus() of CertStatusStore " + store.getName());
        } // end try
    } // end for

    if (certStatusInfo == null) {
        if (exceptionOccurs) {
            fillAuditEvent(event, AuditLevel.INFO, AuditStatus.FAILED,
                    "no CertStatusStore can answer the request");
            return createUnsuccessfulOcspResp(OcspResponseStatus.tryLater);
        } else {
            certStatusInfo = CertStatusInfo.getIssuerUnknownCertStatusInfo(new Date(), null);
        }
    } else if (answeredStore != null && responder.getResponderOption().isInheritCaRevocation()) {
        CertRevocationInfo caRevInfo = answeredStore.getCaRevocationInfo(reqHashAlgo,
                certId.getIssuerNameHash(), certId.getIssuerKeyHash());
        if (caRevInfo != null) {
            CertStatus certStatus = certStatusInfo.getCertStatus();
            boolean replaced = false;
            if (certStatus == CertStatus.GOOD || certStatus == CertStatus.UNKNOWN) {
                replaced = true;
            } else if (certStatus == CertStatus.REVOKED) {
                if (certStatusInfo.getRevocationInfo().getRevocationTime()
                        .after(caRevInfo.getRevocationTime())) {
                    replaced = true;
                }
            }

            if (replaced) {
                CertRevocationInfo newRevInfo;
                if (caRevInfo.getReason() == CrlReason.CA_COMPROMISE) {
                    newRevInfo = caRevInfo;
                } else {
                    newRevInfo = new CertRevocationInfo(CrlReason.CA_COMPROMISE, caRevInfo.getRevocationTime(),
                            caRevInfo.getInvalidityTime());
                }
                certStatusInfo = CertStatusInfo.getRevokedCertStatusInfo(newRevInfo,
                        certStatusInfo.getCertHashAlgo(), certStatusInfo.getCertHash(),
                        certStatusInfo.getThisUpdate(), certStatusInfo.getNextUpdate(),
                        certStatusInfo.getCertprofile());
            } // end if(replaced)
        } // end if
    } // end if

    if (event != null) {
        String certprofile = certStatusInfo.getCertprofile();
        String auditCertType;
        if (certprofile != null) {
            auditCertType = responder.getAuditOption().getCertprofileMapping().get(certprofile);
            if (auditCertType == null) {
                auditCertType = certprofile;
            }
        } else {
            auditCertType = "UNKNOWN";
        }

        event.addEventData(OcspAuditConstants.NAME_type, auditCertType);
    }

    // certStatusInfo must not be null in any case, since at least one store
    // is configured
    Date thisUpdate = certStatusInfo.getThisUpdate();
    if (thisUpdate == null) {
        thisUpdate = new Date();
    }
    Date nextUpdate = certStatusInfo.getNextUpdate();

    List<Extension> extensions = new LinkedList<>();
    boolean unknownAsRevoked = false;
    CertificateStatus bcCertStatus;
    switch (certStatusInfo.getCertStatus()) {
    case GOOD:
        bcCertStatus = null;
        break;

    case ISSUER_UNKNOWN:
        repControl.couldCacheInfo = false;
        bcCertStatus = new UnknownStatus();
        break;

    case UNKNOWN:
    case IGNORE:
        repControl.couldCacheInfo = false;
        if (responder.getResponderOption().getMode() == OcspMode.RFC2560) {
            bcCertStatus = new UnknownStatus();
        } else { // (ocspMode == OCSPMode.RFC6960)
            unknownAsRevoked = true;
            repControl.includeExtendedRevokeExtension = true;
            bcCertStatus = new RevokedStatus(new Date(0L), CrlReason.CERTIFICATE_HOLD.getCode());
        }
        break;
    case REVOKED:
        CertRevocationInfo revInfo = certStatusInfo.getRevocationInfo();
        ASN1GeneralizedTime revTime = new ASN1GeneralizedTime(revInfo.getRevocationTime());
        org.bouncycastle.asn1.x509.CRLReason tmpReason = null;
        if (repOpt.isIncludeRevReason()) {
            tmpReason = org.bouncycastle.asn1.x509.CRLReason.lookup(revInfo.getReason().getCode());
        }
        RevokedInfo tmpRevInfo = new RevokedInfo(revTime, tmpReason);
        bcCertStatus = new RevokedStatus(tmpRevInfo);

        Date invalidityDate = revInfo.getInvalidityTime();
        if (repOpt.isIncludeInvalidityDate() && invalidityDate != null
                && !invalidityDate.equals(revInfo.getRevocationTime())) {
            Extension extension = new Extension(Extension.invalidityDate, false,
                    new ASN1GeneralizedTime(invalidityDate).getEncoded());
            extensions.add(extension);
        }
        break;
    default:
        throw new RuntimeException("unknown CertificateStatus:" + certStatusInfo.getCertStatus());
    } // end switch

    byte[] certHash = certStatusInfo.getCertHash();
    if (certHash != null) {
        ASN1ObjectIdentifier hashAlgOid = certStatusInfo.getCertHashAlgo().getOid();
        AlgorithmIdentifier hashAlgId = new AlgorithmIdentifier(hashAlgOid, DERNull.INSTANCE);
        CertHash bcCertHash = new CertHash(hashAlgId, certHash);

        byte[] encodedCertHash;
        try {
            encodedCertHash = bcCertHash.getEncoded();
        } catch (IOException ex) {
            LogUtil.error(LOG, ex, "answer() bcCertHash.getEncoded");
            if (event != null) {
                fillAuditEvent(event, AuditLevel.ERROR, AuditStatus.FAILED,
                        "CertHash.getEncoded() with IOException");
            }
            return createUnsuccessfulOcspResp(OcspResponseStatus.internalError);
        }

        Extension extension = new Extension(ISISMTTObjectIdentifiers.id_isismtt_at_certHash, false,
                encodedCertHash);

        extensions.add(extension);
    } // end if(certHash != null)

    if (certStatusInfo.getArchiveCutOff() != null) {
        Extension extension = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_archive_cutoff, false,
                new ASN1GeneralizedTime(certStatusInfo.getArchiveCutOff()).getEncoded());
        extensions.add(extension);
    }

    String certStatusText;
    if (bcCertStatus instanceof UnknownStatus) {
        certStatusText = "unknown";
    } else if (bcCertStatus instanceof RevokedStatus) {
        certStatusText = unknownAsRevoked ? "unknown_as_revoked" : "revoked";
    } else if (bcCertStatus == null) {
        certStatusText = "good";
    } else {
        certStatusText = "should-not-happen";
    }

    if (event != null) {
        event.setLevel(AuditLevel.INFO);
        event.setStatus(AuditStatus.SUCCESSFUL);
        event.addEventData(OcspAuditConstants.NAME_status, certStatusText);
    }

    if (LOG.isDebugEnabled()) {
        StringBuilder sb = new StringBuilder(250);
        sb.append("certHashAlgo: ").append(certId.getHashAlgOID().getId()).append(", ");
        sb.append("issuerNameHash: ").append(Hex.toHexString(certId.getIssuerNameHash()).toUpperCase())
                .append(", ");
        sb.append("issuerKeyHash: ").append(Hex.toHexString(certId.getIssuerKeyHash()).toUpperCase())
                .append(", ");
        sb.append("serialNumber: ").append(LogUtil.formatCsn(certId.getSerialNumber())).append(", ");
        sb.append("certStatus: ").append(certStatusText).append(", ");
        sb.append("thisUpdate: ").append(thisUpdate).append(", ");
        sb.append("nextUpdate: ").append(nextUpdate);
        if (certHash != null) {
            sb.append(", certHash: ").append(Hex.toHexString(certHash).toUpperCase());
        }
        LOG.debug(sb.toString());
    }

    Extensions extns = null;
    if (CollectionUtil.isNonEmpty(extensions)) {
        extns = new Extensions(extensions.toArray(new Extension[0]));
    }

    builder.addResponse(certId, bcCertStatus, thisUpdate, nextUpdate, extns);
    repControl.cacheThisUpdate = Math.max(repControl.cacheThisUpdate, thisUpdate.getTime());
    if (nextUpdate != null) {
        repControl.cacheNextUpdate = Math.min(repControl.cacheNextUpdate, nextUpdate.getTime());
    }

    return null;
}

From source file:test.integ.be.fedict.performance.servlet.OcspServlet.java

License:Open Source License

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    String caName = request.getParameter(CA_QUERY_PARAM);
    if (null == caName) {
        throw new ServletException("No CA name found.");
    }//from   www  . ja v a  2  s . com

    CAConfiguration ca = TestPKI.get().findCa(caName);
    if (null == ca) {
        throw new ServletException("CA Config not found for " + caName);
    }

    try {

        if (null == request.getContentType() || !request.getContentType().equals("application/ocsp-request")) {
            LOG.error("Wrong content type: " + request.getContentType());
            return;
        }

        int len = request.getContentLength();
        byte[] ocspRequestData = new byte[len];
        ServletInputStream reader = request.getInputStream();
        int result = reader.read(ocspRequestData);
        if (-1 == result) {
            LOG.error("No data found ?!");
            return;
        }

        BigInteger maxRevokedSN = new BigInteger(Long.toString(ca.getCrlRecords()));

        OCSPReq ocspRequest = new OCSPReq(ocspRequestData);

        BasicOCSPRespGenerator ocspRespGen = new BasicOCSPRespGenerator(ca.getKeyPair().getPublic());
        for (Req req : ocspRequest.getRequestList()) {

            LOG.debug("OCSP request for CA=" + caName + " sn=" + req.getCertID().getSerialNumber());

            if (-1 == req.getCertID().getSerialNumber().compareTo(maxRevokedSN)) {
                LOG.debug("revoked");
                ocspRespGen.addResponse(req.getCertID(),
                        new RevokedStatus(new RevokedInfo(new ASN1GeneralizedTime(new Date()), null)));
            } else {
                ocspRespGen.addResponse(req.getCertID(), CertificateStatus.GOOD);
            }
        }

        BasicOCSPResp ocspResp;
        ocspResp = ocspRespGen.generate("SHA1WITHRSA", ca.getKeyPair().getPrivate(), null, new Date(), "BC");

        OCSPRespGenerator og = new OCSPRespGenerator();

        response.setContentType("application/ocsp-response");
        response.getOutputStream().write((og.generate(OCSPRespGenerator.SUCCESSFUL, ocspResp)).getEncoded());

    } catch (Exception e) {
        LOG.error("Exception: " + e.getMessage(), e);
        throw new ServletException(e);
    }
}