Exemplo n.º 1
0
 function _authCRAM_MD5($uid, $pwd, $cmdid)
 {
     if (PEAR::isError($error = $this->_putCMD($cmdid, "AUTHENTICATE", "CRAM-MD5"))) {
         return $error;
     }
     if (PEAR::isError($args = $this->_recvLn())) {
         return $args;
     }
     $plus = "";
     $this->_getNextToken($args, $plus);
     $space = "";
     $this->_getNextToken($args, $space);
     $challenge = "";
     $this->_getNextToken($args, $challenge);
     $challenge = base64_decode($challenge);
     $cram =& Auth_SASL::factory('crammd5');
     $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge));
     if (PEAR::isError($error = $this->_send($auth_str . "\r\n"))) {
         return $error;
     }
     return true;
 }
Exemplo n.º 2
0
 /**
  * Authenticates the user using the CRAM-MD5 method.
  *
  * @param string The userid to authenticate as.
  * @param string The password to authenticate with.
  *
  * @return mixed Returns a PEAR_Error with an error message on any
  *               kind of failure, or true on success.
  * @access private
  * @since  1.1.0
  */
 function _authCRAM_MD5($uid, $pwd)
 {
     if (PEAR::isError($error = $this->_put('AUTH', 'CRAM-MD5'))) {
         return $error;
     }
     /* 334: Continue authentication request */
     if (PEAR::isError($error = $this->_parseResponse(334))) {
         /* 503: Error: already authenticated */
         if ($this->_code === 503) {
             return true;
         }
         return $error;
     }
     $challenge = base64_decode($this->_arguments[0]);
     $cram =& Auth_SASL::factory('crammd5');
     $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge));
     if (PEAR::isError($error = $this->_put($auth_str))) {
         return $error;
     }
     /* 235: Authentication successful */
     if (PEAR::isError($error = $this->_parseResponse(235))) {
         return $error;
     }
 }
 /**
  * DIGEST-MD5/CRAM-MD5/PLAIN Authentication
  *
  * @param string $user
  * @param string $pass
  * @param string $type Authentication type (PLAIN/CRAM-MD5/DIGEST-MD5)
  *
  * @return resource Connection resourse on success, error code on error
  */
 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] == '+') {
                 $challenge = substr($line, 2);
             } else {
                 return $this->parseResult($line);
             }
             // check response
             $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 {
         // 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;
 }
Exemplo n.º 4
0
 /**
  * Authenticates the user using the DIGEST-MD5 method.
  *
  * @param string $user  The userid to authenticate as.
  * @param string $pass  The password to authenticate with.
  * @param string $euser The effective uid to authenticate as.
  *
  * @return void
  */
 function _authDigestMD5($user, $pass, $euser)
 {
     if (PEAR::isError($challenge = $this->_doCmd('AUTHENTICATE "DIGEST-MD5"', true))) {
         return $challenge;
     }
     $challenge = base64_decode(trim($challenge));
     $digest = Auth_SASL::factory('digestmd5');
     // @todo Really 'localhost'?
     if (PEAR::isError($response = $digest->getResponse($user, $pass, $challenge, 'localhost', 'sieve', $euser))) {
         return $response;
     }
     if (PEAR::isError($result = $this->_sendStringResponse(base64_encode($response)))) {
         return $result;
     }
     if (PEAR::isError($result = $this->_doCmd('', true))) {
         return $result;
     }
     if ($this->_toUpper(substr($result, 0, 2)) == 'OK') {
         return;
     }
     /* We don't use the protocol's third step because SIEVE doesn't allow
      * subsequent authentication, so we just silently ignore it. */
     if (PEAR::isError($result = $this->_sendStringResponse(''))) {
         return $result;
     }
     return $this->_doCmd();
 }
 /**
  * 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;
 }
Exemplo n.º 6
0
 function _authDigest_MD5($uid, $pwd)
 {
     if (PEAR::isError($ret = $this->_send('AUTH DIGEST-MD5'))) {
         return $ret;
     }
     if (PEAR::isError($challenge = $this->_recvLn())) {
         return $challenge;
     }
     if (PEAR::isError($ret = $this->_checkResponse($challenge))) {
         return $ret;
     }
     // remove '+ '
     $challenge = substr($challenge, 2);
     $challenge = base64_decode($challenge);
     $digest =& Auth_SASL::factory('digestmd5');
     $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, "localhost", "pop3"));
     if (PEAR::isError($error = $this->_send($auth_str))) {
         return $error;
     }
     if (PEAR::isError($challenge = $this->_recvLn())) {
         return $challenge;
     }
     if (PEAR::isError($ret = $this->_checkResponse($challenge))) {
         return $ret;
     }
     /*
      * We don't use the protocol's third step because POP3 doesn't allow
      * subsequent authentication, so we just silently ignore it.
      */
     if (PEAR::isError($challenge = $this->_send("\r\n"))) {
         return $challenge;
     }
     if (PEAR::isError($challenge = $this->_recvLn())) {
         return $challenge;
     }
     return $this->_checkResponse($challenge);
 }
