38include_once(dirname(__FILE__).
'/languages/languages.php');
41include_once(dirname(__FILE__).
'/PGTStorage/pgt-main.php');
112 (empty($this->_output_header)
113 ?
'<html><head><title>__TITLE__</title></head><body><h1>__TITLE__</h1>'
114 : $this->_output_header)
139 ?(
'<hr><address>phpCAS __PHPCAS_VERSION__ '.$this->
getString(
CAS_STR_USING_SERVER).
' <a href="__SERVER_BASE_URL__">__SERVER_BASE_URL__</a> (CAS __CAS_VERSION__)</a></address></body></html>')
140 :$this->_output_footer);
152 $this->_output_header =
$header;
164 $this->_output_footer = $footer;
196 if ( empty($this->_lang) )
226 if ( !isset($this->
_strings[$str]) ) {
227 trigger_error(
'string `'.$str.
'\' not defined
for language `
'.$this->getLang().'\
'',E_USER_ERROR);
244 include_once(dirname(__FILE__).
'/languages/'.
$lang.
'.php');
247 trigger_error(
'language `'.
$lang.
'\' is not implemented
',E_USER_ERROR);
249 $this->_lang = $lang;
253 // ########################################################################
255 // ########################################################################
285 var $_server = array(
287 'hostname
' => 'none
',
297 function getServerVersion()
299 return $this->_server['version
'];
307 function getServerHostname()
308 { return $this->_server['hostname
']; }
315 function getServerPort()
316 { return $this->_server['port
']; }
323 function getServerURI()
324 { return $this->_server['uri
']; }
331 function getServerBaseURL()
333 // the URL is build only when needed
334 if ( empty($this->_server['base_url
']) ) {
335 $this->_server['base_url
'] = 'https:
336 .$this->getServerHostname()
338 .$this->getServerPort()
339 .$this->getServerURI();
341 return $this->_server[
'base_url'];
356 if ( empty($this->_server[
'login_url']) ) {
358 $this->_server[
'login_url'] .=
'login?service=';
360 $this->_server[
'login_url'] .= urlencode($this->
getURL());
363 $this->_server[
'login_url'] .=
'&renew=true';
364 } elseif ($gateway) {
366 $this->_server[
'login_url'] .=
'&gateway=true';
370 return $this->_server[
'login_url'];
381 return $this->_server[
'login_url'] =
$url;
393 return $this->_server[
'service_validate_url'] =
$url;
405 return $this->_server[
'proxy_validate_url'] =
$url;
417 return $this->_server[
'saml_validate_url'] =
$url;
429 if ( empty($this->_server[
'service_validate_url']) ) {
432 $this->_server[
'service_validate_url'] = $this->
getServerBaseURL().
'validate';
435 $this->_server[
'service_validate_url'] = $this->
getServerBaseURL().
'serviceValidate';
440 return $this->_server[
'service_validate_url'].
'?service='.urlencode($this->
getURL());
451 if ( empty($this->_server[
'saml_validate_url']) ) {
454 $this->_server[
'saml_validate_url'] = $this->
getServerBaseURL().
'samlValidate';
459 return $this->_server[
'saml_validate_url'].
'?TARGET='.urlencode($this->
getURL());
469 if ( empty($this->_server[
'proxy_validate_url']) ) {
472 $this->_server[
'proxy_validate_url'] =
'';
475 $this->_server[
'proxy_validate_url'] = $this->
getServerBaseURL().
'proxyValidate';
480 return $this->_server[
'proxy_validate_url'].
'?service='.urlencode($this->
getURL());
491 if ( empty($this->_server[
'proxy_url']) ) {
494 $this->_server[
'proxy_url'] =
'';
501 return $this->_server[
'proxy_url'];
512 if ( empty($this->_server[
'logout_url']) ) {
515 return $this->_server[
'logout_url'];
526 return $this->_server[
'logout_url'] =
$url;
539 $this->_curl_options[$key] = $value;
551 # mantis: 0013115: CAS not work on HTTPS
581 $start_session =
true) {
586 if (version_compare(PHP_VERSION,
'5',
'>=') && ini_get(
'zend.ze1_compatibility_mode')) {
587 phpCAS::error(
'phpCAS cannot support zend.ze1_compatibility_mode. Sorry.');
589 $this->_start_session = $start_session;
591 if ($this->_start_session && session_id())
593 phpCAS :: error(
"Another session was started before phpcas. Either disable the session" .
594 " handling for phpcas in the client() call or modify your application to leave" .
595 " session handling to phpcas");
606 $this->_proxy = $proxy;
609 switch ($server_version) {
622 .
'\') is not supported by
phpCAS '
623 .phpCAS::getVersion());
625 $this->_server['version
'] = $server_version;
628 if ( empty($server_hostname)
629 || !preg_match('/[\.\d\-abcdefghijklmnopqrstuvwxyz]*/
',$server_hostname) ) {
630 phpCAS::error('bad CAS server hostname (`
'.$server_hostname.'\
')');
632 $this->_server[
'hostname'] = $server_hostname;
635 if ( $server_port == 0
636 || !is_int($server_port) ) {
637 phpCAS::error(
'bad CAS server port (`'.$server_hostname.
'\')
');
639 $this->_server['port
'] = $server_port;
642 if ( !preg_match('/[\.\d\-_abcdefghijklmnopqrstuvwxyz\/]*/
',$server_uri) ) {
643 phpCAS::error('bad CAS server URI (`
'.$server_uri.'\
')');
646 $server_uri = preg_replace(
'/\/\//',
'/',
'/'.$server_uri.
'/');
647 $this->_server[
'uri'] = $server_uri;
657 phpCAS::error(
'CAS proxies must be secured to use phpCAS; PGT\'s will not be received from the CAS server');
661 $ticket = (isset(
$_GET[
'ticket']) ?
$_GET[
'ticket'] :
null);
664 if( preg_match(
'/^ST-/',$ticket) ) {
667 $this->setST($ticket);
668 //ticket has been taken into account, unset it to hide it to applications
669 unset($_GET['ticket
']);
670 } else if ( !empty($ticket) ) {
671 //ill-formed ticket, halt
672 phpCAS::error('ill-formed ticket found in the URL (ticket=`
'.htmlentities($ticket).'\
')');
676 if( preg_match(
'/^ST-/',$ticket) ) {
678 $this->setST($ticket);
679 unset($_GET['ticket
']);
681 elseif(preg_match('/PT-/
', $ticket)) {
682 phpCAS::trace('PT \
''.$ticket.
'\' found
');
683 $this->setPT($ticket);
684 unset($_GET['ticket
']);
685 } else if ( !empty($ticket) ) {
686 //ill-formed ticket, halt
687 phpCAS::error('ill-formed ticket found in the URL (ticket=`
'.htmlentities($ticket).'\
')');
691 if( preg_match(
'/^[SP]T-/',$ticket) ) {
693 $this->setSA($ticket);
694 unset($_GET['ticket
']);
695 } else if ( !empty($ticket) ) {
696 //ill-formed ticket, halt
697 phpCAS::error('ill-formed ticket found in the URL (ticket=`
'.htmlentities($ticket).'\
')');
722 $this->_start_session = session;
727 $this->_start_session = session;
736 if($this->_start_session){
737 if (!empty ($this->_user))
743 if(version_compare(PHP_VERSION,
'5.3.0',
'<'))
745 include_once
'./Services/Init/classes/class.ilInitialisation.php';
750 $session_id = preg_replace(
'/[^\w]/',
'', $ticket);
752 session_id($session_id);
758 phpCAS :: error(
'Session should only be renamed after successfull authentication');
761 phpCAS :: trace(
"Skipping session rename since phpCAS is not handling the session.");
795 $this->_user = $user;
807 if ( empty($this->_user) ) {
808 phpCAS::error(
'this method should be used only after '.__CLASS__.
'::forceAuthentication() or '.__CLASS__.
'::isAuthenticated()');
831 { $this->_attributes = $attributes; }
834 if ( empty($this->_user) ) {
835 phpCAS::error(
'this method should be used only after '.__CLASS__.
'::forceAuthentication() or '.__CLASS__.
'::isAuthenticated()');
841 {
return !empty($this->_attributes); }
844 {
return (is_array($this->_attributes) && array_key_exists($key, $this->_attributes)); }
848 return $this->_attributes[$key];
861 if( isset(
$_SESSION[
'phpCAS'][
'auth_checked'] ) )
862 unset(
$_SESSION[
'phpCAS'][
'auth_checked']);
888 if (isset(
$_SESSION[
'phpCAS'][
'auth_checked'])) {
889 unset(
$_SESSION[
'phpCAS'][
'auth_checked']);
916 $this->_cache_times_for_auth_recheck =
$n;
931 }
else if (isset(
$_SESSION[
'phpCAS'][
'auth_checked'])) {
933 unset(
$_SESSION[
'phpCAS'][
'auth_checked']);
941 if (! isset(
$_SESSION[
'phpCAS'][
'unauth_count']) )
942 $_SESSION[
'phpCAS'][
'unauth_count'] = -2;
944 if ((
$_SESSION[
'phpCAS'][
'unauth_count'] != -2 && $this->_cache_times_for_auth_recheck == -1)
945 || (
$_SESSION[
'phpCAS'][
'unauth_count'] >= 0 &&
$_SESSION[
'phpCAS'][
'unauth_count'] < $this->_cache_times_for_auth_recheck))
949 if ($this->_cache_times_for_auth_recheck != -1)
952 phpCAS::trace(
'user is not authenticated (cached for '.
$_SESSION[
'phpCAS'][
'unauth_count'].
' times of '.$this->_cache_times_for_auth_recheck.
')');
956 phpCAS::trace(
'user is not authenticated (cached for until login pressed)');
962 $_SESSION[
'phpCAS'][
'auth_checked'] =
true;
990 phpCAS::trace(
'ticket was present and will be discarded, use renewAuthenticate()');
991 header(
'Location: '.$this->
getURL());
996 phpCAS::trace(
'user was already authenticated, no need to look for tickets');
1001 if ( $this->
hasST() ) {
1004 $this->validateST($validate_url,$text_response,$tree_response); // if it fails, it halts
1005 phpCAS::trace('ST `
'.$this->getST().'\
' was validated');
1007 $this->
validatePGT($validate_url,$text_response,$tree_response);
1009 $_SESSION['phpCAS']['pgt
'] = $this->getPGT();
1011 $_SESSION['phpCAS']['user
'] = $this->getUser();
1014 elseif ( $this->hasPT() ) {
1015 // if a Proxy Ticket was given, validate it
1016 phpCAS::trace('PT `
'.$this->getPT().'\
' is present');
1017 $this->
validatePT($validate_url,$text_response,$tree_response);
1019 if ( $this->isProxy() ) {
1020 $this->validatePGT($validate_url,$text_response,$tree_response); // idem
1021 phpCAS::trace('PGT `
'.$this->getPGT().'\
' was validated');
1027 elseif ( $this->
hasSA() ) {
1030 $this->validateSA($validate_url,$text_response,$tree_response); // if it fails, it halts
1031 phpCAS::trace('SA `
'.$this->getSA().'\
' was validated');
1043 header(
'Location: '.$this->
getURL());
1059 return !empty(
$_SESSION[
'phpCAS'][
'user']);
1093 // unset all tickets to enforce authentication
1094 unset($_SESSION['phpCAS']);
1097 } elseif ( !$this->isSessionAuthenticated() && !empty($_SESSION['phpCAS']['pgt
']) ) {
1098 // these two variables should be empty or not empty at the same time
1099 phpCAS::trace('PGT found (`
'.$_SESSION['phpCAS']['pgt
'].'\
') but username is empty');
1112 if(isset(
$_SESSION[
'phpCAS'][
'attributes'])){
1136 header(
'Location: '.$cas_url);
1157 $paramSeparator =
'?';
1159 $cas_url = $cas_url . $paramSeparator .
"url=" . urlencode(
$params[
'url']);
1160 $paramSeparator =
'&';
1162 if (isset(
$params[
'service'])) {
1163 $cas_url = $cas_url . $paramSeparator .
"service=" . urlencode(
$params[
'service']);
1165 header(
'Location: '.$cas_url);
1184 return !empty(
$_POST[
'logoutRequest']);
1209 if(!$this->_start_session){
1210 phpCAS::log(
"phpCAS can't handle logout requests if it does not manage the session.");
1214 if ($check_client) {
1215 if (!$allowed_clients) {
1218 $client_ip =
$_SERVER[
'REMOTE_ADDR'];
1219 $client = gethostbyaddr($client_ip);
1222 foreach ($allowed_clients as $allowed_client) {
1223 if ((
$client == $allowed_client) or ($client_ip == $allowed_client)) {
1224 phpCAS::log(
"Allowed client '".$allowed_client.
"' matches, logout request is allowed");
1228 phpCAS::log(
"Allowed client '".$allowed_client.
"' does not match");
1233 printf(
"Unauthorized!");
1241 preg_match(
"|<samlp:SessionIndex>(.*)</samlp:SessionIndex>|",
$_POST[
'logoutRequest'], $tick, PREG_OFFSET_CAPTURE, 3);
1242 $wrappedSamlSessionIndex = preg_replace(
'|<samlp:SessionIndex>|',
'',$tick[0][0]);
1243 $ticket2logout = preg_replace(
'|</samlp:SessionIndex>|',
'',$wrappedSamlSessionIndex);
1245 $session_id = preg_replace(
'/[^\w]/',
'',$ticket2logout);
1254 session_id($session_id);
1255 $_COOKIE[session_name()]=$session_id;
1256 $_GET[session_name()]=$session_id;
1262 printf(
"Disconnected!");
1307 { $this->_st = $st; }
1315 {
return !empty($this->_st); }
1358 $this->_cas_server_cert = $cert;
1368 $this->_cas_server_ca_cert = $cert;
1376 $this->_no_cas_server_validation =
true;
1392 function validateST($validate_url,&$text_response,&$tree_response)
1403 if ( !$this->
readURL($validate_url,
'',$headers,$text_response,$err_msg) ) {
1404 phpCAS::trace(
'could not open URL \''.$validate_url.
'\' to validate (
'.$err_msg.')
');
1405 $this->authError('ST not validated
',
1407 TRUE/*$no_response*/);
1410 // analyze the result depending on the version
1411 switch ($this->getServerVersion()) {
1412 case CAS_VERSION_1_0:
1413 if (preg_match('/^no\n/
',$text_response)) {
1414 phpCAS::trace('ST has not been validated
');
1415 $this->authError('ST not validated
',
1417 FALSE/*$no_response*/,
1418 FALSE/*$bad_response*/,
1421 if (!preg_match('/^yes\n/
',$text_response)) {
1422 phpCAS::trace('ill-formed response
');
1423 $this->authError('ST not validated
',
1425 FALSE/*$no_response*/,
1426 TRUE/*$bad_response*/,
1429 // ST has been validated, extract the user name
1430 $arr = preg_split('/\n/
',$text_response);
1431 $this->setUser(trim($arr[1]));
1433 case CAS_VERSION_2_0:
1434 // read the response of the CAS server into a DOM object
1435 if ( !($dom = domxml_open_mem($text_response))) {
1437 $this->authError('ST not validated
',
1439 FALSE/*$no_response*/,
1440 TRUE/*$bad_response*/,
1443 // read the root node of the XML tree
1444 if ( !($tree_response = $dom->document_element()) ) {
1445 phpCAS::trace('document_element() failed
');
1446 $this->authError('ST not validated
',
1448 FALSE/*$no_response*/,
1449 TRUE/*$bad_response*/,
1452 // insure that tag name is 'serviceResponse
'
1453 if ( $tree_response->node_name() != 'serviceResponse
' ) {
1454 phpCAS::trace('bad XML root node (should be `serviceResponse\
' instead of `'.$tree_response->node_name().
'\'');
1455 $this->authError(
'ST not validated',
1461 if (
sizeof($success_elements = $tree_response->get_elements_by_tagname(
"authenticationSuccess")) != 0) {
1463 if ( sizeof($user_elements = $success_elements[0]->get_elements_by_tagname(
"user")) == 0) {
1464 phpCAS::trace(
'<authenticationSuccess> found, but no <user>');
1465 $this->authError(
'ST not validated',
1471 $user = trim($user_elements[0]->get_content());
1475 }
else if (
sizeof($failure_elements = $tree_response->get_elements_by_tagname(
"authenticationFailure")) != 0) {
1483 $failure_elements[0]->get_attribute(
'code'),
1484 trim($failure_elements[0]->get_content()));
1486 phpCAS::trace(
'neither <authenticationSuccess> nor <authenticationFailure> found');
1495 $this->renameSession($this->getST());
1522 function validateSA($validate_url,&$text_response,&$tree_response)
1527 $validate_url = $this->getServerSamlValidateURL();
1530 if ( !$this->readURL($validate_url,
'',$headers,$text_response,$err_msg) ) {
1531 phpCAS::trace(
'could not open URL \''.$validate_url.
'\' to validate (
'.$err_msg.')
');
1532 $this->authError('SA not validated
', $validate_url, TRUE/*$no_response*/);
1535 phpCAS::trace('server version:
'.$this->getServerVersion());
1537 // analyze the result depending on the version
1538 switch ($this->getServerVersion()) {
1539 case SAML_VERSION_1_1:
1541 // read the response of the CAS server into a DOM object
1542 if ( !($dom = domxml_open_mem($text_response))) {
1544 $this->authError('SA not validated
',
1546 FALSE/*$no_response*/,
1547 TRUE/*$bad_response*/,
1550 // read the root node of the XML tree
1551 if ( !($tree_response = $dom->document_element()) ) {
1552 phpCAS::trace('document_element() failed
');
1553 $this->authError('SA not validated
',
1555 FALSE/*$no_response*/,
1556 TRUE/*$bad_response*/,
1559 // insure that tag name is 'Envelope
'
1560 if ( $tree_response->node_name() != 'Envelope
' ) {
1561 phpCAS::trace('bad XML root node (should be `Envelope\
' instead of `'.$tree_response->node_name().
'\'');
1562 $this->authError(
'SA not validated',
1569 if (
sizeof($success_elements = $tree_response->get_elements_by_tagname(
"NameIdentifier")) != 0) {
1570 phpCAS::trace(
'NameIdentifier found');
1571 $user = trim($success_elements[0]->get_content());
1572 phpCAS::trace(
'user = `'.$user.
'`');
1573 $this->setUser($user);
1574 $this->setSessionAttributes($text_response);
1576 phpCAS::trace(
'no <NameIdentifier> tag found in SAML payload');
1577 $this->authError(
'SA not validated',
1585 $this->renameSession($this->getSA());
1610 $attr_array = array();
1613 $xPath = $dom->xpath_new_context();
1614 $xPath->xpath_register_ns(
'samlp',
'urn:oasis:names:tc:SAML:1.0:protocol');
1615 $xPath->xpath_register_ns(
'saml',
'urn:oasis:names:tc:SAML:1.0:assertion');
1616 $nodelist = $xPath->xpath_eval(
"//saml:Attribute");
1618 $attrs = $nodelist->nodeset;
1619 foreach($attrs as $attr){
1620 $xres = $xPath->xpath_eval(
"saml:AttributeValue", $attr);
1621 $name = $attr->get_attribute(
"AttributeName");
1622 $value_array = array();
1623 foreach($xres->nodeset as $node){
1624 $value_array[] = $node->get_content();
1626 $attr_array[$name] = $value_array;
1630 foreach($attr_array as $attr_key => $attr_value) {
1631 if(count($attr_value) > 1) {
1632 $this->_attributes[$attr_key] = $attr_value;
1636 $this->_attributes[$attr_key] = $attr_value[0];
1683 return $this->_proxy;
1710 {
return $this->_pgt; }
1718 { $this->_pgt = $pgt; }
1726 {
return !empty($this->_pgt); }
1750 var $_callback_mode = FALSE;
1761 $this->_callback_mode = $callback_mode;
1774 return $this->_callback_mode;
1785 var $_callback_url =
'';
1799 if ( empty($this->_callback_url) ) {
1802 $final_uri =
'https://';
1806 if(empty(
$_SERVER[
'HTTP_X_FORWARDED_SERVER'])){
1810 if (empty(
$_SERVER[
'SERVER_NAME'])) {
1811 $final_uri .=
$_SERVER[
'HTTP_HOST'];
1813 $final_uri .=
$_SERVER[
'SERVER_NAME'];
1816 $final_uri .=
$_SERVER[
'HTTP_X_FORWARDED_SERVER'];
1818 if ( ($this->isHttps() &&
$_SERVER[
'SERVER_PORT']!=443)
1819 || (!$this->isHttps() &&
$_SERVER[
'SERVER_PORT']!=80) ) {
1821 $final_uri .=
$_SERVER[
'SERVER_PORT'];
1823 $request_uri =
$_SERVER[
'REQUEST_URI'];
1824 $request_uri = preg_replace(
'/\?.*$/',
'',$request_uri);
1825 $final_uri .= $request_uri;
1826 $this->setCallbackURL($final_uri);
1828 return $this->_callback_url;
1840 return $this->_callback_url =
$url;
1852 $this->printHTMLHeader(
'phpCAS callback');
1853 $pgt_iou =
$_GET[
'pgtIou'];
1854 $pgt =
$_GET[
'pgtId'];
1855 phpCAS::trace(
'Storing PGT `'.$pgt.
'\' (
id=`
'.$pgt_iou.'\
')');
1856 echo
'<p>Storing PGT `'.$pgt.
'\' (
id=`
'.$pgt_iou.'\
').</p>';
1857 $this->storePGT($pgt,$pgt_iou);
1858 $this->printHTMLFooter();
1881 var $_pgt_storage =
null;
1892 if ( !is_object($this->_pgt_storage) ) {
1893 $this->setPGTStorageFile();
1897 $this->_pgt_storage->init();
1911 $this->initPGTStorage();
1913 $this->_pgt_storage->write($pgt,$pgt_iou);
1928 $this->initPGTStorage();
1930 return $this->_pgt_storage->read($pgt_iou);
1946 if ( is_object($this->_pgt_storage) ) {
1980 if ( is_object($this->_pgt_storage) ) {
1985 trigger_error(
'PGT storage into database is an experimental feature, use at your own risk',E_USER_WARNING);
1988 $this->_pgt_storage =
new PGTStorageDB($this,$user,$password,$database_type,$hostname,$port,$database,$table);
2011 if (
sizeof($arr = $tree_response->get_elements_by_tagname(
"proxyGrantingTicket")) == 0) {
2014 $this->authError(
'Ticket validated but no PGT Iou transmitted',
2021 $pgt_iou = trim($arr[0]->get_content());
2022 $pgt = $this->loadPGT($pgt_iou);
2023 if ( $pgt == FALSE ) {
2025 $this->authError(
'PGT Iou was transmitted but PGT could not be retrieved',
2031 $this->setPGT($pgt);
2065 $cas_url = $this->getServerProxyURL().
'?targetService='.urlencode($target_service).
'&pgt='.$this->getPGT();
2068 if ( !$this->readURL($cas_url,
'',$headers,$cas_response,$err_msg) ) {
2069 phpCAS::trace(
'could not open URL \''.$cas_url.
'\' to validate (
'.$err_msg.')
');
2070 $err_code = PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE;
2071 $err_msg = 'could not retrieve PT (no response from the CAS server)
';
2072 phpCAS::traceEnd(FALSE);
2076 $bad_response = FALSE;
2078 if ( !$bad_response ) {
2079 // read the response of the CAS server into a DOM object
2080 if ( !($dom = @domxml_open_mem($cas_response))) {
2083 $bad_response = TRUE;
2087 if ( !$bad_response ) {
2088 // read the root node of the XML tree
2089 if ( !($root = $dom->document_element()) ) {
2090 phpCAS::trace('document_element() failed
');
2092 $bad_response = TRUE;
2096 if ( !$bad_response ) {
2097 // insure that tag name is 'serviceResponse
'
2098 if ( $root->node_name() != 'serviceResponse
' ) {
2099 phpCAS::trace('node_name() failed
');
2101 $bad_response = TRUE;
2105 if ( !$bad_response ) {
2106 // look for a proxySuccess tag
2107 if ( sizeof($arr = $root->get_elements_by_tagname("proxySuccess")) != 0) {
2108 // authentication succeded, look for a proxyTicket tag
2109 if ( sizeof($arr = $root->get_elements_by_tagname("proxyTicket")) != 0) {
2110 $err_code = PHPCAS_SERVICE_OK;
2112 phpCAS::trace('original PT:
'.trim($arr[0]->get_content()));
2113 $pt = trim($arr[0]->get_content());
2114 phpCAS::traceEnd($pt);
2117 phpCAS::trace('<proxySuccess> was found, but not <proxyTicket>
');
2120 // look for a proxyFailure tag
2121 else if ( sizeof($arr = $root->get_elements_by_tagname("proxyFailure")) != 0) {
2122 // authentication failed, extract the error
2123 $err_code = PHPCAS_SERVICE_PT_FAILURE;
2124 $err_msg = 'PT retrieving failed (code=`
'
2125 .$arr[0]->get_attribute('code
')
2127 .trim($arr[0]->get_content())
2129 phpCAS::traceEnd(FALSE);
2132 phpCAS::trace('neither <proxySuccess> nor <proxyFailure> found
');
2136 // at this step, we are sure that the response of the CAS server was ill-formed
2137 $err_code = PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE;
2138 $err_msg = 'Invalid response from the CAS server (response=`
'.$cas_response.'\
')';
2173 $ch = curl_init(
$url);
2175 if (version_compare(PHP_VERSION,
'5.1.3',
'>=')) {
2177 curl_setopt_array($ch, $this->_curl_options);
2179 foreach ($this->_curl_options as $key => $value) {
2180 curl_setopt($ch, $key, $value);
2184 if ($this->_cas_server_cert ==
'' && $this->_cas_server_ca_cert ==
'' && !$this->_no_cas_server_validation) {
2185 phpCAS::error(
'one of the methods phpCAS::setCasServerCert(), phpCAS::setCasServerCACert() or phpCAS::setNoCasServerValidation() must be called.');
2187 if ($this->_cas_server_cert !=
'' && $this->_cas_server_ca_cert !=
'') {
2189 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
2190 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
2191 curl_setopt($ch, CURLOPT_SSLCERT, $this->_cas_server_cert);
2192 curl_setopt($ch, CURLOPT_CAINFO, $this->_cas_server_ca_cert);
2193 curl_setopt($ch, CURLOPT_VERBOSE,
'1');
2194 phpCAS::trace(
'CURL: Set all required opts for mutual authentication ------');
2195 }
else if ($this->_cas_server_cert !=
'' ) {
2196 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
2197 curl_setopt($ch, CURLOPT_SSLCERT, $this->_cas_server_cert);
2198 }
else if ($this->_cas_server_ca_cert !=
'') {
2199 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
2200 curl_setopt($ch, CURLOPT_CAINFO, $this->_cas_server_ca_cert);
2202 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
2203 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
2207 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
2209 $this->_curl_headers = array();
2210 curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this,
'_curl_read_headers'));
2212 if ( is_array($cookies) ) {
2213 curl_setopt($ch,CURLOPT_COOKIE,implode(
';',$cookies));
2216 if ($this->hasSA()) {
2217 $more_headers = array (
"soapaction: http://www.oasis-open.org/committees/security",
2218 "cache-control: no-cache",
2221 "connection: keep-alive",
2222 "content-type: text/xml");
2224 curl_setopt($ch, CURLOPT_HTTPHEADER, $more_headers);
2225 curl_setopt($ch, CURLOPT_POST, 1);
2226 $data = $this->buildSAMLPayload();
2228 curl_setopt($ch, CURLOPT_POSTFIELDS,
$data);
2231 $buf = curl_exec ($ch);
2233 if ( $buf === FALSE ) {
2235 $err_msg =
'CURL error #'.curl_errno($ch).
': '.curl_error($ch);
2244 $headers = $this->_curl_headers;
2264 $sa = $this->getSA();
2267 $body=
SAML_SOAP_ENV.SAML_SOAP_BODY.SAMLP_REQUEST.SAML_ASSERTION_ARTIFACT.$sa.SAML_ASSERTION_ARTIFACT_CLOSE.SAMLP_REQUEST_CLOSE.SAML_SOAP_BODY_CLOSE.SAML_SOAP_ENV_CLOSE;
2276 var $_curl_headers = array();
2279 $this->_curl_headers[] =
$header;
2303 $pt = $this->retrievePT(
$url,$err_code,$output);
2314 if ( isset(
$_SESSION[
'phpCAS'][
'services'][
$url][
'cookies']) &&
2315 is_array(
$_SESSION[
'phpCAS'][
'services'][
$url][
'cookies']) ) {
2316 foreach (
$_SESSION[
'phpCAS'][
'services'][
$url][
'cookies'] as $name => $val ) {
2317 $cookies[] = $name.
'='.$val;
2322 if ( strstr(
$url,
'?') === FALSE ) {
2323 $service_url =
$url.
'?ticket='.$pt;
2325 $service_url =
$url.
'&ticket='.$pt;
2329 if ( !$this->readURL($service_url,$cookies,$headers,$output,$err_msg) ) {
2331 $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
2339 phpCAS::trace(
'URL`'.$service_url.
'\' has been read, storing cookies:
');
2340 foreach ( $headers as $header ) {
2341 // test if the header is a cookie
2342 if ( preg_match('/^Set-Cookie:/
',$header) ) {
2343 // the header is a cookie, remove the beginning
2344 $header_val = preg_replace('/^Set-Cookie: */
','',$header);
2345 // extract interesting information
2346 $name_val = strtok($header_val,';
');
2347 // extract the name and the value of the cookie
2348 $cookie_name = strtok($name_val,'=
');
2349 $cookie_val = strtok('=
');
2351 $_SESSION['phpCAS']['services
'][$url]['cookies
'][$cookie_name] = $cookie_val;
2352 phpCAS::trace($cookie_name.' ->
'.$cookie_val);
2358 phpCAS::traceEnd($res);
2381 function serviceMail($url,$service,$flags,&$err_code,&$err_msg,&$pt)
2383 phpCAS::traceBegin();
2384 // at first retrieve a PT
2385 $pt = $this->retrievePT($service,$err_code,$output);
2389 // test if PT was retrieved correctly
2391 // note: $err_code and $err_msg are filled by CASClient::retrievePT()
2392 phpCAS::trace('PT was not retrieved correctly
');
2394 phpCAS::trace('opening IMAP URL `
'.$url.'\
'...');
2395 $stream = @imap_open(
$url,$this->getUser(),$pt,$flags);
2398 $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
2402 var_export(imap_errors(),TRUE));
2457 { $this->_pt = $pt; }
2465 {
return !empty($this->_pt); }
2472 {
return 'ST'.substr($this->_sa, 2); }
2480 { $this->_sa = $sa; }
2488 {
return !empty($this->_sa); }
2506 function validatePT(&$validate_url,&$text_response,&$tree_response)
2510 $validate_url = $this->getServerProxyValidateURL().
'&ticket='.$this->getPT();
2512 if ( $this->isProxy() ) {
2514 $validate_url .=
'&pgtUrl='.urlencode($this->getCallbackURL());
2518 if ( !$this->readURL($validate_url,
'',$headers,$text_response,$err_msg) ) {
2519 phpCAS::trace(
'could not open URL \''.$validate_url.
'\' to validate (
'.$err_msg.')
');
2520 $this->authError('PT not validated
',
2522 TRUE/*$no_response*/);
2525 // read the response of the CAS server into a DOM object
2526 if ( !($dom = domxml_open_mem($text_response))) {
2528 $this->authError('PT not validated
',
2530 FALSE/*$no_response*/,
2531 TRUE/*$bad_response*/,
2534 // read the root node of the XML tree
2535 if ( !($tree_response = $dom->document_element()) ) {
2537 $this->authError('PT not validated
',
2539 FALSE/*$no_response*/,
2540 TRUE/*$bad_response*/,
2543 // insure that tag name is 'serviceResponse
'
2544 if ( $tree_response->node_name() != 'serviceResponse
' ) {
2546 $this->authError('PT not validated
',
2548 FALSE/*$no_response*/,
2549 TRUE/*$bad_response*/,
2552 if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) {
2553 // authentication succeded, extract the user name
2554 if ( sizeof($arr = $tree_response->get_elements_by_tagname("user")) == 0) {
2555 // no user specified => error
2556 $this->authError('PT not validated
',
2558 FALSE/*$no_response*/,
2559 TRUE/*$bad_response*/,
2562 $this->setUser(trim($arr[0]->get_content()));
2564 } else if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) {
2565 // authentication succeded, extract the error code and message
2566 $this->authError('PT not validated
',
2568 FALSE/*$no_response*/,
2569 FALSE/*$bad_response*/,
2571 $arr[0]->get_attribute('code
')/*$err_code*/,
2572 trim($arr[0]->get_content())/*$err_msg*/);
2574 $this->authError('PT not validated
',
2576 FALSE/*$no_response*/,
2577 TRUE/*$bad_response*/,
2581 $this->renameSession($this->getPT());
2582 // at this step, PT has been validated and $this->_user has been set,
2584 phpCAS::traceEnd(TRUE);
2590 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2594 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2601 // ########################################################################
2603 // ########################################################################
2623 phpCAS::traceBegin();
2624 // the URL is built when needed only
2625 if ( empty($this->_url) ) {
2627 // remove the ticket if present in the URL
2628 $final_uri = ($this->isHttps()) ? 'https
' : 'http
';
2633 if(empty(
$_SERVER[
'HTTP_X_FORWARDED_SERVER'])){
2637 if (empty(
$_SERVER[
'SERVER_NAME'])) {
2638 $server_name =
$_SERVER[
'HTTP_HOST'];
2640 $server_name =
$_SERVER[
'SERVER_NAME'];
2643 $server_name =
$_SERVER[
'HTTP_X_FORWARDED_SERVER'];
2645 $final_uri .= $server_name;
2646 if (!strpos($server_name,
':')) {
2647 if ( ($this->isHttps() &&
$_SERVER[
'SERVER_PORT']!=443)
2648 || (!$this->isHttps() &&
$_SERVER[
'SERVER_PORT']!=80) ) {
2650 $final_uri .=
$_SERVER[
'SERVER_PORT'];
2654 $request_uri = explode(
'?',
$_SERVER[
'REQUEST_URI'], 2);
2655 $final_uri .= $request_uri[0];
2657 if (isset($request_uri[1]) && $request_uri[1])
2659 $query_string = $this->removeParameterFromQueryString(
'ticket', $request_uri[1]);
2662 if ($query_string !==
'')
2663 $final_uri .=
"?$query_string";
2668 $this->setURL($final_uri);
2687 $parameterName = preg_quote($parameterName);
2688 return preg_replace(
"/&$parameterName(=[^&]*)?|^$parameterName(=[^&]*)?&?/",
'', $queryString);
2722 function authError(
$failure,$cas_url,$no_response,$bad_response=
'',$cas_response=
'',$err_code=
'',$err_msg=
'')
2730 if ( $no_response ) {
2733 if ( $bad_response ) {
2736 switch ($this->getServerVersion()) {
2741 if ( empty($err_code) )
2744 phpCAS::trace(
'Reason: ['.$err_code.
'] CAS error: '.$err_msg);
2750 $this->printHTMLFooter();
The CASClient class is a client interface that provides CAS authentication to PHP applications.
getStartSession($session)
setStartSession($session)
renameSession($ticket)
Renaming the session.
$_start_session
A variable to whether phpcas will use its own session handling.
The PGTStorageDB class is a class for PGT database storage.
The PGTStorageFile class is a class for PGT file storage.
static setSessionHandler()
set session handler to db
The phpCAS class is a simple container for the phpCAS library.
checkAuthentication()
This method is called to check whether the user is authenticated or not.
logout($params)
This method is used to logout from CAS.
isSessionAuthenticated()
This method tells if the current session is authenticated.
renewAuthentication()
This method is called to renew the authentication of the user If the user is authenticated,...
$_user
The Authenticated user.
isAuthenticated()
This method is called to check if the user is authenticated (previously or by tickets given in the UR...
setAttributes($attributes)
handleLogoutRequests($check_client=true, $allowed_clients=false)
This method handles logout requests.
setUser($user)
This method sets the CAS user's login name.
setCacheTimesForAuthRecheck($n)
Set the number of times authentication will be cached before rechecked.
getUser()
This method returns the CAS user's login name.
forceAuthentication()
This method is called to be sure that the user is authenticated.
$_attributes
The Authenticated users attributes.
$_cache_times_for_auth_recheck
An integer that gives the number of times authentication will be cached before rechecked.
redirectToCas($gateway=false, $renew=false)
This method is used to redirect the client to the CAS server.
wasPreviouslyAuthenticated()
This method tells if the user has already been (previously) authenticated by looking into the session...
$_cas_server_cert
the certificate of the CAS server.
setCasServerCert($cert)
Set the certificate of the CAS server.
$_no_cas_server_validation
Set to true not to validate the CAS server.
hasST()
This method tells if a Service Ticket was stored.
setNoCasServerValidation()
Set no SSL validation for the CAS server.
$_cas_server_ca_cert
the certificate of the CAS server CA.
setSessionAttributes($text_response)
This method will parse the DOM and pull out the attributes from the SAML payload and put them into an...
setCasServerCACert($cert)
Set the CA certificate of the CAS server.
validateSA($validate_url, &$text_response, &$tree_response)
This method is used to validate a SAML TICKET; halt on failure, and sets $validate_url,...
setST($st)
This method stores the Service Ticket.
getST()
This method returns the Service Ticket provided in the URL of the request.
validateST($validate_url, &$text_response, &$tree_response)
This method is used to validate a ST; halt on failure, and sets $validate_url, $text_reponse and $tre...
$_st
the Service Ticket provided in the URL of the request if present (empty otherwise).
getCallbackURL()
This method returns the URL that should be used for the PGT callback (in fact the URL of the current ...
setCallbackMode($callback_mode)
This method sets/unsets callback mode.
setCallbackURL($url)
This method sets the callback url.
isCallbackMode()
This method returns TRUE when the CAs client is running i callback mode, FALSE otherwise.
callback()
This method is called by CASClient::CASClient() when running in callback mode.
getServerSamlValidateURL()
This method is used to retrieve the SAML validating URL of the CAS server.
getServerVersion()
This method is used to retrieve the version of the CAS server.
isHttps()
This method checks to see if the request is secured via HTTPS.
getServerHostname()
This method is used to retrieve the hostname of the CAS server.
setServerLoginURL($url)
This method sets the login URL of the CAS server.
CASClient( $server_version, $proxy, $server_hostname, $server_port, $server_uri, $start_session=true)
CASClient constructor.
setServerSamlValidateURL($url)
This method sets the samlValidate URL of the CAS server.
getServerLoginURL($gateway=false, $renew=false)
This method is used to retrieve the login URL of the CAS server.
getServerProxyValidateURL()
This method is used to retrieve the proxy validating URL of the CAS server.
getServerProxyURL()
This method is used to retrieve the proxy URL of the CAS server.
getServerBaseURL()
This method is used to retrieve the base URL of the CAS server.
getServerServiceValidateURL()
This method is used to retrieve the service validating URL of the CAS server.
setServerLogoutURL($url)
This method sets the logout URL of the CAS server.
setExtraCurlOption($key, $value)
This method is used to set additional user curl options.
$_curl_options
An array to store extra curl options.
getServerLogoutURL()
This method is used to retrieve the logout URL of the CAS server.
setServerProxyValidateURL($url)
This method sets the proxyValidate URL of the CAS server.
setServerServiceValidateURL($url)
This method sets the serviceValidate URL of the CAS server.
error($msg)
This method is used by interface methods to print an error and where the function was originally call...
traceExit()
This method is used to indicate the end of the execution of the program.
trace($str)
This method is used to log something in debug mode.
log($str)
Logs a string in debug mode.
traceBegin()
This method is used to indicate the start of the execution of a function in debug mode.
traceEnd($res='')
This method is used to indicate the end of the execution of a function in debug mode.
$_lang
A string corresponding to the language used by phpCAS.
getLang()
This method returns the language used by phpCAS.
const PHPCAS_LANG_DEFAULT
phpCAS default language (when phpCAS::setLang() is not used)
$_strings
array containing the strings used by phpCAS.
setLang($lang)
This method is used to set the language used by phpCAS.
getString($str)
This method returns a string depending on the language.
setURL($url)
This method sets the URL of the current request.
authError($failure, $cas_url, $no_response, $bad_response='', $cas_response='', $err_code='', $err_msg='')
This method is used to print the HTML output when the user was not authenticated.
removeParameterFromQueryString($parameterName, $queryString)
Removes a parameter from a query string.
getURL()
This method returns the URL of the current request (without any ticket CGI parameter).
HTMLFilterOutput($str)
This method filters a string by replacing special tokens by appropriate values and prints it.
setHTMLHeader($header)
This method set the HTML header used for all outputs.
$_output_header
A string used to print the header of HTML pages.
printHTMLHeader($title)
This method prints the header of the HTML output (after filtering).
$_output_footer
A string used to print the footer of HTML pages.
setHTMLFooter($footer)
This method set the HTML footer used for all outputs.
printHTMLFooter()
This method prints the footer of the HTML output (after filtering).
loadPGT($pgt_iou)
This method reads a PGT from its Iou and deletes the corresponding storage entry.
serviceWeb($url, &$err_code, &$output)
This method is used to access an HTTP[S] service.
buildSAMLPayload()
This method is used to build the SAML POST body sent to /samlValidate URL.
setPGTStorageFile($format='', $path='')
This method is used to tell phpCAS to store the response of the CAS server to PGT requests onto the f...
initPGTStorage()
This method is used to initialize the storage of PGT's.
_curl_read_headers($ch, $header)
storePGT($pgt, $pgt_iou)
This method stores a PGT.
retrievePT($target_service, &$err_code, &$err_msg)
This method is used to retrieve PT's from the CAS server thanks to a PGT.
setPGTStorageDB($user, $password, $database_type, $hostname, $port, $database, $table)
This method is used to tell phpCAS to store the response of the CAS server to PGT requests into a dat...
readURL($url, $cookies, &$headers, &$body, &$err_msg)
This method is used to acces a remote URL.
validatePGT(&$validate_url, $text_response, $tree_response)
This method is used to validate a PGT; halt on failure.
setPT($pt)
This method stores the Proxy Ticket.
validatePT(&$validate_url, &$text_response, &$tree_response)
This method is used to validate a ST or PT; halt on failure Used for all CAS 2.0 validations.
hasSA()
This method tells if a SAML Ticket was stored.
hasPT()
This method tells if a Proxy Ticket was stored.
getSA()
This method returns the SAML Ticket provided in the URL of the request.
setSA($sa)
This method stores the SAML Ticket.
getPT()
This method returns the Proxy Ticket provided in the URL of the request.
isProxy()
Tells if a CAS client is a CAS proxy or not.
$_proxy
A boolean telling if the client is a CAS proxy or not.
hasPGT()
This method tells if a Proxy Granting Ticket was stored.
setPGT($pgt)
This method stores the Proxy Granting Ticket.
getPGT()
This method returns the Proxy Granting Ticket given by the CAS server.
const SAML_SOAP_ENV
SOAP envelope for SAML POST.
const SAML_VERSION_1_1
SAML protocol.
const CAS_VERSION_1_0
CAS version 1.0.
const SAML_ATTRIBUTES
SAML Attributes.
getVersion()
This method returns the phpCAS version.
domxml_open_mem($str, $mode=DOMXML_LOAD_PARSING, &$error=NULL)
const CAS_STR_USING_SERVER
a phpCAS string index
const CAS_STR_AUTHENTICATION_FAILED
const CAS_STR_SERVICE_UNAVAILABLE
const CAS_STR_YOU_WERE_NOT_AUTHENTICATED
const CAS_STR_AUTHENTICATION_WANTED
const CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']