Merge branch 'ike-address-ranges'
authorMartin Willi <martin@revosec.ch>
Wed, 4 Sep 2013 08:43:35 +0000 (10:43 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 4 Sep 2013 08:43:35 +0000 (10:43 +0200)
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.

21 files changed:
man/ipsec.conf.5.in
src/charon-cmd/cmd/cmd_connection.c
src/charon-nm/nm/nm_service.c
src/conftest/config.c
src/frontends/android/jni/libandroidbridge/backend/android_service.c
src/frontends/osx/charon-xpc/xpc_dispatch.c
src/libcharon/config/backend_manager.c
src/libcharon/config/ike_cfg.c
src/libcharon/config/ike_cfg.h
src/libcharon/plugins/ha/ha_tunnel.c
src/libcharon/plugins/load_tester/load_tester_config.c
src/libcharon/plugins/maemo/maemo_service.c
src/libcharon/plugins/medcli/medcli_config.c
src/libcharon/plugins/medsrv/medsrv_config.c
src/libcharon/plugins/smp/smp.c
src/libcharon/plugins/sql/sql_config.c
src/libcharon/plugins/stroke/stroke_config.c
src/libcharon/plugins/stroke/stroke_list.c
src/libcharon/plugins/uci/uci_config.c
src/libcharon/sa/ike_sa.c
src/libcharon/sa/trap_manager.c

index 61abc0a..b851729 100644 (file)
@@ -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.
index a697da8..180e8da 100644 (file)
@@ -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 */
index f97c11c..f373675 100644 (file)
@@ -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,
index 1aa9310..5aa742d 100644 (file)
@@ -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);
index 59a4e14..ccf5ce8 100644 (file)
@@ -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));
 
index 0757e9b..df9126c 100644 (file)
@@ -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 */
index f47d571..79f1d9f 100644 (file)
@@ -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)
-               {
-                       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
+               quality = cand->match_me(cand, me);
+               if (!quality)
                {
-                       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;
 }
-
index 54a054e..cb6f6ca 100644 (file)
@@ -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))
+       {
+               host = host_create_from_dns(str, family, port);
+               if (host)
+               {
+                       break;
+               }
+               tried = TRUE;
+       }
+       enumerator->destroy(enumerator);
+
+       if (!host && !tried)
        {
-               *allow_any = this->my_allow_any;
+               /* we have no single host configured, return %any */
+               host = host_create_any(family ?: AF_INET);
+               host->set_port(host, port);
        }
-       return this->me;
+       return host;
 }
 
-METHOD(ike_cfg_t, get_other_addr, char*,
-       private_ike_cfg_t *this, bool *allow_any)
+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)
 {
-       if (allow_any)
+       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))
        {
-               *allow_any = this->other_allow_any;
+               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)
+{
        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;
 }
index 719ceb9..f9e4fbe 100644 (file)
@@ -78,20 +78,50 @@ 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_ @}*/
index 26d152c..74147e5 100644 (file)
@@ -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,
index 26c9871..620d482 100644 (file)
@@ -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));
index f04bc5a..f0f3105 100644 (file)
@@ -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,
index e852e3f..d048b00 100644 (file)
@@ -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));
index 45487a9..ac6076a 100644 (file)
@@ -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));
index a92e571..7bc1700 100644 (file)
@@ -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> */
 
index e6b69a4..a8d34f2 100644 (file)
@@ -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;
        }
index 2e36ce3..bd3f76b 100644 (file)
@@ -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);
                                        }
index 7431514..a582551 100644 (file)
@@ -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))
                        {
index 040d8a8..2a8e403 100644 (file)
@@ -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));
index 2f4e112..2015708 100644 (file)
@@ -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)
                        {
index 37426fc..0d5c10d 100644 (file)
@@ -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);