Exemplo n.º 7
0
 /**
  * Try to authenticate
  *
  * @throws XmppPrebindException if invalid login
  * @return bool
  */
 public function auth()
 {
     $auth = Auth_SASL::factory($this->encryption);
     switch ($this->encryption) {
         case self::ENCRYPTION_PLAIN:
             $authXml = $this->buildPlainAuth($auth);
             break;
         case self::ENCRYPTION_DIGEST_MD5:
             $authXml = $this->sendChallengeAndBuildDigestMd5Auth($auth);
             break;
         case self::ENCRYPTION_CRAM_MD5:
             $authXml = $this->sendChallengeAndBuildCramMd5Auth($auth);
             break;
     }
     /*$response = $this->send($authXml);
     		$body = self::getBodyFromXml($response);
     		error_log("Body of the response: " . $body);
     
     		if (!$body->hasChildNodes() || $body->firstChild->nodeName !== 'success') {
     			throw new XmppPrebindException("Invalid login");
     		}
     		*/
     $this->rid--;
     $this->sendRestart();
     $this->sendBindIfRequired();
     $this->sendSessionIfRequired();
     return true;
 }
Exemplo n.º 8
0
 /**
  * Authenticates the user using the DIGEST-MD5 method.
  *
  * @param string The userid to authenticate as.
  * @param string The password to authenticate with.
  *
  * @return mixed Returns a PEAR_Error with an error message on any
  *               kind of failure, or true on success.
  * @access private
  * @since  1.1.0
  */
 function _authDigest_MD5($uid, $pwd)
 {
     if (PEAR::isError($error = $this->_put('AUTH', 'DIGEST-MD5'))) {
         return $error;
     }
     /* 334: Continue authentication request */
     if (PEAR::isError($error = $this->_parseResponse(334))) {
         /* 503: Error: already authenticated */
         if ($this->_code === 503) {
             return true;
         }
         return $error;
     }
     $challenge = base64_decode($this->_arguments[0]);
     $digest =& Auth_SASL::factory('digestmd5');
     $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, $this->host, "smtp"));
     if (PEAR::isError($error = $this->_put($auth_str))) {
         return $error;
     }
     /* 334: Continue authentication request */
     if (PEAR::isError($error = $this->_parseResponse(334))) {
         return $error;
     }
     /* We don't use the protocol's third step because SMTP doesn't
      * allow subsequent authentication, so we just silently ignore
      * it. */
     if (PEAR::isError($error = $this->_put(' '))) {
         return $error;
     }
     /* 235: Authentication successful */
     if (PEAR::isError($error = $this->_parseResponse(235))) {
         return $error;
     }
 }
