Added a hook to narrow traffic selectors for CHILD_SAs
This commit is contained in:
parent
88fa56b1ad
commit
be715344c2
|
@ -640,6 +640,38 @@ METHOD(bus_t, authorize, bool,
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(bus_t, narrow, void,
|
||||||
|
private_bus_t *this, child_sa_t *child_sa, narrow_hook_t type,
|
||||||
|
linked_list_t *local, linked_list_t *remote)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
ike_sa_t *ike_sa;
|
||||||
|
entry_t *entry;
|
||||||
|
bool keep;
|
||||||
|
|
||||||
|
ike_sa = this->thread_sa->get(this->thread_sa);
|
||||||
|
|
||||||
|
this->mutex->lock(this->mutex);
|
||||||
|
enumerator = this->listeners->create_enumerator(this->listeners);
|
||||||
|
while (enumerator->enumerate(enumerator, &entry))
|
||||||
|
{
|
||||||
|
if (entry->calling || !entry->listener->narrow)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
entry->calling++;
|
||||||
|
keep = entry->listener->narrow(entry->listener, ike_sa, child_sa,
|
||||||
|
type, local, remote);
|
||||||
|
entry->calling--;
|
||||||
|
if (!keep)
|
||||||
|
{
|
||||||
|
unregister_listener(this, entry, enumerator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
this->mutex->unlock(this->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(bus_t, destroy, void,
|
METHOD(bus_t, destroy, void,
|
||||||
private_bus_t *this)
|
private_bus_t *this)
|
||||||
{
|
{
|
||||||
|
@ -676,6 +708,7 @@ bus_t *bus_create()
|
||||||
.child_updown = _child_updown,
|
.child_updown = _child_updown,
|
||||||
.child_rekey = _child_rekey,
|
.child_rekey = _child_rekey,
|
||||||
.authorize = _authorize,
|
.authorize = _authorize,
|
||||||
|
.narrow = _narrow,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.listeners = linked_list_create(),
|
.listeners = linked_list_create(),
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#define BUS_H_
|
#define BUS_H_
|
||||||
|
|
||||||
typedef enum alert_t alert_t;
|
typedef enum alert_t alert_t;
|
||||||
|
typedef enum narrow_hook_t narrow_hook_t;
|
||||||
typedef struct bus_t bus_t;
|
typedef struct bus_t bus_t;
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -85,6 +86,31 @@ enum alert_t {
|
||||||
ALERT_SHUTDOWN_SIGNAL,
|
ALERT_SHUTDOWN_SIGNAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kind of narrow hook.
|
||||||
|
*
|
||||||
|
* There is a non-authenticated (IKE_AUTH) and a authenticated
|
||||||
|
* (CREATE_CHILD_SA) narrowing hook for the initiator. Only one of these
|
||||||
|
* hooks is invoked before the exchange.
|
||||||
|
* To verify the traffic selectors negotiated, each PRE hook has a POST
|
||||||
|
* counterpart that follows. POST hooks are invoked with an authenticated peer.
|
||||||
|
* It is usually not a good idea to narrow in the POST hooks,
|
||||||
|
* as the resulting traffic selector is not negotiated and results
|
||||||
|
* in non-matching policies.
|
||||||
|
*/
|
||||||
|
enum narrow_hook_t {
|
||||||
|
/** invoked as initiator before exchange, peer is not yet authenticated */
|
||||||
|
NARROW_INITIATOR_PRE_NOAUTH,
|
||||||
|
/** invoked as initiator before exchange, peer is authenticated */
|
||||||
|
NARROW_INITIATOR_PRE_AUTH,
|
||||||
|
/** invoked as responder during exchange, peer is authenticated */
|
||||||
|
NARROW_RESPONDER,
|
||||||
|
/** invoked as initiator after exchange, follows a INITIATOR_PRE_NOAUTH */
|
||||||
|
NARROW_INITIATOR_POST_NOAUTH,
|
||||||
|
/** invoked as initiator after exchange, follows a INITIATOR_PRE_AUTH */
|
||||||
|
NARROW_INITIATOR_POST_AUTH,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The bus receives events and sends them to all registered listeners.
|
* The bus receives events and sends them to all registered listeners.
|
||||||
*
|
*
|
||||||
|
@ -216,6 +242,17 @@ struct bus_t {
|
||||||
*/
|
*/
|
||||||
bool (*authorize)(bus_t *this, bool final);
|
bool (*authorize)(bus_t *this, bool final);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CHILD_SA traffic selector narrowing hook.
|
||||||
|
*
|
||||||
|
* @param child_sa CHILD_SA set up with these traffic selectors
|
||||||
|
* @param type type of hook getting invoked
|
||||||
|
* @param local list of local traffic selectors to narrow
|
||||||
|
* @param remote list of remote traffic selectors to narrow
|
||||||
|
*/
|
||||||
|
void (*narrow)(bus_t *this, child_sa_t *child_sa, narrow_hook_t type,
|
||||||
|
linked_list_t *local, linked_list_t *remote);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IKE_SA keymat hook.
|
* IKE_SA keymat hook.
|
||||||
*
|
*
|
||||||
|
|
|
@ -173,6 +173,21 @@ struct listener_t {
|
||||||
*/
|
*/
|
||||||
bool (*authorize)(listener_t *this, ike_sa_t *ike_sa,
|
bool (*authorize)(listener_t *this, ike_sa_t *ike_sa,
|
||||||
bool final, bool *success);
|
bool final, bool *success);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CHILD_SA traffic selector narrowing hook.
|
||||||
|
*
|
||||||
|
* This hook is invoked for each CHILD_SA and allows plugins to modify
|
||||||
|
* the traffic selector list negotiated for this CHILD_SA.
|
||||||
|
*
|
||||||
|
* @param ike_sa IKE_SA the created CHILD_SA is created in
|
||||||
|
* @param child_sa CHILD_SA set up with these traffic selectors
|
||||||
|
* @param type type of hook getting invoked
|
||||||
|
* @param local list of local traffic selectors to narrow
|
||||||
|
* @param remote list of remote traffic selectors to narrow
|
||||||
|
*/
|
||||||
|
bool (*narrow)(listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
|
||||||
|
narrow_hook_t type, linked_list_t *local, linked_list_t *remote);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /** LISTENER_H_ @}*/
|
#endif /** LISTENER_H_ @}*/
|
||||||
|
|
|
@ -273,7 +273,8 @@ static void schedule_inactivity_timeout(private_child_create_t *this)
|
||||||
* - INVALID_ARG: diffie hellman group inacceptable
|
* - INVALID_ARG: diffie hellman group inacceptable
|
||||||
* - NOT_FOUND: TS inacceptable
|
* - NOT_FOUND: TS inacceptable
|
||||||
*/
|
*/
|
||||||
static status_t select_and_install(private_child_create_t *this, bool no_dh)
|
static status_t select_and_install(private_child_create_t *this,
|
||||||
|
bool no_dh, bool ike_auth)
|
||||||
{
|
{
|
||||||
status_t status, status_i, status_o;
|
status_t status, status_i, status_o;
|
||||||
chunk_t nonce_i, nonce_r;
|
chunk_t nonce_i, nonce_r;
|
||||||
|
@ -364,6 +365,25 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
|
||||||
other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
|
other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
|
||||||
other_vip);
|
other_vip);
|
||||||
|
|
||||||
|
if (this->initiator)
|
||||||
|
{
|
||||||
|
if (ike_auth)
|
||||||
|
{
|
||||||
|
charon->bus->narrow(charon->bus, this->child_sa,
|
||||||
|
NARROW_INITIATOR_POST_NOAUTH, my_ts, other_ts);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
charon->bus->narrow(charon->bus, this->child_sa,
|
||||||
|
NARROW_INITIATOR_POST_AUTH, my_ts, other_ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
charon->bus->narrow(charon->bus, this->child_sa,
|
||||||
|
NARROW_RESPONDER, my_ts, other_ts);
|
||||||
|
}
|
||||||
|
|
||||||
if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
|
if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
|
||||||
{
|
{
|
||||||
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
|
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
|
||||||
|
@ -848,6 +868,17 @@ static status_t build_i(private_child_create_t *this, message_t *message)
|
||||||
add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
|
add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message->get_exchange_type(message) == IKE_AUTH)
|
||||||
|
{
|
||||||
|
charon->bus->narrow(charon->bus, this->child_sa,
|
||||||
|
NARROW_INITIATOR_PRE_NOAUTH, this->tsi, this->tsr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
charon->bus->narrow(charon->bus, this->child_sa,
|
||||||
|
NARROW_INITIATOR_PRE_AUTH, this->tsi, this->tsr);
|
||||||
|
}
|
||||||
|
|
||||||
build_payloads(this, message);
|
build_payloads(this, message);
|
||||||
|
|
||||||
this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
|
this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
|
||||||
|
@ -914,7 +945,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
|
||||||
peer_cfg_t *peer_cfg;
|
peer_cfg_t *peer_cfg;
|
||||||
payload_t *payload;
|
payload_t *payload;
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
bool no_dh = TRUE;
|
bool no_dh = TRUE, ike_auth = FALSE;
|
||||||
|
|
||||||
switch (message->get_exchange_type(message))
|
switch (message->get_exchange_type(message))
|
||||||
{
|
{
|
||||||
|
@ -934,6 +965,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
|
||||||
{ /* wait until all authentication round completed */
|
{ /* wait until all authentication round completed */
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
ike_auth = TRUE;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1016,7 +1048,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (select_and_install(this, no_dh))
|
switch (select_and_install(this, no_dh, ike_auth))
|
||||||
{
|
{
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
break;
|
break;
|
||||||
|
@ -1064,7 +1096,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
payload_t *payload;
|
payload_t *payload;
|
||||||
bool no_dh = TRUE;
|
bool no_dh = TRUE, ike_auth = FALSE;
|
||||||
|
|
||||||
switch (message->get_exchange_type(message))
|
switch (message->get_exchange_type(message))
|
||||||
{
|
{
|
||||||
|
@ -1079,6 +1111,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
|
||||||
{ /* wait until all authentication round completed */
|
{ /* wait until all authentication round completed */
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
ike_auth = TRUE;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1159,7 +1192,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (select_and_install(this, no_dh) == SUCCESS)
|
if (select_and_install(this, no_dh, ike_auth) == SUCCESS)
|
||||||
{
|
{
|
||||||
DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
|
DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
|
||||||
"with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
|
"with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
|
||||||
|
|
Loading…
Reference in New Issue