]> granicus.if.org Git - postgresql/commitdiff
Be more paranoid about null return values from libpq status functions.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 25 Nov 2015 22:31:53 +0000 (17:31 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 25 Nov 2015 22:31:53 +0000 (17:31 -0500)
PQhost() can return NULL in non-error situations, namely when a Unix-socket
connection has been selected by default.  That behavior is a tad debatable
perhaps, but for the moment we should make sure that psql copes with it.
Unfortunately, do_connect() failed to: it could pass a NULL pointer to
strcmp(), resulting in crashes on most platforms.  This was reported as a
security issue by ChenQin of Topsec Security Team, but the consensus of
the security list is that it's just a garden-variety bug with no security
implications.

For paranoia's sake, I made the keep_password test not trust PQuser or
PQport either, even though I believe those will never return NULL given
a valid PGconn.

Back-patch to all supported branches.

src/bin/psql/command.c

index 72c00c1251c671e42c2982aca11ddade246013f2..3a82e37401c549159eaf6e24744d7c108ca598fb 100644 (file)
@@ -1750,14 +1750,17 @@ do_connect(char *dbname, char *user, char *host, char *port)
        /*
         * Any change in the parameters read above makes us discard the password.
         * We also discard it if we're to use a conninfo rather than the
-        * positional syntax.
+        * positional syntax.  Note that currently, PQhost() can return NULL for a
+        * default Unix-socket connection, so we have to allow NULL for host.
         */
-       keep_password =
-               (o_conn &&
-                (strcmp(user, PQuser(o_conn)) == 0) &&
-                (!host || strcmp(host, PQhost(o_conn)) == 0) &&
-                (strcmp(port, PQport(o_conn)) == 0) &&
-                !has_connection_string);
+       if (has_connection_string)
+               keep_password = false;
+       else
+               keep_password =
+                       (user && PQuser(o_conn) && strcmp(user, PQuser(o_conn)) == 0) &&
+                       ((host && PQhost(o_conn) && strcmp(host, PQhost(o_conn)) == 0) ||
+                        (host == NULL && PQhost(o_conn) == NULL)) &&
+                       (port && PQport(o_conn) && strcmp(port, PQport(o_conn)) == 0);
 
        /*
         * Grab dbname from old connection unless supplied by caller.  No password
@@ -1769,8 +1772,8 @@ do_connect(char *dbname, char *user, char *host, char *port)
        /*
         * If the user asked to be prompted for a password, ask for one now. If
         * not, use the password from the old connection, provided the username
-        * has not changed. Otherwise, try to connect without a password first,
-        * and then ask for a password if needed.
+        * etc have not changed. Otherwise, try to connect without a password
+        * first, and then ask for a password if needed.
         *
         * XXX: this behavior leads to spurious connection attempts recorded in
         * the postmaster's log.  But libpq offers no API that would let us obtain