Re: iked: address pools for both families
On 1 June 2016 at 10:16, Patrick Wildtwrote: > Hi, > > Currently there is only one address pool which is either v4 or v6. > This means that we cannot have dual-stack VPNs via iked. Clients > then might tunnel all IPv4 traffic, but IPv6 traffic is still using > the non-encrypted default route, which might be a security issue. > To enable dual-stack IKEv2, set up a second address pool which is > specifically for v6. > > Patrick > Looks alright to me. OK mikeb
iked: address pools for both families
Hi, Currently there is only one address pool which is either v4 or v6. This means that we cannot have dual-stack VPNs via iked. Clients then might tunnel all IPv4 traffic, but IPv6 traffic is still using the non-encrypted default route, which might be a security issue. To enable dual-stack IKEv2, set up a second address pool which is specifically for v6. Patrick diff --git sbin/iked/config.c sbin/iked/config.c index 1650258..4b9b3a2 100644 --- sbin/iked/config.c +++ sbin/iked/config.c @@ -104,6 +104,10 @@ config_free_sa(struct iked *env, struct iked_sa *sa) (void)RB_REMOVE(iked_addrpool, >sc_addrpool, sa); free(sa->sa_addrpool); } + if (sa->sa_addrpool6) { + (void)RB_REMOVE(iked_addrpool6, >sc_addrpool6, sa); + free(sa->sa_addrpool6); + } if (sa->sa_policy) { TAILQ_REMOVE(>sa_policy->pol_sapeers, sa, sa_peer_entry); diff --git sbin/iked/iked.h sbin/iked/iked.h index b1c3152..3fb7c9f 100644 --- sbin/iked/iked.h +++ sbin/iked/iked.h @@ -449,9 +449,13 @@ struct iked_sa { struct iked_addr*sa_addrpool; /* address from pool */ RB_ENTRY(iked_sa)sa_addrpool_entry; /* pool entries */ + + struct iked_addr*sa_addrpool6; /* address from pool */ + RB_ENTRY(iked_sa)sa_addrpool6_entry;/* pool entries */ }; RB_HEAD(iked_sas, iked_sa); RB_HEAD(iked_addrpool, iked_sa); +RB_HEAD(iked_addrpool6, iked_sa); struct iked_message { struct ibuf *msg_data; @@ -599,6 +603,7 @@ struct iked { char*sc_ocsp_url; struct iked_addrpool sc_addrpool; + struct iked_addrpool6sc_addrpool6; }; struct iked_socket { @@ -691,6 +696,7 @@ struct iked_user * user_lookup(struct iked *, const char *); RB_PROTOTYPE(iked_sas, iked_sa, sa_entry, sa_cmp); RB_PROTOTYPE(iked_addrpool, iked_sa, sa_addrpool_entry, sa_addrpool_cmp); +RB_PROTOTYPE(iked_addrpool6, iked_sa, sa_addrpool6_entry, sa_addrpool6_cmp); RB_PROTOTYPE(iked_users, iked_user, user_entry, user_cmp); RB_PROTOTYPE(iked_activesas, iked_childsa, csa_node, childsa_cmp); RB_PROTOTYPE(iked_flows, iked_flow, flow_node, flow_cmp); diff --git sbin/iked/ikev2.c sbin/iked/ikev2.c index 7d36800..d4c4290 100644 --- sbin/iked/ikev2.c +++ sbin/iked/ikev2.c @@ -122,7 +122,7 @@ int ikev2_add_buf(struct ibuf *buf, struct ibuf *); int ikev2_ipcomp_enable(struct iked *, struct iked_sa *); voidikev2_ipcomp_csa_free(struct iked *, struct iked_childsa *); -int ikev2_cp_setaddr(struct iked *, struct iked_sa *); +int ikev2_cp_setaddr(struct iked *, struct iked_sa *, sa_family_t); int ikev2_cp_fixaddr(struct iked_sa *, struct iked_addr *, struct iked_addr *); @@ -1739,9 +1739,9 @@ ikev2_add_cp(struct iked *env, struct iked_sa *sa, struct ibuf *buf) in6 = (ikecfg->cfg.address.addr_mask != 128 && (ikecfg->cfg_type == IKEV2_CFG_INTERNAL_IP6_ADDRESS) && - sa->sa_addrpool && - sa->sa_addrpool->addr_af == AF_INET6) ? - (struct sockaddr_in6 *)>sa_addrpool->addr : + sa->sa_addrpool6 && + sa->sa_addrpool6->addr_af == AF_INET6) ? + (struct sockaddr_in6 *)>sa_addrpool6->addr : (struct sockaddr_in6 *)>cfg.address.addr; cfg->cfg_length = htobe16(17); if (ibuf_add(buf, >sin6_addr.s6_addr, 16) == -1) @@ -2184,7 +2184,8 @@ ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa) else if (!sa_stateok(sa, IKEV2_STATE_VALID)) return (0); /* ignore */ - if (ikev2_cp_setaddr(env, sa) < 0) + if (ikev2_cp_setaddr(env, sa, AF_INET) < 0 || + ikev2_cp_setaddr(env, sa, AF_INET6) < 0) return (-1); if (ikev2_childsa_negotiate(env, sa, >sa_kex, >sa_proposals, @@ -2943,6 +2944,12 @@ ikev2_ikesa_enable(struct iked *env, struct iked_sa *sa, struct iked_sa *nsa) sa->sa_addrpool = NULL; RB_INSERT(iked_addrpool, >sc_addrpool, nsa); } + if (sa->sa_addrpool6) { + RB_REMOVE(iked_addrpool6, >sc_addrpool6, sa); + nsa->sa_addrpool6 = sa->sa_addrpool6; + sa->sa_addrpool6 = NULL; + RB_INSERT(iked_addrpool6, >sc_addrpool6, nsa); + } log_debug("%s: activating new IKE SA", __func__); sa_state(env, nsa, IKEV2_STATE_ESTABLISHED); @@ -5029,7 +5036,7 @@ ikev2_print_id(struct iked_id *id, char *idstr, size_t idstrlen) * and remember it in the sa_addrpool attribute. */ int -ikev2_cp_setaddr(struct iked *env, struct iked_sa *sa) +ikev2_cp_setaddr(struct iked *env, struct iked_sa *sa,
Re: iked address pools
You can use cvs add against a mirror to add files. Directories require write access, so that won't work. Then use cvs diff -Nup to include all of the (N)ew files. tech@ is the preferred mailing list for diffs. On 2013 Jun 05 (Wed) at 23:23:53 -0600 (-0600), Ryan Slack wrote: :I wish to submit a working implementation of address pools for iked, :however as it's my first real code contribution and has 643 lines :(mostly patch context) I'm wondering if posting here is the correct :channel. : :Also, what is the preferred/normal way to include new files in a patch? : :--Ryan Slack : -- Be security conscious -- National Defense is at stake.
[PATCH] iked address pools
The following provides address pools for iked. It's nothing fancy, but it seems to work, at least in the cursory testing done against the Windows 7 client. Each policy gets it's own pool, configured by config address start ip - end ip. There is a hard limit of 65536 addresses (8kb) per pool, which should be plenty. There is NO ipv6 support, partly because I'm not really sure how or why it would be needed. A request for a specific ip that is available in the pool will be honoured. Comments please! --Ryan Slack Index: addr_pool.c === RCS file: addr_pool.c diff -N addr_pool.c --- /dev/null 1 Jan 1970 00:00:00 - +++ addr_pool.c 7 Jun 2013 03:05:46 - @@ -0,0 +1,188 @@ + +#include sys/socket.h + +#include netinet/in.h + +#include stdlib.h +#include string.h +#include errno.h +#include err.h + +#include iked.h + +int +addr_pool_init_mask(struct addr_pool* pool, + struct sockaddr_storage *address, u_int8_t prefixlengh) +{ + struct sockaddr_in *a4; + /* struct sockaddr_in6 *a6; */ + + if(pool == NULL) return(-1); + + memcpy(pool-addr, address, sizeof(pool-addr)); + + switch(address-ss_family){ + case AF_INET: + if (!(16 prefixlengh prefixlengh 30)) { + log_warnx(%s: prefixlengh (%d) out of range [16:30], + __func__,prefixlengh); + return(-1); + } + //pool-mask = prefixlen2mask(prefixlengh); + pool-size = (1(32 - prefixlengh)) - 2; + + a4 = (struct sockaddr_in *)pool-addr; + a4-sin_addr.s_addr = ntohl(a4-sin_addr.s_addr) + 1; + a4-sin_addr.s_addr = htonl(a4-sin_addr.s_addr); + + break; + case AF_INET6: + default: + errno = EAFNOSUPPORT; + log_warn(%s: ,__func__); + return (-1); + } + + return(0); +} + +int +addr_pool_init_range(struct addr_pool* pool, +struct sockaddr_storage *start, +struct sockaddr_storage *end) +{ + struct sockaddr_in *a4, *b4; + //struct sockaddr_in6 *a6, *b6; + uint32_t size_l; + + if(pool == NULL || start == NULL || end == NULL) return(-1); + + if (start-ss_family != end-ss_family) { + log_debug(%s: address family mismatch, __func__); + return (-1); + } + + + switch(start-ss_family){ + case AF_INET: + a4 = (struct sockaddr_in *)start; + b4 = (struct sockaddr_in *)end; + + size_l = ntohl(b4-sin_addr.s_addr) - ntohl(a4-sin_addr.s_addr) + 1; + + if ( size_l ADDR_POOL_SIZE_MAX ) { + log_warnx(%s: size (%d) out of range (%d),__func__, size_l, ADDR_POOL_SIZE_MAX); + return(-1); + } + pool-size = size_l; + + break; + case AF_INET6: + default: + errno = EAFNOSUPPORT; + log_warn(%s: , __func__); + return (-1); + } + + memcpy(pool-addr, start, sizeof(pool-addr)); + + return(0); +} + + +int +addr_pool_alloc(struct addr_pool* pool) +{ + if((pool-pool = bit_alloc(pool-size))==NULL) + return (-1); + + log_debug(%s: %s+%d, __func__, + print_host(pool-addr, NULL, 0), pool-size); + + return(0); +} + +int +addr_pool_free(struct addr_pool* pool){ + if(pool-size) + free(pool-pool); + return (0); +} + +int +addr_pool_reqest(struct addr_pool* pool, struct sockaddr_storage *address) +{ + struct sockaddr_in *a4; + //struct sockaddr_in6 *sa6,*pa6; + u_int32_t h_addr; + int32_t i; + if(pool-addr.ss_family != address-ss_family){ + log_debug(%s: address family mismatch, __func__); + return(-1); + } + switch(pool-addr.ss_family){ + case AF_INET: + a4 = ((struct sockaddr_in *)address); + h_addr = ntohl(((struct sockaddr_in*)pool-addr)-sin_addr.s_addr); + i = ntohl(a4-sin_addr.s_addr) - h_addr; + if (0 = i (uint32_t)i pool-size !bit_test(pool-pool,i)) { + bit_set(pool-pool,i); + } else { + bit_ffc(pool-pool,pool-size,i); + bit_set(pool-pool,i); + a4-sin_addr.s_addr = htonl(h_addr + i); + } + log_debug(%s: assigned %s [%d], __func__, + print_host(address, NULL, 0), i); + + break; + case AF_INET6: + default: + errno = EAFNOSUPPORT; + log_warn(%s: , __func__); + return (-1); + } + + return (0); +} + +int +addr_pool_release(struct addr_pool* pool, struct sockaddr_storage
iked address pools
I wish to submit a working implementation of address pools for iked, however as it's my first real code contribution and has 643 lines (mostly patch context) I'm wondering if posting here is the correct channel. Also, what is the preferred/normal way to include new files in a patch? --Ryan Slack