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