phpCAS version 1.3.6

Client.php
Go to the documentation of this file.
1 <?php
2
51 class CAS_Client
52 {
53
54 // ########################################################################
55 // HTML OUTPUT
56 // ########################################################################
75 private function _htmlFilterOutput($str)
76 {
77 $str = str_replace('__CAS_VERSION__', $this->getServerVersion(), $str);
78 $str = str_replace('__PHPCAS_VERSION__', phpCAS::getVersion(), $str);
79 $str = str_replace('__SERVER_BASE_URL__', $this->_getServerBaseURL(), $str);
80 echo $str;
81 }
82
90 private $_output_header = '';
91
101 public function printHTMLHeader($title)
102 {
103 $this->_htmlFilterOutput(
104 str_replace(
105 '__TITLE__', $title,
106 (empty($this->_output_header)
107 ? '<html><head><title>__TITLE__</title></head><body><h1>__TITLE__</h1>'
108 : $this->_output_header)
109 )
110 );
111 }
112
120 private $_output_footer = '';
121
129 public function printHTMLFooter()
130 {
131 $lang = $this->getLangObj();
132 $this->_htmlFilterOutput(
133 empty($this->_output_footer)?
134 (phpCAS::getVerbose())?
135 '<hr><address>phpCAS __PHPCAS_VERSION__ '
136 .$lang->getUsingServer()
137 .' <a href="__SERVER_BASE_URL__">__SERVER_BASE_URL__</a> (CAS __CAS_VERSION__)</a></address></body></html>'
138 :'</body></html>'
139 :$this->_output_footer
140 );
141 }
142
150 public function setHTMLHeader($header)
151 {
152 // Argument Validation
153 if (gettype($header) != 'string')
154 throw new CAS_TypeMismatchException($header, '$header', 'string');
155
156 $this->_output_header = $header;
157 }
158
166 public function setHTMLFooter($footer)
167 {
168 // Argument Validation
169 if (gettype($footer) != 'string')
170 throw new CAS_TypeMismatchException($footer, '$footer', 'string');
171
172 $this->_output_footer = $footer;
173 }
174
175
179 // ########################################################################
180 // INTERNATIONALIZATION
181 // ########################################################################
192 private $_lang = PHPCAS_LANG_DEFAULT;
193
201 public function setLang($lang)
202 {
203 // Argument Validation
204 if (gettype($lang) != 'string')
205 throw new CAS_TypeMismatchException($lang, '$lang', 'string');
206
207 phpCAS::traceBegin();
208 $obj = new $lang();
209 if (!($obj instanceof CAS_Languages_LanguageInterface)) {
210 throw new CAS_InvalidArgumentException(
211 '$className must implement the CAS_Languages_LanguageInterface'
212 );
213 }
214 $this->_lang = $lang;
215 phpCAS::traceEnd();
216 }
222 public function getLangObj()
223 {
224 $classname = $this->_lang;
225 return new $classname();
226 }
227
229 // ########################################################################
230 // CAS SERVER CONFIG
231 // ########################################################################
262 private $_server = array(
263 'version' => -1,
264 'hostname' => 'none',
265 'port' => -1,
266 'uri' => 'none');
267
273 public function getServerVersion()
274 {
275 return $this->_server['version'];
276 }
277
283 private function _getServerHostname()
284 {
285 return $this->_server['hostname'];
286 }
287
293 private function _getServerPort()
294 {
295 return $this->_server['port'];
296 }
297
303 private function _getServerURI()
304 {
305 return $this->_server['uri'];
306 }
307
313 private function _getServerBaseURL()
314 {
315 // the URL is build only when needed
316 if ( empty($this->_server['base_url']) ) {
317 $this->_server['base_url'] = 'https://' . $this->_getServerHostname();
318 if ($this->_getServerPort()!=443) {
319 $this->_server['base_url'] .= ':'
320 .$this->_getServerPort();
321 }
322 $this->_server['base_url'] .= $this->_getServerURI();
323 }
324 return $this->_server['base_url'];
325 }
326
337 public function getServerLoginURL($gateway=false,$renew=false)
338 {
339 phpCAS::traceBegin();
340 // the URL is build only when needed
341 if ( empty($this->_server['login_url']) ) {
342 $this->_server['login_url'] = $this->_buildQueryUrl($this->_getServerBaseURL().'login','service='.urlencode($this->getURL()));
343 }
344 $url = $this->_server['login_url'];
345 if ($renew) {
346 // It is recommended that when the "renew" parameter is set, its
347 // value be "true"
348 $url = $this->_buildQueryUrl($url, 'renew=true');
349 } elseif ($gateway) {
350 // It is recommended that when the "gateway" parameter is set, its
351 // value be "true"
352 $url = $this->_buildQueryUrl($url, 'gateway=true');
353 }
354 phpCAS::traceEnd($url);
355 return $url;
356 }
357
365 public function setServerLoginURL($url)
366 {
367 // Argument Validation
368 if (gettype($url) != 'string')
369 throw new CAS_TypeMismatchException($url, '$url', 'string');
370
371 return $this->_server['login_url'] = $url;
372 }
373
374
382 public function setServerServiceValidateURL($url)
383 {
384 // Argument Validation
385 if (gettype($url) != 'string')
386 throw new CAS_TypeMismatchException($url, '$url', 'string');
387
388 return $this->_server['service_validate_url'] = $url;
389 }
390
391
399 public function setServerProxyValidateURL($url)
400 {
401 // Argument Validation
402 if (gettype($url) != 'string')
403 throw new CAS_TypeMismatchException($url, '$url', 'string');
404
405 return $this->_server['proxy_validate_url'] = $url;
406 }
407
408
416 public function setServerSamlValidateURL($url)
417 {
418 // Argument Validation
419 if (gettype($url) != 'string')
420 throw new CAS_TypeMismatchException($url, '$url', 'string');
421
422 return $this->_server['saml_validate_url'] = $url;
423 }
424
425
431 public function getServerServiceValidateURL()
432 {
433 phpCAS::traceBegin();
434 // the URL is build only when needed
435 if ( empty($this->_server['service_validate_url']) ) {
436 switch ($this->getServerVersion()) {
437 case CAS_VERSION_1_0:
438 $this->_server['service_validate_url'] = $this->_getServerBaseURL()
439 .'validate';
440 break;
441 case CAS_VERSION_2_0:
442 $this->_server['service_validate_url'] = $this->_getServerBaseURL()
443 .'serviceValidate';
444 break;
445 case CAS_VERSION_3_0:
446 $this->_server['service_validate_url'] = $this->_getServerBaseURL()
447 .'p3/serviceValidate';
448 break;
449 }
450 }
451 $url = $this->_buildQueryUrl(
452 $this->_server['service_validate_url'],
453 'service='.urlencode($this->getURL())
454 );
455 phpCAS::traceEnd($url);
456 return $url;
457 }
463 public function getServerSamlValidateURL()
464 {
465 phpCAS::traceBegin();
466 // the URL is build only when needed
467 if ( empty($this->_server['saml_validate_url']) ) {
468 switch ($this->getServerVersion()) {
469 case SAML_VERSION_1_1:
470 $this->_server['saml_validate_url'] = $this->_getServerBaseURL().'samlValidate';
471 break;
472 }
473 }
474
475 $url = $this->_buildQueryUrl(
476 $this->_server['saml_validate_url'],
477 'TARGET='.urlencode($this->getURL())
478 );
479 phpCAS::traceEnd($url);
480 return $url;
481 }
482
488 public function getServerProxyValidateURL()
489 {
490 phpCAS::traceBegin();
491 // the URL is build only when needed
492 if ( empty($this->_server['proxy_validate_url']) ) {
493 switch ($this->getServerVersion()) {
494 case CAS_VERSION_1_0:
495 $this->_server['proxy_validate_url'] = '';
496 break;
497 case CAS_VERSION_2_0:
498 $this->_server['proxy_validate_url'] = $this->_getServerBaseURL().'proxyValidate';
499 break;
500 case CAS_VERSION_3_0:
501 $this->_server['proxy_validate_url'] = $this->_getServerBaseURL().'p3/proxyValidate';
502 break;
503 }
504 }
505 $url = $this->_buildQueryUrl(
506 $this->_server['proxy_validate_url'],
507 'service='.urlencode($this->getURL())
508 );
509 phpCAS::traceEnd($url);
510 return $url;
511 }
512
513
519 public function getServerProxyURL()
520 {
521 // the URL is build only when needed
522 if ( empty($this->_server['proxy_url']) ) {
523 switch ($this->getServerVersion()) {
524 case CAS_VERSION_1_0:
525 $this->_server['proxy_url'] = '';
526 break;
527 case CAS_VERSION_2_0:
528 case CAS_VERSION_3_0:
529 $this->_server['proxy_url'] = $this->_getServerBaseURL().'proxy';
530 break;
531 }
532 }
533 return $this->_server['proxy_url'];
534 }
535
541 public function getServerLogoutURL()
542 {
543 // the URL is build only when needed
544 if ( empty($this->_server['logout_url']) ) {
545 $this->_server['logout_url'] = $this->_getServerBaseURL().'logout';
546 }
547 return $this->_server['logout_url'];
548 }
549
557 public function setServerLogoutURL($url)
558 {
559 // Argument Validation
560 if (gettype($url) != 'string')
561 throw new CAS_TypeMismatchException($url, '$url', 'string');
562
563 return $this->_server['logout_url'] = $url;
564 }
565
569 private $_curl_options = array();
570
579 public function setExtraCurlOption($key, $value)
580 {
581 $this->_curl_options[$key] = $value;
582 }
583
586 // ########################################################################
587 // Change the internal behaviour of phpcas
588 // ########################################################################
589
601 private $_requestImplementation = 'CAS_Request_CurlRequest';
602
611 public function setRequestImplementation ($className)
612 {
613 $obj = new $className;
614 if (!($obj instanceof CAS_Request_RequestInterface)) {
615 throw new CAS_InvalidArgumentException(
616 '$className must implement the CAS_Request_RequestInterface'
617 );
618 }
619 $this->_requestImplementation = $className;
620 }
621
626 private $_clearTicketsFromUrl = true;
627
638 public function setNoClearTicketsFromUrl ()
639 {
640 $this->_clearTicketsFromUrl = false;
641 }
642
646 private $_casAttributeParserCallbackFunction = null;
647
651 private $_casAttributeParserCallbackArgs = array();
652
664 public function setCasAttributeParserCallback($function, array $additionalArgs = array())
665 {
666 $this->_casAttributeParserCallbackFunction = $function;
667 $this->_casAttributeParserCallbackArgs = $additionalArgs;
668 }
669
672 private $_postAuthenticateCallbackFunction = null;
673
677 private $_postAuthenticateCallbackArgs = array();
678
698 public function setPostAuthenticateCallback ($function, array $additionalArgs = array())
699 {
700 $this->_postAuthenticateCallbackFunction = $function;
701 $this->_postAuthenticateCallbackArgs = $additionalArgs;
702 }
703
707 private $_signoutCallbackFunction = null;
708
712 private $_signoutCallbackArgs = array();
713
728 public function setSingleSignoutCallback ($function, array $additionalArgs = array())
729 {
730 $this->_signoutCallbackFunction = $function;
731 $this->_signoutCallbackArgs = $additionalArgs;
732 }
733
734 // ########################################################################
735 // Methods for supplying code-flow feedback to integrators.
736 // ########################################################################
737
745 public function ensureIsProxy()
746 {
747 if (!$this->isProxy()) {
748 throw new CAS_OutOfSequenceBeforeProxyException();
749 }
750 }
751
761 public function markAuthenticationCall ($auth)
762 {
763 // store where the authentication has been checked and the result
764 $dbg = debug_backtrace();
765 $this->_authentication_caller = array (
766 'file' => $dbg[1]['file'],
767 'line' => $dbg[1]['line'],
768 'method' => $dbg[1]['class'] . '::' . $dbg[1]['function'],
769 'result' => (boolean)$auth
770 );
771 }
772 private $_authentication_caller;
773
779 public function wasAuthenticationCalled ()
780 {
781 return !empty($this->_authentication_caller);
782 }
783
792 private function _ensureAuthenticationCalled()
793 {
794 if (!$this->wasAuthenticationCalled()) {
795 throw new CAS_OutOfSequenceBeforeAuthenticationCallException();
796 }
797 }
798
807 public function wasAuthenticationCallSuccessful ()
808 {
809 $this->_ensureAuthenticationCalled();
810 return $this->_authentication_caller['result'];
811 }
812
813
822 public function ensureAuthenticationCallSuccessful()
823 {
824 $this->_ensureAuthenticationCalled();
825 if (!$this->_authentication_caller['result']) {
826 throw new CAS_OutOfSequenceException(
827 'authentication was checked (by '
828 . $this->getAuthenticationCallerMethod()
829 . '() at ' . $this->getAuthenticationCallerFile()
830 . ':' . $this->getAuthenticationCallerLine()
831 . ') but the method returned false'
832 );
833 }
834 }
835
844 public function getAuthenticationCallerFile ()
845 {
846 $this->_ensureAuthenticationCalled();
847 return $this->_authentication_caller['file'];
848 }
849
858 public function getAuthenticationCallerLine ()
859 {
860 $this->_ensureAuthenticationCalled();
861 return $this->_authentication_caller['line'];
862 }
863
872 public function getAuthenticationCallerMethod ()
873 {
874 $this->_ensureAuthenticationCalled();
875 return $this->_authentication_caller['method'];
876 }
877
880 // ########################################################################
881 // CONSTRUCTOR
882 // ########################################################################
902 public function __construct(
903 $server_version,
904 $proxy,
905 $server_hostname,
906 $server_port,
907 $server_uri,
908 $changeSessionID = true
909 ) {
910 // Argument validation
911 if (gettype($server_version) != 'string')
912 throw new CAS_TypeMismatchException($server_version, '$server_version', 'string');
913 if (gettype($proxy) != 'boolean')
914 throw new CAS_TypeMismatchException($proxy, '$proxy', 'boolean');
915 if (gettype($server_hostname) != 'string')
916 throw new CAS_TypeMismatchException($server_hostname, '$server_hostname', 'string');
917 if (gettype($server_port) != 'integer')
918 throw new CAS_TypeMismatchException($server_port, '$server_port', 'integer');
919 if (gettype($server_uri) != 'string')
920 throw new CAS_TypeMismatchException($server_uri, '$server_uri', 'string');
921 if (gettype($changeSessionID) != 'boolean')
922 throw new CAS_TypeMismatchException($changeSessionID, '$changeSessionID', 'boolean');
923
924 phpCAS::traceBegin();
925 // true : allow to change the session_id(), false session_id won't be
926 // change and logout won't be handle because of that
927 $this->_setChangeSessionID($changeSessionID);
928
929 // skip Session Handling for logout requests and if don't want it'
930 if (session_id()=="" && !$this->_isLogoutRequest()) {
931 session_start();
932 phpCAS :: trace("Starting a new session " . session_id());
933 }
934 // Only for debug purposes
935 if ($this->isSessionAuthenticated()){
936 phpCAS :: trace("Session is authenticated as: " . $_SESSION['phpCAS']['user']);
937 } else {
938 phpCAS :: trace("Session is not authenticated");
939 }
940 // are we in proxy mode ?
941 $this->_proxy = $proxy;
942
943 // Make cookie handling available.
944 if ($this->isProxy()) {
945 if (!isset($_SESSION['phpCAS'])) {
946 $_SESSION['phpCAS'] = array();
947 }
948 if (!isset($_SESSION['phpCAS']['service_cookies'])) {
949 $_SESSION['phpCAS']['service_cookies'] = array();
950 }
951 $this->_serviceCookieJar = new CAS_CookieJar(
952 $_SESSION['phpCAS']['service_cookies']
953 );
954 }
955
956 //check version
957 switch ($server_version) {
958 case CAS_VERSION_1_0:
959 if ( $this->isProxy() ) {
960 phpCAS::error(
961 'CAS proxies are not supported in CAS '.$server_version
962 );
963 }
964 break;
965 case CAS_VERSION_2_0:
966 case CAS_VERSION_3_0:
967 break;
968 case SAML_VERSION_1_1:
969 break;
970 default:
971 phpCAS::error(
972 'this version of CAS (`'.$server_version
973 .'\') is not supported by phpCAS '.phpCAS::getVersion()
974 );
975 }
976 $this->_server['version'] = $server_version;
977
978 // check hostname
979 if ( empty($server_hostname)
980 || !preg_match('/[\.\d\-abcdefghijklmnopqrstuvwxyz]*/', $server_hostname)
981 ) {
982 phpCAS::error('bad CAS server hostname (`'.$server_hostname.'\')');
983 }
984 $this->_server['hostname'] = $server_hostname;
985
986 // check port
987 if ( $server_port == 0
988 || !is_int($server_port)
989 ) {
990 phpCAS::error('bad CAS server port (`'.$server_hostname.'\')');
991 }
992 $this->_server['port'] = $server_port;
993
994 // check URI
995 if ( !preg_match('/[\.\d\-_abcdefghijklmnopqrstuvwxyz\/]*/', $server_uri) ) {
996 phpCAS::error('bad CAS server URI (`'.$server_uri.'\')');
997 }
998 // add leading and trailing `/' and remove doubles
999 if(strstr($server_uri, '?') === false) $server_uri .= '/';
1000 $server_uri = preg_replace('/\/\//', '/', '/'.$server_uri);
1001 $this->_server['uri'] = $server_uri;
1002
1003 // set to callback mode if PgtIou and PgtId CGI GET parameters are provided
1004 if ( $this->isProxy() ) {
1005 $this->_setCallbackMode(!empty($_GET['pgtIou'])&&!empty($_GET['pgtId']));
1006 }
1007
1008 if ( $this->_isCallbackMode() ) {
1009 //callback mode: check that phpCAS is secured
1010 if ( !$this->_isHttps() ) {
1011 phpCAS::error(
1012 'CAS proxies must be secured to use phpCAS; PGT\'s will not be received from the CAS server'
1013 );
1014 }
1015 } else {
1016 //normal mode: get ticket and remove it from CGI parameters for
1017 // developers
1018 $ticket = (isset($_GET['ticket']) ? $_GET['ticket'] : null);
1019 if (preg_match('/^[SP]T-/', $ticket) ) {
1020 phpCAS::trace('Ticket \''.$ticket.'\' found');
1021 $this->setTicket($ticket);
1022 unset($_GET['ticket']);
1023 } else if ( !empty($ticket) ) {
1024 //ill-formed ticket, halt
1025 phpCAS::error(
1026 'ill-formed ticket found in the URL (ticket=`'
1027 .htmlentities($ticket).'\')'
1028 );
1029 }
1030
1031 }
1032 phpCAS::traceEnd();
1033 }
1034
1037 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1038 // XX XX
1039 // XX Session Handling XX
1040 // XX XX
1041 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1042
1053 private $_change_session_id = true;
1054
1062 private function _setChangeSessionID($allowed)
1063 {
1064 $this->_change_session_id = $allowed;
1065 }
1066
1072 public function getChangeSessionID()
1073 {
1074 return $this->_change_session_id;
1075 }
1076
1079 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1080 // XX XX
1081 // XX AUTHENTICATION XX
1082 // XX XX
1083 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1084
1096 private $_user = '';
1097
1105 private function _setUser($user)
1106 {
1107 $this->_user = $user;
1108 }
1109
1118 public function getUser()
1119 {
1120 // Sequence validation
1121 $this->ensureAuthenticationCallSuccessful();
1122
1123 return $this->_getUser();
1124 }
1125
1134 private function _getUser()
1135 {
1136 // This is likely a duplicate check that could be removed....
1137 if ( empty($this->_user) ) {
1138 phpCAS::error(
1139 'this method should be used only after '.__CLASS__
1140 .'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()'
1141 );
1142 }
1143 return $this->_user;
1144 }
1145
1153 private $_attributes = array();
1154
1162 public function setAttributes($attributes)
1163 {
1164 $this->_attributes = $attributes;
1165 }
1166
1172 public function getAttributes()
1173 {
1174 // Sequence validation
1175 $this->ensureAuthenticationCallSuccessful();
1176 // This is likely a duplicate check that could be removed....
1177 if ( empty($this->_user) ) {
1178 // if no user is set, there shouldn't be any attributes also...
1179 phpCAS::error(
1180 'this method should be used only after '.__CLASS__
1181 .'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()'
1182 );
1183 }
1184 return $this->_attributes;
1185 }
1186
1192 public function hasAttributes()
1193 {
1194 // Sequence validation
1195 $this->ensureAuthenticationCallSuccessful();
1196
1197 return !empty($this->_attributes);
1198 }
1206 public function hasAttribute($key)
1207 {
1208 // Sequence validation
1209 $this->ensureAuthenticationCallSuccessful();
1210
1211 return $this->_hasAttribute($key);
1212 }
1213
1221 private function _hasAttribute($key)
1222 {
1223 return (is_array($this->_attributes)
1224 && array_key_exists($key, $this->_attributes));
1225 }
1226
1234 public function getAttribute($key)
1235 {
1236 // Sequence validation
1237 $this->ensureAuthenticationCallSuccessful();
1238
1239 if ($this->_hasAttribute($key)) {
1240 return $this->_attributes[$key];
1241 }
1242 }
1243
1251 public function renewAuthentication()
1252 {
1253 phpCAS::traceBegin();
1254 // Either way, the user is authenticated by CAS
1255 if (isset( $_SESSION['phpCAS']['auth_checked'])) {
1256 unset($_SESSION['phpCAS']['auth_checked']);
1257 }
1258 if ( $this->isAuthenticated(true) ) {
1259 phpCAS::trace('user already authenticated');
1260 $res = true;
1261 } else {
1262 $this->redirectToCas(false, true);
1263 // never reached
1264 $res = false;
1265 }
1266 phpCAS::traceEnd();
1267 return $res;
1268 }
1269
1276 public function forceAuthentication()
1277 {
1278 phpCAS::traceBegin();
1279
1280 if ( $this->isAuthenticated() ) {
1281 // the user is authenticated, nothing to be done.
1282 phpCAS::trace('no need to authenticate');
1283 $res = true;
1284 } else {
1285 // the user is not authenticated, redirect to the CAS server
1286 if (isset($_SESSION['phpCAS']['auth_checked'])) {
1287 unset($_SESSION['phpCAS']['auth_checked']);
1288 }
1289 $this->redirectToCas(false/* no gateway */);
1290 // never reached
1291 $res = false;
1292 }
1293 phpCAS::traceEnd($res);
1294 return $res;
1295 }
1296
1303 private $_cache_times_for_auth_recheck = 0;
1304
1312 public function setCacheTimesForAuthRecheck($n)
1313 {
1314 if (gettype($n) != 'integer')
1315 throw new CAS_TypeMismatchException($n, '$n', 'string');
1316
1317 $this->_cache_times_for_auth_recheck = $n;
1318 }
1319
1327 public function checkAuthentication()
1328 {
1329 phpCAS::traceBegin();
1330 $res = false;
1331 if ( $this->isAuthenticated() ) {
1332 phpCAS::trace('user is authenticated');
1333 /* The 'auth_checked' variable is removed just in case it's set. */
1334 unset($_SESSION['phpCAS']['auth_checked']);
1335 $res = true;
1336 } else if (isset($_SESSION['phpCAS']['auth_checked'])) {
1337 // the previous request has redirected the client to the CAS server
1338 // with gateway=true
1339 unset($_SESSION['phpCAS']['auth_checked']);
1340 $res = false;
1341 } else {
1342 // avoid a check against CAS on every request
1343 if (!isset($_SESSION['phpCAS']['unauth_count'])) {
1344 $_SESSION['phpCAS']['unauth_count'] = -2; // uninitialized
1345 }
1346
1347 if (($_SESSION['phpCAS']['unauth_count'] != -2
1348 && $this->_cache_times_for_auth_recheck == -1)
1349 || ($_SESSION['phpCAS']['unauth_count'] >= 0
1350 && $_SESSION['phpCAS']['unauth_count'] < $this->_cache_times_for_auth_recheck)
1351 ) {
1352 $res = false;
1353
1354 if ($this->_cache_times_for_auth_recheck != -1) {
1355 $_SESSION['phpCAS']['unauth_count']++;
1356 phpCAS::trace(
1357 'user is not authenticated (cached for '
1358 .$_SESSION['phpCAS']['unauth_count'].' times of '
1359 .$this->_cache_times_for_auth_recheck.')'
1360 );
1361 } else {
1362 phpCAS::trace(
1363 'user is not authenticated (cached for until login pressed)'
1364 );
1365 }
1366 } else {
1367 $_SESSION['phpCAS']['unauth_count'] = 0;
1368 $_SESSION['phpCAS']['auth_checked'] = true;
1369 phpCAS::trace('user is not authenticated (cache reset)');
1370 $this->redirectToCas(true/* gateway */);
1371 // never reached
1372 $res = false;
1373 }
1374 }
1375 phpCAS::traceEnd($res);
1376 return $res;
1377 }
1378
1388 public function isAuthenticated($renew=false)
1389 {
1390 phpCAS::traceBegin();
1391 $res = false;
1392 $validate_url = '';
1393 if ( $this->_wasPreviouslyAuthenticated() ) {
1394 if ($this->hasTicket()) {
1395 // User has a additional ticket but was already authenticated
1396 phpCAS::trace(
1397 'ticket was present and will be discarded, use renewAuthenticate()'
1398 );
1399 if ($this->_clearTicketsFromUrl) {
1400 phpCAS::trace("Prepare redirect to : ".$this->getURL());
1401 session_write_close();
1402 header('Location: '.$this->getURL());
1403 flush();
1404 phpCAS::traceExit();
1405 throw new CAS_GracefullTerminationException();
1406 } else {
1407 phpCAS::trace(
1408 'Already authenticated, but skipping ticket clearing since setNoClearTicketsFromUrl() was used.'
1409 );
1410 $res = true;
1411 }
1412 } else {
1413 // the user has already (previously during the session) been
1414 // authenticated, nothing to be done.
1415 phpCAS::trace(
1416 'user was already authenticated, no need to look for tickets'
1417 );
1418 $res = true;
1419 }
1420
1421 // Mark the auth-check as complete to allow post-authentication
1422 // callbacks to make use of phpCAS::getUser() and similar methods
1423 $this->markAuthenticationCall($res);
1424 } else {
1425 if ($this->hasTicket()) {
1426 switch ($this->getServerVersion()) {
1427 case CAS_VERSION_1_0:
1428 // if a Service Ticket was given, validate it
1429 phpCAS::trace(
1430 'CAS 1.0 ticket `'.$this->getTicket().'\' is present'
1431 );
1432 $this->validateCAS10(
1433 $validate_url, $text_response, $tree_response, $renew
1434 ); // if it fails, it halts
1435 phpCAS::trace(
1436 'CAS 1.0 ticket `'.$this->getTicket().'\' was validated'
1437 );
1438 $_SESSION['phpCAS']['user'] = $this->_getUser();
1439 $res = true;
1440 $logoutTicket = $this->getTicket();
1441 break;
1442 case CAS_VERSION_2_0:
1443 case CAS_VERSION_3_0:
1444 // if a Proxy Ticket was given, validate it
1445 phpCAS::trace(
1446 'CAS '.$this->getServerVersion().' ticket `'.$this->getTicket().'\' is present'
1447 );
1448 $this->validateCAS20(
1449 $validate_url, $text_response, $tree_response, $renew
1450 ); // note: if it fails, it halts
1451 phpCAS::trace(
1452 'CAS '.$this->getServerVersion().' ticket `'.$this->getTicket().'\' was validated'
1453 );
1454 if ( $this->isProxy() ) {
1455 $this->_validatePGT(
1456 $validate_url, $text_response, $tree_response
1457 ); // idem
1458 phpCAS::trace('PGT `'.$this->_getPGT().'\' was validated');
1459 $_SESSION['phpCAS']['pgt'] = $this->_getPGT();
1460 }
1461 $_SESSION['phpCAS']['user'] = $this->_getUser();
1462 if (!empty($this->_attributes)) {
1463 $_SESSION['phpCAS']['attributes'] = $this->_attributes;
1464 }
1465 $proxies = $this->getProxies();
1466 if (!empty($proxies)) {
1467 $_SESSION['phpCAS']['proxies'] = $this->getProxies();
1468 }
1469 $res = true;
1470 $logoutTicket = $this->getTicket();
1471 break;
1472 case SAML_VERSION_1_1:
1473 // if we have a SAML ticket, validate it.
1474 phpCAS::trace(
1475 'SAML 1.1 ticket `'.$this->getTicket().'\' is present'
1476 );
1477 $this->validateSA(
1478 $validate_url, $text_response, $tree_response, $renew
1479 ); // if it fails, it halts
1480 phpCAS::trace(
1481 'SAML 1.1 ticket `'.$this->getTicket().'\' was validated'
1482 );
1483 $_SESSION['phpCAS']['user'] = $this->_getUser();
1484 $_SESSION['phpCAS']['attributes'] = $this->_attributes;
1485 $res = true;
1486 $logoutTicket = $this->getTicket();
1487 break;
1488 default:
1489 phpCAS::trace('Protocoll error');
1490 break;
1491 }
1492 } else {
1493 // no ticket given, not authenticated
1494 phpCAS::trace('no ticket found');
1495 }
1496
1497 // Mark the auth-check as complete to allow post-authentication
1498 // callbacks to make use of phpCAS::getUser() and similar methods
1499 $this->markAuthenticationCall($res);
1500
1501 if ($res) {
1502 // call the post-authenticate callback if registered.
1503 if ($this->_postAuthenticateCallbackFunction) {
1504 $args = $this->_postAuthenticateCallbackArgs;
1505 array_unshift($args, $logoutTicket);
1506 call_user_func_array(
1507 $this->_postAuthenticateCallbackFunction, $args
1508 );
1509 }
1510
1511 // if called with a ticket parameter, we need to redirect to the
1512 // app without the ticket so that CAS-ification is transparent
1513 // to the browser (for later POSTS) most of the checks and
1514 // errors should have been made now, so we're safe for redirect
1515 // without masking error messages. remove the ticket as a
1516 // security precaution to prevent a ticket in the HTTP_REFERRER
1517 if ($this->_clearTicketsFromUrl) {
1518 phpCAS::trace("Prepare redirect to : ".$this->getURL());
1519 session_write_close();
1520 header('Location: '.$this->getURL());
1521 flush();
1522 phpCAS::traceExit();
1523 throw new CAS_GracefullTerminationException();
1524 }
1525 }
1526 }
1527 phpCAS::traceEnd($res);
1528 return $res;
1529 }
1530
1536 public function isSessionAuthenticated ()
1537 {
1538 return !empty($_SESSION['phpCAS']['user']);
1539 }
1540
1549 private function _wasPreviouslyAuthenticated()
1550 {
1551 phpCAS::traceBegin();
1552
1553 if ( $this->_isCallbackMode() ) {
1554 // Rebroadcast the pgtIou and pgtId to all nodes
1555 if ($this->_rebroadcast&&!isset($_POST['rebroadcast'])) {
1556 $this->_rebroadcast(self::PGTIOU);
1557 }
1558 $this->_callback();
1559 }
1560
1561 $auth = false;
1562
1563 if ( $this->isProxy() ) {
1564 // CAS proxy: username and PGT must be present
1565 if ( $this->isSessionAuthenticated()
1566 && !empty($_SESSION['phpCAS']['pgt'])
1567 ) {
1568 // authentication already done
1569 $this->_setUser($_SESSION['phpCAS']['user']);
1570 if (isset($_SESSION['phpCAS']['attributes'])) {
1571 $this->setAttributes($_SESSION['phpCAS']['attributes']);
1572 }
1573 $this->_setPGT($_SESSION['phpCAS']['pgt']);
1574 phpCAS::trace(
1575 'user = `'.$_SESSION['phpCAS']['user'].'\', PGT = `'
1576 .$_SESSION['phpCAS']['pgt'].'\''
1577 );
1578
1579 // Include the list of proxies
1580 if (isset($_SESSION['phpCAS']['proxies'])) {
1581 $this->_setProxies($_SESSION['phpCAS']['proxies']);
1582 phpCAS::trace(
1583 'proxies = "'
1584 .implode('", "', $_SESSION['phpCAS']['proxies']).'"'
1585 );
1586 }
1587
1588 $auth = true;
1589 } elseif ( $this->isSessionAuthenticated()
1590 && empty($_SESSION['phpCAS']['pgt'])
1591 ) {
1592 // these two variables should be empty or not empty at the same time
1593 phpCAS::trace(
1594 'username found (`'.$_SESSION['phpCAS']['user']
1595 .'\') but PGT is empty'
1596 );
1597 // unset all tickets to enforce authentication
1598 unset($_SESSION['phpCAS']);
1599 $this->setTicket('');
1600 } elseif ( !$this->isSessionAuthenticated()
1601 && !empty($_SESSION['phpCAS']['pgt'])
1602 ) {
1603 // these two variables should be empty or not empty at the same time
1604 phpCAS::trace(
1605 'PGT found (`'.$_SESSION['phpCAS']['pgt']
1606 .'\') but username is empty'
1607 );
1608 // unset all tickets to enforce authentication
1609 unset($_SESSION['phpCAS']);
1610 $this->setTicket('');
1611 } else {
1612 phpCAS::trace('neither user nor PGT found');
1613 }
1614 } else {
1615 // `simple' CAS client (not a proxy): username must be present
1616 if ( $this->isSessionAuthenticated() ) {
1617 // authentication already done
1618 $this->_setUser($_SESSION['phpCAS']['user']);
1619 if (isset($_SESSION['phpCAS']['attributes'])) {
1620 $this->setAttributes($_SESSION['phpCAS']['attributes']);
1621 }
1622 phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\'');
1623
1624 // Include the list of proxies
1625 if (isset($_SESSION['phpCAS']['proxies'])) {
1626 $this->_setProxies($_SESSION['phpCAS']['proxies']);
1627 phpCAS::trace(
1628 'proxies = "'
1629 .implode('", "', $_SESSION['phpCAS']['proxies']).'"'
1630 );
1631 }
1632
1633 $auth = true;
1634 } else {
1635 phpCAS::trace('no user found');
1636 }
1637 }
1638
1639 phpCAS::traceEnd($auth);
1640 return $auth;
1641 }
1642
1653 public function redirectToCas($gateway=false,$renew=false)
1654 {
1655 phpCAS::traceBegin();
1656 $cas_url = $this->getServerLoginURL($gateway, $renew);
1657 session_write_close();
1658 if (php_sapi_name() === 'cli') {
1659 @header('Location: '.$cas_url);
1660 } else {
1661 header('Location: '.$cas_url);
1662 }
1663 phpCAS::trace("Redirect to : ".$cas_url);
1664 $lang = $this->getLangObj();
1665 $this->printHTMLHeader($lang->getAuthenticationWanted());
1666 printf('<p>'. $lang->getShouldHaveBeenRedirected(). '</p>', $cas_url);
1667 $this->printHTMLFooter();
1668 phpCAS::traceExit();
1669 throw new CAS_GracefullTerminationException();
1670 }
1671
1672
1681 public function logout($params)
1682 {
1683 phpCAS::traceBegin();
1684 $cas_url = $this->getServerLogoutURL();
1685 $paramSeparator = '?';
1686 if (isset($params['url'])) {
1687 $cas_url = $cas_url . $paramSeparator . "url="
1688 . urlencode($params['url']);
1689 $paramSeparator = '&';
1690 }
1691 if (isset($params['service'])) {
1692 $cas_url = $cas_url . $paramSeparator . "service="
1693 . urlencode($params['service']);
1694 }
1695 header('Location: '.$cas_url);
1696 phpCAS::trace("Prepare redirect to : ".$cas_url);
1697
1698 phpCAS::trace("Destroying session : ".session_id());
1699 session_unset();
1700 session_destroy();
1701 if (session_status() === PHP_SESSION_NONE) {
1702 phpCAS::trace("Session terminated");
1703 } else {
1704 phpCAS::error("Session was not terminated");
1705 phpCAS::trace("Session was not terminated");
1706 }
1707 $lang = $this->getLangObj();
1708 $this->printHTMLHeader($lang->getLogout());
1709 printf('<p>'.$lang->getShouldHaveBeenRedirected(). '</p>', $cas_url);
1710 $this->printHTMLFooter();
1711 phpCAS::traceExit();
1712 throw new CAS_GracefullTerminationException();
1713 }
1714
1720 private function _isLogoutRequest()
1721 {
1722 return !empty($_POST['logoutRequest']);
1723 }
1724
1735 public function handleLogoutRequests($check_client=true, $allowed_clients=false)
1736 {
1737 phpCAS::traceBegin();
1738 if (!$this->_isLogoutRequest()) {
1739 phpCAS::trace("Not a logout request");
1740 phpCAS::traceEnd();
1741 return;
1742 }
1743 if (!$this->getChangeSessionID()
1744 && is_null($this->_signoutCallbackFunction)
1745 ) {
1746 phpCAS::trace(
1747 "phpCAS can't handle logout requests if it is not allowed to change session_id."
1748 );
1749 }
1750 phpCAS::trace("Logout requested");
1751 $decoded_logout_rq = urldecode($_POST['logoutRequest']);
1752 phpCAS::trace("SAML REQUEST: ".$decoded_logout_rq);
1753 $allowed = false;
1754 if ($check_client) {
1755 if (!$allowed_clients) {
1756 $allowed_clients = array( $this->_getServerHostname() );
1757 }
1758 $client_ip = $_SERVER['REMOTE_ADDR'];
1759 $client = gethostbyaddr($client_ip);
1760 phpCAS::trace("Client: ".$client."/".$client_ip);
1761 foreach ($allowed_clients as $allowed_client) {
1762 if (($client == $allowed_client)
1763 || ($client_ip == $allowed_client)
1764 ) {
1765 phpCAS::trace(
1766 "Allowed client '".$allowed_client
1767 ."' matches, logout request is allowed"
1768 );
1769 $allowed = true;
1770 break;
1771 } else {
1772 phpCAS::trace(
1773 "Allowed client '".$allowed_client."' does not match"
1774 );
1775 }
1776 }
1777 } else {
1778 phpCAS::trace("No access control set");
1779 $allowed = true;
1780 }
1781 // If Logout command is permitted proceed with the logout
1782 if ($allowed) {
1783 phpCAS::trace("Logout command allowed");
1784 // Rebroadcast the logout request
1785 if ($this->_rebroadcast && !isset($_POST['rebroadcast'])) {
1786 $this->_rebroadcast(self::LOGOUT);
1787 }
1788 // Extract the ticket from the SAML Request
1789 preg_match(
1790 "|<samlp:SessionIndex>(.*)</samlp:SessionIndex>|",
1791 $decoded_logout_rq, $tick, PREG_OFFSET_CAPTURE, 3
1792 );
1793 $wrappedSamlSessionIndex = preg_replace(
1794 '|<samlp:SessionIndex>|', '', $tick[0][0]
1795 );
1796 $ticket2logout = preg_replace(
1797 '|</samlp:SessionIndex>|', '', $wrappedSamlSessionIndex
1798 );
1799 phpCAS::trace("Ticket to logout: ".$ticket2logout);
1800
1801 // call the post-authenticate callback if registered.
1802 if ($this->_signoutCallbackFunction) {
1803 $args = $this->_signoutCallbackArgs;
1804 array_unshift($args, $ticket2logout);
1805 call_user_func_array($this->_signoutCallbackFunction, $args);
1806 }
1807
1808 // If phpCAS is managing the session_id, destroy session thanks to
1809 // session_id.
1810 if ($this->getChangeSessionID()) {
1811 $session_id = $this->_sessionIdForTicket($ticket2logout);
1812 phpCAS::trace("Session id: ".$session_id);
1813
1814 // destroy a possible application session created before phpcas
1815 if (session_id() !== "") {
1816 session_unset();
1817 session_destroy();
1818 }
1819 // fix session ID
1820 session_id($session_id);
1821 $_COOKIE[session_name()]=$session_id;
1822 $_GET[session_name()]=$session_id;
1823
1824 // Overwrite session
1825 session_start();
1826 session_unset();
1827 session_destroy();
1828 phpCAS::trace("Session ". $session_id . " destroyed");
1829 }
1830 } else {
1831 phpCAS::error("Unauthorized logout request from client '".$client."'");
1832 phpCAS::trace("Unauthorized logout request from client '".$client."'");
1833 }
1834 flush();
1835 phpCAS::traceExit();
1836 throw new CAS_GracefullTerminationException();
1837
1838 }
1839
1842 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1843 // XX XX
1844 // XX BASIC CLIENT FEATURES (CAS 1.0) XX
1845 // XX XX
1846 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1847
1848 // ########################################################################
1849 // ST
1850 // ########################################################################
1863 private $_ticket = '';
1864
1870 public function getTicket()
1871 {
1872 return $this->_ticket;
1873 }
1874
1882 public function setTicket($st)
1883 {
1884 $this->_ticket = $st;
1885 }
1886
1892 public function hasTicket()
1893 {
1894 return !empty($this->_ticket);
1895 }
1896
1899 // ########################################################################
1900 // ST VALIDATION
1901 // ########################################################################
1912 private $_cas_server_ca_cert = null;
1913
1914
1925 private $_cas_server_cn_validate = true;
1926
1932 private $_no_cas_server_validation = false;
1933
1934
1944 public function setCasServerCACert($cert, $validate_cn)
1945 {
1946 // Argument validation
1947 if (gettype($cert) != 'string') {
1948 throw new CAS_TypeMismatchException($cert, '$cert', 'string');
1949 }
1950 if (gettype($validate_cn) != 'boolean') {
1951 throw new CAS_TypeMismatchException($validate_cn, '$validate_cn', 'boolean');
1952 }
1953 if ( !file_exists($cert) && $this->_requestImplementation !== 'CAS_TestHarness_DummyRequest'){
1954 throw new CAS_InvalidArgumentException("Certificate file does not exist " . $this->_requestImplementation);
1955 }
1956 $this->_cas_server_ca_cert = $cert;
1957 $this->_cas_server_cn_validate = $validate_cn;
1958 }
1959
1965 public function setNoCasServerValidation()
1966 {
1967 $this->_no_cas_server_validation = true;
1968 }
1969
1985 public function validateCAS10(&$validate_url,&$text_response,&$tree_response,$renew=false)
1986 {
1987 phpCAS::traceBegin();
1988 $result = false;
1989 // build the URL to validate the ticket
1990 $validate_url = $this->getServerServiceValidateURL()
1991 .'&ticket='.urlencode($this->getTicket());
1992
1993 if ( $renew ) {
1994 // pass the renew
1995 $validate_url .= '&renew=true';
1996 }
1997
1998 // open and read the URL
1999 if ( !$this->_readURL($validate_url, $headers, $text_response, $err_msg) ) {
2000 phpCAS::trace(
2001 'could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')'
2002 );
2003 throw new CAS_AuthenticationException(
2004 $this, 'CAS 1.0 ticket not validated', $validate_url,
2005 true/*$no_response*/
2006 );
2007 $result = false;
2008 }
2009
2010 if (preg_match('/^no\n/', $text_response)) {
2011 phpCAS::trace('Ticket has not been validated');
2012 throw new CAS_AuthenticationException(
2013 $this, 'ST not validated', $validate_url, false/*$no_response*/,
2014 false/*$bad_response*/, $text_response
2015 );
2016 $result = false;
2017 } else if (!preg_match('/^yes\n/', $text_response)) {
2018 phpCAS::trace('ill-formed response');
2019 throw new CAS_AuthenticationException(
2020 $this, 'Ticket not validated', $validate_url,
2021 false/*$no_response*/, true/*$bad_response*/, $text_response
2022 );
2023 $result = false;
2024 }
2025 // ticket has been validated, extract the user name
2026 $arr = preg_split('/\n/', $text_response);
2027 $this->_setUser(trim($arr[1]));
2028 $result = true;
2029
2030 if ($result) {
2031 $this->_renameSession($this->getTicket());
2032 }
2033 // at this step, ticket has been validated and $this->_user has been set,
2034 phpCAS::traceEnd(true);
2035 return true;
2036 }
2037
2041 // ########################################################################
2042 // SAML VALIDATION
2043 // ########################################################################
2065 public function validateSA(&$validate_url,&$text_response,&$tree_response,$renew=false)
2066 {
2067 phpCAS::traceBegin();
2068 $result = false;
2069 // build the URL to validate the ticket
2070 $validate_url = $this->getServerSamlValidateURL();
2071
2072 if ( $renew ) {
2073 // pass the renew
2074 $validate_url .= '&renew=true';
2075 }
2076
2077 // open and read the URL
2078 if ( !$this->_readURL($validate_url, $headers, $text_response, $err_msg) ) {
2079 phpCAS::trace(
2080 'could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')'
2081 );
2082 throw new CAS_AuthenticationException(
2083 $this, 'SA not validated', $validate_url, true/*$no_response*/
2084 );
2085 }
2086
2087 phpCAS::trace('server version: '.$this->getServerVersion());
2088
2089 // analyze the result depending on the version
2090 switch ($this->getServerVersion()) {
2091 case SAML_VERSION_1_1:
2092 // create new DOMDocument Object
2093 $dom = new DOMDocument();
2094 // Fix possible whitspace problems
2095 $dom->preserveWhiteSpace = false;
2096 // read the response of the CAS server into a DOM object
2097 if (!($dom->loadXML($text_response))) {
2098 phpCAS::trace('dom->loadXML() failed');
2099 throw new CAS_AuthenticationException(
2100 $this, 'SA not validated', $validate_url,
2101 false/*$no_response*/, true/*$bad_response*/,
2102 $text_response
2103 );
2104 $result = false;
2105 }
2106 // read the root node of the XML tree
2107 if (!($tree_response = $dom->documentElement)) {
2108 phpCAS::trace('documentElement() failed');
2109 throw new CAS_AuthenticationException(
2110 $this, 'SA not validated', $validate_url,
2111 false/*$no_response*/, true/*$bad_response*/,
2112 $text_response
2113 );
2114 $result = false;
2115 } else if ( $tree_response->localName != 'Envelope' ) {
2116 // insure that tag name is 'Envelope'
2117 phpCAS::trace(
2118 'bad XML root node (should be `Envelope\' instead of `'
2119 .$tree_response->localName.'\''
2120 );
2121 throw new CAS_AuthenticationException(
2122 $this, 'SA not validated', $validate_url,
2123 false/*$no_response*/, true/*$bad_response*/,
2124 $text_response
2125 );
2126 $result = false;
2127 } else if ($tree_response->getElementsByTagName("NameIdentifier")->length != 0) {
2128 // check for the NameIdentifier tag in the SAML response
2129 $success_elements = $tree_response->getElementsByTagName("NameIdentifier");
2130 phpCAS::trace('NameIdentifier found');
2131 $user = trim($success_elements->item(0)->nodeValue);
2132 phpCAS::trace('user = `'.$user.'`');
2133 $this->_setUser($user);
2134 $this->_setSessionAttributes($text_response);
2135 $result = true;
2136 } else {
2137 phpCAS::trace('no <NameIdentifier> tag found in SAML payload');
2138 throw new CAS_AuthenticationException(
2139 $this, 'SA not validated', $validate_url,
2140 false/*$no_response*/, true/*$bad_response*/,
2141 $text_response
2142 );
2143 $result = false;
2144 }
2145 }
2146 if ($result) {
2147 $this->_renameSession($this->getTicket());
2148 }
2149 // at this step, ST has been validated and $this->_user has been set,
2150 phpCAS::traceEnd($result);
2151 return $result;
2152 }
2153
2162 private function _setSessionAttributes($text_response)
2163 {
2164 phpCAS::traceBegin();
2165
2166 $result = false;
2167
2168 $attr_array = array();
2169
2170 // create new DOMDocument Object
2171 $dom = new DOMDocument();
2172 // Fix possible whitspace problems
2173 $dom->preserveWhiteSpace = false;
2174 if (($dom->loadXML($text_response))) {
2175 $xPath = new DOMXpath($dom);
2176 $xPath->registerNamespace('samlp', 'urn:oasis:names:tc:SAML:1.0:protocol');
2177 $xPath->registerNamespace('saml', 'urn:oasis:names:tc:SAML:1.0:assertion');
2178 $nodelist = $xPath->query("//saml:Attribute");
2179
2180 if ($nodelist) {
2181 foreach ($nodelist as $node) {
2182 $xres = $xPath->query("saml:AttributeValue", $node);
2183 $name = $node->getAttribute("AttributeName");
2184 $value_array = array();
2185 foreach ($xres as $node2) {
2186 $value_array[] = $node2->nodeValue;
2187 }
2188 $attr_array[$name] = $value_array;
2189 }
2190 // UGent addition...
2191 foreach ($attr_array as $attr_key => $attr_value) {
2192 if (count($attr_value) > 1) {
2193 $this->_attributes[$attr_key] = $attr_value;
2194 phpCAS::trace("* " . $attr_key . "=" . print_r($attr_value, true));
2195 } else {
2196 $this->_attributes[$attr_key] = $attr_value[0];
2197 phpCAS::trace("* " . $attr_key . "=" . $attr_value[0]);
2198 }
2199 }
2200 $result = true;
2201 } else {
2202 phpCAS::trace("SAML Attributes are empty");
2203 $result = false;
2204 }
2205 }
2206 phpCAS::traceEnd($result);
2207 return $result;
2208 }
2209
2212 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2213 // XX XX
2214 // XX PROXY FEATURES (CAS 2.0) XX
2215 // XX XX
2216 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2217
2218 // ########################################################################
2219 // PROXYING
2220 // ########################################################################
2230 private $_proxy;
2231
2235 private $_serviceCookieJar;
2236
2242 public function isProxy()
2243 {
2244 return $this->_proxy;
2245 }
2246
2247
2249 // ########################################################################
2250 // PGT
2251 // ########################################################################
2264 private $_pgt = '';
2265
2271 private function _getPGT()
2272 {
2273 return $this->_pgt;
2274 }
2275
2283 private function _setPGT($pgt)
2284 {
2285 $this->_pgt = $pgt;
2286 }
2287
2293 private function _hasPGT()
2294 {
2295 return !empty($this->_pgt);
2296 }
2297
2300 // ########################################################################
2301 // CALLBACK MODE
2302 // ########################################################################
2319 private $_callback_mode = false;
2320
2328 private function _setCallbackMode($callback_mode)
2329 {
2330 $this->_callback_mode = $callback_mode;
2331 }
2332
2339 private function _isCallbackMode()
2340 {
2341 return $this->_callback_mode;
2342 }
2343
2351 private $_callback_url = '';
2352
2360 private function _getCallbackURL()
2361 {
2362 // the URL is built when needed only
2363 if ( empty($this->_callback_url) ) {
2364 $final_uri = '';
2365 // remove the ticket if present in the URL
2366 $final_uri = 'https://';
2367 $final_uri .= $this->_getClientUrl();
2368 $request_uri = $_SERVER['REQUEST_URI'];
2369 $request_uri = preg_replace('/\?.*$/', '', $request_uri);
2370 $final_uri .= $request_uri;
2371 $this->_callback_url = $final_uri;
2372 }
2373 return $this->_callback_url;
2374 }
2375
2383 public function setCallbackURL($url)
2384 {
2385 // Sequence validation
2386 $this->ensureIsProxy();
2387 // Argument Validation
2388 if (gettype($url) != 'string')
2389 throw new CAS_TypeMismatchException($url, '$url', 'string');
2390
2391 return $this->_callback_url = $url;
2392 }
2393
2400 private function _callback()
2401 {
2402 phpCAS::traceBegin();
2403 if (preg_match('/^PGTIOU-[\.\-\w]+$/', $_GET['pgtIou'])) {
2404 if (preg_match('/^[PT]GT-[\.\-\w]+$/', $_GET['pgtId'])) {
2405 $this->printHTMLHeader('phpCAS callback');
2406 $pgt_iou = $_GET['pgtIou'];
2407 $pgt = $_GET['pgtId'];
2408 phpCAS::trace('Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\')');
2409 echo '<p>Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\').</p>';
2410 $this->_storePGT($pgt, $pgt_iou);
2411 $this->printHTMLFooter();
2412 phpCAS::traceExit("Successfull Callback");
2413 } else {
2414 phpCAS::error('PGT format invalid' . $_GET['pgtId']);
2415 phpCAS::traceExit('PGT format invalid' . $_GET['pgtId']);
2416 }
2417 } else {
2418 phpCAS::error('PGTiou format invalid' . $_GET['pgtIou']);
2419 phpCAS::traceExit('PGTiou format invalid' . $_GET['pgtIou']);
2420 }
2421
2422 // Flush the buffer to prevent from sending anything other then a 200
2423 // Success Status back to the CAS Server. The Exception would normally
2424 // report as a 500 error.
2425 flush();
2426 throw new CAS_GracefullTerminationException();
2427 }
2428
2429
2432 // ########################################################################
2433 // PGT STORAGE
2434 // ########################################################################
2447 private $_pgt_storage = null;
2448
2455 private function _initPGTStorage()
2456 {
2457 // if no SetPGTStorageXxx() has been used, default to file
2458 if ( !is_object($this->_pgt_storage) ) {
2459 $this->setPGTStorageFile();
2460 }
2461
2462 // initializes the storage
2463 $this->_pgt_storage->init();
2464 }
2465
2474 private function _storePGT($pgt,$pgt_iou)
2475 {
2476 // ensure that storage is initialized
2477 $this->_initPGTStorage();
2478 // writes the PGT
2479 $this->_pgt_storage->write($pgt, $pgt_iou);
2480 }
2481
2490 private function _loadPGT($pgt_iou)
2491 {
2492 // ensure that storage is initialized
2493 $this->_initPGTStorage();
2494 // read the PGT
2495 return $this->_pgt_storage->read($pgt_iou);
2496 }
2497
2506 public function setPGTStorage($storage)
2507 {
2508 // Sequence validation
2509 $this->ensureIsProxy();
2510
2511 // check that the storage has not already been set
2512 if ( is_object($this->_pgt_storage) ) {
2513 phpCAS::error('PGT storage already defined');
2514 }
2515
2516 // check to make sure a valid storage object was specified
2517 if ( !($storage instanceof CAS_PGTStorage_AbstractStorage) )
2518 throw new CAS_TypeMismatchException($storage, '$storage', 'CAS_PGTStorage_AbstractStorage object');
2519
2520 // store the PGTStorage object
2521 $this->_pgt_storage = $storage;
2522 }
2523
2541 public function setPGTStorageDb(
2542 $dsn_or_pdo, $username='', $password='', $table='', $driver_options=null
2543 ) {
2544 // Sequence validation
2545 $this->ensureIsProxy();
2546
2547 // Argument validation
2548 if (!(is_object($dsn_or_pdo) && $dsn_or_pdo instanceof PDO) && gettype($dsn_or_pdo) != 'string')
2549 throw new CAS_TypeMismatchException($dsn_or_pdo, '$dsn_or_pdo', 'string or PDO object');
2550 if (gettype($username) != 'string')
2551 throw new CAS_TypeMismatchException($username, '$username', 'string');
2552 if (gettype($password) != 'string')
2553 throw new CAS_TypeMismatchException($password, '$password', 'string');
2554 if (gettype($table) != 'string')
2555 throw new CAS_TypeMismatchException($table, '$password', 'string');
2556
2557 // create the storage object
2558 $this->setPGTStorage(
2559 new CAS_PGTStorage_Db(
2560 $this, $dsn_or_pdo, $username, $password, $table, $driver_options
2561 )
2562 );
2563 }
2564
2573 public function setPGTStorageFile($path='')
2574 {
2575 // Sequence validation
2576 $this->ensureIsProxy();
2577
2578 // Argument validation
2579 if (gettype($path) != 'string')
2580 throw new CAS_TypeMismatchException($path, '$path', 'string');
2581
2582 // create the storage object
2583 $this->setPGTStorage(new CAS_PGTStorage_File($this, $path));
2584 }
2585
2586
2587 // ########################################################################
2588 // PGT VALIDATION
2589 // ########################################################################
2604 private function _validatePGT(&$validate_url,$text_response,$tree_response)
2605 {
2606 phpCAS::traceBegin();
2607 if ( $tree_response->getElementsByTagName("proxyGrantingTicket")->length == 0) {
2608 phpCAS::trace('<proxyGrantingTicket> not found');
2609 // authentication succeded, but no PGT Iou was transmitted
2610 throw new CAS_AuthenticationException(
2611 $this, 'Ticket validated but no PGT Iou transmitted',
2612 $validate_url, false/*$no_response*/, false/*$bad_response*/,
2613 $text_response
2614 );
2615 } else {
2616 // PGT Iou transmitted, extract it
2617 $pgt_iou = trim(
2618 $tree_response->getElementsByTagName("proxyGrantingTicket")->item(0)->nodeValue
2619 );
2620 if (preg_match('/^PGTIOU-[\.\-\w]+$/', $pgt_iou)) {
2621 $pgt = $this->_loadPGT($pgt_iou);
2622 if ( $pgt == false ) {
2623 phpCAS::trace('could not load PGT');
2624 throw new CAS_AuthenticationException(
2625 $this,
2626 'PGT Iou was transmitted but PGT could not be retrieved',
2627 $validate_url, false/*$no_response*/,
2628 false/*$bad_response*/, $text_response
2629 );
2630 }
2631 $this->_setPGT($pgt);
2632 } else {
2633 phpCAS::trace('PGTiou format error');
2634 throw new CAS_AuthenticationException(
2635 $this, 'PGT Iou was transmitted but has wrong format',
2636 $validate_url, false/*$no_response*/, false/*$bad_response*/,
2637 $text_response
2638 );
2639 }
2640 }
2641 phpCAS::traceEnd(true);
2642 return true;
2643 }
2644
2645 // ########################################################################
2646 // PGT VALIDATION
2647 // ########################################################################
2648
2658 public function retrievePT($target_service,&$err_code,&$err_msg)
2659 {
2660 // Argument validation
2661 if (gettype($target_service) != 'string')
2662 throw new CAS_TypeMismatchException($target_service, '$target_service', 'string');
2663
2664 phpCAS::traceBegin();
2665
2666 // by default, $err_msg is set empty and $pt to true. On error, $pt is
2667 // set to false and $err_msg to an error message. At the end, if $pt is false
2668 // and $error_msg is still empty, it is set to 'invalid response' (the most
2669 // commonly encountered error).
2670 $err_msg = '';
2671
2672 // build the URL to retrieve the PT
2673 $cas_url = $this->getServerProxyURL().'?targetService='
2674 .urlencode($target_service).'&pgt='.$this->_getPGT();
2675
2676 // open and read the URL
2677 if ( !$this->_readURL($cas_url, $headers, $cas_response, $err_msg) ) {
2678 phpCAS::trace(
2679 'could not open URL \''.$cas_url.'\' to validate ('.$err_msg.')'
2680 );
2681 $err_code = PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE;
2682 $err_msg = 'could not retrieve PT (no response from the CAS server)';
2683 phpCAS::traceEnd(false);
2684 return false;
2685 }
2686
2687 $bad_response = false;
2688
2689 if ( !$bad_response ) {
2690 // create new DOMDocument object
2691 $dom = new DOMDocument();
2692 // Fix possible whitspace problems
2693 $dom->preserveWhiteSpace = false;
2694 // read the response of the CAS server into a DOM object
2695 if ( !($dom->loadXML($cas_response))) {
2696 phpCAS::trace('dom->loadXML() failed');
2697 // read failed
2698 $bad_response = true;
2699 }
2700 }
2701
2702 if ( !$bad_response ) {
2703 // read the root node of the XML tree
2704 if ( !($root = $dom->documentElement) ) {
2705 phpCAS::trace('documentElement failed');
2706 // read failed
2707 $bad_response = true;
2708 }
2709 }
2710
2711 if ( !$bad_response ) {
2712 // insure that tag name is 'serviceResponse'
2713 if ( $root->localName != 'serviceResponse' ) {
2714 phpCAS::trace('localName failed');
2715 // bad root node
2716 $bad_response = true;
2717 }
2718 }
2719
2720 if ( !$bad_response ) {
2721 // look for a proxySuccess tag
2722 if ( $root->getElementsByTagName("proxySuccess")->length != 0) {
2723 $proxy_success_list = $root->getElementsByTagName("proxySuccess");
2724
2725 // authentication succeded, look for a proxyTicket tag
2726 if ( $proxy_success_list->item(0)->getElementsByTagName("proxyTicket")->length != 0) {
2727 $err_code = PHPCAS_SERVICE_OK;
2728 $err_msg = '';
2729 $pt = trim(
2730 $proxy_success_list->item(0)->getElementsByTagName("proxyTicket")->item(0)->nodeValue
2731 );
2732 phpCAS::trace('original PT: '.trim($pt));
2733 phpCAS::traceEnd($pt);
2734 return $pt;
2735 } else {
2736 phpCAS::trace('<proxySuccess> was found, but not <proxyTicket>');
2737 }
2738 } else if ($root->getElementsByTagName("proxyFailure")->length != 0) {
2739 // look for a proxyFailure tag
2740 $proxy_failure_list = $root->getElementsByTagName("proxyFailure");
2741
2742 // authentication failed, extract the error
2743 $err_code = PHPCAS_SERVICE_PT_FAILURE;
2744 $err_msg = 'PT retrieving failed (code=`'
2745 .$proxy_failure_list->item(0)->getAttribute('code')
2746 .'\', message=`'
2747 .trim($proxy_failure_list->item(0)->nodeValue)
2748 .'\')';
2749 phpCAS::traceEnd(false);
2750 return false;
2751 } else {
2752 phpCAS::trace('neither <proxySuccess> nor <proxyFailure> found');
2753 }
2754 }
2755
2756 // at this step, we are sure that the response of the CAS server was
2757 // illformed
2758 $err_code = PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE;
2759 $err_msg = 'Invalid response from the CAS server (response=`'
2760 .$cas_response.'\')';
2761
2762 phpCAS::traceEnd(false);
2763 return false;
2764 }
2765
2768 // ########################################################################
2769 // READ CAS SERVER ANSWERS
2770 // ########################################################################
2771
2790 private function _readURL($url, &$headers, &$body, &$err_msg)
2791 {
2792 phpCAS::traceBegin();
2793 $className = $this->_requestImplementation;
2794 $request = new $className();
2795
2796 if (count($this->_curl_options)) {
2797 $request->setCurlOptions($this->_curl_options);
2798 }
2799
2800 $request->setUrl($url);
2801
2802 if (empty($this->_cas_server_ca_cert) && !$this->_no_cas_server_validation) {
2803 phpCAS::error(
2804 'one of the methods phpCAS::setCasServerCACert() or phpCAS::setNoCasServerValidation() must be called.'
2805 );
2806 }
2807 if ($this->_cas_server_ca_cert != '') {
2808 $request->setSslCaCert(
2809 $this->_cas_server_ca_cert, $this->_cas_server_cn_validate
2810 );
2811 }
2812
2813 // add extra stuff if SAML
2814 if ($this->getServerVersion() == SAML_VERSION_1_1) {
2815 $request->addHeader("soapaction: http://www.oasis-open.org/committees/security");
2816 $request->addHeader("cache-control: no-cache");
2817 $request->addHeader("pragma: no-cache");
2818 $request->addHeader("accept: text/xml");
2819 $request->addHeader("connection: keep-alive");
2820 $request->addHeader("content-type: text/xml");
2821 $request->makePost();
2822 $request->setPostBody($this->_buildSAMLPayload());
2823 }
2824
2825 if ($request->send()) {
2826 $headers = $request->getResponseHeaders();
2827 $body = $request->getResponseBody();
2828 $err_msg = '';
2829 phpCAS::traceEnd(true);
2830 return true;
2831 } else {
2832 $headers = '';
2833 $body = '';
2834 $err_msg = $request->getErrorMessage();
2835 phpCAS::traceEnd(false);
2836 return false;
2837 }
2838 }
2839
2845 private function _buildSAMLPayload()
2846 {
2847 phpCAS::traceBegin();
2848
2849 //get the ticket
2850 $sa = urlencode($this->getTicket());
2851
2852 $body = SAML_SOAP_ENV.SAML_SOAP_BODY.SAMLP_REQUEST
2853 .SAML_ASSERTION_ARTIFACT.$sa.SAML_ASSERTION_ARTIFACT_CLOSE
2854 .SAMLP_REQUEST_CLOSE.SAML_SOAP_BODY_CLOSE.SAML_SOAP_ENV_CLOSE;
2855
2856 phpCAS::traceEnd($body);
2857 return ($body);
2858 }
2859
2862 // ########################################################################
2863 // ACCESS TO EXTERNAL SERVICES
2864 // ########################################################################
2865
2882 public function getProxiedService ($type)
2883 {
2884 // Sequence validation
2885 $this->ensureIsProxy();
2886 $this->ensureAuthenticationCallSuccessful();
2887
2888 // Argument validation
2889 if (gettype($type) != 'string')
2890 throw new CAS_TypeMismatchException($type, '$type', 'string');
2891
2892 switch ($type) {
2893 case PHPCAS_PROXIED_SERVICE_HTTP_GET:
2894 case PHPCAS_PROXIED_SERVICE_HTTP_POST:
2895 $requestClass = $this->_requestImplementation;
2896 $request = new $requestClass();
2897 if (count($this->_curl_options)) {
2898 $request->setCurlOptions($this->_curl_options);
2899 }
2900 $proxiedService = new $type($request, $this->_serviceCookieJar);
2901 if ($proxiedService instanceof CAS_ProxiedService_Testable) {
2902 $proxiedService->setCasClient($this);
2903 }
2904 return $proxiedService;
2905 case PHPCAS_PROXIED_SERVICE_IMAP;
2906 $proxiedService = new CAS_ProxiedService_Imap($this->_getUser());
2907 if ($proxiedService instanceof CAS_ProxiedService_Testable) {
2908 $proxiedService->setCasClient($this);
2909 }
2910 return $proxiedService;
2911 default:
2912 throw new CAS_InvalidArgumentException(
2913 "Unknown proxied-service type, $type."
2914 );
2915 }
2916 }
2917
2933 public function initializeProxiedService (CAS_ProxiedService $proxiedService)
2934 {
2935 // Sequence validation
2936 $this->ensureIsProxy();
2937 $this->ensureAuthenticationCallSuccessful();
2938
2939 $url = $proxiedService->getServiceUrl();
2940 if (!is_string($url)) {
2941 throw new CAS_ProxiedService_Exception(
2942 "Proxied Service ".get_class($proxiedService)
2943 ."->getServiceUrl() should have returned a string, returned a "
2944 .gettype($url)." instead."
2945 );
2946 }
2947 $pt = $this->retrievePT($url, $err_code, $err_msg);
2948 if (!$pt) {
2949 throw new CAS_ProxyTicketException($err_msg, $err_code);
2950 }
2951 $proxiedService->setProxyTicket($pt);
2952 }
2953
2968 public function serviceWeb($url,&$err_code,&$output)
2969 {
2970 // Sequence validation
2971 $this->ensureIsProxy();
2972 $this->ensureAuthenticationCallSuccessful();
2973
2974 // Argument validation
2975 if (gettype($url) != 'string')
2976 throw new CAS_TypeMismatchException($url, '$url', 'string');
2977
2978 try {
2979 $service = $this->getProxiedService(PHPCAS_PROXIED_SERVICE_HTTP_GET);
2980 $service->setUrl($url);
2981 $service->send();
2982 $output = $service->getResponseBody();
2983 $err_code = PHPCAS_SERVICE_OK;
2984 return true;
2985 } catch (CAS_ProxyTicketException $e) {
2986 $err_code = $e->getCode();
2987 $output = $e->getMessage();
2988 return false;
2989 } catch (CAS_ProxiedService_Exception $e) {
2990 $lang = $this->getLangObj();
2991 $output = sprintf(
2992 $lang->getServiceUnavailable(), $url, $e->getMessage()
2993 );
2994 $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
2995 return false;
2996 }
2997 }
2998
3018 public function serviceMail($url,$serviceUrl,$flags,&$err_code,&$err_msg,&$pt)
3019 {
3020 // Sequence validation
3021 $this->ensureIsProxy();
3022 $this->ensureAuthenticationCallSuccessful();
3023
3024 // Argument validation
3025 if (gettype($url) != 'string')
3026 throw new CAS_TypeMismatchException($url, '$url', 'string');
3027 if (gettype($serviceUrl) != 'string')
3028 throw new CAS_TypeMismatchException($serviceUrl, '$serviceUrl', 'string');
3029 if (gettype($flags) != 'integer')
3030 throw new CAS_TypeMismatchException($flags, '$flags', 'string');
3031
3032 try {
3033 $service = $this->getProxiedService(PHPCAS_PROXIED_SERVICE_IMAP);
3034 $service->setServiceUrl($serviceUrl);
3035 $service->setMailbox($url);
3036 $service->setOptions($flags);
3037
3038 $stream = $service->open();
3039 $err_code = PHPCAS_SERVICE_OK;
3040 $pt = $service->getImapProxyTicket();
3041 return $stream;
3042 } catch (CAS_ProxyTicketException $e) {
3043 $err_msg = $e->getMessage();
3044 $err_code = $e->getCode();
3045 $pt = false;
3046 return false;
3047 } catch (CAS_ProxiedService_Exception $e) {
3048 $lang = $this->getLangObj();
3049 $err_msg = sprintf(
3050 $lang->getServiceUnavailable(),
3051 $url,
3052 $e->getMessage()
3053 );
3054 $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
3055 $pt = false;
3056 return false;
3057 }
3058 }
3059
3062 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3063 // XX XX
3064 // XX PROXIED CLIENT FEATURES (CAS 2.0) XX
3065 // XX XX
3066 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3067
3068 // ########################################################################
3069 // PT
3070 // ########################################################################
3086 private $_proxies = array();
3087
3097 public function getProxies()
3098 {
3099 return $this->_proxies;
3100 }
3101
3110 private function _setProxies($proxies)
3111 {
3112 $this->_proxies = $proxies;
3113 if (!empty($proxies)) {
3114 // For proxy-authenticated requests people are not viewing the URL
3115 // directly since the client is another application making a
3116 // web-service call.
3117 // Because of this, stripping the ticket from the URL is unnecessary
3118 // and causes another web-service request to be performed. Additionally,
3119 // if session handling on either the client or the server malfunctions
3120 // then the subsequent request will not complete successfully.
3121 $this->setNoClearTicketsFromUrl();
3122 }
3123 }
3124
3130 private $_allowed_proxy_chains;
3131
3137 public function getAllowedProxyChains ()
3138 {
3139 if (empty($this->_allowed_proxy_chains)) {
3140 $this->_allowed_proxy_chains = new CAS_ProxyChain_AllowedList();
3141 }
3142 return $this->_allowed_proxy_chains;
3143 }
3144
3146 // ########################################################################
3147 // PT VALIDATION
3148 // ########################################################################
3166 public function validateCAS20(&$validate_url,&$text_response,&$tree_response, $renew=false)
3167 {
3168 phpCAS::traceBegin();
3169 phpCAS::trace($text_response);
3170 $result = false;
3171 // build the URL to validate the ticket
3172 if ($this->getAllowedProxyChains()->isProxyingAllowed()) {
3173 $validate_url = $this->getServerProxyValidateURL().'&ticket='
3174 .urlencode($this->getTicket());
3175 } else {
3176 $validate_url = $this->getServerServiceValidateURL().'&ticket='
3177 .urlencode($this->getTicket());
3178 }
3179
3180 if ( $this->isProxy() ) {
3181 // pass the callback url for CAS proxies
3182 $validate_url .= '&pgtUrl='.urlencode($this->_getCallbackURL());
3183 }
3184
3185 if ( $renew ) {
3186 // pass the renew
3187 $validate_url .= '&renew=true';
3188 }
3189
3190 // open and read the URL
3191 if ( !$this->_readURL($validate_url, $headers, $text_response, $err_msg) ) {
3192 phpCAS::trace(
3193 'could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')'
3194 );
3195 throw new CAS_AuthenticationException(
3196 $this, 'Ticket not validated', $validate_url,
3197 true/*$no_response*/
3198 );
3199 $result = false;
3200 }
3201
3202 // create new DOMDocument object
3203 $dom = new DOMDocument();
3204 // Fix possible whitspace problems
3205 $dom->preserveWhiteSpace = false;
3206 // CAS servers should only return data in utf-8
3207 $dom->encoding = "utf-8";
3208 // read the response of the CAS server into a DOMDocument object
3209 if ( !($dom->loadXML($text_response))) {
3210 // read failed
3211 throw new CAS_AuthenticationException(
3212 $this, 'Ticket not validated', $validate_url,
3213 false/*$no_response*/, true/*$bad_response*/, $text_response
3214 );
3215 $result = false;
3216 } else if ( !($tree_response = $dom->documentElement) ) {
3217 // read the root node of the XML tree
3218 // read failed
3219 throw new CAS_AuthenticationException(
3220 $this, 'Ticket not validated', $validate_url,
3221 false/*$no_response*/, true/*$bad_response*/, $text_response
3222 );
3223 $result = false;
3224 } else if ($tree_response->localName != 'serviceResponse') {
3225 // insure that tag name is 'serviceResponse'
3226 // bad root node
3227 throw new CAS_AuthenticationException(
3228 $this, 'Ticket not validated', $validate_url,
3229 false/*$no_response*/, true/*$bad_response*/, $text_response
3230 );
3231 $result = false;
3232 } else if ( $tree_response->getElementsByTagName("authenticationFailure")->length != 0) {
3233 // authentication failed, extract the error code and message and throw exception
3234 $auth_fail_list = $tree_response
3235 ->getElementsByTagName("authenticationFailure");
3236 throw new CAS_AuthenticationException(
3237 $this, 'Ticket not validated', $validate_url,
3238 false/*$no_response*/, false/*$bad_response*/,
3239 $text_response,
3240 $auth_fail_list->item(0)->getAttribute('code')/*$err_code*/,
3241 trim($auth_fail_list->item(0)->nodeValue)/*$err_msg*/
3242 );
3243 $result = false;
3244 } else if ($tree_response->getElementsByTagName("authenticationSuccess")->length != 0) {
3245 // authentication succeded, extract the user name
3246 $success_elements = $tree_response
3247 ->getElementsByTagName("authenticationSuccess");
3248 if ( $success_elements->item(0)->getElementsByTagName("user")->length == 0) {
3249 // no user specified => error
3250 throw new CAS_AuthenticationException(
3251 $this, 'Ticket not validated', $validate_url,
3252 false/*$no_response*/, true/*$bad_response*/, $text_response
3253 );
3254 $result = false;
3255 } else {
3256 $this->_setUser(
3257 trim(
3258 $success_elements->item(0)->getElementsByTagName("user")->item(0)->nodeValue
3259 )
3260 );
3261 $this->_readExtraAttributesCas20($success_elements);
3262 // Store the proxies we are sitting behind for authorization checking
3263 $proxyList = array();
3264 if ( sizeof($arr = $success_elements->item(0)->getElementsByTagName("proxy")) > 0) {
3265 foreach ($arr as $proxyElem) {
3266 phpCAS::trace("Found Proxy: ".$proxyElem->nodeValue);
3267 $proxyList[] = trim($proxyElem->nodeValue);
3268 }
3269 $this->_setProxies($proxyList);
3270 phpCAS::trace("Storing Proxy List");
3271 }
3272 // Check if the proxies in front of us are allowed
3273 if (!$this->getAllowedProxyChains()->isProxyListAllowed($proxyList)) {
3274 throw new CAS_AuthenticationException(
3275 $this, 'Proxy not allowed', $validate_url,
3276 false/*$no_response*/, true/*$bad_response*/,
3277 $text_response
3278 );
3279 $result = false;
3280 } else {
3281 $result = true;
3282 }
3283 }
3284 } else {
3285 throw new CAS_AuthenticationException(
3286 $this, 'Ticket not validated', $validate_url,
3287 false/*$no_response*/, true/*$bad_response*/,
3288 $text_response
3289 );
3290 $result = false;
3291 }
3292 if ($result) {
3293 $this->_renameSession($this->getTicket());
3294 }
3295 // at this step, Ticket has been validated and $this->_user has been set,
3296
3297 phpCAS::traceEnd($result);
3298 return $result;
3299 }
3300
3301
3311 private function _readExtraAttributesCas20($success_elements)
3312 {
3313 phpCAS::traceBegin();
3314
3315 $extra_attributes = array();
3316
3317 // "Jasig Style" Attributes:
3318 //
3319 // <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
3320 // <cas:authenticationSuccess>
3321 // <cas:user>jsmith</cas:user>
3322 // <cas:attributes>
3323 // <cas:attraStyle>RubyCAS</cas:attraStyle>
3324 // <cas:surname>Smith</cas:surname>
3325 // <cas:givenName>John</cas:givenName>
3326 // <cas:memberOf>CN=Staff,OU=Groups,DC=example,DC=edu</cas:memberOf>
3327 // <cas:memberOf>CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu</cas:memberOf>
3328 // </cas:attributes>
3329 // <cas:proxyGrantingTicket>PGTIOU-84678-8a9d2sfa23casd</cas:proxyGrantingTicket>
3330 // </cas:authenticationSuccess>
3331 // </cas:serviceResponse>
3332 //
3333 if ($this->_casAttributeParserCallbackFunction !== null
3334 && is_callable($this->_casAttributeParserCallbackFunction)
3335 ) {
3336 array_unshift($this->_casAttributeParserCallbackArgs, $success_elements->item(0));
3337 phpCas :: trace("Calling attritubeParser callback");
3338 $extra_attributes = call_user_func_array(
3339 $this->_casAttributeParserCallbackFunction,
3340 $this->_casAttributeParserCallbackArgs
3341 );
3342 } elseif ( $success_elements->item(0)->getElementsByTagName("attributes")->length != 0) {
3343 $attr_nodes = $success_elements->item(0)
3344 ->getElementsByTagName("attributes");
3345 phpCas :: trace("Found nested jasig style attributes");
3346 if ($attr_nodes->item(0)->hasChildNodes()) {
3347 // Nested Attributes
3348 foreach ($attr_nodes->item(0)->childNodes as $attr_child) {
3349 phpCas :: trace(
3350 "Attribute [".$attr_child->localName."] = "
3351 .$attr_child->nodeValue
3352 );
3353 $this->_addAttributeToArray(
3354 $extra_attributes, $attr_child->localName,
3355 $attr_child->nodeValue
3356 );
3357 }
3358 }
3359 } else {
3360 // "RubyCAS Style" attributes
3361 //
3362 // <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
3363 // <cas:authenticationSuccess>
3364 // <cas:user>jsmith</cas:user>
3365 //
3366 // <cas:attraStyle>RubyCAS</cas:attraStyle>
3367 // <cas:surname>Smith</cas:surname>
3368 // <cas:givenName>John</cas:givenName>
3369 // <cas:memberOf>CN=Staff,OU=Groups,DC=example,DC=edu</cas:memberOf>
3370 // <cas:memberOf>CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu</cas:memberOf>
3371 //
3372 // <cas:proxyGrantingTicket>PGTIOU-84678-8a9d2sfa23casd</cas:proxyGrantingTicket>
3373 // </cas:authenticationSuccess>
3374 // </cas:serviceResponse>
3375 //
3376 phpCas :: trace("Testing for rubycas style attributes");
3377 $childnodes = $success_elements->item(0)->childNodes;
3378 foreach ($childnodes as $attr_node) {
3379 switch ($attr_node->localName) {
3380 case 'user':
3381 case 'proxies':
3382 case 'proxyGrantingTicket':
3383 break;
3384 default:
3385 if (strlen(trim($attr_node->nodeValue))) {
3386 phpCas :: trace(
3387 "Attribute [".$attr_node->localName."] = ".$attr_node->nodeValue
3388 );
3389 $this->_addAttributeToArray(
3390 $extra_attributes, $attr_node->localName,
3391 $attr_node->nodeValue
3392 );
3393 }
3394 }
3395 }
3396 }
3397
3398 // "Name-Value" attributes.
3399 //
3400 // Attribute format from these mailing list thread:
3401 // http://jasig.275507.n4.nabble.com/CAS-attributes-and-how-they-appear-in-the-CAS-response-td264272.html
3402 // Note: This is a less widely used format, but in use by at least two institutions.
3403 //
3404 // <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
3405 // <cas:authenticationSuccess>
3406 // <cas:user>jsmith</cas:user>
3407 //
3408 // <cas:attribute name='attraStyle' value='Name-Value' />
3409 // <cas:attribute name='surname' value='Smith' />
3410 // <cas:attribute name='givenName' value='John' />
3411 // <cas:attribute name='memberOf' value='CN=Staff,OU=Groups,DC=example,DC=edu' />
3412 // <cas:attribute name='memberOf' value='CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu' />
3413 //
3414 // <cas:proxyGrantingTicket>PGTIOU-84678-8a9d2sfa23casd</cas:proxyGrantingTicket>
3415 // </cas:authenticationSuccess>
3416 // </cas:serviceResponse>
3417 //
3418 if (!count($extra_attributes)
3419 && $success_elements->item(0)->getElementsByTagName("attribute")->length != 0
3420 ) {
3421 $attr_nodes = $success_elements->item(0)
3422 ->getElementsByTagName("attribute");
3423 $firstAttr = $attr_nodes->item(0);
3424 if (!$firstAttr->hasChildNodes()
3425 && $firstAttr->hasAttribute('name')
3426 && $firstAttr->hasAttribute('value')
3427 ) {
3428 phpCas :: trace("Found Name-Value style attributes");
3429 // Nested Attributes
3430 foreach ($attr_nodes as $attr_node) {
3431 if ($attr_node->hasAttribute('name')
3432 && $attr_node->hasAttribute('value')
3433 ) {
3434 phpCas :: trace(
3435 "Attribute [".$attr_node->getAttribute('name')
3436 ."] = ".$attr_node->getAttribute('value')
3437 );
3438 $this->_addAttributeToArray(
3439 $extra_attributes, $attr_node->getAttribute('name'),
3440 $attr_node->getAttribute('value')
3441 );
3442 }
3443 }
3444 }
3445 }
3446
3447 $this->setAttributes($extra_attributes);
3448 phpCAS::traceEnd();
3449 return true;
3450 }
3451
3461 private function _addAttributeToArray(array &$attributeArray, $name, $value)
3462 {
3463 // If multiple attributes exist, add as an array value
3464 if (isset($attributeArray[$name])) {
3465 // Initialize the array with the existing value
3466 if (!is_array($attributeArray[$name])) {
3467 $existingValue = $attributeArray[$name];
3468 $attributeArray[$name] = array($existingValue);
3469 }
3470
3471 $attributeArray[$name][] = trim($value);
3472 } else {
3473 $attributeArray[$name] = trim($value);
3474 }
3475 }
3476
3479 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3480 // XX XX
3481 // XX MISC XX
3482 // XX XX
3483 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3484
3490 // ########################################################################
3491 // URL
3492 // ########################################################################
3499 private $_url = '';
3500
3501
3509 public function setURL($url)
3510 {
3511 // Argument Validation
3512 if (gettype($url) != 'string')
3513 throw new CAS_TypeMismatchException($url, '$url', 'string');
3514
3515 $this->_url = $url;
3516 }
3517
3524 public function getURL()
3525 {
3526 phpCAS::traceBegin();
3527 // the URL is built when needed only
3528 if ( empty($this->_url) ) {
3529 $final_uri = '';
3530 // remove the ticket if present in the URL
3531 $final_uri = ($this->_isHttps()) ? 'https' : 'http';
3532 $final_uri .= '://';
3533
3534 $final_uri .= $this->_getClientUrl();
3535 $request_uri = explode('?', $_SERVER['REQUEST_URI'], 2);
3536 $final_uri .= $request_uri[0];
3537
3538 if (isset($request_uri[1]) && $request_uri[1]) {
3539 $query_string= $this->_removeParameterFromQueryString('ticket', $request_uri[1]);
3540
3541 // If the query string still has anything left,
3542 // append it to the final URI
3543 if ($query_string !== '') {
3544 $final_uri .= "?$query_string";
3545 }
3546 }
3547
3548 phpCAS::trace("Final URI: $final_uri");
3549 $this->setURL($final_uri);
3550 }
3551 phpCAS::traceEnd($this->_url);
3552 return $this->_url;
3553 }
3554
3562 public function setBaseURL($url)
3563 {
3564 // Argument Validation
3565 if (gettype($url) != 'string')
3566 throw new CAS_TypeMismatchException($url, '$url', 'string');
3567
3568 return $this->_server['base_url'] = $url;
3569 }
3570
3571
3577 private function _getClientUrl()
3578 {
3579 $server_url = '';
3580 if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
3581 // explode the host list separated by comma and use the first host
3582 $hosts = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']);
3583 // see rfc7239#5.3 and rfc7230#2.7.1: port is in HTTP_X_FORWARDED_HOST if non default
3584 return $hosts[0];
3585 } else if (!empty($_SERVER['HTTP_X_FORWARDED_SERVER'])) {
3586 $server_url = $_SERVER['HTTP_X_FORWARDED_SERVER'];
3587 } else {
3588 if (empty($_SERVER['SERVER_NAME'])) {
3589 $server_url = $_SERVER['HTTP_HOST'];
3590 } else {
3591 $server_url = $_SERVER['SERVER_NAME'];
3592 }
3593 }
3594 if (!strpos($server_url, ':')) {
3595 if (empty($_SERVER['HTTP_X_FORWARDED_PORT'])) {
3596 $server_port = $_SERVER['SERVER_PORT'];
3597 } else {
3598 $ports = explode(',', $_SERVER['HTTP_X_FORWARDED_PORT']);
3599 $server_port = $ports[0];
3600 }
3601
3602 if ( ($this->_isHttps() && $server_port!=443)
3603 || (!$this->_isHttps() && $server_port!=80)
3604 ) {
3605 $server_url .= ':';
3606 $server_url .= $server_port;
3607 }
3608 }
3609 return $server_url;
3610 }
3611
3617 private function _isHttps()
3618 {
3619 if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
3620 return ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https');
3621 } elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTOCOL'])) {
3622 return ($_SERVER['HTTP_X_FORWARDED_PROTOCOL'] === 'https');
3623 } elseif ( isset($_SERVER['HTTPS'])
3624 && !empty($_SERVER['HTTPS'])
3625 && strcasecmp($_SERVER['HTTPS'], 'off') !== 0
3626 ) {
3627 return true;
3628 }
3629 return false;
3630
3631 }
3632
3643 private function _removeParameterFromQueryString($parameterName, $queryString)
3644 {
3645 $parameterName = preg_quote($parameterName);
3646 return preg_replace(
3647 "/&$parameterName(=[^&]*)?|^$parameterName(=[^&]*)?&?/",
3648 '', $queryString
3649 );
3650 }
3651
3662 private function _buildQueryUrl($url, $query)
3663 {
3664 $url .= (strstr($url, '?') === false) ? '?' : '&';
3665 $url .= $query;
3666 return $url;
3667 }
3668
3676 private function _renameSession($ticket)
3677 {
3678 phpCAS::traceBegin();
3679 if ($this->getChangeSessionID()) {
3680 if (!empty($this->_user)) {
3681 $old_session = $_SESSION;
3682 phpCAS :: trace("Killing session: ". session_id());
3683 session_destroy();
3684 // set up a new session, of name based on the ticket
3685 $session_id = $this->_sessionIdForTicket($ticket);
3686 phpCAS :: trace("Starting session: ". $session_id);
3687 session_id($session_id);
3688 session_start();
3689 phpCAS :: trace("Restoring old session vars");
3690 $_SESSION = $old_session;
3691 } else {
3692 phpCAS :: trace (
3693 'Session should only be renamed after successfull authentication'
3694 );
3695 }
3696 } else {
3697 phpCAS :: trace(
3698 "Skipping session rename since phpCAS is not handling the session."
3699 );
3700 }
3701 phpCAS::traceEnd();
3702 }
3703
3715 private function _sessionIdForTicket($ticket)
3716 {
3717 // Hash the ticket to ensure that the value meets the PHP 7.1 requirement
3718 // that session-ids have a length between 22 and 256 characters.
3719 return hash('sha256', $this->_sessionIdSalt . $ticket);
3720 }
3721
3727 private $_sessionIdSalt = '';
3728
3736 public function setSessionIdSalt($salt) {
3737 $this->_sessionIdSalt = (string)$salt;
3738 }
3739
3740 // ########################################################################
3741 // AUTHENTICATION ERROR HANDLING
3742 // ########################################################################
3759 private function _authError(
3760 $failure,
3761 $cas_url,
3762 $no_response,
3763 $bad_response='',
3764 $cas_response='',
3765 $err_code='',
3766 $err_msg=''
3767 ) {
3768 phpCAS::traceBegin();
3769 $lang = $this->getLangObj();
3770 $this->printHTMLHeader($lang->getAuthenticationFailed());
3771 printf(
3772 $lang->getYouWereNotAuthenticated(), htmlentities($this->getURL()),
3773 isset($_SERVER['SERVER_ADMIN']) ? $_SERVER['SERVER_ADMIN']:''
3774 );
3775 phpCAS::trace('CAS URL: '.$cas_url);
3776 phpCAS::trace('Authentication failure: '.$failure);
3777 if ( $no_response ) {
3778 phpCAS::trace('Reason: no response from the CAS server');
3779 } else {
3780 if ( $bad_response ) {
3781 phpCAS::trace('Reason: bad response from the CAS server');
3782 } else {
3783 switch ($this->getServerVersion()) {
3784 case CAS_VERSION_1_0:
3785 phpCAS::trace('Reason: CAS error');
3786 break;
3787 case CAS_VERSION_2_0:
3788 case CAS_VERSION_3_0:
3789 if ( empty($err_code) ) {
3790 phpCAS::trace('Reason: no CAS error');
3791 } else {
3792 phpCAS::trace(
3793 'Reason: ['.$err_code.'] CAS error: '.$err_msg
3794 );
3795 }
3796 break;
3797 }
3798 }
3799 phpCAS::trace('CAS response: '.$cas_response);
3800 }
3801 $this->printHTMLFooter();
3802 phpCAS::traceExit();
3803 throw new CAS_GracefullTerminationException();
3804 }
3805
3806 // ########################################################################
3807 // PGTIOU/PGTID and logoutRequest rebroadcasting
3808 // ########################################################################
3809
3814 private $_rebroadcast = false;
3815 private $_rebroadcast_nodes = array();
3816
3820 const HOSTNAME = 0;
3821 const IP = 1;
3822
3831 private function _getNodeType($nodeURL)
3832 {
3833 phpCAS::traceBegin();
3834 if (preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/", $nodeURL)) {
3835 phpCAS::traceEnd(self::IP);
3836 return self::IP;
3837 } else {
3838 phpCAS::traceEnd(self::HOSTNAME);
3839 return self::HOSTNAME;
3840 }
3841 }
3842
3850 public function addRebroadcastNode($rebroadcastNodeUrl)
3851 {
3852 // Argument validation
3853 if ( !(bool)preg_match("/^(http|https):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i", $rebroadcastNodeUrl))
3854 throw new CAS_TypeMismatchException($rebroadcastNodeUrl, '$rebroadcastNodeUrl', 'url');
3855
3856 // Store the rebroadcast node and set flag
3857 $this->_rebroadcast = true;
3858 $this->_rebroadcast_nodes[] = $rebroadcastNodeUrl;
3859 }
3860
3864 private $_rebroadcast_headers = array();
3865
3874 public function addRebroadcastHeader($header)
3875 {
3876 if (gettype($header) != 'string')
3877 throw new CAS_TypeMismatchException($header, '$header', 'string');
3878
3879 $this->_rebroadcast_headers[] = $header;
3880 }
3881
3885 const LOGOUT = 0;
3886 const PGTIOU = 1;
3887
3895 private function _rebroadcast($type)
3896 {
3897 phpCAS::traceBegin();
3898
3899 $rebroadcast_curl_options = array(
3900 CURLOPT_FAILONERROR => 1,
3901 CURLOPT_FOLLOWLOCATION => 1,
3902 CURLOPT_RETURNTRANSFER => 1,
3903 CURLOPT_CONNECTTIMEOUT => 1,
3904 CURLOPT_TIMEOUT => 4);
3905
3906 // Try to determine the IP address of the server
3907 if (!empty($_SERVER['SERVER_ADDR'])) {
3908 $ip = $_SERVER['SERVER_ADDR'];
3909 } else if (!empty($_SERVER['LOCAL_ADDR'])) {
3910 // IIS 7
3911 $ip = $_SERVER['LOCAL_ADDR'];
3912 }
3913 // Try to determine the DNS name of the server
3914 if (!empty($ip)) {
3915 $dns = gethostbyaddr($ip);
3916 }
3917 $multiClassName = 'CAS_Request_CurlMultiRequest';
3918 $multiRequest = new $multiClassName();
3919
3920 for ($i = 0; $i < sizeof($this->_rebroadcast_nodes); $i++) {
3921 if ((($this->_getNodeType($this->_rebroadcast_nodes[$i]) == self::HOSTNAME) && !empty($dns) && (stripos($this->_rebroadcast_nodes[$i], $dns) === false))
3922 || (($this->_getNodeType($this->_rebroadcast_nodes[$i]) == self::IP) && !empty($ip) && (stripos($this->_rebroadcast_nodes[$i], $ip) === false))
3923 ) {
3924 phpCAS::trace(
3925 'Rebroadcast target URL: '.$this->_rebroadcast_nodes[$i]
3926 .$_SERVER['REQUEST_URI']
3927 );
3928 $className = $this->_requestImplementation;
3929 $request = new $className();
3930
3931 $url = $this->_rebroadcast_nodes[$i].$_SERVER['REQUEST_URI'];
3932 $request->setUrl($url);
3933
3934 if (count($this->_rebroadcast_headers)) {
3935 $request->addHeaders($this->_rebroadcast_headers);
3936 }
3937
3938 $request->makePost();
3939 if ($type == self::LOGOUT) {
3940 // Logout request
3941 $request->setPostBody(
3942 'rebroadcast=false&logoutRequest='.$_POST['logoutRequest']
3943 );
3944 } else if ($type == self::PGTIOU) {
3945 // pgtIou/pgtId rebroadcast
3946 $request->setPostBody('rebroadcast=false');
3947 }
3948
3949 $request->setCurlOptions($rebroadcast_curl_options);
3950
3951 $multiRequest->addRequest($request);
3952 } else {
3953 phpCAS::trace(
3954 'Rebroadcast not sent to self: '
3955 .$this->_rebroadcast_nodes[$i].' == '.(!empty($ip)?$ip:'')
3956 .'/'.(!empty($dns)?$dns:'')
3957 );
3958 }
3959 }
3960 // We need at least 1 request
3961 if ($multiRequest->getNumRequests() > 0) {
3962 $multiRequest->send();
3963 }
3964 phpCAS::traceEnd();
3965 }
3966
3968 }
3969
3970 ?>
CAS_Client\getAuthenticationCallerFile
getAuthenticationCallerFile()
Definition: Client.php:844
CAS_Client\_setProxies
_setProxies($proxies)
Definition: Client.php:3110
CAS_Client\$_callback_mode
$_callback_mode
Definition: Client.php:2319
CAS_ProxyChain_AllowedList
Definition: AllowedList.php:43
CAS_Client\getLangObj
getLangObj()
Definition: Client.php:222
CAS_Client\$_cache_times_for_auth_recheck
$_cache_times_for_auth_recheck
Definition: Client.php:1303
CAS_Client\_rebroadcast
_rebroadcast($type)
Definition: Client.php:3895
CAS_Client\setServerLoginURL
setServerLoginURL($url)
Definition: Client.php:365
CAS_Client\$_rebroadcast
$_rebroadcast
Definition: Client.php:3814
CAS_Client\_getClientUrl
_getClientUrl()
Definition: Client.php:3577
CAS_Client\getUser
getUser()
Definition: Client.php:1118
CAS_Client\setPGTStorageFile
setPGTStorageFile($path='')
Definition: Client.php:2573
CAS_Client\$_cas_server_cn_validate
$_cas_server_cn_validate
Definition: Client.php:1925
CAS_Client\_loadPGT
_loadPGT($pgt_iou)
Definition: Client.php:2490
CAS_Client\setServerServiceValidateURL
setServerServiceValidateURL($url)
Definition: Client.php:382
PHPCAS_PROXIED_SERVICE_IMAP
const PHPCAS_PROXIED_SERVICE_IMAP
Definition: CAS.php:203
CAS_PGTStorage_Db
Definition: Db.php:46
CAS_Client\initializeProxiedService
initializeProxiedService(CAS_ProxiedService $proxiedService)
Definition: Client.php:2933
CAS_VERSION_1_0
const CAS_VERSION_1_0
Definition: CAS.php:74
phpCAS
Definition: CAS.php:278
$cas_url
$cas_url
Definition: config.example.php:89
CAS_Client\renewAuthentication
renewAuthentication()
Definition: Client.php:1251
CAS_Client\getAttributes
getAttributes()
Definition: Client.php:1172
phpCAS\error
static error($msg)
Definition: CAS.php:543
CAS_Client\printHTMLFooter
printHTMLFooter()
Definition: Client.php:129
CAS_Client\_ensureAuthenticationCalled
_ensureAuthenticationCalled()
Definition: Client.php:792
phpCAS\traceExit
static traceExit()
Definition: CAS.php:661
CAS_Client\$_authentication_caller
$_authentication_caller
Definition: Client.php:772
CAS_Client\retrievePT
retrievePT($target_service, &$err_code, &$err_msg)
Definition: Client.php:2658
SAML_VERSION_1_1
const SAML_VERSION_1_1
Definition: CAS.php:91
CAS_Client\setCasAttributeParserCallback
setCasAttributeParserCallback($function, array $additionalArgs=array())
Definition: Client.php:664
CAS_Client\_initPGTStorage
_initPGTStorage()
Definition: Client.php:2455
CAS_Client\_authError
_authError( $failure, $cas_url, $no_response, $bad_response='', $cas_response='', $err_code='', $err_msg='')
Definition: Client.php:3759
CAS_Client\setPGTStorage
setPGTStorage($storage)
Definition: Client.php:2506
CAS_Client\_getServerPort
_getServerPort()
Definition: Client.php:293
CAS_Client\_getServerHostname
_getServerHostname()
Definition: Client.php:283
CAS_Client\setSingleSignoutCallback
setSingleSignoutCallback($function, array $additionalArgs=array())
Definition: Client.php:728
CAS_VERSION_3_0
const CAS_VERSION_3_0
Definition: CAS.php:82
SAML_SOAP_ENV
const SAML_SOAP_ENV
Definition: CAS.php:101
if
if(isset( $_REQUEST[ 'logout']))
Definition: example_advanced_saml11.php:49
CAS_Client\PGTIOU
const PGTIOU
Definition: Client.php:3886
CAS_Client\hasAttributes
hasAttributes()
Definition: Client.php:1192
CAS_Client\$_cas_server_ca_cert
$_cas_server_ca_cert
Definition: Client.php:1912
CAS_Client\addRebroadcastHeader
addRebroadcastHeader($header)
Definition: Client.php:3874
CAS_Client\wasAuthenticationCalled
wasAuthenticationCalled()
Definition: Client.php:779
CAS_Client\getAttribute
getAttribute($key)
Definition: Client.php:1234
PHPCAS_SERVICE_OK
const PHPCAS_SERVICE_OK
Definition: CAS.php:168
CAS_Client\getServerProxyURL
getServerProxyURL()
Definition: Client.php:519
CAS_Client\$_serviceCookieJar
$_serviceCookieJar
Definition: Client.php:2235
CAS_Client\_removeParameterFromQueryString
_removeParameterFromQueryString($parameterName, $queryString)
Definition: Client.php:3643
CAS_Client\$_server
$_server
Definition: Client.php:262
CAS_Client\wasAuthenticationCallSuccessful
wasAuthenticationCallSuccessful()
Definition: Client.php:807
CAS_ProxiedService_Exception
Definition: Exception.php:40
CAS_Client\getServerProxyValidateURL
getServerProxyValidateURL()
Definition: Client.php:488
CAS_Request_RequestInterface
Definition: RequestInterface.php:40
CAS_ProxiedService
Definition: ProxiedService.php:47
CAS_Client\_setChangeSessionID
_setChangeSessionID($allowed)
Definition: Client.php:1062
phpCAS\traceEnd
static traceEnd($res='')
Definition: CAS.php:638
CAS_TypeMismatchException
Definition: TypeMismatchException.php:40
CAS_Client\setLang
setLang($lang)
Definition: Client.php:201
CAS_Client\_validatePGT
_validatePGT(&$validate_url, $text_response, $tree_response)
Definition: Client.php:2604
CAS_Client\getTicket
getTicket()
Definition: Client.php:1870
CAS_Client\_getServerBaseURL
_getServerBaseURL()
Definition: Client.php:313
PHPCAS_LANG_DEFAULT
const PHPCAS_LANG_DEFAULT
Definition: CAS.php:234
CAS_PGTStorage_File
Definition: File.php:45
phpCAS\trace
static trace($str)
Definition: CAS.php:579
CAS_Client\_isLogoutRequest
_isLogoutRequest()
Definition: Client.php:1720
CAS_Client\setRequestImplementation
setRequestImplementation($className)
Definition: Client.php:611
CAS_OutOfSequenceBeforeAuthenticationCallException
Definition: OutOfSequenceBeforeAuthenticationCallException.php:43
CAS_Client\ensureIsProxy
ensureIsProxy()
Definition: Client.php:745
CAS_Client\$_sessionIdSalt
$_sessionIdSalt
Definition: Client.php:3727
CAS_Client\isAuthenticated
isAuthenticated($renew=false)
Definition: Client.php:1388
CAS_Client\_isHttps
_isHttps()
Definition: Client.php:3617
CAS_Client\hasAttribute
hasAttribute($key)
Definition: Client.php:1206
CAS_Client\_wasPreviouslyAuthenticated
_wasPreviouslyAuthenticated()
Definition: Client.php:1549
CAS_Client\$_output_footer
$_output_footer
Definition: Client.php:120
CAS_Client\_hasPGT
_hasPGT()
Definition: Client.php:2293
CAS_Client\_htmlFilterOutput
_htmlFilterOutput($str)
Definition: Client.php:75
CAS_Client\getChangeSessionID
getChangeSessionID()
Definition: Client.php:1072
CAS_ProxiedService\setProxyTicket
setProxyTicket($proxyTicket)
CAS_Client\_getCallbackURL
_getCallbackURL()
Definition: Client.php:2360
CAS_Client\$_clearTicketsFromUrl
$_clearTicketsFromUrl
Definition: Client.php:626
else
if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']=='on') else
Definition: config.example.php:68
CAS_Client\$_user
$_user
Definition: Client.php:1096
CAS_Client\setCallbackURL
setCallbackURL($url)
Definition: Client.php:2383
CAS_ProxiedService_Imap
Definition: Imap.php:40
CAS_OutOfSequenceException
Definition: OutOfSequenceException.php:44
CAS_Client\_getNodeType
_getNodeType($nodeURL)
Definition: Client.php:3831
CAS_Client\_hasAttribute
_hasAttribute($key)
Definition: Client.php:1221
CAS_Client\$_rebroadcast_headers
$_rebroadcast_headers
Definition: Client.php:3864
CAS_Client\$_casAttributeParserCallbackArgs
$_casAttributeParserCallbackArgs
Definition: Client.php:651
CAS_Client\_buildQueryUrl
_buildQueryUrl($url, $query)
Definition: Client.php:3662
CAS_Client\logout
logout($params)
Definition: Client.php:1681
CAS_Client\IP
const IP
Definition: Client.php:3821
CAS_Client\$_pgt_storage
$_pgt_storage
Definition: Client.php:2447
CAS_Client\_getUser
_getUser()
Definition: Client.php:1134
CAS_Client\_callback
_callback()
Definition: Client.php:2400
PHPCAS_PROXIED_SERVICE_HTTP_POST
const PHPCAS_PROXIED_SERVICE_HTTP_POST
Definition: CAS.php:199
CAS_Client\setBaseURL
setBaseURL($url)
Definition: Client.php:3562
CAS_PGTStorage_AbstractStorage
Definition: AbstractStorage.php:46
CAS_InvalidArgumentException
Definition: InvalidArgumentException.php:40
$client
$client
Definition: create_pgt_storage_db_table.php:30
CAS_Client\markAuthenticationCall
markAuthenticationCall($auth)
Definition: Client.php:761
CAS_Client\getServerServiceValidateURL
getServerServiceValidateURL()
Definition: Client.php:431
CAS_Client\$_output_header
$_output_header
Definition: Client.php:90
CAS_Client\_setUser
_setUser($user)
Definition: Client.php:1105
CAS_Client\_readURL
_readURL($url, &$headers, &$body, &$err_msg)
Definition: Client.php:2790
CAS_Client\redirectToCas
redirectToCas($gateway=false, $renew=false)
Definition: Client.php:1653
CAS_Client\getServerLogoutURL
getServerLogoutURL()
Definition: Client.php:541
CAS_Client\$_signoutCallbackArgs
$_signoutCallbackArgs
Definition: Client.php:712
CAS_Client\setSessionIdSalt
setSessionIdSalt($salt)
Definition: Client.php:3736
CAS_ProxiedService_Testable
Definition: Testable.php:56
PHPCAS_SERVICE_NOT_AVAILABLE
const PHPCAS_SERVICE_NOT_AVAILABLE
Definition: CAS.php:187
CAS_ProxiedService\getServiceUrl
getServiceUrl()
CAS_Client\setServerProxyValidateURL
setServerProxyValidateURL($url)
Definition: Client.php:399
CAS_Client\_setCallbackMode
_setCallbackMode($callback_mode)
Definition: Client.php:2328
$driver_options
$driver_options
Definition: config.example.php:59
CAS_GracefullTerminationException
Definition: GracefullTerminationException.php:43
CAS_Client\setPostAuthenticateCallback
setPostAuthenticateCallback($function, array $additionalArgs=array())
Definition: Client.php:698
CAS_VERSION_2_0
const CAS_VERSION_2_0
Definition: CAS.php:78
phpCAS\getVerbose
static getVerbose()
Definition: CAS.php:496
CAS_Client\getProxies
getProxies()
Definition: Client.php:3097
CAS_Client\$_rebroadcast_nodes
$_rebroadcast_nodes
Definition: Client.php:3815
CAS_Client\_buildSAMLPayload
_buildSAMLPayload()
Definition: Client.php:2845
phpCAS\getVersion
static getVersion()
Definition: CAS.php:714
CAS_Client\_addAttributeToArray
_addAttributeToArray(array &$attributeArray, $name, $value)
Definition: Client.php:3461
CAS_Client\$_allowed_proxy_chains
$_allowed_proxy_chains
Definition: Client.php:3130
CAS_Client\$_postAuthenticateCallbackArgs
$_postAuthenticateCallbackArgs
Definition: Client.php:677
CAS_Client\LOGOUT
const LOGOUT
Definition: Client.php:3885
CAS_Client\validateCAS20
validateCAS20(&$validate_url, &$text_response, &$tree_response, $renew=false)
Definition: Client.php:3166
CAS_Client\setURL
setURL($url)
Definition: Client.php:3509
CAS_Client\$_url
$_url
Definition: Client.php:3499
CAS_Client\setAttributes
setAttributes($attributes)
Definition: Client.php:1162
CAS_Client\printHTMLHeader
printHTMLHeader($title)
Definition: Client.php:101
CAS_Client\ensureAuthenticationCallSuccessful
ensureAuthenticationCallSuccessful()
Definition: Client.php:822
CAS_Client\setHTMLHeader
setHTMLHeader($header)
Definition: Client.php:150
CAS_Client\_sessionIdForTicket
_sessionIdForTicket($ticket)
Definition: Client.php:3715
CAS_Client\hasTicket
hasTicket()
Definition: Client.php:1892
CAS_Client\validateSA
validateSA(&$validate_url, &$text_response, &$tree_response, $renew=false)
Definition: Client.php:2065
CAS_Client\setNoCasServerValidation
setNoCasServerValidation()
Definition: Client.php:1965
CAS_Client\setHTMLFooter
setHTMLFooter($footer)
Definition: Client.php:166
CAS_Client\getURL
getURL()
Definition: Client.php:3524
CAS_Client\$_callback_url
$_callback_url
Definition: Client.php:2351
CAS_Languages_LanguageInterface
Definition: LanguageInterface.php:44
CAS_Client\$_proxy
$_proxy
Definition: Client.php:2230
CAS_Client\getServerVersion
getServerVersion()
Definition: Client.php:273
CAS
CAS_Client\$_ticket
$_ticket
Definition: Client.php:1863
CAS_Client\setServerLogoutURL
setServerLogoutURL($url)
Definition: Client.php:557
CAS_Client\isSessionAuthenticated
isSessionAuthenticated()
Definition: Client.php:1536
CAS_Client\$_change_session_id
$_change_session_id
Definition: Client.php:1053
phpCAS\traceBegin
static traceBegin()
Definition: CAS.php:591
CAS_Client\getServerLoginURL
getServerLoginURL($gateway=false, $renew=false)
Definition: Client.php:337
CAS_Client\$_no_cas_server_validation
$_no_cas_server_validation
Definition: Client.php:1932
$serviceUrl
$serviceUrl
Definition: config.example.php:82
CAS_Client\getAuthenticationCallerLine
getAuthenticationCallerLine()
Definition: Client.php:858
CAS_Client\setNoClearTicketsFromUrl
setNoClearTicketsFromUrl()
Definition: Client.php:638
CAS_Client\forceAuthentication
forceAuthentication()
Definition: Client.php:1276
CAS_Client\isProxy
isProxy()
Definition: Client.php:2242
CAS_Client\__construct
__construct( $server_version, $proxy, $server_hostname, $server_port, $server_uri, $changeSessionID=true)
Definition: Client.php:902
CAS_Client\_isCallbackMode
_isCallbackMode()
Definition: Client.php:2339
CAS_Client\setServerSamlValidateURL
setServerSamlValidateURL($url)
Definition: Client.php:416
CAS_Client
Definition: Client.php:51
CAS_Client\$_attributes
$_attributes
Definition: Client.php:1153
CAS_Client\HOSTNAME
const HOSTNAME
Definition: Client.php:3820
CAS_Client\setCasServerCACert
setCasServerCACert($cert, $validate_cn)
Definition: Client.php:1944
CAS_Client\_setPGT
_setPGT($pgt)
Definition: Client.php:2283
CAS_Client\getAuthenticationCallerMethod
getAuthenticationCallerMethod()
Definition: Client.php:872
$auth
if(isset($_REQUEST['logout'])) if(isset($_REQUEST['login'])) $auth
Definition: example_gateway.php:47
CAS_Client\addRebroadcastNode
addRebroadcastNode($rebroadcastNodeUrl)
Definition: Client.php:3850
CAS_Client\setCacheTimesForAuthRecheck
setCacheTimesForAuthRecheck($n)
Definition: Client.php:1312
CAS_OutOfSequenceBeforeProxyException
Definition: OutOfSequenceBeforeProxyException.php:43
PHPCAS_PROXIED_SERVICE_HTTP_GET
const PHPCAS_PROXIED_SERVICE_HTTP_GET
Definition: CAS.php:195
CAS_Client\setExtraCurlOption
setExtraCurlOption($key, $value)
Definition: Client.php:579
CAS_Client\checkAuthentication
checkAuthentication()
Definition: Client.php:1327
CAS_Client\_storePGT
_storePGT($pgt, $pgt_iou)
Definition: Client.php:2474
CAS_Client\_renameSession
_renameSession($ticket)
Definition: Client.php:3676
CAS_Client\_setSessionAttributes
_setSessionAttributes($text_response)
Definition: Client.php:2162
CAS_Client\setPGTStorageDb
setPGTStorageDb( $dsn_or_pdo, $username='', $password='', $table='', $driver_options=null)
Definition: Client.php:2541
CAS_Client\$_lang
$_lang
Definition: Client.php:192
CAS_Client\getAllowedProxyChains
getAllowedProxyChains()
Definition: Client.php:3137
CAS_Client\_getServerURI
_getServerURI()
Definition: Client.php:303
CAS_Client\$_requestImplementation
$_requestImplementation
Definition: Client.php:601
CAS_ProxyTicketException
Definition: ProxyTicketException.php:41
CAS_Client\serviceMail
serviceMail($url, $serviceUrl, $flags, &$err_code, &$err_msg, &$pt)
Definition: Client.php:3018
CAS_Client\$_casAttributeParserCallbackFunction
$_casAttributeParserCallbackFunction
Definition: Client.php:646
CAS_Client\handleLogoutRequests
handleLogoutRequests($check_client=true, $allowed_clients=false)
Definition: Client.php:1735
CAS_Client\$_pgt
$_pgt
Definition: Client.php:2264
CAS_Client\$_proxies
$_proxies
Definition: Client.php:3086
CAS_Client\setTicket
setTicket($st)
Definition: Client.php:1882
CAS_Client\getProxiedService
getProxiedService($type)
Definition: Client.php:2882
CAS_Client\getServerSamlValidateURL
getServerSamlValidateURL()
Definition: Client.php:463
CAS_AuthenticationException
Definition: AuthenticationException.php:48
CAS_Client\$_curl_options
$_curl_options
Definition: Client.php:569
CAS_Client\$_signoutCallbackFunction
$_signoutCallbackFunction
Definition: Client.php:707
CAS_Client\validateCAS10
validateCAS10(&$validate_url, &$text_response, &$tree_response, $renew=false)
Definition: Client.php:1985
CAS_Client\$_postAuthenticateCallbackFunction
$_postAuthenticateCallbackFunction
Definition: Client.php:672
CAS_CookieJar
Definition: CookieJar.php:41
CAS_Client\serviceWeb
serviceWeb($url, &$err_code, &$output)
Definition: Client.php:2968
CAS_Client\_getPGT
_getPGT()
Definition: Client.php:2271