8000 In pg_dump, remember connection passwords no matter how we got them. · home201448/postgres@1aa41e3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1aa41e3

Browse files
committed
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
1 parent bc7fcab commit 1aa41e3

File tree

1 file changed

+35
-17
lines changed

1 file changed

+35
-17
lines changed

src/bin/pg_dump/pg_backup_db.c

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
112112
PGconn *newConn;
113113
const char *newdb;
114114
const char *newuser;
115-
char *password = AH->savedPassword;
115+
char *password;
116116
bool new_pass;
117117

118118
if (!reqdb)
@@ -128,6 +128,8 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
128128
ahlog(AH, 1, "connecting to database \"%s\" as user \"%s\"\n",
129129
newdb, newuser);
130130

131+
password = AH->savedPassword ? pg_strdup(AH->savedPassword) : NULL;
132+
131133
if (AH->promptPassword == TRI_YES && password == NULL)
132134
{
133135
password = simple_prompt("Password: ", 100, false);
@@ -137,9 +139,8 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
137139

138140
do
139141
{
140-
#define PARAMS_ARRAY_SIZE 7
141-
const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
142-
const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
142+
const char *keywords[7];
143+
const char *values[7];
143144

144145
keywords[0] = "host";
145146
values[0] = PQhost(AH->connection);
@@ -159,9 +160,6 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
159160
new_pass = false;
160161
newConn = PQconnectdbParams(keywords, values, true);
161162

162-
free(keywords);
163-
free(values);
164-
165163
if (!newConn)
166164
exit_horribly(modulename, "failed to reconnect to database\n");
167165

@@ -192,7 +190,18 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
192190
}
193191
} while (new_pass);
194192

195-
AH->savedPassword = password;
193+
/*
194+
* We want to remember connection's actual password, whether or not we got
195+
* it by prompting. So we don't just store the password variable.
196+
*/
197+
if (PQconnectionUsedPassword(newConn))
198+
{
199+
if (AH->savedPassword)
200+
free(AH->savedPassword);
201+
AH->savedPassword = pg_strdup(PQpass(newConn));
202+
}
203+
if (password)
204+
free(password);
196205

197206
/* check for version mismatch */
198207
_check_database_version(AH);
@@ -221,12 +230,14 @@ ConnectDatabase(Archive *AHX,
221230
trivalue prompt_password)
222231
{
223232
ArchiveHandle *AH = (ArchiveHandle *) AHX;
224-
char *password = AH->savedPassword;
233+
char *password;
225234
bool new_pass;
226235

227236
if (AH->connection)
228237
exit_horribly(modulename, "already connected to a database\n");
229238

239+
password = AH->savedPassword ? pg_strdup(AH->savedPassword) : NULL;
240+
230241
if (prompt_password == TRI_YES && password == NULL)
231242
{
232243
password = simple_prompt("Password: ", 100, false);
@@ -241,9 +252,8 @@ ConnectDatabase(Archive *AHX,
241252
*/
242253
do
243254
{
244-
#define PARAMS_ARRAY_SIZE 7
245-
const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
246-
const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
255+
const char *keywords[7];
256+
const char *values[7];
247257

248258
keywords[0] = "host";
249259
values[0] = pghost;
@@ -263,9 +273,6 @@ ConnectDatabase(Archive *AHX,
263273
new_pass = false;
264274
AH->connection = PQconnectdbParams(keywords, values, true);
265275

266-
free(keywords);
267-
free(values);
268-
269276
if (!AH->connection)
270277
exit_horribly(modulename, "failed to connect to database\n");
271278

@@ -282,14 +289,25 @@ ConnectDatabase(Archive *AHX,
282289
}
283290
} while (new_pass);
284291

285-
AH->savedPassword = password;
286-
287292
/* check to see that the backend connection was successfully made */
288293
if (PQstatus(AH->connection) == CONNECTION_BAD)
289294
exit_horribly(modulename, "connection to database \"%s\" failed: %s",
290295
PQdb(AH->connection) ? PQdb(AH->connection) : "",
291296
PQerrorMessage(AH->connection));
292297

298+
/*
299+
* We want to remember connection's actual password, whether or not we got
300+
* it by prompting. So we don't just store the password variable.
301+
*/
302+
if (PQconnectionUsedPassword(AH->connection))
303+
{
304+
if (AH->savedPassword)
305+
free(AH->savedPassword);
306+
AH->savedPassword = pg_strdup(PQpass(AH->connection));
307+
}
308+
if (password)
309+
free(password);
310+
293311
/* check for version mismatch */
294312
_check_database_version(AH);
295313

0 commit comments

Comments
 (0)
0