On tor, 2010-10-21 at 06:38 +0300, Peter Eisentraut wrote:
> So, as previously indicated, let's add some wildcard support to the
> pg_hba.conf host name feature.  After looking around a bit, two syntaxes
> appear to be on offer:
> 
> 1. TCP Wrappers style, leading dot indicates suffix match.
> So .example.com matches anything.example.com.  Not sure how useful that
> would be, but it could be implemented in about 3 lines of code.

Here is a patch for that.

diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index 228cfff..7ab9305 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 1736359..d9d11d8 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 87fed80..87f8499 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,
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to