提交 b16566d7 编写于 作者: P Peter Eisentraut

Add new psql command \password for changing role password with client-side

password encryption.  Also alter createuser command to the same effect.
上级 ea771743
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/alter_role.sgml,v 1.2 2005/07/31 17:19:17 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/alter_role.sgml,v 1.3 2005/12/18 02:17:16 petere Exp $
PostgreSQL documentation
-->
......@@ -182,6 +182,16 @@ ALTER ROLE <replaceable class="PARAMETER">name</replaceable> RESET <replaceable>
to do that.
</para>
<para>
Caution must be exercised when specifying an unencrypted password
with this command. The password will be transmitted to the server
in cleartext, and it might also be logged in the client's command
history or the server log. <xref linkend="app-psql"
endterm="app-psql-title"> contains a command
<command>\password</command> that can be used to safely change a
role's password.
</para>
<para>
It is also possible to tie a
session default to a specific database rather than to a role; see
......
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_role.sgml,v 1.4 2005/11/03 00:51:43 neilc Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/create_role.sgml,v 1.5 2005/12/18 02:17:16 petere Exp $
PostgreSQL documentation
-->
......@@ -357,6 +357,18 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
connection <quote>slot</> remains for the role, it is possible that
both will fail. Also, the limit is never enforced for superusers.
</para>
<para>
Caution must be exercised when specifying an unencrypted password
with this command. The password will be transmitted to the server
in cleartext, and it might also be logged in the client's command
history or the server log. The command <xref
linkend="APP-CREATEUSER" endterm="APP-CREATEUSER-title">, however, transmits
the password encrypted. Also, <xref linkend="app-psql"
endterm="app-psql-title"> contains a command
<command>\password</command> that can be used to safely change the
password later.
</para>
</refsect1>
<refsect1>
......
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.155 2005/12/09 19:19:17 momjian Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.156 2005/12/18 02:17:16 petere Exp $
PostgreSQL documentation
-->
......@@ -1379,6 +1379,19 @@ lo_import 152801
</varlistentry>
<varlistentry>
<term><literal>\password [ <replaceable class=parameter>username</replaceable> ]</literal>
<listitem>
<para>
Changes the password of the specified user or by default the
current user. This command prompts for the new password,
encrypts it, and sends it to the server. This makes sure that
the new password does not appear in the command history, the
server log, or elsewhere in cleartext.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>\pset <replaceable class="parameter">parameter</replaceable> [ <replaceable class="parameter">value</replaceable> ]</literal></term>
......
......@@ -5,7 +5,7 @@
# Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
# $PostgreSQL: pgsql/src/bin/psql/Makefile,v 1.55 2005/12/09 21:19:35 petere Exp $
# $PostgreSQL: pgsql/src/bin/psql/Makefile,v 1.56 2005/12/18 02:17:16 petere Exp $
#
#-------------------------------------------------------------------------
......@@ -17,22 +17,27 @@ include $(top_builddir)/src/Makefile.global
REFDOCDIR= $(top_srcdir)/doc/src/sgml/ref
override CPPFLAGS := -DFRONTEND -I$(srcdir) -I$(libpq_srcdir) $(CPPFLAGS)
override CPPFLAGS := -DFRONTEND -I$(srcdir) -I$(libpq_srcdir) -I$(top_srcdir)/src/bin/pg_dump $(CPPFLAGS)
OBJS= command.o common.o help.o input.o stringutils.o mainloop.o copy.o \
startup.o prompt.o variables.o large_obj.o print.o describe.o \
psqlscan.o tab-complete.o mbprint.o $(WIN32RES)
psqlscan.o tab-complete.o mbprint.o dumputils.o $(WIN32RES)
EXTRA_OBJS = $(top_builddir)/src/backend/parser/keywords.o
FLEXFLAGS = -Cfe
all: submake-libpq submake-libpgport psql
all: submake-libpq submake-libpgport submake-backend psql
psql: $(OBJS) $(libpq_builddir)/libpq.a
$(CC) $(CFLAGS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LIBS) -o $@$(X)
$(CC) $(CFLAGS) $(OBJS) $(EXTRA_OBJS) $(libpq_pgport) $(LDFLAGS) $(LIBS) -o $@$(X)
help.o: $(srcdir)/sql_help.h
dumputils.c: % : $(top_srcdir)/src/bin/pg_dump/%
rm -f $@ && $(LN_S) $< .
ifdef PERL
$(srcdir)/sql_help.h: create_help.pl $(wildcard $(REFDOCDIR)/*.sgml)
$(PERL) $< $(REFDOCDIR) $@
......@@ -48,6 +53,10 @@ else
@$(missing) flex $< $@
endif
.PHONY: submake-backend
submake-backend:
$(MAKE) -C $(top_builddir)/src/backend/parser keywords.o
distprep: $(srcdir)/sql_help.h $(srcdir)/psqlscan.c
install: all installdirs
......@@ -62,7 +71,7 @@ uninstall:
# psqlscan.c is in the distribution tarball, so is not cleaned here
clean distclean:
rm -f psql$(X) $(OBJS)
rm -f psql$(X) $(OBJS) dumputils.c
maintainer-clean: distclean
rm -f $(srcdir)/sql_help.h $(srcdir)/psqlscan.c
......@@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.155 2005/12/08 21:18:22 petere Exp $
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.156 2005/12/18 02:17:16 petere Exp $
*/
#include "postgres_fe.h"
#include "command.h"
......@@ -35,6 +35,8 @@
#include "libpq-fe.h"
#include "pqexpbuffer.h"
#include "libpq/crypt.h"
#include "dumputils.h"
#include "common.h"
#include "copy.h"
......@@ -81,7 +83,7 @@ backslashResult
HandleSlashCmds(PsqlScanState scan_state,
PQExpBuffer query_buf)
{
backslashResult status = CMD_SKIP_LINE;
backslashResult status = PSQL_CMD_SKIP_LINE;
char *cmd;
char *arg;
......@@ -93,7 +95,7 @@ HandleSlashCmds(PsqlScanState scan_state,
/* And try to execute it */
status = exec_command(cmd, scan_state, query_buf);
if (status == CMD_UNKNOWN && strlen(cmd) > 1)
if (status == PSQL_CMD_UNKNOWN && strlen(cmd) > 1)
{
/*
* If the command was not recognized, try to parse it as a one-letter
......@@ -110,23 +112,23 @@ HandleSlashCmds(PsqlScanState scan_state,
status = exec_command(new_cmd, scan_state, query_buf);
if (status != CMD_UNKNOWN)
if (status != PSQL_CMD_UNKNOWN)
{
/* adjust cmd for possible messages below */
cmd[1] = '\0';
}
}
if (status == CMD_UNKNOWN)
if (status == PSQL_CMD_UNKNOWN)
{
if (pset.cur_cmd_interactive)
fprintf(stderr, _("Invalid command \\%s. Try \\? for help.\n"), cmd);
else
psql_error("invalid command \\%s\n", cmd);
status = CMD_ERROR;
status = PSQL_CMD_ERROR;
}
if (status != CMD_ERROR)
if (status != PSQL_CMD_ERROR)
{
/* eat any remaining arguments after a valid command */
/* note we suppress evaluation of backticks here */
......@@ -164,7 +166,7 @@ exec_command(const char *cmd,
bool success = true; /* indicate here if the command ran ok or
* failed */
bool quiet = QUIET();
backslashResult status = CMD_SKIP_LINE;
backslashResult status = PSQL_CMD_SKIP_LINE;
/*
* \a -- toggle field alignment This makes little sense but we keep it
......@@ -368,7 +370,7 @@ exec_command(const char *cmd,
break;
default:
status = CMD_UNKNOWN;
status = PSQL_CMD_UNKNOWN;
}
if (pattern)
......@@ -387,7 +389,7 @@ exec_command(const char *cmd,
if (!query_buf)
{
psql_error("no query buffer\n");
status = CMD_ERROR;
status = PSQL_CMD_ERROR;
}
else
{
......@@ -396,7 +398,7 @@ exec_command(const char *cmd,
expand_tilde(&fname);
if (fname)
canonicalize_path(fname);
status = do_edit(fname, query_buf) ? CMD_NEWEDIT : CMD_ERROR;
status = do_edit(fname, query_buf) ? PSQL_CMD_NEWEDIT : PSQL_CMD_ERROR;
free(fname);
}
}
......@@ -486,7 +488,7 @@ exec_command(const char *cmd,
pset.gfname = pg_strdup(fname);
}
free(fname);
status = CMD_SEND;
status = PSQL_CMD_SEND;
}
/* help */
......@@ -590,7 +592,7 @@ exec_command(const char *cmd,
}
else
status = CMD_UNKNOWN;
status = PSQL_CMD_UNKNOWN;
free(opt1);
free(opt2);
......@@ -618,6 +620,57 @@ exec_command(const char *cmd,
fflush(stdout);
}
/* \password -- set user password */
else if (strcmp(cmd, "password") == 0)
{
char *pw1;
char *pw2;
pw1 = simple_prompt("Enter new password: ", 100, false);
pw2 = simple_prompt("Enter it again: ", 100, false);
if (strcmp(pw1, pw2) != 0)
{
fprintf(stderr, _("Passwords didn't match.\n"));
success = false;
}
else
{
char *opt0 = psql_scan_slash_option(scan_state, OT_SQLID, NULL, true);
char *user;
char encrypted_password[MD5_PASSWD_LEN + 1];
if (opt0)
user = opt0;
else
user = PQuser(pset.db);
if (!pg_md5_encrypt(pw1, user, strlen(user), encrypted_password))
{
fprintf(stderr, _("Password encryption failed.\n"));
success = false;
}
else
{
PQExpBufferData buf;
PGresult *res;
initPQExpBuffer(&buf);
printfPQExpBuffer(&buf, "ALTER ROLE %s PASSWORD '%s';",
fmtId(user), encrypted_password);
res = PSQLexec(buf.data, false);
termPQExpBuffer(&buf);
if (!res)
success = false;
else
PQclear(res);
}
}
free(pw1);
free(pw2);
}
/* \pset -- set printing parameters */
else if (strcmp(cmd, "pset") == 0)
{
......@@ -640,7 +693,7 @@ exec_command(const char *cmd,
/* \q or \quit */
else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
status = CMD_TERMINATE;
status = PSQL_CMD_TERMINATE;
/* reset(clear) the buffer */
else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
......@@ -780,7 +833,7 @@ exec_command(const char *cmd,
if (!query_buf)
{
psql_error("no query buffer\n");
status = CMD_ERROR;
status = PSQL_CMD_ERROR;
}
else
{
......@@ -884,10 +937,10 @@ exec_command(const char *cmd,
#endif
else
status = CMD_UNKNOWN;
status = PSQL_CMD_UNKNOWN;
if (!success)
status = CMD_ERROR;
status = PSQL_CMD_ERROR;
return status;
}
......
......@@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/command.h,v 1.22 2005/01/01 05:43:08 momjian Exp $
* $PostgreSQL: pgsql/src/bin/psql/command.h,v 1.23 2005/12/18 02:17:16 petere Exp $
*/
#ifndef COMMAND_H
#define COMMAND_H
......@@ -15,12 +15,12 @@
typedef enum _backslashResult
{
CMD_UNKNOWN = 0, /* not done parsing yet (internal only) */
CMD_SEND, /* query complete; send off */
CMD_SKIP_LINE, /* keep building query */
CMD_TERMINATE, /* quit program */
CMD_NEWEDIT, /* query buffer was changed (e.g., via \e) */
CMD_ERROR /* the execution of the backslash command
PSQL_CMD_UNKNOWN = 0, /* not done parsing yet (internal only) */
PSQL_CMD_SEND, /* query complete; send off */
PSQL_CMD_SKIP_LINE, /* keep building query */
PSQL_CMD_TERMINATE, /* quit program */
PSQL_CMD_NEWEDIT, /* query buffer was changed (e.g., via \e) */
PSQL_CMD_ERROR /* the execution of the backslash command
* resulted in an error */
} backslashResult;
......
......@@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/mainloop.c,v 1.68 2005/10/15 02:49:40 momjian Exp $
* $PostgreSQL: pgsql/src/bin/psql/mainloop.c,v 1.69 2005/12/18 02:17:16 petere Exp $
*/
#include "postgres_fe.h"
#include "mainloop.h"
......@@ -41,7 +41,7 @@ MainLoop(FILE *source)
int added_nl_pos;
bool success;
volatile int successResult = EXIT_SUCCESS;
volatile backslashResult slashCmdStatus = CMD_UNKNOWN;
volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN;
volatile promptStatus_t prompt_status = PROMPT_READY;
volatile int count_eof = 0;
volatile bool die_on_error = false;
......@@ -104,7 +104,7 @@ MainLoop(FILE *source)
psql_scan_finish(scan_state);
psql_scan_reset(scan_state);
count_eof = 0;
slashCmdStatus = CMD_UNKNOWN;
slashCmdStatus = PSQL_CMD_UNKNOWN;
prompt_status = PROMPT_READY;
if (pset.cur_cmd_interactive)
......@@ -126,7 +126,7 @@ MainLoop(FILE *source)
fflush(stdout);
if (slashCmdStatus == CMD_NEWEDIT)
if (slashCmdStatus == PSQL_CMD_NEWEDIT)
{
/*
* just returned from editing the line? then just copy to the
......@@ -136,7 +136,7 @@ MainLoop(FILE *source)
/* reset parsing state since we are rescanning whole line */
resetPQExpBuffer(query_buf);
psql_scan_reset(scan_state);
slashCmdStatus = CMD_UNKNOWN;
slashCmdStatus = PSQL_CMD_UNKNOWN;
prompt_status = PROMPT_READY;
}
......@@ -231,7 +231,7 @@ MainLoop(FILE *source)
{
/* execute query */
success = SendQuery(query_buf->data);
slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
resetPQExpBuffer(previous_buf);
appendPQExpBufferStr(previous_buf, query_buf->data);
......@@ -257,16 +257,16 @@ MainLoop(FILE *source)
query_buf->len > 0 ?
query_buf : previous_buf);
success = slashCmdStatus != CMD_ERROR;
success = slashCmdStatus != PSQL_CMD_ERROR;
if ((slashCmdStatus == CMD_SEND || slashCmdStatus == CMD_NEWEDIT) &&
if ((slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_NEWEDIT) &&
query_buf->len == 0)
{
/* copy previous buffer to current for handling */
appendPQExpBufferStr(query_buf, previous_buf->data);
}
if (slashCmdStatus == CMD_SEND)
if (slashCmdStatus == PSQL_CMD_SEND)
{
success = SendQuery(query_buf->data);
......@@ -278,7 +278,7 @@ MainLoop(FILE *source)
psql_scan_reset(scan_state);
}
if (slashCmdStatus == CMD_TERMINATE)
if (slashCmdStatus == PSQL_CMD_TERMINATE)
break;
}
......@@ -291,7 +291,7 @@ MainLoop(FILE *source)
psql_scan_finish(scan_state);
free(line);
if (slashCmdStatus == CMD_TERMINATE)
if (slashCmdStatus == PSQL_CMD_TERMINATE)
{
successResult = EXIT_SUCCESS;
break;
......
......@@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.128 2005/11/22 18:17:29 momjian Exp $
* $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.129 2005/12/18 02:17:16 petere Exp $
*/
#include "postgres_fe.h"
......@@ -286,7 +286,7 @@ main(int argc, char *argv[])
options.action_string,
strlen(options.action_string));
successResult = HandleSlashCmds(scan_state, NULL) != CMD_ERROR
successResult = HandleSlashCmds(scan_state, NULL) != PSQL_CMD_ERROR
? EXIT_SUCCESS : EXIT_FAILURE;
psql_scan_destroy(scan_state);
......
......@@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.142 2005/12/08 21:33:58 momjian Exp $
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.143 2005/12/18 02:17:16 petere Exp $
*/
/*----------------------------------------------------------------------
......@@ -536,7 +536,7 @@ psql_completion(char *text, int start, int end)
"\\e", "\\echo", "\\encoding",
"\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
"\\o", "\\p", "\\pset", "\\q", "\\qecho", "\\r", "\\set", "\\t", "\\T",
"\\o", "\\p", "\\password", "\\pset", "\\q", "\\qecho", "\\r", "\\set", "\\t", "\\T",
"\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
};
......@@ -1808,6 +1808,8 @@ psql_completion(char *text, int start, int end)
COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
else if (strcmp(prev_wd, "\\h") == 0 || strcmp(prev_wd, "\\help") == 0)
COMPLETE_WITH_LIST(sql_commands);
else if (strcmp(prev_wd, "\\password") == 0)
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
else if (strcmp(prev_wd, "\\pset") == 0)
{
static const char *const my_list[] =
......
......@@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/scripts/createuser.c,v 1.23 2005/12/12 15:48:04 momjian Exp $
* $PostgreSQL: pgsql/src/bin/scripts/createuser.c,v 1.24 2005/12/18 02:17:16 petere Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -13,6 +13,7 @@
#include "postgres_fe.h"
#include "common.h"
#include "dumputils.h"
#include "libpq/crypt.h"
static void help(const char *progname);
......@@ -246,7 +247,20 @@ main(int argc, char *argv[])
if (encrypted == TRI_NO)
appendPQExpBuffer(&sql, " UNENCRYPTED");
appendPQExpBuffer(&sql, " PASSWORD ");
appendStringLiteral(&sql, newpassword, false);
if (encrypted != TRI_NO)
{
char encrypted_password[MD5_PASSWD_LEN + 1];
if (!pg_md5_encrypt(newpassword, newuser, strlen(newuser), encrypted_password))
{
fprintf(stderr, _("Password encryption failed.\n"));
exit(1);
}
appendStringLiteral(&sql, encrypted_password, false);
}
else
appendStringLiteral(&sql, newpassword, false);
}
if (superuser == TRI_YES)
appendPQExpBuffer(&sql, " SUPERUSER");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册