Commit 67a472d7 authored by Tom Lane's avatar Tom Lane

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
parent be4b0c00
......@@ -12,6 +12,7 @@
#include "catalog/pg_class_d.h"
#include "common/connect.h"
#include "common/logging.h"
#include "common/string.h"
#include "getopt_long.h"
#include "libpq-fe.h"
#include "pg_getopt.h"
......@@ -293,8 +294,7 @@ PGconn *
sql_conn(struct options *my_opts)
{
PGconn *conn;
bool have_password = false;
char password[100];
char *password = NULL;
bool new_pass;
PGresult *res;
......@@ -316,7 +316,7 @@ sql_conn(struct options *my_opts)
keywords[2] = "user";
values[2] = my_opts->username;
keywords[3] = "password";
values[3] = have_password ? password : NULL;
values[3] = password;
keywords[4] = "dbname";
values[4] = my_opts->dbname;
keywords[5] = "fallback_application_name";
......@@ -336,11 +336,10 @@ sql_conn(struct options *my_opts)
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);
......
......@@ -24,6 +24,7 @@
#include "catalog/pg_class_d.h"
#include "common/connect.h"
#include "common/logging.h"
#include "common/string.h"
#include "getopt_long.h"
#include "libpq-fe.h"
#include "pg_getopt.h"
......@@ -69,15 +70,11 @@ vacuumlo(const char *database, const struct _param *param)
int i;
bool new_pass;
bool success = true;
static bool have_password = false;
static char password[100];
static char *password = NULL;
/* Note: password can be carried over from a previous call */
if (param->pg_prompt == TRI_YES && !have_password)
{
simple_prompt("Password: ", password, sizeof(password), false);
have_password = true;
}
if (param->pg_prompt == TRI_YES && !password)
password = simple_prompt("Password: ", false);
/*
* Start the connection. Loop until we have a password if requested by
......@@ -97,7 +94,7 @@ vacuumlo(const char *database, const struct _param *param)
keywords[2] = "user";
values[2] = param->pg_user;
keywords[3] = "password";
values[3] = have_password ? password : NULL;
values[3] = password;
keywords[4] = "dbname";
values[4] = database;
keywords[5] = "fallback_application_name";
......@@ -115,12 +112,11 @@ vacuumlo(const char *database, const struct _param *param)
if (PQstatus(conn) == CONNECTION_BAD &&
PQconnectionNeedsPassword(conn) &&
!have_password &&
!password &&
param->pg_prompt != 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);
......
......@@ -698,7 +698,7 @@ recv_password_packet(Port *port)
}
initStringInfo(&buf);
if (pq_getmessage(&buf, 1000)) /* receive password */
if (pq_getmessage(&buf, 0)) /* receive password */
{
/* EOF - pq_getmessage already logged a suitable message */
pfree(buf.data);
......
......@@ -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;
}
/*
......
......@@ -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;
......
......@@ -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.
......
......@@ -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);
......
......@@ -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);
......
......@@ -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
......
......@@ -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);
......
......@@ -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));
......
......@@ -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)
......
......@@ -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
{
......
......@@ -63,6 +63,7 @@ OBJS_COMMON = \
kwlookup.o \
link-canary.o \
md5.o \
pg_get_line.o \
pg_lzcompress.o \
pgfnames.o \
psprintf.o \
......@@ -92,7 +93,8 @@ OBJS_FRONTEND = \
fe_memutils.o \
file_utils.o \
logging.o \
restricted_token.o
restricted_token.o \
sprompt.o
# foo.o, foo_shlib.o, and foo_srv.o are all built from foo.c
OBJS_SHLIB = $(OBJS_FRONTEND:%.o=%_shlib.o)
......
/*-------------------------------------------------------------------------
*
* pg_get_line.c
* fgets() with an expansible result buffer
*
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* src/common/pg_get_line.c
*
*-------------------------------------------------------------------------
*/
#ifndef FRONTEND
#include "postgres.h"
#else
#include "postgres_fe.h"
#endif
#include "common/string.h"
#include "lib/stringinfo.h"
/*
* pg_get_line()
*
* This is meant to be equivalent to fgets(), except that instead of
* reading into a caller-supplied, fixed-size buffer, it reads into
* a palloc'd (in frontend, really malloc'd) string, which is resized
* as needed to handle indefinitely long input lines. The caller is
* responsible for pfree'ing the result string when appropriate.
*
* As with fgets(), returns NULL if there is a read error or if no
* characters are available before EOF. The caller can distinguish
* these cases by checking ferror(stream).
*
* Since this is meant to be equivalent to fgets(), the trailing newline
* (if any) is not stripped. Callers may wish to apply pg_strip_crlf().
*
* Note that while I/O errors are reflected back to the caller to be
* dealt with, an OOM condition for the palloc'd buffer will not be;
* there'll be an ereport(ERROR) or exit(1) inside stringinfo.c.
*/
char *
pg_get_line(FILE *stream)
{
StringInfoData buf;
initStringInfo(&buf);
/* Read some data, appending it to whatever we already have */
while (fgets(buf.data + buf.len, buf.maxlen - buf.len, stream) != NULL)
{
buf.len += strlen(buf.data + buf.len);
/* Done if we have collected a newline */
if (buf.len > 0 && buf.data[buf.len - 1] == '\n')
return buf.data;
/* Make some more room in the buffer, and loop to read more data */
enlargeStringInfo(&buf, 128);
}
/* Did fgets() fail because of an I/O error? */
if (ferror(stream))
{
/* ensure that free() doesn't mess up errno */
int save_errno = errno;
pfree(buf.data);
errno = save_errno;
return NULL;
}
/* If we read no data before reaching EOF, we should return NULL */
if (buf.len == 0)
{
pfree(buf.data);
return NULL;
}
/* No newline at EOF ... so return what we have */
return buf.data;
}
......@@ -29,12 +29,6 @@
#include "common/unicode_norm.h"
#include "mb/pg_wchar.h"
/*
* Limit on how large password's we will try to process. A password
* larger than this will be treated the same as out-of-memory.
*/
#define MAX_PASSWORD_LENGTH 1024
/*
* In backend, we will use palloc/pfree. In frontend, use malloc, and
* return SASLPREP_OOM on out-of-memory.
......@@ -1078,18 +1072,6 @@ pg_saslprep(const char *input, char **output)
/* Ensure we return *output as NULL on failure */
*output = NULL;
/* Check that the password isn't stupendously long */
if (strlen(input) > MAX_PASSWORD_LENGTH)
{
#ifndef FRONTEND
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("password too long")));
#else
return SASLPREP_OOM;
#endif
}
/*
* Quick check if the input is pure ASCII. An ASCII string requires no
* further processing.
......
......@@ -8,12 +8,15 @@
*
*
* IDENTIFICATION
* src/port/sprompt.c
* src/common/sprompt.c
*
*-------------------------------------------------------------------------
*/
#include "c.h"
#include "common/fe_memutils.h"
#include "common/string.h"
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#endif
......@@ -26,20 +29,17 @@
* passwords interactively. Reads from /dev/tty or stdin/stderr.
*
* prompt: The prompt to print, or NULL if none (automatically localized)
* destination: buffer in which to store result
* destlen: allocated length of destination
* echo: Set to false if you want to hide what is entered (for passwords)
*
* The input (without trailing newline) is returned in the destination buffer,
* with a '\0' appended.
* The input (without trailing newline) is returned as a malloc'd string.
* Caller is responsible for freeing it when done.
*/
void
simple_prompt(const char *prompt, char *destination, size_t destlen, bool echo)
char *
simple_prompt(const char *prompt, bool echo)
{
int length;
char *result;
FILE *termin,
*termout;
#if defined(HAVE_TERMIOS_H)
struct termios t_orig,
t;
......@@ -126,29 +126,14 @@ simple_prompt(const char *prompt, char *destination, size_t destlen, bool echo)
fflush(termout);
}
if (fgets(destination, destlen, termin) == NULL)
destination[0] = '\0';
result = pg_get_line(termin);
length = strlen(destination);
if (length > 0 && destination[length - 1] != '\n')
{
/* eat rest of the line */
char buf[128];
int buflen;
do
{
if (fgets(buf, sizeof(buf), termin) == NULL)
break;
buflen = strlen(buf);
} while (buflen > 0 && buf[buflen - 1] != '\n');
}
/* If we failed to read anything, just return an empty string */
if (result == NULL)
result = pg_strdup("");
/* strip trailing newline, including \r in case we're on Windows */
while (length > 0 &&
(destination[length - 1] == '\n' ||
destination[length - 1] == '\r'))
destination[--length] = '\0';
(void) pg_strip_crlf(result);
if (!echo)
{
......@@ -169,4 +154,6 @@ simple_prompt(const char *prompt, char *destination, size_t destlen, bool echo)
fclose(termin);
fclose(termout);
}
return result;
}
......@@ -10,10 +10,17 @@
#ifndef COMMON_STRING_H
#define COMMON_STRING_H
/* functions in src/common/string.c */
extern bool pg_str_endswith(const char *str, const char *end);
extern int strtoint(const char *pg_restrict str, char **pg_restrict endptr,
int base);
extern void pg_clean_ascii(char *str);
extern int pg_strip_crlf(char *str);
/* functions in src/common/pg_get_line.c */
extern char *pg_get_line(FILE *stream);
/* functions in src/common/sprompt.c */
extern char *simple_prompt(const char *prompt, bool echo);
#endif /* COMMON_STRING_H */
......@@ -213,10 +213,6 @@ extern char *pg_strerror_r(int errnum, char *buf, size_t buflen);
/* Wrap strsignal(), or provide our own version if necessary */
extern const char *pg_strsignal(int signum);
/* Portable prompt handling */
extern void simple_prompt(const char *prompt, char *destination, size_t destlen,
bool echo);
extern int pclose_check(FILE *stream);
/* Global variable holding time zone information. */
......
......@@ -35,6 +35,8 @@ include $(top_builddir)/src/Makefile.global
override CPPFLAGS := -I$(top_builddir)/src/port -DFRONTEND $(CPPFLAGS)
LIBS += $(PTHREAD_LIBS)
# If you add objects here, see also src/tools/msvc/Mkvcbuild.pm
OBJS = \
$(LIBOBJS) \
$(PG_CRC32C_OBJS) \
......@@ -55,7 +57,6 @@ OBJS = \
qsort_arg.o \
quotes.o \
snprintf.o \
sprompt.o \
strerror.o \
tar.o \
thread.o
......
......@@ -102,7 +102,7 @@ sub mkvcbuild
pread.c pwrite.c pg_bitutils.c
pg_strong_random.c pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c
pqsignal.c mkdtemp.c qsort.c qsort_arg.c quotes.c system.c
sprompt.c strerror.c tar.c thread.c
strerror.c tar.c thread.c
win32env.c win32error.c win32security.c win32setlocale.c);
push(@pgportfiles, 'strtof.c') if ($vsVersion < '14.00');
......@@ -123,7 +123,7 @@ sub mkvcbuild
config_info.c controldata_utils.c d2s.c encnames.c exec.c
f2s.c file_perm.c hashfn.c ip.c jsonapi.c
keywords.c kwlookup.c link-canary.c md5.c
pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c
pg_get_line.c pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c
saslprep.c scram-common.c string.c stringinfo.c unicode_norm.c username.c
wait_error.c wchar.c);
......@@ -139,7 +139,7 @@ sub mkvcbuild
our @pgcommonfrontendfiles = (
@pgcommonallfiles, qw(fe_memutils.c file_utils.c
logging.c restricted_token.c));
logging.c restricted_token.c sprompt.c));
our @pgcommonbkndfiles = @pgcommonallfiles;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment