added support for transport mode and (experimental!) BEET mode
support for the type=transport/tunnel parameter in charon
This commit is contained in:
+34
-22
@@ -167,6 +167,11 @@ struct private_child_sa_t {
|
||||
* Specifies if NAT traversal is used
|
||||
*/
|
||||
bool use_natt;
|
||||
|
||||
/**
|
||||
* mode this SA uses, tunnel/transport
|
||||
*/
|
||||
mode_t mode;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -439,7 +444,8 @@ static status_t alloc(private_child_sa_t *this, linked_list_t *proposals)
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus, bool mine)
|
||||
static status_t install(private_child_sa_t *this, proposal_t *proposal,
|
||||
mode_t mode, prf_plus_t *prf_plus, bool mine)
|
||||
{
|
||||
u_int32_t spi;
|
||||
algorithm_t *enc_algo, *int_algo;
|
||||
@@ -536,7 +542,7 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus
|
||||
mine ? this->soft_lifetime : 0,
|
||||
this->hard_lifetime,
|
||||
enc_algo, int_algo,
|
||||
prf_plus, natt, mine);
|
||||
prf_plus, natt, mode, mine);
|
||||
|
||||
this->encryption = *enc_algo;
|
||||
this->integrity = *int_algo;
|
||||
@@ -545,7 +551,8 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus
|
||||
return status;
|
||||
}
|
||||
|
||||
static status_t add(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus)
|
||||
static status_t add(private_child_sa_t *this, proposal_t *proposal,
|
||||
mode_t mode, prf_plus_t *prf_plus)
|
||||
{
|
||||
u_int32_t outbound_spi, inbound_spi;
|
||||
|
||||
@@ -560,14 +567,14 @@ static status_t add(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *
|
||||
inbound_spi = proposal->get_spi(proposal);
|
||||
|
||||
/* install inbound SAs */
|
||||
if (install(this, proposal, prf_plus, TRUE) != SUCCESS)
|
||||
if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/* install outbound SAs, restore spi*/
|
||||
proposal->set_spi(proposal, outbound_spi);
|
||||
if (install(this, proposal, prf_plus, FALSE) != SUCCESS)
|
||||
if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
@@ -576,7 +583,8 @@ static status_t add(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus)
|
||||
static status_t update(private_child_sa_t *this, proposal_t *proposal,
|
||||
mode_t mode, prf_plus_t *prf_plus)
|
||||
{
|
||||
u_int32_t inbound_spi;
|
||||
|
||||
@@ -584,7 +592,7 @@ static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_
|
||||
inbound_spi = proposal->get_spi(proposal);
|
||||
|
||||
/* install outbound SAs */
|
||||
if (install(this, proposal, prf_plus, FALSE) != SUCCESS)
|
||||
if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
@@ -592,7 +600,7 @@ static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_
|
||||
/* restore spi */
|
||||
proposal->set_spi(proposal, inbound_spi);
|
||||
/* install inbound SAs */
|
||||
if (install(this, proposal, prf_plus, TRUE) != SUCCESS)
|
||||
if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
@@ -600,7 +608,9 @@ static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list)
|
||||
static status_t add_policies(private_child_sa_t *this,
|
||||
linked_list_t *my_ts_list,
|
||||
linked_list_t *other_ts_list, mode_t mode)
|
||||
{
|
||||
iterator_t *my_iter, *other_iter;
|
||||
traffic_selector_t *my_ts, *other_ts;
|
||||
@@ -637,16 +647,16 @@ static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list
|
||||
|
||||
/* install 3 policies: out, in and forward */
|
||||
status = charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||
this->me.addr, this->other.addr, my_ts, other_ts,
|
||||
POLICY_OUT, this->protocol, this->reqid, high_prio, FALSE);
|
||||
this->me.addr, this->other.addr, my_ts, other_ts, POLICY_OUT,
|
||||
this->protocol, this->reqid, high_prio, mode, FALSE);
|
||||
|
||||
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||
this->other.addr, this->me.addr, other_ts, my_ts,
|
||||
POLICY_IN, this->protocol, this->reqid, high_prio, FALSE);
|
||||
this->other.addr, this->me.addr, other_ts, my_ts, POLICY_IN,
|
||||
this->protocol, this->reqid, high_prio, mode, FALSE);
|
||||
|
||||
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||
this->other.addr, this->me.addr, other_ts, my_ts,
|
||||
POLICY_FWD, this->protocol, this->reqid, high_prio, FALSE);
|
||||
this->other.addr, this->me.addr, other_ts, my_ts, POLICY_FWD,
|
||||
this->protocol, this->reqid, high_prio, mode, FALSE);
|
||||
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
@@ -673,7 +683,8 @@ static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list
|
||||
{
|
||||
this->state = CHILD_ROUTED;
|
||||
}
|
||||
|
||||
/* needed to update hosts */
|
||||
this->mode = mode;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -928,19 +939,19 @@ static status_t update_policy_hosts(private_child_sa_t *this, host_t *new_me, ho
|
||||
charon->kernel_interface,
|
||||
new_me, new_other,
|
||||
policy->my_ts, policy->other_ts,
|
||||
POLICY_OUT, this->protocol, this->reqid, TRUE, TRUE);
|
||||
POLICY_OUT, this->protocol, this->reqid, TRUE, this->mode, TRUE);
|
||||
|
||||
status |= charon->kernel_interface->add_policy(
|
||||
charon->kernel_interface,
|
||||
new_other, new_me,
|
||||
policy->other_ts, policy->my_ts,
|
||||
POLICY_IN, this->protocol, this->reqid, TRUE, TRUE);
|
||||
POLICY_IN, this->protocol, this->reqid, TRUE, this->mode, TRUE);
|
||||
|
||||
status |= charon->kernel_interface->add_policy(
|
||||
charon->kernel_interface,
|
||||
new_other, new_me,
|
||||
policy->other_ts, policy->my_ts,
|
||||
POLICY_FWD, this->protocol, this->reqid, TRUE, TRUE);
|
||||
POLICY_FWD, this->protocol, this->reqid, TRUE, this->mode, TRUE);
|
||||
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
@@ -1085,10 +1096,10 @@ child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other,
|
||||
this->public.get_spi = (u_int32_t(*)(child_sa_t*, bool))get_spi;
|
||||
this->public.get_protocol = (protocol_id_t(*)(child_sa_t*))get_protocol;
|
||||
this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc;
|
||||
this->public.add = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))add;
|
||||
this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update;
|
||||
this->public.add = (status_t(*)(child_sa_t*,proposal_t*,mode_t,prf_plus_t*))add;
|
||||
this->public.update = (status_t(*)(child_sa_t*,proposal_t*,mode_t,prf_plus_t*))update;
|
||||
this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,host_diff_t,host_diff_t))update_hosts;
|
||||
this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies;
|
||||
this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*,mode_t))add_policies;
|
||||
this->public.get_my_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_my_traffic_selectors;
|
||||
this->public.get_other_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_other_traffic_selectors;
|
||||
this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
|
||||
@@ -1124,6 +1135,7 @@ child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other,
|
||||
this->my_ts = linked_list_create();
|
||||
this->other_ts = linked_list_create();
|
||||
this->protocol = PROTO_NONE;
|
||||
this->mode = MODE_TUNNEL;
|
||||
this->rekeying_transaction = NULL;
|
||||
|
||||
return &this->public;
|
||||
|
||||
@@ -167,10 +167,12 @@ struct child_sa_t {
|
||||
*
|
||||
* @param this calling object
|
||||
* @param proposal proposal for which SPIs are allocated
|
||||
* @param mode mode for the CHILD_SA
|
||||
* @param prf_plus key material to use for key derivation
|
||||
* @return SUCCESS or FAILED
|
||||
*/
|
||||
status_t (*add)(child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus);
|
||||
status_t (*add)(child_sa_t *this, proposal_t *proposal, mode_t mode,
|
||||
prf_plus_t *prf_plus);
|
||||
|
||||
/**
|
||||
* @brief Install the kernel SAs for a proposal, after SPIs have been allocated.
|
||||
@@ -179,10 +181,12 @@ struct child_sa_t {
|
||||
*
|
||||
* @param this calling object
|
||||
* @param proposal proposal for which SPIs are allocated
|
||||
* @param mode mode for the CHILD_SA
|
||||
* @param prf_plus key material to use for key derivation
|
||||
* @return SUCCESS or FAILED
|
||||
*/
|
||||
status_t (*update)(child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus);
|
||||
status_t (*update)(child_sa_t *this, proposal_t *proposal, mode_t mode,
|
||||
prf_plus_t *prf_plus);
|
||||
|
||||
/**
|
||||
* @brief Update the hosts in the kernel SAs and policies
|
||||
@@ -208,11 +212,11 @@ struct child_sa_t {
|
||||
* @param this calling object
|
||||
* @param my_ts traffic selectors for local site
|
||||
* @param other_ts traffic selectors for remote site
|
||||
* @param mode mode for the SA: tunnel/transport
|
||||
* @return SUCCESS or FAILED
|
||||
*/
|
||||
status_t (*add_policies)(child_sa_t *this,
|
||||
linked_list_t *my_ts_list,
|
||||
linked_list_t *other_ts_list);
|
||||
status_t (*add_policies)(child_sa_t *this, linked_list_t *my_ts_list,
|
||||
linked_list_t *other_ts_list, mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Get the traffic selectors of added policies of local host.
|
||||
|
||||
@@ -1173,7 +1173,8 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t
|
||||
child_sa->set_name(child_sa, policy->get_name(policy));
|
||||
my_ts = policy->get_my_traffic_selectors(policy, this->my_host);
|
||||
other_ts = policy->get_other_traffic_selectors(policy, this->other_host);
|
||||
status = child_sa->add_policies(child_sa, my_ts, other_ts);
|
||||
status = child_sa->add_policies(child_sa, my_ts, other_ts,
|
||||
policy->get_mode(policy));
|
||||
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
|
||||
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
|
||||
this->child_sas->insert_last(this->child_sas, child_sa);
|
||||
|
||||
@@ -119,6 +119,11 @@ struct private_create_child_sa_t {
|
||||
*/
|
||||
child_sa_t *rekeyed_sa;
|
||||
|
||||
/**
|
||||
* mode of the CHILD_SA to create: transport/tunnel
|
||||
*/
|
||||
mode_t mode;
|
||||
|
||||
/**
|
||||
* Have we lost the simultaneous rekeying nonce compare?
|
||||
*/
|
||||
@@ -186,6 +191,31 @@ static void cancel(private_create_child_sa_t *this)
|
||||
this->lost = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a notify message.
|
||||
*/
|
||||
static void build_notify(notify_type_t type, chunk_t data, message_t *message, bool flush_message)
|
||||
{
|
||||
notify_payload_t *notify;
|
||||
|
||||
if (flush_message)
|
||||
{
|
||||
payload_t *payload;
|
||||
iterator_t *iterator = message->get_payload_iterator(message);
|
||||
while (iterator->iterate(iterator, (void**)&payload))
|
||||
{
|
||||
payload->destroy(payload);
|
||||
iterator->remove(iterator);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
}
|
||||
|
||||
notify = notify_payload_create();
|
||||
notify->set_notify_type(notify, type);
|
||||
notify->set_notification_data(notify, data);
|
||||
message->add_payload(message, (payload_t*)notify);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of transaction_t.get_request.
|
||||
*/
|
||||
@@ -293,6 +323,28 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
|
||||
request->add_payload(request, (payload_t*)sa_payload);
|
||||
}
|
||||
|
||||
/* notify for transport/BEET mode, we propose it
|
||||
* independent of the traffic selectors */
|
||||
switch (this->policy->get_mode(this->policy))
|
||||
{
|
||||
case MODE_TUNNEL:
|
||||
/* is the default */
|
||||
break;
|
||||
case MODE_TRANSPORT:
|
||||
if (this->ike_sa->is_natt_enabled(this->ike_sa))
|
||||
{
|
||||
DBG1(DBG_IKE, "not using tranport mode, as connection NATed");
|
||||
}
|
||||
else
|
||||
{
|
||||
build_notify(USE_TRANSPORT_MODE, chunk_empty, request, FALSE);
|
||||
}
|
||||
break;
|
||||
case MODE_BEET:
|
||||
build_notify(USE_BEET_MODE, chunk_empty, request, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
{ /* build the NONCE payload for us (initiator) */
|
||||
nonce_payload_t *nonce_payload;
|
||||
|
||||
@@ -374,6 +426,16 @@ static status_t process_notifys(private_create_child_sa_t *this, notify_payload_
|
||||
SIG(this->failsig, "received NO_PROPOSAL_CHOSEN notify");
|
||||
return FAILED;
|
||||
}
|
||||
case USE_TRANSPORT_MODE:
|
||||
{
|
||||
this->mode = MODE_TRANSPORT;
|
||||
return SUCCESS;
|
||||
}
|
||||
case USE_BEET_MODE:
|
||||
{
|
||||
this->mode = MODE_BEET;
|
||||
return SUCCESS;
|
||||
}
|
||||
case REKEY_SA:
|
||||
{
|
||||
u_int32_t spi;
|
||||
@@ -414,28 +476,20 @@ static status_t process_notifys(private_create_child_sa_t *this, notify_payload_
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a notify message.
|
||||
* Check a list of traffic selectors if any selector belongs to host
|
||||
*/
|
||||
static void build_notify(notify_type_t type, chunk_t data, message_t *message, bool flush_message)
|
||||
static bool ts_list_is_host(linked_list_t *list, host_t *host)
|
||||
{
|
||||
notify_payload_t *notify;
|
||||
traffic_selector_t *ts;
|
||||
bool is_host = TRUE;
|
||||
iterator_t *iterator = list->create_iterator(list, TRUE);
|
||||
|
||||
if (flush_message)
|
||||
while (is_host && iterator->iterate(iterator, (void**)&ts))
|
||||
{
|
||||
payload_t *payload;
|
||||
iterator_t *iterator = message->get_payload_iterator(message);
|
||||
while (iterator->iterate(iterator, (void**)&payload))
|
||||
{
|
||||
payload->destroy(payload);
|
||||
iterator->remove(iterator);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
is_host = is_host && ts->is_host(ts, host);
|
||||
}
|
||||
|
||||
notify = notify_payload_create();
|
||||
notify->set_notify_type(notify, type);
|
||||
notify->set_notification_data(notify, data);
|
||||
message->add_payload(message, (payload_t*)notify);
|
||||
iterator->destroy(iterator);
|
||||
return is_host;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -455,11 +509,11 @@ static status_t install_child_sa(private_create_child_sa_t *this, bool initiator
|
||||
|
||||
if (initiator)
|
||||
{
|
||||
status = this->child_sa->update(this->child_sa, this->proposal, prf_plus);
|
||||
status = this->child_sa->update(this->child_sa, this->proposal, 1, prf_plus);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = this->child_sa->add(this->child_sa, this->proposal, prf_plus);
|
||||
status = this->child_sa->add(this->child_sa, this->proposal, 1, prf_plus);
|
||||
}
|
||||
prf_plus->destroy(prf_plus);
|
||||
if (status != SUCCESS)
|
||||
@@ -468,11 +522,11 @@ static status_t install_child_sa(private_create_child_sa_t *this, bool initiator
|
||||
}
|
||||
if (initiator)
|
||||
{
|
||||
status = this->child_sa->add_policies(this->child_sa, this->tsi, this->tsr);
|
||||
status = this->child_sa->add_policies(this->child_sa, this->tsi, this->tsr, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = this->child_sa->add_policies(this->child_sa, this->tsr, this->tsi);
|
||||
status = this->child_sa->add_policies(this->child_sa, this->tsr, this->tsi, 1);
|
||||
}
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
@@ -697,6 +751,44 @@ static status_t get_response(private_create_child_sa_t *this, message_t *request
|
||||
this->policy->get_hostaccess(this->policy),
|
||||
use_natt);
|
||||
this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
|
||||
|
||||
/* check mode, and include notify into reply */
|
||||
switch (this->mode)
|
||||
{
|
||||
case MODE_TUNNEL:
|
||||
/* is the default */
|
||||
break;
|
||||
case MODE_TRANSPORT:
|
||||
if (!ts_list_is_host(this->tsi, other) ||
|
||||
!ts_list_is_host(this->tsr, me))
|
||||
{
|
||||
this->mode = MODE_TUNNEL;
|
||||
DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
|
||||
}
|
||||
else if (this->ike_sa->is_natt_enabled(this->ike_sa))
|
||||
{
|
||||
this->mode = MODE_TUNNEL;
|
||||
DBG1(DBG_IKE, "not using tranport mode, as connection NATed");
|
||||
}
|
||||
else
|
||||
{
|
||||
build_notify(USE_TRANSPORT_MODE, chunk_empty, response, FALSE);
|
||||
}
|
||||
break;
|
||||
case MODE_BEET:
|
||||
if (!ts_list_is_host(this->tsi, NULL) ||
|
||||
!ts_list_is_host(this->tsr, NULL))
|
||||
{
|
||||
this->mode = MODE_TUNNEL;
|
||||
DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
|
||||
}
|
||||
else
|
||||
{
|
||||
build_notify(USE_BEET_MODE, chunk_empty, response, FALSE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (install_child_sa(this, FALSE) != SUCCESS)
|
||||
{
|
||||
SIG(this->failsig, "installing CHILD_SA failed, sending NO_PROPOSAL_CHOSEN notify");
|
||||
@@ -855,6 +947,38 @@ static status_t conclude(private_create_child_sa_t *this, message_t *response,
|
||||
SIG(this->failsig, "CHILD_SA negotiation failed, no CHILD_SA built");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/* check mode if it is acceptable */
|
||||
switch (this->mode)
|
||||
{
|
||||
case MODE_TUNNEL:
|
||||
/* is the default */
|
||||
break;
|
||||
case MODE_TRANSPORT:
|
||||
/* TODO: we should close the CHILD_SA if negotiated
|
||||
* mode is not acceptable for us */
|
||||
if (!ts_list_is_host(this->tsi, me) ||
|
||||
!ts_list_is_host(this->tsr, other))
|
||||
{
|
||||
this->mode = MODE_TUNNEL;
|
||||
DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
|
||||
}
|
||||
else if (this->ike_sa->is_natt_enabled(this->ike_sa))
|
||||
{
|
||||
this->mode = MODE_TUNNEL;
|
||||
DBG1(DBG_IKE, "not using tranport mode, as connection NATed");
|
||||
}
|
||||
break;
|
||||
case MODE_BEET:
|
||||
if (!ts_list_is_host(this->tsi, NULL) ||
|
||||
!ts_list_is_host(this->tsr, NULL))
|
||||
{
|
||||
this->mode = MODE_TUNNEL;
|
||||
DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
new_child = this->child_sa;
|
||||
if (install_child_sa(this, TRUE) != SUCCESS)
|
||||
{
|
||||
@@ -985,6 +1109,7 @@ create_child_sa_t *create_child_sa_create(ike_sa_t *ike_sa)
|
||||
this->policy = NULL;
|
||||
this->tsi = NULL;
|
||||
this->tsr = NULL;
|
||||
this->mode = MODE_TUNNEL;
|
||||
this->randomizer = randomizer_create();
|
||||
this->failsig = CHILD_UP_FAILED;
|
||||
|
||||
|
||||
@@ -128,6 +128,11 @@ struct private_ike_auth_t {
|
||||
* reqid to use for CHILD_SA setup
|
||||
*/
|
||||
u_int32_t reqid;
|
||||
|
||||
/**
|
||||
* mode the CHILD_SA uses: tranport, tunnel, BEET
|
||||
*/
|
||||
mode_t mode;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -182,6 +187,30 @@ static void set_init_messages(private_ike_auth_t *this, chunk_t init_request, ch
|
||||
this->init_response = init_response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a notify message.
|
||||
*/
|
||||
static void build_notify(notify_type_t type, message_t *message, bool flush_message)
|
||||
{
|
||||
notify_payload_t *notify;
|
||||
|
||||
if (flush_message)
|
||||
{
|
||||
payload_t *payload;
|
||||
iterator_t *iterator = message->get_payload_iterator(message);
|
||||
while (iterator->iterate(iterator, (void**)&payload))
|
||||
{
|
||||
payload->destroy(payload);
|
||||
iterator->remove(iterator);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
}
|
||||
|
||||
notify = notify_payload_create();
|
||||
notify->set_notify_type(notify, type);
|
||||
message->add_payload(message, (payload_t*)notify);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of transaction_t.get_request.
|
||||
*/
|
||||
@@ -319,6 +348,28 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
|
||||
request->add_payload(request, (payload_t*)sa_payload);
|
||||
}
|
||||
|
||||
/* notify for transport/BEET mode, we propose it
|
||||
* independent of the traffic selectors */
|
||||
switch (this->policy->get_mode(this->policy))
|
||||
{
|
||||
case MODE_TUNNEL:
|
||||
/* is the default */
|
||||
break;
|
||||
case MODE_TRANSPORT:
|
||||
if (this->ike_sa->is_natt_enabled(this->ike_sa))
|
||||
{
|
||||
DBG1(DBG_IKE, "not using tranport mode, as connection NATed");
|
||||
}
|
||||
else
|
||||
{
|
||||
build_notify(USE_TRANSPORT_MODE, request, FALSE);
|
||||
}
|
||||
break;
|
||||
case MODE_BEET:
|
||||
build_notify(USE_BEET_MODE, request, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
{ /* build TSi payload */
|
||||
linked_list_t *ts_list;
|
||||
ts_payload_t *ts_payload;
|
||||
@@ -376,6 +427,16 @@ static status_t process_notifies(private_ike_auth_t *this, notify_payload_t *not
|
||||
this->build_child = FALSE;
|
||||
return SUCCESS;
|
||||
}
|
||||
case USE_TRANSPORT_MODE:
|
||||
{
|
||||
this->mode = MODE_TRANSPORT;
|
||||
return SUCCESS;
|
||||
}
|
||||
case USE_BEET_MODE:
|
||||
{
|
||||
this->mode = MODE_BEET;
|
||||
return SUCCESS;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (notify_type < 16383)
|
||||
@@ -394,30 +455,6 @@ static status_t process_notifies(private_ike_auth_t *this, notify_payload_t *not
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a notify message.
|
||||
*/
|
||||
static void build_notify(notify_type_t type, message_t *message, bool flush_message)
|
||||
{
|
||||
notify_payload_t *notify;
|
||||
|
||||
if (flush_message)
|
||||
{
|
||||
payload_t *payload;
|
||||
iterator_t *iterator = message->get_payload_iterator(message);
|
||||
while (iterator->iterate(iterator, (void**)&payload))
|
||||
{
|
||||
payload->destroy(payload);
|
||||
iterator->remove(iterator);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
}
|
||||
|
||||
notify = notify_payload_create();
|
||||
notify->set_notify_type(notify, type);
|
||||
message->add_payload(message, (payload_t*)notify);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import certificate requests from a certreq payload
|
||||
*/
|
||||
@@ -501,6 +538,23 @@ static void import_certificate(cert_payload_t *cert_payload)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a list of traffic selectors if any selector belongs to host
|
||||
*/
|
||||
static bool ts_list_is_host(linked_list_t *list, host_t *host)
|
||||
{
|
||||
traffic_selector_t *ts;
|
||||
bool is_host = TRUE;
|
||||
iterator_t *iterator = list->create_iterator(list, TRUE);
|
||||
|
||||
while (is_host && iterator->iterate(iterator, (void**)&ts))
|
||||
{
|
||||
is_host = is_host && ts->is_host(ts, host);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return is_host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install a CHILD_SA for usage
|
||||
*/
|
||||
@@ -518,11 +572,13 @@ static status_t install_child_sa(private_ike_auth_t *this, bool initiator)
|
||||
|
||||
if (initiator)
|
||||
{
|
||||
status = this->child_sa->update(this->child_sa, this->proposal, prf_plus);
|
||||
status = this->child_sa->update(this->child_sa, this->proposal,
|
||||
this->mode, prf_plus);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = this->child_sa->add(this->child_sa, this->proposal, prf_plus);
|
||||
status = this->child_sa->add(this->child_sa, this->proposal,
|
||||
this->mode, prf_plus);
|
||||
}
|
||||
prf_plus->destroy(prf_plus);
|
||||
if (status != SUCCESS)
|
||||
@@ -531,11 +587,13 @@ static status_t install_child_sa(private_ike_auth_t *this, bool initiator)
|
||||
}
|
||||
if (initiator)
|
||||
{
|
||||
status = this->child_sa->add_policies(this->child_sa, this->tsi, this->tsr);
|
||||
status = this->child_sa->add_policies(this->child_sa, this->tsi,
|
||||
this->tsr, this->mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = this->child_sa->add_policies(this->child_sa, this->tsr, this->tsi);
|
||||
status = this->child_sa->add_policies(this->child_sa, this->tsr,
|
||||
this->tsi, this->mode);
|
||||
}
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
@@ -850,6 +908,44 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
|
||||
this->policy->get_hostaccess(this->policy),
|
||||
use_natt);
|
||||
this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
|
||||
|
||||
/* check mode, and include notify into reply */
|
||||
switch (this->mode)
|
||||
{
|
||||
case MODE_TUNNEL:
|
||||
/* is the default */
|
||||
break;
|
||||
case MODE_TRANSPORT:
|
||||
if (!ts_list_is_host(this->tsi, other) ||
|
||||
!ts_list_is_host(this->tsr, me))
|
||||
{
|
||||
this->mode = MODE_TUNNEL;
|
||||
DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
|
||||
}
|
||||
else if (this->ike_sa->is_natt_enabled(this->ike_sa))
|
||||
{
|
||||
this->mode = MODE_TUNNEL;
|
||||
DBG1(DBG_IKE, "not using tranport mode, as connection NATed");
|
||||
}
|
||||
else
|
||||
{
|
||||
build_notify(USE_TRANSPORT_MODE, response, FALSE);
|
||||
}
|
||||
break;
|
||||
case MODE_BEET:
|
||||
if (!ts_list_is_host(this->tsi, NULL) ||
|
||||
!ts_list_is_host(this->tsr, NULL))
|
||||
{
|
||||
this->mode = MODE_TUNNEL;
|
||||
DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
|
||||
}
|
||||
else
|
||||
{
|
||||
build_notify(USE_BEET_MODE, response, FALSE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (install_child_sa(this, FALSE) != SUCCESS)
|
||||
{
|
||||
SIG(CHILD_UP_FAILED, "installing CHILD_SA failed, no CHILD_SA created");
|
||||
@@ -1048,6 +1144,37 @@ static status_t conclude(private_ike_auth_t *this, message_t *response,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* check mode if it is acceptable */
|
||||
switch (this->mode)
|
||||
{
|
||||
case MODE_TUNNEL:
|
||||
/* is the default */
|
||||
break;
|
||||
case MODE_TRANSPORT:
|
||||
/* TODO: we should close the CHILD_SA if negotiated
|
||||
* mode is not acceptable for us */
|
||||
if (!ts_list_is_host(this->tsi, me) ||
|
||||
!ts_list_is_host(this->tsr, other))
|
||||
{
|
||||
this->mode = MODE_TUNNEL;
|
||||
DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
|
||||
}
|
||||
else if (this->ike_sa->is_natt_enabled(this->ike_sa))
|
||||
{
|
||||
this->mode = MODE_TUNNEL;
|
||||
DBG1(DBG_IKE, "not using tranport mode, as connection NATed");
|
||||
}
|
||||
break;
|
||||
case MODE_BEET:
|
||||
if (!ts_list_is_host(this->tsi, NULL) ||
|
||||
!ts_list_is_host(this->tsr, NULL))
|
||||
{
|
||||
this->mode = MODE_TUNNEL;
|
||||
DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (install_child_sa(this, TRUE) != SUCCESS)
|
||||
{
|
||||
SIG(CHILD_UP_FAILED, "installing CHILD_SA failed, no CHILD_SA built");
|
||||
@@ -1126,6 +1253,7 @@ ike_auth_t *ike_auth_create(ike_sa_t *ike_sa)
|
||||
this->tsr = NULL;
|
||||
this->build_child = TRUE;
|
||||
this->reqid = 0;
|
||||
this->mode = MODE_TUNNEL;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user