0003-Switch-password_encryption-to-a-enum.patch

application/x-patch

Filename: 0003-Switch-password_encryption-to-a-enum.patch
Type: application/x-patch
Part: 2
Message: Re: Password identifiers, protocol aging and SCRAM protocol

Patch

Format: format-patch
Series: patch 0003
Subject: Switch password_encryption to a enum
File+
doc/src/sgml/config.sgml 13 3
src/backend/commands/user.c 11 11
src/backend/utils/misc/guc.c 27 13
src/backend/utils/misc/postgresql.conf.sample 1 1
src/include/commands/user.h 8 3
From eee988fa8d858d538f1edb4f2c76db57f07fc4f7 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@otacoo.com>
Date: Mon, 25 Jul 2016 13:59:43 +0900
Subject: [PATCH 3/8] Switch password_encryption to a enum

This makes this parameter more extensible in order to add support for
future password-based authentication protocols.
---
 doc/src/sgml/config.sgml                      | 16 +++++++++--
 src/backend/commands/user.c                   | 22 +++++++--------
 src/backend/utils/misc/guc.c                  | 40 ++++++++++++++++++---------
 src/backend/utils/misc/postgresql.conf.sample |  2 +-
 src/include/commands/user.h                   | 11 ++++++--
 5 files changed, 60 insertions(+), 31 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 7c483c6..2c3566a 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1163,7 +1163,7 @@ include_dir 'conf.d'
      </varlistentry>
 
      <varlistentry id="guc-password-encryption" xreflabel="password_encryption">
-      <term><varname>password_encryption</varname> (<type>boolean</type>)
+      <term><varname>password_encryption</varname> (<type>enum</type>)
       <indexterm>
        <primary><varname>password_encryption</> configuration parameter</primary>
       </indexterm>
@@ -1175,8 +1175,18 @@ include_dir 'conf.d'
         <xref linkend="sql-alterrole">
         without writing either <literal>ENCRYPTED</> or
         <literal>UNENCRYPTED</>, this parameter determines whether the
-        password is to be encrypted. The default is <literal>on</>
-        (encrypt the password).
+        password is to be encrypted.
+       </para>
+
+       <para>
+        A value set to <literal>on</> or <literal>md5</> corresponds to a 
+        MD5-encrypted password, <literal>off</> or <literal>plain</>
+        corresponds to an unencrypted password.
+       </para>
+       
+       <para>
+        The default is <literal>on</> (encrypt the password with MD5
+        encryption).
        </para>
       </listitem>
      </varlistentry>
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 821dce3..da4acdf 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -44,7 +44,7 @@ Oid			binary_upgrade_next_pg_authid_oid = InvalidOid;
 
 
 /* GUC parameter */
-extern bool Password_encryption;
+int Password_encryption = PASSWORD_TYPE_MD5;
 
 /* Hook to check passwords in CreateRole() and AlterRole() */
 check_password_hook_type check_password_hook = NULL;
@@ -80,7 +80,7 @@ CreateRole(CreateRoleStmt *stmt)
 	ListCell   *item;
 	ListCell   *option;
 	char	   *password = NULL;	/* user password */
-	bool		encrypt_password = Password_encryption; /* encrypt password? */
+	int			password_type = Password_encryption;
 	char		encrypted_password[MD5_PASSWD_LEN + 1];
 	bool		issuper = false;	/* Make the user a superuser? */
 	bool		inherit = true; /* Auto inherit privileges? */
@@ -139,9 +139,9 @@ CreateRole(CreateRoleStmt *stmt)
 						 errmsg("conflicting or redundant options")));
 			dpassword = defel;
 			if (strcmp(defel->defname, "encryptedPassword") == 0)
-				encrypt_password = true;
+				password_type = PASSWORD_TYPE_MD5;
 			else if (strcmp(defel->defname, "unencryptedPassword") == 0)
-				encrypt_password = false;
+				password_type = PASSWORD_TYPE_PLAINTEXT;
 		}
 		else if (strcmp(defel->defname, "sysid") == 0)
 		{
@@ -357,7 +357,7 @@ CreateRole(CreateRoleStmt *stmt)
 	if (check_password_hook && password)
 		(*check_password_hook) (stmt->role,
 								password,
-			   isMD5(password) ? PASSWORD_TYPE_MD5 : PASSWORD_TYPE_PLAINTEXT,
+								password_type,
 								validUntil_datum,
 								validUntil_null);
 
@@ -380,7 +380,7 @@ CreateRole(CreateRoleStmt *stmt)
 
 	if (password)
 	{
-		if (!encrypt_password || isMD5(password))
+		if (password_type == PASSWORD_TYPE_PLAINTEXT || isMD5(password))
 			new_record[Anum_pg_authid_rolpassword - 1] =
 				CStringGetTextDatum(password);
 		else
@@ -492,7 +492,7 @@ AlterRole(AlterRoleStmt *stmt)
 	ListCell   *option;
 	char	   *rolename = NULL;
 	char	   *password = NULL;	/* user password */
-	bool		encrypt_password = Password_encryption; /* encrypt password? */
+	int			password_type = Password_encryption;
 	char		encrypted_password[MD5_PASSWD_LEN + 1];
 	int			issuper = -1;	/* Make the user a superuser? */
 	int			inherit = -1;	/* Auto inherit privileges? */
@@ -537,9 +537,9 @@ AlterRole(AlterRoleStmt *stmt)
 						 errmsg("conflicting or redundant options")));
 			dpassword = defel;
 			if (strcmp(defel->defname, "encryptedPassword") == 0)
