Add passwordcheck.min_password_length.
authorNathan Bossart <nathan@postgresql.org>
Tue, 7 Jan 2025 21:06:40 +0000 (15:06 -0600)
committerNathan Bossart <nathan@postgresql.org>
Tue, 7 Jan 2025 21:06:40 +0000 (15:06 -0600)
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

contrib/passwordcheck/expected/passwordcheck.out
contrib/passwordcheck/expected/passwordcheck_1.out
contrib/passwordcheck/passwordcheck.c
contrib/passwordcheck/sql/passwordcheck.sql
doc/src/sgml/passwordcheck.sgml

index dfb2ccfe00851a7b34e3d71be0b52256710afedb..83472c76d2784e6469367a008bf3648ff6f6b7f0 100644 (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
index 9519d60a495e2a4296b83168d58879c80dda48e3..fb12ec45cc4bf7e9458bcefdd53197f1f988520e 100644 (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
index 96ada5b98c6f02b10eeb4b109b46fad535a02b03..3db42a5b99d87c370fd9931884e7e916c5ea46e5 100644 (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;
index 5953ece5c26a88d467dde277a60009f3db06b2c3..21ad8d452b5e46f0b83c9ca09569514a9c3b454f 100644 (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';
 
index 601f489227223833d85960b2d669ee23d8a8be62..7ea32410463b6dce9d9dfcaebbd6fb1a46b940c1 100644 (file)
   </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>