2 * The Shibboleth License, Version 1. Copyright (c) 2002 University Corporation for Advanced Internet Development, Inc.
3 * All rights reserved Redistribution and use in source and binary forms, with or without modification, are permitted
4 * provided that the following conditions are met: Redistributions of source code must retain the above copyright
5 * notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the
6 * above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other
7 * materials provided with the distribution, if any, must include the following acknowledgment: "This product includes
8 * software developed by the University Corporation for Advanced Internet Development <http://www.ucaid.edu>Internet2
9 * Project. Alternately, this acknowledegement may appear in the software itself, if and wherever such third-party
10 * acknowledgments normally appear. Neither the name of Shibboleth nor the names of its contributors, nor Internet2,
11 * nor the University Corporation for Advanced Internet Development, Inc., nor UCAID may be used to endorse or promote
12 * products derived from this software without specific prior written permission. For written permission, please
13 * contact shibboleth@shibboleth.org Products derived from this software may not be called Shibboleth, Internet2,
14 * UCAID, or the University Corporation for Advanced Internet Development, nor may Shibboleth appear in their name,
15 * without prior written permission of the University Corporation for Advanced Internet Development. THIS SOFTWARE IS
16 * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES,
17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
18 * NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS
19 * WITH LICENSEE. IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY CORPORATION FOR ADVANCED
20 * INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
23 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
27 package edu.internet2.middleware.shibboleth.metadata.provider;
29 import java.net.MalformedURLException;
31 import java.security.NoSuchAlgorithmException;
32 import java.text.ParseException;
33 import java.text.SimpleDateFormat;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.HashMap;
38 import java.util.Iterator;
40 import java.util.TimeZone;
42 import org.apache.commons.codec.binary.Hex;
43 import org.apache.log4j.Logger;
44 import org.apache.xml.security.encryption.EncryptionMethod;
45 import org.apache.xml.security.exceptions.XMLSecurityException;
46 import org.apache.xml.security.keys.KeyInfo;
47 import org.opensaml.SAMLAttribute;
48 import org.opensaml.SAMLBinding;
49 import org.opensaml.SAMLBrowserProfile;
50 import org.opensaml.SAMLException;
51 import org.opensaml.XML;
52 import org.opensaml.artifact.Artifact;
53 import org.opensaml.artifact.SAMLArtifactType0001;
54 import org.opensaml.artifact.SAMLArtifactType0002;
55 import org.opensaml.artifact.Util;
56 import org.w3c.dom.Attr;
57 import org.w3c.dom.Element;
58 import org.w3c.dom.NamedNodeMap;
59 import org.w3c.dom.Node;
60 import org.w3c.dom.NodeList;
62 import edu.internet2.middleware.shibboleth.common.Constants;
63 import edu.internet2.middleware.shibboleth.metadata.*;
66 * @author Scott Cantor
68 public class XMLMetadataProvider implements Metadata {
70 private static Logger log = Logger.getLogger(XMLMetadataProvider.class.getName());
71 private Map /* <String,ArrayList<EntityDescriptor> > */ sites = new HashMap();
72 private Map /* <String,ArrayList<EntityDescriptor> > */ sources = new HashMap();
73 private XMLEntityDescriptor rootProvider = null;
74 private XMLEntitiesDescriptor rootGroup = null;
76 public XMLMetadataProvider(Element e) throws SAMLException {
77 if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"EntitiesDescriptor"))
78 rootGroup=new XMLEntitiesDescriptor(e,this, Long.MAX_VALUE, null);
79 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"EntityDescriptor"))
80 rootProvider=new XMLEntityDescriptor(e,this, Long.MAX_VALUE, null);
81 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"SiteGroup"))
82 rootGroup=new XMLEntitiesDescriptor(e,this, Long.MAX_VALUE, null);
83 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"OriginSite"))
84 rootProvider=new XMLEntityDescriptor(e,this, Long.MAX_VALUE, null);
85 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"DestinationSite"))
86 rootProvider=new XMLEntityDescriptor(e,this, Long.MAX_VALUE, null);
88 log.error("Construction requires a valid SAML metadata file");
89 throw new MetadataException("Construction requires a valid SAML metadata file");
93 public EntityDescriptor lookup(String id) {
94 ArrayList list = (ArrayList)sites.get(id);
96 long now = System.currentTimeMillis();
97 for (int i=0; i<list.size(); i++) {
98 if (now < ((XMLEntityDescriptor)list.get(i)).getValidUntil())
99 return (EntityDescriptor)list.get(i);
105 public EntityDescriptor lookup(Artifact artifact) {
106 ArrayList list = null;
108 if (artifact instanceof SAMLArtifactType0001) {
109 list = (ArrayList)sources.get(((SAMLArtifactType0001)artifact).getSourceId());
111 else if (artifact instanceof SAMLArtifactType0002) {
112 list = (ArrayList)sources.get(((SAMLArtifactType0002)artifact).getSourceLocation().toString());
115 log.error("unsupported artifact type (" + artifact.getTypeCode().toString() + ")");
119 long now = System.currentTimeMillis();
120 for (int i=0; i<list.size(); i++) {
121 if (now < ((XMLEntityDescriptor)list.get(i)).getValidUntil())
122 return (EntityDescriptor)list.get(i);
128 class XMLEndpoint implements Endpoint {
129 private Element root = null;
130 private String binding = null;
131 private String location = null;
132 private String resploc = null;
134 XMLEndpoint(Element e) {
136 binding = XML.assign(e.getAttributeNS(null,"Binding"));
137 location = XML.assign(e.getAttributeNS(null,"Location"));
138 resploc = XML.assign(e.getAttributeNS(null,"ResponseLocation"));
141 XMLEndpoint(String binding, String location) {
142 this.binding = binding;
143 this.location = location;
146 public String getBinding() {
150 public String getLocation() {
154 public String getResponseLocation() {
158 public Element getElement() {
163 class XMLIndexedEndpoint extends XMLEndpoint implements IndexedEndpoint {
164 private int index = 0;
166 XMLIndexedEndpoint(Element e) {
168 index = Integer.parseInt(e.getAttributeNS(null,"index"));
171 public int getIndex() {
176 class XMLEndpointManager implements EndpointManager {
177 private ArrayList endpoints = new ArrayList();
178 Endpoint soft = null; // Soft default (not explicit)
179 Endpoint hard = null; // Hard default (explicit)
181 public Iterator getEndpoints() {
182 return endpoints.iterator();
185 public Endpoint getDefaultEndpoint() {
186 if (hard != null) return hard;
187 if (soft != null) return soft;
188 if (!endpoints.isEmpty()) return (Endpoint)endpoints.get(0);
192 public Endpoint getEndpointByIndex(int index) {
193 for (int i=0; i < endpoints.size(); i++) {
194 if (endpoints.get(i) instanceof IndexedEndpoint && index==((IndexedEndpoint)endpoints.get(i)).getIndex())
195 return (Endpoint)endpoints.get(i);
200 public Endpoint getEndpointByBinding(String binding) {
201 for (int i=0; i < endpoints.size(); i++) {
202 if (binding.equals(((Endpoint)endpoints.get(i)).getBinding()))
203 return (Endpoint)endpoints.get(i);
208 protected void add(Endpoint e) {
210 if (hard == null && e.getElement() != null) {
211 String v=XML.assign(e.getElement().getAttributeNS(null,"isDefault"));
212 if (v != null && (v.equals("1") || v.equals("true"))) // explicit default
214 else if (v == null && soft == null) // implicit default
217 else if (hard == null && soft == null) {
218 // No default yet, so this one qualifies as an implicit.
224 class XMLKeyDescriptor implements KeyDescriptor {
226 private int use = KeyDescriptor.UNSPECIFIED;
227 private KeyInfo keyInfo = null;
228 private ArrayList /* <XMLEncryptionMethod> */ methods = new ArrayList();
230 XMLKeyDescriptor(Element e) {
231 if (XML.safeCompare(e.getAttributeNS(null,"use"),"encryption"))
232 use = KeyDescriptor.ENCRYPTION;
233 else if (XML.safeCompare(e.getAttributeNS(null,"use"),"signing"))
234 use = KeyDescriptor.SIGNING;
236 e = XML.getFirstChildElement(e);
238 keyInfo = new KeyInfo(e, null);
240 catch (XMLSecurityException e1) {
241 log.error("unable to process ds:KeyInfo element: " + e1.getMessage());
244 e = XML.getNextSiblingElement(e);
245 while (e != null && XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"EncryptionMethod")) {
246 methods.add(new XMLEncryptionMethod(e));
250 public int getUse() {
254 public Iterator getEncryptionMethods() {
255 return methods.iterator();
258 public KeyInfo getKeyInfo() {
263 class XMLEncryptionMethod implements EncryptionMethod {
266 String params = null;
269 public XMLEncryptionMethod(Element e) {
270 alg = XML.assign(e.getAttributeNS(null, "Algorithm"));
271 e = XML.getFirstChildElement(e);
273 if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.XMLENC_NS,"KeySize")) {
274 if (e.hasChildNodes())
275 size = Integer.parseInt(e.getFirstChild().getNodeValue());
277 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.XMLENC_NS,"OAEParams")) {
278 if (e.hasChildNodes())
279 params = XML.assign(e.getFirstChild().getNodeValue());
281 e = XML.getNextSiblingElement(e);
285 public String getAlgorithm() {
289 public int getKeySize() {
293 public byte[] getOAEPparams() {
294 return params.getBytes();
297 public Iterator getEncryptionMethodInformation() {
301 public void setKeySize(int arg0) {
302 throw new UnsupportedOperationException("EncryptionMethod implementation is read-only.");
305 public void setOAEPparams(byte[] arg0) {
306 throw new UnsupportedOperationException("EncryptionMethod implementation is read-only.");
309 public void addEncryptionMethodInformation(Element arg0) {
310 throw new UnsupportedOperationException("EncryptionMethod implementation is read-only.");
313 public void removeEncryptionMethodInformation(Element arg0) {
314 throw new UnsupportedOperationException("EncryptionMethod implementation is read-only.");
318 class XMLKeyAuthority implements KeyAuthority {
319 private int depth = 1;
320 private ArrayList /* <KeyInfo> */ keys = new ArrayList();
322 XMLKeyAuthority(Element e) {
323 if (e.hasAttributeNS(null,"VerifyDepth"))
324 depth = Integer.parseInt(e.getAttributeNS(null,"VerifyDepth"));
325 e = XML.getFirstChildElement(e, XML.XMLSIG_NS, "KeyInfo");
328 keys.add(new KeyInfo(e, null));
330 catch (XMLSecurityException e1) {
331 log.error("unable to process ds:KeyInfo element: " + e1.getMessage());
333 e = XML.getNextSiblingElement(e, XML.XMLSIG_NS, "KeyInfo");
337 public int getVerifyDepth() {
341 public Iterator getKeyInfos() {
342 return keys.iterator();
347 class XMLOrganization implements Organization {
348 private Element root = null;
349 private HashMap /* <String,String> */ names = new HashMap();
350 private HashMap /* <String,String> */ displays = new HashMap();
351 private HashMap /* <String,URL> */ urls = new HashMap();
353 public XMLOrganization(Element e) throws MetadataException {
355 e=XML.getFirstChildElement(e);
357 if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"OrganizationName")) {
358 if (e.hasChildNodes()) {
359 names.put(e.getAttributeNS(XML.XML_NS,"lang"),XML.assign(e.getFirstChild().getNodeValue()));
362 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"OrganizationDisplayName")) {
363 if (e.hasChildNodes()) {
364 displays.put(e.getAttributeNS(XML.XML_NS,"lang"),XML.assign(e.getFirstChild().getNodeValue()));
367 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"OrganizationURL")) {
368 if (e.hasChildNodes()) {
371 u = new URL(e.getFirstChild().getNodeValue());
373 catch (MalformedURLException e1) {
374 throw new MetadataException("OrganizationURL was invalid: " + e1);
376 urls.put(e.getAttributeNS(XML.XML_NS,"lang"),u);
379 e=XML.getNextSiblingElement(e);
383 public String getName() {
384 return getName("en");
387 public String getName(String lang) {
388 return (String)names.get(lang);
391 public String getDisplayName() {
392 return getDisplayName("en");
395 public String getDisplayName(String lang) {
396 return (String)displays.get(lang);
399 public URL getURL() {
403 public URL getURL(String lang) {
404 return (URL)urls.get(lang);
409 class XMLContactPerson implements ContactPerson {
410 private Element root = null;
412 private String company = null;
413 private String givenName = null;
414 private String surName = null;
415 private ArrayList /* <String> */ emails = new ArrayList();
416 private ArrayList /* <String> */ telephones = new ArrayList();
418 public XMLContactPerson(Element e) throws MetadataException {
420 String rawType = null;
422 // Old metadata or new?
423 if (XML.isElementNamed(root, edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"Contact")) {
424 rawType = root.getAttributeNS(null,"Type");
425 surName = XML.assign(root.getAttributeNS(null,"Name"));
426 if (XML.isEmpty(surName)) {
427 throw new MetadataException("Contact is missing Name attribute.");
429 if (root.hasAttributeNS(null,"Email"))
430 emails.add(e.getAttributeNS(null,"Email"));
433 rawType = root.getAttributeNS(null,"contactType");
435 e=XML.getFirstChildElement(root);
437 if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"Company")) {
438 if (e.hasChildNodes())
439 company=XML.assign(e.getFirstChild().getNodeValue());
441 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"GivenName")) {
442 if (e.hasChildNodes())
443 givenName=XML.assign(e.getFirstChild().getNodeValue());
445 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"SurName")) {
446 if (e.hasChildNodes())
447 surName=XML.assign(e.getFirstChild().getNodeValue());
449 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"EmailAddress")) {
450 if (e.hasChildNodes())
451 emails.add(XML.assign(e.getFirstChild().getNodeValue()));
453 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"TelephoneNumber")) {
454 if (e.hasChildNodes())
455 telephones.add(XML.assign(e.getFirstChild().getNodeValue()));
457 e=XML.getNextSiblingElement(e);
461 if (rawType.equalsIgnoreCase("TECHNICAL")) {
462 type = ContactPerson.TECHNICAL;
463 } else if (rawType.equalsIgnoreCase("SUPPORT")) {
464 type = ContactPerson.SUPPORT;
465 } else if (rawType.equalsIgnoreCase("ADMINISTRATIVE")) {
466 type = ContactPerson.ADMINISTRATIVE;
467 } else if (rawType.equalsIgnoreCase("BILLING")) {
468 type = ContactPerson.BILLING;
469 } else if (rawType.equalsIgnoreCase("OTHER")) {
470 type = ContactPerson.OTHER;
472 throw new MetadataException("Contact has unknown contact type.");
476 public int getType() {
480 public String getGivenName() {
484 public String getSurName() {
488 public String getCompany() {
492 public Iterator getEmailAddresses() {
493 return emails.iterator();
496 public Iterator getTelephoneNumbers() {
497 return telephones.iterator();
500 public Element getElement() {
505 class Role implements RoleDescriptor {
506 private Element root = null;
507 private XMLEntityDescriptor provider = null;
508 private URL errorURL = null;
509 private Organization org = null;
510 private ArrayList /* <ContactPerson> */ contacts = new ArrayList();
511 private long validUntil = Long.MAX_VALUE;
512 protected ArrayList /* <String> */ protocolEnum = new ArrayList();
513 protected ArrayList /* <KeyDescriptor> */ keys = new ArrayList();
515 public Role(XMLEntityDescriptor provider, long validUntil, Element e) throws MetadataException {
517 this.validUntil = validUntil;
518 this.provider = provider;
520 // Check the root element namespace. If SAML2, assume it's the std schema.
521 if (e != null && edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS.equals(e.getNamespaceURI())) {
523 if (e.hasAttributeNS(null,"validUntil")) {
524 SimpleDateFormat formatter = null;
525 String dateTime = XML.assign(e.getAttributeNS(null,"validUntil"));
526 int dot = dateTime.indexOf('.');
528 formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
530 formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
531 formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
533 validUntil=Math.min(validUntil,formatter.parse(dateTime).getTime());
535 catch (ParseException e1) {
536 log.warn("Role descriptor contains invalid expiration time");
540 if (e.hasAttributeNS(null,"errorURL")) {
542 errorURL=new URL(e.getAttributeNS(null,"errorURL"));
544 catch (MalformedURLException e1) {
545 log.error("Role descriptor contains malformed errorURL");
549 // Chop the protocol list into pieces...assume any whitespace can appear in between.
550 protocolEnum.addAll(Arrays.asList(e.getAttributeNS(null,"protocolSupportEnumeration").split("\\s")));
552 e = XML.getFirstChildElement(root,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"KeyDescriptor");
554 keys.add(new XMLKeyDescriptor(e));
555 e = XML.getNextSiblingElement(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"KeyDescriptor");
558 e = XML.getFirstChildElement(root,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"Organization");
560 org=new XMLOrganization(e);
562 e = XML.getFirstChildElement(root,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"ContactPerson");
564 contacts.add(new XMLContactPerson(e));
565 e = XML.getNextSiblingElement(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"ContactPerson");
570 public EntityDescriptor getEntityDescriptor() {
574 public Iterator getProtocolSupportEnumeration() {
575 return protocolEnum.iterator();
578 public boolean hasSupport(String version) {
579 return protocolEnum.contains(version);
582 public boolean isValid() {
583 return System.currentTimeMillis() < validUntil;
586 public URL getErrorURL() {
587 return (errorURL != null) ? errorURL : provider.getErrorURL();
590 public Iterator getKeyDescriptors() {
591 return keys.iterator();
594 public Organization getOrganization() {
595 return (org != null) ? org : provider.getOrganization();
598 public Iterator getContactPersons() {
599 return (contacts.isEmpty()) ? provider.getContactPersons() : contacts.iterator();
602 public Element getElement() {
607 class SSORole extends Role implements SSODescriptor {
608 private XMLEndpointManager artifact = new XMLEndpointManager();
609 private XMLEndpointManager logout = new XMLEndpointManager();
610 private XMLEndpointManager nameid = new XMLEndpointManager();
611 private ArrayList /* <String> */ formats = new ArrayList();
613 public SSORole(XMLEntityDescriptor provider, long validUntil, Element e) throws MetadataException {
614 super(provider, validUntil, e);
616 // Check the root element namespace. If SAML2, assume it's the std schema.
617 if (edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS.equals(e.getNamespaceURI())) {
619 NodeList nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"ArtifactResolutionService");
620 for (i=0; i<nlist.getLength(); i++)
621 artifact.add(new XMLIndexedEndpoint((Element)nlist.item(i)));
623 nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"SingleLogoutService");
624 for (i=0; i<nlist.getLength(); i++)
625 logout.add(new XMLEndpoint((Element)nlist.item(i)));
627 nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"ManageNameIDService");
628 for (i=0; i<nlist.getLength(); i++)
629 nameid.add(new XMLEndpoint((Element)nlist.item(i)));
631 nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"NameIDFormat");
632 for (i=0; i<nlist.getLength(); i++) {
633 if (nlist.item(i).hasChildNodes())
634 formats.add(nlist.item(i).getNodeValue());
638 // For old style, we just do SAML 1.1 compatibility with Shib handles.
639 protocolEnum.add(XML.SAML11_PROTOCOL_ENUM);
640 formats.add(Constants.SHIB_NAMEID_FORMAT_URI);
644 public EndpointManager getArtifactResolutionServiceManager() {
648 public EndpointManager getSingleLogoutServiceManager() {
652 public EndpointManager getManageNameIDServiceManager() {
656 public Iterator getNameIDFormats() {
657 return formats.iterator();
661 class IDPRole extends SSORole implements IDPSSODescriptor, ScopedRoleDescriptor {
662 private ArrayList /* <Scope> */ scopes = new ArrayList();
663 private XMLEndpointManager sso = new XMLEndpointManager();
664 private XMLEndpointManager mapping = new XMLEndpointManager();
665 private XMLEndpointManager idreq = new XMLEndpointManager();
666 private ArrayList /* <String> */ attrprofs = new ArrayList();
667 private ArrayList /* <SAMLAttribute> */ attrs = new ArrayList();
668 private boolean wantAuthnRequestsSigned = false;
669 private String sourceId = null;
671 public IDPRole(XMLEntityDescriptor provider, long validUntil, Element e) throws SAMLException {
672 super(provider, validUntil, e);
673 NodeList domains=null;
675 // Check the root element namespace. If SAML2, assume it's the std schema.
676 if (edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS.equals(e.getNamespaceURI())) {
677 String flag=XML.assign(e.getAttributeNS(null,"WantAuthnRequestsSigned"));
678 wantAuthnRequestsSigned=(XML.safeCompare(flag,"1") || XML.safeCompare(flag,"true"));
680 // Check for extensions.
681 Element ext=XML.getFirstChildElement(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"Extensions");
683 Element ext1=XML.getFirstChildElement(ext,XML.SAML_ARTIFACT_SOURCEID,"SourceID");
684 if (ext1 != null && ext1.hasChildNodes())
685 sourceId=ext1.getFirstChild().getNodeValue();
686 // Save off any domain elements for later.
687 domains = ext.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SHIBMETA_NS,"Scope");
691 NodeList nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"SingleSignOnService");
692 for (i=0; i<nlist.getLength(); i++)
693 sso.add(new XMLEndpoint((Element)(nlist.item(i))));
695 nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"NameIDMappingService");
696 for (i=0; i<nlist.getLength(); i++)
697 mapping.add(new XMLEndpoint((Element)(nlist.item(i))));
699 nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"AssertionIDRequestService");
700 for (i=0; i<nlist.getLength(); i++)
701 idreq.add(new XMLEndpoint((Element)(nlist.item(i))));
703 nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"AttributeProfile");
704 for (i=0; i<nlist.getLength(); i++) {
705 if (nlist.item(i).hasChildNodes())
706 attrprofs.add(nlist.item(i).getFirstChild().getNodeValue());
709 nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2ASSERT_NS,"Attribute");
710 for (i=0; i<nlist.getLength(); i++) {
711 // For now, we need to convert these to plain SAML 1.1 attributes.
712 Element src=(Element)(nlist.item(i));
713 Element copy=e.getOwnerDocument().createElementNS(XML.SAML_NS,"Attribute");
714 copy.setAttributeNS(null,"AttributeName",src.getAttributeNS(null,"Name"));
715 copy.setAttributeNS(null,"AttributeNamespace",src.getAttributeNS(null,"NameFormat"));
716 src=XML.getFirstChildElement(src,edu.internet2.middleware.shibboleth.common.XML.SAML2ASSERT_NS,"AttributeValue");
717 while (src != null) {
718 src=XML.getNextSiblingElement(src,edu.internet2.middleware.shibboleth.common.XML.SAML2ASSERT_NS,"AttributeValue");
719 Element val=e.getOwnerDocument().createElementNS(XML.SAML_NS,"AttributeValue");
720 NamedNodeMap attrs = src.getAttributes();
721 for (int j=0; j<attrs.getLength(); j++)
722 val.setAttributeNodeNS((Attr)(e.getOwnerDocument().importNode(attrs.item(j),true)));
723 while (src.hasChildNodes())
724 val.appendChild(src.getFirstChild());
725 copy.appendChild(val);
727 attrs.add(SAMLAttribute.getInstance(copy));
731 attrprofs.add(Constants.SHIB_ATTRIBUTE_NAMESPACE_URI);
733 domains = e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"Domain");
734 NodeList nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"HandleService");
735 for (i=0; i<nlist.getLength(); i++) {
736 // Manufacture an endpoint for the "Shib" binding.
738 new XMLEndpoint(Constants.SHIB_AUTHNREQUEST_PROFILE_URI,((Element)nlist.item(i)).getAttributeNS(null,"Location"))
741 // We're going to "mock up" a KeyDescriptor that contains the specified Name as a ds:KeyName.
742 Element kd=e.getOwnerDocument().createElementNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"KeyDescriptor");
743 Element ki=e.getOwnerDocument().createElementNS(XML.XMLSIG_NS,"KeyInfo");
744 Element kn=e.getOwnerDocument().createElementNS(XML.XMLSIG_NS,"KeyName");
746 e.getOwnerDocument().createTextNode(((Element)nlist.item(i)).getAttributeNS(null,"Name"))
750 kd.setAttributeNS(null,"use","signing");
751 keys.add(new XMLKeyDescriptor(kd));
755 if (domains != null) {
756 for (int i=0; i < domains.getLength(); i++) {
757 String dom=(domains.item(i).hasChildNodes()) ? domains.item(i).getFirstChild().getNodeValue() : null;
759 String regexp=XML.assign(((Element)domains.item(i)).getAttributeNS(null,"regexp"));
761 new Scope(dom,(XML.safeCompare(regexp,"true") || XML.safeCompare(regexp,"1")))
768 public Iterator getScopes() {
769 return scopes.iterator();
772 public boolean getWantAuthnRequestsSigned() {
773 return wantAuthnRequestsSigned;
776 public EndpointManager getSingleSignOnServiceManager() {
780 public EndpointManager getNameIDMappingServiceManager() {
784 public EndpointManager getAssertionIDRequestServiceManager() {
788 public Iterator getAttributeProfiles() {
789 return attrprofs.iterator();
792 public Iterator getAttributes() {
793 return attrs.iterator();
797 class AARole extends Role implements AttributeAuthorityDescriptor, ScopedRoleDescriptor {
798 private ArrayList /* <Scope> */ scopes = new ArrayList();
799 private XMLEndpointManager query = new XMLEndpointManager();
800 private XMLEndpointManager idreq = new XMLEndpointManager();
801 private ArrayList /* <String> */ attrprofs = new ArrayList();
802 private ArrayList /* <String> */ formats = new ArrayList();
803 private ArrayList /* <SAMLAttribute> */ attrs = new ArrayList();
805 public AARole(XMLEntityDescriptor provider, long validUntil, Element e) throws SAMLException {
806 super(provider, validUntil, e);
807 NodeList domains=null;
809 // Check the root element namespace. If SAML2, assume it's the std schema.
810 if (edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS.equals(e.getNamespaceURI())) {
812 // Check for extensions.
813 Element ext=XML.getFirstChildElement(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"Extensions");
815 // Save off any domain elements for later.
816 domains = ext.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SHIBMETA_NS,"Scope");
820 NodeList nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"AttributeService");
821 for (i=0; i<nlist.getLength(); i++)
822 query.add(new XMLEndpoint((Element)(nlist.item(i))));
824 nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"AssertionIDRequestService");
825 for (i=0; i<nlist.getLength(); i++)
826 idreq.add(new XMLEndpoint((Element)(nlist.item(i))));
828 nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"AttributeProfile");
829 for (i=0; i<nlist.getLength(); i++) {
830 if (nlist.item(i).hasChildNodes())
831 attrprofs.add(nlist.item(i).getFirstChild().getNodeValue());
834 nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2ASSERT_NS,"Attribute");
835 for (i=0; i<nlist.getLength(); i++) {
836 // For now, we need to convert these to plain SAML 1.1 attributes.
837 Element src=(Element)(nlist.item(i));
838 Element copy=e.getOwnerDocument().createElementNS(XML.SAML_NS,"Attribute");
839 copy.setAttributeNS(null,"AttributeName",src.getAttributeNS(null,"Name"));
840 copy.setAttributeNS(null,"AttributeNamespace",src.getAttributeNS(null,"NameFormat"));
841 src=XML.getFirstChildElement(src,edu.internet2.middleware.shibboleth.common.XML.SAML2ASSERT_NS,"AttributeValue");
842 while (src != null) {
843 src=XML.getNextSiblingElement(src,edu.internet2.middleware.shibboleth.common.XML.SAML2ASSERT_NS,"AttributeValue");
844 Element val=e.getOwnerDocument().createElementNS(XML.SAML_NS,"AttributeValue");
845 NamedNodeMap attrs = src.getAttributes();
846 for (int j=0; j<attrs.getLength(); j++)
847 val.setAttributeNodeNS((Attr)(e.getOwnerDocument().importNode(attrs.item(j),true)));
848 while (src.hasChildNodes())
849 val.appendChild(src.getFirstChild());
850 copy.appendChild(val);
852 attrs.add(SAMLAttribute.getInstance(copy));
856 // For old style, we just do SAML 1.1 compatibility with Shib handles.
857 protocolEnum.add(XML.SAML11_PROTOCOL_ENUM);
858 formats.add(Constants.SHIB_NAMEID_FORMAT_URI);
859 attrprofs.add(Constants.SHIB_ATTRIBUTE_NAMESPACE_URI);
860 domains = e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"Domain");
862 NodeList nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"AttributeAuthority");
863 for (i=0; i<nlist.getLength(); i++) {
864 // Manufacture an endpoint for the SOAP binding.
868 ((Element)nlist.item(i)).getAttributeNS(null,"Location")
872 // We're going to "mock up" a KeyDescriptor that contains the specified Name as a ds:KeyName.
873 Element kd=e.getOwnerDocument().createElementNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"KeyDescriptor");
874 Element ki=e.getOwnerDocument().createElementNS(XML.XMLSIG_NS,"KeyInfo");
875 Element kn=e.getOwnerDocument().createElementNS(XML.XMLSIG_NS,"KeyName");
877 e.getOwnerDocument().createTextNode(((Element)nlist.item(i)).getAttributeNS(null,"Name"))
881 kd.setAttributeNS(null,"use","signing");
882 keys.add(new XMLKeyDescriptor(kd));
886 if (domains != null) {
887 for (int i=0; i < domains.getLength(); i++) {
888 String dom=(domains.item(i).hasChildNodes()) ? domains.item(i).getFirstChild().getNodeValue() : null;
890 String regexp=XML.assign(((Element)domains.item(i)).getAttributeNS(null,"regexp"));
892 new Scope(dom,(XML.safeCompare(regexp,"true") || XML.safeCompare(regexp,"1")))
899 public Iterator getScopes() {
900 return scopes.iterator();
903 public EndpointManager getAttributeServiceManager() {
907 public EndpointManager getAssertionIDRequestServiceManager() {
911 public Iterator getAttributeProfiles() {
912 return attrprofs.iterator();
915 public Iterator getAttributes() {
916 return attrs.iterator();
919 public Iterator getNameIDFormats() {
920 return formats.iterator();
924 class SPRole extends SSORole implements SPSSODescriptor {
925 private boolean authnRequestsSigned = false;
926 private boolean wantAssertionsSigned = false;
927 private XMLEndpointManager asc = new XMLEndpointManager();
929 public SPRole(XMLEntityDescriptor provider, long validUntil, Element e) throws MetadataException {
930 super(provider, validUntil, e);
932 // Check the root element namespace. If SAML2, assume it's the std schema.
933 if (edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS.equals(e.getNamespaceURI())) {
934 String flag=XML.assign(e.getAttributeNS(null,"AuthnRequestsSigned"));
935 authnRequestsSigned=(XML.safeCompare(flag,"1") || XML.safeCompare(flag,"true"));
936 flag=XML.assign(e.getAttributeNS(null,"WantAssertionsSigned"));
937 wantAssertionsSigned=(XML.safeCompare(flag,"1") || XML.safeCompare(flag,"true"));
940 NodeList nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"AssertionConsumerService");
941 for (i=0; i<nlist.getLength(); i++)
942 asc.add(new XMLIndexedEndpoint((Element)(nlist.item(i))));
945 nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SAML2ASSERT_NS,"Attribute");
946 for (i=0; i<nlist.getLength(); i++) {
947 // For now, we need to convert these to plain SAML 1.1 attributes.
948 Element src=(Element)(nlist.item(i));
949 Element copy=e.getOwnerDocument().createElementNS(XML.SAML_NS,"Attribute");
950 copy.setAttributeNS(null,"AttributeName",src.getAttributeNS(null,"Name"));
951 copy.setAttributeNS(null,"AttributeNamespace",src.getAttributeNS(null,"NameFormat"));
952 src=XML.getFirstChildElement(src,edu.internet2.middleware.shibboleth.common.XML.SAML2ASSERT_NS,"AttributeValue");
953 while (src != null) {
954 src=XML.getNextSiblingElement(src,edu.internet2.middleware.shibboleth.common.XML.SAML2ASSERT_NS,"AttributeValue");
955 Element val=e.getOwnerDocument().createElementNS(XML.SAML_NS,"AttributeValue");
956 NamedNodeMap attrs = src.getAttributes();
957 for (int j=0; j<attrs.getLength(); j++)
958 val.setAttributeNodeNS((Attr)(e.getOwnerDocument().importNode(attrs.item(j),true)));
959 while (src.hasChildNodes())
960 val.appendChild(src.getFirstChild());
961 copy.appendChild(val);
963 attrs.add(SAMLAttribute.getInstance(copy));
969 NodeList nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"AssertionConsumerServiceURL");
970 for (i=0; i<nlist.getLength(); i++) {
971 // Manufacture an endpoint for the POST profile.
973 new XMLEndpoint(SAMLBrowserProfile.PROFILE_POST_URI,((Element)nlist.item(i)).getAttributeNS(null,"Location"))
977 nlist=e.getElementsByTagNameNS(edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"AttributeRequester");
978 for (i=0; i<nlist.getLength(); i++) {
979 // We're going to "mock up" a KeyDescriptor that contains the specified Name as a ds:KeyName.
980 Element kd=e.getOwnerDocument().createElementNS(edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"KeyDescriptor");
981 Element ki=e.getOwnerDocument().createElementNS(XML.XMLSIG_NS,"KeyInfo");
982 Element kn=e.getOwnerDocument().createElementNS(XML.XMLSIG_NS,"KeyName");
984 e.getOwnerDocument().createTextNode(((Element)nlist.item(i)).getAttributeNS(null,"Name"))
988 kd.setAttributeNS(null,"use","signing");
989 keys.add(new XMLKeyDescriptor(kd));
994 public boolean getAuthnRequestsSigned() {
995 return authnRequestsSigned;
998 public boolean getWantAssertionsSigned() {
999 return wantAssertionsSigned;
1002 public EndpointManager getAssertionConsumerServiceManager() {
1006 public Iterator getAttributeConsumingServices() {
1007 // TODO Auto-generated method stub
1011 public AttributeConsumingService getDefaultAttributeConsumingService() {
1012 // TODO Auto-generated method stub
1016 public AttributeConsumingService getAttributeConsumingServiceByID(String id) {
1017 // TODO Auto-generated method stub
1022 class XMLEntityDescriptor implements ExtendedEntityDescriptor {
1023 private Element root = null;
1024 private EntitiesDescriptor parent = null;
1025 private String id = null;
1026 private URL errorURL = null;
1027 private Organization org = null;
1028 private ArrayList /* <ContactPerson> */ contacts = new ArrayList();
1029 private ArrayList /* <RoleDescriptor> */ roles = new ArrayList();
1030 private AffiliationDescriptor affiliation = null;
1031 private HashMap /* <String,String> */ locs = new HashMap();
1032 private long validUntil = Long.MAX_VALUE;
1033 private ArrayList /* <KeyAuthority> */ keyauths = new ArrayList();
1035 public XMLEntityDescriptor(Element e, XMLMetadataProvider wrapper, long validUntil, EntitiesDescriptor parent) throws SAMLException {
1037 this.parent = parent;
1038 this.validUntil = validUntil;
1040 // Check the root element namespace. If SAML2, assume it's the std schema.
1041 if (edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS.equals(e.getNamespaceURI())) {
1042 id=e.getAttributeNS(null,"entityID");
1044 if (e.hasAttributeNS(null,"validUntil")) {
1045 SimpleDateFormat formatter = null;
1046 String dateTime = XML.assign(e.getAttributeNS(null,"validUntil"));
1047 int dot = dateTime.indexOf('.');
1049 formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
1051 formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
1052 formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
1054 validUntil=Math.min(validUntil,formatter.parse(dateTime).getTime());
1056 catch (ParseException e1) {
1057 log.warn("Entity descriptor contains invalid expiration time");
1061 Element child=XML.getFirstChildElement(e);
1062 while (child != null) {
1063 // Process the various kinds of children that we care about...
1064 if (XML.isElementNamed(child,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"Extensions")) {
1065 Element ext = XML.getFirstChildElement(child,edu.internet2.middleware.shibboleth.common.XML.SHIBMETA_NS,"KeyAuthority");
1066 while (ext != null) {
1067 keyauths.add(new XMLKeyAuthority(ext));
1068 ext = XML.getNextSiblingElement(ext,edu.internet2.middleware.shibboleth.common.XML.SHIBMETA_NS,"KeyAuthority");
1071 else if (XML.isElementNamed(child,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"ContactPerson")) {
1072 contacts.add(new XMLContactPerson(child));
1074 else if (XML.isElementNamed(child,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"Organization")) {
1075 org=new XMLOrganization(child);
1077 else if (XML.isElementNamed(child,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"AdditionalMetadataLocation")) {
1078 Node loc=child.getFirstChild();
1080 locs.put(child.getAttributeNS(null,"namespace"),loc.getNodeValue());
1082 else if (XML.isElementNamed(child,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"IDPSSODescriptor")) {
1083 roles.add(new IDPRole(this,validUntil,child));
1085 else if (XML.isElementNamed(child,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"AttributeAuthorityDescriptor")) {
1086 roles.add(new AARole(this,validUntil,child));
1088 else if (XML.isElementNamed(child,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"SPSSODescriptor")) {
1089 roles.add(new SPRole(this,validUntil,child));
1091 child = XML.getNextSiblingElement(child);
1095 id=e.getAttributeNS(null,"Name");
1096 if (e.hasAttributeNS(null,"ErrorURL")) {
1098 errorURL=new URL(e.getAttributeNS(null,"ErrorURL"));
1100 catch (MalformedURLException e1) {
1101 log.error("Site descriptor contains invalid ErrorURL");
1105 boolean idp=false,aa=false,sp=false; // only want to build a role once
1106 Element child=XML.getFirstChildElement(e);
1107 while (child != null) {
1108 // Process the various kinds of OriginSite children that we care about...
1109 if (XML.isElementNamed(child,edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"Contact")) {
1110 contacts.add(new XMLContactPerson(child));
1112 else if (XML.isElementNamed(child,edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"HandleService") && !idp) {
1113 // Create the IDP role if needed.
1114 roles.add(new IDPRole(this, validUntil, e));
1117 else if (XML.isElementNamed(child,edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"AttributeAuthority") && !aa) {
1118 // Create the AA role if needed.
1119 roles.add(new AARole(this, validUntil, e));
1122 else if (XML.isElementNamed(child,edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"AssertionConsumerServiceURL") && !sp) {
1123 // Create the SP role if needed.
1124 roles.add(new SPRole(this, validUntil, e));
1127 else if (XML.isElementNamed(child,edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"AttributeRequester") && !sp) {
1128 // Create the SP role if needed.
1129 roles.add(new SPRole(this, validUntil, e));
1132 child = XML.getNextSiblingElement(child);
1136 // Each map entry is a list of the descriptors with this ID.
1138 if (wrapper.sites.containsKey(id)) {
1139 list = (ArrayList)wrapper.sites.get(id);
1142 list = new ArrayList();
1143 wrapper.sites.put(id,list);
1147 // Look for an IdP role, and register the artifact source ID and endpoints.
1149 for (int i=0; i<roles.size(); i++) {
1150 if (roles.get(i) instanceof IDPRole) {
1151 idp = (IDPRole)roles.get(i);
1152 if (idp.sourceId != null) {
1153 if (wrapper.sources.containsKey(idp.sourceId)) {
1154 list = (ArrayList)wrapper.sources.get(idp.sourceId);
1157 list = new ArrayList();
1158 wrapper.sources.put(idp.sourceId,list);
1165 sourceId = new String(Hex.encodeHex(Util.generateSourceId(id)));
1167 catch (NoSuchAlgorithmException e1) {
1168 log.error("caught exception while encoding sourceId: " + e1.getMessage());
1171 if (wrapper.sources.containsKey(sourceId)) {
1172 list = (ArrayList)wrapper.sources.get(sourceId);
1175 list = new ArrayList();
1176 wrapper.sources.put(sourceId,list);
1180 Iterator locs=idp.getArtifactResolutionServiceManager().getEndpoints();
1181 while (locs.hasNext()) {
1182 String loc=((Endpoint)locs.next()).getLocation();
1183 if (wrapper.sources.containsKey(loc)) {
1184 list = (ArrayList)wrapper.sources.get(loc);
1187 list = new ArrayList();
1188 wrapper.sources.put(loc,list);
1196 public String getId() {
1200 public boolean isValid() {
1201 return System.currentTimeMillis() < validUntil;
1204 public Iterator getRoleDescriptors() {
1205 return roles.iterator();
1208 public RoleDescriptor getRoleByType(Class type, String protocol) {
1209 for (int i=0; i<roles.size(); i++) {
1210 RoleDescriptor role = (RoleDescriptor)roles.get(i);
1211 if (type.isInstance(role) && role.hasSupport(protocol))
1217 public IDPSSODescriptor getIDPSSODescriptor(String protocol) {
1218 return (IDPSSODescriptor)getRoleByType(IDPSSODescriptor.class, protocol);
1221 public SPSSODescriptor getSPSSODescriptor(String protocol) {
1222 return (SPSSODescriptor)getRoleByType(SPSSODescriptor.class, protocol);
1225 public AuthnAuthorityDescriptor getAuthnAuthorityDescriptor(String protocol) {
1226 return (AuthnAuthorityDescriptor)getRoleByType(AuthnAuthorityDescriptor.class, protocol);
1229 public AttributeAuthorityDescriptor getAttributeAuthorityDescriptor(String protocol) {
1230 return (AttributeAuthorityDescriptor)getRoleByType(AttributeAuthorityDescriptor.class, protocol);
1233 public PDPDescriptor getPDPDescriptor(String protocol) {
1234 return (PDPDescriptor)getRoleByType(PDPDescriptor.class, protocol);
1237 public AffiliationDescriptor getAffiliationDescriptor() {
1241 public Organization getOrganization() {
1245 public Iterator getContactPersons() {
1246 return contacts.iterator();
1249 public Map getAdditionalMetadataLocations() {
1250 return Collections.unmodifiableMap(locs);
1253 public EntitiesDescriptor getEntitiesDescriptor() {
1257 public Element getElement() {
1261 public long getValidUntil() {
1265 public URL getErrorURL() {
1269 public Iterator getKeyAuthorities() {
1270 return keyauths.iterator();
1274 class XMLEntitiesDescriptor implements ExtendedEntitiesDescriptor {
1275 private Element root = null;
1276 private EntitiesDescriptor parent = null;
1277 private String name = null;
1278 private ArrayList /* <EntitiesDescriptor> */ groups = new ArrayList();
1279 private ArrayList /* <EntityDescriptor> */ providers = new ArrayList();
1280 private long validUntil = Long.MAX_VALUE;
1281 private ArrayList /* <KeyAuthority> */ keyauths = new ArrayList();
1283 public XMLEntitiesDescriptor(Element e, XMLMetadataProvider wrapper, long validUntil, EntitiesDescriptor parent) throws SAMLException {
1285 this.parent = parent;
1286 this.validUntil = validUntil;
1287 name = XML.assign(e.getAttributeNS(null, "Name"));
1289 // Check the root element namespace. If SAML2, assume it's the std schema.
1290 if (edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS.equals(e.getNamespaceURI())) {
1292 if (e.hasAttributeNS(null,"validUntil")) {
1293 SimpleDateFormat formatter = null;
1294 String dateTime = XML.assign(e.getAttributeNS(null,"validUntil"));
1295 int dot = dateTime.indexOf('.');
1297 formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
1299 formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
1300 formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
1302 validUntil=Math.min(validUntil,formatter.parse(dateTime).getTime());
1304 catch (ParseException e1) {
1305 log.warn("Entities descriptor contains invalid expiration time");
1309 e = XML.getFirstChildElement(e);
1311 if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"Extensions")) {
1312 Element ext = XML.getFirstChildElement(e,edu.internet2.middleware.shibboleth.common.XML.SHIBMETA_NS,"KeyAuthority");
1313 while (ext != null) {
1314 keyauths.add(new XMLKeyAuthority(ext));
1315 ext = XML.getNextSiblingElement(ext,edu.internet2.middleware.shibboleth.common.XML.SHIBMETA_NS,"KeyAuthority");
1318 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"EntitiesDescriptor"))
1319 groups.add(new XMLEntitiesDescriptor(e, wrapper, this.validUntil, this));
1320 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,"EntityDescriptor"))
1321 providers.add(new XMLEntityDescriptor(e, wrapper, this.validUntil, this));
1322 e = XML.getNextSiblingElement(e);
1326 e = XML.getFirstChildElement(e);
1328 if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"SiteGroup"))
1329 groups.add(new XMLEntitiesDescriptor(e, wrapper, this.validUntil, this));
1330 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"OriginSite"))
1331 providers.add(new XMLEntityDescriptor(e, wrapper, this.validUntil, this));
1332 else if (XML.isElementNamed(e,edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,"DestinationSite"))
1333 providers.add(new XMLEntityDescriptor(e, wrapper, this.validUntil, this));
1334 e = XML.getNextSiblingElement(e);
1339 public String getName() {
1343 public boolean isValid() {
1344 return System.currentTimeMillis() < validUntil;
1347 public EntitiesDescriptor getEntitiesDescriptor() {
1351 public Iterator getEntitiesDescriptors() {
1352 return groups.iterator();
1355 public Iterator getEntityDescriptors() {
1356 return providers.iterator();
1359 public Element getElement() {
1363 public Iterator getKeyAuthorities() {
1364 return keyauths.iterator();