* @author Michael Slusarz * @copyright 2002-2003 Richard Heyes * @copyright 2011-2017 Horde LLC * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 * @package Imap_Client */ class Horde_Imap_Client_Auth_DigestMD5 { /** * Digest response components. * * @var string */ protected $_response; /** * Generate the Digest-MD5 response. * * @param string $id Authentication id (username). * @param string $pass Password. * @param string $challenge The digest challenge sent by the server. * @param string $hostname The hostname of the machine connecting to. * @param string $service The service name (e.g. 'imap', 'pop3'). * * @throws Horde_Imap_Client_Exception */ public function __construct($id, $pass, $challenge, $hostname, $service) { $challenge = $this->_parseChallenge($challenge); $cnonce = $this->_getCnonce(); $digest_uri = sprintf('%s/%s', $service, $hostname); /* Get response value. */ $A1 = sprintf('%s:%s:%s', pack('H32', hash('md5', sprintf('%s:%s:%s', $id, $challenge['realm'], $pass))), $challenge['nonce'], $cnonce); $A2 = 'AUTHENTICATE:' . $digest_uri; $response_value = hash('md5', sprintf('%s:%s:00000001:%s:auth:%s', hash('md5', $A1), $challenge['nonce'], $cnonce, hash('md5', $A2))); $this->_response = array( 'cnonce' => '"' . $cnonce . '"', 'digest-uri' => '"' . $digest_uri . '"', 'maxbuf' => $challenge['maxbuf'], 'nc' => '00000001', 'nonce' => '"' . $challenge['nonce'] . '"', 'qop' => 'auth', 'response' => $response_value, 'username' => '"' . $id . '"' ); if (strlen($challenge['realm'])) { $this->_response['realm'] = '"' . $challenge['realm'] . '"'; } } /** * Cooerce to string. * * @return string The digest response (not base64 encoded). */ public function __toString() { $out = array(); foreach ($this->_response as $key => $val) { $out[] = $key . '=' . $val; } return implode(',', $out); } /** * Return specific digest response directive. * * @return mixed Requested directive, or null if it does not exist. */ public function __get($name) { return isset($this->_response[$name]) ? $this->_response[$name] : null; } /** * Parses and verifies the digest challenge. * * @param string $challenge The digest challenge * * @return array The parsed challenge as an array with directives as keys. * * @throws Horde_Imap_Client_Exception */ protected function _parseChallenge($challenge) { $tokens = array( 'maxbuf' => 65536, 'realm' => '' ); preg_match_all('/([a-z-]+)=("[^"]+(?