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.
This commit is contained in:
Tom Lane 2015-11-25 17:31:53 -05:00
parent 46166197c3
commit c5ef8ce53d
1 changed files with 12 additions and 9 deletions

View 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