aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Bossart <nathan@postgresql.org>2024-12-02 13:30:07 -0600
committerNathan Bossart <nathan@postgresql.org>2024-12-02 13:30:07 -0600
commitdb6a4a985bc09d260d5c29848e3c97f080646a53 (patch)
tree5d57a50559a2a1ae40896a2007a9025a12339f22
parent97173536ed4b1c29dce0dc4119db136e142f60a2 (diff)
downloadpostgresql-db6a4a985bc09d260d5c29848e3c97f080646a53.tar.gz
postgresql-db6a4a985bc09d260d5c29848e3c97f080646a53.zip
Deprecate MD5 passwords.
MD5 has been considered to be unsuitable for use as a cryptographic hash algorithm for some time. Furthermore, MD5 password hashes in PostgreSQL are vulnerable to pass-the-hash attacks, i.e., knowing the username and hashed password is sufficient to authenticate. The SCRAM-SHA-256 method added in v10 is not subject to these problems and is considered to be superior to MD5. This commit marks MD5 password support in PostgreSQL as deprecated and to be removed in a future release. The documentation now contains several deprecation notices, and CREATE ROLE and ALTER ROLE now emit deprecation warnings when setting MD5 passwords. The warnings can be disabled by setting the md5_password_warnings parameter to "off". Reviewed-by: Greg Sabino Mullane, Jim Nasby Discussion: https://postgr.es/m/ZwbfpJJol7lDWajL%40nathan
-rw-r--r--contrib/passwordcheck/expected/passwordcheck.out1
-rw-r--r--contrib/passwordcheck/expected/passwordcheck_1.out1
-rw-r--r--contrib/passwordcheck/sql/passwordcheck.sql1
-rw-r--r--doc/src/sgml/catalogs.sgml9
-rw-r--r--doc/src/sgml/client-auth.sgml17
-rw-r--r--doc/src/sgml/config.sgml24
-rw-r--r--doc/src/sgml/libpq.sgml9
-rw-r--r--doc/src/sgml/protocol.sgml8
-rw-r--r--doc/src/sgml/ref/create_role.sgml8
-rw-r--r--doc/src/sgml/runtime.sgml10
-rw-r--r--src/backend/libpq/crypt.c10
-rw-r--r--src/backend/utils/misc/guc_tables.c9
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample1
-rw-r--r--src/include/libpq/crypt.h3
-rw-r--r--src/test/regress/expected/password.out15
-rw-r--r--src/test/regress/expected/password_1.out9
16 files changed, 135 insertions, 0 deletions
diff --git a/contrib/passwordcheck/expected/passwordcheck.out b/contrib/passwordcheck/expected/passwordcheck.out
index 2027681daf6..dfb2ccfe008 100644
--- a/contrib/passwordcheck/expected/passwordcheck.out
+++ b/contrib/passwordcheck/expected/passwordcheck.out
@@ -1,3 +1,4 @@
+SET md5_password_warnings = off;
LOAD 'passwordcheck';
CREATE USER regress_passwordcheck_user1;
-- ok
diff --git a/contrib/passwordcheck/expected/passwordcheck_1.out b/contrib/passwordcheck/expected/passwordcheck_1.out
index 5d8d5dcc1c2..9519d60a495 100644
--- a/contrib/passwordcheck/expected/passwordcheck_1.out
+++ b/contrib/passwordcheck/expected/passwordcheck_1.out
@@ -1,3 +1,4 @@
+SET md5_password_warnings = off;
LOAD 'passwordcheck';
CREATE USER regress_passwordcheck_user1;
-- ok
diff --git a/contrib/passwordcheck/sql/passwordcheck.sql b/contrib/passwordcheck/sql/passwordcheck.sql
index 1fbd6b0e96e..5953ece5c26 100644
--- a/contrib/passwordcheck/sql/passwordcheck.sql
+++ b/contrib/passwordcheck/sql/passwordcheck.sql
@@ -1,3 +1,4 @@
+SET md5_password_warnings = off;
LOAD 'passwordcheck';
CREATE USER regress_passwordcheck_user1;
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 59bb833f48d..bf3cee08a93 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -1618,6 +1618,15 @@
will store the md5 hash of <literal>xyzzyjoe</literal>.
</para>
+ <warning>
+ <para>
+ Support for MD5-encrypted passwords is deprecated and will be removed in a
+ future release of <productname>PostgreSQL</productname>. Refer to
+ <xref linkend="auth-password"/> for details about migrating to another
+ password type.
+ </para>
+ </warning>
+
<para>
If the password is encrypted with SCRAM-SHA-256, it has the format:
<synopsis>
diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index 51343de7cad..782b49c85ac 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -531,6 +531,15 @@ include_dir <replaceable>directory</replaceable>
user's password. See <xref linkend="auth-password"/>
for details.
</para>
+ <warning>
+ <para>
+ Support for MD5-encrypted passwords is deprecated and will be
+ removed in a future release of
+ <productname>PostgreSQL</productname>. Refer to
+ <xref linkend="auth-password"/> for details about migrating to
+ another password type.
+ </para>
+ </warning>
</listitem>
</varlistentry>
@@ -1260,6 +1269,14 @@ omicron bryanh guest1
server is encrypted for SCRAM (see below), then SCRAM-based
authentication will automatically be chosen instead.
</para>
+
+ <warning>
+ <para>
+ Support for MD5-encrypted passwords is deprecated and will be removed
+ in a future release of <productname>PostgreSQL</productname>. Refer to
+ the text below for details about migrating to another password type.
+ </para>
+ </warning>
</listitem>
</varlistentry>
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 76ab72db964..e0c8325a39c 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1124,6 +1124,14 @@ include_dir 'conf.d'
mechanism, and hence not work with passwords encrypted with
SCRAM-SHA-256. See <xref linkend="auth-password"/> for more details.
</para>
+ <warning>
+ <para>
+ Support for MD5-encrypted passwords is deprecated and will be removed
+ in a future release of <productname>PostgreSQL</productname>. Refer
+ to <xref linkend="auth-password"/> for details about migrating to
+ another password type.
+ </para>
+ </warning>
</listitem>
</varlistentry>
@@ -7913,6 +7921,22 @@ log_line_prefix = '%m [%p] %q%u@%d/%a '
</listitem>
</varlistentry>
+ <varlistentry id="guc-md5-password-warnings" xreflabel="md5_password_warnings">
+ <term><varname>md5_password_warnings</varname> (<type>boolean</type>)
+ <indexterm>
+ <primary><varname>md5_password_warnings</varname> configuration parameter</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Controls whether a <literal>WARNING</literal> about MD5 password
+ deprecation is produced when a <command>CREATE ROLE</command> or
+ <command>ALTER ROLE</command> statement sets an MD5-encrypted password.
+ The default value is <literal>on</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</sect2>
<sect2 id="runtime-config-logging-csvlog">
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index bfefb1289e8..01f259fd0dc 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1341,6 +1341,15 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
<para>
The server must request MD5 hashed password authentication.
</para>
+ <warning>
+ <para>
+ Support for MD5-encrypted passwords is deprecated and will be
+ removed in a future release of
+ <productname>PostgreSQL</productname>. Refer to
+ <xref linkend="auth-password"/> for details about migrating to
+ another password type.
+ </para>
+ </warning>
</listitem>
</varlistentry>
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index cff0c4099e9..fb5dec1172e 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -312,6 +312,14 @@
(Keep in mind the <function>md5()</function> function returns its
result as a hex string.)
</para>
+ <warning>
+ <para>
+ Support for MD5-encrypted passwords is deprecated and will be removed
+ in a future release of <productname>PostgreSQL</productname>. Refer
+ to <xref linkend="auth-password"/> for details about migrating to
+ another password type.
+ </para>
+ </warning>
</listitem>
</varlistentry>
diff --git a/doc/src/sgml/ref/create_role.sgml b/doc/src/sgml/ref/create_role.sgml
index f72ba9affc2..cee23b1ea6b 100644
--- a/doc/src/sgml/ref/create_role.sgml
+++ b/doc/src/sgml/ref/create_role.sgml
@@ -273,6 +273,14 @@ in sync when changing the above synopsis!
different format). This allows reloading of encrypted passwords
during dump/restore.
</para>
+ <warning>
+ <para>
+ Support for MD5-encrypted passwords is deprecated and will be removed
+ in a future release of <productname>PostgreSQL</productname>. Refer
+ to <xref linkend="auth-password"/> for details about migrating to
+ another password type.
+ </para>
+ </warning>
</listitem>
</varlistentry>
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index bcd81e24158..94135e9d5ee 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -2053,6 +2053,16 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
is an Internet standard and is more secure than the PostgreSQL-specific
MD5 authentication protocol.
</para>
+
+ <warning>
+ <para>
+ Support for MD5-encrypted passwords is deprecated and will be removed in
+ a future release of <productname>PostgreSQL</productname>. Refer to
+ <xref linkend="auth-password"/> for details about migrating to another
+ password type.
+ </para>
+ </warning>
+
</listitem>
</varlistentry>
diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c
index b01525dc28a..d37c70901b8 100644
--- a/src/backend/libpq/crypt.c
+++ b/src/backend/libpq/crypt.c
@@ -24,6 +24,8 @@
#include "utils/syscache.h"
#include "utils/timestamp.h"
+/* Enables deprecation warnings for MD5 passwords. */
+bool md5_password_warnings = true;
/*
* Fetch stored password for a user, for authentication.
@@ -174,6 +176,14 @@ encrypt_password(PasswordType target_type, const char *role,
MAX_ENCRYPTED_PASSWORD_LEN)));
}
+ if (md5_password_warnings &&
+ get_password_type(encrypted_password) == PASSWORD_TYPE_MD5)
+ ereport(WARNING,
+ (errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
+ errmsg("setting an MD5-encrypted password"),
+ errdetail("MD5 password support is deprecated and will be removed in a future release of PostgreSQL."),
+ errhint("Refer to the PostgreSQL documentation for details about migrating to another password type.")));
+
return encrypted_password;
}
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 9845abd6932..8cf1afbad20 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -2086,6 +2086,15 @@ struct config_bool ConfigureNamesBool[] =
NULL, NULL, NULL
},
+ {
+ {"md5_password_warnings", PGC_USERSET, CONN_AUTH_AUTH,
+ gettext_noop("Enables deprecation warnings for MD5 passwords."),
+ },
+ &md5_password_warnings,
+ true,
+ NULL, NULL, NULL
+ },
+
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 407cd1e08ca..a2ac7575ca7 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -96,6 +96,7 @@
#authentication_timeout = 1min # 1s-600s
#password_encryption = scram-sha-256 # scram-sha-256 or md5
#scram_iterations = 4096
+#md5_password_warnings = on
# GSSAPI using Kerberos
#krb_server_keyfile = 'FILE:${sysconfdir}/krb5.keytab'
diff --git a/src/include/libpq/crypt.h b/src/include/libpq/crypt.h
index 0bb44004353..db7ea7bd1f5 100644
--- a/src/include/libpq/crypt.h
+++ b/src/include/libpq/crypt.h
@@ -25,6 +25,9 @@
*/
#define MAX_ENCRYPTED_PASSWORD_LEN (512)
+/* Enables deprecation warnings for MD5 passwords. */
+extern PGDLLIMPORT bool md5_password_warnings;
+
/*
* Types of password hashes or secrets.
*
diff --git a/src/test/regress/expected/password.out b/src/test/regress/expected/password.out
index df3857460c2..9bb3ab2818b 100644
--- a/src/test/regress/expected/password.out
+++ b/src/test/regress/expected/password.out
@@ -14,8 +14,14 @@ SET password_encryption = 'scram-sha-256'; -- ok
SET password_encryption = 'md5';
CREATE ROLE regress_passwd1;
ALTER ROLE regress_passwd1 PASSWORD 'role_pwd1';
+WARNING: setting an MD5-encrypted password
+DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL.
+HINT: Refer to the PostgreSQL documentation for details about migrating to another password type.
CREATE ROLE regress_passwd2;
ALTER ROLE regress_passwd2 PASSWORD 'role_pwd2';
+WARNING: setting an MD5-encrypted password
+DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL.
+HINT: Refer to the PostgreSQL documentation for details about migrating to another password type.
SET password_encryption = 'scram-sha-256';
CREATE ROLE regress_passwd3 PASSWORD 'role_pwd3';
CREATE ROLE regress_passwd4 PASSWORD NULL;
@@ -57,14 +63,23 @@ ALTER ROLE regress_passwd2_new RENAME TO regress_passwd2;
SET password_encryption = 'md5';
-- encrypt with MD5
ALTER ROLE regress_passwd2 PASSWORD 'foo';
+WARNING: setting an MD5-encrypted password
+DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL.
+HINT: Refer to the PostgreSQL documentation for details about migrating to another password type.
-- already encrypted, use as they are
ALTER ROLE regress_passwd1 PASSWORD 'md5cd3578025fe2c3d7ed1b9a9b26238b70';
+WARNING: setting an MD5-encrypted password
+DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL.
+HINT: Refer to the PostgreSQL documentation for details about migrating to another password type.
ALTER ROLE regress_passwd3 PASSWORD 'SCRAM-SHA-256$4096:VLK4RMaQLCvNtQ==$6YtlR4t69SguDiwFvbVgVZtuz6gpJQQqUMZ7IQJK5yI=:ps75jrHeYU4lXCcXI4O8oIdJ3eO8o2jirjruw9phBTo=';
SET password_encryption = 'scram-sha-256';
-- create SCRAM secret
ALTER ROLE regress_passwd4 PASSWORD 'foo';
-- already encrypted with MD5, use as it is
CREATE ROLE regress_passwd5 PASSWORD 'md5e73a4b11df52a6068f8b39f90be36023';
+WARNING: setting an MD5-encrypted password
+DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL.
+HINT: Refer to the PostgreSQL documentation for details about migrating to another password type.
-- This looks like a valid SCRAM-SHA-256 secret, but it is not
-- so it should be hashed with SCRAM-SHA-256.
CREATE ROLE regress_passwd6 PASSWORD 'SCRAM-SHA-256$1234';
diff --git a/src/test/regress/expected/password_1.out b/src/test/regress/expected/password_1.out
index bd0c2e48de0..8f613e976a6 100644
--- a/src/test/regress/expected/password_1.out
+++ b/src/test/regress/expected/password_1.out
@@ -61,12 +61,18 @@ ALTER ROLE regress_passwd2 PASSWORD 'foo';
ERROR: password encryption failed: unsupported
-- already encrypted, use as they are
ALTER ROLE regress_passwd1 PASSWORD 'md5cd3578025fe2c3d7ed1b9a9b26238b70';
+WARNING: setting an MD5-encrypted password
+DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL.
+HINT: Refer to the PostgreSQL documentation for details about migrating to another password type.
ALTER ROLE regress_passwd3 PASSWORD 'SCRAM-SHA-256$4096:VLK4RMaQLCvNtQ==$6YtlR4t69SguDiwFvbVgVZtuz6gpJQQqUMZ7IQJK5yI=:ps75jrHeYU4lXCcXI4O8oIdJ3eO8o2jirjruw9phBTo=';
SET password_encryption = 'scram-sha-256';
-- create SCRAM secret
ALTER ROLE regress_passwd4 PASSWORD 'foo';
-- already encrypted with MD5, use as it is
CREATE ROLE regress_passwd5 PASSWORD 'md5e73a4b11df52a6068f8b39f90be36023';
+WARNING: setting an MD5-encrypted password
+DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL.
+HINT: Refer to the PostgreSQL documentation for details about migrating to another password type.
-- This looks like a valid SCRAM-SHA-256 secret, but it is not
-- so it should be hashed with SCRAM-SHA-256.
CREATE ROLE regress_passwd6 PASSWORD 'SCRAM-SHA-256$1234';
@@ -100,6 +106,9 @@ SELECT rolname, regexp_replace(rolpassword, '(SCRAM-SHA-256)\$(\d+):([a-zA-Z0-9+
CREATE ROLE regress_passwd_empty PASSWORD '';
NOTICE: empty string is not a valid password, clearing password
ALTER ROLE regress_passwd_empty PASSWORD 'md585939a5ce845f1a1b620742e3c659e0a';
+WARNING: setting an MD5-encrypted password
+DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL.
+HINT: Refer to the PostgreSQL documentation for details about migrating to another password type.
ALTER ROLE regress_passwd_empty PASSWORD 'SCRAM-SHA-256$4096:hpFyHTUsSWcR7O9P$LgZFIt6Oqdo27ZFKbZ2nV+vtnYM995pDh9ca6WSi120=:qVV5NeluNfUPkwm7Vqat25RjSPLkGeoZBQs6wVv+um4=';
NOTICE: empty string is not a valid password, clearing password
SELECT rolpassword FROM pg_authid WHERE rolname='regress_passwd_empty';