diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index c691f055b68..6e9626fcf38 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1206,7 +1206,8 @@ include_dir 'conf.d' Controls whether a WARNING 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 CREATE ROLE or ALTER ROLE statement sets an MD5-encrypted password. The default value is on. diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 2af5615e54a..12bf153d66f 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -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 diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c index 28857773d9c..e8e840db6b9 100644 --- a/src/backend/libpq/crypt.c +++ b/src/backend/libpq/crypt.c @@ -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. * diff --git a/src/test/authentication/t/001_password.pl b/src/test/authentication/t/001_password.pl index fca78fc4d6a..ac67935c258 100644 --- a/src/test/authentication/t/001_password.pl +++ b/src/test/authentication/t/001_password.pl @@ -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.