--- /dev/null
+/*
+ * The Shibboleth License, Version 1. Copyright (c) 2002 University Corporation for Advanced Internet Development, Inc.
+ * All rights reserved Redistribution and use in source and binary forms, with or without modification, are permitted
+ * provided that the following conditions are met: Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution, if any, must include the following acknowledgment: "This product includes
+ * software developed by the University Corporation for Advanced Internet Development <http://www.ucaid.edu>Internet2
+ * Project. Alternately, this acknowledegement may appear in the software itself, if and wherever such third-party
+ * acknowledgments normally appear. Neither the name of Shibboleth nor the names of its contributors, nor Internet2,
+ * nor the University Corporation for Advanced Internet Development, Inc., nor UCAID may be used to endorse or promote
+ * products derived from this software without specific prior written permission. For written permission, please
+ * contact shibboleth@shibboleth.org Products derived from this software may not be called Shibboleth, Internet2,
+ * UCAID, or the University Corporation for Advanced Internet Development, nor may Shibboleth appear in their name,
+ * without prior written permission of the University Corporation for Advanced Internet Development. THIS SOFTWARE IS
+ * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+ * NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS
+ * WITH LICENSEE. IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY CORPORATION FOR ADVANCED
+ * INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package edu.internet2.middleware.shibboleth.common;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import javax.servlet.http.HttpServlet;
+
+import org.apache.log4j.Logger;
+import org.w3c.dom.Element;
+
+import edu.internet2.middleware.shibboleth.metadata.Metadata;
+import edu.internet2.middleware.shibboleth.metadata.MetadataException;
+import edu.internet2.middleware.shibboleth.metadata.Provider;
+
+/**
+ * @author Walter Hoehn (wassa@columbia.edu)
+ */
+public class TargetFederationComponent extends HttpServlet implements Metadata {
+
+ private static Logger log = Logger.getLogger(TargetFederationComponent.class.getName());
+
+ private ArrayList fedMetadata = new ArrayList();
+
+ protected void addFederationProvider(Element element) {
+ log.debug("Found Federation Provider configuration element.");
+ if (!element.getTagName().equals("FederationProvider")) {
+ log.error("Error while attemtping to load Federation Provider. Malformed provider specificaion.");
+ return;
+ }
+
+ try {
+ fedMetadata.add(FederationProviderFactory.loadProvider(element));
+ } catch (MetadataException e) {
+ log.error("Unable to load Federation Provider. Skipping...");
+ }
+ }
+
+ protected int providerCount() {
+ return fedMetadata.size();
+ }
+
+ public Provider lookup(String providerId) {
+
+ Iterator iterator = fedMetadata.iterator();
+ while (iterator.hasNext()) {
+ Provider provider = ((Metadata) iterator.next()).lookup(providerId);
+ if (provider != null) {
+ return provider;
+ }
+ }
+ return null;
+ }
+}
+
+class FederationProviderFactory {
+
+ private static Logger log = Logger.getLogger(FederationProviderFactory.class.getName());
+
+ public static Metadata loadProvider(Element e) throws MetadataException {
+
+ String className = e.getAttribute("type");
+ if (className == null || className.equals("")) {
+ log.error("Federation Provider requires specification of the attribute \"type\".");
+ throw new MetadataException("Failed to initialize Federation Provider.");
+ } else {
+ try {
+ Class[] params = {Class.forName("org.w3c.dom.Element"),};
+ return (Metadata) Class.forName(className).getConstructor(params).newInstance(new Object[]{e});
+ } catch (Exception loaderException) {
+ log.error("Failed to load Federation Provider implementation class: " + loaderException);
+ if (loaderException instanceof InvocationTargetException) {
+ log.error("Root cause: " + ((InvocationTargetException)loaderException).getTargetException());
+ }
+ throw new MetadataException("Failed to initialize Federation Provider.");
+ }
+ }
+ }
+}
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
-import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.w3c.dom.NodeList;
import sun.misc.BASE64Decoder;
+
+import com.sun.corba.se.internal.core.EndPoint;
+
import edu.internet2.middleware.shibboleth.common.AuthNPrincipal;
import edu.internet2.middleware.shibboleth.common.Credentials;
import edu.internet2.middleware.shibboleth.common.NameIdentifierMapping;
import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException;
import edu.internet2.middleware.shibboleth.common.OriginConfig;
+import edu.internet2.middleware.shibboleth.common.RelyingParty;
import edu.internet2.middleware.shibboleth.common.ServiceProviderMapperException;
import edu.internet2.middleware.shibboleth.common.ShibPOSTProfile;
import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
+import edu.internet2.middleware.shibboleth.common.ShibbolethOriginConfig;
+import edu.internet2.middleware.shibboleth.common.TargetFederationComponent;
+import edu.internet2.middleware.shibboleth.metadata.Endpoint;
+import edu.internet2.middleware.shibboleth.metadata.Provider;
+import edu.internet2.middleware.shibboleth.metadata.ProviderRole;
+import edu.internet2.middleware.shibboleth.metadata.SPProviderRole;
-public class HandleServlet extends HttpServlet {
+public class HandleServlet extends TargetFederationComponent {
private static Logger log = Logger.getLogger(HandleServlet.class.getName());
private static Logger transactionLog = Logger.getLogger("Shibboleth-TRANSACTION");
throw new ShibbolethConfigurationException("Could not load origin configuration.");
}
+ //Load metadata
+ itemElements = originConfig.getDocumentElement().getElementsByTagNameNS(
+ ShibbolethOriginConfig.originConfigNamespace, "FederationProvider");
+ for (int i = 0; i < itemElements.getLength(); i++) {
+ addFederationProvider((Element) itemElements.item(i));
+ }
+ if (providerCount() < 1) {
+ log.error("No Federation Provider metadata loaded.");
+ throw new ShibbolethConfigurationException("Could not load federation metadata.");
+ }
}
public void init() throws ServletException {
HSRelyingParty relyingParty = targetMapper.getRelyingParty(req.getParameter("providerId"));
+ //Get the authN info
String username = configuration.getAuthHeaderName().equalsIgnoreCase("REMOTE_USER")
? req.getRemoteUser()
: req.getHeader(configuration.getAuthHeaderName());
+ //Make sure that the selected relying party configuration is appropriate for this
+ //acceptance URL
+ if (!relyingParty.isLegacyProvider()) {
+ if (isValidAssertionConsumerURL(relyingParty, req.getParameter("shire"))) {
+ log.info("Supplied consumer URL validated for this provider.");
+ } else {
+ log.error("Supplied assertion consumer service URL (" + req.getParameter("shire")
+ + ") is NOT valid for provider (" + relyingParty.getProviderId() + ").");
+ throw new InvalidClientDataException("Invalid assertion consumer service URL.");
+ }
+ }
+
SAMLNameIdentifier nameId = nameMapper.getNameIdentifierName(relyingParty.getHSNameFormatId(),
new AuthNPrincipal(username), relyingParty, relyingParty.getIdentityProvider());
createForm(req, res, buf);
if (relyingParty.isLegacyProvider()) {
- transactionLog.info("Authentication assertion issued to legacy provider (SHIRE: " + req.getParameter("shire")
- + ") on behalf of principal (" + username
- + ") for resource (" + req.getParameter("target") + "). Name Identifier: (" + nameId.getName()
+ transactionLog.info("Authentication assertion issued to legacy provider (SHIRE: "
+ + req.getParameter("shire") + ") on behalf of principal (" + username + ") for resource ("
+ + req.getParameter("target") + "). Name Identifier: (" + nameId.getName()
+ "). Name Identifier Format: (" + nameId.getFormat() + ").");
} else {
transactionLog.info("Authentication assertion issued to provider (" + req.getParameter("providerId")
}
}
+ protected boolean isValidAssertionConsumerURL(RelyingParty relyingParty, String shireURL)
+ throws InvalidClientDataException {
+
+ Provider provider = lookup(relyingParty.getProviderId());
+ if (provider == null) {
+ log.info("No metadata found for provider: (" + relyingParty.getProviderId() + ").");
+ throw new InvalidClientDataException("Request if from an unkown Service Provider.");
+ }
+
+ ProviderRole[] roles = provider.getRoles();
+ if (roles.length == 0) {
+ log.info("Inappropriate metadata for provider.");
+ return false;
+ }
+
+ for (int i = 0; roles.length > i; i++) {
+ if (roles[i] instanceof SPProviderRole) {
+ Endpoint[] endpoints = ((SPProviderRole) roles[i]).getAssertionConsumerServiceURLs();
+ for (int j = 0; endpoints.length > j; j++) {
+ if (shireURL.equals(endpoints[j].getLocation())) {
+ return true;
+ }
+ }
+ }
+ }
+ log.info("Supplied consumer URL not found in metadata.");
+ return false;
+ }
+
class InvalidClientDataException extends Exception {
public InvalidClientDataException(String message) {
// rootAppender.setLayout(new PatternLayout("%-5p %-41X{serviceId} %d{ISO8601} (%c:%L) - %m%n"));
// Logger.getRootLogger().setLevel((Level) Level.DEBUG);
- Logger.getRootLogger().setLevel((Level) Level.INFO);
+ Logger.getRootLogger().setLevel((Level) Level.DEBUG);
rootAppender.setLayout(new PatternLayout("%d{ISO8601} %-5p %-41X{serviceId} - %m%n"));
try {
configureErrorLog(errorLogNode);
} else {
// started out at INFO for logging config messages
- Logger.getRootLogger().setLevel((Level) Level.WARN);
+ Logger.getRootLogger().setLevel((Level) Level.DEBUG);
}
// turn these off by default
import org.apache.log4j.Logger;
import org.apache.xerces.parsers.DOMParser;
+import org.w3c.dom.Element;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
private Metadata currentMeta;
private DOMParser parser;
+ public XMLMetadataLoadWrapper(Element configuration) throws MetadataException, ResourceNotAvailableException {
+ this(configuration.getAttribute("uri"));
+ }
+
public XMLMetadataLoadWrapper(String sitesFileLocation) throws MetadataException, ResourceNotAvailableException {
- super(new ShibResource(sitesFileLocation));
+ super(new ShibResource(sitesFileLocation, XMLMetadataLoadWrapper.class));
parser = new DOMParser();
try {