diff options
author | Ken Raeburn <raeburn@mit.edu> | 2002-11-13 02:05:16 +0000 |
---|---|---|
committer | Ken Raeburn <raeburn@mit.edu> | 2002-11-13 02:05:16 +0000 |
commit | 516e41d1fa9970f0b6f3bd58f46e77ebe2a3beaf (patch) | |
tree | 4a3cc8741ae7b71f9323c26384dd537fe55e8a0c | |
parent | a181cdb39430ca61c92df6c3200d04b5b98fcf31 (diff) | |
download | krb5-516e41d1fa9970f0b6f3bd58f46e77ebe2a3beaf.tar.gz krb5-516e41d1fa9970f0b6f3bd58f46e77ebe2a3beaf.tar.xz krb5-516e41d1fa9970f0b6f3bd58f46e77ebe2a3beaf.zip |
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
-rw-r--r-- | src/include/ChangeLog | 12 | ||||
-rw-r--r-- | src/include/fake-addrinfo.h | 75 |
2 files changed, 82 insertions, 5 deletions
diff --git a/src/include/ChangeLog b/src/include/ChangeLog index 20576f8d95..8931bebf11 100644 --- a/src/include/ChangeLog +++ b/src/include/ChangeLog @@ -1,3 +1,15 @@ +2002-11-12 Ken Raeburn <raeburn@mit.edu> + + * 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 <hartmans@mit.edu> * spnego-asn1.h: New file. diff --git a/src/include/fake-addrinfo.h b/src/include/fake-addrinfo.h index 30c73005bc..37dc5ccac3 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 <string.h> #endif +#ifdef NUMERIC_SERVICE_BROKEN +# include <ctype.h> /* isdigit */ +# include <stdlib.h> /* 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 <errno.h> 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 |