From 5c70a370e2b09daa97d46e3fc4153a25f1a32207 Mon Sep 17 00:00:00 2001 From: Elijah Madden Date: Tue, 4 Dec 2012 17:19:24 +0900 Subject: [PATCH] New AuthType: CRAM-MD5 --- class.smtp.php | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/class.smtp.php b/class.smtp.php index e5d86bc1..ddb624a6 100644 --- a/class.smtp.php +++ b/class.smtp.php @@ -414,10 +414,81 @@ class SMTP { return false; } break; + case 'CRAM-MD5': + // Start authentication + fputs($this->smtp_conn,"AUTH CRAM-MD5" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($code != 334) { + $this->error = + array("error" => "AUTH not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'); + } + return false; + } + + // Get the challenge + $challenge = base64_decode(substr($rply,4)); + + // Build the response + $response = $username . ' ' . $this->hmac($challenge, $password); + + // Send encoded credentials + fputs($this->smtp_conn, base64_encode($response) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($code != 334) { + $this->error = + array("error" => "Credentials not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'); + } + return false; + } + break; } return true; } + /** + * Works like hash_hmac('md5', $data, $key) in case that function is not available + * @access private + * @return string + */ + private function hmac($data, $key) { + if (function_exists('hash_hmac')) { + return hash_hmac('md5', $data, $key); + } + + // The following borrowed from http://php.net/manual/en/function.mhash.php#27225 + + // RFC 2104 HMAC implementation for php. + // Creates an md5 HMAC. + // Eliminates the need to install mhash to compute a HMAC + // Hacked by Lance Rushing + + $b = 64; // byte length for md5 + if (strlen($key) > $b) { + $key = pack("H*",md5($key)); + } + $key = str_pad($key, $b, chr(0x00)); + $ipad = str_pad('', $b, chr(0x36)); + $opad = str_pad('', $b, chr(0x5c)); + $k_ipad = $key ^ $ipad ; + $k_opad = $key ^ $opad; + + return md5($k_opad . pack("H*",md5($k_ipad . $data))); + } + /** * Returns true if connected to a server otherwise false * @access public