From 523adcc12900d67a3a43bc7ca4ef4e84f062bb9a Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 12 Nov 2021 14:55:32 -0500 Subject: [PATCH] Make psql's \password default to CURRENT_USER, not PQuser(conn). The documentation says plainly that \password acts on "the current user" by default. What it actually acted on, or tried to, was the username used to log into the current session. This is not the same thing if one has since done SET ROLE or SET SESSION AUTHENTICATION. Aside from the possible surprise factor, it's quite likely that the current role doesn't have permissions to set the password of the original role. To fix, use "SELECT CURRENT_USER" to get the role name to act on. (This syntax works with servers at least back to 7.0.) Also, in hopes of reducing confusion, include the role name that will be acted on in the password prompt. The discrepancy from the documentation makes this a bug, so back-patch to all supported branches. Patch by me; thanks to Nathan Bossart for review. Discussion: https://postgr.es/m/747443.1635536754@sss.pgh.pa.us --- src/bin/psql/command.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index de4d6a8e37..7218e7798b 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -1824,12 +1824,29 @@ exec_command_password(PsqlScanState scan_state, bool active_branch) if (active_branch) { - char *opt0 = psql_scan_slash_option(scan_state, + char *user = psql_scan_slash_option(scan_state, OT_SQLID, NULL, true); char pw1[100]; char pw2[100]; + PQExpBufferData buf; - simple_prompt("Enter new password: ", pw1, sizeof(pw1), false); + if (user == NULL) + { + /* By default, the command applies to CURRENT_USER */ + PGresult *res; + + res = PSQLexec("SELECT CURRENT_USER"); + if (!res) + return PSQL_CMD_ERROR; + + user = pg_strdup(PQgetvalue(res, 0, 0)); + PQclear(res); + } + + initPQExpBuffer(&buf); + printfPQExpBuffer(&buf, _("Enter new password for user \"%s\": "), user); + + simple_prompt(buf.data, pw1, sizeof(pw1), false); simple_prompt("Enter it again: ", pw2, sizeof(pw2), false); if (strcmp(pw1, pw2) != 0) @@ -1839,14 +1856,8 @@ exec_command_password(PsqlScanState scan_state, bool active_branch) } else { - char *user; char *encrypted_password; - if (opt0) - user = opt0; - else - user = PQuser(pset.db); - encrypted_password = PQencryptPasswordConn(pset.db, pw1, user, NULL); if (!encrypted_password) @@ -1856,15 +1867,12 @@ exec_command_password(PsqlScanState scan_state, bool active_branch) } else { - PQExpBufferData buf; PGresult *res; - initPQExpBuffer(&buf); printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD ", fmtId(user)); appendStringLiteralConn(&buf, encrypted_password, pset.db); res = PSQLexec(buf.data); - termPQExpBuffer(&buf); if (!res) success = false; else @@ -1873,8 +1881,8 @@ exec_command_password(PsqlScanState scan_state, bool active_branch) } } - if (opt0) - free(opt0); + free(user); + termPQExpBuffer(&buf); } else ignore_slash_options(scan_state);