Skip to content

Commit 9601654

Browse files
committed
Override policy rules if password shorter than a certain value
One may define weak policy rules for long passwords (encouraging passphrases) and override these weak rules by harder ones if the password is shorter.
1 parent 31f60f3 commit 9601654

29 files changed

+106
-2
lines changed

conf/config.inc.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,21 @@
111111
$pwd_complexity = 0;
112112
# use pwnedpasswords api v2 to securely check if the password has been on a leak
113113
$use_pwnedpasswords = false;
114+
# override policy if password is shorter than a certain value
115+
# Eg:
116+
# $pwd_min_length = 12;
117+
# $pwd_override_by_length = array(
118+
# array(
119+
# 'valid_if_shorter_than' => 12,
120+
# 'rules' => array(
121+
# 'pwd_min_length' => 8,
122+
# 'pwd_min_lower' => 1,
123+
# 'pwd_min_upper' => 1,
124+
# 'pwd_min_digit' => 1,
125+
# 'pwd_min_special' => 1
126+
# )
127+
# )
128+
#);
114129
# Show policy constraints message:
115130
# always
116131
# never

index.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@
122122
if (!isset($ldap_login_attribute)) { $ldap_login_attribute = "uid"; }
123123
if (!isset($ldap_fullname_attribute)) { $ldap_fullname_attribute = "cn"; }
124124
if (!isset($pwd_forbidden_chars)) { $pwd_forbidden_chars = ""; }
125+
if (!isset($pwd_override_by_length)) { $pwd_override_by_length = array(); }
125126
if (!isset($hash_options)) { $hash_options = array(); }
126127
if (!isset($samba_options)) { $samba_options = array(); }
127128
if (!isset($ldap_starttls)) { $ldap_starttls = false; }
@@ -141,7 +142,8 @@
141142
"pwd_diff_login" => $pwd_diff_login,
142143
"pwd_complexity" => $pwd_complexity,
143144
"use_pwnedpasswords" => $use_pwnedpasswords,
144-
"pwd_no_special_at_ends" => $pwd_no_special_at_ends
145+
"pwd_no_special_at_ends" => $pwd_no_special_at_ends,
146+
"pwd_override_by_length" => $pwd_override_by_length,
145147
);
146148

147149
if (!isset($pwd_show_policy_pos)) { $pwd_show_policy_pos = "above"; }

lang/ca.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,4 @@
137137
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
138138
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
139139
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
140+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/cn.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/cs.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/de.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,4 @@
135135
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
136136
$messages['specialatends'] = "Ihr Passwort enthält das einzige Sonderzeichen am Anfang oder am Ende";
137137
$messages['policyspecialatends'] = "Ein Sonderzeichen, wenn es nur ein einziges gibt, darf nicht am Anfang oder am Ende stehen";
138+
$messages['overriding_policy_by_length'] = "Wenn das Passwort kürzer als %d Zeichen ist, gelten folgende Regeln:";

lang/ee.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,4 @@
135135
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
136136
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
137137
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
138+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/el.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/en.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/es.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,4 @@
134134
$messages['policypwned'] = "Su contraseña no puede haber sido publicada previamente en ninguna lista de contraseñas filtradas accesible al publico de ningun sitio";
135135
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
136136
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
137+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/fr.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/hu.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/it.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/ja.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/nb-NO.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Ditt nye passord er ikke publisert på kjente passord-leak siter";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/nl.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,4 @@
135135
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
136136
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
137137
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
138+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/pl.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,4 @@
135135
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
136136
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
137137
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
138+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/pt-BR.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Parece que sua nova senha não foi publicada como vazada de qualquer site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/pt-PT.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/ru.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/sk.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/sl.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/sv.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/tr.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/uk.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,4 @@
134134
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
135135
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
136136
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
137+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/zh-CN.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lang/zh-TW.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@
133133
$messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site";
134134
$messages['specialatends'] = "Your new password has its only special character at the beginning or end";
135135
$messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end";
136+
$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:";

