smtpd(8) could abort due to a connection from a local, scoped ipv6 address.
authorsemarie <semarie@openbsd.org>
Mon, 6 Feb 2023 18:35:52 +0000 (18:35 +0000)
committersemarie <semarie@openbsd.org>
Mon, 6 Feb 2023 18:35:52 +0000 (18:35 +0000)
avoid using inet_pton(3) which doesn't support scoped ipv6 address, and use
getaddrinfo(3) instead of.

ok millert@ florian@ kn@

usr.sbin/smtpd/envelope.c

index f522faf..c9611be 100644 (file)
@@ -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;