From 516e41d1fa9970f0b6f3bd58f46e77ebe2a3beaf Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Wed, 13 Nov 2002 02:05:16 +0000 Subject: [PATCH] Better type and bounds checking: * fake-addrinfo.h [NEED_FAKE_GETADDRINFO]: Include errno.h. (fake_getnameinfo): Check that socklen_t size arguments are positive and fit in size_t; return EAI_SYSTEM/EINVAL if not. Use the size_t variants when calling string functions. Work around another AIX bug: [_AIX]: Define NUMERIC_SERVICE_BROKEN. [NUMERIC_SERVICE_BROKEN]: Include ctype.h and stdlib.h. (getaddrinfo) [NUMERIC_SERVICE_BROKEN]: If the service name is a numeric string, save its value and the socket type, pass a null pointer to the real getaddrinfo, and patch the returned results. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@14995 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/ChangeLog | 12 ++++++ src/include/fake-addrinfo.h | 75 ++++++++++++++++++++++++++++++++++--- 2 files changed, 82 insertions(+), 5 deletions(-) diff --git a/src/include/ChangeLog b/src/include/ChangeLog index 20576f8d9..8931bebf1 100644 --- a/src/include/ChangeLog +++ b/src/include/ChangeLog @@ -1,3 +1,15 @@ +2002-11-12 Ken Raeburn + + * fake-addrinfo.h [NEED_FAKE_GETADDRINFO]: Include errno.h. + (fake_getnameinfo): Check that socklen_t size arguments are + positive and fit in size_t; return EAI_SYSTEM/EINVAL if not. Use + the size_t variants when calling string functions. + [_AIX]: Define NUMERIC_SERVICE_BROKEN. + [NUMERIC_SERVICE_BROKEN]: Include ctype.h and stdlib.h. + (getaddrinfo) [NUMERIC_SERVICE_BROKEN]: If the service name is a + numeric string, save its value and the socket type, pass a null + pointer to the real getaddrinfo, and patch the returned results. + 2002-10-23 Sam Hartman * spnego-asn1.h: New file. diff --git a/src/include/fake-addrinfo.h b/src/include/fake-addrinfo.h index 30c73005b..37dc5ccac 100644 --- a/src/include/fake-addrinfo.h +++ b/src/include/fake-addrinfo.h @@ -123,10 +123,20 @@ gai_strerror (int code) /*@*/; # define COPY_FIRST_CANONNAME #endif +#ifdef _AIX +# define NUMERIC_SERVICE_BROKEN +#endif + + #ifdef COPY_FIRST_CANONNAME # include #endif +#ifdef NUMERIC_SERVICE_BROKEN +# include /* isdigit */ +# include /* strtoul */ +#endif + #ifdef _WIN32 #define HAVE_GETADDRINFO 1 #define HAVE_GETNAMEINFO 1 @@ -588,6 +598,7 @@ fake_getaddrinfo (const char *name, const char *serv, return 0; } +#include static inline int fake_getnameinfo (const struct sockaddr *sa, socklen_t len, char *host, socklen_t hostlen, @@ -597,12 +608,24 @@ fake_getnameinfo (const struct sockaddr *sa, socklen_t len, struct hostent *hp; const struct sockaddr_in *sinp; struct servent *sp; + size_t hlen, slen; if (sa->sa_family != AF_INET) { return EAI_FAMILY; } sinp = (const struct sockaddr_in *) sa; + hlen = hostlen; + if (hostlen < 0 || hlen != hostlen) { + errno = EINVAL; + return EAI_SYSTEM; + } + slen = servicelen; + if (servicelen < 0 || slen != servicelen) { + errno = EINVAL; + return EAI_SYSTEM; + } + if (host) { if (flags & NI_NUMERICHOST) { #if (defined(__GNUC__) && defined(__mips__)) || 1 /* thread safety always */ @@ -615,12 +638,12 @@ fake_getnameinfo (const struct sockaddr *sa, socklen_t len, numeric_host: uc = (const unsigned char *) &sinp->sin_addr; sprintf(tmpbuf, "%d.%d.%d.%d", uc[0], uc[1], uc[2], uc[3]); - strncpy(host, tmpbuf, hostlen); + strncpy(host, tmpbuf, hlen); #else char *p; numeric_host: p = inet_ntoa (sinp->sin_addr); - strncpy (host, p, hostlen); + strncpy (host, p, hlen); #endif } else { int herr; @@ -635,7 +658,7 @@ fake_getnameinfo (const struct sockaddr *sa, socklen_t len, /* According to the Open Group spec, getnameinfo can silently truncate, but must still return a null-terminated string. */ - strncpy (host, hp->h_name, hostlen); + strncpy (host, hp->h_name, hlen); } host[hostlen-1] = 0; } @@ -649,7 +672,7 @@ fake_getnameinfo (const struct sockaddr *sa, socklen_t len, if (port < 0 || port > 65535) return EAI_FAIL; sprintf (numbuf, "%d", port); - strncpy (service, numbuf, servicelen); + strncpy (service, numbuf, slen); } else { int serr; GET_SERV_BY_PORT(sinp->sin_port, @@ -657,7 +680,7 @@ fake_getnameinfo (const struct sockaddr *sa, socklen_t len, sp, serr); if (sp == 0) goto numeric_service; - strncpy (service, sp->s_name, servicelen); + strncpy (service, sp->s_name, slen); } service[servicelen-1] = 0; } @@ -752,6 +775,33 @@ getaddrinfo (const char *name, const char *serv, const struct addrinfo *hint, struct addrinfo *ai; #endif +#ifdef NUMERIC_SERVICE_BROKEN + int service_is_numeric = 0; + int service_port = 0; + int socket_type = 0; + + /* AIX 4.3.3 is broken. (Or perhaps out of date?) + + If a numeric service is provided, and it doesn't correspond to + a known service name, an error code (for "host not found") is + returned. If the port maps to a known service, all is + well. */ + if (serv && serv[0] && isdigit(serv[0])) { + unsigned long lport; + char *end; + lport = strtoul(serv, &end, 10); + if (!*end) { + if (lport < 0 || lport > 65535) + return EAI_SOCKTYPE; + service_is_numeric = 1; + service_port = htons(lport); + serv = 0; + if (hint) + socket_type = hint->ai_socktype; + } + } +#endif + aierr = (*gaiptr) (name, serv, hint, result); if (aierr || *result == 0) return aierr; @@ -848,6 +898,21 @@ getaddrinfo (const char *name, const char *serv, const struct addrinfo *hint, } #endif +#ifdef NUMERIC_SERVICE_BROKEN + for (ai = *result; ai; ai = ai->ai_next) { + if (socket_type != 0 && ai->ai_socktype == 0) + ai->ai_socktype = socket_type; + switch (ai->ai_family) { + case AF_INET: + ((struct sockaddr_in *)ai->ai_addr)->sin_port = service_port; + break; + case AF_INET6: + ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = service_port; + break; + } + } +#endif + #ifdef _AIX for (ai = *result; ai; ai = ai->ai_next) { /* AIX 4.3.3 libc is broken. It doesn't set the family or len -- 2.26.2