diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c index 676dc7856e0..b95795a2b1e 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -8,7 +8,7 @@ * Darko Prenosil * Shridhar Daithankar * - * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.60.2.1 2007/07/09 01:32:30 joe Exp $ + * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.60.2.2 2008/01/03 21:28:18 tgl Exp $ * Copyright (c) 2001-2006, PostgreSQL Global Development Group * ALL RIGHTS RESERVED; * @@ -91,6 +91,7 @@ static HeapTuple get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 p static Oid get_relid_from_relname(text *relname_text); static char *generate_relation_name(Oid relid); static char *connstr_strip_password(const char *connstr); +static void dblink_security_check(PGconn *conn, remoteConn *rconn, const char *connstr); /* Global */ static remoteConn *pconn = NULL; @@ -177,6 +178,7 @@ typedef struct remoteConnHashEnt else \ { \ connstr = conname_or_str; \ + dblink_security_check(conn, rconn, connstr); \ conn = PQconnectdb(connstr); \ if (PQstatus(conn) == CONNECTION_BAD) \ { \ @@ -191,6 +193,16 @@ typedef struct remoteConnHashEnt } \ } while (0) +#define DBLINK_GET_NAMED_CONN \ + do { \ + char *conname = GET_STR(PG_GETARG_TEXT_P(0)); \ + rconn = getConnectionByName(conname); \ + if(rconn) \ + conn = rconn->conn; \ + else \ + DBLINK_CONN_NOT_AVAIL; \ + } while (0) + #define DBLINK_INIT \ do { \ if (!pconn) \ @@ -231,27 +243,8 @@ dblink_connect(PG_FUNCTION_ARGS) if (connname) rconn = (remoteConn *) palloc(sizeof(remoteConn)); - /* for non-superusers, check that server requires a password */ - if (!superuser()) - { - /* this attempt must fail */ - conn = PQconnectdb(connstr_strip_password(connstr)); - - if (PQstatus(conn) == CONNECTION_OK) - { - PQfinish(conn); - if (rconn) - pfree(rconn); - - ereport(ERROR, - (errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED), - errmsg("password is required"), - errdetail("Non-superuser cannot connect if the server does not request a password."), - errhint("Target server's authentication method must be changed."))); - } - else - PQfinish(conn); - } + /* check password used if not superuser */ + dblink_security_check(conn, rconn, connstr); conn = PQconnectdb(connstr); MemoryContextSwitchTo(oldcontext); @@ -1053,17 +1046,11 @@ PG_FUNCTION_INFO_V1(dblink_is_busy); Datum dblink_is_busy(PG_FUNCTION_ARGS) { - char *msg; PGconn *conn = NULL; - char *conname = NULL; - char *connstr = NULL; remoteConn *rconn = NULL; - bool freeconn = false; DBLINK_INIT; - DBLINK_GET_CONN; - if (!conn) - DBLINK_CONN_NOT_AVAIL; + DBLINK_GET_NAMED_CONN; PQconsumeInput(conn); PG_RETURN_INT32(PQisBusy(conn)); @@ -1084,26 +1071,20 @@ PG_FUNCTION_INFO_V1(dblink_cancel_query); Datum dblink_cancel_query(PG_FUNCTION_ARGS) { - char *msg; int res = 0; PGconn *conn = NULL; - char *conname = NULL; - char *connstr = NULL; remoteConn *rconn = NULL; - bool freeconn = false; PGcancel *cancel; char errbuf[256]; DBLINK_INIT; - DBLINK_GET_CONN; - if (!conn) - DBLINK_CONN_NOT_AVAIL; + DBLINK_GET_NAMED_CONN; cancel = PQgetCancel(conn); res = PQcancel(cancel, errbuf, 256); PQfreeCancel(cancel); - if (res == 0) + if (res == 1) PG_RETURN_TEXT_P(GET_TEXT("OK")); else PG_RETURN_TEXT_P(GET_TEXT(errbuf)); @@ -1126,18 +1107,13 @@ dblink_error_message(PG_FUNCTION_ARGS) { char *msg; PGconn *conn = NULL; - char *conname = NULL; - char *connstr = NULL; remoteConn *rconn = NULL; - bool freeconn = false; DBLINK_INIT; - DBLINK_GET_CONN; - if (!conn) - DBLINK_CONN_NOT_AVAIL; + DBLINK_GET_NAMED_CONN; msg = PQerrorMessage(conn); - if (!msg) + if (msg == NULL || msg[0] == '\0') PG_RETURN_TEXT_P(GET_TEXT("OK")); else PG_RETURN_TEXT_P(GET_TEXT(msg)); @@ -2428,3 +2404,28 @@ connstr_strip_password(const char *connstr) return result.data; } + +static void +dblink_security_check(PGconn *conn, remoteConn *rconn, const char *connstr) +{ + if (!superuser()) + { + /* this attempt must fail */ + conn = PQconnectdb(connstr_strip_password(connstr)); + + if (PQstatus(conn) == CONNECTION_OK) + { + PQfinish(conn); + if (rconn) + pfree(rconn); + + ereport(ERROR, + (errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED), + errmsg("password is required"), + errdetail("Non-superuser cannot connect if the server does not request a password."), + errhint("Target server's authentication method must be changed."))); + } + else + PQfinish(conn); + } +} diff --git a/contrib/dblink/expected/dblink.out b/contrib/dblink/expected/dblink.out index c98ae5cf6b5..67c7194e93b 100644 --- a/contrib/dblink/expected/dblink.out +++ b/contrib/dblink/expected/dblink.out @@ -722,6 +722,12 @@ SELECT dblink_get_connections(); {dtest1,dtest2,dtest3} (1 row) +SELECT dblink_is_busy('dtest1'); + dblink_is_busy +---------------- + 0 +(1 row) + SELECT dblink_disconnect('dtest1'); dblink_disconnect ------------------- @@ -756,3 +762,34 @@ SELECT * from result; 10 | k | {a10,b10,c10} (11 rows) +SELECT dblink_connect('dtest1', 'dbname=contrib_regression'); + dblink_connect +---------------- + OK +(1 row) + +SELECT * from + dblink_send_query('dtest1', 'select * from foo where f1 < 3') as t1; + t1 +---- + 1 +(1 row) + +SELECT dblink_cancel_query('dtest1'); + dblink_cancel_query +--------------------- + OK +(1 row) + +SELECT dblink_error_message('dtest1'); + dblink_error_message +---------------------- + OK +(1 row) + +SELECT dblink_disconnect('dtest1'); + dblink_disconnect +------------------- + OK +(1 row) + diff --git a/contrib/dblink/sql/dblink.sql b/contrib/dblink/sql/dblink.sql index 52a3d049b9c..c2d093323ab 100644 --- a/contrib/dblink/sql/dblink.sql +++ b/contrib/dblink/sql/dblink.sql @@ -342,9 +342,18 @@ UNION ORDER by f1; SELECT dblink_get_connections(); +SELECT dblink_is_busy('dtest1'); SELECT dblink_disconnect('dtest1'); SELECT dblink_disconnect('dtest2'); SELECT dblink_disconnect('dtest3'); + SELECT * from result; +SELECT dblink_connect('dtest1', 'dbname=contrib_regression'); +SELECT * from + dblink_send_query('dtest1', 'select * from foo where f1 < 3') as t1; + +SELECT dblink_cancel_query('dtest1'); +SELECT dblink_error_message('dtest1'); +SELECT dblink_disconnect('dtest1');