public inbox for [email protected]
help / color / mirror / Atom feedFrom: Gilles Darold <[email protected]>
To: PostgreSQL Hackers <[email protected]>
Cc: Andrew Dunstan <[email protected]>
Cc: Bossart, Nathan <[email protected]>
Cc: Tom Lane <[email protected]>
Subject: Re: Pasword expiration warning
Date: Tue, 6 Jan 2026 15:43:20 +0100
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
References: <[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
Le 21/11/2021 à 10:49, Gilles Darold a écrit :
> Le 20/11/2021 à 14:48, Andrew Dunstan a écrit :
>> On 11/19/21 19:17, Bossart, Nathan wrote:
>>> On 11/19/21, 7:56 AM, "Tom Lane" <[email protected]> wrote:
>>>> That leads me to wonder about server-side solutions. It's easy
>>>> enough for the server to see that it's used a password with an
>>>> expiration N days away, but how could that be reported to the
>>>> client? The only idea that comes to mind that doesn't seem like
>>>> a protocol break is to issue a NOTICE message, which doesn't
>>>> seem like it squares with your desire to only do this interactively.
>>>> (Although I'm not sure I believe that's a great idea. If your
>>>> application breaks at 2AM because its password expired, you
>>>> won't be any happier than if your interactive sessions start to
>>>> fail. Maybe a message that would leave a trail in the server log
>>>> would be best after all.)
>>> I bet it's possible to use the ClientAuthentication_hook for this. In
>>> any case, I agree that it probably belongs server-side so that other
>>> clients can benefit from this.
>>>
>> +1 for a server side solution. The people most likely to benefit from
>> this are the people least likely to be using psql IMNSHO.
>>
>>
>> Ok, I can try to implement something at server side using a NOTICE message.
Hi,
Sorry to resurrect this old thread, but I had completely forgotten about
it. If there's still interest in this feature, then please find in
attachment a patch to emit a warning to the client and into the logs
when the password will expire within 7 days by default. A GUC,
password_expire_warning, allow to change the number of days before
sending the message or to disable this feature with setting value 0.
I have chosen to add a new field, const char *warning_message, to struct
ClientConnectionInfo so that it can be used to send other messages to
the client at end of connection ( src/backend/utils/init/postinit.c:
InitPostgres() ). Not sure sure that this is the best way to do that but
as it is a message dedicated to the connection I've though it could be
the right place. If we don't expect other warning message sent to the
client at connection time, just using an integer for the number of days
remaining will be enough. We could use notice but it is not logged by
default and also I think that warning is the good level for this message.
Output at psql connection:
$ /usr/local/pgsql/bin/psql -h localhost -U test -d postgres
Password for user test:
WARNING: your password will expire in 4 days
psql (19devel)
Type "help" for help.
postgres=>
Output in the log:
2026-01-05 23:23:13.763 CET [136001] WARNING: your password
will expire in 4 days
Using a script:
$ perl test_conn.pl
WARNING: your password will expire in 3 days
The message can be handled by any client application to warn the user if
required.
Thanks in advance for your feedback and suggestion for a better
implementation.
Best regards,
--
Gilles Darold
http://hexacluster.ai/
Attachments:
[text/x-patch] password_expire_warning-v1.patch (4.6K, ../[email protected]/2-password_expire_warning-v1.patch)
download | inline diff:
diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c
index 4c1052b3d42..e93a9059f58 100644
--- a/src/backend/libpq/crypt.c
+++ b/src/backend/libpq/crypt.c
@@ -20,6 +20,7 @@
#include "common/scram-common.h"
#include "libpq/crypt.h"
#include "libpq/scram.h"
+#include "postmaster/postmaster.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
#include "utils/timestamp.h"
@@ -27,6 +28,9 @@
/* Enables deprecation warnings for MD5 passwords. */
bool md5_password_warnings = true;
+/* Emit a warning 7 days before password expiration */
+int password_expire_warning = 7;
+
/*
* Fetch stored password for a user, for authentication.
*
@@ -80,6 +84,22 @@ get_role_password(const char *role, const char **logdetail)
return NULL;
}
+ /*
+ * Password OK, but check if rolvaliduntil is less than GUC
+ * password_expire_warning days to send a warning to the client
+ */
+ if (!isnull && password_expire_warning > 0)
+ {
+ float8 result;
+
+ result = ((float8) (vuntil - GetCurrentTimestamp())) / 1000000.0; /* in seconds */
+ result /= 86400; /* in days */
+
+ if ((int) result <= password_expire_warning)
+ MyClientConnectionInfo.warning_message =
+ psprintf("your password will expire in %d days", (int) result);
+ }
+
return shadow_pass;
}
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 563f20374ff..24737c95c28 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -1089,6 +1089,7 @@ RestoreClientConnectionInfo(char *conninfo)
/* Copy the fields back into place */
MyClientConnectionInfo.authn_id = NULL;
+ MyClientConnectionInfo.warning_message = NULL;
MyClientConnectionInfo.auth_method = serialized.auth_method;
if (serialized.authn_id_len >= 0)
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 52c05a9d1d5..356c8ffe215 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -1232,6 +1232,13 @@ InitPostgres(const char *in_dbname, Oid dboid,
/* close the transaction we started above */
if (!bootstrap)
CommitTransactionCommand();
+
+ /*
+ * Emit a warning message to the client when set, for example
+ * to warn the user that the password will expire.
+ */
+ if (MyClientConnectionInfo.warning_message)
+ ereport(WARNING, (errmsg("%s", MyClientConnectionInfo.warning_message)));
}
/*
diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat
index 7c60b125564..b7c42da28da 100644
--- a/src/backend/utils/misc/guc_parameters.dat
+++ b/src/backend/utils/misc/guc_parameters.dat
@@ -2248,6 +2248,15 @@
options => 'password_encryption_options',
},
+{ name => 'password_expire_warning', type => 'int', context => 'PGC_SIGHUP', group => 'CONN_AUTH_AUTH',
+ short_desc => 'Sets the number of days before password expire to emit a warning at client connection. Default is 7 days, 0 means no warning.',
+ flags => 'GUC_UNIT_S',
+ variable => 'password_expire_warning',
+ boot_val => '7',
+ min => '0',
+ max => '30',
+},
+
{ name => 'plan_cache_mode', type => 'enum', context => 'PGC_USERSET', group => 'QUERY_TUNING_OTHER',
short_desc => 'Controls the planner\'s selection of custom or generic plan.',
long_desc => 'Prepared statements can have custom and generic plans, and the planner will attempt to choose which is better. This can be set to override the default behavior.',
diff --git a/src/include/libpq/crypt.h b/src/include/libpq/crypt.h
index f01886e1098..e92f4f151c9 100644
--- a/src/include/libpq/crypt.h
+++ b/src/include/libpq/crypt.h
@@ -28,6 +28,9 @@
/* Enables deprecation warnings for MD5 passwords. */
extern PGDLLIMPORT bool md5_password_warnings;
+/* number of days before emitting a warning for password expiration */
+extern PGDLLIMPORT int password_expire_warning;
+
/*
* Types of password hashes or secrets.
*
diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h
index 921b2daa4ff..4ed61921ccd 100644
--- a/src/include/libpq/libpq-be.h
+++ b/src/include/libpq/libpq-be.h
@@ -103,6 +103,15 @@ typedef struct ClientConnectionInfo
* meaning if authn_id is not NULL; otherwise it's undefined.
*/
UserAuth auth_method;
+
+ /*
+ * Message to send to the client in case of connection success.
+ * When not NULL a WARNING message is sent to the client at end
+ * of the connection in src/backend/utils/init/postinit.c at
+ * enf of InitPostgres(). For example, it is use to show the
+ * password expiration warning.
+ */
+ const char *warning_message;
} ClientConnectionInfo;
/*
view thread (3+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected], [email protected]
Subject: Re: Pasword expiration warning
In-Reply-To: <[email protected]>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox