public function check_password($username, $password) { $ticket = new KRB5CCache(); try { $ticket->initPassword(strtolower($username) . "@" . $this->realm, $password); } catch (Exception $e) { if ($this->debug) { echo "{$e}\n"; } return false; } return true; }
/** * DIGEST-MD5/CRAM-MD5/PLAIN Authentication * * @param string $user Username * @param string $pass Password * @param string $type Authentication type (PLAIN/CRAM-MD5/DIGEST-MD5) * * @return resource Connection resourse on success, error code on error */ protected function authenticate($user, $pass, $type = 'PLAIN') { if ($type == 'CRAM-MD5' || $type == 'DIGEST-MD5') { if ($type == 'DIGEST-MD5' && !class_exists('Auth_SASL')) { $this->setError(self::ERROR_BYE, "The Auth_SASL package is required for DIGEST-MD5 authentication"); return self::ERROR_BAD; } $this->putLine($this->nextTag() . " AUTHENTICATE {$type}"); $line = trim($this->readReply()); if ($line[0] == '+') { $challenge = substr($line, 2); } else { return $this->parseResult($line); } if ($type == 'CRAM-MD5') { // RFC2195: CRAM-MD5 $ipad = ''; $opad = ''; // 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); } // generate hash $hash = md5($this->_xor($pass, $opad) . pack("H*", md5($this->_xor($pass, $ipad) . base64_decode($challenge)))); $reply = base64_encode($user . ' ' . $hash); // send result $this->putLine($reply, true, true); } else { // RFC2831: DIGEST-MD5 // proxy authorization if (!empty($this->prefs['auth_cid'])) { $authc = $this->prefs['auth_cid']; $pass = $this->prefs['auth_pw']; } else { $authc = $user; $user = ''; } $auth_sasl = Auth_SASL::factory('digestmd5'); $reply = base64_encode($auth_sasl->getResponse($authc, $pass, base64_decode($challenge), $this->host, 'imap', $user)); // send result $this->putLine($reply, true, true); $line = trim($this->readReply()); if ($line[0] != '+') { return $this->parseResult($line); } // check response $challenge = substr($line, 2); $challenge = base64_decode($challenge); if (strpos($challenge, 'rspauth=') === false) { $this->setError(self::ERROR_BAD, "Unexpected response from server to DIGEST-MD5 response"); return self::ERROR_BAD; } $this->putLine(''); } $line = $this->readReply(); $result = $this->parseResult($line); } else { if ($type == 'GSSAPI') { if (!extension_loaded('krb5')) { $this->setError(self::ERROR_BYE, "The krb5 extension is required for GSSAPI authentication"); return self::ERROR_BAD; } if (empty($this->prefs['gssapi_cn'])) { $this->setError(self::ERROR_BYE, "The gssapi_cn parameter is required for GSSAPI authentication"); return self::ERROR_BAD; } if (empty($this->prefs['gssapi_context'])) { $this->setError(self::ERROR_BYE, "The gssapi_context parameter is required for GSSAPI authentication"); return self::ERROR_BAD; } putenv('KRB5CCNAME=' . $this->prefs['gssapi_cn']); try { $ccache = new KRB5CCache(); $ccache->open($this->prefs['gssapi_cn']); $gssapicontext = new GSSAPIContext(); $gssapicontext->acquireCredentials($ccache); $token = ''; $success = $gssapicontext->initSecContext($this->prefs['gssapi_context'], null, null, null, $token); $token = base64_encode($token); } catch (Exception $e) { trigger_error($e->getMessage(), E_USER_WARNING); $this->setError(self::ERROR_BYE, "GSSAPI authentication failed"); return self::ERROR_BAD; } $this->putLine($this->nextTag() . " AUTHENTICATE GSSAPI " . $token); $line = trim($this->readReply()); if ($line[0] != '+') { return $this->parseResult($line); } try { $challenge = base64_decode(substr($line, 2)); $gssapicontext->unwrap($challenge, $challenge); $gssapicontext->wrap($challenge, $challenge, true); } catch (Exception $e) { trigger_error($e->getMessage(), E_USER_WARNING); $this->setError(self::ERROR_BYE, "GSSAPI authentication failed"); return self::ERROR_BAD; } $this->putLine(base64_encode($challenge)); $line = $this->readReply(); $result = $this->parseResult($line); } else { // PLAIN // proxy authorization if (!empty($this->prefs['auth_cid'])) { $authc = $this->prefs['auth_cid']; $pass = $this->prefs['auth_pw']; } else { $authc = $user; $user = ''; } $reply = base64_encode($user . chr(0) . $authc . chr(0) . $pass); // RFC 4959 (SASL-IR): save one round trip if ($this->getCapability('SASL-IR')) { list($result, $line) = $this->execute("AUTHENTICATE PLAIN", array($reply), self::COMMAND_LASTLINE | self::COMMAND_CAPABILITY | self::COMMAND_ANONYMIZED); } else { $this->putLine($this->nextTag() . " AUTHENTICATE PLAIN"); $line = trim($this->readReply()); if ($line[0] != '+') { return $this->parseResult($line); } // send result, get reply and process it $this->putLine($reply, true, true); $line = $this->readReply(); $result = $this->parseResult($line); } } } if ($result == self::ERROR_OK) { // optional CAPABILITY response if ($line && preg_match('/\\[CAPABILITY ([^]]+)\\]/i', $line, $matches)) { $this->parseCapability($matches[1], true); } return $this->fp; } else { $this->setError($result, "AUTHENTICATE {$type}: {$line}"); } return $result; }