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