forked from GNUsocial/gnu-social
Bump to phpCAS 1.1.0RC6
This commit is contained in:
@@ -351,6 +351,43 @@ class CASClient
|
||||
{
|
||||
return $this->_server['login_url'] = $url;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method sets the serviceValidate URL of the CAS server.
|
||||
* @param $url the serviceValidate URL
|
||||
* @private
|
||||
* @since 1.1.0 by Joachim Fritschi
|
||||
*/
|
||||
function setServerServiceValidateURL($url)
|
||||
{
|
||||
return $this->_server['service_validate_url'] = $url;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method sets the proxyValidate URL of the CAS server.
|
||||
* @param $url the proxyValidate URL
|
||||
* @private
|
||||
* @since 1.1.0 by Joachim Fritschi
|
||||
*/
|
||||
function setServerProxyValidateURL($url)
|
||||
{
|
||||
return $this->_server['proxy_validate_url'] = $url;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method sets the samlValidate URL of the CAS server.
|
||||
* @param $url the samlValidate URL
|
||||
* @private
|
||||
* @since 1.1.0 by Joachim Fritschi
|
||||
*/
|
||||
function setServerSamlValidateURL($url)
|
||||
{
|
||||
return $this->_server['saml_validate_url'] = $url;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is used to retrieve the service validating URL of the CAS server.
|
||||
@@ -373,7 +410,25 @@ class CASClient
|
||||
// return $this->_server['service_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL());
|
||||
return $this->_server['service_validate_url'].'?service='.urlencode($this->getURL());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to retrieve the SAML validating URL of the CAS server.
|
||||
* @return a URL.
|
||||
* @private
|
||||
*/
|
||||
function getServerSamlValidateURL()
|
||||
{
|
||||
phpCAS::traceBegin();
|
||||
// the URL is build only when needed
|
||||
if ( empty($this->_server['saml_validate_url']) ) {
|
||||
switch ($this->getServerVersion()) {
|
||||
case SAML_VERSION_1_1:
|
||||
$this->_server['saml_validate_url'] = $this->getServerBaseURL().'samlValidate';
|
||||
break;
|
||||
}
|
||||
}
|
||||
phpCAS::traceEnd($this->_server['saml_validate_url'].'?TARGET='.urlencode($this->getURL()));
|
||||
return $this->_server['saml_validate_url'].'?TARGET='.urlencode($this->getURL());
|
||||
}
|
||||
/**
|
||||
* This method is used to retrieve the proxy validating URL of the CAS server.
|
||||
* @return a URL.
|
||||
@@ -497,31 +552,51 @@ class CASClient
|
||||
|
||||
phpCAS::traceBegin();
|
||||
|
||||
if (!$this->isLogoutRequest() && !empty($_GET['ticket']) && $start_session) {
|
||||
// copy old session vars and destroy the current session
|
||||
if (!isset($_SESSION)) {
|
||||
session_start();
|
||||
}
|
||||
$old_session = $_SESSION;
|
||||
session_destroy();
|
||||
// set up a new session, of name based on the ticket
|
||||
$session_id = preg_replace('/[^\w]/','',$_GET['ticket']);
|
||||
phpCAS::LOG("Session ID: " . $session_id);
|
||||
session_id($session_id);
|
||||
if (!isset($_SESSION)) {
|
||||
session_start();
|
||||
}
|
||||
// restore old session vars
|
||||
$_SESSION = $old_session;
|
||||
// Redirect to location without ticket.
|
||||
header('Location: '.$this->getURL());
|
||||
// the redirect header() call and DOM parsing code from domxml-php4-php5.php won't work in PHP4 compatibility mode
|
||||
if (version_compare(PHP_VERSION,'5','>=') && ini_get('zend.ze1_compatibility_mode')) {
|
||||
phpCAS::error('phpCAS cannot support zend.ze1_compatibility_mode. Sorry.');
|
||||
}
|
||||
|
||||
//activate session mechanism if desired
|
||||
if (!$this->isLogoutRequest() && $start_session) {
|
||||
session_start();
|
||||
// skip Session Handling for logout requests and if don't want it'
|
||||
if ($start_session && !$this->isLogoutRequest()) {
|
||||
phpCAS::trace("Starting session handling");
|
||||
// Check for Tickets from the CAS server
|
||||
if (empty($_GET['ticket'])){
|
||||
phpCAS::trace("No ticket found");
|
||||
// only create a session if necessary
|
||||
if (!isset($_SESSION)) {
|
||||
phpCAS::trace("No session found, creating new session");
|
||||
session_start();
|
||||
}
|
||||
}else{
|
||||
phpCAS::trace("Ticket found");
|
||||
// We have to copy any old data before renaming the session
|
||||
if (isset($_SESSION)) {
|
||||
phpCAS::trace("Old active session found, saving old data and destroying session");
|
||||
$old_session = $_SESSION;
|
||||
session_destroy();
|
||||
}else{
|
||||
session_start();
|
||||
phpCAS::trace("Starting possible old session to copy variables");
|
||||
$old_session = $_SESSION;
|
||||
session_destroy();
|
||||
}
|
||||
// set up a new session, of name based on the ticket
|
||||
$session_id = preg_replace('/[^\w]/','',$_GET['ticket']);
|
||||
phpCAS::LOG("Session ID: " . $session_id);
|
||||
session_id($session_id);
|
||||
session_start();
|
||||
// restore old session vars
|
||||
if(isset($old_session)){
|
||||
phpCAS::trace("Restoring old session vars");
|
||||
$_SESSION = $old_session;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
phpCAS::trace("Skipping session creation");
|
||||
}
|
||||
|
||||
|
||||
// are we in proxy mode ?
|
||||
$this->_proxy = $proxy;
|
||||
|
||||
//check version
|
||||
@@ -533,6 +608,8 @@ class CASClient
|
||||
break;
|
||||
case CAS_VERSION_2_0:
|
||||
break;
|
||||
case SAML_VERSION_1_1:
|
||||
break;
|
||||
default:
|
||||
phpCAS::error('this version of CAS (`'
|
||||
.$server_version
|
||||
@@ -541,29 +618,29 @@ class CASClient
|
||||
}
|
||||
$this->_server['version'] = $server_version;
|
||||
|
||||
//check hostname
|
||||
// check hostname
|
||||
if ( empty($server_hostname)
|
||||
|| !preg_match('/[\.\d\-abcdefghijklmnopqrstuvwxyz]*/',$server_hostname) ) {
|
||||
phpCAS::error('bad CAS server hostname (`'.$server_hostname.'\')');
|
||||
}
|
||||
$this->_server['hostname'] = $server_hostname;
|
||||
|
||||
//check port
|
||||
// check port
|
||||
if ( $server_port == 0
|
||||
|| !is_int($server_port) ) {
|
||||
phpCAS::error('bad CAS server port (`'.$server_hostname.'\')');
|
||||
}
|
||||
$this->_server['port'] = $server_port;
|
||||
|
||||
//check URI
|
||||
// check URI
|
||||
if ( !preg_match('/[\.\d\-_abcdefghijklmnopqrstuvwxyz\/]*/',$server_uri) ) {
|
||||
phpCAS::error('bad CAS server URI (`'.$server_uri.'\')');
|
||||
}
|
||||
//add leading and trailing `/' and remove doubles
|
||||
// add leading and trailing `/' and remove doubles
|
||||
$server_uri = preg_replace('/\/\//','/','/'.$server_uri.'/');
|
||||
$this->_server['uri'] = $server_uri;
|
||||
|
||||
//set to callback mode if PgtIou and PgtId CGI GET parameters are provided
|
||||
// set to callback mode if PgtIou and PgtId CGI GET parameters are provided
|
||||
if ( $this->isProxy() ) {
|
||||
$this->setCallbackMode(!empty($_GET['pgtIou'])&&!empty($_GET['pgtId']));
|
||||
}
|
||||
@@ -590,8 +667,12 @@ class CASClient
|
||||
}
|
||||
break;
|
||||
case CAS_VERSION_2_0: // check for a Service or Proxy Ticket
|
||||
if( preg_match('/^[SP]T-/',$ticket) ) {
|
||||
phpCAS::trace('ST or PT \''.$ticket.'\' found');
|
||||
if (preg_match('/^ST-/', $ticket)) {
|
||||
phpCAS::trace('ST \'' . $ticket . '\' found');
|
||||
$this->setST($ticket);
|
||||
unset ($_GET['ticket']);
|
||||
} else if (preg_match('/^PT-/', $ticket)) {
|
||||
phpCAS::trace('PT \'' . $ticket . '\' found');
|
||||
$this->setPT($ticket);
|
||||
unset($_GET['ticket']);
|
||||
} else if ( !empty($ticket) ) {
|
||||
@@ -599,6 +680,16 @@ class CASClient
|
||||
phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
|
||||
}
|
||||
break;
|
||||
case SAML_VERSION_1_1: // SAML just does Service Tickets
|
||||
if( preg_match('/^[SP]T-/',$ticket) ) {
|
||||
phpCAS::trace('SA \''.$ticket.'\' found');
|
||||
$this->setSA($ticket);
|
||||
unset($_GET['ticket']);
|
||||
} else if ( !empty($ticket) ) {
|
||||
//ill-formed ticket, halt
|
||||
phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
phpCAS::traceEnd();
|
||||
@@ -652,6 +743,45 @@ class CASClient
|
||||
}
|
||||
return $this->_user;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************************************
|
||||
* Atrributes section
|
||||
*
|
||||
* @author Matthias Crauwels <matthias.crauwels@ugent.be>, Ghent University, Belgium
|
||||
*
|
||||
***********************************************************************************************************************/
|
||||
/**
|
||||
* The Authenticated users attributes. Written by CASClient::setAttributes(), read by CASClient::getAttributes().
|
||||
* @attention client applications should use phpCAS::getAttributes().
|
||||
*
|
||||
* @hideinitializer
|
||||
* @private
|
||||
*/
|
||||
var $_attributes = array();
|
||||
|
||||
function setAttributes($attributes)
|
||||
{ $this->_attributes = $attributes; }
|
||||
|
||||
function getAttributes() {
|
||||
if ( empty($this->_user) ) { // if no user is set, there shouldn't be any attributes also...
|
||||
phpCAS::error('this method should be used only after '.__CLASS__.'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()');
|
||||
}
|
||||
return $this->_attributes;
|
||||
}
|
||||
|
||||
function hasAttributes()
|
||||
{ return !empty($this->_attributes); }
|
||||
|
||||
function hasAttribute($key)
|
||||
{ return (is_array($this->_attributes) && array_key_exists($key, $this->_attributes)); }
|
||||
|
||||
function getAttribute($key) {
|
||||
if($this->hasAttribute($key)) {
|
||||
return $this->_attributes[$key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called to renew the authentication of the user
|
||||
@@ -778,55 +908,72 @@ class CASClient
|
||||
* This method is called to check if the user is authenticated (previously or by
|
||||
* tickets given in the URL).
|
||||
*
|
||||
* @return TRUE when the user is authenticated.
|
||||
* @return TRUE when the user is authenticated. Also may redirect to the same URL without the ticket.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
function isAuthenticated()
|
||||
{
|
||||
phpCAS::traceBegin();
|
||||
$res = FALSE;
|
||||
$validate_url = '';
|
||||
|
||||
if ( $this->wasPreviouslyAuthenticated() ) {
|
||||
// the user has already (previously during the session) been
|
||||
// authenticated, nothing to be done.
|
||||
phpCAS::trace('user was already authenticated, no need to look for tickets');
|
||||
$res = TRUE;
|
||||
}
|
||||
elseif ( $this->hasST() ) {
|
||||
// if a Service Ticket was given, validate it
|
||||
phpCAS::trace('ST `'.$this->getST().'\' is present');
|
||||
$this->validateST($validate_url,$text_response,$tree_response); // if it fails, it halts
|
||||
phpCAS::trace('ST `'.$this->getST().'\' was validated');
|
||||
if ( $this->isProxy() ) {
|
||||
$this->validatePGT($validate_url,$text_response,$tree_response); // idem
|
||||
phpCAS::trace('PGT `'.$this->getPGT().'\' was validated');
|
||||
$_SESSION['phpCAS']['pgt'] = $this->getPGT();
|
||||
phpCAS::traceBegin();
|
||||
$res = FALSE;
|
||||
$validate_url = '';
|
||||
|
||||
if ( $this->wasPreviouslyAuthenticated() ) {
|
||||
// the user has already (previously during the session) been
|
||||
// authenticated, nothing to be done.
|
||||
phpCAS::trace('user was already authenticated, no need to look for tickets');
|
||||
$res = TRUE;
|
||||
}
|
||||
$_SESSION['phpCAS']['user'] = $this->getUser();
|
||||
$res = TRUE;
|
||||
}
|
||||
elseif ( $this->hasPT() ) {
|
||||
// if a Proxy Ticket was given, validate it
|
||||
phpCAS::trace('PT `'.$this->getPT().'\' is present');
|
||||
$this->validatePT($validate_url,$text_response,$tree_response); // note: if it fails, it halts
|
||||
phpCAS::trace('PT `'.$this->getPT().'\' was validated');
|
||||
if ( $this->isProxy() ) {
|
||||
$this->validatePGT($validate_url,$text_response,$tree_response); // idem
|
||||
phpCAS::trace('PGT `'.$this->getPGT().'\' was validated');
|
||||
$_SESSION['phpCAS']['pgt'] = $this->getPGT();
|
||||
else {
|
||||
if ( $this->hasST() ) {
|
||||
// if a Service Ticket was given, validate it
|
||||
phpCAS::trace('ST `'.$this->getST().'\' is present');
|
||||
$this->validateST($validate_url,$text_response,$tree_response); // if it fails, it halts
|
||||
phpCAS::trace('ST `'.$this->getST().'\' was validated');
|
||||
if ( $this->isProxy() ) {
|
||||
$this->validatePGT($validate_url,$text_response,$tree_response); // idem
|
||||
phpCAS::trace('PGT `'.$this->getPGT().'\' was validated');
|
||||
$_SESSION['phpCAS']['pgt'] = $this->getPGT();
|
||||
}
|
||||
$_SESSION['phpCAS']['user'] = $this->getUser();
|
||||
$res = TRUE;
|
||||
}
|
||||
elseif ( $this->hasPT() ) {
|
||||
// if a Proxy Ticket was given, validate it
|
||||
phpCAS::trace('PT `'.$this->getPT().'\' is present');
|
||||
$this->validatePT($validate_url,$text_response,$tree_response); // note: if it fails, it halts
|
||||
phpCAS::trace('PT `'.$this->getPT().'\' was validated');
|
||||
if ( $this->isProxy() ) {
|
||||
$this->validatePGT($validate_url,$text_response,$tree_response); // idem
|
||||
phpCAS::trace('PGT `'.$this->getPGT().'\' was validated');
|
||||
$_SESSION['phpCAS']['pgt'] = $this->getPGT();
|
||||
}
|
||||
$_SESSION['phpCAS']['user'] = $this->getUser();
|
||||
$res = TRUE;
|
||||
}
|
||||
elseif ( $this->hasSA() ) {
|
||||
// if we have a SAML ticket, validate it.
|
||||
phpCAS::trace('SA `'.$this->getSA().'\' is present');
|
||||
$this->validateSA($validate_url,$text_response,$tree_response); // if it fails, it halts
|
||||
phpCAS::trace('SA `'.$this->getSA().'\' was validated');
|
||||
$_SESSION['phpCAS']['user'] = $this->getUser();
|
||||
$_SESSION['phpCAS']['attributes'] = $this->getAttributes();
|
||||
$res = TRUE;
|
||||
}
|
||||
else {
|
||||
// no ticket given, not authenticated
|
||||
phpCAS::trace('no ticket found');
|
||||
}
|
||||
if ($res) {
|
||||
// if called with a ticket parameter, we need to redirect to the app without the ticket so that CAS-ification is transparent to the browser (for later POSTS)
|
||||
// most of the checks and errors should have been made now, so we're safe for redirect without masking error messages.
|
||||
header('Location: '.$this->getURL());
|
||||
phpCAS::log( "Prepare redirect to : ".$this->getURL() );
|
||||
}
|
||||
}
|
||||
$_SESSION['phpCAS']['user'] = $this->getUser();
|
||||
$res = TRUE;
|
||||
}
|
||||
else {
|
||||
// no ticket given, not authenticated
|
||||
phpCAS::trace('no ticket found');
|
||||
}
|
||||
|
||||
phpCAS::traceEnd($res);
|
||||
return $res;
|
||||
|
||||
phpCAS::traceEnd($res);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -889,6 +1036,9 @@ class CASClient
|
||||
if ( $this->isSessionAuthenticated() ) {
|
||||
// authentication already done
|
||||
$this->setUser($_SESSION['phpCAS']['user']);
|
||||
if(isset($_SESSION['phpCAS']['attributes'])){
|
||||
$this->setAttributes($_SESSION['phpCAS']['attributes']);
|
||||
}
|
||||
phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\'');
|
||||
$auth = TRUE;
|
||||
} else {
|
||||
@@ -917,6 +1067,7 @@ class CASClient
|
||||
|
||||
printf('<p>'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
|
||||
$this->printHTMLFooter();
|
||||
|
||||
phpCAS::traceExit();
|
||||
exit();
|
||||
}
|
||||
@@ -962,11 +1113,15 @@ class CASClient
|
||||
$cas_url = $cas_url . $paramSeparator . "service=" . urlencode($params['service']);
|
||||
}
|
||||
header('Location: '.$cas_url);
|
||||
phpCAS::log( "Prepare redirect to : ".$cas_url );
|
||||
|
||||
session_unset();
|
||||
session_destroy();
|
||||
|
||||
$this->printHTMLHeader($this->getString(CAS_STR_LOGOUT));
|
||||
printf('<p>'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
|
||||
$this->printHTMLFooter();
|
||||
|
||||
phpCAS::traceExit();
|
||||
exit();
|
||||
}
|
||||
@@ -1009,10 +1164,10 @@ class CASClient
|
||||
}
|
||||
$client_ip = $_SERVER['REMOTE_ADDR'];
|
||||
$client = gethostbyaddr($client_ip);
|
||||
phpCAS::log("Client: ".$client);
|
||||
phpCAS::log("Client: ".$client."/".$client_ip);
|
||||
$allowed = false;
|
||||
foreach ($allowed_clients as $allowed_client) {
|
||||
if ($client == $allowed_client) {
|
||||
if (($client == $allowed_client) or ($client_ip == $allowed_client)) {
|
||||
phpCAS::log("Allowed client '".$allowed_client."' matches, logout request is allowed");
|
||||
$allowed = true;
|
||||
break;
|
||||
@@ -1284,6 +1439,151 @@ class CASClient
|
||||
phpCAS::traceEnd(TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ########################################################################
|
||||
// SAML VALIDATION
|
||||
// ########################################################################
|
||||
/**
|
||||
* @addtogroup internalBasic
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* This method is used to validate a SAML TICKET; halt on failure, and sets $validate_url,
|
||||
* $text_reponse and $tree_response on success. These parameters are used later
|
||||
* by CASClient::validatePGT() for CAS proxies.
|
||||
*
|
||||
* @param $validate_url the URL of the request to the CAS server.
|
||||
* @param $text_response the response of the CAS server, as is (XML text).
|
||||
* @param $tree_response the response of the CAS server, as a DOM XML tree.
|
||||
*
|
||||
* @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function validateSA($validate_url,&$text_response,&$tree_response)
|
||||
{
|
||||
phpCAS::traceBegin();
|
||||
|
||||
// build the URL to validate the ticket
|
||||
$validate_url = $this->getServerSamlValidateURL();
|
||||
|
||||
// open and read the URL
|
||||
if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
|
||||
phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
|
||||
$this->authError('SA not validated', $validate_url, TRUE/*$no_response*/);
|
||||
}
|
||||
|
||||
phpCAS::trace('server version: '.$this->getServerVersion());
|
||||
|
||||
// analyze the result depending on the version
|
||||
switch ($this->getServerVersion()) {
|
||||
case SAML_VERSION_1_1:
|
||||
|
||||
// read the response of the CAS server into a DOM object
|
||||
if ( !($dom = domxml_open_mem($text_response))) {
|
||||
phpCAS::trace('domxml_open_mem() failed');
|
||||
$this->authError('SA not validated',
|
||||
$validate_url,
|
||||
FALSE/*$no_response*/,
|
||||
TRUE/*$bad_response*/,
|
||||
$text_response);
|
||||
}
|
||||
// read the root node of the XML tree
|
||||
if ( !($tree_response = $dom->document_element()) ) {
|
||||
phpCAS::trace('document_element() failed');
|
||||
$this->authError('SA not validated',
|
||||
$validate_url,
|
||||
FALSE/*$no_response*/,
|
||||
TRUE/*$bad_response*/,
|
||||
$text_response);
|
||||
}
|
||||
// insure that tag name is 'Envelope'
|
||||
if ( $tree_response->node_name() != 'Envelope' ) {
|
||||
phpCAS::trace('bad XML root node (should be `Envelope\' instead of `'.$tree_response->node_name().'\'');
|
||||
$this->authError('SA not validated',
|
||||
$validate_url,
|
||||
FALSE/*$no_response*/,
|
||||
TRUE/*$bad_response*/,
|
||||
$text_response);
|
||||
}
|
||||
// check for the NameIdentifier tag in the SAML response
|
||||
if ( sizeof($success_elements = $tree_response->get_elements_by_tagname("NameIdentifier")) != 0) {
|
||||
phpCAS::trace('NameIdentifier found');
|
||||
$user = trim($success_elements[0]->get_content());
|
||||
phpCAS::trace('user = `'.$user.'`');
|
||||
$this->setUser($user);
|
||||
$this->setSessionAttributes($text_response);
|
||||
} else {
|
||||
phpCAS::trace('no <NameIdentifier> tag found in SAML payload');
|
||||
$this->authError('SA not validated',
|
||||
$validate_url,
|
||||
FALSE/*$no_response*/,
|
||||
TRUE/*$bad_response*/,
|
||||
$text_response);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// at this step, ST has been validated and $this->_user has been set,
|
||||
phpCAS::traceEnd(TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will parse the DOM and pull out the attributes from the SAML
|
||||
* payload and put them into an array, then put the array into the session.
|
||||
*
|
||||
* @param $text_response the SAML payload.
|
||||
* @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function setSessionAttributes($text_response)
|
||||
{
|
||||
phpCAS::traceBegin();
|
||||
|
||||
$result = FALSE;
|
||||
|
||||
if (isset($_SESSION[SAML_ATTRIBUTES])) {
|
||||
phpCAS::trace("session attrs already set."); //testbml - do we care?
|
||||
}
|
||||
|
||||
$attr_array = array();
|
||||
|
||||
if (($dom = domxml_open_mem($text_response))) {
|
||||
$xPath = $dom->xpath_new_context();
|
||||
$xPath->xpath_register_ns('samlp', 'urn:oasis:names:tc:SAML:1.0:protocol');
|
||||
$xPath->xpath_register_ns('saml', 'urn:oasis:names:tc:SAML:1.0:assertion');
|
||||
$nodelist = $xPath->xpath_eval("//saml:Attribute");
|
||||
$attrs = $nodelist->nodeset;
|
||||
phpCAS::trace($text_response);
|
||||
foreach($attrs as $attr){
|
||||
$xres = $xPath->xpath_eval("saml:AttributeValue", $attr);
|
||||
$name = $attr->get_attribute("AttributeName");
|
||||
$value_array = array();
|
||||
foreach($xres->nodeset as $node){
|
||||
$value_array[] = $node->get_content();
|
||||
|
||||
}
|
||||
phpCAS::trace("* " . $name . "=" . $value_array);
|
||||
$attr_array[$name] = $value_array;
|
||||
}
|
||||
$_SESSION[SAML_ATTRIBUTES] = $attr_array;
|
||||
// UGent addition...
|
||||
foreach($attr_array as $attr_key => $attr_value) {
|
||||
if(count($attr_value) > 1) {
|
||||
$this->_attributes[$attr_key] = $attr_value;
|
||||
}
|
||||
else {
|
||||
$this->_attributes[$attr_key] = $attr_value[0];
|
||||
}
|
||||
}
|
||||
$result = TRUE;
|
||||
}
|
||||
phpCAS::traceEnd($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -1495,6 +1795,7 @@ class CASClient
|
||||
$this->storePGT($pgt,$pgt_iou);
|
||||
$this->printHTMLFooter();
|
||||
phpCAS::traceExit();
|
||||
exit();
|
||||
}
|
||||
|
||||
/** @} */
|
||||
@@ -1585,7 +1886,7 @@ class CASClient
|
||||
}
|
||||
|
||||
// create the storage object
|
||||
$this->_pgt_storage = &new PGTStorageFile($this,$format,$path);
|
||||
$this->_pgt_storage = new PGTStorageFile($this,$format,$path);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1622,7 +1923,7 @@ class CASClient
|
||||
trigger_error('PGT storage into database is an experimental feature, use at your own risk',E_USER_WARNING);
|
||||
|
||||
// create the storage object
|
||||
$this->_pgt_storage = & new PGTStorageDB($this,$user,$password,$database_type,$hostname,$port,$database,$table);
|
||||
$this->_pgt_storage = new PGTStorageDB($this,$user,$password,$database_type,$hostname,$port,$database,$table);
|
||||
}
|
||||
|
||||
// ########################################################################
|
||||
@@ -1643,7 +1944,8 @@ class CASClient
|
||||
*/
|
||||
function validatePGT(&$validate_url,$text_response,$tree_response)
|
||||
{
|
||||
phpCAS::traceBegin();
|
||||
// here cannot use phpCAS::traceBegin(); alongside domxml-php4-to-php5.php
|
||||
phpCAS::log('start validatePGT()');
|
||||
if ( sizeof($arr = $tree_response->get_elements_by_tagname("proxyGrantingTicket")) == 0) {
|
||||
phpCAS::trace('<proxyGrantingTicket> not found');
|
||||
// authentication succeded, but no PGT Iou was transmitted
|
||||
@@ -1666,7 +1968,8 @@ class CASClient
|
||||
}
|
||||
$this->setPGT($pgt);
|
||||
}
|
||||
phpCAS::traceEnd(TRUE);
|
||||
// here, cannot use phpCAS::traceEnd(TRUE); alongside domxml-php4-to-php5.php
|
||||
phpCAS::log('end validatePGT()');
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1819,7 +2122,15 @@ class CASClient
|
||||
if ($this->_cas_server_cert == '' && $this->_cas_server_ca_cert == '' && !$this->_no_cas_server_validation) {
|
||||
phpCAS::error('one of the methods phpCAS::setCasServerCert(), phpCAS::setCasServerCACert() or phpCAS::setNoCasServerValidation() must be called.');
|
||||
}
|
||||
if ($this->_cas_server_cert != '' ) {
|
||||
if ($this->_cas_server_cert != '' && $this->_cas_server_ca_cert != '') {
|
||||
// This branch added by IDMS. Seems phpCAS implementor got a bit confused about the curl options CURLOPT_SSLCERT and CURLOPT_CAINFO
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
|
||||
curl_setopt($ch, CURLOPT_SSLCERT, $this->_cas_server_cert);
|
||||
curl_setopt($ch, CURLOPT_CAINFO, $this->_cas_server_ca_cert);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, '1');
|
||||
phpCAS::trace('CURL: Set all required opts for mutual authentication ------');
|
||||
} else if ($this->_cas_server_cert != '' ) {
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
|
||||
curl_setopt($ch, CURLOPT_SSLCERT, $this->_cas_server_cert);
|
||||
} else if ($this->_cas_server_ca_cert != '') {
|
||||
@@ -1839,11 +2150,28 @@ class CASClient
|
||||
if ( is_array($cookies) ) {
|
||||
curl_setopt($ch,CURLOPT_COOKIE,implode(';',$cookies));
|
||||
}
|
||||
// add extra stuff if SAML
|
||||
if ($this->hasSA()) {
|
||||
$more_headers = array ("soapaction: http://www.oasis-open.org/committees/security",
|
||||
"cache-control: no-cache",
|
||||
"pragma: no-cache",
|
||||
"accept: text/xml",
|
||||
"connection: keep-alive",
|
||||
"content-type: text/xml");
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $more_headers);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
$data = $this->buildSAMLPayload();
|
||||
//phpCAS::trace('SAML Payload: '.print_r($data, TRUE));
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
}
|
||||
// perform the query
|
||||
$buf = curl_exec ($ch);
|
||||
//phpCAS::trace('CURL: Call completed. Response body is: \''.$buf.'\'');
|
||||
if ( $buf === FALSE ) {
|
||||
phpCAS::trace('curl_exec() failed');
|
||||
$err_msg = 'CURL error #'.curl_errno($ch).': '.curl_error($ch);
|
||||
//phpCAS::trace('curl error: '.$err_msg);
|
||||
// close the CURL session
|
||||
curl_close ($ch);
|
||||
$res = FALSE;
|
||||
@@ -1858,7 +2186,28 @@ class CASClient
|
||||
phpCAS::traceEnd($res);
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is used to build the SAML POST body sent to /samlValidate URL.
|
||||
*
|
||||
* @return the SOAP-encased SAMLP artifact (the ticket).
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function buildSAMLPayload()
|
||||
{
|
||||
phpCAS::traceBegin();
|
||||
|
||||
//get the ticket
|
||||
$sa = $this->getSA();
|
||||
//phpCAS::trace("SA: ".$sa);
|
||||
|
||||
$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;
|
||||
|
||||
phpCAS::traceEnd($body);
|
||||
return ($body);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is the callback used by readURL method to request HTTP headers.
|
||||
*/
|
||||
@@ -1951,6 +2300,7 @@ class CASClient
|
||||
*
|
||||
* @param $url a string giving the URL of the service, including the mailing box
|
||||
* for IMAP URLs, as accepted by imap_open().
|
||||
* @param $service a string giving for CAS retrieve Proxy ticket
|
||||
* @param $flags options given to imap_open().
|
||||
* @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on
|
||||
* success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE,
|
||||
@@ -1964,11 +2314,11 @@ class CASClient
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
function serviceMail($url,$flags,&$err_code,&$err_msg,&$pt)
|
||||
function serviceMail($url,$service,$flags,&$err_code,&$err_msg,&$pt)
|
||||
{
|
||||
phpCAS::traceBegin();
|
||||
// at first retrieve a PT
|
||||
$pt = $this->retrievePT($target_service,$err_code,$output);
|
||||
$pt = $this->retrievePT($service,$err_code,$output);
|
||||
|
||||
$stream = FALSE;
|
||||
|
||||
@@ -2049,7 +2399,30 @@ class CASClient
|
||||
*/
|
||||
function hasPT()
|
||||
{ return !empty($this->_pt); }
|
||||
|
||||
/**
|
||||
* This method returns the SAML Ticket provided in the URL of the request.
|
||||
* @return The SAML ticket.
|
||||
* @private
|
||||
*/
|
||||
function getSA()
|
||||
{ return 'ST'.substr($this->_sa, 2); }
|
||||
|
||||
/**
|
||||
* This method stores the SAML Ticket.
|
||||
* @param $sa The SAML Ticket.
|
||||
* @private
|
||||
*/
|
||||
function setSA($sa)
|
||||
{ $this->_sa = $sa; }
|
||||
|
||||
/**
|
||||
* This method tells if a SAML Ticket was stored.
|
||||
* @return TRUE if a SAML Ticket has been stored.
|
||||
* @private
|
||||
*/
|
||||
function hasSA()
|
||||
{ return !empty($this->_sa); }
|
||||
|
||||
/** @} */
|
||||
// ########################################################################
|
||||
// PT VALIDATION
|
||||
@@ -2213,8 +2586,13 @@ class CASClient
|
||||
}
|
||||
}
|
||||
|
||||
$final_uri .= strtok($_SERVER['REQUEST_URI'],"?");
|
||||
$cgi_params = '?'.strtok("?");
|
||||
$php_is_for_sissies = split("\?", $_SERVER['REQUEST_URI'], 2);
|
||||
$final_uri .= $php_is_for_sissies[0];
|
||||
if(sizeof($php_is_for_sissies) > 1){
|
||||
$cgi_params = '?' . $php_is_for_sissies[1];
|
||||
} else {
|
||||
$cgi_params = '?';
|
||||
}
|
||||
// remove the ticket if present in the CGI parameters
|
||||
$cgi_params = preg_replace('/&ticket=[^&]*/','',$cgi_params);
|
||||
$cgi_params = preg_replace('/\?ticket=[^&;]*/','?',$cgi_params);
|
||||
@@ -2294,4 +2672,4 @@ class CASClient
|
||||
/** @} */
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
|
Reference in New Issue
Block a user