summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/iked/config.c15
-rw-r--r--sbin/iked/iked.h14
-rw-r--r--sbin/iked/ikev2.c46
-rw-r--r--sbin/iked/ikev2.h4
-rw-r--r--sbin/iked/parse.y52
-rw-r--r--sbin/iked/policy.c48
6 files changed, 135 insertions, 44 deletions
diff --git a/sbin/iked/config.c b/sbin/iked/config.c
index 9ebf24616d2..306af791338 100644
--- a/sbin/iked/config.c
+++ b/sbin/iked/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.50 2019/05/11 16:30:23 patrick Exp $ */
+/* $OpenBSD: config.c,v 1.51 2019/12/03 12:38:34 tobhe Exp $ */
/*
* Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
@@ -188,6 +188,8 @@ config_new_policy(struct iked *env)
/* XXX caller does this again */
TAILQ_INIT(&pol->pol_proposals);
TAILQ_INIT(&pol->pol_sapeers);
+ TAILQ_INIT(&pol->pol_tssrc);
+ TAILQ_INIT(&pol->pol_tsdst);
RB_INIT(&pol->pol_flows);
return (pol);
@@ -197,6 +199,7 @@ void
config_free_policy(struct iked *env, struct iked_policy *pol)
{
struct iked_sa *sa;
+ struct iked_ts *tsi;
if (pol->pol_flags & IKED_POLICY_REFCNT)
goto remove;
@@ -216,6 +219,14 @@ config_free_policy(struct iked *env, struct iked_policy *pol)
return;
remove:
+ while ((tsi = TAILQ_FIRST(&pol->pol_tssrc))) {
+ TAILQ_REMOVE(&pol->pol_tssrc, tsi, ts_entry);
+ free(tsi);
+ }
+ while ((tsi = TAILQ_FIRST(&pol->pol_tsdst))) {
+ TAILQ_REMOVE(&pol->pol_tsdst, tsi, ts_entry);
+ free(tsi);
+ }
config_free_proposals(&pol->pol_proposals, 0);
config_free_flows(env, &pol->pol_flows);
free(pol);
@@ -732,6 +743,8 @@ config_getpolicy(struct iked *env, struct imsg *imsg)
memcpy(pol, buf, sizeof(*pol));
offset += sizeof(*pol);
+ TAILQ_INIT(&pol->pol_tssrc);
+ TAILQ_INIT(&pol->pol_tsdst);
TAILQ_INIT(&pol->pol_proposals);
TAILQ_INIT(&pol->pol_sapeers);
RB_INIT(&pol->pol_flows);
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
index e580fb96269..163f63196f1 100644
--- a/sbin/iked/iked.h
+++ b/sbin/iked/iked.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: iked.h,v 1.127 2019/11/30 15:44:07 tobhe Exp $ */
+/* $OpenBSD: iked.h,v 1.128 2019/12/03 12:38:34 tobhe Exp $ */
/*
* Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
@@ -140,6 +140,13 @@ struct iked_addr {
in_port_t addr_port;
};
+struct iked_ts {
+ struct iked_addr ts_addr;
+ uint8_t ts_ipproto;
+ TAILQ_ENTRY(iked_ts) ts_entry;
+};
+TAILQ_HEAD(iked_tss, iked_ts);
+
struct iked_flow {
struct iked_addr flow_src;
struct iked_addr flow_dst;
@@ -277,6 +284,10 @@ struct iked_policy {
struct iked_flows pol_flows;
size_t pol_nflows;
+ struct iked_tss pol_tssrc; /* Traffic Selectors Initiator*/
+ size_t pol_tssrc_count;
+ struct iked_tss pol_tsdst; /* Traffic Selectors Responder*/
+ size_t pol_tsdst_count;
struct iked_cfg pol_cfg[IKED_CFG_MAX];
unsigned int pol_ncfg;
@@ -759,6 +770,7 @@ void policy_init(struct iked *);
int policy_lookup(struct iked *, struct iked_message *);
struct iked_policy *
policy_test(struct iked *, struct iked_policy *);
+int policy_generate_ts(struct iked_policy *);
void policy_calc_skip_steps(struct iked_policies *);
void policy_ref(struct iked *, struct iked_policy *);
void policy_unref(struct iked *, struct iked_policy *);
diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c
index b5744f35877..8847a7bdd34 100644
--- a/sbin/iked/ikev2.c
+++ b/sbin/iked/ikev2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2.c,v 1.182 2019/11/30 15:44:07 tobhe Exp $ */
+/* $OpenBSD: ikev2.c,v 1.183 2019/12/03 12:38:34 tobhe Exp $ */
/*
* Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
@@ -188,6 +188,7 @@ int
ikev2_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
{
struct iked *env = p->p_env;
+ struct iked_policy *pol;
switch (imsg->hdr.type) {
case IMSG_CTL_RESET:
@@ -200,6 +201,10 @@ ikev2_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
if (config_getmode(env, imsg->hdr.type) == -1)
return (0); /* ignore error */
timer_del(env, &env->sc_inittmr);
+ TAILQ_FOREACH(pol, &env->sc_policies, pol_entry) {
+ if (policy_generate_ts(pol) == -1)
+ fatalx("%s: too many traffic selectors", __func__);
+ }
if (!env->sc_passive) {
timer_set(env, &env->sc_inittmr, ikev2_init_ike_sa,
NULL);
@@ -1471,7 +1476,6 @@ ikev2_add_ts_payload(struct ibuf *buf, unsigned int type, struct iked_sa *sa)
struct iked_policy *pol = sa->sa_policy;
struct ikev2_tsp *tsp;
struct ikev2_ts *ts;
- struct iked_flow *flow;
struct iked_addr *addr;
struct iked_addr pooladdr;
uint8_t *ptr;
@@ -1479,28 +1483,38 @@ ikev2_add_ts_payload(struct ibuf *buf, unsigned int type, struct iked_sa *sa)
uint32_t av[4], bv[4], mv[4];
struct sockaddr_in *in4;
struct sockaddr_in6 *in6;
+ struct iked_tss *tss;
+ struct iked_ts *tsi;
if ((tsp = ibuf_advance(buf, sizeof(*tsp))) == NULL)
return (-1);
tsp->tsp_count = pol->pol_nflows;
len = sizeof(*tsp);
- RB_FOREACH(flow, iked_flows, &pol->pol_flows) {
+ if (type == IKEV2_PAYLOAD_TSi) {
+ if (sa->sa_hdr.sh_initiator) {
+ tss = &pol->pol_tssrc;
+ tsp->tsp_count = pol->pol_tssrc_count;
+ } else {
+ tss = &pol->pol_tsdst;
+ tsp->tsp_count = pol->pol_tsdst_count;
+ }
+ } else if (type == IKEV2_PAYLOAD_TSr) {
+ if (sa->sa_hdr.sh_initiator) {
+ tss = &pol->pol_tsdst;
+ tsp->tsp_count = pol->pol_tsdst_count;
+ } else {
+ tss = &pol->pol_tssrc;
+ tsp->tsp_count = pol->pol_tssrc_count;
+ }
+ } else
+ return (-1);
+
+ TAILQ_FOREACH(tsi, tss, ts_entry) {
if ((ts = ibuf_advance(buf, sizeof(*ts))) == NULL)
return (-1);
- if (type == IKEV2_PAYLOAD_TSi) {
- if (sa->sa_hdr.sh_initiator)
- addr = &flow->flow_src;
- else
- addr = &flow->flow_dst;
- } else if (type == IKEV2_PAYLOAD_TSr) {
- if (sa->sa_hdr.sh_initiator)
- addr = &flow->flow_dst;
- else
- addr = &flow->flow_src;
- } else
- return (-1);
+ addr = &tsi->ts_addr;
/* patch remote address (if configured to 0.0.0.0) */
if ((type == IKEV2_PAYLOAD_TSi && !sa->sa_hdr.sh_initiator) ||
@@ -1509,7 +1523,7 @@ ikev2_add_ts_payload(struct ibuf *buf, unsigned int type, struct iked_sa *sa)
addr = &pooladdr;
}
- ts->ts_protoid = flow->flow_ipproto;
+ ts->ts_protoid = tsi->ts_ipproto;
if (addr->addr_port) {
ts->ts_startport = addr->addr_port;
diff --git a/sbin/iked/ikev2.h b/sbin/iked/ikev2.h
index 90d683b9ce4..1a0a987e978 100644
--- a/sbin/iked/ikev2.h
+++ b/sbin/iked/ikev2.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2.h,v 1.30 2019/05/11 16:30:23 patrick Exp $ */
+/* $OpenBSD: ikev2.h,v 1.31 2019/12/03 12:38:34 tobhe Exp $ */
/*
* Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
@@ -256,6 +256,8 @@ extern struct iked_constmap ikev2_xformdh_map[];
#define IKEV2_IPV6_OVERHEAD (40 + 8 + 28) /* IPv6 + UDP + IKE_HDR*/
#define IKEV2_MAXLEN_IPV6_FRAG (1280 - IKEV2_IPV6_OVERHEAD)
+#define IKEV2_MAXNUM_TSS 255 /* 8 bit Number of TSs field */
+
#define IKEV2_XFORMESN_NONE 0 /* No ESN */
#define IKEV2_XFORMESN_ESN 1 /* ESN */
diff --git a/sbin/iked/parse.y b/sbin/iked/parse.y
index b2e1eeb48e7..fe052068922 100644
--- a/sbin/iked/parse.y
+++ b/sbin/iked/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.87 2019/11/28 15:52:49 kn Exp $ */
+/* $OpenBSD: parse.y,v 1.88 2019/12/03 12:38:34 tobhe Exp $ */
/*
* Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
@@ -2675,13 +2675,12 @@ create_ike(char *name, int af, uint8_t ipproto, struct ipsec_hosts *hosts,
struct iked_transform *xf;
unsigned int i, j, xfi, noauth;
unsigned int ikepropid = 1, ipsecpropid = 1;
- struct iked_flow flows[64];
+ struct iked_flow *flow, *ftmp;
static unsigned int policy_id = 0;
struct iked_cfg *cfg;
int ret = -1;
bzero(&pol, sizeof(pol));
- bzero(&flows, sizeof(flows));
bzero(idstr, sizeof(idstr));
pol.pol_id = ++policy_id;
@@ -2919,38 +2918,39 @@ create_ike(char *name, int af, uint8_t ipproto, struct ipsec_hosts *hosts,
if (hosts == NULL || hosts->src == NULL || hosts->dst == NULL)
fatalx("create_ike: no traffic selectors/flows");
- for (j = 0, ipa = hosts->src, ipb = hosts->dst; ipa && ipb;
- ipa = ipa->next, ipb = ipb->next, j++) {
- if (j >= nitems(flows))
- fatalx("create_ike: too many flows");
- memcpy(&flows[j].flow_src.addr, &ipa->address,
+ for (ipa = hosts->src, ipb = hosts->dst; ipa && ipb;
+ ipa = ipa->next, ipb = ipb->next) {
+ if ((flow = calloc(1, sizeof(struct iked_flow))) == NULL)
+ fatalx("%s: falied to alloc flow.", __func__);
+
+ memcpy(&flow->flow_src.addr, &ipa->address,
sizeof(ipa->address));
- flows[j].flow_src.addr_af = ipa->af;
- flows[j].flow_src.addr_mask = ipa->mask;
- flows[j].flow_src.addr_net = ipa->netaddress;
- flows[j].flow_src.addr_port = hosts->sport;
+ flow->flow_src.addr_af = ipa->af;
+ flow->flow_src.addr_mask = ipa->mask;
+ flow->flow_src.addr_net = ipa->netaddress;
+ flow->flow_src.addr_port = hosts->sport;
- memcpy(&flows[j].flow_dst.addr, &ipb->address,
+ memcpy(&flow->flow_dst.addr, &ipb->address,
sizeof(ipb->address));
- flows[j].flow_dst.addr_af = ipb->af;
- flows[j].flow_dst.addr_mask = ipb->mask;
- flows[j].flow_dst.addr_net = ipb->netaddress;
- flows[j].flow_dst.addr_port = hosts->dport;
+ flow->flow_dst.addr_af = ipb->af;
+ flow->flow_dst.addr_mask = ipb->mask;
+ flow->flow_dst.addr_net = ipb->netaddress;
+ flow->flow_dst.addr_port = hosts->dport;
ippn = ipa->srcnat;
if (ippn) {
- memcpy(&flows[j].flow_prenat.addr, &ippn->address,
+ memcpy(&flow->flow_prenat.addr, &ippn->address,
sizeof(ippn->address));
- flows[j].flow_prenat.addr_af = ippn->af;
- flows[j].flow_prenat.addr_mask = ippn->mask;
- flows[j].flow_prenat.addr_net = ippn->netaddress;
+ flow->flow_prenat.addr_af = ippn->af;
+ flow->flow_prenat.addr_mask = ippn->mask;
+ flow->flow_prenat.addr_net = ippn->netaddress;
} else {
- flows[j].flow_prenat.addr_af = 0;
+ flow->flow_prenat.addr_af = 0;
}
- flows[j].flow_ipproto = ipproto;
+ flow->flow_ipproto = ipproto;
- if (RB_INSERT(iked_flows, &pol.pol_flows, &flows[j]) == NULL)
+ if (RB_INSERT(iked_flows, &pol.pol_flows, flow) == NULL)
pol.pol_nflows++;
else
warnx("create_ike: duplicate flow");
@@ -3042,6 +3042,10 @@ done:
free(hosts);
}
iaw_free(ikecfg);
+ RB_FOREACH_SAFE(flow, iked_flows, &pol.pol_flows, ftmp) {
+ RB_REMOVE(iked_flows, &pol.pol_flows, flow);
+ free(flow);
+ }
return (ret);
}
diff --git a/sbin/iked/policy.c b/sbin/iked/policy.c
index 450abb90a0f..45c2330dc21 100644
--- a/sbin/iked/policy.c
+++ b/sbin/iked/policy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: policy.c,v 1.50 2019/11/30 15:44:07 tobhe Exp $ */
+/* $OpenBSD: policy.c,v 1.51 2019/12/03 12:38:34 tobhe Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@@ -41,6 +41,10 @@ static __inline int
childsa_cmp(struct iked_childsa *, struct iked_childsa *);
static __inline int
flow_cmp(struct iked_flow *, struct iked_flow *);
+static __inline int
+ addr_cmp(struct iked_addr *, struct iked_addr *, int);
+static __inline int
+ ts_insert_unique(struct iked_addr *, struct iked_tss *, int);
void
@@ -387,6 +391,48 @@ sa_new(struct iked *env, uint64_t ispi, uint64_t rspi,
return (sa);
}
+int
+policy_generate_ts(struct iked_policy *pol)
+{
+ struct iked_flow *flow;
+
+ /* Generate list of traffic selectors from flows */
+ RB_FOREACH(flow, iked_flows, &pol->pol_flows) {
+ if (ts_insert_unique(&flow->flow_src, &pol->pol_tssrc,
+ flow->flow_ipproto) == 1)
+ pol->pol_tssrc_count++;
+ if (ts_insert_unique(&flow->flow_dst, &pol->pol_tsdst,
+ flow->flow_ipproto) == 1)
+ pol->pol_tsdst_count++;
+ }
+ if (pol->pol_tssrc_count > IKEV2_MAXNUM_TSS ||
+ pol->pol_tsdst_count > IKEV2_MAXNUM_TSS)
+ return (-1);
+
+ return (0);
+}
+
+int
+ts_insert_unique(struct iked_addr *addr, struct iked_tss *tss, int ipproto)
+{
+ struct iked_ts *ts;
+
+ /* Remove duplicates */
+ TAILQ_FOREACH(ts, tss, ts_entry) {
+ if (addr_cmp(addr, &ts->ts_addr, 1) == 0)
+ return (0);
+ }
+
+ if ((ts = calloc(1, sizeof(*ts))) == NULL)
+ return (-1);
+
+ ts->ts_ipproto = ipproto;
+ ts->ts_addr = *addr;
+
+ TAILQ_INSERT_TAIL(tss, ts, ts_entry);
+ return (1);
+}
+
void
sa_free(struct iked *env, struct iked_sa *sa)
{