On Thu, Dec 19, 2024 at 09:36:17AM -0600, Nathan Bossart wrote:
> On Thu, Dec 19, 2024 at 07:25:30AM +0000, Bertrand Drouvot wrote:
>> -                                     errmsg("password is too short")));
>> +                                     errmsg("password is too short: %d (< 
>> %d)", pwdlen, min_password_length)));
> 
> I think we should explicitly point to the parameter and note its current
> value.

Like so.

-- 
nathan
>From ce67f3ff5fca47b443195f5bd1932429294bdbfb Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nat...@postgresql.org>
Date: Wed, 18 Dec 2024 14:49:20 -0600
Subject: [PATCH v11 1/1] 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
Discussion: 
https://postgr.es/m/CA%2BugDNyYtHOtWCqVD3YkSVYDWD_1fO8Jm_ahsDGA5dXhbDPwrQ%40mail.gmail.com
---
 .../passwordcheck/expected/passwordcheck.out  |  4 ++
 .../expected/passwordcheck_1.out              |  4 ++
 contrib/passwordcheck/passwordcheck.c         | 26 ++++++++++---
 contrib/passwordcheck/sql/passwordcheck.sql   |  4 ++
 doc/src/sgml/passwordcheck.sgml               | 37 +++++++++++++++++++
 5 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/contrib/passwordcheck/expected/passwordcheck.out 
b/contrib/passwordcheck/expected/passwordcheck.out
index dfb2ccfe00..83472c76d2 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 9519d60a49..fb12ec45cc 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 0785618f2a..d79ecb00b6 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>
@@ -26,11 +27,11 @@
 
 PG_MODULE_MAGIC;
 
-/* Saved hook value in case of unload */
+/* Original hook */
 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 5953ece5c2..21ad8d452b 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 601f489227..7ea3241046 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>
-- 
2.39.5 (Apple Git-154)

Reply via email to