Exemplo n.º 9
0
 /**
  * Authenticates the user using the DIGEST-MD5 method.
  *
  * @param string $uid The userid to authenticate as.
  * @param string $pwd The password to authenticate with.
  * @param string $euser The effective uid to authenticate as.
  *
  * @return array Returns an array containing the response
  *
  * @access private
  * @since  1.0
  */
 function _authDigest_MD5($uid, $pwd, $euser)
 {
     if (PEAR::isError($challenge = $this->_doCmd('AUTHENTICATE "DIGEST-MD5"'))) {
         $this->_error = challenge;
         return challenge;
     }
     $challenge = base64_decode($challenge);
     $digest =& Auth_SASL::factory('digestmd5');
     if (PEAR::isError($param = $digest->getResponse($uid, $pwd, $challenge, "localhost", "sieve", $euser))) {
         return $param;
     }
     $auth_str = base64_encode($param);
     if (PEAR::isError($error = $this->_sendStringResponse($auth_str))) {
         $this->_error = $error;
         return $error;
     }
     if (PEAR::isError($challenge = $this->_doCmd())) {
         $this->_error = $challenge;
         return $challenge;
     }
     if (strtoupper(substr($challenge, 0, 2)) == 'OK') {
         return true;
     }
     /**
      * We don't use the protocol's third step because SIEVE doesn't allow
      * subsequent authentication, so we just silently ignore it.
      */
     if (PEAR::isError($error = $this->_sendStringResponse(''))) {
         $this->_error = $error;
         return $error;
     }
     if (PEAR::isError($res = $this->_doCmd())) {
         return $res;
     }
 }
Exemplo n.º 10
0
 /**
  * Authenticates the user using the CRAM-MD5 method.
  *
  * @param string $uid   The userid to authenticate as.
  * @param string $pwd   The password to authenticate with.
  * @param string $cmdid The cmdID.
  *
  * @return array Returns an array containing the response
  * @access private
  * @since 1.0
  */
 function _authCramMD5($uid, $pwd, $cmdid)
 {
     $error = $this->_putCMD($cmdid, 'AUTHENTICATE', 'CRAM-MD5');
     if ($error instanceof PEAR_Error) {
         return $error;
     }
     $args = $this->_recvLn();
     if ($args instanceof PEAR_Error) {
         return $args;
     }
     $this->_getNextToken($args, $plus);
     $this->_getNextToken($args, $space);
     $this->_getNextToken($args, $challenge);
     $challenge = base64_decode($challenge);
     $cram =& Auth_SASL::factory('crammd5');
     $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge));
     $error = $this->_send($auth_str . "\r\n");
     if ($error instanceof PEAR_Error) {
         return $error;
     }
 }
