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 ( (!m_nonExistingIsGood) || (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