summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaime Pérez Crespo <jaime.perez@uninett.no>2014-01-24 16:36:54 +0000
committerJaime Pérez Crespo <jaime.perez@uninett.no>2014-01-24 16:36:54 +0000
commit57acd8378e263f6abd41a427f01fdcada0391a20 (patch)
tree1e4573af30e5c6250fc99697664f6bf3e16081c3
parentc21dc1ba0d1073de8f0ed1779f626ee8b132c9f7 (diff)
downloadsimplesamlphp-57acd8378e263f6abd41a427f01fdcada0391a20.zip
simplesamlphp-57acd8378e263f6abd41a427f01fdcada0391a20.tar.gz
simplesamlphp-57acd8378e263f6abd41a427f01fdcada0391a20.tar.bz2
Followup on previous commits. Use redirectUntrustedURL() as a shortcut, and let everything else make use of redirectTrustedURL(). Move the responsibility to check the input out of the library, to the places where URLs are grabbed from input parameters.
git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3332 44740490-163a-0410-bde0-09ae8108e29a
-rw-r--r--config-templates/config.php21
-rw-r--r--docs/simplesamlphp-sp-migration.txt3
-rw-r--r--lib/SimpleSAML/Auth/BWC.php6
-rw-r--r--lib/SimpleSAML/Auth/Default.php64
-rw-r--r--lib/SimpleSAML/Auth/ProcessingChain.php11
-rw-r--r--lib/SimpleSAML/Auth/Simple.php2
-rw-r--r--lib/SimpleSAML/Auth/State.php8
-rw-r--r--lib/SimpleSAML/IdP.php2
-rw-r--r--lib/SimpleSAML/IdP/LogoutTraditional.php6
-rw-r--r--lib/SimpleSAML/Utilities.php244
-rw-r--r--lib/SimpleSAML/XHTML/IdPDisco.php8
-rw-r--r--modules/InfoCard/lib/Auth/Source/ICAuth.php13
-rw-r--r--modules/aselect/www/credentials.php13
-rw-r--r--modules/authYubiKey/lib/Auth/Source/YubiKey.php6
-rw-r--r--modules/authfacebook/www/linkback.php7
-rw-r--r--modules/authlinkedin/www/linkback.php6
-rw-r--r--modules/authmyspace/www/linkback.php6
-rw-r--r--modules/authorize/www/authorize_403.php7
-rw-r--r--modules/authtwitter/www/linkback.php6
-rw-r--r--modules/authwindowslive/www/linkback.php7
-rw-r--r--modules/cas/www/linkback.php6
-rw-r--r--modules/casserver/www/login.php4
-rw-r--r--modules/cdc/lib/Server.php2
-rw-r--r--modules/cdc/www/resume.php6
-rw-r--r--modules/consent/www/getconsent.php7
-rw-r--r--modules/consent/www/logout.php7
-rw-r--r--modules/consent/www/noconsent.php7
-rw-r--r--modules/core/lib/Auth/UserPassBase.php6
-rw-r--r--modules/core/lib/Auth/UserPassOrgBase.php12
-rw-r--r--modules/core/www/as_login.php6
-rw-r--r--modules/core/www/as_logout.php2
-rw-r--r--modules/core/www/bwc_resumeauth.php2
-rw-r--r--modules/core/www/cleardiscochoices.php4
-rw-r--r--modules/core/www/idp/logout-iframe-done.php6
-rw-r--r--modules/core/www/idp/logout-iframe.php6
-rw-r--r--modules/core/www/idp/resumelogout.php6
-rw-r--r--modules/core/www/login-admin.php3
-rw-r--r--modules/core/www/loginuserpass.php6
-rw-r--r--modules/core/www/loginuserpassorg.php6
-rw-r--r--modules/core/www/short_sso_interval.php7
-rw-r--r--modules/discopower/lib/PowerIdPDisco.php4
-rw-r--r--modules/exampleauth/lib/Auth/Source/External.php6
-rw-r--r--modules/exampleauth/www/authpage.php12
-rw-r--r--modules/exampleauth/www/redirecttest.php7
-rw-r--r--modules/expirycheck/www/about2expire.php7
-rw-r--r--modules/expirycheck/www/expired.php7
-rw-r--r--modules/multiauth/www/selectsource.php6
-rw-r--r--modules/negotiate/www/backend.php7
-rw-r--r--modules/negotiate/www/retry.php7
-rw-r--r--modules/oauth/www/authorize.php2
-rw-r--r--modules/openid/www/consumer.php7
-rw-r--r--modules/openid/www/linkback.php7
-rw-r--r--modules/openidProvider/lib/Server.php6
-rw-r--r--modules/papi/lib/Auth/Source/PAPI.php14
-rw-r--r--modules/preprodwarning/www/showwarning.php7
-rw-r--r--modules/saml/www/sp/discoresp.php10
-rw-r--r--modules/saml/www/sp/saml1-acs.php16
-rw-r--r--modules/saml/www/sp/saml2-acs.php9
-rw-r--r--modules/saml/www/sp/saml2-logout.php6
-rw-r--r--www/auth/login-admin.php7
-rw-r--r--www/auth/login-cas-ldap.php15
-rw-r--r--www/auth/login-ldapmulti.php21
-rw-r--r--www/auth/login-radius.php21
-rw-r--r--www/auth/login-tlsclient.php15
-rw-r--r--www/auth/login-wayf-ldap.php4
-rw-r--r--www/saml2/idp/SingleLogoutService.php2
-rw-r--r--www/saml2/idp/idpInitSingleLogoutServiceiFrame.php2
-rw-r--r--www/saml2/idp/initSLO.php3
-rw-r--r--www/saml2/sp/AssertionConsumerService.php11
-rw-r--r--www/saml2/sp/SingleLogoutService.php4
-rw-r--r--www/saml2/sp/initSLO.php8
-rw-r--r--www/saml2/sp/initSSO.php7
-rw-r--r--www/shib13/sp/AssertionConsumerService.php9
-rw-r--r--www/shib13/sp/initSSO.php2
-rw-r--r--www/wsfed/sp/initSLO.php4
-rw-r--r--www/wsfed/sp/initSSO.php2
76 files changed, 575 insertions, 266 deletions
diff --git a/config-templates/config.php b/config-templates/config.php
index 66d1cf4..9892733 100644
--- a/config-templates/config.php
+++ b/config-templates/config.php
@@ -701,13 +701,26 @@ $config = array (
'proxy' => NULL,
/*
- * Array of URL's to allow a trusted redirect to.
+ * Array of domains that are allowed when generating links or redirections
+ * to URLs. simpleSAMLphp will use this option to determine whether to
+ * to consider a given URL valid or not, but you should always validate
+ * URLs obtained from the input on your own (i.e. ReturnTo or RelayState
+ * parameters obtained from the $_REQUEST array).
*
- * Set to NULL to disable.
+ * Set to NULL to disable checking of URLs.
+ *
+ * simpleSAMLphp will automatically add your own domain (either by checking
+ * it dinamically, or by using the domain defined in the 'baseurlpath'
+ * directive, the latter having precedence) to the list of trusted domains,
+ * in case this option is NOT set to NULL. In that case, you are explicitly
+ * telling simpleSAMLphp to verify URLs.
+ *
+ * Set to an empty array to disallow ALL redirections or links pointing to
+ * an external URL other than your own domain.
*
* Example:
- * 'redirect.trustedsites' => array('sp.example.com', 'othersite.org'),
+ * 'trusted.url.domains' => array('sp.example.com', 'app.example.com'),
*/
- 'redirect.trustedsites' => NULL,
+ 'trusted.url.domains' => NULL,
);
diff --git a/docs/simplesamlphp-sp-migration.txt b/docs/simplesamlphp-sp-migration.txt
index 72a165e..7b425e0 100644
--- a/docs/simplesamlphp-sp-migration.txt
+++ b/docs/simplesamlphp-sp-migration.txt
@@ -209,6 +209,9 @@ If you want to return to a specific URL after logging out, you should include th
$as->logout('https://example.org/');
+Please make sure the URL is trusted. If you obtain the URL from the user input, make sure it is trusted before
+calling $as->logout(), by using the SimpleSAML_Utilities::checkURLAllowed() method.
+
#### Login link
diff --git a/lib/SimpleSAML/Auth/BWC.php b/lib/SimpleSAML/Auth/BWC.php
index 290c514..923e978 100644
--- a/lib/SimpleSAML/Auth/BWC.php
+++ b/lib/SimpleSAML/Auth/BWC.php
@@ -143,19 +143,19 @@ class SimpleSAML_Auth_BWC extends SimpleSAML_Auth_Simple {
$session = SimpleSAML_Session::getInstance();
if (!$session->isValid($this->authority)) {
/* Not authenticated to this authentication source. */
- SimpleSAML_Utilities::redirectUntrustedURL($url);
+ SimpleSAML_Utilities::redirectTrustedURL($url);
assert('FALSE');
}
if ($this->authority === 'saml2') {
$config = SimpleSAML_Configuration::getInstance();
- SimpleSAML_Utilities::redirectUntrustedURL('/' . $config->getBaseURL() . 'saml2/sp/initSLO.php',
+ SimpleSAML_Utilities::redirectTrustedURL('/' . $config->getBaseURL() . 'saml2/sp/initSLO.php',
array('RelayState' => $url)
);
}
$session->doLogout($this->authority);
- SimpleSAML_Utilities::redirectUntrustedURL($url);
+ SimpleSAML_Utilities::redirectTrustedURL($url);
}
}
diff --git a/lib/SimpleSAML/Auth/Default.php b/lib/SimpleSAML/Auth/Default.php
index 34686aa..ca02e74 100644
--- a/lib/SimpleSAML/Auth/Default.php
+++ b/lib/SimpleSAML/Auth/Default.php
@@ -19,13 +19,21 @@ class SimpleSAML_Auth_Default {
* This function never returns.
*
* @param string $authId The identifier of the authentication source.
- * @param string|array $return The URL or function we should direct the user to after authentication.
- * @param string|NULL $errorURL The URL we should direct the user to after failed authentication.
- * Can be NULL, in which case a standard error page will be shown.
- * @param array $params Extra information about the login. Different authentication requestors may
- * provide different information. Optional, will default to an empty array.
+ * @param string|array $return The URL or function we should direct the
+ * user to after authentication. If using a URL obtained from user input,
+ * please make sure to check it by calling
+ * SimpleSAML_Utilities::checkURLAllowed().
+ * @param string|NULL $errorURL The URL we should direct the user to after
+ * failed authentication. Can be NULL, in which case a standard error page
+ * will be shown. If using a URL obtained from user input, please make sure
+ * to check it by calling SimpleSAML_Utilities::checkURLAllowed().
+ * @param array $params Extra information about the login. Different
+ * authentication requestors may provide different information. Optional,
+ * will default to an empty array.
*/
- public static function initLogin($authId, $return, $errorURL = NULL, array $params = array()) {
+ public static function initLogin($authId, $return, $errorURL = NULL,
+ array $params = array()) {
+
assert('is_string($authId)');
assert('is_string($return) || is_array($return)');
assert('is_string($errorURL) || is_null($errorURL)');
@@ -121,7 +129,7 @@ class SimpleSAML_Auth_Default {
if (is_string($return)) {
/* Redirect... */
- SimpleSAML_Utilities::redirectUntrustedURL($return);
+ SimpleSAML_Utilities::redirectTrustedURL($return);
} else {
call_user_func($return, $state);
assert('FALSE');
@@ -132,11 +140,16 @@ class SimpleSAML_Auth_Default {
/**
* Start logout.
*
- * This function starts a logout operation from the current authentication source. This function
- * will return if the logout operation does not require a redirect.
+ * This function starts a logout operation from the current authentication
+ * source. This function will return if the logout operation does not
+ * require a redirect.
*
- * @param string $returnURL The URL we should redirect the user to after logging out.
- * @param string|NULL $authority The authentication source we are logging out from, or NULL to log out of the most recent.
+ * @param string $returnURL The URL we should redirect the user to after
+ * logging out. No checking is performed on the URL, so make sure to verify
+ * it on beforehand if the URL is obtained from user input. Refer to
+ * SimpleSAML_Utilities::checkURLAllowed() for more information.
+ * @param string|NULL $authority The authentication source we are logging
+ * out from, or NULL to log out from the most recent.
*/
public static function initLogoutReturn($returnURL, $authority = NULL) {
assert('is_string($returnURL)');
@@ -171,11 +184,16 @@ class SimpleSAML_Auth_Default {
/**
* Start logout.
*
- * This function starts a logout operation from the current authentication source. This function
- * never returns.
+ * This function starts a logout operation from the current authentication
+ * source. This function never returns.
*
- * @param string $returnURL The URL we should redirect the user to after logging out.
- * @param string|NULL $authority The authentication source we are logging out from, or NULL to log out of the most recent.
+ * @param string $returnURL The URL we should redirect the user to after
+ * logging out. No checking is performed on the URL, so make sure to verify
+ * it on beforehand if the URL is obtained from user input. Refer to
+ * SimpleSAML_Utilities::checkURLAllowed() for more information.
+ * @param string|NULL $authority The authentication source we are logging
+ * out from, or NULL to log out from the most recent.
+ * @return void This function never returns.
*/
public static function initLogout($returnURL, $authority = NULL) {
assert('is_string($returnURL)');
@@ -184,7 +202,7 @@ class SimpleSAML_Auth_Default {
self::initLogoutReturn($returnURL, $authority);
/* Redirect... */
- SimpleSAML_Utilities::redirectUntrustedURL($returnURL);
+ SimpleSAML_Utilities::redirectTrustedURL($returnURL);
}
@@ -202,7 +220,7 @@ class SimpleSAML_Auth_Default {
$returnURL = $state['SimpleSAML_Auth_Default.ReturnURL'];
/* Redirect... */
- SimpleSAML_Utilities::redirectUntrustedURL($returnURL);
+ SimpleSAML_Utilities::redirectTrustedURL($returnURL);
}
@@ -239,10 +257,14 @@ class SimpleSAML_Auth_Default {
*
* This is used to handle IdP initiated SSO.
*
- * @param string $authId The id of the authentication source that received the request.
- * @param array $state A state array.
- * @param string $redirectTo The URL we should redirect the user to after
- * updating the session.
+ * @param string $authId The id of the authentication source that received
+ * the request.
+ * @param array $state A state array.
+ * @param string $redirectTo The URL we should redirect the user to after
+ * updating the session. The function will check if the URL is allowed, so
+ * there is no need to manually check the URL on beforehand. Please refer
+ * to the 'trusted.url.domains' configuration directive for more
+ * information about allowing (or disallowing) URLs.
*/
public static function handleUnsolicitedAuth($authId, array $state, $redirectTo) {
assert('is_string($authId)');
diff --git a/lib/SimpleSAML/Auth/ProcessingChain.php b/lib/SimpleSAML/Auth/ProcessingChain.php
index da04532..1b60e33 100644
--- a/lib/SimpleSAML/Auth/ProcessingChain.php
+++ b/lib/SimpleSAML/Auth/ProcessingChain.php
@@ -248,7 +248,7 @@ class SimpleSAML_Auth_ProcessingChain {
* in $state['ReturnURL'].
*/
$id = SimpleSAML_Auth_State::saveState($state, self::COMPLETED_STAGE);
- SimpleSAML_Utilities::redirectUntrustedURL($state['ReturnURL'], array(self::AUTHPARAM => $id));
+ SimpleSAML_Utilities::redirectTrustedURL($state['ReturnURL'], array(self::AUTHPARAM => $id));
} else {
/* Pass the state to the function defined in $state['ReturnCall']. */
@@ -302,8 +302,11 @@ class SimpleSAML_Auth_ProcessingChain {
/**
* Retrieve a state which has finished processing.
*
- * @param string $id The identifier of the state. This can be found in the request parameter
- * with index from SimpleSAML_Auth_ProcessingChain::AUTHPARAM.
+ * @param string $id The state identifier. This can be found in the
+ * SimpleSAML_Auth_ProcessingChain::AUTHPARAM request parameter. Please
+ * make sure to sanitize it properly by calling the
+ * SimpleSAML_Utilities::checkURLAllowed() function with the embedded
+ * restart URL, if any. See also SimpleSAML_Utilities::getURLFromStateID().
*/
public static function fetchProcessedState($id) {
assert('is_string($id)');
@@ -351,5 +354,3 @@ class SimpleSAML_Auth_ProcessingChain {
}
}
-
-?> \ No newline at end of file
diff --git a/lib/SimpleSAML/Auth/Simple.php b/lib/SimpleSAML/Auth/Simple.php
index 8577379..4f7d8fb 100644
--- a/lib/SimpleSAML/Auth/Simple.php
+++ b/lib/SimpleSAML/Auth/Simple.php
@@ -219,7 +219,7 @@ class SimpleSAML_Auth_Simple {
$params[$state['ReturnStateParam']] = $stateID;
}
- SimpleSAML_Utilities::redirectUntrustedURL($state['ReturnTo'], $params);
+ SimpleSAML_Utilities::redirectTrustedURL($state['ReturnTo'], $params);
}
}
diff --git a/lib/SimpleSAML/Auth/State.php b/lib/SimpleSAML/Auth/State.php
index 5738766..0b74da2 100644
--- a/lib/SimpleSAML/Auth/State.php
+++ b/lib/SimpleSAML/Auth/State.php
@@ -211,13 +211,7 @@ class SimpleSAML_Auth_State {
assert('is_bool($allowMissing)');
SimpleSAML_Logger::debug('Loading state: ' . var_export($id, TRUE));
- $tmp = explode(':', $id, 2);
- $id = $tmp[0];
- if (count($tmp) === 2) {
- $restartURL = $tmp[1];
- } else {
- $restartURL = NULL;
- }
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($id);
$session = SimpleSAML_Session::getInstance();
$state = $session->getData('SimpleSAML_Auth_State', $id);
diff --git a/lib/SimpleSAML/IdP.php b/lib/SimpleSAML/IdP.php
index 630662d..d94c427 100644
--- a/lib/SimpleSAML/IdP.php
+++ b/lib/SimpleSAML/IdP.php
@@ -529,7 +529,7 @@ class SimpleSAML_IdP {
public static function finishLogoutRedirect(SimpleSAML_IdP $idp, array $state) {
assert('isset($state["core:Logout:URL"])');
- SimpleSAML_Utilities::redirectUntrustedURL($state['core:Logout:URL']);
+ SimpleSAML_Utilities::redirectTrustedURL($state['core:Logout:URL']);
assert('FALSE');
}
diff --git a/lib/SimpleSAML/IdP/LogoutTraditional.php b/lib/SimpleSAML/IdP/LogoutTraditional.php
index 86ce301..f9fa132 100644
--- a/lib/SimpleSAML/IdP/LogoutTraditional.php
+++ b/lib/SimpleSAML/IdP/LogoutTraditional.php
@@ -76,6 +76,12 @@ class SimpleSAML_IdP_LogoutTraditional extends SimpleSAML_IdP_LogoutHandler {
throw new SimpleSAML_Error_Exception('RelayState lost during logout.');
}
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($relayState);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
$state = SimpleSAML_Auth_State::loadState($relayState, 'core:LogoutTraditional');
if ($error === NULL) {
diff --git a/lib/SimpleSAML/Utilities.php b/lib/SimpleSAML/Utilities.php
index 0b37bf8..cd7ef1f 100644
--- a/lib/SimpleSAML/Utilities.php
+++ b/lib/SimpleSAML/Utilities.php
@@ -298,17 +298,80 @@ class SimpleSAML_Utilities {
}
+ /**
+ * Check if a URL is valid and is in our list of allowed URLs.
+ *
+ * @param string $url The URL to check.
+ * @param array $trustedSites An optional white list of domains. If none
+ * specified, the 'trusted.url.domains' configuration directive will be
+ * used.
+ * @return string The normalized URL itself if it is allowed.
+ * @throws SimpleSAML_Error_Exception if the URL is malformed or is not
+ * allowed by configuration.
+ */
+ public static function checkURLAllowed($url, array $trustedSites = NULL) {
+ $url = self::normalizeURL($url);
+
+ // verify that the URL points to an http or https site
+ if (!preg_match('@^https?://@i', $url)) {
+ throw new SimpleSAML_Error_Exception('Invalid URL: '.$url);
+ }
+
+ // get the white list of domains
+ if ($trustedSites === NULL) {
+ $trustedSites = SimpleSAML_Configuration::getInstance()->getArray('trusted.url.domains', NULL);
+ if ($trustedSites === NULL) {
+ $trustedSites = SimpleSAML_Configuration::getInstance()->getArray('redirect.trustedsites', NULL);
+ }
+ }
+
+ // validates the URL's host is among those allowed
+ if ($trustedSites !== NULL) {
+ assert(is_array($trustedSites));
+ preg_match('@^https?://([^/]+)@i', $url, $matches);
+ $hostname = $matches[1];
+
+ // add self host to the white list
+ $self_host = self::getSelfHost();
+ $trustedSites[] = $self_host;
+
+ /* Throw exception due to redirection to untrusted site */
+ if (!in_array($hostname, $trustedSites)) {
+ throw new SimpleSAML_Error_Exception('URL not allowed: '.$url);
+ }
+ }
+ return $url;
+ }
+
+
+ /**
+ * Get a URL embedded in a StateID, in the form 'id:url'.
+ *
+ * @param string $stateId The state ID to use.
+ * @return string The embedded URL if found, NULL otherwise.
+ */
+ public static function getURLFromStateID($stateId) {
+ $tmp = explode(':', $stateId, 2);
+ $id = $tmp[0];
+ $url = NULL;
+ if (count($tmp) === 2) {
+ $url = $tmp[1];
+ }
+ return $url;
+ }
+
+
public static function checkDateConditions($start=NULL, $end=NULL) {
$currentTime = time();
- if (! empty($start)) {
+ if (!empty($start)) {
$startTime = SAML2_Utils::parseSAML2Time($start);
/* Allow for a 10 minute difference in Time */
if (($startTime < 0) || (($startTime - 600) > $currentTime)) {
return FALSE;
}
}
- if (! empty($end)) {
+ if (!empty($end)) {
$endTime = SAML2_Utils::parseSAML2Time($end);
if (($endTime < 0) || ($endTime <= $currentTime)) {
return FALSE;
@@ -493,113 +556,20 @@ class SimpleSAML_Utilities {
return true;
}
-
- /**
- * This function redirects the user to the specified address.
- *
- * This function will use the "HTTP 303 See Other" redirection if the
- * current request used the POST method and the HTTP version is 1.1.
- * Otherwise, a "HTTP 302 Found" redirection will be used.
- *
- * The fuction will also generate a simple web page with a clickable
- * link to the target page.
- *
- * @param string $url The URL we should redirect to. This URL may include
- * query parameters. If this URL is a relative URL (starting with '/'),
- * then it will be turned into an absolute URL by prefixing it with the
- * absolute URL to the root of the website.
- * @param string[] $parameters An array with extra query string parameters
- * which should be appended to the URL. The name of the parameter is the
- * array index. The value of the parameter is the value stored in the index.
- * Both the name and the value will be urlencoded. If the value is NULL,
- * then the parameter will be encoded as just the name, without a value.
- * @param string[] $allowed_redirect_hosts An array with a whitelist of
- * hosts for which redirects are allowed. If NULL, redirections will be
- * allowed to any host. Otherwise, the host of the $url provided must be
- * present in this parameter. If the host is not whitelisted, an exception
- * will be thrown.
- *
- * @return void This function never returns.
- * @deprecated 1.12.0 This function will be removed from the API. Use
- * accordingly the redirectTrustedURL or redirectUntrustedURL functions
- * instead.
+ /*
+ * This is a temporary function, holding the redirect() functionality,
+ * meanwhile we are deprecating the it.
*/
- public static function redirect($url, $parameters = array(), $allowed_redirect_hosts = NULL) {
- assert(is_string($url));
- assert(strlen($url) > 0);
- assert(is_array($parameters));
- if($allowed_redirect_hosts != NULL) assert(is_array($allowed_redirect_hosts));
-
- /* Check for relative URL. */
- if(substr($url, 0, 1) === '/') {
- /* Prefix the URL with the url to the root of the
- * website.
- */
- $url = self::selfURLhost() . $url;
+ private static function _doRedirect($url, $parameters = array()) {
+ if (!empty($parameters)) {
+ $url = self::addURLparameter($url, $parameters);
}
- /* Verify that the URL points to an http or https site. */
- if (!preg_match('@^https?://@i', $url)) {
- throw new SimpleSAML_Error_Exception('Redirect to invalid URL: ' . $url);
- }
-
- /* Validates the URL's host is among those allowed. */
- if ($allowed_redirect_hosts !== NULL) {
- preg_match('@^https?://([^/]+)@i', $url, $matches);
- $hostname = $matches[1];
-
- // add self host to the white list
- $self_host = self::getSelfHost();
- $allowed_redirect_hosts[] = $self_host;
-
- /* Throw exception due to redirection to untrusted site */
- if(!in_array($hostname, $allowed_redirect_hosts)) {
- throw new SimpleSAML_Error_Exception('Redirection not to allowed to URL: ' . $url);
- }
- }
-
- /* Determine which prefix we should put before the first
- * parameter.
- */
- if(strpos($url, '?') === FALSE) {
- $paramPrefix = '?';
- } else {
- $paramPrefix = '&';
- }
-
- /* Iterate over the parameters and append them to the query
- * string.
- */
- foreach($parameters as $name => $value) {
-
- /* Encode the parameter. */
- if($value === NULL) {
- $param = urlencode($name);
- } elseif (is_array($value)) {
- $param = "";
- foreach ($value as $val) {
- $param .= urlencode($name) . "[]=" . urlencode($val) . '&';
- }
- } else {
- $param = urlencode($name) . '=' .
- urlencode($value);
- }
-
- /* Append the parameter to the query string. */
- $url .= $paramPrefix . $param;
-
- /* Every following parameter is guaranteed to follow
- * another parameter. Therefore we use the '&' prefix.
- */
- $paramPrefix = '&';
- }
-
-
/* Set the HTTP result code. This is either 303 See Other or
* 302 Found. HTTP 303 See Other is sent if the HTTP version
* is HTTP/1.1 and the request type was a POST request.
*/
- if($_SERVER['SERVER_PROTOCOL'] === 'HTTP/1.1' &&
+ if ($_SERVER['SERVER_PROTOCOL'] === 'HTTP/1.1' &&
$_SERVER['REQUEST_METHOD'] === 'POST') {
$code = 303;
} else {
@@ -630,7 +600,8 @@ class SimpleSAML_Utilities {
echo '<h1>Redirect</h1>';
echo '<p>';
echo 'You were redirected to: ';
- echo '<a id="redirlink" href="' . htmlspecialchars($url) . '">' . htmlspecialchars($url) . '</a>';
+ echo '<a id="redirlink" href="' .
+ htmlspecialchars($url) . '">' . htmlspecialchars($url) . '</a>';
echo '<script type="text/javascript">document.getElementById("redirlink").focus();</script>';
echo '</p>';
echo '</body>';
@@ -638,6 +609,51 @@ class SimpleSAML_Utilities {
/* End script execution. */
exit;
+ }
+
+
+ /**
+ * This function redirects the user to the specified address.
+ *
+ * This function will use the "HTTP 303 See Other" redirection if the
+ * current request used the POST method and the HTTP version is 1.1.
+ * Otherwise, a "HTTP 302 Found" redirection will be used.
+ *
+ * The fuction will also generate a simple web page with a clickable
+ * link to the target page.
+ *
+ * @param string $url The URL we should redirect to. This URL may include
+ * query parameters. If this URL is a relative URL (starting with '/'),
+ * then it will be turned into an absolute URL by prefixing it with the
+ * absolute URL to the root of the website.
+ * @param string[] $parameters An array with extra query string parameters
+ * which should be appended to the URL. The name of the parameter is the
+ * array index. The value of the parameter is the value stored in the index.
+ * Both the name and the value will be urlencoded. If the value is NULL,
+ * then the parameter will be encoded as just the name, without a value.
+ * @param string[] $allowed_redirect_hosts An array with a whitelist of
+ * hosts for which redirects are allowed. If NULL, redirections will be
+ * allowed to any host. Otherwise, the host of the $url provided must be
+ * present in this parameter. If the host is not whitelisted, an exception
+ * will be thrown.
+ *
+ * @return void This function never returns.
+ * @deprecated 1.12.0 This function will be removed from the API. Instead,
+ * use the redirectTrustedURL or redirectUntrustedURL functions
+ * accordingly.
+ */
+ public static function redirect($url, $parameters = array(),
+ $allowed_redirect_hosts = NULL) {
+
+ assert(is_string($url));
+ assert(strlen($url) > 0);
+ assert(is_array($parameters));
+
+ $url = self::normalizeURL($url);
+ if ($allowed_redirect_hosts !== NULL) {
+ $url = self::checkURLAllowed($url, $allowed_redirect_hosts);
+ }
+ self::_doRedirect($url, $parameters);
}
/**
@@ -665,26 +681,27 @@ class SimpleSAML_Utilities {
* @return void This function never returns.
*/
public static function redirectTrustedURL($url, $parameters = array()) {
- self::redirect($url, $parameters);
+ $url = self::normalizeURL($url);
+ self::_doRedirect($url, $parameters);
}
/**
* This function redirects to the specified URL after performing the
- * appropriate security checks on it. Particularly, it will make sure
- * that the provided URL is allowed by the 'redirect.trustedsites'
- * directive in the configuration.
+ * appropriate security checks on it. Particularly, it will make sure that
+ * the provided URL is allowed by the 'redirect.trustedsites' directive
+ * in the configuration.
*
- * If the aforementioned option is not set or the URL does corresponds
- * to a trusted site, it performs a redirection to it. If the site is
- * not trusted, an exception will be thrown.
+ * If the aforementioned option is not set or the URL does correspond to a
+ * trusted site, it performs a redirection to it. If the site is not
+ * trusted, an exception will be thrown.
*
* See the redirectTrustedURL function for more details.
*
* @return void This function never returns.
*/
public static function redirectUntrustedURL($url, $parameters = array()) {
- $trustedSites = SimpleSAML_Configuration::getInstance()->getArray('redirect.trustedsites', NULL);
- self::redirect($url, $parameters, $trustedSites);
+ $url = self::checkURLAllowed($url);
+ self::_doRedirect($url, $parameters);
}
/**
@@ -1150,8 +1167,7 @@ class SimpleSAML_Utilities {
$base = self::getBaseURL();
}
-
- if(!preg_match('$^((((\w+:)//[^/]+)(/[^?#]*))(?:\?[^#]*)?)(?:#.*)?$', $base, $baseParsed)) {
+ if(!preg_match('/^((((\w+:)\/\/[^\/]+)(\/[^?#]*))(?:\?[^#]*)?)(?:#.*)?/', $base, $baseParsed)) {
throw new Exception('Unable to parse base url: ' . $base);
}
diff --git a/lib/SimpleSAML/XHTML/IdPDisco.php b/lib/SimpleSAML/XHTML/IdPDisco.php
index c1c5be0..7e7eeb9 100644
--- a/lib/SimpleSAML/XHTML/IdPDisco.php
+++ b/lib/SimpleSAML/XHTML/IdPDisco.php
@@ -124,7 +124,7 @@ class SimpleSAML_XHTML_IdPDisco {
if(!array_key_exists('return', $_GET)) {
throw new Exception('Missing parameter: return');
} else {
- $this->returnURL = $_GET['return'];
+ $this->returnURL = SimpleSAML_Utilities::checkURLAllowed($_GET['return']);
}
$this->isPassive = FALSE;
@@ -474,7 +474,7 @@ class SimpleSAML_XHTML_IdPDisco {
} else {
$this->log('Choice made [' . $idp . '] (Redirecting the user back. returnIDParam=' . $this->returnIdParam . ')');
- SimpleSAML_Utilities::redirectUntrustedURL($this->returnURL, array($this->returnIdParam => $idp));
+ SimpleSAML_Utilities::redirectTrustedURL($this->returnURL, array($this->returnIdParam => $idp));
}
return;
@@ -482,7 +482,7 @@ class SimpleSAML_XHTML_IdPDisco {
if ($this->isPassive) {
$this->log('Choice not made. (Redirecting the user back without answer)');
- SimpleSAML_Utilities::redirectUntrustedURL($this->returnURL);
+ SimpleSAML_Utilities::redirectTrustedURL($this->returnURL);
return;
}
@@ -500,7 +500,7 @@ class SimpleSAML_XHTML_IdPDisco {
if(sizeof($idpintersection) == 1) {
$this->log('Choice made [' . $idpintersection[0] . '] (Redirecting the user back. returnIDParam=' . $this->returnIdParam . ')');
- SimpleSAML_Utilities::redirectUntrustedURL($this->returnURL, array($this->returnIdParam => $idpintersection[0]));
+ SimpleSAML_Utilities::redirectTrustedURL($this->returnURL, array($this->returnIdParam => $idpintersection[0]));
}
/*
diff --git a/modules/InfoCard/lib/Auth/Source/ICAuth.php b/modules/InfoCard/lib/Auth/Source/ICAuth.php
index 39e746c..0b76ed1 100644
--- a/modules/InfoCard/lib/Auth/Source/ICAuth.php
+++ b/modules/InfoCard/lib/Auth/Source/ICAuth.php
@@ -42,7 +42,6 @@ class sspmod_InfoCard_Auth_Source_ICAuth extends SimpleSAML_Auth_Source {
public static function handleLogin($authStateId, $xmlToken) {
-SimpleSAML_Logger::debug('ENTRA en icauth');
assert('is_string($authStateId)');
$config = SimpleSAML_Configuration::getInstance();
@@ -61,14 +60,20 @@ SimpleSAML_Logger::debug('ENTRA en icauth');
SimpleSAML_Logger::debug("NOXMLtoken: ".$xmlToken);
$claims = $infocard->process($xmlToken);
if($claims->isValid()) {
-// if(false) {
$attributes = array();
foreach ($Infocard['requiredClaims'] as $claim => $data){
$attributes[$claim] = array($claims->$claim);
}
foreach ($Infocard['optionalClaims'] as $claim => $data){
$attributes[$claim] = array($claims->$claim);
- }
+ }
+
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($authStateId);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
/* Retrieve the authentication state. */
$state = SimpleSAML_Auth_State::loadState($authStateId, self::STAGEID);
/* Find authentication source. */
@@ -78,12 +83,10 @@ SimpleSAML_Logger::debug('ENTRA en icauth');
throw new Exception('Could not find authentication source with id ' . $state[self::AUTHID]);
}
$state['Attributes'] = $attributes;
-SimpleSAML_Logger::debug('VALIDA');
unset($infocard);
unset($claims);
SimpleSAML_Auth_Source::completeAuth($state);
} else {
-SimpleSAML_Logger::debug('NO VALIDA ERROR:'.$claims->getErrorMsg());
unset($infocard);
unset($claims);
return 'wrong_IC';
diff --git a/modules/aselect/www/credentials.php b/modules/aselect/www/credentials.php
index 3d3b8cb..dc0afe7 100644
--- a/modules/aselect/www/credentials.php
+++ b/modules/aselect/www/credentials.php
@@ -7,7 +7,18 @@
* @author Wessel Dankers, Tilburg University
*/
function check_credentials() {
- $state = SimpleSAML_Auth_State::loadState($_REQUEST['ssp_state'], 'aselect:login');
+
+ if (!array_key_exists('ssp_state', $_REQUEST))
+ SimpleSAML_Auth_State::throwException($state, new SimpleSAML_Error_Exception("Missing ssp_state parameter"));
+ $id = $_REQUEST['ssp_state'];
+
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($id);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
+ $state = SimpleSAML_Auth_State::loadState($id, 'aselect:login');
if(!array_key_exists('a-select-server', $_REQUEST))
SimpleSAML_Auth_State::throwException($state, new SimpleSAML_Error_Exception("Missing a-select-server parameter"));
diff --git a/modules/authYubiKey/lib/Auth/Source/YubiKey.php b/modules/authYubiKey/lib/Auth/Source/YubiKey.php
index ae98920..6b14128 100644
--- a/modules/authYubiKey/lib/Auth/Source/YubiKey.php
+++ b/modules/authYubiKey/lib/Auth/Source/YubiKey.php
@@ -124,6 +124,12 @@ class sspmod_authYubiKey_Auth_Source_YubiKey extends SimpleSAML_Auth_Source {
assert('is_string($authStateId)');
assert('is_string($otp)');
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($authStateId);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
/* Retrieve the authentication state. */
$state = SimpleSAML_Auth_State::loadState($authStateId, self::STAGEID);
diff --git a/modules/authfacebook/www/linkback.php b/modules/authfacebook/www/linkback.php
index 3a27fe5..2305f77 100644
--- a/modules/authfacebook/www/linkback.php
+++ b/modules/authfacebook/www/linkback.php
@@ -9,6 +9,13 @@ if (!array_key_exists('AuthState', $_REQUEST) || empty($_REQUEST['AuthState']))
}
$stateID = $_REQUEST['AuthState'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($stateID);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($stateID, sspmod_authfacebook_Auth_Source_Facebook::STAGE_INIT);
/* Find authentication source. */
diff --git a/modules/authlinkedin/www/linkback.php b/modules/authlinkedin/www/linkback.php
index 961eaa6..a169f04 100644
--- a/modules/authlinkedin/www/linkback.php
+++ b/modules/authlinkedin/www/linkback.php
@@ -10,6 +10,12 @@ if (array_key_exists('stateid', $_REQUEST)) {
throw new Exception('Lost OAuth Client State');
}
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($stateId);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($stateId, sspmod_authlinkedin_Auth_Source_LinkedIn::STAGE_INIT);
// http://developer.linkedin.com/docs/DOC-1008#2_Redirect_the_User_to_our_Authorization_Server
diff --git a/modules/authmyspace/www/linkback.php b/modules/authmyspace/www/linkback.php
index 93c4515..81683c8 100644
--- a/modules/authmyspace/www/linkback.php
+++ b/modules/authmyspace/www/linkback.php
@@ -10,6 +10,12 @@ if (array_key_exists('stateid', $_REQUEST)) {
throw new Exception('State Lost - not returned by MySpace Auth');
}
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($stateId);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($stateId, sspmod_authmyspace_Auth_Source_MySpace::STAGE_INIT);
if (array_key_exists('oauth_problem', $_REQUEST)) {
diff --git a/modules/authorize/www/authorize_403.php b/modules/authorize/www/authorize_403.php
index 54d702f..613fa10 100644
--- a/modules/authorize/www/authorize_403.php
+++ b/modules/authorize/www/authorize_403.php
@@ -11,6 +11,13 @@ if (!array_key_exists('StateId', $_REQUEST)) {
}
$id = $_REQUEST['StateId'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($id);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($id, 'authorize:Authorize');
$globalConfig = SimpleSAML_Configuration::getInstance();
diff --git a/modules/authtwitter/www/linkback.php b/modules/authtwitter/www/linkback.php
index de6ec85..0ebea75 100644
--- a/modules/authtwitter/www/linkback.php
+++ b/modules/authtwitter/www/linkback.php
@@ -9,6 +9,12 @@ if (!array_key_exists('AuthState', $_REQUEST) || empty($_REQUEST['AuthState']))
}
$stateID = $_REQUEST['AuthState'];
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($stateID);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($stateID, sspmod_authtwitter_Auth_Source_Twitter::STAGE_INIT);
/* Find authentication source. */
diff --git a/modules/authwindowslive/www/linkback.php b/modules/authwindowslive/www/linkback.php
index 7ae4266..ee8452d 100644
--- a/modules/authwindowslive/www/linkback.php
+++ b/modules/authwindowslive/www/linkback.php
@@ -6,6 +6,13 @@
if (array_key_exists('wrap_client_state', $_REQUEST)) {
$stateId = $_REQUEST['wrap_client_state'];
+
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($stateId);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
$state = SimpleSAML_Auth_State::loadState($stateId, sspmod_authwindowslive_Auth_Source_LiveID::STAGE_INIT);
} else {
throw new Exception('Lost OAuth-WRAP Client State');
diff --git a/modules/cas/www/linkback.php b/modules/cas/www/linkback.php
index 1e6740c..8fe43e2 100644
--- a/modules/cas/www/linkback.php
+++ b/modules/cas/www/linkback.php
@@ -13,6 +13,12 @@ if (!isset($_GET['ticket'])) {
throw new SimpleSAML_Error_BadRequest('Missing ticket parameter.');
}
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($stateId);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($stateId, sspmod_cas_Auth_Source_CAS::STAGE_INIT);
$state['cas:ticket'] = (string)$_GET['ticket'];
diff --git a/modules/casserver/www/login.php b/modules/casserver/www/login.php
index e59c332..0410acd 100644
--- a/modules/casserver/www/login.php
+++ b/modules/casserver/www/login.php
@@ -48,10 +48,8 @@ storeTicket($ticket, $path, array('service' => $service,
'proxies' => array(),
'validbefore' => time() + 5));
-SimpleSAML_Utilities::redirectUntrustedURL(
+SimpleSAML_Utilities::redirectTrustedURL(
SimpleSAML_Utilities::addURLparameter($service,
array('ticket' => $ticket)
)
);
-
-?>
diff --git a/modules/cdc/lib/Server.php b/modules/cdc/lib/Server.php
index 8c962eb..d4dacf7 100644
--- a/modules/cdc/lib/Server.php
+++ b/modules/cdc/lib/Server.php
@@ -327,7 +327,7 @@ class sspmod_cdc_Server {
$url = SimpleSAML_Utilities::addURLparameter($to, $params);
if (strlen($url) < 2048) {
- SimpleSAML_Utilities::redirectUntrustedURL($url);
+ SimpleSAML_Utilities::redirectTrustedURL($url);
} else {
SimpleSAML_Utilities::postRedirect($to, $params);
}
diff --git a/modules/cdc/www/resume.php b/modules/cdc/www/resume.php
index 6e4fcf3..549be22 100644
--- a/modules/cdc/www/resume.php
+++ b/modules/cdc/www/resume.php
@@ -17,6 +17,12 @@ if (!isset($response['id'])) {
throw new SimpleSAML_Error_BadRequest('CDCResponse without id.');
}
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($response['id']);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($response['id'], 'cdc:resume');
SimpleSAML_Auth_ProcessingChain::resumeProcessing($state);
diff --git a/modules/consent/www/getconsent.php b/modules/consent/www/getconsent.php
index 3628bd1..3e30817 100644
--- a/modules/consent/www/getconsent.php
+++ b/modules/consent/www/getconsent.php
@@ -31,6 +31,13 @@ if (!array_key_exists('StateId', $_REQUEST)) {
}
$id = $_REQUEST['StateId'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($id);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($id, 'consent:request');
if (array_key_exists('core:SP', $state)) {
diff --git a/modules/consent/www/logout.php b/modules/consent/www/logout.php
index 5590370..1e46429 100644
--- a/modules/consent/www/logout.php
+++ b/modules/consent/www/logout.php
@@ -10,6 +10,13 @@ if (!array_key_exists('StateId', $_GET)) {
throw new SimpleSAML_Error_BadRequest('Missing required StateId query parameter.');
}
$id = (string)$_GET['StateId'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($id);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($id, 'consent:request');
$state['Responder'] = array('sspmod_consent_Logout', 'postLogout');
diff --git a/modules/consent/www/noconsent.php b/modules/consent/www/noconsent.php
index 06e5554..37b5920 100644
--- a/modules/consent/www/noconsent.php
+++ b/modules/consent/www/noconsent.php
@@ -12,6 +12,13 @@ if (!array_key_exists('StateId', $_REQUEST)) {
}
$id = $_REQUEST['StateId'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($id);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($id, 'consent:request');
$resumeFrom = SimpleSAML_Module::getModuleURL(
diff --git a/modules/core/lib/Auth/UserPassBase.php b/modules/core/lib/Auth/UserPassBase.php
index 633a748..c7ff0be 100644
--- a/modules/core/lib/Auth/UserPassBase.php
+++ b/modules/core/lib/Auth/UserPassBase.php
@@ -197,6 +197,12 @@ abstract class sspmod_core_Auth_UserPassBase extends SimpleSAML_Auth_Source {
assert('is_string($username)');
assert('is_string($password)');
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($authStateId);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
/* Here we retrieve the state array we saved in the authenticate-function. */
$state = SimpleSAML_Auth_State::loadState($authStateId, self::STAGEID);
diff --git a/modules/core/lib/Auth/UserPassOrgBase.php b/modules/core/lib/Auth/UserPassOrgBase.php
index f79c3ae..9c7af97 100644
--- a/modules/core/lib/Auth/UserPassOrgBase.php
+++ b/modules/core/lib/Auth/UserPassOrgBase.php
@@ -209,6 +209,12 @@ abstract class sspmod_core_Auth_UserPassOrgBase extends SimpleSAML_Auth_Source {
assert('is_string($password)');
assert('is_string($organization)');
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($authStateId);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
/* Retrieve the authentication state. */
$state = SimpleSAML_Auth_State::loadState($authStateId, self::STAGEID);
@@ -257,6 +263,12 @@ abstract class sspmod_core_Auth_UserPassOrgBase extends SimpleSAML_Auth_Source {
public static function listOrganizations($authStateId) {
assert('is_string($authStateId)');
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($authStateId);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
/* Retrieve the authentication state. */
$state = SimpleSAML_Auth_State::loadState($authStateId, self::STAGEID);
diff --git a/modules/core/www/as_login.php b/modules/core/www/as_login.php
index a30bd1f..09c0720 100644
--- a/modules/core/www/as_login.php
+++ b/modules/core/www/as_login.php
@@ -19,7 +19,7 @@ if (!is_string($_REQUEST['AuthId'])) {
* Setting up the options for the requireAuth() call later..
*/
$options = array(
- 'ReturnTo' => $_REQUEST['ReturnTo'],
+ 'ReturnTo' => SimpleSAML_Utilities::checkURLAllowed($_REQUEST['ReturnTo']),
);
/*
@@ -30,9 +30,7 @@ if (!empty($_REQUEST['saml:idp'])) {
$options['saml:idp'] = $_REQUEST['saml:idp'];
}
-
-
$as = new SimpleSAML_Auth_Simple($_REQUEST['AuthId']);
$as->requireAuth($options);
-SimpleSAML_Utilities::redirectUntrustedURL($_REQUEST['ReturnTo']);
+SimpleSAML_Utilities::redirectTrustedURL($options['ReturnTo']);
diff --git a/modules/core/www/as_logout.php b/modules/core/www/as_logout.php
index 5ae8a39..dad67d2 100644
--- a/modules/core/www/as_logout.php
+++ b/modules/core/www/as_logout.php
@@ -16,4 +16,4 @@ if (!isset($_REQUEST['AuthId']) || !is_string($_REQUEST['AuthId'])) {
}
$as = new SimpleSAML_Auth_Simple($_REQUEST['AuthId']);
-$as->logout($_REQUEST['ReturnTo']);
+$as->logout(SimpleSAML_Utilities::checkURLAllowed($_REQUEST['ReturnTo']));
diff --git a/modules/core/www/bwc_resumeauth.php b/modules/core/www/bwc_resumeauth.php
index 68b2055..df93707 100644
--- a/modules/core/www/bwc_resumeauth.php
+++ b/modules/core/www/bwc_resumeauth.php
@@ -20,7 +20,7 @@ if ($requestcache['ForceAuthn'] && $requestcache['core:prevSession'] === $sessio
}
if (isset($state['ReturnTo'])) {
- SimpleSAML_Utilities::redirectUntrustedURL($state['ReturnTo']);
+ SimpleSAML_Utilities::redirectTrustedURL($state['ReturnTo']);
}
foreach ($session->getAuthState($authority) as $k => $v) {
diff --git a/modules/core/www/cleardiscochoices.php b/modules/core/www/cleardiscochoices.php
index c94e411..afd7299 100644
--- a/modules/core/www/cleardiscochoices.php
+++ b/modules/core/www/cleardiscochoices.php
@@ -26,12 +26,12 @@ foreach($_COOKIE as $cookieName => $value) {
/* Find where we should go now. */
if(array_key_exists('ReturnTo', $_REQUEST)) {
- $returnTo = $_REQUEST['ReturnTo'];
+ $returnTo = SimpleSAML_Utilities::checkURLAllowed($_REQUEST['ReturnTo']);
} else {
/* Return to the front page if no other destination is given. This is the same as the base cookie path. */
$returnTo = $cookiePath;
}
/* Redirect to destination. */
-SimpleSAML_Utilities::redirectUntrustedURL($returnTo);
+SimpleSAML_Utilities::redirectTrustedURL($returnTo);
diff --git a/modules/core/www/idp/logout-iframe-done.php b/modules/core/www/idp/logout-iframe-done.php
index 72a1e26..6253998 100644
--- a/modules/core/www/idp/logout-iframe-done.php
+++ b/modules/core/www/idp/logout-iframe-done.php
@@ -5,6 +5,12 @@ if (!isset($_REQUEST['id'])) {
}
$id = (string)$_REQUEST['id'];
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($id);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($id, 'core:Logout-IFrame');
$idp = SimpleSAML_IdP::getByState($state);
diff --git a/modules/core/www/idp/logout-iframe.php b/modules/core/www/idp/logout-iframe.php
index 1b751e9..53cdcfc 100644
--- a/modules/core/www/idp/logout-iframe.php
+++ b/modules/core/www/idp/logout-iframe.php
@@ -19,6 +19,12 @@ if ($type !== 'embed' && $type !== 'async') {
SimpleSAML_Stats::log('core:idp:logout-iframe:page', array('type' => $type));
}
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($id);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($id, 'core:Logout-IFrame');
$idp = SimpleSAML_IdP::getByState($state);
diff --git a/modules/core/www/idp/resumelogout.php b/modules/core/www/idp/resumelogout.php
index 37c3e60..f93c8e9 100644
--- a/modules/core/www/idp/resumelogout.php
+++ b/modules/core/www/idp/resumelogout.php
@@ -5,6 +5,12 @@ if (!isset($_REQUEST['id'])) {
}
$id = (string)$_REQUEST['id'];
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($id);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($id, 'core:Logout:afterbridge');
$idp = SimpleSAML_IdP::getByState($state);
diff --git a/modules/core/www/login-admin.php b/modules/core/www/login-admin.php
index 83886a1..3e6438f 100644
--- a/modules/core/www/login-admin.php
+++ b/modules/core/www/login-admin.php
@@ -6,9 +6,8 @@
if (!array_key_exists('ReturnTo', $_REQUEST)) {
throw new SimpleSAML_Error_BadRequest('Missing ReturnTo parameter.');
}
-$returnTo = $_REQUEST['ReturnTo'];
SimpleSAML_Utilities::requireAdmin();
-SimpleSAML_Utilities::redirectUntrustedURL($returnTo);
+SimpleSAML_Utilities::redirectUntrustedURL($_REQUEST['ReturnTo']);
diff --git a/modules/core/www/loginuserpass.php b/modules/core/www/loginuserpass.php
index 71da3ae..cda363b 100644
--- a/modules/core/www/loginuserpass.php
+++ b/modules/core/www/loginuserpass.php
@@ -15,6 +15,12 @@ if (!array_key_exists('AuthState', $_REQUEST)) {
}
$authStateId = $_REQUEST['AuthState'];
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($authStateId);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
/* Retrieve the authentication state. */
$state = SimpleSAML_Auth_State::loadState($authStateId, sspmod_core_Auth_UserPassBase::STAGEID);
diff --git a/modules/core/www/loginuserpassorg.php b/modules/core/www/loginuserpassorg.php
index cda773b..abd9a53 100644
--- a/modules/core/www/loginuserpassorg.php
+++ b/modules/core/www/loginuserpassorg.php
@@ -15,6 +15,12 @@ if (!array_key_exists('AuthState', $_REQUEST)) {
}
$authStateId = $_REQUEST['AuthState'];
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($authStateId);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
/* Retrieve the authentication state. */
$state = SimpleSAML_Auth_State::loadState($authStateId, sspmod_core_Auth_UserPassOrgBase::STAGEID);
diff --git a/modules/core/www/short_sso_interval.php b/modules/core/www/short_sso_interval.php
index 5a51470..e9e5b15 100644
--- a/modules/core/www/short_sso_interval.php
+++ b/modules/core/www/short_sso_interval.php
@@ -12,6 +12,13 @@ if (!array_key_exists('StateId', $_REQUEST)) {
}
$id = $_REQUEST['StateId'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($id);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($id, 'core:short_sso_interval');
if (array_key_exists('continue', $_REQUEST)) {
diff --git a/modules/discopower/lib/PowerIdPDisco.php b/modules/discopower/lib/PowerIdPDisco.php
index 2245931..10aad00 100644
--- a/modules/discopower/lib/PowerIdPDisco.php
+++ b/modules/discopower/lib/PowerIdPDisco.php
@@ -203,7 +203,7 @@ class sspmod_discopower_PowerIdPDisco extends SimpleSAML_XHTML_IdPDisco {
} else {
$this->log('Choice made [' . $idp . '] (Redirecting the user back. returnIDParam=' . $this->returnIdParam . ')');
- SimpleSAML_Utilities::redirectUntrustedURL($this->returnURL, array($this->returnIdParam => $idp));
+ SimpleSAML_Utilities::redirectTrustedURL($this->returnURL, array($this->returnIdParam => $idp));
}
return;
@@ -211,7 +211,7 @@ class sspmod_discopower_PowerIdPDisco extends SimpleSAML_XHTML_IdPDisco {
if ($this->isPassive) {
$this->log('Choice not made. (Redirecting the user back without answer)');
- SimpleSAML_Utilities::redirectUntrustedURL($this->returnURL);
+ SimpleSAML_Utilities::redirectTrustedURL($this->returnURL);
return;
}
diff --git a/modules/exampleauth/lib/Auth/Source/External.php b/modules/exampleauth/lib/Auth/Source/External.php
index d3b16f0..282c6a4 100644
--- a/modules/exampleauth/lib/Auth/Source/External.php
+++ b/modules/exampleauth/lib/Auth/Source/External.php
@@ -186,6 +186,12 @@ class sspmod_exampleauth_Auth_Source_External extends SimpleSAML_Auth_Source {
}
$stateId = (string)$_REQUEST['State'];
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($stateId);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
/*
* Once again, note the second parameter to the loadState function. This must
* match the string we used in the saveState-call above.
diff --git a/modules/exampleauth/www/authpage.php b/modules/exampleauth/www/authpage.php
index 21a284b..bcd01b8 100644
--- a/modules/exampleauth/www/authpage.php
+++ b/modules/exampleauth/www/authpage.php
@@ -14,7 +14,7 @@ if (!isset($_REQUEST['ReturnTo'])) {
die('Missing ReturnTo parameter.');
}
-$returnTo = $_REQUEST['ReturnTo'];
+$returnTo = SimpleSAML_Utilities::checkURLAllowed($_REQUEST['ReturnTo']);
/*
@@ -31,6 +31,13 @@ if (!preg_match('@State=(.*)@', $returnTo, $matches)) {
die('Invalid ReturnTo URL for this example.');
}
$stateId = urldecode($matches[1]);
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($stateId);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
SimpleSAML_Auth_State::loadState($stateId, 'exampleauth:External');
/*
@@ -87,8 +94,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$_SESSION['mail'] = $user['mail'];
$_SESSION['type'] = $user['type'];
- header('Location: ' . $returnTo);
- exit();
+ SimpleSAML_Utilities::redirectTrustedURL($returnTo);
}
}
diff --git a/modules/exampleauth/www/redirecttest.php b/modules/exampleauth/www/redirecttest.php
index 39a1b54..c6d4fb8 100644
--- a/modules/exampleauth/www/redirecttest.php
+++ b/modules/exampleauth/www/redirecttest.php
@@ -13,6 +13,13 @@ if (!array_key_exists('StateId', $_REQUEST)) {
}
$id = $_REQUEST['StateId'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($id);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($id, 'exampleauth:redirectfilter-test');
$state['Attributes']['RedirectTest2'] = array('OK');
diff --git a/modules/expirycheck/www/about2expire.php b/modules/expirycheck/www/about2expire.php
index c696247..487b3f8 100644
--- a/modules/expirycheck/www/about2expire.php
+++ b/modules/expirycheck/www/about2expire.php
@@ -14,6 +14,13 @@ if (!array_key_exists('StateId', $_REQUEST)) {
}
$id = $_REQUEST['StateId'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($id);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($id, 'expirywarning:about2expire');
diff --git a/modules/expirycheck/www/expired.php b/modules/expirycheck/www/expired.php
index 9b94cad..5ec7b93 100644
--- a/modules/expirycheck/www/expired.php
+++ b/modules/expirycheck/www/expired.php
@@ -14,6 +14,13 @@ if (!array_key_exists('StateId', $_REQUEST)) {
}
$id = $_REQUEST['StateId'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($id);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($id, 'expirywarning:expired');
$globalConfig = SimpleSAML_Configuration::getInstance();
diff --git a/modules/multiauth/www/selectsource.php b/modules/multiauth/www/selectsource.php
index 329a1bf..afa28ed 100644
--- a/modules/multiauth/www/selectsource.php
+++ b/modules/multiauth/www/selectsource.php
@@ -16,6 +16,12 @@ if (!array_key_exists('AuthState', $_REQUEST)) {
}
$authStateId = $_REQUEST['AuthState'];
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($authStateId);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
/* Retrieve the authentication state. */
$state = SimpleSAML_Auth_State::loadState($authStateId, sspmod_multiauth_Auth_Source_MultiAuth::STAGEID);
diff --git a/modules/negotiate/www/backend.php b/modules/negotiate/www/backend.php
index f9d3622..347ce8d 100644
--- a/modules/negotiate/www/backend.php
+++ b/modules/negotiate/www/backend.php
@@ -10,6 +10,13 @@
*/
$authStateId = $_REQUEST['AuthState'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($authStateId);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($authStateId, sspmod_negotiate_Auth_Source_Negotiate::STAGEID);
SimpleSAML_Logger::debug('backend - fallback: '.$state['LogoutState']['negotiate:backend']);
diff --git a/modules/negotiate/www/retry.php b/modules/negotiate/www/retry.php
index 2d12eab..858b836 100644
--- a/modules/negotiate/www/retry.php
+++ b/modules/negotiate/www/retry.php
@@ -10,6 +10,13 @@
*/
$authStateId = $_REQUEST['AuthState'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($authStateId);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($authStateId, sspmod_negotiate_Auth_Source_Negotiate::STAGEID);
$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
diff --git a/modules/oauth/www/authorize.php b/modules/oauth/www/authorize.php
index 9b3e032..583c86e 100644
--- a/modules/oauth/www/authorize.php
+++ b/modules/oauth/www/authorize.php
@@ -56,7 +56,7 @@ try {
if ($url) {
// If authorize() returns a URL, take user there (oauth1.0a)
- SimpleSAML_Utilities::redirectUntrustedURL($url);
+ SimpleSAML_Utilities::redirectTrustedURL($url);
}
else if (isset($_REQUEST['oauth_callback'])) {
// If callback was provided in the request (oauth1.0)
diff --git a/modules/openid/www/consumer.php b/modules/openid/www/consumer.php
index 889fbf5..0f8067c 100644
--- a/modules/openid/www/consumer.php
+++ b/modules/openid/www/consumer.php
@@ -6,6 +6,13 @@ if (!array_key_exists('AuthState', $_REQUEST) || empty($_REQUEST['AuthState']))
}
$authState = $_REQUEST['AuthState'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($authState);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($authState, 'openid:init');
$sourceId = $state['openid:AuthId'];
$authSource = SimpleSAML_Auth_Source::getById($sourceId);
diff --git a/modules/openid/www/linkback.php b/modules/openid/www/linkback.php
index 180f9e1..6108ca7 100644
--- a/modules/openid/www/linkback.php
+++ b/modules/openid/www/linkback.php
@@ -6,6 +6,13 @@ if (!array_key_exists('AuthState', $_REQUEST) || empty($_REQUEST['AuthState']))
}
$authState = $_REQUEST['AuthState'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($authState);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($authState, 'openid:auth');
$sourceId = $state['openid:AuthId'];
$authSource = SimpleSAML_Auth_Source::getById($sourceId);
diff --git a/modules/openidProvider/lib/Server.php b/modules/openidProvider/lib/Server.php
index f0596d1..1382cd8 100644
--- a/modules/openidProvider/lib/Server.php
+++ b/modules/openidProvider/lib/Server.php
@@ -329,6 +329,12 @@ class sspmod_openidProvider_Server {
public function loadState($stateId) {
assert('is_string($stateId)');
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($stateId);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
return SimpleSAML_Auth_State::loadState($stateId, 'openidProvider:resumeState');
}
diff --git a/modules/papi/lib/Auth/Source/PAPI.php b/modules/papi/lib/Auth/Source/PAPI.php
index ead66c8..c074093 100644
--- a/modules/papi/lib/Auth/Source/PAPI.php
+++ b/modules/papi/lib/Auth/Source/PAPI.php
@@ -115,6 +115,13 @@ class sspmod_papi_Auth_Source_PAPI extends SimpleSAML_Auth_Source {
if (isset($_REQUEST['SSPStateID'])) {
// yes! restore original request
$this->_stateId = (string)$_REQUEST['SSPStateID'];
+
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($this->_stateId);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
$state = SimpleSAML_Auth_State::loadState($this->_stateId, self::STAGE_INIT);
} else if (!$this->_poa->isAuthenticated()) {
// no! we have to save the request
@@ -161,6 +168,13 @@ class sspmod_papi_Auth_Source_PAPI extends SimpleSAML_Auth_Source {
$this->_poa->logout(true);
} else if (isset($_REQUEST['SSPStateID'])) {
$this->_stateId = (string)$_REQUEST['SSPStateID'];
+
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($this->_stateId);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
$state = SimpleSAML_Auth_State::loadState($this->_stateId, self::STAGE_INIT);
} else {
return;
diff --git a/modules/preprodwarning/www/showwarning.php b/modules/preprodwarning/www/showwarning.php
index d8db645..2c50860 100644
--- a/modules/preprodwarning/www/showwarning.php
+++ b/modules/preprodwarning/www/showwarning.php
@@ -15,6 +15,13 @@ if (!array_key_exists('StateId', $_REQUEST)) {
}
$id = $_REQUEST['StateId'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($id);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
$state = SimpleSAML_Auth_State::loadState($id, 'warning:request');
diff --git a/modules/saml/www/sp/discoresp.php b/modules/saml/www/sp/discoresp.php
index 6d9af38..1479f8a 100644
--- a/modules/saml/www/sp/discoresp.php
+++ b/modules/saml/www/sp/discoresp.php
@@ -12,7 +12,15 @@ if (!array_key_exists('idpentityid', $_REQUEST)) {
throw new SimpleSAML_Error_BadRequest('Missing idpentityid to discovery service response handler');
}
-$state = SimpleSAML_Auth_State::loadState($_REQUEST['AuthID'], 'saml:sp:sso');
+$stateID = $_REQUEST['AuthID'];
+
+// sanitize the input
+$restartURL = SimpleSAML_Utilities::getURLFromStateID($stateID);
+if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+}
+
+$state = SimpleSAML_Auth_State::loadState($stateID, 'saml:sp:sso');
/* Find authentication source. */
assert('array_key_exists("saml:sp:AuthId", $state)');
diff --git a/modules/saml/www/sp/saml1-acs.php b/modules/saml/www/sp/saml1-acs.php
index 28ba711..d9a594c 100644
--- a/modules/saml/www/sp/saml1-acs.php
+++ b/modules/saml/www/sp/saml1-acs.php
@@ -19,17 +19,25 @@ $source = SimpleSAML_Auth_Source::getById($sourceId, 'sspmod_saml_Auth_Source_SP
SimpleSAML_Logger::debug('Received SAML1 response');
-
$target = (string)$_REQUEST['TARGET'];
+
if (preg_match('@^https?://@i', $target)) {
/* Unsolicited response. */
$state = array(
'saml:sp:isUnsolicited' => TRUE,
'saml:sp:AuthId' => $sourceId,
- 'saml:sp:RelayState' => $target,
+ 'saml:sp:RelayState' => SimpleSAML_Utilities::checkURLAllowed($target),
);
} else {
- $state = SimpleSAML_Auth_State::loadState($_REQUEST['TARGET'], 'saml:sp:sso');
+ $stateID = $_REQUEST['TARGET'];
+
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($stateID);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
+ $state = SimpleSAML_Auth_State::loadState($stateID, 'saml:sp:sso');
/* Check that the authentication source is correct. */
assert('array_key_exists("saml:sp:AuthId", $state)');
@@ -80,4 +88,4 @@ $state['LogoutState'] = $logoutState;
$source->handleResponse($state, $responseIssuer, $attributes);
assert('FALSE');
-?> \ No newline at end of file
+?>
diff --git a/modules/saml/www/sp/saml2-acs.php b/modules/saml/www/sp/saml2-acs.php
index a3c8200..09723b6 100644
--- a/modules/saml/www/sp/saml2-acs.php
+++ b/modules/saml/www/sp/saml2-acs.php
@@ -52,6 +52,13 @@ $idpMetadata = array();
$stateId = $response->getInResponseTo();
if (!empty($stateId)) {
+
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($stateId);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
/* This is a response to a request we sent earlier. */
$state = SimpleSAML_Auth_State::loadState($stateId, 'saml:sp:sso');
@@ -75,7 +82,7 @@ if (!empty($stateId)) {
$state = array(
'saml:sp:isUnsolicited' => TRUE,
'saml:sp:AuthId' => $sourceId,
- 'saml:sp:RelayState' => $response->getRelayState(),
+ 'saml:sp:RelayState' => SimpleSAML_Utilities::checkURLAllowed($response->getRelayState()),
);
}
diff --git a/modules/saml/www/sp/saml2-logout.php b/modules/saml/www/sp/saml2-logout.php
index d2b26b0..5d36024 100644
--- a/modules/saml/www/sp/saml2-logout.php
+++ b/modules/saml/www/sp/saml2-logout.php
@@ -54,6 +54,12 @@ if ($message instanceof SAML2_LogoutResponse) {
SimpleSAML_Logger::warning('Unsuccessful logout. Status was: ' . sspmod_saml_Message::getResponseError($message));
}
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($relayState);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
$state = SimpleSAML_Auth_State::loadState($relayState, 'saml:slosent');
$state['saml:sp:LogoutStatus'] = $message->getStatus();
SimpleSAML_Auth_Source::completeLogout($state);
diff --git a/www/auth/login-admin.php b/www/auth/login-admin.php
index 42ac0ec..597b353 100644
--- a/www/auth/login-admin.php
+++ b/www/auth/login-admin.php
@@ -20,7 +20,7 @@ if (!array_key_exists('RelayState', $_REQUEST)) {
throw new SimpleSAML_Error_Error('NORELAYSTATE');
}
-$relaystate = $_REQUEST['RelayState'];
+$relaystate = SimpleSAML_Utilities::checkURLAllowed($_REQUEST['RelayState']);
$correctpassword = $config->getString('auth.adminpassword', '123');
@@ -59,7 +59,7 @@ if (isset($_POST['password'])) {
else
SimpleSAML_Logger::stats('AUTH-login-admin OK');
- SimpleSAML_Utilities::redirectUntrustedURL($relaystate);
+ SimpleSAML_Utilities::redirectTrustedURL($relaystate);
exit(0);
} else {
SimpleSAML_Logger::stats('AUTH-login-admin Failed');
@@ -82,6 +82,3 @@ if (isset($error)) {
}
$t->show();
-
-
-?>
diff --git a/www/auth/login-cas-ldap.php b/www/auth/login-cas-ldap.php
index 2ba907a..281488d 100644
--- a/www/auth/login-cas-ldap.php
+++ b/www/auth/login-cas-ldap.php
@@ -30,8 +30,6 @@ try {
$casconfig = $casldapconfig[$idpentityid]['cas'];
$ldapconfig = $casldapconfig[$idpentityid]['ldap'];
-
-
} catch (Exception $exception) {
throw new SimpleSAML_Error_Error('METADATA', $exception);
}
@@ -44,8 +42,6 @@ if (!array_key_exists('RelayState', $_REQUEST)) {
throw new SimpleSAML_Error_Error('NORELAYSTATE');
}
-
-
function casValidate($cas) {
$service = SimpleSAML_Utilities::selfURL();
@@ -110,12 +106,7 @@ function casValidate($cas) {
}
}
-
-
try {
-
- $relaystate = $_REQUEST['RelayState'];
-
list($username, $casattributes) = casValidate($casconfig);
SimpleSAML_Logger::info('AUTH - cas-ldap: '. $username . ' authenticated by ' . $casconfig['validate']);
@@ -132,11 +123,9 @@ try {
$session->setNameID(array(
'value' => SimpleSAML_Utilities::generateID(),
'Format' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'));
- SimpleSAML_Utilities::redirectUntrustedURL($relaystate);
+
+ SimpleSAML_Utilities::redirectUntrustedURL($_REQUEST['RelayState']);
} catch(Exception $exception) {
throw new SimpleSAML_Error_Error('CASERROR', $exception);
}
-
-
-?> \ No newline at end of file
diff --git a/www/auth/login-ldapmulti.php b/www/auth/login-ldapmulti.php
index aab198a..169800b 100644
--- a/www/auth/login-ldapmulti.php
+++ b/www/auth/login-ldapmulti.php
@@ -10,7 +10,6 @@ $session = SimpleSAML_Session::getInstance();
$ldapconfigfile = $config->getBaseDir() . 'config/ldapmulti.php';
require_once($ldapconfigfile);
-
SimpleSAML_Logger::info('AUTH - ldap-multi: Accessing auth endpoint login-ldapmulti');
$error = null;
@@ -23,6 +22,8 @@ if (!array_key_exists('RelayState', $_REQUEST)) {
throw new SimpleSAML_Error_Error('NORELAYSTATE');
}
+$relaystate = SimpleSAML_Utilities::checkURLAllowed($_REQUEST['RelayState']);
+
if (isset($_POST['username'])) {
try {
@@ -50,8 +51,7 @@ if (isset($_POST['username'])) {
$attributes = $ldap->getAttributes($dn, $ldapconfig['attributes']);
SimpleSAML_Logger::info('AUTH - ldap-multi: '. $_POST['username'] . ' successfully authenticated');
-
-
+
$session->doLogin('login-ldapmulti');
$session->setAttributes($attributes);
@@ -64,19 +64,16 @@ if (isset($_POST['username'])) {
* Also log a specific attribute as set in the config: statistics.authlogattr
*/
$authlogattr = $config->getValue('statistics.authlogattr', null);
- if ($authlogattr && array_key_exists($authlogattr, $attributes))
+ if ($authlogattr && array_key_exists($authlogattr, $attributes)) {
SimpleSAML_Logger::stats('AUTH-login-ldapmulti OK ' . $attributes[$authlogattr][0]);
- else
+ } else {
SimpleSAML_Logger::stats('AUTH-login-ldapmulti OK');
-
-
- $returnto = $_REQUEST['RelayState'];
- SimpleSAML_Utilities::redirectUntrustedURL($returnto);
+ }
+
+ SimpleSAML_Utilities::redirectTrustedURL($relaystate);
} catch (Exception $e) {
-
$error = $e->getMessage();
-
}
}
@@ -84,7 +81,7 @@ if (isset($_POST['username'])) {
$t = new SimpleSAML_XHTML_Template($config, 'login-ldapmulti.php', 'login');
$t->data['header'] = 'simpleSAMLphp: Enter username and password';
-$t->data['relaystate'] = $_REQUEST['RelayState'];
+$t->data['relaystate'] = $relaystate;
$t->data['ldapconfig'] = $ldapmulti;
$t->data['org'] = $_REQUEST['org'];
$t->data['error'] = $error;
diff --git a/www/auth/login-radius.php b/www/auth/login-radius.php
index b95c7ae..5a80f49 100644
--- a/www/auth/login-radius.php
+++ b/www/auth/login-radius.php
@@ -19,6 +19,8 @@ if (!array_key_exists('RelayState', $_REQUEST)) {
throw new SimpleSAML_Error_Error('NORELAYSTATE');
}
+$relaystate = SimpleSAML_Utilities::checkURLAllowed($_REQUEST['RelayState']);
+
if (isset($_POST['username'])) {
@@ -97,21 +99,18 @@ if (isset($_POST['username'])) {
'value' => SimpleSAML_Utilities::generateID(),
'Format' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'));
-
/**
* Create a statistics log entry for every successfull login attempt.
* Also log a specific attribute as set in the config: statistics.authlogattr
*/
$authlogattr = $config->getValue('statistics.authlogattr', null);
- if ($authlogattr && array_key_exists($authlogattr, $attributes))
+ if ($authlogattr && array_key_exists($authlogattr, $attributes)) {
SimpleSAML_Logger::stats('AUTH-login-radius OK ' . $attributes[$authlogattr][0]);
- else
+ } else {
SimpleSAML_Logger::stats('AUTH-login-radius OK');
+ }
-
- $returnto = $_REQUEST['RelayState'];
- SimpleSAML_Utilities::redirectUntrustedURL($returnto);
-
+ SimpleSAML_Utilities::redirectTrustedURL($relaystate);
case RADIUS_ACCESS_REJECT:
@@ -125,13 +124,10 @@ if (isset($_POST['username'])) {
default:
SimpleSAML_Logger::critical('AUTH -radius: General radius error: ' . radius_strerror($radius));
throw new Exception('Error during radius authentication: ' . radius_strerror($radius));
-
}
} catch (Exception $e) {
-
$error = $e->getMessage();
-
}
}
@@ -139,13 +135,10 @@ if (isset($_POST['username'])) {
$t = new SimpleSAML_XHTML_Template($config, 'login.php', 'login');
$t->data['header'] = 'simpleSAMLphp: Enter username and password';
-$t->data['relaystate'] = $_REQUEST['RelayState'];
+$t->data['relaystate'] = $relaystate;
$t->data['error'] = $error;
if (isset($error)) {
$t->data['username'] = $_POST['username'];
}
$t->show();
-
-
-?>
diff --git a/www/auth/login-tlsclient.php b/www/auth/login-tlsclient.php
index 42e2678..0fb6e93 100644
--- a/www/auth/login-tlsclient.php
+++ b/www/auth/login-tlsclient.php
@@ -23,9 +23,6 @@ if (!array_key_exists('RelayState', $_REQUEST)) {
throw new SimpleSAML_Error_Error('NORELAYSTATE');
}
-$relaystate = $_REQUEST['RelayState'];
-
-
try {
$attributes = array();
@@ -55,21 +52,21 @@ try {
$session->setNameID(array(
'value' => SimpleSAML_Utilities::generateID(),
- 'Format' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'));
+ 'Format' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient')
+ );
/**
* Create a statistics log entry for every successfull login attempt.
* Also log a specific attribute as set in the config: statistics.authlogattr
*/
$authlogattr = $config->getValue('statistics.authlogattr', null);
- if ($authlogattr && array_key_exists($authlogattr, $attributes))
+ if ($authlogattr && array_key_exists($authlogattr, $attributes)) {
SimpleSAML_Logger::stats('AUTH-tlsclient OK ' . $attributes[$authlogattr][0]);
- else
+ } else {
SimpleSAML_Logger::stats('AUTH-tlsclient OK');
-
+ }
- $returnto = $_REQUEST['RelayState'];
- SimpleSAML_Utilities::redirectUntrustedURL($returnto);
+ SimpleSAML_Utilities::redirectUntrustedURL($_REQUEST['RelayState']);
} catch (Exception $e) {
diff --git a/www/auth/login-wayf-ldap.php b/www/auth/login-wayf-ldap.php
index 73d5f57..9c8c25e 100644
--- a/www/auth/login-wayf-ldap.php
+++ b/www/auth/login-wayf-ldap.php
@@ -42,7 +42,7 @@ if (!array_key_exists('RelayState', $_REQUEST)) {
throw new SimpleSAML_Error_Error('NORELAYSTATE');
}
-$relaystate = $_REQUEST['RelayState'];
+$relaystate = SimpleSAML_Utilities::checkURLAllowed($_REQUEST['RelayState']);
if ($username = $_POST['username']) {
try {
@@ -59,7 +59,7 @@ if ($username = $_POST['username']) {
$session->setNameID(array(
'value' => SimpleSAML_Utilities::generateID(),
'Format' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'));
- SimpleSAML_Utilities::redirectUntrustedURL($relaystate);
+ SimpleSAML_Utilities::redirectTrustedURL($relaystate);
}
} catch(Exception $e) {
throw new SimpleSAML_Error_Error('LDAPERROR', $e);
diff --git a/www/saml2/idp/SingleLogoutService.php b/www/saml2/idp/SingleLogoutService.php
index 618068c..45a1012 100644
--- a/www/saml2/idp/SingleLogoutService.php
+++ b/www/saml2/idp/SingleLogoutService.php
@@ -18,7 +18,7 @@ $idpEntityId = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted');
$idp = SimpleSAML_IdP::getById('saml2:' . $idpEntityId);
if (isset($_REQUEST['ReturnTo'])) {
- $idp->doLogoutRedirect((string)$_REQUEST['ReturnTo']);
+ $idp->doLogoutRedirect(SimpleSAML_Utilities::checkURLAllowed((string)$_REQUEST['ReturnTo']));
} else {
sspmod_saml_IdP_SAML2::receiveLogoutMessage($idp);
}
diff --git a/www/saml2/idp/idpInitSingleLogoutServiceiFrame.php b/www/saml2/idp/idpInitSingleLogoutServiceiFrame.php
index 24f89b0..9772659 100644
--- a/www/saml2/idp/idpInitSingleLogoutServiceiFrame.php
+++ b/www/saml2/idp/idpInitSingleLogoutServiceiFrame.php
@@ -16,5 +16,5 @@ if (!isset($_REQUEST['RelayState'])) {
throw new SimpleSAML_Error_BadRequest('Missing required RelayState parameter.');
}
-$idp->doLogoutRedirect((string)$_REQUEST['RelayState']);
+$idp->doLogoutRedirect(SimpleSAML_Utilities::checkURLAllowed((string)$_REQUEST['RelayState']));
assert('FALSE');
diff --git a/www/saml2/idp/initSLO.php b/www/saml2/idp/initSLO.php
index d6b23ad..87191b7 100644
--- a/www/saml2/idp/initSLO.php
+++ b/www/saml2/idp/initSLO.php
@@ -11,6 +11,5 @@ if (!isset($_GET['RelayState'])) {
throw new SimpleSAML_Error_Error('NORELAYSTATE');
}
-$returnTo = (string)$_GET['RelayState'];
-$idp->doLogoutRedirect($returnTo);
+$idp->doLogoutRedirect(SimpleSAML_Utilities::checkURLAllowed((string)$_GET['RelayState']));
assert('FALSE'); \ No newline at end of file
diff --git a/www/saml2/sp/AssertionConsumerService.php b/www/saml2/sp/AssertionConsumerService.php
index e024489..c7dc96f 100644
--- a/www/saml2/sp/AssertionConsumerService.php
+++ b/www/saml2/sp/AssertionConsumerService.php
@@ -47,7 +47,7 @@ function finishLogin($authProcState) {
global $session;
$session->doLogin('saml2', $authData);
- SimpleSAML_Utilities::redirectUntrustedURL($authProcState['core:saml20-sp:TargetURL']);
+ SimpleSAML_Utilities::redirectTrustedURL($authProcState['core:saml20-sp:TargetURL']);
}
SimpleSAML_Logger::info('SAML2.0 - SP.AssertionConsumerService: Accessing SAML 2.0 SP endpoint AssertionConsumerService');
@@ -59,6 +59,13 @@ if (array_key_exists(SimpleSAML_Auth_ProcessingChain::AUTHPARAM, $_REQUEST)) {
/* We have returned from the authentication processing filters. */
$authProcId = $_REQUEST[SimpleSAML_Auth_ProcessingChain::AUTHPARAM];
+
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($authProcId);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
$authProcState = SimpleSAML_Auth_ProcessingChain::fetchProcessedState($authProcId);
finishLogin($authProcState);
}
@@ -93,7 +100,7 @@ try {
if($info === NULL) {
/* Fall back to RelayState. */
$info = array();
- $info['RelayState'] = $response->getRelayState();
+ $info['RelayState'] = SimpleSAML_Utilities::checkURLAllowed($response->getRelayState());
if(empty($info['RelayState'])) {
$info['RelayState'] = $spMetadata->getString('RelayState', NULL);
}
diff --git a/www/saml2/sp/SingleLogoutService.php b/www/saml2/sp/SingleLogoutService.php
index 0bd8c73..cf9f94c 100644
--- a/www/saml2/sp/SingleLogoutService.php
+++ b/www/saml2/sp/SingleLogoutService.php
@@ -83,12 +83,14 @@ if ($message instanceof SAML2_LogoutRequest) {
$id = $message->getInResponseTo();
}
+ // 'spLogoutReturnTo' is checked before storing it in the
+ // session, so we trust it here.
$returnTo = $session->getData('spLogoutReturnTo', $id);
if (empty($returnTo)) {
throw new SimpleSAML_Error_Error('LOGOUTINFOLOST');
}
- SimpleSAML_Utilities::redirectUntrustedURL($returnTo);
+ SimpleSAML_Utilities::redirectTrustedURL($returnTo);
} else {
throw new SimpleSAML_Error_Error('SLOSERVICEPARAMS');
diff --git a/www/saml2/sp/initSLO.php b/www/saml2/sp/initSLO.php
index 8402a36..85c13bb 100644
--- a/www/saml2/sp/initSLO.php
+++ b/www/saml2/sp/initSLO.php
@@ -13,7 +13,7 @@ if (!$config->getBoolean('enable.saml20-sp', TRUE))
if (isset($_REQUEST['RelayState'])) {
- $returnTo = $_REQUEST['RelayState'];
+ $returnTo = SimpleSAML_Utilities::checkURLAllowed($_REQUEST['RelayState']);
} else {
throw new SimpleSAML_Error_Error('NORELAYSTATE');
}
@@ -25,7 +25,7 @@ try {
$idpEntityId = $session->getAuthData('saml2', 'saml:sp:IdP');
if ($idpEntityId === NULL) {
SimpleSAML_Logger::info('SAML2.0 - SP.initSLO: User not authenticated with an IdP.');
- SimpleSAML_Utilities::redirectUntrustedURL($returnTo);
+ SimpleSAML_Utilities::redirectTrustedURL($returnTo);
}
$idpMetadata = $metadata->getMetaDataConfig($idpEntityId, 'saml20-idp-remote');
$SLOendpoint = $idpMetadata->getEndpointPrioritizedByBinding('SingleLogoutService', array(
@@ -34,8 +34,8 @@ try {
NULL);
if ($SLOendpoint === NULL) {
$session->doLogout('saml2');
- SimpleSAML_Logger::info('SAML2.0 - SP.initSLO: No supported SingleLogoutService endpoint in IdP.');
- SimpleSAML_Utilities::redirectUntrustedURL($returnTo);
+ SimpleSAML_Logger::info('SAML2.0 - SP.initSLO: No SingleLogoutService endpoint supported in the IdP.');
+ SimpleSAML_Utilities::redirectTrustedURL($returnTo);
}
$spEntityId = isset($_GET['spentityid']) ? $_GET['spentityid'] : $metadata->getMetaDataCurrentEntityID();
diff --git a/www/saml2/sp/initSSO.php b/www/saml2/sp/initSSO.php
index a9ee60f..c6d1780 100644
--- a/www/saml2/sp/initSSO.php
+++ b/www/saml2/sp/initSSO.php
@@ -23,6 +23,7 @@ if (!$config->getBoolean('enable.saml20-sp', TRUE))
if (empty($_GET['RelayState'])) {
throw new SimpleSAML_Error_Error('NORELAYSTATE');
}
+$returnTo = SimpleSAML_Utilities::checkURLAllowed($_GET['RelayState']);
$reachableIDPs = array();
@@ -134,7 +135,7 @@ try {
$assertionConsumerServiceURL = $metadata->getGenerated('AssertionConsumerService', 'saml20-sp-hosted');
$ar->setAssertionConsumerServiceURL($assertionConsumerServiceURL);
- $ar->setRelayState($_REQUEST['RelayState']);
+ $ar->setRelayState($returnTo);
if ($isPassive) {
$ar->setIsPassive(TRUE);
@@ -156,9 +157,9 @@ try {
/* Save request information. */
$info = array();
- $info['RelayState'] = $_REQUEST['RelayState'];
+ $info['RelayState'] = $returnTo;
if(array_key_exists('OnError', $_REQUEST)) {
- $info['OnError'] = $_REQUEST['OnError'];
+ $info['OnError'] = SimpleSAML_Utilities::checkURLAllowed($_REQUEST['OnError']);
}
$session->setData('SAML2:SP:SSO:Info', $ar->getId(), $info);
diff --git a/www/shib13/sp/AssertionConsumerService.php b/www/shib13/sp/AssertionConsumerService.php
index f523c28..bc5a436 100644
--- a/www/shib13/sp/AssertionConsumerService.php
+++ b/www/shib13/sp/AssertionConsumerService.php
@@ -47,6 +47,13 @@ if (array_key_exists(SimpleSAML_Auth_ProcessingChain::AUTHPARAM, $_REQUEST)) {
/* We have returned from the authentication processing filters. */
$authProcId = $_REQUEST[SimpleSAML_Auth_ProcessingChain::AUTHPARAM];
+
+ // sanitize the input
+ $restartURL = SimpleSAML_Utilities::getURLFromStateID($authProcId);
+ if (!is_null($restartURL)) {
+ SimpleSAML_Utilities::checkURLAllowed($restartURL);
+ }
+
$authProcState = SimpleSAML_Auth_ProcessingChain::fetchProcessedState($authProcId);
finishLogin($authProcState);
}
@@ -86,7 +93,7 @@ try {
$authProcState = array(
'core:shib13-sp:NameID' => $authnResponse->getNameID(),
'core:shib13-sp:SessionIndex' => $authnResponse->getSessionIndex(),
- 'core:shib13-sp:TargetURL' => $relayState,
+ 'core:shib13-sp:TargetURL' => SimpleSAML_Utilities::checkURLAllowed($relayState),
'ReturnURL' => SimpleSAML_Utilities::selfURLNoQuery(),
'Attributes' => $authnResponse->getAttributes(),
'Destination' => $spmetadata,
diff --git a/www/shib13/sp/initSSO.php b/www/shib13/sp/initSSO.php
index d666b8b..5d40daa 100644
--- a/www/shib13/sp/initSSO.php
+++ b/www/shib13/sp/initSSO.php
@@ -70,7 +70,7 @@ if (!isset($session) || !$session->isValid('shib13') ) {
$ar = new SimpleSAML_XML_Shib13_AuthnRequest();
$ar->setIssuer($spentityid);
if(isset($_GET['RelayState']))
- $ar->setRelayState($_GET['RelayState']);
+ $ar->setRelayState(SimpleSAML_Utilities::checkURLAllowed($_GET['RelayState']));
SimpleSAML_Logger::info('Shib1.3 - SP.initSSO: SP (' . $spentityid . ') is sending AuthNRequest to IdP (' . $idpentityid . ')');
diff --git a/www/wsfed/sp/initSLO.php b/www/wsfed/sp/initSLO.php
index f31ebaa..318bfa2 100644
--- a/www/wsfed/sp/initSLO.php
+++ b/www/wsfed/sp/initSLO.php
@@ -13,7 +13,7 @@ if (!$config->getBoolean('enable.wsfed-sp', false))
if (isset($_REQUEST['RelayState'])) {
- $returnTo = $_REQUEST['RelayState'];
+ $returnTo = SimpleSAML_Utilities::checkURLAllowed($_REQUEST['RelayState']);
} else {
throw new SimpleSAML_Error_Error('NORELAYSTATE');
}
@@ -53,7 +53,7 @@ if (isset($session) ) {
} else {
SimpleSAML_Logger::info('WS-Fed - SP.initSLO: User is already logged out. Go back to relaystate');
- SimpleSAML_Utilities::redirectUntrustedURL($returnTo);
+ SimpleSAML_Utilities::redirectTrustedURL($returnTo);
}
diff --git a/www/wsfed/sp/initSSO.php b/www/wsfed/sp/initSSO.php
index 0e0b861..f3f1ec7 100644
--- a/www/wsfed/sp/initSSO.php
+++ b/www/wsfed/sp/initSSO.php
@@ -46,7 +46,7 @@ if ($idpentityid == null) {
}
try {
- $relaystate = $_GET['RelayState'];
+ $relaystate = SimpleSAML_Utilities::checkURLAllowed($_GET['RelayState']);
$idpmeta = $metadata->getMetaData($idpentityid, 'wsfed-idp-remote');
$spmeta = $metadata->getMetaData($spentityid, 'wsfed-sp-hosted');