38 include_once(dirname(__FILE__).
'/languages/languages.php');
41 include_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;
550 if ( isset($_SERVER[
'HTTPS']) && !empty($_SERVER[
'HTTPS']) && $_SERVER[
'HTTPS'] ==
'on') {
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 =
'?';
1158 if (isset($params[
'url'])) {
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().
'\'');
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>');
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');
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) {
1571 $user = trim($success_elements[0]->get_content());
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());
1600 function setSessionAttributes($text_response)
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; }
1717 function setPGT($pgt)
1718 { $this->_pgt = $pgt; }
1726 {
return !empty($this->_pgt); }
1750 var $_callback_mode = FALSE;
1759 function setCallbackMode($callback_mode)
1761 $this->_callback_mode = $callback_mode;
1772 function isCallbackMode()
1774 return $this->_callback_mode;
1785 var $_callback_url =
'';
1796 function getCallbackURL()
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;
1838 function setCallbackURL($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;
1889 function initPGTStorage()
1892 if ( !is_object($this->_pgt_storage) ) {
1893 $this->setPGTStorageFile();
1897 $this->_pgt_storage->init();
1908 function storePGT($pgt,$pgt_iou)
1911 $this->initPGTStorage();
1913 $this->_pgt_storage->write($pgt,$pgt_iou);
1925 function loadPGT($pgt_iou)
1928 $this->initPGTStorage();
1930 return $this->_pgt_storage->read($pgt_iou);
1942 function setPGTStorageFile($format=
'',
1946 if ( is_object($this->_pgt_storage) ) {
1971 function setPGTStorageDB($user,
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);
2007 function validatePGT(&$validate_url,$text_response,$tree_response)
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);
2053 function retrievePT($target_service,&$err_code,&$err_msg)
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.'\
')';
2163 function readURL($url,$cookies,&$headers,&$body,&$err_msg)
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;
2259 function buildSAMLPayload()
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();
2277 function _curl_read_headers($ch, $header)
2279 $this->_curl_headers[] = $header;
2280 return strlen($header);
2298 function serviceWeb($url,&$err_code,&$output)
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);
2685 function removeParameterFromQueryString($parameterName, $queryString)
2687 $parameterName = preg_quote($parameterName);
2688 return preg_replace(
"/&$parameterName(=[^&]*)?|^$parameterName(=[^&]*)?&?/",
'', $queryString);
2699 function setURL($url)
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();