aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2008-03-26 15:21:50 +0000
committerMartin Willi <martin@strongswan.org>2008-03-26 15:21:50 +0000
commit7b88a983d8dfb6fa8137bcc53d0e97054cfb18fe (patch)
treec2a7356d574958d2dc9839ab421f47a6bdabe64c
parent391abda0828ea4d7bd1b9e9f81ff7b3108e65c4d (diff)
downloadstrongswan-7b88a983d8dfb6fa8137bcc53d0e97054cfb18fe.tar.bz2
strongswan-7b88a983d8dfb6fa8137bcc53d0e97054cfb18fe.tar.xz
caching of ocsp responses (experimental), no crl caching yet
-rw-r--r--src/charon/credentials/credential_manager.c317
-rw-r--r--src/charon/credentials/sets/cert_cache.c5
-rw-r--r--src/libstrongswan/Makefile.am2
-rw-r--r--src/libstrongswan/credentials/certificates/ac.h2
-rw-r--r--src/libstrongswan/credentials/certificates/certificate.c10
-rw-r--r--src/libstrongswan/credentials/certificates/certificate.h19
-rw-r--r--src/libstrongswan/credentials/certificates/ocsp_request.c19
-rw-r--r--src/libstrongswan/plugins/x509/x509_ac.c10
-rw-r--r--src/libstrongswan/plugins/x509/x509_cert.c11
-rw-r--r--src/libstrongswan/plugins/x509/x509_crl.c34
-rw-r--r--src/libstrongswan/plugins/x509/x509_ocsp_request.c5
-rw-r--r--src/libstrongswan/plugins/x509/x509_ocsp_response.c58
12 files changed, 205 insertions, 287 deletions
diff --git a/src/charon/credentials/credential_manager.c b/src/charon/credentials/credential_manager.c
index 34a801e85..35816a820 100644
--- a/src/charon/credentials/credential_manager.c
+++ b/src/charon/credentials/credential_manager.c
@@ -331,6 +331,7 @@ static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url,
request->destroy(request);
DBG1(DBG_CFG, "requesting ocsp status from '%s' ...", url);
+ /* TODO: unlock manager while fetching? */
if (lib->fetcher->fetch(lib->fetcher, url, &receive,
FETCH_REQUEST_DATA, send,
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");
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;
+
+ 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);
- /* verify the signature of the ocsp response */
+ if (!issuer)
{
- certificate_t *issuer_cert;
- identification_t *responder;
- auth_info_t *auth;
- ocsp_response_wrapper_t *wrapper;
-
- 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);
- responder = response->get_issuer(response);
- DBG1(DBG_CFG, " ocsp signer is \"%D\"", responder);
- issuer_cert = get_trusted_cert(this, KEY_ANY, responder, auth, FALSE, FALSE);
- this->sets->remove(this->sets, wrapper, NULL);
- wrapper->destroy(wrapper);
- auth->destroy(auth);
+ DBG1(DBG_CFG, "OCSP response verification failed, responder cert missing");
+ return FALSE;
+ }
+ 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;
+}
- if (!issuer_cert)
+/**
+ * Get the better of two OCSP responses, and check for usable OCSP info
+ */
+static certificate_t *get_better_ocsp(private_credential_manager_t *this,
+ certificate_t *cand, certificate_t *best,
+ x509_t *subject, x509_t *issuer,
+ cert_validation_t *valid)
+{
+ ocsp_response_t *response;
+ time_t revocation, this_update, next_update, valid_until;
+ crl_reason_t reason;
+
+ 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");
- response->destroy(response);
- 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);
+ DBG1(DBG_CFG, " ocsp response is valid: until %#T", &valid_until);
+ *valid = VALIDATION_GOOD;
}
else
{
- DBG1(DBG_CFG, "ocsp response not accepted from \"%D\"",
- issuer_cert->get_subject(issuer_cert));
- issuer_cert->destroy(issuer_cert);
- response->destroy(response);
- return NULL;
+ DBG1(DBG_CFG, " ocsp response is stale: since %#T", &valid_until);
+ *valid = VALIDATION_STALE;
}
}
- /* TODO: cache response? */
- return response;
+ else
+ {
+ *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,
auth_info_t *auth)
{
- certificate_t *sub = (certificate_t*)subject;
- certificate_t *best_cert = NULL;
- certificate_t *cert;
- public_key_t *public;
+ enumerator_t *enumerator;
cert_validation_t valid = VALIDATION_SKIPPED;
+ certificate_t *best = NULL, *current;
identification_t *keyid = NULL;
- bool stale = TRUE;
-
- /* derive the authorityKeyIdentifier from the issuer's public key */
- cert = &issuer->interface;
- public = cert->get_public_key(cert);
- if (public)
- {
- keyid = public->get_id(public, ID_PUBKEY_SHA1);
- }
-
- /* find a cached ocsp response by authorityKeyIdentifier */
- if (keyid)
- {
- enumerator_t *enumerator = create_cert_enumerator(this,
- CERT_X509_OCSP_RESPONSE,
- KEY_ANY, keyid, TRUE);
- certificate_t *cert;
+ public_key_t *public;
+ char *uri = NULL;
- while (enumerator->enumerate(enumerator, &cert))
+ /** lookup cache for valid OCSP responses */
+ enumerator = create_cert_enumerator(this, CERT_X509_OCSP_RESPONSE,
+ KEY_ANY, NULL, FALSE);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ current->get_ref(current);
+ best = get_better_ocsp(this, current, best, subject, issuer, &valid);
+ if (best && valid != VALIDATION_STALE)
{
- 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);
- }
- }
+ DBG1(DBG_CFG, " used cached ocsp response");
+ break;
}
- enumerator->destroy(enumerator);
}
-
- /* check the validity of the cached ocsp response if one was found */
- if (best_cert)
+ enumerator->destroy(enumerator);
+
+ /* derive the authorityKeyIdentifier from the issuer's public key */
+ current = &issuer->interface;
+ public = current->get_public_key(current);
+ if (public)
{
- 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 );
+ keyid = public->get_id(public, ID_PUBKEY_SHA1);
}
-
- /* fallback to URL fetching from CDPs */
- if (stale && keyid)
+ /** fetch from configured OCSP responder URLs */
+ if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
{
- enumerator_t *enumerator = create_cdp_enumerator(this,
- CERT_X509_OCSP_RESPONSE, keyid);
- char *uri;
-
+ enumerator = create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE, keyid);
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;
-
- if (cert)
+ current = fetch_ocsp(this, uri, &subject->interface,
+ &issuer->interface);
+ if (current)
{
- /* select most recent ocsp response until valid one is found */
- if (best_cert == NULL || cert->is_newer(cert, best_cert))
+ best = get_better_ocsp(this, current, best, subject, issuer, &valid);
+ if (best && valid != VALIDATION_STALE)
{
- time_t nextUpdate;
-
- 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);
+ break;
}
}
}
@@ -497,76 +516,34 @@ static cert_validation_t check_ocsp(private_credential_manager_t *this,
DESTROY_IF(public);
/* 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);
- char *uri;
-
+ enumerator = subject->create_ocsp_uri_enumerator(subject);
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;
-
- if (cert)
+ current = fetch_ocsp(this, uri, &subject->interface,
+ &issuer->interface);
+ if (current)
{
- /* select most recent ocsp response until valid one is found */
- if (best_cert == NULL || cert->is_newer(cert, best_cert))
- {
- time_t nextUpdate;
-
- 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
+ best = get_better_ocsp(this, current, best, subject, issuer, &valid);
+ if (best && valid != VALIDATION_STALE)
{
- cert->destroy(cert);
+ break;
}
}
}
enumerator->destroy(enumerator);
}
-
- /* if we have an ocsp response, check the revocation status */
- if (best_cert)
+ /* an uri was found, but no result. switch validation state to failed */
+ if (valid == VALIDATION_SKIPPED && uri)
{
- time_t revocation, this_update, next_update;
- 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);
+ valid = VALIDATION_FAILED;
}
-
if (auth)
{
auth->add_item(auth, AUTHZ_OCSP_VALIDATION, &valid);
}
+ DESTROY_IF(best);
return valid;
}
@@ -771,7 +748,7 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
enumerator_t *enumerator = crl->create_enumerator(crl);
/* redefine default */
- valid = stale ? VALIDATION_UNKNOWN : VALIDATION_GOOD;
+ valid = stale ? VALIDATION_STALE : VALIDATION_GOOD;
while (enumerator->enumerate(enumerator, &serial, &revocation, &reason))
{
@@ -831,8 +808,10 @@ static bool check_certificate(private_credential_manager_t *this,
case VALIDATION_SKIPPED:
DBG2(DBG_CFG, "ocsp check skipped, no ocsp found");
break;
+ case VALIDATION_STALE:
+ DBG1(DBG_CFG, "ocsp information stale, fallback to crl");
+ break;
case VALIDATION_FAILED:
- case VALIDATION_UNKNOWN:
DBG1(DBG_CFG, "ocsp check failed, fallback to crl");
break;
}
@@ -847,14 +826,12 @@ static bool check_certificate(private_credential_manager_t *this,
case VALIDATION_REVOKED:
/* has already been logged */
return FALSE;
- case VALIDATION_UNKNOWN:
- DBG1(DBG_CFG, "certificate status is unknown");
- break;
case VALIDATION_FAILED:
case VALIDATION_SKIPPED:
DBG1(DBG_CFG, "certificate status is not available");
- break;
- default:
+ break;
+ case VALIDATION_STALE:
+ DBG1(DBG_CFG, "certificate status is unknown, crl is stale");
break;
}
}
@@ -993,8 +970,8 @@ static certificate_t *get_trusted_cert(private_credential_manager_t *this,
subject = get_pretrusted_cert(this, type, id);
if (subject)
{
-
- if (subject->issued_by(subject, subject, TRUE))
+ /* if we find a trusted self signed certificate, we just accept it */
+ if (this->cache->issued_by(this->cache, subject, subject))
{
DBG1(DBG_CFG, " using trusted self-signed certificate \"%D\"",
subject->get_subject(subject));
diff --git a/src/charon/credentials/sets/cert_cache.c b/src/charon/credentials/sets/cert_cache.c
index 17e6d357c..5d4964314 100644
--- a/src/charon/credentials/sets/cert_cache.c
+++ b/src/charon/credentials/sets/cert_cache.c
@@ -93,7 +93,7 @@ static bool issued_by(private_cert_cache_t *this,
return TRUE;
}
/* no cache hit, check signature */
- if (!subject->issued_by(subject, issuer, TRUE))
+ if (!subject->issued_by(subject, issuer))
{
return FALSE;
}
@@ -131,10 +131,9 @@ static bool certs_filter(cert_data_t *data, relation_t **in, certificate_t **out
public_key_t *public;
certificate_t *cert;
- /* serve all subjects, but only if an ID is requestd (no listing) */
cert = (*in)->subject;
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)
{
diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am
index 5f2169cc4..9b0417f05 100644
--- a/src/libstrongswan/Makefile.am
+++ b/src/libstrongswan/Makefile.am
@@ -36,7 +36,7 @@ credentials/certificates/certificate.c credentials/certificates/certificate.h \
credentials/certificates/x509.h credentials/certificates/x509.c \
credentials/certificates/ac.h \
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 \
fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
database/database.h database/database_factory.h database/database_factory.c \
diff --git a/src/libstrongswan/credentials/certificates/ac.h b/src/libstrongswan/credentials/certificates/ac.h
index 7a3b747e0..c9645d68b 100644
--- a/src/libstrongswan/credentials/certificates/ac.h
+++ b/src/libstrongswan/credentials/certificates/ac.h
@@ -51,7 +51,7 @@ struct ac_t {
* @param that other attribute certificate
* @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_ @}*/
diff --git a/src/libstrongswan/credentials/certificates/certificate.c b/src/libstrongswan/credentials/certificates/certificate.c
index 8d159472d..1a83bdf4c 100644
--- a/src/libstrongswan/credentials/certificates/certificate.c
+++ b/src/libstrongswan/credentials/certificates/certificate.c
@@ -32,10 +32,10 @@ ENUM(certificate_type_names, CERT_ANY, CERT_PGP,
);
ENUM(cert_validation_names, VALIDATION_GOOD, VALIDATION_SKIPPED,
- "GOOD",
- "REVOKED",
- "UNKNOWN",
- "FAILED",
- "SKIPPED",
+ "VALIDATION_GOOD",
+ "VALIDATION_STALE",
+ "VALIDATION_REVOKED",
+ "VALIDATION_FAILED",
+ "VALIDATION_SKIPPED",
);
diff --git a/src/libstrongswan/credentials/certificates/certificate.h b/src/libstrongswan/credentials/certificates/certificate.h
index cc3f73a0d..14f4de389 100644
--- a/src/libstrongswan/credentials/certificates/certificate.h
+++ b/src/libstrongswan/credentials/certificates/certificate.h
@@ -62,13 +62,13 @@ extern enum_name_t *certificate_type_names;
enum cert_validation_t {
/** certificate has been validated successfully */
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,
- /* ocsp status is unknown or crl is stale */
- VALIDATION_UNKNOWN,
- /** validation process failed due to an error */
+ /** validation failed due to a processing error */
VALIDATION_FAILED,
- /** validation has been skipped (no cdps available) */
+ /** validation has been skipped due to missing validation information */
VALIDATION_SKIPPED,
};
@@ -129,17 +129,12 @@ struct certificate_t {
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 checksig TRUE to verify signature, FALSE to compare issuer only
* @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.
diff --git a/src/libstrongswan/credentials/certificates/ocsp_request.c b/src/libstrongswan/credentials/certificates/ocsp_request.c
deleted file mode 100644
index 0958be4a0..000000000
--- a/src/libstrongswan/credentials/certificates/ocsp_request.c
+++ /dev/null
@@ -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"
-
diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c
index 42dbc94c2..f90197bad 100644
--- a/src/libstrongswan/plugins/x509/x509_ac.c
+++ b/src/libstrongswan/plugins/x509/x509_ac.c
@@ -714,8 +714,7 @@ static id_match_t has_issuer(private_x509_ac_t *this, identification_t *issuer)
/**
* Implementation of certificate_t.issued_by
*/
-static bool issued_by(private_x509_ac_t *this, certificate_t *issuer,
- bool sigcheck)
+static bool issued_by(private_x509_ac_t *this, certificate_t *issuer)
{
public_key_t *key;
signature_scheme_t scheme;
@@ -753,11 +752,6 @@ static bool issued_by(private_x509_ac_t *this, certificate_t *issuer,
return FALSE;
}
}
-
- if (!sigcheck)
- {
- return TRUE;
- }
/* TODO: generic OID to scheme mapper? */
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.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.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_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;
diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c
index dcd393c23..ab32e13c3 100644
--- a/src/libstrongswan/plugins/x509/x509_cert.c
+++ b/src/libstrongswan/plugins/x509/x509_cert.c
@@ -932,8 +932,7 @@ static id_match_t has_issuer(private_x509_cert_t *this, identification_t *issuer
/**
* Implementation of certificate_t.issued_by
*/
-static bool issued_by(private_x509_cert_t *this, certificate_t *issuer,
- bool sigcheck)
+static bool issued_by(private_x509_cert_t *this, certificate_t *issuer)
{
public_key_t *key;
signature_scheme_t scheme;
@@ -962,10 +961,6 @@ static bool issued_by(private_x509_cert_t *this, certificate_t *issuer,
{
return FALSE;
}
- if (!sigcheck)
- {
- return TRUE;
- }
/* TODO: generic OID to scheme mapper? */
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.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.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_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;
@@ -1220,7 +1215,7 @@ static private_x509_cert_t *create_from_chunk(chunk_t chunk)
}
/* 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;
}
diff --git a/src/libstrongswan/plugins/x509/x509_crl.c b/src/libstrongswan/plugins/x509/x509_crl.c
index d59b15303..a2871977e 100644
--- a/src/libstrongswan/plugins/x509/x509_crl.c
+++ b/src/libstrongswan/plugins/x509/x509_crl.c
@@ -362,15 +362,7 @@ static certificate_type_t get_type(private_x509_crl_t *this)
}
/**
- * Implementation of certificate_t.get_subject
- */
-static identification_t* get_subject(private_x509_crl_t *this)
-{
- return this->issuer;
-}
-
-/**
- * Implementation of certificate_t.get_issuer
+ * Implementation of certificate_t.get_issuer and get_subject
*/
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.
- */
-static id_match_t has_subject(private_x509_crl_t *this, identification_t *subject)
-{
- return ID_MATCH_NONE;
-}
-
-/**
- * Implementation of certificate_t.has_issuer.
+ * Implementation of certificate_t.has_subject and has_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
*/
-static bool issued_by(private_x509_crl_t *this, certificate_t *issuer,
- bool sigcheck)
+static bool issued_by(private_x509_crl_t *this, certificate_t *issuer)
{
public_key_t *key;
signature_scheme_t scheme;
@@ -452,11 +435,6 @@ static bool issued_by(private_x509_crl_t *this, certificate_t *issuer,
return FALSE;
}
}
-
- if (!sigcheck)
- {
- return TRUE;
- }
/* TODO: generic OID to scheme mapper? */
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.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_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.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.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_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;
diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_request.c b/src/libstrongswan/plugins/x509/x509_ocsp_request.c
index 7e3230412..957df2414 100644
--- a/src/libstrongswan/plugins/x509/x509_ocsp_request.c
+++ b/src/libstrongswan/plugins/x509/x509_ocsp_request.c
@@ -378,8 +378,7 @@ static id_match_t has_issuer(private_x509_ocsp_request_t *this,
/**
* Implementation of certificate_t.issued_by
*/
-static bool issued_by(private_x509_ocsp_request_t *this, certificate_t *issuer,
- bool sigcheck)
+static bool issued_by(private_x509_ocsp_request_t *this, certificate_t *issuer)
{
DBG1("OCSP request validation not implemented!");
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.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.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_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;
diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.c b/src/libstrongswan/plugins/x509/x509_ocsp_response.c
index cf1de6b4e..0c1eb8539 100644
--- a/src/libstrongswan/plugins/x509/x509_ocsp_response.c
+++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.c
@@ -31,6 +31,11 @@
#include <credentials/certificates/x509.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;
/**
@@ -58,10 +63,7 @@ struct private_x509_ocsp_response_t {
int signatureAlgorithm;
/**
- * signature enumerator = this->responses->create_enumerator(this->responses);
- while (enumerator->enumerate(enumerator, &response))
- {
- value
+ * signature
*/
chunk_t signature;
@@ -76,6 +78,11 @@ struct private_x509_ocsp_response_t {
time_t producedAt;
/**
+ * latest nextUpdate in this OCSP response
+ */
+ time_t usableUntil;
+
+ /**
* list of included certificates
*/
linked_list_t *certs;
@@ -382,8 +389,9 @@ static bool parse_singleResponse(private_x509_ocsp_response_t *this,
response->status = VALIDATION_FAILED;
response->revocationTime = 0;
response->revocationReason = CRL_UNSPECIFIED;
- response->thisUpdate = 0;
- response->nextUpdate = 0;
+ response->thisUpdate = UNDEFINED_TIME;
+ /* if nextUpdate is missing, we give it a short lifetime */
+ response->nextUpdate = this->producedAt + OCSP_DEFAULT_LIFETIME;
asn1_init(&ctx, blob, level0, FALSE, FALSE);
while (objectID < SINGLE_RESPONSE_ROOF)
@@ -423,17 +431,25 @@ static bool parse_singleResponse(private_x509_ocsp_response_t *this,
}
break;
case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN:
- response->status = VALIDATION_UNKNOWN;
+ response->status = VALIDATION_FAILED;
break;
case SINGLE_RESPONSE_THIS_UPDATE:
response->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
break;
case SINGLE_RESPONSE_NEXT_UPDATE:
response->nextUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
+ if (response->nextUpdate > this->usableUntil)
+ {
+ this->usableUntil = response->nextUpdate;
+ }
break;
}
objectID++;
}
+ if (this->usableUntil == UNDEFINED_TIME)
+ {
+ this->usableUntil = this->producedAt + OCSP_DEFAULT_LIFETIME;
+ }
this->responses->insert_last(this->responses, response);
return TRUE;
}
@@ -643,8 +659,7 @@ static id_match_t has_issuer(private_x509_ocsp_response_t *this,
/**
* Implementation of certificate_t.issued_by
*/
-static bool issued_by(private_x509_ocsp_response_t *this, certificate_t *issuer,
- bool sigcheck)
+static bool issued_by(private_x509_ocsp_response_t *this, certificate_t *issuer)
{
public_key_t *key;
signature_scheme_t scheme;
@@ -685,10 +700,6 @@ static bool issued_by(private_x509_ocsp_response_t *this, certificate_t *issuer,
{
return FALSE;
}
- if (!sigcheck)
- {
- return TRUE;
- }
/* TODO: generic OID to scheme mapper? */
switch (this->signatureAlgorithm)
{
@@ -734,19 +745,7 @@ 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,
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;
-
- enumerator = this->responses->create_enumerator(this->responses);
- if (enumerator->enumerate(enumerator, &response))
- {
- thisUpdate = response->thisUpdate;
- nextUpdate = response->nextUpdate;
- }
- enumerator->destroy(enumerator);
if (when == NULL)
{
@@ -758,13 +757,13 @@ static bool get_validity(private_x509_ocsp_response_t *this, time_t *when,
}
if (not_before)
{
- *not_before = thisUpdate;
+ *not_before = this->producedAt;
}
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.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.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_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;
@@ -869,6 +868,7 @@ static x509_ocsp_response_t *load(chunk_t data)
this->tbsResponseData = chunk_empty;
this->responderId = NULL;
this->producedAt = UNDEFINED_TIME;
+ this->usableUntil = UNDEFINED_TIME;
this->responses = linked_list_create();
this->nonce = chunk_empty;
this->signatureAlgorithm = OID_UNKNOWN;