\n"; foreach ($IDProviders as $key => $value){ if (isset($value['SSO'])){ $message .= $key."
\n"; } } $message .= "
\n"; printError($message); exit; } } /******************************************************************************/ // Validates the URL format and returns the URL without GET arguments and fragment function verifyAndStripReturnURL($url){ $components = parse_url($url); if (!$components){ return false; } $recomposedURL = $components['scheme'].'://'; if (isset($components['user'])){ $recomposedURL .= $components['user']; if (isset($components['pass'])){ $recomposedURL .= ':'.$components['pass']; } $recomposedURL .= '@'; } if (isset($components['host'])){ $recomposedURL .= $components['host']; } if (isset($components['port'])){ $recomposedURL .= ':'.$components['port']; } if (isset($components['path'])){ $recomposedURL .= $components['path']; } return $recomposedURL; } /******************************************************************************/ // Parses the hostname out of a string and returns it function getHostNameFromURI($string){ // Check if string is URN if (preg_match('/^urn:mace:/i', $string)){ // Return last component of URN return end(explode(':', $string)); } // Apparently we are dealing with something like a URL if (preg_match('/([a-zA-Z0-9\-\.]+\.[a-zA-Z0-9\-\.]{2,6})/', $string, $matches)){ return $matches[0]; } else { return ''; } } /******************************************************************************/ // Parses the domain out of a string and returns it function getDomainNameFromURI($string){ // Check if string is URN if (preg_match('/^urn:mace:/i', $string)){ // Return last component of URN return getTopLevelDomain(end(explode(':', $string))); } // Apparently we are dealing with something like a URL if (preg_match('/[a-zA-Z0-9\-\.]+\.([a-zA-Z0-9\-\.]{2,6})/', $string, $matches)){ return getTopLevelDomain($matches[0]); } else { return ''; } } /******************************************************************************/ // Returns top level domain name from a DNS name function getTopLevelDomain($string){ $hostnameComponents = explode('.', $string); if (count($hostnameComponents) >= 2){ return $hostnameComponents[count($hostnameComponents)-2].'.'.$hostnameComponents[count($hostnameComponents)-1]; } else { return $string; } } /******************************************************************************/ // Parses the reverse dns lookup hostname out of a string and returns domain function getDomainNameFromURIHint(){ global $IDProviders; $clientHostname = gethostbyaddr($_SERVER['REMOTE_ADDR']); if ($clientHostname == $_SERVER['REMOTE_ADDR']){ return '-'; } // Get domain name from client host name $clientDomainName = getDomainNameFromURI($clientHostname); if ($clientDomainName == ''){ return '-'; } // Return first matching IdP entityID that contains the client domain name foreach ($IDProviders as $key => $value){ if ( preg_match('/^http.+'.$clientDomainName.'/', $key) || preg_match('/^urn:.+'.$clientDomainName.'$/', $key)){ return $key; } } // No matching entityID was found return '-'; } /******************************************************************************/ // Get the user's language using the accepted language http header function determineLanguage(){ global $langStrings, $defaultLanguage; // Check if language is enforced by PATH-INFO argument if (isset($_SERVER['PATH_INFO']) && !empty($_SERVER['PATH_INFO'])){ foreach ($langStrings as $lang => $values){ if (preg_match('#/'.$lang.'($|/)#',$_SERVER['PATH_INFO'])){ return $lang; } } } // Check if there is a language GET argument if (isset($_GET['lang'])){ $localeComponents = decomposeLocale($_GET['lang']); if ( $localeComponents !== false && isset($langStrings[$localeComponents[0]]) ){ // Return language return $localeComponents[0]; } } // Return default language if no headers are present otherwise if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){ return $defaultLanguage; } // Inspect Accept-Language header which looks like: // Accept-Language: en,de-ch;q=0.8,fr;q=0.7,fr-ch;q=0.5,en-us;q=0.3,de;q=0.2 $languages = explode( ',', trim($_SERVER['HTTP_ACCEPT_LANGUAGE'])); foreach ($languages as $language){ $languageParts = explode(';', $language); // Only treat art before the prioritization $localeComponents = decomposeLocale($languageParts[0]); if ( $localeComponents !== false && isset($langStrings[$localeComponents[0]]) ){ // Return language return $localeComponents[0]; } } return $defaultLanguage; } /******************************************************************************/ // Splits up a string (relazed) according to // http://www.debian.org/doc/manuals/intro-i18n/ch-locale.en.html#s-localename // and returns an array with the four components function decomposeLocale($locale){ // Locale name syntax: language[_territory][.codeset][@modifier] if (!preg_match('/^([a-zA-Z]{2})([-_][a-zA-Z]{2})?(\.[^@]+)?(@.+)?$/', $locale, $matches)){ return false; } else { // Remove matched string in first position array_shift($matches); return $matches; } } /******************************************************************************/ // Gets a string in the user's language. If no localized version is available // for the string, the English string is returned as default. function getLocalString($string, $encoding = ''){ global $defaultLanguage, $langStrings, $language; $textString = ''; if (isset($langStrings[$language][$string])){ $textString = $langStrings[$language][$string]; } else { $textString = $langStrings[$defaultLanguage][$string]; } // Change encoding if necessary if ($encoding == 'js'){ $textString = convertToJSString($textString); } return $textString; } /******************************************************************************/ // Converts string to a JavaScript format that can be used in JS alert function convertToJSString($string){ return addslashes(html_entity_decode($string, ENT_COMPAT, 'UTF-8')); } /******************************************************************************/ // Checks if entityID hostname of a valid IdP exists in path info function getIdPPathInfoHint(){ global $IDProviders; // Check if path info is available at all if (!isset($_SERVER['PATH_INFO']) || empty($_SERVER['PATH_INFO'])){ return '-'; } // Check for entityID hostnames of all available IdPs foreach ($IDProviders as $key => $value){ // Only check actual IdPs if ( isset($value['SSO']) && !empty($value['SSO']) && $value['Type'] != 'wayf' && checkPathInfo(getHostNameFromURI($key)) ){ return $key; } } // Check for entityID domain names of all available IdPs foreach ($IDProviders as $key => $value){ // Only check actual IdPs if ( isset($value['SSO']) && !empty($value['SSO']) && $value['Type'] != 'wayf' && checkPathInfo(getDomainNameFromURI($key)) ){ return $key; } } return '-'; } /******************************************************************************/ // Parses the Kerbores realm out of the string and returns it function getKerberosRealm($string){ global $IDProviders; if ($string !='' ) { // Find a matching Kerberos realm foreach ($IDProviders as $key => $value){ if ($value['Realm'] == $string) return $key; } } return '-'; } /******************************************************************************/ // Determines the IdP according to the IP address if possible function getIPAdressHint() { global $IDProviders; foreach($IDProviders as $name => $idp) { if (is_array($idp) && array_key_exists("IP", $idp)) { $clientIP = $_SERVER["REMOTE_ADDR"]; foreach( $idp["IP"] as $network ) { if (isIPinCIDRBlock($network, $clientIP)) { return $name; } } } } return '-'; } /******************************************************************************/ // Returns true if IP is in IPv4/IPv6 CIDR range // and returns false otherwise function isIPinCIDRBlock($cidr, $ip) { // Split CIDR notation list ($net, $mask) = split ("/", $cidr); // Convert to binary string value of 1s and 0s $netAsBinary = convertIPtoBinaryForm($net); $ipAsBinary = convertIPtoBinaryForm($ip); // Return false if netmask and ip are using different protocols if (strlen($netAsBinary) != strlen($ipAsBinary)){ return false; } // Compare the first $mask bits for($i = 0; $i < $mask; $i++){ // Return false if bits don't match if ($netAsBinary[$i] != $ipAsBinary[$i]){ return false; } } // If we got here, ip matches net return true; } /******************************************************************************/ // Converts IP in human readable format to binary string function convertIPtoBinaryForm($ip){ // Handle IPv4 IP if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false){ return base_convert(ip2long($ip),10,2); } // Return false if IP is neither IPv4 nor a IPv6 IP if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false){ return false; } // Convert IP to binary structure and return false if this fails if(($ipAsBinStructure = inet_pton($ip)) === false) { return false; } $numOfBytes = 16; $ipAsBinaryString = ''; // Convert IP to binary string while ($numOfBytes > 0){ // Convert current byte to decimal number $currentByte = ord($ipAsBinStructure[$numOfBytes - 1]); // Convert currenty byte to string of 1 and 0 $currentByteAsBinary = sprintf("%08b", $currentByte); // Prepend to rest of IP in binary string $ipAsBinaryString = $currentByteAsBinary.$ipAsBinaryString; // Decrease byte counter $numOfBytes--; } return $ipAsBinaryString; } /******************************************************************************/ // Returns true if URL could be verified or if no check is necessary, false otherwise function verifyReturnURL($entityID, $returnURL) { global $SProviders, $useACURLsForReturnParamCheck; // If SP has a , check return param if (isset($SProviders[$entityID]['DSURL'])){ return in_array($returnURL, $SProviders[$entityID]['DSURL']); } // If fall back check is enabled, check return param if (isset($useACURLsForReturnParamCheck) && $useACURLsForReturnParamCheck){ // Return true if no assertion consumer URL is defined to check against // Should never happend if (!isset($SProviders[$entityID]['ACURL'])){ return false; } $returnURLHostName = getHostNameFromURI($returnURL); foreach($SProviders[$entityID]['ACURL'] as $ACURL){ if (getHostNameFromURI($ACURL) == $returnURLHostName){ return true; } } // We haven't found a matchin assertion consumer url so we return false return false; } // SP has no and $useACURLsForReturnParamCheck // is disabled, so we don't check anything return true; } /******************************************************************************/ // Returns a reasonable value for returnIDParam function getReturnIDParam() { if (isset($_GET['returnIDParam']) && !empty($_GET['returnIDParam'])){ return $_GET['returnIDParam']; } else { return 'entityID'; } } /******************************************************************************/ // Returns true if valid Shibboleth 1.x request or Directory Service request function isValidShibRequest(){ return (isValidShib1Request() || isValidDSRequest()); } /******************************************************************************/ // Returns true if valid Shibboleth request function isValidShib1Request(){ if (isset($_GET['shire']) && isset($_GET['target'])){ return true; } else { return false; } } /******************************************************************************/ // Returns true if valid Directory Service request function isValidDSRequest(){ if (isset($_GET['entityID']) && isset($_GET['return'])){ return true; } else { return false; } } /******************************************************************************/ // Returns true if valid Directory Service request function logAccessEntry($protocol, $type, $sp, $idp){ global $WAYFLogFile, $useLogging; if (!$useLogging){ return; } // Let's make sure the file exists and is writable first. if (is_writable($WAYFLogFile)) { // Create log entry $entry = date('Y-m-d H:i:s').' '.$_SERVER['REMOTE_ADDR'].' '.$protocol.' '.$type.' '.$idp.' '.$sp."\n"; // We are opening $filename in append mode. // The file pointer is at the bottom of the file hence // that's where $somecontent will go when we fwrite() it. if (!$handle = fopen($WAYFLogFile, 'a')) { return; } // Try getting lock while (!flock($handle, LOCK_EX)){ usleep(rand(10, 100)); } // Write $somecontent to our opened file. fwrite($handle, $entry); // Release the lock flock($handle, LOCK_UN); // Close file handle fclose($handle); } } /******************************************************************************/ // Returns true if PATH info indicates a request of type $type function isRequestType($type){ // Make sure the type is checked at end of path info return checkPathInfo($type.'$'); } /******************************************************************************/ // Checks for substrings in Path Info and returns true if match was found function checkPathInfo($needle){ if ( isset($_SERVER['PATH_INFO']) && !empty($_SERVER['PATH_INFO']) && preg_match('|/'.$needle.'|', $_SERVER['PATH_INFO'])){ return true; } else { return false; } } /******************************************************************************/ // Converts to the unified datastructure that the Shibboleth DS will be using function convertToShibDSStructure($IDProviders){ global $federationName; $ShibDSIDProviders = array(); foreach ($IDProviders as $key => $value){ // Skip unknown and category entries if( !isset($value['Type']) || $value['Type'] == 'category' || $value['Type'] == 'wayf' ){ continue; } // Init and fill IdP data $identityProvider = array(); $identityProvider['entityID'] = $key; $identityProvider['DisplayNames'][] = array('lang' => 'en', 'value' => $value['Name']); // Add DisplayNames in other languages foreach($value as $lang => $name){ if( $lang == 'Name' || $lang == 'SSO' || $lang == 'Realm' || $lang == 'Type' || $lang == 'IP' ){ continue; } if (isset($name['Name'])){ $identityProvider['DisplayNames'][] = array('lang' => $lang, 'value' => $name['Name']); } } // Add data to ShibDSIDProviders $ShibDSIDProviders[] = $identityProvider; } return $ShibDSIDProviders; } /******************************************************************************/ // Sorts the IDProviders array function sortIdentityProviders(&$IDProviders){ $sortedIDProviders = Array(); $sortedCategories = Array(); foreach ($IDProviders as $entityId => $IDProvider){ if (!is_array($IDProvider) || !isset($IDProvider['Name'])){ // Remove any entries that are not arrays unset($IDProviders[$entityId]); } elseif ($IDProvider['Type'] == 'category'){ $sortedCategories[$entityId] = $IDProvider; } else { $sortedIDProviders[$entityId] = $IDProvider; } } // Sort categories and IdPs if (count($sortedCategories) > 1){ // Sort using index uasort($sortedCategories, 'sortUsingTypeIndexAndName'); } else { // Sort alphabetically using the key of a category ksort($sortedCategories); } // Add category 'unknown' if not present if (!isset($IDProviders['unknown'])){ $sortedCategories['unknown'] = array ( 'Name' => 'Unknown', 'Type' => 'category', ); } // Sort Identity Providers uasort($sortedIDProviders, 'sortUsingTypeIndexAndName'); $IDProviders = Array(); // Compose array $unknownCategoryIsEmpty = true; while(list($categoryKey, $categoryValue) = each($sortedCategories)){ $IDProviders[$categoryKey] = $categoryValue; // Loop through all IdPs foreach ($sortedIDProviders as $IDProvidersPKey => $IDProvidersValue){ // Add IdP if its type matches the current category if ($IDProvidersValue['Type'] == $categoryKey){ $IDProviders[$IDProvidersPKey] = $IDProvidersValue; unset($sortedIDProviders[$IDProvidersPKey]); } // Add IdP if its type is 'unknown' or if there doesnt exist a category for its type if ($categoryKey == 'unknown' || !isset($sortedCategories[$IDProvidersValue['Type']])){ $IDProviders[$IDProvidersPKey] = $IDProvidersValue; unset($sortedIDProviders[$IDProvidersPKey]); $unknownCategoryIsEmpty = false; } } } // Check if unkown category is needed if ($unknownCategoryIsEmpty || (count($sortedCategories) == 1)){ unset($IDProviders['unknown']); } } /******************************************************************************/ // Sorts two entries according to their Type, Index and (local) Name function sortUsingTypeIndexAndName($a, $b){ global $language; if ($a['Type'] != $b['Type']){ return strcmp($b['Type'], $a['Type']); } elseif (isset($a['Index']) && isset($b['Index']) && $a['Index'] != $b['Index']){ return strcmp($a['Index'], $b['Index']); } else { // Sort using locale names $localNameB = (isset($a[$language]['Name'])) ? $a[$language]['Name'] : $a['Name']; $localNameA = (isset($b[$language]['Name'])) ? $b[$language]['Name'] : $b['Name']; return strcmp($localNameB, $localNameA); } } ?>