PluginProbe
Authorizer / 3.15.3
Authorizer v3.15.3
3.15.3 3.15.2 3.15.1 3.15.0 3.14.3 3.14.4 3.14.2 3.14.1 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.9.0 2.9.1 2.9.10 2.9.11 2.9.12 2.9.13 2.9.2 2.9.3 2.9.6 All 126 releases
authorizer / vendor / apereo / phpcas / source / CAS.php

CAS.php in Authorizer 3.15.3, at vendor/apereo/phpcas/source/CAS.php

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