From dada996c325cb394a732621393cd3df91cf77776 Mon Sep 17 00:00:00 2001 From: Olav Morken <olav.morken@uninett.no> Date: Mon, 8 Apr 2013 08:44:05 +0000 Subject: [PATCH] Add initial support for limiting redirect to trusted hosts. Thanks to Daniel Tsosie for implementing this! git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3233 44740490-163a-0410-bde0-09ae8108e29a --- config-templates/config.php | 10 +++++++++ lib/SimpleSAML/Auth/Default.php | 2 +- lib/SimpleSAML/Utilities.php | 39 ++++++++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/config-templates/config.php b/config-templates/config.php index a6812d906..fba47fbe1 100644 --- a/config-templates/config.php +++ b/config-templates/config.php @@ -668,4 +668,14 @@ $config = array ( */ 'proxy' => NULL, + /* + * Array of URL's to allow a trusted redirect to. + * + * Set to NULL to disable. + * + * Example: + * 'redirect.trustedsites' => array('sp.example.com', 'othersite.org'), + */ + 'redirect.trustedsites' => NULL, + ); diff --git a/lib/SimpleSAML/Auth/Default.php b/lib/SimpleSAML/Auth/Default.php index 2f22b3fab..de5873c8a 100644 --- a/lib/SimpleSAML/Auth/Default.php +++ b/lib/SimpleSAML/Auth/Default.php @@ -251,7 +251,7 @@ class SimpleSAML_Auth_Default { $session = SimpleSAML_Session::getInstance(); $session->doLogin($authId, self::extractPersistentAuthState($state)); - SimpleSAML_Utilities::redirect($redirectTo); + SimpleSAML_Utilities::redirectUntrustedURL($redirectTo); } } diff --git a/lib/SimpleSAML/Utilities.php b/lib/SimpleSAML/Utilities.php index 6a902e092..e9587ccc5 100644 --- a/lib/SimpleSAML/Utilities.php +++ b/lib/SimpleSAML/Utilities.php @@ -563,14 +563,20 @@ class SimpleSAML_Utilities { * will be urlencoded. If the value is NULL, then the * parameter will be encoded as just the name, without a * value. + * $allowed_redirect_hosts + * Array whitelist of hosts that redirects are allowed for. + * If NULL value, redirect will be allowed to any host. + * Otherwise, $url host must be present in Array for redirect. + * If the host is not present, an exception will be thrown. * * Returns: * This function never returns. */ - public static function redirect($url, $parameters = array()) { + 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) === '/') { @@ -585,6 +591,17 @@ class SimpleSAML_Utilities { throw new SimpleSAML_Error_Exception('Redirect to invalid URL: ' . $url); } + /* Validates that URL host is among those allowed. */ + if ($allowed_redirect_hosts != NULL) { + preg_match('@^https?://([^/]+)@i', $url, $matches); + $hostname = $matches[1]; + + /* Throw exception for redirect to untrusted site */ + if(!in_array($hostname, $allowed_redirect_hosts)) { + throw new SimpleSAML_Error_Exception('Redirect not to allowed redirect host: ' . $url); + } + } + /* Determine which prefix we should put before the first * parameter. */ @@ -667,6 +684,26 @@ class SimpleSAML_Utilities { exit; } + /* + * This function validates untrusted url has hostname against + * config option 'redirect.trustedsites'. + * + * If option not set or hostname present among trusted sites, + * peforms redirect via function redirect above. + * + * If site is not trusted, an exception will be thrown. + * + * See function redirect for details on url, parameters and return. + */ + public static function redirectUntrustedURL($url, $parameters = array()) { + $redirectTrustedSites = SimpleSAML_Configuration::getInstance()->getArray('redirect.trustedsites', NULL); + try { + self::redirect($url, $parameters, $redirectTrustedSites); + } + catch (SimpleSAML_Error_Exception $e) { + throw new SimpleSAML_Error_Exception('Site not in redirect.trusted sites: ' . $url); + } + } /** * This function transposes a two-dimensional array, so that -- GitLab