| 42 | aurelien | 1 | <?php
 | 
        
           |  |  | 2 |   | 
        
           |  |  | 3 | /**
 | 
        
           |  |  | 4 |  * OpenID server protocol and logic.
 | 
        
           |  |  | 5 |  *
 | 
        
           |  |  | 6 |  * Overview
 | 
        
           |  |  | 7 |  *
 | 
        
           |  |  | 8 |  * An OpenID server must perform three tasks:
 | 
        
           |  |  | 9 |  *
 | 
        
           |  |  | 10 |  *  1. Examine the incoming request to determine its nature and validity.
 | 
        
           |  |  | 11 |  *  2. Make a decision about how to respond to this request.
 | 
        
           |  |  | 12 |  *  3. Format the response according to the protocol.
 | 
        
           |  |  | 13 |  *
 | 
        
           |  |  | 14 |  * The first and last of these tasks may performed by the
 | 
        
           |  |  | 15 |  * 'decodeRequest' and 'encodeResponse' methods of the
 | 
        
           |  |  | 16 |  * Auth_OpenID_Server object.  Who gets to do the intermediate task --
 | 
        
           |  |  | 17 |  * deciding how to respond to the request -- will depend on what type
 | 
        
           |  |  | 18 |  * of request it is.
 | 
        
           |  |  | 19 |  *
 | 
        
           |  |  | 20 |  * If it's a request to authenticate a user (a 'checkid_setup' or
 | 
        
           |  |  | 21 |  * 'checkid_immediate' request), you need to decide if you will assert
 | 
        
           |  |  | 22 |  * that this user may claim the identity in question.  Exactly how you
 | 
        
           |  |  | 23 |  * do that is a matter of application policy, but it generally
 | 
        
           |  |  | 24 |  * involves making sure the user has an account with your system and
 | 
        
           |  |  | 25 |  * is logged in, checking to see if that identity is hers to claim,
 | 
        
           |  |  | 26 |  * and verifying with the user that she does consent to releasing that
 | 
        
           |  |  | 27 |  * information to the party making the request.
 | 
        
           |  |  | 28 |  *
 | 
        
           |  |  | 29 |  * Examine the properties of the Auth_OpenID_CheckIDRequest object,
 | 
        
           |  |  | 30 |  * and if and when you've come to a decision, form a response by
 | 
        
           |  |  | 31 |  * calling Auth_OpenID_CheckIDRequest::answer.
 | 
        
           |  |  | 32 |  *
 | 
        
           |  |  | 33 |  * Other types of requests relate to establishing associations between
 | 
        
           |  |  | 34 |  * client and server and verifing the authenticity of previous
 | 
        
           |  |  | 35 |  * communications.  Auth_OpenID_Server contains all the logic and data
 | 
        
           |  |  | 36 |  * necessary to respond to such requests; just pass it to
 | 
        
           |  |  | 37 |  * Auth_OpenID_Server::handleRequest.
 | 
        
           |  |  | 38 |  *
 | 
        
           |  |  | 39 |  * OpenID Extensions
 | 
        
           |  |  | 40 |  *
 | 
        
           |  |  | 41 |  * Do you want to provide other information for your users in addition
 | 
        
           |  |  | 42 |  * to authentication?  Version 1.2 of the OpenID protocol allows
 | 
        
           |  |  | 43 |  * consumers to add extensions to their requests.  For example, with
 | 
        
           |  |  | 44 |  * sites using the Simple Registration
 | 
        
           |  |  | 45 |  * Extension
 | 
        
           |  |  | 46 |  * (http://www.openidenabled.com/openid/simple-registration-extension/),
 | 
        
           |  |  | 47 |  * a user can agree to have their nickname and e-mail address sent to
 | 
        
           |  |  | 48 |  * a site when they sign up.
 | 
        
           |  |  | 49 |  *
 | 
        
           |  |  | 50 |  * Since extensions do not change the way OpenID authentication works,
 | 
        
           |  |  | 51 |  * code to handle extension requests may be completely separate from
 | 
        
           |  |  | 52 |  * the Auth_OpenID_Request class here.  But you'll likely want data
 | 
        
           |  |  | 53 |  * sent back by your extension to be signed.  Auth_OpenID_Response
 | 
        
           |  |  | 54 |  * provides methods with which you can add data to it which can be
 | 
        
           |  |  | 55 |  * signed with the other data in the OpenID signature.
 | 
        
           |  |  | 56 |  *
 | 
        
           |  |  | 57 |  * For example:
 | 
        
           |  |  | 58 |  *
 | 
        
           |  |  | 59 |  *   //  when request is a checkid_* request
 | 
        
           |  |  | 60 |  *   response = request.answer(True)
 | 
        
           |  |  | 61 |  *   // this will a signed 'openid.sreg.timezone' parameter to the response
 | 
        
           |  |  | 62 |  *   response.addField('sreg', 'timezone', 'America/Los_Angeles')
 | 
        
           |  |  | 63 |  *
 | 
        
           |  |  | 64 |  * Stores
 | 
        
           |  |  | 65 |  *
 | 
        
           |  |  | 66 |  * The OpenID server needs to maintain state between requests in order
 | 
        
           |  |  | 67 |  * to function.  Its mechanism for doing this is called a store.  The
 | 
        
           |  |  | 68 |  * store interface is defined in Interface.php.  Additionally, several
 | 
        
           |  |  | 69 |  * concrete store implementations are provided, so that most sites
 | 
        
           |  |  | 70 |  * won't need to implement a custom store.  For a store backed by flat
 | 
        
           |  |  | 71 |  * files on disk, see Auth_OpenID_FileStore.  For stores based on
 | 
        
           |  |  | 72 |  * MySQL, SQLite, or PostgreSQL, see the Auth_OpenID_SQLStore
 | 
        
           |  |  | 73 |  * subclasses.
 | 
        
           |  |  | 74 |  *
 | 
        
           |  |  | 75 |  * Upgrading
 | 
        
           |  |  | 76 |  *
 | 
        
           |  |  | 77 |  * The keys by which a server looks up associations in its store have
 | 
        
           |  |  | 78 |  * changed in version 1.2 of this library.  If your store has entries
 | 
        
           |  |  | 79 |  * created from version 1.0 code, you should empty it.
 | 
        
           |  |  | 80 |  *
 | 
        
           |  |  | 81 |  * PHP versions 4 and 5
 | 
        
           |  |  | 82 |  *
 | 
        
           |  |  | 83 |  * LICENSE: See the COPYING file included in this distribution.
 | 
        
           |  |  | 84 |  *
 | 
        
           |  |  | 85 |  * @package OpenID
 | 
        
           |  |  | 86 |  * @author JanRain, Inc. <openid@janrain.com>
 | 
        
           |  |  | 87 |  * @copyright 2005 Janrain, Inc.
 | 
        
           |  |  | 88 |  * @license http://www.gnu.org/copyleft/lesser.html LGPL
 | 
        
           |  |  | 89 |  */
 | 
        
           |  |  | 90 |   | 
        
           |  |  | 91 | /**
 | 
        
           |  |  | 92 |  * Required imports
 | 
        
           |  |  | 93 |  */
 | 
        
           |  |  | 94 | require_once "Auth/OpenID.php";
 | 
        
           |  |  | 95 | require_once "Auth/OpenID/Association.php";
 | 
        
           |  |  | 96 | require_once "Auth/OpenID/CryptUtil.php";
 | 
        
           |  |  | 97 | require_once "Auth/OpenID/BigMath.php";
 | 
        
           |  |  | 98 | require_once "Auth/OpenID/DiffieHellman.php";
 | 
        
           |  |  | 99 | require_once "Auth/OpenID/KVForm.php";
 | 
        
           |  |  | 100 | require_once "Auth/OpenID/TrustRoot.php";
 | 
        
           |  |  | 101 | require_once "Auth/OpenID/ServerRequest.php";
 | 
        
           |  |  | 102 |   | 
        
           |  |  | 103 | define('AUTH_OPENID_HTTP_OK', 200);
 | 
        
           |  |  | 104 | define('AUTH_OPENID_HTTP_REDIRECT', 302);
 | 
        
           |  |  | 105 | define('AUTH_OPENID_HTTP_ERROR', 400);
 | 
        
           |  |  | 106 |   | 
        
           |  |  | 107 | global $_Auth_OpenID_Request_Modes,
 | 
        
           |  |  | 108 |     $_Auth_OpenID_OpenID_Prefix,
 | 
        
           |  |  | 109 |     $_Auth_OpenID_Encode_Kvform,
 | 
        
           |  |  | 110 |     $_Auth_OpenID_Encode_Url;
 | 
        
           |  |  | 111 |   | 
        
           |  |  | 112 | /**
 | 
        
           |  |  | 113 |  * @access private
 | 
        
           |  |  | 114 |  */
 | 
        
           |  |  | 115 | $_Auth_OpenID_Request_Modes = array('checkid_setup',
 | 
        
           |  |  | 116 |                                     'checkid_immediate');
 | 
        
           |  |  | 117 |   | 
        
           |  |  | 118 | /**
 | 
        
           |  |  | 119 |  * @access private
 | 
        
           |  |  | 120 |  */
 | 
        
           |  |  | 121 | $_Auth_OpenID_OpenID_Prefix = "openid.";
 | 
        
           |  |  | 122 |   | 
        
           |  |  | 123 | /**
 | 
        
           |  |  | 124 |  * @access private
 | 
        
           |  |  | 125 |  */
 | 
        
           |  |  | 126 | $_Auth_OpenID_Encode_Kvform = array('kfvorm');
 | 
        
           |  |  | 127 |   | 
        
           |  |  | 128 | /**
 | 
        
           |  |  | 129 |  * @access private
 | 
        
           |  |  | 130 |  */
 | 
        
           |  |  | 131 | $_Auth_OpenID_Encode_Url = array('URL/redirect');
 | 
        
           |  |  | 132 |   | 
        
           |  |  | 133 | /**
 | 
        
           |  |  | 134 |  * @access private
 | 
        
           |  |  | 135 |  */
 | 
        
           |  |  | 136 | function _isError($obj, $cls = 'Auth_OpenID_ServerError')
 | 
        
           |  |  | 137 | {
 | 
        
           |  |  | 138 |     return is_a($obj, $cls);
 | 
        
           |  |  | 139 | }
 | 
        
           |  |  | 140 |   | 
        
           |  |  | 141 | /**
 | 
        
           |  |  | 142 |  * An error class which gets instantiated and returned whenever an
 | 
        
           |  |  | 143 |  * OpenID protocol error occurs.  Be prepared to use this in place of
 | 
        
           |  |  | 144 |  * an ordinary server response.
 | 
        
           |  |  | 145 |  *
 | 
        
           |  |  | 146 |  * @package OpenID
 | 
        
           |  |  | 147 |  */
 | 
        
           |  |  | 148 | class Auth_OpenID_ServerError {
 | 
        
           |  |  | 149 |     /**
 | 
        
           |  |  | 150 |      * @access private
 | 
        
           |  |  | 151 |      */
 | 
        
           |  |  | 152 |     function Auth_OpenID_ServerError($query = null, $message = null)
 | 
        
           |  |  | 153 |     {
 | 
        
           |  |  | 154 |         $this->message = $message;
 | 
        
           |  |  | 155 |         $this->query = $query;
 | 
        
           |  |  | 156 |     }
 | 
        
           |  |  | 157 |   | 
        
           |  |  | 158 |     /**
 | 
        
           |  |  | 159 |      * Returns the return_to URL for the request which caused this
 | 
        
           |  |  | 160 |      * error.
 | 
        
           |  |  | 161 |      */
 | 
        
           |  |  | 162 |     function hasReturnTo()
 | 
        
           |  |  | 163 |     {
 | 
        
           |  |  | 164 |         global $_Auth_OpenID_OpenID_Prefix;
 | 
        
           |  |  | 165 |         if ($this->query) {
 | 
        
           |  |  | 166 |             return array_key_exists($_Auth_OpenID_OpenID_Prefix .
 | 
        
           |  |  | 167 |                                     'return_to', $this->query);
 | 
        
           |  |  | 168 |         } else {
 | 
        
           |  |  | 169 |             return false;
 | 
        
           |  |  | 170 |         }
 | 
        
           |  |  | 171 |     }
 | 
        
           |  |  | 172 |   | 
        
           |  |  | 173 |     /**
 | 
        
           |  |  | 174 |      * Encodes this error's response as a URL suitable for
 | 
        
           |  |  | 175 |      * redirection.  If the response has no return_to, another
 | 
        
           |  |  | 176 |      * Auth_OpenID_ServerError is returned.
 | 
        
           |  |  | 177 |      */
 | 
        
           |  |  | 178 |     function encodeToURL()
 | 
        
           |  |  | 179 |     {
 | 
        
           |  |  | 180 |         global $_Auth_OpenID_OpenID_Prefix;
 | 
        
           |  |  | 181 |         $return_to = Auth_OpenID::arrayGet($this->query,
 | 
        
           |  |  | 182 |                                            $_Auth_OpenID_OpenID_Prefix .
 | 
        
           |  |  | 183 |                                            'return_to');
 | 
        
           |  |  | 184 |         if (!$return_to) {
 | 
        
           |  |  | 185 |             return new Auth_OpenID_ServerError(null, "no return_to URL");
 | 
        
           |  |  | 186 |         }
 | 
        
           |  |  | 187 |   | 
        
           |  |  | 188 |         return Auth_OpenID::appendArgs($return_to,
 | 
        
           |  |  | 189 |                             array('openid.mode' => 'error',
 | 
        
           |  |  | 190 |                                   'openid.error' => $this->toString()));
 | 
        
           |  |  | 191 |     }
 | 
        
           |  |  | 192 |   | 
        
           |  |  | 193 |     /**
 | 
        
           |  |  | 194 |      * Encodes the response to key-value form.  This is a
 | 
        
           |  |  | 195 |      * machine-readable format used to respond to messages which came
 | 
        
           |  |  | 196 |      * directly from the consumer and not through the user-agent.  See
 | 
        
           |  |  | 197 |      * the OpenID specification.
 | 
        
           |  |  | 198 |      */
 | 
        
           |  |  | 199 |     function encodeToKVForm()
 | 
        
           |  |  | 200 |     {
 | 
        
           |  |  | 201 |         return Auth_OpenID_KVForm::fromArray(
 | 
        
           |  |  | 202 |                                       array('mode' => 'error',
 | 
        
           |  |  | 203 |                                             'error' => $this->toString()));
 | 
        
           |  |  | 204 |     }
 | 
        
           |  |  | 205 |   | 
        
           |  |  | 206 |     /**
 | 
        
           |  |  | 207 |      * Returns one of $_Auth_OpenID_Encode_Url,
 | 
        
           |  |  | 208 |      * $_Auth_OpenID_Encode_Kvform, or null, depending on the type of
 | 
        
           |  |  | 209 |      * encoding expected for this error's payload.
 | 
        
           |  |  | 210 |      */
 | 
        
           |  |  | 211 |     function whichEncoding()
 | 
        
           |  |  | 212 |     {
 | 
        
           |  |  | 213 |         global $_Auth_OpenID_Encode_Url,
 | 
        
           |  |  | 214 |             $_Auth_OpenID_Encode_Kvform,
 | 
        
           |  |  | 215 |             $_Auth_OpenID_Request_Modes;
 | 
        
           |  |  | 216 |   | 
        
           |  |  | 217 |         if ($this->hasReturnTo()) {
 | 
        
           |  |  | 218 |             return $_Auth_OpenID_Encode_Url;
 | 
        
           |  |  | 219 |         }
 | 
        
           |  |  | 220 |   | 
        
           |  |  | 221 |         $mode = Auth_OpenID::arrayGet($this->query, 'openid.mode');
 | 
        
           |  |  | 222 |   | 
        
           |  |  | 223 |         if ($mode) {
 | 
        
           |  |  | 224 |             if (!in_array($mode, $_Auth_OpenID_Request_Modes)) {
 | 
        
           |  |  | 225 |                 return $_Auth_OpenID_Encode_Kvform;
 | 
        
           |  |  | 226 |             }
 | 
        
           |  |  | 227 |         }
 | 
        
           |  |  | 228 |         return null;
 | 
        
           |  |  | 229 |     }
 | 
        
           |  |  | 230 |   | 
        
           |  |  | 231 |     /**
 | 
        
           |  |  | 232 |      * Returns this error message.
 | 
        
           |  |  | 233 |      */
 | 
        
           |  |  | 234 |     function toString()
 | 
        
           |  |  | 235 |     {
 | 
        
           |  |  | 236 |         if ($this->message) {
 | 
        
           |  |  | 237 |             return $this->message;
 | 
        
           |  |  | 238 |         } else {
 | 
        
           |  |  | 239 |             return get_class($this) . " error";
 | 
        
           |  |  | 240 |         }
 | 
        
           |  |  | 241 |     }
 | 
        
           |  |  | 242 | }
 | 
        
           |  |  | 243 |   | 
        
           |  |  | 244 | /**
 | 
        
           |  |  | 245 |  * An error indicating that the return_to URL is malformed.
 | 
        
           |  |  | 246 |  *
 | 
        
           |  |  | 247 |  * @package OpenID
 | 
        
           |  |  | 248 |  */
 | 
        
           |  |  | 249 | class Auth_OpenID_MalformedReturnURL extends Auth_OpenID_ServerError {
 | 
        
           |  |  | 250 |     function Auth_OpenID_MalformedReturnURL($query, $return_to)
 | 
        
           |  |  | 251 |     {
 | 
        
           |  |  | 252 |         $this->return_to = $return_to;
 | 
        
           |  |  | 253 |         parent::Auth_OpenID_ServerError($query, "malformed return_to URL");
 | 
        
           |  |  | 254 |     }
 | 
        
           |  |  | 255 | }
 | 
        
           |  |  | 256 |   | 
        
           |  |  | 257 | /**
 | 
        
           |  |  | 258 |  * This error is returned when the trust_root value is malformed.
 | 
        
           |  |  | 259 |  *
 | 
        
           |  |  | 260 |  * @package OpenID
 | 
        
           |  |  | 261 |  */
 | 
        
           |  |  | 262 | class Auth_OpenID_MalformedTrustRoot extends Auth_OpenID_ServerError {
 | 
        
           |  |  | 263 |     function toString()
 | 
        
           |  |  | 264 |     {
 | 
        
           |  |  | 265 |         return "Malformed trust root";
 | 
        
           |  |  | 266 |     }
 | 
        
           |  |  | 267 | }
 | 
        
           |  |  | 268 |   | 
        
           |  |  | 269 | /**
 | 
        
           |  |  | 270 |  * The base class for all server request classes.
 | 
        
           |  |  | 271 |  *
 | 
        
           |  |  | 272 |  * @access private
 | 
        
           |  |  | 273 |  * @package OpenID
 | 
        
           |  |  | 274 |  */
 | 
        
           |  |  | 275 | class Auth_OpenID_Request {
 | 
        
           |  |  | 276 |     var $mode = null;
 | 
        
           |  |  | 277 | }
 | 
        
           |  |  | 278 |   | 
        
           |  |  | 279 | /**
 | 
        
           |  |  | 280 |  * A request to verify the validity of a previous response.
 | 
        
           |  |  | 281 |  *
 | 
        
           |  |  | 282 |  * @access private
 | 
        
           |  |  | 283 |  * @package OpenID
 | 
        
           |  |  | 284 |  */
 | 
        
           |  |  | 285 | class Auth_OpenID_CheckAuthRequest extends Auth_OpenID_Request {
 | 
        
           |  |  | 286 |     var $mode = "check_authentication";
 | 
        
           |  |  | 287 |     var $invalidate_handle = null;
 | 
        
           |  |  | 288 |   | 
        
           |  |  | 289 |     function Auth_OpenID_CheckAuthRequest($assoc_handle, $sig, $signed,
 | 
        
           |  |  | 290 |                                           $invalidate_handle = null)
 | 
        
           |  |  | 291 |     {
 | 
        
           |  |  | 292 |         $this->assoc_handle = $assoc_handle;
 | 
        
           |  |  | 293 |         $this->sig = $sig;
 | 
        
           |  |  | 294 |         $this->signed = $signed;
 | 
        
           |  |  | 295 |         if ($invalidate_handle !== null) {
 | 
        
           |  |  | 296 |             $this->invalidate_handle = $invalidate_handle;
 | 
        
           |  |  | 297 |         }
 | 
        
           |  |  | 298 |     }
 | 
        
           |  |  | 299 |   | 
        
           |  |  | 300 |     function fromQuery($query)
 | 
        
           |  |  | 301 |     {
 | 
        
           |  |  | 302 |         global $_Auth_OpenID_OpenID_Prefix;
 | 
        
           |  |  | 303 |   | 
        
           |  |  | 304 |         $required_keys = array('assoc_handle', 'sig', 'signed');
 | 
        
           |  |  | 305 |   | 
        
           |  |  | 306 |         foreach ($required_keys as $k) {
 | 
        
           |  |  | 307 |             if (!array_key_exists($_Auth_OpenID_OpenID_Prefix . $k,
 | 
        
           |  |  | 308 |                                   $query)) {
 | 
        
           |  |  | 309 |                 return new Auth_OpenID_ServerError($query,
 | 
        
           |  |  | 310 |                     sprintf("%s request missing required parameter %s from \
 | 
        
           |  |  | 311 |                             query", "check_authentication", $k));
 | 
        
           |  |  | 312 |             }
 | 
        
           |  |  | 313 |         }
 | 
        
           |  |  | 314 |   | 
        
           |  |  | 315 |         $assoc_handle = $query[$_Auth_OpenID_OpenID_Prefix . 'assoc_handle'];
 | 
        
           |  |  | 316 |         $sig = $query[$_Auth_OpenID_OpenID_Prefix . 'sig'];
 | 
        
           |  |  | 317 |         $signed_list = $query[$_Auth_OpenID_OpenID_Prefix . 'signed'];
 | 
        
           |  |  | 318 |   | 
        
           |  |  | 319 |         $signed_list = explode(",", $signed_list);
 | 
        
           |  |  | 320 |         $signed_pairs = array();
 | 
        
           |  |  | 321 |   | 
        
           |  |  | 322 |         foreach ($signed_list as $field) {
 | 
        
           |  |  | 323 |             if ($field == 'mode') {
 | 
        
           |  |  | 324 |                 // XXX KLUDGE HAX WEB PROTOCoL BR0KENNN
 | 
        
           |  |  | 325 |                 //
 | 
        
           |  |  | 326 |                 // openid.mode is currently check_authentication
 | 
        
           |  |  | 327 |                 // because that's the mode of this request.  But the
 | 
        
           |  |  | 328 |                 // signature was made on something with a different
 | 
        
           |  |  | 329 |                 // openid.mode.
 | 
        
           |  |  | 330 |                 $value = "id_res";
 | 
        
           |  |  | 331 |             } else {
 | 
        
           |  |  | 332 |                 if (array_key_exists($_Auth_OpenID_OpenID_Prefix . $field,
 | 
        
           |  |  | 333 |                                      $query)) {
 | 
        
           |  |  | 334 |                     $value = $query[$_Auth_OpenID_OpenID_Prefix . $field];
 | 
        
           |  |  | 335 |                 } else {
 | 
        
           |  |  | 336 |                     return new Auth_OpenID_ServerError($query,
 | 
        
           |  |  | 337 |                           sprintf("Couldn't find signed field %r in query %s",
 | 
        
           |  |  | 338 |                                   $field, var_export($query, true)));
 | 
        
           |  |  | 339 |                 }
 | 
        
           |  |  | 340 |             }
 | 
        
           |  |  | 341 |             $signed_pairs[] = array($field, $value);
 | 
        
           |  |  | 342 |         }
 | 
        
           |  |  | 343 |   | 
        
           |  |  | 344 |         $result = new Auth_OpenID_CheckAuthRequest($assoc_handle, $sig,
 | 
        
           |  |  | 345 |                                                    $signed_pairs);
 | 
        
           |  |  | 346 |         $result->invalidate_handle = Auth_OpenID::arrayGet($query,
 | 
        
           |  |  | 347 |                     $_Auth_OpenID_OpenID_Prefix . 'invalidate_handle');
 | 
        
           |  |  | 348 |         return $result;
 | 
        
           |  |  | 349 |     }
 | 
        
           |  |  | 350 |   | 
        
           |  |  | 351 |     function answer(&$signatory)
 | 
        
           |  |  | 352 |     {
 | 
        
           |  |  | 353 |         $is_valid = $signatory->verify($this->assoc_handle, $this->sig,
 | 
        
           |  |  | 354 |                                        $this->signed);
 | 
        
           |  |  | 355 |   | 
        
           |  |  | 356 |         // Now invalidate that assoc_handle so it this checkAuth
 | 
        
           |  |  | 357 |         // message cannot be replayed.
 | 
        
           |  |  | 358 |         $signatory->invalidate($this->assoc_handle, true);
 | 
        
           |  |  | 359 |         $response = new Auth_OpenID_ServerResponse($this);
 | 
        
           |  |  | 360 |         $response->fields['is_valid'] = $is_valid ? "true" : "false";
 | 
        
           |  |  | 361 |   | 
        
           |  |  | 362 |         if ($this->invalidate_handle) {
 | 
        
           |  |  | 363 |             $assoc = $signatory->getAssociation($this->invalidate_handle,
 | 
        
           |  |  | 364 |                                                 false);
 | 
        
           |  |  | 365 |             if (!$assoc) {
 | 
        
           |  |  | 366 |                 $response->fields['invalidate_handle'] =
 | 
        
           |  |  | 367 |                     $this->invalidate_handle;
 | 
        
           |  |  | 368 |             }
 | 
        
           |  |  | 369 |         }
 | 
        
           |  |  | 370 |         return $response;
 | 
        
           |  |  | 371 |     }
 | 
        
           |  |  | 372 | }
 | 
        
           |  |  | 373 |   | 
        
           |  |  | 374 | class Auth_OpenID_PlainTextServerSession {
 | 
        
           |  |  | 375 |     /**
 | 
        
           |  |  | 376 |      * An object that knows how to handle association requests with no
 | 
        
           |  |  | 377 |      * session type.
 | 
        
           |  |  | 378 |      */
 | 
        
           |  |  | 379 |     var $session_type = 'plaintext';
 | 
        
           |  |  | 380 |   | 
        
           |  |  | 381 |     function fromQuery($unused_request)
 | 
        
           |  |  | 382 |     {
 | 
        
           |  |  | 383 |         return new Auth_OpenID_PlainTextServerSession();
 | 
        
           |  |  | 384 |     }
 | 
        
           |  |  | 385 |   | 
        
           |  |  | 386 |     function answer($secret)
 | 
        
           |  |  | 387 |     {
 | 
        
           |  |  | 388 |         return array('mac_key' => base64_encode($secret));
 | 
        
           |  |  | 389 |     }
 | 
        
           |  |  | 390 | }
 | 
        
           |  |  | 391 |   | 
        
           |  |  | 392 | class Auth_OpenID_DiffieHellmanServerSession {
 | 
        
           |  |  | 393 |     /**
 | 
        
           |  |  | 394 |      * An object that knows how to handle association requests with
 | 
        
           |  |  | 395 |      * the Diffie-Hellman session type.
 | 
        
           |  |  | 396 |      */
 | 
        
           |  |  | 397 |   | 
        
           |  |  | 398 |     var $session_type = 'DH-SHA1';
 | 
        
           |  |  | 399 |   | 
        
           |  |  | 400 |     function Auth_OpenID_DiffieHellmanServerSession($dh, $consumer_pubkey)
 | 
        
           |  |  | 401 |     {
 | 
        
           |  |  | 402 |         $this->dh = $dh;
 | 
        
           |  |  | 403 |         $this->consumer_pubkey = $consumer_pubkey;
 | 
        
           |  |  | 404 |     }
 | 
        
           |  |  | 405 |   | 
        
           |  |  | 406 |     function fromQuery($query)
 | 
        
           |  |  | 407 |     {
 | 
        
           |  |  | 408 |         $dh_modulus = Auth_OpenID::arrayGet($query, 'openid.dh_modulus');
 | 
        
           |  |  | 409 |         $dh_gen = Auth_OpenID::arrayGet($query, 'openid.dh_gen');
 | 
        
           |  |  | 410 |   | 
        
           |  |  | 411 |         if ((($dh_modulus === null) && ($dh_gen !== null)) ||
 | 
        
           |  |  | 412 |             (($dh_gen === null) && ($dh_modulus !== null))) {
 | 
        
           |  |  | 413 |   | 
        
           |  |  | 414 |             if ($dh_modulus === null) {
 | 
        
           |  |  | 415 |                 $missing = 'modulus';
 | 
        
           |  |  | 416 |             } else {
 | 
        
           |  |  | 417 |                 $missing = 'generator';
 | 
        
           |  |  | 418 |             }
 | 
        
           |  |  | 419 |   | 
        
           |  |  | 420 |             return new Auth_OpenID_ServerError(
 | 
        
           |  |  | 421 |                                 'If non-default modulus or generator is '.
 | 
        
           |  |  | 422 |                                 'supplied, both must be supplied.  Missing '.
 | 
        
           |  |  | 423 |                                 $missing);
 | 
        
           |  |  | 424 |         }
 | 
        
           |  |  | 425 |   | 
        
           |  |  | 426 |         $lib =& Auth_OpenID_getMathLib();
 | 
        
           |  |  | 427 |   | 
        
           |  |  | 428 |         if ($dh_modulus || $dh_gen) {
 | 
        
           |  |  | 429 |             $dh_modulus = $lib->base64ToLong($dh_modulus);
 | 
        
           |  |  | 430 |             $dh_gen = $lib->base64ToLong($dh_gen);
 | 
        
           |  |  | 431 |             if ($lib->cmp($dh_modulus, 0) == 0 ||
 | 
        
           |  |  | 432 |                 $lib->cmp($dh_gen, 0) == 0) {
 | 
        
           |  |  | 433 |                 return new Auth_OpenID_ServerError(
 | 
        
           |  |  | 434 |                   $query, "Failed to parse dh_mod or dh_gen");
 | 
        
           |  |  | 435 |             }
 | 
        
           |  |  | 436 |             $dh = new Auth_OpenID_DiffieHellman($dh_modulus, $dh_gen);
 | 
        
           |  |  | 437 |         } else {
 | 
        
           |  |  | 438 |             $dh = new Auth_OpenID_DiffieHellman();
 | 
        
           |  |  | 439 |         }
 | 
        
           |  |  | 440 |   | 
        
           |  |  | 441 |         $consumer_pubkey = Auth_OpenID::arrayGet($query,
 | 
        
           |  |  | 442 |                                                  'openid.dh_consumer_public');
 | 
        
           |  |  | 443 |         if ($consumer_pubkey === null) {
 | 
        
           |  |  | 444 |             return new Auth_OpenID_ServerError(
 | 
        
           |  |  | 445 |                                   'Public key for DH-SHA1 session '.
 | 
        
           |  |  | 446 |                                   'not found in query');
 | 
        
           |  |  | 447 |         }
 | 
        
           |  |  | 448 |   | 
        
           |  |  | 449 |         $consumer_pubkey =
 | 
        
           |  |  | 450 |             $lib->base64ToLong($consumer_pubkey);
 | 
        
           |  |  | 451 |   | 
        
           |  |  | 452 |         if ($consumer_pubkey === false) {
 | 
        
           |  |  | 453 |             return new Auth_OpenID_ServerError($query,
 | 
        
           |  |  | 454 |                                        "dh_consumer_public is not base64");
 | 
        
           |  |  | 455 |         }
 | 
        
           |  |  | 456 |   | 
        
           |  |  | 457 |         return new Auth_OpenID_DiffieHellmanServerSession($dh,
 | 
        
           |  |  | 458 |                                                           $consumer_pubkey);
 | 
        
           |  |  | 459 |     }
 | 
        
           |  |  | 460 |   | 
        
           |  |  | 461 |     function answer($secret)
 | 
        
           |  |  | 462 |     {
 | 
        
           |  |  | 463 |         $lib =& Auth_OpenID_getMathLib();
 | 
        
           |  |  | 464 |         $mac_key = $this->dh->xorSecret($this->consumer_pubkey, $secret);
 | 
        
           |  |  | 465 |         return array(
 | 
        
           |  |  | 466 |            'dh_server_public' =>
 | 
        
           |  |  | 467 |                 $lib->longToBase64($this->dh->public),
 | 
        
           |  |  | 468 |            'enc_mac_key' => base64_encode($mac_key));
 | 
        
           |  |  | 469 |     }
 | 
        
           |  |  | 470 | }
 | 
        
           |  |  | 471 |   | 
        
           |  |  | 472 | /**
 | 
        
           |  |  | 473 |  * A request to associate with the server.
 | 
        
           |  |  | 474 |  *
 | 
        
           |  |  | 475 |  * @access private
 | 
        
           |  |  | 476 |  * @package OpenID
 | 
        
           |  |  | 477 |  */
 | 
        
           |  |  | 478 | class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request {
 | 
        
           |  |  | 479 |     var $mode = "associate";
 | 
        
           |  |  | 480 |     var $assoc_type = 'HMAC-SHA1';
 | 
        
           |  |  | 481 |   | 
        
           |  |  | 482 |     function Auth_OpenID_AssociateRequest(&$session)
 | 
        
           |  |  | 483 |     {
 | 
        
           |  |  | 484 |         $this->session =& $session;
 | 
        
           |  |  | 485 |     }
 | 
        
           |  |  | 486 |   | 
        
           |  |  | 487 |     function fromQuery($query)
 | 
        
           |  |  | 488 |     {
 | 
        
           |  |  | 489 |         global $_Auth_OpenID_OpenID_Prefix;
 | 
        
           |  |  | 490 |   | 
        
           |  |  | 491 |         $session_classes = array(
 | 
        
           |  |  | 492 |                  'DH-SHA1' => 'Auth_OpenID_DiffieHellmanServerSession',
 | 
        
           |  |  | 493 |                  null => 'Auth_OpenID_PlainTextServerSession');
 | 
        
           |  |  | 494 |   | 
        
           |  |  | 495 |         $session_type = null;
 | 
        
           |  |  | 496 |   | 
        
           |  |  | 497 |         if (array_key_exists($_Auth_OpenID_OpenID_Prefix . 'session_type',
 | 
        
           |  |  | 498 |                              $query)) {
 | 
        
           |  |  | 499 |             $session_type = $query[$_Auth_OpenID_OpenID_Prefix .
 | 
        
           |  |  | 500 |                                    'session_type'];
 | 
        
           |  |  | 501 |         }
 | 
        
           |  |  | 502 |   | 
        
           |  |  | 503 |         if (!array_key_exists($session_type, $session_classes)) {
 | 
        
           |  |  | 504 |             return new Auth_OpenID_ServerError($query,
 | 
        
           |  |  | 505 |                                     "Unknown session type $session_type");
 | 
        
           |  |  | 506 |         }
 | 
        
           |  |  | 507 |   | 
        
           |  |  | 508 |         $session_cls = $session_classes[$session_type];
 | 
        
           |  |  | 509 |         $session = call_user_func_array(array($session_cls, 'fromQuery'),
 | 
        
           |  |  | 510 |                                         array($query));
 | 
        
           |  |  | 511 |   | 
        
           |  |  | 512 |         if (($session === null) || (_isError($session))) {
 | 
        
           |  |  | 513 |             return new Auth_OpenID_ServerError($query,
 | 
        
           |  |  | 514 |                                      "Error parsing $session_type session");
 | 
        
           |  |  | 515 |         }
 | 
        
           |  |  | 516 |   | 
        
           |  |  | 517 |         return new Auth_OpenID_AssociateRequest($session);
 | 
        
           |  |  | 518 |     }
 | 
        
           |  |  | 519 |   | 
        
           |  |  | 520 |     function answer($assoc)
 | 
        
           |  |  | 521 |     {
 | 
        
           |  |  | 522 |         $ml =& Auth_OpenID_getMathLib();
 | 
        
           |  |  | 523 |         $response = new Auth_OpenID_ServerResponse($this);
 | 
        
           |  |  | 524 |   | 
        
           |  |  | 525 |         $response->fields = array('expires_in' => $assoc->getExpiresIn(),
 | 
        
           |  |  | 526 |                                   'assoc_type' => 'HMAC-SHA1',
 | 
        
           |  |  | 527 |                                   'assoc_handle' => $assoc->handle);
 | 
        
           |  |  | 528 |   | 
        
           |  |  | 529 |         $r = $this->session->answer($assoc->secret);
 | 
        
           |  |  | 530 |         foreach ($r as $k => $v) {
 | 
        
           |  |  | 531 |             $response->fields[$k] = $v;
 | 
        
           |  |  | 532 |         }
 | 
        
           |  |  | 533 |   | 
        
           |  |  | 534 |         if ($this->session->session_type != 'plaintext') {
 | 
        
           |  |  | 535 |             $response->fields['session_type'] = $this->session->session_type;
 | 
        
           |  |  | 536 |         }
 | 
        
           |  |  | 537 |   | 
        
           |  |  | 538 |         return $response;
 | 
        
           |  |  | 539 |     }
 | 
        
           |  |  | 540 | }
 | 
        
           |  |  | 541 |   | 
        
           |  |  | 542 | /**
 | 
        
           |  |  | 543 |  * A request to confirm the identity of a user.
 | 
        
           |  |  | 544 |  *
 | 
        
           |  |  | 545 |  * @access private
 | 
        
           |  |  | 546 |  * @package OpenID
 | 
        
           |  |  | 547 |  */
 | 
        
           |  |  | 548 | class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request {
 | 
        
           |  |  | 549 |     var $mode = "checkid_setup"; // or "checkid_immediate"
 | 
        
           |  |  | 550 |     var $immediate = false;
 | 
        
           |  |  | 551 |     var $trust_root = null;
 | 
        
           |  |  | 552 |   | 
        
           |  |  | 553 |     function make($query, $identity, $return_to, $trust_root = null,
 | 
        
           |  |  | 554 |                   $immediate = false, $assoc_handle = null)
 | 
        
           |  |  | 555 |     {
 | 
        
           |  |  | 556 |         if (!Auth_OpenID_TrustRoot::_parse($return_to)) {
 | 
        
           |  |  | 557 |             return new Auth_OpenID_MalformedReturnURL($query, $return_to);
 | 
        
           |  |  | 558 |         }
 | 
        
           |  |  | 559 |   | 
        
           |  |  | 560 |         $r = new Auth_OpenID_CheckIDRequest($identity, $return_to,
 | 
        
           |  |  | 561 |                                             $trust_root, $immediate,
 | 
        
           |  |  | 562 |                                             $assoc_handle);
 | 
        
           |  |  | 563 |   | 
        
           |  |  | 564 |         if (!$r->trustRootValid()) {
 | 
        
           |  |  | 565 |             return new Auth_OpenID_UntrustedReturnURL($return_to,
 | 
        
           |  |  | 566 |                                                       $trust_root);
 | 
        
           |  |  | 567 |         } else {
 | 
        
           |  |  | 568 |             return $r;
 | 
        
           |  |  | 569 |         }
 | 
        
           |  |  | 570 |     }
 | 
        
           |  |  | 571 |   | 
        
           |  |  | 572 |     function Auth_OpenID_CheckIDRequest($identity, $return_to,
 | 
        
           |  |  | 573 |                                         $trust_root = null, $immediate = false,
 | 
        
           |  |  | 574 |                                         $assoc_handle = null)
 | 
        
           |  |  | 575 |     {
 | 
        
           |  |  | 576 |         $this->identity = $identity;
 | 
        
           |  |  | 577 |         $this->return_to = $return_to;
 | 
        
           |  |  | 578 |         $this->trust_root = $trust_root;
 | 
        
           |  |  | 579 |         $this->assoc_handle = $assoc_handle;
 | 
        
           |  |  | 580 |   | 
        
           |  |  | 581 |         if ($immediate) {
 | 
        
           |  |  | 582 |             $this->immediate = true;
 | 
        
           |  |  | 583 |             $this->mode = "checkid_immediate";
 | 
        
           |  |  | 584 |         } else {
 | 
        
           |  |  | 585 |             $this->immediate = false;
 | 
        
           |  |  | 586 |             $this->mode = "checkid_setup";
 | 
        
           |  |  | 587 |         }
 | 
        
           |  |  | 588 |     }
 | 
        
           |  |  | 589 |   | 
        
           |  |  | 590 |     function fromQuery($query)
 | 
        
           |  |  | 591 |     {
 | 
        
           |  |  | 592 |         global $_Auth_OpenID_OpenID_Prefix;
 | 
        
           |  |  | 593 |   | 
        
           |  |  | 594 |         $mode = $query[$_Auth_OpenID_OpenID_Prefix . 'mode'];
 | 
        
           |  |  | 595 |         $immediate = null;
 | 
        
           |  |  | 596 |   | 
        
           |  |  | 597 |         if ($mode == "checkid_immediate") {
 | 
        
           |  |  | 598 |             $immediate = true;
 | 
        
           |  |  | 599 |             $mode = "checkid_immediate";
 | 
        
           |  |  | 600 |         } else {
 | 
        
           |  |  | 601 |             $immediate = false;
 | 
        
           |  |  | 602 |             $mode = "checkid_setup";
 | 
        
           |  |  | 603 |         }
 | 
        
           |  |  | 604 |   | 
        
           |  |  | 605 |         $required = array('identity',
 | 
        
           |  |  | 606 |                           'return_to');
 | 
        
           |  |  | 607 |   | 
        
           |  |  | 608 |         $optional = array('trust_root',
 | 
        
           |  |  | 609 |                           'assoc_handle');
 | 
        
           |  |  | 610 |   | 
        
           |  |  | 611 |         $values = array();
 | 
        
           |  |  | 612 |   | 
        
           |  |  | 613 |         foreach ($required as $field) {
 | 
        
           |  |  | 614 |             if (array_key_exists($_Auth_OpenID_OpenID_Prefix . $field,
 | 
        
           |  |  | 615 |                                  $query)) {
 | 
        
           |  |  | 616 |                 $value = $query[$_Auth_OpenID_OpenID_Prefix . $field];
 | 
        
           |  |  | 617 |             } else {
 | 
        
           |  |  | 618 |                 return new Auth_OpenID_ServerError($query,
 | 
        
           |  |  | 619 |                                sprintf("Missing required field %s from request",
 | 
        
           |  |  | 620 |                                        $field));
 | 
        
           |  |  | 621 |             }
 | 
        
           |  |  | 622 |             $values[$field] = $value;
 | 
        
           |  |  | 623 |         }
 | 
        
           |  |  | 624 |   | 
        
           |  |  | 625 |         foreach ($optional as $field) {
 | 
        
           |  |  | 626 |             $value = null;
 | 
        
           |  |  | 627 |             if (array_key_exists($_Auth_OpenID_OpenID_Prefix . $field,
 | 
        
           |  |  | 628 |                                  $query)) {
 | 
        
           |  |  | 629 |                 $value = $query[$_Auth_OpenID_OpenID_Prefix. $field];
 | 
        
           |  |  | 630 |             }
 | 
        
           |  |  | 631 |             if ($value) {
 | 
        
           |  |  | 632 |                 $values[$field] = $value;
 | 
        
           |  |  | 633 |             }
 | 
        
           |  |  | 634 |         }
 | 
        
           |  |  | 635 |   | 
        
           |  |  | 636 |         if (!Auth_OpenID_TrustRoot::_parse($values['return_to'])) {
 | 
        
           |  |  | 637 |             return new Auth_OpenID_MalformedReturnURL($query,
 | 
        
           |  |  | 638 |                                                       $values['return_to']);
 | 
        
           |  |  | 639 |         }
 | 
        
           |  |  | 640 |   | 
        
           |  |  | 641 |         $obj = Auth_OpenID_CheckIDRequest::make($query,
 | 
        
           |  |  | 642 |                                    $values['identity'],
 | 
        
           |  |  | 643 |                                    $values['return_to'],
 | 
        
           |  |  | 644 |                                    Auth_OpenID::arrayGet($values,
 | 
        
           |  |  | 645 |                                                          'trust_root', null),
 | 
        
           |  |  | 646 |                                    $immediate);
 | 
        
           |  |  | 647 |   | 
        
           |  |  | 648 |         if (is_a($obj, 'Auth_OpenID_ServerError')) {
 | 
        
           |  |  | 649 |             return $obj;
 | 
        
           |  |  | 650 |         }
 | 
        
           |  |  | 651 |   | 
        
           |  |  | 652 |         if (Auth_OpenID::arrayGet($values, 'assoc_handle')) {
 | 
        
           |  |  | 653 |             $obj->assoc_handle = $values['assoc_handle'];
 | 
        
           |  |  | 654 |         }
 | 
        
           |  |  | 655 |   | 
        
           |  |  | 656 |         return $obj;
 | 
        
           |  |  | 657 |     }
 | 
        
           |  |  | 658 |   | 
        
           |  |  | 659 |     function trustRootValid()
 | 
        
           |  |  | 660 |     {
 | 
        
           |  |  | 661 |         if (!$this->trust_root) {
 | 
        
           |  |  | 662 |             return true;
 | 
        
           |  |  | 663 |         }
 | 
        
           |  |  | 664 |   | 
        
           |  |  | 665 |         $tr = Auth_OpenID_TrustRoot::_parse($this->trust_root);
 | 
        
           |  |  | 666 |         if ($tr === false) {
 | 
        
           |  |  | 667 |             return new Auth_OpenID_MalformedTrustRoot(null, $this->trust_root);
 | 
        
           |  |  | 668 |         }
 | 
        
           |  |  | 669 |   | 
        
           |  |  | 670 |         return Auth_OpenID_TrustRoot::match($this->trust_root,
 | 
        
           |  |  | 671 |                                             $this->return_to);
 | 
        
           |  |  | 672 |     }
 | 
        
           |  |  | 673 |   | 
        
           |  |  | 674 |     function answer($allow, $server_url = null)
 | 
        
           |  |  | 675 |     {
 | 
        
           |  |  | 676 |         if ($allow || $this->immediate) {
 | 
        
           |  |  | 677 |             $mode = 'id_res';
 | 
        
           |  |  | 678 |         } else {
 | 
        
           |  |  | 679 |             $mode = 'cancel';
 | 
        
           |  |  | 680 |         }
 | 
        
           |  |  | 681 |   | 
        
           |  |  | 682 |         $response = new Auth_OpenID_CheckIDResponse($this, $mode);
 | 
        
           |  |  | 683 |   | 
        
           |  |  | 684 |         if ($allow) {
 | 
        
           |  |  | 685 |             $response->fields['identity'] = $this->identity;
 | 
        
           |  |  | 686 |             $response->fields['return_to'] = $this->return_to;
 | 
        
           |  |  | 687 |             if (!$this->trustRootValid()) {
 | 
        
           |  |  | 688 |                 return new Auth_OpenID_UntrustedReturnURL($this->return_to,
 | 
        
           |  |  | 689 |                                                           $this->trust_root);
 | 
        
           |  |  | 690 |             }
 | 
        
           |  |  | 691 |         } else {
 | 
        
           |  |  | 692 |             $response->signed = array();
 | 
        
           |  |  | 693 |             if ($this->immediate) {
 | 
        
           |  |  | 694 |                 if (!$server_url) {
 | 
        
           |  |  | 695 |                     return new Auth_OpenID_ServerError(null,
 | 
        
           |  |  | 696 |                                  'setup_url is required for $allow=false \
 | 
        
           |  |  | 697 |                                   in immediate mode.');
 | 
        
           |  |  | 698 |                 }
 | 
        
           |  |  | 699 |   | 
        
           |  |  | 700 |                 $setup_request =& new Auth_OpenID_CheckIDRequest(
 | 
        
           |  |  | 701 |                                                 $this->identity,
 | 
        
           |  |  | 702 |                                                 $this->return_to,
 | 
        
           |  |  | 703 |                                                 $this->trust_root,
 | 
        
           |  |  | 704 |                                                 false,
 | 
        
           |  |  | 705 |                                                 $this->assoc_handle);
 | 
        
           |  |  | 706 |   | 
        
           |  |  | 707 |                 $setup_url = $setup_request->encodeToURL($server_url);
 | 
        
           |  |  | 708 |   | 
        
           |  |  | 709 |                 $response->fields['user_setup_url'] = $setup_url;
 | 
        
           |  |  | 710 |             }
 | 
        
           |  |  | 711 |         }
 | 
        
           |  |  | 712 |   | 
        
           |  |  | 713 |         return $response;
 | 
        
           |  |  | 714 |     }
 | 
        
           |  |  | 715 |   | 
        
           |  |  | 716 |     function encodeToURL($server_url)
 | 
        
           |  |  | 717 |     {
 | 
        
           |  |  | 718 |         global $_Auth_OpenID_OpenID_Prefix;
 | 
        
           |  |  | 719 |   | 
        
           |  |  | 720 |         // Imported from the alternate reality where these classes are
 | 
        
           |  |  | 721 |         // used in both the client and server code, so Requests are
 | 
        
           |  |  | 722 |         // Encodable too.  That's right, code imported from alternate
 | 
        
           |  |  | 723 |         // realities all for the love of you, id_res/user_setup_url.
 | 
        
           |  |  | 724 |   | 
        
           |  |  | 725 |         $q = array('mode' => $this->mode,
 | 
        
           |  |  | 726 |                    'identity' => $this->identity,
 | 
        
           |  |  | 727 |                    'return_to' => $this->return_to);
 | 
        
           |  |  | 728 |   | 
        
           |  |  | 729 |         if ($this->trust_root) {
 | 
        
           |  |  | 730 |             $q['trust_root'] = $this->trust_root;
 | 
        
           |  |  | 731 |         }
 | 
        
           |  |  | 732 |   | 
        
           |  |  | 733 |         if ($this->assoc_handle) {
 | 
        
           |  |  | 734 |             $q['assoc_handle'] = $this->assoc_handle;
 | 
        
           |  |  | 735 |         }
 | 
        
           |  |  | 736 |   | 
        
           |  |  | 737 |         $_q = array();
 | 
        
           |  |  | 738 |   | 
        
           |  |  | 739 |         foreach ($q as $k => $v) {
 | 
        
           |  |  | 740 |             $_q[$_Auth_OpenID_OpenID_Prefix . $k] = $v;
 | 
        
           |  |  | 741 |         }
 | 
        
           |  |  | 742 |   | 
        
           |  |  | 743 |         return Auth_OpenID::appendArgs($server_url, $_q);
 | 
        
           |  |  | 744 |     }
 | 
        
           |  |  | 745 |   | 
        
           |  |  | 746 |     function getCancelURL()
 | 
        
           |  |  | 747 |     {
 | 
        
           |  |  | 748 |         global $_Auth_OpenID_OpenID_Prefix;
 | 
        
           |  |  | 749 |   | 
        
           |  |  | 750 |         if ($this->immediate) {
 | 
        
           |  |  | 751 |             return new Auth_OpenID_ServerError(null,
 | 
        
           |  |  | 752 |                                                "Cancel is not an appropriate \
 | 
        
           |  |  | 753 |                                                response to immediate mode \
 | 
        
           |  |  | 754 |                                                requests.");
 | 
        
           |  |  | 755 |         }
 | 
        
           |  |  | 756 |   | 
        
           |  |  | 757 |         return Auth_OpenID::appendArgs($this->return_to,
 | 
        
           |  |  | 758 |                               array($_Auth_OpenID_OpenID_Prefix . 'mode' =>
 | 
        
           |  |  | 759 |                                     'cancel'));
 | 
        
           |  |  | 760 |     }
 | 
        
           |  |  | 761 | }
 | 
        
           |  |  | 762 |   | 
        
           |  |  | 763 | /**
 | 
        
           |  |  | 764 |  * This class encapsulates the response to an OpenID server request.
 | 
        
           |  |  | 765 |  *
 | 
        
           |  |  | 766 |  * @access private
 | 
        
           |  |  | 767 |  * @package OpenID
 | 
        
           |  |  | 768 |  */
 | 
        
           |  |  | 769 | class Auth_OpenID_ServerResponse {
 | 
        
           |  |  | 770 |   | 
        
           |  |  | 771 |     function Auth_OpenID_ServerResponse($request)
 | 
        
           |  |  | 772 |     {
 | 
        
           |  |  | 773 |         $this->request = $request;
 | 
        
           |  |  | 774 |         $this->fields = array();
 | 
        
           |  |  | 775 |     }
 | 
        
           |  |  | 776 |   | 
        
           |  |  | 777 |     function whichEncoding()
 | 
        
           |  |  | 778 |     {
 | 
        
           |  |  | 779 |         global $_Auth_OpenID_Encode_Kvform,
 | 
        
           |  |  | 780 |             $_Auth_OpenID_Request_Modes,
 | 
        
           |  |  | 781 |             $_Auth_OpenID_Encode_Url;
 | 
        
           |  |  | 782 |   | 
        
           |  |  | 783 |         if (in_array($this->request->mode, $_Auth_OpenID_Request_Modes)) {
 | 
        
           |  |  | 784 |             return $_Auth_OpenID_Encode_Url;
 | 
        
           |  |  | 785 |         } else {
 | 
        
           |  |  | 786 |             return $_Auth_OpenID_Encode_Kvform;
 | 
        
           |  |  | 787 |         }
 | 
        
           |  |  | 788 |     }
 | 
        
           |  |  | 789 |   | 
        
           |  |  | 790 |     function encodeToURL()
 | 
        
           |  |  | 791 |     {
 | 
        
           |  |  | 792 |         global $_Auth_OpenID_OpenID_Prefix;
 | 
        
           |  |  | 793 |   | 
        
           |  |  | 794 |         $fields = array();
 | 
        
           |  |  | 795 |   | 
        
           |  |  | 796 |         foreach ($this->fields as $k => $v) {
 | 
        
           |  |  | 797 |             $fields[$_Auth_OpenID_OpenID_Prefix . $k] = $v;
 | 
        
           |  |  | 798 |         }
 | 
        
           |  |  | 799 |   | 
        
           |  |  | 800 |         return Auth_OpenID::appendArgs($this->request->return_to, $fields);
 | 
        
           |  |  | 801 |     }
 | 
        
           |  |  | 802 |   | 
        
           |  |  | 803 |     function encodeToKVForm()
 | 
        
           |  |  | 804 |     {
 | 
        
           |  |  | 805 |         return Auth_OpenID_KVForm::fromArray($this->fields);
 | 
        
           |  |  | 806 |     }
 | 
        
           |  |  | 807 | }
 | 
        
           |  |  | 808 |   | 
        
           |  |  | 809 | /**
 | 
        
           |  |  | 810 |  * A response to a checkid request.
 | 
        
           |  |  | 811 |  *
 | 
        
           |  |  | 812 |  * @access private
 | 
        
           |  |  | 813 |  * @package OpenID
 | 
        
           |  |  | 814 |  */
 | 
        
           |  |  | 815 | class Auth_OpenID_CheckIDResponse extends Auth_OpenID_ServerResponse {
 | 
        
           |  |  | 816 |   | 
        
           |  |  | 817 |     function Auth_OpenID_CheckIDResponse(&$request, $mode = 'id_res')
 | 
        
           |  |  | 818 |     {
 | 
        
           |  |  | 819 |         parent::Auth_OpenID_ServerResponse($request);
 | 
        
           |  |  | 820 |         $this->fields['mode'] = $mode;
 | 
        
           |  |  | 821 |         $this->signed = array();
 | 
        
           |  |  | 822 |   | 
        
           |  |  | 823 |         if ($mode == 'id_res') {
 | 
        
           |  |  | 824 |             array_push($this->signed, 'mode', 'identity', 'return_to');
 | 
        
           |  |  | 825 |         }
 | 
        
           |  |  | 826 |     }
 | 
        
           |  |  | 827 |   | 
        
           |  |  | 828 |     function addField($namespace, $key, $value, $signed = true)
 | 
        
           |  |  | 829 |     {
 | 
        
           |  |  | 830 |         if ($namespace) {
 | 
        
           |  |  | 831 |             $key = sprintf('%s.%s', $namespace, $key);
 | 
        
           |  |  | 832 |         }
 | 
        
           |  |  | 833 |         $this->fields[$key] = $value;
 | 
        
           |  |  | 834 |         if ($signed && !in_array($key, $this->signed)) {
 | 
        
           |  |  | 835 |             $this->signed[] = $key;
 | 
        
           |  |  | 836 |         }
 | 
        
           |  |  | 837 |     }
 | 
        
           |  |  | 838 |   | 
        
           |  |  | 839 |     function addFields($namespace, $fields, $signed = true)
 | 
        
           |  |  | 840 |     {
 | 
        
           |  |  | 841 |         foreach ($fields as $k => $v) {
 | 
        
           |  |  | 842 |             $this->addField($namespace, $k, $v, $signed);
 | 
        
           |  |  | 843 |         }
 | 
        
           |  |  | 844 |     }
 | 
        
           |  |  | 845 |   | 
        
           |  |  | 846 |     function update($namespace, $other)
 | 
        
           |  |  | 847 |     {
 | 
        
           |  |  | 848 |         $namespaced_fields = array();
 | 
        
           |  |  | 849 |   | 
        
           |  |  | 850 |         foreach ($other->fields as $k => $v) {
 | 
        
           |  |  | 851 |             $name = sprintf('%s.%s', $namespace, $k);
 | 
        
           |  |  | 852 |   | 
        
           |  |  | 853 |             $namespaced_fields[$name] = $v;
 | 
        
           |  |  | 854 |         }
 | 
        
           |  |  | 855 |   | 
        
           |  |  | 856 |         $this->fields = array_merge($this->fields, $namespaced_fields);
 | 
        
           |  |  | 857 |         $this->signed = array_merge($this->signed, $other->signed);
 | 
        
           |  |  | 858 |     }
 | 
        
           |  |  | 859 | }
 | 
        
           |  |  | 860 |   | 
        
           |  |  | 861 | /**
 | 
        
           |  |  | 862 |  * A web-capable response object which you can use to generate a
 | 
        
           |  |  | 863 |  * user-agent response.
 | 
        
           |  |  | 864 |  *
 | 
        
           |  |  | 865 |  * @package OpenID
 | 
        
           |  |  | 866 |  */
 | 
        
           |  |  | 867 | class Auth_OpenID_WebResponse {
 | 
        
           |  |  | 868 |     var $code = AUTH_OPENID_HTTP_OK;
 | 
        
           |  |  | 869 |     var $body = "";
 | 
        
           |  |  | 870 |   | 
        
           |  |  | 871 |     function Auth_OpenID_WebResponse($code = null, $headers = null,
 | 
        
           |  |  | 872 |                                      $body = null)
 | 
        
           |  |  | 873 |     {
 | 
        
           |  |  | 874 |         if ($code) {
 | 
        
           |  |  | 875 |             $this->code = $code;
 | 
        
           |  |  | 876 |         }
 | 
        
           |  |  | 877 |   | 
        
           |  |  | 878 |         if ($headers !== null) {
 | 
        
           |  |  | 879 |             $this->headers = $headers;
 | 
        
           |  |  | 880 |         } else {
 | 
        
           |  |  | 881 |             $this->headers = array();
 | 
        
           |  |  | 882 |         }
 | 
        
           |  |  | 883 |   | 
        
           |  |  | 884 |         if ($body !== null) {
 | 
        
           |  |  | 885 |             $this->body = $body;
 | 
        
           |  |  | 886 |         }
 | 
        
           |  |  | 887 |     }
 | 
        
           |  |  | 888 | }
 | 
        
           |  |  | 889 |   | 
        
           |  |  | 890 | /**
 | 
        
           |  |  | 891 |  * Responsible for the signature of query data and the verification of
 | 
        
           |  |  | 892 |  * OpenID signature values.
 | 
        
           |  |  | 893 |  *
 | 
        
           |  |  | 894 |  * @package OpenID
 | 
        
           |  |  | 895 |  */
 | 
        
           |  |  | 896 | class Auth_OpenID_Signatory {
 | 
        
           |  |  | 897 |   | 
        
           |  |  | 898 |     // = 14 * 24 * 60 * 60; # 14 days, in seconds
 | 
        
           |  |  | 899 |     var $SECRET_LIFETIME = 1209600;
 | 
        
           |  |  | 900 |   | 
        
           |  |  | 901 |     // keys have a bogus server URL in them because the filestore
 | 
        
           |  |  | 902 |     // really does expect that key to be a URL.  This seems a little
 | 
        
           |  |  | 903 |     // silly for the server store, since I expect there to be only one
 | 
        
           |  |  | 904 |     // server URL.
 | 
        
           |  |  | 905 |     var $normal_key = 'http://localhost/|normal';
 | 
        
           |  |  | 906 |     var $dumb_key = 'http://localhost/|dumb';
 | 
        
           |  |  | 907 |   | 
        
           |  |  | 908 |     /**
 | 
        
           |  |  | 909 |      * Create a new signatory using a given store.
 | 
        
           |  |  | 910 |      */
 | 
        
           |  |  | 911 |     function Auth_OpenID_Signatory(&$store)
 | 
        
           |  |  | 912 |     {
 | 
        
           |  |  | 913 |         // assert store is not None
 | 
        
           |  |  | 914 |         $this->store =& $store;
 | 
        
           |  |  | 915 |     }
 | 
        
           |  |  | 916 |   | 
        
           |  |  | 917 |     /**
 | 
        
           |  |  | 918 |      * Verify, using a given association handle, a signature with
 | 
        
           |  |  | 919 |      * signed key-value pairs from an HTTP request.
 | 
        
           |  |  | 920 |      */
 | 
        
           |  |  | 921 |     function verify($assoc_handle, $sig, $signed_pairs)
 | 
        
           |  |  | 922 |     {
 | 
        
           |  |  | 923 |         $assoc = $this->getAssociation($assoc_handle, true);
 | 
        
           |  |  | 924 |         if (!$assoc) {
 | 
        
           |  |  | 925 |             // oidutil.log("failed to get assoc with handle %r to verify sig %r"
 | 
        
           |  |  | 926 |             //             % (assoc_handle, sig))
 | 
        
           |  |  | 927 |             return false;
 | 
        
           |  |  | 928 |         }
 | 
        
           |  |  | 929 |   | 
        
           |  |  | 930 |         $expected_sig = base64_encode($assoc->sign($signed_pairs));
 | 
        
           |  |  | 931 |   | 
        
           |  |  | 932 |         return $sig == $expected_sig;
 | 
        
           |  |  | 933 |     }
 | 
        
           |  |  | 934 |   | 
        
           |  |  | 935 |     /**
 | 
        
           |  |  | 936 |      * Given a response, sign the fields in the response's 'signed'
 | 
        
           |  |  | 937 |      * list, and insert the signature into the response.
 | 
        
           |  |  | 938 |      */
 | 
        
           |  |  | 939 |     function sign($response)
 | 
        
           |  |  | 940 |     {
 | 
        
           |  |  | 941 |         $signed_response = $response;
 | 
        
           |  |  | 942 |         $assoc_handle = $response->request->assoc_handle;
 | 
        
           |  |  | 943 |   | 
        
           |  |  | 944 |         if ($assoc_handle) {
 | 
        
           |  |  | 945 |             // normal mode
 | 
        
           |  |  | 946 |             $assoc = $this->getAssociation($assoc_handle, false);
 | 
        
           |  |  | 947 |             if (!$assoc) {
 | 
        
           |  |  | 948 |                 // fall back to dumb mode
 | 
        
           |  |  | 949 |                 $signed_response->fields['invalidate_handle'] = $assoc_handle;
 | 
        
           |  |  | 950 |                 $assoc = $this->createAssociation(true);
 | 
        
           |  |  | 951 |             }
 | 
        
           |  |  | 952 |         } else {
 | 
        
           |  |  | 953 |             // dumb mode.
 | 
        
           |  |  | 954 |             $assoc = $this->createAssociation(true);
 | 
        
           |  |  | 955 |         }
 | 
        
           |  |  | 956 |   | 
        
           |  |  | 957 |         $signed_response->fields['assoc_handle'] = $assoc->handle;
 | 
        
           |  |  | 958 |         $assoc->addSignature($signed_response->signed,
 | 
        
           |  |  | 959 |                              $signed_response->fields, '');
 | 
        
           |  |  | 960 |         return $signed_response;
 | 
        
           |  |  | 961 |     }
 | 
        
           |  |  | 962 |   | 
        
           |  |  | 963 |     /**
 | 
        
           |  |  | 964 |      * Make a new association.
 | 
        
           |  |  | 965 |      */
 | 
        
           |  |  | 966 |     function createAssociation($dumb = true, $assoc_type = 'HMAC-SHA1')
 | 
        
           |  |  | 967 |     {
 | 
        
           |  |  | 968 |         $secret = Auth_OpenID_CryptUtil::getBytes(20);
 | 
        
           |  |  | 969 |         $uniq = base64_encode(Auth_OpenID_CryptUtil::getBytes(4));
 | 
        
           |  |  | 970 |         $handle = sprintf('{%s}{%x}{%s}', $assoc_type, intval(time()), $uniq);
 | 
        
           |  |  | 971 |   | 
        
           |  |  | 972 |         $assoc = Auth_OpenID_Association::fromExpiresIn(
 | 
        
           |  |  | 973 |                       $this->SECRET_LIFETIME, $handle, $secret, $assoc_type);
 | 
        
           |  |  | 974 |   | 
        
           |  |  | 975 |         if ($dumb) {
 | 
        
           |  |  | 976 |             $key = $this->dumb_key;
 | 
        
           |  |  | 977 |         } else {
 | 
        
           |  |  | 978 |             $key = $this->normal_key;
 | 
        
           |  |  | 979 |         }
 | 
        
           |  |  | 980 |   | 
        
           |  |  | 981 |         $this->store->storeAssociation($key, $assoc);
 | 
        
           |  |  | 982 |         return $assoc;
 | 
        
           |  |  | 983 |     }
 | 
        
           |  |  | 984 |   | 
        
           |  |  | 985 |     /**
 | 
        
           |  |  | 986 |      * Given an association handle, get the association from the
 | 
        
           |  |  | 987 |      * store, or return a ServerError or null if something goes wrong.
 | 
        
           |  |  | 988 |      */
 | 
        
           |  |  | 989 |     function getAssociation($assoc_handle, $dumb)
 | 
        
           |  |  | 990 |     {
 | 
        
           |  |  | 991 |         if ($assoc_handle === null) {
 | 
        
           |  |  | 992 |             return new Auth_OpenID_ServerError(null,
 | 
        
           |  |  | 993 |                                      "assoc_handle must not be null");
 | 
        
           |  |  | 994 |         }
 | 
        
           |  |  | 995 |   | 
        
           |  |  | 996 |         if ($dumb) {
 | 
        
           |  |  | 997 |             $key = $this->dumb_key;
 | 
        
           |  |  | 998 |         } else {
 | 
        
           |  |  | 999 |             $key = $this->normal_key;
 | 
        
           |  |  | 1000 |         }
 | 
        
           |  |  | 1001 |   | 
        
           |  |  | 1002 |         $assoc = $this->store->getAssociation($key, $assoc_handle);
 | 
        
           |  |  | 1003 |   | 
        
           |  |  | 1004 |         if (($assoc !== null) && ($assoc->getExpiresIn() <= 0)) {
 | 
        
           |  |  | 1005 |             $this->store->removeAssociation($key, $assoc_handle);
 | 
        
           |  |  | 1006 |             $assoc = null;
 | 
        
           |  |  | 1007 |         }
 | 
        
           |  |  | 1008 |   | 
        
           |  |  | 1009 |         return $assoc;
 | 
        
           |  |  | 1010 |     }
 | 
        
           |  |  | 1011 |   | 
        
           |  |  | 1012 |     /**
 | 
        
           |  |  | 1013 |      * Invalidate a given association handle.
 | 
        
           |  |  | 1014 |      */
 | 
        
           |  |  | 1015 |     function invalidate($assoc_handle, $dumb)
 | 
        
           |  |  | 1016 |     {
 | 
        
           |  |  | 1017 |         if ($dumb) {
 | 
        
           |  |  | 1018 |             $key = $this->dumb_key;
 | 
        
           |  |  | 1019 |         } else {
 | 
        
           |  |  | 1020 |             $key = $this->normal_key;
 | 
        
           |  |  | 1021 |         }
 | 
        
           |  |  | 1022 |         $this->store->removeAssociation($key, $assoc_handle);
 | 
        
           |  |  | 1023 |     }
 | 
        
           |  |  | 1024 | }
 | 
        
           |  |  | 1025 |   | 
        
           |  |  | 1026 | /**
 | 
        
           |  |  | 1027 |  * Encode an Auth_OpenID_Response to an Auth_OpenID_WebResponse.
 | 
        
           |  |  | 1028 |  *
 | 
        
           |  |  | 1029 |  * @package OpenID
 | 
        
           |  |  | 1030 |  */
 | 
        
           |  |  | 1031 | class Auth_OpenID_Encoder {
 | 
        
           |  |  | 1032 |   | 
        
           |  |  | 1033 |     var $responseFactory = 'Auth_OpenID_WebResponse';
 | 
        
           |  |  | 1034 |   | 
        
           |  |  | 1035 |     /**
 | 
        
           |  |  | 1036 |      * Encode an Auth_OpenID_Response and return an
 | 
        
           |  |  | 1037 |      * Auth_OpenID_WebResponse.
 | 
        
           |  |  | 1038 |      */
 | 
        
           |  |  | 1039 |     function encode(&$response)
 | 
        
           |  |  | 1040 |     {
 | 
        
           |  |  | 1041 |         global $_Auth_OpenID_Encode_Kvform,
 | 
        
           |  |  | 1042 |             $_Auth_OpenID_Encode_Url;
 | 
        
           |  |  | 1043 |   | 
        
           |  |  | 1044 |         $cls = $this->responseFactory;
 | 
        
           |  |  | 1045 |   | 
        
           |  |  | 1046 |         $encode_as = $response->whichEncoding();
 | 
        
           |  |  | 1047 |         if ($encode_as == $_Auth_OpenID_Encode_Kvform) {
 | 
        
           |  |  | 1048 |             $wr = new $cls(null, null, $response->encodeToKVForm());
 | 
        
           |  |  | 1049 |             if (is_a($response, 'Auth_OpenID_ServerError')) {
 | 
        
           |  |  | 1050 |                 $wr->code = AUTH_OPENID_HTTP_ERROR;
 | 
        
           |  |  | 1051 |             }
 | 
        
           |  |  | 1052 |         } else if ($encode_as == $_Auth_OpenID_Encode_Url) {
 | 
        
           |  |  | 1053 |             $location = $response->encodeToURL();
 | 
        
           |  |  | 1054 |             $wr = new $cls(AUTH_OPENID_HTTP_REDIRECT,
 | 
        
           |  |  | 1055 |                            array('location' => $location));
 | 
        
           |  |  | 1056 |         } else {
 | 
        
           |  |  | 1057 |             return new Auth_OpenID_EncodingError($response);
 | 
        
           |  |  | 1058 |         }
 | 
        
           |  |  | 1059 |         return $wr;
 | 
        
           |  |  | 1060 |     }
 | 
        
           |  |  | 1061 | }
 | 
        
           |  |  | 1062 |   | 
        
           |  |  | 1063 | /**
 | 
        
           |  |  | 1064 |  * Returns true if the given response needs a signature.
 | 
        
           |  |  | 1065 |  *
 | 
        
           |  |  | 1066 |  * @access private
 | 
        
           |  |  | 1067 |  */
 | 
        
           |  |  | 1068 | function needsSigning($response)
 | 
        
           |  |  | 1069 | {
 | 
        
           |  |  | 1070 |     return (in_array($response->request->mode, array('checkid_setup',
 | 
        
           |  |  | 1071 |                                                      'checkid_immediate')) &&
 | 
        
           |  |  | 1072 |             $response->signed);
 | 
        
           |  |  | 1073 | }
 | 
        
           |  |  | 1074 |   | 
        
           |  |  | 1075 | /**
 | 
        
           |  |  | 1076 |  * An encoder which also takes care of signing fields when required.
 | 
        
           |  |  | 1077 |  *
 | 
        
           |  |  | 1078 |  * @package OpenID
 | 
        
           |  |  | 1079 |  */
 | 
        
           |  |  | 1080 | class Auth_OpenID_SigningEncoder extends Auth_OpenID_Encoder {
 | 
        
           |  |  | 1081 |   | 
        
           |  |  | 1082 |     function Auth_OpenID_SigningEncoder(&$signatory)
 | 
        
           |  |  | 1083 |     {
 | 
        
           |  |  | 1084 |         $this->signatory =& $signatory;
 | 
        
           |  |  | 1085 |     }
 | 
        
           |  |  | 1086 |   | 
        
           |  |  | 1087 |     /**
 | 
        
           |  |  | 1088 |      * Sign an Auth_OpenID_Response and return an
 | 
        
           |  |  | 1089 |      * Auth_OpenID_WebResponse.
 | 
        
           |  |  | 1090 |      */
 | 
        
           |  |  | 1091 |     function encode(&$response)
 | 
        
           |  |  | 1092 |     {
 | 
        
           |  |  | 1093 |         // the isinstance is a bit of a kludge... it means there isn't
 | 
        
           |  |  | 1094 |         // really an adapter to make the interfaces quite match.
 | 
        
           |  |  | 1095 |         if (!is_a($response, 'Auth_OpenID_ServerError') &&
 | 
        
           |  |  | 1096 |             needsSigning($response)) {
 | 
        
           |  |  | 1097 |   | 
        
           |  |  | 1098 |             if (!$this->signatory) {
 | 
        
           |  |  | 1099 |                 return new Auth_OpenID_ServerError(null,
 | 
        
           |  |  | 1100 |                                        "Must have a store to sign request");
 | 
        
           |  |  | 1101 |             }
 | 
        
           |  |  | 1102 |             if (array_key_exists('sig', $response->fields)) {
 | 
        
           |  |  | 1103 |                 return new Auth_OpenID_AlreadySigned($response);
 | 
        
           |  |  | 1104 |             }
 | 
        
           |  |  | 1105 |             $response = $this->signatory->sign($response);
 | 
        
           |  |  | 1106 |         }
 | 
        
           |  |  | 1107 |         return parent::encode($response);
 | 
        
           |  |  | 1108 |     }
 | 
        
           |  |  | 1109 | }
 | 
        
           |  |  | 1110 |   | 
        
           |  |  | 1111 | /**
 | 
        
           |  |  | 1112 |  * Decode an incoming Auth_OpenID_WebResponse into an
 | 
        
           |  |  | 1113 |  * Auth_OpenID_Request.
 | 
        
           |  |  | 1114 |  *
 | 
        
           |  |  | 1115 |  * @package OpenID
 | 
        
           |  |  | 1116 |  */
 | 
        
           |  |  | 1117 | class Auth_OpenID_Decoder {
 | 
        
           |  |  | 1118 |   | 
        
           |  |  | 1119 |     function Auth_OpenID_Decoder()
 | 
        
           |  |  | 1120 |     {
 | 
        
           |  |  | 1121 |         global $_Auth_OpenID_OpenID_Prefix;
 | 
        
           |  |  | 1122 |         $this->prefix = $_Auth_OpenID_OpenID_Prefix;
 | 
        
           |  |  | 1123 |   | 
        
           |  |  | 1124 |         $this->handlers = array(
 | 
        
           |  |  | 1125 |             'checkid_setup' => 'Auth_OpenID_CheckIDRequest',
 | 
        
           |  |  | 1126 |             'checkid_immediate' => 'Auth_OpenID_CheckIDRequest',
 | 
        
           |  |  | 1127 |             'check_authentication' => 'Auth_OpenID_CheckAuthRequest',
 | 
        
           |  |  | 1128 |             'associate' => 'Auth_OpenID_AssociateRequest'
 | 
        
           |  |  | 1129 |             );
 | 
        
           |  |  | 1130 |     }
 | 
        
           |  |  | 1131 |   | 
        
           |  |  | 1132 |     /**
 | 
        
           |  |  | 1133 |      * Given an HTTP query in an array (key-value pairs), decode it
 | 
        
           |  |  | 1134 |      * into an Auth_OpenID_Request object.
 | 
        
           |  |  | 1135 |      */
 | 
        
           |  |  | 1136 |     function decode($query)
 | 
        
           |  |  | 1137 |     {
 | 
        
           |  |  | 1138 |         if (!$query) {
 | 
        
           |  |  | 1139 |             return null;
 | 
        
           |  |  | 1140 |         }
 | 
        
           |  |  | 1141 |   | 
        
           |  |  | 1142 |         $myquery = array();
 | 
        
           |  |  | 1143 |   | 
        
           |  |  | 1144 |         foreach ($query as $k => $v) {
 | 
        
           |  |  | 1145 |             if (strpos($k, $this->prefix) === 0) {
 | 
        
           |  |  | 1146 |                 $myquery[$k] = $v;
 | 
        
           |  |  | 1147 |             }
 | 
        
           |  |  | 1148 |         }
 | 
        
           |  |  | 1149 |   | 
        
           |  |  | 1150 |         if (!$myquery) {
 | 
        
           |  |  | 1151 |             return null;
 | 
        
           |  |  | 1152 |         }
 | 
        
           |  |  | 1153 |   | 
        
           |  |  | 1154 |         $mode = Auth_OpenID::arrayGet($myquery, $this->prefix . 'mode');
 | 
        
           |  |  | 1155 |         if (!$mode) {
 | 
        
           |  |  | 1156 |             return new Auth_OpenID_ServerError($query,
 | 
        
           |  |  | 1157 |                            sprintf("No %s mode found in query", $this->prefix));
 | 
        
           |  |  | 1158 |         }
 | 
        
           |  |  | 1159 |   | 
        
           |  |  | 1160 |         $handlerCls = Auth_OpenID::arrayGet($this->handlers, $mode,
 | 
        
           |  |  | 1161 |                                             $this->defaultDecoder($query));
 | 
        
           |  |  | 1162 |   | 
        
           |  |  | 1163 |         if (!is_a($handlerCls, 'Auth_OpenID_ServerError')) {
 | 
        
           |  |  | 1164 |             return call_user_func_array(array($handlerCls, 'fromQuery'),
 | 
        
           |  |  | 1165 |                                         array($query));
 | 
        
           |  |  | 1166 |         } else {
 | 
        
           |  |  | 1167 |             return $handlerCls;
 | 
        
           |  |  | 1168 |         }
 | 
        
           |  |  | 1169 |     }
 | 
        
           |  |  | 1170 |   | 
        
           |  |  | 1171 |     function defaultDecoder($query)
 | 
        
           |  |  | 1172 |     {
 | 
        
           |  |  | 1173 |         $mode = $query[$this->prefix . 'mode'];
 | 
        
           |  |  | 1174 |         return new Auth_OpenID_ServerError($query,
 | 
        
           |  |  | 1175 |                        sprintf("No decoder for mode %s", $mode));
 | 
        
           |  |  | 1176 |     }
 | 
        
           |  |  | 1177 | }
 | 
        
           |  |  | 1178 |   | 
        
           |  |  | 1179 | /**
 | 
        
           |  |  | 1180 |  * An error that indicates an encoding problem occurred.
 | 
        
           |  |  | 1181 |  *
 | 
        
           |  |  | 1182 |  * @package OpenID
 | 
        
           |  |  | 1183 |  */
 | 
        
           |  |  | 1184 | class Auth_OpenID_EncodingError {
 | 
        
           |  |  | 1185 |     function Auth_OpenID_EncodingError(&$response)
 | 
        
           |  |  | 1186 |     {
 | 
        
           |  |  | 1187 |         $this->response =& $response;
 | 
        
           |  |  | 1188 |     }
 | 
        
           |  |  | 1189 | }
 | 
        
           |  |  | 1190 |   | 
        
           |  |  | 1191 | /**
 | 
        
           |  |  | 1192 |  * An error that indicates that a response was already signed.
 | 
        
           |  |  | 1193 |  *
 | 
        
           |  |  | 1194 |  * @package OpenID
 | 
        
           |  |  | 1195 |  */
 | 
        
           |  |  | 1196 | class Auth_OpenID_AlreadySigned extends Auth_OpenID_EncodingError {
 | 
        
           |  |  | 1197 |     // This response is already signed.
 | 
        
           |  |  | 1198 | }
 | 
        
           |  |  | 1199 |   | 
        
           |  |  | 1200 | /**
 | 
        
           |  |  | 1201 |  * An error that indicates that the given return_to is not under the
 | 
        
           |  |  | 1202 |  * given trust_root.
 | 
        
           |  |  | 1203 |  *
 | 
        
           |  |  | 1204 |  * @package OpenID
 | 
        
           |  |  | 1205 |  */
 | 
        
           |  |  | 1206 | class Auth_OpenID_UntrustedReturnURL extends Auth_OpenID_ServerError {
 | 
        
           |  |  | 1207 |     function Auth_OpenID_UntrustedReturnURL($return_to, $trust_root)
 | 
        
           |  |  | 1208 |     {
 | 
        
           |  |  | 1209 |         global $_Auth_OpenID_OpenID_Prefix;
 | 
        
           |  |  | 1210 |   | 
        
           |  |  | 1211 |         $query = array(
 | 
        
           |  |  | 1212 |                $_Auth_OpenID_OpenID_Prefix . 'return_to' => $return_to,
 | 
        
           |  |  | 1213 |                $_Auth_OpenID_OpenID_Prefix . 'trust_root' => $trust_root);
 | 
        
           |  |  | 1214 |   | 
        
           |  |  | 1215 |         parent::Auth_OpenID_ServerError($query);
 | 
        
           |  |  | 1216 |     }
 | 
        
           |  |  | 1217 |   | 
        
           |  |  | 1218 |     function toString()
 | 
        
           |  |  | 1219 |     {
 | 
        
           |  |  | 1220 |         global $_Auth_OpenID_OpenID_Prefix;
 | 
        
           |  |  | 1221 |   | 
        
           |  |  | 1222 |         $return_to = $this->query[$_Auth_OpenID_OpenID_Prefix . 'return_to'];
 | 
        
           |  |  | 1223 |         $trust_root = $this->query[$_Auth_OpenID_OpenID_Prefix . 'trust_root'];
 | 
        
           |  |  | 1224 |   | 
        
           |  |  | 1225 |         return sprintf("return_to %s not under trust_root %s",
 | 
        
           |  |  | 1226 |                        $return_to, $trust_root);
 | 
        
           |  |  | 1227 |     }
 | 
        
           |  |  | 1228 | }
 | 
        
           |  |  | 1229 |   | 
        
           |  |  | 1230 | /**
 | 
        
           |  |  | 1231 |  * An object that implements the OpenID protocol for a single URL.
 | 
        
           |  |  | 1232 |  *
 | 
        
           |  |  | 1233 |  * Use this object by calling getOpenIDResponse when you get any
 | 
        
           |  |  | 1234 |  * request for the server URL.
 | 
        
           |  |  | 1235 |  *
 | 
        
           |  |  | 1236 |  * @package OpenID
 | 
        
           |  |  | 1237 |  */
 | 
        
           |  |  | 1238 | class Auth_OpenID_Server {
 | 
        
           |  |  | 1239 |     function Auth_OpenID_Server(&$store)
 | 
        
           |  |  | 1240 |     {
 | 
        
           |  |  | 1241 |         $this->store =& $store;
 | 
        
           |  |  | 1242 |         $this->signatory =& new Auth_OpenID_Signatory($this->store);
 | 
        
           |  |  | 1243 |         $this->encoder =& new Auth_OpenID_SigningEncoder($this->signatory);
 | 
        
           |  |  | 1244 |         $this->decoder =& new Auth_OpenID_Decoder();
 | 
        
           |  |  | 1245 |     }
 | 
        
           |  |  | 1246 |   | 
        
           |  |  | 1247 |     /**
 | 
        
           |  |  | 1248 |      * Handle a request.  Given an Auth_OpenID_Request object, call
 | 
        
           |  |  | 1249 |      * the appropriate Auth_OpenID_Server method to process the
 | 
        
           |  |  | 1250 |      * request and generate a response.
 | 
        
           |  |  | 1251 |      *
 | 
        
           |  |  | 1252 |      * @param Auth_OpenID_Request $request An Auth_OpenID_Request
 | 
        
           |  |  | 1253 |      * returned by Auth_OpenID_Server::decodeRequest.
 | 
        
           |  |  | 1254 |      *
 | 
        
           |  |  | 1255 |      * @return Auth_OpenID_Response $response A response object
 | 
        
           |  |  | 1256 |      * capable of generating a user-agent reply.
 | 
        
           |  |  | 1257 |      */
 | 
        
           |  |  | 1258 |     function handleRequest($request)
 | 
        
           |  |  | 1259 |     {
 | 
        
           |  |  | 1260 |         if (method_exists($this, "openid_" . $request->mode)) {
 | 
        
           |  |  | 1261 |             $handler = array($this, "openid_" . $request->mode);
 | 
        
           |  |  | 1262 |             return call_user_func($handler, $request);
 | 
        
           |  |  | 1263 |         }
 | 
        
           |  |  | 1264 |         return null;
 | 
        
           |  |  | 1265 |     }
 | 
        
           |  |  | 1266 |   | 
        
           |  |  | 1267 |     /**
 | 
        
           |  |  | 1268 |      * The callback for 'check_authentication' messages.
 | 
        
           |  |  | 1269 |      *
 | 
        
           |  |  | 1270 |      * @access private
 | 
        
           |  |  | 1271 |      */
 | 
        
           |  |  | 1272 |     function openid_check_authentication(&$request)
 | 
        
           |  |  | 1273 |     {
 | 
        
           |  |  | 1274 |         return $request->answer($this->signatory);
 | 
        
           |  |  | 1275 |     }
 | 
        
           |  |  | 1276 |   | 
        
           |  |  | 1277 |     /**
 | 
        
           |  |  | 1278 |      * The callback for 'associate' messages.
 | 
        
           |  |  | 1279 |      *
 | 
        
           |  |  | 1280 |      * @access private
 | 
        
           |  |  | 1281 |      */
 | 
        
           |  |  | 1282 |     function openid_associate(&$request)
 | 
        
           |  |  | 1283 |     {
 | 
        
           |  |  | 1284 |         $assoc = $this->signatory->createAssociation(false);
 | 
        
           |  |  | 1285 |         return $request->answer($assoc);
 | 
        
           |  |  | 1286 |     }
 | 
        
           |  |  | 1287 |   | 
        
           |  |  | 1288 |     /**
 | 
        
           |  |  | 1289 |      * Encodes as response in the appropriate format suitable for
 | 
        
           |  |  | 1290 |      * sending to the user agent.
 | 
        
           |  |  | 1291 |      */
 | 
        
           |  |  | 1292 |     function encodeResponse(&$response)
 | 
        
           |  |  | 1293 |     {
 | 
        
           |  |  | 1294 |         return $this->encoder->encode($response);
 | 
        
           |  |  | 1295 |     }
 | 
        
           |  |  | 1296 |   | 
        
           |  |  | 1297 |     /**
 | 
        
           |  |  | 1298 |      * Decodes a query args array into the appropriate
 | 
        
           |  |  | 1299 |      * Auth_OpenID_Request object.
 | 
        
           |  |  | 1300 |      */
 | 
        
           |  |  | 1301 |     function decodeRequest(&$query)
 | 
        
           |  |  | 1302 |     {
 | 
        
           |  |  | 1303 |         return $this->decoder->decode($query);
 | 
        
           |  |  | 1304 |     }
 | 
        
           |  |  | 1305 | }
 | 
        
           |  |  | 1306 |   | 
        
           |  |  | 1307 | ?>
 |