Add passwordcheck.min_password_length.

This new parameter can be used to change the minimum allowed
password length (in bytes).  Note that it has no effect if a user
supplies a pre-encrypted password.

Author: Emanuele Musella, Maurizio Boriani
Reviewed-by: Tomas Vondra, Bertrand Drouvot, Japin Li
Discussion: https://postgr.es/m/CA%2BugDNyYtHOtWCqVD3YkSVYDWD_1fO8Jm_ahsDGA5dXhbDPwrQ%40mail.gmail.com
This commit is contained in:
Nathan Bossart 2025-01-07 15:06:40 -06:00
parent 6d01541960
commit f7e1b3828a
5 changed files with 69 additions and 4 deletions

View File

@ -6,6 +6,10 @@ ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password';
-- error: too short
ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt';
ERROR: password is too short
DETAIL: password must be at least "passwordcheck.min_password_length" (8) bytes long
-- ok
SET passwordcheck.min_password_length = 6;
ALTER USER regress_passwordcheck_user1 PASSWORD 'v_shrt';
-- error: contains user name
ALTER USER regress_passwordcheck_user1 PASSWORD 'xyzregress_passwordcheck_user1';
ERROR: password must not contain user name

View File

@ -6,6 +6,10 @@ ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password';
-- error: too short
ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt';
ERROR: password is too short
DETAIL: password must be at least "passwordcheck.min_password_length" (8) bytes long
-- ok
SET passwordcheck.min_password_length = 6;
ALTER USER regress_passwordcheck_user1 PASSWORD 'v_shrt';
-- error: contains user name
ALTER USER regress_passwordcheck_user1 PASSWORD 'xyzregress_passwordcheck_user1';
ERROR: password must not contain user name

View File

@ -15,6 +15,7 @@
#include "postgres.h"
#include <ctype.h>
#include <limits.h>
#ifdef USE_CRACKLIB
#include <crack.h>
@ -29,8 +30,8 @@ PG_MODULE_MAGIC;
/* Saved hook value */
static check_password_hook_type prev_check_password_hook = NULL;
/* passwords shorter than this will be rejected */
#define MIN_PWD_LENGTH 8
/* GUC variables */
static int min_password_length = 8;
/*
* check_password
@ -93,10 +94,12 @@ check_password(const char *username,
#endif
/* enforce minimum length */
if (pwdlen < MIN_PWD_LENGTH)
if (pwdlen < min_password_length)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("password is too short")));
errmsg("password is too short"),
errdetail("password must be at least \"passwordcheck.min_password_length\" (%d) bytes long",
min_password_length)));
/* check if the password contains the username */
if (strstr(password, username))
@ -142,6 +145,19 @@ check_password(const char *username,
void
_PG_init(void)
{
/* Define custom GUC variables. */
DefineCustomIntVariable("passwordcheck.min_password_length",
"Minimum allowed password length.",
NULL,
&min_password_length,
8,
0, INT_MAX,
PGC_SUSET,
GUC_UNIT_BYTE,
NULL, NULL, NULL);
MarkGUCPrefixReserved("passwordcheck");
/* activate password checks when the module is loaded */
prev_check_password_hook = check_password_hook;
check_password_hook = check_password;

View File

@ -9,6 +9,10 @@ ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password';
-- error: too short
ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt';
-- ok
SET passwordcheck.min_password_length = 6;
ALTER USER regress_passwordcheck_user1 PASSWORD 'v_shrt';
-- error: contains user name
ALTER USER regress_passwordcheck_user1 PASSWORD 'xyzregress_passwordcheck_user1';

View File

@ -59,4 +59,41 @@
</para>
</caution>
<sect2 id="passwordcheck-configuration-parameters">
<title>Configuration Parameters</title>
<variablelist>
<varlistentry>
<term>
<varname>passwordcheck.min_password_length</varname> (<type>integer</type>)
<indexterm>
<primary><varname>passwordcheck.min_password_length</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
The minimum acceptable password length in bytes. The default is 8. Only
superusers can change this setting.
</para>
<note>
<para>
This parameter has no effect if a user supplies a pre-encrypted
password.
</para>
</note>
</listitem>
</varlistentry>
</variablelist>
<para>
In ordinary usage, this parameter is set in
<filename>postgresql.conf</filename>, but superusers can alter it on-the-fly
within their own sessions. Typical usage might be:
</para>
<programlisting>
# postgresql.conf
passwordcheck.min_password_length = 12
</programlisting>
</sect2>
</sect1>