Patches for opensaml profile/binding changes.
authorcantor <cantor@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Fri, 11 Feb 2005 15:32:48 +0000 (15:32 +0000)
committercantor <cantor@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Fri, 11 Feb 2005 15:32:48 +0000 (15:32 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@1240 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

19 files changed:
src/edu/internet2/middleware/shibboleth/aa/AAAttribute.java
src/edu/internet2/middleware/shibboleth/aa/AAServlet.java
src/edu/internet2/middleware/shibboleth/common/InvalidNameIdentifierException.java
src/edu/internet2/middleware/shibboleth/common/OriginSiteMapperException.java
src/edu/internet2/middleware/shibboleth/common/SAMLBindingFactory.java [deleted file]
src/edu/internet2/middleware/shibboleth/common/ShibBrowserProfile.java [new file with mode: 0644]
src/edu/internet2/middleware/shibboleth/common/ShibPOSTProfile.java [deleted file]
src/edu/internet2/middleware/shibboleth/common/UnsupportedProtocolException.java
src/edu/internet2/middleware/shibboleth/idp/IdPResponder.java
src/edu/internet2/middleware/shibboleth/metadata/MetadataException.java
src/edu/internet2/middleware/shibboleth/serviceprovider/AttributeRequestor.java
src/edu/internet2/middleware/shibboleth/serviceprovider/AuthenticationAssertionConsumerServlet.java
src/edu/internet2/middleware/shibboleth/serviceprovider/FilterSupportImpl.java
src/edu/internet2/middleware/shibboleth/serviceprovider/ServiceProviderConfig.java
src/edu/internet2/middleware/shibboleth/serviceprovider/ServiceProviderContext.java
src/edu/internet2/middleware/shibboleth/serviceprovider/ShibBinding.java
src/edu/internet2/middleware/shibboleth/serviceprovider/ShibPOSTProfile.java [deleted file]
src/edu/internet2/middleware/shibboleth/utils/SAML1_0to1_1ConversionFilter.java
tests/edu/internet2/middleware/shibboleth/aa/DNHostNameExtractionTests.java

index a445861..32abcf4 100644 (file)
@@ -56,8 +56,9 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 
+import javax.xml.namespace.QName;
+
 import org.apache.log4j.Logger;
-import org.opensaml.QName;
 import org.opensaml.SAMLAttribute;
 import org.opensaml.SAMLException;
 import org.opensaml.XML;
@@ -201,7 +202,7 @@ public class AAAttribute extends SAMLAttribute implements ResolverAttribute, Arp
                        }
                        Element valueElement = doc.createElementNS(XML.SAML_NS, "AttributeValue");
                        if (type != null) {
-                               valueElement.setAttributeNS(XML.XSI_NS, "xsi:type", "typens:" + type.getLocalName());
+                               valueElement.setAttributeNS(XML.XSI_NS, "xsi:type", "typens:" + type.getLocalPart());
                        }
                        
                        try {
index a7bef9f..b029892 100755 (executable)
@@ -39,6 +39,7 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Random;
 
 import javax.security.auth.x500.X500Principal;
 import javax.servlet.ServletException;
@@ -51,6 +52,7 @@ import org.apache.log4j.MDC;
 import org.apache.xml.security.exceptions.XMLSecurityException;
 import org.apache.xml.security.keys.KeyInfo;
 import org.apache.xml.security.signature.XMLSignature;
+import org.opensaml.*;
 import org.opensaml.InvalidCryptoException;
 import org.opensaml.SAMLAssertion;
 import org.opensaml.SAMLAttribute;
@@ -61,7 +63,6 @@ import org.opensaml.SAMLAudienceRestrictionCondition;
 import org.opensaml.SAMLBinding;
 import org.opensaml.SAMLCondition;
 import org.opensaml.SAMLException;
-import org.opensaml.SAMLIdentifier;
 import org.opensaml.SAMLRequest;
 import org.opensaml.SAMLResponse;
 import org.opensaml.SAMLStatement;
@@ -75,6 +76,7 @@ import edu.internet2.middleware.shibboleth.aa.arp.ArpEngine;
 import edu.internet2.middleware.shibboleth.aa.arp.ArpException;
 import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeResolver;
 import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeResolverException;
+import edu.internet2.middleware.shibboleth.common.*;
 import edu.internet2.middleware.shibboleth.common.Credential;
 import edu.internet2.middleware.shibboleth.common.Credentials;
 import edu.internet2.middleware.shibboleth.common.InvalidNameIdentifierException;
@@ -83,9 +85,7 @@ import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException
 import edu.internet2.middleware.shibboleth.common.NameMapper;
 import edu.internet2.middleware.shibboleth.common.OriginConfig;
 import edu.internet2.middleware.shibboleth.common.RelyingParty;
-import edu.internet2.middleware.shibboleth.common.SAMLBindingFactory;
 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;
@@ -100,14 +100,16 @@ import edu.internet2.middleware.shibboleth.metadata.ProviderRole;
 
 public class AAServlet extends TargetFederationComponent {
 
-       private AAConfig                                configuration;
+    private static Logger           transactionLog  = Logger.getLogger("Shibboleth-TRANSACTION");
+    private static Logger           log             = Logger.getLogger(AAServlet.class.getName());
+    private static Random           idgen           = new Random();
+
+    private AAConfig                           configuration;
        protected AAResponder                   responder;
        private NameMapper                              nameMapper;
        private SAMLBinding                             binding;
-       private static Logger                   transactionLog  = Logger.getLogger("Shibboleth-TRANSACTION");
        private AAServiceProviderMapper targetMapper;
 
-       private static Logger                   log                             = Logger.getLogger(AAServlet.class.getName());
 
        public void init() throws ServletException {
                super.init();
@@ -119,7 +121,7 @@ public class AAServlet extends TargetFederationComponent {
                        nameMapper = new NameMapper();
                        loadConfiguration();
 
-                       binding = SAMLBindingFactory.getInstance(SAMLBinding.SAML_SOAP_HTTPS);
+                       binding = SAMLBindingFactory.getInstance(SAMLBinding.SOAP);
 
                        log.info("Attribute Authority initialization complete.");
 
@@ -216,7 +218,7 @@ public class AAServlet extends TargetFederationComponent {
 
        public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
-               MDC.put("serviceId", "[AA] " + new SAMLIdentifier().toString());
+               MDC.put("serviceId", "[AA] " + idgen.nextInt());
                MDC.put("remoteAddr", req.getRemoteAddr());
                log.info("Handling request.");
 
@@ -392,7 +394,7 @@ public class AAServlet extends TargetFederationComponent {
                                        + credential.getSubjectX500Principal().getName(X500Principal.RFC2253) + ").");
                        //Mockup old requester name for requests from < 1.2 targets
                        if (fromLegacyProvider(req)) {
-                               String legacyName = ShibPOSTProfile.getHostNameFromDN(credential.getSubjectX500Principal());
+                               String legacyName = ShibBrowserProfile.getHostNameFromDN(credential.getSubjectX500Principal());
                                if (legacyName == null) {
                                        log.error("Unable to extract legacy requester name from certificate subject.");
                                }
@@ -502,7 +504,13 @@ public class AAServlet extends TargetFederationComponent {
                                }
                        }
 
-                       binding.respond(resp, samlResponse, ourSE);
+                       try {
+                binding.respond(resp, samlResponse, ourSE);
+            }
+            catch (SAMLException e) {
+                log.error("Caught exception while responding to requester: " + e.getMessage());
+                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error while responding.");
+            }
                }
        }
 
@@ -566,7 +574,13 @@ public class AAServlet extends TargetFederationComponent {
                        binding.respond(httpResponse, samlResponse, null);
                        log.debug("Returning SAML Error Response.");
                } catch (SAMLException se) {
-                       binding.respond(httpResponse, null, exception);
+                       try {
+                binding.respond(httpResponse, null, exception);
+            }
+            catch (SAMLException e) {
+                log.error("Caught exception while responding to requester: " + e.getMessage());
+                httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error while responding.");
+            }
                        log.error("AA failed to make an error message: " + se);
                }
        }
@@ -622,7 +636,7 @@ public class AAServlet extends TargetFederationComponent {
                                                                }
 
                                                                //If that doesn't work, try to match using SSL-style hostname matching
-                                                               if (ShibPOSTProfile.getHostNameFromDN(certificate.getSubjectX500Principal()).equals(
+                                                               if (ShibBrowserProfile.getHostNameFromDN(certificate.getSubjectX500Principal()).equals(
                                                                                keyInfo[k].itemKeyName(l).getKeyName())) {
                                                                        log.debug("Matched against hostname.");
                                                                        return true;
index 6d621bd..96cb98a 100644 (file)
@@ -51,7 +51,7 @@ package edu.internet2.middleware.shibboleth.common;
 
 import java.util.Collection;
 
-import org.opensaml.QName;
+import javax.xml.namespace.QName;
 import org.opensaml.SAMLException;
 import org.w3c.dom.Element;
 
diff --git a/src/edu/internet2/middleware/shibboleth/common/SAMLBindingFactory.java b/src/edu/internet2/middleware/shibboleth/common/SAMLBindingFactory.java
deleted file mode 100755 (executable)
index a581311..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/* 
- * 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 org.opensaml.*;
-
-
-/**
- *  Used by Shibboleth SHAR/AA to locate a SAML binding implementation
- *
- * @author     Scott Cantor
- * @created    April 10, 2002
- */
-public class SAMLBindingFactory
-{
-    /**
-     *  Gets a compatible binding implementation for the specified protocol and
-     *  policies
-     *
-     * @param  protocol                          URI of SAML binding protocol
-     * @return                                   A compatible binding
-     *      implementation
-     */
-    public static SAMLBinding getInstance(String protocol)
-        throws SAMLException
-    {
-        // Current version only knows about the SOAP binding
-        if (protocol == null || !protocol.equals(SAMLBinding.SAML_SOAP_HTTPS))
-            throw new UnsupportedProtocolException("SAMLBindingFactory.getInstance() unable to find binding implementation for specified protocol");            
-        return new SAMLSOAPBinding();
-    }
-}
-
diff --git a/src/edu/internet2/middleware/shibboleth/common/ShibBrowserProfile.java b/src/edu/internet2/middleware/shibboleth/common/ShibBrowserProfile.java
new file mode 100644 (file)
index 0000000..d8e9b1c
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ * 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.security.GeneralSecurityException;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.cert.CertPathBuilder;
+import java.security.cert.CertPathBuilderException;
+import java.security.cert.CertStore;
+import java.security.cert.CollectionCertStoreParameters;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.PKIXCertPathBuilderResult;
+import java.security.cert.X509CertSelector;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.security.auth.x500.X500Principal;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.NDC;
+import org.apache.xml.security.signature.XMLSignature;
+import org.opensaml.*;
+import org.w3c.dom.Document;
+
+import edu.internet2.middleware.shibboleth.hs.HSRelyingParty;
+import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
+import edu.internet2.middleware.shibboleth.metadata.IDPProviderRole;
+import edu.internet2.middleware.shibboleth.metadata.MetadataException;
+import edu.internet2.middleware.shibboleth.metadata.ProviderRole;
+import edu.internet2.middleware.shibboleth.serviceprovider.ServiceProviderConfig;
+import edu.internet2.middleware.shibboleth.serviceprovider.ServiceProviderContext;
+import edu.internet2.middleware.shibboleth.serviceprovider.ServiceProviderConfig.ApplicationInfo;
+
+// TODO: Do the cert extraction methods belong here? Probably not...
+
+// TODO: Suggest we implement a separation layer between the SP config pieces and the input needed
+// for this class. As long as metadata/etc. are shared, this should work.
+
+/**
+ * Basic Shibboleth POST browser profile implementation with basic support for signing
+ * 
+ * @author Scott Cantor @created April 11, 2002
+ */
+public class ShibBrowserProfile implements SAMLBrowserProfile {
+
+       private static Pattern  regex           = Pattern.compile(".*?CN=([^,/]+).*");
+
+       /** XML Signature algorithm to apply */
+       protected String                algorithm       = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
+
+       private static Logger   log                     = Logger.getLogger(ShibBrowserProfile.class.getName());
+
+    /** Policy URIs to attach or check against */
+    protected ArrayList     policies    = new ArrayList();
+
+    protected SAMLBrowserProfile profile = SAMLBrowserProfileFactory.getInstance(); 
+    private static ServiceProviderContext context = ServiceProviderContext.getInstance();
+
+    /*
+     * The C++ class is constructed by passing enumerations of Metadata
+     * providers, trust providers, etc from the <Application>. However,
+     * those providers can change dynamically. This version only keeps
+     * the applicationId that can be used to fetch the ApplicationInfo 
+     * object and, from it, get the collections of provider plugins.
+     * 
+     * TODO: The reason they were still dynamic in C++ was that this wrapper
+     * object was built dynamically. It's now contained within the application
+     * interface itself and so it's "scoped" within the application and shares
+     * the set of plugins from it. One reloads, the other is rebuilt.
+     */
+    private String applicationId = null;
+    
+    /**
+     * Identify the <Application> from which to get plugins.
+     * 
+     * @param applicationId 
+     */
+    public ShibBrowserProfile(String applicationId) throws NoSuchProviderException {
+        this.applicationId = applicationId;
+    }
+
+       /**
+        * Used by HS to generate a signed SAML response conforming to the POST profile
+        * <P>
+        * 
+        * @param recipient
+        *            URL of the assertion consumer
+        * @param relyingParty
+        *            the intended recipient of the response
+        * @param nameId
+        *            Name Identifier for the response
+        * @param subjectIP
+        *            Client address of subject (optional)
+        * @param authMethod
+        *            URI of authentication method being asserted
+        * @param authInstant
+        *            Date and time of authentication being asserted
+        * @param bindings
+        *            Set of SAML authorities the relying party may contact (optional)
+        * @return SAML response to send to accepting site
+        * @exception SAMLException
+        *                Base class of exceptions that may be thrown during processing
+        */
+       public SAMLResponse prepare(String recipient, HSRelyingParty relyingParty, SAMLNameIdentifier nameId,
+                       String subjectIP, String authMethod, Date authInstant, Collection bindings) throws SAMLException {
+
+               Document doc = org.opensaml.XML.parserPool.newDocument();
+
+               ArrayList audiences = new ArrayList();
+               if (relyingParty.getProviderId() != null) {
+                       audiences.add(relyingParty.getProviderId());
+               }
+               if (relyingParty.getName() != null && !relyingParty.getName().equals(relyingParty.getProviderId())) {
+                       audiences.add(relyingParty.getName());
+               }
+
+               String issuer = null;
+               if (relyingParty.isLegacyProvider()) {
+                       
+                       log.debug("Service Provider is running Shibboleth <= 1.1.  Using old style issuer.");
+                       if (relyingParty.getIdentityProvider().getResponseSigningCredential() == null
+                                       || relyingParty.getIdentityProvider().getResponseSigningCredential().getX509Certificate() == null) {
+                               throw new SAMLException("Cannot serve legacy style assertions without an X509 certificate");
+                       }
+                       issuer = getHostNameFromDN(relyingParty.getIdentityProvider().getResponseSigningCredential()
+                                       .getX509Certificate().getSubjectX500Principal());
+                       if (issuer == null || issuer.equals("")) {
+                               throw new SAMLException("Error parsing certificate DN while determining legacy issuer name.");
+                       }
+
+               } else {
+                       issuer = relyingParty.getIdentityProvider().getProviderId();
+               }
+
+        // XXX: Inlined the old prepare method, this whole method should probably be pulled out into the IdP package.
+        // At a minimum, artifact should be integrated in.
+        SAMLResponse r = new SAMLResponse(
+                null,
+                recipient,
+                Collections.singleton(
+                        new SAMLAssertion(
+                                issuer,
+                                new Date(),
+                                new Date(System.currentTimeMillis() + 1000 * SAMLConfig.instance().getIntProperty("org.opensaml.clock-skew")),
+                                Collections.singleton(
+                                        new SAMLAudienceRestrictionCondition(audiences)
+                                        ),
+                                null,
+                                Collections.singleton(
+                                        new SAMLAuthenticationStatement(
+                                                new SAMLSubject(
+                                                        nameId,
+                                                        Collections.singleton(SAMLSubject.CONF_BEARER),
+                                                        null,
+                                                        null
+                                                        ),
+                                                authMethod,
+                                                authInstant,
+                                                subjectIP,
+                                                null,
+                                                bindings
+                                                )
+                                        )
+                                )
+                        ),
+                null
+                );
+               r.toDOM(doc);
+
+               //Sign the assertions, if appropriate
+               if (relyingParty.getIdentityProvider().getAssertionSigningCredential() != null
+                               && relyingParty.getIdentityProvider().getAssertionSigningCredential().getPrivateKey() != null) {
+
+                       String assertionAlgorithm;
+                       if (relyingParty.getIdentityProvider().getAssertionSigningCredential().getCredentialType() == Credential.RSA) {
+                               assertionAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
+                       } else if (relyingParty.getIdentityProvider().getAssertionSigningCredential().getCredentialType() == Credential.DSA) {
+                               assertionAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_DSA;
+                       } else {
+                               throw new InvalidCryptoException(SAMLException.RESPONDER,
+                                               "ShibPOSTProfile.prepare() currently only supports signing with RSA and DSA keys.");
+                       }
+
+                       ((SAMLAssertion) r.getAssertions().next()).sign(assertionAlgorithm, relyingParty.getIdentityProvider()
+                                       .getAssertionSigningCredential().getPrivateKey(), Arrays.asList(relyingParty.getIdentityProvider()
+                                       .getAssertionSigningCredential().getX509CertificateChain()));
+               }
+
+               //Sign the response, if appropriate
+               if (relyingParty.getIdentityProvider().getResponseSigningCredential() != null
+                               && relyingParty.getIdentityProvider().getResponseSigningCredential().getPrivateKey() != null) {
+
+                       String responseAlgorithm;
+                       if (relyingParty.getIdentityProvider().getResponseSigningCredential().getCredentialType() == Credential.RSA) {
+                               responseAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
+                       } else if (relyingParty.getIdentityProvider().getResponseSigningCredential().getCredentialType() == Credential.DSA) {
+                               responseAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_DSA;
+                       } else {
+                               throw new InvalidCryptoException(SAMLException.RESPONDER,
+                                               "ShibPOSTProfile.prepare() currently only supports signing with RSA and DSA keys.");
+                       }
+
+                       r.sign(responseAlgorithm,
+                                       relyingParty.getIdentityProvider().getResponseSigningCredential().getPrivateKey(), Arrays
+                                                       .asList(relyingParty.getIdentityProvider().getResponseSigningCredential()
+                                                                       .getX509CertificateChain()));
+               }
+
+               return r;
+       }
+
+    /**
+     * Given a key from Trust associated with a HS Role from a Metadata Entity Descriptor,
+     * verify the SAML Signature.
+     * 
+     * TODO: Replace this with calls into pluggable Trust provider
+     * 
+     * @param obj           A signed SAMLObject
+     * @param signerName    The signer's ID
+     * @param ks            KeyStore [TrustProvider abstraction violation, may change]
+     * @param knownKey      Key from the Trust entry associated with the signer's Metadata
+     * @throws SAMLException
+     */
+    static void verifySignature(
+            SAMLSignedObject obj, 
+            String signerName, 
+            KeyStore ks, 
+            Key knownKey)
+        throws SAMLException {
+        try {
+            NDC.push("verifySignature");
+            
+            if (!obj.isSigned()) {
+                log.error("unable to find a signature");
+                throw new TrustException(SAMLException.RESPONDER,
+                "ShibPOSTProfile.verifySignature() given an unsigned object");
+            }
+            
+            if (knownKey != null) {
+                log.info("verifying signature with known key value, ignoring signature KeyInfo");
+                obj.verify(knownKey);
+                return;
+            }
+            
+            
+            log.info("verifying signature with embedded KeyInfo");
+            obj.verify();
+            
+            // This is pretty painful, and this is leveraging the supposedly
+            // automatic support in JDK 1.4.
+            // First we have to extract the certificates from the object.
+            Iterator certs_from_obj = obj.getX509Certificates();
+            if (!certs_from_obj.hasNext()) {
+                log.error("need certificates inside object to establish trust");
+                throw new TrustException(SAMLException.RESPONDER,
+                "ShibPOSTProfile.verifySignature() can't find any certificates");
+            }
+            
+            // We assume the first one in the set is the end entity cert.
+            X509Certificate entity_cert = (X509Certificate) certs_from_obj.next();
+            
+            // Match the CN of the entity cert with the expected signer.
+            String dname = entity_cert.getSubjectDN().getName();
+            log.debug("found entity cert with DN: " + dname);
+            String cname = "CN=" + signerName;
+            if (!dname.equalsIgnoreCase(cname) && !dname.regionMatches(true, 0, cname + ',', 0, cname.length() + 1)) {
+                log
+                .error("verifySignature() found a mismatch between the entity certificate's DN and the expected signer: "
+                        + signerName);
+                throw new TrustException(SAMLException.RESPONDER,
+                "ShibPOSTProfile.verifySignature() found mismatch between entity certificate and expected signer");
+            }
+            
+            // Prep a chain between the entity cert and the trusted roots.
+            X509CertSelector targetConstraints = new X509CertSelector();
+            targetConstraints.setCertificate(entity_cert);
+            PKIXBuilderParameters params = new PKIXBuilderParameters(ks, targetConstraints);
+            params.setMaxPathLength(-1);
+            
+            Vector certbag = new Vector();
+            certbag.add(entity_cert);
+            while (certs_from_obj.hasNext())
+                certbag.add(certs_from_obj.next());
+            CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(certbag);
+            CertStore store = CertStore.getInstance("Collection", ccsp);
+            params.addCertStore(store);
+            
+            // Attempt to build a path.
+            CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
+            PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) cpb.build(params);
+        } catch (CertPathBuilderException e) {
+            log.error("caught a cert path builder exception: " + e.getMessage());
+            throw new TrustException(SAMLException.RESPONDER,
+                    "ShibPOSTProfile.verifySignature() unable to build a PKIX certificate path", e);
+        } catch (GeneralSecurityException e) {
+            log.error("caught a general security exception: " + e.getMessage());
+            throw new TrustException(SAMLException.RESPONDER,
+                    "ShibPOSTProfile.verifySignature() unable to build a PKIX certificate path", e);
+        } finally {
+            NDC.pop();
+        }
+    }
+
+    public static String getHostNameFromDN(X500Principal dn) {
+               Matcher matches = regex.matcher(dn.getName(X500Principal.RFC2253));
+               if (!matches.find() || matches.groupCount() > 1) {
+                       log.error("Unable to extract host name name from certificate subject DN.");
+                       return null;
+               }
+               return matches.group(1);
+       }
+
+    /**
+     * @see org.opensaml.SAMLBrowserProfile#setVersion(int, int)
+     */
+    public void setVersion(int major, int minor) throws SAMLException {
+        profile.setVersion(major, minor);
+    }
+
+    /**
+     * @see org.opensaml.SAMLBrowserProfile#receive(java.lang.StringBuffer, javax.servlet.http.HttpServletRequest, java.lang.String, int, org.opensaml.ReplayCache, org.opensaml.SAMLBrowserProfile.ArtifactMapper)
+     */
+    public BrowserProfileResponse receive(
+            StringBuffer issuer,
+            HttpServletRequest reqContext,
+            String recipient,
+            int supportedProfiles,
+            ReplayCache replayCache,
+            ArtifactMapper artifactMapper
+            ) throws SAMLException {
+        
+        String providerId = null;
+        issuer.setLength(0);
+        
+        // Let SAML do all the decoding and parsing
+        BrowserProfileResponse bpr = profile.receive(issuer, reqContext, providerId, supportedProfiles, replayCache, artifactMapper);
+        
+        /*
+         * Now find the Metadata for the Entity that send this assertion.
+         * From the C++, look first for issuer, then namequalifier (for 1.1 compat.)
+         */
+        EntityDescriptor entity = null;
+        String asn_issuer = bpr.assertion.getIssuer();
+        String qualifier = bpr.authnStatement.getSubject().getName().getNameQualifier();
+        ServiceProviderConfig config = context.getServiceProviderConfig();
+        ApplicationInfo appinfo = config.getApplication(applicationId);
+        
+        entity = appinfo.getEntityDescriptor(asn_issuer);
+        providerId=asn_issuer;
+        if (entity==null) {
+            providerId=qualifier;
+            entity= appinfo.getEntityDescriptor(qualifier);
+        }
+        if (entity==null) {
+            log.error("assertion issuer not found in metadata(Issuer ="+
+                    issuer+", NameQualifier="+qualifier);
+            throw new MetadataException("ShibBrowserProfile.receive() metadata lookup failed, unable to process assertion");
+        }
+        issuer.append(providerId);
+        
+        // From the Metadata, get the HS and from it the key
+        ProviderRole[] roles = entity.getRoles();
+        for (int i=0;i<roles.length;i++) {
+            ProviderRole role = roles[i];
+            if (role instanceof IDPProviderRole) {
+                // TODO: Sync up with new SAML metadata profile (uses SAML protocol string instead of SHIB_NS)
+                if (role.hasSupport(XML.SHIB_NS)) {
+                    ;
+                }
+            }
+        }
+        
+        return bpr;
+    }
+}
diff --git a/src/edu/internet2/middleware/shibboleth/common/ShibPOSTProfile.java b/src/edu/internet2/middleware/shibboleth/common/ShibPOSTProfile.java
deleted file mode 100755 (executable)
index 2c72a89..0000000
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * 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.security.GeneralSecurityException;
-import java.security.Key;
-import java.security.KeyStore;
-import java.security.cert.CertPathBuilder;
-import java.security.cert.CertPathBuilderException;
-import java.security.cert.CertStore;
-import java.security.cert.CollectionCertStoreParameters;
-import java.security.cert.PKIXBuilderParameters;
-import java.security.cert.PKIXCertPathBuilderResult;
-import java.security.cert.X509CertSelector;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.Vector;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.security.auth.x500.X500Principal;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.NDC;
-import org.apache.xml.security.signature.XMLSignature;
-import org.opensaml.InvalidAssertionException;
-import org.opensaml.InvalidCryptoException;
-import org.opensaml.SAMLAssertion;
-import org.opensaml.SAMLAuthenticationStatement;
-import org.opensaml.SAMLException;
-import org.opensaml.SAMLNameIdentifier;
-import org.opensaml.SAMLPOSTProfile;
-import org.opensaml.SAMLResponse;
-import org.opensaml.SAMLSignedObject;
-import org.opensaml.SAMLStatement;
-import org.opensaml.SAMLSubject;
-import org.opensaml.TrustException;
-import org.w3c.dom.Document;
-
-import edu.internet2.middleware.shibboleth.hs.HSRelyingParty;
-
-/**
- * Basic Shibboleth POST browser profile implementation with basic support for signing
- * 
- * @author Scott Cantor @created April 11, 2002
- */
-public class ShibPOSTProfile {
-
-       private static Pattern  regex           = Pattern.compile(".*?CN=([^,/]+).*");
-
-       /** XML Signature algorithm to apply */
-       protected String                algorithm       = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
-
-       /** Policy URIs to attach or check against */
-       protected ArrayList             policies        = new ArrayList();
-
-       /** The URL of the receiving SHIRE */
-       protected String                receiver        = null;
-
-       /** Seconds allowed to elapse from issuance of response */
-       protected int                   ttlSeconds      = 0;
-
-       private static Logger   log                     = Logger.getLogger(ShibPOSTProfile.class.getName());
-
-       /**
-        * SHIRE-side constructor for a ShibPOSTProfile object
-        * 
-        * @param policies
-        *            Set of policy URIs that the implementation must support
-        * @param receiver
-        *            URL of SHIRE
-        * @param ttlSeconds
-        *            Length of time in seconds allowed to elapse from issuance of SAML response
-        * @exception SAMLException
-        *                Raised if a profile implementation cannot be constructed from the supplied information
-        */
-       public ShibPOSTProfile(Collection policies, String receiver, int ttlSeconds) throws SAMLException {
-               if (policies == null || policies.size() == 0 || receiver == null || receiver.length() == 0 || ttlSeconds <= 0)
-                       throw new SAMLException(SAMLException.REQUESTER, "ShibPOSTProfile() found a null or invalid argument");
-
-               this.receiver = receiver;
-               this.ttlSeconds = ttlSeconds;
-               this.policies.addAll(policies);
-       }
-
-       /**
-        * HS-side constructor for a ShibPOSTProfile object.
-        */
-       public ShibPOSTProfile() {}
-
-       /**
-        * Locates an assertion containing a "bearer" AuthenticationStatement in the response and validates the enclosing
-        * assertion with respect to the POST profile
-        * 
-        * @param r
-        *            The response to the accepting site
-        * @return An SSO assertion
-        * @throws SAMLException
-        *             Thrown if an SSO assertion can't be found
-        */
-       public SAMLAssertion getSSOAssertion(SAMLResponse r) throws SAMLException {
-               return SAMLPOSTProfile.getSSOAssertion(r, policies);
-       }
-
-       /**
-        * Locates a "bearer" AuthenticationStatement in the assertion and validates the statement with respect to the POST
-        * profile
-        * 
-        * @param a
-        *            The SSO assertion sent to the accepting site
-        * @return A "bearer" authentication statement
-        * @throws SAMLException
-        *             Thrown if an SSO statement can't be found
-        */
-       public SAMLAuthenticationStatement getSSOStatement(SAMLAssertion a) throws SAMLException {
-               return SAMLPOSTProfile.getSSOStatement(a);
-       }
-
-       /**
-        * Examines a response to determine the source site name
-        * 
-        * @param r
-        * @return
-        */
-       String getOriginSite(SAMLResponse r) {
-               Iterator ia = r.getAssertions();
-               while (ia.hasNext()) {
-                       Iterator is = ((SAMLAssertion) ia.next()).getStatements();
-                       while (is.hasNext()) {
-                               SAMLStatement s = (SAMLStatement) is.next();
-                               if (s instanceof SAMLAuthenticationStatement)
-                                       return ((SAMLAuthenticationStatement) s).getSubject().getName().getName();
-                       }
-               }
-               return null;
-       }
-
-       /**
-        * Parse a Base-64 encoded buffer back into a SAML response and test its validity against the POST profile,
-        * including use of the default replay cache
-        * <P>
-        * Also does trust evaluation based on the information available from the origin site mapper, in accordance with
-        * general Shibboleth processing semantics. Club-specific processing must be performed in a subclass.
-        * <P>
-        * 
-        * @param buf
-        *            A Base-64 encoded buffer containing a SAML response
-        * @param originSite
-        * @return SAML response sent by origin site
-        * @exception SAMLException
-        *                Thrown if the response cannot be understood or accepted
-        */
-       public SAMLResponse accept(byte[] buf, StringBuffer originSite) throws SAMLException {
-               // The built-in SAML functionality will do most of the basic non-crypto checks.
-               // Note that if the response only contains a status error, it gets
-               // tossed out as an exception.
-               SAMLResponse r = SAMLPOSTProfile.accept(buf, receiver, ttlSeconds, false);
-
-               if (originSite == null)
-                       originSite = new StringBuffer();
-
-               // Now we do some more non-crypto (ie. cheap) work to match up the origin site
-               // with its associated data. If we can't even find a SSO statement in
-               // the response we just return the response to the caller, who will presumably
-               // notice this.
-               SAMLAssertion assertion = null;
-               SAMLAuthenticationStatement sso = null;
-
-               try {
-                       assertion = getSSOAssertion(r);
-                       sso = getSSOStatement(assertion);
-               } catch (SAMLException e) {
-                       originSite.setLength(0);
-                       originSite.append(getOriginSite(r));
-                       throw e;
-               }
-
-               // Examine the subject information.
-               SAMLSubject subject = sso.getSubject();
-               if (subject.getName().getName() == null)
-                       throw new InvalidAssertionException(SAMLException.RESPONDER,
-                                       "ShibPOSTProfile.accept() requires subject name qualifier");
-
-               originSite.setLength(0);
-               originSite.append(subject.getName().getName());
-               String handleService = assertion.getIssuer();
-
-               // Is this a trusted HS?
-               OriginSiteMapper mapper = Init.getMapper();
-               Iterator hsNames = mapper.getHandleServiceNames(originSite.toString());
-               boolean bFound = false;
-               while (!bFound && hsNames.hasNext())
-                       if (hsNames.next().equals(handleService))
-                               bFound = true;
-               if (!bFound)
-                       throw new TrustException(SAMLException.RESPONDER,
-                                       "ShibPOSTProfile.accept() detected an untrusted HS for the origin site");
-
-               Key hsKey = mapper.getHandleServiceKey(handleService);
-               KeyStore ks = mapper.getTrustedRoots();
-
-               // Signature verification now takes place. We check the assertion and
-               // the response. Assertion signing is optional, response signing is mandatory.
-               try {
-                       NDC.push("accept");
-                       if (assertion.isSigned()) {
-                               log.info("verifying assertion signature");
-                               verifySignature(assertion, handleService, ks, hsKey);
-                       }
-                       log.info("verifying response signature");
-                       verifySignature(r, handleService, ks, hsKey);
-               } finally {
-                       NDC.pop();
-               }
-               return r;
-       }
-
-       /**
-        * Used by HS to generate a signed SAML response conforming to the POST profile
-        * <P>
-        * 
-        * @param recipient
-        *            URL of the assertion consumer
-        * @param relyingParty
-        *            the intended recipient of the response
-        * @param nameId
-        *            Name Identifier for the response
-        * @param subjectIP
-        *            Client address of subject (optional)
-        * @param authMethod
-        *            URI of authentication method being asserted
-        * @param authInstant
-        *            Date and time of authentication being asserted
-        * @param bindings
-        *            Set of SAML authorities the relying party may contact (optional)
-        * @return SAML response to send to accepting site
-        * @exception SAMLException
-        *                Base class of exceptions that may be thrown during processing
-        */
-       public SAMLResponse prepare(String recipient, HSRelyingParty relyingParty, SAMLNameIdentifier nameId,
-                       String subjectIP, String authMethod, Date authInstant, Collection bindings) throws SAMLException {
-
-               Document doc = org.opensaml.XML.parserPool.newDocument();
-
-               ArrayList audiences = new ArrayList();
-               if (relyingParty.getProviderId() != null) {
-                       audiences.add(relyingParty.getProviderId());
-               }
-               if (relyingParty.getName() != null && !relyingParty.getName().equals(relyingParty.getProviderId())) {
-                       audiences.add(relyingParty.getName());
-               }
-
-               String issuer = null;
-               if (relyingParty.isLegacyProvider()) {
-                       
-                       log.debug("Service Provider is running Shibboleth <= 1.1.  Using old style issuer.");
-                       if (relyingParty.getIdentityProvider().getResponseSigningCredential() == null
-                                       || relyingParty.getIdentityProvider().getResponseSigningCredential().getX509Certificate() == null) {
-                               throw new SAMLException("Cannot serve legacy style assertions without an X509 certificate");
-                       }
-                       issuer = getHostNameFromDN(relyingParty.getIdentityProvider().getResponseSigningCredential()
-                                       .getX509Certificate().getSubjectX500Principal());
-                       if (issuer == null || issuer.equals("")) {
-                               throw new SAMLException("Error parsing certificate DN while determining legacy issuer name.");
-                       }
-
-               } else {
-                       issuer = relyingParty.getIdentityProvider().getProviderId();
-               }
-
-               SAMLResponse r = SAMLPOSTProfile.prepare(recipient, issuer, audiences, nameId, subjectIP, authMethod,
-                               authInstant, bindings);
-               r.toDOM(doc);
-
-               //Sign the assertions, if appropriate
-               if (relyingParty.getIdentityProvider().getAssertionSigningCredential() != null
-                               && relyingParty.getIdentityProvider().getAssertionSigningCredential().getPrivateKey() != null) {
-
-                       String assertionAlgorithm;
-                       if (relyingParty.getIdentityProvider().getAssertionSigningCredential().getCredentialType() == Credential.RSA) {
-                               assertionAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
-                       } else if (relyingParty.getIdentityProvider().getAssertionSigningCredential().getCredentialType() == Credential.DSA) {
-                               assertionAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_DSA;
-                       } else {
-                               throw new InvalidCryptoException(SAMLException.RESPONDER,
-                                               "ShibPOSTProfile.prepare() currently only supports signing with RSA and DSA keys.");
-                       }
-
-                       ((SAMLAssertion) r.getAssertions().next()).sign(assertionAlgorithm, relyingParty.getIdentityProvider()
-                                       .getAssertionSigningCredential().getPrivateKey(), Arrays.asList(relyingParty.getIdentityProvider()
-                                       .getAssertionSigningCredential().getX509CertificateChain()));
-               }
-
-               //Sign the response, if appropriate
-               if (relyingParty.getIdentityProvider().getResponseSigningCredential() != null
-                               && relyingParty.getIdentityProvider().getResponseSigningCredential().getPrivateKey() != null) {
-
-                       String responseAlgorithm;
-                       if (relyingParty.getIdentityProvider().getResponseSigningCredential().getCredentialType() == Credential.RSA) {
-                               responseAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
-                       } else if (relyingParty.getIdentityProvider().getResponseSigningCredential().getCredentialType() == Credential.DSA) {
-                               responseAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_DSA;
-                       } else {
-                               throw new InvalidCryptoException(SAMLException.RESPONDER,
-                                               "ShibPOSTProfile.prepare() currently only supports signing with RSA and DSA keys.");
-                       }
-
-                       r.sign(responseAlgorithm,
-                                       relyingParty.getIdentityProvider().getResponseSigningCredential().getPrivateKey(), Arrays
-                                                       .asList(relyingParty.getIdentityProvider().getResponseSigningCredential()
-                                                                       .getX509CertificateChain()));
-               }
-
-               return r;
-       }
-
-       /**
-        * Searches the replay cache for the specified assertion and inserts a newly seen assertion into the cache
-        * <P>
-        * Also performs garbage collection of the cache by deleting expired entries.
-        * 
-        * @param a
-        *            The assertion to check
-        * @return true iff the assertion has not been seen before
-        */
-       public synchronized boolean checkReplayCache(SAMLAssertion a) {
-               // Default implementation uses the basic replay cache implementation.
-               return SAMLPOSTProfile.checkReplayCache(a);
-       }
-
-       /**
-        * Default signature verification algorithm uses an embedded X509 certificate(s) or an explicit key to verify the
-        * signature. The certificate is examined to insure the subject CN matches the signer, and that it is signed by a
-        * trusted CA
-        * 
-        * @param obj
-        *            The object containing the signature
-        * @param signerName
-        *            The name of the signer
-        * @param ks
-        *            A keystore containing trusted root certificates
-        * @param knownKey
-        *            An explicit key to use if a certificate cannot be found
-        * @param simple
-        *            Verify according to simple SAML signature profile?
-        * @throws SAMLException
-        *             Thrown if the signature cannot be verified
-        */
-       protected void verifySignature(SAMLSignedObject obj, String signerName, KeyStore ks, Key knownKey)
-                       throws SAMLException {
-               try {
-                       NDC.push("verifySignature");
-
-                       if (!obj.isSigned()) {
-                               log.error("unable to find a signature");
-                               throw new TrustException(SAMLException.RESPONDER,
-                                               "ShibPOSTProfile.verifySignature() given an unsigned object");
-                       }
-
-                       if (knownKey != null) {
-                               log.info("verifying signature with known key value, ignoring signature KeyInfo");
-                               obj.verify(knownKey);
-                               return;
-                       }
-
-                       log.info("verifying signature with embedded KeyInfo");
-                       obj.verify();
-
-                       // This is pretty painful, and this is leveraging the supposedly
-                       // automatic support in JDK 1.4.
-                       // First we have to extract the certificates from the object.
-                       Iterator certs_from_obj = obj.getX509Certificates();
-                       if (!certs_from_obj.hasNext()) {
-                               log.error("need certificates inside object to establish trust");
-                               throw new TrustException(SAMLException.RESPONDER,
-                                               "ShibPOSTProfile.verifySignature() can't find any certificates");
-                       }
-
-                       // We assume the first one in the set is the end entity cert.
-                       X509Certificate entity_cert = (X509Certificate) certs_from_obj.next();
-
-                       // Match the CN of the entity cert with the expected signer.
-                       String dname = entity_cert.getSubjectDN().getName();
-                       log.debug("found entity cert with DN: " + dname);
-                       String cname = "CN=" + signerName;
-                       if (!dname.equalsIgnoreCase(cname) && !dname.regionMatches(true, 0, cname + ',', 0, cname.length() + 1)) {
-                               log
-                                               .error("verifySignature() found a mismatch between the entity certificate's DN and the expected signer: "
-                                                               + signerName);
-                               throw new TrustException(SAMLException.RESPONDER,
-                                               "ShibPOSTProfile.verifySignature() found mismatch between entity certificate and expected signer");
-                       }
-
-                       // Prep a chain between the entity cert and the trusted roots.
-                       X509CertSelector targetConstraints = new X509CertSelector();
-                       targetConstraints.setCertificate(entity_cert);
-                       PKIXBuilderParameters params = new PKIXBuilderParameters(ks, targetConstraints);
-                       params.setMaxPathLength(-1);
-
-                       Vector certbag = new Vector();
-                       certbag.add(entity_cert);
-                       while (certs_from_obj.hasNext())
-                               certbag.add(certs_from_obj.next());
-                       CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(certbag);
-                       CertStore store = CertStore.getInstance("Collection", ccsp);
-                       params.addCertStore(store);
-
-                       // Attempt to build a path.
-                       CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
-                       PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) cpb.build(params);
-               } catch (CertPathBuilderException e) {
-                       log.error("caught a cert path builder exception: " + e.getMessage());
-                       throw new TrustException(SAMLException.RESPONDER,
-                                       "ShibPOSTProfile.verifySignature() unable to build a PKIX certificate path", e);
-               } catch (GeneralSecurityException e) {
-                       log.error("caught a general security exception: " + e.getMessage());
-                       throw new TrustException(SAMLException.RESPONDER,
-                                       "ShibPOSTProfile.verifySignature() unable to build a PKIX certificate path", e);
-               } finally {
-                       NDC.pop();
-               }
-       }
-
-       public static String getHostNameFromDN(X500Principal dn) {
-               Matcher matches = regex.matcher(dn.getName(X500Principal.RFC2253));
-               if (!matches.find() || matches.groupCount() > 1) {
-                       log.error("Unable to extract host name name from certificate subject DN.");
-                       return null;
-               }
-               return matches.group(1);
-       }
-}
index b8ab5ac..1aa7256 100644 (file)
@@ -51,7 +51,7 @@ package edu.internet2.middleware.shibboleth.common;
 
 import java.util.Collection;
 
-import org.opensaml.QName;
+import javax.xml.namespace.QName;
 import org.opensaml.SAMLException;
 import org.w3c.dom.Element;
 
index ebdb018..d4de0b1 100644 (file)
@@ -39,6 +39,7 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Random;
 
 import javax.security.auth.x500.X500Principal;
 import javax.servlet.RequestDispatcher;
@@ -52,6 +53,7 @@ import org.apache.log4j.MDC;
 import org.apache.xml.security.exceptions.XMLSecurityException;
 import org.apache.xml.security.keys.KeyInfo;
 import org.apache.xml.security.signature.XMLSignature;
+import org.opensaml.*;
 import org.opensaml.InvalidCryptoException;
 import org.opensaml.SAMLAssertion;
 import org.opensaml.SAMLAttribute;
@@ -62,7 +64,6 @@ import org.opensaml.SAMLAudienceRestrictionCondition;
 import org.opensaml.SAMLBinding;
 import org.opensaml.SAMLCondition;
 import org.opensaml.SAMLException;
-import org.opensaml.SAMLIdentifier;
 import org.opensaml.SAMLNameIdentifier;
 import org.opensaml.SAMLRequest;
 import org.opensaml.SAMLResponse;
@@ -94,9 +95,8 @@ import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException
 import edu.internet2.middleware.shibboleth.common.NameMapper;
 import edu.internet2.middleware.shibboleth.common.OriginConfig;
 import edu.internet2.middleware.shibboleth.common.RelyingParty;
-import edu.internet2.middleware.shibboleth.common.SAMLBindingFactory;
 import edu.internet2.middleware.shibboleth.common.ServiceProviderMapperException;
-import edu.internet2.middleware.shibboleth.common.ShibPOSTProfile;
+import edu.internet2.middleware.shibboleth.common.ShibBrowserProfile;
 import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
 import edu.internet2.middleware.shibboleth.common.ShibbolethOriginConfig;
 import edu.internet2.middleware.shibboleth.common.TargetFederationComponent;
@@ -124,7 +124,9 @@ public class IdPResponder extends TargetFederationComponent {
 
        private static Logger transactionLog = Logger.getLogger("Shibboleth-TRANSACTION");
        private static Logger log = Logger.getLogger(IdPResponder.class.getName());
-       private SAMLBinding binding;
+    private static Random           idgen           = new Random();
+
+    private SAMLBinding binding;
        private Semaphore throttle;
        private ArtifactMapper artifactMapper;
        private SSOProfileHandler[] profileHandlers;
@@ -148,7 +150,7 @@ public class IdPResponder extends TargetFederationComponent {
                log.info("Initializing Identity Provider.");
 
                try {
-                       binding = SAMLBindingFactory.getInstance(SAMLBinding.SAML_SOAP_HTTPS);
+                       binding = SAMLBindingFactory.getInstance(SAMLBinding.SOAP);
                        nameMapper = new NameMapper();
                        // TODO this needs to be pluggable
                        artifactMapper = new MemoryArtifactMapper();
@@ -259,7 +261,7 @@ public class IdPResponder extends TargetFederationComponent {
 
        public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
-               MDC.put("serviceId", "[IdP] " + new SAMLIdentifier().toString());
+               MDC.put("serviceId", "[IdP] " + idgen.nextInt());
                MDC.put("remoteAddr", request.getRemoteAddr());
                log.debug("Recieved a request via POST.");
 
@@ -538,7 +540,7 @@ public class IdPResponder extends TargetFederationComponent {
 
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
-               MDC.put("serviceId", "[IdP] " + new SAMLIdentifier().toString());
+               MDC.put("serviceId", "[IdP] " + idgen.nextInt());
                MDC.put("remoteAddr", request.getRemoteAddr());
                log.debug("Recieved a request via GET.");
                log.info("Handling authN request.");
@@ -766,7 +768,7 @@ public class IdPResponder extends TargetFederationComponent {
 
                                                                // If that doesn't work, try to match using
                                                                // SSL-style hostname matching
-                                                               if (ShibPOSTProfile.getHostNameFromDN(certificate.getSubjectX500Principal()).equals(
+                                                               if (ShibBrowserProfile.getHostNameFromDN(certificate.getSubjectX500Principal()).equals(
                                                                                keyInfo[k].itemKeyName(l).getKeyName())) {
                                                                        log.debug("Matched against hostname.");
                                                                        return true;
@@ -804,7 +806,13 @@ public class IdPResponder extends TargetFederationComponent {
                        binding.respond(httpResponse, samlResponse, null);
                        log.debug("Returning SAML Error Response.");
                } catch (SAMLException se) {
-                       binding.respond(httpResponse, null, exception);
+                       try {
+                binding.respond(httpResponse, null, exception);
+            }
+            catch (SAMLException e) {
+                log.error("Caught exception while responding to requester: " + e.getMessage());
+                httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error while responding.");
+            }
                        log.error("Identity Provider failed to make an error message: " + se);
                }
        }
@@ -835,7 +843,7 @@ public class IdPResponder extends TargetFederationComponent {
                                        + credential.getSubjectX500Principal().getName(X500Principal.RFC2253) + ").");
                        // Mockup old requester name for requests from < 1.2 targets
                        if (fromLegacyProvider(req)) {
-                               String legacyName = ShibPOSTProfile.getHostNameFromDN(credential.getSubjectX500Principal());
+                               String legacyName = ShibBrowserProfile.getHostNameFromDN(credential.getSubjectX500Principal());
                                if (legacyName == null) {
                                        log.error("Unable to extract legacy requester name from certificate subject.");
                                }
@@ -939,7 +947,13 @@ public class IdPResponder extends TargetFederationComponent {
                                }
                        }
 
-                       binding.respond(resp, samlResponse, ourSE);
+                       try {
+                binding.respond(resp, samlResponse, ourSE);
+            }
+            catch (SAMLException e) {
+                log.error("Caught exception while responding to requester: " + e.getMessage());
+                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error while responding.");
+            }
                }
        }
 
index e704c04..8970dec 100644 (file)
 
 package edu.internet2.middleware.shibboleth.metadata;
 
+import org.opensaml.SAMLException;
+
 /**
  * Ported from Scott Cantor's C++ interfaces
  * 
  * @author Walter Hoehn (wassa@columbia.edu)
  */
-public class MetadataException extends Exception {
+public class MetadataException extends SAMLException {
 
        public MetadataException(String message) {
                super(message);
index 8cb96be..992c860 100644 (file)
@@ -151,9 +151,9 @@ public class AttributeRequestor {
                // ShibBinding will extract URLs from the Metadata and build
                // parameters so SAML can create the session. It also interfaces
                // to Trust to verify that any signed objects have trusted signatures.
-               ShibBinding binding = new ShibBinding(session.getApplicationId());
                SAMLResponse response = null;
                try {
+            ShibBinding binding = new ShibBinding(session.getApplicationId());
                        response = binding.send(request,aa,null,null);
                } catch (SAMLException e) {;} // response will be null
                if (response==null) {
index 0610bd5..3441df1 100644 (file)
@@ -42,7 +42,6 @@
 package edu.internet2.middleware.shibboleth.serviceprovider;
 
 import java.io.IOException;
-import java.util.Collections;
 
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
@@ -50,11 +49,10 @@ import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import org.opensaml.SAMLAssertion;
-import org.opensaml.SAMLAuthenticationStatement;
+
 import org.opensaml.SAMLException;
-import org.opensaml.SAMLPOSTProfile;
-import org.opensaml.SAMLResponse;
+import org.opensaml.SAMLBrowserProfile;
+import org.opensaml.SAMLBrowserProfile.BrowserProfileResponse;
 import org.w3c.dom.Element;
 import org.apache.log4j.FileAppender;
 import org.apache.log4j.Layout;
@@ -67,6 +65,7 @@ import x0.maceShibbolethTargetConfig1.SessionsDocument.Sessions;
 
 import edu.internet2.middleware.commons.log4j.ThreadLocalAppender;
 import edu.internet2.middleware.shibboleth.common.Credentials;
+import edu.internet2.middleware.shibboleth.common.ShibBrowserProfile;
 import edu.internet2.middleware.shibboleth.metadata.MetadataException;
 import edu.internet2.middleware.shibboleth.resource.AuthenticationFilter;
 import edu.internet2.middleware.shibboleth.serviceprovider.ServiceProviderConfig.ApplicationInfo;
@@ -82,8 +81,8 @@ public class AuthenticationAssertionConsumerServlet extends HttpServlet {
        
        private static ServiceProviderContext context = ServiceProviderContext.getInstance();
        
-       private Element                 configuration;
-       private Credentials                             credentials;
+       private Element                 configuration = null;
+       private Credentials             credentials = null;
        
        public static final String SESSIONPARM =
            "ShibbolethSessionId";
@@ -129,7 +128,6 @@ public class AuthenticationAssertionConsumerServlet extends HttpServlet {
                
                ServletContextInitializer.initServiceProvider(servletContext);
                AuthenticationFilter.setFilterSupport(new FilterSupportImpl());
-               
        }
 
 
@@ -154,12 +152,11 @@ public class AuthenticationAssertionConsumerServlet extends HttpServlet {
             String ipaddr = request.getRemoteAddr();
             
             // URL of Resource that triggered authorization
+            // XXX: I added support to the profile for extracting TARGET, but
+            // it's not too critical in Java since you can grab it easily anyway.
+            // Might be better in the 2.0 future though, since the bindings get trickier.
             String target = request.getParameter("TARGET");
             
-            // Bin64 encoded SAML Authentication Assertion from HS
-            String assertparm = request.getParameter("SAMLResponse");
-            byte [] bin64Assertion = assertparm.getBytes();
-            
             // Map the Resource URL into an <Application>
             String applicationId = config.mapRequest(target);
             ApplicationInfo appinfo = config.getApplication(applicationId);
@@ -181,29 +178,36 @@ public class AuthenticationAssertionConsumerServlet extends HttpServlet {
             log.debug("Authentication received from "+ipaddr+" for "+target+
                         "(application:"+applicationId+") (Provider:"+providerId+")");
 
-            String sessionId = createSessionFromPost(ipaddr, bin64Assertion, applicationId, shireURL, providerId, null);
+            String sessionId = createSessionFromPost(ipaddr, request, applicationId, shireURL, providerId, null);
             
             Cookie cookie = new Cookie("ShibbolethSPSession",sessionId);
             response.addCookie(cookie);
             
             try {
                 response.sendRedirect(target+"?"+SESSIONPARM+"="+sessionId);
-            } catch (IOException e) {}
-        } catch (SAMLException e) {
-               log.error("Authentication Assertion had invalid format.");
-               try {
-                response.sendRedirect("/shibboleth/shireError.html");
-            } catch (IOException e1) {}
+            }
+            catch (IOException e) {
+            }
         }
         catch (MetadataException e) {
-               log.error("Authentication Assertion source not found in Metadata.");
-               try {
+            log.error("Authentication Assertion source not found in Metadata.");
+            try {
+                response.sendRedirect("/shibboleth/shireError.html");
+            }
+            catch (IOException e1) {
+            }
+        }
+        catch (SAMLException e) {
+            log.error("Authentication Assertion had invalid format.");
+            try {
                 response.sendRedirect("/shibboleth/shireError.html");
-            } catch (IOException e1) {}
-        } finally {
+            }
+            catch (IOException e1) {
+            }
+        }
+        finally {
             ServletContextInitializer.finishService(request,response);
         }
-
        }
        
     /**
@@ -216,41 +220,34 @@ public class AuthenticationAssertionConsumerServlet extends HttpServlet {
      * @param providerId Our Entity name
      * @return random key of Session
      * @throws SAMLException
-     * @throws MetadataException
      */
     public static 
     String createSessionFromPost(
             String ipaddr, 
-            byte[] bin64Assertion, 
+            HttpServletRequest req, 
             String applicationId, 
             String shireURL, 
             String providerId,
             String emptySessionId
             ) 
-    throws SAMLException, MetadataException {
+    throws SAMLException {
         String sessionid=null;
         StringBuffer pproviderId = // Get back Origin Entity name from SAML
             new StringBuffer();
         String[] audiences = new String[1];
         audiences[0]=providerId;
         
-        SAMLResponse samldata = null;  
-        SAMLAssertion assertion = null;
-        SAMLAuthenticationStatement authstmt = null;
-        ShibPOSTProfile profile = new ShibPOSTProfile(applicationId);
-        samldata = profile.accept(
-                bin64Assertion, // Assertion from POST of Form field
-                shireURL,   // My URL (Why??)
-                60, 
-                audiences,  // My "Provider" (Entity) ID
-                pproviderId // HS "Provider" (Entity) ID returned
+        ShibBrowserProfile profile = new ShibBrowserProfile(applicationId);
+        BrowserProfileResponse samldata = profile.receive(
+                pproviderId,
+                req,
+                shireURL,   // My URL (Why??) To prevent attackers from redirecting messages. 
+                SAMLBrowserProfile.PROFILE_POST,    // TODO: support both profiles 
+                context.getReplayCache(),
+                null
         );
         
-        assertion = SAMLPOSTProfile.getSSOAssertion(samldata,
-                Collections.singleton(providerId));
-        authstmt = SAMLPOSTProfile.getSSOStatement(assertion);
-        
-
+        // TODO: Audience/condition checking is now the profile caller's job.
         
         // The Authentication Assertion gets placed in a newly created
         // Session object. Later, someone will get an Attribute Assertion
@@ -261,8 +258,8 @@ public class AuthenticationAssertionConsumerServlet extends HttpServlet {
                 applicationId, 
                 ipaddr, 
                 pproviderId.toString(), 
-                assertion, 
-                authstmt,
+                samldata.assertion, 
+                samldata.authnStatement,
                 emptySessionId);
         
         // Very agressive attribute fetch rule 
index 9c54f5e..68ca323 100644 (file)
@@ -17,13 +17,14 @@ package edu.internet2.middleware.shibboleth.serviceprovider;
 
 import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.opensaml.SAMLException;
 
 import x0.maceShibbolethTargetConfig1.SessionsDocument.Sessions;
 
 import edu.internet2.middleware.shibboleth.common.AAP;
 import edu.internet2.middleware.shibboleth.common.AttributeRule;
-import edu.internet2.middleware.shibboleth.metadata.MetadataException;
 import edu.internet2.middleware.shibboleth.resource.FilterSupport;
 import edu.internet2.middleware.shibboleth.serviceprovider.ServiceProviderConfig.ApplicationInfo;
 
@@ -140,7 +141,7 @@ public class FilterSupportImpl implements FilterSupport {
 
     /**
      * @param ipaddr
-     * @param bin64Assertion
+     * @param request
      * @param applicationId
      * @param shireURL
      * @param providerId
@@ -148,7 +149,7 @@ public class FilterSupportImpl implements FilterSupport {
      */
     public String createSessionFromPost(
             String ipaddr, 
-            byte[] bin64Assertion, 
+            HttpServletRequest request, 
             String applicationId, 
             String shireURL, 
             String providerId,
@@ -156,11 +157,9 @@ public class FilterSupportImpl implements FilterSupport {
         String sessionid;
         try {
             sessionid = AuthenticationAssertionConsumerServlet.createSessionFromPost(
-                    ipaddr, bin64Assertion, applicationId, shireURL, providerId,emptySessionId);
+                    ipaddr, request, applicationId, shireURL, providerId,emptySessionId);
         } catch (SAMLException e) {
             return null;
-        } catch (MetadataException e) {
-            return null;
         }
         return sessionid;
     }
index 17a4241..99a6ea2 100644 (file)
@@ -874,7 +874,7 @@ public class ServiceProviderConfig {
         * can fetch the XMLBean by calling getApplicationConf() and 
         * query their value directly.
         */
-       class ApplicationInfo 
+       public class ApplicationInfo 
                implements EntityLocator, ITrust {
                
                private Application applicationConfig;
index 4c53f25..3af0360 100644 (file)
  */
 package edu.internet2.middleware.shibboleth.serviceprovider;
 
+import org.opensaml.NoSuchProviderException;
+import org.opensaml.ReplayCache;
+import org.opensaml.ReplayCacheFactory;
+
 /**
  * Unique object through which all Service Provider objects and collections
  * are found. Obtain a reference to this object by calling the static
@@ -99,7 +103,8 @@ public class ServiceProviderContext {
         * wanted to load and configure the Session Manager in Spring.
         */
        private SessionManager sessionManager = null;
-       
+
+       private ReplayCache replayCache = null;
        
        private ThreadLocal requestContext = new ThreadLocal();
                public void setRequestContext(RequestTracker trk) {
@@ -119,7 +124,7 @@ public class ServiceProviderContext {
        
        // property accessor methods
 
-       public SessionManager getSessionManager() {
+       public synchronized SessionManager getSessionManager() {
            // deferred allocation, since sessionManger needs a reference
            // back to context.
            if (sessionManager==null)
@@ -127,6 +132,18 @@ public class ServiceProviderContext {
                return sessionManager;
        }
 
+    // TODO: Make this pluggable / configurable
+    public synchronized ReplayCache getReplayCache() {
+        if (replayCache == null) {
+            try {
+                replayCache = ReplayCacheFactory.getInstance();
+            }
+            catch (NoSuchProviderException e) {
+            }
+        }
+        return replayCache;
+    }
+    
        public ServiceProviderConfig getServiceProviderConfig() {
                return serviceProviderConfig;
        }
index ef7abe5..8a1fada 100644 (file)
@@ -25,16 +25,8 @@ package edu.internet2.middleware.shibboleth.serviceprovider;
 import java.util.Iterator;
 
 import org.apache.log4j.Logger;
-import org.opensaml.QName;
-import org.opensaml.SAMLAssertion;
-import org.opensaml.SAMLAuthorityBinding;
-import org.opensaml.SAMLBinding;
-import org.opensaml.SAMLException;
-import org.opensaml.SAMLRequest;
-import org.opensaml.SAMLResponse;
-import org.opensaml.SAMLSOAPBinding;
-import org.opensaml.TrustException;
-import org.opensaml.XML;
+import javax.xml.namespace.QName;
+import org.opensaml.*;
 
 import edu.internet2.middleware.shibboleth.metadata.AttributeAuthorityRole;
 import edu.internet2.middleware.shibboleth.metadata.Endpoint;
@@ -65,7 +57,7 @@ public class ShibBinding {
        private static ServiceProviderContext context = ServiceProviderContext.getInstance();
        
        private String applicationId = null;
-       private SAMLBinding sbinding = new SAMLSOAPBinding();
+       private SAMLBinding sbinding = null;
        
        /**
         * While the C++ constructor takes iterators over the Trust and 
@@ -73,11 +65,13 @@ public class ShibBinding {
         * that contains them.
         * 
         * @param applicationId
+        * @throws NoSuchProviderException
         */
        public 
        ShibBinding(
-                       String applicationId) {
+                       String applicationId) throws NoSuchProviderException {
                this.applicationId=applicationId;
+        sbinding = SAMLBindingFactory.getInstance(SAMLBinding.SOAP);
        }
 
        /**
@@ -126,7 +120,7 @@ public class ShibBinding {
                                        String bindingString = binding.getBinding();
                                        if (!bindingString.equals(prevBinding)) {
                                                prevBinding = bindingString;
-                                               resp=sbinding.send(binding,req);
+                                               resp=sbinding.send(binding.getLocation(),req);
                                        }
                                        validateResponseSignatures(role, appinfo, resp);
                                        return resp;
@@ -155,18 +149,8 @@ public class ShibBinding {
                
                log.debug("AA is at "+endpoint.getLocation());
                
-               /*
-                * The "address" of the request is a location URL embedded in
-                * a SAMLAuthorityBinding object. Send the request and get the
-                * response.
-                */
                try {
-                       SAMLAuthorityBinding authbind = 
-                               new SAMLAuthorityBinding(
-                                               endpoint.getBinding(),
-                                               endpoint.getLocation(),
-                                               new QName(XML.SAMLP_NS,"AttributeQuery"));
-                       resp=sbinding.send(authbind,req);
+                       resp=sbinding.send(endpoint.getLocation(),req);
                        log.debug("AA returned Attribute Assertion");
                        validateResponseSignatures(role, appinfo, resp);
                        return resp;
diff --git a/src/edu/internet2/middleware/shibboleth/serviceprovider/ShibPOSTProfile.java b/src/edu/internet2/middleware/shibboleth/serviceprovider/ShibPOSTProfile.java
deleted file mode 100644 (file)
index 5796819..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * ShibPOSTProfile.java
- * 
- * ServiceProvider (Target) front end to the SAMLPOSTProfile
- * function. 
- * 
- * The ...common.ShibPOSTProfile class contained a 
- * prototype Target-side accept() method. However, it did
- * had not been used, did not exactly track the C++ logic, 
- * and was missing the Metadata interface. Yet that code
- * was being used for the Origin. So it seemed safer to
- * build a separate Target-only module here borrowing code
- * from the other module that was complete but tracking as
- * closely as possible the C++ logic.
- * 
- * --------------------
- * 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.security.GeneralSecurityException;
-import java.security.Key;
-import java.security.KeyStore;
-import java.security.cert.CertPathBuilder;
-import java.security.cert.CertPathBuilderException;
-import java.security.cert.CertStore;
-import java.security.cert.CollectionCertStoreParameters;
-import java.security.cert.PKIXBuilderParameters;
-import java.security.cert.PKIXCertPathBuilderResult;
-import java.security.cert.X509CertSelector;
-import java.security.cert.X509Certificate;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Vector;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.NDC;
-import org.opensaml.SAMLAssertion;
-import org.opensaml.SAMLAuthenticationStatement;
-import org.opensaml.SAMLException;
-import org.opensaml.SAMLPOSTProfile;
-import org.opensaml.SAMLResponse;
-import org.opensaml.SAMLSignedObject;
-import org.opensaml.TrustException;
-
-import edu.internet2.middleware.shibboleth.common.XML;
-import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
-import edu.internet2.middleware.shibboleth.metadata.IDPProviderRole;
-import edu.internet2.middleware.shibboleth.metadata.MetadataException;
-import edu.internet2.middleware.shibboleth.metadata.ProviderRole;
-import edu.internet2.middleware.shibboleth.serviceprovider.ServiceProviderConfig.ApplicationInfo;
-
-/**
- * @author Howard Gilbert
- */
-public class ShibPOSTProfile {
-
-       
-       private static Logger log = Logger.getLogger(ShibPOSTProfile.class);
-       private static ServiceProviderContext context = ServiceProviderContext.getInstance();
-       
-       /*
-        * The C++ class is constructed by passing enumerations of Metadata
-        * providers, trust providers, etc from the <Application>. However,
-        * those providers can change dynamically. This version only keeps
-        * the applicationId that can be used to fetch the ApplicationInfo 
-        * object and, from it, get the collections of provider plugins.
-        */
-       private String applicationId = null;
-       
-       /**
-        * Identify the <Application> from which to get plugins.
-        * 
-        * @param applicationId 
-        */
-       public ShibPOSTProfile(String applicationId) {
-               this.applicationId = applicationId;
-       }
-       
-       // Pass through to SAMLPOSTProfile
-    public static SAMLAssertion getSSOAssertion(SAMLResponse r, Collection audiences)
-       throws SAMLException {
-       return SAMLPOSTProfile.getSSOAssertion(r,audiences);
-    }
-       
-    // Pass through to SAMLPOSTProfile
-    public static SAMLAuthenticationStatement getSSOStatement(SAMLAssertion a)
-       throws SAMLException {
-       return SAMLPOSTProfile.getSSOStatement(a);
-    }
-    
-    /**
-     * Favor AuthnStatement Subject NameQualifer, but use Issuer if need be
-     * @param r SAMLResponse
-     * @return NameQualifier or Issuer
-     */
-    public String getProviderId(SAMLResponse r) {
-       String providerId=null;
-       Iterator ia = r.getAssertions();
-       while (ia.hasNext()) {
-               SAMLAssertion a = (SAMLAssertion) ia.next();
-               providerId = a.getIssuer();
-               Iterator is = a.getStatements();
-               while (is.hasNext()) {
-                       SAMLAuthenticationStatement as = 
-                               (SAMLAuthenticationStatement) is.next();
-                       if (as!=null) {
-                                String ret = as.getSubject().getName().getNameQualifier();
-                                if (ret!=null)
-                                       return ret;
-                       }
-               }
-       }
-               return providerId;
-       
-    }
-    
-    /**
-     * Process the Base64 encoded SAML Authentication Assertion
-     * from the Form Field filled in by HS and transmitted by the
-     * Browser.
-     * 
-     * @param buf Array of bytes from the form
-     * @param recipient 
-     * @param ttlSeconds
-     * @param audiences
-     * @param pproviderId  StringBuffer secondary return of providerId
-     * @return SAMLResponse encoded in buffer
-     * @throws SAMLException if SAML Assertion structure is invalid
-     * @throws MetadataException if Origin site missing from metadata
-     */
-    SAMLResponse accept(
-               byte[]buf, 
-                       String recipient, 
-                       int ttlSeconds, 
-                       String[] audiences,
-                       StringBuffer pproviderId
-                       ) throws SAMLException, MetadataException {
-       
-       String providerId = null;
-       pproviderId.setLength(0);
-       SAMLAssertion assertion = null;
-       SAMLAuthenticationStatement sso = null;
-       SAMLResponse r = null;
-       
-       // Let SAML do all the decoding and parsing
-               r = SAMLPOSTProfile.accept(buf,recipient,ttlSeconds,false);
-               
-               // Drill down through the objects
-               assertion = getSSOAssertion(r,Arrays.asList(audiences));
-               sso = getSSOStatement(assertion);
-               
-               // Check recipient and timeout, but not the signature
-               // throws SAMLException if checks fail
-               SAMLPOSTProfile.process(r,recipient,ttlSeconds);
-               
-               /*
-                * Now find the Metadata for the Entity that send this assertion.
-                * From the C++, look first for issuer, then namequalifier
-                */
-               EntityDescriptor entity = null;
-               String issuer = assertion.getIssuer();
-               String qualifier = sso.getSubject().getName().getNameQualifier();
-               ServiceProviderConfig config = context.getServiceProviderConfig();
-               ApplicationInfo appinfo = config.getApplication(applicationId);
-               
-               
-               entity = appinfo.getEntityDescriptor(issuer);
-               providerId=issuer;
-               if (entity==null) {
-                   providerId=qualifier;
-                       entity= appinfo.getEntityDescriptor(qualifier);
-               }
-               if (entity==null) {
-                       log.error("assertion issuer not found in metadata(Issuer ="+
-                                       issuer+", NameQualifier="+qualifier);
-                       throw new MetadataException("ShibPOSTProfile accept() metadata lookup failed, unable to process assertion");
-               }
-               pproviderId.append(providerId);
-               
-               // From the Metadata, get the HS and from it the key
-               ProviderRole[] roles = entity.getRoles();
-               for (int i=0;i<roles.length;i++) {
-                       ProviderRole role = roles[i];
-                       if (role instanceof IDPProviderRole) {
-                               if (role.hasSupport(XML.SHIB_NS)) {
-                                       ;
-                               }
-                       }
-               }
-               
-               return r;
-    }
-    
-    /**
-     * Given a key from Trust associated with a HS Role from a Metadata Entity Descriptor,
-     * verify the SAML Signature.
-     * 
-     * <p>Note: This routine was copied from ...common.ShibPOSTProfile. Will be changed
-     * as needed.</p>
-     * 
-     * @param obj           A signed SAMLObject
-     * @param signerName    The signer's ID
-     * @param ks            KeyStore [TrustProvider abstraction violation, may change]
-     * @param knownKey      Key from the Trust entry associated with the signer's Metadata
-     * @throws SAMLException
-     */
-    static void verifySignature(
-            SAMLSignedObject obj, 
-            String signerName, 
-            KeyStore ks, 
-            Key knownKey)
-       throws SAMLException {
-       try {
-               NDC.push("verifySignature");
-               
-               if (!obj.isSigned()) {
-                       log.error("unable to find a signature");
-                       throw new TrustException(SAMLException.RESPONDER,
-                       "ShibPOSTProfile.verifySignature() given an unsigned object");
-               }
-               
-               if (knownKey != null) {
-                       log.info("verifying signature with known key value, ignoring signature KeyInfo");
-                       obj.verify(knownKey);
-                       return;
-               }
-               
-               
-               log.info("verifying signature with embedded KeyInfo");
-               obj.verify();
-               
-               // This is pretty painful, and this is leveraging the supposedly
-               // automatic support in JDK 1.4.
-               // First we have to extract the certificates from the object.
-               Iterator certs_from_obj = obj.getX509Certificates();
-               if (!certs_from_obj.hasNext()) {
-                       log.error("need certificates inside object to establish trust");
-                       throw new TrustException(SAMLException.RESPONDER,
-                       "ShibPOSTProfile.verifySignature() can't find any certificates");
-               }
-               
-               // We assume the first one in the set is the end entity cert.
-               X509Certificate entity_cert = (X509Certificate) certs_from_obj.next();
-               
-               // Match the CN of the entity cert with the expected signer.
-               String dname = entity_cert.getSubjectDN().getName();
-               log.debug("found entity cert with DN: " + dname);
-               String cname = "CN=" + signerName;
-               if (!dname.equalsIgnoreCase(cname) && !dname.regionMatches(true, 0, cname + ',', 0, cname.length() + 1)) {
-                       log
-                               .error("verifySignature() found a mismatch between the entity certificate's DN and the expected signer: "
-                                               + signerName);
-                       throw new TrustException(SAMLException.RESPONDER,
-                       "ShibPOSTProfile.verifySignature() found mismatch between entity certificate and expected signer");
-               }
-               
-               // Prep a chain between the entity cert and the trusted roots.
-               X509CertSelector targetConstraints = new X509CertSelector();
-               targetConstraints.setCertificate(entity_cert);
-               PKIXBuilderParameters params = new PKIXBuilderParameters(ks, targetConstraints);
-               params.setMaxPathLength(-1);
-               
-               Vector certbag = new Vector();
-               certbag.add(entity_cert);
-               while (certs_from_obj.hasNext())
-                       certbag.add(certs_from_obj.next());
-               CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(certbag);
-               CertStore store = CertStore.getInstance("Collection", ccsp);
-               params.addCertStore(store);
-               
-               // Attempt to build a path.
-               CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
-               PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) cpb.build(params);
-       } catch (CertPathBuilderException e) {
-               log.error("caught a cert path builder exception: " + e.getMessage());
-               throw new TrustException(SAMLException.RESPONDER,
-                               "ShibPOSTProfile.verifySignature() unable to build a PKIX certificate path", e);
-       } catch (GeneralSecurityException e) {
-               log.error("caught a general security exception: " + e.getMessage());
-               throw new TrustException(SAMLException.RESPONDER,
-                               "ShibPOSTProfile.verifySignature() unable to build a PKIX certificate path", e);
-       } finally {
-               NDC.pop();
-       }
-    }
-    
-}
index fdd24a7..ecde6c7 100644 (file)
@@ -51,6 +51,8 @@ import javax.servlet.http.HttpServletResponseWrapper;
 
 import org.apache.log4j.Logger;
 import org.apache.log4j.MDC;
+import org.opensaml.SAMLConfig;
+import org.opensaml.SAMLException;
 import org.opensaml.SAMLIdentifier;
 
 /**
@@ -62,12 +64,12 @@ import org.opensaml.SAMLIdentifier;
 public class SAML1_0to1_1ConversionFilter implements Filter {
 
        private static Logger log = Logger.getLogger(SAML1_0to1_1ConversionFilter.class.getName());
+    private SAMLIdentifier idgen = SAMLConfig.instance().getDefaultIDProvider();
 
        /*
         * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
         */
        public void init(FilterConfig config) throws ServletException {
-
        }
 
        /*
@@ -319,7 +321,12 @@ public class SAML1_0to1_1ConversionFilter implements Filter {
                                int start = matcher.start(2);
                                int end = matcher.end(2);
                                buff.append(input.subSequence(0, start));
-                               buff.append(new SAMLIdentifier().toString());
+                               try {
+                    buff.append(idgen.getIdentifier());
+                }
+                catch (SAMLException e) {
+                    throw new IOException("Unable to obtain a new SAML message ID from provider");
+                }
                                buff.append(input.substring(end));
                                input = buff.toString();
                        }
index 640b362..a5bb002 100644 (file)
@@ -34,7 +34,7 @@ import org.apache.log4j.BasicConfigurator;
 import org.apache.log4j.Level;
 import org.apache.log4j.Logger;
 
-import edu.internet2.middleware.shibboleth.common.ShibPOSTProfile;
+import edu.internet2.middleware.shibboleth.common.ShibBrowserProfile;
 
 /**
  * Validation suite for hack to pull hostnames out of a subject DN.
@@ -73,7 +73,7 @@ public class DNHostNameExtractionTests extends TestCase {
        public void testBasicExtraction() {
 
                try {
-                       assertEquals("Round-trip handle validation failed on DN.", ShibPOSTProfile
+                       assertEquals("Round-trip handle validation failed on DN.", ShibBrowserProfile
                                        .getHostNameFromDN(new X500Principal(dn1)), "wayf.internet2.edu");
 
                } catch (Exception e) {
@@ -84,7 +84,7 @@ public class DNHostNameExtractionTests extends TestCase {
        public void testExtractionWithLowerCaseAttrName() {
 
                try {
-                       assertEquals("Round-trip handle validation failed on DN.", ShibPOSTProfile
+                       assertEquals("Round-trip handle validation failed on DN.", ShibBrowserProfile
                                        .getHostNameFromDN(new X500Principal(dn2)), "wayf.internet2.edu");
 
                } catch (Exception e) {
@@ -95,7 +95,7 @@ public class DNHostNameExtractionTests extends TestCase {
        public void testExtractionWithMultipleCNs() {
 
                try {
-                       assertEquals("Round-trip handle validation failed on DN.", ShibPOSTProfile
+                       assertEquals("Round-trip handle validation failed on DN.", ShibBrowserProfile
                                        .getHostNameFromDN(new X500Principal(dn4)), "wayf.internet2.edu");
 
                } catch (Exception e) {