diff --git a/conf/config.inc.php b/conf/config.inc.php index f1f6853e..62d22e08 100644 --- a/conf/config.inc.php +++ b/conf/config.inc.php @@ -111,6 +111,21 @@ $pwd_complexity = 0; # use pwnedpasswords api v2 to securely check if the password has been on a leak $use_pwnedpasswords = false; +# override policy if password is shorter than a certain value +# Example: +# $pwd_min_length = 12; +# $pwd_override_by_length = array( +# array( +# 'valid_if_shorter_than' => 12, +# 'rules' => array( +# 'pwd_min_length' => 8, +# 'pwd_min_lower' => 1, +# 'pwd_min_upper' => 1, +# 'pwd_min_digit' => 1, +# 'pwd_min_special' => 1 +# ) +# ) +#); # Show policy constraints message: # always # never diff --git a/index.php b/index.php index 10a4a40d..6cc3f63a 100644 --- a/index.php +++ b/index.php @@ -122,6 +122,7 @@ if (!isset($ldap_login_attribute)) { $ldap_login_attribute = "uid"; } if (!isset($ldap_fullname_attribute)) { $ldap_fullname_attribute = "cn"; } if (!isset($pwd_forbidden_chars)) { $pwd_forbidden_chars = ""; } +if (!isset($pwd_override_by_length)) { $pwd_override_by_length = array(); } if (!isset($hash_options)) { $hash_options = array(); } if (!isset($samba_options)) { $samba_options = array(); } if (!isset($ldap_starttls)) { $ldap_starttls = false; } @@ -141,7 +142,8 @@ "pwd_diff_login" => $pwd_diff_login, "pwd_complexity" => $pwd_complexity, "use_pwnedpasswords" => $use_pwnedpasswords, - "pwd_no_special_at_ends" => $pwd_no_special_at_ends + "pwd_no_special_at_ends" => $pwd_no_special_at_ends, + "pwd_override_by_length" => $pwd_override_by_length, ); if (!isset($pwd_show_policy_pos)) { $pwd_show_policy_pos = "above"; } diff --git a/lang/ca.inc.php b/lang/ca.inc.php index 95cdcf03..e0ddf4c9 100644 --- a/lang/ca.inc.php +++ b/lang/ca.inc.php @@ -137,3 +137,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/cn.inc.php b/lang/cn.inc.php index a2035299..9df875c3 100644 --- a/lang/cn.inc.php +++ b/lang/cn.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/cs.inc.php b/lang/cs.inc.php index 9fc42923..ce3f3e49 100644 --- a/lang/cs.inc.php +++ b/lang/cs.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/de.inc.php b/lang/de.inc.php index 371d6363..adc376f5 100644 --- a/lang/de.inc.php +++ b/lang/de.inc.php @@ -135,3 +135,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Ihr Passwort enthält das einzige Sonderzeichen am Anfang oder am Ende"; $messages['policyspecialatends'] = "Ein Sonderzeichen, wenn es nur ein einziges gibt, darf nicht am Anfang oder am Ende stehen"; +$messages['overriding_policy_by_length'] = "Wenn das Passwort kürzer als %d Zeichen ist, gelten folgende Regeln:"; diff --git a/lang/ee.inc.php b/lang/ee.inc.php index dbeb1bf5..061992b9 100644 --- a/lang/ee.inc.php +++ b/lang/ee.inc.php @@ -135,3 +135,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/el.inc.php b/lang/el.inc.php index 82dd8cfd..996f23f4 100644 --- a/lang/el.inc.php +++ b/lang/el.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/en.inc.php b/lang/en.inc.php index 295500d4..fecfd69d 100644 --- a/lang/en.inc.php +++ b/lang/en.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/es.inc.php b/lang/es.inc.php index 4ac2433c..989c1af1 100644 --- a/lang/es.inc.php +++ b/lang/es.inc.php @@ -134,3 +134,4 @@ $messages['policypwned'] = "Su contraseña no puede haber sido publicada previamente en ninguna lista de contraseñas filtradas accesible al publico de ningun sitio"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/fr.inc.php b/lang/fr.inc.php index 6ff7e4ad..196c91a0 100644 --- a/lang/fr.inc.php +++ b/lang/fr.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/hu.inc.php b/lang/hu.inc.php index c620b4f6..f6d4d73a 100644 --- a/lang/hu.inc.php +++ b/lang/hu.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/it.inc.php b/lang/it.inc.php index 3b8e5b31..a7daea9f 100644 --- a/lang/it.inc.php +++ b/lang/it.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/ja.inc.php b/lang/ja.inc.php index 223eb492..b1159fc6 100644 --- a/lang/ja.inc.php +++ b/lang/ja.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/nb-NO.inc.php b/lang/nb-NO.inc.php index 2bf46822..74a53a13 100644 --- a/lang/nb-NO.inc.php +++ b/lang/nb-NO.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Ditt nye passord er ikke publisert på kjente passord-leak siter"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/nl.inc.php b/lang/nl.inc.php index 11ce3119..286d3864 100644 --- a/lang/nl.inc.php +++ b/lang/nl.inc.php @@ -135,3 +135,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/pl.inc.php b/lang/pl.inc.php index 5b805d60..81712d37 100644 --- a/lang/pl.inc.php +++ b/lang/pl.inc.php @@ -135,3 +135,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/pt-BR.inc.php b/lang/pt-BR.inc.php index f600de2b..f2b66c15 100644 --- a/lang/pt-BR.inc.php +++ b/lang/pt-BR.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Parece que sua nova senha não foi publicada como vazada de qualquer site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/pt-PT.inc.php b/lang/pt-PT.inc.php index 775ba6e0..4ca6171b 100644 --- a/lang/pt-PT.inc.php +++ b/lang/pt-PT.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/ru.inc.php b/lang/ru.inc.php index cb5f744a..2dfdf34c 100644 --- a/lang/ru.inc.php +++ b/lang/ru.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/sk.inc.php b/lang/sk.inc.php index f595d0e7..64df4d39 100644 --- a/lang/sk.inc.php +++ b/lang/sk.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/sl.inc.php b/lang/sl.inc.php index 28465340..2645ac9d 100644 --- a/lang/sl.inc.php +++ b/lang/sl.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/sv.inc.php b/lang/sv.inc.php index fb143b2f..d0c8371c 100644 --- a/lang/sv.inc.php +++ b/lang/sv.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/tr.inc.php b/lang/tr.inc.php index ee24bffc..8cf67392 100644 --- a/lang/tr.inc.php +++ b/lang/tr.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/uk.inc.php b/lang/uk.inc.php index b5f5f3eb..2b5ec154 100644 --- a/lang/uk.inc.php +++ b/lang/uk.inc.php @@ -134,3 +134,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/zh-CN.inc.php b/lang/zh-CN.inc.php index b906ffa3..d3d38edb 100644 --- a/lang/zh-CN.inc.php +++ b/lang/zh-CN.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lang/zh-TW.inc.php b/lang/zh-TW.inc.php index 090ef305..c62987e6 100644 --- a/lang/zh-TW.inc.php +++ b/lang/zh-TW.inc.php @@ -133,3 +133,4 @@ $messages['policypwned'] = "Your new password may not be published on any previous public password leak from any site"; $messages['specialatends'] = "Your new password has its only special character at the beginning or end"; $messages['policyspecialatends'] = "Your new password may not have its only special character at the beginning or end"; +$messages['overriding_policy_by_length'] = "If the password is shorter than %d characters, the following rules apply:"; diff --git a/lib/functions.inc.php b/lib/functions.inc.php index a3eb0bbf..08438d9b 100644 --- a/lib/functions.inc.php +++ b/lib/functions.inc.php @@ -180,6 +180,17 @@ function show_policy( $messages, $pwd_policy_config, $result ) { # Display bloc echo "
\n"; echo "

