diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2007-03-08 23:29:04 +0000 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2007-03-08 23:29:04 +0000 |
commit | 1bcb84605fb407328d22db5f9d5ad151056ac761 (patch) | |
tree | e4caf6e7d87f71fdeae58b27698eeef646a543c0 | |
parent | f5fbad4a62da10f59549bf63acd1501b8a494771 (diff) | |
download | strongswan-1bcb84605fb407328d22db5f9d5ad151056ac761.tar.bz2 strongswan-1bcb84605fb407328d22db5f9d5ad151056ac761.tar.xz |
ocsp signer certificate and ocsp response signature can be verified
-rwxr-xr-x | src/charon/config/credentials/credential_store.h | 13 | ||||
-rw-r--r-- | src/charon/config/credentials/local_credential_store.c | 59 | ||||
-rw-r--r-- | src/libstrongswan/Makefile.am | 1 | ||||
-rwxr-xr-x | src/libstrongswan/credential_store.h | 285 | ||||
-rw-r--r-- | src/libstrongswan/crypto/ca.c | 10 | ||||
-rw-r--r-- | src/libstrongswan/crypto/ca.h | 5 | ||||
-rw-r--r-- | src/libstrongswan/crypto/ocsp.c | 179 | ||||
-rw-r--r-- | src/libstrongswan/crypto/ocsp.h | 7 |
8 files changed, 495 insertions, 64 deletions
diff --git a/src/charon/config/credentials/credential_store.h b/src/charon/config/credentials/credential_store.h index 378619691..e19f14789 100755 --- a/src/charon/config/credentials/credential_store.h +++ b/src/charon/config/credentials/credential_store.h @@ -136,13 +136,22 @@ struct credential_store_t { ca_info_t* (*get_issuer) (credential_store_t *this, const x509_t* cert); /** - * @brief Verify an X.509 certificate up to trust anchor including revocation checks + * @brief Verify an X.509 certificate up to trust anchor without any status checks * * @param this calling object * @param cert certificate to be verified - * @param found found a certificate copy in the credential store * @return TRUE if trusted */ + bool (*is_trusted) (credential_store_t *this, x509_t *cert); + + /** + * @brief Verify an X.509 certificate up to trust anchor including status checks + * + * @param this calling object + * @param cert certificate to be verified + * @param found found a certificate copy in the credential store + * @return TRUE if valid, trusted, and current status is good + */ bool (*verify) (credential_store_t *this, x509_t *cert, bool *found); /** diff --git a/src/charon/config/credentials/local_credential_store.c b/src/charon/config/credentials/local_credential_store.c index 1caa33b67..25ba970e2 100644 --- a/src/charon/config/credentials/local_credential_store.c +++ b/src/charon/config/credentials/local_credential_store.c @@ -481,6 +481,60 @@ static void add_uris(ca_info_t *issuer, x509_t *cert) } /** + * Implementation of credential_store_t.is_trusted + */ +static bool is_trusted(private_local_credential_store_t *this, x509_t *cert) +{ + int pathlen; + + DBG2(DBG_CFG, "establishing trust in certificate:"); + + for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) + { + ca_info_t *issuer; + x509_t *issuer_cert; + rsa_public_key_t *issuer_public_key; + bool valid_signature; + + DBG2(DBG_CFG, "subject: '%D'", cert->get_subject(cert)); + DBG2(DBG_CFG, "issuer: '%D'", cert->get_issuer(cert)); + + issuer = get_issuer(this, cert); + if (issuer == NULL) + { + DBG1(DBG_CFG, "issuer info not found"); + return FALSE; + } + DBG2(DBG_CFG, "issuer info found"); + + issuer_cert = issuer->get_certificate(issuer); + issuer_public_key = issuer_cert->get_public_key(issuer_cert); + valid_signature = cert->verify(cert, issuer_public_key); + + if (!valid_signature) + { + DBG1(DBG_CFG, "certificate signature is invalid"); + return FALSE; + } + DBG2(DBG_CFG, "certificate signature is valid"); + + /* check if cert is a self-signed root ca */ + if (pathlen > 0 && cert->is_self_signed(cert)) + { + DBG2(DBG_CFG, "reached self-signed root ca"); + return TRUE; + } + else + { + /* go up one step in the trust chain */ + cert = issuer_cert; + } + } + DBG1(DBG_CFG, "maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN); + return FALSE; +} + +/** * Implementation of credential_store_t.verify. */ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *found) @@ -491,6 +545,8 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f x509_t *end_cert = cert; x509_t *cert_copy = find_certificate(this->certs, end_cert); + DBG2(DBG_CFG, "verifying end entity certificate:"); + *found = (cert_copy != NULL); if (*found) { @@ -565,7 +621,7 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f } /* first check certificate revocation using ocsp */ - status = issuer->verify_by_ocsp(issuer, cert, certinfo); + status = issuer->verify_by_ocsp(issuer, cert, certinfo, &this->public); /* if ocsp service is not available then fall back to crl */ if ((status == CERT_UNDEFINED) || (status == CERT_UNKNOWN && this->strict)) @@ -1234,6 +1290,7 @@ local_credential_store_t * local_credential_store_create(bool strict) this->public.credential_store.get_auth_certificate = (x509_t* (*) (credential_store_t*,u_int,identification_t*))get_auth_certificate; this->public.credential_store.get_ca_certificate_by_keyid = (x509_t* (*) (credential_store_t*,chunk_t))get_ca_certificate_by_keyid; this->public.credential_store.get_issuer = (ca_info_t* (*) (credential_store_t*,const x509_t*))get_issuer; + this->public.credential_store.is_trusted = (bool (*) (credential_store_t*,x509_t*))is_trusted; this->public.credential_store.verify = (bool (*) (credential_store_t*,x509_t*,bool*))verify; this->public.credential_store.add_end_certificate = (x509_t* (*) (credential_store_t*,x509_t*))add_end_certificate; this->public.credential_store.add_auth_certificate = (x509_t* (*) (credential_store_t*,x509_t*,u_int))add_auth_certificate; diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index d07682436..3c1a913c6 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -1,6 +1,7 @@ lib_LTLIBRARIES = libstrongswan.la libstrongswan_la_SOURCES = \ +credential_store.h \ library.c library.h \ chunk.c chunk.h \ debug.c debug.h \ diff --git a/src/libstrongswan/credential_store.h b/src/libstrongswan/credential_store.h new file mode 100755 index 000000000..e19f14789 --- /dev/null +++ b/src/libstrongswan/credential_store.h @@ -0,0 +1,285 @@ +/** + * @file credential_store.h + * + * @brief Interface credential_store_t. + * + */ + +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * 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. + */ + +#ifndef CREDENTIAL_STORE_H_ +#define CREDENTIAL_STORE_H_ + +typedef struct credential_store_t credential_store_t; + +#include <library.h> +#include <crypto/x509.h> +#include <crypto/ca.h> +#include <crypto/rsa/rsa_private_key.h> +#include <crypto/rsa/rsa_public_key.h> +#include <utils/identification.h> + + +/** + * @brief The interface for a credential_store backend. + * + * @b Constructors: + * - stroke_create() + * + * @ingroup config + */ +struct credential_store_t { + + /** + * @brief Returns the secret shared by two specific IDs. + * + * The returned chunk must be destroyed by the caller after usage. + * + * @param this calling object + * @param my_id my ID identifiying the secret. + * @param other_id peer ID identifying the secret. + * @param[out] secret the pre-shared secret will be written there. + * @return + * - NOT_FOUND if no preshared secrets for specific ID could be found + * - SUCCESS + * + */ + status_t (*get_shared_key) (credential_store_t *this, identification_t *my_id, identification_t *other_id, chunk_t *shared_key); + + /** + * @brief Returns the RSA public key of a specific ID. + * + * @param this calling object + * @param id identification_t object identifiying the key. + * @return public key, or NULL if not found + */ + rsa_public_key_t* (*get_rsa_public_key) (credential_store_t *this, identification_t *id); + + /** + * @brief Returns the RSA public key of a specific ID if is trusted + * + * @param this calling object + * @param id identification_t object identifiying the key. + * @return public key, or NULL if not found or not trusted + */ + rsa_public_key_t* (*get_trusted_public_key) (credential_store_t *this, identification_t *id); + + /** + * @brief Returns the RSA private key belonging to an RSA public key + * + * The returned rsa_private_key_t must be destroyed by the caller after usage. + * + * @param this calling object + * @param pubkey public key + * @return private key, or NULL if not found + */ + rsa_private_key_t* (*get_rsa_private_key) (credential_store_t *this, rsa_public_key_t *pubkey); + + /** + * @brief Is there a matching RSA private key belonging to an RSA public key? + * + * @param this calling object + * @param pubkey public key + * @return TRUE if matching private key was found + */ + bool (*has_rsa_private_key) (credential_store_t *this, rsa_public_key_t *pubkey); + + /** + * @brief Returns the certificate of a specific ID. + * + * @param this calling object + * @param id identification_t object identifiying the cert. + * @return certificate, or NULL if not found + */ + x509_t* (*get_certificate) (credential_store_t *this, identification_t *id); + + /** + * @brief Returns the auth certificate of a specific subject distinguished name. + * + * @param this calling object + * @param auth_flags set of allowed authority types + * @param id identification_t object identifiying the cacert. + * @return certificate, or NULL if not found + */ + x509_t* (*get_auth_certificate) (credential_store_t *this, u_int auth_flags, identification_t *id); + + /** + * @brief Returns the ca certificate of a specific keyID. + * + * @param this calling object + * @param keyid identification_t object identifiying the cacert. + * @return certificate, or NULL if not found + */ + x509_t* (*get_ca_certificate_by_keyid) (credential_store_t *this, chunk_t keyid); + + /** + * @brief Returns the issuing ca of a given certificate. + * + * @param this calling object + * @param cert certificate for which issuer ca info is required + * @return ca info, or NULL if not found + */ + ca_info_t* (*get_issuer) (credential_store_t *this, const x509_t* cert); + + /** + * @brief Verify an X.509 certificate up to trust anchor without any status checks + * + * @param this calling object + * @param cert certificate to be verified + * @return TRUE if trusted + */ + bool (*is_trusted) (credential_store_t *this, x509_t *cert); + + /** + * @brief Verify an X.509 certificate up to trust anchor including status checks + * + * @param this calling object + * @param cert certificate to be verified + * @param found found a certificate copy in the credential store + * @return TRUE if valid, trusted, and current status is good + */ + bool (*verify) (credential_store_t *this, x509_t *cert, bool *found); + + /** + * @brief If an end certificate does not already exists in the credential store then add it. + * + * @param this calling object + * @param cert certificate to be added + * @return pointer to the added or already existing certificate + */ + x509_t* (*add_end_certificate) (credential_store_t *this, x509_t *cert); + + /** + * @brief If an authority certificate does not already exists in the credential store then add it. + * + * @param this calling object + * @param cert authority certificate to be added + * @param auth_flag authority flags to add to the certificate + * @return pointer to the added or already existing certificate + */ + x509_t* (*add_auth_certificate) (credential_store_t *this, x509_t *cert, u_int auth_flag); + + /** + * @brief If a ca info record does not already exists in the credential store then add it. + * + * @param this calling object + * @param ca_info ca info record to be added + */ + void (*add_ca_info) (credential_store_t *this, ca_info_t *ca_info); + + /** + * @brief Release a ca info record with a given name. + * + * @param this calling object + * @param name name of the ca info record to be released + * @return + * - SUCCESS, or + * - NOT_FOUND + */ + status_t (*release_ca_info) (credential_store_t *this, const char *name); + + /** + * @brief Create an iterator over all end certificates. + * + * @param this calling object + * @return iterator + */ + iterator_t* (*create_cert_iterator) (credential_store_t *this); + + /** + * @brief Create an iterator over all authority certificates. + * + * @param this calling object + * @return iterator + */ + iterator_t* (*create_auth_cert_iterator) (credential_store_t *this); + + /** + * @brief Create an iterator over all CA info records + * + * @param this calling object + * @return iterator + */ + iterator_t* (*create_cainfo_iterator) (credential_store_t *this); + + /** + * @brief Check if there are any CRLs. + * + * @param this calling object + * @param out output stream + * @param utc either utc or local time + */ + void (*list_crls) (credential_store_t *this, FILE *out, bool utc); + + /** + * @brief Loads ca certificates from a default directory. + * + * Certificates in both DER and PEM format are accepted + * + * @param this calling object + */ + void (*load_ca_certificates) (credential_store_t *this); + + /** + * @brief Loads ocsp certificates from a default directory. + * + * Certificates in both DER and PEM format are accepted + * + * @param this calling object + */ + void (*load_ocsp_certificates) (credential_store_t *this); + + /** + * @brief Loads CRLs from a default directory. + * + * Certificates in both DER and PEM format are accepted + * + * @param this calling object + * @param path directory to load crls from + */ + void (*load_crls) (credential_store_t *this); + + /** + * @brief Loads secrets in ipsec.secrets + * + * Currently, all RSA private key files must be in unencrypted form + * either in DER or PEM format. + * + * @param this calling object + */ + void (*load_secrets) (credential_store_t *this); + + /** + * @brief Destroys a credential_store_t object. + * + * @param this calling object + */ + void (*destroy) (credential_store_t *this); +}; + +/** + * @brief Creates a credential_store_t instance. + * + * @param strict enforce a strict crl policy + * @return credential store instance. + * + * @ingroup config + */ +credential_store_t *credential_store_create(bool strict); + + +#endif /*CREDENTIAL_STORE_H_*/ diff --git a/src/libstrongswan/crypto/ca.c b/src/libstrongswan/crypto/ca.c index 79e469792..e9ccbfd5e 100644 --- a/src/libstrongswan/crypto/ca.c +++ b/src/libstrongswan/crypto/ca.c @@ -382,8 +382,10 @@ err: /** * Implements ca_info_t.verify_by_ocsp. */ -static cert_status_t verify_by_ocsp(private_ca_info_t* this, const x509_t *cert, - certinfo_t *certinfo) +static cert_status_t verify_by_ocsp(private_ca_info_t* this, + const x509_t *cert, + certinfo_t *certinfo, + credential_store_t *credentials) { bool found = FALSE; @@ -419,7 +421,7 @@ static cert_status_t verify_by_ocsp(private_ca_info_t* this, const x509_t *cert, DBG2("ocsp status is not in cache"); ocsp = ocsp_create(this->cacert, this->ocspuris); - ocsp->fetch(ocsp, certinfo); + ocsp->fetch(ocsp, certinfo, credentials); ocsp->destroy(ocsp); } @@ -555,7 +557,7 @@ ca_info_t *ca_info_create(const char *name, x509_t *cacert) this->public.add_ocspuri = (void (*) (ca_info_t*,chunk_t))add_ocspuri; this->public.get_certificate = (x509_t* (*) (ca_info_t*))get_certificate; this->public.verify_by_crl = (cert_status_t (*) (ca_info_t*,const x509_t*,certinfo_t*))verify_by_crl; - this->public.verify_by_ocsp = (cert_status_t (*) (ca_info_t*,const x509_t*,certinfo_t*))verify_by_ocsp; + this->public.verify_by_ocsp = (cert_status_t (*) (ca_info_t*,const x509_t*,certinfo_t*,credential_store_t*))verify_by_ocsp; this->public.destroy = (void (*) (ca_info_t*))destroy; return &this->public; diff --git a/src/libstrongswan/crypto/ca.h b/src/libstrongswan/crypto/ca.h index 1b2e33ed9..0aa3e20e3 100644 --- a/src/libstrongswan/crypto/ca.h +++ b/src/libstrongswan/crypto/ca.h @@ -28,6 +28,8 @@ typedef struct ca_info_t ca_info_t; #include <library.h> #include <chunk.h> +#include <credential_store.h> + #include "x509.h" #include "crl.h" @@ -151,9 +153,10 @@ struct ca_info_t { * @param this ca info object * @param cert certificate to be verified * @param certinfo detailed certificate status information + * @param credentials credential store needed for trust path verification * @return certificate status */ - cert_status_t (*verify_by_ocsp) (ca_info_t* this, const x509_t* cert, certinfo_t* certinfo); + cert_status_t (*verify_by_ocsp) (ca_info_t* this, const x509_t* cert, certinfo_t* certinfo, credential_store_t* credentials); /** * @brief Destroys a ca info record diff --git a/src/libstrongswan/crypto/ocsp.c b/src/libstrongswan/crypto/ocsp.c index 707b0383b..3a4ea3b58 100644 --- a/src/libstrongswan/crypto/ocsp.c +++ b/src/libstrongswan/crypto/ocsp.c @@ -38,6 +38,7 @@ #include <debug.h> #include "hashers/hasher.h" +#include "rsa/rsa_public_key.h" #include "certinfo.h" #include "x509.h" #include "ocsp.h" @@ -107,19 +108,49 @@ struct response_t { chunk_t nonce; int algorithm; chunk_t signature; -}; + x509_t *responder_cert; -const response_t empty_response = { - { NULL, 0 } , /* tbs */ - NULL , /* responder_id_name */ - { NULL, 0 } , /* responder_id_key */ - UNDEFINED_TIME, /* produced_at */ - { NULL, 0 } , /* single_response */ - { NULL, 0 } , /* nonce */ - OID_UNKNOWN , /* signature_algorithm */ - { NULL, 0 } /* signature */ + /** + * @brief Destroys the response_t object + * + * @param this response_t to destroy + */ + void (*destroy) (response_t *this); }; +/** + * Implements response_t.destroy. + */ +static void response_destroy(response_t *this) +{ + DESTROY_IF(this->responder_id_name); + DESTROY_IF(this->responder_cert); +} + +/** + * Creates a response_t object + */ +static response_t* response_create(void) +{ + response_t *this = malloc_thing(response_t); + + this->tbs = chunk_empty; + this->responder_id_name = NULL; + this->responder_id_key = chunk_empty; + this->produced_at = UNDEFINED_TIME; + this->responses = chunk_empty; + this->nonce = chunk_empty; + this->algorithm = OID_UNKNOWN; + this->signature = chunk_empty; + this->responder_cert = NULL; + + this->destroy = (void (*) (response_t*))response_destroy; + + return this; +} + + + /* single response container */ typedef struct single_response single_response_t; @@ -453,15 +484,6 @@ static chunk_t ocsp_build_request(private_ocsp_t *this) } /** - * Check if the OCSP response has a valid signature - */ -static bool ocsp_valid_response(response_t *res) -{ - /* TODO */ - return FALSE; -} - -/** * parse a basic OCSP response */ static bool ocsp_parse_basic_response(chunk_t blob, int level0, response_t *res) @@ -529,24 +551,8 @@ static bool ocsp_parse_basic_response(chunk_t blob, int level0, response_t *res) case BASIC_RESPONSE_CERTIFICATE: { chunk_t blob = chunk_clone(object); - x509_t *cert = x509_create_from_chunk(blob, level+1); - if (cert == NULL) - { - break; - } - if (cert->is_ocsp_signer(cert)) - { - DBG2("received OCSP signer certificate"); - cert->destroy(cert); - /* TODO trust_authcert_candidate(cert, NULL)) - add_authcert(cert, AUTH_OCSP); */ - } - else - { - DBG1("embedded ocsp certificate rejected"); - cert->destroy(cert); - } + res->responder_cert = x509_create_from_chunk(blob, level+1); } break; } @@ -558,7 +564,7 @@ static bool ocsp_parse_basic_response(chunk_t blob, int level0, response_t *res) /** * parse an ocsp response and return the result as a response_t struct */ -static response_status ocsp_parse_response(chunk_t blob, response_t * res) +static response_status ocsp_parse_response(chunk_t blob, response_t *res) { asn1_ctx_t ctx; chunk_t object; @@ -626,6 +632,32 @@ static response_status ocsp_parse_response(chunk_t blob, response_t * res) } /** + * Check if the OCSP response has a valid signature + */ +static bool ocsp_valid_response(response_t *res, x509_t *ocsp_cert) +{ + rsa_public_key_t *public_key; + time_t until = UNDEFINED_TIME; + err_t ugh; + + DBG2("verifying ocsp response signature:"); + DBG2("signer: '%D'", ocsp_cert->get_subject(ocsp_cert)); + DBG2("issuer: '%D'", ocsp_cert->get_issuer(ocsp_cert)); + + ugh = ocsp_cert->is_valid(ocsp_cert, &until); + if (ugh != NULL) + { + DBG1("ocsp signer certificate %s", ugh); + return FALSE; + } + DBG2("ocsp signer certificate is valid"); + + public_key = ocsp_cert->get_public_key(ocsp_cert); + + return public_key->verify_emsa_pkcs1_signature(public_key, res->tbs, res->signature) == SUCCESS; +} + +/** * parse a single OCSP response */ static bool ocsp_parse_single_response(chunk_t blob, int level0, single_response_t *sres) @@ -706,39 +738,76 @@ static void process_single_response(private_ocsp_t *this, single_response_t *sre /** * verify and process ocsp response and update the ocsp cache */ -void ocsp_process_response(private_ocsp_t *this, chunk_t reply) +void ocsp_process_response(private_ocsp_t *this, chunk_t blob, credential_store_t *credentials) { - response_t res = empty_response; + x509_t *ocsp_cert = NULL; + response_t *res = response_create(); /* parse the ocsp response without looking at the single responses yet */ - response_status status = ocsp_parse_response(reply, &res); + response_status status = ocsp_parse_response(blob, res); if (status != STATUS_SUCCESSFUL) { DBG1("error in ocsp response"); - return; + goto err; } /* check if there was a nonce in the request */ - if (this->nonce.ptr != NULL && res.nonce.ptr == NULL) + if (this->nonce.ptr != NULL && res->nonce.ptr == NULL) { DBG1("ocsp response contains no nonce, replay attack possible"); } /* check if the nonces are identical */ - if (res.nonce.ptr != NULL && !chunk_equals(res.nonce, this->nonce)) + if (res->nonce.ptr != NULL && !chunk_equals(res->nonce, this->nonce)) { DBG1("invalid nonce in ocsp response"); - return; + goto err; } - /* check if the response is signed by a trusted key */ - if (!ocsp_valid_response(&res)) + /* check if we received a trusted responder certificate */ + if (res->responder_cert) { - DBG1("invalid ocsp response"); - return; + if (res->responder_cert->is_ocsp_signer(res->responder_cert)) + { + DBG2("received certificate is ocsp signer"); + if (credentials->is_trusted(credentials, res->responder_cert)) + { + DBG2("received ocsp signer certificate is trusted"); + ocsp_cert = credentials->add_auth_certificate(credentials, + res->responder_cert, AUTH_OCSP); + res->responder_cert = NULL; + } + else + { + DBG1("received ocsp signer certificate is not trusted - rejected"); + } + } + else + { + DBG1("received certificate is no ocsp signer - rejected"); + } + } + + /* if we didn't receive a trusted responder cert, search the credential store */ + if (ocsp_cert == NULL) + { + ocsp_cert = credentials->get_auth_certificate(credentials, + AUTH_OCSP|AUTH_CA, res->responder_id_name); + if (ocsp_cert == NULL) + { + DBG1("no ocsp signer certificate found"); + goto err; + } + } + + /* check the response signature */ + if (!ocsp_valid_response(res, ocsp_cert)) + { + DBG1("ocsp response signature is invalid"); + goto err; } - DBG2("valid ocsp response"); + DBG2("ocsp response signature is valid"); /* now parse the single responses one at a time */ { @@ -747,13 +816,13 @@ void ocsp_process_response(private_ocsp_t *this, chunk_t reply) chunk_t object; int objectID = 0; - asn1_init(&ctx, res.responses, 0, FALSE, FALSE); + asn1_init(&ctx, res->responses, 0, FALSE, FALSE); while (objectID < RESPONSES_ROOF) { if (!extract_object(responsesObjects, &objectID, &object, &level, &ctx)) { - return; + goto err; } if (objectID == RESPONSES_SINGLE_RESPONSE) { @@ -767,12 +836,14 @@ void ocsp_process_response(private_ocsp_t *this, chunk_t reply) objectID++; } } +err: + res->destroy(res); } /** * Implements ocsp_t.fetch. */ -static void fetch(private_ocsp_t *this, certinfo_t *certinfo) +static void fetch(private_ocsp_t *this, certinfo_t *certinfo, credential_store_t *credentials) { chunk_t request; chunk_t response; @@ -816,7 +887,7 @@ static void fetch(private_ocsp_t *this, certinfo_t *certinfo) return; } DBG3("ocsp response: %B", &response); - ocsp_process_response(this, response); + ocsp_process_response(this, response, credentials); free(response.ptr); } @@ -853,7 +924,7 @@ ocsp_t *ocsp_create(x509_t *cacert, linked_list_t *uris) } /* public functions */ - this->public.fetch = (void (*) (ocsp_t*,certinfo_t*))fetch; + this->public.fetch = (void (*) (ocsp_t*,certinfo_t*,credential_store_t*))fetch; this->public.destroy = (void (*) (ocsp_t*))destroy; return &this->public; diff --git a/src/libstrongswan/crypto/ocsp.h b/src/libstrongswan/crypto/ocsp.h index 687eae477..42059e1c6 100644 --- a/src/libstrongswan/crypto/ocsp.h +++ b/src/libstrongswan/crypto/ocsp.h @@ -27,7 +27,9 @@ typedef struct ocsp_t ocsp_t; -#include "utils/linked_list.h" +#include <credential_store.h> +#include <utils/linked_list.h> + #include "certinfo.h" /* constants */ @@ -57,8 +59,9 @@ struct ocsp_t { * * @param uris linked list of ocsp uris * @param certinfo certificate status info to be updated + * @param credentials credential store needed for trust path verification */ - void (*fetch) (ocsp_t *this, certinfo_t *certinfo); + void (*fetch) (ocsp_t *this, certinfo_t *certinfo, credential_store_t *credentials); /** * @brief Destroys the ocsp_t object. |