diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index 6e7a1d834dee241a7c8adbb26412fd434720c349..a7c9c8616b30569b71f06857579da045720f8ca9 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -1,4 +1,4 @@
-<!-- $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.15 2001/08/01 23:25:39 tgl Exp $ -->
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.16 2001/08/15 18:42:14 momjian Exp $ -->
 
 <chapter id="client-authentication">
  <title>Client Authentication</title>
@@ -205,11 +205,10 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
          <para>
           Like the <literal>password</literal> method, but the password
           is sent over the wire encrypted using a simple
-          challenge-response protocol. This is still not
-          cryptographically secure but it protects against incidental
+          challenge-response protocol. This protects against incidental
           wire-sniffing. The name of a file may follow the
-          <literal>crypt</literal> keyword that contains a list of users
-          that this record pertains to.
+          <literal>crypt</literal> keyword.  It contains a list of users
+          for this record.
          </para>
         </listitem>
        </varlistentry>
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index ec35b9c96dfc70851aa37f914abf670c9d803311..a6351dd8bd2064a4b427d4aee185789e0271df10 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1,4 +1,4 @@
-<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.18 2001/06/22 23:27:48 petere Exp $ -->
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.19 2001/08/15 18:42:14 momjian Exp $ -->
 
 <chapter id="protocol">
  <title>Frontend/Backend Protocol</title>
@@ -1295,7 +1295,7 @@ EncryptedPasswordPacket (F)
 </Term>
 <ListItem>
 <Para>
-                The encrypted (using crypt()) password.
+                The encrypted (using MD5 or crypt()) password.
 </Para>
 </ListItem>
 </VarListEntry>
diff --git a/doc/src/sgml/ref/alter_user.sgml b/doc/src/sgml/ref/alter_user.sgml
index 534d2a7eb2dcd196f76c06d0148e3e9265a9ad6f..3a502197ab23d265812fb61223bc04d6c62d2c4d 100644
--- a/doc/src/sgml/ref/alter_user.sgml
+++ b/doc/src/sgml/ref/alter_user.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_user.sgml,v 1.14 2001/07/10 22:09:27 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_user.sgml,v 1.15 2001/08/15 18:42:14 momjian Exp $
 Postgres documentation
 -->
 
