Commit c4448683 authored by Joe Conway's avatar Joe Conway

Protect dblink from invalid options when using postgres_fdw server

When dblink uses a postgres_fdw server name for its connection, it
is possible for the connection to have options that are invalid
with dblink (e.g. "updatable"). The recommended way to avoid this
problem is to use dblink_fdw servers instead. However there are use
cases for using postgres_fdw, and possibly other FDWs, for dblink
connection options, therefore protect against trying to use any
options that do not apply by using is_valid_dblink_option() when
building the connection string from the options.

Back-patch to 9.3. Although 9.2 supports FDWs for connection info,
is_valid_dblink_option() did not yet exist, and neither did
postgres_fdw, at least in the postgres source tree. Given the lack
of previous complaints, fixing that seems too invasive/not worth it.

Author: Corey Huinker
Reviewed-By: Joe Conway
Discussion: https://postgr.es/m/CADkLM%3DfWyXVEyYcqbcRnxcHutkP45UHU9WD7XpdZaMfe7S%3DRwA%40mail.gmail.com
parent 01ec2563
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "access/reloptions.h" #include "access/reloptions.h"
#include "catalog/indexing.h" #include "catalog/indexing.h"
#include "catalog/namespace.h" #include "catalog/namespace.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h" #include "catalog/pg_foreign_server.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "catalog/pg_user_mapping.h" #include "catalog/pg_user_mapping.h"
...@@ -2727,6 +2728,25 @@ get_connect_string(const char *servername) ...@@ -2727,6 +2728,25 @@ get_connect_string(const char *servername)
AclResult aclresult; AclResult aclresult;
char *srvname; char *srvname;
static const PQconninfoOption *options = NULL;
/*
* Get list of valid libpq options.
*
* To avoid unnecessary work, we get the list once and use it throughout
* the lifetime of this backend process. We don't need to care about
* memory context issues, because PQconndefaults allocates with malloc.
*/
if (!options)
{
options = PQconndefaults();
if (!options) /* assume reason for failure is OOM */
ereport(ERROR,
(errcode(ERRCODE_FDW_OUT_OF_MEMORY),
errmsg("out of memory"),
errdetail("could not get libpq's default connection options")));
}
/* first gather the server connstr options */ /* first gather the server connstr options */
srvname = pstrdup(servername); srvname = pstrdup(servername);
truncate_identifier(srvname, strlen(srvname), false); truncate_identifier(srvname, strlen(srvname), false);
...@@ -2750,16 +2770,18 @@ get_connect_string(const char *servername) ...@@ -2750,16 +2770,18 @@ get_connect_string(const char *servername)
{ {
DefElem *def = lfirst(cell); DefElem *def = lfirst(cell);
appendStringInfo(buf, "%s='%s' ", def->defname, if (is_valid_dblink_option(options, def->defname, ForeignDataWrapperRelationId))
escape_param_str(strVal(def->arg))); appendStringInfo(buf, "%s='%s' ", def->defname,
escape_param_str(strVal(def->arg)));
} }
foreach(cell, foreign_server->options) foreach(cell, foreign_server->options)
{ {
DefElem *def = lfirst(cell); DefElem *def = lfirst(cell);
appendStringInfo(buf, "%s='%s' ", def->defname, if (is_valid_dblink_option(options, def->defname, ForeignServerRelationId))
escape_param_str(strVal(def->arg))); appendStringInfo(buf, "%s='%s' ", def->defname,
escape_param_str(strVal(def->arg)));
} }
foreach(cell, user_mapping->options) foreach(cell, user_mapping->options)
...@@ -2767,8 +2789,9 @@ get_connect_string(const char *servername) ...@@ -2767,8 +2789,9 @@ get_connect_string(const char *servername)
DefElem *def = lfirst(cell); DefElem *def = lfirst(cell);
appendStringInfo(buf, "%s='%s' ", def->defname, if (is_valid_dblink_option(options, def->defname, UserMappingRelationId))
escape_param_str(strVal(def->arg))); appendStringInfo(buf, "%s='%s' ", def->defname,
escape_param_str(strVal(def->arg)));
} }
return buf->data; return buf->data;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment