summaryrefslogtreecommitdiff
path: root/src/bin
diff options
context:
space:
mode:
authorTom Lane2020-09-04 00:09:18 +0000
committerTom Lane2020-09-04 00:09:18 +0000
commit67a472d71c98c3d2fa322a1b4013080b20720b98 (patch)
tree4b7a6254ec7d2da7f8b36b8eaf645c30a452c92c /src/bin
parentbe4b0c0077e6a1f7be0965f8d93696e0e0eadb52 (diff)
Remove arbitrary restrictions on password length.
This patch started out with the goal of harmonizing various arbitrary limits on password length, but after awhile a better idea emerged: let's just get rid of those fixed limits. recv_password_packet() has an arbitrary limit on the packet size, which we don't really need, so just drop it. (Note that this doesn't really affect anything for MD5 or SCRAM password verification, since those will hash the user's password to something shorter anyway. It does matter for auth methods that require a cleartext password.) Likewise remove the arbitrary error condition in pg_saslprep(). The remaining limits are mostly in client-side code that prompts for passwords. To improve those, refactor simple_prompt() so that it allocates its own result buffer that can be made as big as necessary. Actually, it proves best to make a separate routine pg_get_line() that has essentially the semantics of fgets(), except that it allocates a suitable result buffer and hence will never return a truncated line. (pg_get_line has a lot of potential applications to replace randomly-sized fgets buffers elsewhere, but I'll leave that for another patch.) I built pg_get_line() atop stringinfo.c, which requires moving that code to src/common/; but that seems fine since it was a poor fit for src/port/ anyway. This patch is mostly mine, but it owes a good deal to Nathan Bossart who pressed for a solution to the password length problem and created a predecessor patch. Also thanks to Peter Eisentraut and Stephen Frost for ideas and discussion. Discussion: https://postgr.es/m/09512C4F-8CB9-4021-B455-EF4C4F0D55A0@amazon.com
Diffstat (limited to 'src/bin')
-rw-r--r--src/bin/initdb/initdb.c21
-rw-r--r--src/bin/pg_basebackup/streamutil.c13
-rw-r--r--src/bin/pg_dump/pg_backup_db.c28
-rw-r--r--src/bin/pg_dump/pg_dumpall.c18
-rw-r--r--src/bin/pgbench/pgbench.c11
-rw-r--r--src/bin/psql/command.c22
-rw-r--r--src/bin/psql/startup.c14
-rw-r--r--src/bin/scripts/common.c34
-rw-r--r--src/bin/scripts/createuser.c18
-rw-r--r--src/bin/scripts/dropuser.c6
10 files changed, 92 insertions, 93 deletions
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 786672b1b65..73ddf408654 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -67,6 +67,7 @@
#include "common/file_utils.h"
#include "common/logging.h"
#include "common/restricted_token.h"
+#include "common/string.h"
#include "common/username.h"
#include "fe_utils/string_utils.h"
#include "getaddrinfo.h"
@@ -1481,23 +1482,25 @@ setup_auth(FILE *cmdfd)
static void
get_su_pwd(void)
{
- char pwd1[100];
- char pwd2[100];
+ char *pwd1;
if (pwprompt)
{
/*
* Read password from terminal
*/
+ char *pwd2;
+
printf("\n");
fflush(stdout);
- simple_prompt("Enter new superuser password: ", pwd1, sizeof(pwd1), false);
- simple_prompt("Enter it again: ", pwd2, sizeof(pwd2), false);
+ pwd1 = simple_prompt("Enter new superuser password: ", false);
+ pwd2 = simple_prompt("Enter it again: ", false);
if (strcmp(pwd1, pwd2) != 0)
{
fprintf(stderr, _("Passwords didn't match.\n"));
exit(1);
}
+ free(pwd2);
}
else
{
@@ -1510,7 +1513,6 @@ get_su_pwd(void)
* for now.
*/
FILE *pwf = fopen(pwfilename, "r");
- int i;
if (!pwf)
{
@@ -1518,7 +1520,8 @@ get_su_pwd(void)
pwfilename);
exit(1);
}
- if (!fgets(pwd1, sizeof(pwd1), pwf))
+ pwd1 = pg_get_line(pwf);
+ if (!pwd1)
{
if (ferror(pwf))
pg_log_error("could not read password from file \"%s\": %m",
@@ -1530,12 +1533,10 @@ get_su_pwd(void)
}
fclose(pwf);
- i = strlen(pwd1);
- while (i > 0 && (pwd1[i - 1] == '\r' || pwd1[i - 1] == '\n'))
- pwd1[--i] = '\0';
+ (void) pg_strip_crlf(pwd1);
}
- superuser_password = pg_strdup(pwd1);
+ superuser_password = pwd1;
}
/*
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index c08003e7f2c..be653ebb2d9 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -22,6 +22,7 @@
#include "common/fe_memutils.h"
#include "common/file_perm.h"
#include "common/logging.h"
+#include "common/string.h"
#include "datatype/timestamp.h"
#include "port/pg_bswap.h"
#include "pqexpbuffer.h"
@@ -49,8 +50,7 @@ char *dbuser = NULL;
char *dbport = NULL;
char *dbname = NULL;
int dbgetpassword = 0; /* 0=auto, -1=never, 1=always */
-static bool have_password = false;
-static char password[100];
+static char *password = NULL;
PGconn *conn = NULL;
/*
@@ -150,20 +150,21 @@ GetConnection(void)
}
/* If -W was given, force prompt for password, but only the first time */
- need_password = (dbgetpassword == 1 && !have_password);
+ need_password = (dbgetpassword == 1 && !password);
do
{
/* Get a new password if appropriate */
if (need_password)
{
- simple_prompt("Password: ", password, sizeof(password), false);
- have_password = true;
+ if (password)
+ free(password);
+ password = simple_prompt("Password: ", false);
need_password = false;
}
/* Use (or reuse, on a subsequent connection) password if we have it */
- if (have_password)
+ if (password)
{
keywords[i] = "password";
values[i] = password;
diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c
index 94af11b80a3..12899e26e29 100644
--- a/src/bin/pg_dump/pg_backup_db.c
+++ b/src/bin/pg_dump/pg_backup_db.c
@@ -18,6 +18,7 @@
#endif
#include "common/connect.h"
+#include "common/string.h"
#include "dumputils.h"
#include "fe_utils/string_utils.h"
#include "parallel.h"
@@ -122,7 +123,6 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
const char *newdb;
const char *newuser;
char *password;
- char passbuf[100];
bool new_pass;
if (!reqdb)
@@ -141,10 +141,7 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
password = AH->savedPassword;
if (AH->promptPassword == TRI_YES && password == NULL)
- {
- simple_prompt("Password: ", passbuf, sizeof(passbuf), false);
- password = passbuf;
- }
+ password = simple_prompt("Password: ", false);
initPQExpBuffer(&connstr);
appendPQExpBufferStr(&connstr, "dbname=");
@@ -191,8 +188,9 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
if (AH->promptPassword != TRI_NO)
{
- simple_prompt("Password: ", passbuf, sizeof(passbuf), false);
- password = passbuf;
+ if (password && password != AH->savedPassword)
+ free(password);
+ password = simple_prompt("Password: ", false);
}
else
fatal("connection needs password");
@@ -201,6 +199,9 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
}
} while (new_pass);
+ if (password && password != AH->savedPassword)
+ free(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.
@@ -242,7 +243,6 @@ ConnectDatabase(Archive *AHX,
{
ArchiveHandle *AH = (ArchiveHandle *) AHX;
char *password;
- char passbuf[100];
bool new_pass;
if (AH->connection)
@@ -251,10 +251,8 @@ ConnectDatabase(Archive *AHX,
password = AH->savedPassword;
if (prompt_password == TRI_YES && password == NULL)
- {
- simple_prompt("Password: ", passbuf, sizeof(passbuf), false);
- password = passbuf;
- }
+ password = simple_prompt("Password: ", false);
+
AH->promptPassword = prompt_password;
/*
@@ -293,8 +291,7 @@ ConnectDatabase(Archive *AHX,
prompt_password != TRI_NO)
{
PQfinish(AH->connection);
- simple_prompt("Password: ", passbuf, sizeof(passbuf), false);
- password = passbuf;
+ password = simple_prompt("Password: ", false);
new_pass = true;
}
} while (new_pass);
@@ -309,6 +306,9 @@ ConnectDatabase(Archive *AHX,
PQclear(ExecuteSqlQueryForSingleRow((Archive *) AH,
ALWAYS_SECURE_SEARCH_PATH_SQL));
+ if (password && password != AH->savedPassword)
+ free(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.
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 2c82b39af0d..97d2b8dac1c 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -21,6 +21,7 @@
#include "common/connect.h"
#include "common/file_utils.h"
#include "common/logging.h"
+#include "common/string.h"
#include "dumputils.h"
#include "fe_utils/string_utils.h"
#include "getopt_long.h"
@@ -1643,14 +1644,10 @@ connectDatabase(const char *dbname, const char *connection_string,
const char **keywords = NULL;
const char **values = NULL;
PQconninfoOption *conn_opts = NULL;
- static bool have_password = false;
- static char password[100];
+ static char *password = NULL;
- if (prompt_password == TRI_YES && !have_password)
- {
- simple_prompt("Password: ", password, sizeof(password), false);
- have_password = true;
- }
+ if (prompt_password == TRI_YES && !password)
+ password = simple_prompt("Password: ", false);
/*
* Start the connection. Loop until we have a password if requested by
@@ -1730,7 +1727,7 @@ connectDatabase(const char *dbname, const char *connection_string,
values[i] = pguser;
i++;
}
- if (have_password)
+ if (password)
{
keywords[i] = "password";
values[i] = password;
@@ -1757,12 +1754,11 @@ connectDatabase(const char *dbname, const char *connection_string,
if (PQstatus(conn) == CONNECTION_BAD &&
PQconnectionNeedsPassword(conn) &&
- !have_password &&
+ !password &&
prompt_password != TRI_NO)
{
PQfinish(conn);
- simple_prompt("Password: ", password, sizeof(password), false);
- have_password = true;
+ password = simple_prompt("Password: ", false);
new_pass = true;
}
} while (new_pass);
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 08a5947a9e6..332eabf6379 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -59,6 +59,7 @@
#include "common/int.h"
#include "common/logging.h"
+#include "common/string.h"
#include "fe_utils/cancel.h"
#include "fe_utils/conditional.h"
#include "getopt_long.h"
@@ -1174,8 +1175,7 @@ doConnect(void)
{
PGconn *conn;
bool new_pass;
- static bool have_password = false;
- static char password[100];
+ static char *password = NULL;
/*
* Start the connection. Loop until we have a password if requested by
@@ -1195,7 +1195,7 @@ doConnect(void)
keywords[2] = "user";
values[2] = login;
keywords[3] = "password";
- values[3] = have_password ? password : NULL;
+ values[3] = password;
keywords[4] = "dbname";
values[4] = dbName;
keywords[5] = "fallback_application_name";
@@ -1215,11 +1215,10 @@ doConnect(void)
if (PQstatus(conn) == CONNECTION_BAD &&
PQconnectionNeedsPassword(conn) &&
- !have_password)
+ !password)
{
PQfinish(conn);
- simple_prompt("Password: ", password, sizeof(password), false);
- have_password = true;
+ password = simple_prompt("Password: ", false);
new_pass = true;
}
} while (new_pass);
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 9902a4a2ba8..d4aa0976b5b 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -26,6 +26,7 @@
#include "command.h"
#include "common.h"
#include "common/logging.h"
+#include "common/string.h"
#include "copy.h"
#include "crosstabview.h"
#include "describe.h"
@@ -1964,11 +1965,11 @@ exec_command_password(PsqlScanState scan_state, bool active_branch)
{
char *opt0 = psql_scan_slash_option(scan_state,
OT_SQLID, NULL, true);
- char pw1[100];
- char pw2[100];
+ char *pw1;
+ char *pw2;
- simple_prompt("Enter new password: ", pw1, sizeof(pw1), false);
- simple_prompt("Enter it again: ", pw2, sizeof(pw2), false);
+ pw1 = simple_prompt("Enter new password: ", false);
+ pw2 = simple_prompt("Enter it again: ", false);
if (strcmp(pw1, pw2) != 0)
{
@@ -2013,6 +2014,8 @@ exec_command_password(PsqlScanState scan_state, bool active_branch)
if (opt0)
free(opt0);
+ free(pw1);
+ free(pw2);
}
else
ignore_slash_options(scan_state);
@@ -2058,8 +2061,7 @@ exec_command_prompt(PsqlScanState scan_state, bool active_branch,
if (!pset.inputfile)
{
- result = (char *) pg_malloc(4096);
- simple_prompt(prompt_text, result, 4096, true);
+ result = simple_prompt(prompt_text, true);
}
else
{
@@ -2982,19 +2984,19 @@ copy_previous_query(PQExpBuffer query_buf, PQExpBuffer previous_buf)
static char *
prompt_for_password(const char *username)
{
- char buf[100];
+ char *result;
if (username == NULL || username[0] == '\0')
- simple_prompt("Password: ", buf, sizeof(buf), false);
+ result = simple_prompt("Password: ", false);
else
{
char *prompt_text;
prompt_text = psprintf(_("Password for user %s: "), username);
- simple_prompt(prompt_text, buf, sizeof(buf), false);
+ result = simple_prompt(prompt_text, false);
free(prompt_text);
}
- return pg_strdup(buf);
+ return result;
}
static bool
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 3302bd4dd32..8232a0143bc 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -17,6 +17,7 @@
#include "command.h"
#include "common.h"
#include "common/logging.h"
+#include "common/string.h"
#include "describe.h"
#include "fe_utils/print.h"
#include "getopt_long.h"
@@ -119,8 +120,7 @@ main(int argc, char *argv[])
{
struct adhoc_opts options;
int successResult;
- bool have_password = false;
- char password[100];
+ char *password = NULL;
bool new_pass;
pg_logging_init(argv[0]);
@@ -233,8 +233,7 @@ main(int argc, char *argv[])
* offer a potentially wrong one. Typical uses of this option are
* noninteractive anyway.
*/
- simple_prompt("Password: ", password, sizeof(password), false);
- have_password = true;
+ password = simple_prompt("Password: ", false);
}
/* loop until we have a password if requested by backend */
@@ -251,7 +250,7 @@ main(int argc, char *argv[])
keywords[2] = "user";
values[2] = options.username;
keywords[3] = "password";
- values[3] = have_password ? password : NULL;
+ values[3] = password;
keywords[4] = "dbname"; /* see do_connect() */
values[4] = (options.list_dbs && options.dbname == NULL) ?
"postgres" : options.dbname;
@@ -269,7 +268,7 @@ main(int argc, char *argv[])
if (PQstatus(pset.db) == CONNECTION_BAD &&
PQconnectionNeedsPassword(pset.db) &&
- !have_password &&
+ !password &&
pset.getPassword != TRI_NO)
{
/*
@@ -287,9 +286,8 @@ main(int argc, char *argv[])
password_prompt = pg_strdup(_("Password: "));
PQfinish(pset.db);
- simple_prompt(password_prompt, password, sizeof(password), false);
+ password = simple_prompt(password_prompt, false);
free(password_prompt);
- have_password = true;
new_pass = true;
}
} while (new_pass);
diff --git a/src/bin/scripts/common.c b/src/bin/scripts/common.c
index 420d0d11a5a..e987eef2343 100644
--- a/src/bin/scripts/common.c
+++ b/src/bin/scripts/common.c
@@ -20,6 +20,7 @@
#include "common.h"
#include "common/connect.h"
#include "common/logging.h"
+#include "common/string.h"
#include "fe_utils/cancel.h"
#include "fe_utils/string_utils.h"
@@ -68,18 +69,17 @@ connectDatabase(const char *dbname, const char *pghost,
{
PGconn *conn;
bool new_pass;
- static bool have_password = false;
- static char password[100];
+ static char *password = NULL;
- if (!allow_password_reuse)
- have_password = false;
-
- if (!have_password && prompt_password == TRI_YES)
+ if (!allow_password_reuse && password)
{
- simple_prompt("Password: ", password, sizeof(password), false);
- have_password = true;
+ free(password);
+ password = NULL;
}
+ if (!password && prompt_password == TRI_YES)
+ password = simple_prompt("Password: ", false);
+
/*
* Start the connection. Loop until we have a password if requested by
* backend.
@@ -96,7 +96,7 @@ connectDatabase(const char *dbname, const char *pghost,
keywords[2] = "user";
values[2] = pguser;
keywords[3] = "password";
- values[3] = have_password ? password : NULL;
+ values[3] = password;
keywords[4] = "dbname";
values[4] = dbname;
keywords[5] = "fallback_application_name";
@@ -122,8 +122,9 @@ connectDatabase(const char *dbname, const char *pghost,
prompt_password != TRI_NO)
{
PQfinish(conn);
- simple_prompt("Password: ", password, sizeof(password), false);
- have_password = true;
+ if (password)
+ free(password);
+ password = simple_prompt("Password: ", false);
new_pass = true;
}
} while (new_pass);
@@ -444,14 +445,21 @@ yesno_prompt(const char *question)
for (;;)
{
- char resp[10];
+ char *resp;
- simple_prompt(prompt, resp, sizeof(resp), true);
+ resp = simple_prompt(prompt, true);
if (strcmp(resp, _(PG_YESLETTER)) == 0)
+ {
+ free(resp);
return true;
+ }
if (strcmp(resp, _(PG_NOLETTER)) == 0)
+ {
+ free(resp);
return false;
+ }
+ free(resp);
printf(_("Please answer \"%s\" or \"%s\".\n"),
_(PG_YESLETTER), _(PG_NOLETTER));
diff --git a/src/bin/scripts/createuser.c b/src/bin/scripts/createuser.c
index 9ced079ac75..6179199563c 100644
--- a/src/bin/scripts/createuser.c
+++ b/src/bin/scripts/createuser.c
@@ -13,6 +13,7 @@
#include "postgres_fe.h"
#include "common.h"
#include "common/logging.h"
+#include "common/string.h"
#include "fe_utils/simple_list.h"
#include "fe_utils/string_utils.h"
@@ -63,8 +64,6 @@ main(int argc, char *argv[])
int conn_limit = -2; /* less than minimum valid value */
bool pwprompt = false;
char *newpassword = NULL;
- char newuser_buf[128];
- char newpassword_buf[100];
/* Tri-valued variables. */
enum trivalue createdb = TRI_DEFAULT,
@@ -191,9 +190,7 @@ main(int argc, char *argv[])
{
if (interactive)
{
- simple_prompt("Enter name of role to add: ",
- newuser_buf, sizeof(newuser_buf), true);
- newuser = newuser_buf;
+ newuser = simple_prompt("Enter name of role to add: ", true);
}
else
{
@@ -206,17 +203,16 @@ main(int argc, char *argv[])
if (pwprompt)
{
- char pw2[100];
+ char *pw2;
- simple_prompt("Enter password for new role: ",
- newpassword_buf, sizeof(newpassword_buf), false);
- simple_prompt("Enter it again: ", pw2, sizeof(pw2), false);
- if (strcmp(newpassword_buf, pw2) != 0)
+ newpassword = simple_prompt("Enter password for new role: ", false);
+ pw2 = simple_prompt("Enter it again: ", false);
+ if (strcmp(newpassword, pw2) != 0)
{
fprintf(stderr, _("Passwords didn't match.\n"));
exit(1);
}
- newpassword = newpassword_buf;
+ free(pw2);
}
if (superuser == 0)
diff --git a/src/bin/scripts/dropuser.c b/src/bin/scripts/dropuser.c
index fee270d4f6d..f7ddd1402db 100644
--- a/src/bin/scripts/dropuser.c
+++ b/src/bin/scripts/dropuser.c
@@ -13,6 +13,7 @@
#include "postgres_fe.h"
#include "common.h"
#include "common/logging.h"
+#include "common/string.h"
#include "fe_utils/string_utils.h"
@@ -47,7 +48,6 @@ main(int argc, char *argv[])
enum trivalue prompt_password = TRI_DEFAULT;
bool echo = false;
bool interactive = false;
- char dropuser_buf[128];
PQExpBufferData sql;
@@ -112,9 +112,7 @@ main(int argc, char *argv[])
{
if (interactive)
{
- simple_prompt("Enter name of role to drop: ",
- dropuser_buf, sizeof(dropuser_buf), true);
- dropuser = dropuser_buf;
+ dropuser = simple_prompt("Enter name of role to drop: ", true);
}
else
{