Skip to content

Commit e48ce4f

Browse files
committed
Remove code to match IPv4 pg_hba.conf entries to IPv4-in-IPv6 addresses.
In investigating yesterday's crash report from Hugo Osvaldo Barrera, I only looked back as far as commit f3aec2c where the breakage occurred (which is why I thought the IPv4-in-IPv6 business was undocumented). But actually the logic dates back to commit 3c9bb88 and was simply broken by erroneous refactoring in the later commit. A bit of archives excavation shows that we added the whole business in response to a report that some 2003-era Linux kernels would report IPv4 connections as having IPv4-in-IPv6 addresses. The fact that we've had no complaints since 9.0 seems to be sufficient confirmation that no modern kernels do that, so let's just rip it all out rather than trying to fix it. Do this in the back branches too, thus essentially deciding that our effective behavior since 9.0 is correct. If there are any platforms on which the kernel reports IPv4-in-IPv6 addresses as such, yesterday's fix would have made for a subtle and potentially security-sensitive change in the effective meaning of IPv4 pg_hba.conf entries, which does not seem like a good thing to do in minor releases. So let's let the post-9.0 behavior stand, and change the documentation to match it. In passing, I failed to resist the temptation to wordsmith the description of pg_hba.conf IPv4 and IPv6 address entries a bit. A lot of this text hasn't been touched since we were IPv4-only.
1 parent c99ef9a commit e48ce4f

File tree

4 files changed

+11
-121
lines changed

4 files changed

+11
-121
lines changed

doc/src/sgml/client-auth.sgml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,11 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
250250
</para>
251251

252252
<para>
253-
An IP address given in IPv4 format will match IPv6 connections that
254-
have the corresponding address, for example <literal>127.0.0.1</>
255-
will match the IPv6 address <literal>::ffff:127.0.0.1</>. An entry
256-
given in IPv6 format will match only IPv6 connections, even if the
257-
represented address is in the IPv4-in-IPv6 range. Note that entries
258-
in IPv6 format will be rejected if the system's C library does not have
259-
support for IPv6 addresses.
253+
An entry given in IPv4 format will match only IPv4 connections,
254+
and an entry given in IPv6 format will match only IPv6 connections,
255+
even if the represented address is in the IPv4-in-IPv6 range.
256+
Note that entries in IPv6 format will be rejected if the system's
257+
C library does not have support for IPv6 addresses.
260258
</para>
261259

262260
<para>

src/backend/libpq/hba.c

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -549,42 +549,12 @@ check_db(const char *dbname, const char *role, Oid roleid, char *param_str)
549549
static bool
550550
check_ip(SockAddr *raddr, struct sockaddr * addr, struct sockaddr * mask)
551551
{
552-
if (raddr->addr.ss_family == addr->sa_family)
553-
{
554-
/* Same address family */
555-
if (!pg_range_sockaddr(&raddr->addr,
556-
(struct sockaddr_storage *) addr,
557-
(struct sockaddr_storage *) mask))
558-
return false;
559-
}
560-
#ifdef HAVE_IPV6
561-
else if (addr->sa_family == AF_INET &&
562-
raddr->addr.ss_family == AF_INET6)
563-
{
564-
/*
565-
* If we're connected on IPv6 but the file specifies an IPv4 address
566-
* to match against, promote the latter to an IPv6 address before
567-
* trying to match the client's address.
568-
*/
569-
struct sockaddr_storage addrcopy,
570-
maskcopy;
571-
572-
memcpy(&addrcopy, addr, sizeof(addrcopy));
573-
memcpy(&maskcopy, mask, sizeof(maskcopy));
574-
pg_promote_v4_to_v6_addr(&addrcopy);
575-
pg_promote_v4_to_v6_mask(&maskcopy);
576-
577-
if (!pg_range_sockaddr(&raddr->addr, &addrcopy, &maskcopy))
578-
return false;
579-
}
580-
#endif /* HAVE_IPV6 */
581-
else
582-
{
583-
/* Wrong address family, no IPV6 */
584-
return false;
585-
}
586-
587-
return true;
552+
if (raddr->addr.ss_family == addr->sa_family &&
553+
pg_range_sockaddr(&raddr->addr,
554+
(struct sockaddr_storage *) addr,
555+
(struct sockaddr_storage *) mask))
556+
return true;
557+
return false;
588558
}
589559

