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