".$messages["policy"]."

\n"; + output_policy_list($messages, $pwd_policy_config); + usort($pwd_override_by_length, function($a, $b) { return $b['valid_if_shorter_than'] - $a['valid_if_shorter_than']; }); + foreach($pwd_override_by_length as $override) { + echo "

".sprintf($messages["overriding_policy_by_length"], $override['valid_if_shorter_than']) . "

\n"; + output_policy_list($messages, $override['rules']); + } + echo "
\n"; +} + +function output_policy_list($messages, $policy) { + extract($policy); echo "\n"; - echo "\n"; } # Check password strength @@ -205,6 +215,29 @@ function check_password_strength( $password, $oldpassword, $pwd_policy_config, $ $result = ""; $length = strlen(utf8_decode($password)); + + usort($pwd_override_by_length, function($a, $b) { return $a['valid_if_shorter_than'] - $b['valid_if_shorter_than']; }); + $checked = false; + foreach($pwd_override_by_length as $override) { + if($length < $override['valid_if_shorter_than']) { + $policy = array_merge($pwd_policy_config, $override['rules']); + $result = match_policy($password, $oldpassword, $policy, $login, $length); + $checked = true; + break; + } + } + if(!$checked) { + $result = match_policy($password, $oldpassword, $pwd_policy_config, $login, $length); + } + + return $result; +} + +function match_policy($password, $oldpassword, $pwd_policy_config, $login, $length) { + extract( $pwd_policy_config ); + + $result = ""; + preg_match_all("/[a-z]/", $password, $lower_res); $lower = count( $lower_res[0] ); preg_match_all("/[A-Z]/", $password, $upper_res); diff --git a/tests/CheckPasswordTest.php b/tests/CheckPasswordTest.php index 022f9315..d4e32f92 100644 --- a/tests/CheckPasswordTest.php +++ b/tests/CheckPasswordTest.php @@ -29,6 +29,7 @@ public function testCheckPasswordStrength() "pwd_complexity" => 0, "use_pwnedpasswords" => false, "pwd_no_special_at_ends" => false, + "pwd_override_by_length" => array(), ); $login = "coudot"; @@ -59,11 +60,38 @@ public function testCheckPasswordStrength() "pwd_complexity" => 3, "use_pwnedpasswords" => false, "pwd_no_special_at_ends" => true, + "pwd_override_by_length" => array( + array( + 'valid_if_shorter_than' => 5, + 'rules' => array( + 'pwd_min_length' => 4, + 'pwd_min_digit' => 1, + 'pwd_min_upper' => 1, + 'pwd_min_lower' => 1, + 'pwd_min_special' => 1, + 'pwd_complexity' => 0 + ) + ), + array( + 'valid_if_shorter_than' => 4, + 'rules' => array( + 'pwd_min_length' => 3, + 'pwd_min_lower' => 1, + 'pwd_min_special' => 2, + 'pwd_complexity' => 0 + ) + ) + ), ); $this->assertEquals("notcomplex", check_password_strength( "simple", $oldpassword, $pwd_policy_config, $login ) ); $this->assertEquals("specialatends", check_password_strength( "!simple", $oldpassword, $pwd_policy_config, $login ) ); $this->assertEquals("specialatends", check_password_strength( "simple?", $oldpassword, $pwd_policy_config, $login ) ); + $this->assertEquals("minspecial", check_password_strength( "xyZ1", $oldpassword, $pwd_policy_config, $login ) ); + $this->assertEquals("minupper", check_password_strength( "xy%1", $oldpassword, $pwd_policy_config, $login ) ); + $this->assertEquals("", check_password_strength( "xY%1", $oldpassword, $pwd_policy_config, $login ) ); + $this->assertEquals("minspecial", check_password_strength( "x%1", $oldpassword, $pwd_policy_config, $login ) ); + $this->assertEquals("", check_password_strength( "x%$", $oldpassword, $pwd_policy_config, $login ) ); $this->assertEquals("", check_password_strength( "C0mplex", $oldpassword, $pwd_policy_config, $login ) ); $this->assertEquals("", check_password_strength( "C0!mplex", $oldpassword, $pwd_policy_config, $login ) ); $this->assertEquals("", check_password_strength( "%C0!mplex", $oldpassword, $pwd_policy_config, $login ) ); @@ -99,6 +127,7 @@ public function testCheckPasswordStrengthPwnedPasswords() "pwd_complexity" => 0, "use_pwnedpasswords" => true, "pwd_no_special_at_ends" => false, + "pwd_override_by_length" => array(), ); $this->assertEquals("pwned", check_password_strength( "!1Password", $oldpassword, $pwd_policy_config, $login ) );