Refactorings that serve as the groundwork for adding cache mechanism to protocol...
authorwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Mon, 25 Sep 2006 18:45:36 +0000 (18:45 +0000)
committerwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Mon, 25 Sep 2006 18:45:36 +0000 (18:45 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@2049 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/idp/GeneralProtocolSupport.java [new file with mode: 0644]
src/edu/internet2/middleware/shibboleth/idp/IdPProtocolSupport.java
src/edu/internet2/middleware/shibboleth/idp/IdPResponder.java
src/edu/internet2/middleware/shibboleth/idp/RequestSpecificProtocolSupport.java [new file with mode: 0644]
src/edu/internet2/middleware/shibboleth/idp/provider/SAMLv1_1ArtifactQueryHandler.java
src/edu/internet2/middleware/shibboleth/idp/provider/SAMLv1_AttributeQueryHandler.java

diff --git a/src/edu/internet2/middleware/shibboleth/idp/GeneralProtocolSupport.java b/src/edu/internet2/middleware/shibboleth/idp/GeneralProtocolSupport.java
new file mode 100644 (file)
index 0000000..388a2bf
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * 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
index 576029d..638fbd9 100644 (file)
@@ -11,45 +11,26 @@ 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;
 
 /**
  * Delivers core IdP functionality (Attribute resolution, ARP filtering, Metadata lookup, Signing, Mapping between local &
@@ -57,281 +38,60 @@ import edu.internet2.middleware.shibboleth.metadata.MetadataProviderFactory;
  * 
  * @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
index 6f46be8..0eca8a2 100644 (file)
@@ -67,7 +67,7 @@ public class IdPResponder extends HttpServlet {
 
        private IdPConfig configuration;
        private Map<String, IdPProtocolHandler> protocolHandlers = new HashMap<String, IdPProtocolHandler>();
-       private IdPProtocolSupport protocolSupport;
+       private GeneralProtocolSupport protocolSupport;
 
        /*
         * @see javax.servlet.GenericServlet#init()
@@ -169,7 +169,7 @@ public class IdPResponder extends HttpServlet {
                        }
 
                        // 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");
@@ -270,7 +270,8 @@ public class IdPResponder extends HttpServlet {
                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 */
diff --git a/src/edu/internet2/middleware/shibboleth/idp/RequestSpecificProtocolSupport.java b/src/edu/internet2/middleware/shibboleth/idp/RequestSpecificProtocolSupport.java
new file mode 100644 (file)
index 0000000..792da51
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * 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);
+       }
+
+}
index 907121c..fa64b0d 100644 (file)
@@ -147,7 +147,7 @@ public class SAMLv1_1ArtifactQueryHandler extends SAMLv1_Base_QueryHandler imple
                                        // 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()
@@ -158,7 +158,7 @@ public class SAMLv1_1ArtifactQueryHandler extends SAMLv1_Base_QueryHandler imple
                                        }
                                        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.");
index 1eeaa74..7c057da 100644 (file)
@@ -117,8 +117,8 @@ public class SAMLv1_AttributeQueryHandler extends SAMLv1_Base_QueryHandler imple
                }
 
                // 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 {