made is_newer() a certificate_t method

This commit is contained in:
Andreas Steffen
2008-03-18 10:36:08 +00:00
parent 50045c3b14
commit 8d49b51f8b
7 changed files with 227 additions and 138 deletions
+119 -76
View File
@@ -414,8 +414,8 @@ static ocsp_wrapper_t *ocsp_wrapper_create(ocsp_response_t *response)
/** /**
* Do an OCSP request * Do an OCSP request
*/ */
static ocsp_response_t *fetch_ocsp(private_credential_manager_t *this, char *url, static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url,
certificate_t *subject, certificate_t *issuer) certificate_t *subject, certificate_t *issuer)
{ {
certificate_t *request, *response, *issuer_cert; certificate_t *request, *response, *issuer_cert;
chunk_t send, receive; chunk_t send, receive;
@@ -430,7 +430,7 @@ static ocsp_response_t *fetch_ocsp(private_credential_manager_t *this, char *url
BUILD_CERT, subject->get_ref(subject), BUILD_END); BUILD_CERT, subject->get_ref(subject), BUILD_END);
if (!request) if (!request)
{ {
DBG1(DBG_CFG, "generating OCSP request failed"); DBG1(DBG_CFG, " generating ocsp request failed");
return NULL; return NULL;
} }
@@ -441,7 +441,7 @@ static ocsp_response_t *fetch_ocsp(private_credential_manager_t *this, char *url
FETCH_REQUEST_TYPE, "application/ocsp-request", FETCH_REQUEST_TYPE, "application/ocsp-request",
FETCH_END) != SUCCESS) FETCH_END) != SUCCESS)
{ {
DBG1(DBG_CFG, "OCSP request to %s failed", url); DBG1(DBG_CFG, " ocsp request to %s failed", url);
chunk_free(&send); chunk_free(&send);
return NULL; return NULL;
} }
@@ -452,7 +452,7 @@ static ocsp_response_t *fetch_ocsp(private_credential_manager_t *this, char *url
BUILD_BLOB_ASN1_DER, receive, BUILD_END); BUILD_BLOB_ASN1_DER, receive, BUILD_END);
if (!response) if (!response)
{ {
DBG1(DBG_CFG, "parsing OCSP response from %s failed", url); DBG1(DBG_CFG, " parsing ocsp response failed");
return NULL; return NULL;
} }
@@ -466,14 +466,13 @@ static ocsp_response_t *fetch_ocsp(private_credential_manager_t *this, char *url
auth->destroy(auth); auth->destroy(auth);
if (!issuer_cert) if (!issuer_cert)
{ {
DBG1(DBG_CFG, "verifying OCSP response failed, no trusted " DBG1(DBG_CFG, " ocsp response untrusted: no signer certificate found");
"certificate found");
response->destroy(response); response->destroy(response);
return NULL; return NULL;
} }
if (!response->issued_by(response, issuer_cert, TRUE)) if (!response->issued_by(response, issuer_cert, TRUE))
{ {
DBG1(DBG_CFG, "verifying OCSP response signature failed"); DBG1(DBG_CFG, " ocsp response untrusted: bad signature");
response->destroy(response); response->destroy(response);
issuer_cert->destroy(issuer_cert); issuer_cert->destroy(issuer_cert);
return NULL; return NULL;
@@ -481,8 +480,7 @@ static ocsp_response_t *fetch_ocsp(private_credential_manager_t *this, char *url
issuer_cert->destroy(issuer_cert); issuer_cert->destroy(issuer_cert);
/* TODO: cache response? */ /* TODO: cache response? */
return response;
return (ocsp_response_t*)response;
} }
/** /**
@@ -492,99 +490,155 @@ static cert_validation_t check_ocsp(private_credential_manager_t *this,
x509_t *subject, x509_t *issuer, x509_t *subject, x509_t *issuer,
auth_info_t *auth) auth_info_t *auth)
{ {
public_key_t *public; certificate_t *sub = (certificate_t*)subject;
enumerator_t *enumerator; certificate_t *best_cert = NULL;
ocsp_response_t *response = NULL;
certificate_t *cert, *sub = (certificate_t*)subject;
cert_validation_t valid = VALIDATION_SKIPPED; cert_validation_t valid = VALIDATION_SKIPPED;
identification_t *keyid = NULL; identification_t *keyid = NULL;
char *url; bool stale = TRUE;
cert = &issuer->interface; /* derive the authorityKeyIdentifier from the issuer's public key */
public = cert->get_public_key(cert);
if (public)
{ {
keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1); certificate_t *cert = &issuer->interface;
public_key_t *public = cert->get_public_key(cert);
if (public)
{
keyid = public->get_id(public, ID_PUBKEY_SHA1);
public->destroy(public);
}
} }
/* find a OCSP response by Authority key identifier (cache) */ /* find a cached ocsp response by authorityKeyIdentifier */
if (keyid) if (keyid)
{ {
time_t update, best_update = 0; enumerator_t *enumerator = create_cert_enumerator(this,
CERT_X509_OCSP_RESPONSE,
KEY_ANY, keyid, TRUE);
certificate_t *cert;
enumerator = create_cert_enumerator(this, CERT_X509_OCSP_RESPONSE,
KEY_ANY, keyid, TRUE);
while (enumerator->enumerate(enumerator, &cert)) while (enumerator->enumerate(enumerator, &cert))
{ /* get newest valid response */ {
if (cert->has_subject(cert, sub->get_subject(sub)) && if (cert->has_subject(cert, sub->get_subject(sub)))
cert->get_validity(cert, NULL, &update, NULL) &&
update > best_update)
{ {
best_update = update; /* select most recent ocsp response */
DESTROY_IF(&response->certificate); if (best_cert == NULL || cert->is_newer(cert, best_cert))
response = (ocsp_response_t*)cert; {
valid = VALIDATION_FAILED; DESTROY_IF(best_cert);
best_cert = cert->get_ref(cert);
}
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
} }
/* check the validity of the cached ocsp response if one was found */
if (best_cert)
{
stale = !best_cert->get_validity(best_cert, NULL, NULL, NULL);
DBG1(DBG_CFG, "cached ocsp response is %s", stale? "stale":"valid");
}
/* fallback to URL fetching from CDPs */ /* fallback to URL fetching from CDPs */
if (!response && keyid) if (stale && keyid)
{ {
enumerator = create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE, keyid); enumerator_t *enumerator = create_cdp_enumerator(this,
while (enumerator->enumerate(enumerator, &url)) CERT_X509_OCSP_RESPONSE, keyid);
char *uri;
while (enumerator->enumerate(enumerator, &uri))
{ {
certificate_t* cert = fetch_ocsp(this, uri, &subject->interface,
&issuer->interface);
/* redefine default since we have at least one uri */
valid = VALIDATION_FAILED; valid = VALIDATION_FAILED;
response = fetch_ocsp(this, url, &subject->interface, &issuer->interface);
if (response) if (cert)
{ {
break; /* select most recent ocsp response until valid one is found */
if (best_cert == NULL || cert->is_newer(cert, best_cert))
{
DESTROY_IF(best_cert);
best_cert = cert;
stale = !best_cert->get_validity(best_cert, NULL, NULL, NULL);
DBG1(DBG_CFG, "ocsp response is %s", stale? "stale":"valid");
if (!stale)
{
break;
}
}
else
{
cert->destroy(cert);
}
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
} }
/* fallback to URL fetching from subject certificate's URIs */ /* fallback to URL fetching from subject certificate's URIs */
if (!response) if (stale)
{ {
enumerator = subject->create_ocsp_uri_enumerator(subject); enumerator_t *enumerator = subject->create_ocsp_uri_enumerator(subject);
while (enumerator->enumerate(enumerator, &url)) char *uri;
while (enumerator->enumerate(enumerator, &uri))
{ {
certificate_t* cert = fetch_ocsp(this, uri, &subject->interface,
&issuer->interface);
/* redefine default since we have at least one uri */
valid = VALIDATION_FAILED; valid = VALIDATION_FAILED;
response = fetch_ocsp(this, url, &subject->interface, &issuer->interface);
if (response) if (cert)
{ {
break; /* select most recent ocsp response until valid one is found */
if (best_cert == NULL || cert->is_newer(cert, best_cert))
{
DESTROY_IF(best_cert);
best_cert = cert;
stale = !best_cert->get_validity(best_cert, NULL, NULL, NULL);
DBG1(DBG_CFG, "ocsp response is %s", stale? "stale":"valid");
if (!stale)
{
break;
}
}
else
{
cert->destroy(cert);
}
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
} }
/* look for subject in response */
if (response) /* if we have an ocsp response, check the revocation status */
if (best_cert)
{ {
time_t revocation, this_update, next_update; time_t revocation, this_update, next_update;
crl_reason_t reason; crl_reason_t reason;
ocsp_response_t *response = (ocsp_response_t*)best_cert;
valid = response->get_status(response, subject, issuer, &revocation, valid = response->get_status(response, subject, issuer, &revocation,
&reason, &this_update, &next_update); &reason, &this_update, &next_update);
switch (valid) switch (valid)
{ {
case VALIDATION_FAILED: case VALIDATION_FAILED:
DBG1(DBG_CFG, "subject not found in OCSP response"); DBG1(DBG_CFG, "subject not found in ocsp response");
break; break;
case VALIDATION_REVOKED: case VALIDATION_REVOKED:
DBG1(DBG_CFG, "certificate %D revoked by OCSP at %T: %N", DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
cert->get_subject(cert), &revocation, &revocation, crl_reason_names, reason);
crl_reason_names, reason);
break; break;
case VALIDATION_GOOD: case VALIDATION_GOOD:
break; case VALIDATION_UNKNOWN:
default: default:
break; break;
} }
cert = (certificate_t*)response; best_cert->destroy(best_cert);
cert->destroy(cert);
} }
DESTROY_IF(public);
if (auth) if (auth)
{ {
auth->add_item(auth, AUTHZ_OCSP_VALIDATION, &valid); auth->add_item(auth, AUTHZ_OCSP_VALIDATION, &valid);
@@ -668,7 +722,7 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
} }
} }
/* find a local crl by authorityKeyIdentifier */ /* find a cached crl by authorityKeyIdentifier */
if (keyid) if (keyid)
{ {
enumerator_t *enumerator = create_cert_enumerator(this, CERT_X509_CRL, enumerator_t *enumerator = create_cert_enumerator(this, CERT_X509_CRL,
@@ -677,11 +731,8 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
while (enumerator->enumerate(enumerator, &cert)) while (enumerator->enumerate(enumerator, &cert))
{ {
crl_t *crl = (crl_t*)cert;
crl_t *best_crl = (crl_t*)best_cert;
/* select most recent crl */ /* select most recent crl */
if (best_cert == NULL || crl->is_newer(crl, best_crl)) if (best_cert == NULL || cert->is_newer(cert, best_cert))
{ {
DESTROY_IF(best_cert); DESTROY_IF(best_cert);
best_cert = cert->get_ref(cert); best_cert = cert->get_ref(cert);
@@ -690,15 +741,11 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
} }
/* check the validity of the local crl if one was found */ /* check the validity of the cached crl if one was found */
if (best_cert) if (best_cert)
{ {
stale = !best_cert->get_validity(best_cert, NULL, NULL, NULL); stale = !best_cert->get_validity(best_cert, NULL, NULL, NULL);
DBG1(DBG_CFG, "locally-stored crl is %s", stale? "stale":"valid"); DBG1(DBG_CFG, "cached crl is %s", stale? "stale":"valid");
}
else
{
DBG1(DBG_CFG, "no locally-stored crl found");
} }
/* fallback to fetching crls from cdps defined in ca info sections */ /* fallback to fetching crls from cdps defined in ca info sections */
@@ -717,11 +764,8 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
if (cert) if (cert)
{ {
crl_t *crl = (crl_t*)cert; /* select most recent crl until valid one is found */
crl_t *best_crl = (crl_t*)best_cert; if (best_cert == NULL || cert->is_newer(cert, best_cert))
/* select most recent crl */
if (best_cert == NULL || crl->is_newer(crl, best_crl))
{ {
DESTROY_IF(best_cert); DESTROY_IF(best_cert);
best_cert = cert; best_cert = cert;
@@ -756,11 +800,8 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
if (cert) if (cert)
{ {
crl_t *crl = (crl_t*)cert; /* select most recent crl until valid one is found */
crl_t *best_crl = (crl_t*)best_cert; if (best_cert == NULL || cert->is_newer(cert, best_cert))
/* select most recent crl */
if (best_cert == NULL || crl->is_newer(crl, best_crl))
{ {
DESTROY_IF(best_cert); DESTROY_IF(best_cert);
best_cert = cert; best_cert = cert;
@@ -783,6 +824,7 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
/* if we have a crl, check the revocation status */ /* if we have a crl, check the revocation status */
if (best_cert) if (best_cert)
{ {
chunk_t subject_serial = subject->get_serial(subject);
chunk_t serial; chunk_t serial;
time_t revocation; time_t revocation;
crl_reason_t reason; crl_reason_t reason;
@@ -794,7 +836,7 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
while (enumerator->enumerate(enumerator, &serial, &revocation, &reason)) while (enumerator->enumerate(enumerator, &serial, &revocation, &reason))
{ {
if (chunk_equals(serial, subject->get_serial(subject))) if (chunk_equals(serial, subject_serial))
{ {
DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N", DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
&revocation, crl_reason_names, reason); &revocation, crl_reason_names, reason);
@@ -842,10 +884,11 @@ static bool check_certificate(private_credential_manager_t *this,
switch (check_ocsp(this, (x509_t*)subject, (x509_t*)issuer, auth)) switch (check_ocsp(this, (x509_t*)subject, (x509_t*)issuer, auth))
{ {
case VALIDATION_GOOD: case VALIDATION_GOOD:
DBG1(DBG_CFG, "certificate %D validated by OCSP", DBG1(DBG_CFG, "certificate status is good",
subject->get_subject(subject)); subject->get_subject(subject));
return TRUE; return TRUE;
case VALIDATION_REVOKED: case VALIDATION_REVOKED:
/* has already been logged */
return FALSE; return FALSE;
case VALIDATION_SKIPPED: case VALIDATION_SKIPPED:
DBG2(DBG_CFG, "OCSP check skipped, no OCSP URI found"); DBG2(DBG_CFG, "OCSP check skipped, no OCSP URI found");
+1 -1
View File
@@ -853,7 +853,7 @@ static void add_crl(private_stroke_t *this, crl_t* crl)
} }
if (found) if (found)
{ {
new = crl->is_newer(crl, crl_c); new = cert->is_newer(cert, current);
if (new) if (new)
{ {
this->creds.certs->remove_at(this->creds.certs, enumerator); this->creds.certs->remove_at(this->creds.certs, enumerator);
@@ -159,6 +159,13 @@ struct certificate_t {
bool (*get_validity)(certificate_t *this, time_t *when, bool (*get_validity)(certificate_t *this, time_t *when,
time_t *not_before, time_t *not_after); time_t *not_before, time_t *not_after);
/**
* Is this newer than that?
*
* @return TRUE if newer, FALSE otherwise
*/
bool (*is_newer)(certificate_t *this, certificate_t *that);
/** /**
* Get the certificate in an encoded form. * Get the certificate in an encoded form.
* *
@@ -57,13 +57,6 @@ struct crl_t {
*/ */
certificate_t certificate; certificate_t certificate;
/**
* Is that newer than this?
*
* @return TRUE if newer, FALSE otherwise
*/
bool (*is_newer)(crl_t *this, crl_t *that);
/** /**
* Get the CRL serial number. * Get the CRL serial number.
* *
+22 -4
View File
@@ -1035,17 +1035,34 @@ static bool get_validity(private_x509_cert_t *this, time_t *when,
{ {
t = time(NULL); t = time(NULL);
} }
if (not_after)
{
*not_after = this->notAfter;
}
if (not_before) if (not_before)
{ {
*not_before = this->notBefore; *not_before = this->notBefore;
} }
if (not_after)
{
*not_after = this->notAfter;
}
return (t >= this->notBefore && t <= this->notAfter); return (t >= this->notBefore && t <= this->notAfter);
} }
/**
* Implementation of certificate_t.is_newer.
*/
static bool is_newer(certificate_t *this, certificate_t *that)
{
time_t this_update, that_update, now = time(NULL);
bool new;
this->get_validity(this, &now, &this_update, NULL);
that->get_validity(that, &now, &that_update, NULL);
new = this_update > that_update;
DBG1(" certificate from %#T is %s - existing certificate from %#T %s",
&this_update, FALSE, new ? "newer":"not newer",
&that_update, FALSE, new ? "replaced":"retained");
return new;
}
/** /**
* Implementation of certificate_t.get_encoding. * Implementation of certificate_t.get_encoding.
*/ */
@@ -1155,6 +1172,7 @@ static private_x509_cert_t *load(chunk_t chunk)
this->public.interface.interface.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer,bool))issued_by; this->public.interface.interface.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer,bool))issued_by;
this->public.interface.interface.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key; this->public.interface.interface.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key;
this->public.interface.interface.get_validity = (bool (*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity; this->public.interface.interface.get_validity = (bool (*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity;
this->public.interface.interface.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
this->public.interface.interface.get_encoding = (chunk_t (*)(certificate_t*))get_encoding; this->public.interface.interface.get_encoding = (chunk_t (*)(certificate_t*))get_encoding;
this->public.interface.interface.equals = (bool (*)(certificate_t*, certificate_t *other))equals; this->public.interface.interface.equals = (bool (*)(certificate_t*, certificate_t *other))equals;
this->public.interface.interface.get_ref = (certificate_t* (*)(certificate_t *this))get_ref; this->public.interface.interface.get_ref = (certificate_t* (*)(certificate_t *this))get_ref;
+38 -38
View File
@@ -325,39 +325,6 @@ static bool filter(void *data, revoked_t **revoked, chunk_t *serial, void *p2,
return TRUE; return TRUE;
} }
/**
* Implementation of crl_t.is_newer.
*/
static bool is_newer(private_x509_crl_t *this, crl_t *that)
{
chunk_t that_crlNumber = that->get_serial(that);
bool new;
/* compare crlNumbers if available - otherwise use thisUpdate */
if (this->crlNumber.ptr != NULL && that_crlNumber.ptr != NULL)
{
new = chunk_compare(this->crlNumber, that_crlNumber) > 0;
DBG1(" crl #%#B is %s - existing crl #%#B %s",
&this->crlNumber, new ? "newer":"not newer",
&that_crlNumber, new ? "replaced":"retained");
}
else
{
certificate_t *this_cert = &this->public.crl.certificate;
certificate_t *that_cert = &that->certificate;
time_t this_update, that_update, now = time(NULL);
this_cert->get_validity(this_cert, &now, &this_update, NULL);
that_cert->get_validity(that_cert, &now, &that_update, NULL);
new = this_update > that_update;
DBG1(" crl from %#T is %s - existing crl from %#T %s",
&this_update, FALSE, new ? "newer":"not newer",
&that_update, FALSE, new ? "replaced":"retained");
}
return new;
}
/** /**
* Implementation of crl_t.get_serial. * Implementation of crl_t.get_serial.
*/ */
@@ -550,17 +517,50 @@ static bool get_validity(private_x509_crl_t *this, time_t *when,
{ {
t = time(NULL); t = time(NULL);
} }
if (not_after)
{
*not_after = this->nextUpdate;
}
if (not_before) if (not_before)
{ {
*not_before = this->thisUpdate; *not_before = this->thisUpdate;
} }
if (not_after)
{
*not_after = this->nextUpdate;
}
return (t <= this->nextUpdate); return (t <= this->nextUpdate);
} }
/**
* Implementation of certificate_t.is_newer.
*/
static bool is_newer(private_x509_crl_t *this, crl_t *that)
{
chunk_t that_crlNumber = that->get_serial(that);
bool new;
/* compare crlNumbers if available - otherwise use thisUpdate */
if (this->crlNumber.ptr != NULL && that_crlNumber.ptr != NULL)
{
new = chunk_compare(this->crlNumber, that_crlNumber) > 0;
DBG1(" crl #%#B is %s - existing crl #%#B %s",
&this->crlNumber, new ? "newer":"not newer",
&that_crlNumber, new ? "replaced":"retained");
}
else
{
certificate_t *this_cert = &this->public.crl.certificate;
certificate_t *that_cert = &that->certificate;
time_t this_update, that_update, now = time(NULL);
this_cert->get_validity(this_cert, &now, &this_update, NULL);
that_cert->get_validity(that_cert, &now, &that_update, NULL);
new = this_update > that_update;
DBG1(" crl from %#T is %s - existing crl from %#T %s",
&this_update, FALSE, new ? "newer":"not newer",
&that_update, FALSE, new ? "replaced":"retained");
}
return new;
}
/** /**
* Implementation of certificate_t.get_encoding. * Implementation of certificate_t.get_encoding.
*/ */
@@ -609,7 +609,6 @@ static x509_crl_t *load(chunk_t chunk)
{ {
private_x509_crl_t *this = malloc_thing(private_x509_crl_t); private_x509_crl_t *this = malloc_thing(private_x509_crl_t);
this->public.crl.is_newer = (bool (*)(crl_t*,crl_t*))is_newer;
this->public.crl.get_serial = (chunk_t (*)(crl_t*))get_serial; this->public.crl.get_serial = (chunk_t (*)(crl_t*))get_serial;
this->public.crl.get_authKeyIdentifier = (identification_t* (*)(crl_t*))get_authKeyIdentifier; this->public.crl.get_authKeyIdentifier = (identification_t* (*)(crl_t*))get_authKeyIdentifier;
this->public.crl.create_enumerator = (enumerator_t* (*)(crl_t*))create_enumerator; this->public.crl.create_enumerator = (enumerator_t* (*)(crl_t*))create_enumerator;
@@ -621,6 +620,7 @@ static x509_crl_t *load(chunk_t chunk)
this->public.crl.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer,bool))issued_by; this->public.crl.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer,bool))issued_by;
this->public.crl.certificate.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key; this->public.crl.certificate.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key;
this->public.crl.certificate.get_validity = (bool (*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity; this->public.crl.certificate.get_validity = (bool (*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity;
this->public.crl.certificate.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
this->public.crl.certificate.get_encoding = (chunk_t (*)(certificate_t*))get_encoding; this->public.crl.certificate.get_encoding = (chunk_t (*)(certificate_t*))get_encoding;
this->public.crl.certificate.equals = (bool (*)(certificate_t*, certificate_t *other))equals; this->public.crl.certificate.equals = (bool (*)(certificate_t*, certificate_t *other))equals;
this->public.crl.certificate.get_ref = (certificate_t* (*)(certificate_t *this))get_ref; this->public.crl.certificate.get_ref = (certificate_t* (*)(certificate_t *this))get_ref;
@@ -58,7 +58,10 @@ struct private_x509_ocsp_response_t {
int signatureAlgorithm; int signatureAlgorithm;
/** /**
* signature value * signature enumerator = this->responses->create_enumerator(this->responses);
while (enumerator->enumerate(enumerator, &response))
{
value
*/ */
chunk_t signature; chunk_t signature;
@@ -420,7 +423,7 @@ static bool parse_singleResponse(private_x509_ocsp_response_t *this,
} }
break; break;
case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN: case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN:
response->status = VALIDATION_FAILED; response->status = VALIDATION_UNKNOWN;
break; break;
case SINGLE_RESPONSE_THIS_UPDATE: case SINGLE_RESPONSE_THIS_UPDATE:
response->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME); response->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
@@ -725,13 +728,25 @@ static public_key_t* get_public_key(private_x509_ocsp_response_t *this)
} }
/** /**
* Implementation of x509_cert_t.get_validity. * Implementation of certificate_t.get_validity.
*/ */
static bool get_validity(private_x509_ocsp_response_t *this, time_t *when, static bool get_validity(private_x509_ocsp_response_t *this, time_t *when,
time_t *not_before, time_t *not_after) time_t *not_before, time_t *not_after)
{ {
enumerator_t *enumerator;
single_response_t *response;
time_t thisUpdate = this->producedAt;
time_t nextUpdate = 0;
time_t t; time_t t;
enumerator = this->responses->create_enumerator(this->responses);
if (enumerator->enumerate(enumerator, &response))
{
thisUpdate = response->thisUpdate;
nextUpdate = response->nextUpdate;
}
enumerator->destroy(enumerator);
if (when == NULL) if (when == NULL)
{ {
t = time(NULL); t = time(NULL);
@@ -742,18 +757,30 @@ static bool get_validity(private_x509_ocsp_response_t *this, time_t *when,
} }
if (not_before) if (not_before)
{ {
*not_before = this->producedAt; *not_before = thisUpdate;
} }
if (not_after) if (not_after)
{ {
*not_after = ~0; *not_after = nextUpdate;
} }
/* valid from produceAt up to infinity */ return (t < nextUpdate);
if (t >= this->producedAt) }
{
return TRUE; /**
} * Implementation of certificate_t.is_newer.
return FALSE; */
static bool is_newer(certificate_t *this, certificate_t *that)
{
time_t this_update, that_update, now = time(NULL);
bool new;
this->get_validity(this, &now, &this_update, NULL);
that->get_validity(that, &now, &that_update, NULL);
new = this_update > that_update;
DBG1(" ocsp response from %#T is %s - existing ocsp response from %#T %s",
&this_update, FALSE, new ? "newer":"not newer",
&that_update, FALSE, new ? "replaced":"retained");
return new;
} }
/** /**
@@ -828,6 +855,7 @@ static x509_ocsp_response_t *load(chunk_t data)
this->public.interface.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer,bool))issued_by; this->public.interface.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer,bool))issued_by;
this->public.interface.certificate.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key; this->public.interface.certificate.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key;
this->public.interface.certificate.get_validity = (bool(*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity; this->public.interface.certificate.get_validity = (bool(*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity;
this->public.interface.certificate.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
this->public.interface.certificate.get_encoding = (chunk_t(*)(certificate_t*))get_encoding; this->public.interface.certificate.get_encoding = (chunk_t(*)(certificate_t*))get_encoding;
this->public.interface.certificate.equals = (bool(*)(certificate_t*, certificate_t *other))equals; this->public.interface.certificate.equals = (bool(*)(certificate_t*, certificate_t *other))equals;
this->public.interface.certificate.get_ref = (certificate_t* (*)(certificate_t *this))get_ref; this->public.interface.certificate.get_ref = (certificate_t* (*)(certificate_t *this))get_ref;