23        'urn:oasis:names:tc:SAML:1.0:protocol',
 
   24        'urn:oasis:names:tc:SAML:1.1:protocol',
 
   33        'urn:oasis:names:tc:SAML:2.0:protocol',
 
  150        \
SAML2\XML\md\EntityDescriptor $entityElement,
 
  153        array $parentExtensions = array()
 
  155        assert($maxExpireTime === 
null || is_int($maxExpireTime));
 
  157        $this->spDescriptors = array();
 
  158        $this->idpDescriptors = array();
 
  160        $e = $entityElement->toXML();
 
  161        $e = $e->ownerDocument->saveXML($e);
 
  162        $this->entityDescriptor = base64_encode($e);
 
  163        $this->entityId = $entityElement->entityID;
 
  168        $this->validators[] = $entityElement;
 
  172        $this->scopes = $ext[
'scope'];
 
  173        $this->tags = $ext[
'tags'];
 
  174        $this->entityAttributes = $ext[
'EntityAttributes'];
 
  175        $this->registrationInfo = $ext[
'RegistrationInfo'];
 
  178        foreach ($entityElement->RoleDescriptor as $child) {
 
  179            if ($child instanceof \
SAML2\XML\md\SPSSODescriptor) {
 
  181            } elseif ($child instanceof \
SAML2\XML\md\IDPSSODescriptor) {
 
  183            } elseif ($child instanceof \
SAML2\XML\md\AttributeAuthorityDescriptor) {
 
  188        if ($entityElement->Organization) {
 
  192        if (!empty($entityElement->ContactPerson)) {
 
  193            foreach ($entityElement->ContactPerson as $contact) {
 
  214        } 
catch (\Exception $e) {
 
  215            throw new Exception(
'Failed to read XML from file: '.$file);
 
  234        } 
catch (\Exception $e) {
 
  235            throw new Exception(
'Failed to parse XML string.');
 
  251        assert($document instanceof DOMDocument);
 
  269        assert($entityElement instanceof \
SAML2\XML\md\EntityDescriptor);
 
  287        if ($file === 
null) {
 
  288            throw new Exception(
'Cannot open file NULL. File name not specified.');
 
  295        } 
catch (\Exception $e) {
 
  296            throw new Exception(
'Failed to read XML from file: '.$file);
 
  299        if ($doc->documentElement === 
null) {
 
  300            throw new Exception(
'Opened file is not an XML document: '.$file);
 
  322        } 
catch (\Exception $e) {
 
  323            throw new Exception(
'Failed to parse XML string.');
 
  343        if ($element === 
null) {
 
  344            throw new Exception(
'Document was empty.');
 
  347        if (
SimpleSAML\Utils\XML::isDOMNodeOfType($element, 
'EntityDescriptor', 
'@md') === 
true) {
 
  348            return self::processDescriptorsElement(
new \
SAML2\XML\md\EntityDescriptor($element));
 
  349        } elseif (
SimpleSAML\Utils\XML::isDOMNodeOfType($element, 
'EntitiesDescriptor', 
'@md') === 
true) {
 
  350            return self::processDescriptorsElement(
new \
SAML2\XML\md\EntitiesDescriptor($element));
 
  352            throw new Exception(
'Unexpected root node: ['.$element->namespaceURI.
']:'.$element->localName);
 
  369    private static function processDescriptorsElement(
 
  371        $maxExpireTime = 
null,
 
  373        array $parentExtensions = array()
 
  375        assert($maxExpireTime === 
null || is_int($maxExpireTime));
 
  377        if ($element instanceof \
SAML2\XML\md\EntityDescriptor) {
 
  384        assert($element instanceof \
SAML2\XML\md\EntitiesDescriptor);
 
  392        foreach ($element->children as $child) {
 
  393            $ret += self::processDescriptorsElement($child, $expTime, 
$validators, $extensions);
 
  415        $expire = $element->validUntil;
 
  417        if ($maxExpireTime !== 
null && (
$expire === 
null || $maxExpireTime < 
$expire)) {
 
  443        if (!empty($this->organizationName)) {
 
  447        if (!empty($this->organizationDisplayName)) {
 
  451        if (!empty($this->organizationURL)) {
 
  471        assert(array_key_exists(
'scope', $roleDescriptor));
 
  472        assert(array_key_exists(
'tags', $roleDescriptor));
 
  474        $scopes = array_merge($this->scopes, array_diff($roleDescriptor[
'scope'], $this->scopes));
 
  479        $tags = array_merge($this->tags, array_diff($roleDescriptor[
'tags'], $this->tags));
 
  485        if (!empty($this->registrationInfo)) {
 
  489        if (!empty($this->entityAttributes)) {
 
  498        if (!empty($roleDescriptor[
'UIInfo'])) {
 
  499            $metadata[
'UIInfo'] = $roleDescriptor[
'UIInfo'];
 
  502        if (!empty($roleDescriptor[
'DiscoHints'])) {
 
  503            $metadata[
'DiscoHints'] = $roleDescriptor[
'DiscoHints'];
 
  523        $ret[
'metadata-set'] = 
'shib13-sp-remote';
 
  528        if (count($spd) === 0) {
 
  536        if (array_key_exists(
'expire', $spd)) {
 
  537            $ret[
'expire'] = $spd[
'expire'];
 
  541        $ret[
'AssertionConsumerService'] = $spd[
'AssertionConsumerService'];
 
  544        if (array_key_exists(
'attributes', $spd)) {
 
  545            $ret[
'attributes'] = $spd[
'attributes'];
 
  547        if (array_key_exists(
'attributes.required', $spd)) {
 
  548            $ret[
'attributes.required'] = $spd[
'attributes.required'];
 
  550        if (array_key_exists(
'attributes.NameFormat', $spd)) {
 
  551            $ret[
'attributes.NameFormat'] = $spd[
'attributes.NameFormat'];
 
  555        if (array_key_exists(
'name', $spd)) {
 
  556            $ret[
'name'] = $spd[
'name'];
 
  558        if (array_key_exists(
'description', $spd)) {
 
  559            $ret[
'description'] = $spd[
'description'];
 
  563        if (!empty($spd[
'keys'])) {
 
  564            $ret[
'keys'] = $spd[
'keys'];
 
  571        if (!empty(
$ret[
'UIInfo'][
'DisplayName'])) {
 
  572            $ret[
'name'] = 
$ret[
'UIInfo'][
'DisplayName'];
 
  597        $ret[
'metadata-set'] = 
'shib13-idp-remote';
 
  601        if (count(
$idp) === 0) {
 
  609        if (array_key_exists(
'expire', 
$idp)) {
 
  614        $ret[
'SingleSignOnService'] = 
$idp[
'SingleSignOnService'];
 
  617        $ret[
'ArtifactResolutionService'] = 
$idp[
'ArtifactResolutionService'];
 
  620        if (!empty(
$idp[
'keys'])) {
 
  628        if (!empty(
$ret[
'UIInfo'][
'DisplayName'])) {
 
  629            $ret[
'name'] = 
$ret[
'UIInfo'][
'DisplayName'];
 
  653        $ret[
'metadata-set'] = 
'saml20-sp-remote';
 
  657        if (count($spd) === 0) {
 
  665        if (array_key_exists(
'expire', $spd)) {
 
  666            $ret[
'expire'] = $spd[
'expire'];
 
  670        $ret[
'AssertionConsumerService'] = $spd[
'AssertionConsumerService'];
 
  674        $ret[
'SingleLogoutService'] = $spd[
'SingleLogoutService'];
 
  678        if (count($spd[
'nameIDFormats']) > 0) {
 
  680            $ret[
'NameIDFormat'] = $spd[
'nameIDFormats'][0];
 
  684        if (array_key_exists(
'attributes', $spd)) {
 
  685            $ret[
'attributes'] = $spd[
'attributes'];
 
  687        if (array_key_exists(
'attributes.required', $spd)) {
 
  688            $ret[
'attributes.required'] = $spd[
'attributes.required'];
 
  690        if (array_key_exists(
'attributes.NameFormat', $spd)) {
 
  691            $ret[
'attributes.NameFormat'] = $spd[
'attributes.NameFormat'];
 
  693        if (array_key_exists(
'attributes.index', $spd)) {
 
  694            $ret[
'attributes.index'] = $spd[
'attributes.index'];
 
  696        if (array_key_exists(
'attributes.isDefault', $spd)) {
 
  697            $ret[
'attributes.isDefault'] = $spd[
'attributes.isDefault'];
 
  701        if (array_key_exists(
'name', $spd)) {
 
  702            $ret[
'name'] = $spd[
'name'];
 
  704        if (array_key_exists(
'description', $spd)) {
 
  705            $ret[
'description'] = $spd[
'description'];
 
  709        if (!empty($spd[
'keys'])) {
 
  710            $ret[
'keys'] = $spd[
'keys'];
 
  714        if (array_key_exists(
'AuthnRequestsSigned', $spd)) {
 
  715            $ret[
'validate.authnrequest'] = $spd[
'AuthnRequestsSigned'];
 
  719        if (array_key_exists(
'WantAssertionsSigned', $spd)) {
 
  720            $ret[
'saml20.sign.assertion'] = $spd[
'WantAssertionsSigned'];
 
  727        if (!empty(
$ret[
'UIInfo'][
'DisplayName'])) {
 
  728            $ret[
'name'] = 
$ret[
'UIInfo'][
'DisplayName'];
 
  756        $ret[
'metadata-set'] = 
'saml20-idp-remote';
 
  760        if (count(
$idp) === 0) {
 
  768        if (array_key_exists(
'expire', 
$idp)) {
 
  773        if (
$idp[
'WantAuthnRequestsSigned']) {
 
  774            $ret[
'sign.authnrequest'] = 
true;
 
  778        $ret[
'SingleSignOnService'] = 
$idp[
'SingleSignOnService'];
 
  781        $ret[
'SingleLogoutService'] = 
$idp[
'SingleLogoutService'];
 
  784        $ret[
'ArtifactResolutionService'] = 
$idp[
'ArtifactResolutionService'];
 
  787        $ret[
'NameIDFormats'] = 
$idp[
'nameIDFormats'];
 
  790        if (!empty(
$idp[
'keys'])) {
 
  798        if (!empty(
$ret[
'UIInfo'][
'DisplayName'])) {
 
  799            $ret[
'name'] = 
$ret[
'UIInfo'][
'DisplayName'];
 
  833        assert($expireTime === 
null || is_int($expireTime));
 
  839        if ($expireTime !== 
null) {
 
  841            $ret[
'expire'] = $expireTime;
 
  844        $ret[
'protocols'] = $element->protocolSupportEnumeration;
 
  847        $ret[
'keys'] = array();
 
  848        foreach ($element->KeyDescriptor as $kd) {
 
  856        $ret[
'scope'] = $ext[
'scope'];
 
  857        $ret[
'tags'] = $ext[
'tags'];
 
  858        $ret[
'EntityAttributes'] = $ext[
'EntityAttributes'];
 
  859        $ret[
'UIInfo'] = $ext[
'UIInfo'];
 
  860        $ret[
'DiscoHints'] = $ext[
'DiscoHints'];
 
  884        assert($expireTime === 
null || is_int($expireTime));
 
  896        $sd[
'nameIDFormats'] = $element->NameIDFormat;
 
  911        assert($expireTime === 
null || is_int($expireTime));
 
  919        $attcs = $element->AttributeConsumingService;
 
  920        if (count($attcs) > 0) {
 
  925        if ($element->AuthnRequestsSigned !== 
null) {
 
  926            $sp[
'AuthnRequestsSigned'] = $element->AuthnRequestsSigned;
 
  930        if ($element->WantAssertionsSigned !== 
null) {
 
  931            $sp[
'WantAssertionsSigned'] = $element->WantAssertionsSigned;
 
  934        $this->spDescriptors[] = $sp;
 
  947        assert($expireTime === 
null || is_int($expireTime));
 
  954        if ($element->WantAuthnRequestsSigned) {
 
  955            $idp[
'WantAuthnRequestsSigned'] = 
true;
 
  957            $idp[
'WantAuthnRequestsSigned'] = 
false;
 
  960        $this->idpDescriptors[] = 
$idp;
 
  972        \
SAML2\XML\md\AttributeAuthorityDescriptor $element,
 
  975        assert($expireTime === 
null || is_int($expireTime));
 
  979        $aad[
'metadata-set'] = 
'attributeauthority-remote';
 
  983        $aad[
'NameIDFormat'] = $element->NameIDFormat;
 
  985        $this->attributeAuthorityDescriptors[] = $aad;
 
 1003            'EntityAttributes' => array(),
 
 1004            'RegistrationInfo' => array(),
 
 1005            'UIInfo'           => array(),
 
 1006            'DiscoHints'       => array(),
 
 1010        if (($element instanceof \
SAML2\XML\md\EntityDescriptor || $element instanceof \
SAML2\XML\md\EntitiesDescriptor)
 
 1011                && !empty($parentExtensions[
'RegistrationInfo'])) {
 
 1012            $ret[
'RegistrationInfo'] = $parentExtensions[
'RegistrationInfo'];
 
 1015        foreach ($element->Extensions as $e) {
 
 1016            if ($e instanceof \
SAML2\XML\shibmd\Scope) {
 
 1017                $ret[
'scope'][] = $e->scope;
 
 1022            if ($element instanceof \
SAML2\XML\md\EntityDescriptor ||
 
 1023                $element instanceof \
SAML2\XML\md\EntitiesDescriptor) {
 
 1024                if ($e instanceof \
SAML2\XML\mdrpi\RegistrationInfo) {
 
 1026                    if (isset(
$ret[
'RegistrationInfo'][
'registrationAuthority'])
 
 1027                        && 
$ret[
'RegistrationInfo'][
'registrationAuthority'] !== $e->registrationAuthority) {
 
 1029                          . 
$ret[
'RegistrationInfo'][
'registrationAuthority'] . 
"' with '{$e->registrationAuthority}'");
 
 1031                        $ret[
'RegistrationInfo'][
'registrationAuthority'] = $e->registrationAuthority;
 
 1034                if ($e instanceof \
SAML2\XML\mdattr\EntityAttributes && !empty($e->children)) {
 
 1035                    foreach ($e->children as $attr) {
 
 1038                        if ($attr instanceof \
SAML2\XML\saml\Attribute) {
 
 1039                            if (empty($attr->Name) || empty($attr->AttributeValue)) {
 
 1044                            $name = $attr->Name;
 
 1045                            if (empty($attr->NameFormat)) {
 
 1046                                $name = 
'{'.\SAML2\Constants::NAMEFORMAT_UNSPECIFIED.
'}'.$attr->Name;
 
 1047                            } elseif ($attr->NameFormat !== 
'urn:oasis:names:tc:SAML:2.0:attrname-format:uri') {
 
 1048                                $name = 
'{'.$attr->NameFormat.
'}'.$attr->Name;
 
 1052                            foreach ($attr->AttributeValue as $attrvalue) {
 
 1053                                $values[] = $attrvalue->getString();
 
 1063            if ($element instanceof \
SAML2\XML\md\RoleDescriptor) {
 
 1064                if ($e instanceof \
SAML2\XML\mdui\UIInfo) {
 
 1065                    $ret[
'UIInfo'][
'DisplayName'] = $e->DisplayName;
 
 1066                    $ret[
'UIInfo'][
'Description'] = $e->Description;
 
 1067                    $ret[
'UIInfo'][
'InformationURL'] = $e->InformationURL;
 
 1068                    $ret[
'UIInfo'][
'PrivacyStatementURL'] = $e->PrivacyStatementURL;
 
 1070                    foreach ($e->Keywords as $uiItem) {
 
 1071                        if (!($uiItem instanceof \
SAML2\XML\mdui\Keywords)
 
 1072                            || empty($uiItem->Keywords)
 
 1073                            || empty($uiItem->lang)
 
 1077                        $ret[
'UIInfo'][
'Keywords'][$uiItem->lang] = $uiItem->Keywords;
 
 1079                    foreach ($e->Logo as $uiItem) {
 
 1080                        if (!($uiItem instanceof \
SAML2\XML\mdui\Logo)
 
 1081                            || empty($uiItem->url)
 
 1082                            || empty($uiItem->height)
 
 1083                            || empty($uiItem->width)
 
 1088                            'url'    => $uiItem->url,
 
 1089                            'height' => $uiItem->height,
 
 1090                            'width'  => $uiItem->width,
 
 1092                        if (!empty($uiItem->lang)) {
 
 1093                            $logo[
'lang'] = $uiItem->lang;
 
 1095                        $ret[
'UIInfo'][
'Logo'][] = $logo;
 
 1101            if ($element instanceof \
SAML2\XML\md\IDPSSODescriptor) {
 
 1102                if ($e instanceof \
SAML2\XML\mdui\DiscoHints) {
 
 1103                    $ret[
'DiscoHints'][
'IPHint'] = $e->IPHint;
 
 1104                    $ret[
'DiscoHints'][
'DomainHint'] = $e->DomainHint;
 
 1105                    $ret[
'DiscoHints'][
'GeolocationHint'] = $e->GeolocationHint;
 
 1109            if (!($e instanceof \
SAML2\XML\Chunk)) {
 
 1113            if ($e->localName === 
'Attribute' && $e->namespaceURI === \
SAML2\Constants::NS_SAML) {
 
 1114                $attribute = $e->xml;
 
 1116                $name = $attribute->getAttribute(
'Name');
 
 1118                    array(
'SimpleSAML\Utils\XML', 
'getDOMText'),
 
 1119                    SimpleSAML\Utils\XML::getDOMChildren($attribute, 
'AttributeValue', 
'@saml2')
 
 1122                if (
$name === 
'tags') {
 
 1123                    foreach (
$values as $tagname) {
 
 1124                        if (!empty($tagname)) {
 
 1125                            $ret[
'tags'][] = $tagname;
 
 1142        $this->organizationName = $element->OrganizationName;
 
 1143        $this->organizationDisplayName = $element->OrganizationDisplayName;
 
 1144        $this->organizationURL = $element->OrganizationURL;
 
 1156        $contactPerson = array();
 
 1157        if (!empty($element->contactType)) {
 
 1158            $contactPerson[
'contactType'] = $element->contactType;
 
 1160        if (!empty($element->Company)) {
 
 1161            $contactPerson[
'company'] = $element->Company;
 
 1163        if (!empty($element->GivenName)) {
 
 1164            $contactPerson[
'givenName'] = $element->GivenName;
 
 1166        if (!empty($element->SurName)) {
 
 1167            $contactPerson[
'surName'] = $element->SurName;
 
 1169        if (!empty($element->EmailAddress)) {
 
 1170            $contactPerson[
'emailAddress'] = $element->EmailAddress;
 
 1172        if (!empty($element->TelephoneNumber)) {
 
 1173            $contactPerson[
'telephoneNumber'] = $element->TelephoneNumber;
 
 1175        if (!empty($contactPerson)) {
 
 1176            $this->contacts[] = $contactPerson;
 
 1189        assert(is_array($sp));
 
 1191        $sp[
'name'] = $element->ServiceName;
 
 1192        $sp[
'description'] = $element->ServiceDescription;
 
 1195        $sp[
'attributes'] = array();
 
 1196        $sp[
'attributes.required'] = array();
 
 1197        foreach ($element->RequestedAttribute as $child) {
 
 1198            $attrname = $child->Name;
 
 1199            $sp[
'attributes'][] = $attrname;
 
 1201            if ($child->isRequired !== 
null && $child->isRequired === 
true) {
 
 1202                $sp[
'attributes.required'][] = $attrname;
 
 1205            if ($child->NameFormat !== 
null) {
 
 1206                $attrformat = $child->NameFormat;
 
 1213            } elseif (
$format !== $attrformat) {
 
 1218        if (empty($sp[
'attributes'])) {
 
 1220            unset($sp[
'attributes']);
 
 1222        if (empty($sp[
'attributes.required'])) {
 
 1223            unset($sp[
'attributes.required']);
 
 1227            $sp[
'attributes.NameFormat'] = 
$format;
 
 1250        $ep[
'Binding'] = $element->Binding;
 
 1251        $ep[
'Location'] = $element->Location;
 
 1253        if ($element->ResponseLocation !== 
null) {
 
 1254            $ep[
'ResponseLocation'] = $element->ResponseLocation;
 
 1257        if ($element instanceof \
SAML2\XML\md\IndexedEndpointType) {
 
 1258            $ep[
'index'] = $element->index;
 
 1260            if ($element->isDefault !== 
null) {
 
 1261                $ep[
'isDefault'] = $element->isDefault;
 
 1279        foreach ($endpoints as $ep) {
 
 1305        if ($kd->use === 
'encryption') {
 
 1306            $r[
'encryption'] = 
true;
 
 1307            $r[
'signing'] = 
false;
 
 1308        } elseif ($kd->use === 
'signing') {
 
 1309            $r[
'encryption'] = 
false;
 
 1310            $r[
'signing'] = 
true;
 
 1312            $r[
'encryption'] = 
true;
 
 1313            $r[
'signing'] = 
true;
 
 1316        $keyInfo = $kd->KeyInfo;
 
 1318        foreach ($keyInfo->info as 
$i) {
 
 1319            if (
$i instanceof \
SAML2\XML\ds\X509Data) {
 
 1320                foreach (
$i->data as 
$d) {
 
 1321                    if (
$d instanceof \
SAML2\XML\ds\X509Certificate) {
 
 1322                        $r[
'type'] = 
'X509Certificate';
 
 1323                        $r[
'X509Certificate'] = 
$d->certificate;
 
 1343        assert(is_array($protocols));
 
 1347        foreach ($this->spDescriptors as $spd) {
 
 1348            $sharedProtocols = array_intersect($protocols, $spd[
'protocols']);
 
 1349            if (count($sharedProtocols) > 0) {
 
 1367        assert(is_array($protocols));
 
 1371        foreach ($this->idpDescriptors as $idpd) {
 
 1372            $sharedProtocols = array_intersect($protocols, $idpd[
'protocols']);
 
 1373            if (count($sharedProtocols) > 0) {
 
 1395        assert($doc instanceof DOMDocument);
 
 1398        $ed = $doc->documentElement;
 
 1401            throw new Exception(
'Failed to load SAML metadata from empty XML document.');
 
 1404        if (
SimpleSAML\Utils\XML::isDOMNodeOfType($ed, 
'EntityDescriptor', 
'@md') === 
false) {
 
 1405            throw new Exception(
'Expected first element in the metadata document to be an EntityDescriptor element.');
 
 1408        return new \SAML2\XML\md\EntityDescriptor($ed);
 
 1424            assert(is_string($cert));
 
 1426            if (!file_exists($certFile)) {
 
 1427                throw new Exception(
 
 1428                    'Could not find certificate file ['.$certFile.
'], which is needed to validate signature' 
 1431            $certData = file_get_contents($certFile);
 
 1433            foreach ($this->validators as $validator) {
 
 1434                $key = 
new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, array(
'type' => 
'public'));
 
 1435                $key->loadKey($certData);
 
 1437                    if ($validator->validate(
$key)) {
 
 1440                } 
catch (Exception $e) {
 
 1461        assert(is_string($fingerprint));
 
 1463        $fingerprint = strtolower(str_replace(
":", 
"", $fingerprint));
 
 1465        $candidates = array();
 
 1466        foreach ($this->validators as $validator) {
 
 1467            foreach ($validator->getValidatingCertificates() as $cert) {
 
 1468                $fp = strtolower(sha1(base64_decode($cert)));
 
 1469                $candidates[] = $fp;
 
 1470                if ($fp === $fingerprint) {
 
$metadata['__DYNAMIC:1__']
An exception for terminatinating execution or to throw for unit testing.
const NAMEFORMAT_UNSPECIFIED
The interpretation of the attribute name is left to individual implementations.
static getCertPath($path)
Resolves a path that may be relative to the cert-directory.
static fetch($url, $context=array(), $getHeaders=false)
Helper function to retrieve a file or URL with proxy support, also supporting proxy basic authorizati...
for( $i=6;$i< 13;$i++) for($i=1; $i< 13; $i++) $d
Attribute-related utility methods.