diff -durpN postgresql/doc/src/sgml/libpq.sgml postgresql.1/doc/src/sgml/libpq.sgml
--- postgresql/doc/src/sgml/libpq.sgml	2012-08-03 09:39:30.114266570 +0200
+++ postgresql.1/doc/src/sgml/libpq.sgml	2012-11-20 11:57:41.359859195 +0100
@@ -496,6 +496,49 @@ typedef struct
      </listitem>
     </varlistentry>
 
+    <varlistentry id="libpq-pqconninfo">
+     <term><function>PQconninfo</function><indexterm><primary>PQconninfo</></></term>
+     <listitem>
+      <para>
+       Returns the connection options used by a live connection.
+<synopsis>
+/*
+ * Option flags for PQconninfo
+ */
+#define PG_CONNINFO_NORMAL              0x01
+#define PG_CONNINFO_PASSWORD            0x02
+#define PG_CONNINFO_REPLICATION         0x04
+
+PQconninfoOption *PQconninfo(PGconn *conn, int flags);
+</synopsis>
+      </para>
+
+      <para>
+       Returns a connection options array.  This can be used to determine
+       all possible <function>PQconnectdb</function> options and their
+       current values that were used to connect to the server. The return
+       value points to an array of <structname>PQconninfoOption</structname>
+       structures, which ends with an entry having a null <structfield>keyword</>
+       pointer.  Every notes above for <function>PQconndefaults</function> also apply.
+       An application may present a dialog using the previous settings by:
+<programlisting>
+        PQconninfoOption *options = PQconninfo(conn, PG_CONNINFO_NORMAL | PG_CONNINFO_PASSWORD);
+</programlisting>
+      </para>
+
+      <para>
+       The array returned by the <literal>PG_CONNINFO_REPLICATION</> flag is
+       a subset of <literal>PG_CONNINFO_NORMAL | PG_CONNINFO_PASSWORD</>.
+       This subset excludes some options from the array which are used by the
+       walreceiver module. <application>pg_basebackup</application> uses this
+       pre-filtered list of options to construct <literal>primary_conninfo</>
+       in the automatically generated recovery.conf file.
+      </para>
+
+     </listitem>
+    </varlistentry>
+
+
     <varlistentry id="libpq-pqconninfoparse">
      <term><function>PQconninfoParse</function><indexterm><primary>PQconninfoParse</></></term>
      <listitem>
diff -durpN postgresql/src/interfaces/libpq/exports.txt postgresql.1/src/interfaces/libpq/exports.txt
--- postgresql/src/interfaces/libpq/exports.txt	2012-10-09 09:58:14.342782974 +0200
+++ postgresql.1/src/interfaces/libpq/exports.txt	2012-11-20 10:55:03.396145749 +0100
@@ -164,3 +164,4 @@ PQsetSingleRowMode        161
 lo_lseek64                162
 lo_tell64                 163
 lo_truncate64             164
