diff --git a/doc/src/sgml/ref/alter_role.sgml b/doc/src/sgml/ref/alter_role.sgml
index 7ebd8014f2..641c4ef377 100644
--- a/doc/src/sgml/ref/alter_role.sgml
+++ b/doc/src/sgml/ref/alter_role.sgml
@@ -1,5 +1,5 @@
@@ -182,6 +182,16 @@ ALTER ROLE name RESET
to do that.
+
+ 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. contains a command
+ \password that can be used to safely change a
+ role's password.
+
+
It is also possible to tie a
session default to a specific database rather than to a role; see
diff --git a/doc/src/sgml/ref/create_role.sgml b/doc/src/sgml/ref/create_role.sgml
index 16cd16ef5a..9af33ce212 100644
--- a/doc/src/sgml/ref/create_role.sgml
+++ b/doc/src/sgml/ref/create_role.sgml
@@ -1,5 +1,5 @@
@@ -357,6 +357,18 @@ where option can be:
connection slot> remains for the role, it is possible that
both will fail. Also, the limit is never enforced for superusers.
+
+
+ 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 , however, transmits
+ the password encrypted. Also, contains a command
+ \password that can be used to safely change the
+ password later.
+
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 3d6d0a1d7f..c0c075f11e 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1,5 +1,5 @@
@@ -1379,6 +1379,19 @@ lo_import 152801
+
+ \password [ username ]
+
+
+ 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.
+
+
+
+
\pset parameter [ value ]
diff --git a/src/bin/psql/Makefile b/src/bin/psql/Makefile
index 0499d726a9..0c68922936 100644
--- a/src/bin/psql/Makefile
+++ b/src/bin/psql/Makefile
@@ -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
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index fbff209262..35da9cdf82 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.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;
}
diff --git a/src/bin/psql/command.h b/src/bin/psql/command.h
index ffb47f8520..0d969e015b 100644
--- a/src/bin/psql/command.h
+++ b/src/bin/psql/command.h
@@ -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;
diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c
index 775701a010..cebeda70c0 100644
--- a/src/bin/psql/mainloop.c
+++ b/src/bin/psql/mainloop.c
@@ -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;
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 8aa2b626b3..ee70c7b379 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -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);
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index f8629257f7..a6b230e32b 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -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[] =
diff --git a/src/bin/scripts/createuser.c b/src/bin/scripts/createuser.c
index bb68775fe9..adf9c41b3a 100644
--- a/src/bin/scripts/createuser.c
+++ b/src/bin/scripts/createuser.c
@@ -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");