aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2008-09-22 13:55:14 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2008-09-22 13:55:14 +0000
commitcae7ad906a0337120afe856b0a76b03b8ffc7440 (patch)
treeed5c181dfee6f69d46ecff8eaeaef77035c0466b /src
parent579c025e5fc8d3cc42fc65e1b23da20c9c9f4866 (diff)
downloadpostgresql-cae7ad906a0337120afe856b0a76b03b8ffc7440.tar.gz
postgresql-cae7ad906a0337120afe856b0a76b03b8ffc7440.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/interfaces/libpq/exports.txt3
-rw-r--r--src/interfaces/libpq/fe-connect.c62
-rw-r--r--src/interfaces/libpq/libpq-fe.h10
3 files changed, 65 insertions, 10 deletions
diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index eeabe40671e..655968e5f32 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -1,4 +1,4 @@
-# $PostgreSQL: pgsql/src/interfaces/libpq/exports.txt,v 1.21 2008/09/19 20:06:13 tgl Exp $
+# $PostgreSQL: pgsql/src/interfaces/libpq/exports.txt,v 1.22 2008/09/22 13:55:14 tgl Exp $
# Functions to be exported by libpq DLLs
PQconnectdb 1
PQsetdbLogin 2
@@ -151,3 +151,4 @@ PQsetInstanceData 148
PQresultInstanceData 149
PQresultSetInstanceData 150
PQfireResultCreateEvents 151
+PQconninfoParse 152
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 7e77c9a5c7a..bd70679aa2d 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -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;
}
@@ -3103,17 +3109,55 @@ 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;
@@ -3294,6 +3338,12 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
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.
*/
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index f923b968408..85552d5e34b 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.143 2008/09/17 04:31:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.144 2008/09/22 13:55:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -164,6 +164,7 @@ typedef struct _PQprintOpt
/* ----------------
* Structure for the conninfo parameter definitions returned by PQconndefaults
+ * or PQconninfoParse.
*
* All fields except "val" point at static strings which must not be altered.
* "val" is either NULL or a malloc'd current-value string. PQconninfoFree()
@@ -177,7 +178,7 @@ typedef struct _PQconninfoOption
char *compiled; /* Fallback compiled in default value */
char *val; /* Option's current value, or NULL */
char *label; /* Label for field in connect dialog */
- char *dispchar; /* Character to display for this field in a
+ char *dispchar; /* Indicates how to display this field in a
* connect dialog. Values are: "" Display
* entered value as is "*" Password field -
* hide value "D" Debug option - don't show
@@ -243,7 +244,10 @@ extern void PQfinish(PGconn *conn);
/* get info about connection options known to PQconnectdb */
extern PQconninfoOption *PQconndefaults(void);
-/* free the data structure returned by PQconndefaults() */
+/* parse connection options in same way as PQconnectdb */
+extern PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg);
+
+/* free the data structure returned by PQconndefaults() or PQconninfoParse() */
extern void PQconninfoFree(PQconninfoOption *connOptions);
/*