aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/client-auth.sgml20
-rw-r--r--src/backend/libpq/hba.c22
-rw-r--r--src/backend/libpq/pg_hba.conf.sample3
3 files changed, 43 insertions, 2 deletions
diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index 228cfffda33..7ab9305604b 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -283,6 +283,14 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
</para>
<para>
+ A host name specification that starts with a dot
+ (<literal>.</literal>) matches a suffix of the actual host
+ name. So <literal>.example.com</literal> would match
+ <literal>foo.example.com</literal> (but not just
+ <literal>example.com</literal>).
+ </para>
+
+ <para>
When host names are specified
in <filename>pg_hba.conf</filename>, you should make sure that
name resolution is reasonably fast. It can be of advantage to
@@ -311,6 +319,12 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
</para>
<para>
+ Also, a reverse lookup is necessary to implement the suffix
+ matching feature, because the actual client host name needs to
+ be known in order to match it against the pattern.
+ </para>
+
+ <para>
Note that this behavior is consistent with other popular
implementations of host name-based access control, such as the
Apache HTTP Server and TCP Wrappers.
@@ -605,6 +619,12 @@ host postgres all 192.168.93.0/24 ident
# TYPE DATABASE USER ADDRESS METHOD
host postgres all 192.168.12.10/32 md5
+# Allow any user from hosts in the example.com domain to connect to
+# any database if the user's password is correctly supplied.
+#
+# TYPE DATABASE USER ADDRESS METHOD
+host all all .example.com md5
+
# In the absence of preceding "host" lines, these two lines will
# reject all connections from 192.168.54.1 (since that entry will be
# matched first), but allow Kerberos 5 connections from anywhere else
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 17363599626..d9d11d81b9d 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -565,6 +565,26 @@ ipv6eq(struct sockaddr_in6 *a, struct sockaddr_in6 *b)
#endif /* HAVE_IPV6 */
/*
+ * Check whether host name matches pattern.
+ */
+static bool
+hostname_match(const char *pattern, const char *actual_hostname)
+{
+ if (pattern[0] == '.') /* suffix match */
+ {
+ size_t plen = strlen(pattern);
+ size_t hlen = strlen(actual_hostname);
+
+ if (hlen < plen)
+ return false;
+
+ return (pg_strcasecmp(pattern, actual_hostname + (hlen - plen)) == 0);
+ }
+ else
+ return (pg_strcasecmp(pattern, actual_hostname) == 0);
+}
+
+/*
* Check to see if a connecting IP matches a given host name.
*/
static bool
@@ -588,7 +608,7 @@ check_hostname(hbaPort *port, const char *hostname)
port->remote_hostname = pstrdup(remote_hostname);
}
- if (pg_strcasecmp(port->remote_hostname, hostname) != 0)
+ if (!hostname_match(hostname, port->remote_hostname))
return false;
/* Lookup IP from host name and check against original IP */
diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample
index 87fed80eedf..87f84991bca 100644
--- a/src/backend/libpq/pg_hba.conf.sample
+++ b/src/backend/libpq/pg_hba.conf.sample
@@ -32,7 +32,8 @@
# ADDRESS specifies the set of hosts the record matches. It can be a
# host name, or it is made up of an IP address and a CIDR mask that is
# an integer (between 0 and 32 (IPv4) or 128 (IPv6) inclusive) that
-# specifies the number of significant bits in the mask.
+# specifies the number of significant bits in the mask. A host name
+# that starts with a dot (.) matches a suffix of the actual host name.
# Alternatively, you can write an IP address and netmask in separate
# columns to specify the set of hosts. Instead of a CIDR-address, you
# can write "samehost" to match any of the server's own IP addresses,