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;
}
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 {
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;
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;
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;
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;
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;
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();
nameMapper = new NameMapper();
loadConfiguration();
- binding = SAMLBindingFactory.getInstance(SAMLBinding.SAML_SOAP_HTTPS);
+ binding = SAMLBindingFactory.getInstance(SAMLBinding.SOAP);
log.info("Attribute Authority initialization complete.");
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.");
+ 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.");
}
}
}
- 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.");
+ }
}
}
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);
}
}
}
//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;
package edu.internet2.middleware.shibboleth.common;
-import org.opensaml.QName;
+import javax.xml.namespace.QName;
/**
* @author Walter Hoehn
import java.util.Collection;
-import org.opensaml.QName;
+import javax.xml.namespace.QName;
import org.opensaml.SAMLException;
import org.w3c.dom.Element;
+++ /dev/null
-/*
- * The Shibboleth License, Version 1.
- * Copyright (c) 2002
- * University Corporation for Advanced Internet Development, Inc.
- * All rights reserved
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution, if any, must include
- * the following acknowledgment: "This product includes software developed by
- * the University Corporation for Advanced Internet Development
- * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
- * may appear in the software itself, if and wherever such third-party
- * acknowledgments normally appear.
- *
- * Neither the name of Shibboleth nor the names of its contributors, nor
- * Internet2, nor the University Corporation for Advanced Internet Development,
- * Inc., nor UCAID may be used to endorse or promote products derived from this
- * software without specific prior written permission. For written permission,
- * please contact shibboleth@shibboleth.org
- *
- * Products derived from this software may not be called Shibboleth, Internet2,
- * UCAID, or the University Corporation for Advanced Internet Development, nor
- * may Shibboleth appear in their name, without prior written permission of the
- * University Corporation for Advanced Internet Development.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
- * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
- * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package edu.internet2.middleware.shibboleth.common;
-
-import 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();
- }
-}
-
--- /dev/null
+/*
+ * The Shibboleth License, Version 1. Copyright (c) 2002 University Corporation for Advanced Internet Development, Inc.
+ * All rights reserved Redistribution and use in source and binary forms, with or without modification, are permitted
+ * provided that the following conditions are met: Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution, if any, must include the following acknowledgment: "This product includes
+ * software developed by the University Corporation for Advanced Internet Development <http://www.ucaid.edu> Internet2
+ * Project. Alternately, this acknowledegement may appear in the software itself, if and wherever such third-party
+ * acknowledgments normally appear. Neither the name of Shibboleth nor the names of its contributors, nor Internet2,
+ * nor the University Corporation for Advanced Internet Development, Inc., nor UCAID may be used to endorse or promote
+ * products derived from this software without specific prior written permission. For written permission, please
+ * contact shibboleth@shibboleth.org Products derived from this software may not be called Shibboleth, Internet2,
+ * UCAID, or the University Corporation for Advanced Internet Development, nor may Shibboleth appear in their name,
+ * without prior written permission of the University Corporation for Advanced Internet Development. THIS SOFTWARE IS
+ * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+ * NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS
+ * WITH LICENSEE. IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY CORPORATION FOR ADVANCED
+ * INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package edu.internet2.middleware.shibboleth.common;
+
+import java.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;
+ }
+}
+++ /dev/null
-/*
- * The Shibboleth License, Version 1. Copyright (c) 2002 University Corporation for Advanced Internet Development, Inc.
- * All rights reserved Redistribution and use in source and binary forms, with or without modification, are permitted
- * provided that the following conditions are met: Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the
- * above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other
- * materials provided with the distribution, if any, must include the following acknowledgment: "This product includes
- * software developed by the University Corporation for Advanced Internet Development <http://www.ucaid.edu> Internet2
- * Project. Alternately, this acknowledegement may appear in the software itself, if and wherever such third-party
- * acknowledgments normally appear. Neither the name of Shibboleth nor the names of its contributors, nor Internet2,
- * nor the University Corporation for Advanced Internet Development, Inc., nor UCAID may be used to endorse or promote
- * products derived from this software without specific prior written permission. For written permission, please
- * contact shibboleth@shibboleth.org Products derived from this software may not be called Shibboleth, Internet2,
- * UCAID, or the University Corporation for Advanced Internet Development, nor may Shibboleth appear in their name,
- * without prior written permission of the University Corporation for Advanced Internet Development. THIS SOFTWARE IS
- * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
- * NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS
- * WITH LICENSEE. IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY CORPORATION FOR ADVANCED
- * INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package edu.internet2.middleware.shibboleth.common;
-
-import java.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);
- }
-}
import java.util.Collection;
-import org.opensaml.QName;
+import javax.xml.namespace.QName;
import org.opensaml.SAMLException;
import org.w3c.dom.Element;
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;
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;
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;
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;
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;
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();
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.");
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.");
// 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;
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);
}
}
+ 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.");
}
}
}
- 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.");
+ }
}
}
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);
// 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) {
package edu.internet2.middleware.shibboleth.serviceprovider;
import java.io.IOException;
-import java.util.Collections;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
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;
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;
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";
ServletContextInitializer.initServiceProvider(servletContext);
AuthenticationFilter.setFilterSupport(new FilterSupportImpl());
-
}
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);
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);
}
-
}
/**
* @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
applicationId,
ipaddr,
pproviderId.toString(),
- assertion,
- authstmt,
+ samldata.assertion,
+ samldata.authnStatement,
emptySessionId);
// Very agressive attribute fetch rule
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;
/**
* @param ipaddr
- * @param bin64Assertion
+ * @param request
* @param applicationId
* @param shireURL
* @param providerId
*/
public String createSessionFromPost(
String ipaddr,
- byte[] bin64Assertion,
+ HttpServletRequest request,
String applicationId,
String shireURL,
String providerId,
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;
}
* can fetch the XMLBean by calling getApplicationConf() and
* query their value directly.
*/
- class ApplicationInfo
+ public class ApplicationInfo
implements EntityLocator, ITrust {
private Application applicationConfig;
*/
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
* 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) {
// property accessor methods
- public SessionManager getSessionManager() {
+ public synchronized SessionManager getSessionManager() {
// deferred allocation, since sessionManger needs a reference
// back to context.
if (sessionManager==null)
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;
}
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;
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
* that contains them.
*
* @param applicationId
+ * @throws NoSuchProviderException
*/
public
ShibBinding(
- String applicationId) {
+ String applicationId) throws NoSuchProviderException {
this.applicationId=applicationId;
+ sbinding = SAMLBindingFactory.getInstance(SAMLBinding.SOAP);
}
/**
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;
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;
+++ /dev/null
-/*
- * 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();
- }
- }
-
-}
import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
+import org.opensaml.SAMLConfig;
+import org.opensaml.SAMLException;
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 {
-
}
/*
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();
}
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.
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) {
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) {
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) {