Allow full SSL certificate verification (wherein libpq checks its host name
authorTom Lane
Wed, 14 Jul 2010 17:09:54 +0000 (17:09 +0000)
committerTom Lane
Wed, 14 Jul 2010 17:09:54 +0000 (17:09 +0000)
parameter against server cert's CN field) to succeed in the case where
both host and hostaddr are specified.  As with the existing precedents
for Kerberos, GSSAPI, SSPI, it is the calling application's responsibility
that host and hostaddr match up --- we just use the host name as given.
Per bug #5559 from Christopher Head.

In passing, make the error handling and messages for the no-host-name-given
failure more consistent among these four cases, and correct a lie in the
documentation: we don't attempt to reverse-lookup host from hostaddr
if host is missing.

Back-patch to 8.4 where SSL cert verification was introduced.

doc/src/sgml/libpq.sgml
src/interfaces/libpq/fe-auth.c
src/interfaces/libpq/fe-secure.c
src/interfaces/libpq/libpq-int.h

index 9e047b110d72eaec2033468cc0b38efc9cb91bd9..3073c1f6dbacdd11ad047f0c7c8be7feec849aa0 100644 (file)
@@ -1,4 +1,4 @@
-
+
 
 
  <application>libpq</application> - C Library
 
           
            Using hostaddr instead of host allows the
-           application to avoid a host name look-up, which might be important in
-           applications with time constraints. However, Kerberos and GSSAPI authentication
-           requires the host name. The following therefore applies: If
-           host is specified without hostaddr, a host name
-           lookup occurs. If hostaddr is specified without
-           host, the value for hostaddr gives the remote
-           address. When Kerberos is used, a reverse name query occurs to obtain
-           the host name for Kerberos. If both
-           host and hostaddr are specified, the value for
-           hostaddr gives the remote address; the value for
-           host is ignored, unless Kerberos is used, in which case that
-           value is used for Kerberos authentication. (Note that authentication is
-           likely to fail if libpq is passed a host name
-           that is not the name of the machine at hostaddr.)  Also,
-           host rather than hostaddr is used to identify
-           the connection in ~/.pgpass (see
+           application to avoid a host name look-up, which might be important
+           in applications with time constraints. However, a host name is
+           required for Kerberos, GSSAPI, or SSPI authentication, as well as
+           for full SSL certificate verification. The following rules are
+           used:
+           If host is specified without hostaddr,
+           a host name lookup occurs.
+           If hostaddr is specified without host,
+           the value for hostaddr gives the server address.
+           The connection attempt will fail in any of the cases where a
+           host name is required.
+           If both host and hostaddr are specified,
+           the value for hostaddr gives the server address.
+           The value for host is ignored unless needed for
+           authentication or verification purposes, in which case it will be
+           used as the host name.  Note that authentication is likely to fail
+           if host is not the name of the machine at
+           hostaddr.
+           Also, note that host rather than hostaddr
+           is used to identify the connection in ~/.pgpass (see
            ).
           
 
index 65f3e2625c00fae46b9d7447275e2f9a805c316d..27493075c4371dcab19424e6a43dc1ea199a0c2a 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/interfaces/libpq/fe-auth.c,v 1.144 2010/03/08 10:01:12 mha Exp $
+ *   $PostgreSQL: pgsql/src/interfaces/libpq/fe-auth.c,v 1.144.4.1 2010/07/14 17:09:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -206,10 +206,10 @@ pg_krb5_sendauth(PGconn *conn)
 
    info.pg_krb5_initialised = 0;
 
-   if (!conn->pghost)
+   if (!(conn->pghost && conn->pghost[0] != '\0'))
    {
        printfPQExpBuffer(&conn->errorMessage,
-                         "pg_krb5_sendauth: hostname must be specified for Kerberos authentication\n");
+                         libpq_gettext("host name must be specified\n"));
        return STATUS_ERROR;
    }
 
@@ -426,9 +426,10 @@ pg_GSS_startup(PGconn *conn)
    int         maxlen;
    gss_buffer_desc temp_gbuf;
 
-   if (!conn->pghost)
+   if (!(conn->pghost && conn->pghost[0] != '\0'))
    {
-       printfPQExpBuffer(&conn->errorMessage, libpq_gettext("host name must be specified\n"));
+       printfPQExpBuffer(&conn->errorMessage,
+                         libpq_gettext("host name must be specified\n"));
        return STATUS_ERROR;
    }
 
@@ -652,9 +653,10 @@ pg_SSPI_startup(PGconn *conn, int use_negotiate)
     * but not more complex. We can skip the @REALM part, because Windows will
     * fill that in for us automatically.
     */
-   if (conn->pghost == NULL)
+   if (!(conn->pghost && conn->pghost[0] != '\0'))
    {
-       printfPQExpBuffer(&conn->errorMessage, libpq_gettext("host name must be specified\n"));
+       printfPQExpBuffer(&conn->errorMessage,
+                         libpq_gettext("host name must be specified\n"));
        return STATUS_ERROR;
    }
    conn->sspitarget = malloc(strlen(conn->krbsrvname) + strlen(conn->pghost) + 2);
index 9558010a81cebb16e0b367a31237020b57700600..14a1dcd45996b34d3557d57551f390c9eace1369 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.135 2010/07/06 19:19:01 momjian Exp $
+ *   $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.135.2.1 2010/07/14 17:09:54 tgl Exp $
  *
  * NOTES
  *
@@ -589,16 +589,16 @@ static bool
 verify_peer_name_matches_certificate(PGconn *conn)
 {
    /*
-    * If told not to verify the peer name, don't do it. Return 0 indicating
+    * If told not to verify the peer name, don't do it. Return true indicating
     * that the verification was successful.
     */
    if (strcmp(conn->sslmode, "verify-full") != 0)
        return true;
 
-   if (conn->pghostaddr)
+   if (!(conn->pghost && conn->pghost[0] != '\0'))
    {
        printfPQExpBuffer(&conn->errorMessage,
-                         libpq_gettext("verified SSL connections are only supported when connecting to a host name\n"));
+                         libpq_gettext("host name must be specified for a verified SSL connection\n"));
        return false;
    }
    else
index ca3497f8f788ea8a5620d32e1cea33c6d0b5690f..b968c14a48a334ee7a915d5d1579672f24ec4b06 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.152 2010/07/06 19:19:01 momjian Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.152.2.1 2010/07/14 17:09:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -282,10 +282,9 @@ struct pg_conn
 {
    /* Saved values of connection options */
    char       *pghost;         /* the machine on which the server is running */
-   char       *pghostaddr;     /* the IPv4 address of the machine on which
-                                * the server is running, in IPv4
-                                * numbers-and-dots notation. Takes precedence
-                                * over above. */
+   char       *pghostaddr;     /* the numeric IP address of the machine on
+                                * which the server is running.  Takes
+                                * precedence over above. */
    char       *pgport;         /* the server's communication port */
    char       *pgunixsocket;   /* the Unix-domain socket that the server is
                                 * listening on; if NULL, uses a default