Get rid of client-code dependencies on the exact text of the no-password

error message, by using PQconnectionUsedPassword() instead.  Someday
we might be able to localize that error message, but not until this
coding technique has disappeared everywhere.
This commit is contained in:
Tom Lane 2007-07-08 19:07:38 +00:00
parent 5f7b1f8d9d
commit 8331c11f3f
6 changed files with 58 additions and 69 deletions

View File

@ -4,7 +4,7 @@
* *
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.81 2007/07/02 21:58:31 mha Exp $ * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.82 2007/07/08 19:07:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -480,15 +480,18 @@ test_postmaster_connection(bool do_checkpoint)
if (!*portstr) if (!*portstr)
snprintf(portstr, sizeof(portstr), "%d", DEF_PGPORT); snprintf(portstr, sizeof(portstr), "%d", DEF_PGPORT);
/* We need to set a connect timeout otherwise on Windows the SCM will probably timeout first */ /*
snprintf(connstr, sizeof(connstr), "dbname=postgres port=%s connect_timeout=5", portstr); * We need to set a connect timeout otherwise on Windows the SCM will
* probably timeout first
*/
snprintf(connstr, sizeof(connstr),
"dbname=postgres port=%s connect_timeout=5", portstr);
for (i = 0; i < wait_seconds; i++) for (i = 0; i < wait_seconds; i++)
{ {
if ((conn = PQconnectdb(connstr)) != NULL && if ((conn = PQconnectdb(connstr)) != NULL &&
(PQstatus(conn) == CONNECTION_OK || (PQstatus(conn) == CONNECTION_OK ||
(strcmp(PQerrorMessage(conn), PQconnectionUsedPassword(conn)))
PQnoPasswordSupplied) == 0)))
{ {
PQfinish(conn); PQfinish(conn);
success = true; success = true;

View File

@ -5,7 +5,7 @@
* Implements the basic DB functions used by the archiver. * Implements the basic DB functions used by the archiver.
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.75 2006/10/04 00:30:05 momjian Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.76 2007/07/08 19:07:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -123,13 +123,11 @@ ReconnectToServer(ArchiveHandle *AH, const char *dbname, const char *username)
static PGconn * static PGconn *
_connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser) _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
{ {
int need_pass;
PGconn *newConn; PGconn *newConn;
char *password = NULL;
int badPwd = 0;
int noPwd = 0;
char *newdb; char *newdb;
char *newuser; char *newuser;
char *password = NULL;
bool new_pass;
if (!reqdb) if (!reqdb)
newdb = PQdb(AH->connection); newdb = PQdb(AH->connection);
@ -152,7 +150,7 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
do do
{ {
need_pass = false; new_pass = false;
newConn = PQsetdbLogin(PQhost(AH->connection), PQport(AH->connection), newConn = PQsetdbLogin(PQhost(AH->connection), PQport(AH->connection),
NULL, NULL, newdb, NULL, NULL, newdb,
newuser, password); newuser, password);
@ -161,30 +159,23 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
if (PQstatus(newConn) == CONNECTION_BAD) if (PQstatus(newConn) == CONNECTION_BAD)
{ {
noPwd = (strcmp(PQerrorMessage(newConn), if (!PQconnectionUsedPassword(newConn))
PQnoPasswordSupplied) == 0);
badPwd = (strncmp(PQerrorMessage(newConn),
"Password authentication failed for user", 39) == 0);
if (noPwd || badPwd)
{
if (badPwd)
fprintf(stderr, "Password incorrect\n");
fprintf(stderr, "Connecting to %s as %s\n",
newdb, newuser);
need_pass = true;
if (password)
free(password);
password = simple_prompt("Password: ", 100, false);
}
else
die_horribly(AH, modulename, "could not reconnect to database: %s", die_horribly(AH, modulename, "could not reconnect to database: %s",
PQerrorMessage(newConn)); PQerrorMessage(newConn));
PQfinish(newConn); PQfinish(newConn);
if (password)
fprintf(stderr, "Password incorrect\n");
fprintf(stderr, "Connecting to %s as %s\n",
newdb, newuser);
if (password)
free(password);
password = simple_prompt("Password: ", 100, false);
new_pass = true;
} }
} while (need_pass); } while (new_pass);
if (password) if (password)
free(password); free(password);
@ -214,7 +205,7 @@ ConnectDatabase(Archive *AHX,
{ {
ArchiveHandle *AH = (ArchiveHandle *) AHX; ArchiveHandle *AH = (ArchiveHandle *) AHX;
char *password = NULL; char *password = NULL;
bool need_pass = false; bool new_pass;
if (AH->connection) if (AH->connection)
die_horribly(AH, modulename, "already connected to a database\n"); die_horribly(AH, modulename, "already connected to a database\n");
@ -235,7 +226,7 @@ ConnectDatabase(Archive *AHX,
*/ */
do do
{ {
need_pass = false; new_pass = false;
AH->connection = PQsetdbLogin(pghost, pgport, NULL, NULL, AH->connection = PQsetdbLogin(pghost, pgport, NULL, NULL,
dbname, username, password); dbname, username, password);
@ -243,16 +234,15 @@ ConnectDatabase(Archive *AHX,
die_horribly(AH, modulename, "failed to connect to database\n"); die_horribly(AH, modulename, "failed to connect to database\n");
if (PQstatus(AH->connection) == CONNECTION_BAD && if (PQstatus(AH->connection) == CONNECTION_BAD &&
strcmp(PQerrorMessage(AH->connection), PQnoPasswordSupplied) == 0 && PQconnectionUsedPassword(AH->connection) &&
password == NULL &&
!feof(stdin)) !feof(stdin))
{ {
PQfinish(AH->connection); PQfinish(AH->connection);
need_pass = true;
free(password);
password = NULL;
password = simple_prompt("Password: ", 100, false); password = simple_prompt("Password: ", 100, false);
new_pass = true;
} }
} while (need_pass); } while (new_pass);
if (password) if (password)
free(password); free(password);

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.91 2007/05/15 20:20:21 alvherre Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.92 2007/07/08 19:07:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1310,7 +1310,7 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
const char *pguser, bool require_password, bool fail_on_error) const char *pguser, bool require_password, bool fail_on_error)
{ {
PGconn *conn; PGconn *conn;
bool need_pass = false; bool new_pass;
const char *remoteversion_str; const char *remoteversion_str;
int my_version; int my_version;
static char *password = NULL; static char *password = NULL;
@ -1324,7 +1324,7 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
*/ */
do do
{ {
need_pass = false; new_pass = false;
conn = PQsetdbLogin(pghost, pgport, NULL, NULL, dbname, pguser, password); conn = PQsetdbLogin(pghost, pgport, NULL, NULL, dbname, pguser, password);
if (!conn) if (!conn)
@ -1335,17 +1335,15 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
} }
if (PQstatus(conn) == CONNECTION_BAD && if (PQstatus(conn) == CONNECTION_BAD &&
strcmp(PQerrorMessage(conn), PQnoPasswordSupplied) == 0 && PQconnectionUsedPassword(conn) &&
password == NULL &&
!feof(stdin)) !feof(stdin))
{ {
PQfinish(conn); PQfinish(conn);
need_pass = true;
if (password)
free(password);
password = NULL;
password = simple_prompt("Password: ", 100, false); password = simple_prompt("Password: ", 100, false);
new_pass = true;
} }
} while (need_pass); } while (new_pass);
/* check to see that the backend connection was successfully made */ /* check to see that the backend connection was successfully made */
if (PQstatus(conn) == CONNECTION_BAD) if (PQstatus(conn) == CONNECTION_BAD)

View File

@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2007, PostgreSQL Global Development Group * Copyright (c) 2000-2007, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.179 2007/03/03 17:19:11 momjian Exp $ * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.180 2007/07/08 19:07:38 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "command.h" #include "command.h"
@ -1110,11 +1110,11 @@ 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 * 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 * not, use the password from the old connection, provided the username
* has not changed. Otherwise, try to connect without a password first, * has not changed. Otherwise, try to connect without a password first,
* and then ask for a password if we got the appropriate error message. * and then ask for a password if needed.
* *
* XXX: this behavior is broken. It leads to spurious connection attempts * XXX: this behavior leads to spurious connection attempts recorded
* in the postmaster's log, and doing a string comparison against the * in the postmaster's log. But libpq offers no API that would let us
* returned error message is pretty fragile. * obtain a password and then continue with the first connection attempt.
*/ */
if (pset.getPassword) if (pset.getPassword)
{ {
@ -1141,7 +1141,7 @@ do_connect(char *dbname, char *user, char *host, char *port)
* Connection attempt failed; either retry the connection attempt with * Connection attempt failed; either retry the connection attempt with
* a new password, or give up. * a new password, or give up.
*/ */
if (strcmp(PQerrorMessage(n_conn), PQnoPasswordSupplied) == 0) if (!password && PQconnectionUsedPassword(n_conn))
{ {
PQfinish(n_conn); PQfinish(n_conn);
password = prompt_for_password(user); password = prompt_for_password(user);

View File

@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2007, PostgreSQL Global Development Group * Copyright (c) 2000-2007, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.140 2007/02/01 19:10:29 momjian Exp $ * $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.141 2007/07/08 19:07:38 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
@ -108,7 +108,7 @@ main(int argc, char *argv[])
char *username = NULL; char *username = NULL;
char *password = NULL; char *password = NULL;
char *password_prompt = NULL; char *password_prompt = NULL;
bool need_pass; bool new_pass;
set_pglocale_pgservice(argv[0], "psql"); set_pglocale_pgservice(argv[0], "psql");
@ -204,23 +204,22 @@ main(int argc, char *argv[])
/* loop until we have a password if requested by backend */ /* loop until we have a password if requested by backend */
do do
{ {
need_pass = false; new_pass = false;
pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL, pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL,
options.action == ACT_LIST_DB && options.dbname == NULL ? options.action == ACT_LIST_DB && options.dbname == NULL ?
"postgres" : options.dbname, "postgres" : options.dbname,
username, password); username, password);
if (PQstatus(pset.db) == CONNECTION_BAD && if (PQstatus(pset.db) == CONNECTION_BAD &&
strcmp(PQerrorMessage(pset.db), PQnoPasswordSupplied) == 0 && PQconnectionUsedPassword(pset.db) &&
password == NULL &&
!feof(stdin)) !feof(stdin))
{ {
PQfinish(pset.db); PQfinish(pset.db);
need_pass = true;
free(password);
password = NULL;
password = simple_prompt(password_prompt, 100, false); password = simple_prompt(password_prompt, 100, false);
new_pass = true;
} }
} while (need_pass); } while (new_pass);
free(username); free(username);
free(password); free(password);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/bin/scripts/common.c,v 1.26 2007/04/09 18:21:22 mha Exp $ * $PostgreSQL: pgsql/src/bin/scripts/common.c,v 1.27 2007/07/08 19:07:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -100,7 +100,7 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
{ {
PGconn *conn; PGconn *conn;
char *password = NULL; char *password = NULL;
bool need_pass = false; bool new_pass;
if (require_password) if (require_password)
password = simple_prompt("Password: ", 100, false); password = simple_prompt("Password: ", 100, false);
@ -111,7 +111,7 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
*/ */
do do
{ {
need_pass = false; new_pass = false;
conn = PQsetdbLogin(pghost, pgport, NULL, NULL, dbname, pguser, password); conn = PQsetdbLogin(pghost, pgport, NULL, NULL, dbname, pguser, password);
if (!conn) if (!conn)
@ -122,16 +122,15 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
} }
if (PQstatus(conn) == CONNECTION_BAD && if (PQstatus(conn) == CONNECTION_BAD &&
strcmp(PQerrorMessage(conn), PQnoPasswordSupplied) == 0 && PQconnectionUsedPassword(conn) &&
password == NULL &&
!feof(stdin)) !feof(stdin))
{ {
PQfinish(conn); PQfinish(conn);
need_pass = true;
free(password);
password = NULL;
password = simple_prompt("Password: ", 100, false); password = simple_prompt("Password: ", 100, false);
new_pass = true;
} }
} while (need_pass); } while (new_pass);
if (password) if (password)
free(password); free(password);