diff options
author | Tobias Heider <tobhe@cvs.openbsd.org> | 2021-10-26 17:31:23 +0000 |
---|---|---|
committer | Tobias Heider <tobhe@cvs.openbsd.org> | 2021-10-26 17:31:23 +0000 |
commit | e230659c6f12b27b21c5c648990c8c625aafdd6e (patch) | |
tree | 4d10493950da8ab4d4c405030be8206297bb10ec /sbin | |
parent | 4424b4f8e6a4e62d023c5653c106f3486b412b1e (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.5 | 30 | ||||
-rw-r--r-- | sbin/iked/iked.h | 12 | ||||
-rw-r--r-- | sbin/iked/parse.y | 95 | ||||
-rw-r--r-- | sbin/iked/policy.c | 8 | ||||
-rw-r--r-- | sbin/iked/print.c | 14 | ||||
-rw-r--r-- | sbin/iked/types.h | 3 |
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 */ |