From d09f5b867475fd671853468ec9acc563d026537f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szab=C3=B3=20Gyula?= Date: Tue, 1 Mar 2016 12:25:29 +0100 Subject: [PATCH] psr2 fixes --- config-templates/module_aa.php | 6 +- hooks/hook_frontpage.php | 19 +- lib/AA/SAML2.php | 584 +++++++++++++++++---------------- lib/Auth/Source/Bypass.php | 92 +++--- www/metadata.php | 243 +++++++------- 5 files changed, 471 insertions(+), 473 deletions(-) diff --git a/config-templates/module_aa.php b/config-templates/module_aa.php index 985e973..79dea25 100644 --- a/config-templates/module_aa.php +++ b/config-templates/module_aa.php @@ -18,10 +18,8 @@ //'signResponse' => TRUE, /** - * Sign the whole assertion, default is false. - */ + * Sign the whole assertion, default is false. + */ //'signAssertion' => FALSE, ); - - diff --git a/hooks/hook_frontpage.php b/hooks/hook_frontpage.php index 22572b4..368ea60 100644 --- a/hooks/hook_frontpage.php +++ b/hooks/hook_frontpage.php @@ -1,16 +1,17 @@ SimpleSAML_Module::getModuleURL('aa/metadata.php?output=xhtml'), - 'text' => '{aa:aa:text}', - ); + $links['federation'][] = array( + 'href' => SimpleSAML_Module::getModuleURL('aa/metadata.php?output=xhtml'), + 'text' => '{aa:aa:text}', + ); } -?> diff --git a/lib/AA/SAML2.php b/lib/AA/SAML2.php index 610fa74..5eebf1a 100644 --- a/lib/AA/SAML2.php +++ b/lib/AA/SAML2.php @@ -5,296 +5,300 @@ */ /** -* -*/ + * + */ class sspmod_aa_AA_SAML2 { - - private $binding; - private $query; - private $aaEntityId; - private $aaMetadata; - private $spEntityId; - private $spMetadata; - private $config; - private $attributeNameFormat; - private $signAssertion; - private $signResponse; - - function __construct($metadata) - { - $this->config = SimpleSAML_Configuration::getConfig('module_aa.php'); - - $this->signAssertion = FALSE; - if ($this->config->hasValue('signAssertion')) { - $this->signAssertion = $this->config->getBoolean('signAssertion'); - } - - $this->signResponse = TRUE; - if ($this->config->hasValue('signResponse')) { - $this->signResponse = $this->config->getBoolean('signResponse'); - } - - $this->binding = $this->getBinding(); - $this->query = $this->getQuery(); - $this->attributeNameFormat = $this->getAttributeNameFormat(); - $this->getEntities($metadata); - } - - - public function getBinding() - { - /* Receiving the attribute query */ - $binding = SAML2_Binding::getCurrentBinding(); - - /* Supported binding is SOAP */ - if (! ($binding instanceof SAML2_SOAP)) { - throw new SimpleSAML_Error_BadRequest('[aa] Unsupported binding. It must be SAML2_SOAP.'); - } - SimpleSAML_Logger::debug('[aa] binding: '.var_export($binding,true)); - return $binding; - } - - private function getQuery() - { - $query = $this->binding->receive(); - SimpleSAML_Logger::debug('[aa] query: '.var_export($query,true)); - - if (!($query instanceof SAML2_AttributeQuery)) { - throw new SimpleSAML_Error_BadRequest('Invalid message received on AttributeQuery endpoint.'); - } - return $query; - } - - private function getEntities($metadata) - { - /* Getting the related entities metadata objects */ - $aaEntityId = $metadata->getMetaDataCurrentEntityID('attributeauthority-hosted'); - $aaMetadata = $metadata->getMetadataConfig($aaEntityId, 'attributeauthority-hosted'); - - $spEntityId = $this->query->getIssuer(); - if ($spEntityId === NULL) { - throw new SimpleSAML_Error_BadRequest('Missing in .'); - } - $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote'); - - $this->aaEntityId = $aaEntityId; - $this->aaMetadata = $aaMetadata; - $this->spEntityId = $spEntityId; - $this->spMetadata = $spMetadata; - } - - private function getAttributeNameFormat() - { - /* The name format of the attributes. */ - //$attributeNameFormat = SAML2_Const::NAMEFORMAT_URI; - $attributeNameFormat = 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri'; - if ($this->config->hasValue('attributeNameFormat')) { - $attributeNameFormat = $this->config->getValue('attributeNameFormat'); - } - return $attributeNameFormat; - } - - public function handleAttributeQuery() - { - // Authenticate the requestor - $this->authenticate(); - - // Get all attributes from the auth sources - $attributes = $this->getAttributes(); - - // Filter attributes by AA filters - $this->processFilters($attributes); - - // Filter attributes by SP - $this->filterFromRequest($attributes); - - // Build the whole response - $response = $this->buildResponse($attributes); - - // Send the response - $this->sendResponse($response); - } - - private function authenticate() - { - $client_is_authenticated = FALSE; - - /* Authenticate the requestor by verifying the TLS certificate used for the HTTP query */ - if (array_key_exists('SSL_CLIENT_VERIFY', $_SERVER)){ - SimpleSAML_Logger::debug('[aa] Request was made using the following certificate: '.var_export($_SERVER['SSL_CLIENT_VERIFY'],1)); - } - if (array_key_exists('SSL_CLIENT_VERIFY', $_SERVER) && $_SERVER['SSL_CLIENT_VERIFY'] && $_SERVER['SSL_CLIENT_VERIFY'] != "NONE"){ - /* compare certificate fingerprints */ - $clientCertData = trim(preg_replace('/--.* CERTIFICATE-+-/','',$_SERVER['SSL_CLIENT_CERT'])); - $clientCertFingerprint = strtolower(sha1(base64_decode($clientCertData))); - if(!$clientCertFingerprint) - throw new SimpleSAML_Error_Exception("[aa] Can not calculate certificate fingerprint from the request."); - - $spCertArray = SimpleSAML_Utilities::loadPublicKey($this->spMetadata); - if (!$spCertArray) - throw new SimpleSAML_Error_Exception("[aa] Can not find the public key of the requestor in the metadata!"); - - foreach ($spCertArray['certFingerprint'] as $fingerprint) { - if ($fingerprint && $clientCertFingerprint == $fingerprint) { - $client_is_authenticated = TRUE; - SimpleSAML_Logger::debug('[aa] SSL certificate is checked and valid.'); - break; - } - } - /* Reject the request if the TLS certificate used for the request does not match metadata */ - if (!$client_is_authenticated){ - throw new SimpleSAML_Error_Exception("[aa] SSL certificate check failed."); - } - } - else { - /* The request may be signed, so this is not fatal */ - SimpleSAML_Logger::debug('[aa] SSL client certificate does not exist.'); - } - - /* Authenticate the requestor by verifying the XML signature on the query */ - $certs_of_query = $this->query->getCertificates(); - if (count($certs_of_query) > 0) { - if (sspmod_saml_Message::checkSign($this->spMetadata,$this->query)){ - $client_is_authenticated = TRUE; - SimpleSAML_Logger::debug('[aa] AttributeQuery signature is checked and valid.'); - } else { - /* An invalid or unverifiable signature is fatal */ - throw new SimpleSAML_Error_Exception("[aa] The signature of the AttributeQuery is wrong!"); - } - } - else { - /* The request may be protected by HTTP TLS (X.509) authentication, so this is not fatal */ - SimpleSAML_Logger::debug('[aa] AttributeQuery has no signature.'); - } - - if (! $client_is_authenticated){ - SimpleSAML_Logger::info('[aa] Attribute query was not authenticated. Drop.'); - header('HTTP/1.1 401 Unauthorized'); - header('WWW-Authenticate: None',false); - echo 'Not authenticated. Neither query signature nor SSL client certificate was available.'; - exit; - } - else { - SimpleSAML_Logger::debug('[aa] Attribute query was authenticated.'); - } - } - - private function getAttributes() - { - $nameId=$this->query->getNameId(); - - if (!$nameId) - throw new SimpleSAML_Error_BadRequest('[aa] Error getting NameID from AttributeQuery.'); - if (array_key_exists("Format",$nameId)) { - $nameIdFormat = $nameId["Format"]; - } - - SimpleSAML_Logger::info('[aa] Received attribute query for ' . $nameId['Value'] . ' (nameIdFormat: ' . $nameIdFormat . ')'); - - /* Get the attributes from the AuthSource */ - $spMetadataArray = $this->spMetadata->toArray(); - $aaMetadataArray = $this->aaMetadata->toArray(); - $attributes = array(); - $state = array( - 'Attributes' => $attributes, - 'Destination' => $spMetadataArray, - 'Source' => $aaMetadataArray, - 'aa:nameId' => $nameId['Value'], - 'aa:nameIdFormat' => $nameIdFormat, - ); - - $as = SimpleSAML_Auth_Source::getById($this->config->getValue("authsource")); - $as->authenticate($state); - - $attributes = $state['Attributes']; - - return $attributes; - } - - private function processFilters(&$attributes) - { - $spMetadataArray = $this->spMetadata->toArray(); - $aaMetadataArray = $this->aaMetadata->toArray(); - $pc = new SimpleSAML_Auth_ProcessingChain($aaMetadataArray, $spMetadataArray, 'aa'); - $authProcState = array( - 'Attributes' => $attributes, - 'Destination' => $spMetadataArray, - 'Source' => $aaMetadataArray, - ); - $pc->processStatePassive($authProcState); // backend, passive processing, no user interaction - $attributes = $authProcState['Attributes']; - } - - private function filterFromRequest(&$attributes) - { - $requestedAttributes = $this->query->getAttributes(); - if (count($requestedAttributes) === 0) { - SimpleSAML_Logger::debug('[aa] No attributes requested - return all previously resolved attributes: '.var_export($attributes,true)); - } elseif ($this->query->getAttributeNameFormat() !== $this->attributeNameFormat) { - SimpleSAML_Logger::debug('[aa] NameFormat mismatch - no attributes returned. Expected: '.$this->attributeNameFormat.' Requested: '. $this->query->getAttributeNameFormat()); - $attributes = array(); - } else { - foreach ($attributes as $name => $values) { - if (!array_key_exists($name, $requestedAttributes)) { - /* They didn't request this attribute. */ - SimpleSAML_Logger::debug('[aa] Remove attribute because it was not requested: '.$name); - unset($attributes[$name]); - continue; - } - - if (count($values) === 0) { - /* Return all values. */ - continue; - } - - /* Filter which attribute values we should return. */ - $attributes[$name] = array_intersect($values, $requestedAttributes[$name]); - } - } - } - - - private function buildResponse($returnAttributes) - { - /* SubjectConfirmation */ - $sc = new SAML2_XML_saml_SubjectConfirmation(); - $sc->Method = SAML2_Const::CM_BEARER; - $sc->SubjectConfirmationData = new SAML2_XML_saml_SubjectConfirmationData(); - $sc->SubjectConfirmationData->NotBefore = time(); - $sc->SubjectConfirmationData->NotOnOrAfter = time() + $this->config->getInteger('validFor'); - $sc->SubjectConfirmationData->InResponseTo = $this->query->getId(); - - $assertion = new SAML2_Assertion(); - $assertion->setSubjectConfirmation(array($sc)); - $assertion->setIssuer($this->aaEntityId); - $assertion->setNameId($this->query->getNameId()); - $assertion->setNotBefore(time()); - $assertion->setNotOnOrAfter(time() + $this->config->getInteger('validFor')); - $assertion->setValidAudiences(array($this->spEntityId)); - $assertion->setAttributes($returnAttributes); - $assertion->setAttributeNameFormat($this->attributeNameFormat); - if ($this->signAssertion) { - sspmod_saml_Message::addSign($this->aaMetadata, $this->spMetadata, $assertion); - } - - /* The Response */ - $response = new SAML2_Response(); - $response->setRelayState($this->query->getRelayState()); - $response->setIssuer($this->aaEntityId); - $response->setInResponseTo($this->query->getId()); - $response->setAssertions(array($assertion)); - if ($this->signResponse) { - sspmod_saml_Message::addSign($this->aaMetadata, $this->spMetadata, $response); - } - - return $response; - } - - private function sendResponse($response) - { - SimpleSAML_Logger::debug('[aa] Sending: '.var_export($response,true)); - SimpleSAML_Logger::info('[aa] Sending assertion.'); - $this->binding->send($response); - } + private $binding; + private $query; + private $aaEntityId; + private $aaMetadata; + private $spEntityId; + private $spMetadata; + private $config; + private $attributeNameFormat; + private $signAssertion; + private $signResponse; + + public function __construct($metadata) + { + $this->config = SimpleSAML_Configuration::getConfig('module_aa.php'); + + $this->signAssertion = false; + if ($this->config->hasValue('signAssertion')) { + $this->signAssertion = $this->config->getBoolean('signAssertion'); + } + + $this->signResponse = true; + if ($this->config->hasValue('signResponse')) { + $this->signResponse = $this->config->getBoolean('signResponse'); + } + + $this->binding = $this->getBinding(); + $this->query = $this->getQuery(); + $this->attributeNameFormat = $this->getAttributeNameFormat(); + $this->getEntities($metadata); + } + + public function getBinding() + { + /* Receiving the attribute query */ + $binding = SAML2_Binding::getCurrentBinding(); + + /* Supported binding is SOAP */ + if (!($binding instanceof SAML2_SOAP)) { + throw new SimpleSAML_Error_BadRequest('[aa] Unsupported binding. It must be SAML2_SOAP.'); + } + SimpleSAML_Logger::debug('[aa] binding: '.var_export($binding, true)); + + return $binding; + } + + private function getQuery() + { + $query = $this->binding->receive(); + SimpleSAML_Logger::debug('[aa] query: '.var_export($query, true)); + + if (!($query instanceof SAML2_AttributeQuery)) { + throw new SimpleSAML_Error_BadRequest('Invalid message received on AttributeQuery endpoint.'); + } + + return $query; + } + + private function getEntities($metadata) + { + /* Getting the related entities metadata objects */ + $aaEntityId = $metadata->getMetaDataCurrentEntityID('attributeauthority-hosted'); + $aaMetadata = $metadata->getMetadataConfig($aaEntityId, 'attributeauthority-hosted'); + + $spEntityId = $this->query->getIssuer(); + if ($spEntityId === null) { + throw new SimpleSAML_Error_BadRequest('Missing in .'); + } + $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote'); + + $this->aaEntityId = $aaEntityId; + $this->aaMetadata = $aaMetadata; + $this->spEntityId = $spEntityId; + $this->spMetadata = $spMetadata; + } + + private function getAttributeNameFormat() + { + /* The name format of the attributes. */ + //$attributeNameFormat = SAML2_Const::NAMEFORMAT_URI; + $attributeNameFormat = 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri'; + if ($this->config->hasValue('attributeNameFormat')) { + $attributeNameFormat = $this->config->getValue('attributeNameFormat'); + } + + return $attributeNameFormat; + } + + public function handleAttributeQuery() + { + // Authenticate the requestor + $this->authenticate(); + + // Get all attributes from the auth sources + $attributes = $this->getAttributes(); + + // Filter attributes by AA filters + $this->processFilters($attributes); + + // Filter attributes by SP + $this->filterFromRequest($attributes); + + // Build the whole response + $response = $this->buildResponse($attributes); + + // Send the response + $this->sendResponse($response); + } + + private function authenticate() + { + $client_is_authenticated = false; + + /* Authenticate the requestor by verifying the TLS certificate used for the HTTP query */ + if (array_key_exists('SSL_CLIENT_VERIFY', $_SERVER)) { + SimpleSAML_Logger::debug('[aa] Request was made using the following certificate: '.var_export($_SERVER['SSL_CLIENT_VERIFY'], 1)); + } + if (array_key_exists('SSL_CLIENT_VERIFY', $_SERVER) && $_SERVER['SSL_CLIENT_VERIFY'] && $_SERVER['SSL_CLIENT_VERIFY'] != 'NONE') { + /* compare certificate fingerprints */ + $clientCertData = trim(preg_replace('/--.* CERTIFICATE-+-/', '', $_SERVER['SSL_CLIENT_CERT'])); + $clientCertFingerprint = strtolower(sha1(base64_decode($clientCertData))); + if (!$clientCertFingerprint) { + throw new SimpleSAML_Error_Exception('[aa] Can not calculate certificate fingerprint from the request.'); + } + + $spCertArray = SimpleSAML_Utilities::loadPublicKey($this->spMetadata); + if (!$spCertArray) { + throw new SimpleSAML_Error_Exception('[aa] Can not find the public key of the requestor in the metadata!'); + } + + foreach ($spCertArray['certFingerprint'] as $fingerprint) { + if ($fingerprint && $clientCertFingerprint == $fingerprint) { + $client_is_authenticated = true; + SimpleSAML_Logger::debug('[aa] SSL certificate is checked and valid.'); + break; + } + } + /* Reject the request if the TLS certificate used for the request does not match metadata */ + if (!$client_is_authenticated) { + throw new SimpleSAML_Error_Exception('[aa] SSL certificate check failed.'); + } + } else { + /* The request may be signed, so this is not fatal */ + SimpleSAML_Logger::debug('[aa] SSL client certificate does not exist.'); + } + + /* Authenticate the requestor by verifying the XML signature on the query */ + $certs_of_query = $this->query->getCertificates(); + if (count($certs_of_query) > 0) { + if (sspmod_saml_Message::checkSign($this->spMetadata, $this->query)) { + $client_is_authenticated = true; + SimpleSAML_Logger::debug('[aa] AttributeQuery signature is checked and valid.'); + } else { + /* An invalid or unverifiable signature is fatal */ + throw new SimpleSAML_Error_Exception('[aa] The signature of the AttributeQuery is wrong!'); + } + } else { + /* The request may be protected by HTTP TLS (X.509) authentication, so this is not fatal */ + SimpleSAML_Logger::debug('[aa] AttributeQuery has no signature.'); + } + + if (!$client_is_authenticated) { + SimpleSAML_Logger::info('[aa] Attribute query was not authenticated. Drop.'); + header('HTTP/1.1 401 Unauthorized'); + header('WWW-Authenticate: None', false); + echo 'Not authenticated. Neither query signature nor SSL client certificate was available.'; + exit; + } else { + SimpleSAML_Logger::debug('[aa] Attribute query was authenticated.'); + } + } + + private function getAttributes() + { + $nameId = $this->query->getNameId(); + + if (!$nameId) { + throw new SimpleSAML_Error_BadRequest('[aa] Error getting NameID from AttributeQuery.'); + } + if (array_key_exists('Format', $nameId)) { + $nameIdFormat = $nameId['Format']; + } + + SimpleSAML_Logger::info('[aa] Received attribute query for '.$nameId['Value'].' (nameIdFormat: '.$nameIdFormat.')'); + + /* Get the attributes from the AuthSource */ + $spMetadataArray = $this->spMetadata->toArray(); + $aaMetadataArray = $this->aaMetadata->toArray(); + $attributes = array(); + $state = array( + 'Attributes' => $attributes, + 'Destination' => $spMetadataArray, + 'Source' => $aaMetadataArray, + 'aa:nameId' => $nameId['Value'], + 'aa:nameIdFormat' => $nameIdFormat, + ); + + $as = SimpleSAML_Auth_Source::getById($this->config->getValue('authsource')); + $as->authenticate($state); + + $attributes = $state['Attributes']; + + return $attributes; + } + + private function processFilters(&$attributes) + { + $spMetadataArray = $this->spMetadata->toArray(); + $aaMetadataArray = $this->aaMetadata->toArray(); + $pc = new SimpleSAML_Auth_ProcessingChain($aaMetadataArray, $spMetadataArray, 'aa'); + $authProcState = array( + 'Attributes' => $attributes, + 'Destination' => $spMetadataArray, + 'Source' => $aaMetadataArray, + ); + $pc->processStatePassive($authProcState); // backend, passive processing, no user interaction + $attributes = $authProcState['Attributes']; + } + + private function filterFromRequest(&$attributes) + { + $requestedAttributes = $this->query->getAttributes(); + if (count($requestedAttributes) === 0) { + SimpleSAML_Logger::debug( + '[aa] No attributes requested - return all previously resolved attributes: '.var_export($attributes, true) + ); + } elseif ($this->query->getAttributeNameFormat() !== $this->attributeNameFormat) { + SimpleSAML_Logger::debug( + '[aa] NameFormat mismatch - no attributes returned. Expected: '.$this->attributeNameFormat.' Requested: '.$this->query->getAttributeNameFormat() + ); + $attributes = array(); + } else { + foreach ($attributes as $name => $values) { + if (!array_key_exists($name, $requestedAttributes)) { + /* They didn't request this attribute. */ + SimpleSAML_Logger::debug('[aa] Remove attribute because it was not requested: '.$name); + unset($attributes[$name]); + continue; + } + + if (count($values) === 0) { + /* Return all values. */ + continue; + } + + /* Filter which attribute values we should return. */ + $attributes[$name] = array_intersect($values, $requestedAttributes[$name]); + } + } + } + + private function buildResponse($returnAttributes) + { + /* SubjectConfirmation */ + $sc = new SAML2_XML_saml_SubjectConfirmation(); + $sc->Method = SAML2_Const::CM_BEARER; + $sc->SubjectConfirmationData = new SAML2_XML_saml_SubjectConfirmationData(); + $sc->SubjectConfirmationData->NotBefore = time(); + $sc->SubjectConfirmationData->NotOnOrAfter = time() + $this->config->getInteger('validFor'); + $sc->SubjectConfirmationData->InResponseTo = $this->query->getId(); + + $assertion = new SAML2_Assertion(); + $assertion->setSubjectConfirmation(array($sc)); + $assertion->setIssuer($this->aaEntityId); + $assertion->setNameId($this->query->getNameId()); + $assertion->setNotBefore(time()); + $assertion->setNotOnOrAfter(time() + $this->config->getInteger('validFor')); + $assertion->setValidAudiences(array($this->spEntityId)); + $assertion->setAttributes($returnAttributes); + $assertion->setAttributeNameFormat($this->attributeNameFormat); + if ($this->signAssertion) { + sspmod_saml_Message::addSign($this->aaMetadata, $this->spMetadata, $assertion); + } + + /* The Response */ + $response = new SAML2_Response(); + $response->setRelayState($this->query->getRelayState()); + $response->setIssuer($this->aaEntityId); + $response->setInResponseTo($this->query->getId()); + $response->setAssertions(array($assertion)); + if ($this->signResponse) { + sspmod_saml_Message::addSign($this->aaMetadata, $this->spMetadata, $response); + } + + return $response; + } + + private function sendResponse($response) + { + SimpleSAML_Logger::debug('[aa] Sending: '.var_export($response, true)); + SimpleSAML_Logger::info('[aa] Sending assertion.'); + $this->binding->send($response); + } } diff --git a/lib/Auth/Source/Bypass.php b/lib/Auth/Source/Bypass.php index 117ec73..577a519 100644 --- a/lib/Auth/Source/Bypass.php +++ b/lib/Auth/Source/Bypass.php @@ -5,58 +5,56 @@ * * This class is an authentication source which will always return a user with * the subject nameId in the attributes array. - * + * * Example configuration in the config/authsources.php - * + * * 'default-aa' => array( * 'aa:Bypass', * 'uid' => 'subject_nameid' - * ), + * ), * * @author Gyula Szabó - * @package */ -class sspmod_aa_Auth_Source_Bypass extends SimpleSAML_Auth_Source { - - /** - * Attribute name for the subject nameId - * - * @var string - **/ - private $uid; - - /** - * Constructor for this authentication source. - * - * @param array $info Information about this authentication source. - * @param array $config Configuration. - */ - public function __construct($info, $config) { - assert('is_array($info)'); - assert('is_array($config)'); - - /* Call the parent constructor first, as required by the interface. */ - parent::__construct($info, $config); - - if (!array_key_exists('uid', $config) || !is_string($config["uid"])) - throw new SimpleSAML_Error_Exception("AA configuration error, 'uid' not found or not a string."); - - SimpleSAML_Logger::debug('[aa] auth source Bypass: config uid: '. $config['uid']); - $this->uid = $config['uid']; - } - - - /** - * Log in and set the nameId attribute. - * - * @param array &$state Information about the current authentication. - */ - public function authenticate(&$state) { - assert('is_array($state)'); - - $state['Attributes'][$this->uid] = array($state["aa:nameId"]); - } - +class sspmod_aa_Auth_Source_Bypass extends SimpleSAML_Auth_Source +{ + /** + * Attribute name for the subject nameId. + * + * @var string + **/ + private $uid; + + /** + * Constructor for this authentication source. + * + * @param array $info Information about this authentication source. + * @param array $config Configuration. + */ + public function __construct($info, $config) + { + assert('is_array($info)'); + assert('is_array($config)'); + + /* Call the parent constructor first, as required by the interface. */ + parent::__construct($info, $config); + + if (!array_key_exists('uid', $config) || !is_string($config['uid'])) { + throw new SimpleSAML_Error_Exception("AA configuration error, 'uid' not found or not a string."); + } + + SimpleSAML_Logger::debug('[aa] auth source Bypass: config uid: '.$config['uid']); + $this->uid = $config['uid']; + } + + /** + * Log in and set the nameId attribute. + * + * @param array &$state Information about the current authentication. + */ + public function authenticate(&$state) + { + assert('is_array($state)'); + + $state['Attributes'][$this->uid] = array($state['aa:nameId']); + } } - -?> diff --git a/www/metadata.php b/www/metadata.php index eff7444..9784307 100644 --- a/www/metadata.php +++ b/www/metadata.php @@ -6,132 +6,129 @@ /* Check if valid local session exists.. */ if ($config->getBoolean('admin.protectmetadata', false)) { - SimpleSAML_Utilities::requireAdmin(); + SimpleSAML_Utilities::requireAdmin(); } - try { - $aaentityid = isset($_GET['aaentityid']) ? $_GET['aaentityid'] : $metadata->getMetaDataCurrentEntityID('attributeauthority-hosted'); - $aameta = $metadata->getMetaDataConfig($aaentityid, 'attributeauthority-hosted'); - - $availableCerts = array(); - - $keys = array(); - $certInfo = SimpleSAML_Utilities::loadPublicKey($aameta, FALSE, 'new_'); - if ($certInfo !== NULL) { - $availableCerts['new_aa.crt'] = $certInfo; - $keys[] = array( - 'type' => 'X509Certificate', - 'signing' => TRUE, - 'encryption' => TRUE, - 'X509Certificate' => $certInfo['certData'], - ); - $hasNewCert = TRUE; - } else { - $hasNewCert = FALSE; - } - - $certInfo = SimpleSAML_Utilities::loadPublicKey($aameta, TRUE); - $availableCerts['aa.crt'] = $certInfo; - $keys[] = array( - 'type' => 'X509Certificate', - 'signing' => TRUE, - 'encryption' => ($hasNewCert ? FALSE : TRUE), - 'X509Certificate' => $certInfo['certData'], - ); - - if ($aameta->hasValue('https.certificate')) { - $httpsCert = SimpleSAML_Utilities::loadPublicKey($aameta, TRUE, 'https.'); - assert('isset($httpsCert["certData"])'); - $availableCerts['https.crt'] = $httpsCert; - $keys[] = array( - 'type' => 'X509Certificate', - 'signing' => TRUE, - 'encryption' => FALSE, - 'X509Certificate' => $httpsCert['certData'], - ); - } - - $metaArray = array( - 'metadata-set' => 'attributeauthority-hosted', - 'entityid' => $aaentityid, - 'protocols' => array(SAML2_Const::NS_SAMLP), - 'AttributeService' => array(0 => array( - 'Binding' => SAML2_Const::BINDING_SOAP, - 'Location' => SimpleSAML_Utilities::getBaseURL() . 'module.php/aa/attributeserver.php', + $aaentityid = isset($_GET['aaentityid']) ? $_GET['aaentityid'] : $metadata->getMetaDataCurrentEntityID('attributeauthority-hosted'); + $aameta = $metadata->getMetaDataConfig($aaentityid, 'attributeauthority-hosted'); + + $availableCerts = array(); + + $keys = array(); + $certInfo = SimpleSAML_Utilities::loadPublicKey($aameta, false, 'new_'); + if ($certInfo !== null) { + $availableCerts['new_aa.crt'] = $certInfo; + $keys[] = array( + 'type' => 'X509Certificate', + 'signing' => true, + 'encryption' => true, + 'X509Certificate' => $certInfo['certData'], + ); + $hasNewCert = true; + } else { + $hasNewCert = false; + } + + $certInfo = SimpleSAML_Utilities::loadPublicKey($aameta, true); + $availableCerts['aa.crt'] = $certInfo; + $keys[] = array( + 'type' => 'X509Certificate', + 'signing' => true, + 'encryption' => ($hasNewCert ? false : true), + 'X509Certificate' => $certInfo['certData'], + ); + + if ($aameta->hasValue('https.certificate')) { + $httpsCert = SimpleSAML_Utilities::loadPublicKey($aameta, true, 'https.'); + assert('isset($httpsCert["certData"])'); + $availableCerts['https.crt'] = $httpsCert; + $keys[] = array( + 'type' => 'X509Certificate', + 'signing' => true, + 'encryption' => false, + 'X509Certificate' => $httpsCert['certData'], + ); + } + + $metaArray = array( + 'metadata-set' => 'attributeauthority-hosted', + 'entityid' => $aaentityid, + 'protocols' => array(SAML2_Const::NS_SAMLP), + 'AttributeService' => array(0 => array( + 'Binding' => SAML2_Const::BINDING_SOAP, + 'Location' => SimpleSAML_Utilities::getBaseURL().'module.php/aa/attributeserver.php', ), ), - ); - - if (count($keys) === 1) { - $metaArray['certData'] = $keys[0]['X509Certificate']; - } else { - $metaArray['keys'] = $keys; - } - - $metaArray['NameIDFormat'] = array( - SAML2_Const::NAMEID_PERSISTENT, - SAML2_Const::NAMEID_TRANSIENT - ); - - if ($aameta->hasValue('OrganizationName')) { - $metaArray['OrganizationName'] = $aameta->getLocalizedString('OrganizationName'); - $metaArray['OrganizationDisplayName'] = $aameta->getLocalizedString('OrganizationDisplayName', $metaArray['OrganizationName']); - - if (!$aameta->hasValue('OrganizationURL')) { - throw new SimpleSAML_Error_Exception('If OrganizationName is set, OrganizationURL must also be set.'); - } - $metaArray['OrganizationURL'] = $aameta->getLocalizedString('OrganizationURL'); - } - - if ($aameta->hasValue('scope')) { - $metaArray['scope'] = $aameta->getArray('scope'); - } - - $metaflat = '$metadata[' . var_export($aaentityid, TRUE) . '] = ' . var_export($metaArray, TRUE) . ';'; - - $metaBuilder = new SimpleSAML_Metadata_SAMLBuilder($aaentityid); - $metaBuilder->addAttributeAuthority($metaArray); - $metaBuilder->addOrganizationInfo($metaArray); - $technicalContactEmail = $config->getString('technicalcontact_email', NULL); - if ($technicalContactEmail && $technicalContactEmail !== 'na@example.org') { - $metaBuilder->addContact('technical', array( - 'emailAddress' => $technicalContactEmail, - 'name' => $config->getString('technicalcontact_name', NULL), - )); - } - $metaxml = $metaBuilder->getEntityDescriptorText(); - - /* Sign the metadata if enabled. */ - $metaxml = SimpleSAML_Metadata_Signer::sign($metaxml, $aameta->toArray(), 'SAML 2 IdP'); - - if (array_key_exists('output', $_GET) && $_GET['output'] == 'xhtml') { - $defaultaa = NULL; - - $t = new SimpleSAML_XHTML_Template($config, 'metadata.php', 'admin'); - - $t->data['header'] = 'saml20-aa'; - $t->data['metaurl'] = SimpleSAML_Utilities::selfURLNoQuery(); - $t->data['metadata'] = htmlspecialchars($metaxml); - $t->data['metadataflat'] = htmlspecialchars($metaflat); - $t->data['defaultaa'] = $defaultaa; - $t->show(); - - } else { - - header('Content-Type: application/xml'); - - echo $metaxml; - exit(0); - - } - - - -} catch(Exception $exception) { - - throw new SimpleSAML_Error_Error('METADATA', $exception); - + ); + + if (count($keys) === 1) { + $metaArray['certData'] = $keys[0]['X509Certificate']; + } else { + $metaArray['keys'] = $keys; + } + + $metaArray['NameIDFormat'] = array( + SAML2_Const::NAMEID_PERSISTENT, + SAML2_Const::NAMEID_TRANSIENT, + ); + + if ($aameta->hasValue('OrganizationName')) { + $metaArray['OrganizationName'] = $aameta->getLocalizedString('OrganizationName'); + $metaArray['OrganizationDisplayName'] = $aameta->getLocalizedString( + 'OrganizationDisplayName', + $metaArray['OrganizationName'] + ); + + if (!$aameta->hasValue('OrganizationURL')) { + throw new SimpleSAML_Error_Exception('If OrganizationName is set, OrganizationURL must also be set.'); + } + $metaArray['OrganizationURL'] = $aameta->getLocalizedString('OrganizationURL'); + } + + if ($aameta->hasValue('scope')) { + $metaArray['scope'] = $aameta->getArray('scope'); + } + + $metaflat = '$metadata['.var_export($aaentityid, true).'] = '.var_export($metaArray, true).';'; + + $metaBuilder = new SimpleSAML_Metadata_SAMLBuilder($aaentityid); + $metaBuilder->addAttributeAuthority($metaArray); + $metaBuilder->addOrganizationInfo($metaArray); + $technicalContactEmail = $config->getString('technicalcontact_email', null); + $technicalContactName = $config->getString('technicalcontact_name', null); + if ($technicalContactEmail and $technicalContactEmail !== 'na@example.org') { + $metaBuilder->addContact( + 'technical', + array( + 'contactType' => 'technical', + 'emailAddress' => $technicalContactEmail, + 'name' => $technicalContactName + ) + ); + } + $metaxml = $metaBuilder->getEntityDescriptorText(); + + /* Sign the metadata if enabled. */ + $metaxml = SimpleSAML_Metadata_Signer::sign($metaxml, $aameta->toArray(), 'SAML 2 IdP'); + + if (array_key_exists('output', $_GET) && $_GET['output'] == 'xhtml') { + $defaultaa = null; + + $t = new SimpleSAML_XHTML_Template($config, 'metadata.php', 'admin'); + + $t->data['header'] = 'saml20-aa'; + $t->data['metaurl'] = SimpleSAML_Utilities::selfURLNoQuery(); + $t->data['metadata'] = htmlspecialchars($metaxml); + $t->data['metadataflat'] = htmlspecialchars($metaflat); + $t->data['defaultaa'] = $defaultaa; + $t->show(); + } else { + header('Content-Type: application/xml'); + + echo $metaxml; + exit(0); + } +} catch (Exception $exception) { + throw new SimpleSAML_Error_Error('METADATA', $exception); } - -?>