diff --git a/modules/saml/lib/IdP/SAML2.php b/modules/saml/lib/IdP/SAML2.php index 746bf94e3c2b503a6db8d1bc03aef15db4c0ff4f..822bdf3891f9048a1d9a901e92ca3d6cedf076c1 100644 --- a/modules/saml/lib/IdP/SAML2.php +++ b/modules/saml/lib/IdP/SAML2.php @@ -314,4 +314,126 @@ class sspmod_saml_IdP_SAML2 { $idp->handleAuthenticationRequest($state); } + + /** + * Send a logout response. + * + * @param array &$state The logout state array. + */ + public static function sendLogoutResponse(SimpleSAML_IdP $idp, array $state) { + assert('isset($state["saml:SPEntityId"])'); + assert('isset($state["saml:RequestId"])'); + assert('array_key_exists("saml:RelayState", $state)'); // Can be NULL. + + $spEntityId = $state['saml:SPEntityId']; + + $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); + $idpMetadata = $idp->getConfig(); + $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote'); + + $lr = sspmod_saml2_Message::buildLogoutResponse($idpMetadata, $spMetadata); + $lr->setInResponseTo($state['saml:RequestId']); + $lr->setRelayState($state['saml:RelayState']); + + if (isset($state['core:Failed']) && $state['core:Failed']) { + $lr->setStatus(array( + 'Code' => SAML2_Const::STATUS_SUCCESS, + 'SubCode' => SAML2_Const::STATUS_PARTIAL_LOGOUT, + )); + SimpleSAML_Logger::info('Sending logout response for partial logout to SP ' . var_export($spEntityId, TRUE)); + } else { + SimpleSAML_Logger::debug('Sending logout response to SP ' . var_export($spEntityId, TRUE)); + } + + $binding = new SAML2_HTTPRedirect(); + $binding->setDestination(sspmod_SAML2_Message::getDebugDestination()); + $binding->send($lr); + } + + + /** + * Receive a logout message. + * + * @param SimpleSAML_IdP $idp The IdP we are receiving it for. + */ + public static function receiveLogoutMessage(SimpleSAML_IdP $idp) { + + $binding = SAML2_Binding::getCurrentBinding(); + $message = $binding->receive(); + + $spEntityId = $message->getIssuer(); + if ($spEntityId === NULL) { + /* Without an issuer we have no way to respond to the message. */ + throw new SimpleSAML_Error_BadRequest('Received message on logout endpoint without issuer.'); + } + + $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); + $idpMetadata = $idp->getConfig(); + $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote'); + + sspmod_saml2_Message::validateMessage($idpMetadata, $spMetadata, $message); + + if ($message instanceof SAML2_LogoutResponse) { + + $spEntityId = $message->getIssuer(); + if ($spEntityId === NULL) { + throw new SimpleSAML_Error_Exception('Missing <Issuer> in LogoutResponse.'); + } + + $relayState = $message->getRelayState(); + + if (!$message->isSuccess()) { + $logoutError = sspmod_saml2_Message::getResponseError($message); + SimpleSAML_Logger::warning('Unsuccessful logout. Status was: ' . $logoutError); + } else { + $logoutError = NULL; + } + + $assocId = 'saml:' . $spEntityId; + + $idp->handleLogoutResponse($assocId, $relayState, $logoutError); + + + } elseif ($message instanceof SAML2_LogoutRequest) { + + $state = array( + 'Responder' => array('sspmod_saml_IdP_SAML2', 'sendLogoutResponse'), + 'saml:SPEntityId' => $spEntityId, + 'saml:RelayState' => $message->getRelayState(), + 'saml:RequestId' => $message->getId(), + ); + + $assocId = 'saml:' . $spEntityId; + $idp->handleLogoutRequest($state, $assocId); + + } else { + throw new SimpleSAML_Error_BadRequest('Unknown message received on logout endpoint: ' . get_class($message)); + } + + } + + + /** + * Retrieve a logout URL for a given logout association. + * + * @param SimpleSAML_IdP $idp The IdP we are sending a logout request from. + * @param array $association The association that should be terminated. + * @param string|NULL $relayState An id that should be carried across the logout. + */ + public static function getLogoutURL(SimpleSAML_IdP $idp, array $association, $relayState) { + assert('is_string($relayState) || is_null($relayState)'); + + $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); + $idpMetadata = $idp->getConfig(); + $spMetadata = $metadata->getMetaDataConfig($association['saml:entityID'], 'saml20-sp-remote'); + + $lr = sspmod_saml2_Message::buildLogoutRequest($idpMetadata, $spMetadata); + $lr->setRelayState($relayState); + $lr->setSessionIndex($association['saml:SessionIndex']); + $lr->setNameId($association['saml:NameID']); + + $binding = new SAML2_HTTPRedirect(); + return $binding->getRedirectURL($lr); + } + } diff --git a/templates/logout-iframe.php b/templates/logout-iframe.php deleted file mode 100644 index 52751f97e6846c30f1b00452f58f4882dc536226..0000000000000000000000000000000000000000 --- a/templates/logout-iframe.php +++ /dev/null @@ -1,239 +0,0 @@ -<?php - - $iframehtml = ''; - foreach ($this->data['sparray'] AS $sp) { - $iframehtml .= '<iframe class="hiddeniframe" onload="xajax_updateslostatus()" style="border: 1px solid #888; width: 80%; height: 100px" src="' . htmlentities($sp['url']) . '" ></iframe>'; - } -# $iframehtml = str_replace('"', '\"', $iframehtml); -# $iframehtml = str_replace("\n", '', $iframehtml); -# $iframehtml = str_replace("\r", '', $iframehtml); - - $this->data['hideLanguageBar'] = TRUE; - $this->data['head'] .= '<script type="text/javascript" src="/' . $this->data['baseurlpath'] . 'resources/jquery.js"></script>'; - $this->data['head'] .= '<link rel="stylesheet" type="text/css" href="/' . $this->data['baseurlpath'] . 'resources/slo.css" />'; - - $nologoutSPs = (count($this->data['sparrayNoLogout']) > 0); - - $this->data['head'] .= ' -<script type="text/javascript" language="JavaScript"> -<!-- - - -$(document).ready(function() { - $("div#requirejavascript").show(); -/* $("div.completedButWarnings").hide(); */ - $("div#interrupt").hide(); - $("input#ok").click(function () { - startslo(); - }); - $("input#cancel").click(function () { - sendResponse(); - }); - $("input#returnanyway").click(function () { - sendResponse(); - }); - $("input#interruptbutton").click(function () { - sendResponse(); - }); - - ' . ($nologoutSPs ? '$("#incapablesps").show();' : '$("#incapablesps").hide();') . ' - -}); - -function toolong() { - $("div#interrupt").show().fadeOut("fast").fadeIn("fast"); -} - -/* This function is called when users clicks to start single logout */ -function startslo() { - $("#confirmation").hide(); - $("#hiddeniframecontainer").html("' . str_replace('"', '\"', $iframehtml) . '"); - $("table#slostatustable tr.onhold").removeClass("onhold").addClass("inprogress"); -/* $("div.completedButWarnings").show(); */ -' . ($iframehtml === '' ? 'sendResponse();' : '') . ' - setTimeout("toolong()", 16000); -} - -/* This function is called from the AJAX response with xajax with the hash of the entityid of the SP */ -function slocompletesp($entityhash) { - $("table#slostatustable tr#" + $entityhash).filter(".inprogress").removeClass("inprogress").addClass("completed"). - children().fadeOut("fast").fadeIn("fast"); -} - - -/* SLO completed for all sps. */ -function slocompleted() { -/* $("div.completedButWarnings").show(); */ - $("div#interrupt").hide(); - setTimeout("sendResponse()", 2000); -} - -function sendResponse() { - window.location = "' . $this->data['logoutresponse'] . '"; -} -// --> -</script>'; - - $this->includeAtTemplateBase('includes/header.php'); - -?> - -<!-- Proper fallback for browsers that do not support javascript or have javascript turned off --> -<noscript> - <div id="nojavascriptframe"> - <iframe style="margin: 1em; width: 90%; height: 5em; border: 1px solid #eee" src="SingleLogoutServiceiFrameNoJavascript.php?response=<?php echo urlencode($this->data['logoutresponse']); ?>"></iframe> - </div> -<?php - foreach ($this->data['sparray'] AS $sp) { - echo '<iframe class="hiddeniframe" onload="xajax_updateslostatus()" style="border: 1px solid #888; width: 80%; height: 100px" - src="' . htmlentities($sp['url']) . '" ></iframe>' . "\n"; - } -?> -</noscript> - - - - -<div id="requirejavascript" style="display: none"> - - <?php - #echo('<pre>'); print_r($this->data); exit; - if (array_key_exists('requesterName', $this->data)) { - $requesterName = is_array($this->data['requesterName']) ? - $this->getTranslation($this->data['requesterName']) : $this->data['requesterName']; - } - #echo('<p>' . $this->t('{logout:description}', array('%REQUESTERNAME%' => $requestername)) . '</p>'); - - ?> - - <!-- <div class="loggedout"><?php echo($this->t('{logout:logged_out}', array('%REQUESTERNAME%' => $requestername))); ?></div> --> - - <?php - - if (array_key_exists('requesterName', $this->data)) { - echo('<div><img style="float: left; margin-right: 12px" src="/' . $this->data['baseurlpath'] . 'resources/icons/checkmark48.png" alt="Successful logout" />'); - echo('<p style="padding-top: 16px; ">' . $this->t('{logout:loggedoutfrom}', array('%SP%' => '<strong>' .$requesterName.'</strong>')) . '</p>'); - echo('<p style="height: 0px; clear: left;"></p>'); - echo('</div>'); - } - - echo('<div style="margin-top: 3em; clear: both">'); - echo('<p style="margin-bottom: .5em">' . $this->t('{logout:also_from}') . '</p>'); - - echo '<table id="slostatustable">'; - -/** Remove initiated from. showed above instead - - echo '<tr class="initiated" id="e_initiated">' . "\n"; - echo ' <td><img style="float: left; margin: 3px" src="/' . $this->data['baseurlpath'] . - 'resources/icons/silk/accept.png" alt="Initiated from" /></td>' . "\n"; - echo ' <td>' . $this->t('{logout:initiated}') . '</td>'; - echo ' <td>' . $requesterName . '</td>' ."\n"; - echo '</tr>' . "\n"; - - */ - - - foreach ($this->data['sparrayNoLogout'] AS $spentityid => $sp) { - $spname = is_array($sp['name']) ? $this->getTranslation($sp['name']) : $sp['name']; - echo '<tr class="initiated" id="e' . sha1($spentityid) . '">' . "\n"; - echo ' <td class="statustext">Logout not supported</td>'; - echo ' <td ><img style="" src="/' . $this->data['baseurlpath'] . - 'resources/icons/silk/delete.png" alt="Initiated from" /></td>' . "\n"; - - echo ' <td>' . $spname . '</td>' ."\n"; - echo '</tr>' . "\n"; - } - - - foreach ($this->data['sparray'] AS $spentityid => $sp) { - $spname = is_array($sp['name']) ? $this->getTranslation($sp['name']) : $sp['name']; - - echo '<tr class="ready onhold" id="e' . sha1($spentityid) . '">' . "\n"; - - echo ' <td class="statustext">'; - echo ' <span class="completed">' . $this->t('{logout:completed}') . '</span>' . "\n"; -# echo ' <span class="onhold">' . $this->t('{logout:hold}') . '</span>' . "\n"; -# echo ' <span class="onhold"></span>' . "\n"; - echo ' <span class="inprogress">' . $this->t('{logout:progress}') . '</span>' . "\n"; - echo ' <span class="failed">' . $this->t('{logout:failed}') . '</span>' . "\n"; - echo ' </td>'; - - echo ' <td class="icons">'; - echo ' <img class="completed" src="/' . $this->data['baseurlpath'] . 'resources/icons/silk/accept.png" alt="Completed" />' . "\n"; - echo ' <img class="onhold" src="/' . $this->data['baseurlpath'] . 'resources/icons/bullet16_grey.png" alt="SP SLO on hold" />' . "\n"; - echo ' <img class="inprogress" src="/' . $this->data['baseurlpath'] . 'resources/progress.gif" alt="Progress bar" />' . "\n"; - echo ' <img class="failed" src="/' . $this->data['baseurlpath'] . 'resources/icons/silk/exclamation.png" alt="Failed" />' . "\n"; - echo ' </td>' . "\n"; - - - - echo ' <td>' . $spname . '</td>' ."\n"; - - echo '</tr>' . "\n"; - -// echo '<div class="inprogress" id="e' . sha1($spentityid) . '"> -// <img style="float: left; margin: 3px" src="/' . $this->data['baseurlpath'] . 'resources/progress.gif" alt="Progress bar" />Wait... is logging out from <strong>' . $spname . '</strong></div>' . "\n"; - } - echo '</table></div>'; - - $completed = ' class="allcompleted"'; - if (count($this->data['sparray']) > 0) { - $completed = ''; - } - - - ?> - - <div id="confirmation" style="margin-top: 1em" > - <p> - <?php echo $this->t('{logout:logout_all_question}'); ?> <br /> - </p> - <input type="button" id="ok" name="ok" value="<?php echo $this->t('{logout:logout_all}'); ?>" /> - <?php - - if (array_key_exists('requesterName', $this->data)) { - echo '<input type="button" id="cancel" name="cancel" value="' . $this->t('{logout:logout_only}', array('%SP%' => $requesterName)) . '" />'; - } else { - echo '<input type="button" id="cancel" name="cancel" value="' . $this->t('{logout:no}') . '" />'; - } - - ?> - - - - <p id="incapablesps" > - <?php echo($this->t('{logout:incapablesps}')); ?> - </p> - - - </div> - - - - - - <div id="interrupt" style="margin-top: 1em; border: 1px solid #ccc; padding: 1em; background: #eaeaea" > - <p style="margin: 0px; padding; 0px"> - <img src="/<?php echo($this->data['baseurlpath']); ?>resources/icons/timeout.png" - alt="Timeout" - style="float: left; margin: 0px 5px 0px 0px" - /> - <?php echo $this->t('{logout:respond_info}'); ?> <br /> - <input type="button" id="interruptbutton" name="interrupt" value="<?php echo $this->t('{logout:return}'); ?>" /> - </p> - </div> - - - <div id="hiddeniframecontainer" style="margin: 0px; padding: 0px;"></div> - - -</div> <!-- requirejavascript --> - -<!-- -<script type="text/javascript" language="JavaScript"> - showdiv('requirejavascript'); -</script> ---> - -<?php $this->includeAtTemplateBase('includes/footer.php'); ?> diff --git a/www/saml2/idp/SingleLogoutService.php b/www/saml2/idp/SingleLogoutService.php index 6a9abe1e6908839d40cc65388018bf1f637db62a..618068cd88d3d413ba16cfc9494390598a5f6a36 100644 --- a/www/saml2/idp/SingleLogoutService.php +++ b/www/saml2/idp/SingleLogoutService.php @@ -9,324 +9,17 @@ * @version $Id$ */ -// TODO: Show error message, when shibboleth sp is logged in. - require_once('../../_include.php'); -$config = SimpleSAML_Configuration::getInstance(); -$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); -$session = SimpleSAML_Session::getInstance(); - SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutService: Accessing SAML 2.0 IdP endpoint SingleLogoutService'); -if (!$config->getBoolean('enable.saml20-idp', false)) - SimpleSAML_Utilities::fatalError(isset($session) ? $session->getTrackID() : null, 'NOACCESS'); - -try { - $idpEntityId = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); - $idpMetadata = $metadata->getMetaDataConfig($idpEntityId, 'saml20-idp-hosted'); -} catch (Exception $exception) { - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception); -} - -SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutService: Got IdP entity id: ' . $idpEntityId); - - -$logouttype = $idpMetadata->getString('logouttype', 'traditional'); -if ($logouttype !== 'traditional') - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'NOACCESS', new Exception('This IdP is configured to use logout type [' . $logouttype . '], but this endpoint is only available for IdP using logout type [traditional]')); - - - - -/** - * The $logoutInfo contains information about the current logout operation. - * It can have the following attributes: - * - 'RelayState' - The RelayState which should be returned to the SP which initiated the logout operation. - * - 'Issuer' - The entity id of the SP which initiated the logout operation. - * - 'RequestID' - The id of the LogoutRequest which initiated the logout operation. - */ -$logoutInfo = array(); - - -/** - * This function retrieves the logout info with the given ID. - * - * @param $id The identifier of the logout info. - */ -function fetchLogoutInfo($id) { - global $session; - global $logoutInfo; - - $logoutInfo = $session->getData('idplogoutresponsedata', $id); - - if($logoutInfo === NULL) { - SimpleSAML_Logger::warning('SAML2.0 - IdP.SingleLogoutService: Lost logout information.'); - } -} - - -/** - * This function saves the logout info with the given ID. - * - * @param $id The identifier the logout info should be saved with. - */ -function saveLogoutInfo($id) { - global $session; - global $logoutInfo; - - $session->setData('idplogoutresponsedata', $id, $logoutInfo); -} - - -/** - * If we get an incoming LogoutRequest then we initiate the logout process. - * in this case an SAML 2.0 SP is sending an request, which also is referred to as - * SP initiated Single Logout. - * - */ -if (isset($_REQUEST['SAMLRequest'])) { - - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutService: Got SAML reuqest'); - - $binding = SAML2_Binding::getCurrentBinding(); - - try { - $logoutRequest = $binding->receive(); - if (!($logoutRequest instanceof SAML2_LogoutRequest)) { - throw new Exception('Received a request which wasn\'t a LogoutRequest ' . - 'on logout endpoint. Was: ' . get_class($logoutRequest)); - } - - $spEntityId = $logoutRequest->getIssuer(); - if ($spEntityId === NULL) { - throw new Exception('Missing issuer in logout reqeust.'); - } - - $spMetadata = $metadata->getMetadataConfig($spEntityId, 'saml20-sp-remote'); - - sspmod_saml2_Message::validateMessage($spMetadata, $idpMetadata, $logoutRequest); - - } catch(Exception $exception) { - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'LOGOUTREQUEST', $exception); - } - - SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutService: got Logoutrequest from ' . $spEntityId); - SimpleSAML_Logger::stats('saml20-idp-SLO spinit ' . $spEntityId . ' ' . $idpEntityId); - - /* Fill in the $logoutInfo associative array with information about this logout request. */ - $logoutInfo['Issuer'] = $spEntityId; - $logoutInfo['RequestID'] = $logoutRequest->getId(); - - $logoutInfo['RelayState'] = $logoutRequest->getRelayState(); - - SimpleSAML_Logger::debug('SAML2.0 - IDP.SingleLogoutService: Setting cached request with issuer ' . $spEntityId); - - $session->set_sp_logout_completed($spEntityId); - - - /* - * We receive a Logout Response to a Logout Request that we have issued earlier. - */ -} elseif (isset($_REQUEST['SAMLResponse'])) { - - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutService: Got SAML response'); - - $binding = SAML2_Binding::getCurrentBinding(); - - try { - $logoutResponse = $binding->receive(); - if (!($logoutResponse instanceof SAML2_LogoutResponse)) { - throw new Exception('Received a response which wasn\'t a LogoutResponse ' . - 'on logout endpoint. Was: ' . get_class($logoutResponse)); - } - - $spEntityId = $logoutResponse->getIssuer(); - if ($spEntityId === NULL) { - throw new Exception('Missing issuer in logout response.'); - } - - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutService: SAML response parsed. Issuer is: ' . $spEntityId); - $spMetadata = $metadata->getMetadataConfig($spEntityId, 'saml20-sp-remote'); - - sspmod_saml2_Message::validateMessage($spMetadata, $idpMetadata, $logoutResponse); - - } catch(Exception $exception) { - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'LOGOUTRESPONSE', $exception); - } - - /* Fetch the $logoutInfo variable based on the InResponseTo attribute of the response. */ - fetchLogoutInfo($logoutResponse->getInResponseTo()); - - $session->set_sp_logout_completed($spEntityId); - - SimpleSAML_Logger::info('SAML2.0 - IDP.SingleLogoutService: got LogoutResponse from ' . $spEntityId); - -} elseif(array_key_exists('LogoutID', $_GET)) { - /* This is a response from bridged SLO. */ - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutService: Got response from bridged SLO.'); - - /* Fetch the $logoutInfo variable. */ - fetchLogoutInfo($_GET['LogoutID']); - -} elseif(array_key_exists('ReturnTo', $_GET)) { - /* We have a ReturnTo - this is IdP initialized SLO. */ - $logoutInfo['RelayState'] = $_GET['ReturnTo']; +$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); +$idpEntityId = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); +$idp = SimpleSAML_IdP::getById('saml2:' . $idpEntityId); +if (isset($_REQUEST['ReturnTo'])) { + $idp->doLogoutRedirect((string)$_REQUEST['ReturnTo']); } else { - /* - * We have no idea what to do here. It is neither a logout request, a logout - * response nor a response from bridged SLO. - */ - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutService: No request, response or bridge'); - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'SLOSERVICEPARAMS'); -} - -/* First, log out of the current authentication source. */ -$authority = $session->getAuthority(); -if ($authority !== NULL) { - /* We are logged in. */ - - $bridgedId = SimpleSAML_Utilities::generateID(); - $returnTo = SimpleSAML_Utilities::selfURLNoQuery() . '?LogoutID=' . $bridgedId; - - /* Save the $logoutInfo until we return from the SP. */ - saveLogoutInfo($bridgedId); - - if ($authority === $idpMetadata->getString('auth')) { - /* This is probably an authentication source. */ - SimpleSAML_Auth_Default::initLogoutReturn($returnTo); - } elseif ($authority === 'saml2') { - /* SAML 2 SP which isn't an authentication source. */ - SimpleSAML_Utilities::redirect('/' . $config->getBaseURL() . 'saml2/sp/initSLO.php', - array('RelayState' => $returnTo) - ); - } else { - /* A different old-style authentication file. */ - $session->doLogout(); - } -} - - -/* - * Find the next SP we should log out from. We will search through the list of - * SPs until we find a valid SP with a SingleLogoutService endpoint. - */ -while (TRUE) { - /* Dump the current sessions (for debugging). */ - $session->dump_sp_sessions(); - - /* - * We proceed to send logout requests to all remaining SPs. - */ - $spEntityId = $session->get_next_sp_logout(); - - // If there are no more SPs left, then we will not look for more SPs. - if (empty($spEntityId)) { - break; - } - - try { - $spMetadata = $metadata->getMetadataConfig($spEntityId, 'saml20-sp-remote'); - } catch (Exception $e) { - /* It seems that an SP has disappeared from the metadata between login and logout. */ - SimpleSAML_Logger::info('SAML2.0 - IDP.SingleLogoutService: Missing metadata for ' . - $spEntityId . '; looking for more SPs.'); - continue; - } - - $singleLogoutService = $spMetadata->getDefaultEndpoint('SingleLogoutService', array(SAML2_Const::BINDING_HTTP_REDIRECT), NULL); - if ($singleLogoutService === NULL) { - SimpleSAML_Logger::info('SAML2.0 - IDP.SingleLogoutService: No supported SingleLogoutService for ' . - $spEntityId . '; looking for more SPs.'); - continue; - } - - /* $spEntityId now contains the next SP. */ - break; -} - - -if ($spEntityId) { - - SimpleSAML_Logger::info('SAML2.0 - IDP.SingleLogoutService: Logout next SP ' . $spEntityId); - - try { - - $nameId = $session->getSessionNameId('saml20-sp-remote', $spEntityId); - if($nameId === NULL) { - $nameId = $session->getNameID(); - } - - $lr = sspmod_saml2_Message::buildLogoutRequest($idpMetadata, $spMetadata); - $lr->setSessionIndex($session->getSessionIndex()); - $lr->setNameId($nameId); - - /* Save the $logoutInfo until we return from the SP. */ - saveLogoutInfo($lr->getId()); - - $binding = new SAML2_HTTPRedirect(); - $binding->setDestination(sspmod_SAML2_Message::getDebugDestination()); - $binding->send($lr); - - } catch(Exception $exception) { - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'GENERATELOGOUTREQUEST', $exception); - } -} - -if ($config->getBoolean('debug', false)) - SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutService: LogoutService: All SPs done '); - - - -/* - * Logout procedure is done and we send a Logout Response back to the SP - */ - -try { - - if(!$logoutInfo) { - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'LOGOUTINFOLOST'); - } - - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutService: Found logout info with these keys: ' . join(',', array_keys($logoutInfo))); - - /** - * Clean up session object to save storage. - */ - if ($config->getBoolean('debug', false)) - SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutService: Session Size before cleaning: ' . $session->getSize()); - - $session->clean(); - - if ($config->getBoolean('debug', false)) - SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutService: Session Size after cleaning: ' . $session->getSize()); - - - /* - * Check if the Single Logout procedure is initated by an SP (alternatively IdP initiated SLO - */ - if (array_key_exists('Issuer', $logoutInfo)) { - - $spEntityId = $logoutInfo['Issuer']; - $spMetadata = $metadata->getMetadataConfig($spEntityId, 'saml20-sp-remote'); - - $lr = sspmod_saml2_Message::buildLogoutResponse($idpMetadata, $spMetadata); - $lr->setInResponseTo($logoutInfo['RequestID']); - $lr->setRelayState($logoutInfo['RelayState']); - $binding = new SAML2_HTTPRedirect(); - $binding->setDestination(sspmod_SAML2_Message::getDebugDestination()); - $binding->send($lr); - - } elseif (array_key_exists('RelayState', $logoutInfo)) { - - SimpleSAML_Utilities::redirect($logoutInfo['RelayState']); - exit; - - } else { - echo 'You are logged out'; exit; - } - -} catch(Exception $exception) { - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'GENERATELOGOUTRESPONSE', $exception); + sspmod_saml_IdP_SAML2::receiveLogoutMessage($idp); } +assert('FALSE'); diff --git a/www/saml2/idp/SingleLogoutServiceiFrame.php b/www/saml2/idp/SingleLogoutServiceiFrame.php index 85a6f40c6695b339dca4d2bcb4980223730230b9..1e06782c2bb84ac373d6c61903bca46ac322a467 100644 --- a/www/saml2/idp/SingleLogoutServiceiFrame.php +++ b/www/saml2/idp/SingleLogoutServiceiFrame.php @@ -11,444 +11,10 @@ require_once('../../_include.php'); -$config = SimpleSAML_Configuration::getInstance(); -$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); -$session = SimpleSAML_Session::getInstance(); - SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutServiceiFrame: Accessing SAML 2.0 IdP endpoint SingleLogoutService (iFrame version)'); -SimpleSAML_Logger::debug('Initially; ' . join(',', $session->get_sp_list(SimpleSAML_Session::STATE_ONLINE))); - -if (!$config->getBoolean('enable.saml20-idp', false)) - SimpleSAML_Utilities::fatalError(isset($session) ? $session->getTrackID() : null, 'NOACCESS'); - -try { - $idpentityid = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); - $idpMetadata = $metadata->getMetaDataConfig($idpentityid, 'saml20-idp-hosted'); -} catch (Exception $exception) { - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception); -} - -SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutServiceiFrame: Got IdP entity id: ' . $idpentityid); - - - -$logouttype = 'traditional'; -$idpmeta = $metadata->getMetaDataCurrent('saml20-idp-hosted'); -if (array_key_exists('logouttype', $idpmeta)) $logouttype = $idpmeta['logouttype']; - -if ($logouttype !== 'iframe') - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'NOACCESS', new Exception('This IdP is configured to use logout type [' . $logouttype . '], but this endpoint is only available for IdP using logout type [iframe]')); - - - -/** - * The $logoutInfo contains information about the current logout operation. - * It can have the following attributes: - * - 'RelayState' - The RelayState which should be returned to the SP which initiated the logout operation. - * - 'Issuer' - The entity id of the SP which initiated the logout operation. - * - 'RequestID' - The id of the LogoutRequest which initiated the logout operation. - */ -$logoutInfo = array(); - - -/** - * This function retrieves the logout info with the given ID. - * - * @param $id The identifier of the logout info. - */ -function fetchLogoutInfo($id) { - global $session; - global $logoutInfo; - - $logoutInfo = $session->getData('idplogoutresponsedata', $id); - - if($logoutInfo === NULL) { - SimpleSAML_Logger::warning('SAML2.0 - IdP.SingleLogoutService: Lost logout information.'); - } -} - - -/** - * This function saves the logout info with the given ID. - * - * @param $id The identifier the logout info should be saved with. - */ -function saveLogoutInfo($id) { - global $session; - global $logoutInfo; - - $session->setData('idplogoutresponsedata', $id, $logoutInfo); -} - - -// Include XAJAX definition. -require_once(SimpleSAML_Utilities::resolvePath('libextinc') . '/xajax/xajax.inc.php'); - - - -/* - * This function is called via AJAX and will send LogoutRequest to one single SP by - * sending a LogoutRequest using HTTP-REDIRECT - */ -function updateslostatus() { - - SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutServiceiFrame: Accessing SAML 2.0 IdP endpoint SingleLogoutService (iFrame version) within updateslostatus() '); - - $config = SimpleSAML_Configuration::getInstance(); - $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); - $session = SimpleSAML_Session::getInstance(); - - $idpentityid = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); - - $templistofsps = $session->get_sp_list(SimpleSAML_Session::STATE_ONLINE); - $listofsps = array(); - foreach ($templistofsps AS $spentityid) { - if (!empty($_COOKIE['spstate-' . sha1($spentityid)])) { - $listofsps[] = $spentityid; - continue; - } - - try { - $spMetadata = $metadata->getMetaDataConfig($spentityid, 'saml20-sp-remote'); - } catch (Exception $e) { - /* - * For some reason, the metadata for this SP is no longer available. Most - * likely it was deleted from the IdP while the user had a session to it. - * In any case - skip this SP. - */ - $listofsps[] = $spentityid; - continue; - } - - $singleLogoutService = $spMetadata->getDefaultEndpoint('SingleLogoutService', array(SAML2_Const::BINDING_HTTP_REDIRECT), NULL); - if ($singleLogoutService === NULL) { - /* No logout endpoint. */ - $listofsps[] = $spentityid; - continue; - } - - /* This SP isn't ready yet. */ - } - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutServiceiFrame: templistofsps ' . join(',', $templistofsps)); - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutServiceiFrame: listofsps ' . join(',', $listofsps)); - - - // Using template object to be able to translate name of service provider. - $t = new SimpleSAML_XHTML_Template($config, 'logout-iframe.php'); - - // Instantiate the xajaxResponse object - $objResponse = new xajaxResponse(); - - foreach ($listofsps AS $spentityid) { - - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutServiceiFrame: Completed ' . $spentityid); - - // add a command to the response to assign the innerHTML attribute of - // the element with id="SomeElementId" to whatever the new content is - - try { - $spmetadata = $metadata->getMetaData($spentityid, 'saml20-sp-remote'); - } catch (Exception $e) { - /* - * For some reason, the metadata for this SP is no longer available. Most - * likely it was deleted from the IdP while the user had a session to it. - * In any case - skip this SP. - */ - continue; - } - - $name = array_key_exists('name', $spmetadata) ? $spmetadata['name'] : $spentityid; - - $spname = is_array($name) ? $t->getTranslation($name) : $name; - - $objResponse->addScriptCall('slocompletesp', 'e' . sha1($spentityid)); - - } - - if (count($templistofsps) === count($listofsps)) { - - $templistofsps = $session->get_sp_list(SimpleSAML_Session::STATE_ONLINE); - foreach ($templistofsps AS $spentityid) { - $session->set_sp_logout_completed($spentityid); - setcookie('spstate-' . sha1($spentityid) , '', time() - 3600); // Delete cookie - } - - $objResponse->addScriptCall('slocompleted'); - - /** - * Clean up session object to save storage. - */ - if ($config->getBoolean('debug', false)) - SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutService: Session Size before cleaning: ' . $session->getSize()); - - $session->clean(); - - if ($config->getBoolean('debug', false)) - SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutService: Session Size after cleaning: ' . $session->getSize()); - - } else { - SimpleSAML_Logger::debug('SAML2.0 - sp_logout_completed FALSE'); - } - - //return the xajaxResponse object - return $objResponse; -} - - - -$xajax = new xajax(); -$xajax->registerFunction("updateslostatus"); -$xajax->processRequests(); - - - - - -/* - * If we get an LogoutRequest then we initiate the logout process. - */ -if (isset($_REQUEST['SAMLRequest'])) { - - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutService: Got SAML reuqest'); - - $binding = SAML2_Binding::getCurrentBinding(); - - try { - $logoutrequest = $binding->receive(); - if (!($logoutrequest instanceof SAML2_LogoutRequest)) { - throw new Exception('Not a valid logout request.'); - } - - $spEntityId = $logoutrequest->getIssuer(); - if ($spEntityId === NULL) { - throw new Exception('Missing issuer in logout request.'); - } - - $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote'); - - sspmod_saml2_Message::validateMessage($spMetadata, $idpMetadata, $logoutrequest); - - } catch(Exception $exception) { - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'LOGOUTREQUEST', $exception); - } - - /* Log a warning if the NameID in the LogoutRequest isn't the one we assigned to the SP. */ - $requestNameId = $logoutrequest->getNameId(); - ksort($requestNameId); - $sessionNameId = $session->getSessionNameId('saml20-sp-remote', $spEntityId); - ksort($sessionNameId); - if ($sessionNameId !== NULL && $requestNameId !== $sessionNameId) { - SimpleSAML_Logger::warning('Wrong NameID in LogoutRequest from ' . - var_export($spEntityId, TRUE) . '.'); - } - - /* Log a warning if the SessionIndex in the LogoutRequest isn't correct. */ - $requestSessionIndex = $logoutrequest->getSessionIndex(); - $sessionSessionIndex = $session->getSessionIndex(); - if ($requestSessionIndex !== $sessionSessionIndex) { - SimpleSAML_Logger::warning('Wrong SessionIndex in LogoutRequest from ' . - var_export($spEntityId, TRUE) . '.'); - } - - - // Extract some parameters from the logout request - #$requestid = $logoutrequest->getRequestID(); - $requester = $logoutrequest->getIssuer(); - #$relayState = $logoutrequest->getRelayState(); - $responder = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); - - SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutService: got Logoutrequest from ' . $logoutrequest->getIssuer()); - SimpleSAML_Logger::stats('saml20-idp-SLO spinit ' . $requester . ' ' . $responder); - - - $session->doLogout(); - - - /* Fill in the $logoutInfo associative array with information about this logout request. */ - $logoutInfo['Issuer'] = $logoutrequest->getIssuer(); - $logoutInfo['RequestID'] = $logoutrequest->getId(); - - $relayState = $logoutrequest->getRelayState(); - if($relayState !== NULL) { - $logoutInfo['RelayState'] = $relayState; - } - - SimpleSAML_Logger::debug('SAML2.0 - IDP.SingleLogoutService: Setting cached request with issuer ' . $logoutrequest->getIssuer()); - - $session->set_sp_logout_completed($logoutrequest->getIssuer()); - - -/* - * We receive a Logout Response to a Logout Request that we have issued earlier. - * If so, there is a misconfiguration. - */ -} elseif (isset($_REQUEST['SAMLResponse'])) { - - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'LOGOUTRESPONSE', - new Exception('The SP is likely to be misconfigured. The LogoutResponse is sent to wrong endpoint. This iFrame endpoint only accepts LogoutRequests, and the response is to be sent to a separate endpoint. Please revisit the IdP-Remote metadata on the SP.') - ); - -} else { - /* - * We have no idea what to do here. It is neither a logout request, a logout - * response nor a response from bridged SLO. - */ - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutService: No request, response or bridge'); - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'SLOSERVICEPARAMS'); -} - - -// Debug entries in the log about what services the user is logged into. -$session->dump_sp_sessions(); - - - -/* - * Generate a list of all service providers, and create a LogoutRequest message for all these SPs. - */ -$listofsps = $session->get_sp_list(); -$sparray = array(); -$sparrayNoLogout = array(); -foreach ($listofsps AS $spentityid) { - - // ($issuer, $receiver, $nameid, $nameidformat, $sessionindex, $mode) { - $nameId = $session->getSessionNameId('saml20-sp-remote', $spentityid); - if($nameId === NULL) { - $nameId = $session->getNameID(); - } - - try { - $spMetadata = $metadata->getMetaDataConfig($spentityid, 'saml20-sp-remote'); - } catch (Exception $e) { - /* - * For some reason, the metadata for this SP is no longer available. Most - * likely it was deleted from the IdP while the user had a session to it. - * In any case - skip this SP. - */ - continue; - } - - $name = $spMetadata->getValue('name', $spentityid); - - try { - $lr = sspmod_saml2_Message::buildLogoutRequest($idpMetadata, $spMetadata); - $lr->setSessionIndex($session->getSessionIndex()); - $lr->setNameId($nameId); - - $httpredirect = new SAML2_HTTPRedirect(); - $url = $httpredirect->getRedirectURL($lr); - - $sparray[$spentityid] = array('url' => $url, 'name' => $name); - - /* Add the SP logout request information to the session so that we can check it later. */ - $requestInfo = array( - 'ID' => $lr->getId(), - 'RelayState' => $lr->getRelayState(), - ); - $session->setData('slo-request-info', $spentityid, $requestInfo, 15*60); - - } catch (Exception $e) { - $sparrayNoLogout[$spentityid] = array('name' => $name); - } - -} - - -SimpleSAML_Logger::debug('SAML2.0 - SP Counter. other SPs with SLO support (' . count($sparray) . ') without SLO support (' . count($sparrayNoLogout) . ')'); - - -#print_r($sparray); - - - - - - -/* - * Logout procedure is done and we send a Logout Response back to the SP - */ - -try { - - if(!$logoutInfo) SimpleSAML_Utilities::fatalError($session->getTrackID(), 'LOGOUTINFOLOST'); - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutService: Found logout info with these keys: ' . join(',', array_keys($logoutInfo))); - - /* - * Check if the Single Logout procedure is initated by an SP (alternatively IdP initiated SLO) - */ - if (array_key_exists('Issuer', $logoutInfo)) { - - $spMetadata = $metadata->getMetaDataConfig($logoutInfo['Issuer'], 'saml20-sp-remote'); - - // Find the relaystate if cached. - $relayState = isset($logoutInfo['RelayState']) ? $logoutInfo['RelayState'] : null; - - /* Create a Logout Response. */ - $rg = sspmod_saml2_Message::buildLogoutResponse($idpMetadata, $spMetadata); - $rg->setInResponseTo($logoutInfo['RequestID']); - $rg->setRelayState($relayState); - - $httpredirect = new SAML2_HTTPRedirect(); - - /* - * If the user is not logged into any other SPs, send the LogoutResponse immediately - */ - if (count($sparray) + count($sparrayNoLogout) === 0) { - $httpredirect->setDestination(sspmod_SAML2_Message::getDebugDestination()); - $httpredirect->send($rg); - } else { - $logoutresponse = $httpredirect->getRedirectURL($rg); - } - - - } elseif (array_key_exists('RelayState', $logoutInfo)) { - - SimpleSAML_Utilities::redirect($logoutInfo['RelayState']); - exit; - - } else { - - echo 'You are logged out'; exit; - - } - -} catch(Exception $exception) { - - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'GENERATELOGOUTRESPONSE', $exception); - -} - - - - -$spmeta = $metadata->getMetaData($requester, 'saml20-sp-remote'); -$spname = $requester; -if (array_key_exists('name', $spmeta)) $spname = $spmeta['name']; - - - - - - - -$et = new SimpleSAML_XHTML_Template($config, 'logout-iframe.php'); - -$et->data['header'] = 'Logout'; -$et->data['sparray'] = $sparray; -$et->data['sparrayNoLogout'] = $sparrayNoLogout; - -$et->data['logoutresponse'] = $logoutresponse; -$et->data['xajax'] = $xajax; -$et->data['requesterName'] = $spname; - -$et->data['head'] = $xajax->getJavascript(); - -$et->show(); - -exit(0); - - - - -?> \ No newline at end of file +$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); +$idpEntityId = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); +$idp = SimpleSAML_IdP::getById('saml2:' . $idpEntityId); +sspmod_saml_IdP_SAML2::receiveLogoutMessage($idp); +assert('FALSE'); diff --git a/www/saml2/idp/SingleLogoutServiceiFrameNoJavascript.php b/www/saml2/idp/SingleLogoutServiceiFrameNoJavascript.php deleted file mode 100644 index c5a96ea3a84a5fba379861abdf87ad6c5f46276c..0000000000000000000000000000000000000000 --- a/www/saml2/idp/SingleLogoutServiceiFrameNoJavascript.php +++ /dev/null @@ -1,102 +0,0 @@ -<?php - -/** - * This SAML 2.0 endpoint can receive incoming LogoutRequests. It will also send LogoutResponses, - * and LogoutRequests and also receive LogoutResponses. It is implemeting SLO at the SAML 2.0 IdP. - * - * @author Andreas Ă…kre Solberg, UNINETT AS. <andreas.solberg@uninett.no> - * @package simpleSAMLphp - * @version $Id$ - */ - -require_once('../../_include.php'); - -$config = SimpleSAML_Configuration::getInstance(); -$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); -$session = SimpleSAML_Session::getInstance(); - -SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutServiceiFrame: Accessing SAML 2.0 IdP endpoint SingleLogoutService (iFrame version)'); - -if (!$config->getBoolean('enable.saml20-idp', false)) - SimpleSAML_Utilities::fatalError(isset($session) ? $session->getTrackID() : null, 'NOACCESS'); - -try { - $idpentityid = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); -} catch (Exception $exception) { - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception); -} - -SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutServiceiFrame: Got IdP entity id: ' . $idpentityid); - - - -$logouttype = 'traditional'; -$idpmeta = $metadata->getMetaDataCurrent('saml20-idp-hosted'); -if (array_key_exists('logouttype', $idpmeta)) $logouttype = $idpmeta['logouttype']; - -if ($logouttype !== 'iframe') - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'NOACCESS', new Exception('This IdP is configured to use logout type [' . $logouttype . '], but this endpoint is only available for IdP using logout type [iframe]')); - - - -SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutServiceiFrameNoJavascript: Accessing SAML 2.0 IdP endpoint SingleLogoutService (iFrame version without javascript support) '); - -$config = SimpleSAML_Configuration::getInstance(); -$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); -$session = SimpleSAML_Session::getInstance(); - -$idpentityid = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); - - - -$templistofsps = $session->get_sp_list(SimpleSAML_Session::STATE_ONLINE); -$listofsps = array(); -foreach ($templistofsps AS $spentityid) { - if (!empty($_COOKIE['spstate-' . sha1($spentityid)])) $listofsps[] = $spentityid; -} - - -if (count($templistofsps) === count($listofsps)) { - - $templistofsps = $session->get_sp_list(SimpleSAML_Session::STATE_ONLINE); - foreach ($templistofsps AS $spentityid) { - $session->set_sp_logout_completed($spentityid); - setcookie('spstate-' . sha1($spentityid) , '', time() - 3600); // Delete cookie - } - - - echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> - <meta http-equiv="content-type" content="text/html; charset=utf-8" /> - <title>Logout Update notificator for Non-Javascript Single Log-Out</title> -</head> -<body> - <p>You are successfully logged out. [ <a target="_top" href="' . htmlentities($_REQUEST['response']) . '">Continue</a> ]</p> -</body> -</html> -'; - - - -} else { - echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> - <meta http-equiv="content-type" content="text/html; charset=utf-8" /> - <meta http-equiv="refresh" content="3;url=SingleLogoutServiceiFrameNoJavascript.php?response=' . urlencode($_REQUEST['response']) . '" /> - <title>Logout Update notificator for Non-Javascript Single Log-Out</title> -</head> -<body> - <p> - <img style="float: left; margin: 3px" src="/' . $config->getBaseURL() . 'resources/progress.gif" alt="Progress bar" /> - Logout in progress. [ <a target="_top" href="' . htmlentities($_REQUEST['response']) . '">Interrupt</a> ]</p> -</body> -</html> -'; -} - - -?> \ No newline at end of file diff --git a/www/saml2/idp/SingleLogoutServiceiFrameResponse.php b/www/saml2/idp/SingleLogoutServiceiFrameResponse.php index dddd1b8a19e4157841a1861325b29ad2d011cb43..de95805e93aff5ffa2ef70b8f77e607ccb46c6da 100644 --- a/www/saml2/idp/SingleLogoutServiceiFrameResponse.php +++ b/www/saml2/idp/SingleLogoutServiceiFrameResponse.php @@ -11,79 +11,10 @@ require_once('../../_include.php'); -$config = SimpleSAML_Configuration::getInstance(); -$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); -$session = SimpleSAML_Session::getInstance(); - SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutServiceiFrameResponse: Accessing SAML 2.0 IdP endpoint SingleLogoutServiceResponse (iFrame version)'); -if (!$config->getBoolean('enable.saml20-idp', false)) - SimpleSAML_Utilities::fatalError(isset($session) ? $session->getTrackID() : null, 'NOACCESS'); - -try { - $idpEntityId = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); - $idpMetadata = $metadata->getMetaDataConfig($idpEntityId, 'saml20-idp-hosted'); -} catch (Exception $exception) { - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception); -} - -SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutServiceiFrame: Got IdP entity id: ' . $idpEntityId); - -$logouttype = $idpMetadata->getString('logouttype', 'traditional'); -if ($logouttype !== 'iframe') - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'NOACCESS', new Exception('This IdP is configured to use logout type [' . $logouttype . '], but this endpoint is only available for IdP using logout type [iframe]')); - - -if (!isset($_REQUEST['SAMLResponse'])) { - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'SLOSERVICEPARAMS', - new Exception('No valid SAMLResponse found? Probably some error in remote partys metadata that sends something to this endpoint that is not SAML LogoutResponses') ); -} - -$binding = SAML2_Binding::getCurrentBinding();; -$logoutResponse = $binding->receive();; -if (!($logoutResponse instanceof SAML2_LogoutResponse)) { - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'SLOSERVICEPARAMS', - new Exception('Message received on response endpoint wasn\'t a response. Was: ' . get_class($logoutResponse))); -} - -$spEntityId = $logoutResponse->getIssuer(); -if ($spEntityId === NULL) { - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'SLOSERVICEPARAMS', - new Exception('Missing issuer on logout response.')); -} -$spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote'); - -sspmod_saml2_Message::validateMessage($spMetadata, $idpMetadata, $logoutResponse); - -/* - * Check the logout response against the logout request, and log - * warnings if there is a mismatch. - */ -$requestInfo = $session->getData('slo-request-info', $spEntityId); -if ($requestInfo !== NULL) { - if ($logoutResponse->getInResponseTo() !== $requestInfo['ID']) { - SimpleSAML_Logger::warning('Wrong InResponseTo in LogoutResponse from ' . - var_export($spEntityId, TRUE) . '.'); - } - if ($logoutResponse->getRelayState() !== $requestInfo['RelayState']) { - SimpleSAML_Logger::warning('Wrong RelayState in LogoutResponse from ' . - var_export($spEntityId, TRUE) . '.'); - } -} - -$sphash = sha1($spEntityId); -setcookie('spstate-' . $sphash , '1'); // Duration: 2 hours - -SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutServiceiFrameResponse: Logging out completed'); - -echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> - <meta http-equiv="content-type" content="text/html; charset=utf-8" /> - <title>Logout OK</title> -</head> -<body>OK</body> -</html>'; - -?> \ No newline at end of file +$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); +$idpEntityId = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); +$idp = SimpleSAML_IdP::getById('saml2:' . $idpEntityId); +sspmod_saml_IdP_SAML2::receiveLogoutMessage($idp); +assert('FALSE'); diff --git a/www/saml2/idp/idpInitSingleLogoutServiceiFrame.php b/www/saml2/idp/idpInitSingleLogoutServiceiFrame.php index 4e1b2c866157a74657be02f6fa5a58fcd35af458..18b3d332e68ba018ee38d9c61eff2425b1382bed 100644 --- a/www/saml2/idp/idpInitSingleLogoutServiceiFrame.php +++ b/www/saml2/idp/idpInitSingleLogoutServiceiFrame.php @@ -10,277 +10,13 @@ require_once('../../_include.php'); -$config = SimpleSAML_Configuration::getInstance(); $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); -$session = SimpleSAML_Session::getInstance(); - -SimpleSAML_Logger::info('SAML2.0 - IdP.idpInitSingleLogoutServiceiFrame: Accessing SAML 2.0 IdP endpoint SingleLogoutService (iFrame version)'); - -SimpleSAML_Logger::debug('Initially; ' . join(',', $session->get_sp_list(SimpleSAML_Session::STATE_ONLINE))); - -if (!$config->getBoolean('enable.saml20-idp', false)) - SimpleSAML_Utilities::fatalError(isset($session) ? $session->getTrackID() : null, 'NOACCESS'); - -try { - $idpentityid = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); - $idpMetadata = $metadata->getMetaDataConfig($idpentityid, 'saml20-idp-hosted'); -} catch (Exception $exception) { - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception); -} - -SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutServiceiFrame: Got IdP entity id: ' . $idpentityid); - - - -$logouttype = 'traditional'; -$idpmeta = $metadata->getMetaDataCurrent('saml20-idp-hosted'); -if (array_key_exists('logouttype', $idpmeta)) $logouttype = $idpmeta['logouttype']; - -if ($logouttype !== 'iframe') - SimpleSAML_Utilities::fatalError($session->getTrackID(), 'NOACCESS', new Exception('This IdP is configured to use logout type [' . $logouttype . '], but this endpoint is only available for IdP using logout type [iframe]')); - - - - - - - -/** - * This function retrieves the logout info with the given ID. - * - * @param $id The identifier of the logout info. - */ -function fetchLogoutInfo($id) { - global $session; - global $logoutInfo; - - $logoutInfo = $session->getData('idplogoutresponsedata', $id); - - if($logoutInfo === NULL) { - SimpleSAML_Logger::warning('SAML2.0 - IdP.SingleLogoutService: Lost logout information.'); - } -} - - -/** - * This function saves the logout info with the given ID. - * - * @param $id The identifier the logout info should be saved with. - */ -function saveLogoutInfo($id) { - global $session; - global $logoutInfo; - - $session->setData('idplogoutresponsedata', $id, $logoutInfo); -} - - -// Include XAJAX definition. -require_once(SimpleSAML_Utilities::resolvePath('libextinc') . '/xajax/xajax.inc.php'); - - - -/* - * This function is called via AJAX and will send LogoutRequest to one single SP by - * sending a LogoutRequest using HTTP-REDIRECT - */ -function updateslostatus() { - - SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutServiceiFrame: Accessing SAML 2.0 IdP endpoint SingleLogoutService (iFrame version) within updateslostatus() '); - - $config = SimpleSAML_Configuration::getInstance(); - $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); - $session = SimpleSAML_Session::getInstance(); - - $idpentityid = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); - - $templistofsps = $session->get_sp_list(SimpleSAML_Session::STATE_ONLINE); - $listofsps = array(); - foreach ($templistofsps AS $spentityid) { - if (!empty($_COOKIE['spstate-' . sha1($spentityid)])) { - $listofsps[] = $spentityid; - continue; - } - - try { - $spMetadata = $metadata->getMetaDataConfig($spentityid, 'saml20-sp-remote'); - } catch (Exception $e) { - /* - * For some reason, the metadata for this SP is no longer available. Most - * likely it was deleted from the IdP while the user had a session to it. - * In any case - skip this SP. - */ - $listofsps[] = $spentityid; - continue; - } - - $singleLogoutService = $spMetadata->getDefaultEndpoint('SingleLogoutService', array(SAML2_Const::BINDING_HTTP_REDIRECT), NULL); - if ($singleLogoutService === NULL) { - /* No logout endpoint. */ - $listofsps[] = $spentityid; - continue; - } - - /* This SP isn't ready yet. */ - } - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutServiceiFrame: templistofsps ' . join(',', $templistofsps)); - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutServiceiFrame: listofsps ' . join(',', $listofsps)); - - - // Using template object to be able to translate name of service provider. - $t = new SimpleSAML_XHTML_Template($config, 'logout-iframe.php'); - - // Instantiate the xajaxResponse object - $objResponse = new xajaxResponse(); - - foreach ($listofsps AS $spentityid) { - - SimpleSAML_Logger::debug('SAML2.0 - IdP.SingleLogoutServiceiFrame: Completed ' . $spentityid); - - // add a command to the response to assign the innerHTML attribute of - // the element with id="SomeElementId" to whatever the new content is - - $spmetadata = $metadata->getMetaData($spentityid, 'saml20-sp-remote'); - $name = array_key_exists('name', $spmetadata) ? $spmetadata['name'] : $spentityid; - - $spname = is_array($name) ? $t->getTranslation($name) : $name; - - $objResponse->addScriptCall('slocompletesp', 'e' . sha1($spentityid)); - - } - - if (count($templistofsps) === count($listofsps)) { - - $templistofsps = $session->get_sp_list(SimpleSAML_Session::STATE_ONLINE); - foreach ($templistofsps AS $spentityid) { - $session->set_sp_logout_completed($spentityid); - setcookie('spstate-' . sha1($spentityid) , '', time() - 3600); // Delete cookie - } - - $objResponse->addScriptCall('slocompleted'); - - /** - * Clean up session object to save storage. - */ - if ($config->getBoolean('debug', false)) - SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutService: Session Size before cleaning: ' . $session->getSize()); - - $session->clean(); - - if ($config->getBoolean('debug', false)) - SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutService: Session Size after cleaning: ' . $session->getSize()); - - } else { - SimpleSAML_Logger::debug('SAML2.0 - sp_logout_completed FALSE'); - } - - //return the xajaxResponse object - return $objResponse; -} - - - -$xajax = new xajax(); -$xajax->registerFunction("updateslostatus"); -$xajax->processRequests(); - - - - -/** - * Which URL to send the user to after logout? - */ -$relayState = NULL; -if (array_key_exists('RelayState', $_REQUEST)) $relayState = $_REQUEST['RelayState']; - -// Do logout from the IdP -$session->doLogout(); - -// Debug entries in the log about what services the user is logged into. -$session->dump_sp_sessions(); - - - -/* - * Generate a list of all service providers, and create a LogoutRequest message for all these SPs. - */ -$listofsps = $session->get_sp_list(); -$sparray = array(); -$sparrayNoLogout = array(); -foreach ($listofsps AS $spentityid) { - - // ($issuer, $receiver, $nameid, $nameidformat, $sessionindex, $mode) { - $nameId = $session->getSessionNameId('saml20-sp-remote', $spentityid); - if($nameId === NULL) { - $nameId = $session->getNameID(); - } - - $spMetadata = $metadata->getMetaDataConfig($spentityid, 'saml20-sp-remote'); - $name = $spMetadata->getValue('name', $spentityid); - - try { - $lr = sspmod_saml2_Message::buildLogoutRequest($idpMetadata, $spMetadata); - $lr->setSessionIndex($session->getSessionIndex()); - $lr->setNameId($nameId); - - $httpredirect = new SAML2_HTTPRedirect(); - $url = $httpredirect->getRedirectURL($lr); - - $sparray[$spentityid] = array('url' => $url, 'name' => $name); - - /* Add the SP logout request information to the session so that we can check it later. */ - $requestInfo = array( - 'ID' => $lr->getId(), - 'RelayState' => $lr->getRelayState(), - ); - $session->setData('slo-request-info', $spentityid, $requestInfo, 15*60); - - } catch (Exception $e) { - - $sparrayNoLogout[$spentityid] = array('name' => $name); - - } +$idpEntityId = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); +$idp = SimpleSAML_IdP::getById('saml2:' . $idpEntityId); +if (!isset($_REQUEST['RelayState'])) { + throw new SimpleSAML_Error_BadRequest('Missing required RelayState parameter.'); } - -SimpleSAML_Logger::debug('SAML2.0 - SP Counter. other SPs with SLO support (' . count($sparray) . ') without SLO support (' . count($sparrayNoLogout) . ')'); - - -#print_r($sparray); - - - - -/* - * If the user is not logged into any other SPs. - */ -if (count($sparray) + count($sparrayNoLogout) === 0) { - SimpleSAML_Utilities::redirect($relayState); - exit; -} - - -$et = new SimpleSAML_XHTML_Template($config, 'logout-iframe.php'); - -$et->data['header'] = 'Logout'; -$et->data['sparray'] = $sparray; -$et->data['sparrayNoLogout'] = $sparrayNoLogout; - -$et->data['logoutresponse'] = $relayState; -$et->data['xajax'] = $xajax; - -#$et->data['idpInitRelayState'] = $relayState; - -# $et->data['requesterName'] = $spname; - -$et->data['head'] = $xajax->getJavascript(); - -$et->show(); - -exit(0); - - - - -?> \ No newline at end of file +$idp->doLogoutRedirect((string)$_REQUEST['RelayState']); +assert('FALSE');