+PQconninfo                165
diff -durpN postgresql/src/interfaces/libpq/fe-connect.c postgresql.1/src/interfaces/libpq/fe-connect.c
--- postgresql/src/interfaces/libpq/fe-connect.c	2012-09-09 08:11:09.470401480 +0200
+++ postgresql.1/src/interfaces/libpq/fe-connect.c	2012-11-20 16:25:11.722295729 +0100
@@ -137,6 +137,9 @@ static int ldapServiceLookup(const char
  * PQconninfoOptions[] *must* be NULL.	In a working copy, non-null "val"
  * fields point to malloc'd strings that should be freed when the working
  * array is freed (see PQconninfoFree).
+ *
+ * If you add a new connection option to this list, remember to add it to
+ * PQconninfoMappings[] below.
  * ----------
  */
 static const PQconninfoOption PQconninfoOptions[] = {
@@ -203,16 +206,6 @@ static const PQconninfoOption PQconninfo
 	{"keepalives_count", NULL, NULL, NULL,
 	"TCP-Keepalives-Count", "", 10},	/* strlen(INT32_MAX) == 10 */
 
-#ifdef USE_SSL
-
-	/*
-	 * "requiressl" is deprecated, its purpose having been taken over by
-	 * "sslmode". It remains for backwards compatibility.
-	 */
-	{"requiressl", "PGREQUIRESSL", "0", NULL,
-	"Require-SSL", "D", 1},
-#endif
-
 	/*
 	 * ssl options are allowed even without client SSL support because the
 	 * client can still handle SSL modes "disable" and "allow". Other
@@ -264,6 +257,83 @@ static const PQconninfoOption PQconninfo
 	NULL, NULL, 0}
 };
 
+/*
+ * We need a mapping between the PQconninfoOptions[] array
+ * and PGconn members. We have to keep it separate from
+ * PQconninfoOptions[] to not leak info about PGconn members
+ * to clients.
+ */
+typedef struct PQconninfoMapping {
+	char		*keyword;
+	size_t		member_offset;
+	int		flags;
+} PQconninfoMapping;
+#define PGCONNMEMBERADDR(conn, mapping) ((char **)((char *)conn + mapping->member_offset))
+
+static const PQconninfoMapping PQconninfoMappings[] =
+{
+	/* "authtype" is not used anymore, there is no mapping to PGconn */
+	/* there is no mapping of "service" to PGconn */
+	{ "user", offsetof(struct pg_conn, pguser),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "password", offsetof(struct pg_conn, pgpass),
+	  PG_CONNINFO_PASSWORD | PG_CONNINFO_REPLICATION },
+	{ "connect_timeout", offsetof(struct pg_conn, connect_timeout),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "dbname", offsetof(struct pg_conn, dbName),
+	  PG_CONNINFO_NORMAL },
+	{ "host", offsetof(struct pg_conn, pghost),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "hostaddr", offsetof(struct pg_conn, pghostaddr),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "port", offsetof(struct pg_conn, pgport),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "client_encoding", offsetof(struct pg_conn, client_encoding_initial),
+	  PG_CONNINFO_NORMAL },
+	{ "tty", offsetof(struct pg_conn, pgtty),
+	  PG_CONNINFO_NORMAL },
+	{ "options", offsetof(struct pg_conn, pgoptions),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "application_name", offsetof(struct pg_conn, appname),
+	  PG_CONNINFO_NORMAL },
+	{ "fallback_application_name", offsetof(struct pg_conn, fbappname),
+	  PG_CONNINFO_NORMAL },
+	{ "keepalives", offsetof(struct pg_conn, keepalives),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "keepalives_idle", offsetof(struct pg_conn, keepalives_idle),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "keepalives_interval", offsetof(struct pg_conn, keepalives_interval),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "keepalives_count", offsetof(struct pg_conn, keepalives_count),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "sslmode", offsetof(struct pg_conn, sslmode),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "sslcompression", offsetof(struct pg_conn, sslcompression),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "sslcert", offsetof(struct pg_conn, sslcert),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "sslkey", offsetof(struct pg_conn, sslkey),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "sslrootcert", offsetof(struct pg_conn, sslrootcert),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "sslcrl", offsetof(struct pg_conn, sslcrl),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+	{ "requirepeer", offsetof(struct pg_conn, requirepeer),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
+	{ "krbsrvname", offsetof(struct pg_conn, krbsrvname),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+#endif
+#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
+	{ "gsslib", offsetof(struct pg_conn, requirepeer),
+	  PG_CONNINFO_NORMAL | PG_CONNINFO_REPLICATION },
+#endif
+	{ "replication", offsetof(struct pg_conn, replication),
+	  PG_CONNINFO_NORMAL },
+	/* Terminating entry --- MUST BE LAST */
+	{ NULL, 0, 0 }
+};
+
 static const PQEnvironmentOption EnvironmentOptions[] =
 {
 	/* common user-interface settings */
@@ -295,7 +365,8 @@ static PGconn *makeEmptyPGconn(void);
 static void fillPGconn(PGconn *conn, PQconninfoOption *connOptions);
 static void freePGconn(PGconn *conn);
 static void closePGconn(PGconn *conn);
-static PQconninfoOption *conninfo_init(PQExpBuffer errorMessage);
+static PQconninfoOption *conninfo_init(PQExpBuffer errorMessage,
+						int flags);
 static PQconninfoOption *parse_connection_string(const char *conninfo,
 						PQExpBuffer errorMessage, bool use_defaults);
 static int	uri_prefix_length(const char *connstr);
@@ -627,7 +698,7 @@ PQconnectStart(const char *conninfo)
 static void
 fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
 {
-	const char *tmp;
+	const PQconninfoMapping *mapping;
 
 	/*
 	 * Move option values into conn structure
@@ -637,72 +708,19 @@ fillPGconn(PGconn *conn, PQconninfoOptio
 	 *
 	 * XXX: probably worth checking strdup() return value here...
 	 */
-	tmp = conninfo_getval(connOptions, "hostaddr");
-	conn->pghostaddr = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "host");
-	conn->pghost = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "port");
-	conn->pgport = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "tty");
-	conn->pgtty = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "options");
-	conn->pgoptions = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "application_name");
-	conn->appname = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "fallback_application_name");
-	conn->fbappname = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "dbname");
-	conn->dbName = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "user");
-	conn->pguser = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "password");
-	conn->pgpass = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "connect_timeout");
-	conn->connect_timeout = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "client_encoding");
-	conn->client_encoding_initial = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "keepalives");
-	conn->keepalives = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "keepalives_idle");
-	conn->keepalives_idle = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "keepalives_interval");
-	conn->keepalives_interval = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "keepalives_count");
-	conn->keepalives_count = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "sslmode");
-	conn->sslmode = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "sslcompression");
-	conn->sslcompression = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "sslkey");
-	conn->sslkey = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "sslcert");
-	conn->sslcert = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "sslrootcert");
-	conn->sslrootcert = tmp ? strdup(tmp) : NULL;
-	tmp = conninfo_getval(connOptions, "sslcrl");
-	conn->sslcrl = tmp ? strdup(tmp) : NULL;
-#ifdef USE_SSL
-	tmp = conninfo_getval(connOptions, "requiressl");
-	if (tmp && tmp[0] == '1')
+	for (mapping = PQconninfoMappings; mapping->keyword; mapping++)
 	{
-		/* here warn that the requiressl option is deprecated? */
-		if (conn->sslmode)
-			free(conn->sslmode);
-		conn->sslmode = strdup("require");
+		const char *tmp = conninfo_getval(connOptions, mapping->keyword);
+
+		if (tmp)
+		{
+			char  **connmember = PGCONNMEMBERADDR(conn, mapping);
+
+			if (*connmember)
+				free(*connmember);
+			*connmember = tmp ? strdup(tmp) : NULL;
+		}
 	}
