aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Conway <mail@joeconway.com>2016-12-22 09:19:44 -0800
committerJoe Conway <mail@joeconway.com>2016-12-22 09:20:35 -0800
commitc4448683893bd37b59003603bc9075d362e81b5a (patch)
treee408a8f2fc61a9da47893fd6c8a2650e9bd2157e
parent01ec25631fe0eae6af67c29c61a358dc6b92ed3c (diff)
downloadpostgresql-c4448683893bd37b59003603bc9075d362e81b5a.tar.gz
postgresql-c4448683893bd37b59003603bc9075d362e81b5a.zip
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
-rw-r--r--contrib/dblink/dblink.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index ee45cd244c6..10dc9bd347d 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -40,6 +40,7 @@
#include "access/reloptions.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
+#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_type.h"
#include "catalog/pg_user_mapping.h"
@@ -2727,6 +2728,25 @@ get_connect_string(const char *servername)
AclResult aclresult;
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 */
srvname = pstrdup(servername);
truncate_identifier(srvname, strlen(srvname), false);
@@ -2750,16 +2770,18 @@ get_connect_string(const char *servername)
{
DefElem *def = lfirst(cell);
- appendStringInfo(buf, "%s='%s' ", def->defname,
- escape_param_str(strVal(def->arg)));
+ if (is_valid_dblink_option(options, def->defname, ForeignDataWrapperRelationId))
+ appendStringInfo(buf, "%s='%s' ", def->defname,
+ escape_param_str(strVal(def->arg)));
}
foreach(cell, foreign_server->options)
{
DefElem *def = lfirst(cell);
- appendStringInfo(buf, "%s='%s' ", def->defname,
- escape_param_str(strVal(def->arg)));
+ if (is_valid_dblink_option(options, def->defname, ForeignServerRelationId))
+ appendStringInfo(buf, "%s='%s' ", def->defname,
+ escape_param_str(strVal(def->arg)));
}
foreach(cell, user_mapping->options)
@@ -2767,8 +2789,9 @@ get_connect_string(const char *servername)
DefElem *def = lfirst(cell);
- appendStringInfo(buf, "%s='%s' ", def->defname,
- escape_param_str(strVal(def->arg)));
+ if (is_valid_dblink_option(options, def->defname, UserMappingRelationId))
+ appendStringInfo(buf, "%s='%s' ", def->defname,
+ escape_param_str(strVal(def->arg)));
}
return buf->data;