package edu.internet2.middleware.shibboleth.idp;
import java.io.IOException;
+import java.net.URI;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
/**
* Defines the processing for an IdP-supported protocol. A particular <code>IdPProtocolHandler</code> implementation
- * is registered to process requests delivered from one or more endpoints. Core IdP functionality is delivered through
- * the <code>IdPProtocolSupport</code> class.
+ * is registered to process requests delivered from one or more URL locations. Core IdP functionality is delivered
+ * through the <code>IdPProtocolSupport</code> class.
*
* @author Walter Hoehn
*/
*/
public SAMLResponse processRequest(HttpServletRequest request, HttpServletResponse response,
SAMLRequest samlRequest, IdPProtocolSupport support) throws SAMLException, IOException, ServletException;
+
+ /**
+ * Returns the locations for which this handler should process requests.
+ */
+ public URI[] getLocations();
}
\ No newline at end of file
package edu.internet2.middleware.shibboleth.idp;
import java.io.IOException;
+import java.net.URI;
import java.util.HashMap;
import java.util.Random;
import edu.internet2.middleware.shibboleth.common.ServiceProviderMapper;
import edu.internet2.middleware.shibboleth.common.ServiceProviderMapperException;
import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
-import edu.internet2.middleware.shibboleth.idp.provider.ShibbolethV1SSOHandler;
import edu.internet2.middleware.shibboleth.metadata.Metadata;
import edu.internet2.middleware.shibboleth.metadata.MetadataException;
itemElements = originConfig.getDocumentElement().getElementsByTagNameNS(IdPConfig.configNameSpace,
"ProtocolHandler");
- //TODO Default if no handlers are specified
-
- for (int i = 0; i < itemElements.getLength(); i++) {
- IdPProtocolHandler handler = ProtocolHandlerFactory.getInstance((Element) itemElements.item(i));
+ // Default if no handlers are specified
+ if (itemElements.getLength() < 1) {
+ // TODO work out defaulting
+
+ // If handlers were specified, load them and register them against their locations
+ } else {
+ EACHHANDLER : for (int i = 0; i < itemElements.getLength(); i++) {
+ IdPProtocolHandler handler = ProtocolHandlerFactory.getInstance((Element) itemElements.item(i));
+ URI[] locations = handler.getLocations();
+ EACHLOCATION : for (int j = 0; j < locations.length; j++) {
+ if (protocolHandlers.containsKey(locations[j].toString())) {
+ log.error("Multiple protocol handlers are registered to listen at ("
+ + locations[j]
+ + "). Ignoring all except ("
+ + ((IdPProtocolHandler) protocolHandlers.get(locations[j].toString()))
+ .getHandlerName() + ").");
+ continue EACHLOCATION;
+ }
+ log.info("Registering handler (" + handler.getHandlerName() + ") to listen at (" + locations[j]
+ + ").");
+ protocolHandlers.put(locations[j].toString(), handler);
+ }
+ }
}
- //TODO finish fleshing this out
- log.debug("Starting with Shibboleth v1 protocol handling enabled.");
- protocolHandlers.put("https://wraith.memphis.edu/shibboleth/SSO", new ShibbolethV1SSOHandler());
// Load metadata
itemElements = originConfig.getDocumentElement().getElementsByTagNameNS(IdPConfig.configNameSpace,
MDC.put("serviceId", "[IdP] " + idgen.nextInt());
MDC.put("remoteAddr", request.getRemoteAddr());
- log.debug("Recieved a request via GET for endpoint (" + request.getRequestURL() + ").");
+ log.debug("Recieved a request via GET for location (" + request.getRequestURL() + ").");
try {
// TODO this throttle should probably just wrap signing operations...
IdPProtocolHandler activeHandler = (IdPProtocolHandler) protocolHandlers.get(request.getRequestURL()
.toString());
if (activeHandler == null) {
- log.error("No protocol handler registered for endpoint (" + request.getRequestURL() + ").");
- throw new SAMLException("Request submitted to an invalid endpoint.");
+ log.error("No protocol handler registered for location (" + request.getRequestURL() + ").");
+ throw new SAMLException("Request submitted to an invalid location.");
}
// Pass request to the appropriate handler
MDC.put("serviceId", "[IdP] " + idgen.nextInt());
MDC.put("remoteAddr", request.getRemoteAddr());
- log.debug("Recieved a request via POST for endpoint (" + request.getRequestURL() + ").");
+ log.debug("Recieved a request via POST for location (" + request.getRequestURL() + ").");
// Parse SOAP request and marshall SAML request object
SAMLRequest samlRequest = null;
IdPProtocolHandler activeHandler = (IdPProtocolHandler) protocolHandlers.get(request.getRequestURL()
.toString());
if (activeHandler == null) {
- log.error("No protocol handler registered for endpoint (" + request.getRequestURL() + ").");
- throw new SAMLException("Request submitted to an invalid endpoint.");
+ log.error("No protocol handler registered for location (" + request.getRequestURL() + ").");
+ throw new SAMLException("Request submitted to an invalid location.");
}
// Pass request to the appropriate handler and respond
--- /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.idp.provider;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashSet;
+
+import org.apache.log4j.Logger;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
+import edu.internet2.middleware.shibboleth.idp.IdPConfig;
+import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
+
+/**
+ * Functionality common to all <code>IdPProtocolHandler</code> implementation.
+ *
+ * @author Walter Hoehn
+ */
+public abstract class BaseHandler implements IdPProtocolHandler {
+
+ private static Logger log = Logger.getLogger(BaseHandler.class.getName());
+ private HashSet locations = new HashSet();
+
+ /**
+ * Required DOM-based constructor.
+ */
+ public BaseHandler(Element config) throws ShibbolethConfigurationException {
+
+ // Make sure we have at least one location
+ NodeList locations = config.getElementsByTagNameNS(IdPConfig.configNameSpace, "Location");
+ if (locations.getLength() < 1) {
+ log.error("The <ProtocolHandler/> element must contain at least one <Location/> element.");
+ throw new ShibbolethConfigurationException("Unable to load ProtocolHandler.");
+ }
+
+ // Parse the locations
+ for (int i = 0; i < locations.getLength(); i++) {
+ Node tnode = ((Element) locations.item(i)).getFirstChild();
+ if (tnode != null && tnode.getNodeType() == Node.TEXT_NODE) {
+ String rawURI = tnode.getNodeValue();
+
+ if (rawURI == null || rawURI.equals("")) {
+ log.error("The <Location/> element inside the <ProtocolHandler/> element must contain a URI.");
+ throw new ShibbolethConfigurationException("Unable to load ProtocolHandler.");
+ }
+
+ try {
+ URI location = new URI(rawURI);
+ this.locations.add(location);
+ } catch (URISyntaxException e) {
+ log.error("The <Location/> element inside the <ProtocolHandler/> element contains "
+ + "an improperly formatted URI: " + e);
+ throw new ShibbolethConfigurationException("Unable to load ProtocolHandler.");
+ }
+
+ } else {
+ log.error("The <Location/> element inside the <ProtocolHandler/> element must contain a URI.");
+ throw new ShibbolethConfigurationException("Unable to load ProtocolHandler.");
+ }
+ }
+ }
+
+ /*
+ * @see edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler#getLocations()
+ */
+ public URI[] getLocations() {
+
+ return (URI[]) locations.toArray(new URI[0]);
+ }
+
+}
import org.apache.log4j.Logger;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.keys.KeyInfo;
+import org.w3c.dom.Element;
import edu.internet2.middleware.shibboleth.common.ShibBrowserProfile;
+import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
import edu.internet2.middleware.shibboleth.metadata.KeyDescriptor;
/**
* @author Walter Hoehn
*/
-public abstract class BaseServiceHandler implements IdPProtocolHandler {
+public abstract class BaseServiceHandler extends BaseHandler implements IdPProtocolHandler {
- private static Logger log = Logger.getLogger(BaseServiceHandler.class.getName());
+ /**
+ * Required DOM-based constructor.
+ */
+ public BaseServiceHandler(Element config) throws ShibbolethConfigurationException {
+
+ super(config);
+ }
+
+ private static Logger log = Logger.getLogger(BaseServiceHandler.class.getName());
protected static X509Certificate getCredentialFromProvider(HttpServletRequest req) {
// If that doesn't work, try to match using
// SSL-style hostname matching
- //TODO stop relying on this class
+ // TODO stop relying on this class
if (ShibBrowserProfile.getHostNameFromDN(certificate.getSubjectX500Principal()).equals(
keyInfo.itemKeyName(l).getKeyName())) {
log.debug("Matched against hostname.");
import org.opensaml.SAMLStatement;
import org.opensaml.SAMLSubject;
import org.w3c.dom.Document;
+import org.w3c.dom.Element;
import sun.misc.BASE64Decoder;
import edu.internet2.middleware.shibboleth.common.RelyingParty;
+import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
import edu.internet2.middleware.shibboleth.idp.IdPProtocolSupport;
import edu.internet2.middleware.shibboleth.idp.InvalidClientDataException;
/**
* @author Walter Hoehn
*/
-public class E_AuthSSOHandler implements IdPProtocolHandler {
+public class E_AuthSSOHandler extends BaseHandler implements IdPProtocolHandler {
private static Logger log = Logger.getLogger(E_AuthSSOHandler.class.getName());
private final String name = "EAuth";
private final String eAuthFed = "urn:mace:shibboleth:eAuthFed";
private String csid;
- //TODO validate that the target wants artifact, since it is required for this profile
- //TODO validate that we aren't using signatures
- //TODO validate that we are using the right nameIdentifier format
- //TODO more robust attribute values before we ship
+ // TODO validate that the target wants artifact, since it is required for this profile
+ // TODO validate that we aren't using signatures
+ // TODO validate that we are using the right nameIdentifier format
+ // TODO more robust attribute values before we ship
+ /**
+ * Required DOM-based constructor.
+ */
+ public E_AuthSSOHandler(Element config) throws ShibbolethConfigurationException {
+
+ super(config);
+ }
/*
* @see edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler#getHandlerName()
throw new SAMLException(SAMLException.RESPONDER, "General error processing request.");
}
- //If no aaid is specified, redirect to the eAuth portal
+ // If no aaid is specified, redirect to the eAuth portal
if (request.getParameter("aaid") == null || request.getParameter("aaid").equals("")) {
log.debug("Received an E-Authentication request with no (aaid) parameter. "
+ "Redirecting to the E-Authentication portal.");
return null;
}
- //FUTURE at some point this needs to be integrated with SAML2 session reset
- //If session reset was requested, delete the session and re-direct back
- //Note, this only works with servler form-auth
+ // FUTURE at some point this needs to be integrated with SAML2 session reset
+ // If session reset was requested, delete the session and re-direct back
+ // Note, this only works with servler form-auth
String reAuth = request.getParameter("sessionreset");
if (reAuth != null && reAuth.equals("1")) {
log.debug("E-Authebtication session reset requested.");
// TODO Auto-generated catch block
}
- //TODO figure this out
+ // TODO figure this out
RelyingParty relyingParty = null;
SAMLNameIdentifier nameId = null;
String authenticationMethod = null;
conditions.add(new SAMLAudienceRestrictionCondition(audiences));
}
- //TODO need to pull this out into the generic artifact handling
+ // TODO need to pull this out into the generic artifact handling
String[] confirmationMethods = {SAMLSubject.CONF_ARTIFACT};
SAMLSubject subject = new SAMLSubject(nameId, Arrays.asList(confirmationMethods), null, null);
- //TODO pull from authN system? or make configurable
+ // TODO pull from authN system? or make configurable
ArrayList attributes = new ArrayList();
attributes.add(new SAMLAttribute("assuranceLevel", "http://eauthentication.gsa.gov/federated/attribute", null,
0, Arrays.asList(new String[]{"2"})));
- //TODO Hack Alert!!!
+ // TODO Hack Alert!!!
// Pull attributes from AA
String hackFullName = null;
if (nameId.getName().startsWith("uid=tomcat")) {
"UTF8"));
}
return null;
- } catch (CloneNotSupportedException e) { //TODO handle return null; } }
+ } catch (CloneNotSupportedException e) { // TODO handle return null; } }
}
import org.opensaml.SAMLException;
import org.opensaml.SAMLRequest;
import org.opensaml.SAMLResponse;
+import org.w3c.dom.Element;
import sun.misc.BASE64Decoder;
import edu.internet2.middleware.shibboleth.artifact.ArtifactMapper;
public class SAMLv1_1ArtifactQueryHandler extends BaseServiceHandler implements IdPProtocolHandler {
// TODO figure out how to refactor this
- private ArtifactMapper artifactMapper;
+ private ArtifactMapper artifactMapper;
- private static Logger log = Logger.getLogger(SAMLv1_1ArtifactQueryHandler.class.getName());
+ private static Logger log = Logger.getLogger(SAMLv1_1ArtifactQueryHandler.class.getName());
- SAMLv1_1ArtifactQueryHandler() throws ShibbolethConfigurationException {
- //TODO move the mapper out into protocol support
+ public SAMLv1_1ArtifactQueryHandler(Element config) throws ShibbolethConfigurationException {
+
+ super(config);
+ // TODO move the mapper out into protocol support
artifactMapper = new MemoryArtifactMapper();
}
import org.opensaml.SAMLResponse;
import org.opensaml.SAMLStatement;
import org.opensaml.SAMLSubject;
+import org.w3c.dom.Element;
import sun.misc.BASE64Decoder;
import edu.internet2.middleware.shibboleth.aa.AAException;
import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException;
import edu.internet2.middleware.shibboleth.common.RelyingParty;
import edu.internet2.middleware.shibboleth.common.ShibBrowserProfile;
+import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
import edu.internet2.middleware.shibboleth.idp.IdPProtocolSupport;
import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
private static Logger log = Logger.getLogger(SAMLv1_AttributeQueryHandler.class.getName());
+ /**
+ * Required DOM-based constructor.
+ */
+ public SAMLv1_AttributeQueryHandler(Element config) throws ShibbolethConfigurationException {
+
+ super(config);
+ }
+
/*
* @see edu.internet2.middleware.shibboleth.idp.ProtocolHandler#getHandlerName()
*/
import org.opensaml.SAMLStatement;
import org.opensaml.SAMLSubject;
import org.w3c.dom.Document;
+import org.w3c.dom.Element;
import sun.misc.BASE64Decoder;
import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException;
import edu.internet2.middleware.shibboleth.common.RelyingParty;
import edu.internet2.middleware.shibboleth.common.ShibBrowserProfile;
+import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
import edu.internet2.middleware.shibboleth.idp.IdPProtocolSupport;
import edu.internet2.middleware.shibboleth.idp.InvalidClientDataException;
/**
* @author Walter Hoehn
*/
-public class ShibbolethV1SSOHandler implements IdPProtocolHandler {
+public class ShibbolethV1SSOHandler extends BaseHandler implements IdPProtocolHandler {
private static Logger log = Logger.getLogger(ShibbolethV1SSOHandler.class.getName());
+ /**
+ * Required DOM-based constructor.
+ */
+ public ShibbolethV1SSOHandler(Element config) throws ShibbolethConfigurationException {
+
+ super(config);
+ }
+
/*
* @see edu.internet2.middleware.shibboleth.idp.IdPResponder.ProtocolHandler#processRequest(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
<xs:element name="ProtocolHandler" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
- <xs:element name="Endpoint" type="xs:anyURI" minOccurs="1" maxOccurs="unbounded" />
+ <xs:element name="Location" type="xs:anyURI" minOccurs="1" maxOccurs="unbounded" />
<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="implementation" type="xs:string" use="required" />