/**
  * Verifies authentication response from OpenID server.
  *
  * This is the second step of OpenID authentication process.
  * The function returns true on successful authentication and false on
  * failure.
  *
  * @param array $params HTTP query data from OpenID server
  * @param string &$identity this argument is set to end-user's claimed
  *  identifier or OpenID provider local identifier.
  * @param mixed $extensions extension object or array of extensions objects
  * @return bool
  */
 public function verify($params, &$identity = "", $extensions = null)
 {
     $this->_setError('');
     $version = 1.1;
     if (isset($params['openid_ns']) && $params['openid_ns'] == Zend_OpenId::NS_2_0) {
         $version = 2.0;
     }
     if (isset($params["openid_claimed_id"])) {
         $identity = $params["openid_claimed_id"];
     } else {
         if (isset($params["openid_identity"])) {
             $identity = $params["openid_identity"];
         } else {
             $identity = "";
         }
     }
     if ($version < 2.0 && !isset($params["openid_claimed_id"])) {
         if ($this->_session !== null) {
             if ($this->_session->identity === $identity) {
                 $identity = $this->_session->claimed_id;
             }
         } else {
             if (defined('SID')) {
                 if (isset($_SESSION["zend_openid"]["identity"]) && isset($_SESSION["zend_openid"]["claimed_id"]) && $_SESSION["zend_openid"]["identity"] === $identity) {
                     $identity = $_SESSION["zend_openid"]["claimed_id"];
                 }
             } else {
                 require_once "Zend/Session/Namespace.php";
                 $this->_session = new Zend_Session_Namespace("zend_openid");
                 if ($this->_session->identity === $identity) {
                     $identity = $this->_session->claimed_id;
                 }
             }
         }
     }
     if (empty($params['openid_mode'])) {
         $this->_setError("Missing openid.mode");
         return false;
     }
     if (empty($params['openid_return_to'])) {
         $this->_setError("Missing openid.return_to");
         return false;
     }
     if (empty($params['openid_signed'])) {
         $this->_setError("Missing openid.signed");
         return false;
     }
     if (empty($params['openid_sig'])) {
         $this->_setError("Missing openid.sig");
         return false;
     }
     if ($params['openid_mode'] != 'id_res') {
         $this->_setError("Wrong openid.mode '" . $params['openid_mode'] . "' != 'id_res'");
         return false;
     }
     if (empty($params['openid_assoc_handle'])) {
         $this->_setError("Missing openid.assoc_handle");
         return false;
     }
     if ($params['openid_return_to'] != Zend_OpenId::selfUrl()) {
         /* Ignore query part in openid.return_to */
         $pos = strpos($params['openid_return_to'], '?');
         if ($pos === false || SUBSTR($params['openid_return_to'], 0, $pos) != Zend_OpenId::selfUrl()) {
             $this->_setError("Wrong openid.return_to '" . $params['openid_return_to'] . "' != '" . Zend_OpenId::selfUrl() . "'");
             return false;
         }
     }
     if ($version >= 2.0) {
         if (empty($params['openid_response_nonce'])) {
             $this->_setError("Missing openid.response_nonce");
             return false;
         }
         if (empty($params['openid_op_endpoint'])) {
             $this->_setError("Missing openid.op_endpoint");
             return false;
             /* OpenID 2.0 (11.3) Checking the Nonce */
         } else {
             if (!$this->_storage->isUniqueNonce($params['openid_op_endpoint'], $params['openid_response_nonce'])) {
                 $this->_setError("Duplicate openid.response_nonce");
                 return false;
             }
         }
     }
     if (!empty($params['openid_invalidate_handle'])) {
         if ($this->_storage->getAssociationByHandle($params['openid_invalidate_handle'], $url, $macFunc, $secret, $expires)) {
             $this->_storage->delAssociation($url);
         }
     }
     if ($this->_storage->getAssociationByHandle($params['openid_assoc_handle'], $url, $macFunc, $secret, $expires)) {
         // Security fix - check the association bewteen op_endpoint and assoc_handle
         if (isset($params['openid_op_endpoint']) && $url !== $params['openid_op_endpoint']) {
             $this->_setError("The op_endpoint URI is not the same of URI associated with the assoc_handle");
             return false;
         }
         $signed = explode(',', $params['openid_signed']);
         // Check the parameters for the signature
         // @see https://openid.net/specs/openid-authentication-2_0.html#positive_assertions
         $toCheck = $this->_signParams;
         if (isset($params['openid_claimed_id']) && isset($params['openid_identity'])) {
             $toCheck = array_merge($toCheck, array('claimed_id', 'identity'));
         }
         foreach ($toCheck as $param) {
             if (!in_array($param, $signed, true)) {
                 $this->_setError("The required parameter {$param} is missing in the signed");
                 return false;
             }
         }
         $data = '';
         foreach ($signed as $key) {
             $data .= $key . ':' . $params['openid_' . strtr($key, '.', '_')] . "\n";
         }
         if (base64_decode($params['openid_sig']) == Zend_OpenId::hashHmac($macFunc, $data, $secret)) {
             if (!Zend_OpenId_Extension::forAll($extensions, 'parseResponse', $params)) {
                 $this->_setError("Extension::parseResponse failure");
                 return false;
             }
             /* OpenID 2.0 (11.2) Verifying Discovered Information */
             if (isset($params['openid_claimed_id'])) {
                 $id = $params['openid_claimed_id'];
                 if (!Zend_OpenId::normalize($id)) {
                     $this->_setError("Normalization failed");
                     return false;
                 } else {
                     if (!$this->_discovery($id, $discovered_server, $discovered_version)) {
                         $this->_setError("Discovery failed: " . $this->getError());
                         return false;
                     } else {
                         if (!empty($params['openid_identity']) && $params["openid_identity"] != $id || !empty($params['openid_op_endpoint']) && $params['openid_op_endpoint'] != $discovered_server || $discovered_version != $version) {
                             $this->_setError("Discovery information verification failed");
                             return false;
                         }
                     }
                 }
             }
             return true;
         }
         $this->_storage->delAssociation($url);
         $this->_setError("Signature check failed");
         return false;
     } else {
         /* Use dumb mode */
         if (isset($params['openid_claimed_id'])) {
             $id = $params['openid_claimed_id'];
         } else {
             if (isset($params['openid_identity'])) {
                 $id = $params['openid_identity'];
             } else {
                 $this->_setError("Missing openid.claimed_id and openid.identity");
                 return false;
             }
         }
         if (!Zend_OpenId::normalize($id)) {
             $this->_setError("Normalization failed");
             return false;
         } else {
             if (!$this->_discovery($id, $server, $discovered_version)) {
                 $this->_setError("Discovery failed: " . $this->getError());
                 return false;
             }
         }
         /* OpenID 2.0 (11.2) Verifying Discovered Information */
         if (isset($params['openid_identity']) && $params["openid_identity"] != $id || isset($params['openid_op_endpoint']) && $params['openid_op_endpoint'] != $server || $discovered_version != $version) {
             $this->_setError("Discovery information verification failed");
             return false;
         }
         $params2 = array();
         foreach ($params as $key => $val) {
             if (strpos($key, 'openid_ns_') === 0) {
                 $key = 'openid.ns.' . substr($key, strlen('openid_ns_'));
             } else {
                 if (strpos($key, 'openid_sreg_') === 0) {
                     $key = 'openid.sreg.' . substr($key, strlen('openid_sreg_'));
                 } else {
                     if (strpos($key, 'openid_') === 0) {
                         $key = 'openid.' . substr($key, strlen('openid_'));
                     }
                 }
             }
             $params2[$key] = $val;
         }
         $params2['openid.mode'] = 'check_authentication';
         $ret = $this->_httpRequest($server, 'POST', $params2, $status);
         if ($status != 200) {
             $this->_setError("'Dumb' signature verification HTTP request failed");
             return false;
         }
         $r = array();
         if (is_string($ret)) {
             foreach (explode("\n", $ret) as $line) {
                 $line = trim($line);
                 if (!empty($line)) {
                     $x = explode(':', $line, 2);
                     if (is_array($x) && count($x) == 2) {
                         list($key, $value) = $x;
                         $r[trim($key)] = trim($value);
                     }
                 }
             }
         }
         $ret = $r;
         if (!empty($ret['invalidate_handle'])) {
             if ($this->_storage->getAssociationByHandle($ret['invalidate_handle'], $url, $macFunc, $secret, $expires)) {
                 $this->_storage->delAssociation($url);
             }
         }
         if (isset($ret['is_valid']) && $ret['is_valid'] == 'true') {
             if (!Zend_OpenId_Extension::forAll($extensions, 'parseResponse', $params)) {
                 $this->_setError("Extension::parseResponse failure");
                 return false;
             }
             return true;
         }
         $this->_setError("'Dumb' signature verification failed");
         return false;
     }
 }
