Add support for IKEv2 OCSP extensions (RFC 4806)
Closes strongswan/strongswan#2016 Co-authored-by: Tobias Brunner <tobias@strongswan.org>
This commit is contained in:
1 parent
ddd926b698
commit
15612b3a42
15 files changed
+477
-49
No files matched your search
@@ -96,6 +96,11 @@ struct private_ike_cfg_t {
|
||||
*/
|
||||
bool certreq;
|
||||
|
||||
/**
|
||||
* should we send an OCSP status request?
|
||||
*/
|
||||
bool ocsp_certreq;
|
||||
|
||||
/**
|
||||
* enforce UDP encapsulation
|
||||
*/
|
||||
@@ -134,6 +139,12 @@ METHOD(ike_cfg_t, send_certreq, bool,
|
||||
return this->certreq;
|
||||
}
|
||||
|
||||
METHOD(ike_cfg_t, send_ocsp_certreq, bool,
|
||||
private_ike_cfg_t *this)
|
||||
{
|
||||
return this->ocsp_certreq;
|
||||
}
|
||||
|
||||
METHOD(ike_cfg_t, force_encap_, bool,
|
||||
private_ike_cfg_t *this)
|
||||
{
|
||||
@@ -388,6 +399,7 @@ METHOD(ike_cfg_t, equals, bool,
|
||||
return
|
||||
this->version == other->version &&
|
||||
this->certreq == other->certreq &&
|
||||
this->ocsp_certreq == other->ocsp_certreq &&
|
||||
this->force_encap == other->force_encap &&
|
||||
this->fragmentation == other->fragmentation &&
|
||||
this->childless == other->childless &&
|
||||
@@ -587,6 +599,7 @@ ike_cfg_t *ike_cfg_create(ike_cfg_create_t *data)
|
||||
.public = {
|
||||
.get_version = _get_version,
|
||||
.send_certreq = _send_certreq,
|
||||
.send_ocsp_certreq = _send_ocsp_certreq,
|
||||
.force_encap = _force_encap_,
|
||||
.fragmentation = _fragmentation,
|
||||
.childless = _childless,
|
||||
@@ -611,6 +624,7 @@ ike_cfg_t *ike_cfg_create(ike_cfg_create_t *data)
|
||||
.refcount = 1,
|
||||
.version = data->version,
|
||||
.certreq = !data->no_certreq,
|
||||
.ocsp_certreq = !data->no_ocsp_certreq,
|
||||
.force_encap = data->force_encap,
|
||||
.fragmentation = data->fragmentation,
|
||||
.childless = data->childless,
|
||||
|
||||
@@ -210,6 +210,13 @@ struct ike_cfg_t {
|
||||
*/
|
||||
bool (*send_certreq) (ike_cfg_t *this);
|
||||
|
||||
/**
|
||||
* Should we send an OCSP status request in IKE_SA_INIT?
|
||||
*
|
||||
* @return OCSP status request sending policy
|
||||
*/
|
||||
bool (*send_ocsp_certreq) (ike_cfg_t *this);
|
||||
|
||||
/**
|
||||
* Enforce UDP encapsulation by faking NATD notifies?
|
||||
*
|
||||
@@ -288,6 +295,8 @@ struct ike_cfg_create_t {
|
||||
uint16_t remote_port;
|
||||
/** TRUE to not send any certificate requests */
|
||||
bool no_certreq;
|
||||
/** TRUE to not send OCSP status requests */
|
||||
bool no_ocsp_certreq;
|
||||
/** Enforce UDP encapsulation by faking NATD notify */
|
||||
bool force_encap;
|
||||
/** Use IKE fragmentation */
|
||||
|
||||
@@ -32,6 +32,13 @@ ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
|
||||
"CERT_NEVER_SEND",
|
||||
);
|
||||
|
||||
ENUM(ocsp_policy_names, OCSP_SEND_BOTH, OCSP_SEND_NEVER,
|
||||
"OCSP_SEND_BOTH",
|
||||
"OCSP_SEND_REPLY",
|
||||
"OCSP_SEND_REQUEST",
|
||||
"OCSP_SEND_NEVER",
|
||||
);
|
||||
|
||||
ENUM(unique_policy_names, UNIQUE_NEVER, UNIQUE_KEEP,
|
||||
"UNIQUE_NEVER",
|
||||
"UNIQUE_NO",
|
||||
@@ -81,6 +88,11 @@ struct private_peer_cfg_t {
|
||||
*/
|
||||
cert_policy_t cert_policy;
|
||||
|
||||
/**
|
||||
* should we send OCSP status request/response
|
||||
*/
|
||||
ocsp_policy_t ocsp_policy;
|
||||
|
||||
/**
|
||||
* uniqueness of an IKE_SA
|
||||
*/
|
||||
@@ -495,6 +507,12 @@ METHOD(peer_cfg_t, get_cert_policy, cert_policy_t,
|
||||
return this->cert_policy;
|
||||
}
|
||||
|
||||
METHOD(peer_cfg_t, get_ocsp_policy, ocsp_policy_t,
|
||||
private_peer_cfg_t *this)
|
||||
{
|
||||
return this->ocsp_policy;
|
||||
}
|
||||
|
||||
METHOD(peer_cfg_t, get_unique_policy, unique_policy_t,
|
||||
private_peer_cfg_t *this)
|
||||
{
|
||||
@@ -741,6 +759,7 @@ METHOD(peer_cfg_t, equals, bool,
|
||||
return (
|
||||
get_ike_version(this) == get_ike_version(other) &&
|
||||
this->cert_policy == other->cert_policy &&
|
||||
this->ocsp_policy == other->ocsp_policy &&
|
||||
this->unique == other->unique &&
|
||||
this->keyingtries == other->keyingtries &&
|
||||
this->use_mobike == other->use_mobike &&
|
||||
@@ -828,6 +847,7 @@ peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg,
|
||||
.create_child_cfg_enumerator = _create_child_cfg_enumerator,
|
||||
.select_child_cfg = _select_child_cfg,
|
||||
.get_cert_policy = _get_cert_policy,
|
||||
.get_ocsp_policy = _get_ocsp_policy,
|
||||
.get_unique_policy = _get_unique_policy,
|
||||
.get_keyingtries = _get_keyingtries,
|
||||
.get_rekey_time = _get_rekey_time,
|
||||
@@ -861,6 +881,7 @@ peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg,
|
||||
.child_cfgs = linked_list_create(),
|
||||
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
|
||||
.cert_policy = data->cert_policy,
|
||||
.ocsp_policy = data->ocsp_policy,
|
||||
.unique = data->unique,
|
||||
.keyingtries = data->keyingtries,
|
||||
.rekey_time = data->rekey_time,
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define PEER_CFG_H_
|
||||
|
||||
typedef enum cert_policy_t cert_policy_t;
|
||||
typedef enum ocsp_policy_t ocsp_policy_t;
|
||||
typedef enum unique_policy_t unique_policy_t;
|
||||
typedef struct peer_cfg_t peer_cfg_t;
|
||||
typedef struct peer_cfg_create_t peer_cfg_create_t;
|
||||
@@ -61,6 +62,25 @@ enum cert_policy_t {
|
||||
*/
|
||||
extern enum_name_t *cert_policy_names;
|
||||
|
||||
/**
|
||||
* OCSP status request/response sending policy.
|
||||
*/
|
||||
enum ocsp_policy_t {
|
||||
/** request OCSP status and reply to OCSP status requests */
|
||||
OCSP_SEND_BOTH = 0,
|
||||
/** send OCSP status upon OCSP status request */
|
||||
OCSP_SEND_REPLY = 1,
|
||||
/** send OCSP status request */
|
||||
OCSP_SEND_REQUEST = 2,
|
||||
/** never send OCSP status request or response */
|
||||
OCSP_SEND_NEVER = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum strings for ocsp_policy_t
|
||||
*/
|
||||
extern enum_name_t *ocsp_policy_names;
|
||||
|
||||
/**
|
||||
* Uniqueness of an IKE_SA, used to drop multiple connections with one peer.
|
||||
*/
|
||||
@@ -213,6 +233,13 @@ struct peer_cfg_t {
|
||||
*/
|
||||
cert_policy_t (*get_cert_policy) (peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* Should an OCSP status request/response be sent for this connection?
|
||||
*
|
||||
* @return OCSP sending policy
|
||||
*/
|
||||
ocsp_policy_t (*get_ocsp_policy) (peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* How to handle uniqueness of IKE_SAs?
|
||||
*
|
||||
@@ -397,6 +424,8 @@ struct peer_cfg_t {
|
||||
struct peer_cfg_create_t {
|
||||
/** Whether to send a certificate payload */
|
||||
cert_policy_t cert_policy;
|
||||
/** Whether to send OCSP status request/response */
|
||||
ocsp_policy_t ocsp_policy;
|
||||
/** Uniqueness of an IKE_SA */
|
||||
unique_policy_t unique;
|
||||
/** How many keying tries should be done before giving up */
|
||||
|
||||
@@ -230,6 +230,9 @@ METHOD(cert_payload_t, get_cert, certificate_t*,
|
||||
case ENC_CRL:
|
||||
type = CERT_X509_CRL;
|
||||
break;
|
||||
case ENC_OCSP_CONTENT:
|
||||
type = CERT_X509_OCSP_RESPONSE;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@@ -339,6 +342,9 @@ cert_payload_t *cert_payload_create_from_cert(payload_type_t type,
|
||||
case CERT_X509_AC:
|
||||
this->encoding = ENC_X509_ATTRIBUTE;
|
||||
break;
|
||||
case CERT_X509_OCSP_RESPONSE:
|
||||
this->encoding = ENC_OCSP_CONTENT;
|
||||
break;
|
||||
default:
|
||||
DBG1(DBG_ENC, "embedding %N certificate in payload failed",
|
||||
certificate_type_names, cert->get_type(cert));
|
||||
|
||||
@@ -244,6 +244,8 @@ METHOD(certreq_payload_t, get_cert_type, certificate_type_t,
|
||||
{
|
||||
case ENC_X509_SIGNATURE:
|
||||
return CERT_X509;
|
||||
case ENC_OCSP_CONTENT:
|
||||
return CERT_X509_OCSP_REQUEST;
|
||||
default:
|
||||
return CERT_ANY;
|
||||
}
|
||||
@@ -302,6 +304,9 @@ certreq_payload_t *certreq_payload_create_type(certificate_type_t type)
|
||||
case CERT_X509:
|
||||
this->encoding = ENC_X509_SIGNATURE;
|
||||
break;
|
||||
case CERT_X509_OCSP_REQUEST:
|
||||
this->encoding = ENC_OCSP_CONTENT;
|
||||
break;
|
||||
default:
|
||||
DBG1(DBG_ENC, "certificate type %N not supported in requests",
|
||||
certificate_type_names, type);
|
||||
|
||||
@@ -314,6 +314,7 @@ typedef struct {
|
||||
identification_t *ppk_id;
|
||||
bool ppk_required;
|
||||
cert_policy_t send_cert;
|
||||
ocsp_policy_t ocsp;
|
||||
uint64_t dpd_delay;
|
||||
uint64_t dpd_timeout;
|
||||
fragmentation_t fragmentation;
|
||||
@@ -425,6 +426,7 @@ static void log_peer_data(peer_data_t *data)
|
||||
DBG2(DBG_CFG, " remote_port = %u", data->remote_port);
|
||||
DBG2(DBG_CFG, " send_certreq = %u", data->send_certreq);
|
||||
DBG2(DBG_CFG, " send_cert = %N", cert_policy_names, data->send_cert);
|
||||
DBG2(DBG_CFG, " ocsp = %N", ocsp_policy_names, data->ocsp);
|
||||
DBG2(DBG_CFG, " ppk_id = %Y", data->ppk_id);
|
||||
DBG2(DBG_CFG, " ppk_required = %u", data->ppk_required);
|
||||
DBG2(DBG_CFG, " mobike = %u", data->mobike);
|
||||
@@ -1678,6 +1680,28 @@ CALLBACK(parse_send_cert, bool,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an ocsp_policy_t
|
||||
*/
|
||||
CALLBACK(parse_ocsp, bool,
|
||||
ocsp_policy_t *out, chunk_t v)
|
||||
{
|
||||
enum_map_t map[] = {
|
||||
{ "both", OCSP_SEND_BOTH },
|
||||
{ "reply", OCSP_SEND_REPLY },
|
||||
{ "request", OCSP_SEND_REQUEST },
|
||||
{ "never", OCSP_SEND_NEVER },
|
||||
};
|
||||
int d;
|
||||
|
||||
if (parse_map(map, countof(map), &d, v))
|
||||
{
|
||||
*out = d;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a unique_policy_t
|
||||
*/
|
||||
@@ -1879,6 +1903,7 @@ CALLBACK(peer_kv, bool,
|
||||
{ "childless", parse_childless, &peer->childless },
|
||||
{ "send_certreq", parse_bool, &peer->send_certreq },
|
||||
{ "send_cert", parse_send_cert, &peer->send_cert },
|
||||
{ "ocsp", parse_ocsp, &peer->ocsp },
|
||||
{ "keyingtries", parse_uint32, &peer->keyingtries },
|
||||
{ "unique", parse_unique, &peer->unique },
|
||||
{ "local_port", parse_uint32, &peer->local_port },
|
||||
@@ -2498,6 +2523,7 @@ CALLBACK(config_sn, bool,
|
||||
.send_certreq = TRUE,
|
||||
.pull = TRUE,
|
||||
.send_cert = CERT_SEND_IF_ASKED,
|
||||
.ocsp = OCSP_SEND_REPLY,
|
||||
.version = IKE_ANY,
|
||||
.remote_port = IKEV2_UDP_PORT,
|
||||
.fragmentation = FRAGMENTATION_YES,
|
||||
@@ -2646,6 +2672,8 @@ CALLBACK(config_sn, bool,
|
||||
.remote = peer.remote_addrs,
|
||||
.remote_port = peer.remote_port,
|
||||
.no_certreq = !peer.send_certreq,
|
||||
.no_ocsp_certreq = peer.ocsp != OCSP_SEND_BOTH &&
|
||||
peer.ocsp != OCSP_SEND_REQUEST,
|
||||
.force_encap = peer.encap,
|
||||
.fragmentation = peer.fragmentation,
|
||||
.childless = peer.childless,
|
||||
@@ -2655,6 +2683,7 @@ CALLBACK(config_sn, bool,
|
||||
|
||||
cfg = (peer_cfg_create_t){
|
||||
.cert_policy = peer.send_cert,
|
||||
.ocsp_policy = peer.ocsp,
|
||||
.unique = peer.unique,
|
||||
.keyingtries = peer.keyingtries,
|
||||
.rekey_time = peer.rekey_time,
|
||||
|
||||
@@ -250,6 +250,11 @@ enum ike_condition_t {
|
||||
* All authentication rounds have been completed successfully
|
||||
*/
|
||||
COND_AUTHENTICATED = (1<<14),
|
||||
|
||||
/**
|
||||
* An OCSP status request was received
|
||||
*/
|
||||
COND_OCSP_REQUEST = (1<<15),
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -215,6 +215,66 @@ static void add_attribute_certs(private_ike_cert_post_t *this,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build CERT payload with OCSP status for the given cert
|
||||
*/
|
||||
static cert_payload_t *build_cert_ocsp_payload(certificate_t *cert,
|
||||
certificate_t *issuer)
|
||||
{
|
||||
certificate_t *response;
|
||||
cert_payload_t *payload;
|
||||
|
||||
response = lib->credmgr->get_ocsp(lib->credmgr, cert, issuer);
|
||||
if (!response)
|
||||
{
|
||||
DBG2(DBG_IKE, "no OCSP status for certificate \"%Y\"",
|
||||
cert->get_subject(cert));
|
||||
return NULL;
|
||||
}
|
||||
payload = cert_payload_create_from_cert(PLV2_CERTIFICATE, response);
|
||||
response->destroy(response);
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subject certificate and intermediate CA certificates OCSP status to message
|
||||
*/
|
||||
static void add_cert_ocsp(private_ike_cert_post_t *this, auth_cfg_t *auth,
|
||||
message_t *message)
|
||||
{
|
||||
auth_rule_t type;
|
||||
cert_payload_t *payload;
|
||||
certificate_t *cert, *issuer;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
|
||||
if (!cert)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
enumerator = auth->create_enumerator(auth);
|
||||
while (enumerator->enumerate(enumerator, &type, &issuer))
|
||||
{
|
||||
if (type == AUTH_RULE_CA_CERT || type == AUTH_RULE_IM_CERT)
|
||||
{
|
||||
payload = build_cert_ocsp_payload(cert, issuer);
|
||||
if (payload)
|
||||
{
|
||||
DBG1(DBG_IKE, "sending OCSP status for certificate \"%Y\"",
|
||||
cert->get_subject(cert));
|
||||
message->add_payload(message, (payload_t*)payload);
|
||||
}
|
||||
if (type == AUTH_RULE_CA_CERT)
|
||||
{
|
||||
break;
|
||||
}
|
||||
cert = issuer;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* add certificates to message
|
||||
*/
|
||||
@@ -250,6 +310,23 @@ static void build_certs(private_ike_cert_post_t *this, message_t *message)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (peer_cfg->get_ocsp_policy(peer_cfg))
|
||||
{
|
||||
case OCSP_SEND_NEVER:
|
||||
case OCSP_SEND_REQUEST:
|
||||
break;
|
||||
case OCSP_SEND_REPLY:
|
||||
case OCSP_SEND_BOTH:
|
||||
if (this->ike_sa->has_condition(this->ike_sa, COND_OCSP_REQUEST) &&
|
||||
!this->ike_sa->has_condition(this->ike_sa,
|
||||
COND_ONLINE_VALIDATION_SUSPENDED))
|
||||
{
|
||||
auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
|
||||
add_cert_ocsp(this, auth, message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(task_t, build_i, status_t,
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "ike_cert_pre.h"
|
||||
|
||||
#include <daemon.h>
|
||||
@@ -59,9 +61,51 @@ static void process_certreq(private_ike_cert_pre_t *this,
|
||||
certreq_payload_t *certreq, auth_cfg_t *auth)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
u_int unknown = 0;
|
||||
u_int unknown = 0, known = 0;
|
||||
chunk_t keyid;
|
||||
|
||||
if (certreq->get_cert_type(certreq) == CERT_X509_OCSP_REQUEST)
|
||||
{
|
||||
this->ike_sa->set_condition(this->ike_sa, COND_OCSP_REQUEST, TRUE);
|
||||
|
||||
enumerator = certreq->create_keyid_enumerator(certreq);
|
||||
while (enumerator->enumerate(enumerator, &keyid))
|
||||
{
|
||||
identification_t *id;
|
||||
certificate_t *cert;
|
||||
|
||||
id = identification_create_from_encoding(ID_KEY_ID, keyid);
|
||||
cert = lib->credmgr->get_cert(lib->credmgr,
|
||||
CERT_X509, KEY_ANY, id, TRUE);
|
||||
if (cert)
|
||||
{
|
||||
DBG1(DBG_IKE, "received OCSP cert request claiming trust "
|
||||
"for \"%Y\"", cert->get_subject(cert));
|
||||
cert->destroy(cert);
|
||||
known++;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG2(DBG_IKE, "received OCSP cert request claiming trust for "
|
||||
"unknown certificate with keyid %Y", id);
|
||||
unknown++;
|
||||
}
|
||||
id->destroy(id);
|
||||
|
||||
}
|
||||
if (unknown)
|
||||
{
|
||||
DBG1(DBG_IKE, "received OCSP cert request with %u unknown trusted "
|
||||
"certificates", unknown);
|
||||
}
|
||||
else if (!known)
|
||||
{
|
||||
DBG1(DBG_IKE, "received empty OCSP cert request");
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return;
|
||||
}
|
||||
|
||||
this->ike_sa->set_condition(this->ike_sa, COND_CERTREQ_SEEN, TRUE);
|
||||
|
||||
if (certreq->get_cert_type(certreq) != CERT_X509)
|
||||
@@ -255,6 +299,30 @@ static void process_crl(cert_payload_t *payload, auth_cfg_t *auth)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an OCSP certificate payload
|
||||
*/
|
||||
static void process_ocsp(cert_payload_t *payload, auth_cfg_t *auth,
|
||||
ike_cfg_t *ike_cfg)
|
||||
{
|
||||
certificate_t *cert;
|
||||
|
||||
if (!ike_cfg->send_ocsp_certreq(ike_cfg))
|
||||
{
|
||||
DBG1(DBG_IKE, "received OCSP response, but we didn't request any, "
|
||||
"ignore");
|
||||
return;
|
||||
}
|
||||
|
||||
cert = payload->get_cert(payload);
|
||||
if (cert)
|
||||
{
|
||||
DBG1(DBG_IKE, "received OCSP response issued by \"%Y\"",
|
||||
cert->get_issuer(cert));
|
||||
auth->add(auth, AUTH_HELPER_REVOCATION_CERT, cert);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an attribute certificate payload
|
||||
*/
|
||||
@@ -318,6 +386,10 @@ static void process_certs(private_ike_cert_pre_t *this, message_t *message)
|
||||
case ENC_CRL:
|
||||
process_crl(cert_payload, auth);
|
||||
break;
|
||||
case ENC_OCSP_CONTENT:
|
||||
process_ocsp(cert_payload, auth,
|
||||
this->ike_sa->get_ike_cfg(this->ike_sa));
|
||||
break;
|
||||
case ENC_X509_ATTRIBUTE:
|
||||
process_ac(cert_payload, auth);
|
||||
break;
|
||||
@@ -329,7 +401,6 @@ static void process_certs(private_ike_cert_pre_t *this, message_t *message)
|
||||
case ENC_SPKI:
|
||||
case ENC_RAW_RSA_KEY:
|
||||
case ENC_X509_HASH_AND_URL_BUNDLE:
|
||||
case ENC_OCSP_CONTENT:
|
||||
default:
|
||||
DBG1(DBG_ENC, "certificate encoding %N not supported",
|
||||
cert_encoding_names, encoding);
|
||||
@@ -403,6 +474,36 @@ static void add_certreqs(certreq_payload_t **req, auth_cfg_t *auth)
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* add the keyid of a self-signed OCSP signer to the certificate request payload
|
||||
*/
|
||||
static void add_certreq_ocsp(certreq_payload_t *req, certificate_t *cert)
|
||||
{
|
||||
public_key_t *public;
|
||||
chunk_t keyid;
|
||||
x509_t *x509 = (x509_t*)cert;
|
||||
|
||||
if (cert->get_type(cert) != CERT_X509 ||
|
||||
!(x509->get_flags(x509) & X509_OCSP_SIGNER &&
|
||||
x509->get_flags(x509) & X509_SELF_SIGNED))
|
||||
{
|
||||
/* no self-signed OCSP-signer cert, skip */
|
||||
return;
|
||||
}
|
||||
public = cert->get_public_key(cert);
|
||||
if (!public)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid))
|
||||
{
|
||||
req->add_keyid(req, keyid);
|
||||
DBG1(DBG_IKE, "sending OCSP cert request with self-signed "
|
||||
"OCSP-signer \"%Y\"", cert->get_subject(cert));
|
||||
}
|
||||
public->destroy(public);
|
||||
}
|
||||
|
||||
/**
|
||||
* build certificate requests
|
||||
*/
|
||||
@@ -416,46 +517,59 @@ static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
|
||||
certreq_payload_t *req = NULL;
|
||||
|
||||
ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
|
||||
if (!ike_cfg->send_certreq(ike_cfg))
|
||||
if (ike_cfg->send_certreq(ike_cfg))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* check if we require a specific CA for that peer */
|
||||
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||
if (peer_cfg)
|
||||
{
|
||||
enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
|
||||
while (enumerator->enumerate(enumerator, &auth))
|
||||
/* check if we require a specific CA for that peer */
|
||||
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||
if (peer_cfg)
|
||||
{
|
||||
add_certreqs(&req, auth);
|
||||
enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
|
||||
while (enumerator->enumerate(enumerator, &auth))
|
||||
{
|
||||
add_certreqs(&req, auth);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
if (!req)
|
||||
{
|
||||
/* otherwise add all trusted CA certificates */
|
||||
enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
|
||||
CERT_ANY, KEY_ANY, NULL, TRUE);
|
||||
while (enumerator->enumerate(enumerator, &cert))
|
||||
{
|
||||
add_certreq(&req, cert);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
if (req)
|
||||
{
|
||||
message->add_payload(message, (payload_t*)req);
|
||||
|
||||
if (lib->settings->get_bool(lib->settings,
|
||||
"%s.hash_and_url", FALSE, lib->ns))
|
||||
{
|
||||
message->add_notify(message, FALSE, HTTP_CERT_LOOKUP_SUPPORTED,
|
||||
chunk_empty);
|
||||
this->do_http_lookup = TRUE;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
if (!req)
|
||||
if (ike_cfg->send_ocsp_certreq(ike_cfg))
|
||||
{
|
||||
/* otherwise add all trusted CA certificates */
|
||||
req = certreq_payload_create_type(CERT_X509_OCSP_REQUEST);
|
||||
|
||||
enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
|
||||
CERT_ANY, KEY_ANY, NULL, TRUE);
|
||||
while (enumerator->enumerate(enumerator, &cert))
|
||||
{
|
||||
add_certreq(&req, cert);
|
||||
add_certreq_ocsp(req, cert);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
if (req)
|
||||
{
|
||||
message->add_payload(message, (payload_t*)req);
|
||||
|
||||
if (lib->settings->get_bool(lib->settings,
|
||||
"%s.hash_and_url", FALSE, lib->ns))
|
||||
{
|
||||
message->add_notify(message, FALSE, HTTP_CERT_LOOKUP_SUPPORTED,
|
||||
chunk_empty);
|
||||
this->do_http_lookup = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user