/**
* Authenticate to the POP3 server.
*
* @param string $method POP3 login method.
*
* @throws Horde_Imap_Client_Exception
*/
protected function _tryLogin($method)
{
$username = $this->getParam('username');
$password = $this->getParam('password');
switch ($method) {
case 'CRAM-MD5':
case 'CRAM-SHA1':
case 'CRAM-SHA256':
// RFC 5034: CRAM-MD5
// CRAM-SHA1 & CRAM-SHA256 supported by Courier SASL library
$challenge = $this->_sendLine('AUTH ' . $method);
$response = base64_encode($username . ' ' . hash_hmac(Horde_String::lower(substr($method, 5)), base64_decode(substr($challenge['resp'], 2)), $password, true));
$this->_sendLine($response, array('debug' => sprintf('[AUTH Response (username: %s)]', $username)));
break;
case 'DIGEST-MD5':
// RFC 2831; Obsoleted by RFC 6331
$challenge = $this->_sendLine('AUTH DIGEST-MD5');
$response = base64_encode(new Horde_Imap_Client_Auth_DigestMD5($username, $password, base64_decode(substr($challenge['resp'], 2)), $this->getParam('hostspec'), 'pop3'));
$sresponse = $this->_sendLine($response, array('debug' => sprintf('[AUTH Response (username: %s)]', $username)));
if (stripos(base64_decode(substr($sresponse['resp'], 2)), 'rspauth=') === false) {
throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Unexpected response from server when authenticating."), Horde_Imap_Client_Exception::SERVER_CONNECT);
}
/* POP3 doesn't use protocol's third step. */
$this->_sendLine('');
break;
case 'LOGIN':
// RFC 4616 (AUTH=PLAIN) & 5034 (POP3 SASL)
$this->_sendLine('AUTH LOGIN');
$this->_sendLine(base64_encode($username));
$this->_sendLine(base64_encode($password), array('debug' => sprintf('[AUTH Password (username: %s)]', $username)));
break;
case 'PLAIN':
// RFC 5034
$this->_sendLine('AUTH PLAIN ' . base64_encode(implode("", array($username, $username, $password))), array('debug' => sprintf('AUTH PLAIN [Auth Response (username: %s)]', $username)));
break;
case 'APOP':
/* If UTF8 (+ USER) is active, and non-ASCII exists, need to apply
* SASLprep to username/password. RFC 6856[2.2]. Reject if
* UTF8 (+ USER) is not supported and 8-bit characters exist. */
if (Horde_Mime::is8bit($username) || Horde_Mime::is8bit($password)) {
if (empty($this->_temp['utf8']) || !$this->_capability('UTF8', 'USER') || !class_exists('Horde_Stringprep')) {
$error = true;
} else {
Horde_Stringprep::autoload();
$saslprep = new Znerol\Component\Stringprep\Profile\SASLprep();
try {
$username = $saslprep->apply($username, 'UTF-8', Znerol\Compnonent\Stringprep\Profile::MODE_QUERY);
$password = $saslprep->apply($password, 'UTF-8', Znerol\Compnonent\Stringprep\Profile::MODE_STORE);
$error = false;
} catch (Znerol\Component\Stringprep\ProfileException $e) {
$error = true;
}
}
if ($error) {
throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Authentication failed."), Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED);
}
}
// RFC 1939 [7]
$this->_sendLine('APOP ' . $username . ' ' . hash('md5', $this->_temp['pop3timestamp'] . $password));
break;
case 'USER':
/* POP3 servers without UTF8 (+ USER) does not accept non-ASCII
* in USER/PASS. RFC 6856[2.2] */
if ((empty($this->_temp['utf8']) || !$this->_capability('UTF8', 'USER')) && (Horde_Mime::is8bit($username) || Horde_Mime::is8bit($password))) {
throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Authentication failed."), Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED);
}
// RFC 1939 [7]
$this->_sendLine('USER ' . $username);
$this->_sendLine('PASS ' . $password, array('debug' => 'PASS [Password]'));
break;
case 'SCRAM-SHA-1':
$scram = new Horde_Imap_Client_Auth_Scram($username, $password, 'SHA1');
$c1 = $this->_sendLine('AUTH ' . $method . ' ' . base64_encode($scram->getClientFirstMessage()));
$sr1 = base64_decode(substr($c1['resp'], 2));
if (!$scram->parseServerFirstMessage($sr1)) {
throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Authentication failed."), Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED);
}
$c2 = $this->_sendLine(base64_encode($scram->getClientFinalMessage()));
$sr2 = base64_decode(substr($c2['resp'], 2));
if (!$scram->parseServerFirstMessage($sr)) {
throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Authentication failed."), Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED);
/* This means authentication passed, according to the server,
* but the server signature is incorrect. This indicates that
* server verification has failed. Immediately disconnect from
* the server, since this is a possible security issue. */
$this->logout();
throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Server failed verification check."), Horde_Imap_Client_Exception::LOGIN_SERVER_VERIFICATION_FAILED);
}
$this->_sendLine('');
break;
default:
$e = new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Unknown authentication method: %s"), Horde_Imap_Client_Exception::SERVER_CONNECT);
$e->messagePrintf(array($method));
throw $e;
}
}