caching of ocsp responses (experimental), no crl caching yet
This commit is contained in:
@@ -331,6 +331,7 @@ static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url,
|
|||||||
request->destroy(request);
|
request->destroy(request);
|
||||||
|
|
||||||
DBG1(DBG_CFG, "requesting ocsp status from '%s' ...", url);
|
DBG1(DBG_CFG, "requesting ocsp status from '%s' ...", url);
|
||||||
|
/* TODO: unlock manager while fetching? */
|
||||||
if (lib->fetcher->fetch(lib->fetcher, url, &receive,
|
if (lib->fetcher->fetch(lib->fetcher, url, &receive,
|
||||||
FETCH_REQUEST_DATA, send,
|
FETCH_REQUEST_DATA, send,
|
||||||
FETCH_REQUEST_TYPE, "application/ocsp-request",
|
FETCH_REQUEST_TYPE, "application/ocsp-request",
|
||||||
@@ -350,50 +351,111 @@ static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url,
|
|||||||
DBG1(DBG_CFG, "parsing ocsp response failed");
|
DBG1(DBG_CFG, "parsing ocsp response failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check the signature of an OCSP response
|
||||||
|
*/
|
||||||
|
static bool check_ocsp_response(private_credential_manager_t *this,
|
||||||
|
ocsp_response_t *response)
|
||||||
|
{
|
||||||
|
certificate_t *issuer, *subject;
|
||||||
|
identification_t *responder;
|
||||||
|
auth_info_t *auth;
|
||||||
|
ocsp_response_wrapper_t *wrapper;
|
||||||
|
|
||||||
/* verify the signature of the ocsp response */
|
auth = auth_info_create();
|
||||||
|
wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response);
|
||||||
|
this->sets->remove(this->sets, this->cache, NULL);
|
||||||
|
this->sets->insert_first(this->sets, wrapper);
|
||||||
|
this->sets->insert_first(this->sets, this->cache);
|
||||||
|
|
||||||
|
subject = &response->certificate;
|
||||||
|
responder = subject->get_issuer(subject);
|
||||||
|
issuer = get_trusted_cert(this, KEY_ANY, responder, auth, FALSE, FALSE);
|
||||||
|
|
||||||
|
this->sets->remove(this->sets, wrapper, NULL);
|
||||||
|
wrapper->destroy(wrapper);
|
||||||
|
auth->destroy(auth);
|
||||||
|
|
||||||
|
if (!issuer)
|
||||||
{
|
{
|
||||||
certificate_t *issuer_cert;
|
DBG1(DBG_CFG, "OCSP response verification failed, responder cert missing");
|
||||||
identification_t *responder;
|
return FALSE;
|
||||||
auth_info_t *auth;
|
}
|
||||||
ocsp_response_wrapper_t *wrapper;
|
if (!this->cache->issued_by(this->cache, subject, issuer))
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "OCSP response verification failed");
|
||||||
|
issuer->destroy(issuer);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
issuer->destroy(issuer);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
auth = auth_info_create();
|
/**
|
||||||
wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response);
|
* Get the better of two OCSP responses, and check for usable OCSP info
|
||||||
this->sets->remove(this->sets, this->cache, NULL);
|
*/
|
||||||
this->sets->insert_first(this->sets, wrapper);
|
static certificate_t *get_better_ocsp(private_credential_manager_t *this,
|
||||||
this->sets->insert_first(this->sets, this->cache);
|
certificate_t *cand, certificate_t *best,
|
||||||
responder = response->get_issuer(response);
|
x509_t *subject, x509_t *issuer,
|
||||||
DBG1(DBG_CFG, " ocsp signer is \"%D\"", responder);
|
cert_validation_t *valid)
|
||||||
issuer_cert = get_trusted_cert(this, KEY_ANY, responder, auth, FALSE, FALSE);
|
{
|
||||||
this->sets->remove(this->sets, wrapper, NULL);
|
ocsp_response_t *response;
|
||||||
wrapper->destroy(wrapper);
|
time_t revocation, this_update, next_update, valid_until;
|
||||||
auth->destroy(auth);
|
crl_reason_t reason;
|
||||||
|
|
||||||
if (!issuer_cert)
|
response = (ocsp_response_t*)cand;
|
||||||
|
|
||||||
|
/* check ocsp signature */
|
||||||
|
if (!check_ocsp_response(this, response))
|
||||||
|
{
|
||||||
|
cand->destroy(cand);
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
/* check if response contains our certificate */
|
||||||
|
switch (response->get_status(response, subject, issuer, &revocation, &reason,
|
||||||
|
&this_update, &next_update))
|
||||||
|
{
|
||||||
|
case VALIDATION_REVOKED:
|
||||||
|
/* subject has been revoked by a valid OCSP response */
|
||||||
|
DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
|
||||||
|
&revocation, crl_reason_names, reason);
|
||||||
|
DESTROY_IF(best);
|
||||||
|
return cand;
|
||||||
|
case VALIDATION_GOOD:
|
||||||
|
/* results in either good or stale */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case VALIDATION_FAILED:
|
||||||
|
/* candidate unusable, does not contain our cert */
|
||||||
|
cand->destroy(cand);
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* select the better of the two responses */
|
||||||
|
if (best == NULL || cand->is_newer(cand, best))
|
||||||
|
{
|
||||||
|
DESTROY_IF(best);
|
||||||
|
best = cand;
|
||||||
|
if (best->get_validity(best, NULL, NULL, &valid_until))
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "ocsp response untrusted: no signer certificate found");
|
DBG1(DBG_CFG, " ocsp response is valid: until %#T", &valid_until);
|
||||||
response->destroy(response);
|
*valid = VALIDATION_GOOD;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (this->cache->issued_by(this->cache, response, issuer_cert))
|
|
||||||
{
|
|
||||||
DBG1(DBG_CFG, " ocsp response correctly signed by \"%D\"",
|
|
||||||
issuer_cert->get_subject(issuer_cert));
|
|
||||||
issuer_cert->destroy(issuer_cert);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "ocsp response not accepted from \"%D\"",
|
DBG1(DBG_CFG, " ocsp response is stale: since %#T", &valid_until);
|
||||||
issuer_cert->get_subject(issuer_cert));
|
*valid = VALIDATION_STALE;
|
||||||
issuer_cert->destroy(issuer_cert);
|
|
||||||
response->destroy(response);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* TODO: cache response? */
|
else
|
||||||
return response;
|
{
|
||||||
|
*valid = VALIDATION_STALE;
|
||||||
|
cand->destroy(cand);
|
||||||
|
}
|
||||||
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -403,92 +465,49 @@ 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)
|
||||||
{
|
{
|
||||||
certificate_t *sub = (certificate_t*)subject;
|
enumerator_t *enumerator;
|
||||||
certificate_t *best_cert = NULL;
|
|
||||||
certificate_t *cert;
|
|
||||||
public_key_t *public;
|
|
||||||
cert_validation_t valid = VALIDATION_SKIPPED;
|
cert_validation_t valid = VALIDATION_SKIPPED;
|
||||||
|
certificate_t *best = NULL, *current;
|
||||||
identification_t *keyid = NULL;
|
identification_t *keyid = NULL;
|
||||||
bool stale = TRUE;
|
public_key_t *public;
|
||||||
|
char *uri = NULL;
|
||||||
|
|
||||||
|
/** lookup cache for valid OCSP responses */
|
||||||
|
enumerator = create_cert_enumerator(this, CERT_X509_OCSP_RESPONSE,
|
||||||
|
KEY_ANY, NULL, FALSE);
|
||||||
|
while (enumerator->enumerate(enumerator, ¤t))
|
||||||
|
{
|
||||||
|
current->get_ref(current);
|
||||||
|
best = get_better_ocsp(this, current, best, subject, issuer, &valid);
|
||||||
|
if (best && valid != VALIDATION_STALE)
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, " used cached ocsp response");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
/* derive the authorityKeyIdentifier from the issuer's public key */
|
/* derive the authorityKeyIdentifier from the issuer's public key */
|
||||||
cert = &issuer->interface;
|
current = &issuer->interface;
|
||||||
public = cert->get_public_key(cert);
|
public = current->get_public_key(current);
|
||||||
if (public)
|
if (public)
|
||||||
{
|
{
|
||||||
keyid = public->get_id(public, ID_PUBKEY_SHA1);
|
keyid = public->get_id(public, ID_PUBKEY_SHA1);
|
||||||
}
|
}
|
||||||
|
/** fetch from configured OCSP responder URLs */
|
||||||
/* find a cached ocsp response by authorityKeyIdentifier */
|
if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
|
||||||
if (keyid)
|
|
||||||
{
|
{
|
||||||
enumerator_t *enumerator = create_cert_enumerator(this,
|
enumerator = create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE, keyid);
|
||||||
CERT_X509_OCSP_RESPONSE,
|
|
||||||
KEY_ANY, keyid, TRUE);
|
|
||||||
certificate_t *cert;
|
|
||||||
|
|
||||||
while (enumerator->enumerate(enumerator, &cert))
|
|
||||||
{
|
|
||||||
if (cert->has_subject(cert, sub->get_subject(sub)))
|
|
||||||
{
|
|
||||||
/* select most recent ocsp response */
|
|
||||||
if (best_cert == NULL || cert->is_newer(cert, best_cert))
|
|
||||||
{
|
|
||||||
DESTROY_IF(best_cert);
|
|
||||||
best_cert = cert->get_ref(cert);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
enumerator->destroy(enumerator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check the validity of the cached ocsp response if one was found */
|
|
||||||
if (best_cert)
|
|
||||||
{
|
|
||||||
time_t nextUpdate;
|
|
||||||
|
|
||||||
stale = !best_cert->get_validity(best_cert, NULL, NULL, &nextUpdate);
|
|
||||||
DBG1(DBG_CFG, "cached ocsp response is %s %#T",
|
|
||||||
stale? "stale: since":"valid: until",
|
|
||||||
&nextUpdate, FALSE );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fallback to URL fetching from CDPs */
|
|
||||||
if (stale && keyid)
|
|
||||||
{
|
|
||||||
enumerator_t *enumerator = create_cdp_enumerator(this,
|
|
||||||
CERT_X509_OCSP_RESPONSE, keyid);
|
|
||||||
char *uri;
|
|
||||||
|
|
||||||
while (enumerator->enumerate(enumerator, &uri))
|
while (enumerator->enumerate(enumerator, &uri))
|
||||||
{
|
{
|
||||||
certificate_t* cert = fetch_ocsp(this, uri, &subject->interface,
|
current = fetch_ocsp(this, uri, &subject->interface,
|
||||||
&issuer->interface);
|
&issuer->interface);
|
||||||
|
if (current)
|
||||||
/* redefine default since we have at least one uri */
|
|
||||||
valid = VALIDATION_FAILED;
|
|
||||||
|
|
||||||
if (cert)
|
|
||||||
{
|
{
|
||||||
/* select most recent ocsp response until valid one is found */
|
best = get_better_ocsp(this, current, best, subject, issuer, &valid);
|
||||||
if (best_cert == NULL || cert->is_newer(cert, best_cert))
|
if (best && valid != VALIDATION_STALE)
|
||||||
{
|
{
|
||||||
time_t nextUpdate;
|
break;
|
||||||
|
|
||||||
DESTROY_IF(best_cert);
|
|
||||||
best_cert = cert;
|
|
||||||
stale = !best_cert->get_validity(best_cert, NULL, NULL, &nextUpdate);
|
|
||||||
DBG1(DBG_CFG, "ocsp response is %s %#T",
|
|
||||||
stale? "stale: since":"valid: until",
|
|
||||||
&nextUpdate, FALSE );
|
|
||||||
if (!stale)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cert->destroy(cert);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -497,76 +516,34 @@ static cert_validation_t check_ocsp(private_credential_manager_t *this,
|
|||||||
DESTROY_IF(public);
|
DESTROY_IF(public);
|
||||||
|
|
||||||
/* fallback to URL fetching from subject certificate's URIs */
|
/* fallback to URL fetching from subject certificate's URIs */
|
||||||
if (stale)
|
if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
|
||||||
{
|
{
|
||||||
enumerator_t *enumerator = subject->create_ocsp_uri_enumerator(subject);
|
enumerator = subject->create_ocsp_uri_enumerator(subject);
|
||||||
char *uri;
|
|
||||||
|
|
||||||
while (enumerator->enumerate(enumerator, &uri))
|
while (enumerator->enumerate(enumerator, &uri))
|
||||||
{
|
{
|
||||||
certificate_t* cert = fetch_ocsp(this, uri, &subject->interface,
|
current = fetch_ocsp(this, uri, &subject->interface,
|
||||||
&issuer->interface);
|
&issuer->interface);
|
||||||
|
if (current)
|
||||||
/* redefine default since we have at least one uri */
|
|
||||||
valid = VALIDATION_FAILED;
|
|
||||||
|
|
||||||
if (cert)
|
|
||||||
{
|
{
|
||||||
/* select most recent ocsp response until valid one is found */
|
best = get_better_ocsp(this, current, best, subject, issuer, &valid);
|
||||||
if (best_cert == NULL || cert->is_newer(cert, best_cert))
|
if (best && valid != VALIDATION_STALE)
|
||||||
{
|
{
|
||||||
time_t nextUpdate;
|
break;
|
||||||
|
|
||||||
DESTROY_IF(best_cert);
|
|
||||||
best_cert = cert;
|
|
||||||
stale = !best_cert->get_validity(best_cert, NULL, NULL, &nextUpdate);
|
|
||||||
DBG1(DBG_CFG, "ocsp response is %s %#T",
|
|
||||||
stale? "stale: since":"valid: until",
|
|
||||||
&nextUpdate, FALSE );
|
|
||||||
if (!stale)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cert->destroy(cert);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
}
|
}
|
||||||
|
/* an uri was found, but no result. switch validation state to failed */
|
||||||
/* if we have an ocsp response, check the revocation status */
|
if (valid == VALIDATION_SKIPPED && uri)
|
||||||
if (best_cert)
|
|
||||||
{
|
{
|
||||||
time_t revocation, this_update, next_update;
|
valid = VALIDATION_FAILED;
|
||||||
crl_reason_t reason;
|
|
||||||
ocsp_response_t *response = (ocsp_response_t*)best_cert;
|
|
||||||
|
|
||||||
valid = response->get_status(response, subject, issuer, &revocation,
|
|
||||||
&reason, &this_update, &next_update);
|
|
||||||
switch (valid)
|
|
||||||
{
|
|
||||||
case VALIDATION_FAILED:
|
|
||||||
DBG1(DBG_CFG, "subject not found in ocsp response");
|
|
||||||
break;
|
|
||||||
case VALIDATION_REVOKED:
|
|
||||||
DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
|
|
||||||
&revocation, crl_reason_names, reason);
|
|
||||||
break;
|
|
||||||
case VALIDATION_GOOD:
|
|
||||||
case VALIDATION_UNKNOWN:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
best_cert->destroy(best_cert);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auth)
|
if (auth)
|
||||||
{
|
{
|
||||||
auth->add_item(auth, AUTHZ_OCSP_VALIDATION, &valid);
|
auth->add_item(auth, AUTHZ_OCSP_VALIDATION, &valid);
|
||||||
}
|
}
|
||||||
|
DESTROY_IF(best);
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -771,7 +748,7 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
|
|||||||
enumerator_t *enumerator = crl->create_enumerator(crl);
|
enumerator_t *enumerator = crl->create_enumerator(crl);
|
||||||
|
|
||||||
/* redefine default */
|
/* redefine default */
|
||||||
valid = stale ? VALIDATION_UNKNOWN : VALIDATION_GOOD;
|
valid = stale ? VALIDATION_STALE : VALIDATION_GOOD;
|
||||||
|
|
||||||
while (enumerator->enumerate(enumerator, &serial, &revocation, &reason))
|
while (enumerator->enumerate(enumerator, &serial, &revocation, &reason))
|
||||||
{
|
{
|
||||||
@@ -831,8 +808,10 @@ static bool check_certificate(private_credential_manager_t *this,
|
|||||||
case VALIDATION_SKIPPED:
|
case VALIDATION_SKIPPED:
|
||||||
DBG2(DBG_CFG, "ocsp check skipped, no ocsp found");
|
DBG2(DBG_CFG, "ocsp check skipped, no ocsp found");
|
||||||
break;
|
break;
|
||||||
|
case VALIDATION_STALE:
|
||||||
|
DBG1(DBG_CFG, "ocsp information stale, fallback to crl");
|
||||||
|
break;
|
||||||
case VALIDATION_FAILED:
|
case VALIDATION_FAILED:
|
||||||
case VALIDATION_UNKNOWN:
|
|
||||||
DBG1(DBG_CFG, "ocsp check failed, fallback to crl");
|
DBG1(DBG_CFG, "ocsp check failed, fallback to crl");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -847,14 +826,12 @@ static bool check_certificate(private_credential_manager_t *this,
|
|||||||
case VALIDATION_REVOKED:
|
case VALIDATION_REVOKED:
|
||||||
/* has already been logged */
|
/* has already been logged */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
case VALIDATION_UNKNOWN:
|
|
||||||
DBG1(DBG_CFG, "certificate status is unknown");
|
|
||||||
break;
|
|
||||||
case VALIDATION_FAILED:
|
case VALIDATION_FAILED:
|
||||||
case VALIDATION_SKIPPED:
|
case VALIDATION_SKIPPED:
|
||||||
DBG1(DBG_CFG, "certificate status is not available");
|
DBG1(DBG_CFG, "certificate status is not available");
|
||||||
break;
|
break;
|
||||||
default:
|
case VALIDATION_STALE:
|
||||||
|
DBG1(DBG_CFG, "certificate status is unknown, crl is stale");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -993,8 +970,8 @@ static certificate_t *get_trusted_cert(private_credential_manager_t *this,
|
|||||||
subject = get_pretrusted_cert(this, type, id);
|
subject = get_pretrusted_cert(this, type, id);
|
||||||
if (subject)
|
if (subject)
|
||||||
{
|
{
|
||||||
|
/* if we find a trusted self signed certificate, we just accept it */
|
||||||
if (subject->issued_by(subject, subject, TRUE))
|
if (this->cache->issued_by(this->cache, subject, subject))
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, " using trusted self-signed certificate \"%D\"",
|
DBG1(DBG_CFG, " using trusted self-signed certificate \"%D\"",
|
||||||
subject->get_subject(subject));
|
subject->get_subject(subject));
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ static bool issued_by(private_cert_cache_t *this,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
/* no cache hit, check signature */
|
/* no cache hit, check signature */
|
||||||
if (!subject->issued_by(subject, issuer, TRUE))
|
if (!subject->issued_by(subject, issuer))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -131,10 +131,9 @@ static bool certs_filter(cert_data_t *data, relation_t **in, certificate_t **out
|
|||||||
public_key_t *public;
|
public_key_t *public;
|
||||||
certificate_t *cert;
|
certificate_t *cert;
|
||||||
|
|
||||||
/* serve all subjects, but only if an ID is requestd (no listing) */
|
|
||||||
cert = (*in)->subject;
|
cert = (*in)->subject;
|
||||||
if ((data->cert == CERT_ANY || cert->get_type(cert) == data->cert) &&
|
if ((data->cert == CERT_ANY || cert->get_type(cert) == data->cert) &&
|
||||||
data->id && cert->has_subject(cert, data->id))
|
(!data->id || cert->has_subject(cert, data->id)))
|
||||||
{
|
{
|
||||||
if (data->key == KEY_ANY)
|
if (data->key == KEY_ANY)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ credentials/certificates/certificate.c credentials/certificates/certificate.h \
|
|||||||
credentials/certificates/x509.h credentials/certificates/x509.c \
|
credentials/certificates/x509.h credentials/certificates/x509.c \
|
||||||
credentials/certificates/ac.h \
|
credentials/certificates/ac.h \
|
||||||
credentials/certificates/crl.h credentials/certificates/crl.c \
|
credentials/certificates/crl.h credentials/certificates/crl.c \
|
||||||
credentials/certificates/ocsp_request.h credentials/certificates/ocsp_request.c \
|
credentials/certificates/ocsp_request.h \
|
||||||
credentials/certificates/ocsp_response.h credentials/certificates/ocsp_response.c \
|
credentials/certificates/ocsp_response.h credentials/certificates/ocsp_response.c \
|
||||||
fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
|
fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
|
||||||
database/database.h database/database_factory.h database/database_factory.c \
|
database/database.h database/database_factory.h database/database_factory.c \
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ struct ac_t {
|
|||||||
* @param that other attribute certificate
|
* @param that other attribute certificate
|
||||||
* @return TRUE if same holder
|
* @return TRUE if same holder
|
||||||
*/
|
*/
|
||||||
bool (*equals_holder) (const ac_t *this, const ac_t *other);
|
bool (*equals_holder) (ac_t *this, ac_t *other);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* AC_H_ @}*/
|
#endif /* AC_H_ @}*/
|
||||||
|
|||||||
@@ -32,10 +32,10 @@ ENUM(certificate_type_names, CERT_ANY, CERT_PGP,
|
|||||||
);
|
);
|
||||||
|
|
||||||
ENUM(cert_validation_names, VALIDATION_GOOD, VALIDATION_SKIPPED,
|
ENUM(cert_validation_names, VALIDATION_GOOD, VALIDATION_SKIPPED,
|
||||||
"GOOD",
|
"VALIDATION_GOOD",
|
||||||
"REVOKED",
|
"VALIDATION_STALE",
|
||||||
"UNKNOWN",
|
"VALIDATION_REVOKED",
|
||||||
"FAILED",
|
"VALIDATION_FAILED",
|
||||||
"SKIPPED",
|
"VALIDATION_SKIPPED",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -62,13 +62,13 @@ extern enum_name_t *certificate_type_names;
|
|||||||
enum cert_validation_t {
|
enum cert_validation_t {
|
||||||
/** certificate has been validated successfully */
|
/** certificate has been validated successfully */
|
||||||
VALIDATION_GOOD,
|
VALIDATION_GOOD,
|
||||||
/** validation failed, certificate is revoked */
|
/** certificate has been validated, but check based on stale information */
|
||||||
|
VALIDATION_STALE,
|
||||||
|
/** certificate has been revoked */
|
||||||
VALIDATION_REVOKED,
|
VALIDATION_REVOKED,
|
||||||
/* ocsp status is unknown or crl is stale */
|
/** validation failed due to a processing error */
|
||||||
VALIDATION_UNKNOWN,
|
|
||||||
/** validation process failed due to an error */
|
|
||||||
VALIDATION_FAILED,
|
VALIDATION_FAILED,
|
||||||
/** validation has been skipped (no cdps available) */
|
/** validation has been skipped due to missing validation information */
|
||||||
VALIDATION_SKIPPED,
|
VALIDATION_SKIPPED,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -129,17 +129,12 @@ struct certificate_t {
|
|||||||
id_match_t (*has_issuer)(certificate_t *this, identification_t *issuer);
|
id_match_t (*has_issuer)(certificate_t *this, identification_t *issuer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this certificate is issued by a specific issuer.
|
* Check if this certificate is issued and signed by a specific issuer.
|
||||||
*
|
|
||||||
* As signature verification is computional expensive, it is optional
|
|
||||||
* and may be skipped. While this is not sufficient for verification
|
|
||||||
* purposes, it is to e.g. find matching certificates.
|
|
||||||
*
|
*
|
||||||
* @param issuer issuer's certificate
|
* @param issuer issuer's certificate
|
||||||
* @param checksig TRUE to verify signature, FALSE to compare issuer only
|
|
||||||
* @return TRUE if certificate issued by issuer and trusted
|
* @return TRUE if certificate issued by issuer and trusted
|
||||||
*/
|
*/
|
||||||
bool (*issued_by)(certificate_t *this, certificate_t *issuer, bool checksig);
|
bool (*issued_by)(certificate_t *this, certificate_t *issuer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the public key associated to this certificate.
|
* Get the public key associated to this certificate.
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2008 Martin Willi
|
|
||||||
* Hochschule fuer Technik Rapperswil
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at your
|
|
||||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* for more details.
|
|
||||||
*
|
|
||||||
* $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ocsp_request.h"
|
|
||||||
|
|
||||||
@@ -714,8 +714,7 @@ static id_match_t has_issuer(private_x509_ac_t *this, identification_t *issuer)
|
|||||||
/**
|
/**
|
||||||
* Implementation of certificate_t.issued_by
|
* Implementation of certificate_t.issued_by
|
||||||
*/
|
*/
|
||||||
static bool issued_by(private_x509_ac_t *this, certificate_t *issuer,
|
static bool issued_by(private_x509_ac_t *this, certificate_t *issuer)
|
||||||
bool sigcheck)
|
|
||||||
{
|
{
|
||||||
public_key_t *key;
|
public_key_t *key;
|
||||||
signature_scheme_t scheme;
|
signature_scheme_t scheme;
|
||||||
@@ -753,11 +752,6 @@ static bool issued_by(private_x509_ac_t *this, certificate_t *issuer,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sigcheck)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
/* TODO: generic OID to scheme mapper? */
|
/* TODO: generic OID to scheme mapper? */
|
||||||
switch (this->algorithm)
|
switch (this->algorithm)
|
||||||
{
|
{
|
||||||
@@ -912,7 +906,7 @@ static private_x509_ac_t *create_empty(void)
|
|||||||
this->public.interface.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
|
this->public.interface.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
|
||||||
this->public.interface.certificate.has_subject = (id_match_t(*)(certificate_t*, identification_t *subject))has_subject;
|
this->public.interface.certificate.has_subject = (id_match_t(*)(certificate_t*, identification_t *subject))has_subject;
|
||||||
this->public.interface.certificate.has_issuer = (id_match_t(*)(certificate_t*, identification_t *issuer))has_issuer;
|
this->public.interface.certificate.has_issuer = (id_match_t(*)(certificate_t*, identification_t *issuer))has_issuer;
|
||||||
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))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.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
|
||||||
|
|||||||
@@ -932,8 +932,7 @@ static id_match_t has_issuer(private_x509_cert_t *this, identification_t *issuer
|
|||||||
/**
|
/**
|
||||||
* Implementation of certificate_t.issued_by
|
* Implementation of certificate_t.issued_by
|
||||||
*/
|
*/
|
||||||
static bool issued_by(private_x509_cert_t *this, certificate_t *issuer,
|
static bool issued_by(private_x509_cert_t *this, certificate_t *issuer)
|
||||||
bool sigcheck)
|
|
||||||
{
|
{
|
||||||
public_key_t *key;
|
public_key_t *key;
|
||||||
signature_scheme_t scheme;
|
signature_scheme_t scheme;
|
||||||
@@ -962,10 +961,6 @@ static bool issued_by(private_x509_cert_t *this, certificate_t *issuer,
|
|||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!sigcheck)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
/* TODO: generic OID to scheme mapper? */
|
/* TODO: generic OID to scheme mapper? */
|
||||||
switch (this->algorithm)
|
switch (this->algorithm)
|
||||||
{
|
{
|
||||||
@@ -1174,7 +1169,7 @@ static private_x509_cert_t* create_empty(void)
|
|||||||
this->public.interface.interface.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
|
this->public.interface.interface.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
|
||||||
this->public.interface.interface.has_subject = (id_match_t (*)(certificate_t*, identification_t *subject))has_subject;
|
this->public.interface.interface.has_subject = (id_match_t (*)(certificate_t*, identification_t *subject))has_subject;
|
||||||
this->public.interface.interface.has_issuer = (id_match_t (*)(certificate_t*, identification_t *issuer))has_issuer;
|
this->public.interface.interface.has_issuer = (id_match_t (*)(certificate_t*, identification_t *issuer))has_issuer;
|
||||||
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))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.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
|
||||||
@@ -1220,7 +1215,7 @@ static private_x509_cert_t *create_from_chunk(chunk_t chunk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check if the certificate is self-signed */
|
/* check if the certificate is self-signed */
|
||||||
if (issued_by(this, &this->public.interface.interface, TRUE))
|
if (issued_by(this, &this->public.interface.interface))
|
||||||
{
|
{
|
||||||
this->flags |= X509_SELF_SIGNED;
|
this->flags |= X509_SELF_SIGNED;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -362,15 +362,7 @@ static certificate_type_t get_type(private_x509_crl_t *this)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of certificate_t.get_subject
|
* Implementation of certificate_t.get_issuer and get_subject
|
||||||
*/
|
|
||||||
static identification_t* get_subject(private_x509_crl_t *this)
|
|
||||||
{
|
|
||||||
return this->issuer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of certificate_t.get_issuer
|
|
||||||
*/
|
*/
|
||||||
static identification_t* get_issuer(private_x509_crl_t *this)
|
static identification_t* get_issuer(private_x509_crl_t *this)
|
||||||
{
|
{
|
||||||
@@ -378,15 +370,7 @@ static identification_t* get_issuer(private_x509_crl_t *this)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of certificate_t.has_subject.
|
* Implementation of certificate_t.has_subject and has_issuer.
|
||||||
*/
|
|
||||||
static id_match_t has_subject(private_x509_crl_t *this, identification_t *subject)
|
|
||||||
{
|
|
||||||
return ID_MATCH_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of certificate_t.has_issuer.
|
|
||||||
*/
|
*/
|
||||||
static id_match_t has_issuer(private_x509_crl_t *this, identification_t *issuer)
|
static id_match_t has_issuer(private_x509_crl_t *this, identification_t *issuer)
|
||||||
{
|
{
|
||||||
@@ -413,8 +397,7 @@ static id_match_t has_issuer(private_x509_crl_t *this, identification_t *issuer)
|
|||||||
/**
|
/**
|
||||||
* Implementation of certificate_t.issued_by
|
* Implementation of certificate_t.issued_by
|
||||||
*/
|
*/
|
||||||
static bool issued_by(private_x509_crl_t *this, certificate_t *issuer,
|
static bool issued_by(private_x509_crl_t *this, certificate_t *issuer)
|
||||||
bool sigcheck)
|
|
||||||
{
|
{
|
||||||
public_key_t *key;
|
public_key_t *key;
|
||||||
signature_scheme_t scheme;
|
signature_scheme_t scheme;
|
||||||
@@ -452,11 +435,6 @@ static bool issued_by(private_x509_crl_t *this, certificate_t *issuer,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sigcheck)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
/* TODO: generic OID to scheme mapper? */
|
/* TODO: generic OID to scheme mapper? */
|
||||||
switch (this->algorithm)
|
switch (this->algorithm)
|
||||||
{
|
{
|
||||||
@@ -616,11 +594,11 @@ static private_x509_crl_t* create_empty(void)
|
|||||||
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;
|
||||||
this->public.crl.certificate.get_type = (certificate_type_t (*)(certificate_t *this))get_type;
|
this->public.crl.certificate.get_type = (certificate_type_t (*)(certificate_t *this))get_type;
|
||||||
this->public.crl.certificate.get_subject = (identification_t* (*)(certificate_t *this))get_subject;
|
this->public.crl.certificate.get_subject = (identification_t* (*)(certificate_t *this))get_issuer;
|
||||||
this->public.crl.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
|
this->public.crl.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
|
||||||
this->public.crl.certificate.has_subject = (id_match_t (*)(certificate_t*, identification_t *subject))has_subject;
|
this->public.crl.certificate.has_subject = (id_match_t (*)(certificate_t*, identification_t *subject))has_issuer;
|
||||||
this->public.crl.certificate.has_issuer = (id_match_t (*)(certificate_t*, identification_t *issuer))has_issuer;
|
this->public.crl.certificate.has_issuer = (id_match_t (*)(certificate_t*, identification_t *issuer))has_issuer;
|
||||||
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))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.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
|
||||||
|
|||||||
@@ -378,8 +378,7 @@ static id_match_t has_issuer(private_x509_ocsp_request_t *this,
|
|||||||
/**
|
/**
|
||||||
* Implementation of certificate_t.issued_by
|
* Implementation of certificate_t.issued_by
|
||||||
*/
|
*/
|
||||||
static bool issued_by(private_x509_ocsp_request_t *this, certificate_t *issuer,
|
static bool issued_by(private_x509_ocsp_request_t *this, certificate_t *issuer)
|
||||||
bool sigcheck)
|
|
||||||
{
|
{
|
||||||
DBG1("OCSP request validation not implemented!");
|
DBG1("OCSP request validation not implemented!");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -482,7 +481,7 @@ static private_x509_ocsp_request_t *create_empty()
|
|||||||
this->public.interface.interface.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
|
this->public.interface.interface.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
|
||||||
this->public.interface.interface.has_subject = (id_match_t(*)(certificate_t*, identification_t *subject))has_subject;
|
this->public.interface.interface.has_subject = (id_match_t(*)(certificate_t*, identification_t *subject))has_subject;
|
||||||
this->public.interface.interface.has_issuer = (id_match_t(*)(certificate_t*, identification_t *issuer))has_issuer;
|
this->public.interface.interface.has_issuer = (id_match_t(*)(certificate_t*, identification_t *issuer))has_issuer;
|
||||||
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))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.get_encoding = (chunk_t(*)(certificate_t*))get_encoding;
|
this->public.interface.interface.get_encoding = (chunk_t(*)(certificate_t*))get_encoding;
|
||||||
|
|||||||
@@ -31,6 +31,11 @@
|
|||||||
#include <credentials/certificates/x509.h>
|
#include <credentials/certificates/x509.h>
|
||||||
#include <credentials/certificates/crl.h>
|
#include <credentials/certificates/crl.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* how long do we use an OCSP response without a nextUpdate
|
||||||
|
*/
|
||||||
|
#define OCSP_DEFAULT_LIFETIME 30
|
||||||
|
|
||||||
typedef struct private_x509_ocsp_response_t private_x509_ocsp_response_t;
|
typedef struct private_x509_ocsp_response_t private_x509_ocsp_response_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,10 +63,7 @@ struct private_x509_ocsp_response_t {
|
|||||||
int signatureAlgorithm;
|
int signatureAlgorithm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* signature enumerator = this->responses->create_enumerator(this->responses);
|
* signature
|
||||||
while (enumerator->enumerate(enumerator, &response))
|
|
||||||
{
|
|
||||||
value
|
|
||||||
*/
|
*/
|
||||||
chunk_t signature;
|
chunk_t signature;
|
||||||
|
|
||||||
@@ -75,6 +77,11 @@ struct private_x509_ocsp_response_t {
|
|||||||
*/
|
*/
|
||||||
time_t producedAt;
|
time_t producedAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* latest nextUpdate in this OCSP response
|
||||||
|
*/
|
||||||
|
time_t usableUntil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list of included certificates
|
* list of included certificates
|
||||||
*/
|
*/
|
||||||
@@ -382,8 +389,9 @@ static bool parse_singleResponse(private_x509_ocsp_response_t *this,
|
|||||||
response->status = VALIDATION_FAILED;
|
response->status = VALIDATION_FAILED;
|
||||||
response->revocationTime = 0;
|
response->revocationTime = 0;
|
||||||
response->revocationReason = CRL_UNSPECIFIED;
|
response->revocationReason = CRL_UNSPECIFIED;
|
||||||
response->thisUpdate = 0;
|
response->thisUpdate = UNDEFINED_TIME;
|
||||||
response->nextUpdate = 0;
|
/* if nextUpdate is missing, we give it a short lifetime */
|
||||||
|
response->nextUpdate = this->producedAt + OCSP_DEFAULT_LIFETIME;
|
||||||
|
|
||||||
asn1_init(&ctx, blob, level0, FALSE, FALSE);
|
asn1_init(&ctx, blob, level0, FALSE, FALSE);
|
||||||
while (objectID < SINGLE_RESPONSE_ROOF)
|
while (objectID < SINGLE_RESPONSE_ROOF)
|
||||||
@@ -423,17 +431,25 @@ 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_UNKNOWN;
|
response->status = VALIDATION_FAILED;
|
||||||
break;
|
break;
|
||||||
case SINGLE_RESPONSE_THIS_UPDATE:
|
case SINGLE_RESPONSE_THIS_UPDATE:
|
||||||
response->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
|
response->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
|
||||||
break;
|
break;
|
||||||
case SINGLE_RESPONSE_NEXT_UPDATE:
|
case SINGLE_RESPONSE_NEXT_UPDATE:
|
||||||
response->nextUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
|
response->nextUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
|
||||||
|
if (response->nextUpdate > this->usableUntil)
|
||||||
|
{
|
||||||
|
this->usableUntil = response->nextUpdate;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
objectID++;
|
objectID++;
|
||||||
}
|
}
|
||||||
|
if (this->usableUntil == UNDEFINED_TIME)
|
||||||
|
{
|
||||||
|
this->usableUntil = this->producedAt + OCSP_DEFAULT_LIFETIME;
|
||||||
|
}
|
||||||
this->responses->insert_last(this->responses, response);
|
this->responses->insert_last(this->responses, response);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -643,8 +659,7 @@ static id_match_t has_issuer(private_x509_ocsp_response_t *this,
|
|||||||
/**
|
/**
|
||||||
* Implementation of certificate_t.issued_by
|
* Implementation of certificate_t.issued_by
|
||||||
*/
|
*/
|
||||||
static bool issued_by(private_x509_ocsp_response_t *this, certificate_t *issuer,
|
static bool issued_by(private_x509_ocsp_response_t *this, certificate_t *issuer)
|
||||||
bool sigcheck)
|
|
||||||
{
|
{
|
||||||
public_key_t *key;
|
public_key_t *key;
|
||||||
signature_scheme_t scheme;
|
signature_scheme_t scheme;
|
||||||
@@ -685,10 +700,6 @@ static bool issued_by(private_x509_ocsp_response_t *this, certificate_t *issuer,
|
|||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!sigcheck)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
/* TODO: generic OID to scheme mapper? */
|
/* TODO: generic OID to scheme mapper? */
|
||||||
switch (this->signatureAlgorithm)
|
switch (this->signatureAlgorithm)
|
||||||
{
|
{
|
||||||
@@ -734,20 +745,8 @@ static public_key_t* get_public_key(private_x509_ocsp_response_t *this)
|
|||||||
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);
|
||||||
@@ -758,13 +757,13 @@ static bool get_validity(private_x509_ocsp_response_t *this, time_t *when,
|
|||||||
}
|
}
|
||||||
if (not_before)
|
if (not_before)
|
||||||
{
|
{
|
||||||
*not_before = thisUpdate;
|
*not_before = this->producedAt;
|
||||||
}
|
}
|
||||||
if (not_after)
|
if (not_after)
|
||||||
{
|
{
|
||||||
*not_after = nextUpdate;
|
*not_after = this->usableUntil;
|
||||||
}
|
}
|
||||||
return (t < nextUpdate);
|
return (t < this->usableUntil);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -853,7 +852,7 @@ static x509_ocsp_response_t *load(chunk_t data)
|
|||||||
this->public.interface.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
|
this->public.interface.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
|
||||||
this->public.interface.certificate.has_subject = (id_match_t(*)(certificate_t*, identification_t *subject))has_issuer;
|
this->public.interface.certificate.has_subject = (id_match_t(*)(certificate_t*, identification_t *subject))has_issuer;
|
||||||
this->public.interface.certificate.has_issuer = (id_match_t(*)(certificate_t*, identification_t *issuer))has_issuer;
|
this->public.interface.certificate.has_issuer = (id_match_t(*)(certificate_t*, identification_t *issuer))has_issuer;
|
||||||
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))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.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
|
||||||
@@ -869,6 +868,7 @@ static x509_ocsp_response_t *load(chunk_t data)
|
|||||||
this->tbsResponseData = chunk_empty;
|
this->tbsResponseData = chunk_empty;
|
||||||
this->responderId = NULL;
|
this->responderId = NULL;
|
||||||
this->producedAt = UNDEFINED_TIME;
|
this->producedAt = UNDEFINED_TIME;
|
||||||
|
this->usableUntil = UNDEFINED_TIME;
|
||||||
this->responses = linked_list_create();
|
this->responses = linked_list_create();
|
||||||
this->nonce = chunk_empty;
|
this->nonce = chunk_empty;
|
||||||
this->signatureAlgorithm = OID_UNKNOWN;
|
this->signatureAlgorithm = OID_UNKNOWN;
|
||||||
|
|||||||
Reference in New Issue
Block a user