From 6d4e484edc121fc89f0411ffe0e2b306f11c6e0a Mon Sep 17 00:00:00 2001 From: op Date: Thu, 2 May 2024 18:14:33 +0000 Subject: [PATCH] unbreak parsing of IPv6 addresses in file-backed table(5)s The file parser splits the line on the ':' character too for key-value tables, and so mis-parses IPv6 addresses. The "::1 localhost" example in table(5) is actually parsed as key "" and value ":1 localhost". For list tables, the "# @list" marker can be used as a workaround, but for key-valued the parser has to be fixed. There are also some weird edge cases when splitting the lines. Now the parser always splits on the first whitespace or colon, and then strips the spaces. For lines starting with '[' the parser will jump to the matching ']' before attempting to split. So, for example: [::1]:localhost becomes "[::1]" -> "localhost" [::1] example.org becomes "[::1]" -> "example.org" foo: bar becomes "foo" -> "bar" foo::bar becomes "foo" -> ":bar" foo : bar becomes "foo" -> ": bar" etc... This only affects the parser for file table(5)s and makemap(8). Inline tables or "proc" tables are unaffected. ok gilles@ --- usr.sbin/smtpd/table.5 | 21 ++++++++++++--------- usr.sbin/smtpd/util.c | 40 ++++++++++++++++------------------------ 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/usr.sbin/smtpd/table.5 b/usr.sbin/smtpd/table.5 index 65dca359f38..3f4d40938db 100644 --- a/usr.sbin/smtpd/table.5 +++ b/usr.sbin/smtpd/table.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: table.5,v 1.13 2023/12/27 11:29:56 op Exp $ +.\" $OpenBSD: table.5,v 1.14 2024/05/02 18:14:33 op Exp $ .\" .\" Copyright (c) 2013 Eric Faurot .\" Copyright (c) 2013 Gilles Chehade @@ -16,7 +16,7 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .\" -.Dd $Mdocdate: December 27 2023 $ +.Dd $Mdocdate: May 2 2024 $ .Dt TABLE 5 .Os .Sh NAME @@ -173,10 +173,11 @@ of addresses in the table until a match is found. A netaddr table can contain exact addresses or netmasks, and looks as follow: .Bd -literal -offset indent 192.168.1.1 -::1 -ipv6:::1 +[::1] 192.168.1.0/24 .Ed +.Pp +IPv6 addresses must be enclosed in square brackets. .Ss Userinfo tables Userinfo tables are used in rule context to specify an alternate userbase, mapping virtual users to local system users by UID, GID and home directory. @@ -214,11 +215,11 @@ A source table looks as follow: .Bd -literal -offset indent 192.168.1.2 192.168.1.3 -::1 -::2 -ipv6:::3 -ipv6:::4 +[::1] +[::2] .Ed +.Pp +IPv6 address must be enclosed in square brackets. .Ss Mailaddr tables Mailaddr tables are lists of email addresses. They can be used in the following contexts: @@ -254,10 +255,12 @@ outgoing connection. .Pp The format is a mapping from inet4 or inet6 addresses to hostnames: .Bd -literal -offset indent -::1 localhost +[::1] localhost 127.0.0.1 localhost 88.190.23.165 www.opensmtpd.org .Ed +.Pp +IPv6 addresses must be enclosed in square brackets. .Sh SEE ALSO .Xr smtpd.conf 5 , .Xr makemap 8 , diff --git a/usr.sbin/smtpd/util.c b/usr.sbin/smtpd/util.c index d481162c897..e2e03222ab3 100644 --- a/usr.sbin/smtpd/util.c +++ b/usr.sbin/smtpd/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.156 2024/02/11 09:24:26 op Exp $ */ +/* $OpenBSD: util.c,v 1.157 2024/05/02 18:14:33 op Exp $ */ /* * Copyright (c) 2000,2001 Markus Friedl. All rights reserved. @@ -855,7 +855,7 @@ int parse_table_line(FILE *fp, char **line, size_t *linesize, int *type, char **key, char **val, int *malformed) { - char *keyp, *valp, *p; + char *keyp, *valp; ssize_t linelen; *key = NULL; @@ -885,16 +885,17 @@ parse_table_line(FILE *fp, char **line, size_t *linesize, return 0; } - if (*type == T_NONE) { - for (p = keyp; *p; p++) { - if (*p == ' ' || *p == '\t' || *p == ':') { - *type = T_HASH; - break; - } + if (*keyp == '[') { + if ((valp = strchr(keyp, ']')) == NULL) { + *malformed = 1; + return (0); } - if (*type == T_NONE) - *type = T_LIST; - } + valp++; + } else + valp = keyp + strcspn(keyp, " \t:"); + + if (*type == T_NONE) + *type = (*valp == '\0') ? T_LIST : T_HASH; if (*type == T_LIST) { *key = keyp; @@ -902,20 +903,11 @@ parse_table_line(FILE *fp, char **line, size_t *linesize, } /* T_HASH */ - valp = keyp; - strsep(&valp, " \t:"); - if (valp) { - while (*valp) { - if (!isspace((unsigned char)*valp) && - !(*valp == ':' && - isspace((unsigned char)*(valp + 1)))) - break; - ++valp; - } - if (*valp == '\0') - valp = NULL; + if (*valp != '\0') { + *valp++ = '\0'; + valp += strspn(valp, " \t"); } - if (valp == NULL) + if (*valp == '\0') *malformed = 1; *key = keyp; -- 2.20.1