/** * Attempt to log in using the given username and password. * * On a successful login, this function should return the username as 'uid' attribute, * and merged attributes from the configuration file. * On failure, it should throw an exception. A SimpleSAML_Error_Error('WRONGUSERPASS') * should be thrown in case of a wrong username OR a wrong password, to prevent the * enumeration of usernames. * * @param string $username The username the user wrote. * @param string $password The password the user wrote. * @return array Associative array with the users attributes. */ protected function login($username, $password) { assert('is_string($username)'); assert('is_string($password)'); foreach ($this->users as $userpass) { $matches = explode(':', $userpass, 2); if ($matches[0] == $username) { $crypted = $matches[1]; // This is about the only attribute we can add $attributes = array_merge(array('uid' => array($username)), $this->attributes); // Traditional crypt(3) if (crypt($password, $crypted) == $crypted) { SimpleSAML\Logger::debug('User ' . $username . ' authenticated successfully'); return $attributes; } // Apache's custom MD5 if (APR1_MD5::check($crypted, $password)) { SimpleSAML\Logger::debug('User ' . $username . ' authenticated successfully'); return $attributes; } // SHA1 or plain-text if (SimpleSAML\Utils\Crypto::pwValid($crypted, $password)) { SimpleSAML\Logger::debug('User ' . $username . ' authenticated successfully'); return $attributes; } throw new SimpleSAML_Error_Error('WRONGUSERPASS'); } } throw new SimpleSAML_Error_Error('WRONGUSERPASS'); }
/** * Apply this filter. * * @param array &$request The current request */ public function process(&$request) { assert('is_array($request)'); assert('array_key_exists("Attributes", $request)'); $attributes =& $request['Attributes']; if (!isset($attributes[$this->sourceAttribute])) { return; } // will not overwrite existing attribute if (isset($attributes[$this->targetAttribute])) { return; } $sourceAttrVal = $attributes[$this->sourceAttribute][0]; /* the last position of an @ is usually the beginning of the scope * string */ $scopeIndex = strrpos($sourceAttrVal, '@'); if ($scopeIndex !== FALSE) { $attributes[$this->targetAttribute] = array(); $scope = substr($sourceAttrVal, $scopeIndex + 1); $attributes[$this->targetAttribute][] = $scope; SimpleSAML\Logger::debug('ScopeFromAttribute: Inserted new attribute ' . $this->targetAttribute . ', with scope ' . $scope); } else { SimpleSAML\Logger::warning('ScopeFromAttribute: The configured source attribute ' . $this->sourceAttribute . ' does not have a scope. Did not add attribute ' . $this->targetAttribute . '.'); } }
function driveProcessingChain($idp_metadata, $source, $sp_metadata, $sp_entityid, $attributes, $userid, $hashAttributes = false) { /* * Create a new processing chain */ $pc = new SimpleSAML_Auth_ProcessingChain($idp_metadata, $sp_metadata, 'idp'); /* * Construct the state. * REMEMBER: Do not set Return URL if you are calling processStatePassive */ $authProcState = array('Attributes' => $attributes, 'Destination' => $sp_metadata, 'Source' => $idp_metadata, 'isPassive' => true); /* * Call processStatePAssive. * We are not interested in any user interaction, only modifications to the attributes */ $pc->processStatePassive($authProcState); $attributes = $authProcState['Attributes']; /* * Generate identifiers and hashes */ $destination = $sp_metadata['metadata-set'] . '|' . $sp_entityid; $targeted_id = sspmod_consent_Auth_Process_Consent::getTargetedID($userid, $source, $destination); $attribute_hash = sspmod_consent_Auth_Process_Consent::getAttributeHash($attributes, $hashAttributes); SimpleSAML\Logger::info('consentAdmin: user: '******'consentAdmin: target: ' . $targeted_id); SimpleSAML\Logger::info('consentAdmin: attribute: ' . $attribute_hash); // Return values return array($targeted_id, $attribute_hash, $attributes); }
/** * When the process logic determines that the user is not * authorized for this service, then forward the user to * an 403 unauthorized page. * * Separated this code into its own method so that child * classes can override it and change the action. Forward * thinking in case a "chained" ACL is needed, more complex * permission logic. * * @param array $request */ protected function unauthorized(&$request) { SimpleSAML\Logger::error('ExpectedAuthnContextClassRef: Invalid authentication context: ' . $this->AuthnContextClassRef . '. Accepted values are: ' . var_export($this->accepted, true)); $id = SimpleSAML_Auth_State::saveState($request, 'saml:ExpectedAuthnContextClassRef:unauthorized'); $url = SimpleSAML\Module::getModuleURL('saml/sp/wrong_authncontextclassref.php'); \SimpleSAML\Utils\HTTP::redirectTrustedURL($url, array('StateId' => $id)); }
/** * Hook to run a cron job. * * @param array &$croninfo Output */ function statistics_hook_cron(&$croninfo) { assert('is_array($croninfo)'); assert('array_key_exists("summary", $croninfo)'); assert('array_key_exists("tag", $croninfo)'); $statconfig = SimpleSAML_Configuration::getConfig('module_statistics.php'); if (is_null($statconfig->getValue('cron_tag', NULL))) { return; } if ($statconfig->getValue('cron_tag', NULL) !== $croninfo['tag']) { return; } $maxtime = $statconfig->getInteger('time_limit', NULL); if ($maxtime) { set_time_limit($maxtime); } try { $aggregator = new sspmod_statistics_Aggregator(); $results = $aggregator->aggregate(); if (empty($results)) { SimpleSAML\Logger::notice('Output from statistics aggregator was empty.'); } else { $aggregator->store($results); } } catch (Exception $e) { $message = 'Loganalyzer threw exception: ' . $e->getMessage(); SimpleSAML\Logger::warning($message); $croninfo['summary'][] = $message; } }
public static function receiveAuthnRequest(SimpleSAML_IdP $idp) { try { // accomodate for disfunctional $_GET "windows" slash decoding in PHP $wctx = $_GET['wctx']; foreach (explode('&', $_SERVER['REQUEST_URI']) as $e) { $a = explode('=', $e); if ($a[0] == 'wctx') { $wctx = urldecode($a[1]); } } $requestid = $wctx; $issuer = $_GET['wtrealm']; $requestcache = array('RequestID' => $requestid, 'Issuer' => $issuer, 'RelayState' => $requestid); $spEntityId = $requestcache['Issuer']; $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'adfs-sp-remote'); SimpleSAML\Logger::info('ADFS - IdP.prp: Incoming Authentication request: ' . $issuer . ' id ' . $requestid); } catch (Exception $exception) { throw new SimpleSAML_Error_Error('PROCESSAUTHNREQUEST', $exception); } $sessionLostURL = NULL; // TODO? $forceAuthn = FALSE; $isPassive = FALSE; $state = array('Responder' => array('sspmod_adfs_IdP_ADFS', 'sendResponse'), 'SPMetadata' => $spMetadata->toArray(), 'ForceAuthn' => $forceAuthn, 'isPassive' => $isPassive, 'adfs:wctx' => $wctx); $idp->handleAuthenticationRequest($state); }
/** * Get the NameID value. * * @param array $state The state array. * @return string|null The NameID value. */ protected function getValue(array &$state) { if (!isset($state['Destination']['entityid'])) { SimpleSAML\Logger::warning('No SP entity ID - not generating persistent NameID.'); return null; } $spEntityId = $state['Destination']['entityid']; if (!isset($state['Source']['entityid'])) { SimpleSAML\Logger::warning('No IdP entity ID - not generating persistent NameID.'); return null; } $idpEntityId = $state['Source']['entityid']; if (!isset($state['Attributes'][$this->attribute]) || count($state['Attributes'][$this->attribute]) === 0) { SimpleSAML\Logger::warning('Missing attribute ' . var_export($this->attribute, true) . ' on user - not generating persistent NameID.'); return null; } if (count($state['Attributes'][$this->attribute]) > 1) { SimpleSAML\Logger::warning('More than one value in attribute ' . var_export($this->attribute, true) . ' on user - not generating persistent NameID.'); return null; } $uid = array_values($state['Attributes'][$this->attribute]); // just in case the first index is no longer 0 $uid = $uid[0]; if (empty($uid)) { SimpleSAML\Logger::warning('Empty value in attribute ' . var_export($this->attribute, true) . ' on user - not generating persistent NameID.'); return null; } $secretSalt = SimpleSAML\Utils\Config::getSecretSalt(); $uidData = 'uidhashbase' . $secretSalt; $uidData .= strlen($idpEntityId) . ':' . $idpEntityId; $uidData .= strlen($spEntityId) . ':' . $spEntityId; $uidData .= strlen($uid) . ':' . $uid; $uidData .= $secretSalt; return sha1($uidData); }
function oauth2_hook_cron(&$croninfo) { assert('is_array($croninfo)'); assert('array_key_exists("summary", $croninfo)'); assert('array_key_exists("tag", $croninfo)'); $oauth2config = SimpleSAML_Configuration::getOptionalConfig('module_oauth2.php'); if (is_null($oauth2config->getValue('cron_tag', 'hourly'))) { return; } if ($oauth2config->getValue('cron_tag', NULL) !== $croninfo['tag']) { return; } try { $store = SimpleSAML_Store::getInstance(); if (!$store instanceof \SimpleSAML\Modules\DBAL\Store\DBAL) { throw new \SimpleSAML_Error_Exception('OAuth2 module: Only DBAL Store is supported'); } $accessTokenRepository = new AccessTokenRepository(); $accessTokenRepository->removeExpiredAccessTokens(); $authTokenRepository = new AuthCodeRepository(); $authTokenRepository->removeExpiredAuthCodes(); $refreshTokenRepository = new RefreshTokenRepository(); $refreshTokenRepository->removeExpiredRefreshTokens(); $croninfo['summary'][] = 'OAuth2 clean up. Removed expired entries from OAuth2 storage.'; } catch (Exception $e) { $message = 'OAuth2 clean up cron script failed: ' . $e->getMessage(); SimpleSAML\Logger::warning($message); $croninfo['summary'][] = $message; } }
/** * Process an authentication response. * * This function saves the state, and if necessary redirects the user to the page where the user * is informed about the expiry date of his/her certificate. * * @param array $state The state of the response. */ public function process(&$state) { assert('is_array($state)'); if (isset($state['isPassive']) && $state['isPassive'] === TRUE) { // We have a passive request. Skip the warning return; } if (!isset($_SERVER['SSL_CLIENT_CERT']) || $_SERVER['SSL_CLIENT_CERT'] == '') { return; } $client_cert = $_SERVER['SSL_CLIENT_CERT']; $client_cert_data = openssl_x509_parse($client_cert); if ($client_cert_data == FALSE) { SimpleSAML\Logger::error('authX509: invalid cert'); return; } $validTo = $client_cert_data['validTo_time_t']; $now = time(); $daysleft = (int) (($validTo - $now) / (24 * 60 * 60)); if ($daysleft > $this->warndaysbefore) { // We have a certificate that will be valid for some time. Skip the warning return; } SimpleSAML\Logger::warning('authX509: user certificate expires in ' . $daysleft . ' days'); $state['daysleft'] = $daysleft; $state['renewurl'] = $this->renewurl; /* Save state and redirect. */ $id = SimpleSAML_Auth_State::saveState($state, 'warning:expire'); $url = SimpleSAML\Module::getModuleURL('authX509/expirywarning.php'); \SimpleSAML\Utils\HTTP::redirectTrustedURL($url, array('StateId' => $id)); }
/** * This temporary autoloader allows loading classes with their old-style names (SimpleSAML_Path_Something) even if they * have been migrated to namespaces, by registering an alias for the new class. If the class has not yet been migrated, * the autoloader will then try to load it. * * @param string $class The full name of the class using underscores to separate the elements of the path, and starting * with 'SimpleSAML_'. * @deprecated This function will be removed in SSP 2.0. */ function temporaryLoader($class) { if (!strstr($class, 'SimpleSAML_')) { return; // not a valid class name for old classes } $original = $class; // list of classes that have been renamed or moved $renamed = array('SimpleSAML_Metadata_MetaDataStorageHandlerMDX' => 'SimpleSAML_Metadata_Sources_MDQ', 'SimpleSAML_Logger_LoggingHandlerSyslog' => 'SimpleSAML_Logger_SyslogLoggingHandler', 'SimpleSAML_Logger_LoggingHandlerErrorLog' => 'SimpleSAML_Logger_ErrorLogLoggingHandler', 'SimpleSAML_Logger_LoggingHandlerFile' => 'SimpleSAML_Logger_FileLoggingHandler', 'SimpleSAML_Logger_LoggingHandler' => 'SimpleSAML_Logger_LoggingHandlerInterface'); if (array_key_exists($class, $renamed)) { // the class has been renamed, try to load it and create an alias $class = $renamed[$class]; } // try to load it from the corresponding file $path = explode('_', $class); $file = dirname(__FILE__) . DIRECTORY_SEPARATOR . join(DIRECTORY_SEPARATOR, $path) . '.php'; if (file_exists($file)) { require_once $file; } // it exists, so it's not yet migrated to namespaces if (class_exists($class, false) || interface_exists($class, false)) { return; } // it didn't exist, try to see if it was migrated to namespaces $new = join('\\', $path); if (class_exists($new, false) || interface_exists($new, false)) { // do not try to autoload it if it doesn't exist! It should! class_alias($new, $original); SimpleSAML\Logger::warning("The class or interface '{$original}' is now using namespaces, please use '{$new}'."); } }
/** * Log line. * * @param array &$state The current state. */ public function process(&$state) { assert('is_array($state)'); assert('array_key_exists("Attributes", $state)'); $logAttribute = 'NA'; $source = 'NA'; $dest = 'NA'; if (array_key_exists($this->attribute, $state['Attributes'])) { $logAttribute = $state['Attributes'][$this->attribute][0]; } if (array_key_exists('Source', $state)) { if (isset($state['Source']['core:statistics-id'])) { $source = $state['Source']['core:statistics-id']; } else { $source = $state['Source']['entityid']; } } if (array_key_exists('Destination', $state)) { if (isset($state['Destination']['core:statistics-id'])) { $dest = $state['Destination']['core:statistics-id']; } else { $dest = $state['Destination']['entityid']; } } if (!array_key_exists('PreviousSSOTimestamp', $state)) { // The user hasn't authenticated with this SP earlier in this session SimpleSAML\Logger::stats($this->typeTag . '-first ' . $dest . ' ' . $source . ' ' . $logAttribute); } SimpleSAML\Logger::stats($this->typeTag . ' ' . $dest . ' ' . $source . ' ' . $logAttribute); }
/** * Hook to run a cron job. * * @param array &$croninfo Output */ function sanitycheck_hook_cron(&$croninfo) { assert('is_array($croninfo)'); assert('array_key_exists("summary", $croninfo)'); assert('array_key_exists("tag", $croninfo)'); SimpleSAML\Logger::info('cron [sanitycheck]: Running cron in cron tag [' . $croninfo['tag'] . '] '); try { $sconfig = SimpleSAML_Configuration::getOptionalConfig('config-sanitycheck.php'); $cronTag = $sconfig->getString('cron_tag', null); if ($cronTag === null || $cronTag !== $croninfo['tag']) { return; } $info = array(); $errors = array(); $hookinfo = array('info' => &$info, 'errors' => &$errors); SimpleSAML\Module::callHooks('sanitycheck', $hookinfo); if (count($errors) > 0) { foreach ($errors as $err) { $croninfo['summary'][] = 'Sanitycheck error: ' . $err; } } } catch (Exception $e) { $croninfo['summary'][] = 'Error executing sanity check: ' . $e->getMessage(); } }
/** * Process a authentication response. * * This function checks how long it is since the last time the user was authenticated. * If it is to short a while since, we will show a warning to the user. * * @param array $state The state of the response. */ public function process(&$state) { assert('is_array($state)'); if (!array_key_exists('PreviousSSOTimestamp', $state)) { /* * No timestamp from the previous SSO to this SP. This is the first * time during this session. */ return; } $timeDelta = time() - $state['PreviousSSOTimestamp']; if ($timeDelta >= 10) { // At least 10 seconds since last attempt return; } if (array_key_exists('Destination', $state) && array_key_exists('entityid', $state['Destination'])) { $entityId = $state['Destination']['entityid']; } else { $entityId = 'UNKNOWN'; } SimpleSAML\Logger::warning('WarnShortSSOInterval: Only ' . $timeDelta . ' seconds since last SSO for this user from the SP ' . var_export($entityId, TRUE)); // Save state and redirect $id = SimpleSAML_Auth_State::saveState($state, 'core:short_sso_interval'); $url = SimpleSAML\Module::getModuleURL('core/short_sso_interval.php'); \SimpleSAML\Utils\HTTP::redirectTrustedURL($url, array('StateId' => $id)); }
/** * Apply filter to add groups attribute. * * @param array &$request The current request */ public function process(&$request) { assert('is_array($request)'); assert('array_key_exists("Attributes", $request)'); $groups = array(); $attributes =& $request['Attributes']; $realm = self::getRealm($attributes); if ($realm !== NULL) { $groups[] = 'realm-' . $realm; } foreach ($this->generateGroupsFrom as $name) { if (!array_key_exists($name, $attributes)) { SimpleSAML\Logger::debug('GenerateGroups - attribute \'' . $name . '\' not found.'); /* Attribute not present. */ continue; } foreach ($attributes[$name] as $value) { $value = self::escapeIllegalChars($value); $groups[] = $name . '-' . $value; if ($realm !== NULL) { $groups[] = $name . '-' . $realm . '-' . $value; } } } if (count($groups) > 0) { $attributes['groups'] = $groups; } }
function SimpleSAML_error_handler($errno, $errstr, $errfile = null, $errline = 0, $errcontext = null) { if (!class_exists('SimpleSAML\\Logger')) { /* We are probably logging a deprecation-warning during parsing. Unfortunately, the autoloader is disabled at * this point, so we should stop here. * * See PHP bug: https://bugs.php.net/bug.php?id=47987 */ return false; } if (SimpleSAML\Logger::isErrorMasked($errno)) { // masked error return false; } static $limit = 5; $limit -= 1; if ($limit < 0) { // we have reached the limit in the number of backtraces we will log return false; } // show an error with a full backtrace $e = new SimpleSAML_Error_Exception('Error ' . $errno . ' - ' . $errstr); $e->logError(); // resume normal error processing return false; }
public function finalStep(&$state) { $requestToken = $state['authtwitter:authdata:requestToken']; $parameters = array(); if (!isset($_REQUEST['oauth_token'])) { throw new SimpleSAML_Error_BadRequest("Missing oauth_token parameter."); } if ($requestToken->key !== (string) $_REQUEST['oauth_token']) { throw new SimpleSAML_Error_BadRequest("Invalid oauth_token parameter."); } if (!isset($_REQUEST['oauth_verifier'])) { throw new SimpleSAML_Error_BadRequest("Missing oauth_verifier parameter."); } $parameters['oauth_verifier'] = (string) $_REQUEST['oauth_verifier']; $consumer = new sspmod_oauth_Consumer($this->key, $this->secret); SimpleSAML\Logger::debug("oauth: Using this request token [" . $requestToken->key . "] with the secret [" . $requestToken->secret . "]"); // Replace the request token with an access token $accessToken = $consumer->getAccessToken('https://api.twitter.com/oauth/access_token', $requestToken, $parameters); SimpleSAML\Logger::debug("Got an access token from the OAuth service provider [" . $accessToken->key . "] with the secret [" . $accessToken->secret . "]"); $userdata = $consumer->getUserInfo('https://api.twitter.com/1.1/account/verify_credentials.json', $accessToken); if (!isset($userdata['id_str']) || !isset($userdata['screen_name'])) { throw new SimpleSAML_Error_AuthSource($this->authId, 'Authentication error: id_str and screen_name not set.'); } $attributes = array(); foreach ($userdata as $key => $value) { if (is_string($value)) { $attributes['twitter.' . $key] = array((string) $value); } } $attributes['twitter_at_screen_name'] = array('@' . $userdata['screen_name']); $attributes['twitter_screen_n_realm'] = array($userdata['screen_name'] . '@twitter.com'); $attributes['twitter_targetedID'] = array('http://twitter.com!' . $userdata['id_str']); $state['Attributes'] = $attributes; }
/** * Check that the user has access to the statistics. * * If the user doesn't have access, send the user to the login page. */ public static function checkAccess(SimpleSAML_Configuration $statconfig) { $protected = $statconfig->getBoolean('protected', FALSE); $authsource = $statconfig->getString('auth', NULL); $allowedusers = $statconfig->getValue('allowedUsers', NULL); $useridattr = $statconfig->getString('useridattr', 'eduPersonPrincipalName'); $acl = $statconfig->getValue('acl', NULL); if ($acl !== NULL && !is_string($acl) && !is_array($acl)) { throw new SimpleSAML_Error_Exception('Invalid value for \'acl\'-option. Should be an array or a string.'); } if (!$protected) { return; } if (SimpleSAML\Utils\Auth::isAdmin()) { // User logged in as admin. OK. SimpleSAML\Logger::debug('Statistics auth - logged in as admin, access granted'); return; } if (!isset($authsource)) { // If authsource is not defined, init admin login. SimpleSAML\Utils\Auth::requireAdmin(); } // We are using an authsource for login. $as = new SimpleSAML_Auth_Simple($authsource); $as->requireAuth(); // User logged in with auth source. SimpleSAML\Logger::debug('Statistics auth - valid login with auth source [' . $authsource . ']'); // Retrieving attributes $attributes = $as->getAttributes(); if (!empty($allowedusers)) { // Check if userid exists if (!isset($attributes[$useridattr][0])) { throw new Exception('User ID is missing'); } // Check if userid is allowed access.. if (in_array($attributes[$useridattr][0], $allowedusers)) { SimpleSAML\Logger::debug('Statistics auth - User granted access by user ID [' . $attributes[$useridattr][0] . ']'); return; } SimpleSAML\Logger::debug('Statistics auth - User denied access by user ID [' . $attributes[$useridattr][0] . ']'); } else { SimpleSAML\Logger::debug('Statistics auth - no allowedUsers list.'); } if (!is_null($acl)) { $acl = new sspmod_core_ACL($acl); if ($acl->allows($attributes)) { SimpleSAML\Logger::debug('Statistics auth - allowed access by ACL.'); return; } SimpleSAML\Logger::debug('Statistics auth - denied access by ACL.'); } else { SimpleSAML\Logger::debug('Statistics auth - no ACL configured.'); } throw new SimpleSAML_Error_Exception('Access denied to the current user.'); }
/** * Transforms the XML Document according to the EnvelopedSignature Transform * * @throws Exception * @param string $strXMLData The input XML data * @return string the transformed XML data */ public function transform($strXMLData) { $sxe = simplexml_load_string($strXMLData); $sxe->registerXPathNamespace('ds', 'http://www.w3.org/2000/09/xmldsig#'); list($signature) = $sxe->xpath("//ds:Signature"); if (!isset($signature)) { SimpleSAML\Logger::debug("Unable to locate Signature Block for EnvelopedSignature Transform"); } $transformed_xml = str_replace($signature->asXML(), "", $sxe->asXML()); return $transformed_xml; }
/** * Returns the name of the transform class based on a given URI * * @throws Exception * @param string $uri The transform URI * @return string The transform implementation class name */ protected function _findClassbyURI($uri) { switch ($uri) { case 'http://www.w3.org/2000/09/xmldsig#enveloped-signature': return 'Zend_InfoCard_Xml_Security_Transform_EnvelopedSignature'; case 'http://www.w3.org/2001/10/xml-exc-c14n#': return 'Zend_InfoCard_Xml_Security_Transform_XmlExcC14N'; default: SimpleSAML\Logger::debug("Unknown or Unsupported Transformation Requested"); } }
/** * Redirect to page setting CDC. * * @param array &$state The request state. */ public function process(&$state) { assert('is_array($state)'); if (!isset($state['Source']['entityid'])) { SimpleSAML\Logger::warning('saml:CDC: Could not find IdP entityID.'); return; } // Save state and build request $id = SimpleSAML_Auth_State::saveState($state, 'cdc:resume'); $returnTo = SimpleSAML\Module::getModuleURL('cdc/resume.php', array('domain' => $this->domain)); $params = array('id' => $id, 'entityID' => $state['Source']['entityid']); $this->client->sendRequest($returnTo, 'append', $params); }
/** * Get the NameID value. * * @param array $state The state array. * @return string|null The NameID value. */ protected function getValue(array &$state) { if (!isset($state['Attributes'][$this->attribute]) || count($state['Attributes'][$this->attribute]) === 0) { SimpleSAML\Logger::warning('Missing attribute ' . var_export($this->attribute, true) . ' on user - not generating attribute NameID.'); return null; } if (count($state['Attributes'][$this->attribute]) > 1) { SimpleSAML\Logger::warning('More than one value in attribute ' . var_export($this->attribute, true) . ' on user - not generating attribute NameID.'); } $value = array_values($state['Attributes'][$this->attribute]); // just in case the first index is no longer 0 $value = $value[0]; return $value; }
/** * Attempt to log in using the given username and password. * * @param string $username The username the user wrote. * @param string $password The password the user wrote. * @param string $org The organization the user chose. * @return array Associative array with the users attributes. */ protected function login($username, $password, $org, array $sasl_args = null) { assert('is_string($username)'); assert('is_string($password)'); assert('is_string($org)'); if (!array_key_exists($org, $this->ldapOrgs)) { // The user has selected an organization which doesn't exist anymore. SimpleSAML\Logger::warning('Authentication source ' . var_export($this->authId, true) . ': Organization seems to have disappeared while the user logged in.' . ' Organization was ' . var_export($org, true)); throw new SimpleSAML_Error_Error('WRONGUSERPASS'); } if ($this->includeOrgInUsername) { $username = $username . '@' . $org; } return $this->ldapOrgs[$org]->login($username, $password, $sasl_args); }
/** * Transform the input XML based on C14n XML Exclusive Canonicalization rules * * @throws Exception * @param string $strXMLData The input XML * @return string The output XML */ public function transform($strXMLData) { $dom = new DOMDocument(); $dom->loadXML($strXMLData); if ($strXMLData == NULL) { SimpleSAML\Logger::debug("NOXML: " . $dom->saveXML()); } else { SimpleSAML\Logger::debug("XMLcan: " . $dom->saveXML()); } if (method_exists($dom, 'C14N')) { return $dom->C14N(true, false); } SimpleSAML\Logger::debug("This transform requires the C14N() method to exist in the DOM extension"); throw new Exception('This transform requires the C14N() method to exist in the DOM extension'); }
/** * Filter out YubiKey 'otp' attribute and replace it with * a 'yubiPrefix' attribute that leaves out the dynamic part. * * @param array &$state The state we should update. */ public function process(&$state) { assert('is_array($state)'); assert('array_key_exists("Attributes", $state)'); $attributes = $state['Attributes']; SimpleSAML\Logger::debug('OTP2YubiPrefix: enter with attributes: ' . implode(',', array_keys($attributes))); $otps = $attributes['otp']; $otp = $otps['0']; $token_size = 32; $identity = substr($otp, 0, strlen($otp) - $token_size); $attributes['yubiPrefix'] = array($identity); SimpleSAML\Logger::info('OTP2YubiPrefix: otp: ' . $otp . ' identity: ' . $identity . ' (otp keys: ' . implode(',', array_keys($otps)) . ')'); unset($attributes['otp']); SimpleSAML\Logger::debug('OTP2YubiPrefix: leaving with attributes: ' . implode(',', array_keys($attributes))); }
/** * Attempt to log in using the given username and password. * * On a successful login, this function should return the users attributes. On failure, * it should throw an exception. If the error was caused by the user entering the wrong * username OR password, a SimpleSAML_Error_Error('WRONGUSERPASS') should be thrown. * * The username is UTF-8 encoded, and the hash is base64 encoded. * * @param string $username The username the user wrote. * @param string $password The password the user wrote. * @return array Associative array with the users attributes. */ protected function login($username, $password) { assert('is_string($username)'); assert('is_string($password)'); foreach ($this->users as $userpass => $attrs) { $matches = explode(':', $userpass, 2); if ($matches[0] === $username) { if (SimpleSAML\Utils\Crypto::pwValid($matches[1], $password)) { return $this->users[$userpass]; } else { SimpleSAML\Logger::debug('Incorrect password "' . $password . '" for user ' . $username); } } } throw new SimpleSAML_Error_Error('WRONGUSERPASS'); }
/** * Receive an authentication request. * * @param SimpleSAML_IdP $idp The IdP we are receiving it for. */ public static function receiveAuthnRequest(SimpleSAML_IdP $idp) { if (isset($_REQUEST['cookieTime'])) { $cookieTime = (int) $_REQUEST['cookieTime']; if ($cookieTime + 5 > time()) { /* * Less than five seconds has passed since we were * here the last time. Cookies are probably disabled. */ \SimpleSAML\Utils\HTTP::checkSessionCookie(\SimpleSAML\Utils\HTTP::getSelfURL()); } } if (!isset($_REQUEST['providerId'])) { throw new SimpleSAML_Error_BadRequest('Missing providerId parameter.'); } $spEntityId = (string) $_REQUEST['providerId']; if (!isset($_REQUEST['shire'])) { throw new SimpleSAML_Error_BadRequest('Missing shire parameter.'); } $shire = (string) $_REQUEST['shire']; if (isset($_REQUEST['target'])) { $target = $_REQUEST['target']; } else { $target = NULL; } SimpleSAML\Logger::info('Shib1.3 - IdP.SSOService: Got incoming Shib authnRequest from ' . var_export($spEntityId, TRUE) . '.'); $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'shib13-sp-remote'); $found = FALSE; foreach ($spMetadata->getEndpoints('AssertionConsumerService') as $ep) { if ($ep['Binding'] !== 'urn:oasis:names:tc:SAML:1.0:profiles:browser-post') { continue; } if ($ep['Location'] !== $shire) { continue; } $found = TRUE; break; } if (!$found) { throw new Exception('Invalid AssertionConsumerService for SP ' . var_export($spEntityId, TRUE) . ': ' . var_export($shire, TRUE)); } SimpleSAML_Stats::log('saml:idp:AuthnRequest', array('spEntityID' => $spEntityId, 'protocol' => 'saml1')); $sessionLostURL = \SimpleSAML\Utils\HTTP::addURLParameters(\SimpleSAML\Utils\HTTP::getSelfURL(), array('cookieTime' => time())); $state = array('Responder' => array('sspmod_saml_IdP_SAML1', 'sendResponse'), 'SPMetadata' => $spMetadata->toArray(), SimpleSAML_Auth_State::RESTART => $sessionLostURL, 'saml:shire' => $shire, 'saml:target' => $target, 'saml:AuthnRequestReceivedAt' => microtime(TRUE)); $idp->handleAuthenticationRequest($state); }
/** * Continue the logout operation. * * This function will never return. * * @param string $assocId The association that is terminated. * @param string|null $relayState The RelayState from the start of the logout. * @param SimpleSAML_Error_Exception|null $error The error that occurred during session termination (if any). * * @throws SimpleSAML_Error_Exception If the RelayState was lost during logout. */ public function onResponse($assocId, $relayState, SimpleSAML_Error_Exception $error = null) { assert('is_string($assocId)'); assert('is_string($relayState) || is_null($relayState)'); if ($relayState === null) { throw new SimpleSAML_Error_Exception('RelayState lost during logout.'); } $state = SimpleSAML_Auth_State::loadState($relayState, 'core:LogoutTraditional'); if ($error === null) { SimpleSAML\Logger::info('Logged out of ' . var_export($assocId, true) . '.'); $this->idp->terminateAssociation($assocId); } else { SimpleSAML\Logger::warning('Error received from ' . var_export($assocId, true) . ' during logout:'); $error->logWarning(); $state['core:Failed'] = true; } self::logoutNextSP($state); }
public static function handleLogin($authStateId, $xmlToken) { assert('is_string($authStateId)'); $config = SimpleSAML_Configuration::getInstance(); $autoconfig = $config->copyFromBase('logininfocard', 'config-login-infocard.php'); $idp_key = $autoconfig->getValue('idp_key'); $idp_pass = $autoconfig->getValue('idp_key_pass', NULL); $sts_crt = $autoconfig->getValue('sts_crt'); $Infocard = $autoconfig->getValue('InfoCard'); $infocard = new sspmod_InfoCard_RP_InfoCard(); $infocard->addIDPKey($idp_key, $idp_pass); $infocard->addSTSCertificate($sts_crt); if (!$xmlToken) { SimpleSAML\Logger::debug("XMLtoken: " . $xmlToken); } else { SimpleSAML\Logger::debug("NOXMLtoken: " . $xmlToken); } $claims = $infocard->process($xmlToken); if ($claims->isValid()) { $attributes = array(); foreach ($Infocard['requiredClaims'] as $claim => $data) { $attributes[$claim] = array($claims->{$claim}); } foreach ($Infocard['optionalClaims'] as $claim => $data) { $attributes[$claim] = array($claims->{$claim}); } // Retrieve the authentication state $state = SimpleSAML_Auth_State::loadState($authStateId, self::STAGEID); // Find authentication source assert('array_key_exists(self::AUTHID, $state)'); $source = SimpleSAML_Auth_Source::getById($state[self::AUTHID]); if ($source === NULL) { throw new Exception('Could not find authentication source with id ' . $state[self::AUTHID]); } $state['Attributes'] = $attributes; unset($infocard); unset($claims); SimpleSAML_Auth_Source::completeAuth($state); } else { unset($infocard); unset($claims); return 'wrong_IC'; } }
/** * Store a NameID to attribute. * * @param array &$state The request state. */ public function process(&$state) { assert('is_array($state)'); if (!isset($state['saml:NameID'][SAML2_Const::NAMEID_PERSISTENT])) { SimpleSAML\Logger::warning('Unable to generate eduPersonTargetedID because no persistent NameID was available.'); return; } $nameID = $state['saml:NameID'][SAML2_Const::NAMEID_PERSISTENT]; if ($this->nameId) { $doc = SAML2_DOMDocumentFactory::create(); $root = $doc->createElement('root'); $doc->appendChild($root); SAML2_Utils::addNameId($root, $nameID); $value = $doc->saveXML($root->firstChild); } else { $value = $nameID['Value']; } $state['Attributes'][$this->attribute] = array($value); }
/** * Hook to run a cron job. * * @param array &$croninfo Output */ function riak_hook_cron(&$croninfo) { assert('is_array($croninfo)'); assert('array_key_exists("summary", $croninfo)'); assert('array_key_exists("tag", $croninfo)'); if ($croninfo['tag'] !== 'hourly') { return; } try { $store = new sspmod_riak_Store_Store(); $result = $store->bucket->indexSearch('expires', 'int', 1, time() - 30); foreach ($result as $link) { $link->getBinary()->delete(); } SimpleSAML\Logger::info(sprintf("deleted %s riak key%s", sizeof($result), sizeof($result) == 1 ? '' : 's')); } catch (Exception $e) { $message = 'riak threw exception: ' . $e->getMessage(); SimpleSAML\Logger::warning($message); $croninfo['summary'][] = $message; } }