2 * The Shibboleth License, Version 1.
4 * University Corporation for Advanced Internet Development, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution, if any, must include
17 * the following acknowledgment: "This product includes software developed by
18 * the University Corporation for Advanced Internet Development
19 * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
20 * may appear in the software itself, if and wherever such third-party
21 * acknowledgments normally appear.
23 * Neither the name of Shibboleth nor the names of its contributors, nor
24 * Internet2, nor the University Corporation for Advanced Internet Development,
25 * Inc., nor UCAID may be used to endorse or promote products derived from this
26 * software without specific prior written permission. For written permission,
27 * please contact shibboleth@shibboleth.org
29 * Products derived from this software may not be called Shibboleth, Internet2,
30 * UCAID, or the University Corporation for Advanced Internet Development, nor
31 * may Shibboleth appear in their name, without prior written permission of the
32 * University Corporation for Advanced Internet Development.
35 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
36 * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
38 * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
39 * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
40 * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
41 * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
42 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
47 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 /* XMLMetadata.cpp - a metadata implementation that uses an XML-based registry
60 #include <sys/types.h>
63 #include <log4cpp/Category.hh>
64 #include <xercesc/util/XMLChar.hpp>
65 #include <xsec/enc/XSECCryptoException.hpp>
66 #include <xsec/enc/XSECKeyInfoResolverDefault.hpp>
67 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
69 using namespace shibboleth;
71 using namespace log4cpp;
76 class XMLMetadataImpl : public ReloadableXMLFileImpl
79 class ContactPerson : public IContactPerson
82 ContactPerson(const DOMElement* e);
85 ContactType getType() const { return m_type; }
86 const char* getCompany() const { return m_company.get(); }
87 const char* getGivenName() const { return m_givenName.get(); }
88 const char* getSurName() const { return m_surName.get(); }
89 Iterator<string> getEmailAddresses() const { return m_emails; }
90 Iterator<string> getTelephoneNumbers() const { return m_phones; }
91 const DOMElement* getElement() const { return m_root; }
94 const DOMElement* m_root;
96 auto_ptr<char> m_givenName,m_surName,m_company;
97 vector<string> m_emails,m_phones;
100 class Organization : public IOrganization
103 Organization(const DOMElement* e);
106 const char* getName(const char* lang="en") const { return forLang(m_names,lang); }
107 const char* getDisplayName(const char* lang="en") const { return forLang(m_displays,lang); }
108 const char* getURL(const char* lang="en") const { return forLang(m_urls,lang); }
109 const DOMElement* getElement() const { return m_root; }
112 const char* forLang(const map<string,string>& m, const char* lang) const {
113 map<string,string>::const_iterator i=m.find(lang);
114 return (i==m.end()) ? NULL : i->second.c_str();
116 const DOMElement* m_root;
117 map<string,string> m_names,m_displays,m_urls;
120 class EntityDescriptor;
122 class EncryptionMethod : public XENCEncryptionMethod
125 EncryptionMethod(const DOMElement* e);
126 ~EncryptionMethod() {}
128 const XMLCh * getAlgorithm(void) const { return m_alg; }
129 const XMLCh * getDigestMethod(void) const { return m_digest; }
130 const XMLCh * getOAEPparams(void) const { return m_params; }
131 int getKeySize(void) const { return m_size; }
132 DOMElement* getElement(void) const { return const_cast<DOMElement*>(m_root); }
133 void setDigestMethod(const XMLCh * method) {throw exception();}
134 void setOAEPparams(const XMLCh * params) {throw exception();}
135 void setKeySize(int size) {throw exception();}
138 const DOMElement* m_root;
140 const XMLCh* m_digest;
141 const XMLCh* m_params;
145 class KeyDescriptor : public IKeyDescriptor
148 KeyDescriptor(const DOMElement* e);
151 KeyUse getUse() const { return m_use; }
152 DSIGKeyInfoList* getKeyInfo() const { return m_klist; }
153 saml::Iterator<const XENCEncryptionMethod*> getEncryptionMethods() const { return m_methods; }
154 const DOMElement* getElement() const { return m_root; }
157 const DOMElement* m_root;
159 mutable DSIGKeyInfoList* m_klist;
160 vector<const XENCEncryptionMethod*> m_methods;
163 class KeyAuthority : public IKeyAuthority
166 KeyAuthority(const DOMElement* e);
169 int getVerifyDepth() const { return m_depth; }
170 Iterator<DSIGKeyInfoList*> getKeyInfos() const { return m_klists; }
174 vector<DSIGKeyInfoList*> m_klists;
177 class Role : public virtual IRoleDescriptor
180 Role(const EntityDescriptor* provider, time_t validUntil, const DOMElement* e);
184 const IEntityDescriptor* getEntityDescriptor() const {return m_provider;}
185 Iterator<const XMLCh*> getProtocolSupportEnumeration() const {return m_protocolEnum;}
186 bool hasSupport(const XMLCh* protocol) const;
187 const char* getErrorURL() const {return (m_errorURL ? m_errorURL : m_provider->getErrorURL());}
188 bool isValid() const {return time(NULL) < m_validUntil;}
189 Iterator<const IKeyDescriptor*> getKeyDescriptors() const {return m_keys;}
190 const IOrganization* getOrganization() const {return m_org ? m_org : m_provider->getOrganization();}
191 Iterator<const IContactPerson*> getContactPersons() const
192 {return (m_contacts.empty() ? m_provider->getContactPersons() : m_contacts);}
193 const DOMElement* getElement() const {return m_root;}
196 vector<const XMLCh*> m_protocolEnum;
197 vector<const IKeyDescriptor*> m_keys;
200 const EntityDescriptor* m_provider;
201 const DOMElement* m_root;
202 XMLCh* m_protocolEnumCopy;
205 vector<const IContactPerson*> m_contacts;
209 class Endpoint : public virtual IEndpoint
212 Endpoint(const DOMElement* e) : m_root(e),
213 m_binding(e->getAttributeNS(NULL,L(Binding))),
214 m_location(e->getAttributeNS(NULL,SHIB_L(Location))),
215 m_resploc(e->getAttributeNS(NULL,SHIB_L(ResponseLocation))) {}
216 Endpoint(const XMLCh* binding, const XMLCh* loc)
217 : m_root(NULL), m_binding(binding), m_location(loc), m_resploc(NULL) {}
220 const XMLCh* getBinding() const { return m_binding; }
221 const XMLCh* getLocation() const { return m_location; }
222 const XMLCh* getResponseLocation() const { return m_resploc; }
223 const DOMElement* getElement() const { return m_root; }
226 const DOMElement* m_root;
227 const XMLCh* m_binding;
228 const XMLCh* m_location;
229 const XMLCh* m_resploc;
232 class IndexedEndpoint : public Endpoint, public virtual IIndexedEndpoint
235 IndexedEndpoint(const DOMElement* e) : Endpoint(e), m_index(XMLString::parseInt(e->getAttributeNS(NULL,SHIB_L(index)))) {}
236 unsigned short getIndex() const {return m_index;}
239 unsigned short m_index;
242 class EndpointManager : public IEndpointManager
245 EndpointManager() : m_soft(NULL), m_hard(NULL) {}
247 for (vector<const IEndpoint*>::iterator i=m_endpoints.begin(); i!=m_endpoints.end(); i++)
248 delete const_cast<IEndpoint*>(*i);
250 saml::Iterator<const IEndpoint*> getEndpoints() const {return m_endpoints;}
251 const IEndpoint* getDefaultEndpoint() const {
252 if (m_hard) return m_hard;
253 if (m_soft) return m_soft;
254 if (!m_endpoints.empty()) return *(m_endpoints.begin());
257 const IEndpoint* getEndpointByIndex(unsigned short index) const {
258 for (vector<const IEndpoint*>::const_iterator i=m_endpoints.begin(); i!=m_endpoints.end(); i++) {
259 const IIndexedEndpoint* temp=dynamic_cast<const IIndexedEndpoint*>(*i);
260 if (temp && index==temp->getIndex())
265 const IEndpoint* getEndpointByBinding(const XMLCh* binding) const {
266 for (vector<const IEndpoint*>::const_iterator i=m_endpoints.begin(); i!=m_endpoints.end(); i++)
267 if (!XMLString::compareString(binding,(*i)->getBinding()))
271 void add(IEndpoint* e) {
272 m_endpoints.push_back(e);
273 if (!m_hard && e->getElement()) {
274 const XMLCh* v=e->getElement()->getAttributeNS(NULL,SHIB_L(isDefault));
275 if (v && (*v==chDigit_1 || *v==chLatin_t)) // explicit default
277 else if ((!v || !*v) && !m_soft) // implicit default
280 else if (!m_hard && !m_soft) {
281 // No default yet, so this one qualifies as an implicit.
287 vector<const IEndpoint*> m_endpoints;
288 const IEndpoint* m_soft; // Soft default (not explicit)
289 const IEndpoint* m_hard; // Hard default (explicit)
292 class SSORole : public Role, public virtual ISSODescriptor
295 SSORole(const EntityDescriptor* provider, time_t validUntil, const DOMElement* e);
297 const IEndpointManager* getArtifactResolutionServiceManager() const {return &m_artifact;}
298 const IEndpointManager* getSingleLogoutServiceManager() const {return &m_logout;}
299 const IEndpointManager* getManageNameIDServiceManager() const {return &m_nameid;}
300 saml::Iterator<const XMLCh*> getNameIDFormats() const {return m_formats;}
303 EndpointManager m_artifact,m_logout,m_nameid;
304 vector<const XMLCh*> m_formats;
307 class ScopedRole : public virtual IScopedRoleDescriptor
310 ScopedRole(const DOMElement* e);
311 saml::Iterator<std::pair<const XMLCh*,bool> > getScopes() const {return m_scopes;}
314 vector<pair<const XMLCh*,bool> > m_scopes;
317 class IDPRole : public SSORole, public ScopedRole, public virtual IIDPSSODescriptor
320 IDPRole(const EntityDescriptor* provider, time_t validUntil, const DOMElement* e);
322 bool getWantAuthnRequestsSigned() const {return m_wantAuthnRequestsSigned;}
323 const IEndpointManager* getSingleSignOnServiceManager() const {return &m_sso;}
324 const IEndpointManager* getNameIDMappingServiceManager() const {return &m_mapping;}
325 const IEndpointManager* getAssertionIDRequestServiceManager() const {return &m_idreq;}
326 saml::Iterator<const XMLCh*> getAttributeProfiles() const {return m_attrprofs;}
327 saml::Iterator<const saml::SAMLAttribute*> getAttributes() const {return m_attrs;}
330 EndpointManager m_sso,m_mapping,m_idreq;
331 vector<const XMLCh*> m_attrprofs;
332 vector<const SAMLAttribute*> m_attrs;
333 bool m_wantAuthnRequestsSigned;
334 const XMLCh* m_sourceId;
335 friend class EntityDescriptor;
338 class AARole : public Role, public ScopedRole, public virtual IAttributeAuthorityDescriptor
341 AARole(const EntityDescriptor* provider, time_t validUntil, const DOMElement* e);
343 const IEndpointManager* getAttributeServiceManager() const {return &m_query;}
344 const IEndpointManager* getAssertionIDRequestServiceManager() const {return &m_idreq;}
345 saml::Iterator<const XMLCh*> getNameIDFormats() const {return m_formats;}
346 saml::Iterator<const XMLCh*> getAttributeProfiles() const {return m_attrprofs;}
347 saml::Iterator<const saml::SAMLAttribute*> getAttributes() const {return m_attrs;}
350 EndpointManager m_query,m_idreq;
351 vector<const XMLCh*> m_formats,m_attrprofs;
352 vector<const SAMLAttribute*> m_attrs;
355 class EntityDescriptor : public IExtendedEntityDescriptor
360 XMLMetadataImpl* wrapper,
361 time_t validUntil=LONG_MAX,
362 const IEntitiesDescriptor* parent=NULL
367 const XMLCh* getId() const {return m_id;}
368 bool isValid() const {return time(NULL) < m_validUntil;}
369 Iterator<const IRoleDescriptor*> getRoleDescriptors() const {return m_roles;}
370 const IIDPSSODescriptor* getIDPSSODescriptor(const XMLCh* protocol) const;
371 const ISPSSODescriptor* getSPSSODescriptor(const XMLCh* protocol) const {return NULL;}
372 const IAuthnAuthorityDescriptor* getAuthnAuthorityDescriptor(const XMLCh* protocol) const {return NULL;}
373 const IAttributeAuthorityDescriptor* getAttributeAuthorityDescriptor(const XMLCh* protocol) const;
374 const IPDPDescriptor* getPDPDescriptor(const XMLCh* protocol) const {return NULL;}
375 const IAffiliationDescriptor* getAffiliationDescriptor() const {return NULL;}
376 const IOrganization* getOrganization() const {return m_org;}
377 Iterator<const IContactPerson*> getContactPersons() const {return m_contacts;}
378 Iterator<pair<const XMLCh*,const XMLCh*> > getAdditionalMetadataLocations() const {return m_locs;}
379 const IEntitiesDescriptor* getEntitiesDescriptor() const {return m_parent;}
380 Iterator<const IKeyAuthority*> getKeyAuthorities() const {return m_keyauths;}
381 const DOMElement* getElement() const {return m_root;}
384 const char* getErrorURL() const {return m_errorURL.get();}
385 time_t getValidUntil() const {return m_validUntil;}
387 const DOMElement* m_root;
388 const IEntitiesDescriptor* m_parent;
390 auto_ptr<char> m_errorURL;
391 IOrganization* m_org;
392 vector<const IContactPerson*> m_contacts;
393 vector<const IRoleDescriptor*> m_roles;
394 vector<pair<const XMLCh*,const XMLCh*> > m_locs;
395 vector<const IKeyAuthority*> m_keyauths;
399 class EntitiesDescriptor : public IExtendedEntitiesDescriptor
404 XMLMetadataImpl* wrapper,
405 time_t validUntil=LONG_MAX,
406 const IEntitiesDescriptor* parent=NULL
408 ~EntitiesDescriptor();
410 const XMLCh* getName() const {return m_name;}
411 bool isValid() const {return time(NULL) < m_validUntil;}
412 const IEntitiesDescriptor* getEntitiesDescriptor() const {return m_parent;}
413 Iterator<const IEntitiesDescriptor*> getEntitiesDescriptors() const {return m_groups;}
414 Iterator<const IEntityDescriptor*> getEntityDescriptors() const {return m_providers;}
415 Iterator<const IKeyAuthority*> getKeyAuthorities() const {return m_keyauths;}
416 const DOMElement* getElement() const {return m_root;}
419 const DOMElement* m_root;
420 const IEntitiesDescriptor* m_parent;
422 vector<const IEntitiesDescriptor*> m_groups;
423 vector<const IEntityDescriptor*> m_providers;
424 vector<const IKeyAuthority*> m_keyauths;
428 XMLMetadataImpl(const char* pathname) : ReloadableXMLFileImpl(pathname), m_rootProvider(NULL), m_rootGroup(NULL) { init(); }
429 XMLMetadataImpl(const DOMElement* e) : ReloadableXMLFileImpl(e), m_rootProvider(NULL), m_rootGroup(NULL) { init(); }
433 typedef multimap<string,const EntityDescriptor*> sitemap_t;
436 EntityDescriptor* m_rootProvider;
437 EntitiesDescriptor* m_rootGroup;
440 class XMLMetadata : public IMetadata, public ReloadableXMLFile
443 XMLMetadata(const DOMElement* e) : ReloadableXMLFile(e), m_exclusions(true) {
444 static const XMLCh uri[] = { chLatin_u, chLatin_r, chLatin_i, chNull };
445 if (e->hasAttributeNS(NULL,uri)) {
446 // First check for explicit enablement of entities.
447 DOMNodeList* nlist=e->getElementsByTagName(SHIB_L(Include));
448 for (int i=0; nlist && i<nlist->getLength(); i++) {
449 if (nlist->item(i)->hasChildNodes()) {
450 auto_ptr_char temp(nlist->item(i)->getFirstChild()->getNodeValue());
452 m_set.insert(temp.get());
457 // If there was no explicit enablement, build a set of exclusions.
459 nlist=e->getElementsByTagName(SHIB_L(Exclude));
460 for (int j=0; nlist && j<nlist->getLength(); j++) {
461 if (nlist->item(j)->hasChildNodes()) {
462 auto_ptr_char temp(nlist->item(j)->getFirstChild()->getNodeValue());
464 m_set.insert(temp.get());
472 const IEntityDescriptor* lookup(const char* providerId, bool strict=true) const;
473 const IEntityDescriptor* lookup(const XMLCh* providerId, bool strict=true) const;
474 const IEntityDescriptor* lookup(const saml::SAMLArtifact* artifact) const;
475 pair<const IEntitiesDescriptor*,const IEntityDescriptor*> getRoot() const;
478 virtual ReloadableXMLFileImpl* newImplementation(const char* pathname, bool first=true) const;
479 virtual ReloadableXMLFileImpl* newImplementation(const DOMElement* e, bool first=true) const;
487 IPlugIn* XMLMetadataFactory(const DOMElement* e)
489 auto_ptr<XMLMetadata> m(new XMLMetadata(e));
490 m->getImplementation();
494 ReloadableXMLFileImpl* XMLMetadata::newImplementation(const DOMElement* e, bool first) const
496 return new XMLMetadataImpl(e);
499 ReloadableXMLFileImpl* XMLMetadata::newImplementation(const char* pathname, bool first) const
501 return new XMLMetadataImpl(pathname);
504 XMLMetadataImpl::ContactPerson::ContactPerson(const DOMElement* e) : m_root(e)
506 const XMLCh* type=NULL;
508 // Old metadata or new?
509 if (saml::XML::isElementNamed(e,::XML::SHIB_NS,SHIB_L(Contact))) {
510 type=e->getAttributeNS(NULL,SHIB_L(Type));
511 m_surName=auto_ptr<char>(toUTF8(e->getAttributeNS(NULL,SHIB_L(Name))));
512 if (e->hasAttributeNS(NULL,SHIB_L(Email))) {
513 auto_ptr<char> temp(toUTF8(e->getAttributeNS(NULL,SHIB_L(Email))));
515 m_emails.push_back(temp.get());
518 else if (saml::XML::isElementNamed(e,::XML::SAML2META_NS,SHIB_L(ContactPerson))) {
519 type=e->getAttributeNS(NULL,SHIB_L(contactType));
521 e=saml::XML::getFirstChildElement(e);
523 if (saml::XML::isElementNamed(e,::XML::SAML2META_NS,SHIB_L(Company))) {
524 n=e->getFirstChild();
525 if (n) m_company=auto_ptr<char>(toUTF8(n->getNodeValue()));
527 else if (saml::XML::isElementNamed(e,::XML::SAML2META_NS,SHIB_L(GivenName))) {
528 n=e->getFirstChild();
529 if (n) m_givenName=auto_ptr<char>(toUTF8(n->getNodeValue()));
531 else if (saml::XML::isElementNamed(e,::XML::SAML2META_NS,SHIB_L(SurName))) {
532 n=e->getFirstChild();
533 if (n) m_surName=auto_ptr<char>(toUTF8(n->getNodeValue()));
535 else if (saml::XML::isElementNamed(e,::XML::SAML2META_NS,SHIB_L(EmailAddress))) {
536 n=e->getFirstChild();
538 auto_ptr<char> temp(toUTF8(n->getNodeValue()));
539 if (temp.get()) m_emails.push_back(temp.get());
542 else if (saml::XML::isElementNamed(e,::XML::SAML2META_NS,SHIB_L(TelephoneNumber))) {
543 n=e->getFirstChild();
545 auto_ptr<char> temp(toUTF8(n->getNodeValue()));
546 if (temp.get()) m_phones.push_back(temp.get());
549 e=saml::XML::getNextSiblingElement(e);
553 if (!XMLString::compareString(type,SHIB_L(technical)))
554 m_type=IContactPerson::technical;
555 else if (!XMLString::compareString(type,SHIB_L(support)))
556 m_type=IContactPerson::support;
557 else if (!XMLString::compareString(type,SHIB_L(administrative)))
558 m_type=IContactPerson::administrative;
559 else if (!XMLString::compareString(type,SHIB_L(billing)))
560 m_type=IContactPerson::billing;
561 else if (!XMLString::compareString(type,SHIB_L(other)))
562 m_type=IContactPerson::other;
565 XMLMetadataImpl::Organization::Organization(const DOMElement* e) : m_root(e)
568 e=saml::XML::getFirstChildElement(e);
570 if (saml::XML::isElementNamed(e,::XML::SAML2META_NS,SHIB_L(OrganizationName))) {
571 n=e->getFirstChild();
573 auto_ptr<char> name(toUTF8(n->getNodeValue()));
574 auto_ptr_char lang(e->getAttributeNS(saml::XML::XML_NS,L(lang)));
575 m_names[lang.get()]=name.get();
578 else if (saml::XML::isElementNamed(e,::XML::SAML2META_NS,SHIB_L(OrganizationDisplayName))) {
579 n=e->getFirstChild();
581 auto_ptr<char> display(toUTF8(n->getNodeValue()));
582 auto_ptr_char lang(e->getAttributeNS(saml::XML::XML_NS,L(lang)));
583 m_displays[lang.get()]=display.get();
586 else if (saml::XML::isElementNamed(e,::XML::SAML2META_NS,SHIB_L(OrganizationURL))) {
587 n=e->getFirstChild();
589 auto_ptr<char> url(toUTF8(n->getNodeValue()));
590 auto_ptr_char lang(e->getAttributeNS(saml::XML::XML_NS,L(lang)));
591 m_urls[lang.get()]=url.get();
594 e=saml::XML::getNextSiblingElement(e);
598 XMLMetadataImpl::EncryptionMethod::EncryptionMethod(const DOMElement* e) : m_root(e)
600 m_alg=e->getAttributeNS(NULL,SHIB_L(Algorithm));
601 e=saml::XML::getFirstChildElement(e);
603 if (saml::XML::isElementNamed(e,::XML::XMLENC_NS,SHIB_L(KeySize))) {
604 DOMNode* n=e->getFirstChild();
605 if (n) m_size=XMLString::parseInt(n->getNodeValue());
607 else if (saml::XML::isElementNamed(e,saml::XML::XMLSIG_NS,SHIB_L(DigestMethod))) {
608 DOMNode* n=e->getFirstChild();
609 if (n) m_digest=n->getNodeValue();
611 else if (saml::XML::isElementNamed(e,::XML::XMLENC_NS,SHIB_L(OAEParams))) {
612 DOMNode* n=e->getFirstChild();
613 if (n) m_params=n->getNodeValue();
615 e=saml::XML::getNextSiblingElement(e);
619 XMLMetadataImpl::KeyDescriptor::KeyDescriptor(const DOMElement* e) : m_root(e), m_use(unspecified), m_klist(NULL)
622 saml::NDC ndc("KeyDescriptor");
624 if (!XMLString::compareString(e->getAttributeNS(NULL,SHIB_L(use)),SHIB_L(encryption)))
626 else if (!XMLString::compareString(e->getAttributeNS(NULL,SHIB_L(use)),SHIB_L(signing)))
629 m_klist = new DSIGKeyInfoList(NULL);
631 // Process ds:KeyInfo
632 e=saml::XML::getFirstChildElement(e);
634 // We let XMLSec hack through anything it can. This should evolve over time, or we can
635 // plug in our own KeyResolver later...
636 DOMElement* child=saml::XML::getFirstChildElement(e);
639 if (!m_klist->addXMLKeyInfo(child)) {
640 Category::getInstance(XMLPROVIDERS_LOGCAT".Metadata").warn(
641 "skipped unsupported ds:KeyInfo child element");
644 catch (XSECCryptoException& xe) {
645 Category::getInstance(XMLPROVIDERS_LOGCAT".Metadata").error(
646 "unable to process ds:KeyInfo child element: %s",xe.getMsg());
648 child=saml::XML::getNextSiblingElement(child);
651 // Check for encryption methods.
652 e=saml::XML::getNextSiblingElement(e);
653 while (e && saml::XML::isElementNamed(e,::XML::SAML2META_NS,SHIB_L(EncryptionMethod)))
654 m_methods.push_back(new EncryptionMethod(e));
657 XMLMetadataImpl::KeyDescriptor::~KeyDescriptor()
659 for (vector<const XENCEncryptionMethod*>::iterator i=m_methods.begin(); i!=m_methods.end(); i++)
660 delete const_cast<XENCEncryptionMethod*>(*i);
664 XMLMetadataImpl::KeyAuthority::KeyAuthority(const DOMElement* e) : m_depth(1)
667 saml::NDC ndc("KeyAuthority");
669 if (e->hasAttributeNS(NULL,SHIB_L(VerifyDepth)))
670 m_depth=XMLString::parseInt(e->getAttributeNS(NULL,SHIB_L(VerifyDepth)));
672 // Process ds:KeyInfo children
673 e=saml::XML::getFirstChildElement(e,saml::XML::XMLSIG_NS,L(KeyInfo));
675 auto_ptr<DSIGKeyInfoList> klist(new DSIGKeyInfoList(NULL));
677 // We let XMLSec hack through anything it can. This should evolve over time, or we can
678 // plug in our own KeyResolver later...
679 DOMElement* child=saml::XML::getFirstChildElement(e);
682 if (!klist->addXMLKeyInfo(child)) {
683 Category::getInstance(XMLPROVIDERS_LOGCAT".Metadata").warn(
684 "skipped unresolvable ds:KeyInfo child element");
687 catch (XSECCryptoException& xe) {
688 Category::getInstance(XMLPROVIDERS_LOGCAT".Metadata").error(
689 "unable to process ds:KeyInfo child element: %s",xe.getMsg());
691 child=saml::XML::getNextSiblingElement(child);
694 if (klist->getSize()>0)
695 m_klists.push_back(klist.release());
697 Category::getInstance(XMLPROVIDERS_LOGCAT".Metadata").warn(
698 "skipping ds:KeyInfo with no resolvable child elements");
699 e=saml::XML::getNextSiblingElement(e,saml::XML::XMLSIG_NS,L(KeyInfo));
703 XMLMetadataImpl::KeyAuthority::~KeyAuthority()
705 for (vector<DSIGKeyInfoList*>::iterator i=m_klists.begin(); i!=m_klists.end(); i++)
709 XMLMetadataImpl::Role::Role(const EntityDescriptor* provider, time_t validUntil, const DOMElement* e)
710 : m_provider(provider), m_errorURL(NULL), m_protocolEnumCopy(NULL), m_org(NULL), m_validUntil(validUntil), m_root(e)
712 // Check the root element namespace. If SAML2, assume it's the std schema.
713 if (e && !XMLString::compareString(e->getNamespaceURI(),::XML::SAML2META_NS)) {
715 if (e->hasAttributeNS(NULL,SHIB_L(validUntil))) {
716 SAMLDateTime exp(e->getAttributeNS(NULL,SHIB_L(validUntil)));
718 m_validUntil=min(m_validUntil,exp.getEpoch());
721 if (e->hasAttributeNS(NULL,SHIB_L(errorURL)))
722 m_errorURL=toUTF8(e->getAttributeNS(NULL,SHIB_L(errorURL)));
724 // Chop the protocol list into pieces...assume any whitespace can appear in between.
725 m_protocolEnumCopy=XMLString::replicate(e->getAttributeNS(NULL,SHIB_L(protocolSupportEnumeration)));
726 XMLCh* temp=m_protocolEnumCopy;
727 while (temp && *temp) {
729 while (*temp && !XMLChar1_1::isWhitespace(*temp)) temp++;
732 m_protocolEnum.push_back(start);
733 while (*temp && XMLChar1_1::isWhitespace(*temp)) temp++;
736 e=saml::XML::getFirstChildElement(m_root,::XML::SAML2META_NS,SHIB_L(KeyDescriptor));
738 m_keys.push_back(new KeyDescriptor(e));
739 e=saml::XML::getNextSiblingElement(e,::XML::SAML2META_NS,SHIB_L(KeyDescriptor));
742 e=saml::XML::getFirstChildElement(m_root,::XML::SAML2META_NS,SHIB_L(Organization));
744 m_org=new Organization(e);
746 e=saml::XML::getFirstChildElement(m_root,::XML::SAML2META_NS,SHIB_L(ContactPerson));
748 m_contacts.push_back(new ContactPerson(e));
749 e=saml::XML::getNextSiblingElement(e,::XML::SAML2META_NS,SHIB_L(ContactPerson));
754 XMLMetadataImpl::Role::~Role()
758 if (m_protocolEnumCopy) XMLString::release(&m_protocolEnumCopy);
759 for (vector<const IKeyDescriptor*>::iterator i=m_keys.begin(); i!=m_keys.end(); i++)
760 delete const_cast<IKeyDescriptor*>(*i);
761 for (vector<const IContactPerson*>::iterator j=m_contacts.begin(); j!=m_contacts.end(); j++)
762 delete const_cast<IContactPerson*>(*j);
765 bool XMLMetadataImpl::Role::hasSupport(const XMLCh* protocol) const
767 Iterator<const XMLCh*> i(m_protocolEnum);
768 while (i.hasNext()) {
769 if (!XMLString::compareString(protocol,i.next()))
775 XMLMetadataImpl::SSORole::SSORole(const EntityDescriptor* provider, time_t validUntil, const DOMElement* e)
776 : Role(provider,validUntil,e)
778 // Check the root element namespace. If SAML2, assume it's the std schema.
779 if (!XMLString::compareString(e->getNamespaceURI(),::XML::SAML2META_NS)) {
781 DOMNodeList* nlist=e->getElementsByTagNameNS(::XML::SAML2META_NS,SHIB_L(ArtifactResolutionService));
782 for (i=0; nlist && i<nlist->getLength(); i++)
783 m_artifact.add(new IndexedEndpoint(static_cast<DOMElement*>(nlist->item(i))));
785 nlist=e->getElementsByTagNameNS(::XML::SAML2META_NS,SHIB_L(SingleLogoutService));
786 for (i=0; nlist && i<nlist->getLength(); i++)
787 m_logout.add(new Endpoint(static_cast<DOMElement*>(nlist->item(i))));
789 nlist=e->getElementsByTagNameNS(::XML::SAML2META_NS,SHIB_L(ManageNameIDService));
790 for (i=0; nlist && i<nlist->getLength(); i++)
791 m_nameid.add(new Endpoint(static_cast<DOMElement*>(nlist->item(i))));
793 nlist=e->getElementsByTagNameNS(::XML::SAML2META_NS,SHIB_L(NameIDFormat));
794 for (i=0; nlist && i<nlist->getLength(); i++) {
795 DOMNode* n=nlist->item(i)->getFirstChild();
796 if (n) m_formats.push_back(n->getNodeValue());
800 // For old style, we just do SAML 1.1 compatibility with Shib handles.
801 m_protocolEnum.push_back(saml::XML::SAML11_PROTOCOL_ENUM);
802 m_formats.push_back(shibboleth::Constants::SHIB_NAMEID_FORMAT_URI);
806 XMLMetadataImpl::ScopedRole::ScopedRole(const DOMElement* e)
808 // Check the root element namespace. If SAML2, assume it's the std schema.
809 DOMNodeList* nlist=NULL;
810 if (!XMLString::compareString(e->getNamespaceURI(),::XML::SAML2META_NS)) {
811 e=saml::XML::getFirstChildElement(e,::XML::SAML2META_NS,SHIB_L(Extensions));
812 nlist=e->getElementsByTagNameNS(::XML::SHIBMETA_NS,SHIB_L(Scope));
815 nlist=e->getElementsByTagNameNS(::XML::SHIB_NS,SHIB_L(Domain));
818 for (int i=0; nlist && i < nlist->getLength(); i++) {
819 const XMLCh* dom=(nlist->item(i)->hasChildNodes()) ? nlist->item(i)->getFirstChild()->getNodeValue() : NULL;
821 const XMLCh* regexp=static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,SHIB_L(regexp));
823 pair<const XMLCh*,bool>(dom,(regexp && (*regexp==chLatin_t || *regexp==chDigit_1)))
829 XMLMetadataImpl::IDPRole::IDPRole(const EntityDescriptor* provider, time_t validUntil, const DOMElement* e)
830 : SSORole(provider,validUntil,e), ScopedRole(e), m_wantAuthnRequestsSigned(false), m_sourceId(NULL)
832 // Check the root element namespace. If SAML2, assume it's the std schema.
833 if (!XMLString::compareString(e->getNamespaceURI(),::XML::SAML2META_NS)) {
834 const XMLCh* flag=e->getAttributeNS(NULL,SHIB_L(WantAuthnRequestsSigned));
835 m_wantAuthnRequestsSigned=(flag && (*flag==chDigit_1 || *flag==chLatin_t));
837 // Check for SourceID extension.
838 DOMElement* ext=saml::XML::getFirstChildElement(e,::XML::SAML2META_NS,SHIB_L(Extensions));
840 ext=saml::XML::getFirstChildElement(ext,saml::XML::SAML_ARTIFACT_SOURCEID,SHIB_L(SourceID));
841 if (ext && ext->hasChildNodes())
842 m_sourceId=ext->getFirstChild()->getNodeValue();
846 DOMNodeList* nlist=e->getElementsByTagNameNS(::XML::SAML2META_NS,SHIB_L(SingleSignOnService));
847 for (i=0; nlist && i<nlist->getLength(); i++)
848 m_sso.add(new Endpoint(static_cast<DOMElement*>(nlist->item(i))));
850 nlist=e->getElementsByTagNameNS(::XML::SAML2META_NS,SHIB_L(NameIDMappingService));
851 for (i=0; nlist && i<nlist->getLength(); i++)
852 m_mapping.add(new Endpoint(static_cast<DOMElement*>(nlist->item(i))));
854 nlist=e->getElementsByTagNameNS(::XML::SAML2META_NS,SHIB_L(AssertionIDRequestService));
855 for (i=0; nlist && i<nlist->getLength(); i++)
856 m_idreq.add(new Endpoint(static_cast<DOMElement*>(nlist->item(i))));
858 nlist=e->getElementsByTagNameNS(::XML::SAML2META_NS,SHIB_L(AttributeProfile));
859 for (i=0; nlist && i<nlist->getLength(); i++) {
860 DOMNode* n=nlist->item(i)->getFirstChild();
861 if (n) m_attrprofs.push_back(n->getNodeValue());
864 nlist=e->getElementsByTagNameNS(::XML::SAML2ASSERT_NS,L(Attribute));
865 for (i=0; nlist && i<nlist->getLength(); i++) {
866 // For now, we need to convert these to plain SAML 1.1 attributes.
867 DOMElement* src=static_cast<DOMElement*>(nlist->item(i));
868 DOMElement* copy=e->getOwnerDocument()->createElementNS(saml::XML::SAML_NS,L(Attribute));
869 copy->setAttributeNS(NULL,L(AttributeName),src->getAttributeNS(NULL,SHIB_L(Name)));
870 copy->setAttributeNS(NULL,L(AttributeNamespace),src->getAttributeNS(NULL,SHIB_L(NameFormat)));
871 src=saml::XML::getFirstChildElement(src,::XML::SAML2ASSERT_NS,L(AttributeValue));
873 src=saml::XML::getNextSiblingElement(src,::XML::SAML2ASSERT_NS,L(AttributeValue));
874 DOMElement* val=e->getOwnerDocument()->createElementNS(saml::XML::SAML_NS,L(AttributeValue));
875 DOMNamedNodeMap* attrs = src->getAttributes();
876 for (int j=0; j<attrs->getLength(); j++)
877 val->setAttributeNodeNS(static_cast<DOMAttr*>(e->getOwnerDocument()->importNode(attrs->item(j),true)));
878 while (src->hasChildNodes())
879 val->appendChild(src->getFirstChild());
880 copy->appendChild(val);
882 m_attrs.push_back(SAMLAttribute::getInstance(copy));
886 m_attrprofs.push_back(Constants::SHIB_ATTRIBUTE_NAMESPACE_URI);
888 DOMNodeList* nlist=e->getElementsByTagNameNS(::XML::SHIB_NS,SHIB_L(HandleService));
889 for (i=0; nlist && i<nlist->getLength(); i++) {
890 // Manufacture an endpoint for the "Shib" binding.
892 new Endpoint(Constants::SHIB_AUTHNREQUEST_PROFILE_URI,static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,SHIB_L(Location)))
895 // We're going to "mock up" a KeyDescriptor that contains the specified Name as a ds:KeyName.
896 DOMElement* kd=e->getOwnerDocument()->createElementNS(::XML::SAML2META_NS,SHIB_L(KeyDescriptor));
897 DOMElement* ki=e->getOwnerDocument()->createElementNS(saml::XML::XMLSIG_NS,L(KeyInfo));
898 DOMElement* kn=e->getOwnerDocument()->createElementNS(saml::XML::XMLSIG_NS,SHIB_L(KeyName));
900 e->getOwnerDocument()->createTextNode(
901 static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,SHIB_L(Name))
906 kd->setAttributeNS(NULL,SHIB_L(use),SHIB_L(signing));
907 m_keys.push_back(new KeyDescriptor(kd));
912 XMLMetadataImpl::IDPRole::~IDPRole()
914 for (vector<const SAMLAttribute*>::iterator i=m_attrs.begin(); i!=m_attrs.end(); i++)
915 delete const_cast<SAMLAttribute*>(*i);
918 XMLMetadataImpl::AARole::AARole(const EntityDescriptor* provider, time_t validUntil, const DOMElement* e)
919 : Role(provider,validUntil,e), ScopedRole(e)
921 // Check the root element namespace. If SAML2, assume it's the std schema.
922 if (!XMLString::compareString(e->getNamespaceURI(),::XML::SAML2META_NS)) {
924 DOMNodeList* nlist=e->getElementsByTagNameNS(::XML::SAML2META_NS,SHIB_L(AttributeService));
925 for (i=0; nlist && i<nlist->getLength(); i++)
926 m_query.add(new Endpoint(static_cast<DOMElement*>(nlist->item(i))));
928 nlist=e->getElementsByTagNameNS(::XML::SAML2META_NS,SHIB_L(AssertionIDRequestService));
929 for (i=0; nlist && i<nlist->getLength(); i++)
930 m_idreq.add(new Endpoint(static_cast<DOMElement*>(nlist->item(i))));
932 nlist=e->getElementsByTagNameNS(::XML::SAML2META_NS,SHIB_L(NameIDFormat));
933 for (i=0; nlist && i<nlist->getLength(); i++) {
934 DOMNode* n=nlist->item(i)->getFirstChild();
935 if (n) m_formats.push_back(n->getNodeValue());
938 nlist=e->getElementsByTagNameNS(::XML::SAML2META_NS,SHIB_L(AttributeProfile));
939 for (i=0; nlist && i<nlist->getLength(); i++) {
940 DOMNode* n=nlist->item(i)->getFirstChild();
941 if (n) m_attrprofs.push_back(n->getNodeValue());
944 nlist=e->getElementsByTagNameNS(::XML::SAML2ASSERT_NS,L(Attribute));
945 for (i=0; nlist && i<nlist->getLength(); i++) {
946 // For now, we need to convert these to plain SAML 1.1 attributes.
947 DOMElement* src=static_cast<DOMElement*>(nlist->item(i));
948 DOMElement* copy=e->getOwnerDocument()->createElementNS(saml::XML::SAML_NS,L(Attribute));
949 copy->setAttributeNS(NULL,L(AttributeName),src->getAttributeNS(NULL,SHIB_L(Name)));
950 copy->setAttributeNS(NULL,L(AttributeNamespace),src->getAttributeNS(NULL,SHIB_L(NameFormat)));
951 src=saml::XML::getFirstChildElement(src,::XML::SAML2ASSERT_NS,L(AttributeValue));
953 src=saml::XML::getNextSiblingElement(src,::XML::SAML2ASSERT_NS,L(AttributeValue));
954 DOMElement* val=e->getOwnerDocument()->createElementNS(saml::XML::SAML_NS,L(AttributeValue));
955 DOMNamedNodeMap* attrs = src->getAttributes();
956 for (int j=0; j<attrs->getLength(); j++)
957 val->setAttributeNodeNS(static_cast<DOMAttr*>(e->getOwnerDocument()->importNode(attrs->item(j),true)));
958 while (src->hasChildNodes())
959 val->appendChild(src->getFirstChild());
960 copy->appendChild(val);
962 m_attrs.push_back(SAMLAttribute::getInstance(copy));
966 // For old style, we just do SAML 1.1 compatibility with Shib handles.
967 m_protocolEnum.push_back(saml::XML::SAML11_PROTOCOL_ENUM);
968 m_formats.push_back(Constants::SHIB_NAMEID_FORMAT_URI);
969 m_attrprofs.push_back(Constants::SHIB_ATTRIBUTE_NAMESPACE_URI);
971 DOMNodeList* nlist=e->getElementsByTagNameNS(::XML::SHIB_NS,SHIB_L(AttributeAuthority));
972 for (i=0; nlist && i<nlist->getLength(); i++) {
973 // Manufacture an endpoint for the SOAP binding.
977 static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,SHIB_L(Location))
981 // We're going to "mock up" a KeyDescriptor that contains the specified Name as a ds:KeyName.
982 DOMElement* kd=e->getOwnerDocument()->createElementNS(::XML::SAML2META_NS,SHIB_L(KeyDescriptor));
983 DOMElement* ki=e->getOwnerDocument()->createElementNS(saml::XML::XMLSIG_NS,L(KeyInfo));
984 DOMElement* kn=e->getOwnerDocument()->createElementNS(saml::XML::XMLSIG_NS,SHIB_L(KeyName));
986 e->getOwnerDocument()->createTextNode(
987 static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,SHIB_L(Name))
992 m_keys.push_back(new KeyDescriptor(kd));
997 XMLMetadataImpl::AARole::~AARole()
999 for (vector<const SAMLAttribute*>::iterator i=m_attrs.begin(); i!=m_attrs.end(); i++)
1000 delete const_cast<SAMLAttribute*>(*i);
1003 XMLMetadataImpl::EntityDescriptor::EntityDescriptor(
1004 const DOMElement* e, XMLMetadataImpl* wrapper, time_t validUntil, const IEntitiesDescriptor* parent
1005 ) : m_root(e), m_parent(parent), m_org(NULL), m_validUntil(validUntil)
1007 // Check the root element namespace. If SAML2, assume it's the std schema.
1008 if (!XMLString::compareString(e->getNamespaceURI(),::XML::SAML2META_NS)) {
1009 m_id=e->getAttributeNS(NULL,SHIB_L(entityID));
1011 if (e->hasAttributeNS(NULL,SHIB_L(validUntil))) {
1012 SAMLDateTime exp(e->getAttributeNS(NULL,SHIB_L(validUntil)));
1013 exp.parseDateTime();
1014 m_validUntil=min(validUntil,exp.getEpoch());
1017 DOMElement* child=saml::XML::getFirstChildElement(e);
1019 // Process the various kinds of children that we care about...
1020 if (saml::XML::isElementNamed(e,::XML::SAML2META_NS,SHIB_L(Extensions))) {
1021 DOMElement* ext = saml::XML::getFirstChildElement(child,::XML::SHIBMETA_NS,SHIB_L(KeyAuthority));
1023 m_keyauths.push_back(new KeyAuthority(ext));
1024 ext = saml::XML::getNextSiblingElement(ext,::XML::SHIBMETA_NS,SHIB_L(KeyAuthority));
1027 else if (saml::XML::isElementNamed(child,::XML::SAML2META_NS,SHIB_L(ContactPerson))) {
1028 m_contacts.push_back(new ContactPerson(child));
1030 else if (saml::XML::isElementNamed(child,::XML::SAML2META_NS,SHIB_L(Organization))) {
1031 m_org=new Organization(child);
1033 else if (saml::XML::isElementNamed(child,::XML::SAML2META_NS,SHIB_L(AdditionalMetadataLocation))) {
1034 DOMNode* loc=child->getFirstChild();
1037 pair<const XMLCh*,const XMLCh*>(child->getAttributeNS(NULL,::XML::Literals::_namespace),loc->getNodeValue())
1040 else if (saml::XML::isElementNamed(child,::XML::SAML2META_NS,SHIB_L(IDPSSODescriptor))) {
1041 m_roles.push_back(new IDPRole(this,m_validUntil,child));
1043 else if (saml::XML::isElementNamed(child,::XML::SAML2META_NS,SHIB_L(AttributeAuthorityDescriptor))) {
1044 m_roles.push_back(new AARole(this,m_validUntil,child));
1046 child = saml::XML::getNextSiblingElement(child);
1050 m_id=e->getAttributeNS(NULL,SHIB_L(Name));
1051 m_errorURL=auto_ptr<char>(toUTF8(e->getAttributeNS(NULL,SHIB_L(ErrorURL))));
1053 bool idp=false,aa=false; // only want to build a role once
1054 DOMElement* child=saml::XML::getFirstChildElement(e);
1056 // Process the various kinds of OriginSite children that we care about...
1057 if (saml::XML::isElementNamed(child,::XML::SHIB_NS,SHIB_L(Contact))) {
1058 m_contacts.push_back(new ContactPerson(child));
1060 else if (saml::XML::isElementNamed(child,::XML::SHIB_NS,SHIB_L(HandleService)) && !idp) {
1061 // Create the IDP role if needed.
1062 m_roles.push_back(new IDPRole(this, m_validUntil, e));
1065 else if (saml::XML::isElementNamed(child,::XML::SHIB_NS,SHIB_L(AttributeAuthority)) && !aa) {
1066 // Create the AA role if needed.
1067 m_roles.push_back(new AARole(this, m_validUntil, e));
1070 child = saml::XML::getNextSiblingElement(child);
1074 auto_ptr_char id(m_id);
1075 wrapper->m_sites.insert(pair<string,const EntityDescriptor*>(id.get(),this));
1077 // Look for an IdP role, and register the artifact source ID and endpoints.
1078 const IDPRole* idp=NULL;
1079 for (vector<const IRoleDescriptor*>::const_iterator r=m_roles.begin(); r!=m_roles.end(); r++) {
1080 if (idp=dynamic_cast<const IDPRole*>(*r)) {
1081 if (idp->m_sourceId) {
1082 auto_ptr_char sourceid(idp->m_sourceId);
1083 wrapper->m_sources.insert(pair<string,const EntityDescriptor*>(sourceid.get(),this));
1086 string sourceid=SAMLArtifact::toHex(SAMLArtifactType0001::generateSourceId(id.get()));
1087 Category::getInstance(XMLPROVIDERS_LOGCAT".Metadata").debug(
1088 "generated artifact SourceID (%s) for entity (%s)",sourceid.c_str(),id.get()
1090 wrapper->m_sources.insert(pair<string,const EntityDescriptor*>(sourceid,this));
1092 Iterator<const IEndpoint*> locs=idp->getArtifactResolutionServiceManager()->getEndpoints();
1093 while (locs.hasNext()) {
1094 auto_ptr_char loc(locs.next()->getLocation());
1095 wrapper->m_sources.insert(pair<string,const EntityDescriptor*>(loc.get(),this));
1101 const IIDPSSODescriptor* XMLMetadataImpl::EntityDescriptor::getIDPSSODescriptor(const XMLCh* protocol) const
1103 const IIDPSSODescriptor* ret=NULL;
1104 for (vector<const IRoleDescriptor*>::const_iterator i=m_roles.begin(); i!=m_roles.end(); i++) {
1105 if ((*i)->hasSupport(protocol) && (*i)->isValid() && (ret=dynamic_cast<const IIDPSSODescriptor*>(*i)))
1111 const IAttributeAuthorityDescriptor* XMLMetadataImpl::EntityDescriptor::getAttributeAuthorityDescriptor(const XMLCh* protocol) const
1113 const IAttributeAuthorityDescriptor* ret=NULL;
1114 for (vector<const IRoleDescriptor*>::const_iterator i=m_roles.begin(); i!=m_roles.end(); i++) {
1115 if ((*i)->hasSupport(protocol) && (*i)->isValid() && (ret=dynamic_cast<const IAttributeAuthorityDescriptor*>(*i)))
1121 XMLMetadataImpl::EntityDescriptor::~EntityDescriptor()
1124 for (vector<const IContactPerson*>::iterator i=m_contacts.begin(); i!=m_contacts.end(); i++)
1125 delete const_cast<IContactPerson*>(*i);
1126 for (vector<const IRoleDescriptor*>::iterator j=m_roles.begin(); j!=m_roles.end(); j++)
1127 delete const_cast<IRoleDescriptor*>(*j);
1128 for (vector<const IKeyAuthority*>::iterator k=m_keyauths.begin(); k!=m_keyauths.end(); k++)
1129 delete const_cast<IKeyAuthority*>(*k);
1132 XMLMetadataImpl::EntitiesDescriptor::EntitiesDescriptor(
1133 const DOMElement* e, XMLMetadataImpl* wrapper, time_t validUntil, const IEntitiesDescriptor* parent
1134 ) : m_root(e), m_name(e->getAttributeNS(NULL,SHIB_L(Name))), m_parent(parent), m_validUntil(validUntil)
1136 // Check the root element namespace. If SAML2, assume it's the std schema.
1137 if (!XMLString::compareString(e->getNamespaceURI(),::XML::SAML2META_NS)) {
1139 if (e->hasAttributeNS(NULL,SHIB_L(validUntil))) {
1140 SAMLDateTime exp(e->getAttributeNS(NULL,SHIB_L(validUntil)));
1141 exp.parseDateTime();
1142 m_validUntil=min(validUntil,exp.getEpoch());
1145 e=saml::XML::getFirstChildElement(e);
1147 if (saml::XML::isElementNamed(e,::XML::SAML2META_NS,SHIB_L(Extensions))) {
1148 DOMElement* ext = saml::XML::getFirstChildElement(e,::XML::SHIBMETA_NS,SHIB_L(KeyAuthority));
1150 m_keyauths.push_back(new KeyAuthority(ext));
1151 ext = saml::XML::getNextSiblingElement(ext,::XML::SHIBMETA_NS,SHIB_L(KeyAuthority));
1154 else if (saml::XML::isElementNamed(e,::XML::SAML2META_NS,SHIB_L(EntitiesDescriptor)))
1155 m_groups.push_back(new EntitiesDescriptor(e,wrapper,m_validUntil,this));
1156 else if (saml::XML::isElementNamed(e,::XML::SAML2META_NS,SHIB_L(EntityDescriptor)))
1157 m_providers.push_back(new EntityDescriptor(e,wrapper,m_validUntil,this));
1158 e=saml::XML::getNextSiblingElement(e);
1162 e=saml::XML::getFirstChildElement(e);
1164 if (saml::XML::isElementNamed(e,::XML::SHIB_NS,SHIB_L(SiteGroup)))
1165 m_groups.push_back(new EntitiesDescriptor(e,wrapper,m_validUntil,this));
1166 else if (saml::XML::isElementNamed(e,::XML::SHIB_NS,SHIB_L(OriginSite)))
1167 m_providers.push_back(new EntityDescriptor(e,wrapper,m_validUntil,this));
1168 e=saml::XML::getNextSiblingElement(e);
1173 XMLMetadataImpl::EntitiesDescriptor::~EntitiesDescriptor()
1175 for (vector<const IEntityDescriptor*>::iterator i=m_providers.begin(); i!=m_providers.end(); i++)
1176 delete const_cast<IEntityDescriptor*>(*i);
1177 for (vector<const IEntitiesDescriptor*>::iterator j=m_groups.begin(); j!=m_groups.end(); j++)
1178 delete const_cast<IEntitiesDescriptor*>(*j);
1179 for (vector<const IKeyAuthority*>::iterator k=m_keyauths.begin(); k!=m_keyauths.end(); k++)
1180 delete const_cast<IKeyAuthority*>(*k);
1183 void XMLMetadataImpl::init()
1188 Category& log=Category::getInstance(XMLPROVIDERS_LOGCAT".Metadata");
1192 if (saml::XML::isElementNamed(m_root,::XML::SAML2META_NS,SHIB_L(EntitiesDescriptor)))
1193 m_rootGroup=new EntitiesDescriptor(m_root,this);
1194 else if (saml::XML::isElementNamed(m_root,::XML::SAML2META_NS,SHIB_L(EntityDescriptor)))
1195 m_rootProvider=new EntityDescriptor(m_root,this);
1196 else if (saml::XML::isElementNamed(m_root,::XML::SHIB_NS,SHIB_L(SiteGroup)))
1197 m_rootGroup=new EntitiesDescriptor(m_root,this);
1198 else if (saml::XML::isElementNamed(m_root,::XML::SHIB_NS,SHIB_L(OriginSite)))
1199 m_rootProvider=new EntityDescriptor(m_root,this);
1201 log.error("Construction requires a valid SAML metadata file");
1202 throw MetadataException("Construction requires a valid SAML metadata file");
1205 catch (SAMLException& e)
1207 log.errorStream() << "Error while parsing SAML metadata: " << e.what() << CategoryStream::ENDLINE;
1208 this->~XMLMetadataImpl();
1214 log.error("Unexpected error while parsing SAML metadata");
1215 this->~XMLMetadataImpl();
1221 XMLMetadataImpl::~XMLMetadataImpl()
1224 delete m_rootProvider;
1227 const IEntityDescriptor* XMLMetadata::lookup(const char* providerId, bool strict) const
1229 if (strict && m_exclusions && m_set.find(providerId)!=m_set.end())
1231 else if (strict && !m_exclusions && m_set.find(providerId)==m_set.end())
1234 XMLMetadataImpl* impl=dynamic_cast<XMLMetadataImpl*>(getImplementation());
1235 pair<XMLMetadataImpl::sitemap_t::const_iterator,XMLMetadataImpl::sitemap_t::const_iterator> range=
1236 impl->m_sites.equal_range(providerId);
1238 time_t now=time(NULL);
1239 for (XMLMetadataImpl::sitemap_t::const_iterator i=range.first; i!=range.second; i++)
1240 if (now < i->second->getValidUntil())
1243 if (!strict && range.first!=range.second)
1244 return range.first->second;
1249 const IEntityDescriptor* XMLMetadata::lookup(const XMLCh* providerId, bool strict) const
1251 auto_ptr_char temp(providerId);
1252 return lookup(temp.get(),strict);
1255 const IEntityDescriptor* XMLMetadata::lookup(const SAMLArtifact* artifact) const
1257 time_t now=time(NULL);
1258 XMLMetadataImpl* impl=dynamic_cast<XMLMetadataImpl*>(getImplementation());
1259 pair<XMLMetadataImpl::sitemap_t::const_iterator,XMLMetadataImpl::sitemap_t::const_iterator> range;
1261 // Depends on type of artifact.
1262 const SAMLArtifactType0001* type1=dynamic_cast<const SAMLArtifactType0001*>(artifact);
1264 range=impl->m_sources.equal_range(SAMLArtifact::toHex(type1->getSourceID()));
1267 const SAMLArtifactType0002* type2=dynamic_cast<const SAMLArtifactType0002*>(artifact);
1269 range=impl->m_sources.equal_range(type2->getSourceLocation());
1275 // Check exclude list.
1276 if (range.first!=range.second) {
1277 auto_ptr_char id(range.first->second->getId());
1278 if (m_exclusions && m_set.find(id.get())!=m_set.end())
1280 else if (!m_exclusions && m_set.find(id.get())==m_set.end())
1283 for (XMLMetadataImpl::sitemap_t::const_iterator i=range.first; i!=range.second; i++)
1284 if (now < i->second->getValidUntil())
1291 pair<const IEntitiesDescriptor*,const IEntityDescriptor*> XMLMetadata::getRoot() const
1293 XMLMetadataImpl* impl=dynamic_cast<XMLMetadataImpl*>(getImplementation());
1294 return make_pair(impl->m_rootGroup,impl->m_rootProvider);