Example #1
0
 /**
  * Notify about an event.
  *
  * @param string $event  The event.
  * @param array $data  Event data. Optional.
  */
 public static function log($event, array $data = array())
 {
     assert('is_string($event)');
     assert('!isset($data["op"])');
     assert('!isset($data["time"])');
     assert('!isset($data["_id"])');
     if (!self::$initialized) {
         self::initOutputs();
         self::$initialized = TRUE;
     }
     if (empty(self::$outputs)) {
         /* Not enabled. */
         return;
     }
     $data['op'] = $event;
     $data['time'] = microtime(TRUE);
     /* The ID generation is designed to cluster IDs related in time close together. */
     $int_t = (int) $data['time'];
     $hd = openssl_random_pseudo_bytes(16);
     $data['_id'] = sprintf('%016x%s', $int_t, bin2hex($hd));
     foreach (self::$outputs as $out) {
         $out->emit($data);
     }
 }
<?php

if (!isset($_REQUEST['id'])) {
    throw new SimpleSAML_Error_BadRequest('Missing required parameter: id');
}
if (isset($_REQUEST['type'])) {
    $type = (string) $_REQUEST['type'];
    if (!in_array($type, array('init', 'js', 'nojs', 'embed'), TRUE)) {
        throw new SimpleSAML_Error_BadRequest('Invalid value for type.');
    }
} else {
    $type = 'init';
}
if ($type !== 'embed' && $type !== 'async') {
    SimpleSAML_Logger::stats('slo-iframe ' . $type);
    SimpleSAML_Stats::log('core:idp:logout-iframe:page', array('type' => $type));
}
$state = SimpleSAML_Auth_State::loadState($_REQUEST['id'], 'core:Logout-IFrame');
$idp = SimpleSAML_IdP::getByState($state);
if ($type !== 'init') {
    /* Update association state. */
    $associations = $idp->getAssociations();
    foreach ($state['core:Logout-IFrame:Associations'] as $assocId => &$sp) {
        $spId = sha1($assocId);
        /* Move SPs from 'onhold' to 'inprogress'. */
        if ($sp['core:Logout-IFrame:State'] === 'onhold') {
            $sp['core:Logout-IFrame:State'] = 'inprogress';
        }
        /* Check for update through request. */
        if (isset($_REQUEST[$spId])) {
            $s = $_REQUEST[$spId];
Example #3
0
 /**
  * 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_saml_Message::validateMessage($spMetadata, $idpMetadata, $message);
     if ($message instanceof SAML2_LogoutResponse) {
         SimpleSAML_Logger::info('Received SAML 2.0 LogoutResponse from: ' . var_export($spEntityId, TRUE));
         $statsData = array('spEntityID' => $spEntityId, 'idpEntityID' => $idpMetadata->getString('entityid'));
         if (!$message->isSuccess()) {
             $statsData['error'] = $message->getStatus();
         }
         SimpleSAML_Stats::log('saml:idp:LogoutResponse:recv', $statsData);
         $relayState = $message->getRelayState();
         if (!$message->isSuccess()) {
             $logoutError = sspmod_saml_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) {
         SimpleSAML_Logger::info('Received SAML 2.0 LogoutRequest from: ' . var_export($spEntityId, TRUE));
         SimpleSAML_Stats::log('saml:idp:LogoutRequest:recv', array('spEntityID' => $spEntityId, 'idpEntityID' => $idpMetadata->getString('entityid')));
         $spStatsId = $spMetadata->getString('core:statistics-id', $spEntityId);
         SimpleSAML_Logger::stats('saml20-idp-SLO spinit ' . $spStatsId . ' ' . $idpMetadata->getString('entityid'));
         $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)');
     SimpleSAML_Logger::info('Sending SAML 2.0 LogoutRequest to: ' . var_export($association['saml:entityID'], TRUE));
     $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
     $idpMetadata = $idp->getConfig();
     $spMetadata = $metadata->getMetaDataConfig($association['saml:entityID'], 'saml20-sp-remote');
     $lr = sspmod_saml_Message::buildLogoutRequest($idpMetadata, $spMetadata);
     $lr->setRelayState($relayState);
     $lr->setSessionIndex($association['saml:SessionIndex']);
     $lr->setNameId($association['saml:NameID']);
     $assertionLifetime = $spMetadata->getInteger('assertion.lifetime', NULL);
     if ($assertionLifetime === NULL) {
         $assertionLifetime = $idpMetadata->getInteger('assertion.lifetime', 300);
     }
     $lr->setNotOnOrAfter(time() + $assertionLifetime);
     $encryptNameId = $spMetadata->getBoolean('nameid.encryption', NULL);
     if ($encryptNameId === NULL) {
         $encryptNameId = $idpMetadata->getBoolean('nameid.encryption', FALSE);
     }
     if ($encryptNameId) {
         $lr->encryptNameId(sspmod_saml_Message::getEncryptionKey($spMetadata));
     }
     SimpleSAML_Stats::log('saml:idp:LogoutRequest:sent', array('spEntityID' => $association['saml:entityID'], 'idpEntityID' => $idpMetadata->getString('entityid')));
     $binding = new SAML2_HTTPRedirect();
     return $binding->getRedirectURL($lr);
 }
Example #5
0
 /**
  * Process a authentication response
  *
  * This function saves the state, and redirects the user to the page where
  * the user can authorize the release of the attributes.
  * If storage is used and the consent has already been given the user is 
  * passed on.
  *
  * @param array &$state The state of the response.
  *
  * @return void
  */
 public function process(&$state)
 {
     assert('is_array($state)');
     assert('array_key_exists("UserID", $state)');
     assert('array_key_exists("Destination", $state)');
     assert('array_key_exists("entityid", $state["Destination"])');
     assert('array_key_exists("metadata-set", $state["Destination"])');
     assert('array_key_exists("entityid", $state["Source"])');
     assert('array_key_exists("metadata-set", $state["Source"])');
     $spEntityId = $state['Destination']['entityid'];
     $idpEntityId = $state['Source']['entityid'];
     $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
     /**
      * If the consent module is active on a bridge $state['saml:sp:IdP']
      * will contain an entry id for the remote IdP. If not, then the
      * consent module is active on a local IdP and nothing needs to be
      * done.
      */
     if (isset($state['saml:sp:IdP'])) {
         $idpEntityId = $state['saml:sp:IdP'];
         $idpmeta = $metadata->getMetaData($idpEntityId, 'saml20-idp-remote');
         $state['Source'] = $idpmeta;
     }
     $statsData = array('spEntityID' => $spEntityId);
     // Do not use consent if disabled
     if (isset($state['Source']['consent.disable']) && self::checkDisable($state['Source']['consent.disable'], $spEntityId)) {
         SimpleSAML_Logger::debug('Consent: Consent disabled for entity ' . $spEntityId . ' with IdP ' . $idpEntityId);
         SimpleSAML_Stats::log('consent:disabled', $statsData);
         return;
     }
     if (isset($state['Destination']['consent.disable']) && self::checkDisable($state['Destination']['consent.disable'], $idpEntityId)) {
         SimpleSAML_Logger::debug('Consent: Consent disabled for entity ' . $spEntityId . ' with IdP ' . $idpEntityId);
         SimpleSAML_Stats::log('consent:disabled', $statsData);
         return;
     }
     if ($this->_store !== null) {
         $source = $state['Source']['metadata-set'] . '|' . $idpEntityId;
         $destination = $state['Destination']['metadata-set'] . '|' . $spEntityId;
         $attributes = $state['Attributes'];
         // Remove attributes that do not require consent
         foreach ($attributes as $attrkey => $attrval) {
             if (in_array($attrkey, $this->_noconsentattributes)) {
                 unset($attributes[$attrkey]);
             }
         }
         SimpleSAML_Logger::debug('Consent: userid: ' . $state['UserID']);
         SimpleSAML_Logger::debug('Consent: source: ' . $source);
         SimpleSAML_Logger::debug('Consent: destination: ' . $destination);
         $userId = self::getHashedUserID($state['UserID'], $source);
         $targetedId = self::getTargetedID($state['UserID'], $source, $destination);
         $attributeSet = self::getAttributeHash($attributes, $this->_includeValues);
         SimpleSAML_Logger::debug('Consent: hasConsent() [' . $userId . '|' . $targetedId . '|' . $attributeSet . ']');
         try {
             if ($this->_store->hasConsent($userId, $targetedId, $attributeSet)) {
                 // Consent already given
                 SimpleSAML_Logger::stats('Consent: Consent found');
                 SimpleSAML_Stats::log('consent:found', $statsData);
                 return;
             }
             SimpleSAML_Logger::stats('Consent: Consent notfound');
             SimpleSAML_Stats::log('consent:notfound', $statsData);
             $state['consent:store'] = $this->_store;
             $state['consent:store.userId'] = $userId;
             $state['consent:store.destination'] = $targetedId;
             $state['consent:store.attributeSet'] = $attributeSet;
         } catch (Exception $e) {
             SimpleSAML_Logger::error('Consent: Error reading from storage: ' . $e->getMessage());
             SimpleSAML_Logger::stats('Consent: Failed');
             SimpleSAML_Stats::log('consent:failed', $statsData);
         }
     } else {
         SimpleSAML_Logger::stats('Consent: No storage');
         SimpleSAML_Stats::log('consent:nostorage', $statsData);
     }
     $state['consent:focus'] = $this->_focus;
     $state['consent:checked'] = $this->_checked;
     $state['consent:hiddenAttributes'] = $this->_hiddenAttributes;
     $state['consent:noconsentattributes'] = $this->_noconsentattributes;
     $state['consent:showNoConsentAboutService'] = $this->_showNoConsentAboutService;
     // User interaction nessesary. Throw exception on isPassive request
     if (isset($state['isPassive']) && $state['isPassive'] == true) {
         SimpleSAML_Stats::log('consent:nopassive', $statsData);
         throw new SimpleSAML_Error_NoPassive('Unable to give consent on passive request.');
     }
     // Save state and redirect
     $id = SimpleSAML_Auth_State::saveState($state, 'consent:request');
     $url = SimpleSAML_Module::getModuleURL('consent/getconsent.php');
     SimpleSAML_Utilities::redirectTrustedURL($url, array('StateId' => $id));
 }
    } else {
        $spentityid = 'UNKNOWN';
    }
}
// The user has pressed the yes-button
if (array_key_exists('yes', $_REQUEST)) {
    if (array_key_exists('saveconsent', $_REQUEST)) {
        SimpleSAML_Logger::stats('consentResponse remember');
    } else {
        SimpleSAML_Logger::stats('consentResponse rememberNot');
    }
    $statsInfo = array('remember' => array_key_exists('saveconsent', $_REQUEST));
    if (isset($state['Destination']['entityid'])) {
        $statsInfo['spEntityID'] = $state['Destination']['entityid'];
    }
    SimpleSAML_Stats::log('consent:accept', $statsInfo);
    if (array_key_exists('consent:store', $state) && array_key_exists('saveconsent', $_REQUEST) && $_REQUEST['saveconsent'] === '1') {
        /* Save consent. */
        $store = $state['consent:store'];
        $userId = $state['consent:store.userId'];
        $targetedId = $state['consent:store.destination'];
        $attributeSet = $state['consent:store.attributeSet'];
        SimpleSAML_Logger::debug('Consent - saveConsent() : [' . $userId . '|' . $targetedId . '|' . $attributeSet . ']');
        try {
            $store->saveConsent($userId, $targetedId, $attributeSet);
        } catch (Exception $e) {
            SimpleSAML_Logger::error('Consent: Error writing to storage: ' . $e->getMessage());
        }
    }
    SimpleSAML_Auth_ProcessingChain::resumeProcessing($state);
}
/* Find the status of all SPs. */
foreach ($SPs as $assocId => &$sp) {
    $spId = 'logout-iframe-' . sha1($assocId);
    if (isset($_REQUEST[$spId])) {
        $spStatus = $_REQUEST[$spId];
        if ($spStatus === 'completed' || $spStatus === 'failed') {
            $sp['core:Logout-IFrame:State'] = $spStatus;
        }
    }
    if (!isset($associations[$assocId])) {
        $sp['core:Logout-IFrame:State'] = 'completed';
    }
}
/* Terminate the associations. */
foreach ($SPs as $assocId => $sp) {
    if ($sp['core:Logout-IFrame:State'] === 'completed') {
        $idp->terminateAssociation($assocId);
    } else {
        SimpleSAML_Logger::warning('Unable to terminate association with ' . var_export($assocId, TRUE) . '.');
        if (isset($sp['saml:entityID'])) {
            $spId = $sp['saml:entityID'];
        } else {
            $spId = $assocId;
        }
        SimpleSAML_Logger::stats('slo-iframe-fail ' . $spId);
        SimpleSAML_Stats::log('core:idp:logout-iframe:spfail', array('sp' => $spId));
        $state['core:Failed'] = TRUE;
    }
}
/* We are done. */
$idp->finishLogout($state);
Example #8
0
 */
if (!array_key_exists('StateId', $_REQUEST)) {
    throw new SimpleSAML_Error_BadRequest('Missing required StateId query parameter.');
}
$id = $_REQUEST['StateId'];
// sanitize the input
$sid = SimpleSAML_Utilities::parseStateID($id);
if (!is_null($sid['url'])) {
    SimpleSAML_Utilities::checkURLAllowed($sid['url']);
}
$state = SimpleSAML_Auth_State::loadState($id, 'consent:request');
$resumeFrom = SimpleSAML_Module::getModuleURL('consent/getconsent.php', array('StateId' => $id));
$logoutLink = SimpleSAML_Module::getModuleURL('consent/logout.php', array('StateId' => $id));
$aboutService = null;
if (!isset($state['consent:showNoConsentAboutService']) || $state['consent:showNoConsentAboutService']) {
    if (isset($state['Destination']['url.about'])) {
        $aboutService = $state['Destination']['url.about'];
    }
}
$statsInfo = array();
if (isset($state['Destination']['entityid'])) {
    $statsInfo['spEntityID'] = $state['Destination']['entityid'];
}
SimpleSAML_Stats::log('consent:reject', $statsInfo);
$globalConfig = SimpleSAML_Configuration::getInstance();
$t = new SimpleSAML_XHTML_Template($globalConfig, 'consent:noconsent.php');
$t->data['dstMetadata'] = $state['Destination'];
$t->data['resumeFrom'] = $resumeFrom;
$t->data['aboutService'] = $aboutService;
$t->data['logoutLink'] = $logoutLink;
$t->show();
Example #9
0
 /**
  * Receive an authentication request.
  *
  * @param SimpleSAML_IdP $idp  The IdP we are receiving it for.
  */
 public static function receiveAuthnRequest(SimpleSAML_IdP $idp)
 {
     if (isset($_REQUEST['cookieTime'])) {
         $cookieTime = (int) $_REQUEST['cookieTime'];
         if ($cookieTime + 5 > time()) {
             /*
              * Less than five seconds has passed since we were
              * here the last time. Cookies are probably disabled.
              */
             \SimpleSAML\Utils\HTTP::checkSessionCookie(\SimpleSAML\Utils\HTTP::getSelfURL());
         }
     }
     if (!isset($_REQUEST['providerId'])) {
         throw new SimpleSAML_Error_BadRequest('Missing providerId parameter.');
     }
     $spEntityId = (string) $_REQUEST['providerId'];
     if (!isset($_REQUEST['shire'])) {
         throw new SimpleSAML_Error_BadRequest('Missing shire parameter.');
     }
     $shire = (string) $_REQUEST['shire'];
     if (isset($_REQUEST['target'])) {
         $target = $_REQUEST['target'];
     } else {
         $target = NULL;
     }
     SimpleSAML\Logger::info('Shib1.3 - IdP.SSOService: Got incoming Shib authnRequest from ' . var_export($spEntityId, TRUE) . '.');
     $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
     $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'shib13-sp-remote');
     $found = FALSE;
     foreach ($spMetadata->getEndpoints('AssertionConsumerService') as $ep) {
         if ($ep['Binding'] !== 'urn:oasis:names:tc:SAML:1.0:profiles:browser-post') {
             continue;
         }
         if ($ep['Location'] !== $shire) {
             continue;
         }
         $found = TRUE;
         break;
     }
     if (!$found) {
         throw new Exception('Invalid AssertionConsumerService for SP ' . var_export($spEntityId, TRUE) . ': ' . var_export($shire, TRUE));
     }
     SimpleSAML_Stats::log('saml:idp:AuthnRequest', array('spEntityID' => $spEntityId, 'protocol' => 'saml1'));
     $sessionLostURL = \SimpleSAML\Utils\HTTP::addURLParameters(\SimpleSAML\Utils\HTTP::getSelfURL(), array('cookieTime' => time()));
     $state = array('Responder' => array('sspmod_saml_IdP_SAML1', 'sendResponse'), 'SPMetadata' => $spMetadata->toArray(), SimpleSAML_Auth_State::RESTART => $sessionLostURL, 'saml:shire' => $shire, 'saml:target' => $target, 'saml:AuthnRequestReceivedAt' => microtime(TRUE));
     $idp->handleAuthenticationRequest($state);
 }
}
$associations = $idp->getAssociations();
if (!isset($associations[$assocId])) {
    throw new SimpleSAML_Error_BadRequest('Invalid association id.');
}
$association = $associations[$assocId];
$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
$idpMetadata = $idp->getConfig();
$spMetadata = $metadata->getMetaDataConfig($association['saml:entityID'], 'saml20-sp-remote');
$lr = sspmod_saml_Message::buildLogoutRequest($idpMetadata, $spMetadata);
$lr->setSessionIndex($association['saml:SessionIndex']);
$lr->setNameId($association['saml:NameID']);
$assertionLifetime = $spMetadata->getInteger('assertion.lifetime', NULL);
if ($assertionLifetime === NULL) {
    $assertionLifetime = $idpMetadata->getInteger('assertion.lifetime', 300);
}
$lr->setNotOnOrAfter(time() + $assertionLifetime);
$encryptNameId = $spMetadata->getBoolean('nameid.encryption', NULL);
if ($encryptNameId === NULL) {
    $encryptNameId = $idpMetadata->getBoolean('nameid.encryption', FALSE);
}
if ($encryptNameId) {
    $lr->encryptNameId(sspmod_saml_Message::getEncryptionKey($spMetadata));
}
SimpleSAML_Stats::log('saml:idp:LogoutRequest:sent', array('spEntityID' => $association['saml:entityID'], 'idpEntityID' => $idpMetadata->getString('entityid')));
$bindings = array(\SAML2\Constants::BINDING_HTTP_POST);
$dst = $spMetadata->getDefaultEndpoint('SingleLogoutService', $bindings);
$binding = \SAML2\Binding::getBinding($dst['Binding']);
$lr->setDestination($dst['Location']);
$lr->setRelayState($relayState);
$binding->send($lr);