1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-21 00:42:43 +03:00

Fix up the PQconnectionUsedPassword mess: create a separate

PQconnectionNeedsPassword function that tells the right thing for whether to
prompt for a password, and improve PQconnectionUsedPassword so that it checks
whether the password used by the connection was actually supplied as a
connection argument, instead of coming from environment or a password file.
Per bug report from Mark Cave-Ayland and subsequent discussion.
This commit is contained in:
Tom Lane
2007-12-09 19:01:40 +00:00
parent cb1ab30fdc
commit 4f9bf7fc5a
13 changed files with 102 additions and 41 deletions

View File

@@ -1,4 +1,4 @@
# $PostgreSQL: pgsql/src/interfaces/libpq/exports.txt,v 1.17 2007/10/13 20:18:41 tgl Exp $
# $PostgreSQL: pgsql/src/interfaces/libpq/exports.txt,v 1.18 2007/12/09 19:01:40 tgl Exp $
# Functions to be exported by libpq DLLs
PQconnectdb 1
PQsetdbLogin 2
@@ -139,3 +139,4 @@ PQsendDescribePortal 136
lo_truncate 137
PQconnectionUsedPassword 138
pg_valid_server_encoding_id 139
PQconnectionNeedsPassword 140

View 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.134 2007/12/04 13:02:53 mha Exp $
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-auth.c,v 1.135 2007/12/09 19:01:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -954,7 +954,8 @@ pg_fe_sendauth(AuthRequest areq, PGconn *conn)
case AUTH_REQ_MD5:
case AUTH_REQ_CRYPT:
case AUTH_REQ_PASSWORD:
if (conn->pgpass == NULL || *conn->pgpass == '\0')
conn->password_needed = true;
if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
{
printfPQExpBuffer(&conn->errorMessage,
PQnoPasswordSupplied);

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.353 2007/11/15 21:14:46 momjian Exp $
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.354 2007/12/09 19:01:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -232,7 +232,7 @@ static PGconn *makeEmptyPGconn(void);
static void freePGconn(PGconn *conn);
static void closePGconn(PGconn *conn);
static PQconninfoOption *conninfo_parse(const char *conninfo,
PQExpBuffer errorMessage);
PQExpBuffer errorMessage, bool *password_from_string);
static char *conninfo_getval(PQconninfoOption *connOptions,
const char *keyword);
static void defaultNoticeReceiver(void *arg, const PGresult *res);
@@ -376,7 +376,8 @@ connectOptions1(PGconn *conn, const char *conninfo)
/*
* Parse the conninfo string
*/
connOptions = conninfo_parse(conninfo, &conn->errorMessage);
connOptions = conninfo_parse(conninfo, &conn->errorMessage,
&conn->pgpass_from_client);
if (connOptions == NULL)
{
conn->status = CONNECTION_BAD;
@@ -472,6 +473,7 @@ connectOptions2(PGconn *conn)
conn->dbName, conn->pguser);
if (conn->pgpass == NULL)
conn->pgpass = strdup(DefaultPassword);
conn->pgpass_from_client = false;
}
/*
@@ -555,10 +557,11 @@ PQconninfoOption *
PQconndefaults(void)
{
PQExpBufferData errorBuf;
bool password_from_string;
PQconninfoOption *connOptions;
initPQExpBuffer(&errorBuf);
connOptions = conninfo_parse("", &errorBuf);
connOptions = conninfo_parse("", &errorBuf, &password_from_string);
termPQExpBuffer(&errorBuf);
return connOptions;
}
@@ -659,6 +662,7 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
if (conn->pgpass)
free(conn->pgpass);
conn->pgpass = strdup(pwd);
conn->pgpass_from_client = true;
}
/*
@@ -1718,10 +1722,6 @@ keep_going: /* We will come back to here until there is
*/
conn->inStart = conn->inCursor;
/* Save the authentication request type, if first one. */
if (conn->areq == AUTH_REQ_OK)
conn->areq = areq;
/* Respond to the request if necessary. */
/*
@@ -1924,7 +1924,7 @@ makeEmptyPGconn(void)
conn->std_strings = false; /* unless server says differently */
conn->verbosity = PQERRORS_DEFAULT;
conn->sock = -1;
conn->areq = AUTH_REQ_OK; /* until we receive something else */
conn->password_needed = false;
#ifdef USE_SSL
conn->allow_ssl_try = true;
conn->wait_ssl_try = false;
@@ -3064,9 +3064,12 @@ parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
* If successful, a malloc'd PQconninfoOption array is returned.
* If not successful, NULL is returned and an error message is
* left in errorMessage.
* *password_from_string is set TRUE if we got a password from the
* conninfo string, otherwise FALSE.
*/
static PQconninfoOption *
conninfo_parse(const char *conninfo, PQExpBuffer errorMessage)
conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
bool *password_from_string)
{
char *pname;
char *pval;
@@ -3077,6 +3080,8 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage)
PQconninfoOption *options;
PQconninfoOption *option;
*password_from_string = false; /* default result */
/* Make a working copy of PQconninfoOptions */
options = malloc(sizeof(PQconninfoOptions));
if (options == NULL)
@@ -3233,6 +3238,12 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage)
free(buf);
return NULL;
}
/*
* Special handling for password
*/
if (strcmp(option->keyword, "password") == 0)
*password_from_string = (option->val[0] != '\0');
}
/* Done with the modifiable input string */
@@ -3475,14 +3486,24 @@ PQbackendPID(const PGconn *conn)
return conn->be_pid;
}
int
PQconnectionNeedsPassword(const PGconn *conn)
{
if (!conn)
return false;
if (conn->password_needed &&
(conn->pgpass == NULL || conn->pgpass[0] == '\0'))
return true;
else
return false;
}
int
PQconnectionUsedPassword(const PGconn *conn)
{
if (!conn)
return false;
if (conn->areq == AUTH_REQ_MD5 ||
conn->areq == AUTH_REQ_CRYPT ||
conn->areq == AUTH_REQ_PASSWORD)
if (conn->password_needed && conn->pgpass_from_client)
return true;
else
return false;

View File

@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.139 2007/10/13 20:18:42 tgl Exp $
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.140 2007/12/09 19:01:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -263,6 +263,7 @@ extern int PQserverVersion(const PGconn *conn);
extern char *PQerrorMessage(const PGconn *conn);
extern int PQsocket(const PGconn *conn);
extern int PQbackendPID(const PGconn *conn);
extern int PQconnectionNeedsPassword(const PGconn *conn);
extern int PQconnectionUsedPassword(const PGconn *conn);
extern int PQclientEncoding(const PGconn *conn);
extern int PQsetClientEncoding(PGconn *conn, const char *encoding);
@@ -426,7 +427,7 @@ extern void PQfreemem(void *ptr);
#define PQfreeNotify(ptr) PQfreemem(ptr)
/* Error when no password was given. */
/* Note: depending on this is deprecated; use PQconnectionUsedPassword(). */
/* Note: depending on this is deprecated; use PQconnectionNeedsPassword(). */
#define PQnoPasswordSupplied "fe_sendauth: no password supplied\n"
/*

View File

@@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.127 2007/11/15 21:14:46 momjian Exp $
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.128 2007/12/09 19:01:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -291,6 +291,7 @@ struct pg_conn
char *dbName; /* database name */
char *pguser; /* Postgres username and password, if any */
char *pgpass;
bool pgpass_from_client; /* did password come from connect args? */
char *sslmode; /* SSL mode (require,prefer,allow,disable) */
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
char *krbsrvname; /* Kerberos service name */
@@ -323,7 +324,7 @@ struct pg_conn
SockAddr raddr; /* Remote address */
ProtocolVersion pversion; /* FE/BE protocol version in use */
int sversion; /* server version, e.g. 70401 for 7.4.1 */
AuthRequest areq; /* auth type demanded by server */
bool password_needed; /* true if server demanded a password */
/* Transient state needed while establishing connection */
struct addrinfo *addrlist; /* list of possible backend addresses */