summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2015-12-23 14:25:31 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2015-12-23 14:25:31 -0500
commit534a4159c290bd1d49bad702f7f600f92cfdcd67 (patch)
tree442ac2f3d3ad48667a1abf1df90927750d2f99ef
parentbc72c3b3fa109760c66635450b386edd7a8c29c7 (diff)
In pg_dump, remember connection passwords no matter how we got them.
When pg_dump prompts the user for a password, it remembers the password for possible re-use by parallel worker processes. However, libpq might have extracted the password from a connection string originally passed as "dbname". Since we don't record the original form of dbname but break it down to host/port/etc, the password gets lost. Fix that by retrieving the actual password from the PGconn. (It strikes me that this whole approach is rather broken, as it will also lose other information such as options that might have been present in the connection string. But we'll leave that problem for another day.) In passing, get rid of rather silly use of malloc() for small fixed-size arrays. Back-patch to 9.3 where parallel pg_dump was introduced. Report and fix by Zeus Kronion, adjusted a bit by Michael Paquier and me
-rw-r--r--src/bin/pg_dump/pg_backup_db.c52
1 files changed, 35 insertions, 17 deletions
diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c
index b5b778cde70..615504efd56 100644
--- a/src/bin/pg_dump/pg_backup_db.c
+++ b/src/bin/pg_dump/pg_backup_db.c
@@ -111,7 +111,7 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
PGconn *newConn;
const char *newdb;
const char *newuser;
- char *password = AH->savedPassword;
+ char *password;
bool new_pass;
if (!reqdb)
@@ -127,6 +127,8 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
ahlog(AH, 1, "connecting to database \"%s\" as user \"%s\"\n",
newdb, newuser);
+ password = AH->savedPassword ? pg_strdup(AH->savedPassword) : NULL;
+
if (AH->promptPassword == TRI_YES && password == NULL)
{
password = simple_prompt("Password: ", 100, false);
@@ -136,9 +138,8 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
do
{
-#define PARAMS_ARRAY_SIZE 7
- const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
- const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
+ const char *keywords[7];
+ const char *values[7];
keywords[0] = "host";
values[0] = PQhost(AH->connection);
@@ -158,9 +159,6 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
new_pass = false;
newConn = PQconnectdbParams(keywords, values, true);
- free(keywords);
- free(values);
-
if (!newConn)
exit_horribly(modulename, "failed to reconnect to database\n");
@@ -191,7 +189,18 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
}
} while (new_pass);
- AH->savedPassword = password;
+ /*
+ * We want to remember connection's actual password, whether or not we got
+ * it by prompting. So we don't just store the password variable.
+ */
+ if (PQconnectionUsedPassword(newConn))
+ {
+ if (AH->savedPassword)
+ free(AH->savedPassword);
+ AH->savedPassword = pg_strdup(PQpass(newConn));
+ }
+ if (password)
+ free(password);
/* check for version mismatch */
_check_database_version(AH);
@@ -220,12 +229,14 @@ ConnectDatabase(Archive *AHX,
enum trivalue prompt_password)
{
ArchiveHandle *AH = (ArchiveHandle *) AHX;
- char *password = AH->savedPassword;
+ char *password;
bool new_pass;
if (AH->connection)
exit_horribly(modulename, "already connected to a database\n");
+ password = AH->savedPassword ? pg_strdup(AH->savedPassword) : NULL;
+
if (prompt_password == TRI_YES && password == NULL)
{
password = simple_prompt("Password: ", 100, false);
@@ -240,9 +251,8 @@ ConnectDatabase(Archive *AHX,
*/
do
{
-#define PARAMS_ARRAY_SIZE 7
- const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
- const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
+ const char *keywords[7];
+ const char *values[7];
keywords[0] = "host";
values[0] = pghost;
@@ -262,9 +272,6 @@ ConnectDatabase(Archive *AHX,
new_pass = false;
AH->connection = PQconnectdbParams(keywords, values, true);
- free(keywords);
- free(values);
-
if (!AH->connection)
exit_horribly(modulename, "failed to connect to database\n");
@@ -281,14 +288,25 @@ ConnectDatabase(Archive *AHX,
}
} while (new_pass);
- AH->savedPassword = password;
-
/* check to see that the backend connection was successfully made */
if (PQstatus(AH->connection) == CONNECTION_BAD)
exit_horribly(modulename, "connection to database \"%s\" failed: %s",
PQdb(AH->connection) ? PQdb(AH->connection) : "",
PQerrorMessage(AH->connection));
+ /*
+ * We want to remember connection's actual password, whether or not we got
+ * it by prompting. So we don't just store the password variable.
+ */
+ if (PQconnectionUsedPassword(AH->connection))
+ {
+ if (AH->savedPassword)
+ free(AH->savedPassword);
+ AH->savedPassword = pg_strdup(PQpass(AH->connection));
+ }
+ if (password)
+ free(password);
+
/* check for version mismatch */
_check_database_version(AH);