diff options
-rw-r--r-- | src/backend/libpq/hba.c | 67 | ||||
-rw-r--r-- | src/backend/libpq/ip.c | 28 | ||||
-rw-r--r-- | src/include/libpq/ip.h | 4 |
3 files changed, 48 insertions, 51 deletions
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index 2e212636211..55d96e16eaf 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.113 2003/09/05 20:31:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.114 2003/09/05 23:07:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -550,12 +550,12 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) char *token; char *db; char *user; - struct addrinfo *file_ip_addr = NULL, - *file_ip_mask = NULL; + struct addrinfo *gai_result; struct addrinfo hints; - struct sockaddr_storage *mask; - char *cidr_slash; int ret; + struct sockaddr_storage addr; + struct sockaddr_storage mask; + char *cidr_slash; Assert(line != NIL); line_number = lfirsti(line); @@ -648,6 +648,7 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) if (cidr_slash) *cidr_slash = '\0'; + /* Get the IP address either way */ hints.ai_flags = AI_NUMERICHOST; hints.ai_family = PF_UNSPEC; hints.ai_socktype = 0; @@ -657,9 +658,8 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) hints.ai_addr = NULL; hints.ai_next = NULL; - /* Get the IP address either way */ - ret = getaddrinfo_all(token, NULL, &hints, &file_ip_addr); - if (ret || !file_ip_addr) + ret = getaddrinfo_all(token, NULL, &hints, &gai_result); + if (ret || !gai_result) { ereport(LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), @@ -667,17 +667,21 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) token, gai_strerror(ret)))); if (cidr_slash) *cidr_slash = '/'; + if (gai_result) + freeaddrinfo_all(hints.ai_family, gai_result); goto hba_syntax; } if (cidr_slash) *cidr_slash = '/'; + memcpy(&addr, gai_result->ai_addr, gai_result->ai_addrlen); + freeaddrinfo_all(hints.ai_family, gai_result); + /* Get the netmask */ if (cidr_slash) { - if (SockAddr_cidr_mask(&mask, cidr_slash + 1, - file_ip_addr->ai_family) < 0) + if (SockAddr_cidr_mask(&mask, cidr_slash + 1, addr.ss_family) < 0) goto hba_syntax; } else @@ -688,17 +692,22 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) goto hba_syntax; token = lfirst(line); - ret = getaddrinfo_all(token, NULL, &hints, &file_ip_mask); - if (ret || !file_ip_mask) + ret = getaddrinfo_all(token, NULL, &hints, &gai_result); + if (ret || !gai_result) + { + if (gai_result) + freeaddrinfo_all(hints.ai_family, gai_result); goto hba_syntax; + } - mask = (struct sockaddr_storage *) file_ip_mask->ai_addr; + memcpy(&mask, gai_result->ai_addr, gai_result->ai_addrlen); + freeaddrinfo_all(hints.ai_family, gai_result); - if (file_ip_addr->ai_family != mask->ss_family) + if (addr.ss_family != mask.ss_family) goto hba_syntax; } - if (file_ip_addr->ai_family != port->raddr.addr.ss_family) + if (addr.ss_family != port->raddr.addr.ss_family) { /* * Wrong address family. We allow only one case: if the @@ -706,20 +715,24 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) * address to IPv6 and try to match that way. */ #ifdef HAVE_IPV6 - if (file_ip_addr->ai_family == AF_INET && + if (addr.ss_family == AF_INET && port->raddr.addr.ss_family == AF_INET6) { - promote_v4_to_v6_addr((struct sockaddr_storage *) file_ip_addr->ai_addr); - promote_v4_to_v6_mask(mask); + promote_v4_to_v6_addr(&addr); + promote_v4_to_v6_mask(&mask); } else #endif /* HAVE_IPV6 */ { - freeaddrinfo_all(hints.ai_family, file_ip_addr); + /* Line doesn't match client port, so ignore it. */ return; } } + /* Ignore line if client port is not in the matching addr range. */ + if (!rangeSockAddr(&port->raddr.addr, &addr, &mask)) + return; + /* Read the rest of the line. */ line = lnext(line); if (!line) @@ -727,16 +740,6 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) parse_hba_auth(line, &port->auth_method, &port->auth_arg, error_p); if (*error_p) goto hba_syntax; - - /* Must meet network restrictions */ - if (!rangeSockAddr(&port->raddr.addr, - (struct sockaddr_storage *) file_ip_addr->ai_addr, - mask)) - goto hba_freeaddr; - - freeaddrinfo_all(hints.ai_family, file_ip_addr); - if (file_ip_mask) - freeaddrinfo_all(hints.ai_family, file_ip_mask); } else goto hba_syntax; @@ -763,12 +766,6 @@ hba_syntax: line_number))); *error_p = true; - -hba_freeaddr: - if (file_ip_addr) - freeaddrinfo_all(hints.ai_family, file_ip_addr); - if (file_ip_mask) - freeaddrinfo_all(hints.ai_family, file_ip_mask); } diff --git a/src/backend/libpq/ip.c b/src/backend/libpq/ip.c index 6ab5f57fd78..4ecc542c27c 100644 --- a/src/backend/libpq/ip.c +++ b/src/backend/libpq/ip.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.20 2003/09/05 20:31:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.21 2003/09/05 23:07:21 tgl Exp $ * * This file and the IPV6 implementation were initially provided by * Nigel Kukard <nkukard@lbsd.net>, Linux Based Systems Design @@ -332,15 +332,15 @@ rangeSockAddrAF_INET6(const struct sockaddr_in6 * addr, * SockAddr_cidr_mask - make a network mask of the appropriate family * and required number of significant bits * - * Note: Returns a static pointer for the mask, so it's not thread safe, - * and a second call will overwrite the data. + * The resulting mask is placed in *mask, which had better be big enough. + * + * Return value is 0 if okay, -1 if not. */ int -SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family) +SockAddr_cidr_mask(struct sockaddr_storage * mask, char *numbits, int family) { long bits; char *endptr; - static struct sockaddr_storage sock; struct sockaddr_in mask4; #ifdef HAVE_IPV6 @@ -359,15 +359,13 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family) ) return -1; - *mask = &sock; - switch (family) { case AF_INET: mask4.sin_addr.s_addr = htonl((0xffffffffUL << (32 - bits)) & 0xffffffffUL); - memcpy(&sock, &mask4, sizeof(mask4)); + memcpy(mask, &mask4, sizeof(mask4)); break; #ifdef HAVE_IPV6 case AF_INET6: @@ -387,7 +385,7 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family) } bits -= 8; } - memcpy(&sock, &mask6, sizeof(mask6)); + memcpy(mask, &mask6, sizeof(mask6)); break; } #endif @@ -395,7 +393,7 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family) return -1; } - sock.ss_family = family; + mask->ss_family = family; return 0; } @@ -406,8 +404,9 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family) * promote_v4_to_v6_addr --- convert an AF_INET addr to AF_INET6, using * the standard convention for IPv4 addresses mapped into IPv6 world * - * The passed addr is modified in place. Note that we only worry about - * setting the fields that rangeSockAddr will look at. + * The passed addr is modified in place; be sure it is large enough to + * hold the result! Note that we only worry about setting the fields + * that rangeSockAddr will look at. */ void promote_v4_to_v6_addr(struct sockaddr_storage * addr) @@ -440,8 +439,9 @@ promote_v4_to_v6_addr(struct sockaddr_storage * addr) * This must be different from promote_v4_to_v6_addr because we want to * set the high-order bits to 1's not 0's. * - * The passed addr is modified in place. Note that we only worry about - * setting the fields that rangeSockAddr will look at. + * The passed addr is modified in place; be sure it is large enough to + * hold the result! Note that we only worry about setting the fields + * that rangeSockAddr will look at. */ void promote_v4_to_v6_mask(struct sockaddr_storage * addr) diff --git a/src/include/libpq/ip.h b/src/include/libpq/ip.h index 9858faaddc9..32f7835c429 100644 --- a/src/include/libpq/ip.h +++ b/src/include/libpq/ip.h @@ -5,7 +5,7 @@ * * Copyright (c) 2003, PostgreSQL Global Development Group * - * $Id: ip.h,v 1.11 2003/09/05 20:31:36 tgl Exp $ + * $Id: ip.h,v 1.12 2003/09/05 23:07:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -30,7 +30,7 @@ extern int rangeSockAddr(const struct sockaddr_storage * addr, const struct sockaddr_storage * netaddr, const struct sockaddr_storage * netmask); -extern int SockAddr_cidr_mask(struct sockaddr_storage ** mask, +extern int SockAddr_cidr_mask(struct sockaddr_storage * mask, char *numbits, int family); #ifdef HAVE_IPV6 |