-				encrypt_password = true;
+				password_type = PASSWORD_TYPE_MD5;
 			else if (strcmp(defel->defname, "unencryptedPassword") == 0)
-				encrypt_password = false;
+				password_type = PASSWORD_TYPE_PLAINTEXT;
 		}
 		else if (strcmp(defel->defname, "superuser") == 0)
 		{
@@ -732,7 +732,7 @@ AlterRole(AlterRoleStmt *stmt)
 	if (check_password_hook && password)
 		(*check_password_hook) (rolename,
 								password,
-			   isMD5(password) ? PASSWORD_TYPE_MD5 : PASSWORD_TYPE_PLAINTEXT,
+								password_type,
 								validUntil_datum,
 								validUntil_null);
 
@@ -791,7 +791,7 @@ AlterRole(AlterRoleStmt *stmt)
 	/* password */
 	if (password)
 	{
-		if (!encrypt_password || isMD5(password))
+		if (password_type == PASSWORD_TYPE_PLAINTEXT || isMD5(password))
 			new_record[Anum_pg_authid_rolpassword - 1] =
 				CStringGetTextDatum(password);
 		else
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index c5178f7..7274eca 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -34,6 +34,7 @@
 #include "catalog/namespace.h"
 #include "commands/async.h"
 #include "commands/prepare.h"
+#include "commands/user.h"
 #include "commands/vacuum.h"
 #include "commands/variable.h"
 #include "commands/trigger.h"
@@ -393,6 +394,20 @@ static const struct config_enum_entry force_parallel_mode_options[] = {
 	{NULL, 0, false}
 };
 
+static const struct config_enum_entry password_encryption_options[] = {
+	{"off", PASSWORD_TYPE_PLAINTEXT, false},
+	{"on", PASSWORD_TYPE_MD5, false},
+	{"md5", PASSWORD_TYPE_MD5, false},
+	{"plain", PASSWORD_TYPE_PLAINTEXT, false},
+	{"true", PASSWORD_TYPE_MD5, true},
+	{"false", PASSWORD_TYPE_PLAINTEXT, true},
+	{"yes", PASSWORD_TYPE_MD5, true},
+	{"no", PASSWORD_TYPE_PLAINTEXT, true},
+	{"1", PASSWORD_TYPE_MD5, true},
+	{"0", PASSWORD_TYPE_PLAINTEXT, true},
+	{NULL, 0, false}
+};
+
 /*
  * Options for enum values stored in other modules
  */
@@ -423,8 +438,6 @@ bool		check_function_bodies = true;
 bool		default_with_oids = false;
 bool		SQL_inheritance = true;
 
-bool		Password_encryption = true;
-
 int			log_min_error_statement = ERROR;
 int			log_min_messages = WARNING;
 int			client_min_messages = NOTICE;
@@ -1314,17 +1327,6 @@ static struct config_bool ConfigureNamesBool[] =
 		NULL, NULL, NULL
 	},
 	{
-		{"password_encryption", PGC_USERSET, CONN_AUTH_SECURITY,
-			gettext_noop("Encrypt passwords."),
-			gettext_noop("When a password is specified in CREATE USER or "
-			   "ALTER USER without writing either ENCRYPTED or UNENCRYPTED, "
-						 "this parameter determines whether the password is to be encrypted.")
-		},
-		&Password_encryption,
-		true,
-		NULL, NULL, NULL
-	},
-	{
 		{"transform_null_equals", PGC_USERSET, COMPAT_OPTIONS_CLIENT,
 			gettext_noop("Treats \"expr=NULL\" as \"expr IS NULL\"."),
 			gettext_noop("When turned on, expressions of the form expr = NULL "
@@ -3810,6 +3812,18 @@ static struct config_enum ConfigureNamesEnum[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"password_encryption", PGC_USERSET, CONN_AUTH_SECURITY,
+			gettext_noop("Encrypt passwords."),
+			gettext_noop("When a password is specified in CREATE USER or "
+			   "ALTER USER without writing either ENCRYPTED or UNENCRYPTED, "
+						 "this parameter determines whether the password is to be encrypted.")
+		},
+		&Password_encryption,
+		PASSWORD_TYPE_MD5, password_encryption_options,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 6d0666c..c61ed8d 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -85,7 +85,7 @@
 #ssl_key_file = 'server.key'		# (change requires restart)
 #ssl_ca_file = ''			# (change requires restart)
 #ssl_crl_file = ''			# (change requires restart)
-#password_encryption = on
+#password_encryption = on		# on, off, md5 or plain
 #db_user_namespace = off
 #row_security = on
 
diff --git a/src/include/commands/user.h b/src/include/commands/user.h
index d35cb0c..3acbcbd 100644
--- a/src/include/commands/user.h
+++ b/src/include/commands/user.h
@@ -15,9 +15,14 @@
 #include "nodes/parsenodes.h"
 
 
-/* Hook to check passwords in CreateRole() and AlterRole() */
-#define PASSWORD_TYPE_PLAINTEXT		0
-#define PASSWORD_TYPE_MD5			1
+/* Types of password */
+typedef enum PasswordType
+{
+	PASSWORD_TYPE_PLAINTEXT = 0,
+	PASSWORD_TYPE_MD5
+} PasswordType;
+
+extern int Password_encryption;
 
 typedef void (*check_password_hook_type) (const char *username, const char *password, int password_type, Datum validuntil_time, bool validuntil_null);
 
-- 
2.9.3