From 8981ca0467316a5d046d5c257ceea57a49333c87 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Sat, 14 Jan 2017 16:19:54 -0500 Subject: [PATCH] [core] use getaddrinfo,inet_pton vs gethostbyname (fixes #2783) when available, use getaddrinfo(),inet_pton() instead of gethostbyname() NOTE: behavior change: mod_scgi now listens to INADDR_LOOPBACK if "host" is not specified. (Prior behavior was INADDR_ANY.) Backends should not listen on potentially public IPs unless explicitly configured to do so. This change matches a change to mod_fastcgi made in 2008. x-ref "gethostbyname deprecated, should use getaddrinfo" https://redmine.lighttpd.net/issues/2783 --- src/mod_fastcgi.c | 19 +++++++++++++------ src/mod_scgi.c | 23 +++++++++++++++-------- src/network.c | 19 +++++++++++++++++++ 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c index 3abf8957..ec8090ea 100644 --- a/src/mod_fastcgi.c +++ b/src/mod_fastcgi.c @@ -929,8 +929,15 @@ static int fcgi_spawn_connection(server *srv, "ERROR: Unix Domain sockets are not supported."); return -1; #endif + } else if (buffer_string_is_empty(host->host)) { + memset(&fcgi_addr_in, 0, sizeof(fcgi_addr_in)); + fcgi_addr_in.sin_family = AF_INET; + fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + fcgi_addr_in.sin_port = htons(proc->port); + servlen = sizeof(fcgi_addr_in); + fcgi_addr = (struct sockaddr *) &fcgi_addr_in; #if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) - } else if (host->family == AF_INET6 && !buffer_string_is_empty(host->host)) { + } else if (host->family == AF_INET6) { memset(&fcgi_addr_in6, 0, sizeof(fcgi_addr_in6)); fcgi_addr_in6.sin6_family = AF_INET6; inet_pton(AF_INET6, host->host->ptr, (char *) &fcgi_addr_in6.sin6_addr); @@ -941,16 +948,15 @@ static int fcgi_spawn_connection(server *srv, } else { memset(&fcgi_addr_in, 0, sizeof(fcgi_addr_in)); fcgi_addr_in.sin_family = AF_INET; - - if (buffer_string_is_empty(host->host)) { - fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - } else { +#if defined(HAVE_INET_PTON) + inet_pton(AF_INET, host->host->ptr, (char *) &fcgi_addr_in.sin_addr); +#else + { struct hostent *he; /* set a useful default */ fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - if (NULL == (he = gethostbyname(host->host->ptr))) { log_error_write(srv, __FILE__, __LINE__, "sdb", "gethostbyname failed: ", @@ -971,6 +977,7 @@ static int fcgi_spawn_connection(server *srv, memcpy(&(fcgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length); } +#endif fcgi_addr_in.sin_port = htons(proc->port); servlen = sizeof(fcgi_addr_in); diff --git a/src/mod_scgi.c b/src/mod_scgi.c index 74b36cec..fd0eeb90 100644 --- a/src/mod_scgi.c +++ b/src/mod_scgi.c @@ -710,8 +710,15 @@ static int scgi_spawn_connection(server *srv, "ERROR: Unix Domain sockets are not supported."); return -1; #endif + } else if (buffer_string_is_empty(host->host)) { + memset(&scgi_addr_in, 0, sizeof(scgi_addr_in)); + scgi_addr_in.sin_family = AF_INET; + scgi_addr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + scgi_addr_in.sin_port = htons(proc->port); + servlen = sizeof(scgi_addr_in); + scgi_addr = (struct sockaddr *) &scgi_addr_in; #if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) - } else if (host->family == AF_INET6 && !buffer_string_is_empty(host->host)) { + } else if (host->family == AF_INET6) { memset(&scgi_addr_in6, 0, sizeof(scgi_addr_in6)); scgi_addr_in6.sin6_family = AF_INET6; inet_pton(AF_INET6, host->host->ptr, (char *) &scgi_addr_in6.sin6_addr); @@ -722,15 +729,14 @@ static int scgi_spawn_connection(server *srv, } else { memset(&scgi_addr_in, 0, sizeof(scgi_addr_in)); scgi_addr_in.sin_family = AF_INET; - - if (buffer_string_is_empty(host->host)) { - scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY); - } else { +#if defined(HAVE_INET_PTON) + inet_pton(AF_INET, host->host->ptr, (char *) &scgi_addr_in.sin_addr); +#else + { struct hostent *he; - /* set a usefull default */ - scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY); - + /* set a useful default */ + scgi_addr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); if (NULL == (he = gethostbyname(host->host->ptr))) { log_error_write(srv, __FILE__, __LINE__, @@ -752,6 +758,7 @@ static int scgi_spawn_connection(server *srv, memcpy(&(scgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length); } +#endif scgi_addr_in.sin_port = htons(proc->port); servlen = sizeof(scgi_addr_in); diff --git a/src/network.c b/src/network.c index 9afd5f88..2c787d0c 100644 --- a/src/network.c +++ b/src/network.c @@ -216,6 +216,24 @@ static int network_server_init(server *srv, buffer *host_token, size_t sidx) { if (host == NULL) { srv_socket->addr.ipv4.sin_addr.s_addr = htonl(INADDR_ANY); } else { +#ifdef HAVE_INET_PTON /*(reuse HAVE_INET_PTON for presence of getaddrinfo())*/ + struct addrinfo hints, *res; + int r; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) { + log_error_write(srv, __FILE__, __LINE__, + "sssss", "getaddrinfo failed: ", + gai_strerror(r), "'", host, "'"); + goto error_free_socket; + } + + memcpy(&(srv_socket->addr.ipv4), res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); +#else struct hostent *he; if (NULL == (he = gethostbyname(host))) { log_error_write(srv, __FILE__, __LINE__, @@ -235,6 +253,7 @@ static int network_server_init(server *srv, buffer *host_token, size_t sidx) { } memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length); +#endif } srv_socket->addr.ipv4.sin_port = htons(port); addr_len = sizeof(struct sockaddr_in);