Support AUTHENTICATE LOGIN for IMAP connections (#5563)

Add imap_auth_type=IMAP to force use of LOGIN instead of AUTHENTICATE LOGIN.
In imap_auth_type=CHECK mode prefer LOGIN over AUTHENTICATE LOGIN (for performance reasons).
pull/5480/merge
Aleksander Machniak 7 years ago
parent cfc8b60fde
commit f7809af6e4

@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
- Support AUTHENTICATE LOGIN for IMAP connections (#5563)
- Support LDAP GSSAPI authentication (#5703)
- Allow contacts without an email address (#5079)
- Localized timezone selector (#4983)

@ -137,8 +137,9 @@ $config['default_host'] = 'localhost';
// TCP port used for IMAP connections
$config['default_port'] = 143;
// IMAP AUTH type (DIGEST-MD5, CRAM-MD5, LOGIN, PLAIN or null to use
// best server supported one)
// IMAP authentication method (DIGEST-MD5, CRAM-MD5, LOGIN, PLAIN or null).
// Use 'IMAP' to authenticate with IMAP LOGIN command.
// By default the most secure method (from supported) will be selected.
$config['imap_auth_type'] = null;
// IMAP socket context options

@ -667,7 +667,7 @@ class rcube_imap_generic
$line = $this->readReply();
$result = $this->parseResult($line);
}
else { // PLAIN
else if ($type == 'PLAIN') {
// proxy authorization
if (!empty($this->prefs['auth_cid'])) {
$authc = $this->prefs['auth_cid'];
@ -699,8 +699,29 @@ class rcube_imap_generic
$result = $this->parseResult($line);
}
}
else if ($type == 'LOGIN') {
$this->putLine($this->nextTag() . " AUTHENTICATE LOGIN");
if ($result == self::ERROR_OK) {
$line = trim($this->readReply());
if ($line[0] != '+') {
return $this->parseResult($line);
}
$this->putLine(base64_encode($user), true, true);
$line = trim($this->readReply());
if ($line[0] != '+') {
return $this->parseResult($line);
}
// send result, get reply and process it
$this->putLine(base64_encode($pass), true, true);
$line = $this->readReply();
$result = $this->parseResult($line);
}
if ($result === self::ERROR_OK) {
// optional CAPABILITY response
if ($line && preg_match('/\[CAPABILITY ([^]]+)\]/i', $line, $matches)) {
$this->parseCapability($matches[1], true);
@ -724,6 +745,12 @@ class rcube_imap_generic
*/
protected function login($user, $password)
{
// Prevent from sending credentials in plain text when connection is not secure
if ($this->getCapability('LOGINDISABLED')) {
$this->setError(self::ERROR_BAD, "Login disabled by IMAP server");
return false;
}
list($code, $response) = $this->execute('LOGIN', array(
$this->escape($user), $this->escape($password)), self::COMMAND_CAPABILITY | self::COMMAND_ANONYMIZED);
@ -850,22 +877,11 @@ class rcube_imap_generic
$result = null;
// check for supported auth methods
if ($auth_method == 'CHECK') {
if (!$auth_method || $auth_method == 'CHECK') {
if ($auth_caps = $this->getCapability('AUTH')) {
$auth_methods = $auth_caps;
}
// RFC 2595 (LOGINDISABLED) LOGIN disabled when connection is not secure
$login_disabled = $this->getCapability('LOGINDISABLED');
if (($key = array_search('LOGIN', $auth_methods)) !== false) {
if ($login_disabled) {
unset($auth_methods[$key]);
}
}
else if (!$login_disabled) {
$auth_methods[] = 'LOGIN';
}
// Use best (for security) supported authentication method
$all_methods = array('DIGEST-MD5', 'CRAM-MD5', 'CRAM_MD5', 'PLAIN', 'LOGIN');
@ -878,17 +894,10 @@ class rcube_imap_generic
break;
}
}
}
else {
// Prevent from sending credentials in plain text when connection is not secure
if ($auth_method == 'LOGIN' && $this->getCapability('LOGINDISABLED')) {
$this->setError(self::ERROR_BAD, "Login disabled by IMAP server");
$this->closeConnection();
return false;
}
// replace AUTH with CRAM-MD5 for backward compat.
if ($auth_method == 'AUTH') {
$auth_method = 'CRAM-MD5';
// Prefer LOGIN over AUTHENTICATE LOGIN for performance reasons
if ($auth_method == 'LOGIN' && !$this->getCapability('LOGINDISABLED')) {
$auth_method = 'IMAP';
}
}
@ -901,13 +910,16 @@ class rcube_imap_generic
$auth_method = 'CRAM-MD5';
case 'CRAM-MD5':
case 'DIGEST-MD5':
case 'PLAIN':
case 'GSSAPI':
case 'PLAIN':
case 'LOGIN':
$result = $this->authenticate($user, $password, $auth_method);
break;
case 'LOGIN':
case 'IMAP':
$result = $this->login($user, $password);
break;
default:
$this->setError(self::ERROR_BAD, "Configuration error. Unknown auth method: $auth_method");
}

Loading…
Cancel
Save