]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Warn on password auth with MD5-encrypted passwords
authorFujii Masao <fujii@postgresql.org>
Wed, 1 Jul 2026 11:57:28 +0000 (20:57 +0900)
committerFujii Masao <fujii@postgresql.org>
Wed, 1 Jul 2026 11:58:08 +0000 (20:58 +0900)
Commit bc60ee860 added a connection warning after successful MD5
authentication, but only for the md5 authentication method. A role with
an MD5-encrypted password can also authenticate via the password method,
which left that path without the same deprecation warning.

Emit the MD5 deprecation connection warning after successful
password authentication as well, when the stored password is
MD5-encrypted.

Backpatch to v19, where the MD5 connection warning was introduced.

Author: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Japin Li <japinli@hotmail.com>
Discussion: https://postgr.es/m/CAHGQGwGkWfn5rtHzvdRbVk+PCefQU3gun3hc7QnaMXHFa5Bu3w@mail.gmail.com
Backpatch-through: 19

doc/src/sgml/config.sgml
src/backend/libpq/auth.c
src/backend/libpq/crypt.c
src/test/authentication/t/001_password.pl

index 24f6a72f7582feee9c88a071a07e6995f5bb3897..45827687b9c951637f6e6e90709311a5ff604b26 100644 (file)
@@ -1206,7 +1206,8 @@ include_dir 'conf.d'
       <listitem>
        <para>
         Controls whether a <literal>WARNING</literal> about MD5 password
-        deprecation is produced upon successful MD5 password authentication or
+        deprecation is produced upon successful authentication using an
+        MD5-encrypted password or
         when a <command>CREATE ROLE</command> or
         <command>ALTER ROLE</command> statement sets an MD5-encrypted password.
         The default value is <literal>on</literal>.
index 2af5615e54a45c3d271114981071b4bc021f9d3f..12bf153d66f25f38b2a0650ffcb96dc5cf338abf 100644 (file)
@@ -48,6 +48,8 @@
 static void auth_failed(Port *port, int elevel, int status,
                                                const char *logdetail);
 static char *recv_password_packet(Port *port);
+static bool md5_password_warning_enabled(void);
+static void queue_md5_password_warning(void);
 
 
 /*----------------------------------------------------------------
@@ -795,6 +797,7 @@ CheckPasswordAuth(Port *port, const char **logdetail)
        char       *passwd;
        int                     result;
        char       *shadow_pass;
+       bool            md5_password = false;
 
        sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
 
@@ -807,6 +810,7 @@ CheckPasswordAuth(Port *port, const char **logdetail)
        {
                result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
                                                                        logdetail);
+               md5_password = (get_password_type(shadow_pass) == PASSWORD_TYPE_MD5);
        }
        else
                result = STATUS_ERROR;
@@ -816,7 +820,11 @@ CheckPasswordAuth(Port *port, const char **logdetail)
        pfree(passwd);
 
        if (result == STATUS_OK)
+       {
+               if (md5_password)
+                       queue_md5_password_warning();
                set_authn_id(port, port->user_name);
+       }
 
        return result;
 }
@@ -913,9 +921,34 @@ CheckMD5Auth(Port *port, char *shadow_pass, const char **logdetail)
 
        pfree(passwd);
 
+       if (result == STATUS_OK)
+               queue_md5_password_warning();
+
        return result;
 }
 
+static bool
+md5_password_warning_enabled(void)
+{
+       return md5_password_warnings;
+}
+
+static void
+queue_md5_password_warning(void)
+{
+       MemoryContext oldcontext;
+       char       *warning;
+       char       *detail;
+
+       oldcontext = MemoryContextSwitchTo(TopMemoryContext);
+
+       warning = pstrdup(_("authenticated with an MD5-encrypted password"));
+       detail = pstrdup(_("MD5 password support is deprecated and will be removed in a future release of PostgreSQL."));
+       StoreConnectionWarning(warning, detail, md5_password_warning_enabled);
+
+       MemoryContextSwitchTo(oldcontext);
+}
+
 
 /*----------------------------------------------------------------
  * GSSAPI authentication system
index 28857773d9ccc655d81cb1712d56dab603a310ff..e8e840db6b964dc637121d910af8d616c868bf78 100644 (file)
@@ -32,8 +32,6 @@ int                   password_expiration_warning_threshold = 604800;
 /* Enables deprecation warnings for MD5 passwords. */
 bool           md5_password_warnings = true;
 
-static bool md5_password_warning_enabled(void);
-
 /*
  * Fetch stored password for a user, for authentication.
  *
@@ -297,21 +295,7 @@ md5_crypt_verify(const char *role, const char *shadow_pass,
 
        if (strlen(client_pass) == strlen(crypt_pwd) &&
                timingsafe_bcmp(client_pass, crypt_pwd, strlen(crypt_pwd)) == 0)
-       {
-               MemoryContext oldcontext;
-               char       *warning;
-               char       *detail;
-
                retval = STATUS_OK;
-
-               oldcontext = MemoryContextSwitchTo(TopMemoryContext);
-
-               warning = pstrdup(_("authenticated with an MD5-encrypted password"));
-               detail = pstrdup(_("MD5 password support is deprecated and will be removed in a future release of PostgreSQL."));
-               StoreConnectionWarning(warning, detail, md5_password_warning_enabled);
-
-               MemoryContextSwitchTo(oldcontext);
-       }
        else
        {
                *logdetail = psprintf(_("Password does not match for user \"%s\"."),
@@ -322,12 +306,6 @@ md5_crypt_verify(const char *role, const char *shadow_pass,
        return retval;
 }
 
-static bool
-md5_password_warning_enabled(void)
-{
-       return md5_password_warnings;
-}
-
 /*
  * Check given password for given user, and return STATUS_OK or STATUS_ERROR.
  *
index fca78fc4d6a3324e5a8970e402b519f0f2560dcd..ac67935c258ec1bf1eef736a21787a00b05aa494 100644 (file)
@@ -385,9 +385,19 @@ SKIP:
 {
        skip "MD5 not supported" unless $md5_works;
        test_conn($node, 'user=md5_role', 'password', 0,
+               expected_stderr => qr/authenticated with an MD5-encrypted password/,
                log_like =>
                  [qr/connection authenticated: identity="md5_role" method=password/]
        );
+
+       $node->connect_ok(
+               'user=md5_role_no_warnings',
+               'password with warnings disabled',
+               sql => 'SHOW md5_password_warnings',
+               expected_stdout => qr/^off$/,
+               log_like => [
+                       qr/connection authenticated: identity="md5_role_no_warnings" method=password/
+               ]);
 }
 
 # require_auth succeeds here with a plaintext password.