mirror of
https://github.com/strongswan/strongswan.git
synced 2025-10-07 00:01:49 -04:00
added support for transport mode and (experimental!) BEET mode
support for the type=transport/tunnel parameter in charon
This commit is contained in:
parent
38ab8048f5
commit
7652be891c
@ -130,6 +130,11 @@ struct private_policy_t {
|
|||||||
* What to do with an SA when other peer seams to be dead?
|
* What to do with an SA when other peer seams to be dead?
|
||||||
*/
|
*/
|
||||||
bool dpd_action;
|
bool dpd_action;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mode to propose for a initiated CHILD: tunnel/transport
|
||||||
|
*/
|
||||||
|
mode_t mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -378,7 +383,6 @@ static dpd_action_t get_dpd_action(private_policy_t *this)
|
|||||||
return this->dpd_action;
|
return this->dpd_action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of policy_t.add_my_traffic_selector
|
* Implementation of policy_t.add_my_traffic_selector
|
||||||
*/
|
*/
|
||||||
@ -423,6 +427,14 @@ static u_int32_t get_hard_lifetime(private_policy_t *this)
|
|||||||
return this->hard_lifetime;
|
return this->hard_lifetime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of policy_t.get_mode.
|
||||||
|
*/
|
||||||
|
static mode_t get_mode(private_policy_t *this)
|
||||||
|
{
|
||||||
|
return this->mode;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements policy_t.get_ref.
|
* Implements policy_t.get_ref.
|
||||||
*/
|
*/
|
||||||
@ -475,7 +487,7 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o
|
|||||||
auth_method_t auth_method,
|
auth_method_t auth_method,
|
||||||
u_int32_t hard_lifetime, u_int32_t soft_lifetime,
|
u_int32_t hard_lifetime, u_int32_t soft_lifetime,
|
||||||
u_int32_t jitter, char *updown, bool hostaccess,
|
u_int32_t jitter, char *updown, bool hostaccess,
|
||||||
dpd_action_t dpd_action)
|
mode_t mode, dpd_action_t dpd_action)
|
||||||
{
|
{
|
||||||
private_policy_t *this = malloc_thing(private_policy_t);
|
private_policy_t *this = malloc_thing(private_policy_t);
|
||||||
|
|
||||||
@ -501,6 +513,7 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o
|
|||||||
this->public.get_dpd_action = (dpd_action_t (*) (policy_t*))get_dpd_action;
|
this->public.get_dpd_action = (dpd_action_t (*) (policy_t*))get_dpd_action;
|
||||||
this->public.get_soft_lifetime = (u_int32_t (*) (policy_t *))get_soft_lifetime;
|
this->public.get_soft_lifetime = (u_int32_t (*) (policy_t *))get_soft_lifetime;
|
||||||
this->public.get_hard_lifetime = (u_int32_t (*) (policy_t *))get_hard_lifetime;
|
this->public.get_hard_lifetime = (u_int32_t (*) (policy_t *))get_hard_lifetime;
|
||||||
|
this->public.get_mode = (mode_t (*) (policy_t *))get_mode;
|
||||||
this->public.get_ref = (void (*) (policy_t*))get_ref;
|
this->public.get_ref = (void (*) (policy_t*))get_ref;
|
||||||
this->public.destroy = (void (*) (policy_t*))destroy;
|
this->public.destroy = (void (*) (policy_t*))destroy;
|
||||||
|
|
||||||
@ -515,6 +528,7 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o
|
|||||||
this->updown = (updown == NULL) ? NULL : strdup(updown);
|
this->updown = (updown == NULL) ? NULL : strdup(updown);
|
||||||
this->hostaccess = hostaccess;
|
this->hostaccess = hostaccess;
|
||||||
this->dpd_action = dpd_action;
|
this->dpd_action = dpd_action;
|
||||||
|
this->mode = mode;
|
||||||
|
|
||||||
/* initialize private members*/
|
/* initialize private members*/
|
||||||
this->refcount = 1;
|
this->refcount = 1;
|
||||||
|
@ -52,6 +52,22 @@ enum dpd_action_t {
|
|||||||
DPD_RESTART,
|
DPD_RESTART,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mode of an IPsec SA.
|
||||||
|
*
|
||||||
|
* These are equal to those defined in XFRM, so don't change.
|
||||||
|
*
|
||||||
|
* @ingroup config
|
||||||
|
*/
|
||||||
|
enum mode_t {
|
||||||
|
/** transport mode, no inner address */
|
||||||
|
MODE_TRANSPORT = 0,
|
||||||
|
/** tunnel mode, inner and outer addresses */
|
||||||
|
MODE_TUNNEL = 1,
|
||||||
|
/** BEET mode, tunnel mode but fixed, bound inner addresses */
|
||||||
|
MODE_BEET = 4,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum names for dpd_action_t.
|
* enum names for dpd_action_t.
|
||||||
*/
|
*/
|
||||||
@ -290,6 +306,14 @@ struct policy_t {
|
|||||||
*/
|
*/
|
||||||
u_int32_t (*get_hard_lifetime) (policy_t *this);
|
u_int32_t (*get_hard_lifetime) (policy_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the mode to use for the CHILD_SA, tunnel, transport or BEET.
|
||||||
|
*
|
||||||
|
* @param this policy
|
||||||
|
* @return lifetime in seconds
|
||||||
|
*/
|
||||||
|
mode_t (*get_mode) (policy_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get a new reference.
|
* @brief Get a new reference.
|
||||||
*
|
*
|
||||||
@ -334,6 +358,7 @@ struct policy_t {
|
|||||||
* @param jitter range of randomization time
|
* @param jitter range of randomization time
|
||||||
* @param updown updown script to execute on up/down event
|
* @param updown updown script to execute on up/down event
|
||||||
* @param hostaccess allow access to the host itself (used by the updown script)
|
* @param hostaccess allow access to the host itself (used by the updown script)
|
||||||
|
* @param mode mode to propose for CHILD_SA, transport, tunnel or BEET
|
||||||
* @param dpd_action what to to with a CHILD_SA when other peer does not respond
|
* @param dpd_action what to to with a CHILD_SA when other peer does not respond
|
||||||
* @return policy_t object
|
* @return policy_t object
|
||||||
*
|
*
|
||||||
@ -343,8 +368,7 @@ policy_t *policy_create(char *name,
|
|||||||
identification_t *my_id, identification_t *other_id,
|
identification_t *my_id, identification_t *other_id,
|
||||||
auth_method_t auth_method,
|
auth_method_t auth_method,
|
||||||
u_int32_t hard_lifetime, u_int32_t soft_lifetime,
|
u_int32_t hard_lifetime, u_int32_t soft_lifetime,
|
||||||
u_int32_t jitter,
|
u_int32_t jitter, char *updown, bool hostaccess,
|
||||||
char *updown, bool hostaccess,
|
mode_t mode, dpd_action_t dpd_action);
|
||||||
dpd_action_t dpd_action);
|
|
||||||
|
|
||||||
#endif /* POLICY_H_ */
|
#endif /* POLICY_H_ */
|
||||||
|
@ -447,15 +447,27 @@ static u_int8_t get_protocol(private_traffic_selector_t *this)
|
|||||||
*/
|
*/
|
||||||
static bool is_host(private_traffic_selector_t *this, host_t *host)
|
static bool is_host(private_traffic_selector_t *this, host_t *host)
|
||||||
{
|
{
|
||||||
chunk_t addr;
|
if (host)
|
||||||
int family = host->get_family(host);
|
|
||||||
|
|
||||||
if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
|
|
||||||
(family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
|
|
||||||
{
|
{
|
||||||
addr = host->get_address(host);
|
chunk_t addr;
|
||||||
if (memeq(addr.ptr, this->from, addr.len) &&
|
int family = host->get_family(host);
|
||||||
memeq(addr.ptr, this->to, addr.len))
|
|
||||||
|
if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
|
||||||
|
(family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
|
||||||
|
{
|
||||||
|
addr = host->get_address(host);
|
||||||
|
if (memeq(addr.ptr, this->from, addr.len) &&
|
||||||
|
memeq(addr.ptr, this->to, addr.len))
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t length = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
|
||||||
|
|
||||||
|
if (memeq(this->from, this->to, length))
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -164,6 +164,8 @@ struct traffic_selector_t {
|
|||||||
* Traffic selector may describe the end of *-to-host tunnel. In this
|
* Traffic selector may describe the end of *-to-host tunnel. In this
|
||||||
* case, the address range is a single address equal to the hosts
|
* case, the address range is a single address equal to the hosts
|
||||||
* peer address.
|
* peer address.
|
||||||
|
* If host is NULL, the traffic selector is checked if it is a single host,
|
||||||
|
* but not a specific one.
|
||||||
*
|
*
|
||||||
* @param this calling obect
|
* @param this calling obect
|
||||||
* @param host host_t specifying the address range
|
* @param host host_t specifying the address range
|
||||||
|
@ -88,6 +88,8 @@ enum notify_type_t {
|
|||||||
NO_NATS_ALLOWED = 16402,
|
NO_NATS_ALLOWED = 16402,
|
||||||
/* repeated authentication extension, RFC4478 */
|
/* repeated authentication extension, RFC4478 */
|
||||||
AUTH_LIFETIME = 16403,
|
AUTH_LIFETIME = 16403,
|
||||||
|
/* BEET mode, not even a draft yet. private use */
|
||||||
|
USE_BEET_MODE = 40960,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,7 +99,6 @@ enum notify_type_t {
|
|||||||
*/
|
*/
|
||||||
extern enum_name_t *notify_type_names;
|
extern enum_name_t *notify_type_names;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class representing an IKEv2-Notify Payload.
|
* @brief Class representing an IKEv2-Notify Payload.
|
||||||
*
|
*
|
||||||
|
@ -167,6 +167,11 @@ struct private_child_sa_t {
|
|||||||
* Specifies if NAT traversal is used
|
* Specifies if NAT traversal is used
|
||||||
*/
|
*/
|
||||||
bool use_natt;
|
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;
|
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;
|
u_int32_t spi;
|
||||||
algorithm_t *enc_algo, *int_algo;
|
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,
|
mine ? this->soft_lifetime : 0,
|
||||||
this->hard_lifetime,
|
this->hard_lifetime,
|
||||||
enc_algo, int_algo,
|
enc_algo, int_algo,
|
||||||
prf_plus, natt, mine);
|
prf_plus, natt, mode, mine);
|
||||||
|
|
||||||
this->encryption = *enc_algo;
|
this->encryption = *enc_algo;
|
||||||
this->integrity = *int_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;
|
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;
|
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);
|
inbound_spi = proposal->get_spi(proposal);
|
||||||
|
|
||||||
/* install inbound SAs */
|
/* install inbound SAs */
|
||||||
if (install(this, proposal, prf_plus, TRUE) != SUCCESS)
|
if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS)
|
||||||
{
|
{
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* install outbound SAs, restore spi*/
|
/* install outbound SAs, restore spi*/
|
||||||
proposal->set_spi(proposal, outbound_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;
|
return FAILED;
|
||||||
}
|
}
|
||||||
@ -576,7 +583,8 @@ static status_t add(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *
|
|||||||
return SUCCESS;
|
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;
|
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);
|
inbound_spi = proposal->get_spi(proposal);
|
||||||
|
|
||||||
/* install outbound SAs */
|
/* install outbound SAs */
|
||||||
if (install(this, proposal, prf_plus, FALSE) != SUCCESS)
|
if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS)
|
||||||
{
|
{
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
@ -592,7 +600,7 @@ static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_
|
|||||||
/* restore spi */
|
/* restore spi */
|
||||||
proposal->set_spi(proposal, inbound_spi);
|
proposal->set_spi(proposal, inbound_spi);
|
||||||
/* install inbound SAs */
|
/* install inbound SAs */
|
||||||
if (install(this, proposal, prf_plus, TRUE) != SUCCESS)
|
if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS)
|
||||||
{
|
{
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
@ -600,7 +608,9 @@ static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_
|
|||||||
return SUCCESS;
|
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;
|
iterator_t *my_iter, *other_iter;
|
||||||
traffic_selector_t *my_ts, *other_ts;
|
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 */
|
/* install 3 policies: out, in and forward */
|
||||||
status = charon->kernel_interface->add_policy(charon->kernel_interface,
|
status = charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||||
this->me.addr, this->other.addr, my_ts, other_ts,
|
this->me.addr, this->other.addr, my_ts, other_ts, POLICY_OUT,
|
||||||
POLICY_OUT, this->protocol, this->reqid, high_prio, FALSE);
|
this->protocol, this->reqid, high_prio, mode, FALSE);
|
||||||
|
|
||||||
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
|
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||||
this->other.addr, this->me.addr, other_ts, my_ts,
|
this->other.addr, this->me.addr, other_ts, my_ts, POLICY_IN,
|
||||||
POLICY_IN, this->protocol, this->reqid, high_prio, FALSE);
|
this->protocol, this->reqid, high_prio, mode, FALSE);
|
||||||
|
|
||||||
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
|
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||||
this->other.addr, this->me.addr, other_ts, my_ts,
|
this->other.addr, this->me.addr, other_ts, my_ts, POLICY_FWD,
|
||||||
POLICY_FWD, this->protocol, this->reqid, high_prio, FALSE);
|
this->protocol, this->reqid, high_prio, mode, FALSE);
|
||||||
|
|
||||||
if (status != SUCCESS)
|
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;
|
this->state = CHILD_ROUTED;
|
||||||
}
|
}
|
||||||
|
/* needed to update hosts */
|
||||||
|
this->mode = mode;
|
||||||
return SUCCESS;
|
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,
|
charon->kernel_interface,
|
||||||
new_me, new_other,
|
new_me, new_other,
|
||||||
policy->my_ts, policy->other_ts,
|
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(
|
status |= charon->kernel_interface->add_policy(
|
||||||
charon->kernel_interface,
|
charon->kernel_interface,
|
||||||
new_other, new_me,
|
new_other, new_me,
|
||||||
policy->other_ts, policy->my_ts,
|
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(
|
status |= charon->kernel_interface->add_policy(
|
||||||
charon->kernel_interface,
|
charon->kernel_interface,
|
||||||
new_other, new_me,
|
new_other, new_me,
|
||||||
policy->other_ts, policy->my_ts,
|
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)
|
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_spi = (u_int32_t(*)(child_sa_t*, bool))get_spi;
|
||||||
this->public.get_protocol = (protocol_id_t(*)(child_sa_t*))get_protocol;
|
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.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.add = (status_t(*)(child_sa_t*,proposal_t*,mode_t,prf_plus_t*))add;
|
||||||
this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update;
|
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.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_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_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;
|
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->my_ts = linked_list_create();
|
||||||
this->other_ts = linked_list_create();
|
this->other_ts = linked_list_create();
|
||||||
this->protocol = PROTO_NONE;
|
this->protocol = PROTO_NONE;
|
||||||
|
this->mode = MODE_TUNNEL;
|
||||||
this->rekeying_transaction = NULL;
|
this->rekeying_transaction = NULL;
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
|
@ -167,10 +167,12 @@ struct child_sa_t {
|
|||||||
*
|
*
|
||||||
* @param this calling object
|
* @param this calling object
|
||||||
* @param proposal proposal for which SPIs are allocated
|
* @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
|
* @param prf_plus key material to use for key derivation
|
||||||
* @return SUCCESS or FAILED
|
* @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.
|
* @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 this calling object
|
||||||
* @param proposal proposal for which SPIs are allocated
|
* @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
|
* @param prf_plus key material to use for key derivation
|
||||||
* @return SUCCESS or FAILED
|
* @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
|
* @brief Update the hosts in the kernel SAs and policies
|
||||||
@ -208,11 +212,11 @@ struct child_sa_t {
|
|||||||
* @param this calling object
|
* @param this calling object
|
||||||
* @param my_ts traffic selectors for local site
|
* @param my_ts traffic selectors for local site
|
||||||
* @param other_ts traffic selectors for remote site
|
* @param other_ts traffic selectors for remote site
|
||||||
|
* @param mode mode for the SA: tunnel/transport
|
||||||
* @return SUCCESS or FAILED
|
* @return SUCCESS or FAILED
|
||||||
*/
|
*/
|
||||||
status_t (*add_policies)(child_sa_t *this,
|
status_t (*add_policies)(child_sa_t *this, linked_list_t *my_ts_list,
|
||||||
linked_list_t *my_ts_list,
|
linked_list_t *other_ts_list, mode_t mode);
|
||||||
linked_list_t *other_ts_list);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the traffic selectors of added policies of local host.
|
* @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));
|
child_sa->set_name(child_sa, policy->get_name(policy));
|
||||||
my_ts = policy->get_my_traffic_selectors(policy, this->my_host);
|
my_ts = policy->get_my_traffic_selectors(policy, this->my_host);
|
||||||
other_ts = policy->get_other_traffic_selectors(policy, this->other_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));
|
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
|
||||||
other_ts->destroy_offset(other_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);
|
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;
|
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?
|
* Have we lost the simultaneous rekeying nonce compare?
|
||||||
*/
|
*/
|
||||||
@ -186,6 +191,31 @@ static void cancel(private_create_child_sa_t *this)
|
|||||||
this->lost = TRUE;
|
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.
|
* 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);
|
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) */
|
{ /* build the NONCE payload for us (initiator) */
|
||||||
nonce_payload_t *nonce_payload;
|
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");
|
SIG(this->failsig, "received NO_PROPOSAL_CHOSEN notify");
|
||||||
return FAILED;
|
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:
|
case REKEY_SA:
|
||||||
{
|
{
|
||||||
u_int32_t spi;
|
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;
|
is_host = is_host && ts->is_host(ts, host);
|
||||||
iterator_t *iterator = message->get_payload_iterator(message);
|
|
||||||
while (iterator->iterate(iterator, (void**)&payload))
|
|
||||||
{
|
|
||||||
payload->destroy(payload);
|
|
||||||
iterator->remove(iterator);
|
|
||||||
}
|
|
||||||
iterator->destroy(iterator);
|
|
||||||
}
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
notify = notify_payload_create();
|
return is_host;
|
||||||
notify->set_notify_type(notify, type);
|
|
||||||
notify->set_notification_data(notify, data);
|
|
||||||
message->add_payload(message, (payload_t*)notify);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -455,11 +509,11 @@ static status_t install_child_sa(private_create_child_sa_t *this, bool initiator
|
|||||||
|
|
||||||
if (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
|
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);
|
prf_plus->destroy(prf_plus);
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
@ -468,11 +522,11 @@ static status_t install_child_sa(private_create_child_sa_t *this, bool initiator
|
|||||||
}
|
}
|
||||||
if (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
|
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)
|
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),
|
this->policy->get_hostaccess(this->policy),
|
||||||
use_natt);
|
use_natt);
|
||||||
this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
|
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)
|
if (install_child_sa(this, FALSE) != SUCCESS)
|
||||||
{
|
{
|
||||||
SIG(this->failsig, "installing CHILD_SA failed, sending NO_PROPOSAL_CHOSEN notify");
|
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");
|
SIG(this->failsig, "CHILD_SA negotiation failed, no CHILD_SA built");
|
||||||
return FAILED;
|
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;
|
new_child = this->child_sa;
|
||||||
if (install_child_sa(this, TRUE) != SUCCESS)
|
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->policy = NULL;
|
||||||
this->tsi = NULL;
|
this->tsi = NULL;
|
||||||
this->tsr = NULL;
|
this->tsr = NULL;
|
||||||
|
this->mode = MODE_TUNNEL;
|
||||||
this->randomizer = randomizer_create();
|
this->randomizer = randomizer_create();
|
||||||
this->failsig = CHILD_UP_FAILED;
|
this->failsig = CHILD_UP_FAILED;
|
||||||
|
|
||||||
|
@ -128,6 +128,11 @@ struct private_ike_auth_t {
|
|||||||
* reqid to use for CHILD_SA setup
|
* reqid to use for CHILD_SA setup
|
||||||
*/
|
*/
|
||||||
u_int32_t reqid;
|
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;
|
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.
|
* 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);
|
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 */
|
{ /* build TSi payload */
|
||||||
linked_list_t *ts_list;
|
linked_list_t *ts_list;
|
||||||
ts_payload_t *ts_payload;
|
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;
|
this->build_child = FALSE;
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
case USE_TRANSPORT_MODE:
|
||||||
|
{
|
||||||
|
this->mode = MODE_TRANSPORT;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
case USE_BEET_MODE:
|
||||||
|
{
|
||||||
|
this->mode = MODE_BEET;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if (notify_type < 16383)
|
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
|
* 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
|
* 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)
|
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
|
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);
|
prf_plus->destroy(prf_plus);
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
@ -531,11 +587,13 @@ static status_t install_child_sa(private_ike_auth_t *this, bool initiator)
|
|||||||
}
|
}
|
||||||
if (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
|
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)
|
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),
|
this->policy->get_hostaccess(this->policy),
|
||||||
use_natt);
|
use_natt);
|
||||||
this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
|
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)
|
if (install_child_sa(this, FALSE) != SUCCESS)
|
||||||
{
|
{
|
||||||
SIG(CHILD_UP_FAILED, "installing CHILD_SA failed, no CHILD_SA created");
|
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
|
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)
|
if (install_child_sa(this, TRUE) != SUCCESS)
|
||||||
{
|
{
|
||||||
SIG(CHILD_UP_FAILED, "installing CHILD_SA failed, no CHILD_SA built");
|
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->tsr = NULL;
|
||||||
this->build_child = TRUE;
|
this->build_child = TRUE;
|
||||||
this->reqid = 0;
|
this->reqid = 0;
|
||||||
|
this->mode = MODE_TUNNEL;
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
@ -503,7 +503,7 @@ static status_t add_sa(private_kernel_interface_t *this,
|
|||||||
protocol_id_t protocol, u_int32_t reqid,
|
protocol_id_t protocol, u_int32_t reqid,
|
||||||
u_int64_t expire_soft, u_int64_t expire_hard,
|
u_int64_t expire_soft, u_int64_t expire_hard,
|
||||||
algorithm_t *enc_alg, algorithm_t *int_alg,
|
algorithm_t *enc_alg, algorithm_t *int_alg,
|
||||||
prf_plus_t *prf_plus, natt_conf_t *natt,
|
prf_plus_t *prf_plus, natt_conf_t *natt, mode_t mode,
|
||||||
bool replace)
|
bool replace)
|
||||||
{
|
{
|
||||||
unsigned char request[BUFFER_SIZE];
|
unsigned char request[BUFFER_SIZE];
|
||||||
@ -529,7 +529,7 @@ static status_t add_sa(private_kernel_interface_t *this,
|
|||||||
sa->id.spi = spi;
|
sa->id.spi = spi;
|
||||||
sa->id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
|
sa->id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
|
||||||
sa->family = src->get_family(src);
|
sa->family = src->get_family(src);
|
||||||
sa->mode = TRUE; /* tunnel mode */
|
sa->mode = mode;
|
||||||
sa->replay_window = 32;
|
sa->replay_window = 32;
|
||||||
sa->reqid = reqid;
|
sa->reqid = reqid;
|
||||||
/* we currently do not expire SAs by volume/packet count */
|
/* we currently do not expire SAs by volume/packet count */
|
||||||
@ -970,7 +970,8 @@ static status_t add_policy(private_kernel_interface_t *this,
|
|||||||
traffic_selector_t *src_ts,
|
traffic_selector_t *src_ts,
|
||||||
traffic_selector_t *dst_ts,
|
traffic_selector_t *dst_ts,
|
||||||
policy_dir_t direction, protocol_id_t protocol,
|
policy_dir_t direction, protocol_id_t protocol,
|
||||||
u_int32_t reqid, bool high_prio, bool update)
|
u_int32_t reqid, bool high_prio, mode_t mode,
|
||||||
|
bool update)
|
||||||
{
|
{
|
||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
kernel_policy_t *current, *policy;
|
kernel_policy_t *current, *policy;
|
||||||
@ -992,7 +993,7 @@ static status_t add_policy(private_kernel_interface_t *this,
|
|||||||
iterator = this->policies->create_iterator(this->policies, TRUE);
|
iterator = this->policies->create_iterator(this->policies, TRUE);
|
||||||
while (iterator->iterate(iterator, (void**)¤t))
|
while (iterator->iterate(iterator, (void**)¤t))
|
||||||
{
|
{
|
||||||
if (memcmp(current, policy, sizeof(struct xfrm_selector)) == 0 &&
|
if (memcmp(¤t->sel, &policy->sel, sizeof(struct xfrm_selector)) == 0 &&
|
||||||
policy->direction == current->direction)
|
policy->direction == current->direction)
|
||||||
{
|
{
|
||||||
free(policy);
|
free(policy);
|
||||||
@ -1068,7 +1069,7 @@ static status_t add_policy(private_kernel_interface_t *this,
|
|||||||
tmpl->reqid = reqid;
|
tmpl->reqid = reqid;
|
||||||
tmpl->id.proto = (protocol == PROTO_AH) ? KERNEL_AH : KERNEL_ESP;
|
tmpl->id.proto = (protocol == PROTO_AH) ? KERNEL_AH : KERNEL_ESP;
|
||||||
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
|
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
|
||||||
tmpl->mode = TRUE;
|
tmpl->mode = mode;
|
||||||
tmpl->family = src->get_family(src);
|
tmpl->family = src->get_family(src);
|
||||||
|
|
||||||
host2xfrm(src, &tmpl->saddr);
|
host2xfrm(src, &tmpl->saddr);
|
||||||
@ -1266,11 +1267,11 @@ kernel_interface_t *kernel_interface_create()
|
|||||||
|
|
||||||
/* public functions */
|
/* public functions */
|
||||||
this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
|
this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
|
||||||
this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,algorithm_t*,algorithm_t*,prf_plus_t*,natt_conf_t*,bool))add_sa;
|
this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,algorithm_t*,algorithm_t*,prf_plus_t*,natt_conf_t*,mode_t,bool))add_sa;
|
||||||
this->public.update_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_diff_t,host_diff_t))update_sa;
|
this->public.update_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_diff_t,host_diff_t))update_sa;
|
||||||
this->public.query_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t*))query_sa;
|
this->public.query_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t*))query_sa;
|
||||||
this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
|
this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
|
||||||
this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,bool))add_policy;
|
this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,mode_t,bool))add_policy;
|
||||||
this->public.query_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
|
this->public.query_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
|
||||||
this->public.del_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t))del_policy;
|
this->public.del_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t))del_policy;
|
||||||
this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
|
this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
|
||||||
|
@ -118,6 +118,7 @@ struct kernel_interface_t {
|
|||||||
* @param int_alg Algorithm to use for integrity protection
|
* @param int_alg Algorithm to use for integrity protection
|
||||||
* @param prf_plus PRF to derive keys from
|
* @param prf_plus PRF to derive keys from
|
||||||
* @param natt NAT-T Configuration, or NULL of no NAT-T used
|
* @param natt NAT-T Configuration, or NULL of no NAT-T used
|
||||||
|
* @param mode mode of the SA (tunnel, transport)
|
||||||
* @param replace Should an already installed SA be updated?
|
* @param replace Should an already installed SA be updated?
|
||||||
* @return
|
* @return
|
||||||
* - SUCCESS
|
* - SUCCESS
|
||||||
@ -128,7 +129,8 @@ struct kernel_interface_t {
|
|||||||
protocol_id_t protocol, u_int32_t reqid,
|
protocol_id_t protocol, u_int32_t reqid,
|
||||||
u_int64_t expire_soft, u_int64_t expire_hard,
|
u_int64_t expire_soft, u_int64_t expire_hard,
|
||||||
algorithm_t *enc_alg, algorithm_t *int_alg,
|
algorithm_t *enc_alg, algorithm_t *int_alg,
|
||||||
prf_plus_t *prf_plus, natt_conf_t *natt, bool update);
|
prf_plus_t *prf_plus, natt_conf_t *natt,
|
||||||
|
mode_t mode, bool update);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Update the hosts on an installed SA.
|
* @brief Update the hosts on an installed SA.
|
||||||
@ -206,6 +208,7 @@ struct kernel_interface_t {
|
|||||||
* @param protocol protocol to use to protect traffic (AH/ESP)
|
* @param protocol protocol to use to protect traffic (AH/ESP)
|
||||||
* @param reqid uniqe ID of an SA to use to enforce policy
|
* @param reqid uniqe ID of an SA to use to enforce policy
|
||||||
* @param high_prio if TRUE, uses a higher priority than any with FALSE
|
* @param high_prio if TRUE, uses a higher priority than any with FALSE
|
||||||
|
* @param mode mode of SA (tunnel, transport)
|
||||||
* @param update update an existing policy, if TRUE
|
* @param update update an existing policy, if TRUE
|
||||||
* @return
|
* @return
|
||||||
* - SUCCESS
|
* - SUCCESS
|
||||||
@ -216,7 +219,8 @@ struct kernel_interface_t {
|
|||||||
traffic_selector_t *src_ts,
|
traffic_selector_t *src_ts,
|
||||||
traffic_selector_t *dst_ts,
|
traffic_selector_t *dst_ts,
|
||||||
policy_dir_t direction, protocol_id_t protocol,
|
policy_dir_t direction, protocol_id_t protocol,
|
||||||
u_int32_t reqid, bool high_prio, bool update);
|
u_int32_t reqid, bool high_prio,
|
||||||
|
mode_t mode, bool update);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Query the use time of a policy.
|
* @brief Query the use time of a policy.
|
||||||
|
@ -398,7 +398,7 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
|
|||||||
msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
|
msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
|
||||||
msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
|
msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
|
||||||
msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
|
msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
|
||||||
msg->add_conn.dpd.action);
|
msg->add_conn.mode, msg->add_conn.dpd.action);
|
||||||
policy->add_my_traffic_selector(policy, my_ts);
|
policy->add_my_traffic_selector(policy, my_ts);
|
||||||
policy->add_other_traffic_selector(policy, other_ts);
|
policy->add_other_traffic_selector(policy, other_ts);
|
||||||
policy->add_authorities(policy, my_ca, other_ca);
|
policy->add_authorities(policy, my_ca, other_ca);
|
||||||
|
@ -234,9 +234,11 @@ signifying that no IPsec processing should be done at all;
|
|||||||
signifying that packets should be discarded; and
|
signifying that packets should be discarded; and
|
||||||
.BR reject ,
|
.BR reject ,
|
||||||
signifying that packets should be discarded and a diagnostic ICMP returned.
|
signifying that packets should be discarded and a diagnostic ICMP returned.
|
||||||
Charon currently supports only the
|
Charon currently supports only
|
||||||
.BR tunnel
|
.BR tunnel
|
||||||
connection type.
|
and
|
||||||
|
.BR transport
|
||||||
|
connection types.
|
||||||
.TP
|
.TP
|
||||||
.B left
|
.B left
|
||||||
(required)
|
(required)
|
||||||
|
@ -194,6 +194,7 @@ int starter_stroke_add_conn(starter_conn_t *conn)
|
|||||||
msg.add_conn.name = push_string(&msg, connection_name(conn));
|
msg.add_conn.name = push_string(&msg, connection_name(conn));
|
||||||
msg.add_conn.auth_method = (conn->policy & POLICY_PSK)?
|
msg.add_conn.auth_method = (conn->policy & POLICY_PSK)?
|
||||||
SHARED_KEY_MESSAGE_INTEGRITY_CODE : RSA_DIGITAL_SIGNATURE;
|
SHARED_KEY_MESSAGE_INTEGRITY_CODE : RSA_DIGITAL_SIGNATURE;
|
||||||
|
msg.add_conn.mode = (conn->policy & POLICY_TUNNEL) ? 1 : 0;
|
||||||
|
|
||||||
if (conn->policy & POLICY_DONT_REKEY)
|
if (conn->policy & POLICY_DONT_REKEY)
|
||||||
{
|
{
|
||||||
|
@ -106,6 +106,7 @@ static int add_connection(char *name,
|
|||||||
|
|
||||||
msg.add_conn.name = push_string(&msg, name);
|
msg.add_conn.name = push_string(&msg, name);
|
||||||
msg.add_conn.ikev2 = 1;
|
msg.add_conn.ikev2 = 1;
|
||||||
|
msg.add_conn.mode = 1;
|
||||||
|
|
||||||
msg.add_conn.rekey.reauth = 0;
|
msg.add_conn.rekey.reauth = 0;
|
||||||
msg.add_conn.rekey.ipsec_lifetime = 0;
|
msg.add_conn.rekey.ipsec_lifetime = 0;
|
||||||
|
@ -137,6 +137,7 @@ struct stroke_msg_t {
|
|||||||
char *name;
|
char *name;
|
||||||
int ikev2;
|
int ikev2;
|
||||||
int auth_method;
|
int auth_method;
|
||||||
|
int mode;
|
||||||
struct {
|
struct {
|
||||||
char *ike;
|
char *ike;
|
||||||
char *esp;
|
char *esp;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user