-#endif
-	tmp = conninfo_getval(connOptions, "requirepeer");
-	conn->requirepeer = tmp ? strdup(tmp) : NULL;
-#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
-	tmp = conninfo_getval(connOptions, "krbsrvname");
-	conn->krbsrvname = tmp ? strdup(tmp) : NULL;
-#endif
-#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
-	tmp = conninfo_getval(connOptions, "gsslib");
-	conn->gsslib = tmp ? strdup(tmp) : NULL;
-#endif
-	tmp = conninfo_getval(connOptions, "replication");
-	conn->replication = tmp ? strdup(tmp) : NULL;
 }
 
 /*
@@ -884,7 +902,7 @@ PQconndefaults(void)
 	if (PQExpBufferDataBroken(errorBuf))
 		return NULL;			/* out of memory already :-( */
 
-	connOptions = conninfo_init(&errorBuf);
+	connOptions = conninfo_init(&errorBuf, PG_CONNINFO_NORMAL | PG_CONNINFO_PASSWORD);
 	if (connOptions != NULL)
 	{
 		if (!conninfo_add_defaults(connOptions, &errorBuf))
@@ -4008,9 +4026,11 @@ PQconninfoParse(const char *conninfo, ch
  * Build a working copy of the constant PQconninfoOptions array.
  */
 static PQconninfoOption *
-conninfo_init(PQExpBuffer errorMessage)
+conninfo_init(PQExpBuffer errorMessage, int flags)
 {
+	const PQconninfoMapping	*mapping;
 	PQconninfoOption *options;
+	PQconninfoOption *opt_dest;
 
 	options = (PQconninfoOption *) malloc(sizeof(PQconninfoOptions));
 	if (options == NULL)
@@ -4019,7 +4039,23 @@ conninfo_init(PQExpBuffer errorMessage)
 						  libpq_gettext("out of memory\n"));
 		return NULL;
 	}
-	memcpy(options, PQconninfoOptions, sizeof(PQconninfoOptions));
+
+	opt_dest = options;
+	for (mapping = PQconninfoMappings; mapping->keyword; mapping++)
+	{
+		PQconninfoOption *opt_src;
+
+		if (!(mapping->flags & flags))
+			continue;
+
+		opt_src = conninfo_find((PQconninfoOption *)PQconninfoOptions, mapping->keyword);
+		if (opt_src)
+		{
+			memcpy(opt_dest, opt_src, sizeof(PQconninfoOption));
+			opt_dest++;
+		}
+	}
+	MemSet(opt_dest, 0, sizeof(PQconninfoOption));
 
 	return options;
 }