示例#2
0
 /**
  * Verifies authentication response from OpenID server.
  *
  * This is the second step of OpenID authentication process.
  * The function returns true on successful authentication and false on
  * failure.
  *
  * @param array $params HTTP query data from OpenID server
  * @param string &$identity this argument is set to end-user's claimed
  *  identifier or OpenID provider local identifier.
  * @param mixed $extensions extension object or array of extensions objects
  * @return bool
  */
 public function verify($params, &$identity = "", $extensions = null)
 {
     $version = 1.1;
     if (isset($params['openid_ns']) && $params['openid_ns'] == Zend_OpenId::NS_2_0) {
         $version = 2.0;
     }
     if (isset($params["openid_claimed_id"])) {
         $identity = $params["openid_claimed_id"];
     } else {
         if (isset($params["openid_identity"])) {
             $identity = $params["openid_identity"];
         } else {
             $identity = "";
         }
     }
     if ($version < 2.0 && !isset($params["openid_claimed_id"])) {
         if ($this->_session === null) {
             require_once "Zend/Session/Namespace.php";
             $this->_session = new Zend_Session_Namespace("zend_openid");
         }
         $session = $this->_session;
         if ($session->identity == $identity) {
             $identity = $session->claimed_id;
         }
     }
     if (empty($params['openid_return_to']) || empty($params['openid_signed']) || empty($params['openid_sig']) || empty($params['openid_mode']) || empty($params['openid_assoc_handle']) || $params['openid_mode'] != 'id_res' || $params['openid_return_to'] != Zend_OpenId::selfUrl()) {
         return false;
     }
     if ($version >= 2.0) {
         if (empty($params['openid_response_nonce']) || empty($params['openid_op_endpoint'])) {
             return false;
             /* OpenID 2.0 (11.3) Checking the Nonce */
         } else {
             if (!$this->_storage->isUniqueNonce($params['openid_op_endpoint'], $params['openid_response_nonce'])) {
                 return false;
             }
         }
     }
     if (!empty($params['openid_invalidate_handle'])) {
         if ($this->_storage->getAssociationByHandle($params['openid_invalidate_handle'], $url, $macFunc, $secret, $expires)) {
             $this->_storage->delAssociation($url);
         }
     }
     if ($this->_storage->getAssociationByHandle($params['openid_assoc_handle'], $url, $macFunc, $secret, $expires)) {
         $signed = explode(',', $params['openid_signed']);
         $data = '';
         foreach ($signed as $key) {
             $data .= $key . ':' . $params['openid_' . strtr($key, '.', '_')] . "\n";
         }
         if (base64_decode($params['openid_sig']) == Zend_OpenId::hashHmac($macFunc, $data, $secret)) {
             if (!Zend_OpenId_Extension::forAll($extensions, 'parseResponse', $params)) {
                 return false;
             }
             /* OpenID 2.0 (11.2) Verifying Discovered Information */
             if (isset($params['openid_claimed_id'])) {
                 $id = $params['openid_claimed_id'];
                 if (!Zend_OpenId::normalize($id) || !$this->_discovery($id, $discovered_server, $discovered_version) || isset($params['openid_identity']) && $params["openid_identity"] != $id || isset($params['openid_op_endpoint']) && $params['openid_op_endpoint'] != $discovered_server || $discovered_version != $version) {
                     return false;
                 }
             }
             return true;
         }
         $this->_storage->delAssociation($url);
         return false;
     } else {
         /* Use dumb mode */
         if (isset($params['openid_claimed_id'])) {
             $id = $params['openid_claimed_id'];
         } else {
             if (isset($params['openid_identity'])) {
                 $id = $params['openid_identity'];
             } else {
                 return false;
             }
         }
         if (!$this->_discovery($id, $server, $discovered_version)) {
             return false;
         }
         /* OpenID 2.0 (11.2) Verifying Discovered Information */
         if (isset($params['openid_identity']) && $params["openid_identity"] != $id || isset($params['openid_op_endpoint']) && $params['openid_op_endpoint'] != $server || $discovered_version != $version) {
             return false;
         }
         $params2 = array();
         foreach ($params as $key => $val) {
             if (strpos($key, 'openid_ns_') === 0) {
                 $key = 'openid.ns.' . substr($key, strlen('openid_ns_'));
             } else {
                 if (strpos($key, 'openid_sreg_') === 0) {
                     $key = 'openid.sreg.' . substr($key, strlen('openid_sreg_'));
                 } else {
                     if (strpos($key, 'openid_') === 0) {
                         $key = 'openid.' . substr($key, strlen('openid_'));
                     }
                 }
             }
             $params2[$key] = $val;
         }
         $params2['openid.mode'] = 'check_authentication';
         $ret = $this->_httpRequest($server, 'POST', $params2, $status);
         if ($status != 200) {
             return false;
         }
         $r = array();
         if (is_string($ret)) {
             foreach (explode("\n", $ret) as $line) {
                 $line = trim($line);
                 if (!empty($line)) {
                     $x = explode(':', $line, 2);
                     if (is_array($x) && count($x) == 2) {
                         list($key, $value) = $x;
                         $r[trim($key)] = trim($value);
                     }
                 }
             }
         }
         $ret = $r;
         if (!empty($ret['invalidate_handle'])) {
             if ($this->_storage->getAssociationByHandle($ret['invalidate_handle'], $url, $macFunc, $secret, $expires)) {
                 $this->_storage->delAssociation($url);
             }
         }
         if (isset($ret['is_valid']) && $ret['is_valid'] == 'true') {
             if (!Zend_OpenId_Extension::forAll($extensions, 'parseResponse', $params)) {
                 return false;
             }
             return true;
         }
         return false;
     }
 }