24        'urn:oasis:names:tc:SAML:1.0:protocol',
 
   25        'urn:oasis:names:tc:SAML:1.1:protocol',
 
   35        'urn:oasis:names:tc:SAML:2.0:protocol',
 
  165        \
SAML2\XML\md\EntityDescriptor $entityElement,
 
  168        array $parentExtensions = 
null 
  170        assert(
'is_null($maxExpireTime) || is_int($maxExpireTime)');
 
  172        $this->spDescriptors = array();
 
  173        $this->idpDescriptors = array();
 
  175        $e = $entityElement->toXML();
 
  176        $e = $e->ownerDocument->saveXML($e);
 
  177        $this->entityDescriptor = base64_encode($e);
 
  178        $this->entityId = $entityElement->entityID;
 
  183        $this->validators[] = $entityElement;
 
  187        $this->scopes = $ext[
'scope'];
 
  188        $this->tags = $ext[
'tags'];
 
  189        $this->entityAttributes = $ext[
'EntityAttributes'];
 
  190        $this->registrationInfo = $ext[
'RegistrationInfo'];
 
  193        foreach ($entityElement->RoleDescriptor as $child) {
 
  195            if ($child instanceof \
SAML2\XML\md\SPSSODescriptor) {
 
  197            } elseif ($child instanceof \
SAML2\XML\md\IDPSSODescriptor) {
 
  199            } elseif ($child instanceof \
SAML2\XML\md\AttributeAuthorityDescriptor) {
 
  204        if ($entityElement->Organization) {
 
  208        if (!empty($entityElement->ContactPerson)) {
 
  209            foreach ($entityElement->ContactPerson as $contact) {
 
  230        } 
catch(\Exception $e) {
 
  231            throw new Exception(
'Failed to read XML from file: '.
$file);
 
  250        } 
catch(\Exception $e) {
 
  251            throw new Exception(
'Failed to parse XML string.');
 
  267        assert(
'$document instanceof DOMDocument');
 
  285        assert(
'$entityElement instanceof \SAML2\XML\md\EntityDescriptor');
 
  305        if (
$file === 
null) {
 
  306            throw new Exception(
'Cannot open file NULL. File name not specified.');
 
  313        } 
catch(\Exception $e) {
 
  314            throw new Exception(
'Failed to read XML from file: '.
$file);
 
  317        if ($doc->documentElement === 
null) {
 
  318            throw new Exception(
'Opened file is not an XML document: '.
$file);
 
  340        } 
catch(\Exception $e) {
 
  341            throw new Exception(
'Failed to parse XML string.');
 
  361        if ($element === 
null) {
 
  362            throw new Exception(
'Document was empty.');
 
  365        if (
SimpleSAML\Utils\XML::isDOMNodeOfType($element, 
'EntityDescriptor', 
'@md') === 
true) {
 
  366            return self::processDescriptorsElement(
new \
SAML2\XML\md\EntityDescriptor($element));
 
  367        } elseif (
SimpleSAML\Utils\XML::isDOMNodeOfType($element, 
'EntitiesDescriptor', 
'@md') === 
true) {
 
  368            return self::processDescriptorsElement(
new \
SAML2\XML\md\EntitiesDescriptor($element));
 
  370            throw new Exception(
'Unexpected root node: ['.$element->namespaceURI.
']:'.$element->localName);
 
  387    private static function processDescriptorsElement(
 
  389        $maxExpireTime = 
null,
 
  391        array $parentExtensions = array()
 
  393        assert(
'is_null($maxExpireTime) || is_int($maxExpireTime)');
 
  395        if ($element instanceof \
SAML2\XML\md\EntityDescriptor) {
 
  402        assert(
'$element instanceof \SAML2\XML\md\EntitiesDescriptor');
 
  410        foreach ($element->children as $child) {
 
  411            $ret += self::processDescriptorsElement($child, $expTime, 
$validators, $extensions);
 
  433        $expire = $element->validUntil;
 
  435        if ($maxExpireTime !== 
null && (
$expire === 
null || $maxExpireTime < 
$expire)) {
 
  461        if (!empty($this->organizationName)) {
 
  465        if (!empty($this->organizationDisplayName)) {
 
  469        if (!empty($this->organizationURL)) {
 
  489        assert(
'array_key_exists("scope", $roleDescriptor)');
 
  490        assert(
'array_key_exists("tags", $roleDescriptor)');
 
  492        $scopes = array_merge($this->scopes, array_diff($roleDescriptor[
'scope'], $this->scopes));
 
  497        $tags = array_merge($this->tags, array_diff($roleDescriptor[
'tags'], $this->tags));
 
  503        if (!empty($this->registrationInfo)) {
 
  507        if (!empty($this->entityAttributes)) {
 
  516        if (!empty($roleDescriptor[
'UIInfo'])) {
 
  517            $metadata[
'UIInfo'] = $roleDescriptor[
'UIInfo'];
 
  520        if (!empty($roleDescriptor[
'DiscoHints'])) {
 
  521            $metadata[
'DiscoHints'] = $roleDescriptor[
'DiscoHints'];
 
  541        $ret[
'metadata-set'] = 
'shib13-sp-remote';
 
  546        if (count($spd) === 0) {
 
  554        if (array_key_exists(
'expire', $spd)) {
 
  555            $ret[
'expire'] = $spd[
'expire'];
 
  559        $ret[
'AssertionConsumerService'] = $spd[
'AssertionConsumerService'];
 
  562        if (array_key_exists(
'attributes', $spd)) {
 
  563            $ret[
'attributes'] = $spd[
'attributes'];
 
  565        if (array_key_exists(
'attributes.required', $spd)) {
 
  566            $ret[
'attributes.required'] = $spd[
'attributes.required'];
 
  568        if (array_key_exists(
'attributes.NameFormat', $spd)) {
 
  569            $ret[
'attributes.NameFormat'] = $spd[
'attributes.NameFormat'];
 
  573        if (array_key_exists(
'name', $spd)) {
 
  574            $ret[
'name'] = $spd[
'name'];
 
  576        if (array_key_exists(
'description', $spd)) {
 
  577            $ret[
'description'] = $spd[
'description'];
 
  581        if (!empty($spd[
'keys'])) {
 
  582            $ret[
'keys'] = $spd[
'keys'];
 
  589        if (!empty(
$ret[
'UIInfo'][
'DisplayName'])) {
 
  590            $ret[
'name'] = 
$ret[
'UIInfo'][
'DisplayName'];
 
  615        $ret[
'metadata-set'] = 
'shib13-idp-remote';
 
  619        if (count(
$idp) === 0) {
 
  627        if (array_key_exists(
'expire', 
$idp)) {
 
  632        $ret[
'SingleSignOnService'] = 
$idp[
'SingleSignOnService'];
 
  635        $ret[
'ArtifactResolutionService'] = 
$idp[
'ArtifactResolutionService'];
 
  638        if (!empty(
$idp[
'keys'])) {
 
  646        if (!empty(
$ret[
'UIInfo'][
'DisplayName'])) {
 
  647            $ret[
'name'] = 
$ret[
'UIInfo'][
'DisplayName'];
 
  671        $ret[
'metadata-set'] = 
'saml20-sp-remote';
 
  675        if (count($spd) === 0) {
 
  683        if (array_key_exists(
'expire', $spd)) {
 
  684            $ret[
'expire'] = $spd[
'expire'];
 
  688        $ret[
'AssertionConsumerService'] = $spd[
'AssertionConsumerService'];
 
  692        $ret[
'SingleLogoutService'] = $spd[
'SingleLogoutService'];
 
  696        if (count($spd[
'nameIDFormats']) > 0) {
 
  698            $ret[
'NameIDFormat'] = $spd[
'nameIDFormats'][0];
 
  702        if (array_key_exists(
'attributes', $spd)) {
 
  703            $ret[
'attributes'] = $spd[
'attributes'];
 
  705        if (array_key_exists(
'attributes.required', $spd)) {
 
  706            $ret[
'attributes.required'] = $spd[
'attributes.required'];
 
  708        if (array_key_exists(
'attributes.NameFormat', $spd)) {
 
  709            $ret[
'attributes.NameFormat'] = $spd[
'attributes.NameFormat'];
 
  713        if (array_key_exists(
'name', $spd)) {
 
  714            $ret[
'name'] = $spd[
'name'];
 
  716        if (array_key_exists(
'description', $spd)) {
 
  717            $ret[
'description'] = $spd[
'description'];
 
  721        if (!empty($spd[
'keys'])) {
 
  722            $ret[
'keys'] = $spd[
'keys'];
 
  726        if (array_key_exists(
'AuthnRequestsSigned', $spd)) {
 
  727            $ret[
'validate.authnrequest'] = $spd[
'AuthnRequestsSigned'];
 
  731        if (array_key_exists(
'WantAssertionsSigned', $spd)) {
 
  732            $ret[
'saml20.sign.assertion'] = $spd[
'WantAssertionsSigned'];
 
  739        if (!empty(
$ret[
'UIInfo'][
'DisplayName'])) {
 
  740            $ret[
'name'] = 
$ret[
'UIInfo'][
'DisplayName'];
 
  768        $ret[
'metadata-set'] = 
'saml20-idp-remote';
 
  772        if (count(
$idp) === 0) {
 
  780        if (array_key_exists(
'expire', 
$idp)) {
 
  785        if (
$idp[
'WantAuthnRequestsSigned']) {
 
  786            $ret[
'sign.authnrequest'] = 
true;
 
  790        $ret[
'SingleSignOnService'] = 
$idp[
'SingleSignOnService'];
 
  793        $ret[
'SingleLogoutService'] = 
$idp[
'SingleLogoutService'];
 
  796        $ret[
'ArtifactResolutionService'] = 
$idp[
'ArtifactResolutionService'];
 
  799        $ret[
'NameIDFormats'] = 
$idp[
'nameIDFormats'];
 
  802        if (!empty(
$idp[
'keys'])) {
 
  810        if (!empty(
$ret[
'UIInfo'][
'DisplayName'])) {
 
  811            $ret[
'name'] = 
$ret[
'UIInfo'][
'DisplayName'];
 
  845        assert(
'is_null($expireTime) || is_int($expireTime)');
 
  851        if ($expireTime !== 
null) {
 
  853            $ret[
'expire'] = $expireTime;
 
  856        $ret[
'protocols'] = $element->protocolSupportEnumeration;
 
  859        $ret[
'keys'] = array();
 
  860        foreach ($element->KeyDescriptor as $kd) {
 
  868        $ret[
'scope'] = $ext[
'scope'];
 
  869        $ret[
'tags'] = $ext[
'tags'];
 
  870        $ret[
'EntityAttributes'] = $ext[
'EntityAttributes'];
 
  871        $ret[
'UIInfo'] = $ext[
'UIInfo'];
 
  872        $ret[
'DiscoHints'] = $ext[
'DiscoHints'];
 
  896        assert(
'is_null($expireTime) || is_int($expireTime)');
 
  908        $sd[
'nameIDFormats'] = $element->NameIDFormat;
 
  923        assert(
'is_null($expireTime) || is_int($expireTime)');
 
  931        $attcs = $element->AttributeConsumingService;
 
  932        if (count($attcs) > 0) {
 
  937        if ($element->AuthnRequestsSigned !== 
null) {
 
  938            $sp[
'AuthnRequestsSigned'] = $element->AuthnRequestsSigned;
 
  942        if ($element->WantAssertionsSigned !== 
null) {
 
  943            $sp[
'WantAssertionsSigned'] = $element->WantAssertionsSigned;
 
  946        $this->spDescriptors[] = $sp;
 
  959        assert(
'is_null($expireTime) || is_int($expireTime)');
 
  966        if ($element->WantAuthnRequestsSigned) {
 
  967            $idp[
'WantAuthnRequestsSigned'] = 
true;
 
  969            $idp[
'WantAuthnRequestsSigned'] = 
false;
 
  972        $this->idpDescriptors[] = 
$idp;
 
  984        \
SAML2\XML\md\AttributeAuthorityDescriptor $element,
 
  987        assert(
'is_null($expireTime) || is_int($expireTime)');
 
  991        $aad[
'metadata-set'] = 
'attributeauthority-remote';
 
  995        $aad[
'NameIDFormat'] = $element->NameIDFormat;
 
  997        $this->attributeAuthorityDescriptors[] = $aad;
 
 1015            'EntityAttributes' => array(),
 
 1016            'RegistrationInfo' => array(),
 
 1017            'UIInfo'           => array(),
 
 1018            'DiscoHints'       => array(),
 
 1022        if (($element instanceof \
SAML2\XML\md\EntityDescriptor || $element instanceof \
SAML2\XML\md\EntitiesDescriptor)
 
 1023                && !empty($parentExtensions[
'RegistrationInfo'])) {
 
 1024            $ret[
'RegistrationInfo'] = $parentExtensions[
'RegistrationInfo'];
 
 1027        foreach ($element->Extensions as $e) {
 
 1029            if ($e instanceof \
SAML2\XML\shibmd\Scope) {
 
 1030                $ret[
'scope'][] = $e->scope;
 
 1035            if ($element instanceof \
SAML2\XML\md\EntityDescriptor ||
 
 1036                $element instanceof \
SAML2\XML\md\EntitiesDescriptor) {
 
 1039                if ($e instanceof \
SAML2\XML\mdrpi\RegistrationInfo) {
 
 1041                    if (isset(
$ret[
'RegistrationInfo'][
'registrationAuthority'])
 
 1042                        && 
$ret[
'RegistrationInfo'][
'registrationAuthority'] !== $e->registrationAuthority) {
 
 1044                          . 
$ret[
'RegistrationInfo'][
'registrationAuthority'] . 
"' with '{$e->registrationAuthority}'");
 
 1046                        $ret[
'RegistrationInfo'][
'registrationAuthority'] = $e->registrationAuthority;
 
 1049                if ($e instanceof \
SAML2\XML\mdattr\EntityAttributes && !empty($e->children)) {
 
 1050                    foreach ($e->children as $attr) {
 
 1053                        if ($attr instanceof \
SAML2\XML\saml\Attribute) {
 
 1054                            if (empty($attr->Name) || empty($attr->AttributeValue)) {
 
 1059                            $name = $attr->Name;
 
 1060                            if (empty($attr->NameFormat)) {
 
 1061                                $name = 
'{'.\SAML2\Constants::NAMEFORMAT_UNSPECIFIED.
'}'.$attr->Name;
 
 1062                            } elseif ($attr->NameFormat !== 
'urn:oasis:names:tc:SAML:2.0:attrname-format:uri') {
 
 1063                                $name = 
'{'.$attr->NameFormat.
'}'.$attr->Name;
 
 1067                            foreach ($attr->AttributeValue as $attrvalue) {
 
 1068                                $values[] = $attrvalue->getString();
 
 1071                            $ret[
'EntityAttributes'][
$name] = $values;
 
 1078            if ($element instanceof \
SAML2\XML\md\RoleDescriptor) {
 
 1079                if ($e instanceof \
SAML2\XML\mdui\UIInfo) {
 
 1081                    $ret[
'UIInfo'][
'DisplayName'] = $e->DisplayName;
 
 1082                    $ret[
'UIInfo'][
'Description'] = $e->Description;
 
 1083                    $ret[
'UIInfo'][
'InformationURL'] = $e->InformationURL;
 
 1084                    $ret[
'UIInfo'][
'PrivacyStatementURL'] = $e->PrivacyStatementURL;
 
 1086                    foreach ($e->Keywords as $uiItem) {
 
 1087                        if (!($uiItem instanceof \
SAML2\XML\mdui\Keywords)
 
 1088                            || empty($uiItem->Keywords)
 
 1089                            || empty($uiItem->lang)
 
 1093                        $ret[
'UIInfo'][
'Keywords'][$uiItem->lang] = $uiItem->Keywords;
 
 1095                    foreach ($e->Logo as $uiItem) {
 
 1096                        if (!($uiItem instanceof \
SAML2\XML\mdui\Logo)
 
 1097                            || empty($uiItem->url)
 
 1098                            || empty($uiItem->height)
 
 1099                            || empty($uiItem->width)
 
 1104                            'url'    => $uiItem->url,
 
 1105                            'height' => $uiItem->height,
 
 1106                            'width'  => $uiItem->width,
 
 1108                        if (!empty($uiItem->lang)) {
 
 1109                            $logo[
'lang'] = $uiItem->lang;
 
 1111                        $ret[
'UIInfo'][
'Logo'][] = $logo;
 
 1117            if ($element instanceof \
SAML2\XML\md\IDPSSODescriptor) {
 
 1119                if ($e instanceof \
SAML2\XML\mdui\DiscoHints) {
 
 1120                    $ret[
'DiscoHints'][
'IPHint'] = $e->IPHint;
 
 1121                    $ret[
'DiscoHints'][
'DomainHint'] = $e->DomainHint;
 
 1122                    $ret[
'DiscoHints'][
'GeolocationHint'] = $e->GeolocationHint;
 
 1126            if (!($e instanceof \
SAML2\XML\Chunk)) {
 
 1130            if ($e->localName === 
'Attribute' && $e->namespaceURI === \
SAML2\Constants::NS_SAML) {
 
 1131                $attribute = $e->getXML();
 
 1133                $name = $attribute->getAttribute(
'Name');
 
 1134                $values = array_map(
 
 1135                    array(
'SimpleSAML\Utils\XML', 
'getDOMText'),
 
 1136                    SimpleSAML\Utils\XML::getDOMChildren($attribute, 
'AttributeValue', 
'@saml2')
 
 1139                if (
$name === 
'tags') {
 
 1140                    foreach ($values as $tagname) {
 
 1141                        if (!empty($tagname)) {
 
 1142                            $ret[
'tags'][] = $tagname;
 
 1159        $this->organizationName = $element->OrganizationName;
 
 1160        $this->organizationDisplayName = $element->OrganizationDisplayName;
 
 1161        $this->organizationURL = $element->OrganizationURL;
 
 1173        $contactPerson = array();
 
 1174        if (!empty($element->contactType)) {
 
 1175            $contactPerson[
'contactType'] = $element->contactType;
 
 1177        if (!empty($element->Company)) {
 
 1178            $contactPerson[
'company'] = $element->Company;
 
 1180        if (!empty($element->GivenName)) {
 
 1181            $contactPerson[
'givenName'] = $element->GivenName;
 
 1183        if (!empty($element->SurName)) {
 
 1184            $contactPerson[
'surName'] = $element->SurName;
 
 1186        if (!empty($element->EmailAddress)) {
 
 1187            $contactPerson[
'emailAddress'] = $element->EmailAddress;
 
 1189        if (!empty($element->TelephoneNumber)) {
 
 1190            $contactPerson[
'telephoneNumber'] = $element->TelephoneNumber;
 
 1192        if (!empty($contactPerson)) {
 
 1193            $this->contacts[] = $contactPerson;
 
 1206        assert(
'is_array($sp)');
 
 1208        $sp[
'name'] = $element->ServiceName;
 
 1209        $sp[
'description'] = $element->ServiceDescription;
 
 1212        $sp[
'attributes'] = array();
 
 1213        $sp[
'attributes.required'] = array();
 
 1214        foreach ($element->RequestedAttribute as $child) {
 
 1215            $attrname = $child->Name;
 
 1216            $sp[
'attributes'][] = $attrname;
 
 1218            if ($child->isRequired !== 
null && $child->isRequired === 
true) {
 
 1219                $sp[
'attributes.required'][] = $attrname;
 
 1222            if ($child->NameFormat !== 
null) {
 
 1223                $attrformat = $child->NameFormat;
 
 1230            } elseif (
$format !== $attrformat) {
 
 1235        if (empty($sp[
'attributes'])) {
 
 1237            unset($sp[
'attributes']);
 
 1239        if (empty($sp[
'attributes.required'])) {
 
 1240            unset($sp[
'attributes.required']);
 
 1244            $sp[
'attributes.NameFormat'] = 
$format;
 
 1267        $ep[
'Binding'] = $element->Binding;
 
 1268        $ep[
'Location'] = $element->Location;
 
 1270        if ($element->ResponseLocation !== 
null) {
 
 1271            $ep[
'ResponseLocation'] = $element->ResponseLocation;
 
 1274        if ($element instanceof \
SAML2\XML\md\IndexedEndpointType) {
 
 1275            $ep[
'index'] = $element->index;
 
 1277            if ($element->isDefault !== 
null) {
 
 1278                $ep[
'isDefault'] = $element->isDefault;
 
 1296        foreach ($endpoints as $ep) {
 
 1322        if ($kd->use === 
'encryption') {
 
 1323            $r[
'encryption'] = 
true;
 
 1324            $r[
'signing'] = 
false;
 
 1325        } elseif ($kd->use === 
'signing') {
 
 1326            $r[
'encryption'] = 
false;
 
 1327            $r[
'signing'] = 
true;
 
 1329            $r[
'encryption'] = 
true;
 
 1330            $r[
'signing'] = 
true;
 
 1333        $keyInfo = $kd->KeyInfo;
 
 1335        foreach ($keyInfo->info as 
$i) {
 
 1336            if (
$i instanceof \
SAML2\XML\ds\X509Data) {
 
 1337                foreach (
$i->data as 
$d) {
 
 1338                    if (
$d instanceof \
SAML2\XML\ds\X509Certificate) {
 
 1339                        $r[
'type'] = 
'X509Certificate';
 
 1340                        $r[
'X509Certificate'] = 
$d->certificate;
 
 1360        assert(
'is_array($protocols)');
 
 1364        foreach ($this->spDescriptors as $spd) {
 
 1365            $sharedProtocols = array_intersect($protocols, $spd[
'protocols']);
 
 1366            if (count($sharedProtocols) > 0) {
 
 1384        assert(
'is_array($protocols)');
 
 1388        foreach ($this->idpDescriptors as $idpd) {
 
 1389            $sharedProtocols = array_intersect($protocols, $idpd[
'protocols']);
 
 1390            if (count($sharedProtocols) > 0) {
 
 1412        assert(
'$doc instanceof DOMDocument');
 
 1415        $ed = $doc->documentElement;
 
 1418            throw new Exception(
'Failed to load SAML metadata from empty XML document.');
 
 1421        if (
SimpleSAML\Utils\XML::isDOMNodeOfType($ed, 
'EntityDescriptor', 
'@md') === 
false) {
 
 1422            throw new Exception(
'Expected first element in the metadata document to be an EntityDescriptor element.');
 
 1425        return new \SAML2\XML\md\EntityDescriptor($ed);
 
 1441            assert(
'is_string($cert)');
 
 1443            if (!file_exists($certFile)) {
 
 1444                throw new Exception(
 
 1445                    'Could not find certificate file ['.$certFile.
'], which is needed to validate signature' 
 1448            $certData = file_get_contents($certFile);
 
 1450            foreach ($this->validators as $validator) {
 
 1451                $key = 
new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array(
'type' => 
'public'));
 
 1452                $key->loadKey($certData);
 
 1454                    if ($validator->validate(
$key)) {
 
 1457                } 
catch (Exception $e) {
 
 1478        assert(
'is_string($fingerprint)');
 
 1480        $fingerprint = strtolower(str_replace(
":", 
"", $fingerprint));
 
 1482        $candidates = array();
 
 1483        foreach ($this->validators as $validator) {
 
 1484            foreach ($validator->getValidatingCertificates() as $cert) {
 
 1486                $fp = strtolower(sha1(base64_decode($cert)));
 
 1487                $candidates[] = $fp;
 
 1488                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.
if(!file_exists("$old.txt")) if( $old===$new) if(file_exists("$new.txt")) $file