/*
+ * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
* ServiceProviderConfig.java
*
* A ServiceProviderConfig object holds an instance of the Shibboleth
* configuration file should be noted while processing continues.
* This strategy reports all the errors in all the files to the log
* rather than stopping at the first error.
- *
- * --------------------
- * Copyright 2002, 2004
- * University Corporation for Advanced Internet Development, Inc.
- * All rights reserved
- * [Thats all we have to say to protect ourselves]
- * Your permission to use this code is governed by "The Shibboleth License".
- * A copy may be found at http://shibboleth.internet2.edu/license.html
- * [Nothing in copyright law requires license text in every file.]
*/
package edu.internet2.middleware.shibboleth.serviceprovider;
import java.util.TreeMap;
import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.opensaml.SAMLAssertion;
import x0.maceShibbolethTargetConfig1.LocalConfigurationType;
import x0.maceShibbolethTargetConfig1.PluggableType;
import x0.maceShibbolethTargetConfig1.RequestMapDocument;
+import x0.maceShibbolethTargetConfig1.SPConfigDocument;
import x0.maceShibbolethTargetConfig1.SPConfigType;
import x0.maceShibbolethTargetConfig1.ShibbolethTargetConfigDocument;
import x0.maceShibbolethTargetConfig1.ApplicationDocument.Application;
import x0.maceShibbolethTargetConfig1.ApplicationsDocument.Applications;
import x0.maceShibbolethTargetConfig1.HostDocument.Host;
+import x0.maceShibbolethTargetConfig1.HostDocument.Host.Scheme.Enum;
import x0.maceShibbolethTargetConfig1.PathDocument.Path;
import edu.internet2.middleware.shibboleth.aap.AAP;
import edu.internet2.middleware.shibboleth.aap.AttributeRule;
+import edu.internet2.middleware.shibboleth.aap.provider.XMLAAPProvider;
import edu.internet2.middleware.shibboleth.common.Credentials;
+import edu.internet2.middleware.shibboleth.common.PluggableConfigurationComponent;
import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
import edu.internet2.middleware.shibboleth.common.Trust;
import edu.internet2.middleware.shibboleth.common.provider.ShibbolethTrust;
+import edu.internet2.middleware.shibboleth.metadata.EntitiesDescriptor;
import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
import edu.internet2.middleware.shibboleth.metadata.Metadata;
import edu.internet2.middleware.shibboleth.metadata.RoleDescriptor;
+import edu.internet2.middleware.shibboleth.metadata.provider.XMLMetadataProvider;
import edu.internet2.middleware.shibboleth.xml.Parser;
/**
*/
public class ServiceProviderConfig {
-
+ // Map key prefix for inline plugin configuration elements
private static final String INLINEURN = "urn:inlineBS:ID";
- private static Logger log = Logger.getLogger(ServiceProviderConfig.class);
+
+ private static Logger initlog = Logger.getLogger(ContextListener.SHIBBOLETH_INIT+".Config");
+ private static Logger reqlog = Logger.getLogger(ServiceProviderConfig.class);
private SPConfigType // The XMLBean from the main config file
- config = null; // (i.e. shibboleth.xml)
+ config = null;
/*
new TreeMap/*<String, Metadata>*/();
public void addOrReplaceMetadataImplementor(String uri, Metadata m) {
+ initlog.info("addOrReplaceMetadataImplementor " + uri+ " as "+m.getClass());
entityLocators.put(uri, m);
}
new TreeMap/*<String, AAP>*/();
public void addOrReplaceAAPImplementor(String uri, AAP a) {
+ initlog.info("addOrReplaceAAPImplementor " + uri+ " as "+a.getClass());
attributePolicies.put(uri,a);
}
new TreeMap/*<String, Trust>*/();
public void addOrReplaceTrustImplementor(String uri, Trust t) {
+ initlog.info("addOrReplaceTrustImplementor " + uri+ " as "+t.getClass());
certificateValidators.put(uri,t);
}
*/
private static final String XMLTRUSTPROVIDERTYPE =
- "edu.internet2.middleware.shibboleth.common.provider.XMLTrust";
+ "edu.internet2.middleware.shibboleth.common.provider.ShibbolethTrust";
private static final String XMLAAPPROVIDERTYPE =
- "edu.internet2.middleware.shibboleth.serviceprovider.XMLAAP";
+ "edu.internet2.middleware.shibboleth.aap.provider.XMLAAP";
private static final String XMLFEDERATIONPROVIDERTYPE =
- "edu.internet2.middleware.shibboleth.common.provider.XMLMetadata";
- private static final String XMLREVOCATIONPROVIDERTYPE =
- "edu.internet2.middleware.shibboleth.common.provider.XMLRevocation";
+ "edu.internet2.middleware.shibboleth.metadata.provider.XMLMetadata";
private static final String XMLREQUESTMAPPROVIDERTYPE =
- "edu.internet2.middleware.shibboleth.serviceprovider.XMLRequestMap";
+ "edu.internet2.middleware.shibboleth.sp.provider.NativeRequestMapProvider";
private static final String XMLCREDENTIALSPROVIDERTYPE =
"edu.internet2.middleware.shibboleth.common.Credentials";
throws ShibbolethConfigurationException {
if (config!=null) {
- log.error("ServiceProviderConfig.loadConfigObjects may not be called twice for the same object.");
+ initlog.error("ServiceProviderConfig.loadConfigObjects may not be called twice for the same object.");
throw new ShibbolethConfigurationException("Cannot reload configuration into same object.");
}
+
+ initlog.info("Loading SP configuration from "+configFilePath);
Document configDoc;
try {
configDoc = Parser.loadDom(configFilePath, true);
} catch (Exception e) {
+ initlog.error("XML Parser error "+e.toString());
throw new ShibbolethConfigurationException("XML error in "+configFilePath);
}
loadConfigBean(configDoc);
String urlhostname = url.getHost();
String urlpath = url.getPath();
int urlport = url.getPort();
- if (urlport==0) {
- if (urlscheme.equals("http"))
- urlport=80;
- else if (urlscheme.equals("https"))
- urlport=443;
- }
// find Host entry for this virtual server
Host[] hostArray = requestMap.getHostArray();
for (int ihost=0;ihost<hostArray.length;ihost++) {
Host host = hostArray[ihost];
- String hostScheme = host.getScheme().toString();
+ Enum scheme = host.getScheme();
String hostName = host.getName();
String hostApplicationId = host.getApplicationId();
long hostport = host.getPort();
- if (hostport==0) {
- if (hostScheme.equals("http"))
- hostport=80;
- else if (hostScheme.equals("https"))
- hostport=443;
- }
- if (!urlscheme.equals(hostScheme) ||
- !urlhostname.equals(hostName)||
+ if (scheme != null &&
+ !urlscheme.equals(scheme.toString()))
+ continue;
+ if (!urlhostname.equals(hostName))
+ continue;
+ if (hostport!=0 &&
+ urlport!=0 &&
urlport!=hostport)
continue;
}
}
+ reqlog.debug("mapRequest mapped "+urlreq+" into "+applicationId);
return applicationId;
}
private void loadConfigBean(Document configDoc)
throws ShibbolethConfigurationException {
boolean anyError=false;
- ShibbolethTargetConfigDocument configBeanDoc;
- try {
- // reprocess the already validated DOM to create a bean with typed fields
- // dump the trash (comments, processing instructions, extra whitespace)
- configBeanDoc = ShibbolethTargetConfigDocument.Factory.parse(configDoc,
- new XmlOptions().setLoadStripComments().setLoadStripProcinsts().setLoadStripWhitespace());
- config=configBeanDoc.getShibbolethTargetConfig();
+
+ Element documentElement = configDoc.getDocumentElement();
+ // reprocess the already validated DOM to create a bean with typed fields
+ // dump the trash (comments, processing instructions, extra whitespace)
+ try {
+ if (documentElement.getLocalName().equals("ShibbolethTargetConfig")) {
+ initlog.debug("SP Configuration file is in 1.2 syntax.");
+ ShibbolethTargetConfigDocument configBeanDoc;
+ configBeanDoc = ShibbolethTargetConfigDocument.Factory.parse(configDoc,
+ new XmlOptions().setLoadStripComments().setLoadStripProcinsts().setLoadStripWhitespace());
+ config = configBeanDoc.getShibbolethTargetConfig();
+ } else if (documentElement.getLocalName().equals("SPConfig")) {
+ initlog.debug("SP Configuration file is in 1.3 syntax.");
+ SPConfigDocument configBeanDoc;
+ configBeanDoc = SPConfigDocument.Factory.parse(configDoc,
+ new XmlOptions().setLoadStripComments().setLoadStripProcinsts().setLoadStripWhitespace());
+ config = configBeanDoc.getSPConfig();
+ } else {
+ initlog.error("Root element not ShibbolethTargetConfig or SPConfig");
+ throw new XmlException("Root element not ShibbolethTargetConfig or SPConfig");
+ }
} catch (XmlException e) {
// Since the DOM was already validated against the schema, errors will not typically occur here
- log.error("Error while parsing shibboleth configuration");
+ initlog.error("Error while parsing shibboleth configuration");
throw new ShibbolethConfigurationException("Error while parsing shibboleth configuration");
}
- // Extract the "root Element" object from the "Document" object
- SPConfigType config = configBeanDoc.getShibbolethTargetConfig();
+ String loggerUrlString = config.getLogger();
+ if (loggerUrlString!=null) {
+ try {
+ URL loggerURL = new URL(loggerUrlString);
+ initlog.warn("logging is being reconfigured by "+ loggerUrlString);
+ PropertyConfigurator.configure(loggerURL);
+ } catch (MalformedURLException e) {
+ // This error is not serious enough to prevent initialization
+ initlog.error("Ignoring invalid value for logger attribute "+loggerUrlString );
+ }
+ }
Applications apps = config.getApplications(); // <Applications>
defaultApp.setCredentialUse(apps.getCredentialUse());
defaultApp.setErrors(apps.getErrors());
defaultApp.setFederationProviderArray(apps.getFederationProviderArray());
+ defaultApp.setMetadataProviderArray(apps.getMetadataProviderArray());
defaultApp.setProviderId(apps.getProviderId());
- defaultApp.setRevocationProviderArray(apps.getRevocationProviderArray());
defaultApp.setSessions(apps.getSessions());
defaultApp.setTrustProviderArray(apps.getTrustProviderArray());
anyError |= processCredentials();
anyError |= processPluggableRequestMapProvider();
- if (anyError)
+ if (anyError) {
+ initlog.error("SP Initialization terminated due to configuration errors");
throw new ShibbolethConfigurationException("Errors processing configuration file, see log");
+ }
}
* Routine to handle CredentialProvider
*
* <p>Note: This only handles in-line XML.
- * Also, Credentials was an existing Origin class, so it doesn't
+ * Also, Credentials was an existing IdP class, so it doesn't
* implement the new PluggableConfigurationComponent interface and
* can't be loaded by generic plugin support.
* </p>
String pluggabletype = pluggable[i].getType();
if (!pluggabletype.equals(
"edu.internet2.middleware.shibboleth.common.Credentials")) {
- log.error("Unsupported CredentialsProvider type "+pluggabletype);
+ initlog.error("Unsupported CredentialsProvider type "+pluggabletype);
anyError=true;
continue;
}
Node credentialsNode=credentialsProviderNode.getFirstChild();
credentials = new Credentials((Element)credentialsNode);
} catch(Exception e) {
- log.error("Cannot process Credentials element of Shibboleth configuration");
- log.error(e);
+ initlog.error("Cannot process Credentials element of Shibboleth configuration",e);
anyError=true;
continue;
}
Class implclass,
Class interfaceClass,
String builtinName,
- //String schemaname,
Map /*<String,PluggableConfigurationComponent>*/uriMap
) {
if (!pluggabletype.equals(builtinName)) {
// Not the builtin type, try to load user class by name
+ initlog.info("loading user-specified pluggable class "+pluggabletype);
try {
implclass = Class.forName(pluggabletype);
} catch (ClassNotFoundException e) {
- log.error("Type value "+pluggabletype+" not found as supplied Java class");
+ initlog.error("Type value "+pluggabletype+" not found as supplied Java class");
return null;
}
if (!interfaceClass.isAssignableFrom(implclass)||
!PluggableConfigurationComponent.class.isAssignableFrom(implclass)) {
- log.error(pluggabletype+" class does not support required interfaces.");
+ initlog.error(pluggabletype+" class does not support required interfaces.");
return null;
}
}
try {
impl = (PluggableConfigurationComponent) implclass.newInstance();
} catch (Exception e) {
- log.error("Unable to instantiate "+pluggabletype);
+ initlog.error("Unable to instantiate "+pluggabletype);
return null;
}
try {
Node fragment = pluggable.newDomNode(); // XML-Fragment node
Node pluggableNode = fragment.getFirstChild(); // PluggableType
- Node contentNode=pluggableNode.getFirstChild();// root element
+ Element contentNode=(Element) pluggableNode.getFirstChild();// root element
impl.initialize(contentNode);
} catch (Exception e) {
- log.error("XML error " + e);
+ initlog.error("XML error " + e);
return null;
}
return "";
}
- /*
- String tempname = impl.getSchemaPathname();
- if (tempname!=null)
- schemaname=tempname;
- */
try {
Document extdoc = Parser.loadDom(uri,true);
if (extdoc==null)
return null;
- impl.initialize(extdoc);
+ impl.initialize(extdoc.getDocumentElement());
} catch (Exception e) {
- log.error("XML error " + e);
+ initlog.error("XML error " + e);
return null;
}
}
*/
private boolean processPluggableMetadata(ApplicationInfo appinfo) {
boolean anyError = false;
- PluggableType[] pluggable = appinfo.getApplicationConfig().getFederationProviderArray();
+ PluggableType[] pluggable1 = appinfo.getApplicationConfig().getFederationProviderArray();
+ PluggableType[] pluggable2 = appinfo.getApplicationConfig().getMetadataProviderArray();
+ PluggableType[] pluggable;
+ if (pluggable1.length==0) {
+ pluggable=pluggable2;
+ } else if (pluggable2.length==0) {
+ pluggable=pluggable1;
+ } else {
+ pluggable = new PluggableType[pluggable1.length+pluggable2.length];
+ for (int i=0;i<pluggable2.length;i++) {
+ pluggable[i]=pluggable2[i];
+ }
+ for (int i=0;i<pluggable1.length;i++) {
+ pluggable[i+pluggable2.length]=pluggable1[i];
+ }
+ }
for (int i = 0;i<pluggable.length;i++) {
String uri = processPluggable(pluggable[i],
- XMLMetadataImpl.class,
+ XMLMetadataProvider.class,
Metadata.class,
XMLFEDERATIONPROVIDERTYPE,
- //METADATASCHEMA,
entityLocators);
if (uri==null)
anyError=true;
Document sitedoc = Parser.loadDom(uri,true);
if (sitedoc==null)
return false;
- XMLMetadataImpl impl = new XMLMetadataImpl();
- impl.initialize(sitedoc);
+ XMLMetadataProvider impl = new XMLMetadataProvider();
+ impl.initialize(sitedoc.getDocumentElement());
addOrReplaceMetadataImplementor(uri,impl);
} catch (Exception e) {
- log.error("Error while parsing Metadata file "+uri);
- log.error("XML error " + e);
+ initlog.error("Error while parsing Metadata file "+uri);
+ initlog.error("XML error " + e);
return false;
}
return true;
PluggableType[] pluggable = appinfo.getApplicationConfig().getAAPProviderArray();
for (int i = 0;i<pluggable.length;i++) {
String uri = processPluggable(pluggable[i],
- XMLAAPImpl.class,
+ XMLAAPProvider.class,
AAP.class,
XMLAAPPROVIDERTYPE,
- //AAPSCHEMA,
attributePolicies);
if (uri==null)
anyError=true;
if (aapdoc==null)
return false;
AttributeAcceptancePolicyDocument aap = AttributeAcceptancePolicyDocument.Factory.parse(aapdoc);
- XMLAAPImpl impl = new XMLAAPImpl();
- impl.initialize(aapdoc);
+ XMLAAPProvider impl = new XMLAAPProvider();
+ impl.initialize(aapdoc.getDocumentElement());
addOrReplaceAAPImplementor(uri,impl);
} catch (Exception e) {
- log.error("Error while parsing AAP file "+uri);
- log.error("XML error " + e);
+ initlog.error("Error while parsing AAP file "+uri);
+ initlog.error("XML error " + e);
return false;
}
return true;
ShibbolethTrust.class,
Trust.class,
XMLTRUSTPROVIDERTYPE,
- //TRUSTSCHEMA,
certificateValidators);
if (uri==null)
anyError=true;
private boolean processPluggableRequestMapProvider(){
LocalConfigurationType shire = config.getSHIRE();
+ if (shire==null)
+ shire = config.getLocal();
+ if (shire==null) {
+ initlog.error("No SHIRE or Local element.");
+ return true;
+ }
PluggableType mapProvider = shire.getRequestMapProvider();
String pluggabletype = mapProvider.getType();
if (!pluggabletype.equals(XMLREQUESTMAPPROVIDERTYPE)) {
- log.error("Unsupported RequestMapProvider type "+pluggabletype);
+ initlog.error("Unsupported RequestMapProvider type "+pluggabletype);
return true;
}
requestMapDoc = RequestMapDocument.Factory.parse(contentNode);
} catch (Exception e) {
- log.error("Error while parsing inline RequestMap");
- log.error("XML error " + e);
+ initlog.error("Error while parsing inline RequestMap");
+ initlog.error("XML error " + e);
return true;
}
return true;
requestMapDoc = RequestMapDocument.Factory.parse(mapdoc);
} catch (Exception e) {
- log.error("Error while parsing RequestMap file "+uri);
- log.error("XML error " + e);
+ initlog.error("Error while parsing RequestMap file "+uri);
+ initlog.error("XML error " + e);
return true;
}
}
}
-
+ // Generate Map keys for inline plugin configuration Elements
private int inlinenum = 1;
private String genDummyUri() {
return INLINEURN+Integer.toString(inlinenum++);
* function in the new interface that will use the new term, but
* it does the same thing.</p>
*
- * @param id ID of the OriginSite entity
+ * @param id ID of the IdP entity
* @return EntityDescriptor metadata object for that site.
*/
- public EntityDescriptor lookup(String id) {
+ public EntityDescriptor lookup(String id, boolean strict) {
Iterator iuris = groupUris.iterator();
while (iuris.hasNext()) {
String uri =(String) iuris.next();
Metadata locator=getMetadataImplementor(uri);
- EntityDescriptor entity = locator.lookup(id);
- if (entity!=null)
+ EntityDescriptor entity = locator.lookup(id, strict);
+ if (entity!=null) {
+ reqlog.debug("Metadata.lookup resolved Entity "+ id);
return entity;
+ }
}
+ reqlog.warn("Metadata.lookup failed to resolve Entity "+ id);
return null;
}
- public EntityDescriptor lookup(Artifact artifact) {
+ public EntityDescriptor lookup(Artifact artifact, boolean strict) {
Iterator iuris = groupUris.iterator();
while (iuris.hasNext()) {
String uri =(String) iuris.next();
Metadata locator=getMetadataImplementor(uri);
- EntityDescriptor entity = locator.lookup(artifact);
- if (entity!=null)
+ EntityDescriptor entity = locator.lookup(artifact, strict);
+ if (entity!=null) {
+ reqlog.debug("Metadata.lookup resolved Artifact "+ artifact);
return entity;
+ }
}
+ reqlog.warn("Metadata.lookup failed to resolve Artifact "+ artifact);
return null;
}
+
+ public EntityDescriptor lookup(String id) {
+ return lookup(id,true);
+ }
+
+ public EntityDescriptor lookup(Artifact artifact) {
+ return lookup(artifact,true);
+ }
+
+ public EntityDescriptor getRootEntity() {
+ return null;
+ }
+
+ public EntitiesDescriptor getRootEntities() {
+ return null;
+ }
/**
* Return the current array of objects that implement the Trust interface
// Foreach AAP in the collection
AAP[] providers = getAAPProviders();
if (providers.length == 0) {
- log.info("no filters specified, accepting entire assertion");
+ reqlog.info("no filters specified, accepting entire assertion");
return;
}
for (int i=0;i<providers.length;i++) {
AAP aap = providers[i];
if (aap.anyAttribute()) {
- log.info("any attribute enabled, accepting entire assertion");
+ reqlog.info("any attribute enabled, accepting entire assertion");
continue;
}
}
rule.apply(attribute,role);
}
catch (SAMLException ex) {
- log.info("no values remain, removing attribute");
+ reqlog.info("no values remain, removing attribute");
attributeStatement.removeAttribute(iattribute--);
break;
}
}
}
if (!ruleFound) {
- log.warn("no rule found for attribute (" + attribute.getName() + "), filtering it out");
+ reqlog.warn("no rule found for attribute (" + attribute.getName() + "), filtering it out");
attributeStatement.removeAttribute(iattribute--);
}
iattribute++;
}
catch (SAMLException ex) {
// The statement is now defunct.
- log.info("no attributes remain, removing statement");
+ reqlog.info("no attributes remain, removing statement");
assertion.removeStatement(istatement);
}
}
if (trust.validate(token,role))
return true;
}
+ reqlog.warn("SAML object failed Trust validation.");
return false;
}
/**
* A method of Trust that we must declare to claim that
* ApplicationInfo implements Trust. However, no code in the
- * ServiceProvider calls this (probably an Origin thing).
+ * ServiceProvider calls this (probably an IdP thing).
*
* @param revocations
* @param role
if (trust.validate(certificateEE,certificateChain,descriptor))
return true;
}
+ reqlog.warn("X.509 Certificate failed Trust validate");
return false;
}
if (trust.validate(certificateEE,certificateChain,descriptor,checkName))
return true;
}
+ reqlog.warn("X.509 Certificate failed Trust validate");
return false;
}
+
+ public String getProviderId() {
+ String entityId = this.applicationConfig.getProviderId();
+ if (entityId==null && this!=defaultApplicationInfo) {
+ entityId = defaultApplicationInfo.getProviderId();
+ }
+ return entityId;
+ }
}
super();
}
}
+
+
+
+ public Credentials getCredentials() {
+ return credentials;
+ }
}