/** * Initialize a AffiliationDescriptor. * * @param DOMElement|NULL $xml The XML element we should load. */ public function __construct(DOMElement $xml = NULL) { parent::__construct($xml); if ($xml === NULL) { return; } if (!$xml->hasAttribute('affiliationOwnerID')) { throw new Exception('Missing affiliationOwnerID on AffiliationDescriptor.'); } $this->affiliationOwnerID = $xml->getAttribute('affiliationOwnerID'); if ($xml->hasAttribute('ID')) { $this->ID = $xml->getAttribute('ID'); } if ($xml->hasAttribute('validUntil')) { $this->validUntil = SimpleSAML_Utilities::parseSAML2Time($xml->getAttribute('validUntil')); } if ($xml->hasAttribute('cacheDuration')) { $this->cacheDuration = $xml->getAttribute('cacheDuration'); } $this->Extensions = SAML2_XML_md_Extensions::getList($xml); $this->AffiliateMember = SAML2_Utils::extractStrings($xml, './saml_metadata:AffiliateMember'); if (empty($this->AffiliateMember)) { throw new Exception('Missing AffiliateMember in AffiliationDescriptor.'); } foreach (SAML2_Utils::xpQuery($xml, './saml_metadata:KeyDescriptor') as $kd) { $this->KeyDescriptor[] = new SAML2_XML_md_KeyDescriptor($kd); } }
/** * Initialize an EntitiesDescriptor. * * @param DOMElement|NULL $xml The XML element we should load. */ public function __construct(DOMElement $xml = NULL) { parent::__construct($xml); if ($xml === NULL) { return; } if ($xml->hasAttribute('ID')) { $this->ID = $xml->getAttribute('ID'); } if ($xml->hasAttribute('validUntil')) { $this->validUntil = SimpleSAML_Utilities::parseSAML2Time($xml->getAttribute('validUntil')); } if ($xml->hasAttribute('cacheDuration')) { $this->cacheDuration = $xml->getAttribute('cacheDuration'); } if ($xml->hasAttribute('Name')) { $this->Name = $xml->getAttribute('Name'); } $this->Extensions = SAML2_XML_md_Extensions::getList($xml); foreach (SAML2_Utils::xpQuery($xml, './saml_metadata:EntityDescriptor|./saml_metadata:EntitiesDescriptor') as $node) { if ($node->localName === 'EntityDescriptor') { $this->children[] = new SAML2_XML_md_EntityDescriptor($node); } else { $this->children[] = new SAML2_XML_md_EntitiesDescriptor($node); } } }
/** * Constructor for SAML 2 logout request messages. * * @param DOMElement|NULL $xml The input message. */ public function __construct(DOMElement $xml = NULL) { parent::__construct('LogoutRequest', $xml); $this->sessionIndexes = array(); if ($xml === NULL) { return; } if ($xml->hasAttribute('NotOnOrAfter')) { $this->notOnOrAfter = SimpleSAML_Utilities::parseSAML2Time($xml->getAttribute('NotOnOrAfter')); } $nameId = SAML2_Utils::xpQuery($xml, './saml_assertion:NameID | ./saml_assertion:EncryptedID/xenc:EncryptedData'); if (empty($nameId)) { throw new Exception('Missing <saml:NameID> or <saml:EncryptedID> in <samlp:LogoutRequest>.'); } elseif (count($nameId) > 1) { throw new Exception('More than one <saml:NameID> or <saml:EncryptedD> in <samlp:LogoutRequest>.'); } $nameId = $nameId[0]; if ($nameId->localName === 'EncryptedData') { /* The NameID element is encrypted. */ $this->encryptedNameId = $nameId; } else { $this->nameId = SAML2_Utils::parseNameId($nameId); } $sessionIndexes = SAML2_Utils::xpQuery($xml, './saml_protocol:SessionIndex'); foreach ($sessionIndexes as $sessionIndex) { $this->sessionIndexes[] = trim($sessionIndex->textContent); } }
/** * Create/parse a mdrpi:RegistrationInfo element. * * @param DOMElement|NULL $xml The XML element we should load. */ public function __construct(DOMElement $xml = NULL) { if ($xml === NULL) { return; } if (!$xml->hasAttribute('registrationAuthority')) { throw new Exception('Missing required attribute "registrationAuthority" in mdrpi:RegistrationInfo element.'); } $this->registrationAuthority = $xml->getAttribute('registrationAuthority'); if ($xml->hasAttribute('registrationInstant')) { $this->registrationInstant = SimpleSAML_Utilities::parseSAML2Time($xml->getAttribute('registrationInstant')); } $this->RegistrationPolicy = SAML2_Utils::extractLocalizedStrings($xml, SAML2_XML_mdrpi_Common::NS_MDRPI, 'RegistrationPolicy'); }
/** * Create/parse a mdrpi:PublicationInfo element. * * @param DOMElement|NULL $xml The XML element we should load. */ public function __construct(DOMElement $xml = NULL) { if ($xml === NULL) { return; } if (!$xml->hasAttribute('publisher')) { throw new Exception('Missing required attribute "publisher" in mdrpi:PublicationInfo element.'); } $this->publisher = $xml->getAttribute('publisher'); if ($xml->hasAttribute('creationInstant')) { $this->creationInstant = SimpleSAML_Utilities::parseSAML2Time($xml->getAttribute('creationInstant')); } if ($xml->hasAttribute('publicationId')) { $this->publicationId = $xml->getAttribute('publicationId'); } $this->UsagePolicy = SAML2_Utils::extractLocalizedStrings($xml, SAML2_XML_mdrpi_Common::NS_MDRPI, 'UsagePolicy'); }
/** * Initialize (and parse? a SubjectConfirmationData element. * * @param DOMElement|NULL $xml The XML element we should load. */ public function __construct(DOMElement $xml = NULL) { if ($xml === NULL) { return; } if ($xml->hasAttribute('NotBefore')) { $this->NotBefore = SimpleSAML_Utilities::parseSAML2Time($xml->getAttribute('NotBefore')); } if ($xml->hasAttribute('NotOnOrAfter')) { $this->NotOnOrAfter = SimpleSAML_Utilities::parseSAML2Time($xml->getAttribute('NotOnOrAfter')); } if ($xml->hasAttribute('Recipient')) { $this->Recipient = $xml->getAttribute('Recipient'); } if ($xml->hasAttribute('InResponseTo')) { $this->InResponseTo = $xml->getAttribute('InResponseTo'); } if ($xml->hasAttribute('Address')) { $this->Address = $xml->getAttribute('Address'); } }
/** * Initialize (and parse) a SubjectConfirmationData element. * * @param DOMElement|NULL $xml The XML element we should load. */ public function __construct(DOMElement $xml = NULL) { if ($xml === NULL) { return; } if ($xml->hasAttribute('NotBefore')) { $this->NotBefore = SimpleSAML_Utilities::parseSAML2Time($xml->getAttribute('NotBefore')); } if ($xml->hasAttribute('NotOnOrAfter')) { $this->NotOnOrAfter = SimpleSAML_Utilities::parseSAML2Time($xml->getAttribute('NotOnOrAfter')); } if ($xml->hasAttribute('Recipient')) { $this->Recipient = $xml->getAttribute('Recipient'); } if ($xml->hasAttribute('InResponseTo')) { $this->InResponseTo = $xml->getAttribute('InResponseTo'); } if ($xml->hasAttribute('Address')) { $this->Address = $xml->getAttribute('Address'); } for ($n = $xml->firstChild; $n !== NULL; $n = $n->nextSibling) { if (!$n instanceof DOMElement) { continue; } if ($n->namespaceURI !== XMLSecurityDSig::XMLDSIGNS) { $this->info[] = new SAML2_XML_Chunk($n); continue; } switch ($n->localName) { case 'KeyInfo': $this->info[] = new SAML2_XML_ds_KeyInfo($n); break; default: $this->info[] = new SAML2_XML_Chunk($n); break; } } }
/** * Parse AuthnStatement in assertion. * * @param DOMElement $xml The assertion XML element. */ private function parseAuthnStatement(DOMElement $xml) { $as = SAML2_Utils::xpQuery($xml, './saml_assertion:AuthnStatement'); if (empty($as)) { $this->authnInstant = NULL; return; } elseif (count($as) > 1) { throw new Exception('More that one <saml:AuthnStatement> in <saml:Assertion> not supported.'); } $as = $as[0]; $this->authnStatement = array(); if (!$as->hasAttribute('AuthnInstant')) { throw new Exception('Missing required AuthnInstant attribute on <saml:AuthnStatement>.'); } $this->authnInstant = SimpleSAML_Utilities::parseSAML2Time($as->getAttribute('AuthnInstant')); if ($as->hasAttribute('SessionNotOnOrAfter')) { $this->sessionNotOnOrAfter = SimpleSAML_Utilities::parseSAML2Time($as->getAttribute('SessionNotOnOrAfter')); } if ($as->hasAttribute('SessionIndex')) { $this->sessionIndex = $as->getAttribute('SessionIndex'); } $ac = SAML2_Utils::xpQuery($as, './saml_assertion:AuthnContext'); if (empty($ac)) { throw new Exception('Missing required <saml:AuthnContext> in <saml:AuthnStatement>.'); } elseif (count($ac) > 1) { throw new Exception('More than one <saml:AuthnContext> in <saml:AuthnStatement>.'); } $ac = $ac[0]; $accr = SAML2_Utils::xpQuery($ac, './saml_assertion:AuthnContextClassRef'); if (empty($accr)) { $acdr = SAML2_Utils::xpQuery($ac, './saml_assertion:AuthnContextDeclRef'); if (empty($acdr)) { throw new Exception('Neither <saml:AuthnContextClassRef> nor <saml:AuthnContextDeclRef> found in <saml:AuthnContext>.'); } elseif (count($accr) > 1) { throw new Exception('More than one <saml:AuthnContextDeclRef> in <saml:AuthnContext>.'); } $this->authnContext = trim($acdr[0]->textContent); } elseif (count($accr) > 1) { throw new Exception('More than one <saml:AuthnContextClassRef> in <saml:AuthnContext>.'); } else { $this->authnContext = trim($accr[0]->textContent); } $this->AuthenticatingAuthority = SAML2_Utils::extractStrings($ac, SAML2_Const::NS_SAML, 'AuthenticatingAuthority'); }
/** * Initialize a message. * * This constructor takes an optional parameter with a DOMElement. If this * parameter is given, the message will be initialized with data from that * XML element. * * If no XML element is given, the message is initialized with suitable * default values. * * @param string $tagName The tag name of the root element. * @param DOMElement|NULL $xml The input message. */ protected function __construct($tagName, DOMElement $xml = NULL) { assert('is_string($tagName)'); $this->tagName = $tagName; $this->id = SimpleSAML_Utilities::generateID(); $this->issueInstant = time(); $this->certificates = array(); $this->validators = array(); if ($xml === NULL) { return; } if (!$xml->hasAttribute('ID')) { throw new Exception('Missing ID attribute on SAML message.'); } $this->id = $xml->getAttribute('ID'); if ($xml->getAttribute('Version') !== '2.0') { /* Currently a very strict check. */ throw new Exception('Unsupported version: ' . $xml->getAttribute('Version')); } $this->issueInstant = SimpleSAML_Utilities::parseSAML2Time($xml->getAttribute('IssueInstant')); if ($xml->hasAttribute('Destination')) { $this->destination = $xml->getAttribute('Destination'); } $issuer = SAML2_Utils::xpQuery($xml, './saml_assertion:Issuer'); if (!empty($issuer)) { $this->issuer = trim($issuer[0]->textContent); } /* Validate the signature element of the message. */ try { $sig = SAML2_Utils::validateElement($xml); if ($sig !== FALSE) { $this->certificates = $sig['Certificates']; $this->validators[] = array('Function' => array('SAML2_Utils', 'validateSignature'), 'Data' => $sig); } } catch (Exception $e) { /* Ignore signature validation errors. */ } }
/** * Determine how long a given element can be cached. * * This function looks for the 'cacheDuration' and 'validUntil' attributes to determine * how long a given XML-element is valid. It returns this as na unix timestamp. * * If both the 'cacheDuration' and 'validUntil' attributes are present, the shorter of them * will be returned. * * @param DOMElement $element The element we should determine the expiry time of. * @return int The unix timestamp for when the element should expire. Will be NULL if no * limit is set for the element. */ private static function getExpireTime(DOMElement $element) { if ($element->hasAttribute('cacheDuration')) { $cacheDuration = $element->getAttribute('cacheDuration'); $cacheDuration = SimpleSAML_Utilities::parseDuration($cacheDuration, time()); } else { $cacheDuration = NULL; } if ($element->hasAttribute('validUntil')) { $validUntil = $element->getAttribute('validUntil'); $validUntil = SimpleSAML_Utilities::parseSAML2Time($validUntil); } else { $validUntil = NULL; } if ($cacheDuration !== NULL && $validUntil !== NULL) { /* Both are given. Return the shortest. */ if ($cacheDuration < $validUntil) { return $cacheDuration; } else { return $validUntil; } } elseif ($cacheDuration !== NULL) { return $cacheDuration; } elseif ($validUntil !== NULL) { return $validUntil; } else { return NULL; } }
/** * Initialize an EntitiyDescriptor. * * @param DOMElement|NULL $xml The XML element we should load. */ public function __construct(DOMElement $xml = NULL) { parent::__construct($xml); if ($xml === NULL) { return; } if (!$xml->hasAttribute('entityID')) { throw new Exception('Missing required attribute entityID on EntityDescriptor.'); } $this->entityID = $xml->getAttribute('entityID'); if ($xml->hasAttribute('ID')) { $this->ID = $xml->getAttribute('ID'); } if ($xml->hasAttribute('validUntil')) { $this->validUntil = SimpleSAML_Utilities::parseSAML2Time($xml->getAttribute('validUntil')); } if ($xml->hasAttribute('cacheDuration')) { $this->cacheDuration = $xml->getAttribute('cacheDuration'); } $this->Extensions = SAML2_XML_md_Extensions::getList($xml); for ($node = $xml->firstChild; $node !== NULL; $node = $node->nextSibling) { if (!$node instanceof DOMElement) { continue; } if ($node->namespaceURI !== SAML2_Const::NS_MD) { continue; } switch ($node->localName) { case 'RoleDescriptor': $this->RoleDescriptor[] = new SAML2_XML_md_UnknownRoleDescriptor($node); break; case 'IDPSSODescriptor': $this->RoleDescriptor[] = new SAML2_XML_md_IDPSSODescriptor($node); break; case 'SPSSODescriptor': $this->RoleDescriptor[] = new SAML2_XML_md_SPSSODescriptor($node); break; case 'AuthnAuthorityDescriptor': $this->RoleDescriptor[] = new SAML2_XML_md_AuthnAuthorityDescriptor($node); break; case 'AttributeAuthorityDescriptor': $this->RoleDescriptor[] = new SAML2_XML_md_AttributeAuthorityDescriptor($node); break; case 'PDPDescriptor': $this->RoleDescriptor[] = new SAML2_XML_md_PDPDescriptor($node); break; } } $affiliationDescriptor = SAML2_Utils::xpQuery($xml, './saml_metadata:AffiliationDescriptor'); if (count($affiliationDescriptor) > 1) { throw new Exception('More than one AffiliationDescriptor in the entity.'); } elseif (!empty($affiliationDescriptor)) { $this->AffiliationDescriptor = new SAML2_XML_md_AffiliationDescriptor($affiliationDescriptor[0]); } if (empty($this->RoleDescriptor) && is_null($this->AffiliationDescriptor)) { throw new Exception('Must have either one of the RoleDescriptors or an AffiliationDescriptor in EntityDescriptor.'); } elseif (!empty($this->RoleDescriptor) && !is_null($this->AffiliationDescriptor)) { throw new Exception('AffiliationDescriptor cannot be combined with other RoleDescriptor elements in EntityDescriptor.'); } $organization = SAML2_Utils::xpQuery($xml, './saml_metadata:Organization'); if (count($organization) > 1) { throw new Exception('More than one Organization in the entity.'); } elseif (!empty($organization)) { $this->Organization = new SAML2_XML_md_Organization($organization[0]); } foreach (SAML2_Utils::xpQuery($xml, './saml_metadata:ContactPerson') as $cp) { $this->ContactPerson[] = new SAML2_XML_md_ContactPerson($cp); } foreach (SAML2_Utils::xpQuery($xml, './saml_metadata:AdditionalMetadataLocation') as $aml) { $this->AdditionalMetadataLocation[] = new SAML2_XML_md_AdditionalMetadataLocation($aml); } }
/** * Initialize a RoleDescriptor. * * @param string $elementName The name of this element. * @param DOMElement|NULL $xml The XML element we should load. */ protected function __construct($elementName, DOMElement $xml = NULL) { assert('is_string($elementName)'); parent::__construct($xml); $this->elementName = $elementName; if ($xml === NULL) { return; } if ($xml->hasAttribute('ID')) { $this->ID = $xml->getAttribute('ID'); } if ($xml->hasAttribute('validUntil')) { $this->validUntil = SimpleSAML_Utilities::parseSAML2Time($xml->getAttribute('validUntil')); } if ($xml->hasAttribute('cacheDuration')) { $this->cacheDuration = $xml->getAttribute('cacheDuration'); } if (!$xml->hasAttribute('protocolSupportEnumeration')) { throw new Exception('Missing protocolSupportEnumeration attribute on ' . $xml->localName); } $this->protocolSupportEnumeration = preg_split('/[\\s]+/', $xml->getAttribute('protocolSupportEnumeration')); if ($xml->hasAttribute('errorURL')) { $this->errorURL = $xml->getAttribute('errorURL'); } $this->Extensions = SAML2_XML_md_Extensions::getList($xml); foreach (SAML2_Utils::xpQuery($xml, './saml_metadata:KeyDescriptor') as $kd) { $this->KeyDescriptor[] = new SAML2_XML_md_KeyDescriptor($kd); } $organization = SAML2_Utils::xpQuery($xml, './saml_metadata:Organization'); if (count($organization) > 1) { throw new Exception('More than one Organization in the entity.'); } elseif (!empty($organization)) { $this->Organization = new SAML2_XML_md_Organization($organization[0]); } foreach (SAML2_Utils::xpQuery($xml, './saml_metadata:ContactPerson') as $cp) { $this->contactPersons[] = new SAML2_XML_md_ContactPerson($cp); } }