$temp->add(new admin_setting_configtext('minpasswordlower', get_string('minpasswordlower', 'admin'), get_string('configminpasswordlower', 'admin'), 1, PARAM_INT));
$temp->add(new admin_setting_configtext('minpasswordupper', get_string('minpasswordupper', 'admin'), get_string('configminpasswordupper', 'admin'), 1, PARAM_INT));
$temp->add(new admin_setting_configtext('minpasswordnonalphanum', get_string('minpasswordnonalphanum', 'admin'), get_string('configminpasswordnonalphanum', 'admin'), 1, PARAM_INT));
+ $temp->add(new admin_setting_configtext('maxconsecutiveidentchars', get_string('maxconsecutiveidentchars', 'admin'), get_string('configmaxconsecutiveidentchars', 'admin'), 3, PARAM_INT));
$temp->add(new admin_setting_configcheckbox('disableuserimages', get_string('disableuserimages', 'admin'), get_string('configdisableuserimages', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('emailchangeconfirmation', get_string('emailchangeconfirmation', 'admin'), get_string('configemailchangeconfirmation', 'admin'), 1));
$ADMIN->add('security', $temp);
$string['configmemcachedhosts'] = 'For memcached. Comma-separated list of hosts that are running the memcached daemon. Use IP addresses to avoid DNS latency. memcached does not behave well if you add/remove hosts on a running setup.';
$string['configmemcachedpconn'] = 'For memcached. Use persistent connections. Use carefully -- it can make Apache/PHP crash after a restart of the memcached daemon.';
$string['configmessaging'] = 'Should the messaging system between site users be enabled?';
+$string['configmaxconsecutiveidentchars'] = 'Passwords must not have more than this number of consecutive identical characters. Use 0 to disable this check.';
$string['configminpassworddigits'] = 'Passwords must have at least these many digits.';
$string['configminpasswordlength'] = 'Passwords must be at least these many characters long.';
$string['configminpasswordlower'] = 'Passwords must have at least these many lower case letters.';
$string['memcachedhosts'] = 'memcached hosts';
$string['memcachedpconn'] = 'memcached use persistent connections';
$string['messaging'] = 'Enable messaging system';
+$string['maxconsecutiveidentchars'] = 'Consecutive identical characters';
$string['minpasswordlength'] = 'Password Length';
$string['minpassworddigits'] = 'Digits';
$string['minpasswordlower'] = 'Lowercase letters';
$string['chooseauthmethod'] = 'Choose an authentication method';
$string['createpasswordifneeded'] = 'Create password if needed';
$string['errorpasswordupdate'] = 'Error updating password, password not changed';
+$string['errormaxconsecutiveidentchars'] = 'Passwords must have at most $a consecutive identical characters.';
$string['errorminpasswordlength'] = 'Passwords must be at least $a characters long.';
$string['errorminpassworddigits'] = 'Passwords must have at least $a digit(s).';
$string['errorminpasswordlower'] = 'Passwords must have at least $a lower case letter(s).';
if (preg_match_all('/[^[:upper:][:lower:][:digit:]]/u', $password, $matches) < $CFG->minpasswordnonalphanum) {
$errmsg .= '<div>'. get_string('errorminpasswordnonalphanum', 'auth', $CFG->minpasswordnonalphanum) .'</div>';
}
+ if (!check_consecutive_identical_characters($password, $CFG->maxconsecutiveidentchars)) {
+ $errmsg .= '<div>'. get_string('errormaxconsecutiveidentchars', 'auth', $CFG->maxconsecutiveidentchars) .'</div>';
+ }
if ($errmsg == '') {
return true;
return $CFG->siteidentifier;
}
+/**
+ * Check whether the given password has no more than the specified
+ * number of consecutive identical characters.
+ *
+ * @param string $password password to be checked agains the password policy
+ * @param integer $maxchars maximum number of consecutive identical characters
+ */
+function check_consecutive_identical_characters($password, $maxchars) {
+
+ if ($maxchars < 1) {
+ return true; // 0 is to disable this check
+ }
+ if (strlen($password) <= $maxchars) {
+ return true; // too short to fail this test
+ }
+
+ $previouschar = '';
+ $consecutivecount = 1;
+ foreach (str_split($password) as $char) {
+ if ($char != $previouschar) {
+ $consecutivecount = 1;
+ }
+ else {
+ $consecutivecount++;
+ if ($consecutivecount > $maxchars) {
+ return false; // check failed already
+ }
+ }
+
+ $previouschar = $char;
+ }
+
+ return true;
+}
+
// vim:autoindent:expandtab:shiftwidth=4:tabstop=4:tw=140:
?>