590560
/*

src/backend/libpq/ip.c

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -412,79 +412,6 @@ pg_sockaddr_cidr_mask(struct sockaddr_storage * mask, char *numbits, int family)
412412
}
413413

414414

415-
#ifdef HAVE_IPV6
416-
417-
/*
418-
* pg_promote_v4_to_v6_addr --- convert an AF_INET addr to AF_INET6, using
419-
* the standard convention for IPv4 addresses mapped into IPv6 world
420-
*
421-
* The passed addr is modified in place; be sure it is large enough to
422-
* hold the result! Note that we only worry about setting the fields
423-
* that pg_range_sockaddr will look at.
424-
*/
425-
void
426-
pg_promote_v4_to_v6_addr(struct sockaddr_storage * addr)
427-
{
428-
struct sockaddr_in addr4;
429-
struct sockaddr_in6 addr6;
430-
uint32 ip4addr;
431-
432-
memcpy(&addr4, addr, sizeof(addr4));
433-
ip4addr = ntohl(addr4.sin_addr.s_addr);
434-
435-
memset(&addr6, 0, sizeof(addr6));
436-
437-
addr6.sin6_family = AF_INET6;
438-
439-
addr6.sin6_addr.s6_addr[10] = 0xff;
440-
addr6.sin6_addr.s6_addr[11] = 0xff;
441-
addr6.sin6_addr.s6_addr[12] = (ip4addr >> 24) & 0xFF;
442-
addr6.sin6_addr.s6_addr[13] = (ip4addr >> 16) & 0xFF;
443-
addr6.sin6_addr.s6_addr[14] = (ip4addr >> 8) & 0xFF;
444-
addr6.sin6_addr.s6_addr[15] = (ip4addr) & 0xFF;
445-
446-
memcpy(addr, &addr6, sizeof(addr6));
447-
}
448-
449-
/*
450-
* pg_promote_v4_to_v6_mask --- convert an AF_INET netmask to AF_INET6, using
451-
* the standard convention for IPv4 addresses mapped into IPv6 world
452-
*
453-
* This must be different from pg_promote_v4_to_v6_addr because we want to
454-
* set the high-order bits to 1's not 0's.
455-
*
456-
* The passed addr is modified in place; be sure it is large enough to
457-
* hold the result! Note that we only worry about setting the fields
458-
* that pg_range_sockaddr will look at.
459-
*/
460-
void
461-
pg_promote_v4_to_v6_mask(struct sockaddr_storage * addr)
462-
{
463-
struct sockaddr_in addr4;
464-
struct sockaddr_in6 addr6;
465-
uint32 ip4addr;
466-
int i;
467-
468-
memcpy(&addr4, addr, sizeof(addr4));
469-
ip4addr = ntohl(addr4.sin_addr.s_addr);
470-
471-
memset(&addr6, 0, sizeof(addr6));
472-
473-
addr6.sin6_family = AF_INET6;
474-
475-
for (i = 0; i < 12; i++)
476-
addr6.sin6_addr.s6_addr[i] = 0xff;
477-
478-
addr6.sin6_addr.s6_addr[12] = (ip4addr >> 24) & 0xFF;
479-
addr6.sin6_addr.s6_addr[13] = (ip4addr >> 16) & 0xFF;
480-
addr6.sin6_addr.s6_addr[14] = (ip4addr >> 8) & 0xFF;
481-
addr6.sin6_addr.s6_addr[15] = (ip4addr) & 0xFF;
482-
483-
memcpy(addr, &addr6, sizeof(addr6));
484-
}
485-
#endif /* HAVE_IPV6 */
486-
487-
488415
/*
489416
* Run the callback function for the addr/mask, after making sure the
490417
* mask is sane for the addr.

src/include/libpq/ip.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,6 @@ extern int pg_range_sockaddr(const struct sockaddr_storage * addr,
4646
extern int pg_sockaddr_cidr_mask(struct sockaddr_storage * mask,
4747
char *numbits, int family);
4848

49-
#ifdef HAVE_IPV6
50-
extern void pg_promote_v4_to_v6_addr(struct sockaddr_storage * addr);
51-
extern void pg_promote_v4_to_v6_mask(struct sockaddr_storage * addr);
52-
#endif
53-
5449
extern int pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data);
5550

5651
#endif /* IP_H */

0 commit comments

Comments
 (0)