From: YASUOKA Masahiko Subject: diff: deleting flow/sa by ipsecctl To: tobhe@openbsd.org, tech@openbsd.org Date: Fri, 26 Jul 2024 11:26:12 +0900 Hello, When we have flows and SAs like following, % doas ipsecctl -sa FLOWS: flow esp in proto udp from 203.0.113.80 port l2tp to 192.0.2.51 port l2tp peer 203.0.113.80 srcid 192.0.2.51/32 dstid 10.0.2.15/32 type require flow esp out proto udp from 192.0.2.51 port l2tp to 203.0.113.80 port l2tp peer 203.0.113.80 srcid 192.0.2.51/32 dstid 10.0.2.15/32 type require SAD: esp transport from 203.0.113.80 to 192.0.2.51 spi 0x94194be1 auth hmac-sha1 enc aes esp transport from 192.0.2.51 to 203.0.113.80 spi 0xc1c584a2 auth hmac-sha1 enc aes % if deleting the first flow is desired, % doas ipsecctl -ndf - flow esp in proto udp from 203.0.113.80 port l2tp to 192.0.2.51 port l2tp peer 203.0.113.80 srcid 192.0.2.51/32 dstid 10.0.2.15/32 type require stdin: 1: syntax error ipsecctl: Syntax error in config file: ipsec rules not loaded % error. Because ipsecctl doesn't accept address/mask format for {src,dst}id. also, deleting the first SA is desired, % doas ipsecctl -ndf - esp transport from 203.0.113.80 to 192.0.2.51 spi 0x94194be1 auth hmac-sha1 enc aes stdin: 1: no authentication key specified ipsecctl: Syntax error in config file: ipsec rules not loaded % fails because ipsecctl requires authentication and encryption key always. The diff changes ipsecctl to accept addr/mask of flow id and SA without keys when deleting. As for the ID, /32 can be deleted when show. I didn't take that way because IP address/mask is valid in RFC and pfkey seems to support that. ok? Index: ipsecctl.c =================================================================== RCS file: /disk/cvs/openbsd/src/sbin/ipsecctl/ipsecctl.c,v diff -u -p -r1.88 ipsecctl.c --- ipsecctl.c 6 Feb 2024 05:39:28 -0000 1.88 +++ ipsecctl.c 26 Jul 2024 02:06:57 -0000 @@ -112,7 +112,7 @@ ipsecctl_rules(char *filename, int opts) TAILQ_INIT(&ipsec.rule_queue); TAILQ_INIT(&ipsec.bundle_queue); - if (parse_rules(filename, &ipsec) < 0) { + if (parse_rules(filename, &ipsec, opts) < 0) { warnx("Syntax error in config file: ipsec rules not loaded"); error = 1; } else { Index: ipsecctl.h =================================================================== RCS file: /disk/cvs/openbsd/src/sbin/ipsecctl/ipsecctl.h,v diff -u -p -r1.77 ipsecctl.h --- ipsecctl.h 9 Oct 2023 15:32:14 -0000 1.77 +++ ipsecctl.h 26 Jul 2024 02:06:57 -0000 @@ -242,7 +242,7 @@ struct ipsecctl { struct ipsec_bundle_queue bundle_queue; }; -int parse_rules(const char *, struct ipsecctl *); +int parse_rules(const char *, struct ipsecctl *, int); int cmdline_symset(char *); int ipsecctl_add_rule(struct ipsecctl *, struct ipsec_rule *); void ipsecctl_free_rule(struct ipsec_rule *); Index: parse.y =================================================================== RCS file: /disk/cvs/openbsd/src/sbin/ipsecctl/parse.y,v diff -u -p -r1.183 parse.y --- parse.y 7 Aug 2023 04:10:08 -0000 1.183 +++ parse.y 26 Jul 2024 02:06:57 -0000 @@ -87,6 +87,7 @@ int cmdline_symset(char *); static struct ipsecctl *ipsec = NULL; static int debug = 0; +static int delete = 0; const struct ipsec_xf authxfs[] = { { "unknown", AUTHXF_UNKNOWN, 0, 0 }, @@ -668,6 +669,22 @@ type : /* empty */ { ; id : STRING { $$ = $1; } + | STRING '/' NUMBER { + struct in6_addr ia; + char *str; + + if (!(0 <= $3 && + ((inet_pton(AF_INET, $1, &ia) == 1 && $3 <= 32) || + (inet_pton(AF_INET6, $1, &ia) == 1 && $3 <= 128)))){ + free($1); + yyerror("invalid ip address/mask"); + YYERROR; + } + if (asprintf(&str, "%s/%d", $1, (int)$3) == -1) + err(1, "id: asprintf"); + free($1); + $$ = str; + } ; spispec : SPI STRING { @@ -1432,12 +1449,13 @@ popfile(void) } int -parse_rules(const char *filename, struct ipsecctl *ipsecx) +parse_rules(const char *filename, struct ipsecctl *ipsecx, int opts) { struct sym *sym; int errors = 0; ipsec = ipsecx; + delete = (opts & IPSECCTL_OPT_DELETE)? 1 : 0; if ((file = pushfile(filename, 1)) == NULL) { return (-1); @@ -2412,7 +2430,8 @@ validate_sa(u_int32_t spi, u_int8_t saty return (0); } if (xfs && xfs->authxf) { - if (!authkey && xfs->authxf != &authxfs[AUTHXF_NONE]) { + if (!delete && + !authkey && xfs->authxf != &authxfs[AUTHXF_NONE]) { yyerror("no authentication key specified"); return (0); } @@ -2423,7 +2442,7 @@ validate_sa(u_int32_t spi, u_int8_t saty } } if (xfs && xfs->encxf) { - if (!enckey && xfs->encxf != &encxfs[ENCXF_NULL]) { + if (!delete && !enckey && xfs->encxf != &encxfs[ENCXF_NULL]) { yyerror("no encryption key specified"); return (0); }