0009-Add-clause-PASSWORD-val-USING-protocol-to-CREATE-ALT.patch
application/x-patch
Filename: 0009-Add-clause-PASSWORD-val-USING-protocol-to-CREATE-ALT.patch
Type: application/x-patch
Part: 5
Patch
Format: format-patch
Series: patch 0009
Subject: Add clause PASSWORD val USING protocol to CREATE/ALTER ROLE
| File | + | − |
|---|---|---|
| doc/src/sgml/ref/alter_role.sgml | 2 | 0 |
| doc/src/sgml/ref/create_role.sgml | 19 | 0 |
| src/backend/commands/user.c | 67 | 5 |
| src/backend/parser/gram.y | 6 | 0 |
From f7332f59b99777dd4fe689e0d85cae9defea2f92 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@otacoo.com>
Date: Mon, 25 Jul 2016 16:00:32 +0900
Subject: [PATCH 09/10] Add clause PASSWORD val USING protocol to CREATE/ALTER
ROLE
This clause allows users to be able to enforce with which protocol
a given password is used with. if the value given is already encrypted,
the value is used as-is.
---
doc/src/sgml/ref/alter_role.sgml | 2 ++
doc/src/sgml/ref/create_role.sgml | 19 +++++++++++
src/backend/commands/user.c | 72 ++++++++++++++++++++++++++++++++++++---
src/backend/parser/gram.y | 6 ++++
4 files changed, 94 insertions(+), 5 deletions(-)
diff --git a/doc/src/sgml/ref/alter_role.sgml b/doc/src/sgml/ref/alter_role.sgml
index da36ad9..3cae101 100644
--- a/doc/src/sgml/ref/alter_role.sgml
+++ b/doc/src/sgml/ref/alter_role.sgml
@@ -34,6 +34,7 @@ ALTER ROLE <replaceable class="PARAMETER">role_specification</replaceable> [ WIT
| BYPASSRLS | NOBYPASSRLS
| CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
+ | PASSWORD '<replaceable class="PARAMETER">password</replaceable>' USING '<replaceable class="PARAMETER">protocol</replaceable>'
| VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
ALTER ROLE <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
@@ -169,6 +170,7 @@ ALTER ROLE { <replaceable class="PARAMETER">role_specification</replaceable> | A
<term><literal>NOBYPASSRLS</literal></term>
<term><literal>CONNECTION LIMIT</literal> <replaceable class="parameter">connlimit</replaceable></term>
<term><literal>PASSWORD</> <replaceable class="parameter">password</replaceable></term>
+ <term><literal>PASSWORD</> <replaceable class="parameter">password</replaceable> USING <replaceable class="parameter">protocol</replaceable></term>
<term><literal>ENCRYPTED</></term>
<term><literal>UNENCRYPTED</></term>
<term><literal>VALID UNTIL</literal> '<replaceable class="parameter">timestamp</replaceable>'</term>
diff --git a/doc/src/sgml/ref/create_role.sgml b/doc/src/sgml/ref/create_role.sgml
index 93f0763..b25d2c0 100644
--- a/doc/src/sgml/ref/create_role.sgml
+++ b/doc/src/sgml/ref/create_role.sgml
@@ -34,6 +34,7 @@ CREATE ROLE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replac
| BYPASSRLS | NOBYPASSRLS
| CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
+ | PASSWORD '<replaceable class="PARAMETER">password</replaceable>' USING '<replaceable class="PARAMETER">protocol</replaceable>'
| VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
| IN ROLE <replaceable class="PARAMETER">role_name</replaceable> [, ...]
| IN GROUP <replaceable class="PARAMETER">role_name</replaceable> [, ...]
@@ -245,6 +246,24 @@ CREATE ROLE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replac
</varlistentry>
<varlistentry>
+ <term><literal>PASSWORD</> <replaceable class="parameter">password</replaceable> USING <replaceable class="parameter">protocol</replaceable></term>
+ <listitem>
+ <para>
+ Sets the role's password using the wanted protocol. (A password
+ is only of use for roles having the <literal>LOGIN</literal>
+ attribute, but you can nonetheless define one for roles without it.)
+ If you do not plan to use password authentication you can omit this
+ option. The protocols supported are <literal>md5</> to enforce
+ a password to be MD5-encrypted, <literal>scram</> to enforce a password
+ to be encrypted with SCRAM-SHA256, or <literal>plain</> to use
+ an unencrypted password. If the presented password string is already
+ in MD5-encrypted or SCRAM-encrypted format, then it is stored encrypted
+ as-is.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>VALID UNTIL</literal> '<replaceable class="parameter">timestamp</replaceable>'</term>
<listitem>
<para>
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 1fc4245..054cc45 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -178,7 +178,8 @@ CreateRole(CreateRoleStmt *stmt)
if (strcmp(defel->defname, "password") == 0 ||
strcmp(defel->defname, "encryptedPassword") == 0 ||
- strcmp(defel->defname, "unencryptedPassword") == 0)
+ strcmp(defel->defname, "unencryptedPassword") == 0 ||
+ strcmp(defel->defname, "protocolPassword") == 0)
{
if (dpassword)
ereport(ERROR,
@@ -186,9 +187,41 @@ CreateRole(CreateRoleStmt *stmt)
errmsg("conflicting or redundant options")));
dpassword = defel;
if (strcmp(defel->defname, "encryptedPassword") == 0)
+ {
password_type = PASSWORD_TYPE_MD5;
+ if (dpassword && dpassword->arg)
+ password = strVal(dpassword->arg);
+ }
else if (strcmp(defel->defname, "unencryptedPassword") == 0)
+ {
password_type = PASSWORD_TYPE_PLAINTEXT;
+ if (dpassword && dpassword->arg)
+ password = strVal(dpassword->arg);
+ }
+ else if (strcmp(defel->defname, "protocolPassword") == 0)
+ {
+ /*
+ * This is a list of two elements, the password is first and
+ * then there is the protocol wanted by caller.
+ */
+ if (dpassword && dpassword->arg)
+ {
+ char *protocol = strVal(lsecond((List *) dpassword->arg));
+
+ password = strVal(linitial((List *) dpassword->arg));
+
+ if (strcmp(protocol, "md5") == 0)
+ password_type = PASSWORD_TYPE_MD5;
+ else if (strcmp(protocol, "plain") == 0)
+ password_type = PASSWORD_TYPE_PLAINTEXT;
+ else if (strcmp(protocol, "scram") == 0)
+ password_type = PASSWORD_TYPE_SCRAM;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unsupported password protocol %s", protocol)));
+ }
+ }
}
else if (strcmp(defel->defname, "sysid") == 0)
{
@@ -296,8 +329,6 @@ CreateRole(CreateRoleStmt *stmt)
defel->defname);
}
- if (dpassword && dpassword->arg)
- password = strVal(dpassword->arg);
if (dissuper)
issuper = intVal(dissuper->arg) != 0;
if (dinherit)
@@ -571,6 +602,7 @@ AlterRole(AlterRoleStmt *stmt)
if (strcmp(defel->defname, "password") == 0 ||
strcmp(defel->defname, "encryptedPassword") == 0 ||
+ strcmp(defel->defname, "protocolPassword") == 0 ||
strcmp(defel->defname, "unencryptedPassword") == 0)
{
if (dpassword)
@@ -579,9 +611,41 @@ AlterRole(AlterRoleStmt *stmt)
errmsg("conflicting or redundant options")));
dpassword = defel;
if (strcmp(defel->defname, "encryptedPassword") == 0)
+ {
password_type = PASSWORD_TYPE_MD5;
+ if (dpassword && dpassword->arg)
+ password = strVal(dpassword->arg);
+ }
else if (strcmp(defel->defname, "unencryptedPassword") == 0)
+ {
password_type = PASSWORD_TYPE_PLAINTEXT;
+ if (dpassword && dpassword->arg)
+ password = strVal(dpassword->arg);
+ }
+ else if (strcmp(defel->defname, "protocolPassword") == 0)
+ {
+ /*
+ * This is a list of two elements, the password is first and
+ * then there is the protocol wanted by caller.
+ */
+ if (dpassword && dpassword->arg)
+ {
+ char *protocol = strVal(lsecond((List *) dpassword->arg));
+
+ if (strcmp(protocol, "md5") == 0)
+ password_type = PASSWORD_TYPE_MD5;
+ else if (strcmp(protocol, "plain") == 0)
+ password_type = PASSWORD_TYPE_PLAINTEXT;
+ else if (strcmp(protocol, "scram") == 0)
+ password_type = PASSWORD_TYPE_SCRAM;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unsupported password protocol %s", protocol)));
+
+ password = strVal(linitial((List *) dpassword->arg));
+ }
+ }
}
else if (strcmp(defel->defname, "superuser") == 0)
{
@@ -669,8 +733,6 @@ AlterRole(AlterRoleStmt *stmt)
defel->defname);
}
- if (dpassword && dpassword->arg)
- password = strVal(dpassword->arg);
if (dissuper)
issuper = intVal(dissuper->arg);
if (dinherit)
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index b6e4618..b94dccd 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -932,6 +932,12 @@ AlterOptRoleElem:
{
$$ = makeDefElem("password", NULL);
}
+ | PASSWORD Sconst USING Sconst
+ {
+ $$ = makeDefElem("protocolPassword",
+ (Node *)list_make2(makeString($2),
+ makeString($4)));
+ }
| ENCRYPTED PASSWORD Sconst
{
$$ = makeDefElem("encryptedPassword",
--
2.9.2