lib/functions.inc.php

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,17 @@ function show_policy( $messages, $pwd_policy_config, $result ) {
180180
# Display bloc
181181
echo "<div class=\"help alert alert-warning\">\n";
182182
echo "<p>".$messages["policy"]."</p>\n";
183+
output_policy_list($messages, $pwd_policy_config);
184+
usort($pwd_override_by_length, function($a, $b) { return $b['valid_if_shorter_than'] - $a['valid_if_shorter_than']; });
185+
foreach($pwd_override_by_length as $override) {
186+
echo "<p>".sprintf($messages["overriding_policy_by_length"], $override['valid_if_shorter_than']) . "</p>\n";
187+
output_policy_list($messages, $override['rules']);
188+
}
189+
echo "</div>\n";
190+
}
191+
192+
function output_policy_list($messages, $policy) {
193+
extract($policy);
183194
echo "<ul>\n";
184195
if ( $pwd_min_length ) { echo "<li>".$messages["policyminlength"] ." $pwd_min_length</li>\n"; }
185196
if ( $pwd_max_length ) { echo "<li>".$messages["policymaxlength"] ." $pwd_max_length</li>\n"; }
@@ -194,7 +205,6 @@ function show_policy( $messages, $pwd_policy_config, $result ) {
194205
if ( $use_pwnedpasswords ) { echo "<li>".$messages["policypwned"] ."\n"; }
195206
if ( $pwd_no_special_at_ends ) { echo "<li>".$messages["policyspecialatends"] ."</li>\n"; }
196207
echo "</ul>\n";
197-
echo "</div>\n";
198208
}
199209

200210
# Check password strength
@@ -205,6 +215,29 @@ function check_password_strength( $password, $oldpassword, $pwd_policy_config, $
205215
$result = "";
206216

207217
$length = strlen(utf8_decode($password));
218+
219+
usort($pwd_override_by_length, function($a, $b) { return $a['valid_if_shorter_than'] - $b['valid_if_shorter_than']; });
220+
$checked = false;
221+
foreach($pwd_override_by_length as $override) {
222+
if($length < $override['valid_if_shorter_than']) {
223+
$policy = array_merge($pwd_policy_config, $override['rules']);
224+
$result = match_policy($password, $oldpassword, $policy, $login, $length, $entry);
225+
$checked = true;
226+
break;
227+
}
228+
}
229+
if(!$checked) {
230+
$result = match_policy($password, $oldpassword, $pwd_policy_config, $login, $length, $entry);
231+
}
232+
233+
return $result;
234+
}
235+
236+
function match_policy($password, $oldpassword, $pwd_policy_config, $login, $length, $entry ) {
237+
extract( $pwd_policy_config );
238+
239+
$result = "";
240+
208241
preg_match_all("/[a-z]/", $password, $lower_res);
209242
$lower = count( $lower_res[0] );
210243
preg_match_all("/[A-Z]/", $password, $upper_res);

tests/CheckPasswordTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public function testCheckPasswordStrength()
2929
"pwd_complexity" => 0,
3030
"use_pwnedpasswords" => false,
3131
"pwd_no_special_at_ends" => false,
32+
"pwd_override_by_length" => array(),
3233
);
3334

3435
$login = "coudot";
@@ -59,11 +60,38 @@ public function testCheckPasswordStrength()
5960
"pwd_complexity" => 3,
6061
"use_pwnedpasswords" => false,
6162
"pwd_no_special_at_ends" => true,
63+
"pwd_override_by_length" => array(
64+
array(
65+
'valid_if_shorter_than' => 5,
66+
'rules' => array(
67+
'pwd_min_length' => 4,
68+
'pwd_min_digit' => 1,
69+
'pwd_min_upper' => 1,
70+
'pwd_min_lower' => 1,
71+
'pwd_min_special' => 1,
72+
'pwd_complexity' => 0
73+
)
74+
),
75+
array(
76+
'valid_if_shorter_than' => 4,
77+
'rules' => array(
78+
'pwd_min_length' => 3,
79+
'pwd_min_lower' => 1,
80+
'pwd_min_special' => 2,
81+
'pwd_complexity' => 0
82+
)
83+
)
84+
),
6285
);
6386

6487
$this->assertEquals("notcomplex", check_password_strength( "simple", $oldpassword, $pwd_policy_config, $login ) );
6588
$this->assertEquals("specialatends", check_password_strength( "!simple", $oldpassword, $pwd_policy_config, $login ) );
6689
$this->assertEquals("specialatends", check_password_strength( "simple?", $oldpassword, $pwd_policy_config, $login ) );
90+
$this->assertEquals("minspecial", check_password_strength( "xyZ1", $oldpassword, $pwd_policy_config, $login ) );
91+
$this->assertEquals("minupper", check_password_strength( "xy%1", $oldpassword, $pwd_policy_config, $login ) );
92+
$this->assertEquals("", check_password_strength( "xY%1", $oldpassword, $pwd_policy_config, $login ) );
93+
$this->assertEquals("minspecial", check_password_strength( "x%1", $oldpassword, $pwd_policy_config, $login ) );
94+
$this->assertEquals("", check_password_strength( "x%$", $oldpassword, $pwd_policy_config, $login ) );
6795
$this->assertEquals("", check_password_strength( "C0mplex", $oldpassword, $pwd_policy_config, $login ) );
6896
$this->assertEquals("", check_password_strength( "C0!mplex", $oldpassword, $pwd_policy_config, $login ) );
6997
$this->assertEquals("", check_password_strength( "%C0!mplex", $oldpassword, $pwd_policy_config, $login ) );
@@ -99,6 +127,7 @@ public function testCheckPasswordStrengthPwnedPasswords()
99127
"pwd_complexity" => 0,
100128
"use_pwnedpasswords" => true,
101129
"pwd_no_special_at_ends" => false,
130+
"pwd_override_by_length" => array(),
102131
);
103132

104133
$this->assertEquals("pwned", check_password_strength( "!1Password", $oldpassword, $pwd_policy_config, $login ) );

0 commit comments

Comments
 (0)