1: <?php
   2: 
   3:    4:    5:    6:    7:    8:    9:   10:   11:   12:   13:   14:   15:   16:   17:   18:   19:   20:   21:   22:   23:   24:   25:   26:   27:   28:   29:   30:   31:   32:   33:   34:   35:   36:   37:   38:   39:   40:   41:   42:   43:   44:   45:   46:   47:   48:   49:   50:   51:   52:   53:   54:   55:   56:   57:   58:   59:   60:   61:   62:   63:   64:   65:   66:   67:   68:   69:   70:   71:   72:   73:   74:   75:   76:   77:   78:   79:   80:   81:   82:   83:   84:   85:   86:   87:   88:   89:   90: 
  91: 
  92:   93:   94: 
  95: require_once "Auth/OpenID.php";
  96: require_once "Auth/OpenID/Association.php";
  97: require_once "Auth/OpenID/CryptUtil.php";
  98: require_once "Auth/OpenID/BigMath.php";
  99: require_once "Auth/OpenID/DiffieHellman.php";
 100: require_once "Auth/OpenID/KVForm.php";
 101: require_once "Auth/OpenID/TrustRoot.php";
 102: require_once "Auth/OpenID/ServerRequest.php";
 103: require_once "Auth/OpenID/Message.php";
 104: require_once "Auth/OpenID/Nonce.php";
 105: 
 106: define('AUTH_OPENID_HTTP_OK', 200);
 107: define('AUTH_OPENID_HTTP_REDIRECT', 302);
 108: define('AUTH_OPENID_HTTP_ERROR', 400);
 109: 
 110:  111:  112: 
 113: global $_Auth_OpenID_Request_Modes;
 114: $_Auth_OpenID_Request_Modes = array('checkid_setup',
 115:                                     'checkid_immediate');
 116: 
 117:  118:  119: 
 120: define('Auth_OpenID_ENCODE_KVFORM', 'kfvorm');
 121: 
 122:  123:  124: 
 125: define('Auth_OpenID_ENCODE_URL', 'URL/redirect');
 126: 
 127:  128:  129: 
 130: define('Auth_OpenID_ENCODE_HTML_FORM', 'HTML form');
 131: 
 132:  133:  134: 
 135: function Auth_OpenID_isError($obj, $cls = Auth_OpenID_ServerError)
 136: {
 137:     return ($obj instanceof $cls);
 138: }
 139: 
 140:  141:  142:  143:  144:  145:  146: 
 147: class Auth_OpenID_ServerError {
 148:      149:  150: 
 151:     function Auth_OpenID_ServerError($message = null, $text = null,
 152:                                      $reference = null, $contact = null)
 153:     {
 154:         $this->message = $message;
 155:         $this->text = $text;
 156:         $this->contact = $contact;
 157:         $this->reference = $reference;
 158:     }
 159: 
 160:     function getReturnTo()
 161:     {
 162:         if ($this->message &&
 163:             $this->message->hasKey(Auth_OpenID_OPENID_NS, 'return_to')) {
 164:             return $this->message->getArg(Auth_OpenID_OPENID_NS,
 165:                                           'return_to');
 166:         } else {
 167:             return null;
 168:         }
 169:     }
 170: 
 171:      172:  173:  174: 
 175:     function hasReturnTo()
 176:     {
 177:         return $this->getReturnTo() !== null;
 178:     }
 179: 
 180:      181:  182:  183:  184: 
 185:     function encodeToURL()
 186:     {
 187:         if (!$this->message) {
 188:             return null;
 189:         }
 190: 
 191:         $msg = $this->toMessage();
 192:         return $msg->toURL($this->getReturnTo());
 193:     }
 194: 
 195:      196:  197:  198:  199:  200: 
 201:     function encodeToKVForm()
 202:     {
 203:         return Auth_OpenID_KVForm::fromArray(
 204:                                       array('mode' => 'error',
 205:                                             'error' => $this->toString()));
 206:     }
 207: 
 208:     function toFormMarkup($form_tag_attrs=null)
 209:     {
 210:         $msg = $this->toMessage();
 211:         return $msg->toFormMarkup($this->getReturnTo(), $form_tag_attrs);
 212:     }
 213: 
 214:     function toHTML($form_tag_attrs=null)
 215:     {
 216:         return Auth_OpenID::autoSubmitHTML(
 217:                       $this->toFormMarkup($form_tag_attrs));
 218:     }
 219: 
 220:     function toMessage()
 221:     {
 222:         
 223:         
 224:         $namespace = $this->message->getOpenIDNamespace();
 225:         $reply = new Auth_OpenID_Message($namespace);
 226:         $reply->setArg(Auth_OpenID_OPENID_NS, 'mode', 'error');
 227:         $reply->setArg(Auth_OpenID_OPENID_NS, 'error', $this->toString());
 228: 
 229:         if ($this->contact !== null) {
 230:             $reply->setArg(Auth_OpenID_OPENID_NS, 'contact', $this->contact);
 231:         }
 232: 
 233:         if ($this->reference !== null) {
 234:             $reply->setArg(Auth_OpenID_OPENID_NS, 'reference',
 235:                            $this->reference);
 236:         }
 237: 
 238:         return $reply;
 239:     }
 240: 
 241:      242:  243:  244:  245: 
 246:     function whichEncoding()
 247:     {
 248:         global $_Auth_OpenID_Request_Modes;
 249: 
 250:         if ($this->hasReturnTo()) {
 251:             if ($this->message->isOpenID2() &&
 252:                 (strlen($this->encodeToURL()) >
 253:                    Auth_OpenID_OPENID1_URL_LIMIT)) {
 254:                 return Auth_OpenID_ENCODE_HTML_FORM;
 255:             } else {
 256:                 return Auth_OpenID_ENCODE_URL;
 257:             }
 258:         }
 259: 
 260:         if (!$this->message) {
 261:             return null;
 262:         }
 263: 
 264:         $mode = $this->message->getArg(Auth_OpenID_OPENID_NS,
 265:                                        'mode');
 266: 
 267:         if ($mode) {
 268:             if (!in_array($mode, $_Auth_OpenID_Request_Modes)) {
 269:                 return Auth_OpenID_ENCODE_KVFORM;
 270:             }
 271:         }
 272:         return null;
 273:     }
 274: 
 275:      276:  277: 
 278:     function toString()
 279:     {
 280:         if ($this->text) {
 281:             return $this->text;
 282:         } else {
 283:             return get_class($this) . " error";
 284:         }
 285:     }
 286: }
 287: 
 288:  289:  290:  291:  292:  293: 
 294: class Auth_OpenID_NoReturnToError extends Auth_OpenID_ServerError {
 295:     function Auth_OpenID_NoReturnToError($message = null,
 296:                                          $text = "No return_to URL available")
 297:     {
 298:         parent::Auth_OpenID_ServerError($message, $text);
 299:     }
 300: 
 301:     function toString()
 302:     {
 303:         return "No return_to available";
 304:     }
 305: }
 306: 
 307:  308:  309:  310:  311: 
 312: class Auth_OpenID_MalformedReturnURL extends Auth_OpenID_ServerError {
 313:     function Auth_OpenID_MalformedReturnURL($message, $return_to)
 314:     {
 315:         $this->return_to = $return_to;
 316:         parent::Auth_OpenID_ServerError($message, "malformed return_to URL");
 317:     }
 318: }
 319: 
 320:  321:  322:  323:  324: 
 325: class Auth_OpenID_MalformedTrustRoot extends Auth_OpenID_ServerError {
 326:     function Auth_OpenID_MalformedTrustRoot($message = null,
 327:                                             $text = "Malformed trust root")
 328:     {
 329:         parent::Auth_OpenID_ServerError($message, $text);
 330:     }
 331: 
 332:     function toString()
 333:     {
 334:         return "Malformed trust root";
 335:     }
 336: }
 337: 
 338:  339:  340:  341:  342: 
 343: class Auth_OpenID_Request {
 344:     var $mode = null;
 345: }
 346: 
 347:  348:  349:  350:  351: 
 352: class Auth_OpenID_CheckAuthRequest extends Auth_OpenID_Request {
 353:     var $mode = "check_authentication";
 354:     var $invalidate_handle = null;
 355: 
 356:     function Auth_OpenID_CheckAuthRequest($assoc_handle, $signed,
 357:                                           $invalidate_handle = null)
 358:     {
 359:         $this->assoc_handle = $assoc_handle;
 360:         $this->signed = $signed;
 361:         if ($invalidate_handle !== null) {
 362:             $this->invalidate_handle = $invalidate_handle;
 363:         }
 364:         $this->namespace = Auth_OpenID_OPENID2_NS;
 365:         $this->message = null;
 366:     }
 367: 
 368:     static function fromMessage($message, $server=null)
 369:     {
 370:         $required_keys = array('assoc_handle', 'sig', 'signed');
 371: 
 372:         foreach ($required_keys as $k) {
 373:             if (!$message->getArg(Auth_OpenID_OPENID_NS, $k)) {
 374:                 return new Auth_OpenID_ServerError($message,
 375:                     sprintf("%s request missing required parameter %s from \
 376:                             query", "check_authentication", $k));
 377:             }
 378:         }
 379: 
 380:         $assoc_handle = $message->getArg(Auth_OpenID_OPENID_NS, 'assoc_handle');
 381:         $sig = $message->getArg(Auth_OpenID_OPENID_NS, 'sig');
 382: 
 383:         $signed_list = $message->getArg(Auth_OpenID_OPENID_NS, 'signed');
 384:         $signed_list = explode(",", $signed_list);
 385: 
 386:         $signed = $message;
 387:         if ($signed->hasKey(Auth_OpenID_OPENID_NS, 'mode')) {
 388:             $signed->setArg(Auth_OpenID_OPENID_NS, 'mode', 'id_res');
 389:         }
 390: 
 391:         $result = new Auth_OpenID_CheckAuthRequest($assoc_handle, $signed);
 392:         $result->message = $message;
 393:         $result->sig = $sig;
 394:         $result->invalidate_handle = $message->getArg(Auth_OpenID_OPENID_NS,
 395:                                                       'invalidate_handle');
 396:         return $result;
 397:     }
 398: 
 399:     function answer($signatory)
 400:     {
 401:         $is_valid = $signatory->verify($this->assoc_handle, $this->signed);
 402: 
 403:         
 404:         
 405:         $signatory->invalidate($this->assoc_handle, true);
 406:         $response = new Auth_OpenID_ServerResponse($this);
 407: 
 408:         $response->fields->setArg(Auth_OpenID_OPENID_NS,
 409:                                   'is_valid',
 410:                                   ($is_valid ? "true" : "false"));
 411: 
 412:         if ($this->invalidate_handle) {
 413:             $assoc = $signatory->getAssociation($this->invalidate_handle,
 414:                                                 false);
 415:             if (!$assoc) {
 416:                 $response->fields->setArg(Auth_OpenID_OPENID_NS,
 417:                                           'invalidate_handle',
 418:                                           $this->invalidate_handle);
 419:             }
 420:         }
 421:         return $response;
 422:     }
 423: }
 424: 
 425:  426:  427:  428:  429: 
 430: class Auth_OpenID_PlainTextServerSession {
 431:      432:  433:  434: 
 435:     var $session_type = 'no-encryption';
 436:     var $needs_math = false;
 437:     var $allowed_assoc_types = array('HMAC-SHA1', 'HMAC-SHA256');
 438: 
 439:     static function fromMessage($unused_request)
 440:     {
 441:         return new Auth_OpenID_PlainTextServerSession();
 442:     }
 443: 
 444:     function answer($secret)
 445:     {
 446:         return array('mac_key' => base64_encode($secret));
 447:     }
 448: }
 449: 
 450:  451:  452:  453:  454: 
 455: class Auth_OpenID_DiffieHellmanSHA1ServerSession {
 456:      457:  458:  459: 
 460: 
 461:     var $session_type = 'DH-SHA1';
 462:     var $needs_math = true;
 463:     var $allowed_assoc_types = array('HMAC-SHA1');
 464:     var $hash_func = 'Auth_OpenID_SHA1';
 465: 
 466:     function Auth_OpenID_DiffieHellmanSHA1ServerSession($dh, $consumer_pubkey)
 467:     {
 468:         $this->dh = $dh;
 469:         $this->consumer_pubkey = $consumer_pubkey;
 470:     }
 471: 
 472:     static function getDH($message)
 473:     {
 474:         $dh_modulus = $message->getArg(Auth_OpenID_OPENID_NS, 'dh_modulus');
 475:         $dh_gen = $message->getArg(Auth_OpenID_OPENID_NS, 'dh_gen');
 476: 
 477:         if ((($dh_modulus === null) && ($dh_gen !== null)) ||
 478:             (($dh_gen === null) && ($dh_modulus !== null))) {
 479: 
 480:             if ($dh_modulus === null) {
 481:                 $missing = 'modulus';
 482:             } else {
 483:                 $missing = 'generator';
 484:             }
 485: 
 486:             return new Auth_OpenID_ServerError($message,
 487:                                 'If non-default modulus or generator is '.
 488:                                 'supplied, both must be supplied.  Missing '.
 489:                                 $missing);
 490:         }
 491: 
 492:         $lib = Auth_OpenID_getMathLib();
 493: 
 494:         if ($dh_modulus || $dh_gen) {
 495:             $dh_modulus = $lib->base64ToLong($dh_modulus);
 496:             $dh_gen = $lib->base64ToLong($dh_gen);
 497:             if ($lib->cmp($dh_modulus, 0) == 0 ||
 498:                 $lib->cmp($dh_gen, 0) == 0) {
 499:                 return new Auth_OpenID_ServerError(
 500:                   $message, "Failed to parse dh_mod or dh_gen");
 501:             }
 502:             $dh = new Auth_OpenID_DiffieHellman($dh_modulus, $dh_gen);
 503:         } else {
 504:             $dh = new Auth_OpenID_DiffieHellman();
 505:         }
 506: 
 507:         $consumer_pubkey = $message->getArg(Auth_OpenID_OPENID_NS,
 508:                                             'dh_consumer_public');
 509:         if ($consumer_pubkey === null) {
 510:             return new Auth_OpenID_ServerError($message,
 511:                                   'Public key for DH-SHA1 session '.
 512:                                   'not found in query');
 513:         }
 514: 
 515:         $consumer_pubkey =
 516:             $lib->base64ToLong($consumer_pubkey);
 517: 
 518:         if ($consumer_pubkey === false) {
 519:             return new Auth_OpenID_ServerError($message,
 520:                                        "dh_consumer_public is not base64");
 521:         }
 522: 
 523:         return array($dh, $consumer_pubkey);
 524:     }
 525: 
 526:     static function fromMessage($message)
 527:     {
 528:         $result = Auth_OpenID_DiffieHellmanSHA1ServerSession::getDH($message);
 529: 
 530:         if (($result instanceof  Auth_OpenID_ServerError)) {
 531:             return $result;
 532:         } else {
 533:             list($dh, $consumer_pubkey) = $result;
 534:             return new Auth_OpenID_DiffieHellmanSHA1ServerSession($dh,
 535:                                                     $consumer_pubkey);
 536:         }
 537:     }
 538: 
 539:     function answer($secret)
 540:     {
 541:         $lib = Auth_OpenID_getMathLib();
 542:         $mac_key = $this->dh->xorSecret($this->consumer_pubkey, $secret,
 543:                                         $this->hash_func);
 544:         return array(
 545:            'dh_server_public' =>
 546:                 $lib->longToBase64($this->dh->public),
 547:            'enc_mac_key' => base64_encode($mac_key));
 548:     }
 549: }
 550: 
 551:  552:  553:  554:  555: 
 556: class Auth_OpenID_DiffieHellmanSHA256ServerSession
 557:       extends Auth_OpenID_DiffieHellmanSHA1ServerSession {
 558: 
 559:     var $session_type = 'DH-SHA256';
 560:     var $hash_func = 'Auth_OpenID_SHA256';
 561:     var $allowed_assoc_types = array('HMAC-SHA256');
 562: 
 563:     static function fromMessage($message)
 564:     {
 565:         $result = Auth_OpenID_DiffieHellmanSHA1ServerSession::getDH($message);
 566: 
 567:         if ($result instanceof Auth_OpenID_ServerError) {
 568:             return $result;
 569:         } else {
 570:             list($dh, $consumer_pubkey) = $result;
 571:             return new Auth_OpenID_DiffieHellmanSHA256ServerSession($dh,
 572:                                                       $consumer_pubkey);
 573:         }
 574:     }
 575: }
 576: 
 577:  578:  579:  580:  581: 
 582: class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request {
 583:     var $mode = "associate";
 584: 
 585:     static function getSessionClasses()
 586:     {
 587:         return array(
 588:           'no-encryption' => 'Auth_OpenID_PlainTextServerSession',
 589:           'DH-SHA1' => 'Auth_OpenID_DiffieHellmanSHA1ServerSession',
 590:           'DH-SHA256' => 'Auth_OpenID_DiffieHellmanSHA256ServerSession');
 591:     }
 592: 
 593:     function Auth_OpenID_AssociateRequest($session, $assoc_type)
 594:     {
 595:         $this->session = $session;
 596:         $this->namespace = Auth_OpenID_OPENID2_NS;
 597:         $this->assoc_type = $assoc_type;
 598:     }
 599: 
 600:     static function fromMessage($message, $server=null)
 601:     {
 602:         if ($message->isOpenID1()) {
 603:             $session_type = $message->getArg(Auth_OpenID_OPENID_NS,
 604:                                              'session_type');
 605: 
 606:             if ($session_type == 'no-encryption') {
 607:                 
 608:                 
 609:             } else if (!$session_type) {
 610:                 $session_type = 'no-encryption';
 611:             }
 612:         } else {
 613:             $session_type = $message->getArg(Auth_OpenID_OPENID_NS,
 614:                                              'session_type');
 615:             if ($session_type === null) {
 616:                 return new Auth_OpenID_ServerError($message,
 617:                   "session_type missing from request");
 618:             }
 619:         }
 620: 
 621:         $session_class = Auth_OpenID::arrayGet(
 622:            Auth_OpenID_AssociateRequest::getSessionClasses(),
 623:            $session_type);
 624: 
 625:         if ($session_class === null) {
 626:             return new Auth_OpenID_ServerError($message,
 627:                                                "Unknown session type " .
 628:                                                $session_type);
 629:         }
 630: 
 631:         $session = call_user_func(array($session_class, 'fromMessage'),
 632:                                   $message);
 633:         if ($session instanceof Auth_OpenID_ServerError) {
 634:             return $session;
 635:         }
 636: 
 637:         $assoc_type = $message->getArg(Auth_OpenID_OPENID_NS,
 638:                                        'assoc_type', 'HMAC-SHA1');
 639: 
 640:         if (!in_array($assoc_type, $session->allowed_assoc_types)) {
 641:             $fmt = "Session type %s does not support association type %s";
 642:             return new Auth_OpenID_ServerError($message,
 643:               sprintf($fmt, $session_type, $assoc_type));
 644:         }
 645: 
 646:         $obj = new Auth_OpenID_AssociateRequest($session, $assoc_type);
 647:         $obj->message = $message;
 648:         $obj->namespace = $message->getOpenIDNamespace();
 649:         return $obj;
 650:     }
 651: 
 652:     function answer($assoc)
 653:     {
 654:         $response = new Auth_OpenID_ServerResponse($this);
 655:         $response->fields->updateArgs(Auth_OpenID_OPENID_NS,
 656:            array(
 657:                  'expires_in' => sprintf('%d', $assoc->getExpiresIn()),
 658:                  'assoc_type' => $this->assoc_type,
 659:                  'assoc_handle' => $assoc->handle));
 660: 
 661:         $response->fields->updateArgs(Auth_OpenID_OPENID_NS,
 662:            $this->session->answer($assoc->secret));
 663: 
 664:         if (! ($this->session->session_type == 'no-encryption'
 665:                && $this->message->isOpenID1())) {
 666:             $response->fields->setArg(Auth_OpenID_OPENID_NS,
 667:                                       'session_type',
 668:                                       $this->session->session_type);
 669:         }
 670: 
 671:         return $response;
 672:     }
 673: 
 674:     function answerUnsupported($text_message,
 675:                                $preferred_association_type=null,
 676:                                $preferred_session_type=null)
 677:     {
 678:         if ($this->message->isOpenID1()) {
 679:             return new Auth_OpenID_ServerError($this->message);
 680:         }
 681: 
 682:         $response = new Auth_OpenID_ServerResponse($this);
 683:         $response->fields->setArg(Auth_OpenID_OPENID_NS,
 684:                                   'error_code', 'unsupported-type');
 685:         $response->fields->setArg(Auth_OpenID_OPENID_NS,
 686:                                   'error', $text_message);
 687: 
 688:         if ($preferred_association_type) {
 689:             $response->fields->setArg(Auth_OpenID_OPENID_NS,
 690:                                       'assoc_type',
 691:                                       $preferred_association_type);
 692:         }
 693: 
 694:         if ($preferred_session_type) {
 695:             $response->fields->setArg(Auth_OpenID_OPENID_NS,
 696:                                       'session_type',
 697:                                       $preferred_session_type);
 698:         }
 699:         $response->code = AUTH_OPENID_HTTP_ERROR;
 700:         return $response;
 701:     }
 702: }
 703: 
 704:  705:  706:  707:  708: 
 709: class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request {
 710:      711:  712:  713: 
 714:     var $verifyReturnTo = 'Auth_OpenID_verifyReturnTo';
 715: 
 716:      717:  718: 
 719:     var $mode = "checkid_setup"; 
 720: 
 721:      722:  723: 
 724:     var $immediate = false;
 725: 
 726:      727:  728: 
 729:     var $trust_root = null;
 730: 
 731:      732:  733:  734: 
 735:     var $namespace;
 736: 
 737:     static function make($message, $identity, $return_to, $trust_root = null,
 738:                   $immediate = false, $assoc_handle = null, $server = null)
 739:     {
 740:         if ($server === null) {
 741:             return new Auth_OpenID_ServerError($message,
 742:                                                "server must not be null");
 743:         }
 744: 
 745:         if ($return_to &&
 746:             !Auth_OpenID_TrustRoot::_parse($return_to)) {
 747:             return new Auth_OpenID_MalformedReturnURL($message, $return_to);
 748:         }
 749: 
 750:         $r = new Auth_OpenID_CheckIDRequest($identity, $return_to,
 751:                                             $trust_root, $immediate,
 752:                                             $assoc_handle, $server);
 753: 
 754:         $r->namespace = $message->getOpenIDNamespace();
 755:         $r->message = $message;
 756: 
 757:         if (!$r->trustRootValid()) {
 758:             return new Auth_OpenID_UntrustedReturnURL($message,
 759:                                                       $return_to,
 760:                                                       $trust_root);
 761:         } else {
 762:             return $r;
 763:         }
 764:     }
 765: 
 766:     function Auth_OpenID_CheckIDRequest($identity, $return_to,
 767:                                         $trust_root = null, $immediate = false,
 768:                                         $assoc_handle = null, $server = null,
 769:                                         $claimed_id = null)
 770:     {
 771:         $this->namespace = Auth_OpenID_OPENID2_NS;
 772:         $this->assoc_handle = $assoc_handle;
 773:         $this->identity = $identity;
 774:         if ($claimed_id === null) {
 775:             $this->claimed_id = $identity;
 776:         } else {
 777:             $this->claimed_id = $claimed_id;
 778:         }
 779:         $this->return_to = $return_to;
 780:         $this->trust_root = $trust_root;
 781:         $this->server = $server;
 782: 
 783:         if ($immediate) {
 784:             $this->immediate = true;
 785:             $this->mode = "checkid_immediate";
 786:         } else {
 787:             $this->immediate = false;
 788:             $this->mode = "checkid_setup";
 789:         }
 790:     }
 791: 
 792:     function equals($other)
 793:     {
 794:         return (
 795:                 ($other instanceof Auth_OpenID_CheckIDRequest) &&
 796:                 ($this->namespace == $other->namespace) &&
 797:                 ($this->assoc_handle == $other->assoc_handle) &&
 798:                 ($this->identity == $other->identity) &&
 799:                 ($this->claimed_id == $other->claimed_id) &&
 800:                 ($this->return_to == $other->return_to) &&
 801:                 ($this->trust_root == $other->trust_root));
 802:     }
 803: 
 804:      805:  806:  807:  808:  809:  810:  811:  812:  813:  814:  815:  816:  817: 
 818:     function returnToVerified()
 819:     {
 820:         $fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
 821:         return call_user_func_array($this->verifyReturnTo,
 822:                                     array($this->trust_root, $this->return_to, $fetcher));
 823:     }
 824: 
 825:     static function fromMessage($message, $server)
 826:     {
 827:         $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode');
 828:         $immediate = null;
 829: 
 830:         if ($mode == "checkid_immediate") {
 831:             $immediate = true;
 832:             $mode = "checkid_immediate";
 833:         } else {
 834:             $immediate = false;
 835:             $mode = "checkid_setup";
 836:         }
 837: 
 838:         $return_to = $message->getArg(Auth_OpenID_OPENID_NS,
 839:                                       'return_to');
 840: 
 841:         if (($message->isOpenID1()) &&
 842:             (!$return_to)) {
 843:             $fmt = "Missing required field 'return_to' from checkid request";
 844:             return new Auth_OpenID_ServerError($message, $fmt);
 845:         }
 846: 
 847:         $identity = $message->getArg(Auth_OpenID_OPENID_NS,
 848:                                      'identity');
 849:         $claimed_id = $message->getArg(Auth_OpenID_OPENID_NS, 'claimed_id');
 850:         if ($message->isOpenID1()) {
 851:             if ($identity === null) {
 852:                 $s = "OpenID 1 message did not contain openid.identity";
 853:                 return new Auth_OpenID_ServerError($message, $s);
 854:             }
 855:         } else {
 856:             if ($identity && !$claimed_id) {
 857:                 $s = "OpenID 2.0 message contained openid.identity but not " .
 858:                   "claimed_id";
 859:                 return new Auth_OpenID_ServerError($message, $s);
 860:             } else if ($claimed_id && !$identity) {
 861:                 $s = "OpenID 2.0 message contained openid.claimed_id " .
 862:                   "but not identity";
 863:                 return new Auth_OpenID_ServerError($message, $s);
 864:             }
 865:         }
 866: 
 867:         
 868:         
 869:         
 870:         if ($message->isOpenID1()) {
 871:             $trust_root_param = 'trust_root';
 872:         } else {
 873:             $trust_root_param = 'realm';
 874:         }
 875:         $trust_root = $message->getArg(Auth_OpenID_OPENID_NS,
 876:                                        $trust_root_param);
 877:         if (! $trust_root) {
 878:             $trust_root = $return_to;
 879:         }
 880: 
 881:         if (! $message->isOpenID1() &&
 882:             ($return_to === null) &&
 883:             ($trust_root === null)) {
 884:             return new Auth_OpenID_ServerError($message,
 885:               "openid.realm required when openid.return_to absent");
 886:         }
 887: 
 888:         $assoc_handle = $message->getArg(Auth_OpenID_OPENID_NS,
 889:                                          'assoc_handle');
 890: 
 891:         $obj = Auth_OpenID_CheckIDRequest::make($message,
 892:                                                 $identity,
 893:                                                 $return_to,
 894:                                                 $trust_root,
 895:                                                 $immediate,
 896:                                                 $assoc_handle,
 897:                                                 $server);
 898: 
 899:         if ($obj instanceof Auth_OpenID_ServerError) {
 900:             return $obj;
 901:         }
 902: 
 903:         $obj->claimed_id = $claimed_id;
 904: 
 905:         return $obj;
 906:     }
 907: 
 908:     function idSelect()
 909:     {
 910:         
 911:         
 912:         return $this->identity == Auth_OpenID_IDENTIFIER_SELECT;
 913:     }
 914: 
 915:     function trustRootValid()
 916:     {
 917:         if (!$this->trust_root) {
 918:             return true;
 919:         }
 920: 
 921:         $tr = Auth_OpenID_TrustRoot::_parse($this->trust_root);
 922:         if ($tr === false) {
 923:             return new Auth_OpenID_MalformedTrustRoot($this->message,
 924:                                                       $this->trust_root);
 925:         }
 926: 
 927:         if ($this->return_to !== null) {
 928:             return Auth_OpenID_TrustRoot::match($this->trust_root,
 929:                                                 $this->return_to);
 930:         } else {
 931:             return true;
 932:         }
 933:     }
 934: 
 935:      936:  937:  938:  939:  940:  941:  942:  943:  944:  945:  946:  947:  948:  949:  950:  951:  952:  953:  954:  955:  956:  957:  958:  959:  960:  961:  962:  963:  964:  965:  966:  967:  968:  969:  970:  971:  972:  973: 
 974:     function answer($allow, $server_url = null, $identity = null,
 975:                     $claimed_id = null)
 976:     {
 977:         if (!$this->return_to) {
 978:             return new Auth_OpenID_NoReturnToError();
 979:         }
 980: 
 981:         if (!$server_url) {
 982:             if ((!$this->message->isOpenID1()) &&
 983:                 (!$this->server->op_endpoint)) {
 984:                 return new Auth_OpenID_ServerError(null,
 985:                   "server should be constructed with op_endpoint to " .
 986:                   "respond to OpenID 2.0 messages.");
 987:             }
 988: 
 989:             $server_url = $this->server->op_endpoint;
 990:         }
 991: 
 992:         if ($allow) {
 993:             $mode = 'id_res';
 994:         } else if ($this->message->isOpenID1()) {
 995:             if ($this->immediate) {
 996:                 $mode = 'id_res';
 997:             } else {
 998:                 $mode = 'cancel';
 999:             }
1000:         } else {
1001:             if ($this->immediate) {
1002:                 $mode = 'setup_needed';
1003:             } else {
1004:                 $mode = 'cancel';
1005:             }
1006:         }
1007: 
1008:         if (!$this->trustRootValid()) {
1009:             return new Auth_OpenID_UntrustedReturnURL(null,
1010:                                                       $this->return_to,
1011:                                                       $this->trust_root);
1012:         }
1013: 
1014:         $response = new Auth_OpenID_ServerResponse($this);
1015: 
1016:         if ($claimed_id &&
1017:             ($this->message->isOpenID1())) {
1018:             return new Auth_OpenID_ServerError(null,
1019:               "claimed_id is new in OpenID 2.0 and not " .
1020:               "available for ".$this->namespace);
1021:         }
1022: 
1023:         if ($identity && !$claimed_id) {
1024:             $claimed_id = $identity;
1025:         }
1026: 
1027:         if ($allow) {
1028: 
1029:             if ($this->identity == Auth_OpenID_IDENTIFIER_SELECT) {
1030:                 if (!$identity) {
1031:                     return new Auth_OpenID_ServerError(null,
1032:                       "This request uses IdP-driven identifier selection.  " .
1033:                       "You must supply an identifier in the response.");
1034:                 }
1035: 
1036:                 $response_identity = $identity;
1037:                 $response_claimed_id = $claimed_id;
1038: 
1039:             } else if ($this->identity) {
1040:                 if ($identity &&
1041:                     ($this->identity != $identity)) {
1042:                     $fmt = "Request was for %s, cannot reply with identity %s";
1043:                     return new Auth_OpenID_ServerError(null,
1044:                       sprintf($fmt, $this->identity, $identity));
1045:                 }
1046: 
1047:                 $response_identity = $this->identity;
1048:                 $response_claimed_id = $this->claimed_id;
1049:             } else {
1050:                 if ($identity) {
1051:                     return new Auth_OpenID_ServerError(null,
1052:                       "This request specified no identity and " .
1053:                       "you supplied ".$identity);
1054:                 }
1055: 
1056:                 $response_identity = null;
1057:             }
1058: 
1059:             if (($this->message->isOpenID1()) &&
1060:                 ($response_identity === null)) {
1061:                 return new Auth_OpenID_ServerError(null,
1062:                   "Request was an OpenID 1 request, so response must " .
1063:                   "include an identifier.");
1064:             }
1065: 
1066:             $response->fields->updateArgs(Auth_OpenID_OPENID_NS,
1067:                    array('mode' => $mode,
1068:                          'return_to' => $this->return_to,
1069:                          'response_nonce' => Auth_OpenID_mkNonce()));
1070: 
1071:             if (!$this->message->isOpenID1()) {
1072:                 $response->fields->setArg(Auth_OpenID_OPENID_NS,
1073:                                           'op_endpoint', $server_url);
1074:             }
1075: 
1076:             if ($response_identity !== null) {
1077:                 $response->fields->setArg(
1078:                                           Auth_OpenID_OPENID_NS,
1079:                                           'identity',
1080:                                           $response_identity);
1081:                 if ($this->message->isOpenID2()) {
1082:                     $response->fields->setArg(
1083:                                               Auth_OpenID_OPENID_NS,
1084:                                               'claimed_id',
1085:                                               $response_claimed_id);
1086:                 }
1087:             }
1088: 
1089:         } else {
1090:             $response->fields->setArg(Auth_OpenID_OPENID_NS,
1091:                                       'mode', $mode);
1092: 
1093:             if ($this->immediate) {
1094:                 if (($this->message->isOpenID1()) &&
1095:                     (!$server_url)) {
1096:                     return new Auth_OpenID_ServerError(null,
1097:                                  'setup_url is required for $allow=false \
1098:                                   in OpenID 1.x immediate mode.');
1099:                 }
1100: 
1101:                 $setup_request = new Auth_OpenID_CheckIDRequest(
1102:                                                 $this->identity,
1103:                                                 $this->return_to,
1104:                                                 $this->trust_root,
1105:                                                 false,
1106:                                                 $this->assoc_handle,
1107:                                                 $this->server,
1108:                                                 $this->claimed_id);
1109:                 $setup_request->message = $this->message;
1110: 
1111:                 $setup_url = $setup_request->encodeToURL($server_url);
1112: 
1113:                 if ($setup_url === null) {
1114:                     return new Auth_OpenID_NoReturnToError();
1115:                 }
1116: 
1117:                 $response->fields->setArg(Auth_OpenID_OPENID_NS,
1118:                                           'user_setup_url',
1119:                                           $setup_url);
1120:             }
1121:         }
1122: 
1123:         return $response;
1124:     }
1125: 
1126:     function encodeToURL($server_url)
1127:     {
1128:         if (!$this->return_to) {
1129:             return new Auth_OpenID_NoReturnToError();
1130:         }
1131: 
1132:         
1133:         
1134:         
1135:         
1136: 
1137:         $q = array('mode' => $this->mode,
1138:                    'identity' => $this->identity,
1139:                    'claimed_id' => $this->claimed_id,
1140:                    'return_to' => $this->return_to);
1141: 
1142:         if ($this->trust_root) {
1143:             if ($this->message->isOpenID1()) {
1144:                 $q['trust_root'] = $this->trust_root;
1145:             } else {
1146:                 $q['realm'] = $this->trust_root;
1147:             }
1148:         }
1149: 
1150:         if ($this->assoc_handle) {
1151:             $q['assoc_handle'] = $this->assoc_handle;
1152:         }
1153: 
1154:         $response = new Auth_OpenID_Message(
1155:             $this->message->getOpenIDNamespace());
1156:         $response->updateArgs(Auth_OpenID_OPENID_NS, $q);
1157:         return $response->toURL($server_url);
1158:     }
1159: 
1160:     function getCancelURL()
1161:     {
1162:         if (!$this->return_to) {
1163:             return new Auth_OpenID_NoReturnToError();
1164:         }
1165: 
1166:         if ($this->immediate) {
1167:             return new Auth_OpenID_ServerError(null,
1168:                                                "Cancel is not an appropriate \
1169:                                                response to immediate mode \
1170:                                                requests.");
1171:         }
1172: 
1173:         $response = new Auth_OpenID_Message(
1174:             $this->message->getOpenIDNamespace());
1175:         $response->setArg(Auth_OpenID_OPENID_NS, 'mode', 'cancel');
1176:         return $response->toURL($this->return_to);
1177:     }
1178: }
1179: 
1180: 1181: 1182: 1183: 1184: 
1185: class Auth_OpenID_ServerResponse {
1186: 
1187:     function Auth_OpenID_ServerResponse($request)
1188:     {
1189:         $this->request = $request;
1190:         $this->fields = new Auth_OpenID_Message($this->request->namespace);
1191:     }
1192: 
1193:     function whichEncoding()
1194:     {
1195:       global $_Auth_OpenID_Request_Modes;
1196: 
1197:         if (in_array($this->request->mode, $_Auth_OpenID_Request_Modes)) {
1198:             if ($this->fields->isOpenID2() &&
1199:                 (strlen($this->encodeToURL()) >
1200:                    Auth_OpenID_OPENID1_URL_LIMIT)) {
1201:                 return Auth_OpenID_ENCODE_HTML_FORM;
1202:             } else {
1203:                 return Auth_OpenID_ENCODE_URL;
1204:             }
1205:         } else {
1206:             return Auth_OpenID_ENCODE_KVFORM;
1207:         }
1208:     }
1209: 
1210:     1211: 1212: 1213: 1214: 
1215:     function toFormMarkup($form_tag_attrs=null)
1216:     {
1217:         return $this->fields->toFormMarkup($this->request->return_to,
1218:                                            $form_tag_attrs);
1219:     }
1220: 
1221:     1222: 1223: 1224: 
1225:     function toHTML()
1226:     {
1227:         return Auth_OpenID::autoSubmitHTML($this->toFormMarkup());
1228:     }
1229: 
1230:     1231: 1232: 1233: 1234: 1235: 
1236:     function renderAsForm()
1237:     {
1238:         return $this->whichEncoding() == Auth_OpenID_ENCODE_HTML_FORM;
1239:     }
1240: 
1241: 
1242:     function encodeToURL()
1243:     {
1244:         return $this->fields->toURL($this->request->return_to);
1245:     }
1246: 
1247:     function addExtension($extension_response)
1248:     {
1249:         $extension_response->toMessage($this->fields);
1250:     }
1251: 
1252:     function needsSigning()
1253:     {
1254:         return $this->fields->getArg(Auth_OpenID_OPENID_NS,
1255:                                      'mode') == 'id_res';
1256:     }
1257: 
1258:     function encodeToKVForm()
1259:     {
1260:         return $this->fields->toKVForm();
1261:     }
1262: }
1263: 
1264: 1265: 1266: 1267: 1268: 1269: 
1270: class Auth_OpenID_WebResponse {
1271:     var $code = AUTH_OPENID_HTTP_OK;
1272:     var $body = "";
1273: 
1274:     function Auth_OpenID_WebResponse($code = null, $headers = null,
1275:                                      $body = null)
1276:     {
1277:         if ($code) {
1278:             $this->code = $code;
1279:         }
1280: 
1281:         if ($headers !== null) {
1282:             $this->headers = $headers;
1283:         } else {
1284:             $this->headers = array();
1285:         }
1286: 
1287:         if ($body !== null) {
1288:             $this->body = $body;
1289:         }
1290:     }
1291: }
1292: 
1293: 1294: 1295: 1296: 1297: 1298: 
1299: class Auth_OpenID_Signatory {
1300: 
1301:     
1302:     var $SECRET_LIFETIME = 1209600;
1303: 
1304:     
1305:     
1306:     
1307:     
1308:     var $normal_key = 'http://localhost/|normal';
1309:     var $dumb_key = 'http://localhost/|dumb';
1310: 
1311:     1312: 1313: 
1314:     function Auth_OpenID_Signatory($store)
1315:     {
1316:         
1317:         $this->store = $store;
1318:     }
1319: 
1320:     1321: 1322: 1323: 
1324:     function verify($assoc_handle, $message)
1325:     {
1326:         $assoc = $this->getAssociation($assoc_handle, true);
1327:         if (!$assoc) {
1328:             
1329:             
1330:             return false;
1331:         }
1332: 
1333:         return $assoc->checkMessageSignature($message);
1334:     }
1335: 
1336:     1337: 1338: 1339: 
1340:     function sign($response)
1341:     {
1342:         $signed_response = $response;
1343:         $assoc_handle = $response->request->assoc_handle;
1344: 
1345:         if ($assoc_handle) {
1346:             
1347:             $assoc = $this->getAssociation($assoc_handle, false, false);
1348:             if (!$assoc || ($assoc->getExpiresIn() <= 0)) {
1349:                 
1350:                 $signed_response->fields->setArg(Auth_OpenID_OPENID_NS,
1351:                              'invalidate_handle', $assoc_handle);
1352:                 $assoc_type = ($assoc ? $assoc->assoc_type : 'HMAC-SHA1');
1353: 
1354:                 if ($assoc && ($assoc->getExpiresIn() <= 0)) {
1355:                     $this->invalidate($assoc_handle, false);
1356:                 }
1357: 
1358:                 $assoc = $this->createAssociation(true, $assoc_type);
1359:             }
1360:         } else {
1361:             
1362:             $assoc = $this->createAssociation(true);
1363:         }
1364: 
1365:         $signed_response->fields = $assoc->signMessage(
1366:                                       $signed_response->fields);
1367:         return $signed_response;
1368:     }
1369: 
1370:     1371: 1372: 
1373:     function createAssociation($dumb = true, $assoc_type = 'HMAC-SHA1')
1374:     {
1375:         $secret = Auth_OpenID_CryptUtil::getBytes(
1376:                     Auth_OpenID_getSecretSize($assoc_type));
1377: 
1378:         $uniq = base64_encode(Auth_OpenID_CryptUtil::getBytes(4));
1379:         $handle = sprintf('{%s}{%x}{%s}', $assoc_type, intval(time()), $uniq);
1380: 
1381:         $assoc = Auth_OpenID_Association::fromExpiresIn(
1382:                       $this->SECRET_LIFETIME, $handle, $secret, $assoc_type);
1383: 
1384:         if ($dumb) {
1385:             $key = $this->dumb_key;
1386:         } else {
1387:             $key = $this->normal_key;
1388:         }
1389: 
1390:         $this->store->storeAssociation($key, $assoc);
1391:         return $assoc;
1392:     }
1393: 
1394:     1395: 1396: 1397: 
1398:     function getAssociation($assoc_handle, $dumb, $check_expiration=true)
1399:     {
1400:         if ($assoc_handle === null) {
1401:             return new Auth_OpenID_ServerError(null,
1402:                                      "assoc_handle must not be null");
1403:         }
1404: 
1405:         if ($dumb) {
1406:             $key = $this->dumb_key;
1407:         } else {
1408:             $key = $this->normal_key;
1409:         }
1410: 
1411:         $assoc = $this->store->getAssociation($key, $assoc_handle);
1412: 
1413:         if (($assoc !== null) && ($assoc->getExpiresIn() <= 0)) {
1414:             if ($check_expiration) {
1415:                 $this->store->removeAssociation($key, $assoc_handle);
1416:                 $assoc = null;
1417:             }
1418:         }
1419: 
1420:         return $assoc;
1421:     }
1422: 
1423:     1424: 1425: 
1426:     function invalidate($assoc_handle, $dumb)
1427:     {
1428:         if ($dumb) {
1429:             $key = $this->dumb_key;
1430:         } else {
1431:             $key = $this->normal_key;
1432:         }
1433:         $this->store->removeAssociation($key, $assoc_handle);
1434:     }
1435: }
1436: 
1437: 1438: 1439: 1440: 1441: 1442: 
1443: class Auth_OpenID_Encoder {
1444: 
1445:     var $responseFactory = 'Auth_OpenID_WebResponse';
1446: 
1447:     1448: 1449: 1450: 
1451:     function encode($response)
1452:     {
1453:         $cls = $this->responseFactory;
1454: 
1455:         $encode_as = $response->whichEncoding();
1456:         if ($encode_as == Auth_OpenID_ENCODE_KVFORM) {
1457:             $wr = new $cls(null, null, $response->encodeToKVForm());
1458:             if ($response instanceof Auth_OpenID_ServerError) {
1459:                 $wr->code = AUTH_OPENID_HTTP_ERROR;
1460:             }
1461:         } else if ($encode_as == Auth_OpenID_ENCODE_URL) {
1462:             $location = $response->encodeToURL();
1463:             $wr = new $cls(AUTH_OPENID_HTTP_REDIRECT,
1464:                            array('location' => $location));
1465:         } else if ($encode_as == Auth_OpenID_ENCODE_HTML_FORM) {
1466:           $wr = new $cls(AUTH_OPENID_HTTP_OK, array(),
1467:                          $response->toHTML());
1468:         } else {
1469:             return new Auth_OpenID_EncodingError($response);
1470:         }
1471:         
1472:         if(isset($response->code)) {
1473:             $wr->code = $response->code;
1474:         }
1475:         return $wr;
1476:     }
1477: }
1478: 
1479: 1480: 1481: 1482: 1483: 
1484: class Auth_OpenID_SigningEncoder extends Auth_OpenID_Encoder {
1485: 
1486:     function Auth_OpenID_SigningEncoder($signatory)
1487:     {
1488:         $this->signatory = $signatory;
1489:     }
1490: 
1491:     1492: 1493: 1494: 
1495:     function encode($response)
1496:     {
1497:         
1498:         
1499:         if (!$response instanceof Auth_OpenID_ServerError &&
1500:             $response->needsSigning()) {
1501: 
1502:             if (!$this->signatory) {
1503:                 return new Auth_OpenID_ServerError(null,
1504:                                        "Must have a store to sign request");
1505:             }
1506: 
1507:             if ($response->fields->hasKey(Auth_OpenID_OPENID_NS, 'sig')) {
1508:                 return new Auth_OpenID_AlreadySigned($response);
1509:             }
1510:             $response = $this->signatory->sign($response);
1511:         }
1512: 
1513:         return parent::encode($response);
1514:     }
1515: }
1516: 
1517: 1518: 1519: 1520: 1521: 
1522: class Auth_OpenID_Decoder {
1523: 
1524:     function Auth_OpenID_Decoder($server)
1525:     {
1526:         $this->server = $server;
1527: 
1528:         $this->handlers = array(
1529:             'checkid_setup' => 'Auth_OpenID_CheckIDRequest',
1530:             'checkid_immediate' => 'Auth_OpenID_CheckIDRequest',
1531:             'check_authentication' => 'Auth_OpenID_CheckAuthRequest',
1532:             'associate' => 'Auth_OpenID_AssociateRequest'
1533:             );
1534:     }
1535: 
1536:     1537: 1538: 1539: 
1540:     function decode($query)
1541:     {
1542:         if (!$query) {
1543:             return null;
1544:         }
1545: 
1546:         $message = Auth_OpenID_Message::fromPostArgs($query);
1547: 
1548:         if ($message === null) {
1549:             1550: 1551: 1552: 1553: 1554: 1555: 
1556:             $old_ns = $query['openid.ns'];
1557: 
1558:             $query['openid.ns'] = Auth_OpenID_OPENID2_NS;
1559:             $message = Auth_OpenID_Message::fromPostArgs($query);
1560:             return new Auth_OpenID_ServerError(
1561:                   $message,
1562:                   sprintf("Invalid OpenID namespace URI: %s", $old_ns));
1563:         }
1564: 
1565:         $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode');
1566:         if (!$mode) {
1567:             return new Auth_OpenID_ServerError($message,
1568:                                                "No mode value in message");
1569:         }
1570: 
1571:         if (Auth_OpenID::isFailure($mode)) {
1572:             return new Auth_OpenID_ServerError($message,
1573:                                                $mode->message);
1574:         }
1575: 
1576:         $handlerCls = Auth_OpenID::arrayGet($this->handlers, $mode,
1577:                                             $this->defaultDecoder($message));
1578: 
1579:         if (!($handlerCls instanceof Auth_OpenID_ServerError)) {
1580:             return call_user_func_array(array($handlerCls, 'fromMessage'),
1581:                                         array($message, $this->server));
1582:         } else {
1583:             return $handlerCls;
1584:         }
1585:     }
1586: 
1587:     function defaultDecoder($message)
1588:     {
1589:         $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode');
1590: 
1591:         if (Auth_OpenID::isFailure($mode)) {
1592:             return new Auth_OpenID_ServerError($message,
1593:                                                $mode->message);
1594:         }
1595: 
1596:         return new Auth_OpenID_ServerError($message,
1597:                        sprintf("Unrecognized OpenID mode %s", $mode));
1598:     }
1599: }
1600: 
1601: 1602: 1603: 1604: 1605: 
1606: class Auth_OpenID_EncodingError {
1607:     function Auth_OpenID_EncodingError($response)
1608:     {
1609:         $this->response = $response;
1610:     }
1611: }
1612: 
1613: 1614: 1615: 1616: 1617: 
1618: class Auth_OpenID_AlreadySigned extends Auth_OpenID_EncodingError {
1619:     
1620: }
1621: 
1622: 1623: 1624: 1625: 1626: 1627: 
1628: class Auth_OpenID_UntrustedReturnURL extends Auth_OpenID_ServerError {
1629:     function Auth_OpenID_UntrustedReturnURL($message, $return_to,
1630:                                             $trust_root)
1631:     {
1632:         parent::Auth_OpenID_ServerError($message, "Untrusted return_to URL");
1633:         $this->return_to = $return_to;
1634:         $this->trust_root = $trust_root;
1635:     }
1636: 
1637:     function toString()
1638:     {
1639:         return sprintf("return_to %s not under trust_root %s",
1640:                        $this->return_to, $this->trust_root);
1641:     }
1642: }
1643: 
1644: 1645: 1646: 1647: 1648: 1649: 1650: 1651: 1652: 1653: 1654: 1655: 1656: 1657: 1658: 1659: 1660: 1661: 1662: 1663: 1664: 1665: 1666: 1667: 1668: 1669: 1670: 1671: 1672: 1673: 1674: 1675: 1676: 1677: 1678: 1679: 1680: 
1681: class Auth_OpenID_Server {
1682:     function Auth_OpenID_Server($store, $op_endpoint=null)
1683:     {
1684:         $this->store = $store;
1685:         $this->signatory = new Auth_OpenID_Signatory($this->store);
1686:         $this->encoder = new Auth_OpenID_SigningEncoder($this->signatory);
1687:         $this->decoder = new Auth_OpenID_Decoder($this);
1688:         $this->op_endpoint = $op_endpoint;
1689:         $this->negotiator = Auth_OpenID_getDefaultNegotiator();
1690:     }
1691: 
1692:     1693: 1694: 1695: 1696: 1697: 1698: 1699: 1700: 1701: 1702: 
1703:     function handleRequest($request)
1704:     {
1705:         if (method_exists($this, "openid_" . $request->mode)) {
1706:             $handler = array($this, "openid_" . $request->mode);
1707:             return call_user_func($handler, &$request);
1708:         }
1709:         return null;
1710:     }
1711: 
1712:     1713: 1714: 
1715:     function openid_check_authentication($request)
1716:     {
1717:         return $request->answer($this->signatory);
1718:     }
1719: 
1720:     1721: 1722: 
1723:     function openid_associate($request)
1724:     {
1725:         $assoc_type = $request->assoc_type;
1726:         $session_type = $request->session->session_type;
1727:         if ($this->negotiator->isAllowed($assoc_type, $session_type)) {
1728:             $assoc = $this->signatory->createAssociation(false,
1729:                                                          $assoc_type);
1730:             return $request->answer($assoc);
1731:         } else {
1732:             $message = sprintf('Association type %s is not supported with '.
1733:                                'session type %s', $assoc_type, $session_type);
1734:             list($preferred_assoc_type, $preferred_session_type) =
1735:                 $this->negotiator->getAllowedType();
1736:             return $request->answerUnsupported($message,
1737:                                                $preferred_assoc_type,
1738:                                                $preferred_session_type);
1739:         }
1740:     }
1741: 
1742:     1743: 1744: 1745: 
1746:     function encodeResponse($response)
1747:     {
1748:         return $this->encoder->encode($response);
1749:     }
1750: 
1751:     1752: 1753: 1754: 
1755:     function decodeRequest($query=null)
1756:     {
1757:         if ($query === null) {
1758:             $query = Auth_OpenID::getQuery();
1759:         }
1760: 
1761:         return $this->decoder->decode($query);
1762:     }
1763: }
1764: 
1765: 
1766: