Merge branch 'mbb-reauth-online-revocation'
With these changes initiators of make-before-break reauthentications
suspend online revocation checks until after the new IKE_SA and all
CHILD_SAs are established. See f1cbacc5d1 for details why that's
necessary.
This commit is contained in:
@@ -11,6 +11,15 @@ strongswan-5.4.0
|
||||
constraints against IKEv2 authentication in rightauth, which allows the use
|
||||
of different signature schemes for trustchain verification and authentication.
|
||||
|
||||
- The initiator of an IKEv2 make-before-break reauthentication now suspends
|
||||
online certificate revocation checks (OCSP, CRLs) until the new IKE_SA and all
|
||||
CHILD_SAs are established. This is required if the checks are done over the
|
||||
CHILD_SA established with the new IKE_SA. This is not possible until the
|
||||
initiator installs this SA and that only happens after the authentication is
|
||||
completed successfully. So we suspend the checks during the reauthentication
|
||||
and do them afterwards, if they fail the IKE_SA is closed. This change has no
|
||||
effect on the behavior during the authentication of the initial IKE_SA.
|
||||
|
||||
- For the vici plugin a Vici:Session Perl CPAN module has been added to allow
|
||||
Perl applications to control and/or monitor the IKE daemon using the VICI
|
||||
interface, similar to the existing Python egg or Ruby gem.
|
||||
|
||||
@@ -111,7 +111,8 @@ sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \
|
||||
sa/ikev2/tasks/ike_reauth_complete.c sa/ikev2/tasks/ike_reauth_complete.h \
|
||||
sa/ikev2/tasks/ike_redirect.c sa/ikev2/tasks/ike_redirect.h \
|
||||
sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \
|
||||
sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h
|
||||
sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h \
|
||||
sa/ikev2/tasks/ike_verify_peer_cert.c sa/ikev2/tasks/ike_verify_peer_cert.h
|
||||
|
||||
libcharon_la_SOURCES += \
|
||||
sa/ikev1/keymat_v1.c sa/ikev1/keymat_v1.h \
|
||||
|
||||
@@ -111,7 +111,8 @@ sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \
|
||||
sa/ikev2/tasks/ike_reauth_complete.c sa/ikev2/tasks/ike_reauth_complete.h \
|
||||
sa/ikev2/tasks/ike_redirect.c sa/ikev2/tasks/ike_redirect.h \
|
||||
sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \
|
||||
sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h
|
||||
sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h \
|
||||
sa/ikev2/tasks/ike_verify_peer_cert.c sa/ikev2/tasks/ike_verify_peer_cert.h
|
||||
endif
|
||||
|
||||
if USE_IKEV1
|
||||
|
||||
+117
-3
@@ -58,6 +58,7 @@
|
||||
#include <sa/ikev2/tasks/ike_auth_lifetime.h>
|
||||
#include <sa/ikev2/tasks/ike_reauth_complete.h>
|
||||
#include <sa/ikev2/tasks/ike_redirect.h>
|
||||
#include <credentials/sets/auth_cfg_wrapper.h>
|
||||
|
||||
#ifdef ME
|
||||
#include <sa/ikev2/tasks/ike_me.h>
|
||||
@@ -482,6 +483,113 @@ static void flush_auth_cfgs(private_ike_sa_t *this)
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(ike_sa_t, verify_peer_certificate, bool,
|
||||
private_ike_sa_t *this)
|
||||
{
|
||||
enumerator_t *e1, *e2, *certs;
|
||||
auth_cfg_t *cfg, *cfg_done;
|
||||
certificate_t *peer, *cert;
|
||||
public_key_t *key;
|
||||
auth_cfg_t *auth;
|
||||
auth_cfg_wrapper_t *wrapper;
|
||||
time_t not_before, not_after;
|
||||
bool valid = TRUE, found;
|
||||
|
||||
if (this->state != IKE_ESTABLISHED)
|
||||
{
|
||||
DBG1(DBG_IKE, "unable to verify peer certificate in state %N",
|
||||
ike_sa_state_names, this->state);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!this->flush_auth_cfg &&
|
||||
lib->settings->get_bool(lib->settings,
|
||||
"%s.flush_auth_cfg", FALSE, lib->ns))
|
||||
{ /* we can do this check only once if auth configs are flushed */
|
||||
DBG1(DBG_IKE, "unable to verify peer certificate as authentication "
|
||||
"information has been flushed");
|
||||
return FALSE;
|
||||
}
|
||||
this->public.set_condition(&this->public, COND_ONLINE_VALIDATION_SUSPENDED,
|
||||
FALSE);
|
||||
|
||||
e1 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, FALSE);
|
||||
e2 = array_create_enumerator(this->other_auths);
|
||||
while (e1->enumerate(e1, &cfg))
|
||||
{
|
||||
if (!e2->enumerate(e2, &cfg_done))
|
||||
{ /* this should not happen as the authentication should never have
|
||||
* succeeded */
|
||||
valid = FALSE;
|
||||
break;
|
||||
}
|
||||
if ((uintptr_t)cfg_done->get(cfg_done,
|
||||
AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_PUBKEY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
peer = cfg_done->get(cfg_done, AUTH_RULE_SUBJECT_CERT);
|
||||
if (!peer)
|
||||
{
|
||||
DBG1(DBG_IKE, "no subject certificate found, skipping certificate "
|
||||
"verification");
|
||||
continue;
|
||||
}
|
||||
if (!peer->get_validity(peer, NULL, ¬_before, ¬_after))
|
||||
{
|
||||
DBG1(DBG_IKE, "peer certificate invalid (valid from %T to %T)",
|
||||
¬_before, FALSE, ¬_after, FALSE);
|
||||
valid = FALSE;
|
||||
break;
|
||||
}
|
||||
key = peer->get_public_key(peer);
|
||||
if (!key)
|
||||
{
|
||||
DBG1(DBG_IKE, "unable to retrieve public key, skipping certificate "
|
||||
"verification");
|
||||
continue;
|
||||
}
|
||||
DBG1(DBG_IKE, "verifying peer certificate");
|
||||
/* serve received certificates */
|
||||
wrapper = auth_cfg_wrapper_create(cfg_done);
|
||||
lib->credmgr->add_local_set(lib->credmgr, &wrapper->set, FALSE);
|
||||
certs = lib->credmgr->create_trusted_enumerator(lib->credmgr,
|
||||
key->get_type(key), peer->get_subject(peer), TRUE);
|
||||
key->destroy(key);
|
||||
|
||||
found = FALSE;
|
||||
while (certs->enumerate(certs, &cert, &auth))
|
||||
{
|
||||
if (peer->equals(peer, cert))
|
||||
{
|
||||
cfg_done->add(cfg_done, AUTH_RULE_CERT_VALIDATION_SUSPENDED,
|
||||
FALSE);
|
||||
cfg_done->merge(cfg_done, auth, FALSE);
|
||||
valid = cfg_done->complies(cfg_done, cfg, TRUE);
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
certs->destroy(certs);
|
||||
lib->credmgr->remove_local_set(lib->credmgr, &wrapper->set);
|
||||
wrapper->destroy(wrapper);
|
||||
if (!found || !valid)
|
||||
{
|
||||
valid = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
e1->destroy(e1);
|
||||
e2->destroy(e2);
|
||||
|
||||
if (this->flush_auth_cfg)
|
||||
{
|
||||
this->flush_auth_cfg = FALSE;
|
||||
flush_auth_cfgs(this);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
METHOD(ike_sa_t, get_proposal, proposal_t*,
|
||||
private_ike_sa_t *this)
|
||||
{
|
||||
@@ -1441,9 +1549,14 @@ METHOD(ike_sa_t, process_message, status_t,
|
||||
status = this->task_manager->process_message(this->task_manager, message);
|
||||
if (this->flush_auth_cfg && this->state == IKE_ESTABLISHED)
|
||||
{
|
||||
/* authentication completed */
|
||||
this->flush_auth_cfg = FALSE;
|
||||
flush_auth_cfgs(this);
|
||||
/* authentication completed but if the online validation is suspended we
|
||||
* need the auth cfgs until we did the delayed verification, we flush
|
||||
* them afterwards */
|
||||
if (!has_condition(this, COND_ONLINE_VALIDATION_SUSPENDED))
|
||||
{
|
||||
this->flush_auth_cfg = FALSE;
|
||||
flush_auth_cfgs(this);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -2750,6 +2863,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
|
||||
.set_peer_cfg = _set_peer_cfg,
|
||||
.get_auth_cfg = _get_auth_cfg,
|
||||
.create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
|
||||
.verify_peer_certificate = _verify_peer_certificate,
|
||||
.add_auth_cfg = _add_auth_cfg,
|
||||
.get_proposal = _get_proposal,
|
||||
.set_proposal = _set_proposal,
|
||||
|
||||
@@ -217,6 +217,11 @@ enum ike_condition_t {
|
||||
* This IKE_SA has been redirected
|
||||
*/
|
||||
COND_REDIRECTED = (1<<11),
|
||||
|
||||
/**
|
||||
* Online certificate revocation checking is suspended for this IKE_SA
|
||||
*/
|
||||
COND_ONLINE_VALIDATION_SUSPENDED = (1<<12),
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -521,6 +526,14 @@ struct ike_sa_t {
|
||||
*/
|
||||
enumerator_t* (*create_auth_cfg_enumerator)(ike_sa_t *this, bool local);
|
||||
|
||||
/**
|
||||
* Verify the trustchains (validity, revocation) in completed public key
|
||||
* auth rounds.
|
||||
*
|
||||
* @return TRUE if certificates were valid, FALSE otherwise
|
||||
*/
|
||||
bool (*verify_peer_certificate)(ike_sa_t *this);
|
||||
|
||||
/**
|
||||
* Get the selected proposal of this IKE_SA.
|
||||
*
|
||||
|
||||
@@ -173,7 +173,7 @@ METHOD(authenticator_t, process, status_t,
|
||||
sig = sig_payload->get_hash(sig_payload);
|
||||
auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
|
||||
enumerator = lib->credmgr->create_public_enumerator(lib->credmgr, this->type,
|
||||
id, auth);
|
||||
id, auth, TRUE);
|
||||
while (enumerator->enumerate(enumerator, &public, ¤t_auth))
|
||||
{
|
||||
if (public->verify(public, scheme, hash, sig))
|
||||
|
||||
@@ -365,6 +365,7 @@ METHOD(authenticator_t, process, status_t,
|
||||
status_t status = NOT_FOUND;
|
||||
keymat_v2_t *keymat;
|
||||
const char *reason = "unsupported";
|
||||
bool online;
|
||||
|
||||
auth_payload = (auth_payload_t*)message->get_payload(message, PLV2_AUTH);
|
||||
if (!auth_payload)
|
||||
@@ -408,8 +409,10 @@ METHOD(authenticator_t, process, status_t,
|
||||
return FAILED;
|
||||
}
|
||||
auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
|
||||
online = !this->ike_sa->has_condition(this->ike_sa,
|
||||
COND_ONLINE_VALIDATION_SUSPENDED);
|
||||
enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
|
||||
key_type, id, auth);
|
||||
key_type, id, auth, online);
|
||||
while (enumerator->enumerate(enumerator, &public, ¤t_auth))
|
||||
{
|
||||
if (public->verify(public, scheme, octets, auth_data))
|
||||
@@ -421,6 +424,10 @@ METHOD(authenticator_t, process, status_t,
|
||||
auth->merge(auth, current_auth, FALSE);
|
||||
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
|
||||
auth->add(auth, AUTH_RULE_IKE_SIGNATURE_SCHEME, (uintptr_t)scheme);
|
||||
if (!online)
|
||||
{
|
||||
auth->add(auth, AUTH_RULE_CERT_VALIDATION_SUSPENDED, TRUE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <sa/ikev2/tasks/ike_config.h>
|
||||
#include <sa/ikev2/tasks/ike_dpd.h>
|
||||
#include <sa/ikev2/tasks/ike_vendor.h>
|
||||
#include <sa/ikev2/tasks/ike_verify_peer_cert.h>
|
||||
#include <sa/ikev2/tasks/child_create.h>
|
||||
#include <sa/ikev2/tasks/child_rekey.h>
|
||||
#include <sa/ikev2/tasks/child_delete.h>
|
||||
@@ -527,6 +528,11 @@ METHOD(task_manager_t, initiate, status_t,
|
||||
exchange = INFORMATIONAL;
|
||||
break;
|
||||
}
|
||||
if (activate_task(this, TASK_IKE_VERIFY_PEER_CERT))
|
||||
{
|
||||
exchange = INFORMATIONAL;
|
||||
break;
|
||||
}
|
||||
case IKE_REKEYING:
|
||||
if (activate_task(this, TASK_IKE_DELETE))
|
||||
{
|
||||
@@ -624,7 +630,7 @@ METHOD(task_manager_t, initiate, status_t,
|
||||
if (this->initiating.type == EXCHANGE_TYPE_UNDEFINED)
|
||||
{
|
||||
message->destroy(message);
|
||||
return SUCCESS;
|
||||
return initiate(this);
|
||||
}
|
||||
|
||||
if (!generate_message(this, message, &this->initiating.packets))
|
||||
@@ -1650,8 +1656,12 @@ static void trigger_mbb_reauth(private_task_manager_t *this)
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
/* suspend online revocation checking until the SA is established */
|
||||
new->set_condition(new, COND_ONLINE_VALIDATION_SUSPENDED, TRUE);
|
||||
|
||||
if (new->initiate(new, NULL, 0, NULL, NULL) != DESTROY_ME)
|
||||
{
|
||||
new->queue_task(new, (task_t*)ike_verify_peer_cert_create(new));
|
||||
new->queue_task(new, (task_t*)ike_reauth_complete_create(new,
|
||||
this->ike_sa->get_id(this->ike_sa)));
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Tobias Brunner
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ike_verify_peer_cert.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <sa/ikev2/tasks/ike_delete.h>
|
||||
|
||||
typedef struct private_ike_verify_peer_cert_t private_ike_verify_peer_cert_t;
|
||||
|
||||
/**
|
||||
* Private members
|
||||
*/
|
||||
struct private_ike_verify_peer_cert_t {
|
||||
|
||||
/**
|
||||
* Public methods and task_t interface.
|
||||
*/
|
||||
ike_verify_peer_cert_t public;
|
||||
|
||||
/**
|
||||
* Assigned IKE_SA.
|
||||
*/
|
||||
ike_sa_t *ike_sa;
|
||||
|
||||
/**
|
||||
* Child ike_delete task, if necessary
|
||||
*/
|
||||
ike_delete_t *ike_delete;
|
||||
};
|
||||
|
||||
METHOD(task_t, build_i, status_t,
|
||||
private_ike_verify_peer_cert_t *this, message_t *message)
|
||||
{
|
||||
if (!this->ike_sa->verify_peer_certificate(this->ike_sa))
|
||||
{
|
||||
DBG1(DBG_IKE, "peer certificate verification failed, deleting SA");
|
||||
this->ike_delete = ike_delete_create(this->ike_sa, TRUE);
|
||||
return this->ike_delete->task.build(&this->ike_delete->task, message);
|
||||
}
|
||||
DBG1(DBG_IKE, "peer certificate successfully verified");
|
||||
message->set_exchange_type(message, EXCHANGE_TYPE_UNDEFINED);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(task_t, process_i, status_t,
|
||||
private_ike_verify_peer_cert_t *this, message_t *message)
|
||||
{
|
||||
if (this->ike_delete)
|
||||
{
|
||||
this->ike_delete->task.process(&this->ike_delete->task, message);
|
||||
/* try to reestablish the IKE_SA and all children */
|
||||
this->ike_sa->reestablish(this->ike_sa);
|
||||
}
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
METHOD(task_t, get_type, task_type_t,
|
||||
private_ike_verify_peer_cert_t *this)
|
||||
{
|
||||
return TASK_IKE_VERIFY_PEER_CERT;
|
||||
}
|
||||
|
||||
METHOD(task_t, migrate, void,
|
||||
private_ike_verify_peer_cert_t *this, ike_sa_t *ike_sa)
|
||||
{
|
||||
if (this->ike_delete)
|
||||
{
|
||||
this->ike_delete->task.migrate(&this->ike_delete->task, ike_sa);
|
||||
}
|
||||
this->ike_sa = ike_sa;
|
||||
}
|
||||
|
||||
METHOD(task_t, destroy, void,
|
||||
private_ike_verify_peer_cert_t *this)
|
||||
{
|
||||
if (this->ike_delete)
|
||||
{
|
||||
this->ike_delete->task.destroy(&this->ike_delete->task);
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
ike_verify_peer_cert_t *ike_verify_peer_cert_create(ike_sa_t *ike_sa)
|
||||
{
|
||||
private_ike_verify_peer_cert_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.task = {
|
||||
.get_type = _get_type,
|
||||
.migrate = _migrate,
|
||||
.build = _build_i,
|
||||
.process = _process_i,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
.ike_sa = ike_sa,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Tobias Brunner
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup ike_verify_peer_cert ike_verify_peer_cert
|
||||
* @{ @ingroup tasks_v2
|
||||
*/
|
||||
|
||||
#ifndef IKE_VERIFY_PEER_CERT_H_
|
||||
#define IKE_VERIFY_PEER_CERT_H_
|
||||
|
||||
typedef struct ike_verify_peer_cert_t ike_verify_peer_cert_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <sa/ike_sa.h>
|
||||
#include <sa/task.h>
|
||||
|
||||
/**
|
||||
* Task of type ike_verify_peer_cert, verifies a peer's certificate.
|
||||
*
|
||||
* This task (re-)verifies the peer's certificate explicitly including online
|
||||
* OCSP and CRL checks.
|
||||
*/
|
||||
struct ike_verify_peer_cert_t {
|
||||
|
||||
/**
|
||||
* Implements the task_t interface
|
||||
*/
|
||||
task_t task;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new ike_verify_peer_cert task.
|
||||
*
|
||||
* This task is initiator only.
|
||||
*
|
||||
* @param ike_sa IKE_SA this task works for
|
||||
* @return ike_verify_peer_cert task to handle by the task_manager
|
||||
*/
|
||||
ike_verify_peer_cert_t *ike_verify_peer_cert_create(ike_sa_t *ike_sa);
|
||||
|
||||
#endif /** IKE_VERIFY_PEER_CERT_H_ @}*/
|
||||
@@ -29,6 +29,7 @@ ENUM(task_type_names, TASK_IKE_INIT, TASK_ISAKMP_CERT_POST,
|
||||
"IKE_REAUTH",
|
||||
"IKE_REAUTH_COMPLETE",
|
||||
"IKE_REDIRECT",
|
||||
"IKE_VERIFY_PEER_CERT",
|
||||
"IKE_DELETE",
|
||||
"IKE_DPD",
|
||||
"IKE_VENDOR",
|
||||
|
||||
@@ -59,6 +59,8 @@ enum task_type_t {
|
||||
TASK_IKE_REAUTH_COMPLETE,
|
||||
/** redirect an active IKE_SA */
|
||||
TASK_IKE_REDIRECT,
|
||||
/** verify a peer's certificate */
|
||||
TASK_IKE_VERIFY_PEER_CERT,
|
||||
/** delete an IKE_SA */
|
||||
TASK_IKE_DELETE,
|
||||
/** liveness check */
|
||||
|
||||
@@ -46,6 +46,7 @@ ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_AC_CERT,
|
||||
"RULE_SUBJECT_CERT",
|
||||
"RULE_CRL_VALIDATION",
|
||||
"RULE_OCSP_VALIDATION",
|
||||
"RULE_CERT_VALIDATION_SUSPENDED",
|
||||
"RULE_GROUP",
|
||||
"RULE_RSA_STRENGTH",
|
||||
"RULE_ECDSA_STRENGTH",
|
||||
@@ -80,6 +81,7 @@ static inline bool is_multi_value_rule(auth_rule_t type)
|
||||
case AUTH_RULE_AAA_IDENTITY:
|
||||
case AUTH_RULE_XAUTH_IDENTITY:
|
||||
case AUTH_RULE_XAUTH_BACKEND:
|
||||
case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
|
||||
case AUTH_HELPER_SUBJECT_CERT:
|
||||
case AUTH_HELPER_SUBJECT_HASH_URL:
|
||||
case AUTH_RULE_MAX:
|
||||
@@ -214,6 +216,7 @@ static void init_entry(entry_t *this, auth_rule_t type, va_list args)
|
||||
case AUTH_RULE_BLISS_STRENGTH:
|
||||
case AUTH_RULE_SIGNATURE_SCHEME:
|
||||
case AUTH_RULE_IKE_SIGNATURE_SCHEME:
|
||||
case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
|
||||
/* integer type */
|
||||
this->value = (void*)(uintptr_t)va_arg(args, u_int);
|
||||
break;
|
||||
@@ -264,6 +267,7 @@ static bool entry_equals(entry_t *e1, entry_t *e2)
|
||||
case AUTH_RULE_BLISS_STRENGTH:
|
||||
case AUTH_RULE_SIGNATURE_SCHEME:
|
||||
case AUTH_RULE_IKE_SIGNATURE_SCHEME:
|
||||
case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
|
||||
{
|
||||
return e1->value == e2->value;
|
||||
}
|
||||
@@ -356,6 +360,7 @@ static void destroy_entry_value(entry_t *entry)
|
||||
case AUTH_RULE_BLISS_STRENGTH:
|
||||
case AUTH_RULE_SIGNATURE_SCHEME:
|
||||
case AUTH_RULE_IKE_SIGNATURE_SCHEME:
|
||||
case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
|
||||
case AUTH_RULE_MAX:
|
||||
break;
|
||||
}
|
||||
@@ -389,6 +394,7 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator,
|
||||
case AUTH_RULE_BLISS_STRENGTH:
|
||||
case AUTH_RULE_SIGNATURE_SCHEME:
|
||||
case AUTH_RULE_IKE_SIGNATURE_SCHEME:
|
||||
case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
|
||||
/* integer type */
|
||||
entry->value = (void*)(uintptr_t)va_arg(args, u_int);
|
||||
break;
|
||||
@@ -471,6 +477,7 @@ METHOD(auth_cfg_t, get, void*,
|
||||
case AUTH_RULE_OCSP_VALIDATION:
|
||||
return (void*)VALIDATION_FAILED;
|
||||
case AUTH_RULE_IDENTITY_LOOSE:
|
||||
case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
|
||||
return (void*)FALSE;
|
||||
case AUTH_RULE_IDENTITY:
|
||||
case AUTH_RULE_EAP_IDENTITY:
|
||||
@@ -757,6 +764,11 @@ METHOD(auth_cfg_t, complies, bool,
|
||||
{
|
||||
uintptr_t validated;
|
||||
|
||||
if (get(this, AUTH_RULE_CERT_VALIDATION_SUSPENDED))
|
||||
{ /* skip validation, may happen later */
|
||||
break;
|
||||
}
|
||||
|
||||
e2 = create_enumerator(this);
|
||||
while (e2->enumerate(e2, &t2, &validated))
|
||||
{
|
||||
@@ -934,6 +946,8 @@ METHOD(auth_cfg_t, complies, bool,
|
||||
/* just an indication when verifying AUTH_RULE_IDENTITY */
|
||||
case AUTH_RULE_XAUTH_BACKEND:
|
||||
/* not enforced, just a hint for local authentication */
|
||||
case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
|
||||
/* not a constraint */
|
||||
case AUTH_HELPER_IM_CERT:
|
||||
case AUTH_HELPER_SUBJECT_CERT:
|
||||
case AUTH_HELPER_IM_HASH_URL:
|
||||
@@ -1086,6 +1100,7 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy
|
||||
case AUTH_RULE_BLISS_STRENGTH:
|
||||
case AUTH_RULE_SIGNATURE_SCHEME:
|
||||
case AUTH_RULE_IKE_SIGNATURE_SCHEME:
|
||||
case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
|
||||
{
|
||||
add(this, type, (uintptr_t)value);
|
||||
break;
|
||||
@@ -1257,6 +1272,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
|
||||
case AUTH_RULE_BLISS_STRENGTH:
|
||||
case AUTH_RULE_SIGNATURE_SCHEME:
|
||||
case AUTH_RULE_IKE_SIGNATURE_SCHEME:
|
||||
case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
|
||||
clone->add(clone, type, (uintptr_t)value);
|
||||
break;
|
||||
case AUTH_RULE_MAX:
|
||||
|
||||
@@ -94,6 +94,8 @@ enum auth_rule_t {
|
||||
AUTH_RULE_CRL_VALIDATION,
|
||||
/** result of a OCSP validation, cert_validation_t */
|
||||
AUTH_RULE_OCSP_VALIDATION,
|
||||
/** CRL/OCSP validation is disabled, bool */
|
||||
AUTH_RULE_CERT_VALIDATION_SUSPENDED,
|
||||
/** subject is member of a group, identification_t*
|
||||
* The group membership constraint is fulfilled if the subject is member of
|
||||
* one group defined in the constraints. */
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Tobias Brunner
|
||||
* Copyright (C) 2007 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
@@ -917,6 +918,8 @@ METHOD(enumerator_t, trusted_destroy, void,
|
||||
DESTROY_IF(this->auth);
|
||||
DESTROY_IF(this->candidates);
|
||||
this->failed->destroy_offset(this->failed, offsetof(certificate_t, destroy));
|
||||
/* check for delayed certificate cache queue */
|
||||
cache_queue(this->this);
|
||||
free(this);
|
||||
}
|
||||
|
||||
@@ -985,7 +988,6 @@ METHOD(enumerator_t, public_destroy, void,
|
||||
this->wrapper->destroy(this->wrapper);
|
||||
}
|
||||
this->this->lock->unlock(this->this->lock);
|
||||
|
||||
/* check for delayed certificate cache queue */
|
||||
cache_queue(this->this);
|
||||
free(this);
|
||||
@@ -993,7 +995,7 @@ METHOD(enumerator_t, public_destroy, void,
|
||||
|
||||
METHOD(credential_manager_t, create_public_enumerator, enumerator_t*,
|
||||
private_credential_manager_t *this, key_type_t type, identification_t *id,
|
||||
auth_cfg_t *auth)
|
||||
auth_cfg_t *auth, bool online)
|
||||
{
|
||||
public_enumerator_t *enumerator;
|
||||
|
||||
@@ -1002,7 +1004,7 @@ METHOD(credential_manager_t, create_public_enumerator, enumerator_t*,
|
||||
.enumerate = (void*)_public_enumerate,
|
||||
.destroy = _public_destroy,
|
||||
},
|
||||
.inner = create_trusted_enumerator(this, type, id, TRUE),
|
||||
.inner = create_trusted_enumerator(this, type, id, online),
|
||||
.this = this,
|
||||
);
|
||||
if (auth)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Tobias Brunner
|
||||
* Copyright (C) 2007-2009 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
@@ -202,14 +203,18 @@ struct credential_manager_t {
|
||||
* where the auth config helper contains rules for constraint checks.
|
||||
* This function is very similar to create_trusted_enumerator(), but
|
||||
* gets public keys directly.
|
||||
* If online is set, revocations are checked online for the whole
|
||||
* trustchain.
|
||||
*
|
||||
* @param type type of the key to get
|
||||
* @param id owner of the key, signer of the signature
|
||||
* @param auth authentication infos
|
||||
* @param online whether revocations should be checked online
|
||||
* @return enumerator
|
||||
*/
|
||||
enumerator_t* (*create_public_enumerator)(credential_manager_t *this,
|
||||
key_type_t type, identification_t *id, auth_cfg_t *auth);
|
||||
key_type_t type, identification_t *id, auth_cfg_t *auth,
|
||||
bool online);
|
||||
|
||||
/**
|
||||
* Cache a certificate by invoking cache_cert() on all registered sets.
|
||||
|
||||
@@ -320,7 +320,8 @@ static public_key_t *find_public_key(private_tls_peer_t *this)
|
||||
if (cert)
|
||||
{
|
||||
enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
|
||||
KEY_ANY, cert->get_subject(cert), this->server_auth);
|
||||
KEY_ANY, cert->get_subject(cert),
|
||||
this->server_auth, TRUE);
|
||||
while (enumerator->enumerate(enumerator, ¤t, &auth))
|
||||
{
|
||||
found = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
|
||||
|
||||
@@ -548,7 +548,7 @@ static status_t process_cert_verify(private_tls_server_t *this,
|
||||
bio_reader_t *sig;
|
||||
|
||||
enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
|
||||
KEY_ANY, this->peer, this->peer_auth);
|
||||
KEY_ANY, this->peer, this->peer_auth, TRUE);
|
||||
while (enumerator->enumerate(enumerator, &public, &auth))
|
||||
{
|
||||
sig = bio_reader_create(reader->peek(reader));
|
||||
|
||||
@@ -24,6 +24,9 @@ openssl crl -in crl.pem -outform der -out strongswan.crl
|
||||
cp strongswan.crl ${ROOT}
|
||||
cp strongswanCert.pem ${ROOT}
|
||||
cp index.html ${ROOT}
|
||||
# revoke moon's current CERT
|
||||
pki --signcrl --cacert strongswanCert.pem --cakey strongswanKey.pem --lifetime 30 --reason key-compromise --cert newcerts/2B.pem --lastcrl strongswan.crl > strongswan_moon_revoked.crl
|
||||
cp strongswan_moon_revoked.crl ${ROOT}
|
||||
cd /etc/openssl/research
|
||||
openssl ca -gencrl -crldays 15 -config /etc/openssl/research/openssl.cnf -out crl.pem
|
||||
openssl crl -in crl.pem -outform der -out research.crl
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
This scenario tests <b>make-before-break reauthentication</b> using overlapping
|
||||
IKE_SAs by setting the <i>make_before_break</i> strongswan.conf option. The
|
||||
initiator <b>carol</b> reauthenticates the IKE_SA with host <b>moon</b> using
|
||||
<b>ikelifetime=10s</b>, but does not close the old IKE_SA before the replacement
|
||||
CHILD_SA is in place. A constant ping from <b>carol</b> to client <b>alice</b>
|
||||
hiding in the subnet behind <b>moon</b> tests if the CHILD_SA works during the
|
||||
whole procedure.
|
||||
<p/>
|
||||
Because the responder is always able to install CHILD_SAs before the initiator
|
||||
is, some traffic sent by the responder over such a CHILD_SA might get dropped by
|
||||
the initiator (until it also installed the CHILD_SA). This is particularly
|
||||
problematic if OCSP/CRL checks are delayed or if they can also be done via the
|
||||
IPsec tunnel once it's established. Therefore, online OCSP/CRL checks are
|
||||
suspended during the reauthentication and done afterwards. This is verified here
|
||||
by revoking the responder's certificate after the SA got initially established.
|
||||
@@ -0,0 +1,10 @@
|
||||
winnetou::cp /var/www/strongswan.crl /var/www/strongswan.crl.bak
|
||||
winnetou::cp /var/www/strongswan_moon_revoked.crl /var/www/strongswan.crl
|
||||
carol::ipsec purgecrls
|
||||
moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*[email protected]::YES
|
||||
carol::ipsec status 2> /dev/null::home\[1]: ESTABLISHED.*[email protected].*moon.strongswan.org::YES
|
||||
carol::sleep 6
|
||||
carol::cat /var/log/daemon.log::certificate was revoked.*key compromise::YES
|
||||
carol::cat /var/log/daemon.log::peer certificate verification failed, deleting SA::YES
|
||||
moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*[email protected]::NO
|
||||
carol::ipsec status 2> /dev/null::home\[2]: ESTABLISHED.*[email protected].*moon.strongswan.org::NO
|
||||
@@ -0,0 +1,21 @@
|
||||
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
strictcrlpolicy=yes
|
||||
|
||||
conn %default
|
||||
keylife=20m
|
||||
ikelifetime=10s
|
||||
rekeymargin=5s
|
||||
rekeyfuzz=0%
|
||||
keyingtries=1
|
||||
|
||||
conn home
|
||||
left=PH_IP_CAROL
|
||||
leftcert=carolCert.pem
|
||||
[email protected]
|
||||
right=PH_IP_MOON
|
||||
[email protected]
|
||||
rightsubnet=10.1.0.0/16
|
||||
keyexchange=ikev2
|
||||
auto=add
|
||||
@@ -0,0 +1,7 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
charon {
|
||||
load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc stroke kernel-netlink socket-default updown
|
||||
|
||||
make_before_break = yes
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
strictcrlpolicy=yes
|
||||
|
||||
conn %default
|
||||
ikelifetime=30m
|
||||
keylife=20m
|
||||
rekeymargin=0s
|
||||
keyingtries=1
|
||||
|
||||
conn rw
|
||||
left=PH_IP_MOON
|
||||
leftcert=moonCert.pem
|
||||
[email protected]
|
||||
leftsubnet=10.1.0.0/16
|
||||
right=%any
|
||||
keyexchange=ikev2
|
||||
auto=add
|
||||
@@ -0,0 +1,5 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
charon {
|
||||
load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc stroke kernel-netlink socket-default updown
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
winnetou::cp /var/www/strongswan.crl.bak /var/www/strongswan.crl
|
||||
moon::ipsec stop
|
||||
carol::ipsec stop
|
||||
@@ -0,0 +1,4 @@
|
||||
moon::ipsec start
|
||||
carol::ipsec start
|
||||
carol::expect-connection home
|
||||
carol::ipsec up home
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This configuration file provides information on the
|
||||
# guest instances used for this test
|
||||
|
||||
# All guest instances that are required for this test
|
||||
#
|
||||
VIRTHOSTS="alice moon carol winnetou"
|
||||
|
||||
# Corresponding block diagram
|
||||
#
|
||||
DIAGRAM="a-m-c-w.png"
|
||||
|
||||
# Guest instances on which tcpdump is to be started
|
||||
#
|
||||
TCPDUMPHOSTS="moon"
|
||||
|
||||
# Guest instances on which IPsec is started
|
||||
# Used for IPsec logging purposes
|
||||
#
|
||||
IPSECHOSTS="moon carol"
|
||||
Reference in New Issue
Block a user