12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766 |
- <?php
- /**
- * OpenID server protocol and logic.
- *
- * Overview
- *
- * An OpenID server must perform three tasks:
- *
- * 1. Examine the incoming request to determine its nature and validity.
- * 2. Make a decision about how to respond to this request.
- * 3. Format the response according to the protocol.
- *
- * The first and last of these tasks may performed by the {@link
- * Auth_OpenID_Server::decodeRequest()} and {@link
- * Auth_OpenID_Server::encodeResponse} methods. Who gets to do the
- * intermediate task -- deciding how to respond to the request -- will
- * depend on what type of request it is.
- *
- * If it's a request to authenticate a user (a 'checkid_setup' or
- * 'checkid_immediate' request), you need to decide if you will assert
- * that this user may claim the identity in question. Exactly how you
- * do that is a matter of application policy, but it generally
- * involves making sure the user has an account with your system and
- * is logged in, checking to see if that identity is hers to claim,
- * and verifying with the user that she does consent to releasing that
- * information to the party making the request.
- *
- * Examine the properties of the {@link Auth_OpenID_CheckIDRequest}
- * object, and if and when you've come to a decision, form a response
- * by calling {@link Auth_OpenID_CheckIDRequest::answer()}.
- *
- * Other types of requests relate to establishing associations between
- * client and server and verifing the authenticity of previous
- * communications. {@link Auth_OpenID_Server} contains all the logic
- * and data necessary to respond to such requests; just pass it to
- * {@link Auth_OpenID_Server::handleRequest()}.
- *
- * OpenID Extensions
- *
- * Do you want to provide other information for your users in addition
- * to authentication? Version 1.2 of the OpenID protocol allows
- * consumers to add extensions to their requests. For example, with
- * sites using the Simple Registration
- * Extension
- * (http://openid.net/specs/openid-simple-registration-extension-1_0.html),
- * a user can agree to have their nickname and e-mail address sent to
- * a site when they sign up.
- *
- * Since extensions do not change the way OpenID authentication works,
- * code to handle extension requests may be completely separate from
- * the {@link Auth_OpenID_Request} class here. But you'll likely want
- * data sent back by your extension to be signed. {@link
- * Auth_OpenID_ServerResponse} provides methods with which you can add
- * data to it which can be signed with the other data in the OpenID
- * signature.
- *
- * For example:
- *
- * <pre> // when request is a checkid_* request
- * $response = $request->answer(true);
- * // this will a signed 'openid.sreg.timezone' parameter to the response
- * response.addField('sreg', 'timezone', 'America/Los_Angeles')</pre>
- *
- * Stores
- *
- * The OpenID server needs to maintain state between requests in order
- * to function. Its mechanism for doing this is called a store. The
- * store interface is defined in Interface.php. Additionally, several
- * concrete store implementations are provided, so that most sites
- * won't need to implement a custom store. For a store backed by flat
- * files on disk, see {@link Auth_OpenID_FileStore}. For stores based
- * on MySQL, SQLite, or PostgreSQL, see the {@link
- * Auth_OpenID_SQLStore} subclasses.
- *
- * Upgrading
- *
- * The keys by which a server looks up associations in its store have
- * changed in version 1.2 of this library. If your store has entries
- * created from version 1.0 code, you should empty it.
- *
- * PHP versions 4 and 5
- *
- * LICENSE: See the COPYING file included in this distribution.
- *
- * @package OpenID
- * @author JanRain, Inc. <openid@janrain.com>
- * @copyright 2005-2008 Janrain, Inc.
- * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
- */
- /**
- * Required imports
- */
- require_once "Auth/OpenID.php";
- require_once "Auth/OpenID/Association.php";
- require_once "Auth/OpenID/CryptUtil.php";
- require_once "Auth/OpenID/BigMath.php";
- require_once "Auth/OpenID/DiffieHellman.php";
- require_once "Auth/OpenID/KVForm.php";
- require_once "Auth/OpenID/TrustRoot.php";
- require_once "Auth/OpenID/ServerRequest.php";
- require_once "Auth/OpenID/Message.php";
- require_once "Auth/OpenID/Nonce.php";
- define('AUTH_OPENID_HTTP_OK', 200);
- define('AUTH_OPENID_HTTP_REDIRECT', 302);
- define('AUTH_OPENID_HTTP_ERROR', 400);
- /**
- * @access private
- */
- global $_Auth_OpenID_Request_Modes;
- $_Auth_OpenID_Request_Modes = array('checkid_setup',
- 'checkid_immediate');
- /**
- * @access private
- */
- define('Auth_OpenID_ENCODE_KVFORM', 'kfvorm');
- /**
- * @access private
- */
- define('Auth_OpenID_ENCODE_URL', 'URL/redirect');
- /**
- * @access private
- */
- define('Auth_OpenID_ENCODE_HTML_FORM', 'HTML form');
- /**
- * @access private
- */
- function Auth_OpenID_isError($obj, $cls = 'Auth_OpenID_ServerError')
- {
- return is_a($obj, $cls);
- }
- /**
- * An error class which gets instantiated and returned whenever an
- * OpenID protocol error occurs. Be prepared to use this in place of
- * an ordinary server response.
- *
- * @package OpenID
- */
- class Auth_OpenID_ServerError {
- /**
- * @access private
- */
- function Auth_OpenID_ServerError($message = null, $text = null,
- $reference = null, $contact = null)
- {
- $this->message = $message;
- $this->text = $text;
- $this->contact = $contact;
- $this->reference = $reference;
- }
- function getReturnTo()
- {
- if ($this->message &&
- $this->message->hasKey(Auth_OpenID_OPENID_NS, 'return_to')) {
- return $this->message->getArg(Auth_OpenID_OPENID_NS,
- 'return_to');
- } else {
- return null;
- }
- }
- /**
- * Returns the return_to URL for the request which caused this
- * error.
- */
- function hasReturnTo()
- {
- return $this->getReturnTo() !== null;
- }
- /**
- * Encodes this error's response as a URL suitable for
- * redirection. If the response has no return_to, another
- * Auth_OpenID_ServerError is returned.
- */
- function encodeToURL()
- {
- if (!$this->message) {
- return null;
- }
- $msg = $this->toMessage();
- return $msg->toURL($this->getReturnTo());
- }
- /**
- * Encodes the response to key-value form. This is a
- * machine-readable format used to respond to messages which came
- * directly from the consumer and not through the user-agent. See
- * the OpenID specification.
- */
- function encodeToKVForm()
- {
- return Auth_OpenID_KVForm::fromArray(
- array('mode' => 'error',
- 'error' => $this->toString()));
- }
- function toFormMarkup($form_tag_attrs=null)
- {
- $msg = $this->toMessage();
- return $msg->toFormMarkup($this->getReturnTo(), $form_tag_attrs);
- }
- function toHTML($form_tag_attrs=null)
- {
- return Auth_OpenID::autoSubmitHTML(
- $this->toFormMarkup($form_tag_attrs));
- }
- function toMessage()
- {
- // Generate a Message object for sending to the relying party,
- // after encoding.
- $namespace = $this->message->getOpenIDNamespace();
- $reply = new Auth_OpenID_Message($namespace);
- $reply->setArg(Auth_OpenID_OPENID_NS, 'mode', 'error');
- $reply->setArg(Auth_OpenID_OPENID_NS, 'error', $this->toString());
- if ($this->contact !== null) {
- $reply->setArg(Auth_OpenID_OPENID_NS, 'contact', $this->contact);
- }
- if ($this->reference !== null) {
- $reply->setArg(Auth_OpenID_OPENID_NS, 'reference',
- $this->reference);
- }
- return $reply;
- }
- /**
- * Returns one of Auth_OpenID_ENCODE_URL,
- * Auth_OpenID_ENCODE_KVFORM, or null, depending on the type of
- * encoding expected for this error's payload.
- */
- function whichEncoding()
- {
- global $_Auth_OpenID_Request_Modes;
- if ($this->hasReturnTo()) {
- if ($this->message->isOpenID2() &&
- (strlen($this->encodeToURL()) >
- Auth_OpenID_OPENID1_URL_LIMIT)) {
- return Auth_OpenID_ENCODE_HTML_FORM;
- } else {
- return Auth_OpenID_ENCODE_URL;
- }
- }
- if (!$this->message) {
- return null;
- }
- $mode = $this->message->getArg(Auth_OpenID_OPENID_NS,
- 'mode');
- if ($mode) {
- if (!in_array($mode, $_Auth_OpenID_Request_Modes)) {
- return Auth_OpenID_ENCODE_KVFORM;
- }
- }
- return null;
- }
- /**
- * Returns this error message.
- */
- function toString()
- {
- if ($this->text) {
- return $this->text;
- } else {
- return get_class($this) . " error";
- }
- }
- }
- /**
- * Error returned by the server code when a return_to is absent from a
- * request.
- *
- * @package OpenID
- */
- class Auth_OpenID_NoReturnToError extends Auth_OpenID_ServerError {
- function Auth_OpenID_NoReturnToError($message = null,
- $text = "No return_to URL available")
- {
- parent::Auth_OpenID_ServerError($message, $text);
- }
- function toString()
- {
- return "No return_to available";
- }
- }
- /**
- * An error indicating that the return_to URL is malformed.
- *
- * @package OpenID
- */
- class Auth_OpenID_MalformedReturnURL extends Auth_OpenID_ServerError {
- function Auth_OpenID_MalformedReturnURL($message, $return_to)
- {
- $this->return_to = $return_to;
- parent::Auth_OpenID_ServerError($message, "malformed return_to URL");
- }
- }
- /**
- * This error is returned when the trust_root value is malformed.
- *
- * @package OpenID
- */
- class Auth_OpenID_MalformedTrustRoot extends Auth_OpenID_ServerError {
- function Auth_OpenID_MalformedTrustRoot($message = null,
- $text = "Malformed trust root")
- {
- parent::Auth_OpenID_ServerError($message, $text);
- }
- function toString()
- {
- return "Malformed trust root";
- }
- }
- /**
- * The base class for all server request classes.
- *
- * @package OpenID
- */
- class Auth_OpenID_Request {
- var $mode = null;
- }
- /**
- * A request to verify the validity of a previous response.
- *
- * @package OpenID
- */
- class Auth_OpenID_CheckAuthRequest extends Auth_OpenID_Request {
- var $mode = "check_authentication";
- var $invalidate_handle = null;
- function Auth_OpenID_CheckAuthRequest($assoc_handle, $signed,
- $invalidate_handle = null)
- {
- $this->assoc_handle = $assoc_handle;
- $this->signed = $signed;
- if ($invalidate_handle !== null) {
- $this->invalidate_handle = $invalidate_handle;
- }
- $this->namespace = Auth_OpenID_OPENID2_NS;
- $this->message = null;
- }
- static function fromMessage($message, $server=null)
- {
- $required_keys = array('assoc_handle', 'sig', 'signed');
- foreach ($required_keys as $k) {
- if (!$message->getArg(Auth_OpenID_OPENID_NS, $k)) {
- return new Auth_OpenID_ServerError($message,
- sprintf("%s request missing required parameter %s from \
- query", "check_authentication", $k));
- }
- }
- $assoc_handle = $message->getArg(Auth_OpenID_OPENID_NS, 'assoc_handle');
- $sig = $message->getArg(Auth_OpenID_OPENID_NS, 'sig');
- $signed_list = $message->getArg(Auth_OpenID_OPENID_NS, 'signed');
- $signed_list = explode(",", $signed_list);
- $signed = $message;
- if ($signed->hasKey(Auth_OpenID_OPENID_NS, 'mode')) {
- $signed->setArg(Auth_OpenID_OPENID_NS, 'mode', 'id_res');
- }
- $result = new Auth_OpenID_CheckAuthRequest($assoc_handle, $signed);
- $result->message = $message;
- $result->sig = $sig;
- $result->invalidate_handle = $message->getArg(Auth_OpenID_OPENID_NS,
- 'invalidate_handle');
- return $result;
- }
- function answer($signatory)
- {
- $is_valid = $signatory->verify($this->assoc_handle, $this->signed);
- // Now invalidate that assoc_handle so it this checkAuth
- // message cannot be replayed.
- $signatory->invalidate($this->assoc_handle, true);
- $response = new Auth_OpenID_ServerResponse($this);
- $response->fields->setArg(Auth_OpenID_OPENID_NS,
- 'is_valid',
- ($is_valid ? "true" : "false"));
- if ($this->invalidate_handle) {
- $assoc = $signatory->getAssociation($this->invalidate_handle,
- false);
- if (!$assoc) {
- $response->fields->setArg(Auth_OpenID_OPENID_NS,
- 'invalidate_handle',
- $this->invalidate_handle);
- }
- }
- return $response;
- }
- }
- /**
- * A class implementing plaintext server sessions.
- *
- * @package OpenID
- */
- class Auth_OpenID_PlainTextServerSession {
- /**
- * An object that knows how to handle association requests with no
- * session type.
- */
- var $session_type = 'no-encryption';
- var $needs_math = false;
- var $allowed_assoc_types = array('HMAC-SHA1', 'HMAC-SHA256');
- static function fromMessage($unused_request)
- {
- return new Auth_OpenID_PlainTextServerSession();
- }
- function answer($secret)
- {
- return array('mac_key' => base64_encode($secret));
- }
- }
- /**
- * A class implementing DH-SHA1 server sessions.
- *
- * @package OpenID
- */
- class Auth_OpenID_DiffieHellmanSHA1ServerSession {
- /**
- * An object that knows how to handle association requests with
- * the Diffie-Hellman session type.
- */
- var $session_type = 'DH-SHA1';
- var $needs_math = true;
- var $allowed_assoc_types = array('HMAC-SHA1');
- var $hash_func = 'Auth_OpenID_SHA1';
- function Auth_OpenID_DiffieHellmanSHA1ServerSession($dh, $consumer_pubkey)
- {
- $this->dh = $dh;
- $this->consumer_pubkey = $consumer_pubkey;
- }
- static function getDH($message)
- {
- $dh_modulus = $message->getArg(Auth_OpenID_OPENID_NS, 'dh_modulus');
- $dh_gen = $message->getArg(Auth_OpenID_OPENID_NS, 'dh_gen');
- if ((($dh_modulus === null) && ($dh_gen !== null)) ||
- (($dh_gen === null) && ($dh_modulus !== null))) {
- if ($dh_modulus === null) {
- $missing = 'modulus';
- } else {
- $missing = 'generator';
- }
- return new Auth_OpenID_ServerError($message,
- 'If non-default modulus or generator is '.
- 'supplied, both must be supplied. Missing '.
- $missing);
- }
- $lib = Auth_OpenID_getMathLib();
- if ($dh_modulus || $dh_gen) {
- $dh_modulus = $lib->base64ToLong($dh_modulus);
- $dh_gen = $lib->base64ToLong($dh_gen);
- if ($lib->cmp($dh_modulus, 0) == 0 ||
- $lib->cmp($dh_gen, 0) == 0) {
- return new Auth_OpenID_ServerError(
- $message, "Failed to parse dh_mod or dh_gen");
- }
- $dh = new Auth_OpenID_DiffieHellman($dh_modulus, $dh_gen);
- } else {
- $dh = new Auth_OpenID_DiffieHellman();
- }
- $consumer_pubkey = $message->getArg(Auth_OpenID_OPENID_NS,
- 'dh_consumer_public');
- if ($consumer_pubkey === null) {
- return new Auth_OpenID_ServerError($message,
- 'Public key for DH-SHA1 session '.
- 'not found in query');
- }
- $consumer_pubkey =
- $lib->base64ToLong($consumer_pubkey);
- if ($consumer_pubkey === false) {
- return new Auth_OpenID_ServerError($message,
- "dh_consumer_public is not base64");
- }
- return array($dh, $consumer_pubkey);
- }
- static function fromMessage($message)
- {
- $result = Auth_OpenID_DiffieHellmanSHA1ServerSession::getDH($message);
- if (is_a($result, 'Auth_OpenID_ServerError')) {
- return $result;
- } else {
- list($dh, $consumer_pubkey) = $result;
- return new Auth_OpenID_DiffieHellmanSHA1ServerSession($dh,
- $consumer_pubkey);
- }
- }
- function answer($secret)
- {
- $lib = Auth_OpenID_getMathLib();
- $mac_key = $this->dh->xorSecret($this->consumer_pubkey, $secret,
- $this->hash_func);
- return array(
- 'dh_server_public' =>
- $lib->longToBase64($this->dh->public),
- 'enc_mac_key' => base64_encode($mac_key));
- }
- }
- /**
- * A class implementing DH-SHA256 server sessions.
- *
- * @package OpenID
- */
- class Auth_OpenID_DiffieHellmanSHA256ServerSession
- extends Auth_OpenID_DiffieHellmanSHA1ServerSession {
- var $session_type = 'DH-SHA256';
- var $hash_func = 'Auth_OpenID_SHA256';
- var $allowed_assoc_types = array('HMAC-SHA256');
- static function fromMessage($message)
- {
- $result = Auth_OpenID_DiffieHellmanSHA1ServerSession::getDH($message);
- if (is_a($result, 'Auth_OpenID_ServerError')) {
- return $result;
- } else {
- list($dh, $consumer_pubkey) = $result;
- return new Auth_OpenID_DiffieHellmanSHA256ServerSession($dh,
- $consumer_pubkey);
- }
- }
- }
- /**
- * A request to associate with the server.
- *
- * @package OpenID
- */
- class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request {
- var $mode = "associate";
- static function getSessionClasses()
- {
- return array(
- 'no-encryption' => 'Auth_OpenID_PlainTextServerSession',
- 'DH-SHA1' => 'Auth_OpenID_DiffieHellmanSHA1ServerSession',
- 'DH-SHA256' => 'Auth_OpenID_DiffieHellmanSHA256ServerSession');
- }
- function Auth_OpenID_AssociateRequest($session, $assoc_type)
- {
- $this->session = $session;
- $this->namespace = Auth_OpenID_OPENID2_NS;
- $this->assoc_type = $assoc_type;
- }
- static function fromMessage($message, $server=null)
- {
- if ($message->isOpenID1()) {
- $session_type = $message->getArg(Auth_OpenID_OPENID_NS,
- 'session_type');
- if ($session_type == 'no-encryption') {
- // oidutil.log('Received OpenID 1 request with a no-encryption '
- // 'assocaition session type. Continuing anyway.')
- } else if (!$session_type) {
- $session_type = 'no-encryption';
- }
- } else {
- $session_type = $message->getArg(Auth_OpenID_OPENID_NS,
- 'session_type');
- if ($session_type === null) {
- return new Auth_OpenID_ServerError($message,
- "session_type missing from request");
- }
- }
- $session_class = Auth_OpenID::arrayGet(
- Auth_OpenID_AssociateRequest::getSessionClasses(),
- $session_type);
- if ($session_class === null) {
- return new Auth_OpenID_ServerError($message,
- "Unknown session type " .
- $session_type);
- }
- $session = call_user_func(array($session_class, 'fromMessage'),
- $message);
- if (is_a($session, 'Auth_OpenID_ServerError')) {
- return $session;
- }
- $assoc_type = $message->getArg(Auth_OpenID_OPENID_NS,
- 'assoc_type', 'HMAC-SHA1');
- if (!in_array($assoc_type, $session->allowed_assoc_types)) {
- $fmt = "Session type %s does not support association type %s";
- return new Auth_OpenID_ServerError($message,
- sprintf($fmt, $session_type, $assoc_type));
- }
- $obj = new Auth_OpenID_AssociateRequest($session, $assoc_type);
- $obj->message = $message;
- $obj->namespace = $message->getOpenIDNamespace();
- return $obj;
- }
- function answer($assoc)
- {
- $response = new Auth_OpenID_ServerResponse($this);
- $response->fields->updateArgs(Auth_OpenID_OPENID_NS,
- array(
- 'expires_in' => sprintf('%d', $assoc->getExpiresIn()),
- 'assoc_type' => $this->assoc_type,
- 'assoc_handle' => $assoc->handle));
- $response->fields->updateArgs(Auth_OpenID_OPENID_NS,
- $this->session->answer($assoc->secret));
- if (! ($this->session->session_type == 'no-encryption'
- && $this->message->isOpenID1())) {
- $response->fields->setArg(Auth_OpenID_OPENID_NS,
- 'session_type',
- $this->session->session_type);
- }
- return $response;
- }
- function answerUnsupported($text_message,
- $preferred_association_type=null,
- $preferred_session_type=null)
- {
- if ($this->message->isOpenID1()) {
- return new Auth_OpenID_ServerError($this->message);
- }
- $response = new Auth_OpenID_ServerResponse($this);
- $response->fields->setArg(Auth_OpenID_OPENID_NS,
- 'error_code', 'unsupported-type');
- $response->fields->setArg(Auth_OpenID_OPENID_NS,
- 'error', $text_message);
- if ($preferred_association_type) {
- $response->fields->setArg(Auth_OpenID_OPENID_NS,
- 'assoc_type',
- $preferred_association_type);
- }
- if ($preferred_session_type) {
- $response->fields->setArg(Auth_OpenID_OPENID_NS,
- 'session_type',
- $preferred_session_type);
- }
- $response->code = AUTH_OPENID_HTTP_ERROR;
- return $response;
- }
- }
- /**
- * A request to confirm the identity of a user.
- *
- * @package OpenID
- */
- class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request {
- /**
- * Return-to verification callback. Default is
- * Auth_OpenID_verifyReturnTo from TrustRoot.php.
- */
- var $verifyReturnTo = 'Auth_OpenID_verifyReturnTo';
- /**
- * The mode of this request.
- */
- var $mode = "checkid_setup"; // or "checkid_immediate"
- /**
- * Whether this request is for immediate mode.
- */
- var $immediate = false;
- /**
- * The trust_root value for this request.
- */
- var $trust_root = null;
- /**
- * The OpenID namespace for this request.
- * deprecated since version 2.0.2
- */
- var $namespace;
-
- static function make($message, $identity, $return_to, $trust_root = null,
- $immediate = false, $assoc_handle = null, $server = null)
- {
- if ($server === null) {
- return new Auth_OpenID_ServerError($message,
- "server must not be null");
- }
- if ($return_to &&
- !Auth_OpenID_TrustRoot::_parse($return_to)) {
- return new Auth_OpenID_MalformedReturnURL($message, $return_to);
- }
- $r = new Auth_OpenID_CheckIDRequest($identity, $return_to,
- $trust_root, $immediate,
- $assoc_handle, $server);
- $r->namespace = $message->getOpenIDNamespace();
- $r->message = $message;
- if (!$r->trustRootValid()) {
- return new Auth_OpenID_UntrustedReturnURL($message,
- $return_to,
- $trust_root);
- } else {
- return $r;
- }
- }
- function Auth_OpenID_CheckIDRequest($identity, $return_to,
- $trust_root = null, $immediate = false,
- $assoc_handle = null, $server = null,
- $claimed_id = null)
- {
- $this->namespace = Auth_OpenID_OPENID2_NS;
- $this->assoc_handle = $assoc_handle;
- $this->identity = $identity;
- if ($claimed_id === null) {
- $this->claimed_id = $identity;
- } else {
- $this->claimed_id = $claimed_id;
- }
- $this->return_to = $return_to;
- $this->trust_root = $trust_root;
- $this->server = $server;
- if ($immediate) {
- $this->immediate = true;
- $this->mode = "checkid_immediate";
- } else {
- $this->immediate = false;
- $this->mode = "checkid_setup";
- }
- }
- function equals($other)
- {
- return (
- (is_a($other, 'Auth_OpenID_CheckIDRequest')) &&
- ($this->namespace == $other->namespace) &&
- ($this->assoc_handle == $other->assoc_handle) &&
- ($this->identity == $other->identity) &&
- ($this->claimed_id == $other->claimed_id) &&
- ($this->return_to == $other->return_to) &&
- ($this->trust_root == $other->trust_root));
- }
- /*
- * Does the relying party publish the return_to URL for this
- * response under the realm? It is up to the provider to set a
- * policy for what kinds of realms should be allowed. This
- * return_to URL verification reduces vulnerability to data-theft
- * attacks based on open proxies, corss-site-scripting, or open
- * redirectors.
- *
- * This check should only be performed after making sure that the
- * return_to URL matches the realm.
- *
- * @return true if the realm publishes a document with the
- * return_to URL listed, false if not or if discovery fails
- */
- function returnToVerified()
- {
- $fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
- return call_user_func_array($this->verifyReturnTo,
- array($this->trust_root, $this->return_to, $fetcher));
- }
- static function fromMessage($message, $server)
- {
- $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode');
- $immediate = null;
- if ($mode == "checkid_immediate") {
- $immediate = true;
- $mode = "checkid_immediate";
- } else {
- $immediate = false;
- $mode = "checkid_setup";
- }
- $return_to = $message->getArg(Auth_OpenID_OPENID_NS,
- 'return_to');
- if (($message->isOpenID1()) &&
- (!$return_to)) {
- $fmt = "Missing required field 'return_to' from checkid request";
- return new Auth_OpenID_ServerError($message, $fmt);
- }
- $identity = $message->getArg(Auth_OpenID_OPENID_NS,
- 'identity');
- $claimed_id = $message->getArg(Auth_OpenID_OPENID_NS, 'claimed_id');
- if ($message->isOpenID1()) {
- if ($identity === null) {
- $s = "OpenID 1 message did not contain openid.identity";
- return new Auth_OpenID_ServerError($message, $s);
- }
- } else {
- if ($identity && !$claimed_id) {
- $s = "OpenID 2.0 message contained openid.identity but not " .
- "claimed_id";
- return new Auth_OpenID_ServerError($message, $s);
- } else if ($claimed_id && !$identity) {
- $s = "OpenID 2.0 message contained openid.claimed_id " .
- "but not identity";
- return new Auth_OpenID_ServerError($message, $s);
- }
- }
- // There's a case for making self.trust_root be a TrustRoot
- // here. But if TrustRoot isn't currently part of the
- // "public" API, I'm not sure it's worth doing.
- if ($message->isOpenID1()) {
- $trust_root_param = 'trust_root';
- } else {
- $trust_root_param = 'realm';
- }
- $trust_root = $message->getArg(Auth_OpenID_OPENID_NS,
- $trust_root_param);
- if (! $trust_root) {
- $trust_root = $return_to;
- }
- if (! $message->isOpenID1() &&
- ($return_to === null) &&
- ($trust_root === null)) {
- return new Auth_OpenID_ServerError($message,
- "openid.realm required when openid.return_to absent");
- }
- $assoc_handle = $message->getArg(Auth_OpenID_OPENID_NS,
- 'assoc_handle');
- $obj = Auth_OpenID_CheckIDRequest::make($message,
- $identity,
- $return_to,
- $trust_root,
- $immediate,
- $assoc_handle,
- $server);
- if (is_a($obj, 'Auth_OpenID_ServerError')) {
- return $obj;
- }
- $obj->claimed_id = $claimed_id;
- return $obj;
- }
- function idSelect()
- {
- // Is the identifier to be selected by the IDP?
- // So IDPs don't have to import the constant
- return $this->identity == Auth_OpenID_IDENTIFIER_SELECT;
- }
- function trustRootValid()
- {
- if (!$this->trust_root) {
- return true;
- }
- $tr = Auth_OpenID_TrustRoot::_parse($this->trust_root);
- if ($tr === false) {
- return new Auth_OpenID_MalformedTrustRoot($this->message,
- $this->trust_root);
- }
- if ($this->return_to !== null) {
- return Auth_OpenID_TrustRoot::match($this->trust_root,
- $this->return_to);
- } else {
- return true;
- }
- }
- /**
- * Respond to this request. Return either an
- * {@link Auth_OpenID_ServerResponse} or
- * {@link Auth_OpenID_ServerError}.
- *
- * @param bool $allow Allow this user to claim this identity, and
- * allow the consumer to have this information?
- *
- * @param string $server_url DEPRECATED. Passing $op_endpoint to
- * the {@link Auth_OpenID_Server} constructor makes this optional.
- *
- * When an OpenID 1.x immediate mode request does not succeed, it
- * gets back a URL where the request may be carried out in a
- * not-so-immediate fashion. Pass my URL in here (the fully
- * qualified address of this server's endpoint, i.e.
- * http://example.com/server), and I will use it as a base for the
- * URL for a new request.
- *
- * Optional for requests where {@link $immediate} is false or
- * $allow is true.
- *
- * @param string $identity The OP-local identifier to answer with.
- * Only for use when the relying party requested identifier
- * selection.
- *
- * @param string $claimed_id The claimed identifier to answer
- * with, for use with identifier selection in the case where the
- * claimed identifier and the OP-local identifier differ,
- * i.e. when the claimed_id uses delegation.
- *
- * If $identity is provided but this is not, $claimed_id will
- * default to the value of $identity. When answering requests
- * that did not ask for identifier selection, the response
- * $claimed_id will default to that of the request.
- *
- * This parameter is new in OpenID 2.0.
- *
- * @return mixed
- */
- function answer($allow, $server_url = null, $identity = null,
- $claimed_id = null)
- {
- if (!$this->return_to) {
- return new Auth_OpenID_NoReturnToError();
- }
- if (!$server_url) {
- if ((!$this->message->isOpenID1()) &&
- (!$this->server->op_endpoint)) {
- return new Auth_OpenID_ServerError(null,
- "server should be constructed with op_endpoint to " .
- "respond to OpenID 2.0 messages.");
- }
- $server_url = $this->server->op_endpoint;
- }
- if ($allow) {
- $mode = 'id_res';
- } else if ($this->message->isOpenID1()) {
- if ($this->immediate) {
- $mode = 'id_res';
- } else {
- $mode = 'cancel';
- }
- } else {
- if ($this->immediate) {
- $mode = 'setup_needed';
- } else {
- $mode = 'cancel';
- }
- }
- if (!$this->trustRootValid()) {
- return new Auth_OpenID_UntrustedReturnURL(null,
- $this->return_to,
- $this->trust_root);
- }
- $response = new Auth_OpenID_ServerResponse($this);
- if ($claimed_id &&
- ($this->message->isOpenID1())) {
- return new Auth_OpenID_ServerError(null,
- "claimed_id is new in OpenID 2.0 and not " .
- "available for ".$this->namespace);
- }
- if ($identity && !$claimed_id) {
- $claimed_id = $identity;
- }
- if ($allow) {
- if ($this->identity == Auth_OpenID_IDENTIFIER_SELECT) {
- if (!$identity) {
- return new Auth_OpenID_ServerError(null,
- "This request uses IdP-driven identifier selection. " .
- "You must supply an identifier in the response.");
- }
- $response_identity = $identity;
- $response_claimed_id = $claimed_id;
- } else if ($this->identity) {
- if ($identity &&
- ($this->identity != $identity)) {
- $fmt = "Request was for %s, cannot reply with identity %s";
- return new Auth_OpenID_ServerError(null,
- sprintf($fmt, $this->identity, $identity));
- }
- $response_identity = $this->identity;
- $response_claimed_id = $this->claimed_id;
- } else {
- if ($identity) {
- return new Auth_OpenID_ServerError(null,
- "This request specified no identity and " .
- "you supplied ".$identity);
- }
- $response_identity = null;
- }
- if (($this->message->isOpenID1()) &&
- ($response_identity === null)) {
- return new Auth_OpenID_ServerError(null,
- "Request was an OpenID 1 request, so response must " .
- "include an identifier.");
- }
- $response->fields->updateArgs(Auth_OpenID_OPENID_NS,
- array('mode' => $mode,
- 'return_to' => $this->return_to,
- 'response_nonce' => Auth_OpenID_mkNonce()));
- if (!$this->message->isOpenID1()) {
- $response->fields->setArg(Auth_OpenID_OPENID_NS,
- 'op_endpoint', $server_url);
- }
- if ($response_identity !== null) {
- $response->fields->setArg(
- Auth_OpenID_OPENID_NS,
- 'identity',
- $response_identity);
- if ($this->message->isOpenID2()) {
- $response->fields->setArg(
- Auth_OpenID_OPENID_NS,
- 'claimed_id',
- $response_claimed_id);
- }
- }
- } else {
- $response->fields->setArg(Auth_OpenID_OPENID_NS,
- 'mode', $mode);
- if ($this->immediate) {
- if (($this->message->isOpenID1()) &&
- (!$server_url)) {
- return new Auth_OpenID_ServerError(null,
- 'setup_url is required for $allow=false \
- in OpenID 1.x immediate mode.');
- }
- $setup_request = new Auth_OpenID_CheckIDRequest(
- $this->identity,
- $this->return_to,
- $this->trust_root,
- false,
- $this->assoc_handle,
- $this->server,
- $this->claimed_id);
- $setup_request->message = $this->message;
- $setup_url = $setup_request->encodeToURL($server_url);
- if ($setup_url === null) {
- return new Auth_OpenID_NoReturnToError();
- }
- $response->fields->setArg(Auth_OpenID_OPENID_NS,
- 'user_setup_url',
- $setup_url);
- }
- }
- return $response;
- }
- function encodeToURL($server_url)
- {
- if (!$this->return_to) {
- return new Auth_OpenID_NoReturnToError();
- }
- // Imported from the alternate reality where these classes are
- // used in both the client and server code, so Requests are
- // Encodable too. That's right, code imported from alternate
- // realities all for the love of you, id_res/user_setup_url.
- $q = array('mode' => $this->mode,
- 'identity' => $this->identity,
- 'claimed_id' => $this->claimed_id,
- 'return_to' => $this->return_to);
- if ($this->trust_root) {
- if ($this->message->isOpenID1()) {
- $q['trust_root'] = $this->trust_root;
- } else {
- $q['realm'] = $this->trust_root;
- }
- }
- if ($this->assoc_handle) {
- $q['assoc_handle'] = $this->assoc_handle;
- }
- $response = new Auth_OpenID_Message(
- $this->message->getOpenIDNamespace());
- $response->updateArgs(Auth_OpenID_OPENID_NS, $q);
- return $response->toURL($server_url);
- }
- function getCancelURL()
- {
- if (!$this->return_to) {
- return new Auth_OpenID_NoReturnToError();
- }
- if ($this->immediate) {
- return new Auth_OpenID_ServerError(null,
- "Cancel is not an appropriate \
- response to immediate mode \
- requests.");
- }
- $response = new Auth_OpenID_Message(
- $this->message->getOpenIDNamespace());
- $response->setArg(Auth_OpenID_OPENID_NS, 'mode', 'cancel');
- return $response->toURL($this->return_to);
- }
- }
- /**
- * This class encapsulates the response to an OpenID server request.
- *
- * @package OpenID
- */
- class Auth_OpenID_ServerResponse {
- function Auth_OpenID_ServerResponse($request)
- {
- $this->request = $request;
- $this->fields = new Auth_OpenID_Message($this->request->namespace);
- }
- function whichEncoding()
- {
- global $_Auth_OpenID_Request_Modes;
- if (in_array($this->request->mode, $_Auth_OpenID_Request_Modes)) {
- if ($this->fields->isOpenID2() &&
- (strlen($this->encodeToURL()) >
- Auth_OpenID_OPENID1_URL_LIMIT)) {
- return Auth_OpenID_ENCODE_HTML_FORM;
- } else {
- return Auth_OpenID_ENCODE_URL;
- }
- } else {
- return Auth_OpenID_ENCODE_KVFORM;
- }
- }
- /*
- * Returns the form markup for this response.
- *
- * @return str
- */
- function toFormMarkup($form_tag_attrs=null)
- {
- return $this->fields->toFormMarkup($this->request->return_to,
- $form_tag_attrs);
- }
- /*
- * Returns an HTML document containing the form markup for this
- * response that autosubmits with javascript.
- */
- function toHTML()
- {
- return Auth_OpenID::autoSubmitHTML($this->toFormMarkup());
- }
- /*
- * Returns True if this response's encoding is ENCODE_HTML_FORM.
- * Convenience method for server authors.
- *
- * @return bool
- */
- function renderAsForm()
- {
- return $this->whichEncoding() == Auth_OpenID_ENCODE_HTML_FORM;
- }
- function encodeToURL()
- {
- return $this->fields->toURL($this->request->return_to);
- }
- function addExtension($extension_response)
- {
- $extension_response->toMessage($this->fields);
- }
- function needsSigning()
- {
- return $this->fields->getArg(Auth_OpenID_OPENID_NS,
- 'mode') == 'id_res';
- }
- function encodeToKVForm()
- {
- return $this->fields->toKVForm();
- }
- }
- /**
- * A web-capable response object which you can use to generate a
- * user-agent response.
- *
- * @package OpenID
- */
- class Auth_OpenID_WebResponse {
- var $code = AUTH_OPENID_HTTP_OK;
- var $body = "";
- function Auth_OpenID_WebResponse($code = null, $headers = null,
- $body = null)
- {
- if ($code) {
- $this->code = $code;
- }
- if ($headers !== null) {
- $this->headers = $headers;
- } else {
- $this->headers = array();
- }
- if ($body !== null) {
- $this->body = $body;
- }
- }
- }
- /**
- * Responsible for the signature of query data and the verification of
- * OpenID signature values.
- *
- * @package OpenID
- */
- class Auth_OpenID_Signatory {
- // = 14 * 24 * 60 * 60; # 14 days, in seconds
- var $SECRET_LIFETIME = 1209600;
- // keys have a bogus server URL in them because the filestore
- // really does expect that key to be a URL. This seems a little
- // silly for the server store, since I expect there to be only one
- // server URL.
- var $normal_key = 'http://localhost/|normal';
- var $dumb_key = 'http://localhost/|dumb';
- /**
- * Create a new signatory using a given store.
- */
- function Auth_OpenID_Signatory($store)
- {
- // assert store is not None
- $this->store = $store;
- }
- /**
- * Verify, using a given association handle, a signature with
- * signed key-value pairs from an HTTP request.
- */
- function verify($assoc_handle, $message)
- {
- $assoc = $this->getAssociation($assoc_handle, true);
- if (!$assoc) {
- // oidutil.log("failed to get assoc with handle %r to verify sig %r"
- // % (assoc_handle, sig))
- return false;
- }
- return $assoc->checkMessageSignature($message);
- }
- /**
- * Given a response, sign the fields in the response's 'signed'
- * list, and insert the signature into the response.
- */
- function sign($response)
- {
- $signed_response = $response;
- $assoc_handle = $response->request->assoc_handle;
- if ($assoc_handle) {
- // normal mode
- $assoc = $this->getAssociation($assoc_handle, false, false);
- if (!$assoc || ($assoc->getExpiresIn() <= 0)) {
- // fall back to dumb mode
- $signed_response->fields->setArg(Auth_OpenID_OPENID_NS,
- 'invalidate_handle', $assoc_handle);
- $assoc_type = ($assoc ? $assoc->assoc_type : 'HMAC-SHA1');
- if ($assoc && ($assoc->getExpiresIn() <= 0)) {
- $this->invalidate($assoc_handle, false);
- }
- $assoc = $this->createAssociation(true, $assoc_type);
- }
- } else {
- // dumb mode.
- $assoc = $this->createAssociation(true);
- }
- $signed_response->fields = $assoc->signMessage(
- $signed_response->fields);
- return $signed_response;
- }
- /**
- * Make a new association.
- */
- function createAssociation($dumb = true, $assoc_type = 'HMAC-SHA1')
- {
- $secret = Auth_OpenID_CryptUtil::getBytes(
- Auth_OpenID_getSecretSize($assoc_type));
- $uniq = base64_encode(Auth_OpenID_CryptUtil::getBytes(4));
- $handle = sprintf('{%s}{%x}{%s}', $assoc_type, intval(time()), $uniq);
- $assoc = Auth_OpenID_Association::fromExpiresIn(
- $this->SECRET_LIFETIME, $handle, $secret, $assoc_type);
- if ($dumb) {
- $key = $this->dumb_key;
- } else {
- $key = $this->normal_key;
- }
- $this->store->storeAssociation($key, $assoc);
- return $assoc;
- }
- /**
- * Given an association handle, get the association from the
- * store, or return a ServerError or null if something goes wrong.
- */
- function getAssociation($assoc_handle, $dumb, $check_expiration=true)
- {
- if ($assoc_handle === null) {
- return new Auth_OpenID_ServerError(null,
- "assoc_handle must not be null");
- }
- if ($dumb) {
- $key = $this->dumb_key;
- } else {
- $key = $this->normal_key;
- }
- $assoc = $this->store->getAssociation($key, $assoc_handle);
- if (($assoc !== null) && ($assoc->getExpiresIn() <= 0)) {
- if ($check_expiration) {
- $this->store->removeAssociation($key, $assoc_handle);
- $assoc = null;
- }
- }
- return $assoc;
- }
- /**
- * Invalidate a given association handle.
- */
- function invalidate($assoc_handle, $dumb)
- {
- if ($dumb) {
- $key = $this->dumb_key;
- } else {
- $key = $this->normal_key;
- }
- $this->store->removeAssociation($key, $assoc_handle);
- }
- }
- /**
- * Encode an {@link Auth_OpenID_ServerResponse} to an
- * {@link Auth_OpenID_WebResponse}.
- *
- * @package OpenID
- */
- class Auth_OpenID_Encoder {
- var $responseFactory = 'Auth_OpenID_WebResponse';
- /**
- * Encode an {@link Auth_OpenID_ServerResponse} and return an
- * {@link Auth_OpenID_WebResponse}.
- */
- function encode($response)
- {
- $cls = $this->responseFactory;
- $encode_as = $response->whichEncoding();
- if ($encode_as == Auth_OpenID_ENCODE_KVFORM) {
- $wr = new $cls(null, null, $response->encodeToKVForm());
- if (is_a($response, 'Auth_OpenID_ServerError')) {
- $wr->code = AUTH_OPENID_HTTP_ERROR;
- }
- } else if ($encode_as == Auth_OpenID_ENCODE_URL) {
- $location = $response->encodeToURL();
- $wr = new $cls(AUTH_OPENID_HTTP_REDIRECT,
- array('location' => $location));
- } else if ($encode_as == Auth_OpenID_ENCODE_HTML_FORM) {
- $wr = new $cls(AUTH_OPENID_HTTP_OK, array(),
- $response->toHTML());
- } else {
- return new Auth_OpenID_EncodingError($response);
- }
- /* Allow the response to carry a custom error code (ex: for Association errors) */
- if(isset($response->code)) {
- $wr->code = $response->code;
- }
- return $wr;
- }
- }
- /**
- * An encoder which also takes care of signing fields when required.
- *
- * @package OpenID
- */
- class Auth_OpenID_SigningEncoder extends Auth_OpenID_Encoder {
- function Auth_OpenID_SigningEncoder($signatory)
- {
- $this->signatory = $signatory;
- }
- /**
- * Sign an {@link Auth_OpenID_ServerResponse} and return an
- * {@link Auth_OpenID_WebResponse}.
- */
- function encode($response)
- {
- // the isinstance is a bit of a kludge... it means there isn't
- // really an adapter to make the interfaces quite match.
- if (!is_a($response, 'Auth_OpenID_ServerError') &&
- $response->needsSigning()) {
- if (!$this->signatory) {
- return new Auth_OpenID_ServerError(null,
- "Must have a store to sign request");
- }
- if ($response->fields->hasKey(Auth_OpenID_OPENID_NS, 'sig')) {
- return new Auth_OpenID_AlreadySigned($response);
- }
- $response = $this->signatory->sign($response);
- }
- return parent::encode($response);
- }
- }
- /**
- * Decode an incoming query into an Auth_OpenID_Request.
- *
- * @package OpenID
- */
- class Auth_OpenID_Decoder {
- function Auth_OpenID_Decoder($server)
- {
- $this->server = $server;
- $this->handlers = array(
- 'checkid_setup' => 'Auth_OpenID_CheckIDRequest',
- 'checkid_immediate' => 'Auth_OpenID_CheckIDRequest',
- 'check_authentication' => 'Auth_OpenID_CheckAuthRequest',
- 'associate' => 'Auth_OpenID_AssociateRequest'
- );
- }
- /**
- * Given an HTTP query in an array (key-value pairs), decode it
- * into an Auth_OpenID_Request object.
- */
- function decode($query)
- {
- if (!$query) {
- return null;
- }
- $message = Auth_OpenID_Message::fromPostArgs($query);
- if ($message === null) {
- /*
- * It's useful to have a Message attached to a
- * ProtocolError, so we override the bad ns value to build
- * a Message out of it. Kinda kludgy, since it's made of
- * lies, but the parts that aren't lies are more useful
- * than a 'None'.
- */
- $old_ns = $query['openid.ns'];
- $query['openid.ns'] = Auth_OpenID_OPENID2_NS;
- $message = Auth_OpenID_Message::fromPostArgs($query);
- return new Auth_OpenID_ServerError(
- $message,
- sprintf("Invalid OpenID namespace URI: %s", $old_ns));
- }
- $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode');
- if (!$mode) {
- return new Auth_OpenID_ServerError($message,
- "No mode value in message");
- }
- if (Auth_OpenID::isFailure($mode)) {
- return new Auth_OpenID_ServerError($message,
- $mode->message);
- }
- $handlerCls = Auth_OpenID::arrayGet($this->handlers, $mode,
- $this->defaultDecoder($message));
- if (!is_a($handlerCls, 'Auth_OpenID_ServerError')) {
- return call_user_func_array(array($handlerCls, 'fromMessage'),
- array($message, $this->server));
- } else {
- return $handlerCls;
- }
- }
- function defaultDecoder($message)
- {
- $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode');
- if (Auth_OpenID::isFailure($mode)) {
- return new Auth_OpenID_ServerError($message,
- $mode->message);
- }
- return new Auth_OpenID_ServerError($message,
- sprintf("Unrecognized OpenID mode %s", $mode));
- }
- }
- /**
- * An error that indicates an encoding problem occurred.
- *
- * @package OpenID
- */
- class Auth_OpenID_EncodingError {
- function Auth_OpenID_EncodingError($response)
- {
- $this->response = $response;
- }
- }
- /**
- * An error that indicates that a response was already signed.
- *
- * @package OpenID
- */
- class Auth_OpenID_AlreadySigned extends Auth_OpenID_EncodingError {
- // This response is already signed.
- }
- /**
- * An error that indicates that the given return_to is not under the
- * given trust_root.
- *
- * @package OpenID
- */
- class Auth_OpenID_UntrustedReturnURL extends Auth_OpenID_ServerError {
- function Auth_OpenID_UntrustedReturnURL($message, $return_to,
- $trust_root)
- {
- parent::Auth_OpenID_ServerError($message, "Untrusted return_to URL");
- $this->return_to = $return_to;
- $this->trust_root = $trust_root;
- }
- function toString()
- {
- return sprintf("return_to %s not under trust_root %s",
- $this->return_to, $this->trust_root);
- }
- }
- /**
- * I handle requests for an OpenID server.
- *
- * Some types of requests (those which are not checkid requests) may
- * be handed to my {@link handleRequest} method, and I will take care
- * of it and return a response.
- *
- * For your convenience, I also provide an interface to {@link
- * Auth_OpenID_Decoder::decode()} and {@link
- * Auth_OpenID_SigningEncoder::encode()} through my methods {@link
- * decodeRequest} and {@link encodeResponse}.
- *
- * All my state is encapsulated in an {@link Auth_OpenID_OpenIDStore}.
- *
- * Example:
- *
- * <pre> $oserver = new Auth_OpenID_Server(Auth_OpenID_FileStore($data_path),
- * "http://example.com/op");
- * $request = $oserver->decodeRequest();
- * if (in_array($request->mode, array('checkid_immediate',
- * 'checkid_setup'))) {
- * if ($app->isAuthorized($request->identity, $request->trust_root)) {
- * $response = $request->answer(true);
- * } else if ($request->immediate) {
- * $response = $request->answer(false);
- * } else {
- * $app->showDecidePage($request);
- * return;
- * }
- * } else {
- * $response = $oserver->handleRequest($request);
- * }
- *
- * $webresponse = $oserver->encode($response);</pre>
- *
- * @package OpenID
- */
- class Auth_OpenID_Server {
- function Auth_OpenID_Server($store, $op_endpoint=null)
- {
- $this->store = $store;
- $this->signatory = new Auth_OpenID_Signatory($this->store);
- $this->encoder = new Auth_OpenID_SigningEncoder($this->signatory);
- $this->decoder = new Auth_OpenID_Decoder($this);
- $this->op_endpoint = $op_endpoint;
- $this->negotiator = Auth_OpenID_getDefaultNegotiator();
- }
- /**
- * Handle a request. Given an {@link Auth_OpenID_Request} object,
- * call the appropriate {@link Auth_OpenID_Server} method to
- * process the request and generate a response.
- *
- * @param Auth_OpenID_Request $request An {@link Auth_OpenID_Request}
- * returned by {@link Auth_OpenID_Server::decodeRequest()}.
- *
- * @return Auth_OpenID_ServerResponse $response A response object
- * capable of generating a user-agent reply.
- */
- function handleRequest($request)
- {
- if (method_exists($this, "openid_" . $request->mode)) {
- $handler = array($this, "openid_" . $request->mode);
- return call_user_func_array($handler, array($request));
- }
- return null;
- }
- /**
- * The callback for 'check_authentication' messages.
- */
- function openid_check_authentication($request)
- {
- return $request->answer($this->signatory);
- }
- /**
- * The callback for 'associate' messages.
- */
- function openid_associate($request)
- {
- $assoc_type = $request->assoc_type;
- $session_type = $request->session->session_type;
- if ($this->negotiator->isAllowed($assoc_type, $session_type)) {
- $assoc = $this->signatory->createAssociation(false,
- $assoc_type);
- return $request->answer($assoc);
- } else {
- $message = sprintf('Association type %s is not supported with '.
- 'session type %s', $assoc_type, $session_type);
- list($preferred_assoc_type, $preferred_session_type) =
- $this->negotiator->getAllowedType();
- return $request->answerUnsupported($message,
- $preferred_assoc_type,
- $preferred_session_type);
- }
- }
- /**
- * Encodes as response in the appropriate format suitable for
- * sending to the user agent.
- */
- function encodeResponse($response)
- {
- return $this->encoder->encode($response);
- }
- /**
- * Decodes a query args array into the appropriate
- * {@link Auth_OpenID_Request} object.
- */
- function decodeRequest($query=null)
- {
- if ($query === null) {
- $query = Auth_OpenID::getQuery();
- }
- return $this->decoder->decode($query);
- }
- }
|