Exemplo n.º 11
0
 /**
  * Factory class. Returns an object of the request
  * type.
  *
  * @param string $type One of: Anonymous
  *                             Plain
  *                             CramMD5
  *                             DigestMD5
  *                             SCRAM-* (any mechanism of the SCRAM family)
  *                     Types are not case sensitive
  */
 function &factory($type)
 {
     switch (strtolower($type)) {
         case 'anonymous':
             $filename = 'include/Auth/SASL/Anonymous.php';
             $classname = 'Auth_SASL_Anonymous';
             break;
         case 'login':
             $filename = 'include/Auth/SASL/Login.php';
             $classname = 'Auth_SASL_Login';
             break;
         case 'plain':
             $filename = 'include/Auth/SASL/Plain.php';
             $classname = 'Auth_SASL_Plain';
             break;
         case 'external':
             $filename = 'include/Auth/SASL/External.php';
             $classname = 'Auth_SASL_External';
             break;
         case 'crammd5':
             // $msg = 'Deprecated mechanism name. Use IANA-registered name: CRAM-MD5.';
             // trigger_error($msg, E_USER_DEPRECATED);
         // $msg = 'Deprecated mechanism name. Use IANA-registered name: CRAM-MD5.';
         // trigger_error($msg, E_USER_DEPRECATED);
         case 'cram-md5':
             $filename = 'include/Auth/SASL/CramMD5.php';
             $classname = 'Auth_SASL_CramMD5';
             break;
         case 'digestmd5':
             // $msg = 'Deprecated mechanism name. Use IANA-registered name: DIGEST-MD5.';
             // trigger_error($msg, E_USER_DEPRECATED);
         // $msg = 'Deprecated mechanism name. Use IANA-registered name: DIGEST-MD5.';
         // trigger_error($msg, E_USER_DEPRECATED);
         case 'digest-md5':
             // $msg = 'DIGEST-MD5 is a deprecated SASL mechanism as per RFC-6331. Using it could be a security risk.';
             // trigger_error($msg, E_USER_NOTICE);
             $filename = 'include/Auth/SASL/DigestMD5.php';
             $classname = 'Auth_SASL_DigestMD5';
             break;
         default:
             $scram = '/^SCRAM-(.{1,9})$/i';
             if (preg_match($scram, $type, $matches)) {
                 $hash = $matches[1];
                 $filename = 'include/Auth/SASL/SCRAM.php';
                 $classname = 'Auth_SASL_SCRAM';
                 $parameter = $hash;
                 break;
             }
             return Auth_SASL::raiseError('Invalid SASL mechanism type');
             break;
     }
     require_once $filename;
     if (isset($parameter)) {
         $obj = new $classname($parameter);
     } else {
         $obj = new $classname();
     }
     return $obj;
 }
Exemplo n.º 12
0
 function _authCRAM_MD5($uid, $pwd)
 {
     if (PEAR::isError($error = $this->_put('AUTH', 'CRAM-MD5'))) {
         return $error;
     }
     if (PEAR::isError($error = $this->_parseResponse(334))) {
         return $error;
     }
     $challenge = base64_decode($this->_arguments[0]);
     $cram =& Auth_SASL::factory('crammd5');
     $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge));
     if (PEAR::isError($error = $this->_put($auth_str))) {
         return $error;
     }
     if (PEAR::isError($error = $this->_parseResponse(235))) {
         return $error;
     }
 }
Exemplo n.º 13
0
 /**
  * Connect to the XMPP server with the supplied node & password
  *
  * @param string $node Node without domain
  * @param string $password Password
  */
 public function connect($node = null, $password = null)
 {
     if ($node != null && $password != null) {
         $this->node = $node;
         $this->password = $password;
         $this->jid = $this->node . '@' . $this->domain;
         if ($this->resource != '') {
             $this->jid .= '/' . $this->resource;
         }
     }
     // Init connection & get server supported mechanisms
     $response = $this->sendInitConnection();
     $body = self::getBodyFromXml($response);
     $this->sid = $body->getAttribute('sid');
     $mechanisms = $body->firstChild->getElementsByTagName('mechanism');
     foreach ($mechanisms as $value) {
         $this->mechanisms[] = $value->nodeValue;
     }
     /* If node & password not provided and server supports ANONYMOUS
      * we select that mechanism. To select other mechanisms we must have node
      * & password
      */
     if (in_array(self::ENCRYPTION_ANONYMOUS, $this->mechanisms) && $node == null && $password == null) {
         $this->encryption = self::ENCRYPTION_ANONYMOUS;
     } else {
         if (in_array(self::ENCRYPTION_DIGEST_MD5, $this->mechanisms) && $node != null && $password != null) {
             $this->encryption = self::ENCRYPTION_DIGEST_MD5;
         } elseif (in_array(self::ENCRYPTION_CRAM_MD5, $this->mechanisms) && $node != null && $password != null) {
             $this->encryption = self::ENCRYPTION_CRAM_MD5;
         } elseif (in_array(self::ENCRYPTION_PLAIN, $this->mechanisms) && $node != null && $password != null) {
             $this->encryption = self::ENCRYPTION_PLAIN;
         } else {
             throw new XmppBoshConnectionException("No encryption supported by the server is supported by this library.");
         }
     }
     // Authentication process using selected mechanism
     $auth = Auth_SASL::factory($this->encryption);
     switch ($this->encryption) {
         case self::ENCRYPTION_PLAIN:
             $response = $this->buildPlainAuth($auth);
             break;
         case self::ENCRYPTION_DIGEST_MD5:
             $response = $this->sendChallengeAndBuildDigestMd5Auth($auth);
             break;
         case self::ENCRYPTION_CRAM_MD5:
             $response = $this->sendChallengeAndBuildCramMd5Auth($auth);
             break;
         case self::ENCRYPTION_ANONYMOUS:
             $response = $this->buildAnonymousAuth($auth);
             break;
     }
     $response = $this->send($response);
     $body = self::getBodyFromXml($response);
     // Authentication success or failure
     if (!$body->hasChildNodes() || $body->firstChild->nodeName !== 'success') {
         throw new XmppBoshException("Invalid login");
     }
     // For ANONYMOUS mechanism we send new init, for others restart
     if ($this->encryption != self::ENCRYPTION_ANONYMOUS) {
         $response = $this->sendRestart();
     } else {
         $response = $this->sendInitConnection();
     }
     // Detect are bind and session required
     $body = self::getBodyFromXml($response);
     foreach ($body->childNodes as $bodyChildNodes) {
         if ($bodyChildNodes->nodeName === 'stream:features') {
             foreach ($bodyChildNodes->childNodes as $streamFeatures) {
                 if ($streamFeatures->nodeName === 'bind') {
                     $this->doBind = true;
                 } elseif ($streamFeatures->nodeName === 'session') {
                     $this->doSession = true;
                 }
             }
         }
     }
     // If bind required we send it
     if ($this->doBind) {
         $response = $this->sendBind();
         // For ANONYMOUS mechanism bind returns full JID, so lets store it
         if ($this->encryption == self::ENCRYPTION_ANONYMOUS) {
             $body = self::getBodyFromXml($response);
             if ($body->hasChildNodes() && $body->firstChild->getAttribute('type') == 'result') {
                 $this->jid = $body->firstChild->firstChild->firstChild->nodeValue;
             } else {
                 throw new XmppException('Subscription request not successful');
             }
         }
     }
     // If session required we send it
     if ($this->doSession) {
         $response = $this->sendSession();
     }
 }
