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:
parent
579c025e5f
commit
cae7ad906a
|
@ -8,7 +8,7 @@
|
||||||
* Darko Prenosil <Darko.Prenosil@finteh.hr>
|
* Darko Prenosil <Darko.Prenosil@finteh.hr>
|
||||||
* Shridhar Daithankar <shridhar_daithankar@persistent.co.in>
|
* Shridhar Daithankar <shridhar_daithankar@persistent.co.in>
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.74 2008/07/03 03:56:57 joe Exp $
|
* $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.75 2008/09/22 13:55:13 tgl Exp $
|
||||||
* Copyright (c) 2001-2008, PostgreSQL Global Development Group
|
* Copyright (c) 2001-2008, PostgreSQL Global Development Group
|
||||||
* ALL RIGHTS RESERVED;
|
* ALL RIGHTS RESERVED;
|
||||||
*
|
*
|
||||||
|
@ -93,6 +93,7 @@ static int16 get_attnum_pk_pos(int2vector *pkattnums, int16 pknumatts, int16 key
|
||||||
static HeapTuple get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals);
|
static HeapTuple get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals);
|
||||||
static Oid get_relid_from_relname(text *relname_text);
|
static Oid get_relid_from_relname(text *relname_text);
|
||||||
static char *generate_relation_name(Oid relid);
|
static char *generate_relation_name(Oid relid);
|
||||||
|
static void dblink_connstr_check(const char *connstr);
|
||||||
static void dblink_security_check(PGconn *conn, remoteConn *rconn);
|
static void dblink_security_check(PGconn *conn, remoteConn *rconn);
|
||||||
static void dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail);
|
static void dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail);
|
||||||
|
|
||||||
|
@ -165,6 +166,7 @@ typedef struct remoteConnHashEnt
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
connstr = conname_or_str; \
|
connstr = conname_or_str; \
|
||||||
|
dblink_connstr_check(connstr); \
|
||||||
conn = PQconnectdb(connstr); \
|
conn = PQconnectdb(connstr); \
|
||||||
if (PQstatus(conn) == CONNECTION_BAD) \
|
if (PQstatus(conn) == CONNECTION_BAD) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -229,6 +231,9 @@ dblink_connect(PG_FUNCTION_ARGS)
|
||||||
|
|
||||||
if (connname)
|
if (connname)
|
||||||
rconn = (remoteConn *) palloc(sizeof(remoteConn));
|
rconn = (remoteConn *) palloc(sizeof(remoteConn));
|
||||||
|
|
||||||
|
/* check password in connection string if not superuser */
|
||||||
|
dblink_connstr_check(connstr);
|
||||||
conn = PQconnectdb(connstr);
|
conn = PQconnectdb(connstr);
|
||||||
|
|
||||||
MemoryContextSwitchTo(oldcontext);
|
MemoryContextSwitchTo(oldcontext);
|
||||||
|
@ -246,7 +251,7 @@ dblink_connect(PG_FUNCTION_ARGS)
|
||||||
errdetail("%s", msg)));
|
errdetail("%s", msg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check password used if not superuser */
|
/* check password actually used if not superuser */
|
||||||
dblink_security_check(conn, rconn);
|
dblink_security_check(conn, rconn);
|
||||||
|
|
||||||
if (connname)
|
if (connname)
|
||||||
|
@ -2251,6 +2256,46 @@ dblink_security_check(PGconn *conn, remoteConn *rconn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For non-superusers, insist that the connstr specify a password. This
|
||||||
|
* prevents a password from being picked up from .pgpass, a service file,
|
||||||
|
* the environment, etc. We don't want the postgres user's passwords
|
||||||
|
* to be accessible to non-superusers.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
dblink_connstr_check(const char *connstr)
|
||||||
|
{
|
||||||
|
if (!superuser())
|
||||||
|
{
|
||||||
|
PQconninfoOption *options;
|
||||||
|
PQconninfoOption *option;
|
||||||
|
bool connstr_gives_password = false;
|
||||||
|
|
||||||
|
options = PQconninfoParse(connstr, NULL);
|
||||||
|
if (options)
|
||||||
|
{
|
||||||
|
for (option = options; option->keyword != NULL; option++)
|
||||||
|
{
|
||||||
|
if (strcmp(option->keyword, "password") == 0)
|
||||||
|
{
|
||||||
|
if (option->val != NULL && option->val[0] != '\0')
|
||||||
|
{
|
||||||
|
connstr_gives_password = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PQconninfoFree(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!connstr_gives_password)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED),
|
||||||
|
errmsg("password is required"),
|
||||||
|
errdetail("Non-superusers must provide a password in the connection string.")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail)
|
dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/dblink.sgml,v 1.4 2008/04/04 16:57:21 momjian Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/dblink.sgml,v 1.5 2008/09/22 13:55:13 tgl Exp $ -->
|
||||||
|
|
||||||
<sect1 id="dblink">
|
<sect1 id="dblink">
|
||||||
<title>dblink</title>
|
<title>dblink</title>
|
||||||
|
@ -140,12 +140,19 @@
|
||||||
involve a password, then impersonation and subsequent escalation of
|
involve a password, then impersonation and subsequent escalation of
|
||||||
privileges can occur, because the session will appear to have
|
privileges can occur, because the session will appear to have
|
||||||
originated from the user as which the local <productname>PostgreSQL</>
|
originated from the user as which the local <productname>PostgreSQL</>
|
||||||
server runs. Therefore, <function>dblink_connect_u()</> is initially
|
server runs. Also, even if the remote server does demand a password,
|
||||||
|
it is possible for the password to be supplied from the server
|
||||||
|
environment, such as a <filename>~/.pgpass</> file belonging to the
|
||||||
|
server's user. This opens not only a risk of impersonation, but the
|
||||||
|
possibility of exposing a password to an untrustworthy remote server.
|
||||||
|
Therefore, <function>dblink_connect_u()</> is initially
|
||||||
installed with all privileges revoked from <literal>PUBLIC</>,
|
installed with all privileges revoked from <literal>PUBLIC</>,
|
||||||
making it un-callable except by superusers. In some situations
|
making it un-callable except by superusers. In some situations
|
||||||
it may be appropriate to grant <literal>EXECUTE</> permission for
|
it may be appropriate to grant <literal>EXECUTE</> permission for
|
||||||
<function>dblink_connect_u()</> to specific users who are considered
|
<function>dblink_connect_u()</> to specific users who are considered
|
||||||
trustworthy, but this should be done with care.
|
trustworthy, but this should be done with care. It is also recommended
|
||||||
|
that any <filename>~/.pgpass</> file belonging to the server's user
|
||||||
|
<emphasis>not</> contain any records specifying a wildcard host name.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.263 2008/09/19 20:06:13 tgl Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.264 2008/09/22 13:55:13 tgl Exp $ -->
|
||||||
|
|
||||||
<chapter id="libpq">
|
<chapter id="libpq">
|
||||||
<title><application>libpq</application> - C Library</title>
|
<title><application>libpq</application> - C Library</title>
|
||||||
|
@ -593,7 +593,7 @@ typedef struct
|
||||||
char *compiled; /* Fallback compiled in default value */
|
char *compiled; /* Fallback compiled in default value */
|
||||||
char *val; /* Option's current value, or NULL */
|
char *val; /* Option's current value, or NULL */
|
||||||
char *label; /* Label for field in connect dialog */
|
char *label; /* Label for field in connect dialog */
|
||||||
char *dispchar; /* Character to display for this field
|
char *dispchar; /* Indicates how to display this field
|
||||||
in a connect dialog. Values are:
|
in a connect dialog. Values are:
|
||||||
"" Display entered value as is
|
"" Display entered value as is
|
||||||
"*" Password field - hide value
|
"*" Password field - hide value
|
||||||
|
@ -624,6 +624,51 @@ typedef struct
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><function>PQconninfoParse</function><indexterm><primary>PQconninfoParse</></></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Returns parsed connection options from the provided connection string.
|
||||||
|
|
||||||
|
<synopsis>
|
||||||
|
PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg);
|
||||||
|
</synopsis>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Parses a connection string and returns the resulting options as an
|
||||||
|
array; or returns NULL if there is a problem with the connection
|
||||||
|
string. This can be used to determine
|
||||||
|
the <function>PQconnectdb</function> options in the provided
|
||||||
|
connection string. The return value points to an array of
|
||||||
|
<structname>PQconninfoOption</structname> structures, which ends
|
||||||
|
with an entry having a null <structfield>keyword</> pointer.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Note that only options explicitly specified in the string will have
|
||||||
|
values set in the result array; no defaults are inserted.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If <literal>errmsg</> is not NULL, then <literal>*errmsg</> is set
|
||||||
|
to NULL on success, else to a malloc'd error string explaining
|
||||||
|
the problem. (It is also possible for <literal>*errmsg</> to be
|
||||||
|
set to NULL even when NULL is returned; this indicates an out-of-memory
|
||||||
|
situation.)
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
After processing the options array, free it by passing it to
|
||||||
|
<function>PQconninfoFree</function>. If this is not done, some memory
|
||||||
|
is leaked for each call to <function>PQconninfoParse</function>.
|
||||||
|
Conversely, if an error occurs and <literal>errmsg</> is not NULL,
|
||||||
|
be sure to free the error string using <function>PQfreemem</>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><function>PQfinish</function><indexterm><primary>PQfinish</></></term>
|
<term><function>PQfinish</function><indexterm><primary>PQfinish</></></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -2985,39 +3030,6 @@ typedef struct {
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<function>PQfreemem</function>
|
|
||||||
<indexterm>
|
|
||||||
<primary>PQfreemem</primary>
|
|
||||||
</indexterm>
|
|
||||||
</term>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Frees memory allocated by <application>libpq</>.
|
|
||||||
<synopsis>
|
|
||||||
void PQfreemem(void *ptr);
|
|
||||||
</synopsis>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Frees memory allocated by <application>libpq</>, particularly
|
|
||||||
<function>PQescapeByteaConn</function>,
|
|
||||||
<function>PQescapeBytea</function>,
|
|
||||||
<function>PQunescapeBytea</function>,
|
|
||||||
and <function>PQnotifies</function>.
|
|
||||||
It is particularly important that this function, rather than
|
|
||||||
<function>free()</>, be used on Microsoft Windows. This is because
|
|
||||||
allocating memory in a DLL and releasing it in the application works
|
|
||||||
only if multithreaded/single-threaded, release/debug, and static/dynamic
|
|
||||||
flags are the same for the DLL and the application. On non-Microsoft
|
|
||||||
Windows platforms, this function is the same as the standard library
|
|
||||||
function <function>free()</>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
@ -4537,6 +4549,63 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>);
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<function>PQfreemem</function>
|
||||||
|
<indexterm>
|
||||||
|
<primary>PQfreemem</primary>
|
||||||
|
</indexterm>
|
||||||
|
</term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Frees memory allocated by <application>libpq</>.
|
||||||
|
<synopsis>
|
||||||
|
void PQfreemem(void *ptr);
|
||||||
|
</synopsis>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Frees memory allocated by <application>libpq</>, particularly
|
||||||
|
<function>PQescapeByteaConn</function>,
|
||||||
|
<function>PQescapeBytea</function>,
|
||||||
|
<function>PQunescapeBytea</function>,
|
||||||
|
and <function>PQnotifies</function>.
|
||||||
|
It is particularly important that this function, rather than
|
||||||
|
<function>free()</>, be used on Microsoft Windows. This is because
|
||||||
|
allocating memory in a DLL and releasing it in the application works
|
||||||
|
only if multithreaded/single-threaded, release/debug, and static/dynamic
|
||||||
|
flags are the same for the DLL and the application. On non-Microsoft
|
||||||
|
Windows platforms, this function is the same as the standard library
|
||||||
|
function <function>free()</>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<function>PQconninfoFree</function>
|
||||||
|
<indexterm>
|
||||||
|
<primary>PQconninfoFree</primary>
|
||||||
|
</indexterm>
|
||||||
|
</term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Frees the data structures allocated by
|
||||||
|
<function>PQconndefaults</> or <function>PQconninfoParse</>.
|
||||||
|
<synopsis>
|
||||||
|
void PQconninfoFree(PQconninfoOption *connOptions);
|
||||||
|
</synopsis>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
A simple <function>PQfreemem</function> will not do for this, since
|
||||||
|
the array contains references to subsidiary strings.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
<term>
|
||||||
<function>PQencryptPassword</function>
|
<function>PQencryptPassword</function>
|
||||||
|
|
|
@ -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
|
# Functions to be exported by libpq DLLs
|
||||||
PQconnectdb 1
|
PQconnectdb 1
|
||||||
PQsetdbLogin 2
|
PQsetdbLogin 2
|
||||||
|
@ -151,3 +151,4 @@ PQsetInstanceData 148
|
||||||
PQresultInstanceData 149
|
PQresultInstanceData 149
|
||||||
PQresultSetInstanceData 150
|
PQresultSetInstanceData 150
|
||||||
PQfireResultCreateEvents 151
|
PQfireResultCreateEvents 151
|
||||||
|
PQconninfoParse 152
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 freePGconn(PGconn *conn);
|
||||||
static void closePGconn(PGconn *conn);
|
static void closePGconn(PGconn *conn);
|
||||||
static PQconninfoOption *conninfo_parse(const char *conninfo,
|
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,
|
static char *conninfo_getval(PQconninfoOption *connOptions,
|
||||||
const char *keyword);
|
const char *keyword);
|
||||||
static void defaultNoticeReceiver(void *arg, const PGresult *res);
|
static void defaultNoticeReceiver(void *arg, const PGresult *res);
|
||||||
|
@ -376,7 +377,7 @@ connectOptions1(PGconn *conn, const char *conninfo)
|
||||||
/*
|
/*
|
||||||
* Parse the conninfo string
|
* Parse the conninfo string
|
||||||
*/
|
*/
|
||||||
connOptions = conninfo_parse(conninfo, &conn->errorMessage,
|
connOptions = conninfo_parse(conninfo, &conn->errorMessage, true,
|
||||||
&conn->pgpass_from_client);
|
&conn->pgpass_from_client);
|
||||||
if (connOptions == NULL)
|
if (connOptions == NULL)
|
||||||
{
|
{
|
||||||
|
@ -542,7 +543,9 @@ connectOptions2(PGconn *conn)
|
||||||
* PQconndefaults
|
* PQconndefaults
|
||||||
*
|
*
|
||||||
* Parse an empty string like PQconnectdb() would do and return the
|
* 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
|
* Using this function, an application may determine all possible options
|
||||||
* and their current default values.
|
* and their current default values.
|
||||||
|
@ -561,7 +564,10 @@ PQconndefaults(void)
|
||||||
PQconninfoOption *connOptions;
|
PQconninfoOption *connOptions;
|
||||||
|
|
||||||
initPQExpBuffer(&errorBuf);
|
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);
|
termPQExpBuffer(&errorBuf);
|
||||||
return connOptions;
|
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
|
* Conninfo parser routine
|
||||||
*
|
*
|
||||||
* If successful, a malloc'd PQconninfoOption array is returned.
|
* If successful, a malloc'd PQconninfoOption array is returned.
|
||||||
* If not successful, NULL is returned and an error message is
|
* If not successful, NULL is returned and an error message is
|
||||||
* left in errorMessage.
|
* 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
|
* *password_from_string is set TRUE if we got a password from the
|
||||||
* conninfo string, otherwise FALSE.
|
* conninfo string, otherwise FALSE.
|
||||||
*/
|
*/
|
||||||
static PQconninfoOption *
|
static PQconninfoOption *
|
||||||
conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
|
conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
|
||||||
bool *password_from_string)
|
bool use_defaults, bool *password_from_string)
|
||||||
{
|
{
|
||||||
char *pname;
|
char *pname;
|
||||||
char *pval;
|
char *pval;
|
||||||
|
@ -3293,6 +3337,12 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
|
||||||
/* Done with the modifiable input string */
|
/* Done with the modifiable input string */
|
||||||
free(buf);
|
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
|
* If there's a service spec, use it to obtain any not-explicitly-given
|
||||||
* parameters.
|
* parameters.
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, 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/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
|
* Structure for the conninfo parameter definitions returned by PQconndefaults
|
||||||
|
* or PQconninfoParse.
|
||||||
*
|
*
|
||||||
* All fields except "val" point at static strings which must not be altered.
|
* 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()
|
* "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 *compiled; /* Fallback compiled in default value */
|
||||||
char *val; /* Option's current value, or NULL */
|
char *val; /* Option's current value, or NULL */
|
||||||
char *label; /* Label for field in connect dialog */
|
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
|
* connect dialog. Values are: "" Display
|
||||||
* entered value as is "*" Password field -
|
* entered value as is "*" Password field -
|
||||||
* hide value "D" Debug option - don't show
|
* 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 */
|
/* get info about connection options known to PQconnectdb */
|
||||||
extern PQconninfoOption *PQconndefaults(void);
|
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);
|
extern void PQconninfoFree(PQconninfoOption *connOptions);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue