Skip to content

Commit 2cc896b

Browse files
committed
Apply 0005-Refactor-decision-making-of-password-encryption-into.patch + cherry-pick babe05b
1 parent 62c05c0 commit 2cc896b

File tree

5 files changed

+120
-56
lines changed

5 files changed

+120
-56
lines changed

doc/src/sgml/config.sgml

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,21 +1163,22 @@ include_dir 'conf.d'
11631163
</varlistentry>
11641164

11651165
<varlistentry id="guc-password-encryption" xreflabel="password_encryption">
1166-
<term><varname>password_encryption</varname> (<type>boolean</type>)
1166+
<term><varname>password_encryption</varname> (<type>enum</type>)
11671167
<indexterm>
11681168
<primary><varname>password_encryption</> configuration parameter</primary>
11691169
</indexterm>
11701170
</term>
11711171
<listitem>
11721172
<para>
1173-
When a password is specified in <xref
1174-
linkend="sql-createuser"> or
1175-
<xref linkend="sql-alterrole">
1176-
without writing either <literal>ENCRYPTED</> or
1177-
<literal>UNENCRYPTED</>, this parameter determines whether the
1178-
password is to be encrypted. The default is <literal>on</>
1179-
(encrypt the password).
1173+
When a password is specified in <xref linkend="sql-createuser"> or
1174+
<xref linkend="sql-alterrole"> without writing either <literal>ENCRYPTED</>
1175+
or <literal>UNENCRYPTED</>, this parameter determines whether the
1176+
password is to be encrypted. The default value is <literal>md5</>, which
1177+
stores the password as an MD5 hash. Setting this to <literal>plain</> stores
1178+
it in plaintext. <literal>on</> and <literal>off</> are also accepted, as
1179+
aliases for <literal>md5</> and <literal>plain</>, respectively.
11801180
</para>
1181+
11811182
</listitem>
11821183
</varlistentry>
11831184

src/backend/commands/user.c

Lines changed: 67 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Oid binary_upgrade_next_pg_authid_oid = InvalidOid;
4444

4545

4646
/* GUC parameter */
47-
extern bool Password_encryption;
47+
int Password_encryption = PASSWORD_TYPE_MD5;
4848

4949
/* Hook to check passwords in CreateRole() and AlterRole() */
5050
check_password_hook_type check_password_hook = NULL;
@@ -55,6 +55,8 @@ static void AddRoleMems(const char *rolename, Oid roleid,
5555
static void DelRoleMems(const char *rolename, Oid roleid,
5656
List *memberSpecs, List *memberIds,
5757
bool admin_opt);
58+
static char *encrypt_password(char *passwd, char *rolname,
59+
int passwd_type);
5860

5961

6062
/* Check if current user has createrole privileges */
@@ -64,6 +66,48 @@ have_createrole_privilege(void)
6466
return has_createrole_privilege(GetUserId());
6567
}
6668

69+
/*
70+
* Encrypt a password if necessary for insertion in pg_authid.
71+
*
72+
* If a password is found as already MD5-encrypted, no error is raised
73+
* to ease the dump and reload of such data. Returns a palloc'ed string
74+
* holding the encrypted password.
75+
*/
76+
static char *
77+
encrypt_password(char *password, char *rolname, int passwd_type)
78+
{
79+
char *res;
80+
81+
Assert(password != NULL);
82+
83+
/*
84+
* If a password is already identified as MD5-encrypted, it is used
85+
* as such. If the password given is not encrypted, adapt it depending
86+
* on the type wanted by the caller of this routine.
87+
*/
88+
if (isMD5(password))
89+
res = pstrdup(password);
90+
else
91+
{
92+
switch (passwd_type)
93+
{
94+
case PASSWORD_TYPE_PLAINTEXT:
95+
res = pstrdup(password);
96+
break;
97+
case PASSWORD_TYPE_MD5:
98+
res = (char *) palloc(MD5_PASSWD_LEN + 1);
99+
if (!pg_md5_encrypt(password, rolname,
100+
strlen(rolname),
101+
res))
102+
elog(ERROR, "password encryption failed");
103+
break;
104+
default:
105+
Assert(0); /* should not come here */
106+
}
107+
}
108+
109+
return res;
110+
}
67111

68112
/*
69113
* CREATE ROLE
@@ -80,8 +124,8 @@ CreateRole(CreateRoleStmt *stmt)
80124
ListCell *item;
81125
ListCell *option;
82126
char *password = NULL; /* user password */
83-
bool encrypt_password = Password_encryption; /* encrypt password? */
84-
char encrypted_password[MD5_PASSWD_LEN + 1];
127+
int password_type = Password_encryption; /* encrypt password? */
128+
char *encrypted_passwd;
85129
bool issuper = false; /* Make the user a superuser? */
86130
bool inherit = true; /* Auto inherit privileges? */
87131
bool createrole = false; /* Can this user create roles? */
@@ -139,9 +183,9 @@ CreateRole(CreateRoleStmt *stmt)
139183
errmsg("conflicting or redundant options")));
140184
dpassword = defel;
141185
if (strcmp(defel->defname, "encryptedPassword") == 0)
142-
encrypt_password = true;
186+
password_type = PASSWORD_TYPE_MD5;
143187
else if (strcmp(defel->defname, "unencryptedPassword") == 0)
144-
encrypt_password = false;
188+
password_type = PASSWORD_TYPE_PLAINTEXT;
145189
}
146190
else if (strcmp(defel->defname, "sysid") == 0)
147191
{
@@ -380,17 +424,13 @@ CreateRole(CreateRoleStmt *stmt)
380424

381425
if (password)
382426
{
383-
if (!encrypt_password || isMD5(password))
384-
new_record[Anum_pg_authid_rolpassword - 1] =
385-
CStringGetTextDatum(password);
386-
else
387-
{
388-
if (!pg_md5_encrypt(password, stmt->role, strlen(stmt->role),
389-
encrypted_password))
390-
elog(ERROR, "password encryption failed");
391-
new_record[Anum_pg_authid_rolpassword - 1] =
392-
CStringGetTextDatum(encrypted_password);
393-
}
427+
encrypted_passwd = encrypt_password(password,
428+
stmt->role,
429+
password_type);
430+
431+
new_record[Anum_pg_authid_rolpassword - 1] =
432+
CStringGetTextDatum(encrypted_passwd);
433+
pfree(encrypted_passwd);
394434
}
395435
else
396436
new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
@@ -492,8 +532,8 @@ AlterRole(AlterRoleStmt *stmt)
492532
ListCell *option;
493533
char *rolename = NULL;
494534
char *password = NULL; /* user password */
495-
bool encrypt_password = Password_encryption; /* encrypt password? */
496-
char encrypted_password[MD5_PASSWD_LEN + 1];
535+
int password_type = Password_encryption; /* encrypt password? */
536+
char *encrypted_passwd;
497537
int issuper = -1; /* Make the user a superuser? */
498538
int inherit = -1; /* Auto inherit privileges? */
499539
int createrole = -1; /* Can this user create roles? */
@@ -537,9 +577,9 @@ AlterRole(AlterRoleStmt *stmt)
537577
errmsg("conflicting or redundant options")));
538578
dpassword = defel;
539579
if (strcmp(defel->defname, "encryptedPassword") == 0)
540-
encrypt_password = true;
580+
password_type = PASSWORD_TYPE_MD5;
541581
else if (strcmp(defel->defname, "unencryptedPassword") == 0)
542-
encrypt_password = false;
582+
password_type = PASSWORD_TYPE_PLAINTEXT;
543583
}
544584
else if (strcmp(defel->defname, "superuser") == 0)
545585
{
@@ -791,18 +831,14 @@ AlterRole(AlterRoleStmt *stmt)
791831
/* password */
792832
if (password)
793833
{
794-
if (!encrypt_password || isMD5(password))
795-
new_record[Anum_pg_authid_rolpassword - 1] =
796-
CStringGetTextDatum(password);
797-
else
798-
{
799-
if (!pg_md5_encrypt(password, rolename, strlen(rolename),
800-
encrypted_password))
801-
elog(ERROR, "password encryption failed");
802-
new_record[Anum_pg_authid_rolpassword - 1] =
803-
CStringGetTextDatum(encrypted_password);
804-
}
834+
encrypted_passwd = encrypt_password(password,
835+
rolename,
836+
password_type);
837+
838+
new_record[Anum_pg_authid_rolpassword - 1] =
839+
CStringGetTextDatum(encrypted_passwd);
805840
new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
841+
pfree(encrypted_passwd);
806842
}
807843

808844
/* unset password */

src/backend/utils/misc/guc.c

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "catalog/namespace.h"
3636
#include "commands/async.h"
3737
#include "commands/prepare.h"
38+
#include "commands/user.h"
3839
#include "commands/vacuum.h"
3940
#include "commands/variable.h"
4041
#include "commands/trigger.h"
@@ -395,6 +396,24 @@ static const struct config_enum_entry force_parallel_mode_options[] = {
395396
{NULL, 0, false}
396397
};
397398

399+
/*
400+
* password_encryption used to be a boolean, so accept all the likely
401+
* variants of "on" and "off", too.
402+
*/
403+
static const struct config_enum_entry password_encryption_options[] = {
404+
{"plain", PASSWORD_TYPE_PLAINTEXT, false},
405+
{"md5", PASSWORD_TYPE_MD5, false},
406+
{"off", PASSWORD_TYPE_PLAINTEXT, false},
407+
{"on", PASSWORD_TYPE_MD5, false},
408+
{"true", PASSWORD_TYPE_MD5, true},
409+
{"false", PASSWORD_TYPE_PLAINTEXT, true},
410+
{"yes", PASSWORD_TYPE_MD5, true},
411+
{"no", PASSWORD_TYPE_PLAINTEXT, true},
412+
{"1", PASSWORD_TYPE_MD5, true},
413+
{"0", PASSWORD_TYPE_PLAINTEXT, true},
414+
{NULL, 0, false}
415+
};
416+
398417
/*
399418
* Options for enum values stored in other modules
400419
*/
@@ -425,8 +444,6 @@ bool check_function_bodies = true;
425444
bool default_with_oids = false;
426445
bool SQL_inheritance = true;
427446

428-
bool Password_encryption = true;
429-
430447
int log_min_error_statement = ERROR;
431448
int log_min_messages = WARNING;
432449
int client_min_messages = NOTICE;
@@ -1325,17 +1342,6 @@ static struct config_bool ConfigureNamesBool[] =
13251342
true,
13261343
NULL, NULL, NULL
13271344
},
1328-
{
1329-
{"password_encryption", PGC_USERSET, CONN_AUTH_SECURITY,
1330-
gettext_noop("Encrypt passwords."),
1331-
gettext_noop("When a password is specified in CREATE USER or "
1332-
"ALTER USER without writing either ENCRYPTED or UNENCRYPTED, "
1333-
"this parameter determines whether the password is to be encrypted.")
1334-
},
1335-
&Password_encryption,
1336-
true,
1337-
NULL, NULL, NULL
1338-
},
13391345
{
13401346
{"transform_null_equals", PGC_USERSET, COMPAT_OPTIONS_CLIENT,
13411347
gettext_noop("Treats \"expr=NULL\" as \"expr IS NULL\"."),
@@ -3899,6 +3905,18 @@ static struct config_enum ConfigureNamesEnum[] =
38993905
NULL, NULL, NULL
39003906
},
39013907

3908+
{
3909+
{"password_encryption", PGC_USERSET, CONN_AUTH_SECURITY,
3910+
gettext_noop("Encrypt passwords."),
3911+
gettext_noop("When a password is specified in CREATE USER or "
3912+
"ALTER USER without writing either ENCRYPTED or UNENCRYPTED, "
3913+
"this parameter determines whether the password is to be encrypted.")
3914+
},
3915+
&Password_encryption,
3916+
PASSWORD_TYPE_MD5, password_encryption_options,
3917+
NULL, NULL, NULL
3918+
},
3919+
39023920
/* End-of-list marker */
39033921
{
39043922
{NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL

src/backend/utils/misc/postgresql.conf.sample

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
#ssl_key_file = 'server.key' # (change requires restart)
8686
#ssl_ca_file = '' # (change requires restart)
8787
#ssl_crl_file = '' # (change requires restart)
88-
#password_encryption = on
88+
#password_encryption = md5 # md5 or plain
8989
#db_user_namespace = off
9090
#row_security = on
9191

src/include/commands/user.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,19 @@
1515
#include "nodes/parsenodes.h"
1616

1717

18-
/* Hook to check passwords in CreateRole() and AlterRole() */
19-
#define PASSWORD_TYPE_PLAINTEXT 0
20-
#define PASSWORD_TYPE_MD5 1
18+
/*
19+
* Types of password, for Password_encryption GUC and the password_type
20+
* argument of the check-password hook.
21+
*/
22+
typedef enum PasswordType
23+
{
24+
PASSWORD_TYPE_PLAINTEXT = 0,
25+
PASSWORD_TYPE_MD5
26+
} PasswordType;
27+
28+
extern int Password_encryption; /* GUC */
2129

30+
/* Hook to check passwords in CreateRole() and AlterRole() */
2231
typedef void (*check_password_hook_type) (const char *username, const char *password, int password_type, Datum validuntil_time, bool validuntil_null);
2332

2433
extern PGDLLIMPORT check_password_hook_type check_password_hook;

0 commit comments

Comments
 (0)