32 $session_id =
$session->getSessionId();
33 if (is_null($session_id)) {
35 throw new \SimpleSAML_Error_Exception(
'Cannot save POST data to a transient session.');
42 return preg_replace(
'#^https:#',
'http:',
$url);
56 if (array_key_exists(
'HTTP_HOST',
$_SERVER)) {
58 } elseif (array_key_exists(
'SERVER_NAME',
$_SERVER)) {
66 $decomposed = explode(
":",
$current);
67 $port = array_pop($decomposed);
68 if (!is_numeric($port)) {
69 array_push($decomposed, $port);
71 $current = implode($decomposed,
":");
86 if (!array_key_exists(
'HTTPS',
$_SERVER)) {
112 if (self::getServerHTTPS()) {
113 if ($port !==
'443') {
117 if ($port !==
'80') {
150 if (!is_string(
$url) || empty(
$url) || !is_array($parameters)) {
151 throw new \InvalidArgumentException(
'Invalid input parameters.');
153 if (!empty($parameters)) {
154 $url = self::addURLParameters(
$url, $parameters);
161 if (
$_SERVER[
'SERVER_PROTOCOL'] ===
'HTTP/1.1' &&
162 $_SERVER[
'REQUEST_METHOD'] ===
'POST' 169 if (strlen(
$url) > 2048) {
173 if (!headers_sent()) {
178 header(
'Pragma: no-cache');
179 header(
'Cache-Control: no-cache, no-store, must-revalidate');
183 echo
'<?xml version="1.0" encoding="UTF-8"?>'.
"\n";
184 echo
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"';
185 echo
' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'.
"\n";
186 echo
'<html xmlns="http://www.w3.org/1999/xhtml">'.
"\n";
188 echo
' <meta http-equiv="content-type" content="text/html; charset=utf-8">'.
"\n";
189 echo
' <meta http-equiv="refresh" content="0;URL=\''.htmlspecialchars(
$url).
'\'">'."\n
"; 190 echo " <title>Redirect</title>
\n"; 193 echo " <h1>Redirect</h1>
\n"; 194 echo ' <p>You were redirected to: <a id="redirlink
" href="'.htmlspecialchars($url).'">'; 195 echo htmlspecialchars($url)."</a>
\n"; 196 echo ' <script type="text/javascript
">document.getElementById("redirlink
").focus();</script>'."\n"; 201 // end script execution 218 private static function savePOSTData(\SimpleSAML_Session $session, $destination, $data) 220 // generate a random ID to avoid replay attacks 221 $id = Random::generateID(); 224 'url' => $destination, 227 // save the post data to the session, tied to the random ID 228 $session->setData('core_postdatalink', $id, $postData); 247 public static function addURLParameters($url, $parameters) 249 if (!is_string($url) || !is_array($parameters)) { 250 throw new \InvalidArgumentException('Invalid input parameters.'); 253 $queryStart = strpos($url, '?'); 254 if ($queryStart === false) { 259 $oldQuery = substr($url, $queryStart + 1); 260 if ($oldQuery === false) { 263 $oldQuery = self::parseQueryString($oldQuery); 265 $url = substr($url, 0, $queryStart + 1); 269 $query = array_merge($oldQuery, $parameters); 270 $url .= http_build_query($query, '', '&'); 287 public static function checkSessionCookie($retryURL = null) 289 if (!is_null($retryURL) && !is_string($retryURL)) { 290 throw new \InvalidArgumentException('Invalid input parameters.'); 293 $session = \SimpleSAML_Session::getSessionFromRequest(); 294 if ($session->hasSessionCookie()) { 298 // we didn't have a session cookie. Redirect to the no-cookie page 300 $url = Module::getModuleURL('core/no_cookie.php'); 301 if ($retryURL !== null) { 302 $url = self::addURLParameters($url, array('retryURL' => $retryURL)); 304 self::redirectTrustedURL($url); 322 public static function checkURLAllowed($url, array $trustedSites = null) 327 $url = self::normalizeURL($url); 329 if (filter_var($url, FILTER_VALIDATE_URL) === false) { 330 throw new \SimpleSAML_Error_Exception('Invalid URL: '.$url); 333 // get the white list of domains 334 if ($trustedSites === null) { 335 $trustedSites = \SimpleSAML_Configuration::getInstance()->getValue('trusted.url.domains', array()); 338 // validates the URL's host is among those allowed 339 if (is_array($trustedSites)) { 340 assert(is_array($trustedSites)); 341 $components = parse_url($url); 342 $hostname = $components['host']; 344 // check for userinfo 345 if ((isset($components['user']) && strpos($components['user'], '\\') !== false) || 346 (isset($components['pass']) && strpos($components['pass'], '\\') !== false) 348 throw new \SimpleSAML_Error_Exception('Invalid URL: '.$url); 351 // allow URLs with standard ports specified (non-standard ports must then be allowed explicitly) 352 if (isset($components['port']) && 353 (($components['scheme'] === 'http' && $components['port'] !== 80) || 354 ($components['scheme'] === 'https' && $components['port'] !== 443)) 356 $hostname = $hostname.':'.$components['port']; 359 $self_host = self::getSelfHostWithNonStandardPort(); 361 $trustedRegex = \SimpleSAML_Configuration::getInstance()->getValue('trusted.url.regex', false); 365 // add self host to the white list 366 $trustedSites[] = preg_quote($self_host); 367 foreach ($trustedSites as $regex) { 368 // Add start and end delimiters. 369 $regex = "@^{$regex}$
@"; 370 if (preg_match($regex, $hostname)) { 376 // add self host to the white list 377 $trustedSites[] = $self_host; 378 $trusted = in_array($hostname, $trustedSites, true); 381 // throw exception due to redirection to untrusted site 383 throw new \SimpleSAML_Error_Exception('URL not allowed: '.$url); 409 public static function fetch($url, $context = array(), $getHeaders = false) 411 if (!is_string($url)) { 412 throw new \InvalidArgumentException('Invalid input parameters.'); 415 $config = \SimpleSAML_Configuration::getInstance(); 417 $proxy = $config->getString('proxy', null); 418 if ($proxy !== null) { 419 if (!isset($context['http']['proxy'])) { 420 $context['http']['proxy'] = $proxy; 422 $proxy_auth = $config->getString('proxy.auth', false); 423 if ($proxy_auth !== false) { 424 $context['http']['header'] = "Proxy-Authorization: Basic
".base64_encode($proxy_auth); 426 if (!isset($context['http']['request_fulluri'])) { 427 $context['http']['request_fulluri'] = true; 430 * If the remote endpoint over HTTPS uses the SNI extension (Server Name Indication RFC 4366), the proxy 431 * could introduce a mismatch between the names in the Host: HTTP header and the SNI_server_name in TLS 432 * negotiation (thanks to Cristiano Valli @ GARR-IDEM to have pointed this problem). 433 * See: https://bugs.php.net/bug.php?id=63519 434 * These controls will force the same value for both fields. 435 * Marco Ferrante (marco@csita.unige.it), Nov 2012 437 if (preg_match('#^https#i', $url) 438 && defined('OPENSSL_TLSEXT_SERVER_NAME') 439 && OPENSSL_TLSEXT_SERVER_NAME 441 // extract the hostname 442 $hostname = parse_url($url, PHP_URL_HOST); 443 if (!empty($hostname)) { 444 $context['ssl'] = array( 445 'SNI_server_name' => $hostname, 446 'SNI_enabled' => true, 449 Logger::warning('Invalid URL format or local URL used through a proxy'); 454 $context = stream_context_create($context); 455 $data = file_get_contents($url, false, $context); 456 if ($data === false) { 457 $error = error_get_last(); 458 throw new \SimpleSAML_Error_Exception('Error fetching '.var_export($url, true).':'. 459 (is_array($error) ? $error['message'] : 'no error available')); 464 if (isset($http_response_header)) { 466 foreach ($http_response_header as $h) { 467 if (preg_match('@^HTTP/1\.[01]\s+\d{3}\s+@', $h)) { 468 $headers = array(); // reset 472 $bits = explode(':', $h, 2); 473 if (count($bits) === 2) { 474 $headers[strtolower($bits[0])] = trim($bits[1]); 478 // no HTTP headers, probably a different protocol, e.g. file 481 return array($data, $headers); 499 public static function getAcceptLanguage() 501 if (!array_key_exists('HTTP_ACCEPT_LANGUAGE', $_SERVER)) { 502 // no Accept-Language header, return an empty set 506 $languages = explode(',', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE'])); 510 foreach ($languages as $l) { 511 $opts = explode(';', $l); 513 $l = trim(array_shift($opts)); // the language is the first element 517 // iterate over all options, and check for the quality option 518 foreach ($opts as $o) { 519 $o = explode('=', $o); 521 // skip option with no value 526 $value = trim($o[1]); 533 // remove the old key to ensure that the element is added to the end 536 // set the quality in the result 539 if (strpos($l, '-')) { 540 // the language includes a region part 542 // extract the language without the region 543 $l = explode('-', $l); 546 // add this language to the result (unless it is defined already) 547 if (!array_key_exists($l, $ret)) { 563 public static function guessBasePath() 565 if (!array_key_exists('REQUEST_URI', $_SERVER) || !array_key_exists('SCRIPT_FILENAME', $_SERVER)) { 568 // get the name of the current script 569 $path = explode('/', $_SERVER['SCRIPT_FILENAME']); 570 $script = array_pop($path); 572 // get the portion of the URI up to the script, i.e.: /simplesaml/some/directory/script.php 573 if (!preg_match('#^/(?:[^/]+/)*'.$script.'#', $_SERVER['REQUEST_URI'], $matches)) { 576 $uri_s = explode('/', $matches[0]); 577 $file_s = explode('/', $_SERVER['SCRIPT_FILENAME']); 579 // compare both arrays from the end, popping elements matching out of them 580 while ($uri_s[count($uri_s) - 1] === $file_s[count($file_s) - 1]) { 584 // we are now left with the minimum part of the URI that does not match anything in the file system, use it 585 return join('/', $uri_s).'/'; 598 public static function getBaseURL() 600 $globalConfig = \SimpleSAML_Configuration::getInstance(); 601 $baseURL = $globalConfig->getString('baseurlpath', 'simplesaml/'); 603 if (preg_match('#^https?://.*/?$#D', $baseURL, $matches)) { 604 // full URL in baseurlpath, override local server values 605 return rtrim($baseURL, '/').'/'; 607 (preg_match('#^/?([^/]?.*/)$#D', $baseURL, $matches)) || 608 (preg_match('#^\*(.*)/$#D', $baseURL, $matches)) || 613 $protocol .= (self::getServerHTTPS()) ? 's' : ''; 616 $hostname = self::getServerHost(); 617 $port = self::getServerPort(); 618 $path = $globalConfig->getBasePath(); 620 return $protocol.$hostname.$port.$path; 623 * Invalid 'baseurlpath'. We cannot recover from this, so throw a critical exception and try to be graceful 624 * with the configuration. Use a guessed base path instead of the one provided. 626 $c = $globalConfig->toArray(); 627 $c['baseurlpath'] = self::guessBasePath(); 628 throw new \SimpleSAML\Error\CriticalConfigurationError( 629 'Invalid value for \'baseurlpath\' in config.php. Valid format is in the form: '. 630 '[(http|https)://(hostname|fqdn)[:port]]/[path/to/simplesaml/]. It must end with a \'/\'.', 647 public static function getFirstPathElement($trailingslash = true) 649 if (preg_match('|^/(.*?)/|', $_SERVER['SCRIPT_NAME'], $matches)) { 650 return ($trailingslash ? '/' : '').$matches[1]; 668 public static function getPOSTRedirectURL($destination, $data) 670 if (!is_string($destination) || !is_array($data)) { 671 throw new \InvalidArgumentException('Invalid input parameters.'); 674 $config = \SimpleSAML_Configuration::getInstance(); 675 $allowed = $config->getBoolean('enable.http_post', false); 677 if ($allowed && preg_match("#^
http:#
", $destination) && self::isHTTPS()) { 678 // we need to post the data to HTTP 679 $url = self::getSecurePOSTRedirectURL($destination, $data); 680 } else { // post the data directly 681 $session = \SimpleSAML_Session::getSessionFromRequest(); 682 $id = self::savePOSTData($session, $destination, $data); 683 $url = Module::getModuleURL('core/postredirect.php', array('RedirId' => $id)); 699 public static function getSelfHost() 701 $decomposed = explode(':', self::getSelfHostWithNonStandardPort()); 702 return array_shift($decomposed); 717 public static function getSelfHostWithNonStandardPort() 719 $url = self::getBaseURL(); 722 $colon = strpos($url, '://'); 724 $length = strcspn($url, '/', $start); 726 return substr($url, $start, $length); 738 public static function getSelfHostWithPath() 740 $baseurl = explode("/
", self::getBaseURL()); 741 $elements = array_slice($baseurl, 3 - count($baseurl), count($baseurl) - 4); 742 $path = implode("/
", $elements); 743 return self::getSelfHostWithNonStandardPort()."/
".$path; 762 public static function getSelfURL() 764 $cfg = \SimpleSAML_Configuration::getInstance(); 765 $baseDir = $cfg->getBaseDir(); 766 $cur_path = realpath($_SERVER['SCRIPT_FILENAME']); 767 // make sure we got a string from realpath() 768 $cur_path = is_string($cur_path) ? $cur_path : ''; 769 // find the path to the current script relative to the www/ directory of SimpleSAMLphp 770 $rel_path = str_replace($baseDir.'www'.DIRECTORY_SEPARATOR, '', $cur_path); 771 // convert that relative path to an HTTP query 772 $url_path = str_replace(DIRECTORY_SEPARATOR, '/', $rel_path); 773 // find where the relative path starts in the current request URI 774 $uri_pos = (!empty($url_path)) ? strpos($_SERVER['REQUEST_URI'], $url_path) : false; 776 if ($cur_path == $rel_path || $uri_pos === false) { 778 * We were accessed from an external script. This can happen in the following cases: 780 * - $_SERVER['SCRIPT_FILENAME'] points to a script that doesn't exist. E.g. functional testing. In this 781 * case, realpath() returns false and str_replace an empty string, so we compare them loosely. 783 * - The URI requested does not belong to a script in the www/ directory of SimpleSAMLphp. In that case, 784 * removing SimpleSAMLphp's base dir from the current path yields the same path, so $cur_path and 785 * $rel_path are equal. 787 * - The request URI does not match the current script. Even if the current script is located in the www/ 788 * directory of SimpleSAMLphp, the URI does not contain its relative path, and $uri_pos is false. 790 * It doesn't matter which one of those cases we have. We just know we can't apply our base URL to the 791 * current URI, so we need to build it back from the PHP environment, unless we have a base URL specified 792 * for this case in the configuration. First, check if that's the case. 796 $appcfg = $cfg->getConfigItem('application', null); 797 $appurl = ($appcfg instanceof \SimpleSAML_Configuration) ? $appcfg->getString('baseURL', '') : ''; 798 if (!empty($appurl)) { 799 $protocol = parse_url($appurl, PHP_URL_SCHEME); 800 $hostname = parse_url($appurl, PHP_URL_HOST); 801 $port = parse_url($appurl, PHP_URL_PORT); 802 $port = !empty($port) ? ':'.$port : ''; 804 } else { // no base URL specified for app, just use the current URL 806 $protocol .= (self::getServerHTTPS()) ? 's' : ''; 807 $hostname = self::getServerHost(); 808 $port = self::getServerPort(); 810 return $protocol.'://'.$hostname.$port.$_SERVER['REQUEST_URI']; 813 return self::getBaseURL().$rel_path.substr($_SERVER['REQUEST_URI'], $uri_pos + strlen($url_path)); 826 public static function getSelfURLHost() 828 $url = self::getSelfURL(); 831 $colon = strpos($url, '://'); 833 $length = strcspn($url, '/', $start) + $start; 834 return substr($url, 0, $length); 846 public static function getSelfURLNoQuery() 848 $url = self::getSelfURL(); 849 $pos = strpos($url, '?'); 853 return substr($url, 0, $pos); 865 public static function isHTTPS() 867 return strpos(self::getSelfURL(), 'https://') === 0; 883 public static function normalizeURL($url) 885 if (!is_string($url)) { 886 throw new \InvalidArgumentException('Invalid input parameters.'); 889 $url = self::resolveURL($url, self::getSelfURL()); 891 // verify that the URL is to a http or https site 892 if (!preg_match('@^https?://@i', $url)) { 893 throw new \InvalidArgumentException('Invalid URL: '.$url); 915 public static function parseQueryString($query_string) 917 if (!is_string($query_string)) { 918 throw new \InvalidArgumentException('Invalid input parameters.'); 922 if (empty($query_string)) { 926 foreach (explode('&', $query_string) as $param) { 927 $param = explode('=', $param); 928 $name = urldecode($param[0]); 929 if (count($param) === 1) { 932 $value = urldecode($param[1]); 934 $res[$name] = $value; 962 public static function redirectTrustedURL($url, $parameters = array()) 964 if (!is_string($url) || !is_array($parameters)) { 965 throw new \InvalidArgumentException('Invalid input parameters.'); 968 $url = self::normalizeURL($url); 969 self::redirect($url, $parameters); 994 public static function redirectUntrustedURL($url, $parameters = array()) 996 if (!is_string($url) || !is_array($parameters)) { 997 throw new \InvalidArgumentException('Invalid input parameters.'); 1000 $url = self::checkURLAllowed($url); 1001 self::redirect($url, $parameters); 1026 public static function resolveURL($url, $base = null) 1028 if ($base === null) { 1029 $base = self::getBaseURL(); 1032 if (!is_string($url) || !is_string($base)) { 1033 throw new \InvalidArgumentException('Invalid input parameters.'); 1036 if (!preg_match('/^((((\w+:)\/\/[^\/]+)(\/[^?#]*))(?:\?[^#]*)?)(?:#.*)?/', $base, $baseParsed)) { 1037 throw new \InvalidArgumentException('Unable to parse base url: '.$base); 1040 $baseDir = dirname($baseParsed[5].'filename'); 1041 $baseScheme = $baseParsed[4]; 1042 $baseHost = $baseParsed[3]; 1043 $basePath = $baseParsed[2]; 1044 $baseQuery = $baseParsed[1]; 1046 if (preg_match('$^\w+:$', $url)) { 1050 if (substr($url, 0, 2) === '//') { 1051 return $baseScheme.$url; 1054 if ($url[0] === '/') { 1055 return $baseHost.$url; 1057 if ($url[0] === '?') { 1058 return $basePath.$url; 1060 if ($url[0] === '#') { 1061 return $baseQuery.$url; 1064 // we have a relative path. Remove query string/fragment and save it as $tail 1065 $queryPos = strpos($url, '?'); 1066 $fragmentPos = strpos($url, '#'); 1067 if ($queryPos !== false || $fragmentPos !== false) { 1068 if ($queryPos === false) { 1069 $tailPos = $fragmentPos; 1070 } elseif ($fragmentPos === false) { 1071 $tailPos = $queryPos; 1072 } elseif ($queryPos < $fragmentPos) { 1073 $tailPos = $queryPos; 1075 $tailPos = $fragmentPos; 1078 $tail = substr($url, $tailPos); 1079 $dir = substr($url, 0, $tailPos); 1085 $dir = System::resolvePath($dir, $baseDir); 1087 return $baseHost.$dir.$tail; 1107 public static function setCookie($name, $value, $params = null, $throw = true) 1109 if (!(is_string($name) && // $name must be a string 1110 (is_string($value) || is_null($value)) && // $value can be a string or null 1111 (is_array($params) || is_null($params)) && // $params can be an array or null 1112 is_bool($throw)) // $throw must be boolean 1114 throw new \InvalidArgumentException('Invalid input parameters.'); 1117 $default_params = array( 1127 if ($params !== null) { 1128 $params = array_merge($default_params, $params); 1130 $params = $default_params; 1133 // Do not set secure cookie if not on HTTPS 1134 if ($params['secure'] && !self::isHTTPS()) { 1136 throw new \SimpleSAML\Error\CannotSetCookie( 1137 'Setting secure cookie on plain HTTP is not allowed.', 1138 \SimpleSAML\Error\CannotSetCookie::SECURE_COOKIE 1141 Logger::warning('Error setting cookie: setting secure cookie on plain HTTP is not allowed.'); 1145 if ($value === null) { 1146 $expire = time() - 365 * 24 * 60 * 60; 1147 } elseif (isset($params['expire'])) { 1148 $expire = $params['expire']; 1149 } elseif ($params['lifetime'] === 0) { 1152 $expire = time() + $params['lifetime']; 1155 if ($params['raw']) { 1156 $success = @setrawcookie( 1166 $success = @setcookie( 1179 throw new \SimpleSAML\Error\CannotSetCookie( 1180 'Headers already sent.', 1181 \SimpleSAML\Error\CannotSetCookie::HEADERS_SENT 1184 Logger::warning('Error setting cookie: headers already sent.'); 1205 public static function submitPOSTData($destination, $data) 1207 if (!is_string($destination) || !is_array($data)) { 1208 throw new \InvalidArgumentException('Invalid input parameters.'); 1211 $config = \SimpleSAML_Configuration::getInstance(); 1212 $allowed = $config->getBoolean('enable.http_post', false); 1214 if ($allowed && preg_match("#^
http:#
", $destination) && self::isHTTPS()) { 1215 // we need to post the data to HTTP 1216 self::redirect(self::getSecurePOSTRedirectURL($destination, $data)); 1219 $p = new \SimpleSAML_XHTML_Template($config, 'post.php'); 1220 $p->data['destination'] = $destination; 1221 $p->data['post'] = $data; static redirect($url, $parameters=array())
This function redirects the user to the specified address.
static getServerHost()
Retrieve Host value from $_SERVER environment variables.
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
static getServerHTTPS()
Retrieve HTTPS status from $_SERVER environment variables.
static aesEncrypt($data)
Encrypt data using AES-256-CBC and the system-wide secret salt as key.
if(!array_key_exists('StateId', $_REQUEST)) $id
if(! $in) print Initializing normalization quick check tables n
static getModuleURL($resource, array $parameters=array())
Get absolute URL to a specified module resource.
static http()
Fetches the global http state from ILIAS.
Add a drawing to the header
Create styles array
The data for the language used.
static getServerPort()
Retrieve the port number from $_SERVER environment variables.
static getSecurePOSTRedirectURL($destination, $data)
Obtain a URL where we can redirect to securely post a form with the given data to a specific destinat...
static getSessionFromRequest()
Retrieves the current session.