• Main Page
  • Related Pages
  • Modules
  • Classes
  • Files
  • Examples
  • File List
  • File Members

CAS/client.php

Go to the documentation of this file.
00001 <?php
00002 
00003 /*
00004  * Copyright © 2003-2010, The ESUP-Portail consortium & the JA-SIG Collaborative.
00005  * All rights reserved.
00006  * 
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are met:
00009  * 
00010  *     * Redistributions of source code must retain the above copyright notice,
00011  *       this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright notice,
00013  *       this list of conditions and the following disclaimer in the documentation
00014  *       and/or other materials provided with the distribution.
00015  *     * Neither the name of the ESUP-Portail consortium & the JA-SIG
00016  *       Collaborative nor the names of its contributors may be used to endorse or
00017  *       promote products derived from this software without specific prior
00018  *       written permission.
00019 
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00021  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00022  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00023  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
00024  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00025  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00026  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00027  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00029  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  */
00031 
00037 // include internationalization stuff
00038 include_once(dirname(__FILE__).'/languages/languages.php');
00039 
00040 // include PGT storage classes
00041 include_once(dirname(__FILE__).'/PGTStorage/pgt-main.php');
00042 
00051 class CASClient
00052 {
00053         
00054         // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00055         // XX                                                                    XX
00056         // XX                          CONFIGURATION                             XX
00057         // XX                                                                    XX
00058         // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00059         
00060         // ########################################################################
00061         //  HTML OUTPUT
00062         // ########################################################################
00081         function HTMLFilterOutput($str)
00082                 {
00083                 $str = str_replace('__CAS_VERSION__',$this->getServerVersion(),$str);
00084                 $str = str_replace('__PHPCAS_VERSION__',phpCAS::getVersion(),$str);
00085                 $str = str_replace('__SERVER_BASE_URL__',$this->getServerBaseURL(),$str);
00086                 echo $str;
00087                 }
00088         
00097         var $_output_header = '';
00098         
00108         function printHTMLHeader($title)
00109                 {
00110                 $this->HTMLFilterOutput(str_replace('__TITLE__',
00111                         $title,
00112                         (empty($this->_output_header)
00113                                         ? '<html><head><title>__TITLE__</title></head><body><h1>__TITLE__</h1>'
00114                                                         : $this->_output_header)
00115                 )
00116                 );
00117                 }
00118         
00127         var $_output_footer = '';
00128         
00136         function printHTMLFooter()
00137                 {
00138                 $this->HTMLFilterOutput(empty($this->_output_footer)
00139                         ?('<hr><address>phpCAS __PHPCAS_VERSION__ '.$this->getString(CAS_STR_USING_SERVER).' <a href="__SERVER_BASE_URL__">__SERVER_BASE_URL__</a> (CAS __CAS_VERSION__)</a></address></body></html>')
00140                                         :$this->_output_footer);
00141                 }
00142         
00150         function setHTMLHeader($header)
00151                 {
00152                 $this->_output_header = $header;
00153                 }
00154         
00162         function setHTMLFooter($footer)
00163                 {
00164                 $this->_output_footer = $footer;
00165                 }
00166         
00168         // ########################################################################
00169         //  INTERNATIONALIZATION
00170         // ########################################################################
00185         var $_lang = '';
00186         
00194         function getLang()
00195                 {
00196                 if ( empty($this->_lang) )
00197                         $this->setLang(PHPCAS_LANG_DEFAULT);
00198                 return $this->_lang;
00199                 }
00200         
00210         var $_strings;
00211         
00221         function getString($str)
00222                 {
00223                 // call CASclient::getLang() to be sure the language is initialized
00224                 $this->getLang();
00225                 
00226                 if ( !isset($this->_strings[$str]) ) {
00227                         trigger_error('string `'.$str.'\' not defined for language `'.$this->getLang().'\'',E_USER_ERROR);
00228                 }
00229                 return $this->_strings[$str];
00230                 }
00231         
00241         function setLang($lang)
00242                 {
00243                 // include the corresponding language file
00244                 include_once(dirname(__FILE__).'/languages/'.$lang.'.php');
00245                 
00246                 if ( !is_array($this->_strings) ) {
00247                         trigger_error('language `'.$lang.'\' is not implemented',E_USER_ERROR);
00248                 }
00249                 $this->_lang = $lang;
00250                 }
00251         
00253         // ########################################################################
00254         //  CAS SERVER CONFIG
00255         // ########################################################################
00285         var $_server = array(
00286                 'version' => -1,
00287                 'hostname' => 'none',
00288                 'port' => -1,
00289                 'uri' => 'none'
00290         );
00291         
00297         function getServerVersion()
00298                 { 
00299                 return $this->_server['version']; 
00300                 }
00301         
00307         function getServerHostname()
00308                 { return $this->_server['hostname']; }
00309         
00315         function getServerPort()
00316                 { return $this->_server['port']; }
00317         
00323         function getServerURI()
00324                 { return $this->_server['uri']; }
00325         
00331         function getServerBaseURL()
00332                 { 
00333                 // the URL is build only when needed
00334                 if ( empty($this->_server['base_url']) ) {
00335                         $this->_server['base_url'] = 'https://'
00336                                 .$this->getServerHostname()
00337                                 .':'
00338                                 .$this->getServerPort()
00339                                 .$this->getServerURI();
00340                 }
00341                 return $this->_server['base_url']; 
00342                 }
00343         
00353         function getServerLoginURL($gateway=false,$renew=false) {
00354                 phpCAS::traceBegin();
00355                 // the URL is build only when needed
00356                 if ( empty($this->_server['login_url']) ) {
00357                         $this->_server['login_url'] = $this->getServerBaseURL();
00358                         $this->_server['login_url'] .= 'login?service=';
00359                         // $this->_server['login_url'] .= preg_replace('/&/','%26',$this->getURL());
00360                         $this->_server['login_url'] .= urlencode($this->getURL());
00361                         if($renew) {
00362                                 // It is recommended that when the "renew" parameter is set, its value be "true"
00363                                 $this->_server['login_url'] .= '&renew=true';
00364                         } elseif ($gateway) {
00365                                 // It is recommended that when the "gateway" parameter is set, its value be "true"
00366                                 $this->_server['login_url'] .= '&gateway=true';
00367                         }
00368                 }
00369                 phpCAS::traceEnd($this->_server['login_url']);
00370                 return $this->_server['login_url'];
00371         } 
00372         
00379         function setServerLoginURL($url)
00380                 {
00381                 return $this->_server['login_url'] = $url;
00382                 }
00383         
00384         
00391         function setServerServiceValidateURL($url)
00392                 {
00393                 return $this->_server['service_validate_url'] = $url;
00394                 }
00395         
00396         
00403         function setServerProxyValidateURL($url)
00404                 {
00405                 return $this->_server['proxy_validate_url'] = $url;
00406                 }
00407         
00408         
00415         function setServerSamlValidateURL($url)
00416                 {
00417                 return $this->_server['saml_validate_url'] = $url;
00418                 }
00419         
00420         
00426         function getServerServiceValidateURL()
00427                 { 
00428                 // the URL is build only when needed
00429                 if ( empty($this->_server['service_validate_url']) ) {
00430                         switch ($this->getServerVersion()) {
00431                                 case CAS_VERSION_1_0:
00432                                         $this->_server['service_validate_url'] = $this->getServerBaseURL().'validate';
00433                                         break;
00434                                 case CAS_VERSION_2_0:
00435                                         $this->_server['service_validate_url'] = $this->getServerBaseURL().'serviceValidate';
00436                                         break;
00437                         }
00438                 }
00439                 //      return $this->_server['service_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL()); 
00440                 return $this->_server['service_validate_url'].'?service='.urlencode($this->getURL()); 
00441                 }
00447         function getServerSamlValidateURL()
00448                 {
00449                 phpCAS::traceBegin();
00450                 // the URL is build only when needed
00451                 if ( empty($this->_server['saml_validate_url']) ) {
00452                         switch ($this->getServerVersion()) {
00453                                 case SAML_VERSION_1_1:
00454                                         $this->_server['saml_validate_url'] = $this->getServerBaseURL().'samlValidate';
00455                                         break;
00456                         }
00457                 }
00458                 phpCAS::traceEnd($this->_server['saml_validate_url'].'?TARGET='.urlencode($this->getURL()));
00459                 return $this->_server['saml_validate_url'].'?TARGET='.urlencode($this->getURL());
00460                 }
00466         function getServerProxyValidateURL()
00467                 { 
00468                 // the URL is build only when needed
00469                 if ( empty($this->_server['proxy_validate_url']) ) {
00470                         switch ($this->getServerVersion()) {
00471                                 case CAS_VERSION_1_0:
00472                                         $this->_server['proxy_validate_url'] = '';
00473                                         break;
00474                                 case CAS_VERSION_2_0:
00475                                         $this->_server['proxy_validate_url'] = $this->getServerBaseURL().'proxyValidate';
00476                                         break;
00477                         }
00478                 }
00479                 //      return $this->_server['proxy_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL()); 
00480                 return $this->_server['proxy_validate_url'].'?service='.urlencode($this->getURL()); 
00481                 }
00482         
00488         function getServerProxyURL()
00489                 { 
00490                 // the URL is build only when needed
00491                 if ( empty($this->_server['proxy_url']) ) {
00492                         switch ($this->getServerVersion()) {
00493                                 case CAS_VERSION_1_0:
00494                                         $this->_server['proxy_url'] = '';
00495                                         break;
00496                                 case CAS_VERSION_2_0:
00497                                         $this->_server['proxy_url'] = $this->getServerBaseURL().'proxy';
00498                                         break;
00499                         }
00500                 }
00501                 return $this->_server['proxy_url']; 
00502                 }
00503         
00509         function getServerLogoutURL()
00510                 { 
00511                 // the URL is build only when needed
00512                 if ( empty($this->_server['logout_url']) ) {
00513                         $this->_server['logout_url'] = $this->getServerBaseURL().'logout';
00514                 }
00515                 return $this->_server['logout_url']; 
00516                 }
00517         
00524         function setServerLogoutURL($url)
00525                 {
00526                 return $this->_server['logout_url'] = $url;
00527                 }
00528         
00532         var $_curl_options = array();
00533         
00537         function setExtraCurlOption($key, $value)
00538                 {
00539                 $this->_curl_options[$key] = $value;
00540                 }
00541         
00547         function isHttps() {
00548                 //if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) ) {
00549                 //0.4.24 by Hinnack
00550                 if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
00551                         return true;
00552                 } else {
00553                         return false;
00554                 }
00555         }
00556         
00557         // ########################################################################
00558         //  CONSTRUCTOR
00559         // ########################################################################
00574         function CASClient(
00575                                            $server_version,
00576                                            $proxy,
00577                                            $server_hostname,
00578                                            $server_port,
00579                                            $server_uri,
00580                                            $start_session = true) {
00581                 
00582                 phpCAS::traceBegin();
00583                 
00584                 // the redirect header() call and DOM parsing code from domxml-php4-php5.php won't work in PHP4 compatibility mode
00585                 if (version_compare(PHP_VERSION,'5','>=') && ini_get('zend.ze1_compatibility_mode')) {
00586                         phpCAS::error('phpCAS cannot support zend.ze1_compatibility_mode. Sorry.');
00587                 }
00588                 $this->_start_session = $start_session;
00589 
00590                 if ($this->_start_session && session_id())
00591                 {
00592                         phpCAS :: error("Another session was started before phpcas. Either disable the session" .
00593                                 " handling for phpcas in the client() call or modify your application to leave" .
00594                                 " session handling to phpcas");                 
00595                 }
00596                 // skip Session Handling for logout requests and if don't want it'
00597                 if ($start_session && !$this->isLogoutRequest())
00598                 {
00599                         phpCAS :: trace("Starting a new session");
00600                         session_start();
00601                 }
00602                 
00603                 
00604                 // are we in proxy mode ?
00605                 $this->_proxy = $proxy;
00606                 
00607                 //check version
00608                 switch ($server_version) {
00609                         case CAS_VERSION_1_0:
00610                                 if ( $this->isProxy() )
00611                                         phpCAS::error('CAS proxies are not supported in CAS '
00612                                                 .$server_version);
00613                                 break;
00614                         case CAS_VERSION_2_0:
00615                                 break;
00616                         case SAML_VERSION_1_1:
00617                                 break;
00618                         default:
00619                                 phpCAS::error('this version of CAS (`'
00620                                         .$server_version
00621                                         .'\') is not supported by phpCAS '
00622                                         .phpCAS::getVersion());
00623                 }
00624                 $this->_server['version'] = $server_version;
00625                 
00626                 // check hostname
00627                 if ( empty($server_hostname) 
00628                                 || !preg_match('/[\.\d\-abcdefghijklmnopqrstuvwxyz]*/',$server_hostname) ) {
00629                         phpCAS::error('bad CAS server hostname (`'.$server_hostname.'\')');
00630                 }
00631                 $this->_server['hostname'] = $server_hostname;
00632                 
00633                 // check port
00634                 if ( $server_port == 0 
00635                         || !is_int($server_port) ) {
00636                         phpCAS::error('bad CAS server port (`'.$server_hostname.'\')');
00637                 }
00638                 $this->_server['port'] = $server_port;
00639                 
00640                 // check URI
00641                 if ( !preg_match('/[\.\d\-_abcdefghijklmnopqrstuvwxyz\/]*/',$server_uri) ) {
00642                         phpCAS::error('bad CAS server URI (`'.$server_uri.'\')');
00643                 }
00644                 // add leading and trailing `/' and remove doubles      
00645                 $server_uri = preg_replace('/\/\//','/','/'.$server_uri.'/');
00646                 $this->_server['uri'] = $server_uri;
00647                 
00648                 // set to callback mode if PgtIou and PgtId CGI GET parameters are provided 
00649                 if ( $this->isProxy() ) {
00650                         $this->setCallbackMode(!empty($_GET['pgtIou'])&&!empty($_GET['pgtId']));
00651                 }
00652                 
00653                 if ( $this->isCallbackMode() ) {
00654                         //callback mode: check that phpCAS is secured
00655                         if ( !$this->isHttps() ) {
00656                                 phpCAS::error('CAS proxies must be secured to use phpCAS; PGT\'s will not be received from the CAS server');
00657                         }
00658                 } else {
00659                         //normal mode: get ticket and remove it from CGI parameters for developpers
00660                         $ticket = (isset($_GET['ticket']) ? $_GET['ticket'] : null);
00661                         switch ($this->getServerVersion()) {
00662                                 case CAS_VERSION_1_0: // check for a Service Ticket
00663                                         if( preg_match('/^ST-/',$ticket) ) {
00664                                                 phpCAS::trace('ST \''.$ticket.'\' found');
00665                                                 //ST present
00666                                                 $this->setST($ticket);
00667                                                 //ticket has been taken into account, unset it to hide it to applications
00668                                                 unset($_GET['ticket']);
00669                                         } else if ( !empty($ticket) ) {
00670                                                 //ill-formed ticket, halt
00671                                                 phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
00672                                         }
00673                                         break;
00674                                 case CAS_VERSION_2_0: // check for a Service or Proxy Ticket
00675                                         if( preg_match('/^[SP]T-/',$ticket) ) {
00676                                                 phpCAS::trace('ST or PT \''.$ticket.'\' found');
00677                                                 $this->setPT($ticket);
00678                                                 unset($_GET['ticket']);
00679                                         } else if ( !empty($ticket) ) {
00680                                                 //ill-formed ticket, halt
00681                                                 phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
00682                                         } 
00683                                         break;
00684                                 case SAML_VERSION_1_1: // SAML just does Service Tickets
00685                                         if( preg_match('/^[SP]T-/',$ticket) ) {
00686                                                 phpCAS::trace('SA \''.$ticket.'\' found');
00687                                                 $this->setSA($ticket);
00688                                                 unset($_GET['ticket']);
00689                                         } else if ( !empty($ticket) ) {
00690                                                 //ill-formed ticket, halt
00691                                                 phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
00692                                         }
00693                                         break;
00694                         }
00695                 }
00696                 phpCAS::traceEnd();
00697         }
00698         
00701         // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00702         // XX                                                                    XX
00703         // XX                           Session Handling                         XX
00704         // XX                                                                    XX
00705         // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00706 
00712         var $_start_session = true;
00713 
00714         function setStartSession($session)
00715         {
00716                 $this->_start_session = session;
00717         }
00718 
00719         function getStartSession($session)
00720         {
00721                 $this->_start_session = session;
00722         }
00723 
00727         function renameSession($ticket)
00728         {
00729                 phpCAS::traceBegin();
00730                 if($this->_start_session){
00731                         if (!empty ($this->_user))
00732                         {
00733                                 $old_session = $_SESSION;
00734                                 session_destroy();
00735                                 // set up a new session, of name based on the ticket
00736                                 $session_id = preg_replace('/[^\w]/', '', $ticket);
00737                                 phpCAS :: trace("Session ID: ".$session_id);
00738                                 session_id($session_id);
00739                                 session_start();
00740                                 phpCAS :: trace("Restoring old session vars");
00741                                 $_SESSION = $old_session;
00742                         } else
00743                         {
00744                                 phpCAS :: error('Session should only be renamed after successfull authentication');
00745                         }
00746                 }else{
00747                         phpCAS :: trace("Skipping session rename since phpCAS is not handling the session.");                   
00748                 }
00749                 phpCAS::traceEnd();             
00750         }       
00751         
00752         // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00753         // XX                                                                    XX
00754         // XX                           AUTHENTICATION                           XX
00755         // XX                                                                    XX
00756         // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00757         
00770         var $_user = '';
00771         
00779         function setUser($user)
00780                 {
00781                 $this->_user = $user;
00782                 }
00783         
00791         function getUser()
00792                 {
00793                 if ( empty($this->_user) ) {
00794                         phpCAS::error('this method should be used only after '.__CLASS__.'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()');
00795                 }
00796                 return $this->_user;
00797                 }
00798         
00799         
00800         
00801         /***********************************************************************************************************************
00802          * Atrributes section
00803          * 
00804          * @author Matthias Crauwels <matthias.crauwels@ugent.be>, Ghent University, Belgium
00805          * 
00806          ***********************************************************************************************************************/
00814         var $_attributes = array();
00815         
00816         function setAttributes($attributes)     
00817                 { $this->_attributes = $attributes; }
00818         
00819         function getAttributes() {
00820                 if ( empty($this->_user) ) { // if no user is set, there shouldn't be any attributes also...
00821                         phpCAS::error('this method should be used only after '.__CLASS__.'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()');
00822                 }
00823                 return $this->_attributes;
00824         }
00825         
00826         function hasAttributes()
00827                 { return !empty($this->_attributes); }
00828         
00829         function hasAttribute($key)
00830                 { return (is_array($this->_attributes) && array_key_exists($key, $this->_attributes)); }
00831         
00832         function getAttribute($key)     {
00833                 if($this->hasAttribute($key)) {
00834                         return $this->_attributes[$key];
00835                 }
00836         }
00837         
00844         function renewAuthentication(){
00845                 phpCAS::traceBegin();
00846                 // Either way, the user is authenticated by CAS
00847                 if( isset( $_SESSION['phpCAS']['auth_checked'] ) )
00848                         unset($_SESSION['phpCAS']['auth_checked']);
00849                 if ( $this->isAuthenticated() ) {
00850                         phpCAS::trace('user already authenticated; renew');
00851                         $this->redirectToCas(false,true);
00852                 } else {
00853                         $this->redirectToCas();
00854                 }
00855                 phpCAS::traceEnd();
00856         }
00857         
00864         function forceAuthentication()
00865                 {
00866                 phpCAS::traceBegin();
00867                 
00868                 if ( $this->isAuthenticated() ) {
00869                         // the user is authenticated, nothing to be done.
00870                         phpCAS::trace('no need to authenticate');
00871                         $res = TRUE;
00872                 } else {
00873                         // the user is not authenticated, redirect to the CAS server
00874                         if (isset($_SESSION['phpCAS']['auth_checked'])) {
00875                                 unset($_SESSION['phpCAS']['auth_checked']);
00876                         }
00877                         $this->redirectToCas(FALSE/* no gateway */);    
00878                         // never reached
00879                         $res = FALSE;
00880                 }
00881                 phpCAS::traceEnd($res);
00882                 return $res;
00883                 }
00884         
00891         var $_cache_times_for_auth_recheck = 0;
00892         
00900         function setCacheTimesForAuthRecheck($n)
00901                 {
00902                 $this->_cache_times_for_auth_recheck = $n;
00903                 }
00904         
00910         function checkAuthentication()
00911                 {
00912                 phpCAS::traceBegin();
00913                 
00914                 if ( $this->isAuthenticated() ) {
00915                         phpCAS::trace('user is authenticated');
00916                         $res = TRUE;
00917                 } else if (isset($_SESSION['phpCAS']['auth_checked'])) {
00918                         // the previous request has redirected the client to the CAS server with gateway=true
00919                         unset($_SESSION['phpCAS']['auth_checked']);
00920                         $res = FALSE;
00921                 } else {
00922                         //        $_SESSION['phpCAS']['auth_checked'] = true;
00923                         //          $this->redirectToCas(TRUE/* gateway */);    
00924                         //          // never reached
00925                         //          $res = FALSE;
00926                         // avoid a check against CAS on every request
00927                         if (! isset($_SESSION['phpCAS']['unauth_count']) )
00928                                 $_SESSION['phpCAS']['unauth_count'] = -2; // uninitialized
00929                         
00930                         if (($_SESSION['phpCAS']['unauth_count'] != -2 && $this->_cache_times_for_auth_recheck == -1) 
00931                                         || ($_SESSION['phpCAS']['unauth_count'] >= 0 && $_SESSION['phpCAS']['unauth_count'] < $this->_cache_times_for_auth_recheck))
00932                         {
00933                                 $res = FALSE;
00934                                 
00935                                 if ($this->_cache_times_for_auth_recheck != -1)
00936                                 {
00937                                         $_SESSION['phpCAS']['unauth_count']++;
00938                                         phpCAS::trace('user is not authenticated (cached for '.$_SESSION['phpCAS']['unauth_count'].' times of '.$this->_cache_times_for_auth_recheck.')');
00939                                 }
00940                                 else
00941                                 {
00942                                         phpCAS::trace('user is not authenticated (cached for until login pressed)');
00943                                 }
00944                         }
00945                         else
00946                         {
00947                                 $_SESSION['phpCAS']['unauth_count'] = 0;
00948                                 $_SESSION['phpCAS']['auth_checked'] = true;
00949                                 phpCAS::trace('user is not authenticated (cache reset)');
00950                                 $this->redirectToCas(TRUE/* gateway */);        
00951                                 // never reached
00952                                 $res = FALSE;
00953                         }
00954                 }
00955                 phpCAS::traceEnd($res);
00956                 return $res;
00957                 }
00958         
00967         function isAuthenticated()
00968                 {
00969                 phpCAS::traceBegin();
00970                 $res = FALSE;
00971                 $validate_url = '';
00972                 
00973                 if ( $this->wasPreviouslyAuthenticated() ) {
00974                         if($this->hasST() || $this->hasPT() || $this->hasSA()){
00975                                 // User has a additional ticket but was already authenticated
00976                                 phpCAS::trace('ticket was present and will be discarded, use renewAuthenticate()');
00977                                 header('Location: '.$this->getURL());
00978                                 phpCAS::log( "Prepare redirect to remove ticket: ".$this->getURL() );
00979                         }else{
00980                                 // the user has already (previously during the session) been
00981                                 // authenticated, nothing to be done.
00982                                 phpCAS::trace('user was already authenticated, no need to look for tickets');
00983                         }
00984                         $res = TRUE;
00985                 }
00986                 else {
00987                         if ( $this->hasST() ) {
00988                                 // if a Service Ticket was given, validate it
00989                                 phpCAS::trace('ST `'.$this->getST().'\' is present');
00990                                 $this->validateST($validate_url,$text_response,$tree_response); // if it fails, it halts
00991                                 phpCAS::trace('ST `'.$this->getST().'\' was validated');
00992                                 if ( $this->isProxy() ) {
00993                                         $this->validatePGT($validate_url,$text_response,$tree_response); // idem
00994                                         phpCAS::trace('PGT `'.$this->getPGT().'\' was validated');
00995                                         $_SESSION['phpCAS']['pgt'] = $this->getPGT();
00996                                 }
00997                                 $_SESSION['phpCAS']['user'] = $this->getUser();
00998                                 $res = TRUE;
00999                         }
01000                         elseif ( $this->hasPT() ) {
01001                                 // if a Proxy Ticket was given, validate it
01002                                 phpCAS::trace('PT `'.$this->getPT().'\' is present');
01003                                 $this->validatePT($validate_url,$text_response,$tree_response); // note: if it fails, it halts
01004                                 phpCAS::trace('PT `'.$this->getPT().'\' was validated');
01005                                 if ( $this->isProxy() ) {
01006                                         $this->validatePGT($validate_url,$text_response,$tree_response); // idem
01007                                         phpCAS::trace('PGT `'.$this->getPGT().'\' was validated');
01008                                         $_SESSION['phpCAS']['pgt'] = $this->getPGT();
01009                                 }
01010                                 $_SESSION['phpCAS']['user'] = $this->getUser();
01011                                 $res = TRUE;
01012                         }
01013                         elseif ( $this->hasSA() ) {
01014                                 // if we have a SAML ticket, validate it.
01015                                 phpCAS::trace('SA `'.$this->getSA().'\' is present');
01016                                 $this->validateSA($validate_url,$text_response,$tree_response); // if it fails, it halts
01017                                 phpCAS::trace('SA `'.$this->getSA().'\' was validated');
01018                                 $_SESSION['phpCAS']['user'] = $this->getUser();
01019                                 $_SESSION['phpCAS']['attributes'] = $this->getAttributes();
01020                                 $res = TRUE;
01021                         }
01022                         else {
01023                                 // no ticket given, not authenticated
01024                                 phpCAS::trace('no ticket found');
01025                         }
01026                         if ($res) {
01027                                 // if called with a ticket parameter, we need to redirect to the app without the ticket so that CAS-ification is transparent to the browser (for later POSTS)
01028                                 // most of the checks and errors should have been made now, so we're safe for redirect without masking error messages.
01029                                 header('Location: '.$this->getURL());
01030                                 phpCAS::log( "Prepare redirect to : ".$this->getURL() );
01031                         }
01032                 }
01033                 
01034                 phpCAS::traceEnd($res);
01035                 return $res;
01036                 }
01037         
01043         function isSessionAuthenticated ()
01044                 {
01045                 return !empty($_SESSION['phpCAS']['user']);
01046                 }
01047         
01058         function wasPreviouslyAuthenticated()
01059                 {
01060                 phpCAS::traceBegin();
01061                 
01062                 if ( $this->isCallbackMode() ) {
01063                         $this->callback();
01064                 }
01065                 
01066                 $auth = FALSE;
01067                 
01068                 if ( $this->isProxy() ) {
01069                         // CAS proxy: username and PGT must be present
01070                         if ( $this->isSessionAuthenticated() && !empty($_SESSION['phpCAS']['pgt']) ) {
01071                                 // authentication already done
01072                                 $this->setUser($_SESSION['phpCAS']['user']);
01073                                 $this->setPGT($_SESSION['phpCAS']['pgt']);
01074                                 phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\', PGT = `'.$_SESSION['phpCAS']['pgt'].'\''); 
01075                                 $auth = TRUE;
01076                         } elseif ( $this->isSessionAuthenticated() && empty($_SESSION['phpCAS']['pgt']) ) {
01077                                 // these two variables should be empty or not empty at the same time
01078                                 phpCAS::trace('username found (`'.$_SESSION['phpCAS']['user'].'\') but PGT is empty');
01079                                 // unset all tickets to enforce authentication
01080                                 unset($_SESSION['phpCAS']);
01081                                 $this->setST('');
01082                                 $this->setPT('');
01083                         } elseif ( !$this->isSessionAuthenticated() && !empty($_SESSION['phpCAS']['pgt']) ) {
01084                                 // these two variables should be empty or not empty at the same time
01085                                 phpCAS::trace('PGT found (`'.$_SESSION['phpCAS']['pgt'].'\') but username is empty'); 
01086                                 // unset all tickets to enforce authentication
01087                                 unset($_SESSION['phpCAS']);
01088                                 $this->setST('');
01089                                 $this->setPT('');
01090                         } else {
01091                                 phpCAS::trace('neither user not PGT found'); 
01092                         }
01093                 } else {
01094                         // `simple' CAS client (not a proxy): username must be present
01095                         if ( $this->isSessionAuthenticated() ) {
01096                                 // authentication already done
01097                                 $this->setUser($_SESSION['phpCAS']['user']);
01098                                 if(isset($_SESSION['phpCAS']['attributes'])){
01099                                         $this->setAttributes($_SESSION['phpCAS']['attributes']);
01100                                 }
01101                                 phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\''); 
01102                                 $auth = TRUE;
01103                         } else {
01104                                 phpCAS::trace('no user found');
01105                         }
01106                 }
01107                 
01108                 phpCAS::traceEnd($auth);
01109                 return $auth;
01110                 }
01111         
01119         function redirectToCas($gateway=false,$renew=false){
01120                 phpCAS::traceBegin();
01121                 $cas_url = $this->getServerLoginURL($gateway,$renew);
01122                 header('Location: '.$cas_url);
01123                 phpCAS::log( "Redirect to : ".$cas_url );
01124                 
01125                 $this->printHTMLHeader($this->getString(CAS_STR_AUTHENTICATION_WANTED));
01126                 
01127                 printf('<p>'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
01128                 $this->printHTMLFooter();
01129                 
01130                 phpCAS::traceExit();
01131                 exit();
01132         }
01133         
01134         
01140         function logout($params) {
01141                 phpCAS::traceBegin();
01142                 $cas_url = $this->getServerLogoutURL();
01143                 $paramSeparator = '?';
01144                 if (isset($params['url'])) {
01145                         $cas_url = $cas_url . $paramSeparator . "url=" . urlencode($params['url']); 
01146                         $paramSeparator = '&';
01147                 }
01148                 if (isset($params['service'])) {
01149                         $cas_url = $cas_url . $paramSeparator . "service=" . urlencode($params['service']); 
01150                 }
01151                 header('Location: '.$cas_url);
01152                 phpCAS::log( "Prepare redirect to : ".$cas_url );
01153                 
01154                 session_unset();
01155                 session_destroy();
01156                 
01157                 $this->printHTMLHeader($this->getString(CAS_STR_LOGOUT));
01158                 printf('<p>'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
01159                 $this->printHTMLFooter();
01160                 
01161                 phpCAS::traceExit();
01162                 exit();
01163         }
01164         
01169         function isLogoutRequest() {
01170                 return !empty($_POST['logoutRequest']);
01171         }
01172         
01177         function isLogoutRequestAllowed() {
01178         }
01179         
01188         function handleLogoutRequests($check_client=true, $allowed_clients=false) {
01189                 phpCAS::traceBegin();
01190                 if (!$this->isLogoutRequest()) {
01191                         phpCAS::log("Not a logout request");
01192                         phpCAS::traceEnd();
01193                         return;
01194                 }
01195                 if(!$this->_start_session){
01196                         phpCAS::log("phpCAS can't handle logout requests if it does not manage the session.");
01197                 }
01198                 phpCAS::log("Logout requested");
01199                 phpCAS::log("SAML REQUEST: ".$_POST['logoutRequest']);
01200                 if ($check_client) {
01201                         if (!$allowed_clients) {
01202                                 $allowed_clients = array( $this->getServerHostname() ); 
01203                         }
01204                         $client_ip = $_SERVER['REMOTE_ADDR'];
01205                         $client = gethostbyaddr($client_ip);
01206                         phpCAS::log("Client: ".$client."/".$client_ip); 
01207                         $allowed = false;
01208                         foreach ($allowed_clients as $allowed_client) {
01209                                 if (($client == $allowed_client) or ($client_ip == $allowed_client)) { 
01210                                         phpCAS::log("Allowed client '".$allowed_client."' matches, logout request is allowed");
01211                                         $allowed = true;
01212                                         break;
01213                                 } else {
01214                                         phpCAS::log("Allowed client '".$allowed_client."' does not match");
01215                                 }
01216                         }
01217                         if (!$allowed) {
01218                                 phpCAS::error("Unauthorized logout request from client '".$client."'");
01219                                 printf("Unauthorized!");
01220                                 phpCAS::traceExit();
01221                                 exit();
01222                         }
01223                 } else {
01224                         phpCAS::log("No access control set");
01225                 }
01226                 // Extract the ticket from the SAML Request
01227                 preg_match("|<samlp:SessionIndex>(.*)</samlp:SessionIndex>|", $_POST['logoutRequest'], $tick, PREG_OFFSET_CAPTURE, 3);
01228                 $wrappedSamlSessionIndex = preg_replace('|<samlp:SessionIndex>|','',$tick[0][0]);
01229                 $ticket2logout = preg_replace('|</samlp:SessionIndex>|','',$wrappedSamlSessionIndex);
01230                 phpCAS::log("Ticket to logout: ".$ticket2logout);
01231                 $session_id = preg_replace('/[^\w]/','',$ticket2logout);
01232                 phpCAS::log("Session id: ".$session_id);
01233                 
01234                 // destroy a possible application session created before phpcas
01235                 if(session_id()){
01236                         session_unset();
01237                         session_destroy();
01238                 }
01239                 // fix session ID
01240                 session_id($session_id);
01241                 $_COOKIE[session_name()]=$session_id;
01242                 $_GET[session_name()]=$session_id;
01243                 
01244                 // Overwrite session
01245                 session_start();        
01246                 session_unset();
01247                 session_destroy();
01248                 printf("Disconnected!");
01249                 phpCAS::traceExit();
01250                 exit();
01251         }
01252         
01255         // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
01256         // XX                                                                    XX
01257         // XX                  BASIC CLIENT FEATURES (CAS 1.0)                   XX
01258         // XX                                                                    XX
01259         // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
01260         
01261         // ########################################################################
01262         //  ST
01263         // ########################################################################
01277         var $_st = '';
01278         
01284         function getST()
01285                 { return $this->_st; }
01286         
01292         function setST($st)
01293                 { $this->_st = $st; }
01294         
01300         function hasST()
01301                 { return !empty($this->_st); }
01302         
01305         // ########################################################################
01306         //  ST VALIDATION
01307         // ########################################################################
01319         var $_cas_server_cert = '';
01320         
01327         var $_cas_server_ca_cert = '';
01328         
01335         var $_no_cas_server_validation = false;
01336         
01342         function setCasServerCert($cert)
01343                 {
01344                 $this->_cas_server_cert = $cert;
01345                 }
01346         
01352         function setCasServerCACert($cert)
01353                 {
01354                 $this->_cas_server_ca_cert = $cert;
01355                 }
01356         
01360         function setNoCasServerValidation()
01361                 {
01362                 $this->_no_cas_server_validation = true;
01363                 }
01364         
01378         function validateST($validate_url,&$text_response,&$tree_response)
01379                 {
01380                 phpCAS::traceBegin();
01381                 // build the URL to validate the ticket
01382                 $validate_url = $this->getServerServiceValidateURL().'&ticket='.$this->getST();
01383                 if ( $this->isProxy() ) {
01384                         // pass the callback url for CAS proxies
01385                         $validate_url .= '&pgtUrl='.urlencode($this->getCallbackURL());
01386                 }
01387                 
01388                 // open and read the URL
01389                 if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
01390                         phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
01391                         $this->authError('ST not validated',
01392                                 $validate_url,
01393                                 TRUE/*$no_response*/);
01394                 }
01395                 
01396                 // analyze the result depending on the version
01397                 switch ($this->getServerVersion()) {
01398                         case CAS_VERSION_1_0:
01399                                 if (preg_match('/^no\n/',$text_response)) {
01400                                         phpCAS::trace('ST has not been validated');
01401                                         $this->authError('ST not validated',
01402                                                 $validate_url,
01403                                                 FALSE/*$no_response*/,
01404                                                 FALSE/*$bad_response*/,
01405                                                 $text_response);
01406                                 }
01407                                 if (!preg_match('/^yes\n/',$text_response)) {
01408                                         phpCAS::trace('ill-formed response');
01409                                         $this->authError('ST not validated',
01410                                                 $validate_url,
01411                                                 FALSE/*$no_response*/,
01412                                                 TRUE/*$bad_response*/,
01413                                                 $text_response);
01414                                 }
01415                                 // ST has been validated, extract the user name
01416                                 $arr = preg_split('/\n/',$text_response);
01417                                 $this->setUser(trim($arr[1]));
01418                                 break;
01419                         case CAS_VERSION_2_0:
01420                                 // read the response of the CAS server into a DOM object
01421                                 if ( !($dom = domxml_open_mem($text_response))) {
01422                                         phpCAS::trace('domxml_open_mem() failed');
01423                                         $this->authError('ST not validated',
01424                                                 $validate_url,
01425                                                 FALSE/*$no_response*/,
01426                                                 TRUE/*$bad_response*/,
01427                                                 $text_response);
01428                                 }
01429                                 // read the root node of the XML tree
01430                                 if ( !($tree_response = $dom->document_element()) ) {
01431                                         phpCAS::trace('document_element() failed');
01432                                         $this->authError('ST not validated',
01433                                                 $validate_url,
01434                                                 FALSE/*$no_response*/,
01435                                                 TRUE/*$bad_response*/,
01436                                                 $text_response);
01437                                 }
01438                                 // insure that tag name is 'serviceResponse'
01439                                 if ( $tree_response->node_name() != 'serviceResponse' ) {
01440                                         phpCAS::trace('bad XML root node (should be `serviceResponse\' instead of `'.$tree_response->node_name().'\'');
01441                                         $this->authError('ST not validated',
01442                                                 $validate_url,
01443                                                 FALSE/*$no_response*/,
01444                                                 TRUE/*$bad_response*/,
01445                                                 $text_response);
01446                                 }
01447                                 if ( sizeof($success_elements = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) {
01448                                         // authentication succeded, extract the user name
01449                                         if ( sizeof($user_elements = $success_elements[0]->get_elements_by_tagname("user")) == 0) {
01450                                                 phpCAS::trace('<authenticationSuccess> found, but no <user>');
01451                                                 $this->authError('ST not validated',
01452                                                         $validate_url,
01453                                                         FALSE/*$no_response*/,
01454                                                         TRUE/*$bad_response*/,
01455                                                         $text_response);
01456                                         }
01457                                         $user = trim($user_elements[0]->get_content());
01458                                         phpCAS::trace('user = `'.$user);
01459                                         $this->setUser($user);
01460                                         
01461                                 } else if ( sizeof($failure_elements = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) {
01462                                         phpCAS::trace('<authenticationFailure> found');
01463                                         // authentication failed, extract the error code and message
01464                                         $this->authError('ST not validated',
01465                                                 $validate_url,
01466                                                 FALSE/*$no_response*/,
01467                                                 FALSE/*$bad_response*/,
01468                                                 $text_response,
01469                                                 $failure_elements[0]->get_attribute('code')/*$err_code*/,
01470                                                 trim($failure_elements[0]->get_content())/*$err_msg*/);
01471                                 } else {
01472                                         phpCAS::trace('neither <authenticationSuccess> nor <authenticationFailure> found');
01473                                         $this->authError('ST not validated',
01474                                                 $validate_url,
01475                                                 FALSE/*$no_response*/,
01476                                                 TRUE/*$bad_response*/,
01477                                                 $text_response);
01478                                 }
01479                                 break;
01480                 }
01481                 $this->renameSession($this->getST());
01482                 // at this step, ST has been validated and $this->_user has been set,
01483                 phpCAS::traceEnd(TRUE);
01484                 return TRUE;
01485                 }
01486         
01487         // ########################################################################
01488         //  SAML VALIDATION
01489         // ########################################################################
01508         function validateSA($validate_url,&$text_response,&$tree_response)
01509                 {
01510                 phpCAS::traceBegin();
01511                 
01512                 // build the URL to validate the ticket
01513                 $validate_url = $this->getServerSamlValidateURL();
01514                 
01515                 // open and read the URL
01516                 if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
01517                         phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
01518                         $this->authError('SA not validated', $validate_url, TRUE/*$no_response*/);
01519                 }
01520                 
01521                 phpCAS::trace('server version: '.$this->getServerVersion());
01522                 
01523                 // analyze the result depending on the version
01524                 switch ($this->getServerVersion()) {
01525                         case SAML_VERSION_1_1:
01526                                 
01527                                 // read the response of the CAS server into a DOM object
01528                                 if ( !($dom = domxml_open_mem($text_response))) {
01529                                         phpCAS::trace('domxml_open_mem() failed');
01530                                         $this->authError('SA not validated',
01531                                                 $validate_url,
01532                                                 FALSE/*$no_response*/,
01533                                                 TRUE/*$bad_response*/,
01534                                                 $text_response);
01535                                 }
01536                                 // read the root node of the XML tree
01537                                 if ( !($tree_response = $dom->document_element()) ) {
01538                                         phpCAS::trace('document_element() failed');
01539                                         $this->authError('SA not validated',
01540                                                 $validate_url,
01541                                                 FALSE/*$no_response*/,
01542                                                 TRUE/*$bad_response*/,
01543                                                 $text_response);
01544                                 }
01545                                 // insure that tag name is 'Envelope'
01546                                 if ( $tree_response->node_name() != 'Envelope' ) {
01547                                         phpCAS::trace('bad XML root node (should be `Envelope\' instead of `'.$tree_response->node_name().'\'');
01548                                         $this->authError('SA not validated',
01549                                                 $validate_url,
01550                                                 FALSE/*$no_response*/,
01551                                                 TRUE/*$bad_response*/,
01552                                                 $text_response);
01553                                 }
01554                                 // check for the NameIdentifier tag in the SAML response
01555                                 if ( sizeof($success_elements = $tree_response->get_elements_by_tagname("NameIdentifier")) != 0) {
01556                                         phpCAS::trace('NameIdentifier found');
01557                                         $user = trim($success_elements[0]->get_content());
01558                                         phpCAS::trace('user = `'.$user.'`');
01559                                         $this->setUser($user);
01560                                         $this->setSessionAttributes($text_response);
01561                                 } else {
01562                                         phpCAS::trace('no <NameIdentifier> tag found in SAML payload');
01563                                         $this->authError('SA not validated',
01564                                                 $validate_url,
01565                                                 FALSE/*$no_response*/,
01566                                                 TRUE/*$bad_response*/,
01567                                                 $text_response);
01568                                 }
01569                                 break;
01570                 }
01571                 $this->renameSession($this->getSA());
01572                 // at this step, ST has been validated and $this->_user has been set,
01573                 phpCAS::traceEnd(TRUE);
01574                 return TRUE;
01575                 }
01576         
01586         function setSessionAttributes($text_response)
01587                 {
01588                 phpCAS::traceBegin();
01589                 
01590                 $result = FALSE;
01591                 
01592                 if (isset($_SESSION[SAML_ATTRIBUTES])) {
01593                         phpCAS::trace("session attrs already set.");  //testbml - do we care?
01594                 }
01595                 
01596                 $attr_array = array();
01597                 
01598                 if (($dom = domxml_open_mem($text_response))) {
01599                         $xPath = $dom->xpath_new_context();
01600                         $xPath->xpath_register_ns('samlp', 'urn:oasis:names:tc:SAML:1.0:protocol');
01601                         $xPath->xpath_register_ns('saml', 'urn:oasis:names:tc:SAML:1.0:assertion');
01602                         $nodelist = $xPath->xpath_eval("//saml:Attribute");
01603                         if($nodelist){
01604                                 $attrs = $nodelist->nodeset;
01605                                 foreach($attrs as $attr){
01606                                         $xres = $xPath->xpath_eval("saml:AttributeValue", $attr);
01607                                         $name = $attr->get_attribute("AttributeName");
01608                                         $value_array = array();
01609                                         foreach($xres->nodeset as $node){
01610                                                 $value_array[] = $node->get_content();
01611                                         }
01612                                         $attr_array[$name] = $value_array;
01613                                 }
01614                                 $_SESSION[SAML_ATTRIBUTES] = $attr_array;
01615                                 // UGent addition...
01616                                 foreach($attr_array as $attr_key => $attr_value) {
01617                                         if(count($attr_value) > 1) {
01618                                                 $this->_attributes[$attr_key] = $attr_value;
01619                                                 phpCAS::trace("* " . $attr_key . "=" . $attr_value);
01620                                         }
01621                                         else {
01622                                                 $this->_attributes[$attr_key] = $attr_value[0];
01623                                                 phpCAS::trace("* " . $attr_key . "=" . $attr_value[0]);
01624                                         }
01625                                 }
01626                                 $result = TRUE;
01627                         }else{
01628                                 phpCAS::trace("SAML Attributes are empty");
01629                                 $result = FALSE;
01630                         }
01631                 }
01632                 phpCAS::traceEnd($result);
01633                 return $result;
01634                 }
01635         
01638         // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
01639         // XX                                                                    XX
01640         // XX                     PROXY FEATURES (CAS 2.0)                       XX
01641         // XX                                                                    XX
01642         // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
01643         
01644         // ########################################################################
01645         //  PROXYING
01646         // ########################################################################
01658         var $_proxy;
01659         
01667         function isProxy()
01668                 {
01669                 return $this->_proxy;
01670                 }
01671         
01673         // ########################################################################
01674         //  PGT
01675         // ########################################################################
01688         var $_pgt = '';
01689         
01695         function getPGT()
01696                 { return $this->_pgt; }
01697         
01703         function setPGT($pgt)
01704                 { $this->_pgt = $pgt; }
01705         
01711         function hasPGT()
01712                 { return !empty($this->_pgt); }
01713         
01716         // ########################################################################
01717         //  CALLBACK MODE
01718         // ########################################################################
01736         var $_callback_mode = FALSE;
01737         
01745         function setCallbackMode($callback_mode)
01746                 {
01747                 $this->_callback_mode = $callback_mode;
01748                 }
01749         
01758         function isCallbackMode()
01759                 {
01760                 return $this->_callback_mode;
01761                 }
01762         
01771         var $_callback_url = '';
01772         
01782         function getCallbackURL()
01783                 {
01784                 // the URL is built when needed only
01785                 if ( empty($this->_callback_url) ) {
01786                         $final_uri = '';
01787                         // remove the ticket if present in the URL
01788                         $final_uri = 'https://';
01789                         /* replaced by Julien Marchal - v0.4.6
01790                          * $this->uri .= $_SERVER['SERVER_NAME'];
01791                          */
01792                         if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){
01793                                 /* replaced by teedog - v0.4.12
01794                                  * $final_uri .= $_SERVER['SERVER_NAME'];
01795                                  */
01796                                 if (empty($_SERVER['SERVER_NAME'])) {
01797                                         $final_uri .= $_SERVER['HTTP_HOST'];
01798                                 } else {
01799                                         $final_uri .= $_SERVER['SERVER_NAME'];
01800                                 }
01801                         } else {
01802                                 $final_uri .= $_SERVER['HTTP_X_FORWARDED_SERVER'];
01803                         }
01804                         if ( ($this->isHttps() && $_SERVER['SERVER_PORT']!=443)
01805                                         || (!$this->isHttps() && $_SERVER['SERVER_PORT']!=80) ) {
01806                                 $final_uri .= ':';
01807                                 $final_uri .= $_SERVER['SERVER_PORT'];
01808                         }
01809                         $request_uri = $_SERVER['REQUEST_URI'];
01810                         $request_uri = preg_replace('/\?.*$/','',$request_uri);
01811                         $final_uri .= $request_uri;
01812                         $this->setCallbackURL($final_uri);
01813                 }
01814                 return $this->_callback_url;
01815                 }
01816         
01824         function setCallbackURL($url)
01825                 {
01826                 return $this->_callback_url = $url;
01827                 }
01828         
01835         function callback()
01836                 {
01837                 phpCAS::traceBegin();
01838                 $this->printHTMLHeader('phpCAS callback');
01839                 $pgt_iou = $_GET['pgtIou'];
01840                 $pgt = $_GET['pgtId'];
01841                 phpCAS::trace('Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\')');
01842                 echo '<p>Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\').</p>';
01843                 $this->storePGT($pgt,$pgt_iou);
01844                 $this->printHTMLFooter();
01845                 phpCAS::traceExit();
01846                 exit();
01847                 }
01848         
01851         // ########################################################################
01852         //  PGT STORAGE
01853         // ########################################################################
01867         var $_pgt_storage = null;
01868         
01875         function initPGTStorage()
01876                 {
01877                 // if no SetPGTStorageXxx() has been used, default to file
01878                 if ( !is_object($this->_pgt_storage) ) {
01879                         $this->setPGTStorageFile();
01880                 }
01881                 
01882                 // initializes the storage
01883                 $this->_pgt_storage->init();
01884                 }
01885         
01894         function storePGT($pgt,$pgt_iou)
01895                 {
01896                 // ensure that storage is initialized
01897                 $this->initPGTStorage();
01898                 // writes the PGT
01899                 $this->_pgt_storage->write($pgt,$pgt_iou);
01900                 }
01901         
01911         function loadPGT($pgt_iou)
01912                 {
01913                 // ensure that storage is initialized
01914                 $this->initPGTStorage();
01915                 // read the PGT
01916                 return $this->_pgt_storage->read($pgt_iou);
01917                 }
01918         
01928         function setPGTStorageFile($format='',
01929                 $path='')
01930                 {
01931                 // check that the storage has not already been set
01932                 if ( is_object($this->_pgt_storage) ) {
01933                         phpCAS::error('PGT storage already defined');
01934                 }
01935                 
01936                 // create the storage object
01937                 $this->_pgt_storage = new PGTStorageFile($this,$format,$path);
01938                 }
01939         
01957         function setPGTStorageDB($user,
01958                                                          $password,
01959                                                          $database_type,
01960                                                          $hostname,
01961                                                          $port,
01962                                                          $database,
01963                                                          $table)
01964                 {
01965                 // check that the storage has not already been set
01966                 if ( is_object($this->_pgt_storage) ) {
01967                         phpCAS::error('PGT storage already defined');
01968                 }
01969                 
01970                 // warn the user that he should use file storage...
01971                 trigger_error('PGT storage into database is an experimental feature, use at your own risk',E_USER_WARNING);
01972                 
01973                 // create the storage object
01974                 $this->_pgt_storage = new PGTStorageDB($this,$user,$password,$database_type,$hostname,$port,$database,$table);
01975                 }
01976         
01977         // ########################################################################
01978         //  PGT VALIDATION
01979         // ########################################################################
01993         function validatePGT(&$validate_url,$text_response,$tree_response)
01994                 {
01995                 // here cannot use phpCAS::traceBegin(); alongside domxml-php4-to-php5.php
01996                 phpCAS::log('start validatePGT()');
01997                 if ( sizeof($arr = $tree_response->get_elements_by_tagname("proxyGrantingTicket")) == 0) {
01998                         phpCAS::trace('<proxyGrantingTicket> not found');
01999                         // authentication succeded, but no PGT Iou was transmitted
02000                         $this->authError('Ticket validated but no PGT Iou transmitted',
02001                                 $validate_url,
02002                                 FALSE/*$no_response*/,
02003                                 FALSE/*$bad_response*/,
02004                                 $text_response);
02005                 } else {
02006                         // PGT Iou transmitted, extract it
02007                         $pgt_iou = trim($arr[0]->get_content());
02008                         $pgt = $this->loadPGT($pgt_iou);
02009                         if ( $pgt == FALSE ) {
02010                                 phpCAS::trace('could not load PGT');
02011                                 $this->authError('PGT Iou was transmitted but PGT could not be retrieved',
02012                                         $validate_url,
02013                                         FALSE/*$no_response*/,
02014                                         FALSE/*$bad_response*/,
02015                                         $text_response);
02016                         }
02017                         $this->setPGT($pgt);
02018                 }
02019                 // here, cannot use     phpCAS::traceEnd(TRUE); alongside domxml-php4-to-php5.php
02020                 phpCAS::log('end validatePGT()');
02021                 return TRUE;
02022                 }
02023         
02024         // ########################################################################
02025         //  PGT VALIDATION
02026         // ########################################################################
02027         
02039         function retrievePT($target_service,&$err_code,&$err_msg)
02040                 {
02041                 phpCAS::traceBegin();
02042                 
02043                 // by default, $err_msg is set empty and $pt to TRUE. On error, $pt is
02044                 // set to false and $err_msg to an error message. At the end, if $pt is FALSE 
02045                 // and $error_msg is still empty, it is set to 'invalid response' (the most
02046                 // commonly encountered error).
02047                 $err_msg = '';
02048                 
02049                 // build the URL to retrieve the PT
02050                 //      $cas_url = $this->getServerProxyURL().'?targetService='.preg_replace('/&/','%26',$target_service).'&pgt='.$this->getPGT();
02051                 $cas_url = $this->getServerProxyURL().'?targetService='.urlencode($target_service).'&pgt='.$this->getPGT();
02052                 
02053                 // open and read the URL
02054                 if ( !$this->readURL($cas_url,''/*cookies*/,$headers,$cas_response,$err_msg) ) {
02055                         phpCAS::trace('could not open URL \''.$cas_url.'\' to validate ('.$err_msg.')');
02056                         $err_code = PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE;
02057                         $err_msg = 'could not retrieve PT (no response from the CAS server)';
02058                         phpCAS::traceEnd(FALSE);
02059                         return FALSE;
02060                 }
02061                 
02062                 $bad_response = FALSE;
02063                 
02064                 if ( !$bad_response ) {
02065                         // read the response of the CAS server into a DOM object
02066                         if ( !($dom = @domxml_open_mem($cas_response))) {
02067                                 phpCAS::trace('domxml_open_mem() failed');
02068                                 // read failed
02069                                 $bad_response = TRUE;
02070                         } 
02071                 }
02072                 
02073                 if ( !$bad_response ) {
02074                         // read the root node of the XML tree
02075                         if ( !($root = $dom->document_element()) ) {
02076                                 phpCAS::trace('document_element() failed');
02077                                 // read failed
02078                                 $bad_response = TRUE;
02079                         } 
02080                 }
02081                 
02082                 if ( !$bad_response ) {
02083                         // insure that tag name is 'serviceResponse'
02084                         if ( $root->node_name() != 'serviceResponse' ) {
02085                                 phpCAS::trace('node_name() failed');
02086                                 // bad root node
02087                                 $bad_response = TRUE;
02088                         } 
02089                 }
02090                 
02091                 if ( !$bad_response ) {
02092                         // look for a proxySuccess tag
02093                         if ( sizeof($arr = $root->get_elements_by_tagname("proxySuccess")) != 0) {
02094                                 // authentication succeded, look for a proxyTicket tag
02095                                 if ( sizeof($arr = $root->get_elements_by_tagname("proxyTicket")) != 0) {
02096                                         $err_code = PHPCAS_SERVICE_OK;
02097                                         $err_msg = '';
02098                                         phpCAS::trace('original PT: '.trim($arr[0]->get_content()));
02099                                         $pt = trim($arr[0]->get_content());
02100                                         phpCAS::traceEnd($pt);
02101                                         return $pt;
02102                                 } else {
02103                                         phpCAS::trace('<proxySuccess> was found, but not <proxyTicket>');
02104                                 }
02105                         } 
02106                         // look for a proxyFailure tag
02107                         else if ( sizeof($arr = $root->get_elements_by_tagname("proxyFailure")) != 0) {
02108                                 // authentication failed, extract the error
02109                                 $err_code = PHPCAS_SERVICE_PT_FAILURE;
02110                                 $err_msg = 'PT retrieving failed (code=`'
02111                                         .$arr[0]->get_attribute('code')
02112                                         .'\', message=`'
02113                                         .trim($arr[0]->get_content())
02114                                         .'\')';
02115                                 phpCAS::traceEnd(FALSE);
02116                                 return FALSE;
02117                         } else {
02118                                 phpCAS::trace('neither <proxySuccess> nor <proxyFailure> found');
02119                         }
02120                 }
02121                 
02122                 // at this step, we are sure that the response of the CAS server was ill-formed
02123                 $err_code = PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE;
02124                 $err_msg = 'Invalid response from the CAS server (response=`'.$cas_response.'\')';
02125                 
02126                 phpCAS::traceEnd(FALSE);
02127                 return FALSE;
02128                 }
02129         
02130         // ########################################################################
02131         // ACCESS TO EXTERNAL SERVICES
02132         // ########################################################################
02133         
02149         function readURL($url,$cookies,&$headers,&$body,&$err_msg)
02150                 {
02151                 phpCAS::traceBegin();
02152                 $headers = '';
02153                 $body = '';
02154                 $err_msg = '';
02155                 
02156                 $res = TRUE;
02157                 
02158                 // initialize the CURL session
02159                 $ch = curl_init($url);
02160                 
02161                 if (version_compare(PHP_VERSION,'5.1.3','>=')) {
02162                         //only avaible in php5
02163                         curl_setopt_array($ch, $this->_curl_options);
02164                 } else {
02165                         foreach ($this->_curl_options as $key => $value) {
02166                                 curl_setopt($ch, $key, $value);
02167                         }
02168                 }
02169                 
02170                 if ($this->_cas_server_cert == '' && $this->_cas_server_ca_cert == '' && !$this->_no_cas_server_validation) {
02171                         phpCAS::error('one of the methods phpCAS::setCasServerCert(), phpCAS::setCasServerCACert() or phpCAS::setNoCasServerValidation() must be called.');
02172                 }
02173                 if ($this->_cas_server_cert != '' && $this->_cas_server_ca_cert != '') {
02174                         // This branch added by IDMS. Seems phpCAS implementor got a bit confused about the curl options CURLOPT_SSLCERT and CURLOPT_CAINFO
02175                         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
02176                         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
02177                         curl_setopt($ch, CURLOPT_SSLCERT, $this->_cas_server_cert);
02178                         curl_setopt($ch, CURLOPT_CAINFO, $this->_cas_server_ca_cert);
02179                         curl_setopt($ch, CURLOPT_VERBOSE, '1');
02180                         phpCAS::trace('CURL: Set all required opts for mutual authentication ------');
02181                 } else if ($this->_cas_server_cert != '' ) {
02182                         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
02183                         curl_setopt($ch, CURLOPT_SSLCERT, $this->_cas_server_cert);
02184                 } else if ($this->_cas_server_ca_cert != '') {
02185                         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
02186                         curl_setopt($ch, CURLOPT_CAINFO, $this->_cas_server_ca_cert);
02187                 } else {
02188                         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
02189                         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
02190                 }
02191                 
02192                 // return the CURL output into a variable
02193                 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
02194                 // get the HTTP header with a callback
02195                 $this->_curl_headers = array(); // empty the headers array
02196                 curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, '_curl_read_headers'));
02197                 // add cookies headers
02198                 if ( is_array($cookies) ) {
02199                         curl_setopt($ch,CURLOPT_COOKIE,implode(';',$cookies));
02200                 }
02201                 // add extra stuff if SAML
02202                 if ($this->hasSA()) {
02203                         $more_headers = array ("soapaction: http://www.oasis-open.org/committees/security",
02204                                 "cache-control: no-cache",
02205                                 "pragma: no-cache",
02206                                 "accept: text/xml",
02207                                 "connection: keep-alive",
02208                         "content-type: text/xml");
02209                         
02210                         curl_setopt($ch, CURLOPT_HTTPHEADER, $more_headers);
02211                         curl_setopt($ch, CURLOPT_POST, 1);
02212                         $data = $this->buildSAMLPayload();
02213                         //phpCAS::trace('SAML Payload: '.print_r($data, TRUE));
02214                         curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
02215                 }
02216                 // perform the query
02217                 $buf = curl_exec ($ch);
02218                 //phpCAS::trace('CURL: Call completed. Response body is: \''.$buf.'\'');
02219                 if ( $buf === FALSE ) {
02220                         phpCAS::trace('curl_exec() failed');
02221                         $err_msg = 'CURL error #'.curl_errno($ch).': '.curl_error($ch);
02222                         //phpCAS::trace('curl error: '.$err_msg);
02223                         // close the CURL session
02224                         curl_close ($ch);
02225                         $res = FALSE;
02226                 } else {
02227                         // close the CURL session
02228                         curl_close ($ch);
02229                         
02230                         $headers = $this->_curl_headers;
02231                         $body = $buf;
02232                 }
02233                 
02234                 phpCAS::traceEnd($res);
02235                 return $res;
02236                 }
02237         
02245         function buildSAMLPayload()
02246                 {
02247                 phpCAS::traceBegin();
02248                 
02249                 //get the ticket
02250                 $sa = $this->getSA();
02251                 //phpCAS::trace("SA: ".$sa);
02252                 
02253                 $body=SAML_SOAP_ENV.SAML_SOAP_BODY.SAMLP_REQUEST.SAML_ASSERTION_ARTIFACT.$sa.SAML_ASSERTION_ARTIFACT_CLOSE.SAMLP_REQUEST_CLOSE.SAML_SOAP_BODY_CLOSE.SAML_SOAP_ENV_CLOSE;
02254                 
02255                 phpCAS::traceEnd($body);
02256                 return ($body);
02257                 }
02258         
02262         var $_curl_headers = array();
02263         function _curl_read_headers($ch, $header)
02264                 {
02265                 $this->_curl_headers[] = $header;
02266                 return strlen($header);
02267                 }
02268         
02284         function serviceWeb($url,&$err_code,&$output)
02285                 {
02286                 phpCAS::traceBegin();
02287                 $cookies = array();
02288                 // at first retrieve a PT
02289                 $pt = $this->retrievePT($url,$err_code,$output);
02290                 
02291                 $res = TRUE;
02292                 
02293                 // test if PT was retrieved correctly
02294                 if ( !$pt ) {
02295                         // note: $err_code and $err_msg are filled by CASClient::retrievePT()
02296                         phpCAS::trace('PT was not retrieved correctly');
02297                         $res = FALSE;
02298                 } else {
02299                         // add cookies if necessary
02300                         if ( isset($_SESSION['phpCAS']['services'][$url]['cookies']) && 
02301                                         is_array($_SESSION['phpCAS']['services'][$url]['cookies']) ) {
02302                                 foreach ( $_SESSION['phpCAS']['services'][$url]['cookies'] as $name => $val ) { 
02303                                         $cookies[] = $name.'='.$val;
02304                                 }
02305                         }
02306                         
02307                         // build the URL including the PT
02308                         if ( strstr($url,'?') === FALSE ) {
02309                                 $service_url = $url.'?ticket='.$pt;
02310                         } else {
02311                                 $service_url = $url.'&ticket='.$pt;
02312                         }
02313                         
02314                         phpCAS::trace('reading URL`'.$service_url.'\'');
02315                         if ( !$this->readURL($service_url,$cookies,$headers,$output,$err_msg) ) {
02316                                 phpCAS::trace('could not read URL`'.$service_url.'\'');
02317                                 $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
02318                                 // give an error message
02319                                 $output = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE),
02320                                         $service_url,
02321                                         $err_msg);
02322                                 $res = FALSE;
02323                         } else {
02324                                 // URL has been fetched, extract the cookies
02325                                 phpCAS::trace('URL`'.$service_url.'\' has been read, storing cookies:');
02326                                 foreach ( $headers as $header ) {
02327                                         // test if the header is a cookie
02328                                         if ( preg_match('/^Set-Cookie:/',$header) ) {
02329                                                 // the header is a cookie, remove the beginning
02330                                                 $header_val = preg_replace('/^Set-Cookie: */','',$header);
02331                                                 // extract interesting information
02332                                                 $name_val = strtok($header_val,'; ');
02333                                                 // extract the name and the value of the cookie
02334                                                 $cookie_name = strtok($name_val,'=');
02335                                                 $cookie_val = strtok('=');
02336                                                 // store the cookie 
02337                                                 $_SESSION['phpCAS']['services'][$url]['cookies'][$cookie_name] = $cookie_val;
02338                                                 phpCAS::trace($cookie_name.' -> '.$cookie_val);
02339                                         }
02340                                 }
02341                         }
02342                 }
02343                 
02344                 phpCAS::traceEnd($res);
02345                 return $res;
02346                 }
02347         
02367         function serviceMail($url,$service,$flags,&$err_code,&$err_msg,&$pt)
02368                 {
02369                 phpCAS::traceBegin();
02370                 // at first retrieve a PT
02371                 $pt = $this->retrievePT($service,$err_code,$output);
02372                 
02373                 $stream = FALSE;
02374                 
02375                 // test if PT was retrieved correctly
02376                 if ( !$pt ) {
02377                         // note: $err_code and $err_msg are filled by CASClient::retrievePT()
02378                         phpCAS::trace('PT was not retrieved correctly');
02379                 } else {
02380                         phpCAS::trace('opening IMAP URL `'.$url.'\'...');
02381                         $stream = @imap_open($url,$this->getUser(),$pt,$flags);
02382                         if ( !$stream ) {
02383                                 phpCAS::trace('could not open URL');
02384                                 $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
02385                                 // give an error message
02386                                 $err_msg = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE),
02387                                         $service_url,
02388                                         var_export(imap_errors(),TRUE));
02389                                 $pt = FALSE;
02390                                 $stream = FALSE;
02391                         } else {
02392                                 phpCAS::trace('ok');
02393                         }
02394                 }
02395                 
02396                 phpCAS::traceEnd($stream);
02397                 return $stream;
02398                 }
02399         
02402         // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
02403         // XX                                                                    XX
02404         // XX                  PROXIED CLIENT FEATURES (CAS 2.0)                 XX
02405         // XX                                                                    XX
02406         // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
02407         
02408         // ########################################################################
02409         //  PT
02410         // ########################################################################
02424         var $_pt = '';
02425         
02431         function getPT()
02432                 {
02433                 //      return 'ST'.substr($this->_pt, 2);
02434                 return $this->_pt;
02435                 }
02436         
02442         function setPT($pt)
02443                 { $this->_pt = $pt; }
02444         
02450         function hasPT()
02451                 { return !empty($this->_pt); }
02457         function getSA()
02458                 { return 'ST'.substr($this->_sa, 2); }
02459         
02465         function setSA($sa)
02466                 { $this->_sa = $sa; }
02467         
02473         function hasSA()
02474                 { return !empty($this->_sa); }
02475         
02477         // ########################################################################
02478         //  PT VALIDATION
02479         // ########################################################################
02492         function validatePT(&$validate_url,&$text_response,&$tree_response)
02493                 {
02494                 phpCAS::traceBegin();
02495                 // build the URL to validate the ticket
02496                 $validate_url = $this->getServerProxyValidateURL().'&ticket='.$this->getPT();
02497                 
02498                 if ( $this->isProxy() ) {
02499                         // pass the callback url for CAS proxies
02500                         $validate_url .= '&pgtUrl='.urlencode($this->getCallbackURL());
02501                 }
02502                 
02503                 // open and read the URL
02504                 if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
02505                         phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
02506                         $this->authError('PT not validated',
02507                                 $validate_url,
02508                                 TRUE/*$no_response*/);
02509                 }
02510                 
02511                 // read the response of the CAS server into a DOM object
02512                 if ( !($dom = domxml_open_mem($text_response))) {
02513                         // read failed
02514                         $this->authError('PT not validated',
02515                                 $validate_url,
02516                                 FALSE/*$no_response*/,
02517                                 TRUE/*$bad_response*/,
02518                                 $text_response);
02519                 }
02520                 // read the root node of the XML tree
02521                 if ( !($tree_response = $dom->document_element()) ) {
02522                         // read failed
02523                         $this->authError('PT not validated',
02524                                 $validate_url,
02525                                 FALSE/*$no_response*/,
02526                                 TRUE/*$bad_response*/,
02527                                 $text_response);
02528                 }
02529                 // insure that tag name is 'serviceResponse'
02530                 if ( $tree_response->node_name() != 'serviceResponse' ) {
02531                         // bad root node
02532                         $this->authError('PT not validated',
02533                                 $validate_url,
02534                                 FALSE/*$no_response*/,
02535                                 TRUE/*$bad_response*/,
02536                                 $text_response);
02537                 }
02538                 if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) {
02539                         // authentication succeded, extract the user name
02540                         if ( sizeof($arr = $tree_response->get_elements_by_tagname("user")) == 0) {
02541                                 // no user specified => error
02542                                 $this->authError('PT not validated',
02543                                         $validate_url,
02544                                         FALSE/*$no_response*/,
02545                                         TRUE/*$bad_response*/,
02546                                         $text_response);
02547                         }
02548                         $this->setUser(trim($arr[0]->get_content()));
02549                         
02550                 } else if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) {
02551                         // authentication succeded, extract the error code and message
02552                         $this->authError('PT not validated',
02553                                 $validate_url,
02554                                 FALSE/*$no_response*/,
02555                                 FALSE/*$bad_response*/,
02556                                 $text_response,
02557                                 $arr[0]->get_attribute('code')/*$err_code*/,
02558                                 trim($arr[0]->get_content())/*$err_msg*/);
02559                 } else {
02560                         $this->authError('PT not validated',
02561                                 $validate_url,  
02562                                 FALSE/*$no_response*/,
02563                                 TRUE/*$bad_response*/,
02564                                 $text_response);
02565                 }
02566                 
02567                 $this->renameSession($this->getPT());
02568                 // at this step, PT has been validated and $this->_user has been set,
02569                 
02570                 phpCAS::traceEnd(TRUE);
02571                 return TRUE;
02572                 }
02573         
02576         // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
02577         // XX                                                                    XX
02578         // XX                               MISC                                 XX
02579         // XX                                                                    XX
02580         // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
02581         
02587         // ########################################################################
02588         //  URL
02589         // ########################################################################
02597         var $_url = '';
02598         
02607         function getURL()
02608                 {
02609                 phpCAS::traceBegin();
02610                 // the URL is built when needed only
02611                 if ( empty($this->_url) ) {
02612                         $final_uri = '';
02613                         // remove the ticket if present in the URL
02614                         $final_uri = ($this->isHttps()) ? 'https' : 'http';
02615                         $final_uri .= '://';
02616                         /* replaced by Julien Marchal - v0.4.6
02617                          * $this->_url .= $_SERVER['SERVER_NAME'];
02618                          */
02619                         if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){
02620                                 /* replaced by teedog - v0.4.12
02621                                  * $this->_url .= $_SERVER['SERVER_NAME'];
02622                                  */
02623                                 if (empty($_SERVER['SERVER_NAME'])) {
02624                                         $server_name = $_SERVER['HTTP_HOST'];
02625                                 } else {
02626                                         $server_name = $_SERVER['SERVER_NAME'];
02627                                 }
02628                         } else {
02629                                 $server_name = $_SERVER['HTTP_X_FORWARDED_SERVER'];
02630                         }
02631                         $final_uri .= $server_name;
02632                         if (!strpos($server_name, ':')) {
02633                                 if ( ($this->isHttps() && $_SERVER['SERVER_PORT']!=443)
02634                                                 || (!$this->isHttps() && $_SERVER['SERVER_PORT']!=80) ) {
02635                                         $final_uri .= ':';
02636                                         $final_uri .= $_SERVER['SERVER_PORT'];
02637                                 }
02638                         }
02639                         
02640                         $request_uri    = explode('?', $_SERVER['REQUEST_URI'], 2);
02641                         $final_uri              .= $request_uri[0];
02642                         
02643                         if (isset($request_uri[1]) && $request_uri[1])
02644                         {
02645                                 $query_string   = $this->removeParameterFromQueryString('ticket', $request_uri[1]);
02646                                 
02647                                 // If the query string still has anything left, append it to the final URI
02648                                 if ($query_string !== '')
02649                                         $final_uri      .= "?$query_string";
02650                                 
02651                         }
02652                         
02653                         phpCAS::trace("Final URI: $final_uri");
02654                         $this->setURL($final_uri);
02655                 }
02656                 phpCAS::traceEnd($this->_url);
02657                 return $this->_url;
02658         }
02659         
02660 
02661                 
02671         function removeParameterFromQueryString($parameterName, $queryString)
02672         {
02673                 $parameterName  = preg_quote($parameterName);
02674                 return preg_replace("/&$parameterName(=[^&]*)?|^$parameterName(=[^&]*)?&?/", '', $queryString);
02675         }
02676 
02677         
02685         function setURL($url)
02686                 {
02687                 $this->_url = $url;
02688                 }
02689         
02690         // ########################################################################
02691         //  AUTHENTICATION ERROR HANDLING
02692         // ########################################################################
02708         function authError($failure,$cas_url,$no_response,$bad_response='',$cas_response='',$err_code='',$err_msg='')
02709                 {
02710                 phpCAS::traceBegin();
02711                 
02712                 $this->printHTMLHeader($this->getString(CAS_STR_AUTHENTICATION_FAILED));
02713                 printf($this->getString(CAS_STR_YOU_WERE_NOT_AUTHENTICATED),htmlentities($this->getURL()),$_SERVER['SERVER_ADMIN']);
02714                 phpCAS::trace('CAS URL: '.$cas_url);
02715                 phpCAS::trace('Authentication failure: '.$failure);
02716                 if ( $no_response ) {
02717                         phpCAS::trace('Reason: no response from the CAS server');
02718                 } else {
02719                         if ( $bad_response ) {
02720                                 phpCAS::trace('Reason: bad response from the CAS server');
02721                         } else {
02722                                 switch ($this->getServerVersion()) {
02723                                         case CAS_VERSION_1_0:
02724                                                 phpCAS::trace('Reason: CAS error');
02725                                                 break;
02726                                         case CAS_VERSION_2_0:
02727                                                 if ( empty($err_code) )
02728                                                         phpCAS::trace('Reason: no CAS error');
02729                                                 else
02730                                                         phpCAS::trace('Reason: ['.$err_code.'] CAS error: '.$err_msg);
02731                                                 break;
02732                                 }
02733                         }
02734                         phpCAS::trace('CAS response: '.$cas_response);
02735                 }
02736                 $this->printHTMLFooter();
02737                 phpCAS::traceExit();
02738                 exit();
02739                 }
02740         
02742 }
02743 
02744 ?>

Generated on Tue Aug 3 2010 08:38:39 for phpCAS by  doxygen 1.7.1