summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorTimotheus Pokorra <tp@tbits.net>2015-04-17 16:43:00 +0200
committerTimotheus Pokorra <tp@tbits.net>2015-04-17 16:43:00 +0200
commitda251955a799248e7e8b465a1faabf9ea5f25eac (patch)
tree0659d17870c2fe769d84f62d65a7b9b95c61b6a1 /lib
parent358428eb8ec573e79c610b3f7aa96cb2365f35f5 (diff)
downloadwebadmin-da251955a799248e7e8b465a1faabf9ea5f25eac.tar.gz
Password policy improvements.
calculate the special characters automatically if they are not defined in the password policy config value. prepare to support special characters beyond 7-bit, but not using them to generate a password because the characters might be not known to the user (eg. umlaut). if 389ds has been configured for 8-bit characters for the password, you can allow such characters in the password policy now.
Diffstat (limited to 'lib')
-rw-r--r--lib/password_policy.php84
1 files changed, 73 insertions, 11 deletions
diff --git a/lib/password_policy.php b/lib/password_policy.php
index 4375623..9482e76 100644
--- a/lib/password_policy.php
+++ b/lib/password_policy.php
@@ -28,13 +28,64 @@ class password_policy {
{
// TODO: get the password policy from LDAP instead?
$conf = Conf::get_instance();
- return $conf->get('kolab', 'password_policy', Conf::AUTO);
+
+ $passwordpolicy = $conf->get('kolab', 'password_policy', Conf::AUTO);
+
+ if (!isset($passwordpolicy['specialChars'])) {
+ $passwordpolicy['specialChars'] = self::get_special_characters($passwordpolicy);
+ }
+
+ return $passwordpolicy;
}
/**
- * validate if password matches the password policy
- * @throws an exception if password is not secure enough
- */
+ * calculate which special characters will work in the current setup
+ *
+ * @return string with the allowed special characters
+ */
+ private static function get_special_characters($passwordpolicy)
+ {
+ $special_chars = '';
+
+ // only use the characters from the 127 bit range. otherwise the user gets characters that he cannot type or does not know, eg Umlaut
+ $maxcharacter = 127;
+
+ for ($c = 33; $c < $maxcharacter; $c++) {
+ if ($c >= ord('0') && $c <= ord('9')) {
+ continue;
+ }
+
+ if ($c >= ord('a') && $c <= ord('z')) {
+ continue;
+ }
+
+ if ($c >= ord('A') && $c <= ord('Z')) {
+ continue;
+ }
+
+ if ($c == 127 || $c == 255) {
+ continue;
+ }
+
+ # do not use some characters that are not well-known to users
+ if (chr($c) == '`' || chr($c) == '|') {
+ continue;
+ }
+
+ if ($c > 127) {
+ $special_chars .= mb_convert_encoding('&#' . intval($c) . ';', 'UTF-8', 'HTML-ENTITIES');
+ } else {
+ $special_chars .= chr($c);
+ }
+ }
+
+ return $special_chars;
+ }
+
+ /**
+ * validate if password matches the password policy
+ * @throws an exception if password is not secure enough
+ */
public static function validate_password($password)
{
$passwordpolicy = self::get_password_policy();
@@ -81,9 +132,12 @@ class password_policy {
kolab_api_controller::translate("user.password.morespecial", $passwordpolicy['minSpecial'], $passwordpolicy['specialChars']).'<br/>';
}
- if ($countUpperCaseChars + $countLowerCaseChars + $countDigits + $countSpecialChars < strlen($password)) {
- $errors .= kolab_api_controller::translate("error").": ".
- kolab_api_controller::translate("user.password.notallowed").'<br/>';
+ # by default there is a 7-bit password enforcement plugin enabled on 389ds
+ if ($passwordpolicy['7bitPasswordEnforcement'] == '0') {
+ // do not test for characters beyond 127
+ } else if ($countUpperCaseChars + $countLowerCaseChars + $countDigits + $countSpecialChars < strlen($password)) {
+ $errors .= kolab_api_controller::translate("error").": ".
+ kolab_api_controller::translate("user.password.notallowed").'<br/>';
}
if ($errors != "") {
@@ -123,20 +177,28 @@ class password_policy {
if ($passwordpolicy['minSpecial'] > 0) {
# using rand instead of /dev/urandom to avoid problems with special characters on bash command line
for ($countSpecialChar = 0; $countSpecialChar < $passwordpolicy['minSpecial']; $countSpecialChar++) {
- $password .= $passwordpolicy['specialChars'][(rand() % strlen($passwordpolicy['specialChars']))];
+ $password .= mb_substr($passwordpolicy['specialChars'], rand() % mb_strlen($passwordpolicy['specialChars']), 1);
}
}
$numberLowerCase = $passwordpolicy['minLower'];
- if ($passwordpolicy['minLength'] > strlen($password) + $passwordpolicy['minLower']) {
- $numberLowerCase = $passwordpolicy['minLength'] - strlen($password);
+ if ($passwordpolicy['minLength'] > mb_strlen($password) + $passwordpolicy['minLower']) {
+ $numberLowerCase = $passwordpolicy['minLength'] - mb_strlen($password);
}
unset($pwd_snippet);
exec("head -c 200 /dev/urandom | tr -dc a-z | head -c".$numberLowerCase, $pwd_snippet);
$password .= $pwd_snippet[0];
- return str_shuffle($password);
+ $len = mb_strlen($password);
+ $pwd_chars = array();
+ while($len-- > 0) {
+ $pwd_chars[] = mb_substr($password, $len, 1);
+ }
+
+ shuffle($pwd_chars);
+
+ return join('', $pwd_chars);
}
}