Index: dblink.c
===================================================================
RCS file: /opt/src/cvs/pgsql/contrib/dblink/dblink.c,v
retrieving revision 1.74
diff -c -r1.74 dblink.c
*** dblink.c	3 Jul 2008 03:56:57 -0000	1.74
--- dblink.c	10 Aug 2008 04:59:05 -0000
***************
*** 93,99 ****
  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 char *generate_relation_name(Oid relid);
! 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);
  
  /* Global */
--- 93,99 ----
  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 char *generate_relation_name(Oid relid);
! static void dblink_security_check(void);
  static void dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail);
  
  /* Global */
***************
*** 164,169 ****
--- 164,170 ----
  			} \
  			else \
  			{ \
+ 				dblink_security_check(); \
  				connstr = conname_or_str; \
  				conn = PQconnectdb(connstr); \
  				if (PQstatus(conn) == CONNECTION_BAD) \
***************
*** 175,181 ****
  							 errmsg("could not establish connection"), \
  							 errdetail("%s", msg))); \
  				} \
- 				dblink_security_check(conn, rconn); \
  				freeconn = true; \
  			} \
  	} while (0)
--- 176,181 ----
***************
*** 229,234 ****
--- 229,237 ----
  
  	if (connname)
  		rconn = (remoteConn *) palloc(sizeof(remoteConn));
+ 
+ 	/* only connect if superuser */
+ 	dblink_security_check();
  	conn = PQconnectdb(connstr);
  
  	MemoryContextSwitchTo(oldcontext);
***************
*** 246,254 ****
  				 errdetail("%s", msg)));
  	}
  
- 	/* check password used if not superuser */
- 	dblink_security_check(conn, rconn);
- 
  	if (connname)
  	{
  		rconn->conn = conn;
--- 249,254 ----
***************
*** 2232,2253 ****
  }
  
  static void
! dblink_security_check(PGconn *conn, remoteConn *rconn)
  {
  	if (!superuser())
  	{
! 		if (!PQconnectionUsedPassword(conn))
! 		{
! 			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.")));
! 		}
  	}
  }
  
--- 2232,2246 ----
  }
  
  static void
! dblink_security_check()
  {
  	if (!superuser())
  	{
! 		ereport(ERROR,
! 			  (errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED),
! 			   errmsg("superuser is required"),
! 			   errdetail("Non-superuser cannot connect remotely."),
! 			   errhint("Use dblink_connect_u to connect as superuser.")));
  	}
  }
  
Index: dblink.sql.in
===================================================================
RCS file: /opt/src/cvs/pgsql/contrib/dblink/dblink.sql.in,v
retrieving revision 1.17
diff -c -r1.17 dblink.sql.in
*** dblink.sql.in	5 Apr 2008 02:44:42 -0000	1.17
--- dblink.sql.in	11 Aug 2008 03:44:34 -0000
***************
*** 3,10 ****
  -- Adjust this setting to control where the objects get created.
  SET search_path = public;
  
! -- dblink_connect now restricts non-superusers to password
! -- authenticated connections
  CREATE OR REPLACE FUNCTION dblink_connect (text)
  RETURNS text
  AS 'MODULE_PATHNAME','dblink_connect'
--- 3,9 ----
  -- Adjust this setting to control where the objects get created.
  SET search_path = public;
  
! -- dblink_connect now rejects all non-superusers
  CREATE OR REPLACE FUNCTION dblink_connect (text)
  RETURNS text
  AS 'MODULE_PATHNAME','dblink_connect'
***************
*** 16,23 ****
  LANGUAGE C STRICT;
  
  -- dblink_connect_u allows non-superusers to use
! -- non-password authenticated connections, but initially
! -- privileges are revoked from public
  CREATE OR REPLACE FUNCTION dblink_connect_u (text)
  RETURNS text
  AS 'MODULE_PATHNAME','dblink_connect'
--- 15,21 ----
  LANGUAGE C STRICT;
  
  -- dblink_connect_u allows non-superusers to use
! -- connections, but initially privileges are revoked from public
  CREATE OR REPLACE FUNCTION dblink_connect_u (text)
  RETURNS text
  AS 'MODULE_PATHNAME','dblink_connect'
***************
*** 202,204 ****
--- 200,229 ----
  RETURNS text
  AS 'MODULE_PATHNAME', 'dblink_error_message'
  LANGUAGE C STRICT;
+ 
+ -- dblink_u and dblink_exec_u allows non-superusers to use
+ -- connect strings, but initially privileges are revoked from public
+ 
+ CREATE OR REPLACE FUNCTION dblink_u (text, text)
+ RETURNS setof record
+ AS 'MODULE_PATHNAME','dblink_record'
+ LANGUAGE C STRICT SECURITY DEFINER;
+ REVOKE ALL ON FUNCTION dblink_u (text, text) FROM public;
+ 
+ CREATE OR REPLACE FUNCTION dblink_u (text, text, boolean)
+ RETURNS setof record
+ AS 'MODULE_PATHNAME','dblink_record'
+ LANGUAGE C STRICT SECURITY DEFINER;
+ REVOKE ALL ON FUNCTION dblink_u (text, text, boolean) FROM public;
+ 
+ CREATE OR REPLACE FUNCTION dblink_exec_u (text, text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_exec'
+ LANGUAGE C STRICT SECURITY DEFINER;
+ REVOKE ALL ON FUNCTION dblink_exec_u (text, text) FROM public;
+ 
+ CREATE OR REPLACE FUNCTION dblink_exec_u (text, text, boolean)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_exec'
+ LANGUAGE C STRICT SECURITY DEFINER;
+ REVOKE ALL ON FUNCTION dblink_exec_u (text, text, boolean) FROM public;
