Implement SP authn by credential names via metadata, dump 1.1 legacy mode.
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / idp / provider / SAMLv1_AttributeQueryHandler.java
index 49e2683..c88e1a3 100644 (file)
@@ -1,26 +1,17 @@
 /*
- * 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.
+ * 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.
  */
 
 package edu.internet2.middleware.shibboleth.idp.provider;
@@ -50,28 +41,41 @@ import org.opensaml.SAMLAttributeStatement;
 import org.opensaml.SAMLAudienceRestrictionCondition;
 import org.opensaml.SAMLCondition;
 import org.opensaml.SAMLException;
+import org.opensaml.SAMLNameIdentifier;
 import org.opensaml.SAMLRequest;
 import org.opensaml.SAMLResponse;
 import org.opensaml.SAMLStatement;
 import org.opensaml.SAMLSubject;
+import org.opensaml.XML;
+import org.w3c.dom.Element;
 
-import sun.misc.BASE64Decoder;
 import edu.internet2.middleware.shibboleth.aa.AAException;
 import edu.internet2.middleware.shibboleth.common.InvalidNameIdentifierException;
+import edu.internet2.middleware.shibboleth.common.NameIdentifierMapping;
 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;
+import edu.internet2.middleware.shibboleth.metadata.AttributeRequesterDescriptor;
 import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
+import edu.internet2.middleware.shibboleth.metadata.RoleDescriptor;
+import edu.internet2.middleware.shibboleth.metadata.SPSSODescriptor;
 
 /**
  * @author Walter Hoehn
  */
 public class SAMLv1_AttributeQueryHandler extends BaseServiceHandler implements IdPProtocolHandler {
 
-       private static Logger   log     = Logger.getLogger(SAMLv1_AttributeQueryHandler.class.getName());
+       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()
@@ -81,51 +85,35 @@ public class SAMLv1_AttributeQueryHandler extends BaseServiceHandler implements
                return "SAML v1.1 Attribute Query";
        }
 
