diff --git a/lib/SimpleSAML/Auth/Default.php b/lib/SimpleSAML/Auth/Default.php index 3e7814b4d0987df343e7f608074e545959a4161f..ed2f75f077f82ef96f639719ec10516fd27551fc 100644 --- a/lib/SimpleSAML/Auth/Default.php +++ b/lib/SimpleSAML/Auth/Default.php @@ -11,116 +11,129 @@ * * @deprecated This class will be removed in SSP 2.0. */ -class SimpleSAML_Auth_Default { +class SimpleSAML_Auth_Default +{ - /** - * @deprecated This method will be removed in SSP 2.0. Use SimpleSAML_Auth_Source::initLogin() instead. - */ - public static function initLogin($authId, $return, $errorURL = NULL, - array $params = array()) { + /** + * @deprecated This method will be removed in SSP 2.0. Use SimpleSAML_Auth_Source::initLogin() instead. + */ + public static function initLogin( + $authId, + $return, + $errorURL = null, + array $params = array() + ) { - $as = self::getAuthSource($authId); - $as->initLogin($return, $errorURL, $params); - } - - - /** - * @deprecated This method will be removed in SSP 2.0. Please use - * SimpleSAML_Auth_State::getPersistentAuthData() instead. - */ - public static function extractPersistentAuthState(array &$state) { - - return SimpleSAML_Auth_State::getPersistentAuthData($state); - } - - - /** - * @deprecated This method will be removed in SSP 2.0. Please use SimpleSAML_Auth_Source::loginCompleted() instead. - */ - public static function loginCompleted($state) { - SimpleSAML_Auth_Source::loginCompleted($state); - } - - - /** - * @deprecated This method will be removed in SSP 2.0. - */ - public static function initLogoutReturn($returnURL, $authority) { - assert('is_string($returnURL)'); - assert('is_string($authority)'); - - $session = SimpleSAML_Session::getSessionFromRequest(); - - $state = $session->getAuthData($authority, 'LogoutState'); - $session->doLogout($authority); - - $state['SimpleSAML_Auth_Default.ReturnURL'] = $returnURL; - $state['LogoutCompletedHandler'] = array(get_class(), 'logoutCompleted'); - - $as = SimpleSAML_Auth_Source::getById($authority); - if ($as === NULL) { - // The authority wasn't an authentication source... - self::logoutCompleted($state); - } - - $as->logout($state); - } - - - /** - * @deprecated This method will be removed in SSP 2.0. - */ - public static function initLogout($returnURL, $authority) { - assert('is_string($returnURL)'); - assert('is_string($authority)'); - - self::initLogoutReturn($returnURL, $authority); - - \SimpleSAML\Utils\HTTP::redirectTrustedURL($returnURL); - } - - - /** - * @deprecated This method will be removed in SSP 2.0. - */ - public static function logoutCompleted($state) { - assert('is_array($state)'); - assert('array_key_exists("SimpleSAML_Auth_Default.ReturnURL", $state)'); - - \SimpleSAML\Utils\HTTP::redirectTrustedURL($state['SimpleSAML_Auth_Default.ReturnURL']); - } - - - /** - * @deprecated This method will be removed in SSP 2.0. Please use SimpleSAML_Auth_Source::logoutCallback() instead. - */ - public static function logoutCallback($state) { - SimpleSAML_Auth_Source::logoutCallback($state); - } - - - /** - * @deprecated This method will be removed in SSP 2.0. Please use - * sspmod_saml_Auth_Source_SP::handleUnsolicitedAuth() instead. - */ - public static function handleUnsolicitedAuth($authId, array $state, $redirectTo) { - sspmod_saml_Auth_Source_SP::handleUnsolicitedAuth($authId, $state, $redirectTo); - } - - - /** - * Return an authentication source by ID. - * - * @param string $id The id of the authentication source. - * @return SimpleSAML_Auth_Source The authentication source. - * @throws Exception If the $id does not correspond with an authentication source. - */ - private static function getAuthSource($id) { - $as = SimpleSAML_Auth_Source::getById($id); - if ($as === null) { - throw new Exception('Invalid authentication source: ' . $id); - } - return $as; - } + $as = self::getAuthSource($authId); + $as->initLogin($return, $errorURL, $params); + } + + + /** + * @deprecated This method will be removed in SSP 2.0. Please use + * SimpleSAML_Auth_State::getPersistentAuthData() instead. + */ + public static function extractPersistentAuthState(array &$state) + { + + return SimpleSAML_Auth_State::getPersistentAuthData($state); + } + + + /** + * @deprecated This method will be removed in SSP 2.0. Please use SimpleSAML_Auth_Source::loginCompleted() instead. + */ + public static function loginCompleted($state) + { + SimpleSAML_Auth_Source::loginCompleted($state); + } + + + /** + * @deprecated This method will be removed in SSP 2.0. + */ + public static function initLogoutReturn($returnURL, $authority) + { + assert('is_string($returnURL)'); + assert('is_string($authority)'); + + $session = SimpleSAML_Session::getSessionFromRequest(); + + $state = $session->getAuthData($authority, 'LogoutState'); + $session->doLogout($authority); + + $state['SimpleSAML_Auth_Default.ReturnURL'] = $returnURL; + $state['LogoutCompletedHandler'] = array(get_class(), 'logoutCompleted'); + + $as = SimpleSAML_Auth_Source::getById($authority); + if ($as === null) { + // The authority wasn't an authentication source... + self::logoutCompleted($state); + } + + $as->logout($state); + } + + + /** + * @deprecated This method will be removed in SSP 2.0. + */ + public static function initLogout($returnURL, $authority) + { + assert('is_string($returnURL)'); + assert('is_string($authority)'); + + self::initLogoutReturn($returnURL, $authority); + + \SimpleSAML\Utils\HTTP::redirectTrustedURL($returnURL); + } + + + /** + * @deprecated This method will be removed in SSP 2.0. + */ + public static function logoutCompleted($state) + { + assert('is_array($state)'); + assert('array_key_exists("SimpleSAML_Auth_Default.ReturnURL", $state)'); + + \SimpleSAML\Utils\HTTP::redirectTrustedURL($state['SimpleSAML_Auth_Default.ReturnURL']); + } + + + /** + * @deprecated This method will be removed in SSP 2.0. Please use SimpleSAML_Auth_Source::logoutCallback() instead. + */ + public static function logoutCallback($state) + { + SimpleSAML_Auth_Source::logoutCallback($state); + } + + + /** + * @deprecated This method will be removed in SSP 2.0. Please use + * sspmod_saml_Auth_Source_SP::handleUnsolicitedAuth() instead. + */ + public static function handleUnsolicitedAuth($authId, array $state, $redirectTo) + { + sspmod_saml_Auth_Source_SP::handleUnsolicitedAuth($authId, $state, $redirectTo); + } + + + /** + * Return an authentication source by ID. + * + * @param string $id The id of the authentication source. + * @return SimpleSAML_Auth_Source The authentication source. + * @throws Exception If the $id does not correspond with an authentication source. + */ + private static function getAuthSource($id) + { + $as = SimpleSAML_Auth_Source::getById($id); + if ($as === null) { + throw new Exception('Invalid authentication source: ' . $id); + } + return $as; + } } diff --git a/lib/SimpleSAML/Auth/LDAP.php b/lib/SimpleSAML/Auth/LDAP.php index 0aa5304c0b02fc80bce496109cf005443e940d40..08ca44ad55574ab96e65bad05bbcc8ec2c37eaa3 100644 --- a/lib/SimpleSAML/Auth/LDAP.php +++ b/lib/SimpleSAML/Auth/LDAP.php @@ -437,12 +437,16 @@ class SimpleSAML_Auth_LDAP // SASL Bind, with error handling $authz_id = $sasl_args['authz_id']; - $error = @ldap_sasl_bind($this->ldap, $dn, $password, + $error = @ldap_sasl_bind( + $this->ldap, + $dn, + $password, $sasl_args['mech'], $sasl_args['realm'], $sasl_args['authc_id'], $sasl_args['authz_id'], - $sasl_args['props']); + $sasl_args['props'] + ); } else { // Simple Bind, with error handling $authz_id = $dn; @@ -553,7 +557,6 @@ class SimpleSAML_Auth_LDAP // Parsing each found attribute into our result set $result = array(); // Recycling $result... Possibly bad practice. for ($i = 0; $i < $attributes['count']; $i++) { - // Ignore attributes that exceed the maximum allowed size $name = $attributes[$i]; $attribute = $attributes[$name]; @@ -576,12 +579,10 @@ class SimpleSAML_Auth_LDAP } else { $values[] = $value; } - } // Adding $result[$name] = $values; - } // We're done @@ -631,7 +632,6 @@ class SimpleSAML_Auth_LDAP */ $attributes = $this->getAttributes($dn, $config['attributes']); return $attributes; - } @@ -658,9 +658,9 @@ class SimpleSAML_Auth_LDAP foreach ($values as $key => $val) { // Escaping of filter meta characters $val = str_replace('\\', '\5c', $val); - $val = str_replace('*', '\2a', $val); - $val = str_replace('(', '\28', $val); - $val = str_replace(')', '\29', $val); + $val = str_replace('*', '\2a', $val); + $val = str_replace('(', '\28', $val); + $val = str_replace(')', '\29', $val); // ASCII < 32 escaping $val = self::asc2hex32($val); @@ -713,8 +713,11 @@ class SimpleSAML_Auth_LDAP } if (preg_match("/^u:/", $authz_id)) { - return $this->searchfordn($searchBase, $searchAttributes, - preg_replace("/^u:/", "", $authz_id)); + return $this->searchfordn( + $searchBase, + $searchAttributes, + preg_replace("/^u:/", "", $authz_id) + ); } return $authz_id; } @@ -726,9 +729,9 @@ class SimpleSAML_Auth_LDAP * ldap_exop_whoami() has been provided as a third party patch that * waited several years to get its way upstream: * http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/databases/php-ldap/files - * + * * When it was integrated into PHP repository, the function prototype - * was changed, The new prototype was used in third party patch for + * was changed, The new prototype was used in third party patch for * PHP 7.0 and 7.1, hence the version test below. */ public function whoami($searchBase, $searchAttributes) diff --git a/lib/SimpleSAML/Auth/ProcessingChain.php b/lib/SimpleSAML/Auth/ProcessingChain.php index 361d81f9d97b4b1327f7046e43091ddbde2a94e9..e4b6095a169ed7f7e0fb0f145fe6514eb7d858fc 100644 --- a/lib/SimpleSAML/Auth/ProcessingChain.php +++ b/lib/SimpleSAML/Auth/ProcessingChain.php @@ -10,351 +10,357 @@ * @author Olav Morken, UNINETT AS. * @package SimpleSAMLphp */ -class SimpleSAML_Auth_ProcessingChain { - - - /** - * The list of remaining filters which should be applied to the state. - */ - const FILTERS_INDEX = 'SimpleSAML_Auth_ProcessingChain.filters'; - - - /** - * The stage we use for completed requests. - */ - const COMPLETED_STAGE = 'SimpleSAML_Auth_ProcessingChain.completed'; - - - /** - * The request parameter we will use to pass the state identifier when we redirect after - * having completed processing of the state. - */ - const AUTHPARAM = 'AuthProcId'; - - - /** - * All authentication processing filters, in the order they should be applied. - */ - private $filters; - - - /** - * Initialize an authentication processing chain for the given service provider - * and identity provider. - * - * @param array $idpMetadata The metadata for the IdP. - * @param array $spMetadata The metadata for the SP. - */ - public function __construct($idpMetadata, $spMetadata, $mode = 'idp') { - assert('is_array($idpMetadata)'); - assert('is_array($spMetadata)'); - - $this->filters = array(); - - $config = SimpleSAML_Configuration::getInstance(); - $configauthproc = $config->getArray('authproc.' . $mode, NULL); - - if (!empty($configauthproc)) { - $configfilters = self::parseFilterList($configauthproc); - self::addFilters($this->filters, $configfilters); - } - - if (array_key_exists('authproc', $idpMetadata)) { - $idpFilters = self::parseFilterList($idpMetadata['authproc']); - self::addFilters($this->filters, $idpFilters); - } - - if (array_key_exists('authproc', $spMetadata)) { - $spFilters = self::parseFilterList($spMetadata['authproc']); - self::addFilters($this->filters, $spFilters); - } - - - SimpleSAML\Logger::debug('Filter config for ' . $idpMetadata['entityid'] . '->' . - $spMetadata['entityid'] . ': ' . str_replace("\n", '', var_export($this->filters, TRUE))); - - } - - - /** - * Sort & merge filter configuration - * - * Inserts unsorted filters into sorted filter list. This sort operation is stable. - * - * @param array &$target Target filter list. This list must be sorted. - * @param array $src Source filters. May be unsorted. - */ - private static function addFilters(&$target, $src) { - assert('is_array($target)'); - assert('is_array($src)'); - - foreach ($src as $filter) { - $fp = $filter->priority; - - // Find insertion position for filter - for($i = count($target)-1; $i >= 0; $i--) { - if ($target[$i]->priority <= $fp) { - // The new filter should be inserted after this one - break; - } - } - /* $i now points to the filter which should preceede the current filter. */ - array_splice($target, $i+1, 0, array($filter)); - } - - } - - - /** - * Parse an array of authentication processing filters. - * - * @param array $filterSrc Array with filter configuration. - * @return array Array of SimpleSAML_Auth_ProcessingFilter objects. - */ - private static function parseFilterList($filterSrc) { - assert('is_array($filterSrc)'); - - $parsedFilters = array(); - - foreach ($filterSrc as $priority => $filter) { - - if (is_string($filter)) { - $filter = array('class' => $filter); - } - - if (!is_array($filter)) { - throw new Exception('Invalid authentication processing filter configuration: ' . - 'One of the filters wasn\'t a string or an array.'); - } - - $parsedFilters[] = self::parseFilter($filter, $priority); - } - - return $parsedFilters; - } - - - /** - * Parse an authentication processing filter. - * - * @param array $config Array with the authentication processing filter configuration. - * @param int $priority The priority of the current filter, (not included in the filter - * definition.) - * @return SimpleSAML_Auth_ProcessingFilter The parsed filter. - */ - private static function parseFilter($config, $priority) { - assert('is_array($config)'); - - if (!array_key_exists('class', $config)) - throw new Exception('Authentication processing filter without name given.'); - - $className = SimpleSAML\Module::resolveClass($config['class'], 'Auth_Process', 'SimpleSAML_Auth_ProcessingFilter'); - $config['%priority'] = $priority; - unset($config['class']); - return new $className($config, NULL); - } - - - /** - * Process the given state. - * - * This function will only return if processing completes. If processing requires showing - * a page to the user, we will not be able to return from this function. There are two ways - * this can be handled: - * - Redirect to a URL: We will redirect to the URL set in $state['ReturnURL']. - * - Call a function: We will call the function set in $state['ReturnCall']. - * - * If an exception is thrown during processing, it should be handled by the caller of - * this function. If the user has redirected to a different page, the exception will be - * returned through the exception handler defined on the state array. See - * SimpleSAML_Auth_State for more information. - * - * @see SimpleSAML_Auth_State - * @see SimpleSAML_Auth_State::EXCEPTION_HANDLER_URL - * @see SimpleSAML_Auth_State::EXCEPTION_HANDLER_FUNC - * - * @param array &$state The state we are processing. - */ - public function processState(&$state) { - assert('is_array($state)'); - assert('array_key_exists("ReturnURL", $state) || array_key_exists("ReturnCall", $state)'); - assert('!array_key_exists("ReturnURL", $state) || !array_key_exists("ReturnCall", $state)'); - - $state[self::FILTERS_INDEX] = $this->filters; - - try { - - // TODO: remove this in SSP 2.0 - if (!array_key_exists('UserID', $state)) { - // No unique user ID present. Attempt to add one. - self::addUserID($state); - } - - while (count($state[self::FILTERS_INDEX]) > 0) { - $filter = array_shift($state[self::FILTERS_INDEX]); - $filter->process($state); - } - - } catch (SimpleSAML_Error_Exception $e) { - // No need to convert the exception - throw $e; - } catch (Exception $e) { - /* +class SimpleSAML_Auth_ProcessingChain +{ + + + /** + * The list of remaining filters which should be applied to the state. + */ + const FILTERS_INDEX = 'SimpleSAML_Auth_ProcessingChain.filters'; + + + /** + * The stage we use for completed requests. + */ + const COMPLETED_STAGE = 'SimpleSAML_Auth_ProcessingChain.completed'; + + + /** + * The request parameter we will use to pass the state identifier when we redirect after + * having completed processing of the state. + */ + const AUTHPARAM = 'AuthProcId'; + + + /** + * All authentication processing filters, in the order they should be applied. + */ + private $filters; + + + /** + * Initialize an authentication processing chain for the given service provider + * and identity provider. + * + * @param array $idpMetadata The metadata for the IdP. + * @param array $spMetadata The metadata for the SP. + */ + public function __construct($idpMetadata, $spMetadata, $mode = 'idp') + { + assert('is_array($idpMetadata)'); + assert('is_array($spMetadata)'); + + $this->filters = array(); + + $config = SimpleSAML_Configuration::getInstance(); + $configauthproc = $config->getArray('authproc.' . $mode, null); + + if (!empty($configauthproc)) { + $configfilters = self::parseFilterList($configauthproc); + self::addFilters($this->filters, $configfilters); + } + + if (array_key_exists('authproc', $idpMetadata)) { + $idpFilters = self::parseFilterList($idpMetadata['authproc']); + self::addFilters($this->filters, $idpFilters); + } + + if (array_key_exists('authproc', $spMetadata)) { + $spFilters = self::parseFilterList($spMetadata['authproc']); + self::addFilters($this->filters, $spFilters); + } + + + SimpleSAML\Logger::debug('Filter config for ' . $idpMetadata['entityid'] . '->' . + $spMetadata['entityid'] . ': ' . str_replace("\n", '', var_export($this->filters, true))); + } + + + /** + * Sort & merge filter configuration + * + * Inserts unsorted filters into sorted filter list. This sort operation is stable. + * + * @param array &$target Target filter list. This list must be sorted. + * @param array $src Source filters. May be unsorted. + */ + private static function addFilters(&$target, $src) + { + assert('is_array($target)'); + assert('is_array($src)'); + + foreach ($src as $filter) { + $fp = $filter->priority; + + // Find insertion position for filter + for ($i = count($target)-1; $i >= 0; $i--) { + if ($target[$i]->priority <= $fp) { + // The new filter should be inserted after this one + break; + } + } + /* $i now points to the filter which should preceede the current filter. */ + array_splice($target, $i+1, 0, array($filter)); + } + } + + + /** + * Parse an array of authentication processing filters. + * + * @param array $filterSrc Array with filter configuration. + * @return array Array of SimpleSAML_Auth_ProcessingFilter objects. + */ + private static function parseFilterList($filterSrc) + { + assert('is_array($filterSrc)'); + + $parsedFilters = array(); + + foreach ($filterSrc as $priority => $filter) { + if (is_string($filter)) { + $filter = array('class' => $filter); + } + + if (!is_array($filter)) { + throw new Exception('Invalid authentication processing filter configuration: ' . + 'One of the filters wasn\'t a string or an array.'); + } + + $parsedFilters[] = self::parseFilter($filter, $priority); + } + + return $parsedFilters; + } + + + /** + * Parse an authentication processing filter. + * + * @param array $config Array with the authentication processing filter configuration. + * @param int $priority The priority of the current filter, (not included in the filter + * definition.) + * @return SimpleSAML_Auth_ProcessingFilter The parsed filter. + */ + private static function parseFilter($config, $priority) + { + assert('is_array($config)'); + + if (!array_key_exists('class', $config)) { + throw new Exception('Authentication processing filter without name given.'); + } + + $className = SimpleSAML\Module::resolveClass($config['class'], 'Auth_Process', 'SimpleSAML_Auth_ProcessingFilter'); + $config['%priority'] = $priority; + unset($config['class']); + return new $className($config, null); + } + + + /** + * Process the given state. + * + * This function will only return if processing completes. If processing requires showing + * a page to the user, we will not be able to return from this function. There are two ways + * this can be handled: + * - Redirect to a URL: We will redirect to the URL set in $state['ReturnURL']. + * - Call a function: We will call the function set in $state['ReturnCall']. + * + * If an exception is thrown during processing, it should be handled by the caller of + * this function. If the user has redirected to a different page, the exception will be + * returned through the exception handler defined on the state array. See + * SimpleSAML_Auth_State for more information. + * + * @see SimpleSAML_Auth_State + * @see SimpleSAML_Auth_State::EXCEPTION_HANDLER_URL + * @see SimpleSAML_Auth_State::EXCEPTION_HANDLER_FUNC + * + * @param array &$state The state we are processing. + */ + public function processState(&$state) + { + assert('is_array($state)'); + assert('array_key_exists("ReturnURL", $state) || array_key_exists("ReturnCall", $state)'); + assert('!array_key_exists("ReturnURL", $state) || !array_key_exists("ReturnCall", $state)'); + + $state[self::FILTERS_INDEX] = $this->filters; + + try { + // TODO: remove this in SSP 2.0 + if (!array_key_exists('UserID', $state)) { + // No unique user ID present. Attempt to add one. + self::addUserID($state); + } + + while (count($state[self::FILTERS_INDEX]) > 0) { + $filter = array_shift($state[self::FILTERS_INDEX]); + $filter->process($state); + } + } catch (SimpleSAML_Error_Exception $e) { + // No need to convert the exception + throw $e; + } catch (Exception $e) { + /* * To be consistent with the exception we return after an redirect, * we convert this exception before returning it. */ - throw new SimpleSAML_Error_UnserializableException($e); - } - - // Completed - } - - - /** - * Continues processing of the state. - * - * This function is used to resume processing by filters which for example needed to show - * a page to the user. - * - * This function will never return. Exceptions thrown during processing will be passed - * to whatever exception handler is defined in the state array. - * - * @param array $state The state we are processing. - */ - public static function resumeProcessing($state) { - assert('is_array($state)'); - - while (count($state[self::FILTERS_INDEX]) > 0) { - $filter = array_shift($state[self::FILTERS_INDEX]); - try { - $filter->process($state); - } catch (SimpleSAML_Error_Exception $e) { - SimpleSAML_Auth_State::throwException($state, $e); - } catch (Exception $e) { - $e = new SimpleSAML_Error_UnserializableException($e); - SimpleSAML_Auth_State::throwException($state, $e); - } - } - - // Completed - - assert('array_key_exists("ReturnURL", $state) || array_key_exists("ReturnCall", $state)'); - assert('!array_key_exists("ReturnURL", $state) || !array_key_exists("ReturnCall", $state)'); - - - if (array_key_exists('ReturnURL', $state)) { - /* + throw new SimpleSAML_Error_UnserializableException($e); + } + + // Completed + } + + + /** + * Continues processing of the state. + * + * This function is used to resume processing by filters which for example needed to show + * a page to the user. + * + * This function will never return. Exceptions thrown during processing will be passed + * to whatever exception handler is defined in the state array. + * + * @param array $state The state we are processing. + */ + public static function resumeProcessing($state) + { + assert('is_array($state)'); + + while (count($state[self::FILTERS_INDEX]) > 0) { + $filter = array_shift($state[self::FILTERS_INDEX]); + try { + $filter->process($state); + } catch (SimpleSAML_Error_Exception $e) { + SimpleSAML_Auth_State::throwException($state, $e); + } catch (Exception $e) { + $e = new SimpleSAML_Error_UnserializableException($e); + SimpleSAML_Auth_State::throwException($state, $e); + } + } + + // Completed + + assert('array_key_exists("ReturnURL", $state) || array_key_exists("ReturnCall", $state)'); + assert('!array_key_exists("ReturnURL", $state) || !array_key_exists("ReturnCall", $state)'); + + + if (array_key_exists('ReturnURL', $state)) { + /* * Save state information, and redirect to the URL specified * in $state['ReturnURL']. */ - $id = SimpleSAML_Auth_State::saveState($state, self::COMPLETED_STAGE); - \SimpleSAML\Utils\HTTP::redirectTrustedURL($state['ReturnURL'], array(self::AUTHPARAM => $id)); - } else { - /* Pass the state to the function defined in $state['ReturnCall']. */ - - // We are done with the state array in the session. Delete it. - SimpleSAML_Auth_State::deleteState($state); - - $func = $state['ReturnCall']; - assert('is_callable($func)'); - - call_user_func($func, $state); - assert(FALSE); - } - } - - - /** - * Process the given state passivly. - * - * Modules with user interaction are expected to throw an SimpleSAML_Error_NoPassive exception - * which are silently ignored. Exceptions of other types are passed further up the call stack. - * - * This function will only return if processing completes. - * - * @param array &$state The state we are processing. - */ - public function processStatePassive(&$state) { - assert('is_array($state)'); - // Should not be set when calling this method - assert('!array_key_exists("ReturnURL", $state)'); - - // Notify filters about passive request - $state['isPassive'] = TRUE; - - $state[self::FILTERS_INDEX] = $this->filters; - - // TODO: remove this in SSP 2.0 - if (!array_key_exists('UserID', $state)) { - // No unique user ID present. Attempt to add one. - self::addUserID($state); - } - - while (count($state[self::FILTERS_INDEX]) > 0) { - $filter = array_shift($state[self::FILTERS_INDEX]); - try { - $filter->process($state); - - // Ignore SimpleSAML_Error_NoPassive exceptions - } catch (SimpleSAML_Error_NoPassive $e) { } - } - } - - /** - * Retrieve a state which has finished processing. - * - * @param string $id The state identifier. + $id = SimpleSAML_Auth_State::saveState($state, self::COMPLETED_STAGE); + \SimpleSAML\Utils\HTTP::redirectTrustedURL($state['ReturnURL'], array(self::AUTHPARAM => $id)); + } else { + /* Pass the state to the function defined in $state['ReturnCall']. */ + + // We are done with the state array in the session. Delete it. + SimpleSAML_Auth_State::deleteState($state); + + $func = $state['ReturnCall']; + assert('is_callable($func)'); + + call_user_func($func, $state); + assert(false); + } + } + + + /** + * Process the given state passivly. + * + * Modules with user interaction are expected to throw an SimpleSAML_Error_NoPassive exception + * which are silently ignored. Exceptions of other types are passed further up the call stack. + * + * This function will only return if processing completes. + * + * @param array &$state The state we are processing. + */ + public function processStatePassive(&$state) + { + assert('is_array($state)'); + // Should not be set when calling this method + assert('!array_key_exists("ReturnURL", $state)'); + + // Notify filters about passive request + $state['isPassive'] = true; + + $state[self::FILTERS_INDEX] = $this->filters; + + // TODO: remove this in SSP 2.0 + if (!array_key_exists('UserID', $state)) { + // No unique user ID present. Attempt to add one. + self::addUserID($state); + } + + while (count($state[self::FILTERS_INDEX]) > 0) { + $filter = array_shift($state[self::FILTERS_INDEX]); + try { + $filter->process($state); + + // Ignore SimpleSAML_Error_NoPassive exceptions + } catch (SimpleSAML_Error_NoPassive $e) { + } + } + } + + /** + * Retrieve a state which has finished processing. + * + * @param string $id The state identifier. * @see SimpleSAML_Auth_State::parseStateID() * @return Array The state referenced by the $id parameter. - */ - public static function fetchProcessedState($id) { - assert('is_string($id)'); - - return SimpleSAML_Auth_State::loadState($id, self::COMPLETED_STAGE); - } - - - /** - * @deprecated This method will be removed in SSP 2.0. - */ - private static function addUserID(&$state) { - assert('is_array($state)'); - assert('array_key_exists("Attributes", $state)'); - - if (isset($state['Destination']['userid.attribute'])) { - $attributeName = $state['Destination']['userid.attribute']; - SimpleSAML\Logger::warning("The 'userid.attribute' option has been deprecated."); - } elseif (isset($state['Source']['userid.attribute'])) { - $attributeName = $state['Source']['userid.attribute']; - SimpleSAML\Logger::warning("The 'userid.attribute' option has been deprecated."); - } else { - // Default attribute - $attributeName = 'eduPersonPrincipalName'; - } - - if (!array_key_exists($attributeName, $state['Attributes'])) { - return; - } - - $uid = $state['Attributes'][$attributeName]; - if (count($uid) === 0) { - SimpleSAML\Logger::warning('Empty user id attribute [' . $attributeName . '].'); - return; - } - - if (count($uid) > 1) { - SimpleSAML\Logger::warning('Multiple attribute values for user id attribute [' . $attributeName . '].'); - return; - } - - // TODO: the attribute value should be trimmed - $uid = $uid[0]; - - if (empty($uid)) { - SimpleSAML\Logger::warning('Empty value in attribute '.$attributeName.". on user. Cannot set UserID."); - return; - } - $state['UserID'] = $uid; - } - + */ + public static function fetchProcessedState($id) + { + assert('is_string($id)'); + + return SimpleSAML_Auth_State::loadState($id, self::COMPLETED_STAGE); + } + + + /** + * @deprecated This method will be removed in SSP 2.0. + */ + private static function addUserID(&$state) + { + assert('is_array($state)'); + assert('array_key_exists("Attributes", $state)'); + + if (isset($state['Destination']['userid.attribute'])) { + $attributeName = $state['Destination']['userid.attribute']; + SimpleSAML\Logger::warning("The 'userid.attribute' option has been deprecated."); + } elseif (isset($state['Source']['userid.attribute'])) { + $attributeName = $state['Source']['userid.attribute']; + SimpleSAML\Logger::warning("The 'userid.attribute' option has been deprecated."); + } else { + // Default attribute + $attributeName = 'eduPersonPrincipalName'; + } + + if (!array_key_exists($attributeName, $state['Attributes'])) { + return; + } + + $uid = $state['Attributes'][$attributeName]; + if (count($uid) === 0) { + SimpleSAML\Logger::warning('Empty user id attribute [' . $attributeName . '].'); + return; + } + + if (count($uid) > 1) { + SimpleSAML\Logger::warning('Multiple attribute values for user id attribute [' . $attributeName . '].'); + return; + } + + // TODO: the attribute value should be trimmed + $uid = $uid[0]; + + if (empty($uid)) { + SimpleSAML\Logger::warning('Empty value in attribute '.$attributeName.". on user. Cannot set UserID."); + return; + } + $state['UserID'] = $uid; + } } diff --git a/lib/SimpleSAML/Auth/ProcessingFilter.php b/lib/SimpleSAML/Auth/ProcessingFilter.php index 2e576ff40326bde41fe12f2fcf6d30dc896160f8..9b271c04eeda3e6ef6e14a2dc5538bb0f94ff730 100644 --- a/lib/SimpleSAML/Auth/ProcessingFilter.php +++ b/lib/SimpleSAML/Auth/ProcessingFilter.php @@ -18,49 +18,50 @@ * @author Olav Morken, UNINETT AS. * @package SimpleSAMLphp */ -abstract class SimpleSAML_Auth_ProcessingFilter { +abstract class SimpleSAML_Auth_ProcessingFilter +{ - /** - * Priority of this filter. - * - * Used when merging IdP and SP processing chains. - * The priority can be any integer. The default for most filters is 50. Filters may however - * specify their own default, if they typically should be amongst the first or the last filters. - * - * The prioroty can also be overridden by the user by specifying the '%priority' option. - */ - public $priority = 50; + /** + * Priority of this filter. + * + * Used when merging IdP and SP processing chains. + * The priority can be any integer. The default for most filters is 50. Filters may however + * specify their own default, if they typically should be amongst the first or the last filters. + * + * The prioroty can also be overridden by the user by specifying the '%priority' option. + */ + public $priority = 50; - /** - * Constructor for a processing filter. - * - * Any processing filter which implements its own constructor must call this - * constructor first. - * - * @param array &$config Configuration for this filter. - * @param mixed $reserved For future use. - */ - public function __construct(&$config, $reserved) { - assert('is_array($config)'); + /** + * Constructor for a processing filter. + * + * Any processing filter which implements its own constructor must call this + * constructor first. + * + * @param array &$config Configuration for this filter. + * @param mixed $reserved For future use. + */ + public function __construct(&$config, $reserved) + { + assert('is_array($config)'); - if(array_key_exists('%priority', $config)) { - $this->priority = $config['%priority']; - if(!is_int($this->priority)) { - throw new Exception('Invalid priority: ' . var_export($this->priority, TRUE)); - } - unset($config['%priority']); - } - } + if (array_key_exists('%priority', $config)) { + $this->priority = $config['%priority']; + if (!is_int($this->priority)) { + throw new Exception('Invalid priority: ' . var_export($this->priority, true)); + } + unset($config['%priority']); + } + } - /** - * Process a request. - * - * When a filter returns from this function, it is assumed to have completed its task. - * - * @param array &$request The request we are currently processing. - */ - abstract public function process(&$request); - + /** + * Process a request. + * + * When a filter returns from this function, it is assumed to have completed its task. + * + * @param array &$request The request we are currently processing. + */ + abstract public function process(&$request); } diff --git a/lib/SimpleSAML/Auth/State.php b/lib/SimpleSAML/Auth/State.php index 447f9619ebb29921ea9dbef183a49f754a3094ae..05743d8cbbc5a082fceff242f0122be79111ea74 100644 --- a/lib/SimpleSAML/Auth/State.php +++ b/lib/SimpleSAML/Auth/State.php @@ -345,7 +345,6 @@ class SimpleSAML_Auth_State assert('is_array($state)'); if (array_key_exists(self::EXCEPTION_HANDLER_URL, $state)) { - // Save the exception $state[self::EXCEPTION_DATA] = $exception; $id = self::saveState($state, self::EXCEPTION_STAGE);