List of usage examples for org.bouncycastle.cert.ocsp OCSPRespBuilder INTERNAL_ERROR
int INTERNAL_ERROR
To view the source code for org.bouncycastle.cert.ocsp OCSPRespBuilder INTERNAL_ERROR.
Click Source Link
From source file:org.apache.nifi.web.security.x509.ocsp.OcspCertificateValidator.java
License:Apache License
/** * Gets the OCSP status for the specified subject and issuer certificates. * * @param ocspStatusKey status key//from ww w . j av a 2 s . c om * @return ocsp status */ private OcspStatus getOcspStatus(final OcspRequest ocspStatusKey) { final X509Certificate subjectCertificate = ocspStatusKey.getSubjectCertificate(); final X509Certificate issuerCertificate = ocspStatusKey.getIssuerCertificate(); // initialize the default status final OcspStatus ocspStatus = new OcspStatus(); ocspStatus.setVerificationStatus(VerificationStatus.Unknown); ocspStatus.setValidationStatus(ValidationStatus.Unknown); try { // prepare the request final BigInteger subjectSerialNumber = subjectCertificate.getSerialNumber(); final DigestCalculatorProvider calculatorProviderBuilder = new JcaDigestCalculatorProviderBuilder() .setProvider("BC").build(); final CertificateID certificateId = new CertificateID( calculatorProviderBuilder.get(CertificateID.HASH_SHA1), new X509CertificateHolder(issuerCertificate.getEncoded()), subjectSerialNumber); // generate the request final OCSPReqBuilder requestGenerator = new OCSPReqBuilder(); requestGenerator.addRequest(certificateId); // Create a nonce to avoid replay attack BigInteger nonce = BigInteger.valueOf(System.currentTimeMillis()); Extension ext = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, true, new DEROctetString(nonce.toByteArray())); requestGenerator.setRequestExtensions(new Extensions(new Extension[] { ext })); final OCSPReq ocspRequest = requestGenerator.build(); // perform the request final Response response = getClientResponse(ocspRequest); // ensure the request was completed successfully if (Response.Status.OK.getStatusCode() != response.getStatusInfo().getStatusCode()) { logger.warn(String.format("OCSP request was unsuccessful (%s).", response.getStatus())); return ocspStatus; } // interpret the response OCSPResp ocspResponse = new OCSPResp(response.readEntity(InputStream.class)); // verify the response status switch (ocspResponse.getStatus()) { case OCSPRespBuilder.SUCCESSFUL: ocspStatus.setResponseStatus(OcspStatus.ResponseStatus.Successful); break; case OCSPRespBuilder.INTERNAL_ERROR: ocspStatus.setResponseStatus(OcspStatus.ResponseStatus.InternalError); break; case OCSPRespBuilder.MALFORMED_REQUEST: ocspStatus.setResponseStatus(OcspStatus.ResponseStatus.MalformedRequest); break; case OCSPRespBuilder.SIG_REQUIRED: ocspStatus.setResponseStatus(OcspStatus.ResponseStatus.SignatureRequired); break; case OCSPRespBuilder.TRY_LATER: ocspStatus.setResponseStatus(OcspStatus.ResponseStatus.TryLater); break; case OCSPRespBuilder.UNAUTHORIZED: ocspStatus.setResponseStatus(OcspStatus.ResponseStatus.Unauthorized); break; default: ocspStatus.setResponseStatus(OcspStatus.ResponseStatus.Unknown); break; } // only proceed if the response was successful if (ocspResponse.getStatus() != OCSPRespBuilder.SUCCESSFUL) { logger.warn(String.format("OCSP request was unsuccessful (%s).", ocspStatus.getResponseStatus().toString())); return ocspStatus; } // ensure the appropriate response object final Object ocspResponseObject = ocspResponse.getResponseObject(); if (ocspResponseObject == null || !(ocspResponseObject instanceof BasicOCSPResp)) { logger.warn(String.format("Unexpected OCSP response object: %s", ocspResponseObject)); return ocspStatus; } // get the response object final BasicOCSPResp basicOcspResponse = (BasicOCSPResp) ocspResponse.getResponseObject(); // attempt to locate the responder certificate final X509CertificateHolder[] responderCertificates = basicOcspResponse.getCerts(); if (responderCertificates.length != 1) { logger.warn(String.format("Unexpected number of OCSP responder certificates: %s", responderCertificates.length)); return ocspStatus; } // get the responder certificate final X509Certificate trustedResponderCertificate = getTrustedResponderCertificate( responderCertificates[0], issuerCertificate); if (trustedResponderCertificate != null) { // verify the response if (basicOcspResponse.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider("BC") .build(trustedResponderCertificate.getPublicKey()))) { ocspStatus.setVerificationStatus(VerificationStatus.Verified); } else { ocspStatus.setVerificationStatus(VerificationStatus.Unverified); } } else { ocspStatus.setVerificationStatus(VerificationStatus.Unverified); } // validate the response final SingleResp[] responses = basicOcspResponse.getResponses(); for (SingleResp singleResponse : responses) { final CertificateID responseCertificateId = singleResponse.getCertID(); final BigInteger responseSerialNumber = responseCertificateId.getSerialNumber(); if (responseSerialNumber.equals(subjectSerialNumber)) { Object certStatus = singleResponse.getCertStatus(); // interpret the certificate status if (CertificateStatus.GOOD == certStatus) { ocspStatus.setValidationStatus(ValidationStatus.Good); } else if (certStatus instanceof RevokedStatus) { ocspStatus.setValidationStatus(ValidationStatus.Revoked); } else { ocspStatus.setValidationStatus(ValidationStatus.Unknown); } } } } catch (final OCSPException | IOException | ProcessingException | OperatorCreationException e) { logger.error(e.getMessage(), e); } catch (CertificateException e) { e.printStackTrace(); } return ocspStatus; }
From source file:org.cesecore.certificates.ocsp.OcspResponseGeneratorSessionBean.java
License:Open Source License
/** * This method exists solely to avoid code duplication when error handling in getOcspResponse. * // w ww. j av a 2 s . co m * @param responseGenerator A OCSPRespBuilder for generating a response with state INTERNAL_ERROR. * @param transactionLogger The TransactionLogger for this call. * @param auditLogger The AuditLogger for this call. * @param e The thrown exception. * @return a response with state INTERNAL_ERROR. * @throws OCSPException if generation of the response failed. */ private OCSPResp processDefaultError(OCSPRespBuilder responseGenerator, TransactionLogger transactionLogger, AuditLogger auditLogger, Throwable e) throws OCSPException { 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.error(errMsg, e); if (transactionLogger.isEnabled()) { transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.INTERNAL_ERROR); transactionLogger.writeln(); } if (auditLogger.isEnabled()) { auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.INTERNAL_ERROR); } return responseGenerator.build(OCSPRespBuilder.INTERNAL_ERROR, null); // RFC 2560: responseBytes are not set on error. }
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.j a v a 2s . 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.ejbca.core.protocol.ocsp.OcspJunitHelper.java
License:Open Source License
/** * Verify that the OCSP response code is Internal Error. * @param caid//from www .ja va 2 s . co m * @param cacert * @param certSerial * @throws NoSuchProviderException * @throws IOException * @throws OCSPException * @throws CertificateException * @throws OperatorCreationException */ public void verifyResponseInternalError(int caid, X509Certificate cacert, BigInteger certSerial) throws NoSuchProviderException, IOException, OCSPException, OperatorCreationException, CertificateException { verifyStatus(caid, cacert, certSerial, OCSPRespBuilder.INTERNAL_ERROR, Status.Unknown, Integer.MIN_VALUE, null); }
From source file:org.ejbca.core.protocol.ocsp.OcspJunitHelper.java
License:Open Source License
private void verifyStatus(int caid, X509Certificate cacert, BigInteger certSerial, int ocspResponseStatus, Status expectedStatus, int expectedReason, Date expectedRevTime) throws NoSuchProviderException, IOException, OCSPException, OperatorCreationException, CertificateException { // And an OCSP request final OCSPReqBuilder gen = new OCSPReqBuilder(); gen.addRequest(new JcaCertificateID(SHA1DigestCalculator.buildSha1Instance(), cacert, certSerial)); log.debug("ocspTestCert.getSerialNumber() = " + certSerial); final String sNonce = "123456789"; Extension[] extensions = new Extension[1]; extensions[0] = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, false, new DEROctetString(sNonce.getBytes())); gen.setRequestExtensions(new Extensions(extensions)); final OCSPReq req = gen.build(); // Send the request and receive a singleResponse final SingleResp[] singleResps = sendOCSPPost(req.getEncoded(), sNonce, ocspResponseStatus, 200); // if we expected internal error, we should not expect any data, and can not make any more tests if (ocspResponseStatus == OCSPRespBuilder.INTERNAL_ERROR) { return;/*from ww w. j a v a2 s . c o m*/ } if (ocspResponseStatus == OCSPRespBuilder.UNAUTHORIZED) { return; } assertEquals("No of SingleResps should be 1.", 1, singleResps.length); final SingleResp singleResp = singleResps[0]; final CertificateID certId = singleResp.getCertID(); assertEquals("Serno in response does not match serno in request.", certId.getSerialNumber(), certSerial); final Object status = singleResp.getCertStatus(); final String statusClassName = status != null ? status.getClass().getName() : "GOOD";// status==null means GOOD switch (expectedStatus) { case Unknown: assertTrue("Status is not Unknown: " + statusClassName, status instanceof UnknownStatus); break; case Good: if (status != CertificateStatus.GOOD) { log.debug("Certificate status: " + status.getClass().getName()); } assertEquals("Status is not Good, was: " + statusClassName + ".", CertificateStatus.GOOD, status); break; case Revoked: assertTrue("Status is not Revoked: " + statusClassName, status instanceof RevokedStatus); final int reason = ((RevokedStatus) status).getRevocationReason(); assertEquals("Wrong revocation reason", expectedReason, reason); if (expectedRevTime != null) { final Date revTime = ((RevokedStatus) status).getRevocationTime(); assertEquals("Wrong revocation time", expectedRevTime, revTime); } break; } }
From source file:org.ejbca.core.protocol.ocsp.ProtocolOcspHttpTest.java
License:Open Source License
/** * Verify OCSP response for a malicious request. Uses nonsense payload. * * HTTP Content-length: 1000 byte ASN1 sequence length: 199995 byte Payload * size: 200000 byte (not including HTTP header) *//*w w w . java 2s .c o m*/ @Test public void test18MaliciousOcspRequest() throws Exception { log.trace(">test18MaliciousOcspRequest"); int i = 0; // Construct the fake data. byte data[] = new byte[LimitLengthASN1Reader.MAX_REQUEST_SIZE * 2]; // The first byte indicate that this is a sequence. Necessary to past // the first test as an accepted OCSP object. data[0] = (byte) BERTags.SEQUENCE; // The second byte indicates the number if the following bytes are more // than can be represented by one byte and will be represented by 3 // bytes instead. data[1] = (byte) 0x83; // The third through the forth bytes are the number of the following // bytes. (0x030D3B = 199995) data[2] = (byte) 0x03; // MSB data[3] = (byte) 0x0D; data[4] = (byte) 0x3B; // LSB // Fill the rest of the array with some fake data. for (i = 5; i < data.length; i++) { data[i] = (byte) i; } // Create the HTTP header String path = "/ejbca/" + resourceOcsp; String headers = "POST " + path + " HTTP/1.1\r\n" + "Host: " + httpHost + "\r\n" + "Content-Type: application/ocsp-request\r\n" + "Content-Length: 1000\r\n" + "\r\n"; // Merge the HTTP headers and the raw data into one package. byte input[] = concatByteArrays(headers.getBytes(), data); // Create the socket. Socket socket = new Socket(InetAddress.getByName(httpHost), Integer.parseInt(httpPort)); OutputStream os = socket.getOutputStream(); try { // Send data byte for byte. try { os.write(input); } catch (IOException e) { log.info("Socket threw an IOException.", e); // Windows throws an IOException when trying to write more bytes to // the server than it should. JBoss on Linux does not. // assertTrue("Tried to write more than it should to the server (>1000), "+i, i > 1000); return; } /* Note that an Apache proxy interprets this as two requests in the same session (where the second one is bad): HTTP/1.1 200 OK Date: Thu, 27 Mar 2014 16:13:24 GMT Server: Apache/2.4.6 (Unix) OpenSSL/1.0.1e Content-Type: application/ocsp-response Content-Length: 5 0 HTTP/1.1 400 Bad Request Date: Thu, 27 Mar 2014 16:13:24 GMT Server: Apache/2.4.6 (Unix) OpenSSL/1.0.1e Content-Length: 226 Connection: close Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>400 Bad Request</title> </head><body> <h1>Bad Request</h1> <p>Your browser sent a request that this server could not understand.<br /> </p> </body></html> But since the response is ANS1 encoded, the response is still correctly parsed even though we provide 420 bytes extra. */ // Reading the response. InputStream ins = socket.getInputStream(); byte ret[] = new byte[1024]; int len = ins.read(ret); assertTrue("Could not read response.", len != -1); // Removing the HTTP headers. The HTTP headers end at the first occurrence of "\r\n\r\n". for (i = 3; i < len; i++) { if ((ret[i] == 0x0A) && (ret[i - 1] == 0x0D) && (ret[i - 2] == 0x0A) && (ret[i - 3] == 0x0D)) { break; } } log.info("response headers: " + new String(ret, 0, i)); int start = i + 1; byte respa[] = new byte[len - start]; for (i = start; i < len; i++) { respa[i - start] = ret[i]; } log.info("response contains: " + respa.length + " bytes."); log.info("response bytes: " + Hex.toHexString(respa)); log.info("response as string:" + new String(respa)); // Reading the response as a OCSPResp. When the input data array is // longer than allowed the OCSP response will return as an internal // error. OCSPResp response = new OCSPResp(respa); assertEquals("Incorrect response status.", OCSPRespBuilder.INTERNAL_ERROR, response.getStatus()); } finally { os.close(); socket.close(); } log.trace("<test18MaliciousOcspRequest"); }
From source file:org.ejbca.ui.cli.Ocsp.java
License:Open Source License
@Override protected void execute(String[] args) { try {/*from ww w.jav a2 s.c om*/ CryptoProviderTools.installBCProvider(); final String ksfilename; final String kspwd; final String ocspUrlFromCLI; final String certfilename; final String cacertfilename; boolean useGet = false; boolean signRequest = false; if (args.length > 1 && args[1].equals("stress")) { new StressTest(args); return; } else if (args.length >= 6) { ksfilename = args[1]; kspwd = args[2]; ocspUrlFromCLI = args[3].equals("null") ? null : args[3]; certfilename = args[4]; cacertfilename = args[5]; signRequest = true; if (args.length == 7) { useGet = "GET".equalsIgnoreCase(args[6]); } } else if (args.length >= 4) { ksfilename = null; kspwd = null; ocspUrlFromCLI = args[1].equals("null") ? null : args[1]; certfilename = args[2]; cacertfilename = args[3]; if (args.length == 5) { useGet = "GET".equalsIgnoreCase(args[4]); } } else { System.out.println( "Usage 1: OCSP <KeyStoreFilename> <KeyStorePassword> <OCSPUrl | null> <CertificateFileName | HexEncodedCertificateSerialNumber> <CA-CertificateFileName> [<POST | GET>]"); System.out.println( "Usage 2: OCSP <OCSPUrl | null> <CertificateFileName | HexEncodedCertificateSerialNumber> <CA-CertificateFileName> [<POST | GET>]"); System.out.println("Usage 3: OCSP stress ..."); System.out.println("Keystore should be a PKCS12. GET requests will not use a nonce."); System.out.println( "OCSPUrl is like: http://127.0.0.1:8080/ejbca/publicweb/status/ocsp or https://127.0.0.1:8443/ejbca/publicweb/status/ocsp"); System.out.println("OCSP response status is: GOOD=" + OCSPUnidResponse.OCSP_GOOD + ", REVOKED=" + OCSPUnidResponse.OCSP_REVOKED + ", UNKNOWN=" + OCSPUnidResponse.OCSP_UNKNOWN); System.out.println( "OcspUrl can be set to 'null', in that case the program looks for an AIA extension containing the OCSP URI."); System.out.println("Just the stress argument gives further info about the stress test."); return; } OCSPUnidResponse response = null; BigInteger serial = null; final Matcher matcher = Pattern.compile("[0-9a-fA-F]+").matcher(certfilename); if (matcher.matches()) { // It is a certificate serial number instead if a certificate filename try { serial = new BigInteger(certfilename, 16); if (ocspUrlFromCLI == null) { System.out.println("OCSP URL is reqired if a serial number is used."); System.exit(-1); // NOPMD, it's not a JEE app } final OCSPUnidClient client = OCSPUnidClient.getOCSPUnidClient(ksfilename, kspwd, ocspUrlFromCLI, signRequest, ksfilename != null); response = client.lookup(new BigInteger(certfilename, 16), getCertFromPemFile(cacertfilename), useGet); } catch (NumberFormatException e) { // Not a hex serial number System.out.println( "The input that looked like a serial number was not one, try to read it as a file."); } } if (serial == null) { // It's not a certificate serial number, so treat it as a filename final Certificate userCert = getCertFromPemFile(certfilename); String ocspUrl = ocspUrlFromCLI; if (ocspUrl == null) { ocspUrl = CertTools.getAuthorityInformationAccessOcspUrl(userCert); if (ocspUrl == null) { System.out.println("OCSP URL is required since none was found in the certificate."); System.exit(-1); // NOPMD, it's not a JEE app } } final OCSPUnidClient client = OCSPUnidClient.getOCSPUnidClient(ksfilename, kspwd, ocspUrl, signRequest, true); response = client.lookup(userCert, getCertFromPemFile(cacertfilename), useGet); } if (response.getErrorCode() != OCSPUnidResponse.ERROR_NO_ERROR) { System.out.println("Error querying OCSP server."); System.out.println("Error code is: " + response.getErrorCode()); } if (response.getHttpReturnCode() != 200) { System.out.println("Http return code is: " + response.getHttpReturnCode()); } if (response.getResponseStatus() == 0) { System.out.print("OCSP return value is: " + response.getStatus() + " ("); switch (response.getStatus()) { case OCSPUnidResponse.OCSP_GOOD: System.out.println("good)"); break; case OCSPUnidResponse.OCSP_REVOKED: System.out.println("revoked)"); break; case OCSPUnidResponse.OCSP_UNKNOWN: System.out.println("unknown)"); break; } System.out.println("producedAt: " + response.getProducedAt() + " thisUpdate: " + response.getThisUpdate() + " nextUpdate: " + response.getNextUpdate()); if (response.getFnr() != null) { System.out.println("Returned Fnr is: " + response.getFnr()); } } else { System.out.print("OCSP response status is: " + response.getResponseStatus() + " ("); switch (response.getResponseStatus()) { case OCSPRespBuilder.MALFORMED_REQUEST: System.out.println("malformed request)"); break; case OCSPRespBuilder.INTERNAL_ERROR: System.out.println("internal error"); break; case OCSPRespBuilder.TRY_LATER: System.out.println("try later)"); break; case OCSPRespBuilder.SIG_REQUIRED: System.out.println("signature required)"); break; case OCSPRespBuilder.UNAUTHORIZED: System.out.println("unauthorized)"); break; } } } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); System.exit(-1); // NOPMD, it's not a JEE app } }
From source file:org.ejbca.ui.web.protocol.OCSPServlet.java
License:Open Source License
private void processOcspRequest(HttpServletRequest request, HttpServletResponse response, final HttpMethod httpMethod) throws ServletException { final String remoteAddress = request.getRemoteAddr(); final String remoteHost = request.getRemoteHost(); final StringBuffer requestUrl = request.getRequestURL(); final 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);/* ww w . j a v a2 s .com*/ try { if (auditLogger.isEnabled()) { auditLogger.paramPut(PatternLogger.LOG_ID, Integer.valueOf(localTransactionId)); auditLogger.paramPut(PatternLogger.SESSION_ID, sessionID); auditLogger.paramPut(PatternLogger.CLIENT_IP, remoteAddress); } if (transactionLogger.isEnabled()) { transactionLogger.paramPut(PatternLogger.LOG_ID, Integer.valueOf(localTransactionId)); transactionLogger.paramPut(PatternLogger.SESSION_ID, sessionID); transactionLogger.paramPut(PatternLogger.CLIENT_IP, remoteAddress); } OCSPRespBuilder responseGenerator = new OCSPRespBuilder(); OcspResponseInformation ocspResponseInformation = null; try { byte[] requestBytes = checkAndGetRequestBytes(request, httpMethod); X509Certificate[] requestCertificates = (X509Certificate[]) request .getAttribute("javax.servlet.request.X509Certificate"); ocspResponseInformation = integratedOcspResponseGeneratorSession.getOcspResponse(requestBytes, requestCertificates, remoteAddress, remoteHost, requestUrl, auditLogger, transactionLogger); } catch (MalformedRequestException 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); if (log.isDebugEnabled()) { log.debug(errMsg, e); } // RFC 2560: responseBytes are not set on error. ocspResponseInformation = new OcspResponseInformation( responseGenerator.build(OCSPRespBuilder.MALFORMED_REQUEST, null), OcspConfiguration.getMaxAge(CertificateProfileConstants.CERTPROFILE_NO_PROFILE)); if (transactionLogger.isEnabled()) { transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.MALFORMED_REQUEST); transactionLogger.writeln(); } if (auditLogger.isEnabled()) { auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.MALFORMED_REQUEST); } } catch (Throwable e) { // NOPMD, we really want to catch everything here to return internal error on unexpected errors if (transactionLogger.isEnabled()) { transactionLogger.paramPut(IPatternLogger.PROCESS_TIME, IPatternLogger.PROCESS_TIME); } if (auditLogger.isEnabled()) { auditLogger.paramPut(IPatternLogger.PROCESS_TIME, IPatternLogger.PROCESS_TIME); } final String errMsg = intres.getLocalizedMessage("ocsp.errorprocessreq", e.getMessage()); log.info(errMsg); if (log.isDebugEnabled()) { log.debug(errMsg, e); } // RFC 2560: responseBytes are not set on error. ocspResponseInformation = new OcspResponseInformation( responseGenerator.build(OCSPRespBuilder.INTERNAL_ERROR, null), OcspConfiguration.getMaxAge(CertificateProfileConstants.CERTPROFILE_NO_PROFILE)); if (transactionLogger.isEnabled()) { transactionLogger.paramPut(TransactionLogger.STATUS, OCSPRespBuilder.INTERNAL_ERROR); transactionLogger.writeln(); } if (auditLogger.isEnabled()) { auditLogger.paramPut(AuditLogger.STATUS, OCSPRespBuilder.INTERNAL_ERROR); } } byte[] ocspResponseBytes = ocspResponseInformation.getOcspResponse(); response.setContentType("application/ocsp-response"); response.setContentLength(ocspResponseBytes.length); if (HttpMethod.GET.equals(httpMethod)) { addRfc5019CacheHeaders(request, response, ocspResponseInformation); } else { if (log.isDebugEnabled()) { log.debug( "Will not add RFC 5019 cache headers: \"clients MUST use the GET method (to enable OCSP response caching)\""); } } response.getOutputStream().write(ocspResponseBytes); response.getOutputStream().flush(); } catch (Exception e) { log.error("", e); transactionLogger.flush(); auditLogger.flush(); } }