summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Bossart2025-01-07 21:06:40 +0000
committerNathan Bossart2025-01-07 21:06:40 +0000
commitf7e1b3828a930639aefb5746a214cb5ddf734361 (patch)
tree336b31633f29da5e3eab7b25e0277b29f0d04299
parent6d01541960e2a42c92ef67be9a1c4842cd4458d6 (diff)
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
-rw-r--r--contrib/passwordcheck/expected/passwordcheck.out4
-rw-r--r--contrib/passwordcheck/expected/passwordcheck_1.out4
-rw-r--r--contrib/passwordcheck/passwordcheck.c24
-rw-r--r--contrib/passwordcheck/sql/passwordcheck.sql4
-rw-r--r--doc/src/sgml/passwordcheck.sgml37
5 files changed, 69 insertions, 4 deletions
diff --git a/contrib/passwordcheck/expected/passwordcheck.out b/contrib/passwordcheck/expected/passwordcheck.out
index dfb2ccfe008..83472c76d27 100644
--- a/contrib/passwordcheck/expected/passwordcheck.out
+++ b/contrib/passwordcheck/expected/passwordcheck.out
@@ -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
diff --git a/contrib/passwordcheck/expected/passwordcheck_1.out b/contrib/passwordcheck/expected/passwordcheck_1.out
index 9519d60a495..fb12ec45cc4 100644
--- a/contrib/passwordcheck/expected/passwordcheck_1.out
+++ b/contrib/passwordcheck/expected/passwordcheck_1.out
@@ -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
diff --git a/contrib/passwordcheck/passwordcheck.c b/contrib/passwordcheck/passwordcheck.c
index 96ada5b98c6..3db42a5b99d 100644
--- a/contrib/passwordcheck/passwordcheck.c
+++ b/contrib/passwordcheck/passwordcheck.c
@@ -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;
diff --git a/contrib/passwordcheck/sql/passwordcheck.sql b/contrib/passwordcheck/sql/passwordcheck.sql
index 5953ece5c26..21ad8d452b5 100644
--- a/contrib/passwordcheck/sql/passwordcheck.sql
+++ b/contrib/passwordcheck/sql/passwordcheck.sql
@@ -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';
diff --git a/doc/src/sgml/passwordcheck.sgml b/doc/src/sgml/passwordcheck.sgml
index 601f4892272..7ea32410463 100644
--- a/doc/src/sgml/passwordcheck.sgml
+++ b/doc/src/sgml/passwordcheck.sgml
@@ -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>