From d44b4deaad9f347c2e83ab50c7252f14fad1ef63 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Wed, 25 Nov 2015 17:31:54 -0500 Subject: [PATCH] Be more paranoid about null return values from libpq status functions. 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 | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index b9880fcc577..974cfcac0c4 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -1522,15 +1522,18 @@ 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. + * We also discard it if we're to use a conninfo rather than the + * 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 @@ -1542,8 +1545,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 -- GitLab