mirror of
https://github.com/postgres/postgres.git
synced 2025-06-29 10:41:53 +03:00
Fix dblink_connect() so that it verifies that a password is supplied in the
conninfo string *before* trying to connect to the remote server, not after. As pointed out by Marko Kreen, in certain not-very-plausible situations this could result in sending a password from the postgres user's .pgpass file, or other places that non-superusers shouldn't have access to, to an untrustworthy remote server. The cleanest fix seems to be to expose libpq's conninfo-string-parsing code so that dblink can check for a password option without duplicating the parsing logic. Joe Conway, with a little cleanup by Tom Lane
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.360 2008/09/17 04:31:08 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.361 2008/09/22 13:55:14 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -232,7 +232,8 @@ static PGconn *makeEmptyPGconn(void);
|
||||
static void freePGconn(PGconn *conn);
|
||||
static void closePGconn(PGconn *conn);
|
||||
static PQconninfoOption *conninfo_parse(const char *conninfo,
|
||||
PQExpBuffer errorMessage, bool *password_from_string);
|
||||
PQExpBuffer errorMessage, bool use_defaults,
|
||||
bool *password_from_string);
|
||||
static char *conninfo_getval(PQconninfoOption *connOptions,
|
||||
const char *keyword);
|
||||
static void defaultNoticeReceiver(void *arg, const PGresult *res);
|
||||
@ -376,7 +377,7 @@ connectOptions1(PGconn *conn, const char *conninfo)
|
||||
/*
|
||||
* Parse the conninfo string
|
||||
*/
|
||||
connOptions = conninfo_parse(conninfo, &conn->errorMessage,
|
||||
connOptions = conninfo_parse(conninfo, &conn->errorMessage, true,
|
||||
&conn->pgpass_from_client);
|
||||
if (connOptions == NULL)
|
||||
{
|
||||
@ -542,7 +543,9 @@ connectOptions2(PGconn *conn)
|
||||
* PQconndefaults
|
||||
*
|
||||
* Parse an empty string like PQconnectdb() would do and return the
|
||||
* working connection options array.
|
||||
* resulting connection options array, ie, all the default values that are
|
||||
* available from the environment etc. On error (eg out of memory),
|
||||
* NULL is returned.
|
||||
*
|
||||
* Using this function, an application may determine all possible options
|
||||
* and their current default values.
|
||||
@ -561,7 +564,10 @@ PQconndefaults(void)
|
||||
PQconninfoOption *connOptions;
|
||||
|
||||
initPQExpBuffer(&errorBuf);
|
||||
connOptions = conninfo_parse("", &errorBuf, &password_from_string);
|
||||
if (errorBuf.data == NULL)
|
||||
return NULL; /* out of memory already :-( */
|
||||
connOptions = conninfo_parse("", &errorBuf, true,
|
||||
&password_from_string);
|
||||
termPQExpBuffer(&errorBuf);
|
||||
return connOptions;
|
||||
}
|
||||
@ -3102,18 +3108,56 @@ parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PQconninfoParse
|
||||
*
|
||||
* Parse a string like PQconnectdb() would do and return the
|
||||
* resulting connection options array. NULL is returned on failure.
|
||||
* The result contains only options specified directly in the string,
|
||||
* not any possible default values.
|
||||
*
|
||||
* If errmsg isn't NULL, *errmsg is set to NULL on success, or a malloc'd
|
||||
* string on failure (use PQfreemem to free it). In out-of-memory conditions
|
||||
* both *errmsg and the result could be NULL.
|
||||
*
|
||||
* NOTE: the returned array is dynamically allocated and should
|
||||
* be freed when no longer needed via PQconninfoFree().
|
||||
*/
|
||||
PQconninfoOption *
|
||||
PQconninfoParse(const char *conninfo, char **errmsg)
|
||||
{
|
||||
PQExpBufferData errorBuf;
|
||||
bool password_from_string;
|
||||
PQconninfoOption *connOptions;
|
||||
|
||||
if (errmsg)
|
||||
*errmsg = NULL; /* default */
|
||||
initPQExpBuffer(&errorBuf);
|
||||
if (errorBuf.data == NULL)
|
||||
return NULL; /* out of memory already :-( */
|
||||
connOptions = conninfo_parse(conninfo, &errorBuf, false,
|
||||
&password_from_string);
|
||||
if (connOptions == NULL && errmsg)
|
||||
*errmsg = errorBuf.data;
|
||||
else
|
||||
termPQExpBuffer(&errorBuf);
|
||||
return connOptions;
|
||||
}
|
||||
|
||||
/*
|
||||
* Conninfo parser routine
|
||||
*
|
||||
* If successful, a malloc'd PQconninfoOption array is returned.
|
||||
* If not successful, NULL is returned and an error message is
|
||||
* left in errorMessage.
|
||||
* Defaults are supplied (from a service file, environment variables, etc)
|
||||
* for unspecified options, but only if use_defaults is TRUE.
|
||||
* *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,
|
||||
bool *password_from_string)
|
||||
bool use_defaults, bool *password_from_string)
|
||||
{
|
||||
char *pname;
|
||||
char *pval;
|
||||
@ -3293,6 +3337,12 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
|
||||
/* Done with the modifiable input string */
|
||||
free(buf);
|
||||
|
||||
/*
|
||||
* Stop here if caller doesn't want defaults filled in.
|
||||
*/
|
||||
if (!use_defaults)
|
||||
return options;
|
||||
|
||||
/*
|
||||
* If there's a service spec, use it to obtain any not-explicitly-given
|
||||
* parameters.
|
||||
|
Reference in New Issue
Block a user