1<?php 2 3/** 4 * Licensed to Jasig under one or more contributor license 5 * agreements. See the NOTICE file distributed with this work for 6 * additional information regarding copyright ownership. 7 * 8 * Jasig licenses this file to you under the Apache License, 9 * Version 2.0 (the "License"); you may not use this file except in 10 * compliance with the License. You may obtain a copy of the License at: 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 * 21 * 22 * Interface class of the phpCAS library 23 * PHP Version 5 24 * 25 * @file CAS/CAS.php 26 * @category Authentication 27 * @package PhpCAS 28 * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr> 29 * @author Olivier Berger <olivier.berger@it-sudparis.eu> 30 * @author Brett Bieber <brett.bieber@gmail.com> 31 * @author Joachim Fritschi <jfritschi@freenet.de> 32 * @author Adam Franco <afranco@middlebury.edu> 33 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 34 * @link https://wiki.jasig.org/display/CASC/phpCAS 35 * @ingroup public 36 */ 37 38 39// 40// hack by Vangelis Haniotakis to handle the absence of $_SERVER['REQUEST_URI'] 41// in IIS 42// 43if (!isset($_SERVER['REQUEST_URI']) && isset($_SERVER['SCRIPT_NAME']) && isset($_SERVER['QUERY_STRING'])) { 44 $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING']; 45} 46 47// Add a E_USER_DEPRECATED for php versions <= 5.2 48if (!defined('E_USER_DEPRECATED')) { 49 define('E_USER_DEPRECATED', E_USER_NOTICE); 50} 51 52 53// ######################################################################## 54// CONSTANTS 55// ######################################################################## 56 57// ------------------------------------------------------------------------ 58// CAS VERSIONS 59// ------------------------------------------------------------------------ 60 61/** 62 * phpCAS version. accessible for the user by phpCAS::getVersion(). 63 */ 64define('PHPCAS_VERSION', '1.3.5'); 65 66/** 67 * @addtogroup public 68 * @{ 69 */ 70 71/** 72 * CAS version 1.0 73 */ 74define("CAS_VERSION_1_0", '1.0'); 75/*! 76 * CAS version 2.0 77*/ 78define("CAS_VERSION_2_0", '2.0'); 79/** 80 * CAS version 3.0 81 */ 82define("CAS_VERSION_3_0", '3.0'); 83 84// ------------------------------------------------------------------------ 85// SAML defines 86// ------------------------------------------------------------------------ 87 88/** 89 * SAML protocol 90 */ 91define("SAML_VERSION_1_1", 'S1'); 92 93/** 94 * XML header for SAML POST 95 */ 96define("SAML_XML_HEADER", '<?xml version="1.0" encoding="UTF-8"?>'); 97 98/** 99 * SOAP envelope for SAML POST 100 */ 101define("SAML_SOAP_ENV", '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/>'); 102 103/** 104 * SOAP body for SAML POST 105 */ 106define("SAML_SOAP_BODY", '<SOAP-ENV:Body>'); 107 108/** 109 * SAMLP request 110 */ 111define("SAMLP_REQUEST", '<samlp:Request xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" MajorVersion="1" MinorVersion="1" RequestID="_192.168.16.51.1024506224022" IssueInstant="2002-06-19T17:03:44.022Z">'); 112define("SAMLP_REQUEST_CLOSE", '</samlp:Request>'); 113 114/** 115 * SAMLP artifact tag (for the ticket) 116 */ 117define("SAML_ASSERTION_ARTIFACT", '<samlp:AssertionArtifact>'); 118 119/** 120 * SAMLP close 121 */ 122define("SAML_ASSERTION_ARTIFACT_CLOSE", '</samlp:AssertionArtifact>'); 123 124/** 125 * SOAP body close 126 */ 127define("SAML_SOAP_BODY_CLOSE", '</SOAP-ENV:Body>'); 128 129/** 130 * SOAP envelope close 131 */ 132define("SAML_SOAP_ENV_CLOSE", '</SOAP-ENV:Envelope>'); 133 134/** 135 * SAML Attributes 136 */ 137define("SAML_ATTRIBUTES", 'SAMLATTRIBS'); 138 139/** 140 * SAML Attributes 141 */ 142define("DEFAULT_ERROR", 'Internal script failure'); 143 144/** @} */ 145/** 146 * @addtogroup publicPGTStorage 147 * @{ 148 */ 149// ------------------------------------------------------------------------ 150// FILE PGT STORAGE 151// ------------------------------------------------------------------------ 152/** 153 * Default path used when storing PGT's to file 154 */ 155define("CAS_PGT_STORAGE_FILE_DEFAULT_PATH", session_save_path()); 156/** @} */ 157// ------------------------------------------------------------------------ 158// SERVICE ACCESS ERRORS 159// ------------------------------------------------------------------------ 160/** 161 * @addtogroup publicServices 162 * @{ 163 */ 164 165/** 166 * phpCAS::service() error code on success 167 */ 168define("PHPCAS_SERVICE_OK", 0); 169/** 170 * phpCAS::service() error code when the PT could not retrieve because 171 * the CAS server did not respond. 172 */ 173define("PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE", 1); 174/** 175 * phpCAS::service() error code when the PT could not retrieve because 176 * the response of the CAS server was ill-formed. 177 */ 178define("PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE", 2); 179/** 180 * phpCAS::service() error code when the PT could not retrieve because 181 * the CAS server did not want to. 182 */ 183define("PHPCAS_SERVICE_PT_FAILURE", 3); 184/** 185 * phpCAS::service() error code when the service was not available. 186 */ 187define("PHPCAS_SERVICE_NOT_AVAILABLE", 4); 188 189// ------------------------------------------------------------------------ 190// SERVICE TYPES 191// ------------------------------------------------------------------------ 192/** 193 * phpCAS::getProxiedService() type for HTTP GET 194 */ 195define("PHPCAS_PROXIED_SERVICE_HTTP_GET", 'CAS_ProxiedService_Http_Get'); 196/** 197 * phpCAS::getProxiedService() type for HTTP POST 198 */ 199define("PHPCAS_PROXIED_SERVICE_HTTP_POST", 'CAS_ProxiedService_Http_Post'); 200/** 201 * phpCAS::getProxiedService() type for IMAP 202 */ 203define("PHPCAS_PROXIED_SERVICE_IMAP", 'CAS_ProxiedService_Imap'); 204 205 206/** @} */ 207// ------------------------------------------------------------------------ 208// LANGUAGES 209// ------------------------------------------------------------------------ 210/** 211 * @addtogroup publicLang 212 * @{ 213 */ 214 215define("PHPCAS_LANG_ENGLISH", 'CAS_Languages_English'); 216define("PHPCAS_LANG_FRENCH", 'CAS_Languages_French'); 217define("PHPCAS_LANG_GREEK", 'CAS_Languages_Greek'); 218define("PHPCAS_LANG_GERMAN", 'CAS_Languages_German'); 219define("PHPCAS_LANG_JAPANESE", 'CAS_Languages_Japanese'); 220define("PHPCAS_LANG_SPANISH", 'CAS_Languages_Spanish'); 221define("PHPCAS_LANG_CATALAN", 'CAS_Languages_Catalan'); 222define("PHPCAS_LANG_CHINESE_SIMPLIFIED", 'CAS_Languages_ChineseSimplified'); 223 224/** @} */ 225 226/** 227 * @addtogroup internalLang 228 * @{ 229 */ 230 231/** 232 * phpCAS default language (when phpCAS::setLang() is not used) 233 */ 234define("PHPCAS_LANG_DEFAULT", PHPCAS_LANG_ENGLISH); 235 236/** @} */ 237// ------------------------------------------------------------------------ 238// DEBUG 239// ------------------------------------------------------------------------ 240/** 241 * @addtogroup publicDebug 242 * @{ 243 */ 244 245/** 246 * The default directory for the debug file under Unix. 247 */ 248function gettmpdir() 249{ 250 if (!empty($_ENV['TMP'])) { 251 return realpath($_ENV['TMP']); 252 } 253 if (!empty($_ENV['TMPDIR'])) { 254 return realpath($_ENV['TMPDIR']); 255 } 256 if (!empty($_ENV['TEMP'])) { 257 return realpath($_ENV['TEMP']); 258 } 259 return "/tmp"; 260} 261define('DEFAULT_DEBUG_DIR', gettmpdir() . "/"); 262 263/** @} */ 264 265// include the class autoloader 266require_once dirname(__FILE__) . '/CAS/Autoload.php'; 267 268/** 269 * The phpCAS class is a simple container for the phpCAS library. It provides CAS 270 * authentication for web applications written in PHP. 271 * 272 * @ingroup public 273 * @class phpCAS 274 * @category Authentication 275 * @package PhpCAS 276 * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr> 277 * @author Olivier Berger <olivier.berger@it-sudparis.eu> 278 * @author Brett Bieber <brett.bieber@gmail.com> 279 * @author Joachim Fritschi <jfritschi@freenet.de> 280 * @author Adam Franco <afranco@middlebury.edu> 281 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 282 * @link https://wiki.jasig.org/display/CASC/phpCAS 283 */ 284 285class phpCAS 286{ 287 288 /** 289 * This variable is used by the interface class phpCAS. 290 * 291 * @var CAS_Client 292 * @hideinitializer 293 */ 294 private static $_PHPCAS_CLIENT; 295 296 /** 297 * This variable is used to store where the initializer is called from 298 * (to print a comprehensive error in case of multiple calls). 299 * 300 * @hideinitializer 301 */ 302 private static $_PHPCAS_INIT_CALL; 303 304 /** 305 * This variable is used to store phpCAS debug mode. 306 * 307 * @hideinitializer 308 */ 309 private static $_PHPCAS_DEBUG; 310 311 /** 312 * This variable is used to enable verbose mode 313 * This pevents debug info to be show to the user. Since it's a security 314 * feature the default is false 315 * 316 * @hideinitializer 317 */ 318 private static $_PHPCAS_VERBOSE = false; 319 320 321 // ######################################################################## 322 // INITIALIZATION 323 // ######################################################################## 324 325 /** 326 * @addtogroup publicInit 327 * @{ 328 */ 329 330 /** 331 * phpCAS client initializer. 332 * 333 * @param string $server_version the version of the CAS server 334 * @param string $server_hostname the hostname of the CAS server 335 * @param string $server_port the port the CAS server is running on 336 * @param string $server_uri the URI the CAS server is responding on 337 * @param bool $changeSessionID Allow phpCAS to change the session_id (Single 338 * Sign Out/handleLogoutRequests is based on that change) 339 * 340 * @return a newly created CAS_Client object 341 * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be 342 * called, only once, and before all other methods (except phpCAS::getVersion() 343 * and phpCAS::setDebug()). 344 */ 345 public static function client( 346 $server_version, 347 $server_hostname, 348 $server_port, 349 $server_uri, 350 $changeSessionID = true 351 ) { 352 phpCAS :: traceBegin(); 353 if (is_object(self::$_PHPCAS_CLIENT)) { 354 phpCAS :: error(self::$_PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . self::$_PHPCAS_INIT_CALL['file'] . ':' . self::$_PHPCAS_INIT_CALL['line'] . ')'); 355 } 356 357 // store where the initializer is called from 358 $dbg = debug_backtrace(); 359 self::$_PHPCAS_INIT_CALL = array( 360 'done' => true, 361 'file' => $dbg[0]['file'], 362 'line' => $dbg[0]['line'], 363 'method' => __CLASS__ . '::' . __FUNCTION__ 364 ); 365 366 // initialize the object $_PHPCAS_CLIENT 367 try { 368 self::$_PHPCAS_CLIENT = new CAS_Client( 369 $server_version, 370 false, 371 $server_hostname, 372 $server_port, 373 $server_uri, 374 $changeSessionID 375 ); 376 } catch (Exception $e) { 377 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 378 } 379 phpCAS :: traceEnd(); 380 } 381 382 /** 383 * phpCAS proxy initializer. 384 * 385 * @param string $server_version the version of the CAS server 386 * @param string $server_hostname the hostname of the CAS server 387 * @param string $server_port the port the CAS server is running on 388 * @param string $server_uri the URI the CAS server is responding on 389 * @param bool $changeSessionID Allow phpCAS to change the session_id (Single 390 * Sign Out/handleLogoutRequests is based on that change) 391 * 392 * @return a newly created CAS_Client object 393 * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be 394 * called, only once, and before all other methods (except phpCAS::getVersion() 395 * and phpCAS::setDebug()). 396 */ 397 public static function proxy( 398 $server_version, 399 $server_hostname, 400 $server_port, 401 $server_uri, 402 $changeSessionID = true 403 ) { 404 phpCAS :: traceBegin(); 405 if (is_object(self::$_PHPCAS_CLIENT)) { 406 phpCAS :: error(self::$_PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . self::$_PHPCAS_INIT_CALL['file'] . ':' . self::$_PHPCAS_INIT_CALL['line'] . ')'); 407 } 408 409 // store where the initialzer is called from 410 $dbg = debug_backtrace(); 411 self::$_PHPCAS_INIT_CALL = array( 412 'done' => true, 413 'file' => $dbg[0]['file'], 414 'line' => $dbg[0]['line'], 415 'method' => __CLASS__ . '::' . __FUNCTION__ 416 ); 417 418 // initialize the object $_PHPCAS_CLIENT 419 try { 420 self::$_PHPCAS_CLIENT = new CAS_Client( 421 $server_version, 422 true, 423 $server_hostname, 424 $server_port, 425 $server_uri, 426 $changeSessionID 427 ); 428 } catch (Exception $e) { 429 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 430 } 431 phpCAS :: traceEnd(); 432 } 433 434 /** 435 * Answer whether or not the client or proxy has been initialized 436 * 437 * @return bool 438 */ 439 public static function isInitialized() 440 { 441 return (is_object(self::$_PHPCAS_CLIENT)); 442 } 443 444 /** @} */ 445 // ######################################################################## 446 // DEBUGGING 447 // ######################################################################## 448 449 /** 450 * @addtogroup publicDebug 451 * @{ 452 */ 453 454 /** 455 * Set/unset debug mode 456 * 457 * @param string $filename the name of the file used for logging, or false 458 * to stop debugging. 459 * 460 * @return void 461 */ 462 public static function setDebug($filename = '') 463 { 464 if ($filename != false && gettype($filename) != 'string') { 465 phpCAS :: error('type mismatched for parameter $dbg (should be false or the name of the log file)'); 466 } 467 if ($filename === false) { 468 self::$_PHPCAS_DEBUG['filename'] = false; 469 } else { 470 if (empty($filename)) { 471 if (preg_match('/^Win.*/', getenv('OS'))) { 472 if (isset($_ENV['TMP'])) { 473 $debugDir = $_ENV['TMP'] . '/'; 474 } else { 475 $debugDir = ''; 476 } 477 } else { 478 $debugDir = DEFAULT_DEBUG_DIR; 479 } 480 $filename = $debugDir . 'phpCAS.log'; 481 } 482 483 if (empty(self::$_PHPCAS_DEBUG['unique_id'])) { 484 self::$_PHPCAS_DEBUG['unique_id'] = substr(strtoupper(md5(uniqid(''))), 0, 4); 485 } 486 487 self::$_PHPCAS_DEBUG['filename'] = $filename; 488 self::$_PHPCAS_DEBUG['indent'] = 0; 489 490 phpCAS :: trace('START (' . date("Y-m-d H:i:s") . ') phpCAS-' . PHPCAS_VERSION . ' ******************'); 491 } 492 } 493 494 /** 495 * Enable verbose errors messages in the website output 496 * This is a security relevant since internal status info may leak an may 497 * help an attacker. Default is therefore false 498 * 499 * @param bool $verbose enable verbose output 500 * 501 * @return void 502 */ 503 public static function setVerbose($verbose) 504 { 505 if ($verbose === true) { 506 self::$_PHPCAS_VERBOSE = true; 507 } else { 508 self::$_PHPCAS_VERBOSE = false; 509 } 510 } 511 512 513 /** 514 * Show is verbose mode is on 515 * 516 * @return boot verbose 517 */ 518 public static function getVerbose() 519 { 520 return self::$_PHPCAS_VERBOSE; 521 } 522 523 /** 524 * Logs a string in debug mode. 525 * 526 * @param string $str the string to write 527 * 528 * @return void 529 * @private 530 */ 531 public static function log($str) 532 { 533 $indent_str = "."; 534 535 536 if (!empty(self::$_PHPCAS_DEBUG['filename'])) { 537 // Check if file exists and modifiy file permissions to be only 538 // readable by the webserver 539 if (!file_exists(self::$_PHPCAS_DEBUG['filename'])) { 540 touch(self::$_PHPCAS_DEBUG['filename']); 541 // Chmod will fail on windows 542 @chmod(self::$_PHPCAS_DEBUG['filename'], 0600); 543 } 544 for ($i = 0; $i < self::$_PHPCAS_DEBUG['indent']; $i++) { 545 $indent_str .= '| '; 546 } 547 // allow for multiline output with proper identing. Usefull for 548 // dumping cas answers etc. 549 $str2 = str_replace("\n", "\n" . self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str, $str); 550 error_log(self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str . $str2 . "\n", 3, self::$_PHPCAS_DEBUG['filename']); 551 } 552 } 553 554 /** 555 * This method is used by interface methods to print an error and where the 556 * function was originally called from. 557 * 558 * @param string $msg the message to print 559 * 560 * @return void 561 * @private 562 */ 563 public static function error($msg) 564 { 565 phpCAS :: traceBegin(); 566 $dbg = debug_backtrace(); 567 $function = '?'; 568 $file = '?'; 569 $line = '?'; 570 if (is_array($dbg)) { 571 for ($i = 1; $i < sizeof($dbg); $i++) { 572 if (is_array($dbg[$i]) && isset($dbg[$i]['class'])) { 573 if ($dbg[$i]['class'] == __CLASS__) { 574 $function = $dbg[$i]['function']; 575 $file = $dbg[$i]['file']; 576 $line = $dbg[$i]['line']; 577 } 578 } 579 } 580 } 581 if (self::$_PHPCAS_VERBOSE) { 582 echo "<br />\n<b>phpCAS error</b>: <font color=\"FF0000\"><b>" . __CLASS__ . "::" . $function . '(): ' . htmlentities($msg) . "</b></font> in <b>" . $file . "</b> on line <b>" . $line . "</b><br />\n"; 583 } else { 584 echo "<br />\n<b>Error</b>: <font color=\"FF0000\"><b>" . DEFAULT_ERROR . "</b><br />\n"; 585 } 586 phpCAS :: trace($msg . ' in ' . $file . 'on line ' . $line); 587 phpCAS :: traceEnd(); 588 589 throw new CAS_GracefullTerminationException(__CLASS__ . "::" . $function . '(): ' . $msg); 590 } 591 592 /** 593 * This method is used to log something in debug mode. 594 * 595 * @param string $str string to log 596 * 597 * @return void 598 */ 599 public static function trace($str) 600 { 601 $dbg = debug_backtrace(); 602 phpCAS :: log($str . ' [' . basename($dbg[0]['file']) . ':' . $dbg[0]['line'] . ']'); 603 } 604 605 /** 606 * This method is used to indicate the start of the execution of a function 607 * in debug mode. 608 * 609 * @return void 610 */ 611 public static function traceBegin() 612 { 613 $dbg = debug_backtrace(); 614 $str = '=> '; 615 if (!empty($dbg[1]['class'])) { 616 $str .= $dbg[1]['class'] . '::'; 617 } 618 $str .= $dbg[1]['function'] . '('; 619 if (is_array($dbg[1]['args'])) { 620 foreach ($dbg[1]['args'] as $index => $arg) { 621 if ($index != 0) { 622 $str .= ', '; 623 } 624 if (is_object($arg)) { 625 $str .= get_class($arg); 626 } else { 627 $str .= str_replace(array("\r\n", "\n", "\r"), "", var_export($arg, true)); 628 } 629 } 630 } 631 if (isset($dbg[1]['file'])) { 632 $file = basename($dbg[1]['file']); 633 } else { 634 $file = 'unknown_file'; 635 } 636 if (isset($dbg[1]['line'])) { 637 $line = $dbg[1]['line']; 638 } else { 639 $line = 'unknown_line'; 640 } 641 $str .= ') [' . $file . ':' . $line . ']'; 642 phpCAS :: log($str); 643 if (!isset(self::$_PHPCAS_DEBUG['indent'])) { 644 self::$_PHPCAS_DEBUG['indent'] = 0; 645 } else { 646 self::$_PHPCAS_DEBUG['indent']++; 647 } 648 } 649 650 /** 651 * This method is used to indicate the end of the execution of a function in 652 * debug mode. 653 * 654 * @param string $res the result of the function 655 * 656 * @return void 657 */ 658 public static function traceEnd($res = '') 659 { 660 if (empty(self::$_PHPCAS_DEBUG['indent'])) { 661 self::$_PHPCAS_DEBUG['indent'] = 0; 662 } else { 663 self::$_PHPCAS_DEBUG['indent']--; 664 } 665 $dbg = debug_backtrace(); 666 $str = ''; 667 if (is_object($res)) { 668 $str .= '<= ' . get_class($res); 669 } else { 670 $str .= '<= ' . str_replace(array("\r\n", "\n", "\r"), "", var_export($res, true)); 671 } 672 673 phpCAS :: log($str); 674 } 675 676 /** 677 * This method is used to indicate the end of the execution of the program 678 * 679 * @return void 680 */ 681 public static function traceExit() 682 { 683 phpCAS :: log('exit()'); 684 while (self::$_PHPCAS_DEBUG['indent'] > 0) { 685 phpCAS :: log('-'); 686 self::$_PHPCAS_DEBUG['indent']--; 687 } 688 } 689 690 /** @} */ 691 // ######################################################################## 692 // INTERNATIONALIZATION 693 // ######################################################################## 694 /** 695 * @addtogroup publicLang 696 * @{ 697 */ 698 699 /** 700 * This method is used to set the language used by phpCAS. 701 * 702 * @param string $lang string representing the language. 703 * 704 * @return void 705 * 706 * @sa PHPCAS_LANG_FRENCH, PHPCAS_LANG_ENGLISH 707 * @note Can be called only once. 708 */ 709 public static function setLang($lang) 710 { 711 phpCAS::_validateClientExists(); 712 713 try { 714 self::$_PHPCAS_CLIENT->setLang($lang); 715 } catch (Exception $e) { 716 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 717 } 718 } 719 720 /** @} */ 721 // ######################################################################## 722 // VERSION 723 // ######################################################################## 724 /** 725 * @addtogroup public 726 * @{ 727 */ 728 729 /** 730 * This method returns the phpCAS version. 731 * 732 * @return the phpCAS version. 733 */ 734 public static function getVersion() 735 { 736 return PHPCAS_VERSION; 737 } 738 739 /** @} */ 740 // ######################################################################## 741 // HTML OUTPUT 742 // ######################################################################## 743 /** 744 * @addtogroup publicOutput 745 * @{ 746 */ 747 748 /** 749 * This method sets the HTML header used for all outputs. 750 * 751 * @param string $header the HTML header. 752 * 753 * @return void 754 */ 755 public static function setHTMLHeader($header) 756 { 757 phpCAS::_validateClientExists(); 758 759 try { 760 self::$_PHPCAS_CLIENT->setHTMLHeader($header); 761 } catch (Exception $e) { 762 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 763 } 764 } 765 766 /** 767 * This method sets the HTML footer used for all outputs. 768 * 769 * @param string $footer the HTML footer. 770 * 771 * @return void 772 */ 773 public static function setHTMLFooter($footer) 774 { 775 phpCAS::_validateClientExists(); 776 777 try { 778 self::$_PHPCAS_CLIENT->setHTMLFooter($footer); 779 } catch (Exception $e) { 780 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 781 } 782 } 783 784 /** @} */ 785 // ######################################################################## 786 // PGT STORAGE 787 // ######################################################################## 788 /** 789 * @addtogroup publicPGTStorage 790 * @{ 791 */ 792 793 /** 794 * This method can be used to set a custom PGT storage object. 795 * 796 * @param CAS_PGTStorage $storage a PGT storage object that inherits from the 797 * CAS_PGTStorage class 798 * 799 * @return void 800 */ 801 public static function setPGTStorage($storage) 802 { 803 phpCAS :: traceBegin(); 804 phpCAS::_validateProxyExists(); 805 806 try { 807 self::$_PHPCAS_CLIENT->setPGTStorage($storage); 808 } catch (Exception $e) { 809 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 810 } 811 phpCAS :: traceEnd(); 812 } 813 814 /** 815 * This method is used to tell phpCAS to store the response of the 816 * CAS server to PGT requests in a database. 817 * 818 * @param string $dsn_or_pdo a dsn string to use for creating a PDO 819 * object or a PDO object 820 * @param string $username the username to use when connecting to the 821 * database 822 * @param string $password the password to use when connecting to the 823 * database 824 * @param string $table the table to use for storing and retrieving 825 * PGT's 826 * @param string $driver_options any driver options to use when connecting 827 * to the database 828 * 829 * @return void 830 */ 831 public static function setPGTStorageDb( 832 $dsn_or_pdo, 833 $username = '', 834 $password = '', 835 $table = '', 836 $driver_options = null 837 ) { 838 phpCAS :: traceBegin(); 839 phpCAS::_validateProxyExists(); 840 841 try { 842 self::$_PHPCAS_CLIENT->setPGTStorageDb($dsn_or_pdo, $username, $password, $table, $driver_options); 843 } catch (Exception $e) { 844 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 845 } 846 phpCAS :: traceEnd(); 847 } 848 849 /** 850 * This method is used to tell phpCAS to store the response of the 851 * CAS server to PGT requests onto the filesystem. 852 * 853 * @param string $path the path where the PGT's should be stored 854 * 855 * @return void 856 */ 857 public static function setPGTStorageFile($path = '') 858 { 859 phpCAS :: traceBegin(); 860 phpCAS::_validateProxyExists(); 861 862 try { 863 self::$_PHPCAS_CLIENT->setPGTStorageFile($path); 864 } catch (Exception $e) { 865 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 866 } 867 phpCAS :: traceEnd(); 868 } 869 /** @} */ 870 // ######################################################################## 871 // ACCESS TO EXTERNAL SERVICES 872 // ######################################################################## 873 /** 874 * @addtogroup publicServices 875 * @{ 876 */ 877 878 /** 879 * Answer a proxy-authenticated service handler. 880 * 881 * @param string $type The service type. One of 882 * PHPCAS_PROXIED_SERVICE_HTTP_GET; PHPCAS_PROXIED_SERVICE_HTTP_POST; 883 * PHPCAS_PROXIED_SERVICE_IMAP 884 * 885 * @return CAS_ProxiedService 886 * @throws InvalidArgumentException If the service type is unknown. 887 */ 888 public static function getProxiedService($type) 889 { 890 phpCAS :: traceBegin(); 891 phpCAS::_validateProxyExists(); 892 893 try { 894 $res = self::$_PHPCAS_CLIENT->getProxiedService($type); 895 } catch (Exception $e) { 896 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 897 } 898 899 phpCAS :: traceEnd(); 900 return $res; 901 } 902 903 /** 904 * Initialize a proxied-service handler with the proxy-ticket it should use. 905 * 906 * @param CAS_ProxiedService $proxiedService Proxied Service Handler 907 * 908 * @return void 909 * @throws CAS_ProxyTicketException If there is a proxy-ticket failure. 910 * The code of the Exception will be one of: 911 * PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE 912 * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE 913 * PHPCAS_SERVICE_PT_FAILURE 914 */ 915 public static function initializeProxiedService(CAS_ProxiedService $proxiedService) 916 { 917 phpCAS::_validateProxyExists(); 918 919 try { 920 self::$_PHPCAS_CLIENT->initializeProxiedService($proxiedService); 921 } catch (Exception $e) { 922 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 923 } 924 } 925 926 /** 927 * This method is used to access an HTTP[S] service. 928 * 929 * @param string $url the service to access. 930 * @param string &$err_code an error code Possible values are 931 * PHPCAS_SERVICE_OK (on success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, 932 * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, PHPCAS_SERVICE_PT_FAILURE, 933 * PHPCAS_SERVICE_NOT_AVAILABLE. 934 * @param string &$output the output of the service (also used to give an 935 * error message on failure). 936 * 937 * @return bool true on success, false otherwise (in this later case, 938 * $err_code gives the reason why it failed and $output contains an error 939 * message). 940 */ 941 public static function serviceWeb($url, &$err_code, &$output) 942 { 943 phpCAS :: traceBegin(); 944 phpCAS::_validateProxyExists(); 945 946 try { 947 $res = self::$_PHPCAS_CLIENT->serviceWeb($url, $err_code, $output); 948 } catch (Exception $e) { 949 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 950 } 951 952 phpCAS :: traceEnd($res); 953 return $res; 954 } 955 956 /** 957 * This method is used to access an IMAP/POP3/NNTP service. 958 * 959 * @param string $url a string giving the URL of the service, 960 * including the mailing box for IMAP URLs, as accepted by imap_open(). 961 * @param string $service a string giving for CAS retrieve Proxy ticket 962 * @param string $flags options given to imap_open(). 963 * @param string &$err_code an error code Possible values are 964 * PHPCAS_SERVICE_OK (on success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, 965 * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, PHPCAS_SERVICE_PT_FAILURE, 966 * PHPCAS_SERVICE_NOT_AVAILABLE. 967 * @param string &$err_msg an error message on failure 968 * @param string &$pt the Proxy Ticket (PT) retrieved from the CAS 969 * server to access the URL on success, false on error). 970 * 971 * @return object IMAP stream on success, false otherwise (in this later 972 * case, $err_code gives the reason why it failed and $err_msg contains an 973 * error message). 974 */ 975 public static function serviceMail($url, $service, $flags, &$err_code, &$err_msg, &$pt) 976 { 977 phpCAS :: traceBegin(); 978 phpCAS::_validateProxyExists(); 979 980 try { 981 $res = self::$_PHPCAS_CLIENT->serviceMail($url, $service, $flags, $err_code, $err_msg, $pt); 982 } catch (Exception $e) { 983 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 984 } 985 986 phpCAS :: traceEnd($res); 987 return $res; 988 } 989 990 /** @} */ 991 // ######################################################################## 992 // AUTHENTICATION 993 // ######################################################################## 994 /** 995 * @addtogroup publicAuth 996 * @{ 997 */ 998 999 /** 1000 * Set the times authentication will be cached before really accessing the 1001 * CAS server in gateway mode: 1002 * - -1: check only once, and then never again (until you pree login) 1003 * - 0: always check 1004 * - n: check every "n" time 1005 * 1006 * @param int $n an integer. 1007 * 1008 * @return void 1009 */ 1010 public static function setCacheTimesForAuthRecheck($n) 1011 { 1012 phpCAS::_validateClientExists(); 1013 1014 try { 1015 self::$_PHPCAS_CLIENT->setCacheTimesForAuthRecheck($n); 1016 } catch (Exception $e) { 1017 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1018 } 1019 } 1020 1021 1022 /** 1023 * Set a callback function to be run when receiving CAS attributes 1024 * 1025 * The callback function will be passed an $success_elements 1026 * payload of the response (\DOMElement) as its first parameter. 1027 * 1028 * @param string $function Callback function 1029 * @param array $additionalArgs optional array of arguments 1030 * 1031 * @return void 1032 */ 1033 public static function setCasAttributeParserCallback($function, array $additionalArgs = array()) 1034 { 1035 phpCAS::_validateClientExists(); 1036 1037 self::$_PHPCAS_CLIENT->setCasAttributeParserCallback($function, $additionalArgs); 1038 } 1039 1040 /** 1041 * Set a callback function to be run when a user authenticates. 1042 * 1043 * The callback function will be passed a $logoutTicket as its first 1044 * parameter, followed by any $additionalArgs you pass. The $logoutTicket 1045 * parameter is an opaque string that can be used to map the session-id to 1046 * logout request in order to support single-signout in applications that 1047 * manage their own sessions (rather than letting phpCAS start the session). 1048 * 1049 * phpCAS::forceAuthentication() will always exit and forward client unless 1050 * they are already authenticated. To perform an action at the moment the user 1051 * logs in (such as registering an account, performing logging, etc), register 1052 * a callback function here. 1053 * 1054 * @param string $function Callback function 1055 * @param array $additionalArgs optional array of arguments 1056 * 1057 * @return void 1058 */ 1059 public static function setPostAuthenticateCallback($function, array $additionalArgs = array()) 1060 { 1061 phpCAS::_validateClientExists(); 1062 1063 self::$_PHPCAS_CLIENT->setPostAuthenticateCallback($function, $additionalArgs); 1064 } 1065 1066 /** 1067 * Set a callback function to be run when a single-signout request is 1068 * received. The callback function will be passed a $logoutTicket as its 1069 * first parameter, followed by any $additionalArgs you pass. The 1070 * $logoutTicket parameter is an opaque string that can be used to map a 1071 * session-id to the logout request in order to support single-signout in 1072 * applications that manage their own sessions (rather than letting phpCAS 1073 * start and destroy the session). 1074 * 1075 * @param string $function Callback function 1076 * @param array $additionalArgs optional array of arguments 1077 * 1078 * @return void 1079 */ 1080 public static function setSingleSignoutCallback($function, array $additionalArgs = array()) 1081 { 1082 phpCAS::_validateClientExists(); 1083 1084 self::$_PHPCAS_CLIENT->setSingleSignoutCallback($function, $additionalArgs); 1085 } 1086 1087 /** 1088 * This method is called to check if the user is already authenticated 1089 * locally or has a global cas session. A already existing cas session is 1090 * determined by a cas gateway call.(cas login call without any interactive 1091 * prompt) 1092 * 1093 * @return true when the user is authenticated, false when a previous 1094 * gateway login failed or the function will not return if the user is 1095 * redirected to the cas server for a gateway login attempt 1096 */ 1097 public static function checkAuthentication() 1098 { 1099 phpCAS :: traceBegin(); 1100 phpCAS::_validateClientExists(); 1101 1102 $auth = self::$_PHPCAS_CLIENT->checkAuthentication(); 1103 1104 // store where the authentication has been checked and the result 1105 self::$_PHPCAS_CLIENT->markAuthenticationCall($auth); 1106 1107 phpCAS :: traceEnd($auth); 1108 return $auth; 1109 } 1110 1111 /** 1112 * This method is called to force authentication if the user was not already 1113 * authenticated. If the user is not authenticated, halt by redirecting to 1114 * the CAS server. 1115 * 1116 * @return bool Authentication 1117 */ 1118 public static function forceAuthentication() 1119 { 1120 phpCAS :: traceBegin(); 1121 phpCAS::_validateClientExists(); 1122 $auth = self::$_PHPCAS_CLIENT->forceAuthentication(); 1123 1124 // store where the authentication has been checked and the result 1125 self::$_PHPCAS_CLIENT->markAuthenticationCall($auth); 1126 1127 /* if (!$auth) { 1128 phpCAS :: trace('user is not authenticated, redirecting to the CAS server'); 1129 self::$_PHPCAS_CLIENT->forceAuthentication(); 1130 } else { 1131 phpCAS :: trace('no need to authenticate (user `' . phpCAS :: getUser() . '\' is already authenticated)'); 1132 }*/ 1133 1134 phpCAS :: traceEnd(); 1135 return $auth; 1136 } 1137 1138 /** 1139 * This method is called to renew the authentication. 1140 * 1141 * @return void 1142 **/ 1143 public static function renewAuthentication() 1144 { 1145 phpCAS :: traceBegin(); 1146 phpCAS::_validateClientExists(); 1147 1148 $auth = self::$_PHPCAS_CLIENT->renewAuthentication(); 1149 1150 // store where the authentication has been checked and the result 1151 self::$_PHPCAS_CLIENT->markAuthenticationCall($auth); 1152 1153 //self::$_PHPCAS_CLIENT->renewAuthentication(); 1154 phpCAS :: traceEnd(); 1155 } 1156 1157 /** 1158 * This method is called to check if the user is authenticated (previously or by 1159 * tickets given in the URL). 1160 * 1161 * @return true when the user is authenticated. 1162 */ 1163 public static function isAuthenticated() 1164 { 1165 phpCAS :: traceBegin(); 1166 phpCAS::_validateClientExists(); 1167 1168 // call the isAuthenticated method of the $_PHPCAS_CLIENT object 1169 $auth = self::$_PHPCAS_CLIENT->isAuthenticated(); 1170 1171 // store where the authentication has been checked and the result 1172 self::$_PHPCAS_CLIENT->markAuthenticationCall($auth); 1173 1174 phpCAS :: traceEnd($auth); 1175 return $auth; 1176 } 1177 1178 /** 1179 * Checks whether authenticated based on $_SESSION. Useful to avoid 1180 * server calls. 1181 * 1182 * @return bool true if authenticated, false otherwise. 1183 * @since 0.4.22 by Brendan Arnold 1184 */ 1185 public static function isSessionAuthenticated() 1186 { 1187 phpCAS::_validateClientExists(); 1188 1189 return (self::$_PHPCAS_CLIENT->isSessionAuthenticated()); 1190 } 1191 1192 /** 1193 * This method returns the CAS user's login name. 1194 * 1195 * @return string the login name of the authenticated user 1196 * @warning should only be called after phpCAS::forceAuthentication() 1197 * or phpCAS::checkAuthentication(). 1198 * */ 1199 public static function getUser() 1200 { 1201 phpCAS::_validateClientExists(); 1202 1203 try { 1204 return self::$_PHPCAS_CLIENT->getUser(); 1205 } catch (Exception $e) { 1206 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1207 } 1208 } 1209 1210 /** 1211 * Answer attributes about the authenticated user. 1212 * 1213 * @warning should only be called after phpCAS::forceAuthentication() 1214 * or phpCAS::checkAuthentication(). 1215 * 1216 * @return array 1217 */ 1218 public static function getAttributes() 1219 { 1220 phpCAS::_validateClientExists(); 1221 1222 try { 1223 return self::$_PHPCAS_CLIENT->getAttributes(); 1224 } catch (Exception $e) { 1225 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1226 } 1227 } 1228 1229 /** 1230 * Answer true if there are attributes for the authenticated user. 1231 * 1232 * @warning should only be called after phpCAS::forceAuthentication() 1233 * or phpCAS::checkAuthentication(). 1234 * 1235 * @return bool 1236 */ 1237 public static function hasAttributes() 1238 { 1239 phpCAS::_validateClientExists(); 1240 1241 try { 1242 return self::$_PHPCAS_CLIENT->hasAttributes(); 1243 } catch (Exception $e) { 1244 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1245 } 1246 } 1247 1248 /** 1249 * Answer true if an attribute exists for the authenticated user. 1250 * 1251 * @param string $key attribute name 1252 * 1253 * @return bool 1254 * @warning should only be called after phpCAS::forceAuthentication() 1255 * or phpCAS::checkAuthentication(). 1256 */ 1257 public static function hasAttribute($key) 1258 { 1259 phpCAS::_validateClientExists(); 1260 1261 try { 1262 return self::$_PHPCAS_CLIENT->hasAttribute($key); 1263 } catch (Exception $e) { 1264 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1265 } 1266 } 1267 1268 /** 1269 * Answer an attribute for the authenticated user. 1270 * 1271 * @param string $key attribute name 1272 * 1273 * @return mixed string for a single value or an array if multiple values exist. 1274 * @warning should only be called after phpCAS::forceAuthentication() 1275 * or phpCAS::checkAuthentication(). 1276 */ 1277 public static function getAttribute($key) 1278 { 1279 phpCAS::_validateClientExists(); 1280 1281 try { 1282 return self::$_PHPCAS_CLIENT->getAttribute($key); 1283 } catch (Exception $e) { 1284 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1285 } 1286 } 1287 1288 /** 1289 * Handle logout requests. 1290 * 1291 * @param bool $check_client additional safety check 1292 * @param array $allowed_clients array of allowed clients 1293 * 1294 * @return void 1295 */ 1296 public static function handleLogoutRequests($check_client = true, $allowed_clients = false) 1297 { 1298 phpCAS::_validateClientExists(); 1299 1300 return (self::$_PHPCAS_CLIENT->handleLogoutRequests($check_client, $allowed_clients)); 1301 } 1302 1303 /** 1304 * This method returns the URL to be used to login. 1305 * or phpCAS::isAuthenticated(). 1306 * 1307 * @return the login name of the authenticated user 1308 */ 1309 public static function getServerLoginURL() 1310 { 1311 phpCAS::_validateClientExists(); 1312 1313 return self::$_PHPCAS_CLIENT->getServerLoginURL(); 1314 } 1315 1316 /** 1317 * Set the login URL of the CAS server. 1318 * 1319 * @param string $url the login URL 1320 * 1321 * @return void 1322 * @since 0.4.21 by Wyman Chan 1323 */ 1324 public static function setServerLoginURL($url = '') 1325 { 1326 phpCAS :: traceBegin(); 1327 phpCAS::_validateClientExists(); 1328 1329 try { 1330 self::$_PHPCAS_CLIENT->setServerLoginURL($url); 1331 } catch (Exception $e) { 1332 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1333 } 1334 1335 phpCAS :: traceEnd(); 1336 } 1337 1338 /** 1339 * Set the serviceValidate URL of the CAS server. 1340 * Used for all CAS versions of URL validations. 1341 * Examples: 1342 * CAS 1.0 http://www.exemple.com/validate 1343 * CAS 2.0 http://www.exemple.com/validateURL 1344 * CAS 3.0 http://www.exemple.com/p3/serviceValidate 1345 * 1346 * @param string $url the serviceValidate URL 1347 * 1348 * @return void 1349 */ 1350 public static function setServerServiceValidateURL($url = '') 1351 { 1352 phpCAS :: traceBegin(); 1353 phpCAS::_validateClientExists(); 1354 1355 try { 1356 self::$_PHPCAS_CLIENT->setServerServiceValidateURL($url); 1357 } catch (Exception $e) { 1358 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1359 } 1360 1361 phpCAS :: traceEnd(); 1362 } 1363 1364 /** 1365 * Set the proxyValidate URL of the CAS server. 1366 * Used for all CAS versions of proxy URL validations 1367 * Examples: 1368 * CAS 1.0 http://www.exemple.com/ 1369 * CAS 2.0 http://www.exemple.com/proxyValidate 1370 * CAS 3.0 http://www.exemple.com/p3/proxyValidate 1371 * 1372 * @param string $url the proxyValidate URL 1373 * 1374 * @return void 1375 */ 1376 public static function setServerProxyValidateURL($url = '') 1377 { 1378 phpCAS :: traceBegin(); 1379 phpCAS::_validateClientExists(); 1380 1381 try { 1382 self::$_PHPCAS_CLIENT->setServerProxyValidateURL($url); 1383 } catch (Exception $e) { 1384 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1385 } 1386 1387 phpCAS :: traceEnd(); 1388 } 1389 1390 /** 1391 * Set the samlValidate URL of the CAS server. 1392 * 1393 * @param string $url the samlValidate URL 1394 * 1395 * @return void 1396 */ 1397 public static function setServerSamlValidateURL($url = '') 1398 { 1399 phpCAS :: traceBegin(); 1400 phpCAS::_validateClientExists(); 1401 1402 try { 1403 self::$_PHPCAS_CLIENT->setServerSamlValidateURL($url); 1404 } catch (Exception $e) { 1405 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1406 } 1407 1408 phpCAS :: traceEnd(); 1409 } 1410 1411 /** 1412 * This method returns the URL to be used to login. 1413 * or phpCAS::isAuthenticated(). 1414 * 1415 * @return the login name of the authenticated user 1416 */ 1417 public static function getServerLogoutURL() 1418 { 1419 phpCAS::_validateClientExists(); 1420 1421 return self::$_PHPCAS_CLIENT->getServerLogoutURL(); 1422 } 1423 1424 /** 1425 * Set the logout URL of the CAS server. 1426 * 1427 * @param string $url the logout URL 1428 * 1429 * @return void 1430 * @since 0.4.21 by Wyman Chan 1431 */ 1432 public static function setServerLogoutURL($url = '') 1433 { 1434 phpCAS :: traceBegin(); 1435 phpCAS::_validateClientExists(); 1436 1437 try { 1438 self::$_PHPCAS_CLIENT->setServerLogoutURL($url); 1439 } catch (Exception $e) { 1440 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1441 } 1442 1443 phpCAS :: traceEnd(); 1444 } 1445 1446 /** 1447 * This method is used to logout from CAS. 1448 * 1449 * @param string $params an array that contains the optional url and 1450 * service parameters that will be passed to the CAS server 1451 * 1452 * @return void 1453 */ 1454 public static function logout($params = "") 1455 { 1456 phpCAS :: traceBegin(); 1457 phpCAS::_validateClientExists(); 1458 1459 $parsedParams = array(); 1460 if ($params != "") { 1461 if (is_string($params)) { 1462 phpCAS :: error('method `phpCAS::logout($url)\' is now deprecated, use `phpCAS::logoutWithUrl($url)\' instead'); 1463 } 1464 if (!is_array($params)) { 1465 phpCAS :: error('type mismatched for parameter $params (should be `array\')'); 1466 } 1467 foreach ($params as $key => $value) { 1468 if ($key != "service" && $key != "url") { 1469 phpCAS :: error('only `url\' and `service\' parameters are allowed for method `phpCAS::logout($params)\''); 1470 } 1471 $parsedParams[$key] = $value; 1472 } 1473 } 1474 self::$_PHPCAS_CLIENT->logout($parsedParams); 1475 // never reached 1476 phpCAS :: traceEnd(); 1477 } 1478 1479 /** 1480 * This method is used to logout from CAS. Halts by redirecting to the CAS 1481 * server. 1482 * 1483 * @param string $service a URL that will be transmitted to the CAS server 1484 * 1485 * @return void 1486 */ 1487 public static function logoutWithRedirectService($service) 1488 { 1489 phpCAS :: traceBegin(); 1490 phpCAS::_validateClientExists(); 1491 1492 if (!is_string($service)) { 1493 phpCAS :: error('type mismatched for parameter $service (should be `string\')'); 1494 } 1495 self::$_PHPCAS_CLIENT->logout(array( "service" => $service )); 1496 // never reached 1497 phpCAS :: traceEnd(); 1498 } 1499 1500 /** 1501 * This method is used to logout from CAS. Halts by redirecting to the CAS 1502 * server. 1503 * 1504 * @param string $url a URL that will be transmitted to the CAS server 1505 * 1506 * @return void 1507 * @deprecated The url parameter has been removed from the CAS server as of 1508 * version 3.3.5.1 1509 */ 1510 public static function logoutWithUrl($url) 1511 { 1512 trigger_error('Function deprecated for cas servers >= 3.3.5.1', E_USER_DEPRECATED); 1513 phpCAS :: traceBegin(); 1514 if (!is_object(self::$_PHPCAS_CLIENT)) { 1515 phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()'); 1516 } 1517 if (!is_string($url)) { 1518 phpCAS :: error('type mismatched for parameter $url (should be `string\')'); 1519 } 1520 self::$_PHPCAS_CLIENT->logout(array( "url" => $url )); 1521 // never reached 1522 phpCAS :: traceEnd(); 1523 } 1524 1525 /** 1526 * This method is used to logout from CAS. Halts by redirecting to the CAS 1527 * server. 1528 * 1529 * @param string $service a URL that will be transmitted to the CAS server 1530 * @param string $url a URL that will be transmitted to the CAS server 1531 * 1532 * @return void 1533 * 1534 * @deprecated The url parameter has been removed from the CAS server as of 1535 * version 3.3.5.1 1536 */ 1537 public static function logoutWithRedirectServiceAndUrl($service, $url) 1538 { 1539 trigger_error('Function deprecated for cas servers >= 3.3.5.1', E_USER_DEPRECATED); 1540 phpCAS :: traceBegin(); 1541 phpCAS::_validateClientExists(); 1542 1543 if (!is_string($service)) { 1544 phpCAS :: error('type mismatched for parameter $service (should be `string\')'); 1545 } 1546 if (!is_string($url)) { 1547 phpCAS :: error('type mismatched for parameter $url (should be `string\')'); 1548 } 1549 self::$_PHPCAS_CLIENT->logout( 1550 array( 1551 "service" => $service, 1552 "url" => $url 1553 ) 1554 ); 1555 // never reached 1556 phpCAS :: traceEnd(); 1557 } 1558 1559 /** 1560 * Set the fixed URL that will be used by the CAS server to transmit the 1561 * PGT. When this method is not called, a phpCAS script uses its own URL 1562 * for the callback. 1563 * 1564 * @param string $url the URL 1565 * 1566 * @return void 1567 */ 1568 public static function setFixedCallbackURL($url = '') 1569 { 1570 phpCAS :: traceBegin(); 1571 phpCAS::_validateProxyExists(); 1572 1573 try { 1574 self::$_PHPCAS_CLIENT->setCallbackURL($url); 1575 } catch (Exception $e) { 1576 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1577 } 1578 1579 phpCAS :: traceEnd(); 1580 } 1581 1582 /** 1583 * Set the fixed URL that will be set as the CAS service parameter. When this 1584 * method is not called, a phpCAS script uses its own URL. 1585 * 1586 * @param string $url the URL 1587 * 1588 * @return void 1589 */ 1590 public static function setFixedServiceURL($url) 1591 { 1592 phpCAS :: traceBegin(); 1593 phpCAS::_validateProxyExists(); 1594 1595 try { 1596 self::$_PHPCAS_CLIENT->setURL($url); 1597 } catch (Exception $e) { 1598 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1599 } 1600 1601 phpCAS :: traceEnd(); 1602 } 1603 1604 /** 1605 * Get the URL that is set as the CAS service parameter. 1606 * 1607 * @return string Service Url 1608 */ 1609 public static function getServiceURL() 1610 { 1611 phpCAS::_validateProxyExists(); 1612 return (self::$_PHPCAS_CLIENT->getURL()); 1613 } 1614 1615 /** 1616 * Retrieve a Proxy Ticket from the CAS server. 1617 * 1618 * @param string $target_service Url string of service to proxy 1619 * @param string &$err_code error code 1620 * @param string &$err_msg error message 1621 * 1622 * @return string Proxy Ticket 1623 */ 1624 public static function retrievePT($target_service, &$err_code, &$err_msg) 1625 { 1626 phpCAS::_validateProxyExists(); 1627 1628 try { 1629 return (self::$_PHPCAS_CLIENT->retrievePT($target_service, $err_code, $err_msg)); 1630 } catch (Exception $e) { 1631 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1632 } 1633 } 1634 1635 /** 1636 * Set the certificate of the CAS server CA and if the CN should be properly 1637 * verified. 1638 * 1639 * @param string $cert CA certificate file name 1640 * @param bool $validate_cn Validate CN in certificate (default true) 1641 * 1642 * @return void 1643 */ 1644 public static function setCasServerCACert($cert, $validate_cn = true) 1645 { 1646 phpCAS :: traceBegin(); 1647 phpCAS::_validateClientExists(); 1648 1649 try { 1650 self::$_PHPCAS_CLIENT->setCasServerCACert($cert, $validate_cn); 1651 } catch (Exception $e) { 1652 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1653 } 1654 1655 phpCAS :: traceEnd(); 1656 } 1657 1658 /** 1659 * Set no SSL validation for the CAS server. 1660 * 1661 * @return void 1662 */ 1663 public static function setNoCasServerValidation() 1664 { 1665 phpCAS :: traceBegin(); 1666 phpCAS::_validateClientExists(); 1667 1668 phpCAS :: trace('You have configured no validation of the legitimacy of the cas server. This is not recommended for production use.'); 1669 self::$_PHPCAS_CLIENT->setNoCasServerValidation(); 1670 phpCAS :: traceEnd(); 1671 } 1672 1673 1674 /** 1675 * Disable the removal of a CAS-Ticket from the URL when authenticating 1676 * DISABLING POSES A SECURITY RISK: 1677 * We normally remove the ticket by an additional redirect as a security 1678 * precaution to prevent a ticket in the HTTP_REFERRER or be carried over in 1679 * the URL parameter 1680 * 1681 * @return void 1682 */ 1683 public static function setNoClearTicketsFromUrl() 1684 { 1685 phpCAS :: traceBegin(); 1686 phpCAS::_validateClientExists(); 1687 1688 self::$_PHPCAS_CLIENT->setNoClearTicketsFromUrl(); 1689 phpCAS :: traceEnd(); 1690 } 1691 1692 /** @} */ 1693 1694 /** 1695 * Change CURL options. 1696 * CURL is used to connect through HTTPS to CAS server 1697 * 1698 * @param string $key the option key 1699 * @param string $value the value to set 1700 * 1701 * @return void 1702 */ 1703 public static function setExtraCurlOption($key, $value) 1704 { 1705 phpCAS :: traceBegin(); 1706 phpCAS::_validateClientExists(); 1707 1708 self::$_PHPCAS_CLIENT->setExtraCurlOption($key, $value); 1709 phpCAS :: traceEnd(); 1710 } 1711 1712 /** 1713 * If you want your service to be proxied you have to enable it (default 1714 * disabled) and define an accepable list of proxies that are allowed to 1715 * proxy your service. 1716 * 1717 * Add each allowed proxy definition object. For the normal CAS_ProxyChain 1718 * class, the constructor takes an array of proxies to match. The list is in 1719 * reverse just as seen from the service. Proxies have to be defined in reverse 1720 * from the service to the user. If a user hits service A and gets proxied via 1721 * B to service C the list of acceptable on C would be array(B,A). The definition 1722 * of an individual proxy can be either a string or a regexp (preg_match is used) 1723 * that will be matched against the proxy list supplied by the cas server 1724 * when validating the proxy tickets. The strings are compared starting from 1725 * the beginning and must fully match with the proxies in the list. 1726 * Example: 1727 * phpCAS::allowProxyChain(new CAS_ProxyChain(array( 1728 * 'https://app.example.com/' 1729 * ))); 1730 * phpCAS::allowProxyChain(new CAS_ProxyChain(array( 1731 * '/^https:\/\/app[0-9]\.example\.com\/rest\//', 1732 * 'http://client.example.com/' 1733 * ))); 1734 * 1735 * For quick testing or in certain production screnarios you might want to 1736 * allow allow any other valid service to proxy your service. To do so, add 1737 * the "Any" chain: 1738 * phpcas::allowProxyChain(new CAS_ProxyChain_Any); 1739 * THIS SETTING IS HOWEVER NOT RECOMMENDED FOR PRODUCTION AND HAS SECURITY 1740 * IMPLICATIONS: YOU ARE ALLOWING ANY SERVICE TO ACT ON BEHALF OF A USER 1741 * ON THIS SERVICE. 1742 * 1743 * @param CAS_ProxyChain_Interface $proxy_chain A proxy-chain that will be 1744 * matched against the proxies requesting access 1745 * 1746 * @return void 1747 */ 1748 public static function allowProxyChain(CAS_ProxyChain_Interface $proxy_chain) 1749 { 1750 phpCAS :: traceBegin(); 1751 phpCAS::_validateClientExists(); 1752 1753 if (self::$_PHPCAS_CLIENT->getServerVersion() !== CAS_VERSION_2_0 1754 && self::$_PHPCAS_CLIENT->getServerVersion() !== CAS_VERSION_3_0 1755 ) { 1756 phpCAS :: error('this method can only be used with the cas 2.0/3.0 protocols'); 1757 } 1758 self::$_PHPCAS_CLIENT->getAllowedProxyChains()->allowProxyChain($proxy_chain); 1759 phpCAS :: traceEnd(); 1760 } 1761 1762 /** 1763 * Answer an array of proxies that are sitting in front of this application. 1764 * This method will only return a non-empty array if we have received and 1765 * validated a Proxy Ticket. 1766 * 1767 * @return array 1768 * @access public 1769 * @since 6/25/09 1770 */ 1771 public static function getProxies() 1772 { 1773 phpCAS::_validateProxyExists(); 1774 1775 return(self::$_PHPCAS_CLIENT->getProxies()); 1776 } 1777 1778 // ######################################################################## 1779 // PGTIOU/PGTID and logoutRequest rebroadcasting 1780 // ######################################################################## 1781 1782 /** 1783 * Add a pgtIou/pgtId and logoutRequest rebroadcast node. 1784 * 1785 * @param string $rebroadcastNodeUrl The rebroadcast node URL. Can be 1786 * hostname or IP. 1787 * 1788 * @return void 1789 */ 1790 public static function addRebroadcastNode($rebroadcastNodeUrl) 1791 { 1792 phpCAS::traceBegin(); 1793 phpCAS::log('rebroadcastNodeUrl:' . $rebroadcastNodeUrl); 1794 phpCAS::_validateClientExists(); 1795 1796 try { 1797 self::$_PHPCAS_CLIENT->addRebroadcastNode($rebroadcastNodeUrl); 1798 } catch (Exception $e) { 1799 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1800 } 1801 1802 phpCAS::traceEnd(); 1803 } 1804 1805 /** 1806 * This method is used to add header parameters when rebroadcasting 1807 * pgtIou/pgtId or logoutRequest. 1808 * 1809 * @param String $header Header to send when rebroadcasting. 1810 * 1811 * @return void 1812 */ 1813 public static function addRebroadcastHeader($header) 1814 { 1815 phpCAS :: traceBegin(); 1816 phpCAS::_validateClientExists(); 1817 1818 try { 1819 self::$_PHPCAS_CLIENT->addRebroadcastHeader($header); 1820 } catch (Exception $e) { 1821 phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); 1822 } 1823 1824 phpCAS :: traceEnd(); 1825 } 1826 1827 /** 1828 * Checks if a client already exists 1829 * 1830 * @throws CAS_OutOfSequenceBeforeClientException 1831 * 1832 * @return void 1833 */ 1834 private static function _validateClientExists() 1835 { 1836 if (!is_object(self::$_PHPCAS_CLIENT)) { 1837 throw new CAS_OutOfSequenceBeforeClientException(); 1838 } 1839 } 1840 1841 /** 1842 * Checks of a proxy client aready exists 1843 * 1844 * @throws CAS_OutOfSequenceBeforeProxyException 1845 * 1846 * @return void 1847 */ 1848 private static function _validateProxyExists() 1849 { 1850 if (!is_object(self::$_PHPCAS_CLIENT)) { 1851 throw new CAS_OutOfSequenceBeforeProxyException(); 1852 } 1853 } 1854 1855 /** 1856 * For testing purposes, use this method to set the client to a test double 1857 * 1858 * @return void 1859 */ 1860 public static function setCasClient(\CAS_Client $client) 1861 { 1862 self::$_PHPCAS_CLIENT = $client; 1863 } 1864} 1865// ######################################################################## 1866// DOCUMENTATION 1867// ######################################################################## 1868 1869// ######################################################################## 1870// MAIN PAGE 1871 1872/** 1873 * @mainpage 1874 * 1875 * The following pages only show the source documentation. 1876 * 1877 */ 1878 1879// ######################################################################## 1880// MODULES DEFINITION 1881 1882/** @defgroup public User interface */ 1883 1884/** @defgroup publicInit Initialization 1885 * @ingroup public */ 1886 1887/** @defgroup publicAuth Authentication 1888 * @ingroup public */ 1889 1890/** @defgroup publicServices Access to external services 1891 * @ingroup public */ 1892 1893/** @defgroup publicConfig Configuration 1894 * @ingroup public */ 1895 1896/** @defgroup publicLang Internationalization 1897 * @ingroup publicConfig */ 1898 1899/** @defgroup publicOutput HTML output 1900 * @ingroup publicConfig */ 1901 1902/** @defgroup publicPGTStorage PGT storage 1903 * @ingroup publicConfig */ 1904 1905/** @defgroup publicDebug Debugging 1906 * @ingroup public */ 1907 1908/** @defgroup internal Implementation */ 1909 1910/** @defgroup internalAuthentication Authentication 1911 * @ingroup internal */ 1912 1913/** @defgroup internalBasic CAS Basic client features (CAS 1.0, Service Tickets) 1914 * @ingroup internal */ 1915 1916/** @defgroup internalProxy CAS Proxy features (CAS 2.0, Proxy Granting Tickets) 1917 * @ingroup internal */ 1918 1919/** @defgroup internalSAML CAS SAML features (SAML 1.1) 1920 * @ingroup internal */ 1921 1922/** @defgroup internalPGTStorage PGT storage 1923 * @ingroup internalProxy */ 1924 1925/** @defgroup internalPGTStorageDb PGT storage in a database 1926 * @ingroup internalPGTStorage */ 1927 1928/** @defgroup internalPGTStorageFile PGT storage on the filesystem 1929 * @ingroup internalPGTStorage */ 1930 1931/** @defgroup internalCallback Callback from the CAS server 1932 * @ingroup internalProxy */ 1933 1934/** @defgroup internalProxyServices Proxy other services 1935 * @ingroup internalProxy */ 1936 1937/** @defgroup internalService CAS client features (CAS 2.0, Proxied service) 1938 * @ingroup internal */ 1939 1940/** @defgroup internalConfig Configuration 1941 * @ingroup internal */ 1942 1943/** @defgroup internalBehave Internal behaviour of phpCAS 1944 * @ingroup internalConfig */ 1945 1946/** @defgroup internalOutput HTML output 1947 * @ingroup internalConfig */ 1948 1949/** @defgroup internalLang Internationalization 1950 * @ingroup internalConfig 1951 * 1952 * To add a new language: 1953 * - 1. define a new constant PHPCAS_LANG_XXXXXX in CAS/CAS.php 1954 * - 2. copy any file from CAS/languages to CAS/languages/XXXXXX.php 1955 * - 3. Make the translations 1956 */ 1957 1958/** @defgroup internalDebug Debugging 1959 * @ingroup internal */ 1960 1961/** @defgroup internalMisc Miscellaneous 1962 * @ingroup internal */ 1963 1964// ######################################################################## 1965// EXAMPLES 1966 1967/** 1968 * @example example_simple.php 1969 */ 1970/** 1971 * @example example_service.php 1972 */ 1973/** 1974 * @example example_service_that_proxies.php 1975 */ 1976/** 1977 * @example example_service_POST.php 1978 */ 1979/** 1980 * @example example_proxy_serviceWeb.php 1981 */ 1982/** 1983 * @example example_proxy_serviceWeb_chaining.php 1984 */ 1985/** 1986 * @example example_proxy_POST.php 1987 */ 1988/** 1989 * @example example_proxy_GET.php 1990 */ 1991/** 1992 * @example example_lang.php 1993 */ 1994/** 1995 * @example example_html.php 1996 */ 1997/** 1998 * @example example_pgt_storage_file.php 1999 */ 2000/** 2001 * @example example_pgt_storage_db.php 2002 */ 2003/** 2004 * @example example_gateway.php 2005 */ 2006/** 2007 * @example example_logout.php 2008 */ 2009/** 2010 * @example example_rebroadcast.php 2011 */ 2012/** 2013 * @example example_custom_urls.php 2014 */ 2015/** 2016 * @example example_advanced_saml11.php 2017 */ 2018