--- /dev/null
+/*
+ * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.] Licensed under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in
+ * writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ * OF ANY KIND, either express or implied. See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.internet2.middleware.shibboleth.idp;
+
+import java.net.URI;
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.apache.log4j.Logger;
+import org.apache.xml.security.signature.XMLSignature;
+import org.opensaml.InvalidCryptoException;
+import org.opensaml.SAMLAssertion;
+import org.opensaml.SAMLAttribute;
+import org.opensaml.SAMLException;
+import org.opensaml.SAMLResponse;
+import org.opensaml.saml2.metadata.EntitiesDescriptor;
+import org.opensaml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml2.metadata.RoleDescriptor;
+import org.opensaml.saml2.metadata.provider.ChainingMetadataProvider;
+import org.opensaml.saml2.metadata.provider.MetadataFilter;
+import org.opensaml.saml2.metadata.provider.MetadataProvider;
+import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.opensaml.security.TrustEngine;
+import org.opensaml.security.X509EntityCredential;
+import org.opensaml.xml.XMLObject;
+import org.w3c.dom.Element;
+
+import edu.internet2.middleware.shibboleth.aa.AAAttribute;
+import edu.internet2.middleware.shibboleth.aa.AAException;
+import edu.internet2.middleware.shibboleth.aa.arp.ArpEngine;
+import edu.internet2.middleware.shibboleth.aa.arp.ArpProcessingException;
+import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeResolver;
+import edu.internet2.middleware.shibboleth.artifact.ArtifactMapper;
+import edu.internet2.middleware.shibboleth.common.Credential;
+import edu.internet2.middleware.shibboleth.common.RelyingParty;
+import edu.internet2.middleware.shibboleth.common.RelyingPartyMapper;
+import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
+import edu.internet2.middleware.shibboleth.common.provider.ShibbolethTrustEngine;
+import edu.internet2.middleware.shibboleth.metadata.MetadataProviderFactory;
+
+/**
+ * IdPProtocolSupport implementation that offers functionality that is not specific to a particular request.
+ *
+ * @author Walter Hoehn
+ */
+public class GeneralProtocolSupport implements IdPProtocolSupport, MetadataProvider {
+
+ private static Logger log = Logger.getLogger(GeneralProtocolSupport.class.getName());
+ private Logger transactionLog;
+ private IdPConfig config;
+ private RelyingPartyMapper rpMapper;
+ private ArpEngine arpEngine;
+ private AttributeResolver resolver;
+ private ArtifactMapper artifactMapper;
+ private Semaphore throttle;
+ private TrustEngine<X509EntityCredential> trust = new ShibbolethTrustEngine();
+ private ChainingMetadataProvider wrappedMetadataProvider = new ChainingMetadataProvider();
+
+ GeneralProtocolSupport(IdPConfig config, Logger transactionLog, RelyingPartyMapper spMapper, ArpEngine arpEngine,
+ AttributeResolver resolver, ArtifactMapper artifactMapper) throws ShibbolethConfigurationException {
+
+ this.transactionLog = transactionLog;
+ this.config = config;
+ this.rpMapper = spMapper;
+ spMapper.setMetadata(this);
+ this.arpEngine = arpEngine;
+ this.resolver = resolver;
+ this.artifactMapper = artifactMapper;
+
+ // Load a semaphore that throttles how many requests the IdP will handle at once
+ throttle = new Semaphore(config.getMaxThreads());
+ }
+
+ public Logger getTransactionLog() {
+
+ return transactionLog;
+ }
+
+ public IdPConfig getIdPConfig() {
+
+ return config;
+ }
+
+ public RelyingPartyMapper getRelyingPartyMapper() {
+
+ return rpMapper;
+ }
+
+ public void signAssertions(SAMLAssertion[] assertions, RelyingParty relyingParty) throws InvalidCryptoException,
+ SAMLException {
+
+ if (relyingParty.getIdentityProvider().getSigningCredential() == null
+ || relyingParty.getIdentityProvider().getSigningCredential().getPrivateKey() == null) { throw new InvalidCryptoException(
+ SAMLException.RESPONDER, "Invalid signing credential."); }
+
+ for (int i = 0; i < assertions.length; i++) {
+ String assertionAlgorithm;
+ if (relyingParty.getIdentityProvider().getSigningCredential().getCredentialType() == Credential.RSA) {
+ assertionAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
+ } else if (relyingParty.getIdentityProvider().getSigningCredential().getCredentialType() == Credential.DSA) {
+ assertionAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_DSA;
+ } else {
+ throw new InvalidCryptoException(SAMLException.RESPONDER,
+ "The Shibboleth IdP currently only supports signing with RSA and DSA keys.");
+ }
+
+ try {
+ throttle.enter();
+ assertions[i].sign(assertionAlgorithm, relyingParty.getIdentityProvider().getSigningCredential()
+ .getPrivateKey(), Arrays.asList(relyingParty.getIdentityProvider().getSigningCredential()
+ .getX509CertificateChain()));
+ } finally {
+ throttle.exit();
+ }
+ }
+ }
+
+ public void signResponse(SAMLResponse response, RelyingParty relyingParty) throws SAMLException {
+
+ // Make sure we have an appropriate credential
+ if (relyingParty.getIdentityProvider().getSigningCredential() == null
+ || relyingParty.getIdentityProvider().getSigningCredential().getPrivateKey() == null) { throw new InvalidCryptoException(
+ SAMLException.RESPONDER, "Invalid signing credential."); }
+
+ // Sign the response
+ String responseAlgorithm;
+ if (relyingParty.getIdentityProvider().getSigningCredential().getCredentialType() == Credential.RSA) {
+ responseAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
+ } else if (relyingParty.getIdentityProvider().getSigningCredential().getCredentialType() == Credential.DSA) {
+ responseAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_DSA;
+ } else {
+ throw new InvalidCryptoException(SAMLException.RESPONDER,
+ "The Shibboleth IdP currently only supports signing with RSA and DSA keys.");
+ }
+ try {
+ throttle.enter();
+ response.sign(responseAlgorithm, relyingParty.getIdentityProvider().getSigningCredential().getPrivateKey(),
+ Arrays.asList(relyingParty.getIdentityProvider().getSigningCredential().getX509CertificateChain()));
+ } finally {
+ throttle.exit();
+ }
+ }
+
+ public void addMetadataProvider(Element element) {
+
+ log.debug("Found Metadata Provider configuration element.");
+ if (!element.getTagName().equals("MetadataProvider")) {
+ log.error("Error while attemtping to load Metadata Provider. Malformed provider specificaion.");
+ return;
+ }
+
+ try {
+ wrappedMetadataProvider.addMetadataProvider(MetadataProviderFactory.loadProvider(element));
+ } catch (MetadataProviderException e) {
+ log.error("Unable to load Metadata Provider. Skipping...");
+ }
+
+ }
+
+ public Collection<? extends SAMLAttribute> getReleaseAttributes(Principal principal, RelyingParty relyingParty,
+ String requester) throws AAException {
+
+ try {
+ Collection<URI> potentialAttributes = arpEngine.listPossibleReleaseAttributes(principal, requester);
+ return getReleaseAttributes(principal, relyingParty, requester, potentialAttributes);
+
+ } catch (ArpProcessingException e) {
+ log.error("An error occurred while processing the ARPs for principal (" + principal.getName() + ") :"
+ + e.getMessage());
+ throw new AAException("Error retrieving data for principal.");
+ }
+ }
+
+ public Collection<? extends SAMLAttribute> getReleaseAttributes(Principal principal, RelyingParty relyingParty,
+ String requester, Collection<URI> attributeNames) throws AAException {
+
+ try {
+ Map<String, AAAttribute> attributes = new HashMap<String, AAAttribute>();
+ for (URI name : attributeNames) {
+
+ AAAttribute attribute = new AAAttribute(name.toString(), false);
+ attributes.put(attribute.getName(), attribute);
+ }
+
+ Collection<URI> constraintAttributes = arpEngine.listRequiredConstraintAttributes(principal, requester,
+ attributeNames);
+ for (URI name : constraintAttributes) {
+ if (!attributes.containsKey(name.toString())) {
+ // don't care about schema hack since these attributes won't be returned to SP
+ AAAttribute attribute = new AAAttribute(name.toString(), false);
+ attributes.put(attribute.getName(), attribute);
+ }
+ }
+
+ return resolveAttributes(principal, requester, relyingParty.getIdentityProvider().getProviderId(),
+ attributes);
+
+ } catch (SAMLException e) {
+ log.error("An error occurred while creating attributes for principal (" + principal.getName() + ") :"
+ + e.getMessage());
+ throw new AAException("Error retrieving data for principal.");
+
+ } catch (ArpProcessingException e) {
+ log.error("An error occurred while processing the ARPs for principal (" + principal.getName() + ") :"
+ + e.getMessage());
+ throw new AAException("Error retrieving data for principal.");
+ }
+ }
+
+ public Collection<? extends SAMLAttribute> resolveAttributes(Principal principal, String requester,
+ String responder, Map<String, AAAttribute> attributeSet) throws ArpProcessingException {
+
+ resolver.resolveAttributes(principal, requester, responder, attributeSet);
+ arpEngine.filterAttributes(attributeSet.values(), principal, requester);
+ return attributeSet.values();
+ }
+
+ public Collection<? extends SAMLAttribute> resolveAttributesNoPolicies(Principal principal, String requester,
+ String responder, Map<String, AAAttribute> attributeSet) {
+
+ resolver.resolveAttributes(principal, requester, responder, attributeSet);
+ return attributeSet.values();
+ }
+
+ /**
+ * Cleanup resources that won't be released when this object is garbage-collected
+ */
+ public void destroy() {
+
+ resolver.destroy();
+ arpEngine.destroy();
+ }
+
+ public ArtifactMapper getArtifactMapper() {
+
+ return artifactMapper;
+ }
+
+ public TrustEngine<X509EntityCredential> getTrustEngine() {
+
+ return trust;
+ }
+
+ public boolean requireValidMetadata() {
+
+ return wrappedMetadataProvider.requireValidMetadata();
+ }
+
+ public void setRequireValidMetadata(boolean requireValidMetadata) {
+
+ wrappedMetadataProvider.setRequireValidMetadata(requireValidMetadata);
+ }
+
+ public MetadataFilter getMetadataFilter() {
+
+ return wrappedMetadataProvider.getMetadataFilter();
+ }
+
+ public void setMetadataFilter(MetadataFilter newFilter) throws MetadataProviderException {
+
+ wrappedMetadataProvider.setMetadataFilter(newFilter);
+ }
+
+ public XMLObject getMetadata() throws MetadataProviderException {
+
+ return wrappedMetadataProvider.getMetadata();
+ }
+
+ public EntitiesDescriptor getEntitiesDescriptor(String name) throws MetadataProviderException {
+
+ return wrappedMetadataProvider.getEntitiesDescriptor(name);
+ }
+
+ public EntityDescriptor getEntityDescriptor(String entityID) throws MetadataProviderException {
+
+ return wrappedMetadataProvider.getEntityDescriptor(entityID);
+ }
+
+ public List<RoleDescriptor> getRole(String entityID, QName roleName) throws MetadataProviderException {
+
+ return wrappedMetadataProvider.getRole(entityID, roleName);
+ }
+
+ public RoleDescriptor getRole(String entityID, QName roleName, String supportedProtocol)
+ throws MetadataProviderException {
+
+ return wrappedMetadataProvider.getRole(entityID, roleName, supportedProtocol);
+ }
+
+ public int providerCount() {
+
+ return wrappedMetadataProvider.getProviders().size();
+ }
+
+ private class Semaphore {
+
+ private int value;
+
+ public Semaphore(int value) {
+
+ this.value = value;
+ }
+
+ public synchronized void enter() {
+
+ --value;
+ if (value < 0) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ // squelch and continue
+ }
+ }
+ }
+
+ public synchronized void exit() {
+
+ ++value;
+ notify();
+ }
+ }
+
+}
\ No newline at end of file
import java.net.URI;
import java.security.Principal;
-import java.util.Arrays;
import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
import java.util.Map;
-import javax.xml.namespace.QName;
-
import org.apache.log4j.Logger;
-import org.apache.xml.security.signature.XMLSignature;
import org.opensaml.InvalidCryptoException;
import org.opensaml.SAMLAssertion;
import org.opensaml.SAMLAttribute;
import org.opensaml.SAMLException;
import org.opensaml.SAMLResponse;
-import org.opensaml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.RoleDescriptor;
-import org.opensaml.saml2.metadata.provider.ChainingMetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
import org.opensaml.security.TrustEngine;
import org.opensaml.security.X509EntityCredential;
-import org.opensaml.xml.XMLObject;
import org.w3c.dom.Element;
import edu.internet2.middleware.shibboleth.aa.AAAttribute;
import edu.internet2.middleware.shibboleth.aa.AAException;
-import edu.internet2.middleware.shibboleth.aa.arp.ArpEngine;
import edu.internet2.middleware.shibboleth.aa.arp.ArpProcessingException;
-import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeResolver;
import edu.internet2.middleware.shibboleth.artifact.ArtifactMapper;
-import edu.internet2.middleware.shibboleth.common.Credential;
import edu.internet2.middleware.shibboleth.common.RelyingParty;
import edu.internet2.middleware.shibboleth.common.RelyingPartyMapper;
-import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
-import edu.internet2.middleware.shibboleth.common.provider.ShibbolethTrustEngine;
-import edu.internet2.middleware.shibboleth.metadata.MetadataProviderFactory;
/**
* Delivers core IdP functionality (Attribute resolution, ARP filtering, Metadata lookup, Signing, Mapping between local &
*
* @author Walter Hoehn
*/
-public class IdPProtocolSupport implements MetadataProvider {
-
- private static Logger log = Logger.getLogger(IdPProtocolSupport.class.getName());
- private Logger transactionLog;
- private IdPConfig config;
- private RelyingPartyMapper spMapper;
- private ArpEngine arpEngine;
- private AttributeResolver resolver;
- private ArtifactMapper artifactMapper;
- private Semaphore throttle;
- private TrustEngine<X509EntityCredential> trust = new ShibbolethTrustEngine();
- private ChainingMetadataProvider wrappedMetadataProvider = new ChainingMetadataProvider();
-
- IdPProtocolSupport(IdPConfig config, Logger transactionLog, RelyingPartyMapper spMapper, ArpEngine arpEngine,
- AttributeResolver resolver, ArtifactMapper artifactMapper) throws ShibbolethConfigurationException {
-
- this.transactionLog = transactionLog;
- this.config = config;
- this.spMapper = spMapper;
- spMapper.setMetadata(this);
- this.arpEngine = arpEngine;
- this.resolver = resolver;
- this.artifactMapper = artifactMapper;
-
- // Load a semaphore that throttles how many requests the IdP will handle at once
- throttle = new Semaphore(config.getMaxThreads());
- }
+public interface IdPProtocolSupport extends MetadataProvider {
- public Logger getTransactionLog() {
-
- return transactionLog;
- }
-
- public IdPConfig getIdPConfig() {
-
- return config;
- }
+ /**
+ * Facility for logging transaction information. Should be used by most Protocol Hanlder implementations.
+ */
+ public Logger getTransactionLog();
- public RelyingPartyMapper getRelyingPartyMapper() {
+ /**
+ * Access to system-wide configuration.
+ */
+ public IdPConfig getIdPConfig();
- return spMapper;
- }
+ /**
+ * Access to relying party-specific configuration.
+ */
+ public RelyingPartyMapper getRelyingPartyMapper();
public void signAssertions(SAMLAssertion[] assertions, RelyingParty relyingParty) throws InvalidCryptoException,
- SAMLException {
-
- if (relyingParty.getIdentityProvider().getSigningCredential() == null
- || relyingParty.getIdentityProvider().getSigningCredential().getPrivateKey() == null) { throw new InvalidCryptoException(
- SAMLException.RESPONDER, "Invalid signing credential."); }
-
- for (int i = 0; i < assertions.length; i++) {
- String assertionAlgorithm;
- if (relyingParty.getIdentityProvider().getSigningCredential().getCredentialType() == Credential.RSA) {
- assertionAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
- } else if (relyingParty.getIdentityProvider().getSigningCredential().getCredentialType() == Credential.DSA) {
- assertionAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_DSA;
- } else {
- throw new InvalidCryptoException(SAMLException.RESPONDER,
- "The Shibboleth IdP currently only supports signing with RSA and DSA keys.");
- }
-
- try {
- throttle.enter();
- assertions[i].sign(assertionAlgorithm, relyingParty.getIdentityProvider().getSigningCredential()
- .getPrivateKey(), Arrays.asList(relyingParty.getIdentityProvider().getSigningCredential()
- .getX509CertificateChain()));
- } finally {
- throttle.exit();
- }
- }
- }
+ SAMLException;
- public void signResponse(SAMLResponse response, RelyingParty relyingParty) throws SAMLException {
+ public void signResponse(SAMLResponse response, RelyingParty relyingParty) throws SAMLException;
- // Make sure we have an appropriate credential
- if (relyingParty.getIdentityProvider().getSigningCredential() == null
- || relyingParty.getIdentityProvider().getSigningCredential().getPrivateKey() == null) { throw new InvalidCryptoException(
- SAMLException.RESPONDER, "Invalid signing credential."); }
-
- // Sign the response
- String responseAlgorithm;
- if (relyingParty.getIdentityProvider().getSigningCredential().getCredentialType() == Credential.RSA) {
- responseAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
- } else if (relyingParty.getIdentityProvider().getSigningCredential().getCredentialType() == Credential.DSA) {
- responseAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_DSA;
- } else {
- throw new InvalidCryptoException(SAMLException.RESPONDER,
- "The Shibboleth IdP currently only supports signing with RSA and DSA keys.");
- }
- try {
- throttle.enter();
- response.sign(responseAlgorithm, relyingParty.getIdentityProvider().getSigningCredential().getPrivateKey(),
- Arrays.asList(relyingParty.getIdentityProvider().getSigningCredential().getX509CertificateChain()));
- } finally {
- throttle.exit();
- }
- }
-
- protected void addMetadataProvider(Element element) {
-
- log.debug("Found Metadata Provider configuration element.");
- if (!element.getTagName().equals("MetadataProvider")) {
- log.error("Error while attemtping to load Metadata Provider. Malformed provider specificaion.");
- return;
- }
-
- try {
- wrappedMetadataProvider.addMetadataProvider(MetadataProviderFactory.loadProvider(element));
- } catch (MetadataProviderException e) {
- log.error("Unable to load Metadata Provider. Skipping...");
- }
-
- }
+ /**
+ * Registered a metadata provider based on supplied XML configuration.
+ */
+ public void addMetadataProvider(Element element);
public Collection<? extends SAMLAttribute> getReleaseAttributes(Principal principal, RelyingParty relyingParty,
- String requester) throws AAException {
-
- try {
- Collection<URI> potentialAttributes = arpEngine.listPossibleReleaseAttributes(principal, requester);
- return getReleaseAttributes(principal, relyingParty, requester, potentialAttributes);
-
- } catch (ArpProcessingException e) {
- log.error("An error occurred while processing the ARPs for principal (" + principal.getName() + ") :"
- + e.getMessage());
- throw new AAException("Error retrieving data for principal.");
- }
- }
+ String requester) throws AAException;
public Collection<? extends SAMLAttribute> getReleaseAttributes(Principal principal, RelyingParty relyingParty,
- String requester, Collection<URI> attributeNames) throws AAException {
-
- try {
- Map<String, AAAttribute> attributes = new HashMap<String, AAAttribute>();
- for (URI name : attributeNames) {
-
- AAAttribute attribute = new AAAttribute(name.toString(), false);
- attributes.put(attribute.getName(), attribute);
- }
-
- Collection<URI> constraintAttributes = arpEngine.listRequiredConstraintAttributes(principal, requester,
- attributeNames);
- for (URI name : constraintAttributes) {
- if (!attributes.containsKey(name.toString())) {
- // don't care about schema hack since these attributes won't be returned to SP
- AAAttribute attribute = new AAAttribute(name.toString(), false);
- attributes.put(attribute.getName(), attribute);
- }
- }
-
- return resolveAttributes(principal, requester, relyingParty.getIdentityProvider().getProviderId(),
- attributes);
-
- } catch (SAMLException e) {
- log.error("An error occurred while creating attributes for principal (" + principal.getName() + ") :"
- + e.getMessage());
- throw new AAException("Error retrieving data for principal.");
-
- } catch (ArpProcessingException e) {
- log.error("An error occurred while processing the ARPs for principal (" + principal.getName() + ") :"
- + e.getMessage());
- throw new AAException("Error retrieving data for principal.");
- }
- }
+ String requester, Collection<URI> attributeNames) throws AAException;
public Collection<? extends SAMLAttribute> resolveAttributes(Principal principal, String requester,
- String responder, Map<String, AAAttribute> attributeSet) throws ArpProcessingException {
-
- resolver.resolveAttributes(principal, requester, responder, attributeSet);
- arpEngine.filterAttributes(attributeSet.values(), principal, requester);
- return attributeSet.values();
- }
+ String responder, Map<String, AAAttribute> attributeSet) throws ArpProcessingException;
public Collection<? extends SAMLAttribute> resolveAttributesNoPolicies(Principal principal, String requester,
- String responder, Map<String, AAAttribute> attributeSet) {
-
- resolver.resolveAttributes(principal, requester, responder, attributeSet);
- return attributeSet.values();
- }
+ String responder, Map<String, AAAttribute> attributeSet);
/**
* Cleanup resources that won't be released when this object is garbage-collected
*/
- public void destroy() {
+ public void destroy();
- resolver.destroy();
- arpEngine.destroy();
- }
+ public ArtifactMapper getArtifactMapper();
- public ArtifactMapper getArtifactMapper() {
-
- return artifactMapper;
- }
-
- public TrustEngine<X509EntityCredential> getTrust() {
-
- return trust;
- }
-
- public boolean requireValidMetadata() {
-
- return wrappedMetadataProvider.requireValidMetadata();
- }
-
- public void setRequireValidMetadata(boolean requireValidMetadata) {
-
- wrappedMetadataProvider.setRequireValidMetadata(requireValidMetadata);
- }
-
- public MetadataFilter getMetadataFilter() {
-
- return wrappedMetadataProvider.getMetadataFilter();
- }
-
- public void setMetadataFilter(MetadataFilter newFilter) throws MetadataProviderException {
-
- wrappedMetadataProvider.setMetadataFilter(newFilter);
- }
-
- public XMLObject getMetadata() throws MetadataProviderException {
-
- return wrappedMetadataProvider.getMetadata();
- }
-
- public EntitiesDescriptor getEntitiesDescriptor(String name) throws MetadataProviderException {
-
- return wrappedMetadataProvider.getEntitiesDescriptor(name);
- }
-
- public EntityDescriptor getEntityDescriptor(String entityID) throws MetadataProviderException {
-
- return wrappedMetadataProvider.getEntityDescriptor(entityID);
- }
-
- public List<RoleDescriptor> getRole(String entityID, QName roleName) throws MetadataProviderException {
-
- return wrappedMetadataProvider.getRole(entityID, roleName);
- }
-
- public RoleDescriptor getRole(String entityID, QName roleName, String supportedProtocol)
- throws MetadataProviderException {
-
- return wrappedMetadataProvider.getRole(entityID, roleName, supportedProtocol);
- }
-
- public int providerCount() {
-
- return wrappedMetadataProvider.getProviders().size();
- }
-
- private class Semaphore {
-
- private int value;
-
- public Semaphore(int value) {
-
- this.value = value;
- }
-
- public synchronized void enter() {
-
- --value;
- if (value < 0) {
- try {
- wait();
- } catch (InterruptedException e) {
- // squelch and continue
- }
- }
- }
-
- public synchronized void exit() {
+ /**
+ * Returns an OpenSAML2 Trust Engine implementation.
+ */
+ public TrustEngine<X509EntityCredential> getTrustEngine();
- ++value;
- notify();
- }
- }
+ /**
+ * Returns the number of active Metadata Providers.
+ */
+ public int providerCount();
}
\ No newline at end of file
private IdPConfig configuration;
private Map<String, IdPProtocolHandler> protocolHandlers = new HashMap<String, IdPProtocolHandler>();
- private IdPProtocolSupport protocolSupport;
+ private GeneralProtocolSupport protocolSupport;
/*
* @see javax.servlet.GenericServlet#init()
}
// Load protocol handlers and support library
- protocolSupport = new IdPProtocolSupport(configuration, transactionLog, spMapper, arpEngine, resolver,
+ protocolSupport = new GeneralProtocolSupport(configuration, transactionLog, spMapper, arpEngine, resolver,
artifactMapper);
itemElements = idPConfig.getDocumentElement().getElementsByTagNameNS(IdPConfig.configNameSpace,
"ProtocolHandler");
IdPProtocolHandler activeHandler = lookupProtocolHandler(request);
// Pass request to the appropriate handler and respond
log.info("Processing " + activeHandler.getHandlerName() + " request.");
- activeHandler.processRequest(request, response, protocolSupport);
+ activeHandler.processRequest(request, response, new RequestSpecificProtocolSupport(protocolSupport, request,
+ response));
}
/** Determine which protocol handler is active for this endpoint */
--- /dev/null
+/*
+ * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.internet2.middleware.shibboleth.idp;
+
+import java.net.URI;
+import java.security.Principal;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.namespace.QName;
+
+import org.apache.log4j.Logger;
+import org.opensaml.InvalidCryptoException;
+import org.opensaml.SAMLAssertion;
+import org.opensaml.SAMLAttribute;
+import org.opensaml.SAMLException;
+import org.opensaml.SAMLResponse;
+import org.opensaml.saml2.metadata.EntitiesDescriptor;
+import org.opensaml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml2.metadata.RoleDescriptor;
+import org.opensaml.saml2.metadata.provider.MetadataFilter;
+import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.opensaml.security.TrustEngine;
+import org.opensaml.security.X509EntityCredential;
+import org.opensaml.xml.XMLObject;
+import org.w3c.dom.Element;
+
+import edu.internet2.middleware.shibboleth.aa.AAAttribute;
+import edu.internet2.middleware.shibboleth.aa.AAException;
+import edu.internet2.middleware.shibboleth.aa.arp.ArpProcessingException;
+import edu.internet2.middleware.shibboleth.artifact.ArtifactMapper;
+import edu.internet2.middleware.shibboleth.common.RelyingParty;
+import edu.internet2.middleware.shibboleth.common.RelyingPartyMapper;
+
+/**
+ * IdPProtocolSupport implementation that offers functionality that is specific to a particular request.
+ *
+ * @author Walter Hoehn
+ */
+public class RequestSpecificProtocolSupport implements IdPProtocolSupport {
+
+ IdPProtocolSupport wrapped;
+
+ RequestSpecificProtocolSupport(GeneralProtocolSupport generalSupport, HttpServletRequest request,
+ HttpServletResponse response) {
+
+ wrapped = generalSupport;
+ }
+
+ public void addMetadataProvider(Element element) {
+
+ wrapped.addMetadataProvider(element);
+ }
+
+ public void destroy() {
+
+ wrapped.destroy();
+ }
+
+ public ArtifactMapper getArtifactMapper() {
+
+ return wrapped.getArtifactMapper();
+ }
+
+ public IdPConfig getIdPConfig() {
+
+ return wrapped.getIdPConfig();
+ }
+
+ public Collection<? extends SAMLAttribute> getReleaseAttributes(Principal principal, RelyingParty relyingParty,
+ String requester) throws AAException {
+
+ return wrapped.getReleaseAttributes(principal, relyingParty, requester);
+ }
+
+ public Collection<? extends SAMLAttribute> getReleaseAttributes(Principal principal, RelyingParty relyingParty,
+ String requester, Collection<URI> attributeNames) throws AAException {
+
+ return wrapped.getReleaseAttributes(principal, relyingParty, requester, attributeNames);
+ }
+
+ public RelyingPartyMapper getRelyingPartyMapper() {
+
+ return wrapped.getRelyingPartyMapper();
+ }
+
+ public Logger getTransactionLog() {
+
+ return wrapped.getTransactionLog();
+ }
+
+ public TrustEngine<X509EntityCredential> getTrustEngine() {
+
+ return wrapped.getTrustEngine();
+ }
+
+ public int providerCount() {
+
+ return wrapped.providerCount();
+ }
+
+ public Collection<? extends SAMLAttribute> resolveAttributes(Principal principal, String requester,
+ String responder, Map<String, AAAttribute> attributeSet) throws ArpProcessingException {
+
+ return wrapped.resolveAttributes(principal, requester, responder, attributeSet);
+ }
+
+ public Collection<? extends SAMLAttribute> resolveAttributesNoPolicies(Principal principal, String requester,
+ String responder, Map<String, AAAttribute> attributeSet) {
+
+ return wrapped.resolveAttributesNoPolicies(principal, requester, responder, attributeSet);
+ }
+
+ public void signAssertions(SAMLAssertion[] assertions, RelyingParty relyingParty) throws InvalidCryptoException,
+ SAMLException {
+
+ wrapped.signAssertions(assertions, relyingParty);
+ }
+
+ public void signResponse(SAMLResponse response, RelyingParty relyingParty) throws SAMLException {
+
+ wrapped.signResponse(response, relyingParty);
+ }
+
+ public EntitiesDescriptor getEntitiesDescriptor(String name) throws MetadataProviderException {
+
+ return wrapped.getEntitiesDescriptor(name);
+ }
+
+ public EntityDescriptor getEntityDescriptor(String entityID) throws MetadataProviderException {
+
+ return wrapped.getEntityDescriptor(entityID);
+ }
+
+ public XMLObject getMetadata() throws MetadataProviderException {
+
+ return wrapped.getMetadata();
+ }
+
+ public MetadataFilter getMetadataFilter() {
+
+ return wrapped.getMetadataFilter();
+ }
+
+ public List<RoleDescriptor> getRole(String entityID, QName roleName) throws MetadataProviderException {
+
+ return wrapped.getRole(entityID, roleName);
+ }
+
+ public RoleDescriptor getRole(String entityID, QName roleName, String supportedProtocol)
+ throws MetadataProviderException {
+
+ return wrapped.getRole(entityID, roleName, supportedProtocol);
+ }
+
+ public boolean requireValidMetadata() {
+
+ return wrapped.requireValidMetadata();
+ }
+
+ public void setMetadataFilter(MetadataFilter newFilter) throws MetadataProviderException {
+
+ wrapped.setMetadataFilter(newFilter);
+ }
+
+ public void setRequireValidMetadata(boolean requireValidMetadata) {
+
+ wrapped.setRequireValidMetadata(requireValidMetadata);
+ }
+
+}
// Make sure that the suppplied credential is valid for the provider to which the artifact was
// issued
if (chain != null && chain.length > 0) {
- if (!support.getTrust().validate(new HttpX509EntityCredential(request), role)) {
+ if (!support.getTrustEngine().validate(new HttpX509EntityCredential(request), role)) {
log.error("Supplied TLS credential ("
+ chain[0].getSubjectX500Principal().getName(X500Principal.RFC2253)
+ ") is NOT valid for provider (" + mapping.getServiceProviderId()
}
if (samlRequest.isSigned()) {
- if (!support.getTrust().validate(samlRequest, role)) {
+ if (!support.getTrustEngine().validate(samlRequest, role)) {
log.error("Signed SAML request message did NOT contain a valid signature from provider ("
+ mapping.getServiceProviderId() + "), to whom this artifact was issued.");
throw new SAMLException(SAMLException.REQUESTER, "Invalid signature.");
}
// Make sure that the supplied credential is valid for the selected provider role.
- if ((ar_role != null && support.getTrust().validate(credential, ar_role))
- || (sp_role != null && support.getTrust().validate(credential, sp_role))) {
+ if ((ar_role != null && support.getTrustEngine().validate(credential, ar_role))
+ || (sp_role != null && support.getTrustEngine().validate(credential, sp_role))) {
log.info("Supplied credentials validated for this provider.");
return assertedId;
} else {