@@ -27,7 +27,7 @@ ALTER USER <replaceable class="PARAMETER">username</replaceable> [ [ WITH ] <rep
 
 where <replaceable class="PARAMETER">option</replaceable> can be:
 
-	  PASSWORD '<replaceable class="PARAMETER">password</replaceable>' 
+	  [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>' 
         | CREATEDB | NOCREATEDB
         | CREATEUSER | NOCREATEUSER 
         | VALID UNTIL '<replaceable class="PARAMETER">abstime</replaceable>'
@@ -53,10 +53,13 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
      </varlistentry>
 
      <varlistentry>
-      <term><replaceable class="PARAMETER">password</replaceable></term>
+      <term><replaceable class="PARAMETER">[ encrypted | unencrypted ] password</replaceable></term>
       <listitem>
        <para>
 	The new password to be used for this account.
+	<literal>Encrypted</literal>/ <literal>unencrypted</literal>
+	controls whether the password is stored encrypted in the
+	database.
        </para>
       </listitem>
      </varlistentry>
diff --git a/doc/src/sgml/ref/create_user.sgml b/doc/src/sgml/ref/create_user.sgml
index 8c97dbcf86795ff0ed2740887a051c1cb1277535..f72b20f59d7e1c2b2e1bfd913f679a12a9e803ab 100644
--- a/doc/src/sgml/ref/create_user.sgml
+++ b/doc/src/sgml/ref/create_user.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_user.sgml,v 1.17 2001/07/10 22:09:27 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_user.sgml,v 1.18 2001/08/15 18:42:14 momjian Exp $
 Postgres documentation
 -->
 
@@ -28,7 +28,7 @@ CREATE USER <replaceable class="PARAMETER">username</replaceable> [ [ WITH ] <re
 where <replaceable class="PARAMETER">option</replaceable> can be:
     
 	  SYSID <replaceable class="PARAMETER">uid</replaceable> 
-        | PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
+        | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
         | CREATEDB | NOCREATEDB
         | CREATEUSER | NOCREATEUSER
         | IN GROUP <replaceable class="PARAMETER">groupname</replaceable> [, ...]
@@ -72,12 +72,19 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
      </varlistentry>
 
      <varlistentry>
-      <term><replaceable class="parameter">password</replaceable></term>
+      <term><replaceable class="parameter">[ encrypted | unencrypted ] password</replaceable></term>
       <listitem>
        <para>
         Sets the user's password. If you do not plan to use password
         authentication you can omit this option, otherwise the user
         won't be able to connect to a password-authenticated server.
+	</para>
+	<para>
+	<literal>ENCRYPTED/UNENCRYPTED</literal> controls whether the
+	password is stored encrypted in the database. Older clients may
+	have trouble communicating using encrypted password storage.
+	</para>
+	<para>
         See the chapter on client authentication in the
 	<citetitle>Administrator's Guide</citetitle> for details on
         how to set up authentication mechanisms.
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index d4d4dd8d538c6a2274bafffb092d2913b289f032..6e80adf00ebb459194a30f62c17d4a944460168d 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.74 2001/08/09 16:20:43 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.75 2001/08/15 18:42:14 momjian Exp $
 -->
 
 <Chapter Id="runtime">
@@ -967,6 +967,18 @@ env PGOPTIONS='-c geqo=off' psql
 
    <para>
     <variablelist>
+     <varlistentry>
+      <term>AUSTRALIAN_TIMEZONES (<type>bool</type>)</term>
+      <listitem>
+       <para>
+        If set to true, <literal>CST</literal>, <literal>EST</literal>,
+        and <literal>SAT</literal> are interpreted as Australian
+        timezones rather than as North American Central/Eastern
+        Timezones and Saturday. The default is false.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <indexterm>
        <primary>deadlock</primary>
@@ -1260,18 +1272,6 @@ dynamic_library_path = '/usr/local/lib:/home/my_project/lib:$libdir:$libdir/cont
       </listitem>
      </varlistentry>
 
-     <varlistentry>
-      <term>AUSTRALIAN_TIMEZONES (<type>bool</type>)</term>
-      <listitem>
-       <para>
-        If set to true, <literal>CST</literal>, <literal>EST</literal>,
-        and <literal>SAT</literal> are interpreted as Australian
-        timezones rather than as North American Central/Eastern
-        Timezones and Saturday. The default is false.
-       </para>
-      </listitem>
-     </varlistentry>
-
      <varlistentry>
       <indexterm>
        <primary>SSL</primary>
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 47c8dfa4313813b90041ba527988e67a857aff1a..7f62b1992801107f073774da6134bb1066fa2835 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.79 2001/07/12 18:02:59 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.80 2001/08/15 18:42:14 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -25,6 +25,7 @@
 #include "catalog/indexing.h"
 #include "commands/user.h"
 #include "libpq/crypt.h"
+#include "libpq/md5.h"
 #include "miscadmin.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
@@ -34,7 +35,7 @@
 
 
 static void CheckPgUserAclNotNull(void);
-
+extern bool Password_encryption;
 
 /*---------------------------------------------------------------------
  * write_password_file / update_pg_pwd
@@ -201,72 +202,80 @@ CreateUser(CreateUserStmt *stmt)
 	int			max_id = -1;
 	List	   *item, *option;
 	char	   *password = NULL;	/* PostgreSQL user password */
+	bool		encrypt_password = Password_encryption;	/* encrypt password? */
+	char		encrypted_password[MD5_PASSWD_LEN+1];
 	int			sysid = 0;			/* PgSQL system id (valid if havesysid) */
 	bool		createdb = false;	/* Can the user create databases? */
 	bool		createuser = false;	/* Can this user create users? */
 	List	   *groupElts = NIL;	/* The groups the user is a member of */
 	char	   *validUntil = NULL;	/* The time the login is valid until */
-    DefElem    *dpassword = NULL;
-    DefElem    *dsysid = NULL;
-    DefElem    *dcreatedb = NULL;
-    DefElem    *dcreateuser = NULL;
-    DefElem    *dgroupElts = NULL;
-    DefElem    *dvalidUntil = NULL;
+	DefElem    *dpassword = NULL;
+	DefElem    *dsysid = NULL;
+	DefElem    *dcreatedb = NULL;
+	DefElem    *dcreateuser = NULL;
+	DefElem    *dgroupElts = NULL;
+	DefElem    *dvalidUntil = NULL;
 
 	/* Extract options from the statement node tree */
 	foreach(option, stmt->options)
 	{
 		DefElem *defel = (DefElem *) lfirst(option);
 
-        if (strcasecmp(defel->defname, "password") == 0) {
-            if (dpassword)
-                elog(ERROR, "CREATE USER: conflicting options");
-            dpassword = defel;
-        }
-        else if (strcasecmp(defel->defname, "sysid") == 0) {
-            if (dsysid)
-                elog(ERROR, "CREATE USER: conflicting options");
-            dsysid = defel;
-        }
-        else if (strcasecmp(defel->defname, "createdb") == 0) {
-            if (dcreatedb)
-                elog(ERROR, "CREATE USER: conflicting options");
-            dcreatedb = defel;
-        }
-        else if (strcasecmp(defel->defname, "createuser") == 0) {
-            if (dcreateuser)
-                elog(ERROR, "CREATE USER: conflicting options");
-            dcreateuser = defel;
-        } 
-        else if (strcasecmp(defel->defname, "groupElts") == 0) {
-            if (dgroupElts)
-                elog(ERROR, "CREATE USER: conflicting options");
-            dgroupElts = defel;
-        }
-        else if (strcasecmp(defel->defname, "validUntil") == 0) {
-            if (dvalidUntil)
-                elog(ERROR, "CREATE USER: conflicting options");
-            dvalidUntil = defel;
-        }
-        else 
-            elog(ERROR,"CREATE USER: option \"%s\" not recognized",
-                 defel->defname);
-    }
-
-    if (dcreatedb)
+		if (strcasecmp(defel->defname, "password") == 0 ||
+			strcasecmp(defel->defname, "encryptedPassword") == 0 ||
+			strcasecmp(defel->defname, "unencryptedPassword") == 0) {
+			if (dpassword)
+				elog(ERROR, "CREATE USER: conflicting options");
+			dpassword = defel;
+			if (strcasecmp(defel->defname, "encryptedPassword") == 0)
+				encrypt_password = true;
+			else if (strcasecmp(defel->defname, "unencryptedPassword") == 0)
+				encrypt_password = false;
+		}
+		else if (strcasecmp(defel->defname, "sysid") == 0) {
+			if (dsysid)
+				elog(ERROR, "CREATE USER: conflicting options");
+			dsysid = defel;
+		}
+		else if (strcasecmp(defel->defname, "createdb") == 0) {
+			if (dcreatedb)
+				elog(ERROR, "CREATE USER: conflicting options");
+			dcreatedb = defel;
+		}
+		else if (strcasecmp(defel->defname, "createuser") == 0) {
+			if (dcreateuser)
+				elog(ERROR, "CREATE USER: conflicting options");
+			dcreateuser = defel;
+		}
+		else if (strcasecmp(defel->defname, "groupElts") == 0) {
+			if (dgroupElts)
+				elog(ERROR, "CREATE USER: conflicting options");
+			dgroupElts = defel;
+		}
+		else if (strcasecmp(defel->defname, "validUntil") == 0) {
+			if (dvalidUntil)
+				elog(ERROR, "CREATE USER: conflicting options");
+			dvalidUntil = defel;
+		}
+		else
+			elog(ERROR,"CREATE USER: option \"%s\" not recognized",
+				 defel->defname);
+	}
+
+	if (dcreatedb)
 		createdb = intVal(dcreatedb->arg) != 0;
-    if (dcreateuser)
+	if (dcreateuser)
 		createuser = intVal(dcreateuser->arg) != 0;
-    if (dsysid)
+	if (dsysid)
 	{
 		sysid = intVal(dsysid->arg);
 		havesysid = true;
 	}
-    if (dvalidUntil)
+	if (dvalidUntil)
 		validUntil = strVal(dvalidUntil->arg);
-    if (dpassword)
+	if (dpassword)
 		password = strVal(dpassword->arg);
-    if (dgroupElts)
+	if (dgroupElts)
 		groupElts = (List *) dgroupElts->arg;
 
 	/* Check some permissions first */
@@ -337,8 +346,18 @@ CreateUser(CreateUserStmt *stmt)
 	new_record[Anum_pg_shadow_usecatupd - 1] = BoolGetDatum(createuser);
 
 	if (password)
-		new_record[Anum_pg_shadow_passwd - 1] =
-			DirectFunctionCall1(textin, CStringGetDatum(password));
+	{
+		if (!encrypt_password || isMD5(password))
+			new_record[Anum_pg_shadow_passwd - 1] =
+				DirectFunctionCall1(textin, CStringGetDatum(password));
+		else
+		{
+			if (!EncryptMD5(password, stmt->user, encrypted_password))
+				elog(ERROR, "CREATE USER: password encryption failed");
+			new_record[Anum_pg_shadow_passwd - 1] =
+				DirectFunctionCall1(textin, CStringGetDatum(encrypted_password));
+		}
+	}
 	if (validUntil)
 		new_record[Anum_pg_shadow_valuntil - 1] =
 			DirectFunctionCall1(nabstimein, CStringGetDatum(validUntil));
@@ -418,6 +437,8 @@ AlterUser(AlterUserStmt *stmt)
 	bool		null;
 	List       *option;
 	char	   *password = NULL;	/* PostgreSQL user password */
+	bool		encrypt_password = Password_encryption;	/* encrypt password? */
+	char		encrypted_password[MD5_PASSWD_LEN+1];
 	int			createdb = -1;		/* Can the user create databases? */
 	int			createuser = -1;	/* Can this user create users? */
 	char	   *validUntil = NULL;	/* The time the login is valid until */
@@ -431,10 +452,16 @@ AlterUser(AlterUserStmt *stmt)
 	{
 		DefElem *defel = (DefElem *) lfirst(option);
 
-		if (strcasecmp(defel->defname, "password") == 0) {
+		if (strcasecmp(defel->defname, "password") == 0 ||
+			strcasecmp(defel->defname, "encryptedPassword") == 0 ||
+			strcasecmp(defel->defname, "unencryptedPassword") == 0) {
 			if (dpassword)
 				elog(ERROR, "ALTER USER: conflicting options");
 			dpassword = defel;
+			if (strcasecmp(defel->defname, "encryptedPassword") == 0)
+				encrypt_password = true;
+			else if (strcasecmp(defel->defname, "unencryptedPassword") == 0)
+				encrypt_password = false;
 		}
 		else if (strcasecmp(defel->defname, "createdb") == 0) {
 			if (dcreatedb)
@@ -445,17 +472,17 @@ AlterUser(AlterUserStmt *stmt)
 			if (dcreateuser)
 				elog(ERROR, "ALTER USER: conflicting options");
 			dcreateuser = defel;
-		} 
+		}
 		else if (strcasecmp(defel->defname, "validUntil") == 0) {
 			if (dvalidUntil)
 				elog(ERROR, "ALTER USER: conflicting options");
 			dvalidUntil = defel;
 		}
-		else 
+		else
 			elog(ERROR,"ALTER USER: option \"%s\" not recognized",
 				 defel->defname);
 	}
- 
+
 	if (dcreatedb)
 		createdb = intVal(dcreatedb->arg);
 	if (dcreateuser)
@@ -464,8 +491,8 @@ AlterUser(AlterUserStmt *stmt)
 		validUntil = strVal(dvalidUntil->arg);
 	if (dpassword)
 		password = strVal(dpassword->arg);
- 
- 	if (password)
+
+	if (password)
 		CheckPgUserAclNotNull();
 
 	/* must be superuser or just want to change your own password */
@@ -552,8 +579,16 @@ AlterUser(AlterUserStmt *stmt)
 	/* password */
 	if (password)
 	{
-		new_record[Anum_pg_shadow_passwd - 1] =
-			DirectFunctionCall1(textin, CStringGetDatum(password));
+		if (!encrypt_password || isMD5(password))
+			new_record[Anum_pg_shadow_passwd - 1] =
+				DirectFunctionCall1(textin, CStringGetDatum(password));
+		else
+		{
+			if (!EncryptMD5(password, stmt->user, encrypted_password))
+				elog(ERROR, "CREATE USER: password encryption failed");
+			new_record[Anum_pg_shadow_passwd - 1] =
+				DirectFunctionCall1(textin, CStringGetDatum(encrypted_password));
+		}
 		new_record_nulls[Anum_pg_shadow_passwd - 1] = ' ';
 	}
 	else
@@ -793,40 +828,40 @@ CreateGroup(CreateGroupStmt *stmt)
 	Datum		new_record[Natts_pg_group];
 	char		new_record_nulls[Natts_pg_group];
 	List	   *item,
-               *option,
+			   *option,
 			   *newlist = NIL;
 	ArrayType  *userarray;
-    int			sysid = 0;
-    List	   *userElts = NIL;
-    DefElem    *dsysid = NULL;
-    DefElem    *duserElts = NULL;
+	int			sysid = 0;
+	List	   *userElts = NIL;
+	DefElem    *dsysid = NULL;
+	DefElem    *duserElts = NULL;
 
 	foreach(option, stmt->options)
 	{
 		DefElem *defel = (DefElem *) lfirst(option);
 
-        if (strcasecmp(defel->defname, "sysid") == 0) {
-            if (dsysid)
-                elog(ERROR, "CREATE GROUP: conflicting options");
-            dsysid = defel;
-        }
-        else if (strcasecmp(defel->defname, "userElts") == 0) {
-            if (duserElts)
-                elog(ERROR, "CREATE GROUP: conflicting options");
-            duserElts = defel;
-        }
-        else 
-            elog(ERROR,"CREATE GROUP: option \"%s\" not recognized",
-                 defel->defname);
-    }
-
-    if (dsysid)
+		if (strcasecmp(defel->defname, "sysid") == 0) {
+			if (dsysid)
+				elog(ERROR, "CREATE GROUP: conflicting options");
+			dsysid = defel;
+		}
+		else if (strcasecmp(defel->defname, "userElts") == 0) {
+			if (duserElts)
+				elog(ERROR, "CREATE GROUP: conflicting options");
+			duserElts = defel;
+		}
+		else
+			elog(ERROR,"CREATE GROUP: option \"%s\" not recognized",
+				 defel->defname);
+	}
+
+	if (dsysid)
 	{
 		sysid = intVal(dsysid->arg);
 		havesysid = true;
 	}
 
-    if (duserElts)
+	if (duserElts)
 		userElts = (List *) duserElts->arg;
 
 	/*
diff --git a/src/backend/libpq/Makefile b/src/backend/libpq/Makefile
index 619a0c86900075f8a29132dc95eaac28848740ca..d71e5c9765d4be8d35e77cba92b1fa4cc72f745b 100644
--- a/src/backend/libpq/Makefile
+++ b/src/backend/libpq/Makefile
@@ -4,7 +4,7 @@
 #    Makefile for libpq subsystem (backend half of libpq interface)
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.24 2000/08/25 10:00:30 petere Exp $
+#    $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.25 2001/08/15 18:42:14 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -15,7 +15,7 @@ include $(top_builddir)/src/Makefile.global
 # be-fsstubs is here for historical reasons, probably belongs elsewhere
 
 OBJS = be-fsstubs.o \
-	auth.o crypt.o hba.o password.o \
+	auth.o crypt.o hba.o md5.o password.o \
 	pqcomm.o pqformat.o pqpacket.o pqsignal.o util.o
 
 
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 81d4865ce6971783d5926c365e5ef2c56b5e1530..fe7bc3c9d1d0ecb5921f85b49398897b332a6089 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.56 2001/08/07 10:44:13 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.57 2001/08/15 18:42:14 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -420,9 +420,8 @@ auth_failed(Port *port)
 			authmethod = "IDENT";
 			break;
 		case uaPassword:
-			authmethod = "Password";
-			break;
 		case uaCrypt:
+		case uaMD5:
 			authmethod = "Password";
 			break;
 	}
@@ -507,6 +506,11 @@ ClientAuthentication(Port *port)
 			status = recv_and_check_password_packet(port);
 			break;
 
+		case uaMD5:
+			sendAuthRequest(port, AUTH_REQ_MD5);
+			status = recv_and_check_password_packet(port);
+			break;
+
 		case uaTrust:
 			status = STATUS_OK;
 			break;
@@ -532,7 +536,7 @@ sendAuthRequest(Port *port, AuthRequest areq)
 	pq_sendint(&buf, (int32) areq, sizeof(int32));
 
 	/* Add the salt for encrypted passwords. */
-	if (areq == AUTH_REQ_CRYPT)
+	if (areq == AUTH_REQ_CRYPT || areq == AUTH_REQ_MD5)
 	{
 		pq_sendint(&buf, port->salt[0], 1);
 		pq_sendint(&buf, port->salt[1], 1);
@@ -557,7 +561,7 @@ recv_and_check_password_packet(Port *port)
 	if (pq_eof() == EOF || pq_getint(&len, 4) == EOF)
 		return STATUS_ERROR;	/* client didn't want to send password */
 	initStringInfo(&buf);
-	pq_getstr(&buf);
+	pq_getstr(&buf);		/* receive password */
 
 	if (DebugLvl)
 		fprintf(stderr, "received password packet with len=%d, pw=%s\n",
@@ -579,7 +583,7 @@ checkPassword(Port *port, char *user, char *password)
 	if (port->auth_arg[0] != '\0')
 		return verify_password(port, user, password);
 
-	return crypt_verify(port, user, password);
+	return md5_crypt_verify(port, user, password);
 }
 
 
@@ -594,7 +598,6 @@ old_be_recvauth(Port *port)
 	MsgType		msgtype = (MsgType) port->proto;
 
 	/* Handle the authentication that's offered. */
-
 	switch (msgtype)
 	{
 		case STARTUP_KRB4_MSG:
@@ -634,6 +637,7 @@ map_old_to_new(Port *port, UserAuth old, int status)
 	switch (port->auth_method)
 	{
 		case uaCrypt:
+		case uaMD5:
 		case uaReject:
 			status = STATUS_ERROR;
 			break;
diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c
index e89963f9f65b9f74ea324cd45d6400b76cb3e92a..62393d26e0201133b9ea00437419a49d954fc7a1 100644
--- a/src/backend/libpq/crypt.c
+++ b/src/backend/libpq/crypt.c
@@ -9,7 +9,7 @@
  * Dec 17, 1997 - Todd A. Brandys
  *	Orignal Version Completed.
  *
- * $Id: crypt.c,v 1.32 2001/06/23 23:26:17 petere Exp $
+ * $Id: crypt.c,v 1.33 2001/08/15 18:42:14 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,6 +19,7 @@
 
 #include "postgres.h"
 #include "libpq/crypt.h"
+#include "libpq/md5.h"
 #include "miscadmin.h"
 #include "storage/fd.h"
 #include "utils/nabstime.h"
@@ -254,7 +255,7 @@ crypt_getloginfo(const char *user, char **passwd, char **valuntil)
 /*-------------------------------------------------------------------------*/
 
 int
-crypt_verify(const Port *port, const char *user, const char *pgpass)
+md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
 {
 
 	char	   *passwd,
@@ -280,9 +281,47 @@ crypt_verify(const Port *port, const char *user, const char *pgpass)
 	 * Compare with the encrypted or plain password depending on the
 	 * authentication method being used for this connection.
 	 */
-
-	crypt_pwd =
-		(port->auth_method == uaCrypt ? crypt(passwd, port->salt) : passwd);
+	 switch (port->auth_method)
+	 {
+		case uaCrypt:
+			crypt_pwd = crypt(passwd, port->salt);
+			break;
+		case uaMD5:
+			crypt_pwd = palloc(MD5_PASSWD_LEN+1);
+
+			if (isMD5(passwd))
+			{
+				if (!EncryptMD5(passwd + strlen("md5"),
+								(char *)port->salt, crypt_pwd))
+				{
+					pfree(crypt_pwd);
+					return STATUS_ERROR;
+				}
+			}
+			else
+			{
+				char *crypt_pwd2 = palloc(MD5_PASSWD_LEN+1);
+
+				if (!EncryptMD5(passwd, port->user, crypt_pwd2))
+				{
+					pfree(crypt_pwd);
+					pfree(crypt_pwd2);
+					return STATUS_ERROR;
+				}
+				if (!EncryptMD5(crypt_pwd2 + strlen("md5"), port->salt,
+								crypt_pwd))
+				{
+					pfree(crypt_pwd);
+					pfree(crypt_pwd2);
+					return STATUS_ERROR;
+				}
+				pfree(crypt_pwd2);
+			}
+			break;
+		default:
+			crypt_pwd = passwd;
+			break;
+	}
 
 	if (!strcmp(pgpass, crypt_pwd))
 	{
@@ -302,9 +341,11 @@ crypt_verify(const Port *port, const char *user, const char *pgpass)
 			retval = STATUS_OK;
 	}
 
-	pfree((void *) passwd);
+	pfree(passwd);
 	if (valuntil)
-		pfree((void *) valuntil);
+		pfree(valuntil);
+	if (port->auth_method == uaMD5)
+		pfree(crypt_pwd);
 
 	return retval;
 }
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index b91427460d263d4099cc636726fe7f99540c1591..d12225ab0eae15ef5e508a1d9c5dcf73fb540b86 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.61 2001/08/02 14:39:35 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.62 2001/08/15 18:42:15 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -203,8 +203,8 @@ free_lines(List **lines)
  *  *error_p.  line points to the next token of the line.
  */
 static void
-parse_hba_auth(List *line, UserAuth *userauth_p, char *auth_arg,
-				bool *error_p)
+parse_hba_auth(List *line, ProtocolVersion proto, UserAuth *userauth_p,
+				char *auth_arg, bool *error_p)
 {
 	char		*token;
 
@@ -227,7 +227,15 @@ parse_hba_auth(List *line, UserAuth *userauth_p, char *auth_arg,
 		else if (strcmp(token, "reject") == 0)
 			*userauth_p = uaReject;
 		else if (strcmp(token, "crypt") == 0)
-			*userauth_p = uaCrypt;
+		{
+			/* if the client supports it, use MD5 */
+			if (PG_PROTOCOL_MAJOR(proto) > 2 ||
+				(PG_PROTOCOL_MAJOR(proto) == 2 &&
+				 PG_PROTOCOL_MINOR(proto) >= 1))
+				*userauth_p = uaMD5;
+			else
+				*userauth_p = uaCrypt;
+		}
 		else
 			*error_p = true;
 		line = lnext(line);
@@ -285,7 +293,8 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
 		line = lnext(line);
 		if (!line)
 			goto hba_syntax;
-		parse_hba_auth(line, &port->auth_method, port->auth_arg, error_p);
+		parse_hba_auth(line, port->proto, &port->auth_method,
+					   port->auth_arg, error_p);
 		if (*error_p)
 			goto hba_syntax;
 
@@ -354,7 +363,8 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
 		line = lnext(line);
 		if (!line)
 			goto hba_syntax;
-		parse_hba_auth(line, &port->auth_method, port->auth_arg, error_p);
+		parse_hba_auth(line, port->proto, &port->auth_method,
+					   port->auth_arg, error_p);
 		if (*error_p)
 			goto hba_syntax;
 
diff --git a/src/backend/libpq/password.c b/src/backend/libpq/password.c
index 2d4559a296c42f0631846d539d8332041ff61d83..e98ab6bc0af7201fb0f68c5ce16afba54df67d2b 100644
--- a/src/backend/libpq/password.c
+++ b/src/backend/libpq/password.c
@@ -2,7 +2,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: password.c,v 1.37 2001/06/18 16:11:30 momjian Exp $
+ * $Id: password.c,v 1.38 2001/08/15 18:42:15 momjian Exp $
  *
  */
 
@@ -82,11 +82,14 @@ verify_password(const Port *port, const char *user, const char *password)
 			 * the current code needs non-encrypted passwords to
 			 * encrypt with a random salt.
 			 */
-			if (port->auth_method == uaCrypt
-				|| test_pw == NULL || test_pw[0] == '\0'
-				|| strcmp(test_pw, "+") == 0)
-				return crypt_verify(port, user, password);
-
+			if (port->auth_method == uaCrypt ||
+				port->auth_method == uaMD5 ||
+				test_pw == NULL ||
+				test_pw[0] == '\0' ||
+				strcmp(test_pw, "+") == 0)
+				return md5_crypt_verify(port, user, password);
+
+			/* external password file is crypt-only */
 			if (strcmp(crypt(password, test_pw), test_pw) == 0)
 			{
 				/* it matched. */
diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample
index 7dc39ee67b950711a3a15705782bd8da19372f91..a489b78a70b400baca506d54c26a7776814e85b8 100644
--- a/src/backend/libpq/pg_hba.conf.sample
+++ b/src/backend/libpq/pg_hba.conf.sample
@@ -3,7 +3,6 @@
 # 
 # 
 # This file controls:
-# 
 # 	o which hosts are allowed to connect
 # 	o how users are authenticated on each host
 # 	o databases accessible by each host
@@ -24,7 +23,6 @@
 # ============
 # 
 # There are three types of records:
-# 
 # 	o host
 # 	o hostssl
 # 	o local
@@ -40,7 +38,6 @@
 #   host  DBNAME  IP_ADDRESS  ADDRESS_MASK  AUTH_TYPE  [AUTH_ARGUMENT]
 # 
 # DBNAME can be:
-# 
 # 	o the name of a PostgreSQL database
 # 	o "all" to indicate all databases
 # 	o "sameuser" to allow access only to databases with the same
@@ -80,7 +77,6 @@
 # allowed only if this record type appears.
 # 
 # Format:
-# 
 #   local  DBNAME  AUTH_TYPE  [AUTH_ARGUMENT]
 # 
 # This format is identical to the "host" record type except the IP_ADDRESS
@@ -219,4 +215,3 @@
 
 local      all                                          trust
 host       all         127.0.0.1     255.255.255.255    trust
-
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 391d821119a9d9679d35b167e10c22b391d9ad68..57242a5978a33e7d9217ab27ddb18a9a95ebe019 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.244 2001/08/13 21:34:51 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.245 2001/08/15 18:42:15 momjian Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -306,7 +306,7 @@ static void doNegateFloat(Value *v);
 		CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
 		DAY_P, DEC, DECIMAL, DECLARE, DEFAULT, DELETE, DESC,
 		DISTINCT, DOUBLE, DROP,
-		ELSE, END_TRANS, ESCAPE, EXCEPT, EXECUTE, EXISTS, EXTRACT,
+		ELSE, ENCRYPTED, END_TRANS, ESCAPE, EXCEPT, EXECUTE, EXISTS, EXTRACT,
 		FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
 		GLOBAL, GRANT, GROUP, HAVING, HOUR_P,
 		IN, INNER_P, INSENSITIVE, INSERT, INTERSECT, INTERVAL, INTO, IS,
@@ -319,7 +319,7 @@ static void doNegateFloat(Value *v);
 		SCHEMA, SCROLL, SECOND_P, SELECT, SESSION, SESSION_USER, SET, SOME, SUBSTRING,
 		TABLE, TEMPORARY, THEN, TIME, TIMESTAMP, TIMEZONE_HOUR,
 		TIMEZONE_MINUTE, TO, TRAILING, TRANSACTION, TRIM, TRUE_P,
-		UNION, UNIQUE, UNKNOWN, UPDATE, USER, USING,
+		UNENCRYPTED, UNION, UNIQUE, UNKNOWN, UPDATE, USER, USING,
 		VALUES, VARCHAR, VARYING, VIEW,
 		WHEN, WHERE, WITH, WORK, YEAR_P, ZONE
 
@@ -558,6 +558,18 @@ OptUserElem:  PASSWORD Sconst
 				  $$->defname = "password";
 				  $$->arg = (Node *)makeString($2);
 				}
+			  | ENCRYPTED PASSWORD Sconst
+                { 
+				  $$ = makeNode(DefElem);
+				  $$->defname = "encryptedPassword";
+				  $$->arg = (Node *)makeString($3);
+				}
+			  | UNENCRYPTED PASSWORD Sconst
+                { 
+				  $$ = makeNode(DefElem);
+				  $$->defname = "unencryptedPassword";
+				  $$->arg = (Node *)makeString($3);
+				}
               | SYSID Iconst
 				{
 				  $$ = makeNode(DefElem);
@@ -5765,6 +5777,7 @@ ColLabel:  ColId						{ $$ = $1; }
 		| DISTINCT						{ $$ = "distinct"; }
 		| DO							{ $$ = "do"; }
 		| ELSE							{ $$ = "else"; }
+		| ENCRYPTED						{ $$ = "encrypted"; }
 		| END_TRANS						{ $$ = "end"; }
 		| EXCEPT						{ $$ = "except"; }
 		| EXISTS						{ $$ = "exists"; }
@@ -5836,6 +5849,7 @@ ColLabel:  ColId						{ $$ = $1; }
 		| TRANSACTION					{ $$ = "transaction"; }
 		| TRIM							{ $$ = "trim"; }
 		| TRUE_P						{ $$ = "true"; }
+		| UNENCRYPTED					{ $$ = "unencrypted"; }
 		| UNION							{ $$ = "union"; }
 		| UNIQUE						{ $$ = "unique"; }
 		| UNKNOWN						{ $$ = "unknown"; }
diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c
index 014b1198503c4b704a2e6086d0ebd9a0388f611d..3fb39c0821ea5b0e05eddfd0921675a8cf08b202 100644
--- a/src/backend/parser/keywords.c
+++ b/src/backend/parser/keywords.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.94 2001/07/16 05:06:58 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.95 2001/08/15 18:42:15 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -102,6 +102,7 @@ static ScanKeyword ScanKeywords[] = {
 	{"each", EACH},
 	{"else", ELSE},
 	{"encoding", ENCODING},
+	{"encrypted", ENCRYPTED},
 	{"end", END_TRANS},
 	{"escape", ESCAPE},
 	{"except", EXCEPT},
@@ -262,6 +263,7 @@ static ScanKeyword ScanKeywords[] = {
 	{"truncate", TRUNCATE},
 	{"trusted", TRUSTED},
 	{"type", TYPE_P},
+	{"unencrypted", UNENCRYPTED},
 	{"union", UNION},
 	{"unique", UNIQUE},
 	{"unknown", UNKNOWN},
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index cc666047815b10dc82d19c279e7fb1598f0709ae..b0bb99817d125e965ca711f2c4723f2c40b52379 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -4,7 +4,7 @@
  * Support for grand unified configuration scheme, including SET
  * command, configuration file, and command line options.
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.45 2001/07/05 15:19:40 wieck Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.46 2001/08/15 18:42:15 momjian Exp $
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  * Written by Peter Eisentraut <peter_e@gmx.net>.
@@ -80,6 +80,8 @@ bool		SQL_inheritance = true;
 
 bool		Australian_timezones = false;
 
+bool		Password_encryption = false;
+
 #ifndef PG_KRB_SRVTAB
 #define PG_KRB_SRVTAB ""
 #endif
@@ -246,11 +248,12 @@ static struct config_bool
 
 	{"sql_inheritance", PGC_USERSET, &SQL_inheritance, true, NULL},
 
-	{"australian_timezones", PGC_USERSET, &Australian_timezones,
-	false, ClearDateCache},
+	{"australian_timezones", PGC_USERSET, &Australian_timezones, false, ClearDateCache},
 
 	{"fixbtree", PGC_POSTMASTER, &FixBTree, true, NULL},
 
+	{"password_encryption", PGC_USERSET, &Password_encryption, false, NULL},
+
 	{NULL, 0, NULL, false, NULL}
 };
 
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 6b25bbca6c6160a5d3f01c68cd89767a8e357896..78abcd50c28bcb1b7329fc34b89e84151e0cd40d 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -176,9 +176,10 @@
 #
 #	Misc
 #
-#default_transaction_isolation = 'read committed'
-#sql_inheritance = true
 #australian_timezones = false
 #deadlock_timeout = 1000
+#default_transaction_isolation = 'read committed'
 #max_expr_depth = 10000 # min 10
+#password_encryption = false
+#sql_inheritance = true
 
diff --git a/src/include/libpq/crypt.h b/src/include/libpq/crypt.h
index c3f58ee1639f07af38a03959e9eef1b1d0e705ba..030921c254ba1674f723f8996619990edd681f79 100644
--- a/src/include/libpq/crypt.h
+++ b/src/include/libpq/crypt.h
@@ -22,10 +22,6 @@ extern int	pwd_cache_count;
 extern char *crypt_getpwdfilename(void);
 extern char *crypt_getpwdreloadfilename(void);
 
-#ifdef NOT_USED
-extern MsgType crypt_salt(const char *user);
-
-#endif
-extern int	crypt_verify(const Port *port, const char *user, const char *pgpass);
+extern int md5_crypt_verify(const Port *port, const char *user, const char *pgpass);
 
 #endif
diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h
index 0d792da3d35c2dbf15e95d1314bbf90e7c2a9d9c..11f052d36346185eaba25ac1ccab216af0018916 100644
--- a/src/include/libpq/hba.h
+++ b/src/include/libpq/hba.h
@@ -4,7 +4,7 @@
  *	  Interface to hba.c
  *
  *
- * $Id: hba.h,v 1.22 2001/08/01 23:25:39 tgl Exp $
+ * $Id: hba.h,v 1.23 2001/08/15 18:42:15 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,7 +35,9 @@ typedef enum UserAuth
 	uaTrust,
 	uaIdent,
 	uaPassword,
-	uaCrypt
+	uaCrypt,
+	uaMD5		/* 	This starts as uaCrypt from pg_hba.conf, but gets 
+					overridden if the client supports MD5 */
 } UserAuth;
 
 typedef struct Port hbaPort;
diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h
index 0f90ecdc67d4897683068cff83497bc5f05a6639..c709553f69bd6206832b05ed6e2a1118ab383a3a 100644
--- a/src/include/libpq/pqcomm.h
+++ b/src/include/libpq/pqcomm.h
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pqcomm.h,v 1.55 2001/03/22 04:00:48 momjian Exp $
+ * $Id: pqcomm.h,v 1.56 2001/08/15 18:42:15 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -90,7 +90,7 @@ typedef union SockAddr
 /* The earliest and latest frontend/backend protocol version supported. */
 
 #define PG_PROTOCOL_EARLIEST	PG_PROTOCOL(0,0)
-#define PG_PROTOCOL_LATEST	PG_PROTOCOL(2,0)
+#define PG_PROTOCOL_LATEST	PG_PROTOCOL(2,1)
 
 /*
  * All packets sent to the postmaster start with the length.  This is omitted
@@ -127,11 +127,12 @@ typedef struct StartupPacket
 
 /* These are the authentication requests sent by the backend. */
 
-#define AUTH_REQ_OK		0		/* User is authenticated  */
+#define AUTH_REQ_OK			0	/* User is authenticated  */
 #define AUTH_REQ_KRB4		1	/* Kerberos V4 */
 #define AUTH_REQ_KRB5		2	/* Kerberos V5 */
 #define AUTH_REQ_PASSWORD	3	/* Password */
-#define AUTH_REQ_CRYPT		4	/* Encrypted password */
+#define AUTH_REQ_CRYPT		4	/* crypt password */
+#define AUTH_REQ_MD5		5	/* md5 password */
 
 typedef uint32 AuthRequest;
 
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index c3afaf89ecaf9656e79f38e9e3ba549ed20046c7..89e0670911b7d940cacbfea2a43ccb4edfac207a 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: miscadmin.h,v 1.88 2001/08/05 02:06:50 tgl Exp $
+ * $Id: miscadmin.h,v 1.89 2001/08/15 18:42:15 momjian Exp $
  *
  * NOTES
  *	  some of the information in this file should be moved to
@@ -171,8 +171,10 @@ extern bool enableFsync;
 extern bool allowSystemTableMods;
 extern int	SortMem;
 
-/* a few postmaster startup options are exported here so the
-   configuration file processor has access to them */
+/*
+ *	A few postmaster startup options are exported here so the
+ *  configuration file processor can access them.
+ */
 
 extern bool NetServer;
 extern bool EnableSSL;
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index 91759e9786d200c24db6930be8040284b9b7306c..73507a15b34ca8966722985d6f32eff863787ff8 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -4,7 +4,7 @@
 #
 # Copyright (c) 1994, Regents of the University of California
 #
-# $Header: /cvsroot/pgsql/src/interfaces/libpq/Makefile,v 1.53 2001/07/15 13:45:04 petere Exp $
+# $Header: /cvsroot/pgsql/src/interfaces/libpq/Makefile,v 1.54 2001/08/15 18:42:15 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -20,7 +20,7 @@ SO_MINOR_VERSION= 2
 override CPPFLAGS := -I$(srcdir) $(CPPFLAGS) -DFRONTEND -DSYSCONFDIR='"$(sysconfdir)"'
 
 OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \
-      pqexpbuffer.o dllist.o pqsignal.o \
+      pqexpbuffer.o dllist.o md5.o pqsignal.o \
       $(INET_ATON) $(SNPRINTF) $(STRERROR)
 
 ifdef MULTIBYTE
@@ -33,7 +33,7 @@ endif
 SHLIB_LINK += $(filter -L%, $(LDFLAGS)) $(filter -lcrypt -ldes -lkrb -lcom_err -lcrypto -lk5crypto -lkrb5 -lssl -lsocket -lnsl -lresolv -lintl, $(LIBS))
 
 
-all: all-lib
+all: md5.c md5.h all-lib
 
 # Shared library stuff
 include $(top_srcdir)/src/Makefile.shlib
@@ -49,6 +49,12 @@ backend_src = $(top_srcdir)/src/backend
 dllist.c: $(backend_src)/lib/dllist.c
 	rm -f $@ && $(LN_S) $< .
 
+md5.c: $(backend_src)/libpq/md5.c
+	rm -f $@ && $(LN_S) $< .
+
+md5.h: $(backend_src)/../include/libpq/md5.h
+	rm -f $@ && $(LN_S) $< .
+
 # this only gets done if configure finds system doesn't have inet_aton()
 inet_aton.c: $(backend_src)/port/inet_aton.c
 	rm -f $@ && $(LN_S) $< .
@@ -82,7 +88,7 @@ uninstall: uninstall-lib
 	rm -f $(addprefix $(DESTDIR)$(includedir)/, libpq-fe.h libpq-int.h pqexpbuffer.h)
 
 clean distclean maintainer-clean: clean-lib
-	rm -f $(OBJS) dllist.c wchar.c
+	rm -f $(OBJS) dllist.c md5.c md5.h wchar.c
 	rm -f $(OBJS) inet_aton.c snprintf.c strerror.c
 
 depend dep:
diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c
index d8b27c3772923c8711fd459b704da6e41ac9d17d..6f874c485bb0230121748a265bf2dca4003245f8 100644
--- a/src/interfaces/libpq/fe-auth.c
+++ b/src/interfaces/libpq/fe-auth.c
@@ -10,7 +10,7 @@
  * exceed INITIAL_EXPBUFFER_SIZE (currently 256 bytes).
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.48 2001/07/15 13:45:04 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.49 2001/08/15 18:42:15 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,6 +33,7 @@
 #include "libpq-fe.h"
 #include "libpq-int.h"
 #include "fe-auth.h"
+#include "md5.h"
 
 #ifdef WIN32
 #include "win32.h"
@@ -434,12 +435,52 @@ pg_krb5_sendauth(char *PQerrormsg, int sock,
 static int
 pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
 {
+	int ret;
+	char *crypt_pwd;
+
 	/* Encrypt the password if needed. */
 
-	if (areq == AUTH_REQ_CRYPT)
-		password = crypt(password, conn->salt);
+	switch (areq)
+	{
+		case AUTH_REQ_CRYPT:
+			crypt_pwd = crypt(password, conn->salt);
+			break;
+		case AUTH_REQ_MD5:
+			{
+				char *crypt_pwd2;
+
+				if (!(crypt_pwd = malloc(MD5_PASSWD_LEN+1)) ||
+					!(crypt_pwd2 = malloc(MD5_PASSWD_LEN+1)))
+				{
+					perror("malloc");
+					return STATUS_ERROR;
+				}
+				if (!EncryptMD5(password, conn->pguser, crypt_pwd2))
+				{
+					free(crypt_pwd);
+					free(crypt_pwd2);
+					return STATUS_ERROR;
+				}
+				if (!EncryptMD5(crypt_pwd2 + strlen("md5"), conn->salt,
+								crypt_pwd))
+				{
+					free(crypt_pwd);
+					free(crypt_pwd2);
+					return STATUS_ERROR;
+				}
+				free(crypt_pwd2);
+				break;
+			}
+		default:
+			/* discard const so we can assign it */
+			crypt_pwd = (char *)password;
+			break;
+	}
 
-	return pqPacketSend(conn, password, strlen(password) + 1);
+	ret = pqPacketSend(conn, crypt_pwd, strlen(crypt_pwd) + 1);
+	if (areq == AUTH_REQ_MD5)
+		free(crypt_pwd);
+	return ret;
 }
 
 /*
@@ -494,6 +535,7 @@ fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
 
 		case AUTH_REQ_PASSWORD:
 		case AUTH_REQ_CRYPT:
+		case AUTH_REQ_MD5:
 			if (password == NULL || *password == '\0')
 			{
 				(void) sprintf(PQerrormsg,
@@ -506,9 +548,7 @@ fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
 				 "fe_sendauth: error sending password authentication\n");
 				return STATUS_ERROR;
 			}
-
 			break;
-
 		default:
 			snprintf(PQerrormsg, PQERRORMSG_LENGTH,
 					 libpq_gettext("authentication method %u not supported\n"), areq);
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 47f5d55c32325caeb0d4c4ded811395d5509ecf7..32983c53ad1a57a195b3fed2dd3e2cb58e451051 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.172 2001/08/03 22:11:39 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.173 2001/08/15 18:42:15 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1341,7 +1341,7 @@ keep_going:						/* We will come back to here until there
 				}
 
 				/* Get the password salt if there is one. */
-				if (areq == AUTH_REQ_CRYPT)
+				if (areq == AUTH_REQ_CRYPT || areq == AUTH_REQ_MD5)
 				{
 					if (pqGetnchar(conn->salt, sizeof(conn->salt), conn))
 					{
@@ -1960,7 +1960,7 @@ static void
 closePGconn(PGconn *conn)
 {
 	/* Note that the protocol doesn't allow us to send Terminate
-       messages during the startup phase. */
+	   messages during the startup phase. */
 	if (conn->sock >= 0 && conn->status == CONNECTION_OK)
 	{
 
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index c512f6928c6c0ce08b822b91354573d0cd0a4bcf..c5dfcd4210d60efc7492eb40a5756de858446755 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.105 2001/08/03 22:11:39 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.106 2001/08/15 18:42:15 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1269,7 +1269,6 @@ errout:
 static int
 getNotice(PGconn *conn)
 {
-
 	/*
 	 * Since the Notice might be pretty long, we create a temporary
 	 * PQExpBuffer rather than using conn->workBuffer.	workBuffer is
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 5e90e492f1278f5a02794e9f95f0bf2f406cfbe8..a681e72beed6ae6e3dcb634a57b21e5192c72e23 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-int.h,v 1.36 2001/07/15 13:45:04 petere Exp $
+ * $Id: libpq-int.h,v 1.37 2001/08/15 18:42:16 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,7 +45,7 @@
  * pqcomm.h describe what the backend knows, not what libpq knows.
  */
 
-#define PG_PROTOCOL_LIBPQ	PG_PROTOCOL(2,0)
+#define PG_PROTOCOL_LIBPQ	PG_PROTOCOL(2,1)
 
 /*
  * POSTGRES backend dependent Constants.
diff --git a/src/interfaces/odbc/connection.c b/src/interfaces/odbc/connection.c
index 90fc132b98114c4f2ed67859d376b392c13b747a..42196df9eedd2e005edc350f51b15ba32643f388 100644
--- a/src/interfaces/odbc/connection.c
+++ b/src/interfaces/odbc/connection.c
@@ -677,7 +677,7 @@ CC_connect(ConnectionClass *self, char do_password)
 						mylog("auth got 'R'\n");
 
 						areq = SOCK_get_int(sock, 4);
-						if (areq == AUTH_REQ_CRYPT)
+						if (areq == AUTH_REQ_CRYPT || areq == AUTH_REQ_MD5)
 							SOCK_get_n_char(sock, salt, 2);
 
 						mylog("areq = %d\n", areq);
@@ -717,6 +717,7 @@ CC_connect(ConnectionClass *self, char do_password)
 							break;
 
 						case AUTH_REQ_CRYPT:
+						case AUTH_REQ_MD5:
 							self->errormsg = "Password crypt authentication not supported";
 							self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
 							return 0;
@@ -1672,15 +1673,15 @@ CC_log_error(char *func, char *desc, ConnectionClass *self)
 
 int     CC_get_max_query_len(const ConnectionClass *conn)
 {
-        int     value;
-        /* Long Queries in 7.0+ */
-        if (PG_VERSION_GE(conn, 7.0))
-                value = 0 /* MAX_STATEMENT_LEN */;
-        /* Prior to 7.0 we used 2*BLCKSZ */
-        else if (PG_VERSION_GE(conn, 6.5))
-                value = (2 * BLCKSZ);
-        else
-                /* Prior to 6.5 we used BLCKSZ */
-                value = BLCKSZ;
-        return value;
+		int     value;
+		/* Long Queries in 7.0+ */
+		if (PG_VERSION_GE(conn, 7.0))
+				value = 0 /* MAX_STATEMENT_LEN */;
+		/* Prior to 7.0 we used 2*BLCKSZ */
+		else if (PG_VERSION_GE(conn, 6.5))
+				value = (2 * BLCKSZ);
+		else
+				/* Prior to 6.5 we used BLCKSZ */
+				value = BLCKSZ;
+		return value;
 }
diff --git a/src/interfaces/odbc/connection.h b/src/interfaces/odbc/connection.h
index d3eb8700b2861ccc40ed4719e825cfc3cbedf2ec..1038bf117ba01d39162b5dcf4a5260ccb68c88dc 100644
--- a/src/interfaces/odbc/connection.h
+++ b/src/interfaces/odbc/connection.h
@@ -93,6 +93,7 @@ typedef enum
 #define AUTH_REQ_KRB5								2
 #define AUTH_REQ_PASSWORD							3
 #define AUTH_REQ_CRYPT								4
+#define AUTH_REQ_MD5								5
 
 /*	Startup Packet sizes */
 #define SM_DATABASE									64