summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorTobias Heider <tobhe@cvs.openbsd.org>2021-10-26 17:31:23 +0000
committerTobias Heider <tobhe@cvs.openbsd.org>2021-10-26 17:31:23 +0000
commite230659c6f12b27b21c5c648990c8c625aafdd6e (patch)
tree4d10493950da8ab4d4c405030be8206297bb10ec /sbin
parent4424b4f8e6a4e62d023c5653c106f3486b412b1e (diff)
Make proto config option accept a list to allow specifying multiple
protocols for a single policy, e.g. "proto { ipencap, ipv6 }". feedback and ok benno@ ok patrick@
Diffstat (limited to 'sbin')
-rw-r--r--sbin/iked/iked.conf.530
-rw-r--r--sbin/iked/iked.h12
-rw-r--r--sbin/iked/parse.y95
-rw-r--r--sbin/iked/policy.c8
-rw-r--r--sbin/iked/print.c14
-rw-r--r--sbin/iked/types.h3
6 files changed, 114 insertions, 48 deletions
diff --git a/sbin/iked/iked.conf.5 b/sbin/iked/iked.conf.5
index df1a0f09442..7787cf851d5 100644
--- a/sbin/iked/iked.conf.5
+++ b/sbin/iked/iked.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: iked.conf.5,v 1.86 2021/08/03 12:46:30 tobhe Exp $
+.\" $OpenBSD: iked.conf.5,v 1.87 2021/10/26 17:31:22 tobhe Exp $
.\"
.\" Copyright (c) 2010 - 2014 Reyk Floeter <reyk@openbsd.org>
.\" Copyright (c) 2004 Mathieu Sauve-Frankel All rights reserved.
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: August 3 2021 $
+.Dd $Mdocdate: October 26 2021 $
.Dt IKED.CONF 5
.Os
.Sh NAME
@@ -93,6 +93,16 @@ keyword, for example:
.Bd -literal -offset indent
include "/etc/macros.conf"
.Ed
+.Pp
+Certain parameters can be expressed as lists, in which case
+.Xr iked 8
+generates all the necessary flow combinations.
+For example:
+.Bd -literal -offset indent
+ikev2 esp proto { tcp, udp } \e
+ from 192.168.1.1 to 10.0.0.18 \e
+ peer 192.168.10.1
+.Ed
.Sh MACROS
Macros can be defined that will later be expanded in context.
Macro names must start with a letter, digit, or underscore,
@@ -354,7 +364,13 @@ Note that this only matters for IKEv2 endpoints and does not
restrict the traffic selectors to negotiate flows with different
address families, e.g. IPv6 flows negotiated by IPv4 endpoints.
.Pp
-.It Ic proto Ar protocol
+.It Xo
+.Ic proto Ar protocol
+.Xc
+.It Xo
+.Ic proto
+.Ic { Ar protocol ... Ic }
+.Xc
The optional
.Ic proto
parameter restricts the flow to a specific IP protocol.
@@ -368,6 +384,14 @@ For a list of all the protocol name to number mappings used by
see the file
.Pa /etc/protocols .
.Pp
+Multiple
+.Ar protocol
+entries can be specified, separated by commas or whitespace,
+if enclosed in curly brackets:
+.Bd -literal -offset indent
+proto { tcp, udp }
+.Ed
+.Pp
.It Ic rdomain Ar number
Specify a different routing domain for unencrypted traffic.
The resulting IPsec SAs will match outgoing packets in the specified
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
index b8abfcf1c6c..6843d4b2938 100644
--- a/sbin/iked/iked.h
+++ b/sbin/iked/iked.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: iked.h,v 1.194 2021/10/12 10:01:59 tobhe Exp $ */
+/* $OpenBSD: iked.h,v 1.195 2021/10/26 17:31:22 tobhe Exp $ */
/*
* Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
@@ -242,10 +242,9 @@ struct iked_policy {
#define IKED_SKIP_FLAGS 0
#define IKED_SKIP_AF 1
-#define IKED_SKIP_PROTO 2
-#define IKED_SKIP_SRC_ADDR 3
-#define IKED_SKIP_DST_ADDR 4
-#define IKED_SKIP_COUNT 5
+#define IKED_SKIP_SRC_ADDR 2
+#define IKED_SKIP_DST_ADDR 3
+#define IKED_SKIP_COUNT 4
struct iked_policy *pol_skip[IKED_SKIP_COUNT];
uint8_t pol_flags;
@@ -265,7 +264,8 @@ struct iked_policy {
int pol_af;
int pol_rdomain;
uint8_t pol_saproto;
- unsigned int pol_ipproto;
+ unsigned int pol_ipproto[IKED_IPPROTO_MAX];
+ unsigned int pol_nipproto;
struct iked_addr pol_peer;
struct iked_static_id pol_peerid;
diff --git a/sbin/iked/parse.y b/sbin/iked/parse.y
index 1f3267ebc54..8eac03668af 100644
--- a/sbin/iked/parse.y
+++ b/sbin/iked/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.134 2021/10/15 15:01:27 naddy Exp $ */
+/* $OpenBSD: parse.y,v 1.135 2021/10/26 17:31:22 tobhe Exp $ */
/*
* Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
@@ -374,7 +374,7 @@ void copy_transforms(unsigned int,
const struct ipsec_xf **, unsigned int,
struct iked_transform **, unsigned int *,
struct iked_transform *, size_t);
-int create_ike(char *, int, uint8_t,
+int create_ike(char *, int, struct ipsec_addr_wrap *,
int, struct ipsec_hosts *,
struct ipsec_hosts *, struct ipsec_mode *,
struct ipsec_mode *, uint8_t,
@@ -388,9 +388,9 @@ uint8_t x2i(unsigned char *);
int parsekey(unsigned char *, size_t, struct iked_auth *);
int parsekeyfile(char *, struct iked_auth *);
void iaw_free(struct ipsec_addr_wrap *);
-static int create_flow(struct iked_policy *pol, struct ipsec_addr_wrap *ipa,
+static int create_flow(struct iked_policy *pol, int, struct ipsec_addr_wrap *ipa,
struct ipsec_addr_wrap *ipb);
-static int expand_flows(struct iked_policy *, struct ipsec_addr_wrap *,
+static int expand_flows(struct iked_policy *, int, struct ipsec_addr_wrap *,
struct ipsec_addr_wrap *);
static struct ipsec_addr_wrap *
expand_keyword(struct ipsec_addr_wrap *);
@@ -407,7 +407,6 @@ typedef struct {
uint8_t ikemode;
uint8_t dir;
uint8_t satype;
- uint8_t proto;
char *string;
uint16_t port;
struct ipsec_hosts *hosts;
@@ -415,6 +414,7 @@ typedef struct {
struct ipsec_addr_wrap *anyhost;
struct ipsec_addr_wrap *host;
struct ipsec_addr_wrap *cfg;
+ struct ipsec_addr_wrap *proto;
struct {
char *srcid;
char *dstid;
@@ -449,8 +449,7 @@ typedef struct {
%token <v.number> NUMBER
%type <v.string> string
%type <v.satype> satype
-%type <v.proto> proto
-%type <v.number> protoval
+%type <v.proto> proto proto_list protoval
%type <v.hosts> hosts hosts_list
%type <v.port> port
%type <v.number> portval af rdomain
@@ -630,10 +629,23 @@ af : /* empty */ { $$ = AF_UNSPEC; }
| INET6 { $$ = AF_INET6; }
;
-proto : /* empty */ { $$ = 0; }
+proto : /* empty */ { $$ = NULL; }
| PROTO protoval { $$ = $2; }
- | PROTO ESP { $$ = IPPROTO_ESP; }
- | PROTO AH { $$ = IPPROTO_AH; }
+ | PROTO '{' proto_list '}' { $$ = $3; }
+ ;
+
+proto_list : protoval { $$ = $1; }
+ | proto_list comma protoval {
+ if ($3 == NULL)
+ $$ = $1;
+ else if ($1 == NULL)
+ $$ = $3;
+ else {
+ $1->tail->next = $3;
+ $1->tail = $3->tail;
+ $$ = $1;
+ }
+ }
;
protoval : STRING {
@@ -644,7 +656,12 @@ protoval : STRING {
yyerror("unknown protocol: %s", $1);
YYERROR;
}
- $$ = p->p_proto;
+
+ if (($$ = calloc(1, sizeof(*$$))) == NULL)
+ err(1, "protoval: calloc");
+
+ $$->type = p->p_proto;
+ $$->tail = $$;
free($1);
}
| NUMBER {
@@ -652,6 +669,11 @@ protoval : STRING {
yyerror("protocol outside range");
YYERROR;
}
+ if (($$ = calloc(1, sizeof(*$$))) == NULL)
+ err(1, "protoval: calloc");
+
+ $$->type = $1;
+ $$->tail = $$;
}
;
@@ -2444,7 +2466,7 @@ copy_transforms(unsigned int type,
}
int
-create_ike(char *name, int af, uint8_t ipproto,
+create_ike(char *name, int af, struct ipsec_addr_wrap *ipproto,
int rdomain, struct ipsec_hosts *hosts,
struct ipsec_hosts *peers, struct ipsec_mode *ike_sa,
struct ipsec_mode *ipsec_sa, uint8_t saproto,
@@ -2454,7 +2476,7 @@ create_ike(char *name, int af, uint8_t ipproto,
struct ipsec_addr_wrap *ikecfg, char *iface)
{
char idstr[IKED_ID_SIZE];
- struct ipsec_addr_wrap *ipa, *ipb;
+ struct ipsec_addr_wrap *ipa, *ipb, *ipp;
struct iked_auth *ikeauth;
struct iked_policy pol;
struct iked_proposal *p, *ptmp;
@@ -2473,7 +2495,15 @@ create_ike(char *name, int af, uint8_t ipproto,
pol.pol_certreqtype = env->sc_certreqtype;
pol.pol_af = af;
pol.pol_saproto = saproto;
- pol.pol_ipproto = ipproto;
+ for (i = 0, ipp = ipproto; ipp; ipp = ipp->next, i++) {
+ if (i > IKED_IPPROTO_MAX) {
+ yyerror("too many protocols");
+ return (-1);
+ }
+ pol.pol_ipproto[i] = ipp->type;
+ pol.pol_nipproto++;
+ }
+
pol.pol_flags = flags;
pol.pol_rdomain = rdomain;
memcpy(&pol.pol_auth, authtype, sizeof(struct iked_auth));
@@ -2823,13 +2853,15 @@ create_ike(char *name, int af, uint8_t ipproto,
}
}
- if (hosts == NULL || hosts->src == NULL || hosts->dst == NULL)
- fatalx("create_ike: no traffic selectors/flows");
-
for (ipa = hosts->src, ipb = hosts->dst; ipa && ipb;
- ipa = ipa->next, ipb = ipb->next)
- if (expand_flows(&pol, ipa, ipb))
- fatalx("create_ike: invalid flow");
+ ipa = ipa->next, ipb = ipb->next) {
+ for (j = 0; j < pol.pol_nipproto; j++)
+ if (expand_flows(&pol, pol.pol_ipproto[j], ipa, ipb))
+ fatalx("create_ike: invalid flow");
+ if (pol.pol_nipproto == 0)
+ if (expand_flows(&pol, 0, ipa, ipb))
+ fatalx("create_ike: invalid flow");
+ }
for (j = 0, ipa = ikecfg; ipa; ipa = ipa->next, j++) {
if (j >= IKED_CFG_MAX)
@@ -2918,6 +2950,7 @@ done:
free(hosts);
}
iaw_free(ikecfg);
+ iaw_free(ipproto);
RB_FOREACH_SAFE(flow, iked_flows, &pol.pol_flows, ftmp) {
RB_REMOVE(iked_flows, &pol.pol_flows, flow);
free(flow);
@@ -2929,7 +2962,7 @@ done:
}
static int
-create_flow(struct iked_policy *pol, struct ipsec_addr_wrap *ipa,
+create_flow(struct iked_policy *pol, int proto, struct ipsec_addr_wrap *ipa,
struct ipsec_addr_wrap *ipb)
{
struct iked_flow *flow;
@@ -2969,8 +3002,8 @@ create_flow(struct iked_policy *pol, struct ipsec_addr_wrap *ipa,
}
flow->flow_dir = IPSP_DIRECTION_OUT;
+ flow->flow_ipproto = proto;
flow->flow_saproto = pol->pol_saproto;
- flow->flow_ipproto = pol->pol_ipproto;
flow->flow_rdomain = pol->pol_rdomain;
if (RB_INSERT(iked_flows, &pol->pol_flows, flow) == NULL)
@@ -2984,11 +3017,15 @@ create_flow(struct iked_policy *pol, struct ipsec_addr_wrap *ipa,
}
static int
-expand_flows(struct iked_policy *pol, struct ipsec_addr_wrap *src,
+expand_flows(struct iked_policy *pol, int proto, struct ipsec_addr_wrap *src,
struct ipsec_addr_wrap *dst)
{
struct ipsec_addr_wrap *ipa = NULL, *ipb = NULL;
int ret = -1;
+ int srcaf, dstaf;
+
+ srcaf = src->af;
+ dstaf = dst->af;
if (src->af == AF_UNSPEC &&
dst->af == AF_UNSPEC) {
@@ -2998,7 +3035,7 @@ expand_flows(struct iked_policy *pol, struct ipsec_addr_wrap *src,
ipb = expand_keyword(dst);
if (!ipa || !ipb)
goto done;
- if (create_flow(pol, ipa, ipb))
+ if (create_flow(pol, proto, ipa, ipb))
goto done;
iaw_free(ipa);
@@ -3008,26 +3045,28 @@ expand_flows(struct iked_policy *pol, struct ipsec_addr_wrap *src,
ipb = expand_keyword(dst);
if (!ipa || !ipb)
goto done;
- if (create_flow(pol, ipa, ipb))
+ if (create_flow(pol, proto, ipa, ipb))
goto done;
} else if (src->af == AF_UNSPEC) {
src->af = dst->af;
ipa = expand_keyword(src);
if (!ipa)
goto done;
- if (create_flow(pol, ipa, dst))
+ if (create_flow(pol, proto, ipa, dst))
goto done;
} else if (dst->af == AF_UNSPEC) {
dst->af = src->af;
ipa = expand_keyword(dst);
if (!ipa)
goto done;
- if (create_flow(pol, src, ipa))
+ if (create_flow(pol, proto, src, ipa))
goto done;
- } else if (create_flow(pol, src, dst))
+ } else if (create_flow(pol, proto, src, dst))
goto done;
ret = 0;
done:
+ src->af = srcaf;
+ dst->af = dstaf;
iaw_free(ipa);
iaw_free(ipb);
return (ret);
diff --git a/sbin/iked/policy.c b/sbin/iked/policy.c
index 8869b00e2f3..b26e4825e64 100644
--- a/sbin/iked/policy.c
+++ b/sbin/iked/policy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: policy.c,v 1.84 2021/10/12 10:01:59 tobhe Exp $ */
+/* $OpenBSD: policy.c,v 1.85 2021/10/26 17:31:22 tobhe Exp $ */
/*
* Copyright (c) 2020-2021 Tobias Heider <tobhe@openbsd.org>
@@ -223,9 +223,6 @@ policy_test(struct iked *env, struct iked_policy *key)
else if (key->pol_af && p->pol_af &&
key->pol_af != p->pol_af)
p = p->pol_skip[IKED_SKIP_AF];
- else if (key->pol_ipproto && p->pol_ipproto &&
- key->pol_ipproto != p->pol_ipproto)
- p = p->pol_skip[IKED_SKIP_PROTO];
else if (sockaddr_cmp((struct sockaddr *)&key->pol_peer.addr,
(struct sockaddr *)&p->pol_peer.addr,
p->pol_peer.addr_mask) != 0)
@@ -334,9 +331,6 @@ policy_calc_skip_steps(struct iked_policies *policies)
prev->pol_af != AF_UNSPEC &&
cur->pol_af != prev->pol_af)
IKED_SET_SKIP_STEPS(IKED_SKIP_AF);
- if (cur->pol_ipproto && prev->pol_ipproto &&
- cur->pol_ipproto != prev->pol_ipproto)
- IKED_SET_SKIP_STEPS(IKED_SKIP_PROTO);
if (IKED_ADDR_NEQ(&cur->pol_peer, &prev->pol_peer))
IKED_SET_SKIP_STEPS(IKED_SKIP_DST_ADDR);
if (IKED_ADDR_NEQ(&cur->pol_local, &prev->pol_local))
diff --git a/sbin/iked/print.c b/sbin/iked/print.c
index 0ad493006e2..607e9333f15 100644
--- a/sbin/iked/print.c
+++ b/sbin/iked/print.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: print.c,v 1.2 2021/03/21 22:18:00 tobhe Exp $ */
+/* $OpenBSD: print.c,v 1.3 2021/10/26 17:31:22 tobhe Exp $ */
/*
* Copyright (c) 2019-2021 Tobias Heider <tobias.heider@stusta.de>
@@ -90,8 +90,16 @@ print_policy(struct iked_policy *pol)
print_verbose(" %s", print_xf(pol->pol_saproto, 0, saxfs));
- if (pol->pol_ipproto)
- print_verbose(" proto %s", print_proto(pol->pol_ipproto));
+ if (pol->pol_nipproto > 0) {
+ print_verbose(" proto {");
+ for (i = 0; i < pol->pol_nipproto; i++) {
+ if (i == 0)
+ print_verbose(" %s", print_proto(pol->pol_ipproto[i]));
+ else
+ print_verbose(", %s", print_proto(pol->pol_ipproto[i]));
+ }
+ print_verbose(" }");
+ }
if (pol->pol_af) {
if (pol->pol_af == AF_INET)
diff --git a/sbin/iked/types.h b/sbin/iked/types.h
index 18f83044b82..dd81c3e6cc1 100644
--- a/sbin/iked/types.h
+++ b/sbin/iked/types.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: types.h,v 1.45 2021/09/01 15:30:06 tobhe Exp $ */
+/* $OpenBSD: types.h,v 1.46 2021/10/26 17:31:22 tobhe Exp $ */
/*
* Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
@@ -63,6 +63,7 @@
#define IKED_PSK_SIZE 1024 /* XXX should be dynamic */
#define IKED_MSGBUF_MAX 8192
#define IKED_CFG_MAX 16 /* maximum CP attributes */
+#define IKED_IPPROTO_MAX 16
#define IKED_TAG_SIZE 64
#define IKED_CYCLE_BUFFERS 8 /* # of static buffers for mapping */
#define IKED_PASSWORD_SIZE 256 /* limited by most EAP types */