From e33a72f289be36ca3b28af4ce5cdc741c07859b8 Mon Sep 17 00:00:00 2001 From: Robin Hack Date: Mon, 7 Sep 2015 14:51:10 +0200 Subject: [PATCH] nwrap: Better check service string sanity. Fixes bug 11501. Patch use strtol() instead of atoi() to convert strings to numbers. This helps better check sanity of service input string. TESTS: Added new test: test_nwrap_getaddrinfo_flags_ai_numericserv Test checks if non-valid input is passed correctly. Signed-off-by: Robin Hack --- src/nss_wrapper.c | 48 ++++++++++++++++++++++++++++-------------------- tests/test_getaddrinfo.c | 27 +++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/src/nss_wrapper.c b/src/nss_wrapper.c index d3395d7..a79bd39 100644 --- a/src/nss_wrapper.c +++ b/src/nss_wrapper.c @@ -3880,6 +3880,8 @@ static int nwrap_getaddrinfo(const char *node, int eai = EAI_SYSTEM; int ret; int rc; + char *end_ptr; + long sl; if (node == NULL && service == NULL) { return EAI_NONAME; @@ -3910,33 +3912,39 @@ static int nwrap_getaddrinfo(const char *node, } if (service != NULL && service[0] != '\0') { - if (isdigit((int)service[0])) { - port = (unsigned short)atoi(service); - } else { - const char *proto = NULL; - struct servent *s; + const char *proto = NULL; + struct servent *s; - if (hints->ai_protocol != 0) { - struct protoent *pent; + errno = 0; + sl = strtol(service, &end_ptr, 10); - pent = getprotobynumber(hints->ai_protocol); - if (pent != NULL) { - proto = pent->p_name; - } + if (*end_ptr == '\0' || end_ptr != service) { + port = sl; + goto port_ok; + } else if (hints->ai_flags & AI_NUMERICSERV) { + return EAI_SERVICE; + } + + if (hints->ai_protocol != 0) { + struct protoent *pent; + + pent = getprotobynumber(hints->ai_protocol); + if (pent != NULL) { + proto = pent->p_name; } + } - s = getservbyname(service, proto); - if (s != NULL) { - port = ntohs(s->s_port); - } else { - if (p != NULL) { - freeaddrinfo(p); - } - return EAI_SERVICE; + s = getservbyname(service, proto); + if (s != NULL) { + port = ntohs(s->s_port); + } else { + if (p != NULL) { + freeaddrinfo(p); } + return EAI_SERVICE; } } - +port_ok: rc = 0; if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET) { rc = inet_pton(AF_INET, node, &addr.in.v4); diff --git a/tests/test_getaddrinfo.c b/tests/test_getaddrinfo.c index b7532ef..42ccc59 100644 --- a/tests/test_getaddrinfo.c +++ b/tests/test_getaddrinfo.c @@ -435,6 +435,32 @@ static void test_nwrap_getaddrinfo_flags_ai_numerichost(void **state) freeaddrinfo(res); } +static void test_nwrap_getaddrinfo_flags_ai_numericserv(void **state) +{ + struct addrinfo hints; + struct addrinfo *res; + int rc; + + (void) state; /* unused */ + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* For wildcard IP address */ + hints.ai_protocol = 0; /* Any protocol */ + hints.ai_canonname = NULL; + + rc = getaddrinfo(NULL, "echo", &hints, &res); + assert_int_equal(rc, EAI_NONAME); + + rc = getaddrinfo(NULL, "80", &hints, &res); + assert_int_equal(rc, 0); + + /* Crippled input */ + rc = getaddrinfo(NULL, "80a1", &hints, &res); + assert_int_equal(rc, EAI_NONAME); +} + int main(void) { int rc; @@ -448,6 +474,7 @@ int main(void) { unit_test(test_nwrap_getaddrinfo_dot), unit_test(test_nwrap_getaddrinfo_ipv6), unit_test(test_nwrap_getaddrinfo_flags_ai_numerichost), + unit_test(test_nwrap_getaddrinfo_flags_ai_numericserv), }; rc = run_tests(tests); -- 1.8.3.1