From 44ab596b01ecfab2f990be44cab23647a8c8963f Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Thu, 5 Dec 2002 18:39:43 +0000
Subject: [PATCH] Allow 'password' encryption even when pg_shadow has MD5
 passwords, per report from Terry Yapt and Hiroshi.

Backpatch to 7.3.
---
 src/backend/libpq/crypt.c | 28 ++++++++++++++++++++++------
 src/include/libpq/crypt.h |  4 ++--
 2 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c
index 9cc6b483ed1..7270dfc82ce 100644
--- a/src/backend/libpq/crypt.c
+++ b/src/backend/libpq/crypt.c
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/libpq/crypt.c,v 1.49 2002/09/04 20:31:19 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/libpq/crypt.c,v 1.50 2002/12/05 18:39:43 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,7 +29,7 @@
 
 
 int
-md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
+md5_crypt_verify(const Port *port, const char *user, char *pgpass)
 {
 	char	   *passwd = NULL,
 			   *valuntil = NULL,
@@ -37,6 +37,7 @@ md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
 	int			retval = STATUS_ERROR;
 	List	  **line;
 	List	   *token;
+	char	   *crypt_pgpass = pgpass;
 
 	if ((line = get_user_line(user)) == NULL)
 		return STATUS_ERROR;
@@ -54,11 +55,11 @@ md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
 	if (passwd == NULL || *passwd == '\0')
 		return STATUS_ERROR;
 
-	/* If they encrypt their password, force MD5 */
-	if (isMD5(passwd) && port->auth_method != uaMD5)
+	/* We can't do crypt with pg_shadow MD5 passwords */
+	if (isMD5(passwd) && port->auth_method == uaCrypt)
 	{
 		elog(LOG, "Password is stored MD5 encrypted.  "
-			 "'password' and 'crypt' auth methods cannot be used.");
+			 "'crypt' auth method cannot be used.");
 		return STATUS_ERROR;
 	}
 
@@ -72,6 +73,7 @@ md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
 			crypt_pwd = palloc(MD5_PASSWD_LEN + 1);
 			if (isMD5(passwd))
 			{
+				/* pg_shadow already encrypted, only do salt */
 				if (!EncryptMD5(passwd + strlen("md5"),
 								(char *) port->md5Salt,
 								sizeof(port->md5Salt), crypt_pwd))
@@ -82,6 +84,7 @@ md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
 			}
 			else
 			{
+				/* pg_shadow plain, double-encrypt */
 				char	   *crypt_pwd2 = palloc(MD5_PASSWD_LEN + 1);
 
 				if (!EncryptMD5(passwd, port->user, strlen(port->user),
@@ -110,11 +113,22 @@ md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
 				break;
 			}
 		default:
+			if (isMD5(passwd))
+			{
+				/* Encrypt user-supplied password to match MD5 in pg_shadow */
+				crypt_pgpass = palloc(MD5_PASSWD_LEN + 1);
+				if (!EncryptMD5(pgpass, port->user, strlen(port->user),
+								crypt_pgpass))
+				{
+					pfree(crypt_pgpass);
+					return STATUS_ERROR;
+				}
+			}
 			crypt_pwd = passwd;
 			break;
 	}
 
-	if (strcmp(pgpass, crypt_pwd) == 0)
+	if (strcmp(crypt_pgpass, crypt_pwd) == 0)
 	{
 		/*
 		 * Password OK, now check to be sure we are not past valuntil
@@ -136,6 +150,8 @@ md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
 
 	if (port->auth_method == uaMD5)
 		pfree(crypt_pwd);
+	if (crypt_pgpass != pgpass)
+		pfree(crypt_pgpass);
 
 	return retval;
 }
diff --git a/src/include/libpq/crypt.h b/src/include/libpq/crypt.h
index 246ab0bd66b..b3b050a8365 100644
--- a/src/include/libpq/crypt.h
+++ b/src/include/libpq/crypt.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: crypt.h,v 1.22 2002/09/04 20:31:42 momjian Exp $
+ * $Id: crypt.h,v 1.23 2002/12/05 18:39:43 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,7 +23,7 @@
 
 
 extern int md5_crypt_verify(const Port *port, const char *user,
-				 const char *pgpass);
+				char *pgpass);
 extern bool md5_hash(const void *buff, size_t len, char *hexsum);
 extern bool CheckMD5Pwd(char *passwd, char *storedpwd, char *seed);
 
-- 
GitLab