Merge branch 'master' of github.com:roundcube/roundcubemail

pull/6495/head
Aleksander Machniak 6 years ago
commit c93d11b473

@ -18,6 +18,8 @@ CHANGELOG Roundcube Webmail
- Elastic: Improved UX of search dialogs (#6416) - Elastic: Improved UX of search dialogs (#6416)
- Elastic: Fix unwanted thread expanding when selecting a collapsed thread in non-mobile mode (#6445) - Elastic: Fix unwanted thread expanding when selecting a collapsed thread in non-mobile mode (#6445)
- Log errors caused by low pcre.backtrack_limit when sending a mail message (#6433) - Log errors caused by low pcre.backtrack_limit when sending a mail message (#6433)
- Fix incorrect IMAP SASL GSSAPI negotiation (#6308)
- Fix so unicode in local part of the email address is also supported in recipient inputs (#6490)
- Fix bug where autocomplete list could be displayed out of screen (#6469) - Fix bug where autocomplete list could be displayed out of screen (#6469)
- Fix style/navigation on error page depending on authentication state (#6362) - Fix style/navigation on error page depending on authentication state (#6362)
- Fix so invalid smtp_helo_host is never used, fallback to localhost (#6408) - Fix so invalid smtp_helo_host is never used, fallback to localhost (#6408)

@ -402,7 +402,7 @@ triggerEvent: function(evt, e)
// check if input is a valid email address // check if input is a valid email address
// By Cal Henderson <cal@iamcal.com> // By Cal Henderson <cal@iamcal.com>
// http://code.iamcal.com/php/rfc822/ // http://code.iamcal.com/php/rfc822/
function rcube_check_email(input, inline, count) function rcube_check_email(input, inline, count, strict)
{ {
if (!input) if (!input)
return count ? 0 : false; return count ? 0 : false;
@ -438,7 +438,7 @@ function rcube_check_email(input, inline, count)
'\\u05d1\\u05f2\\u05b7\\u05e9\\u05e4\\u05bc\\u05d9\\u05dc\\x2e\\u05d8\\u05e2\\u05e1\\u05d8' '\\u05d1\\u05f2\\u05b7\\u05e9\\u05e4\\u05bc\\u05d9\\u05dc\\x2e\\u05d8\\u05e2\\u05e1\\u05d8'
], ],
icann_addr = 'mailtest\\x40('+icann_domains.join('|')+')', icann_addr = 'mailtest\\x40('+icann_domains.join('|')+')',
word = '('+atom+'|'+quoted_string+')', word = strict ? '('+atom+'|'+quoted_string+')' : '[^\\u0000-\\u0020\\u002e\\u00a0\\u0040\\u007f\\u2028\\u2029]+',
delim = '[,;\\s\\n]', delim = '[,;\\s\\n]',
local_part = word+'(\\x2e'+word+')*', local_part = word+'(\\x2e'+word+')*',
addr_spec = '(('+local_part+'\\x40'+domain+')|('+icann_addr+'))', addr_spec = '(('+local_part+'\\x40'+domain+')|('+icann_addr+'))',

@ -405,6 +405,8 @@ class rcube_imap_generic
{ {
$this->errornum = $code; $this->errornum = $code;
$this->error = $msg; $this->error = $msg;
return $code;
} }
/** /**
@ -522,9 +524,8 @@ class rcube_imap_generic
{ {
if ($type == 'CRAM-MD5' || $type == 'DIGEST-MD5') { if ($type == 'CRAM-MD5' || $type == 'DIGEST-MD5') {
if ($type == 'DIGEST-MD5' && !class_exists('Auth_SASL')) { if ($type == 'DIGEST-MD5' && !class_exists('Auth_SASL')) {
$this->setError(self::ERROR_BYE, return $this->setError(self::ERROR_BYE,
"The Auth_SASL package is required for DIGEST-MD5 authentication"); "The Auth_SASL package is required for DIGEST-MD5 authentication");
return self::ERROR_BAD;
} }
$this->putLine($this->nextTag() . " AUTHENTICATE $type"); $this->putLine($this->nextTag() . " AUTHENTICATE $type");
@ -596,9 +597,8 @@ class rcube_imap_generic
$challenge = substr($line, 2); $challenge = substr($line, 2);
$challenge = base64_decode($challenge); $challenge = base64_decode($challenge);
if (strpos($challenge, 'rspauth=') === false) { if (strpos($challenge, 'rspauth=') === false) {
$this->setError(self::ERROR_BAD, return $this->setError(self::ERROR_BAD,
"Unexpected response from server to DIGEST-MD5 response"); "Unexpected response from server to DIGEST-MD5 response");
return self::ERROR_BAD;
} }
$this->putLine(''); $this->putLine('');
@ -609,21 +609,18 @@ class rcube_imap_generic
} }
else if ($type == 'GSSAPI') { else if ($type == 'GSSAPI') {
if (!extension_loaded('krb5')) { if (!extension_loaded('krb5')) {
$this->setError(self::ERROR_BYE, return $this->setError(self::ERROR_BYE,
"The krb5 extension is required for GSSAPI authentication"); "The krb5 extension is required for GSSAPI authentication");
return self::ERROR_BAD;
} }
if (empty($this->prefs['gssapi_cn'])) { if (empty($this->prefs['gssapi_cn'])) {
$this->setError(self::ERROR_BYE, return $this->setError(self::ERROR_BYE,
"The gssapi_cn parameter is required for GSSAPI authentication"); "The gssapi_cn parameter is required for GSSAPI authentication");
return self::ERROR_BAD;
} }
if (empty($this->prefs['gssapi_context'])) { if (empty($this->prefs['gssapi_context'])) {
$this->setError(self::ERROR_BYE, return $this->setError(self::ERROR_BYE,
"The gssapi_context parameter is required for GSSAPI authentication"); "The gssapi_context parameter is required for GSSAPI authentication");
return self::ERROR_BAD;
} }
putenv('KRB5CCNAME=' . $this->prefs['gssapi_cn']); putenv('KRB5CCNAME=' . $this->prefs['gssapi_cn']);
@ -640,8 +637,7 @@ class rcube_imap_generic
} }
catch (Exception $e) { catch (Exception $e) {
trigger_error($e->getMessage(), E_USER_WARNING); trigger_error($e->getMessage(), E_USER_WARNING);
$this->setError(self::ERROR_BYE, "GSSAPI authentication failed"); return $this->setError(self::ERROR_BYE, "GSSAPI authentication failed");
return self::ERROR_BAD;
} }
$this->putLine($this->nextTag() . " AUTHENTICATE GSSAPI " . $token); $this->putLine($this->nextTag() . " AUTHENTICATE GSSAPI " . $token);
@ -652,17 +648,37 @@ class rcube_imap_generic
} }
try { try {
$challenge = base64_decode(substr($line, 2)); $itoken = base64_decode(substr($line, 2));
$gssapicontext->unwrap($challenge, $challenge);
$gssapicontext->wrap($challenge, $challenge, true); if (!$gssapicontext->unwrap($itoken, $itoken)) {
throw new Exception("GSSAPI SASL input token unwrap failed");
}
if (strlen($itoken) < 4) {
throw new Exception("GSSAPI SASL input token invalid");
}
// Integrity/encryption layers are not supported. The first bit
// indicates that the server supports "no security layers".
// 0x00 should not occur, but support broken implementations.
$server_layers = ord($itoken[0]);
if ($server_layers && ($server_layers & 0x1) != 0x1) {
throw new Exception("Server requires GSSAPI SASL integrity/encryption");
}
// Construct output token. 0x01 in the first octet = SASL layer "none",
// zero in the following three octets = no data follows.
// See https://github.com/cyrusimap/cyrus-sasl/blob/e41cfb986c1b1935770de554872247453fdbb079/plugins/gssapi.c#L1284
if (!$gssapicontext->wrap(pack("CCCC", 0x1, 0, 0, 0), $otoken, true)) {
throw new Exception("GSSAPI SASL output token wrap failed");
}
} }
catch (Exception $e) { catch (Exception $e) {
trigger_error($e->getMessage(), E_USER_WARNING); trigger_error($e->getMessage(), E_USER_WARNING);
$this->setError(self::ERROR_BYE, "GSSAPI authentication failed"); return $this->setError(self::ERROR_BYE, "GSSAPI authentication failed");
return self::ERROR_BAD;
} }
$this->putLine(base64_encode($challenge)); $this->putLine(base64_encode($otoken));
$line = $this->readReply(); $line = $this->readReply();
$result = $this->parseResult($line); $result = $this->parseResult($line);
@ -726,13 +742,11 @@ class rcube_imap_generic
if ($line && preg_match('/\[CAPABILITY ([^]]+)\]/i', $line, $matches)) { if ($line && preg_match('/\[CAPABILITY ([^]]+)\]/i', $line, $matches)) {
$this->parseCapability($matches[1], true); $this->parseCapability($matches[1], true);
} }
return $this->fp; return $this->fp;
} }
else {
$this->setError($result, "AUTHENTICATE $type: $line");
}
return $result; return $this->setError($result, "AUTHENTICATE $type: $line");
} }
/** /**
@ -747,8 +761,7 @@ class rcube_imap_generic
{ {
// Prevent from sending credentials in plain text when connection is not secure // Prevent from sending credentials in plain text when connection is not secure
if ($this->getCapability('LOGINDISABLED')) { if ($this->getCapability('LOGINDISABLED')) {
$this->setError(self::ERROR_BAD, "Login disabled by IMAP server"); return $this->setError(self::ERROR_BAD, "Login disabled by IMAP server");
return false;
} }
list($code, $response) = $this->execute('LOGIN', array( list($code, $response) = $this->execute('LOGIN', array(

Loading…
Cancel
Save