List of usage examples for org.bouncycastle.asn1.ocsp RevokedInfo RevokedInfo
public RevokedInfo(ASN1GeneralizedTime revocationTime, CRLReason revocationReason)
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); } }