diff --git a/CHANGELOG b/CHANGELOG index d9c978df7..171e3563d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ CHANGELOG Roundcube Webmail - Plugin API: Add 'pass' argument in 'authenticate' hook (#1487134) - Fix attachments of type message/rfc822 are not listed on attachments list +- Add 'login_lc' config option for case-insensitive authentication (#1487113) RELEASE 0.5-BETA ---------------- diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist index 2b18da333..785a20ae8 100644 --- a/config/main.inc.php.dist +++ b/config/main.inc.php.dist @@ -183,6 +183,10 @@ $rcmail_config['force_https'] = false; // Allow browser-autocompletion on login form $rcmail_config['login_autocomplete'] = false; +// If users authentication is not case sensitive this must be enabled. +// You can also use it to force conversion of logins to lower case. +$rcmail_config['login_lc'] = false; + // automatically create a new Roundcube user when log-in the first time. // a new user will be created once the IMAP login succeeds. // set to false if only registered users can use this service diff --git a/program/include/rcmail.php b/program/include/rcmail.php index d376e98bf..0eecd8ddb 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -678,10 +678,16 @@ class rcmail $username .= '@'.rcube_parse_host($config['username_domain']); } + // Convert username to lowercase. If IMAP backend + // is case-insensitive we need to store always the same username (#1487113) + if ($config['login_lc']) { + $username = mb_strtolower($username); + } + // try to resolve email address from virtuser table - if (strpos($username, '@')) - if ($virtuser = rcube_user::email2user($username)) - $username = $virtuser; + if (strpos($username, '@') && ($virtuser = rcube_user::email2user($username))) { + $username = $virtuser; + } // Here we need IDNA ASCII // Only rcube_contacts class is using domain names in Unicode @@ -704,8 +710,14 @@ class rcmail if (!($imap_login = $this->imap->connect($host, $username, $pass, $imap_port, $imap_ssl))) { // try with lowercase $username_lc = mb_strtolower($username); - if ($username_lc != $username && ($imap_login = $this->imap->connect($host, $username_lc, $pass, $imap_port, $imap_ssl))) - $username = $username_lc; + if ($username_lc != $username) { + // try to find user record again -> overwrite username + if (!$user && ($user = rcube_user::query($username_lc, $host))) + $username_lc = $user->data['username']; + + if ($imap_login = $this->imap->connect($host, $username_lc, $pass, $imap_port, $imap_ssl)) + $username = $username_lc; + } } // exit if IMAP login failed diff --git a/program/include/rcube_user.php b/program/include/rcube_user.php index e4506cff7..ee6db77cc 100644 --- a/program/include/rcube_user.php +++ b/program/include/rcube_user.php @@ -358,13 +358,17 @@ class rcube_user { $dbh = rcmail::get_instance()->get_dbh(); + // use BINARY (case-sensitive) comparison on MySQL, other engines are case-sensitive + $prefix = preg_match('/^mysql/', $dbh->db_provider) ? 'BINARY ' : ''; + // query for matching user name $query = "SELECT * FROM ".get_table_name('users')." WHERE mail_host = ? AND %s = ?"; - $sql_result = $dbh->query(sprintf($query, 'username'), $host, $user); + + $sql_result = $dbh->query(sprintf($query, $prefix.'username'), $host, $user); // query for matching alias if (!($sql_arr = $dbh->fetch_assoc($sql_result))) { - $sql_result = $dbh->query(sprintf($query, 'alias'), $host, $user); + $sql_result = $dbh->query(sprintf($query, $prefix.'alias'), $host, $user); $sql_arr = $dbh->fetch_assoc($sql_result); }