📄 consumer.php
字号:
return false; } /** * @access private */ function _doIdRes($message, $endpoint, $return_to) { // Checks for presence of appropriate fields (and checks // signed list fields) $result = $this->_idResCheckForFields($message); if (Auth_OpenID::isFailure($result)) { return $result; } if (!$this->_checkReturnTo($message, $return_to)) { return new Auth_OpenID_FailureResponse(null, sprintf("return_to does not match return URL. Expected %s, got %s", $return_to, $message->getArg(Auth_OpenID_OPENID_NS, 'return_to'))); } // Verify discovery information: $result = $this->_verifyDiscoveryResults($message, $endpoint); if (Auth_OpenID::isFailure($result)) { return $result; } $endpoint = $result; $result = $this->_idResCheckSignature($message, $endpoint->server_url); if (Auth_OpenID::isFailure($result)) { return $result; } $result = $this->_idResCheckNonce($message, $endpoint); if (Auth_OpenID::isFailure($result)) { return $result; } $signed_list_str = $message->getArg(Auth_OpenID_OPENID_NS, 'signed', Auth_OpenID_NO_DEFAULT); $signed_list = explode(',', $signed_list_str); $signed_fields = Auth_OpenID::addPrefix($signed_list, "openid."); return new Auth_OpenID_SuccessResponse($endpoint, $message, $signed_fields); } /** * @access private */ function _checkReturnTo($message, $return_to) { // Check an OpenID message and its openid.return_to value // against a return_to URL from an application. Return True // on success, False on failure. // Check the openid.return_to args against args in the // original message. $result = Auth_OpenID_GenericConsumer::_verifyReturnToArgs( $message->toPostArgs()); if (Auth_OpenID::isFailure($result)) { return false; } // Check the return_to base URL against the one in the // message. $msg_return_to = $message->getArg(Auth_OpenID_OPENID_NS, 'return_to'); $return_to_parts = parse_url($return_to); $msg_return_to_parts = parse_url($msg_return_to); // If port is absent from both, add it so it's equal in the // check below. if ((!array_key_exists('port', $return_to_parts)) && (!array_key_exists('port', $msg_return_to_parts))) { $return_to_parts['port'] = null; $msg_return_to_parts['port'] = null; } // If path is absent from both, add it so it's equal in the // check below. if ((!array_key_exists('path', $return_to_parts)) && (!array_key_exists('path', $msg_return_to_parts))) { $return_to_parts['path'] = null; $msg_return_to_parts['path'] = null; } // The URL scheme, authority, and path MUST be the same // between the two URLs. foreach (array('scheme', 'host', 'port', 'path') as $component) { // If the url component is absent in either URL, fail. // There should always be a scheme, host, port, and path. if (!array_key_exists($component, $return_to_parts)) { return false; } if (!array_key_exists($component, $msg_return_to_parts)) { return false; } if (Auth_OpenID::arrayGet($return_to_parts, $component) !== Auth_OpenID::arrayGet($msg_return_to_parts, $component)) { return false; } } return true; } /** * @access private */ function _verifyReturnToArgs($query) { // Verify that the arguments in the return_to URL are present in this // response. $message = Auth_OpenID_Message::fromPostArgs($query); $return_to = $message->getArg(Auth_OpenID_OPENID_NS, 'return_to'); // XXX: this should be checked by _idResCheckForFields if (!$return_to) { return new Auth_OpenID_FailureResponse(null, "Response has no return_to"); } $parsed_url = parse_url($return_to); $q = array(); if (array_key_exists('query', $parsed_url)) { $rt_query = $parsed_url['query']; $q = Auth_OpenID::parse_str($rt_query); } foreach ($q as $rt_key => $rt_value) { if (!array_key_exists($rt_key, $query)) { return new Auth_OpenID_FailureResponse(null, sprintf("return_to parameter %s absent from query", $rt_key)); } else { $value = $query[$rt_key]; if ($rt_value != $value) { return new Auth_OpenID_FailureResponse(null, sprintf("parameter %s value %s does not match " . "return_to value %s", $rt_key, $value, $rt_value)); } } } // Make sure all non-OpenID arguments in the response are also // in the signed return_to. $bare_args = $message->getArgs(Auth_OpenID_BARE_NS); foreach ($bare_args as $key => $value) { if (Auth_OpenID::arrayGet($q, $key) != $value) { return new Auth_OpenID_FailureResponse(null, sprintf("Parameter %s = %s not in return_to URL", $key, $value)); } } return true; } /** * @access private */ function _idResCheckSignature($message, $server_url) { $assoc_handle = $message->getArg(Auth_OpenID_OPENID_NS, 'assoc_handle'); $assoc = $this->store->getAssociation($server_url, $assoc_handle); if ($assoc) { if ($assoc->getExpiresIn() <= 0) { // XXX: It might be a good idea sometimes to re-start // the authentication with a new association. Doing it // automatically opens the possibility for // denial-of-service by a server that just returns // expired associations (or really short-lived // associations) return new Auth_OpenID_FailureResponse(null, 'Association with ' . $server_url . ' expired'); } if (!$assoc->checkMessageSignature($message)) { return new Auth_OpenID_FailureResponse(null, "Bad signature"); } } else { // It's not an association we know about. Stateless mode // is our only possible path for recovery. XXX - async // framework will not want to block on this call to // _checkAuth. if (!$this->_checkAuth($message, $server_url)) { return new Auth_OpenID_FailureResponse(null, "Server denied check_authentication"); } } return null; } /** * @access private */ function _verifyDiscoveryResults($message, $endpoint=null) { if ($message->getOpenIDNamespace() == Auth_OpenID_OPENID2_NS) { return $this->_verifyDiscoveryResultsOpenID2($message, $endpoint); } else { return $this->_verifyDiscoveryResultsOpenID1($message, $endpoint); } } /** * @access private */ function _verifyDiscoveryResultsOpenID1($message, $endpoint) { $claimed_id = $message->getArg(Auth_OpenID_BARE_NS, $this->openid1_return_to_identifier_name); if (($endpoint === null) && ($claimed_id === null)) { return new Auth_OpenID_FailureResponse($endpoint, 'When using OpenID 1, the claimed ID must be supplied, ' . 'either by passing it through as a return_to parameter ' . 'or by using a session, and supplied to the GenericConsumer ' . 'as the argument to complete()'); } else if (($endpoint !== null) && ($claimed_id === null)) { $claimed_id = $endpoint->claimed_id; } $to_match = new Auth_OpenID_ServiceEndpoint(); $to_match->type_uris = array(Auth_OpenID_TYPE_1_1); $to_match->local_id = $message->getArg(Auth_OpenID_OPENID1_NS, 'identity'); // Restore delegate information from the initiation phase $to_match->claimed_id = $claimed_id; if ($to_match->local_id === null) { return new Auth_OpenID_FailureResponse($endpoint, "Missing required field openid.identity"); } $to_match_1_0 = $to_match->copy(); $to_match_1_0->type_uris = array(Auth_OpenID_TYPE_1_0); if ($endpoint !== null) { $result = $this->_verifyDiscoverySingle($endpoint, $to_match); if (is_a($result, 'Auth_OpenID_TypeURIMismatch')) { $result = $this->_verifyDiscoverySingle($endpoint, $to_match_1_0); } if (Auth_OpenID::isFailure($result)) { // oidutil.log("Error attempting to use stored // discovery information: " + str(e)) // oidutil.log("Attempting discovery to // verify endpoint") } else { return $endpoint; } } // Endpoint is either bad (failed verification) or None $result = $this->_discoverAndVerify($to_match); if (is_a($result, 'Auth_OpenID_TypeURIMismatch')) { return $this->_discoverAndVerify($to_match_1_0); } else { return $result; } } /** * @access private */ function _verifyDiscoverySingle($endpoint, $to_match) { // Every type URI that's in the to_match endpoint has to be // present in the discovered endpoint. foreach ($to_match->type_uris as $type_uri) { if (!$endpoint->usesExtension($type_uri)) { return new Auth_OpenID_TypeURIMismatch($endpoint, "Required type ".$type_uri." not present"); } } // Fragments do not influence discovery, so we can't compare a // claimed identifier with a fragment to discovered // information. list($defragged_claimed_id, $_) = Auth_OpenID::urldefrag($to_match->claimed_id); if ($defragged_claimed_id != $endpoint->claimed_id) { return new Auth_OpenID_FailureResponse($endpoint, sprintf('Claimed ID does not match (different subjects!), ' . 'Expected %s, got %s', $defragged_claimed_id, $endpoint->claimed_id)); } if ($to_match->getLocalID() != $endpoint->getLocalID()) { return new Auth_OpenID_FailureResponse($endpoint, sprintf('local_id mismatch. Expected %s, got %s', $to_match->getLocalID(), $endpoint->getLocalID())); } // If the server URL is None, this must be an OpenID 1 // response, because op_endpoint is a required parameter in // OpenID 2. In that case, we don't actually care what the // discovered server_url is, because signature checking or // check_auth should take care of that check for us. if ($to_match->server_url === null) { if ($to_match->preferredNamespace() != Auth_OpenID_OPENID1_NS) { return new Auth_OpenID_FailureResponse($endpoint, "Preferred namespace mismatch (bug)"); } } else if ($to_match->server_url != $endpoint->server_url) { return new Auth_OpenID_FailureResponse($endpoint, sprintf('OP Endpoint mismatch. Expected %s, got %s', $to_match->server_url, $endpoint->server_url)); } return null; } /** * @access private */ function _verifyDiscoveryResultsOpenID2($message, $endpoint) { $to_match = new Auth_OpenID_ServiceEndpoint(); $to_match->type_uris = array(Auth_OpenID_TYPE_2_0); $to_match->claimed_id = $message->getArg(Auth_OpenID_OPENID2_NS, 'claimed_id'); $to_match->local_id = $message->getArg(Auth_OpenID_OPENID2_NS, 'identity'); $to_match->server_url = $message->getArg(Auth_OpenID_OPENID2_NS, 'op_endpoint'); if ($to_match->server_url === null) { return new Auth_OpenID_FailureResponse($endpoint, "OP Endpoint URL missing"); } // claimed_id and identifier must both be present or both be // absent if (($to_match->claimed_id === null) && ($to_match->local_id !== null)) { return new Auth_OpenID_FailureResponse($endpoint, 'openid.identity is present without openid.claimed_id'); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -