- Add SASL-IR support (RFC 4959)

- Add LOGINDISABLED support (RFC 2595)
- Add support for AUTH=PLAIN authentication to IMAP
release-0.6
alecpl 14 years ago
parent cb7d32ebdd
commit 7bf255bfe1

@ -21,8 +21,8 @@ CHANGELOG Roundcube Webmail
- Improve tabs to fixed width and add tabs in identities info (#1486974)
- Add unique index on users.username+users.mail_host
- Make htmleditor option more consistent and add option to use HTML on reply to HTML message (#1485840)
- Use empty envelope sender address for message disposition notifications (RFC2298.3)
- Support SMTP Delivery Status Notifications - RFC3461 (#1486142)
- Use empty envelope sender address for message disposition notifications (RFC 2298.3)
- Support SMTP Delivery Status Notifications - RFC 3461 (#1486142)
- Use css sprite image for messages list
- Add (different) attachment icon for messages of type multipart/report (#1486165)
- Prevent from inserting empty link when composing HTML message (#1486944)
@ -31,16 +31,19 @@ CHANGELOG Roundcube Webmail
- Improve displaying of UI messages (#1486977)
- Fix double e-mail filed in identity form (#1487054)
- Display IMAP errors for LIST/THREAD/SEARCH commands (#1486905)
- Add LITERAL+ (IMAP4 non-synchronizing literals) support (RFC2088)
- Add LITERAL+ (IMAP4 non-synchronizing literals) support (RFC 2088)
- Add separate column for message status icon (#1486665)
- Add ACL extension support into IMAP classes (RFC4314)
- Add ACL extension support into IMAP classes (RFC 4314)
- Add ANNOTATEMORE extension support into IMAP classes (draft-daboo-imap-annotatemore)
- Add METADATA extension support into IMAP classes (RFC5464)
- Add METADATA extension support into IMAP classes (RFC 5464)
- Fix decoding of e-mail address strings in message headers (#1487068)
- Fix handling of attachments when Content-Disposition is not inline nor attachment (#1487051)
- Improve performance of unseen messages counting (#1487058)
- Improve performance of messages counting using ESEARCH extension (RFC4731)
- Add LIST-STATUS support in rcube_imap_generic class (RFC5819)
- Add LIST-STATUS support in rcube_imap_generic class (RFC 5819)
- Add SASL-IR support in IMAP (RFC 4959)
- Add LOGINDISABLED support (RFC 2595)
- Add support for AUTH=PLAIN in IMAP authentication
RELEASE 0.4.2
-------------

@ -70,8 +70,8 @@ $rcmail_config['default_host'] = '';
// TCP port used for IMAP connections
$rcmail_config['default_port'] = 143;
// IMAP auth type. Can be "auth" (CRAM-MD5), "plain" (PLAIN) or "check" to auto detect.
// Optional, defaults to "check"
// IMAP auth type. Can be "auth" (CRAM-MD5), "plain" (PLAIN), "login" (LOGIN)
// or "check" (or empty) to auto detect. Optional, defaults to "check"
$rcmail_config['imap_auth_type'] = null;
// If you know your imap's root directory and its folder delimiter,

@ -370,44 +370,95 @@ class rcube_imap_generic
$this->capability_readed = false;
}
function authenticate($user, $pass, $encChallenge)
/**
* CRAM-MD5/PLAIN Authentication
*
* @param string $user
* @param string $pass
* @param string $type Authentication type (PLAIN or CRAM-MD5)
*
* @return resource Connection resourse on success, error code on error
*/
function authenticate($user, $pass, $type='PLAIN')
{
$ipad = '';
$opad = '';
if ($type == 'CRAM-MD5') {
$ipad = '';
$opad = '';
// initialize ipad, opad
for ($i=0; $i<64; $i++) {
$ipad .= chr(0x36);
$opad .= chr(0x5C);
}
// initialize ipad, opad
for ($i=0; $i<64; $i++) {
$ipad .= chr(0x36);
$opad .= chr(0x5C);
}
// pad $pass so it's 64 bytes
$padLen = 64 - strlen($pass);
for ($i=0; $i<$padLen; $i++) {
$pass .= chr(0);
}
// pad $pass so it's 64 bytes
$padLen = 64 - strlen($pass);
for ($i=0; $i<$padLen; $i++) {
$pass .= chr(0);
}
$this->putLine($this->next_tag() . " AUTHENTICATE CRAM-MD5");
$line = trim($this->readLine(1024));
if ($line[0] == '+') {
$challenge = substr($line,2);
}
else {
return self::ERROR_BYE;
}
// generate hash
$hash = md5($this->_xor($pass,$opad) . pack("H*", md5($this->_xor($pass, $ipad) . base64_decode($encChallenge))));
// generate hash
$hash = md5($this->_xor($pass, $opad) . pack("H*", md5($this->_xor($pass, $ipad) . base64_decode($encChallenge))));
$reply = base64_encode($user . ' ' . $hash);
// generate reply
$reply = base64_encode($user . ' ' . $hash);
// send result, get reply and process it
$this->putLine($reply);
$line = $this->readLine(1024);
$result = $this->parseResult($line);
if ($result != self::ERROR_OK) {
$this->set_error($result, "Unble to authenticate user (CRAM-MD5): $line");
}
}
else { // PLAIN
$reply = base64_encode($user . chr(0) . $user . chr(0) . $pass);
// send result, get reply
$this->putLine($reply);
$line = $this->readLine(1024);
// RFC 4959 (SASL-IR): save one round trip
if ($this->getCapability('SASL-IR')) {
$result = $this->execute("AUTHENTICATE PLAIN", array($reply), self::COMMAND_NORESPONSE);
}
else {
$this->putLine($this->next_tag() . " AUTHENTICATE PLAIN");
$line = trim($this->readLine(1024));
if ($line[0] != '+') {
return self::ERROR_BYE;
}
// send result, get reply and process it
$this->putLine($reply);
$line = $this->readLine(1024);
$result = $this->parseResult($line);
if ($result != self::ERROR_OK) {
$this->set_error($result, "Unble to authenticate user (AUTH): $line");
}
}
}
// process result
$result = $this->parseResult($line);
if ($result == self::ERROR_OK) {
return $this->fp;
}
$this->error = "Authentication for $user failed (AUTH): $line";
return $result;
}
/**
* LOGIN Authentication
*
* @param string $user
* @param string $pass
*
* @return resource Connection resourse on success, error code on error
*/
function login($user, $password)
{
list($code, $response) = $this->execute('LOGIN', array(
@ -422,9 +473,6 @@ class rcube_imap_generic
return $this->fp;
}
@fclose($this->fp);
$this->fp = false;
return $code;
}
@ -634,44 +682,48 @@ class rcube_imap_generic
}
}
$orig_method = $auth_method;
$auth_methods = array();
$result = null;
// check for supported auth methods
if ($auth_method == 'CHECK') {
// check for supported auth methods
if ($this->getCapability('AUTH=CRAM-MD5') || $this->getCapability('AUTH=CRAM_MD5')) {
$auth_method = 'AUTH';
$auth_methods[] = 'AUTH';
}
else {
// default to plain text auth
$auth_method = 'PLAIN';
if ($this->getCapability('AUTH=PLAIN')) {
$auth_methods[] = 'PLAIN';
}
// RFC 2595 (LOGINDISABLED) LOGIN disabled when connection is not secure
if (!$this->getCapability('LOGINDISABLED')) {
$auth_methods[] = 'LOGIN';
}
}
else {
$auth_methods[] = $auth_method;
}
if ($auth_method == 'AUTH') {
// do CRAM-MD5 authentication
$this->putLine($this->next_tag() . " AUTHENTICATE CRAM-MD5");
$line = trim($this->readLine(1024));
if ($line[0] == '+') {
// got a challenge string, try CRAM-MD5
$result = $this->authenticate($user, $password, substr($line,2));
// stop if server sent BYE response
if ($result == self::ERROR_BYE) {
return false;
}
}
// Authenticate
foreach ($auth_methods as $method) {
switch ($method) {
case 'AUTH':
$result = $this->authenticate($user, $password, 'CRAM-MD5');
break;
case 'PLAIN':
$result = $this->authenticate($user, $password, 'PLAIN');
break;
case 'LOGIN':
$result = $this->login($user, $password);
break;
default:
$this->set_error(self::ERROR_BAD, "Configuration error. Unknown auth method: $method");
}
if (!is_resource($result) && $orig_method == 'CHECK') {
$auth_method = 'PLAIN';
if (is_resource($result)) {
break;
}
}
if ($auth_method == 'PLAIN') {
// do plain text auth
$result = $this->login($user, $password);
}
// Connected and authenticated
if (is_resource($result)) {
if ($this->prefs['force_caps']) {
$this->clearCapability();
@ -680,9 +732,13 @@ class rcube_imap_generic
$this->logged = true;
return true;
} else {
return false;
}
}
// Close connection
@fclose($this->fp);
$this->fp = false;
return false;
}
function connected()

Loading…
Cancel
Save