Index | Thread | Search

From:
YASUOKA Masahiko <yasuoka@openbsd.org>
Subject:
diff: deleting flow/sa by ipsecctl
To:
tobhe@openbsd.org, tech@openbsd.org
Date:
Fri, 26 Jul 2024 11:26:12 +0900

Download raw body.

Thread
  • YASUOKA Masahiko:

    diff: deleting flow/sa by ipsecctl

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);
 		}