diff options
author | Sebastien Marie <semarie@cvs.openbsd.org> | 2023-02-06 18:35:53 +0000 |
---|---|---|
committer | Sebastien Marie <semarie@cvs.openbsd.org> | 2023-02-06 18:35:53 +0000 |
commit | 08aceaedb1d485ea4f3ba89f8de65e665eb19568 (patch) | |
tree | 8e8de4f7c02a145c0db6fb06e0290cc01a76d177 /usr.sbin | |
parent | 0914769a7753cbf69c0c95c31608c8dff78f0602 (diff) |
smtpd(8) could abort due to a connection from a local, scoped ipv6 address.
avoid using inet_pton(3) which doesn't support scoped ipv6 address, and use
getaddrinfo(3) instead of.
ok millert@ florian@ kn@
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/smtpd/envelope.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/usr.sbin/smtpd/envelope.c b/usr.sbin/smtpd/envelope.c index f522faf44d3..c9611beb48f 100644 --- a/usr.sbin/smtpd/envelope.c +++ b/usr.sbin/smtpd/envelope.c @@ -1,4 +1,4 @@ -/* $OpenBSD: envelope.c,v 1.50 2022/09/24 17:08:32 millert Exp $ */ +/* $OpenBSD: envelope.c,v 1.51 2023/02/06 18:35:52 semarie Exp $ */ /* * Copyright (c) 2013 Eric Faurot <eric@openbsd.org> @@ -270,24 +270,28 @@ ascii_load_string(char *dest, char *buf, size_t len) static int ascii_load_sockaddr(struct sockaddr_storage *ss, char *buf) { - struct sockaddr_in6 ssin6; - struct sockaddr_in ssin; - - memset(&ssin, 0, sizeof ssin); - memset(&ssin6, 0, sizeof ssin6); - if (!strcmp("local", buf)) { ss->ss_family = AF_LOCAL; } else if (buf[0] == '[' && buf[strlen(buf)-1] == ']') { + struct addrinfo hints, *res0; + buf[strlen(buf)-1] = '\0'; - if (inet_pton(AF_INET6, buf+1, &ssin6.sin6_addr) != 1) + + /* getaddrinfo() is used to support scoped addresses. */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_flags = AI_NUMERICHOST; + if (getaddrinfo(buf+1, NULL, &hints, &res0) != 0) return 0; - ssin6.sin6_family = AF_INET6; - memcpy(ss, &ssin6, sizeof(ssin6)); - ss->ss_len = sizeof(struct sockaddr_in6); + memcpy(ss, res0->ai_addr, res0->ai_addrlen); + ss->ss_len = res0->ai_addrlen; + freeaddrinfo(res0); } else { + struct sockaddr_in ssin; + + memset(&ssin, 0, sizeof ssin); if (inet_pton(AF_INET, buf, &ssin.sin_addr) != 1) return 0; ssin.sin_family = AF_INET; |