Merge branch 'ike-address-ranges'
Adds support for multiple subnets and address ranges in left/right ipsec.conf options. As responder the connection is acceptable if the address is in one of the ranges/subnets. To initiate connections, at least one single IP or hostname is required for the peer address.
This commit is contained in:
+10
-3
@@ -488,9 +488,8 @@ Relevant only locally, other end need not agree on it.
|
||||
synonym for
|
||||
.BR lifetime .
|
||||
.TP
|
||||
.BR left " = <ip address> | <fqdn> | " %any
|
||||
(required)
|
||||
the IP address of the left participant's public-network interface
|
||||
.BR left " = <ip address> | <fqdn> | " %any " | <range> | <subnet> "
|
||||
The IP address of the left participant's public-network interface
|
||||
or one of several magic values.
|
||||
The value
|
||||
.B %any
|
||||
@@ -510,6 +509,14 @@ If
|
||||
.B %any
|
||||
is used for the remote endpoint it literally means any IP address.
|
||||
|
||||
To limit the connection to a specific range of hosts, a range (
|
||||
.BR 10.1.0.0-10.2.255.255
|
||||
) or a subnet (
|
||||
.BR 10.1.0.0/16
|
||||
) can be specified, and multiple addresses, ranges and subnets can be separated
|
||||
by commas. While one can freely combine these items, to initiate the connection
|
||||
at least one non-range/subnet is required.
|
||||
|
||||
Please note that with the usage of wildcards multiple connection descriptions
|
||||
might match a given incoming connection attempt. The most specific description
|
||||
is used in that case.
|
||||
|
||||
@@ -163,8 +163,8 @@ static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this)
|
||||
{
|
||||
remote_port = IKEV2_NATT_PORT;
|
||||
}
|
||||
ike_cfg = ike_cfg_create(version, TRUE, FALSE, "0.0.0.0", FALSE, local_port,
|
||||
this->host, FALSE, remote_port, FRAGMENTATION_NO, 0);
|
||||
ike_cfg = ike_cfg_create(version, TRUE, FALSE, "0.0.0.0", local_port,
|
||||
this->host, remote_port, FRAGMENTATION_NO, 0);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
peer_cfg = peer_cfg_create("cmd", ike_cfg,
|
||||
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
|
||||
|
||||
@@ -527,9 +527,9 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
||||
/**
|
||||
* Set up configurations
|
||||
*/
|
||||
ike_cfg = ike_cfg_create(IKEV2, TRUE, encap, "0.0.0.0", FALSE,
|
||||
ike_cfg = ike_cfg_create(IKEV2, TRUE, encap, "0.0.0.0",
|
||||
charon->socket->get_port(charon->socket, FALSE),
|
||||
(char*)address, FALSE, IKEV2_UDP_PORT,
|
||||
(char*)address, IKEV2_UDP_PORT,
|
||||
FRAGMENTATION_NO, 0);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
peer_cfg = peer_cfg_create(priv->name, ike_cfg,
|
||||
|
||||
@@ -103,9 +103,9 @@ static ike_cfg_t *load_ike_config(private_config_t *this,
|
||||
|
||||
ike_cfg = ike_cfg_create(IKEV2, TRUE,
|
||||
settings->get_bool(settings, "configs.%s.fake_nat", FALSE, config),
|
||||
settings->get_str(settings, "configs.%s.lhost", "%any", config), FALSE,
|
||||
settings->get_str(settings, "configs.%s.lhost", "%any", config),
|
||||
settings->get_int(settings, "configs.%s.lport", 500, config),
|
||||
settings->get_str(settings, "configs.%s.rhost", "%any", config), FALSE,
|
||||
settings->get_str(settings, "configs.%s.rhost", "%any", config),
|
||||
settings->get_int(settings, "configs.%s.rport", 500, config),
|
||||
FRAGMENTATION_NO, 0);
|
||||
token = settings->get_str(settings, "configs.%s.proposal", NULL, config);
|
||||
|
||||
@@ -525,9 +525,9 @@ static job_requeue_t initiate(private_android_service_t *this)
|
||||
}
|
||||
};
|
||||
|
||||
ike_cfg = ike_cfg_create(IKEV2, TRUE, TRUE, "0.0.0.0", FALSE,
|
||||
ike_cfg = ike_cfg_create(IKEV2, TRUE, TRUE, "0.0.0.0",
|
||||
charon->socket->get_port(charon->socket, FALSE),
|
||||
this->gateway, FALSE, IKEV2_UDP_PORT,
|
||||
this->gateway, IKEV2_UDP_PORT,
|
||||
FRAGMENTATION_NO, 0);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
|
||||
|
||||
@@ -84,8 +84,8 @@ static peer_cfg_t* create_peer_cfg(char *name, char *host)
|
||||
{
|
||||
remote_port = IKEV2_NATT_PORT;
|
||||
}
|
||||
ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, "0.0.0.0", FALSE, local_port,
|
||||
host, FALSE, remote_port, FRAGMENTATION_NO, 0);
|
||||
ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, "0.0.0.0", local_port,
|
||||
host, remote_port, FRAGMENTATION_NO, 0);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
peer_cfg = peer_cfg_create(name, ike_cfg,
|
||||
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
|
||||
|
||||
@@ -84,10 +84,8 @@ static enumerator_t *ike_enum_create(backend_t *backend, ike_data_t *data)
|
||||
static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other,
|
||||
ike_version_t version)
|
||||
{
|
||||
host_t *me_cand, *other_cand;
|
||||
char *my_addr, *other_addr;
|
||||
bool my_allow_any, other_allow_any;
|
||||
ike_cfg_match_t match = MATCH_NONE;
|
||||
int quality;
|
||||
|
||||
if (cand->get_version(cand) != IKE_ANY &&
|
||||
version != cand->get_version(cand))
|
||||
@@ -97,26 +95,12 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other,
|
||||
|
||||
if (me)
|
||||
{
|
||||
my_addr = cand->get_my_addr(cand, &my_allow_any);
|
||||
me_cand = host_create_from_dns(my_addr, me->get_family(me), 0);
|
||||
if (!me_cand)
|
||||
quality = cand->match_me(cand, me);
|
||||
if (!quality)
|
||||
{
|
||||
return MATCH_NONE;
|
||||
}
|
||||
if (me_cand->ip_equals(me_cand, me))
|
||||
{
|
||||
match += MATCH_ME;
|
||||
}
|
||||
else if (my_allow_any || me_cand->is_anyaddr(me_cand))
|
||||
{
|
||||
match += MATCH_ANY;
|
||||
}
|
||||
else
|
||||
{
|
||||
me_cand->destroy(me_cand);
|
||||
return MATCH_NONE;
|
||||
}
|
||||
me_cand->destroy(me_cand);
|
||||
match += quality * MATCH_ME;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -125,26 +109,12 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other,
|
||||
|
||||
if (other)
|
||||
{
|
||||
other_addr = cand->get_other_addr(cand, &other_allow_any);
|
||||
other_cand = host_create_from_dns(other_addr, other->get_family(other), 0);
|
||||
if (!other_cand)
|
||||
quality = cand->match_other(cand, other);
|
||||
if (!quality)
|
||||
{
|
||||
return MATCH_NONE;
|
||||
}
|
||||
if (other_cand->ip_equals(other_cand, other))
|
||||
{
|
||||
match += MATCH_OTHER;
|
||||
}
|
||||
else if (other_allow_any || other_cand->is_anyaddr(other_cand))
|
||||
{
|
||||
match += MATCH_ANY;
|
||||
}
|
||||
else
|
||||
{
|
||||
other_cand->destroy(other_cand);
|
||||
return MATCH_NONE;
|
||||
}
|
||||
other_cand->destroy(other_cand);
|
||||
match += quality * MATCH_OTHER;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -165,7 +135,6 @@ METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*,
|
||||
{
|
||||
ike_cfg_t *current, *found = NULL;
|
||||
char *my_addr, *other_addr;
|
||||
bool my_allow_any, other_allow_any;
|
||||
enumerator_t *enumerator;
|
||||
ike_cfg_match_t match, best = MATCH_ANY;
|
||||
ike_data_t *data;
|
||||
@@ -189,11 +158,10 @@ METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*,
|
||||
match, me, other, ike_version_names, version);
|
||||
if (match)
|
||||
{
|
||||
my_addr = current->get_my_addr(current, &my_allow_any);
|
||||
other_addr = current->get_other_addr(current, &other_allow_any);
|
||||
DBG2(DBG_CFG, " candidate: %s%s...%s%s, prio %d",
|
||||
my_allow_any ? "%":"", my_addr,
|
||||
other_allow_any ? "%":"", other_addr, match);
|
||||
my_addr = current->get_my_addr(current);
|
||||
other_addr = current->get_other_addr(current);
|
||||
DBG2(DBG_CFG, " candidate: %s...%s, prio %d",
|
||||
my_addr, other_addr, match);
|
||||
if (match > best)
|
||||
{
|
||||
DESTROY_IF(found);
|
||||
@@ -207,11 +175,10 @@ METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*,
|
||||
this->lock->unlock(this->lock);
|
||||
if (found)
|
||||
{
|
||||
my_addr = found->get_my_addr(found, &my_allow_any);
|
||||
other_addr = found->get_other_addr(found, &other_allow_any);
|
||||
DBG2(DBG_CFG, "found matching ike config: %s%s...%s%s with prio %d",
|
||||
my_allow_any ? "%":"", my_addr,
|
||||
other_allow_any ? "%":"", other_addr, best);
|
||||
my_addr = found->get_my_addr(found);
|
||||
other_addr = found->get_other_addr(found);
|
||||
DBG2(DBG_CFG, "found matching ike config: %s...%s with prio %d",
|
||||
my_addr, other_addr, best);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
@@ -481,4 +448,3 @@ backend_manager_t *backend_manager_create()
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
|
||||
+233
-19
@@ -50,24 +50,34 @@ struct private_ike_cfg_t {
|
||||
ike_version_t version;
|
||||
|
||||
/**
|
||||
* Address of local host
|
||||
* Address list string for local host
|
||||
*/
|
||||
char *me;
|
||||
|
||||
/**
|
||||
* Address of remote host
|
||||
* Address list string for remote host
|
||||
*/
|
||||
char *other;
|
||||
|
||||
/**
|
||||
* Allow override of local address
|
||||
* Local single host or DNS names, as allocated char*
|
||||
*/
|
||||
bool my_allow_any;
|
||||
linked_list_t *my_hosts;
|
||||
|
||||
/**
|
||||
* Allow override of remote address
|
||||
* Remote single host or DNS names, as allocated char*
|
||||
*/
|
||||
bool other_allow_any;
|
||||
linked_list_t *other_hosts;
|
||||
|
||||
/**
|
||||
* Local ranges/subnets this config matches to, as traffic_selector_t*
|
||||
*/
|
||||
linked_list_t *my_ranges;
|
||||
|
||||
/**
|
||||
* Remote ranges/subnets this config matches to, as traffic_selector_t*
|
||||
*/
|
||||
linked_list_t *other_ranges;
|
||||
|
||||
/**
|
||||
* our source port
|
||||
@@ -129,23 +139,124 @@ METHOD(ike_cfg_t, fragmentation, fragmentation_t,
|
||||
return this->fragmentation;
|
||||
}
|
||||
|
||||
METHOD(ike_cfg_t, get_my_addr, char*,
|
||||
private_ike_cfg_t *this, bool *allow_any)
|
||||
/**
|
||||
* Common function for resolve_me/other
|
||||
*/
|
||||
static host_t* resolve(linked_list_t *hosts, int family, u_int16_t port)
|
||||
{
|
||||
if (allow_any)
|
||||
enumerator_t *enumerator;
|
||||
host_t *host = NULL;
|
||||
bool tried = FALSE;
|
||||
char *str;
|
||||
|
||||
enumerator = hosts->create_enumerator(hosts);
|
||||
while (enumerator->enumerate(enumerator, &str))
|
||||
{
|
||||
*allow_any = this->my_allow_any;
|
||||
host = host_create_from_dns(str, family, port);
|
||||
if (host)
|
||||
{
|
||||
break;
|
||||
}
|
||||
tried = TRUE;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (!host && !tried)
|
||||
{
|
||||
/* we have no single host configured, return %any */
|
||||
host = host_create_any(family ?: AF_INET);
|
||||
host->set_port(host, port);
|
||||
}
|
||||
return host;
|
||||
}
|
||||
|
||||
METHOD(ike_cfg_t, resolve_me, host_t*,
|
||||
private_ike_cfg_t *this, int family)
|
||||
{
|
||||
return resolve(this->my_hosts, family, this->my_port);
|
||||
}
|
||||
|
||||
METHOD(ike_cfg_t, resolve_other, host_t*,
|
||||
private_ike_cfg_t *this, int family)
|
||||
{
|
||||
return resolve(this->other_hosts, family, this->other_port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Common function for match_me/other
|
||||
*/
|
||||
static u_int match(linked_list_t *hosts, linked_list_t *ranges, host_t *cand)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
traffic_selector_t *ts;
|
||||
char *str;
|
||||
host_t *host;
|
||||
u_int8_t mask;
|
||||
u_int quality = 0;
|
||||
|
||||
/* try single hosts first */
|
||||
enumerator = hosts->create_enumerator(hosts);
|
||||
while (enumerator->enumerate(enumerator, &str))
|
||||
{
|
||||
host = host_create_from_dns(str, cand->get_family(cand), 0);
|
||||
if (host)
|
||||
{
|
||||
if (host->ip_equals(host, cand))
|
||||
{
|
||||
quality = max(quality, 128 + 1);
|
||||
}
|
||||
if (host->is_anyaddr(host))
|
||||
{
|
||||
quality = max(quality, 1);
|
||||
}
|
||||
host->destroy(host);
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
/* then ranges/subnets */
|
||||
enumerator = ranges->create_enumerator(ranges);
|
||||
while (enumerator->enumerate(enumerator, &ts))
|
||||
{
|
||||
if (ts->includes(ts, cand))
|
||||
{
|
||||
if (ts->to_subnet(ts, &host, &mask))
|
||||
{
|
||||
quality = max(quality, mask + 1);
|
||||
host->destroy(host);
|
||||
}
|
||||
else
|
||||
{
|
||||
quality = max(quality, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
return quality;
|
||||
}
|
||||
|
||||
METHOD(ike_cfg_t, match_me, u_int,
|
||||
private_ike_cfg_t *this, host_t *host)
|
||||
{
|
||||
return match(this->my_hosts, this->my_ranges, host);
|
||||
}
|
||||
|
||||
METHOD(ike_cfg_t, match_other, u_int,
|
||||
private_ike_cfg_t *this, host_t *host)
|
||||
{
|
||||
return match(this->other_hosts, this->other_ranges, host);
|
||||
}
|
||||
|
||||
METHOD(ike_cfg_t, get_my_addr, char*,
|
||||
private_ike_cfg_t *this)
|
||||
{
|
||||
return this->me;
|
||||
}
|
||||
|
||||
METHOD(ike_cfg_t, get_other_addr, char*,
|
||||
private_ike_cfg_t *this, bool *allow_any)
|
||||
private_ike_cfg_t *this)
|
||||
{
|
||||
if (allow_any)
|
||||
{
|
||||
*allow_any = this->other_allow_any;
|
||||
}
|
||||
return this->other;
|
||||
}
|
||||
|
||||
@@ -313,16 +424,110 @@ METHOD(ike_cfg_t, destroy, void,
|
||||
offsetof(proposal_t, destroy));
|
||||
free(this->me);
|
||||
free(this->other);
|
||||
this->my_hosts->destroy_function(this->my_hosts, free);
|
||||
this->other_hosts->destroy_function(this->other_hosts, free);
|
||||
this->my_ranges->destroy_offset(this->my_ranges,
|
||||
offsetof(traffic_selector_t, destroy));
|
||||
this->other_ranges->destroy_offset(this->other_ranges,
|
||||
offsetof(traffic_selector_t, destroy));
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to parse a string as subnet
|
||||
*/
|
||||
static traffic_selector_t* make_subnet(char *str)
|
||||
{
|
||||
char *pos;
|
||||
|
||||
pos = strchr(str, '/');
|
||||
if (!pos)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return traffic_selector_create_from_cidr(str, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to parse a string as an IP range
|
||||
*/
|
||||
static traffic_selector_t* make_range(char *str)
|
||||
{
|
||||
traffic_selector_t *ts;
|
||||
ts_type_t type;
|
||||
char *pos;
|
||||
host_t *from, *to;
|
||||
|
||||
pos = strchr(str, '-');
|
||||
if (!pos)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
to = host_create_from_string(pos + 1, 0);
|
||||
if (!to)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
str = strndup(str, pos - str);
|
||||
from = host_create_from_string_and_family(str, to->get_family(to), 0);
|
||||
free(str);
|
||||
if (!from)
|
||||
{
|
||||
to->destroy(to);
|
||||
return NULL;
|
||||
}
|
||||
if (to->get_family(to) == AF_INET)
|
||||
{
|
||||
type = TS_IPV4_ADDR_RANGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = TS_IPV6_ADDR_RANGE;
|
||||
}
|
||||
ts = traffic_selector_create_from_bytes(0, type,
|
||||
from->get_address(from), 0,
|
||||
to->get_address(to), 0);
|
||||
from->destroy(from);
|
||||
to->destroy(to);
|
||||
return ts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse address string into lists of single hosts and ranges/subnets
|
||||
*/
|
||||
static void parse_addresses(char *str, linked_list_t *hosts,
|
||||
linked_list_t *ranges)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
traffic_selector_t *ts;
|
||||
|
||||
enumerator = enumerator_create_token(str, ",", " ");
|
||||
while (enumerator->enumerate(enumerator, &str))
|
||||
{
|
||||
ts = make_subnet(str);
|
||||
if (ts)
|
||||
{
|
||||
ranges->insert_last(ranges, ts);
|
||||
continue;
|
||||
}
|
||||
ts = make_range(str);
|
||||
if (ts)
|
||||
{
|
||||
ranges->insert_last(ranges, ts);
|
||||
continue;
|
||||
}
|
||||
hosts->insert_last(hosts, strdup(str));
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap,
|
||||
char *me, bool my_allow_any, u_int16_t my_port,
|
||||
char *other, bool other_allow_any, u_int16_t other_port,
|
||||
char *me, u_int16_t my_port,
|
||||
char *other, u_int16_t other_port,
|
||||
fragmentation_t fragmentation, u_int8_t dscp)
|
||||
{
|
||||
private_ike_cfg_t *this;
|
||||
@@ -333,6 +538,10 @@ ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap,
|
||||
.send_certreq = _send_certreq,
|
||||
.force_encap = _force_encap_,
|
||||
.fragmentation = _fragmentation,
|
||||
.resolve_me = _resolve_me,
|
||||
.resolve_other = _resolve_other,
|
||||
.match_me = _match_me,
|
||||
.match_other = _match_other,
|
||||
.get_my_addr = _get_my_addr,
|
||||
.get_other_addr = _get_other_addr,
|
||||
.get_my_port = _get_my_port,
|
||||
@@ -352,14 +561,19 @@ ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap,
|
||||
.force_encap = force_encap,
|
||||
.fragmentation = fragmentation,
|
||||
.me = strdup(me),
|
||||
.my_ranges = linked_list_create(),
|
||||
.my_hosts = linked_list_create(),
|
||||
.other = strdup(other),
|
||||
.my_allow_any = my_allow_any,
|
||||
.other_allow_any = other_allow_any,
|
||||
.other_ranges = linked_list_create(),
|
||||
.other_hosts = linked_list_create(),
|
||||
.my_port = my_port,
|
||||
.other_port = other_port,
|
||||
.dscp = dscp,
|
||||
.proposals = linked_list_create(),
|
||||
);
|
||||
|
||||
parse_addresses(me, this->my_hosts, this->my_ranges);
|
||||
parse_addresses(other, this->other_hosts, this->other_ranges);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -77,21 +77,51 @@ struct ike_cfg_t {
|
||||
*/
|
||||
ike_version_t (*get_version)(ike_cfg_t *this);
|
||||
|
||||
/**
|
||||
* Resolve the local address to use for initiation.
|
||||
*
|
||||
* @param family address family to prefer, or AF_UNSPEC
|
||||
* @return resolved host, NULL on error
|
||||
*/
|
||||
host_t* (*resolve_me)(ike_cfg_t *this, int family);
|
||||
|
||||
/**
|
||||
* Resolve the remote address to use for initiation.
|
||||
*
|
||||
* @param family address family to prefer, or AF_UNSPEC
|
||||
* @return resolved host, NULL on error
|
||||
*/
|
||||
host_t* (*resolve_other)(ike_cfg_t *this, int family);
|
||||
|
||||
/**
|
||||
* Check how good a host matches to the configured local address.
|
||||
*
|
||||
* @param host host to check match quality
|
||||
* @return quality of the match, 0 if not matching at all
|
||||
*/
|
||||
u_int (*match_me)(ike_cfg_t *this, host_t *host);
|
||||
|
||||
/**
|
||||
* Check how good a host matches to the configured remote address.
|
||||
*
|
||||
* @param host host to check match quality
|
||||
* @return quality of the match, 0 if not matching at all
|
||||
*/
|
||||
u_int (*match_other)(ike_cfg_t *this, host_t *host);
|
||||
|
||||
/**
|
||||
* Get own address.
|
||||
*
|
||||
* @param allow_any allow any address to match
|
||||
* @return string of address/DNS name
|
||||
*/
|
||||
char* (*get_my_addr) (ike_cfg_t *this, bool *allow_any);
|
||||
char* (*get_my_addr) (ike_cfg_t *this);
|
||||
|
||||
/**
|
||||
* Get peer's address.
|
||||
*
|
||||
* @param allow_any allow any address to match
|
||||
* @return string of address/DNS name
|
||||
*/
|
||||
char* (*get_other_addr) (ike_cfg_t *this, bool *allow_any);
|
||||
char* (*get_other_addr) (ike_cfg_t *this);
|
||||
|
||||
/**
|
||||
* Get the port to use as our source port.
|
||||
@@ -200,24 +230,27 @@ struct ike_cfg_t {
|
||||
/**
|
||||
* Creates a ike_cfg_t object.
|
||||
*
|
||||
* Supplied hosts become owned by ike_cfg, the name gets cloned.
|
||||
* Supplied hosts become owned by ike_cfg, strings get cloned.
|
||||
*
|
||||
* me and other are comma separated lists of IP addresses, DNS names, IP ranges
|
||||
* or subnets. When initiating, the first non-range/subnet address is used
|
||||
* as address. When responding, a match is performed against all items in the
|
||||
* list.
|
||||
*
|
||||
* @param version IKE major version to use for this config
|
||||
* @param certreq TRUE to send a certificate request
|
||||
* @param force_encap enforce UDP encapsulation by faking NATD notify
|
||||
* @param me address/DNS name of local peer
|
||||
* @param my_allow_any allow override of local address by any address
|
||||
* @param my_port IKE port to use as source, 500 uses IKEv2 port floating
|
||||
* @param other address/DNS name of remote peer
|
||||
* @param other_allow_any allow override of remote address by any address
|
||||
* @param other_port IKE port to use as dest, 500 uses IKEv2 port floating
|
||||
* @param fragmentation use IKEv1 fragmentation
|
||||
* @param dscp DSCP value to send IKE packets with
|
||||
* @return ike_cfg_t object.
|
||||
*/
|
||||
ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap,
|
||||
char *me, bool my_allow_any, u_int16_t my_port,
|
||||
char *other, bool other_allow_any, u_int16_t other_port,
|
||||
char *me, u_int16_t my_port,
|
||||
char *other, u_int16_t other_port,
|
||||
fragmentation_t fragmentation, u_int8_t dscp);
|
||||
|
||||
#endif /** IKE_CFG_H_ @}*/
|
||||
|
||||
@@ -203,9 +203,9 @@ static void setup_tunnel(private_ha_tunnel_t *this,
|
||||
lib->credmgr->add_set(lib->credmgr, &this->creds.public);
|
||||
|
||||
/* create config and backend */
|
||||
ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, local, FALSE,
|
||||
ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, local,
|
||||
charon->socket->get_port(charon->socket, FALSE),
|
||||
remote, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
|
||||
remote, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
peer_cfg = peer_cfg_create("ha", ike_cfg, CERT_NEVER_SEND,
|
||||
UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE,
|
||||
|
||||
@@ -544,16 +544,15 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
|
||||
if (this->port && num)
|
||||
{
|
||||
ike_cfg = ike_cfg_create(this->version, TRUE, FALSE,
|
||||
local, FALSE, this->port + num - 1,
|
||||
remote, FALSE, IKEV2_NATT_PORT,
|
||||
local, this->port + num - 1,
|
||||
remote, IKEV2_NATT_PORT,
|
||||
FRAGMENTATION_NO, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ike_cfg = ike_cfg_create(this->version, TRUE, FALSE,
|
||||
local, FALSE,
|
||||
ike_cfg = ike_cfg_create(this->version, TRUE, FALSE, local,
|
||||
charon->socket->get_port(charon->socket, FALSE),
|
||||
remote, FALSE, IKEV2_UDP_PORT,
|
||||
remote, IKEV2_UDP_PORT,
|
||||
FRAGMENTATION_NO, 0);
|
||||
}
|
||||
ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal));
|
||||
|
||||
@@ -323,10 +323,9 @@ static gboolean initiate_connection(private_maemo_service_t *this,
|
||||
NULL);
|
||||
}
|
||||
|
||||
ike_cfg = ike_cfg_create(IKEV2, TRUE, FALSE, "0.0.0.0", FALSE,
|
||||
ike_cfg = ike_cfg_create(IKEV2, TRUE, FALSE, "0.0.0.0",
|
||||
charon->socket->get_port(charon->socket, FALSE),
|
||||
hostname, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO,
|
||||
0);
|
||||
hostname, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
|
||||
peer_cfg = peer_cfg_create(this->current, ike_cfg,
|
||||
|
||||
@@ -102,10 +102,9 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
|
||||
DESTROY_IF(e);
|
||||
return NULL;
|
||||
}
|
||||
ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE,
|
||||
"0.0.0.0", FALSE,
|
||||
ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, "0.0.0.0",
|
||||
charon->socket->get_port(charon->socket, FALSE),
|
||||
address, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
|
||||
address, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
med_cfg = peer_cfg_create(
|
||||
"mediation", ike_cfg,
|
||||
@@ -377,10 +376,9 @@ medcli_config_t *medcli_config_create(database_t *db)
|
||||
.db = db,
|
||||
.rekey = lib->settings->get_time(lib->settings, "medcli.rekey", 1200),
|
||||
.dpd = lib->settings->get_time(lib->settings, "medcli.dpd", 300),
|
||||
.ike = ike_cfg_create(IKEV2, FALSE, FALSE,
|
||||
"0.0.0.0", FALSE,
|
||||
.ike = ike_cfg_create(IKEV2, FALSE, FALSE, "0.0.0.0",
|
||||
charon->socket->get_port(charon->socket, FALSE),
|
||||
"0.0.0.0", FALSE, IKEV2_UDP_PORT,
|
||||
"0.0.0.0", IKEV2_UDP_PORT,
|
||||
FRAGMENTATION_NO, 0),
|
||||
);
|
||||
this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
|
||||
|
||||
@@ -139,10 +139,9 @@ medsrv_config_t *medsrv_config_create(database_t *db)
|
||||
.db = db,
|
||||
.rekey = lib->settings->get_time(lib->settings, "medsrv.rekey", 1200),
|
||||
.dpd = lib->settings->get_time(lib->settings, "medsrv.dpd", 300),
|
||||
.ike = ike_cfg_create(IKEV2, FALSE, FALSE,
|
||||
"0.0.0.0", FALSE,
|
||||
.ike = ike_cfg_create(IKEV2, FALSE, FALSE, "0.0.0.0",
|
||||
charon->socket->get_port(charon->socket, FALSE),
|
||||
"0.0.0.0", FALSE, IKEV2_UDP_PORT,
|
||||
"0.0.0.0", IKEV2_UDP_PORT,
|
||||
FRAGMENTATION_NO, 0),
|
||||
);
|
||||
this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
|
||||
|
||||
@@ -309,9 +309,9 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write
|
||||
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
|
||||
xmlTextWriterStartElement(writer, "ikeconfig");
|
||||
xmlTextWriterWriteElement(writer, "local",
|
||||
ike_cfg->get_my_addr(ike_cfg, NULL));
|
||||
ike_cfg->get_my_addr(ike_cfg));
|
||||
xmlTextWriterWriteElement(writer, "remote",
|
||||
ike_cfg->get_other_addr(ike_cfg, NULL));
|
||||
ike_cfg->get_other_addr(ike_cfg));
|
||||
xmlTextWriterEndElement(writer);
|
||||
/* </ikeconfig> */
|
||||
|
||||
|
||||
@@ -258,11 +258,9 @@ static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e,
|
||||
{
|
||||
ike_cfg_t *ike_cfg;
|
||||
|
||||
ike_cfg = ike_cfg_create(IKEV2, certreq, force_encap,
|
||||
local, FALSE,
|
||||
ike_cfg = ike_cfg_create(IKEV2, certreq, force_encap, local,
|
||||
charon->socket->get_port(charon->socket, FALSE),
|
||||
remote, FALSE, IKEV2_UDP_PORT,
|
||||
FRAGMENTATION_NO, 0);
|
||||
remote, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
|
||||
add_ike_proposals(this, ike_cfg, id);
|
||||
return ike_cfg;
|
||||
}
|
||||
|
||||
@@ -191,53 +191,86 @@ static void add_proposals(private_stroke_config_t *this, char *string,
|
||||
*/
|
||||
static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
stroke_end_t tmp_end;
|
||||
ike_cfg_t *ike_cfg;
|
||||
host_t *host;
|
||||
u_int16_t ikeport;
|
||||
char me[256], other[256], *token;
|
||||
bool swapped = FALSE;;
|
||||
|
||||
host = host_create_from_dns(msg->add_conn.other.address, 0, 0);
|
||||
if (host)
|
||||
enumerator = enumerator_create_token(msg->add_conn.other.address, ",", " ");
|
||||
while (enumerator->enumerate(enumerator, &token))
|
||||
{
|
||||
if (hydra->kernel_interface->get_interface(hydra->kernel_interface,
|
||||
host, NULL))
|
||||
if (!strchr(token, '/'))
|
||||
{
|
||||
DBG2(DBG_CFG, "left is other host, swapping ends");
|
||||
tmp_end = msg->add_conn.me;
|
||||
msg->add_conn.me = msg->add_conn.other;
|
||||
msg->add_conn.other = tmp_end;
|
||||
host->destroy(host);
|
||||
}
|
||||
else
|
||||
{
|
||||
host->destroy(host);
|
||||
host = host_create_from_dns(msg->add_conn.me.address, 0, 0);
|
||||
host = host_create_from_dns(token, 0, 0);
|
||||
if (host)
|
||||
{
|
||||
if (!hydra->kernel_interface->get_interface(
|
||||
if (hydra->kernel_interface->get_interface(
|
||||
hydra->kernel_interface, host, NULL))
|
||||
{
|
||||
DBG1(DBG_CFG, "left nor right host is our side, "
|
||||
"assuming left=local");
|
||||
DBG2(DBG_CFG, "left is other host, swapping ends");
|
||||
tmp_end = msg->add_conn.me;
|
||||
msg->add_conn.me = msg->add_conn.other;
|
||||
msg->add_conn.other = tmp_end;
|
||||
host->destroy(host);
|
||||
swapped = TRUE;
|
||||
}
|
||||
host->destroy(host);
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (!swapped)
|
||||
{
|
||||
enumerator = enumerator_create_token(msg->add_conn.me.address, ",", " ");
|
||||
while (enumerator->enumerate(enumerator, &token))
|
||||
{
|
||||
if (!strchr(token, '/'))
|
||||
{
|
||||
host = host_create_from_dns(token, 0, 0);
|
||||
if (host)
|
||||
{
|
||||
if (!hydra->kernel_interface->get_interface(
|
||||
hydra->kernel_interface, host, NULL))
|
||||
{
|
||||
DBG1(DBG_CFG, "left nor right host is our side, "
|
||||
"assuming left=local");
|
||||
}
|
||||
host->destroy(host);
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
if (msg->add_conn.me.allow_any)
|
||||
{
|
||||
snprintf(me, sizeof(me), "%s,0.0.0.0/0,::/0",
|
||||
msg->add_conn.me.address);
|
||||
}
|
||||
if (msg->add_conn.other.allow_any)
|
||||
{
|
||||
snprintf(other, sizeof(other), "%s,0.0.0.0/0,::/0",
|
||||
msg->add_conn.other.address);
|
||||
}
|
||||
ikeport = msg->add_conn.me.ikeport;
|
||||
ikeport = (ikeport == IKEV2_UDP_PORT) ?
|
||||
charon->socket->get_port(charon->socket, FALSE) : ikeport;
|
||||
ike_cfg = ike_cfg_create(msg->add_conn.version,
|
||||
msg->add_conn.other.sendcert != CERT_NEVER_SEND,
|
||||
msg->add_conn.force_encap,
|
||||
msg->add_conn.me.address,
|
||||
msg->add_conn.me.allow_any,
|
||||
msg->add_conn.me.allow_any ?
|
||||
me : msg->add_conn.me.address,
|
||||
ikeport,
|
||||
msg->add_conn.other.address,
|
||||
msg->add_conn.other.allow_any,
|
||||
msg->add_conn.other.allow_any ?
|
||||
other : msg->add_conn.other.address,
|
||||
msg->add_conn.other.ikeport,
|
||||
msg->add_conn.fragmentation,
|
||||
msg->add_conn.ikedscp);
|
||||
|
||||
add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg, NULL);
|
||||
return ike_cfg;
|
||||
}
|
||||
@@ -824,7 +857,15 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strchr(ike_cfg->get_my_addr(ike_cfg, NULL), ':'))
|
||||
char *addr, *next, *hit;
|
||||
|
||||
/* guess virtual IP family based on local address. If
|
||||
* multiple addresses are specified, we look at the first
|
||||
* only, as with leftallowany a ::/0 is always appended. */
|
||||
addr = ike_cfg->get_my_addr(ike_cfg);
|
||||
next = strchr(addr, ',');
|
||||
hit = strchr(addr, ':');
|
||||
if (hit && (!next || hit < next))
|
||||
{
|
||||
vip = host_create_any(AF_INET6);
|
||||
}
|
||||
|
||||
@@ -544,7 +544,6 @@ METHOD(stroke_list_t, status, void,
|
||||
while (enumerator->enumerate(enumerator, &peer_cfg))
|
||||
{
|
||||
char *my_addr, *other_addr;
|
||||
bool my_allow_any, other_allow_any;
|
||||
|
||||
if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
|
||||
{
|
||||
@@ -553,12 +552,10 @@ METHOD(stroke_list_t, status, void,
|
||||
|
||||
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
|
||||
ike_version = peer_cfg->get_ike_version(peer_cfg);
|
||||
my_addr = ike_cfg->get_my_addr(ike_cfg, &my_allow_any);
|
||||
other_addr = ike_cfg->get_other_addr(ike_cfg, &other_allow_any);
|
||||
fprintf(out, "%12s: %s%s...%s%s %N", peer_cfg->get_name(peer_cfg),
|
||||
my_allow_any ? "%":"", my_addr,
|
||||
other_allow_any ? "%":"", other_addr,
|
||||
ike_version_names, ike_version);
|
||||
my_addr = ike_cfg->get_my_addr(ike_cfg);
|
||||
other_addr = ike_cfg->get_other_addr(ike_cfg);
|
||||
fprintf(out, "%12s: %s...%s %N", peer_cfg->get_name(peer_cfg),
|
||||
my_addr, other_addr, ike_version_names, ike_version);
|
||||
|
||||
if (ike_version == IKEV1 && peer_cfg->use_aggressive(peer_cfg))
|
||||
{
|
||||
|
||||
@@ -152,10 +152,9 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
|
||||
&ike_proposal, &esp_proposal, &ike_rekey, &esp_rekey))
|
||||
{
|
||||
DESTROY_IF(this->peer_cfg);
|
||||
ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE,
|
||||
local_addr, FALSE,
|
||||
ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, local_addr,
|
||||
charon->socket->get_port(charon->socket, FALSE),
|
||||
remote_addr, FALSE, IKEV2_UDP_PORT,
|
||||
remote_addr, IKEV2_UDP_PORT,
|
||||
FRAGMENTATION_NO, 0);
|
||||
ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE));
|
||||
this->peer_cfg = peer_cfg_create(
|
||||
@@ -251,10 +250,9 @@ METHOD(enumerator_t, ike_enumerator_enumerate, bool,
|
||||
&local_addr, &remote_addr, &ike_proposal))
|
||||
{
|
||||
DESTROY_IF(this->ike_cfg);
|
||||
this->ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE,
|
||||
local_addr, FALSE,
|
||||
this->ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, local_addr,
|
||||
charon->socket->get_port(charon->socket, FALSE),
|
||||
remote_addr, FALSE, IKEV2_UDP_PORT,
|
||||
remote_addr, IKEV2_UDP_PORT,
|
||||
FRAGMENTATION_NO, 0);
|
||||
this->ike_cfg->add_proposal(this->ike_cfg,
|
||||
create_proposal(ike_proposal, PROTO_IKE));
|
||||
|
||||
+12
-16
@@ -1077,7 +1077,7 @@ METHOD(ike_sa_t, initiate_mediated, status_t,
|
||||
static void resolve_hosts(private_ike_sa_t *this)
|
||||
{
|
||||
host_t *host;
|
||||
int family = 0;
|
||||
int family = AF_UNSPEC;
|
||||
|
||||
switch (charon->socket->supported_families(charon->socket))
|
||||
{
|
||||
@@ -1099,12 +1099,7 @@ static void resolve_hosts(private_ike_sa_t *this)
|
||||
}
|
||||
else
|
||||
{
|
||||
char *other_addr;
|
||||
u_int16_t other_port;
|
||||
|
||||
other_addr = this->ike_cfg->get_other_addr(this->ike_cfg, NULL);
|
||||
other_port = this->ike_cfg->get_other_port(this->ike_cfg);
|
||||
host = host_create_from_dns(other_addr, family, other_port);
|
||||
host = this->ike_cfg->resolve_other(this->ike_cfg, family);
|
||||
}
|
||||
if (host)
|
||||
{
|
||||
@@ -1118,17 +1113,12 @@ static void resolve_hosts(private_ike_sa_t *this)
|
||||
}
|
||||
else
|
||||
{
|
||||
char *my_addr;
|
||||
u_int16_t my_port;
|
||||
|
||||
/* use same address family as for other */
|
||||
if (!this->other_host->is_anyaddr(this->other_host))
|
||||
{
|
||||
family = this->other_host->get_family(this->other_host);
|
||||
}
|
||||
my_addr = this->ike_cfg->get_my_addr(this->ike_cfg, NULL);
|
||||
my_port = this->ike_cfg->get_my_port(this->ike_cfg);
|
||||
host = host_create_from_dns(my_addr, family, my_port);
|
||||
host = this->ike_cfg->resolve_me(this->ike_cfg, family);
|
||||
|
||||
if (host && host->is_anyaddr(host) &&
|
||||
!this->other_host->is_anyaddr(this->other_host))
|
||||
@@ -1142,7 +1132,7 @@ static void resolve_hosts(private_ike_sa_t *this)
|
||||
}
|
||||
else
|
||||
{ /* fallback to address family specific %any(6), if configured */
|
||||
host = host_create_from_dns(my_addr, family, my_port);
|
||||
host = this->ike_cfg->resolve_me(this->ike_cfg, family);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1172,8 +1162,14 @@ METHOD(ike_sa_t, initiate, status_t,
|
||||
#endif /* ME */
|
||||
)
|
||||
{
|
||||
char *addr = this->ike_cfg->get_other_addr(this->ike_cfg, NULL);
|
||||
bool is_anyaddr = streq(addr, "%any") || streq(addr, "%any6");
|
||||
bool is_anyaddr;
|
||||
host_t *host;
|
||||
char *addr;
|
||||
|
||||
addr = this->ike_cfg->get_my_addr(this->ike_cfg);
|
||||
host = this->ike_cfg->resolve_other(this->ike_cfg, AF_UNSPEC);
|
||||
is_anyaddr = host && host->is_anyaddr(host);
|
||||
DESTROY_IF(host);
|
||||
|
||||
if (is_anyaddr || !this->retry_initiate_interval)
|
||||
{
|
||||
|
||||
@@ -105,16 +105,14 @@ METHOD(trap_manager_t, install, u_int32_t,
|
||||
|
||||
/* try to resolve addresses */
|
||||
ike_cfg = peer->get_ike_cfg(peer);
|
||||
other = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg, NULL),
|
||||
0, ike_cfg->get_other_port(ike_cfg));
|
||||
other = ike_cfg->resolve_other(ike_cfg, AF_UNSPEC);
|
||||
if (!other || other->is_anyaddr(other))
|
||||
{
|
||||
DESTROY_IF(other);
|
||||
DBG1(DBG_CFG, "installing trap failed, remote address unknown");
|
||||
return 0;
|
||||
}
|
||||
me = host_create_from_dns(ike_cfg->get_my_addr(ike_cfg, NULL),
|
||||
other->get_family(other), ike_cfg->get_my_port(ike_cfg));
|
||||
me = ike_cfg->resolve_me(ike_cfg, other->get_family(other));
|
||||
if (!me || me->is_anyaddr(me))
|
||||
{
|
||||
DESTROY_IF(me);
|
||||
|
||||
Reference in New Issue
Block a user