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