@@ -4095,7 +4131,7 @@ conninfo_parse(const char *conninfo, PQE
 	PQconninfoOption *options;
 
 	/* Make a working copy of PQconninfoOptions */
-	options = conninfo_init(errorMessage);
+	options = conninfo_init(errorMessage, PG_CONNINFO_NORMAL | PG_CONNINFO_PASSWORD);
 	if (options == NULL)
 		return NULL;
 
@@ -4295,7 +4331,7 @@ conninfo_array_parse(const char *const *
 	}
 
 	/* Make a working copy of PQconninfoOptions */
-	options = conninfo_init(errorMessage);
+	options = conninfo_init(errorMessage, PG_CONNINFO_NORMAL | PG_CONNINFO_PASSWORD);
 	if (options == NULL)
 	{
 		PQconninfoFree(dbname_options);
@@ -4485,7 +4521,7 @@ conninfo_uri_parse(const char *uri, PQEx
 	PQconninfoOption *options;
 
 	/* Make a working copy of PQconninfoOptions */
-	options = conninfo_init(errorMessage);
+	options = conninfo_init(errorMessage, PG_CONNINFO_NORMAL | PG_CONNINFO_PASSWORD);
 	if (options == NULL)
 		return NULL;
 
@@ -5066,6 +5102,45 @@ conninfo_find(PQconninfoOption *connOpti
 }
 
 
+/*
+ * Return the connection options used for the connections
+ */
+PQconninfoOption *
+PQconninfo(PGconn *conn, int flags)
+{
+	PQExpBufferData errorBuf;
+	PQconninfoOption *connOptions;
+
+	if (conn == NULL)
+		return NULL;
+
+	/* We don't actually report any errors here, but callees want a buffer */
+	initPQExpBuffer(&errorBuf);
+	if (PQExpBufferDataBroken(errorBuf))
+		return NULL;		/* out of memory already :-( */
+
+	connOptions = conninfo_init(&errorBuf, flags);
+
+	if (connOptions != NULL)
+	{
+		const PQconninfoMapping *mapping;
+
+		for (mapping = PQconninfoMappings; mapping->keyword; mapping++)
+		{
+			char **connmember = PGCONNMEMBERADDR(conn, mapping);
+
+			if (*connmember)
+				conninfo_storeval(connOptions, mapping->keyword, *connmember,
+					&errorBuf, false, false);
+		}
+	}
+
+	termPQExpBuffer(&errorBuf);
+
+	return connOptions;
+}
+
+
 void
 PQconninfoFree(PQconninfoOption *connOptions)
 {
diff -durpN postgresql/src/interfaces/libpq/libpq-fe.h postgresql.1/src/interfaces/libpq/libpq-fe.h
--- postgresql/src/interfaces/libpq/libpq-fe.h	2012-10-09 09:58:14.343782980 +0200
+++ postgresql.1/src/interfaces/libpq/libpq-fe.h	2012-11-20 11:49:36.747692399 +0100
@@ -36,6 +36,13 @@ extern		"C"
 #define PG_COPYRES_EVENTS		  0x04
 #define PG_COPYRES_NOTICEHOOKS	  0x08
 
+/*
+ * Option flags for PQconninfo
+ */
+#define PG_CONNINFO_NORMAL		0x01
+#define PG_CONNINFO_PASSWORD		0x02
+#define PG_CONNINFO_REPLICATION		0x04
+
 /* Application-visible enum types */
 
 /*
@@ -262,6 +269,9 @@ extern PQconninfoOption *PQconndefaults(
 /* parse connection options in same way as PQconnectdb */
 extern PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg);
 
+/* return the connection options used by a live connection */
+extern PQconninfoOption *PQconninfo(PGconn *conn, int flags);
+
 /* free the data structure returned by PQconndefaults() or PQconninfoParse() */
 extern void PQconninfoFree(PQconninfoOption *connOptions);
 
