Skip to content

Commit

Permalink
Override policy rules if password shorter than a certain value
Browse files Browse the repository at this point in the history
One may define weak policy rules for long passwords (encouraging
passphrases) and override these weak rules by harder ones if the
password is shorter.
  • Loading branch information
myrho committed May 15, 2019
1 parent 31f60f3 commit 398c9a3
Show file tree
Hide file tree
Showing 29 changed files with 106 additions and 2 deletions.
15 changes: 15 additions & 0 deletions conf/config.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion index.php
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand All @@ -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"; }
Expand Down
1 change: 1 addition & 0 deletions lang/ca.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/cn.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/cs.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/de.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/ee.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/el.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/en.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/es.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/fr.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/hu.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/it.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/ja.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/nb-NO.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/nl.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/pl.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/pt-BR.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/pt-PT.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/ru.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/sk.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/sl.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/sv.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/tr.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/uk.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/zh-CN.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
1 change: 1 addition & 0 deletions lang/zh-TW.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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:";
35 changes: 34 additions & 1 deletion lib/functions.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,17 @@ function show_policy( $messages, $pwd_policy_config, $result ) {
# Display bloc
echo "<div class=\"help alert alert-warning\">\n";
echo "<p>".$messages["policy"]."</p>\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 "<p>".sprintf($messages["overriding_policy_by_length"], $override['valid_if_shorter_than']) . "</p>\n";
output_policy_list($messages, $override['rules']);
}
echo "</div>\n";
}

function output_policy_list($messages, $policy) {
extract($policy);
echo "<ul>\n";
if ( $pwd_min_length ) { echo "<li>".$messages["policyminlength"] ." $pwd_min_length</li>\n"; }
if ( $pwd_max_length ) { echo "<li>".$messages["policymaxlength"] ." $pwd_max_length</li>\n"; }
Expand All @@ -194,7 +205,6 @@ function show_policy( $messages, $pwd_policy_config, $result ) {
if ( $use_pwnedpasswords ) { echo "<li>".$messages["policypwned"] ."\n"; }
if ( $pwd_no_special_at_ends ) { echo "<li>".$messages["policyspecialatends"] ."</li>\n"; }
echo "</ul>\n";
echo "</div>\n";
}

# Check password strength
Expand All @@ -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);
Expand Down
29 changes: 29 additions & 0 deletions tests/CheckPasswordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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 ) );
Expand Down Expand Up @@ -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 ) );
Expand Down

0 comments on commit 398c9a3

Please sign in to comment.