-       private String getEffectiveName(HttpServletRequest req, RelyingParty relyingParty, IdPProtocolSupport support)
+       private String authenticateAs(String assertedId, X509Certificate[] chain, IdPProtocolSupport support)
                        throws InvalidProviderCredentialException {
-
-               X509Certificate credential = getCredentialFromProvider(req);
-
-               if (credential == null || credential.getSubjectX500Principal().getName(X500Principal.RFC2253).equals("")) {
-                       log.info("Request is from an unauthenticated service provider.");
+               // See if we have metadata for this provider
+               EntityDescriptor provider = support.lookup(assertedId);
+               if (provider == null) {
+                       log.info("No metadata found for providerId: (" + assertedId + ").");
                        return null;
+               }
+               else {
+                       log.info("Metadata found for providerId: (" + assertedId + ").");
+               }
+               RoleDescriptor ar_role = provider.getAttributeRequesterDescriptor(XML.SAML11_PROTOCOL_ENUM);
+               RoleDescriptor sp_role = provider.getSPSSODescriptor(XML.SAML11_PROTOCOL_ENUM);
+               if (ar_role == null && sp_role == null) {
+                       log.info("SPSSO and Stand-Alone Requester roles not found in metadata for provider: ("
+                                       + assertedId + ").");
+                       return null;
+               }
 
+               // Make sure that the supplied credential is valid for the selected provider role.
+               if ((ar_role != null && support.getTrust().validate(chain[0], chain, ar_role)) ||
+                       (sp_role != null &&     support.getTrust().validate(chain[0], chain, sp_role))) {
+                       log.info("Supplied credentials validated for this provider.");
+                       return assertedId;
                } else {
-                       log.info("Request contains credential: ("
-                                       + credential.getSubjectX500Principal().getName(X500Principal.RFC2253) + ").");
-                       // Mockup old requester name for requests from < 1.2 targets
-                       if (fromLegacyProvider(req)) {
-                               String legacyName = ShibBrowserProfile.getHostNameFromDN(credential.getSubjectX500Principal());
-                               if (legacyName == null) {
-                                       log.error("Unable to extract legacy requester name from certificate subject.");
-                               }
-
-                               log.info("Request from legacy service provider: (" + legacyName + ").");
-                               return legacyName;
-
-                       } else {
-
-                               // See if we have metadata for this provider
-                               EntityDescriptor provider = support.lookup(relyingParty.getProviderId());
-                               if (provider == null) {
-                                       log.info("No metadata found for provider: (" + relyingParty.getProviderId() + ").");
-                                       log.info("Treating remote provider as unauthenticated.");
-                                       return null;
-                               }
-
-                               // Make sure that the suppplied credential is valid for the
-                               // selected relying party
-                               if (isValidCredential(provider, credential)) {
-                                       log.info("Supplied credential validated for this provider.");
-                                       log.info("Request from service provider: (" + relyingParty.getProviderId() + ").");
-                                       return relyingParty.getProviderId();
-                               } else {
-                                       log.error("Supplied credential ("
-                                                       + credential.getSubjectX500Principal().getName(X500Principal.RFC2253)
-                                                       + ") is NOT valid for provider (" + relyingParty.getProviderId() + ").");
-                                       throw new InvalidProviderCredentialException("Invalid credential.");
-                               }
-                       }
+                       log.error("Supplied credentials ("
+                                       + chain[0].getSubjectX500Principal().getName(X500Principal.RFC2253)
+                                       + ") are NOT valid for provider (" + assertedId + ").");
+                       throw new InvalidProviderCredentialException("Invalid credentials.");
                }
        }
 
@@ -135,69 +123,101 @@ public class SAMLv1_AttributeQueryHandler extends BaseServiceHandler implements
         *      edu.internet2.middleware.shibboleth.idp.ProtocolSupport)
         */
        public SAMLResponse processRequest(HttpServletRequest request, HttpServletResponse response,
-                       SAMLRequest samlRequest, IdPProtocolSupport support) throws SAMLException, InvalidClientDataException,
-                       IOException, ServletException {
-
-               // TODO negate this and throw an error if it isn't
-               if (samlRequest.getQuery() != null && (samlRequest.getQuery() instanceof SAMLAttributeQuery)) {
-                       log.info("Recieved an attribute query.");
-                       // processAttributeQuery(samlRequest, request, response);
+                       SAMLRequest samlRequest, IdPProtocolSupport support) throws SAMLException, IOException, ServletException {
 
+               if (samlRequest.getQuery() == null || !(samlRequest.getQuery() instanceof SAMLAttributeQuery)) {
+                       log.error("Protocol Handler can only respond to SAML Attribute Queries.");
+                       throw new SAMLException("General error processing request.");
                }
 
                RelyingParty relyingParty = null;
-
                SAMLAttributeQuery attributeQuery = (SAMLAttributeQuery) samlRequest.getQuery();
 
-               if (!fromLegacyProvider(request)) {
-                       log.info("Remote provider has identified itself as: (" + attributeQuery.getResource() + ").");
-               }
-
                // This is the requester name that will be passed to subsystems
                String effectiveName = null;
 
-               X509Certificate credential = getCredentialFromProvider(request);
-               if (credential == null || credential.getSubjectX500Principal().getName(X500Principal.RFC2253).equals("")) {
-                       log.info("Request is from an unauthenticated service provider.");
-               } else {
-
-                       // Identify a Relying Party
-                       relyingParty = support.getServiceProviderMapper().getRelyingParty(attributeQuery.getResource());
+               // Log the physical credential supplied, if any.
+               X509Certificate[] credentials = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
+               if (credentials == null || credentials.length == 0 ||
+                               credentials[0].getSubjectX500Principal().getName(X500Principal.RFC2253).equals("")) {
+                       log.info("Request contained no credentials, treating as an unauthenticated service provider.");
+               }
+               else {
+                       log.info("Request contains credentials: ("
+                                       + credentials[0].getSubjectX500Principal().getName(X500Principal.RFC2253) + ").");
 
+                       // Try and authenticate the requester as any of the potentially relevant identifiers we know.                   
                        try {
-                               effectiveName = getEffectiveName(request, relyingParty, support);
+                               if (attributeQuery.getResource() != null) {
+                                       log.info("Remote provider has identified itself as: (" + attributeQuery.getResource() + ").");
+                                       effectiveName = authenticateAs(attributeQuery.getResource(), credentials, support);
+                               }
+
+                               if (effectiveName == null) {
+                                       log.info("Remote provider not yet identified, attempting to derive requesting provider from credentials.");
+
+                                       // Try the additional candidates.
+                                       String[] candidateNames = getCredentialNames(credentials[0]);
+                                       for (int c = 0; effectiveName == null && c < candidateNames.length; c++) {
+                                               effectiveName = authenticateAs(candidateNames[c], credentials, support);
+                                       }
+                               }
                        } catch (InvalidProviderCredentialException ipc) {
-                               //TODO no, throw an exception
-                               //sendSAMLFailureResponse(response, samlRequest, new SAMLException(SAMLException.RESPONDER,
-                               //              "Invalid credentials for request."));
-                               return null;
+                               throw new SAMLException(SAMLException.REQUESTER, "Invalid credentials for request.");
                        }
                }
-
+               
                if (effectiveName == null) {
+                       log.info("Unable to locate metadata about provider, treating as an unauthenticated service provider.");
                        log.debug("Using default Relying Party for unauthenticated provider.");
                        relyingParty = support.getServiceProviderMapper().getRelyingParty(null);
                }
+               else {
+                       // Identify a Relying Party
+                       log.debug("Mapping authenticated provider (" + effectiveName + ") to Relying Party.");
+                       relyingParty = support.getServiceProviderMapper().getRelyingParty(effectiveName);
+               }
 
-               // Fail if we can't honor SAML Subject Confirmation
-               if (!fromLegacyProvider(request)) {
-                       Iterator iterator = attributeQuery.getSubject().getConfirmationMethods();
-                       boolean hasConfirmationMethod = false;
-                       while (iterator.hasNext()) {
-                               log.info("Request contains SAML Subject Confirmation method: (" + (String) iterator.next() + ").");
-                       }
-                       if (hasConfirmationMethod) { throw new SAMLException(SAMLException.REQUESTER,
-                                       "This SAML authority cannot honor requests containing the supplied SAML Subject Confirmation Method."); }
+               // Fail if we can't honor SAML Subject Confirmation unless the only one supplied is
+               // bearer, in which case this is probably a Shib 1.1 query, and we'll let it slide for now.
+               // TODO: remove the compatibility with 1.1 and be strict about this?
+               boolean hasConfirmationMethod = false;
+               boolean hasOnlyBearer = true;
+               Iterator iterator = attributeQuery.getSubject().getConfirmationMethods();
+               while (iterator.hasNext()) {
+                       String method = (String) iterator.next();
+                       log.info("Request contains SAML Subject Confirmation method: (" + method + ").");
+                       hasConfirmationMethod = true;
+                       if (!method.equals(SAMLSubject.CONF_BEARER))
+                               hasOnlyBearer = false;
+               }
+               if (hasConfirmationMethod && !hasOnlyBearer) {
+                       throw new SAMLException(SAMLException.REQUESTER,
+                               "This SAML authority cannot honor requests containing the supplied SAML Subject Confirmation Method(s).");
                }
 
                // Map Subject to local principal
-               Principal principal;
+               Principal principal = null;
                try {
-                       principal = support.getNameMapper().getPrincipal(attributeQuery.getSubject().getName(), relyingParty,
-                                       relyingParty.getIdentityProvider());
+                       SAMLNameIdentifier nameId = attributeQuery.getSubject().getNameIdentifier();
+                       log.debug("Name Identifier format: (" + nameId.getFormat() + ").");
+                       NameIdentifierMapping mapping = null;
+                       try {
+                               mapping = support.getNameMapper().getNameIdentifierMapping(new URI(nameId.getFormat()));
+                       } catch (URISyntaxException e) {
+                               log.error("Invalid Name Identifier format.");
+                       }
+                       if (mapping == null) { throw new NameIdentifierMappingException("Name Identifier format not registered."); }
+
+                       // Don't honor the request if the active relying party configuration does not contain a mapping with the
+                       // name identifier format from the request
+                       if (!Arrays.asList(relyingParty.getNameMapperIds()).contains(mapping.getId())) { throw new NameIdentifierMappingException(
+                                       "Name Identifier format not valid for this relying party."); }
 
+                       principal = mapping.getPrincipal(nameId, relyingParty, relyingParty.getIdentityProvider());
                        log.info("Request is for principal (" + principal.getName() + ").");
 
+                       // Get attributes from resolver
                        SAMLAttribute[] attrs;
                        Iterator requestedAttrsIterator = attributeQuery.getDesignators();
                        if (requestedAttrsIterator.hasNext()) {
@@ -209,40 +229,43 @@ public class SAMLv1_AttributeQueryHandler extends BaseServiceHandler implements
                                                log.debug("Designated attribute: (" + attribute.getName() + ")");
                                                requestedAttrs.add(new URI(attribute.getName()));
                                        } catch (URISyntaxException use) {
-                                               log
-                                                               .error("Request designated an attribute name that does not conform to the required URI syntax ("
-                                                                               + attribute.getName() + ").  Ignoring this attribute");
+                                               log.error("Request designated an attribute name that does not conform "
+                                                               + "to the required URI syntax (" + attribute.getName() + ").  Ignoring this attribute");
                                        }
                                }
 
-                               attrs = support.getReleaseAttributes(principal, effectiveName, null, (URI[]) requestedAttrs
-                                               .toArray(new URI[0]));
+                               attrs = support.getReleaseAttributes(principal, relyingParty, effectiveName, null,
+                                               (URI[]) requestedAttrs.toArray(new URI[0]));
                        } else {
                                log.info("Request does not designate specific attributes, resolving all available.");
-                               attrs = support.getReleaseAttributes(principal, effectiveName, null);
+                               attrs = support.getReleaseAttributes(principal, relyingParty, effectiveName, null);
                        }
 
                        log.info("Found " + attrs.length + " attribute(s) for " + principal.getName());
 
+                       // Put attributes names in the transaction log when it is set to DEBUG
+                       if (support.getTransactionLog().isDebugEnabled() && attrs.length > 0) {
+                               StringBuffer attrNameBuffer = new StringBuffer();
+                               for (int i = 0; i < attrs.length; i++) {
+                                       attrNameBuffer.append("(" + attrs[i].getName() + ")");
+                               }
+                               support.getTransactionLog()
+                                               .debug(
+                                                               "Attribute assertion generated for provider (" + effectiveName
+                                                                               + ") on behalf of principal (" + principal.getName()
+                                                                               + ") with the following attributes: " + attrNameBuffer.toString());
+                       }
+
                        SAMLResponse samlResponse = null;
 
                        if (attrs == null || attrs.length == 0) {
                                // No attribute found
                                samlResponse = new SAMLResponse(samlRequest.getId(), null, null, null);
-                       } else {
 
-                               //      SAMLAttributeQuery attributeQuery = (SAMLAttributeQuery) samlRequest.getQuery();
-
-                               //TODO catch clonenotsupportedexception
-                               //TODO no, put the use inside this blcok so we don't have to init
+                       } else {
                                // Reference requested subject
-                               SAMLSubject rSubject = null;
-                               try {
-                                       rSubject = (SAMLSubject) attributeQuery.getSubject().clone();
-                               } catch (CloneNotSupportedException e1) {
-                                       // TODO Auto-generated catch block
-                                       e1.printStackTrace();
-                               }
+                               SAMLSubject rSubject = (SAMLSubject) attributeQuery.getSubject().clone();
+
                                ArrayList audiences = new ArrayList();
                                if (relyingParty.getProviderId() != null) {
                                        audiences.add(relyingParty.getProviderId());
@@ -250,6 +273,7 @@ public class SAMLv1_AttributeQueryHandler extends BaseServiceHandler implements
                                if (relyingParty.getName() != null && !relyingParty.getName().equals(relyingParty.getProviderId())) {
                                        audiences.add(relyingParty.getName());
                                }
+
                                SAMLCondition condition = new SAMLAudienceRestrictionCondition(audiences);
 
                                // Put all attributes into an assertion
@@ -269,86 +293,91 @@ public class SAMLv1_AttributeQueryHandler extends BaseServiceHandler implements
                                SAMLAssertion sAssertion = new SAMLAssertion(relyingParty.getIdentityProvider().getProviderId(), now,
                                                then, Collections.singleton(condition), null, Collections.singleton(statement));
 
+                               // Sign the assertions, if necessary
+                               boolean metaDataIndicatesSignAssertions = false;
+                               EntityDescriptor descriptor = support.lookup(relyingParty.getProviderId());
+                               if (descriptor != null) {
+                                       AttributeRequesterDescriptor ar = descriptor
+                                                       .getAttributeRequesterDescriptor(org.opensaml.XML.SAML11_PROTOCOL_ENUM);
+                                       if (ar != null) {
+                                               if (ar.getWantAssertionsSigned()) {
+                                                       metaDataIndicatesSignAssertions = true;
+                                               }
+                                       }
+                                       if (!metaDataIndicatesSignAssertions) {
+                                               SPSSODescriptor sp = descriptor.getSPSSODescriptor(org.opensaml.XML.SAML11_PROTOCOL_ENUM);
+                                               if (sp != null) {
+                                                       if (sp.getWantAssertionsSigned()) {
+                                                               metaDataIndicatesSignAssertions = true;
+                                                       }
+                                               }
+                                       }
+                               }
+                               if (relyingParty.wantsAssertionsSigned() || metaDataIndicatesSignAssertions) {
+                                       support.signAssertions(new SAMLAssertion[]{sAssertion}, relyingParty);
+                               }
+
                                samlResponse = new SAMLResponse(samlRequest.getId(), null, Collections.singleton(sAssertion), null);
-                               IdPProtocolSupport.addSignatures(samlResponse, relyingParty, support.lookup(relyingParty
-                                               .getProviderId()), false);
                        }
 
                        if (log.isDebugEnabled()) { // This takes some processing, so only do it if we need to
-                               try {
-                                       log.debug("Dumping generated SAML Response:"
-                                                       + System.getProperty("line.separator")
-                                                       + new String(
-                                                                       new BASE64Decoder().decodeBuffer(new String(samlResponse.toBase64(), "ASCII")),
-                                                                       "UTF8"));
-                               } catch (SAMLException e) {
-                                       log.error("Encountered an error while decoding SAMLReponse for logging purposes.");
-                               } catch (IOException e) {
-                                       log.error("Encountered an error while decoding SAMLReponse for logging purposes.");
-                               }
+                               log.debug("Dumping generated SAML Response:" + System.getProperty("line.separator")
+                                               + samlResponse.toString());
                        }
 
-                       log.info("Successfully responded about " + principal.getName());
+                       log.info("Successfully created response for principal (" + principal.getName() + ").");
 
                        if (effectiveName == null) {
-                               if (fromLegacyProvider(request)) {
-                                       support.getTransactionLog().info(
-                                                       "Attribute assertion issued to anonymous legacy provider at (" + request.getRemoteAddr()
-                                                                       + ") on behalf of principal (" + principal.getName() + ").");
-                               } else {
-                                       support.getTransactionLog().info(
-                                                       "Attribute assertion issued to anonymous provider at (" + request.getRemoteAddr()
-                                                                       + ") on behalf of principal (" + principal.getName() + ").");
-                               }
+                               support.getTransactionLog().info(
+                                               "Attribute assertion issued to anonymous provider at (" + request.getRemoteAddr()
+                                                               + ") on behalf of principal (" + principal.getName() + ").");
                        } else {
-                               if (fromLegacyProvider(request)) {
-                                       support.getTransactionLog().info(
-                                                       "Attribute assertion issued to legacy provider (" + effectiveName
-                                                                       + ") on behalf of principal (" + principal.getName() + ").");
-                               } else {
-                                       support.getTransactionLog().info(
-                                                       "Attribute assertion issued to provider (" + effectiveName + ") on behalf of principal ("
-                                                                       + principal.getName() + ").");
-                               }
+                               support.getTransactionLog().info(
+                                               "Attribute assertion issued to provider (" + effectiveName + ") on behalf of principal ("
+                                                               + principal.getName() + ").");
                        }
-               } catch (InvalidNameIdentifierException e) {
-                       // TODO Auto-generated catch block
-                       e.printStackTrace();
-               } catch (NameIdentifierMappingException e) {
-                       // TODO Auto-generated catch block
-                       e.printStackTrace();
-               } catch (AAException e) {
-                       //TODO get rid of AAException, I think
-                       // TODO Auto-generated catch block
-                       e.printStackTrace();
-               }
 
-               // TODO not NULL!!!
-               return null;
-
-               /*
-                * throw new SAMLException(SAMLException.REQUESTER, "Identity Provider unable to respond to this SAML Request
-                * type."); } catch (InvalidNameIdentifierException invalidNameE) { log.info("Could not associate the request
-                * subject with a principal: " + invalidNameE); try { // TODO once again, ifgure out passThruErrors if (false) { //
-                * if (relyingParty.passThruErrors()) { sendSAMLFailureResponse(response, samlRequest, new
-                * SAMLException(Arrays.asList(invalidNameE .getSAMLErrorCodes()), "The supplied Subject was unrecognized.",
-                * invalidNameE)); } else { sendSAMLFailureResponse(response, samlRequest, new
-                * SAMLException(Arrays.asList(invalidNameE .getSAMLErrorCodes()), "The supplied Subject was unrecognized.")); }
-                * return; } catch (Exception ee) { log.fatal("Could not construct a SAML error response: " + ee); throw new
-                * ServletException("Identity Provider response failure."); }
-                */
+                       return samlResponse;
 
-       }
+               } catch (SAMLException e) {
+                       if (relyingParty.passThruErrors()) {
+                               throw new SAMLException("General error processing request.", e);
+                       } else {
+                               throw new SAMLException("General error processing request.");
+                       }
 
-       private static boolean fromLegacyProvider(HttpServletRequest request) {
+               } catch (InvalidNameIdentifierException e) {
+                       log.error("Could not associate the request's subject with a principal: " + e);
+                       if (relyingParty.passThruErrors()) {
+                               throw new SAMLException(Arrays.asList(e.getSAMLErrorCodes()), "The supplied Subject was unrecognized.",
+                                               e);
+                       } else {
+                               throw new SAMLException(Arrays.asList(e.getSAMLErrorCodes()), "The supplied Subject was unrecognized.");
+                       }
 
-               String version = request.getHeader("Shibboleth");
-               if (version != null) {
-                       log.debug("Request from Shibboleth version: " + version);
-                       return false;
+               } catch (NameIdentifierMappingException e) {
+                       log.error("Encountered an error while mapping the name identifier from the request: " + e);
+                       if (relyingParty.passThruErrors()) {
+                               throw new SAMLException("General error processing request.", e);
+                       } else {
+                               throw new SAMLException("General error processing request.");
+                       }
+
+               } catch (AAException e) {
+                       log.error("Encountered an error while resolving resolving attributes: " + e);
+                       if (relyingParty.passThruErrors()) {
+                               throw new SAMLException("General error processing request.", e);
+                       } else {
+                               throw new SAMLException("General error processing request.");
+                       }
+
+               } catch (CloneNotSupportedException e) {
+                       log.error("Encountered an error while cloning request subject for use in response: " + e);
+                       if (relyingParty.passThruErrors()) {
+                               throw new SAMLException("General error processing request.", e);
+                       } else {
+                               throw new SAMLException("General error processing request.");
+                       }
                }
-               log.debug("No version header found.");
-               return true;
        }
-
 }
\ No newline at end of file