From b16566d77168540730d7ca26f8fe1832f15d450e Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter_e@gmx.net>
Date: Sun, 18 Dec 2005 02:17:16 +0000
Subject: [PATCH] Add new psql command \password for changing role password
 with client-side password encryption.  Also alter createuser command to the
 same effect.

---
 doc/src/sgml/ref/alter_role.sgml  | 12 ++++-
 doc/src/sgml/ref/create_role.sgml | 14 ++++-
 doc/src/sgml/ref/psql-ref.sgml    | 15 +++++-
 src/bin/psql/Makefile             | 21 +++++---
 src/bin/psql/command.c            | 87 +++++++++++++++++++++++++------
 src/bin/psql/command.h            | 14 ++---
 src/bin/psql/mainloop.c           | 22 ++++----
 src/bin/psql/startup.c            |  4 +-
 src/bin/psql/tab-complete.c       |  6 ++-
 src/bin/scripts/createuser.c      | 18 ++++++-
 10 files changed, 163 insertions(+), 50 deletions(-)

diff --git a/doc/src/sgml/ref/alter_role.sgml b/doc/src/sgml/ref/alter_role.sgml
index 7ebd8014f29..641c4ef377c 100644
--- a/doc/src/sgml/ref/alter_role.sgml
+++ b/doc/src/sgml/ref/alter_role.sgml
@@ -1,5 +1,5 @@
 <!--
-$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
diff --git a/doc/src/sgml/ref/create_role.sgml b/doc/src/sgml/ref/create_role.sgml
index 16cd16ef5ac..9af33ce2120 100644
--- a/doc/src/sgml/ref/create_role.sgml
+++ b/doc/src/sgml/ref/create_role.sgml
@@ -1,5 +1,5 @@
 <!--
-$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>
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 3d6d0a1d7f7..c0c075f11e3 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1,5 +1,5 @@
 <!--
-$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>
 
diff --git a/src/bin/psql/Makefile b/src/bin/psql/Makefile
index 0499d726a95..0c689229364 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 fbff2092624..35da9cdf829 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 ffb47f8520e..0d969e015b7 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 775701a0106..cebeda70c00 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 8aa2b626b39..ee70c7b379a 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 f8629257f74..a6b230e32bf 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 bb68775fe99..adf9c41b3a2 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");
-- 
GitLab