Exemplo n.º 14
0
 /**
  * Authenticates the user using the DIGEST-MD5 method.
  *
  * @param string $user  The userid to authenticate as.
  * @param string $pass  The password to authenticate with.
  * @param string $euser The effective uid to authenticate as.
  *
  * @throws \Horde\ManageSieve\Exception
  */
 protected function _authDigestMD5($user, $pass, $euser)
 {
     $challenge = $this->_doCmd('AUTHENTICATE "DIGEST-MD5"', true);
     $challenge = base64_decode(trim($challenge));
     $digest = Auth_SASL::factory('digestmd5');
     // @todo Really 'localhost'?
     $response = $digest->getResponse($user, $pass, $challenge, 'localhost', 'sieve', $euser);
     if (is_a($response, 'PEAR_Error')) {
         throw new Exception($response);
     }
     $this->_sendStringResponse(base64_encode($response));
     $this->_doCmd('', true);
     if (\Horde_String::upper(substr($result, 0, 2)) == 'OK') {
         return;
     }
     /* We don't use the protocol's third step because SIEVE doesn't allow
      * subsequent authentication, so we just silently ignore it. */
     $this->_sendStringResponse('');
     $this->_doCmd();
 }
 /**
  * Log the user into the IMAP server.
  *
  * @access private
  *
  * @param string $username  Username.
  * @param string $password  Encrypted password.
  * @param string $method    IMAP login method.
  *
  * @return mixed  True on success, PEAR_Error on error.
  */
 function _login($username, $password, $method)
 {
     switch ($method) {
         case 'cram-md5':
         case 'digest-md5':
             /* If we don't have Auth_SASL package install, return error. */
             if (!@(include_once 'Auth/SASL.php')) {
                 return PEAR::raiseError(lang("CRAM-MD5 or DIGEST-MD5 requires the Auth_SASL package to be installed."), 'horde.error');
             }
             $tag = $this->_generateSid();
             fwrite($this->_stream, $tag . ' AUTHENTICATE ' . strtoupper($method) . "\r\n");
             $challenge = explode(' ', $this->_fgets(), 3);
             if ($method == 'cram-md5') {
                 $auth_sasl = Auth_SASL::factory('crammd5');
                 $response = $auth_sasl->getResponse($username, $password, base64_decode($challenge[1]));
                 fwrite($this->_stream, base64_encode($response) . "\r\n");
                 $read = $this->_fgets();
             } elseif ($method == 'digest-md5') {
                 $auth_sasl = Auth_SASL::factory('digestmd5');
                 $response = $auth_sasl->getResponse($username, $password, base64_decode($challenge[1]), $this->_host, 'imap');
                 fwrite($this->_stream, base64_encode($response) . "\r\n");
                 $response = explode(' ', $this->_fgets());
                 $response = base64_decode($response[1]);
                 if (strpos($response, 'rspauth=') === false) {
                     return PEAR::raiseError(lang("Unexpected response from server to Digest-MD5 response."), 'horde.error');
                 }
                 fwrite($this->_stream, "\r\n");
                 $read = $this->_fgets();
             } else {
                 return PEAR::raiseError(lang("The IMAP server does not appear to support the authentication method selected. Please contact your system administrator."), 'horde.error');
             }
             break;
         case 'login':
             $tag = $this->_generateSid();
             $query = $tag . " LOGIN {$username} {" . strlen($password) . "}\r\n";
             fwrite($this->_stream, $query);
             $read = $this->_fgets();
             if (substr($read, 0, 1) == '+') {
                 fwrite($this->_stream, "{$password}\r\n");
                 $read = $this->_fgets();
             } else {
                 return PEAR::raiseError(lang("Unexpected response from server to LOGIN command."), 'horde.error');
             }
             break;
         case 'plain':
             $tag = $this->_generateSid();
             $sasl = $this->queryCapability('SASL-IR');
             $auth = base64_encode("{$username}{$username}{$password}");
             if ($sasl) {
                 // IMAP Extension for SASL Initial Client Response
                 // <draft-siemborski-imap-sasl-initial-response-01b.txt>
                 $query = $tag . " AUTHENTICATE PLAIN {$auth}\r\n";
                 fwrite($this->_stream, $query);
                 $read = $this->_fgets();
             } else {
                 $query = $tag . " AUTHENTICATE PLAIN\r\n";
                 fwrite($this->_stream, $query);
                 $read = $this->_fgets();
                 if (substr($read, 0, 1) == '+') {
                     fwrite($this->_stream, "{$auth}\r\n");
                     $read = $this->_fgets();
                 } else {
                     return PEAR::raiseError(lang("Unexpected response from server to AUTHENTICATE command."), 'horde.error');
                 }
             }
             break;
     }
     /* Check for failed login. */
     $results = explode(' ', $read, 3);
     $response = $results[1];
     if ($response != 'OK') {
         $message = !empty($results[2]) ? htmlspecialchars($results[2]) : lang("No message returned.");
         switch ($response) {
             case 'NO':
                 return PEAR::raiseError(sprintf(lang("Bad login name or password."), $message), 'horde.error');
             case 'BAD':
             default:
                 return PEAR::raiseError(sprintf(lang("Bad request: %s"), $message), 'horde.error');
         }
     }
     return true;
 }