package edu.internet2.middleware.shibboleth.idp;
import java.net.URI;
-import java.net.URL;
import java.security.Principal;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
+import java.util.Collection;
+import java.util.Map;
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.artifact.Artifact;
+import org.opensaml.saml2.metadata.provider.MetadataProvider;
+import org.opensaml.security.TrustEngine;
+import org.opensaml.security.X509EntityCredential;
import org.w3c.dom.Element;
import edu.internet2.middleware.shibboleth.aa.AAAttribute;
-import edu.internet2.middleware.shibboleth.aa.AAAttributeSet;
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.NameMapper;
import edu.internet2.middleware.shibboleth.common.RelyingParty;
-import edu.internet2.middleware.shibboleth.common.ServiceProviderMapper;
-import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
-import edu.internet2.middleware.shibboleth.common.Trust;
-import edu.internet2.middleware.shibboleth.common.provider.ShibbolethTrust;
-import edu.internet2.middleware.shibboleth.metadata.EntitiesDescriptor;
-import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
-import edu.internet2.middleware.shibboleth.metadata.Metadata;
-import edu.internet2.middleware.shibboleth.metadata.MetadataException;
+import edu.internet2.middleware.shibboleth.common.RelyingPartyMapper;
/**
* Delivers core IdP functionality (Attribute resolution, ARP filtering, Metadata lookup, Signing, Mapping between local &
*
* @author Walter Hoehn
*/
-public class IdPProtocolSupport implements Metadata {
+public interface IdPProtocolSupport extends MetadataProvider {
- private static Logger log = Logger.getLogger(IdPProtocolSupport.class.getName());
- private Logger transactionLog;
- private IdPConfig config;
- private ArrayList metadata = new ArrayList();
- private NameMapper nameMapper;
- private ServiceProviderMapper spMapper;
- private ArpEngine arpEngine;
- private AttributeResolver resolver;
- private ArtifactMapper artifactMapper;
- private Semaphore throttle;
- private Trust trust = new ShibbolethTrust();
-
- IdPProtocolSupport(IdPConfig config, Logger transactionLog, NameMapper nameMapper, ServiceProviderMapper spMapper,
- ArpEngine arpEngine, AttributeResolver resolver, ArtifactMapper artifactMapper)
- throws ShibbolethConfigurationException {
-
- this.transactionLog = transactionLog;
- this.config = config;
- this.nameMapper = nameMapper;
- 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 Logger getTransactionLog() {
-
- return transactionLog;
- }
-
- public IdPConfig getIdPConfig() {
-
- return config;
- }
-
- public NameMapper getNameMapper() {
-
- return nameMapper;
- }
+ /**
+ * Facility for logging transaction information. Should be used by most Protocol Hanlder implementations.
+ */
+ public Logger getTransactionLog();
- public ServiceProviderMapper getServiceProviderMapper() {
+ /**
+ * 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();
- }
- }
- }
-
- 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 {
- metadata.add(MetadataProviderFactory.loadProvider(element));
- } catch (MetadataException e) {
- log.error("Unable to load Metadata Provider. Skipping...");
- }
- }
-
- public int providerCount() {
-
- return metadata.size();
- }
-
- public EntityDescriptor lookup(String providerId, boolean strict) {
-
- Iterator iterator = metadata.iterator();
- while (iterator.hasNext()) {
- EntityDescriptor provider = ((Metadata) iterator.next()).lookup(providerId);
- if (provider != null) { return provider; }
- }
- return null;
- }
-
- public EntityDescriptor lookup(Artifact artifact, boolean strict) {
-
- Iterator iterator = metadata.iterator();
- while (iterator.hasNext()) {
- EntityDescriptor provider = ((Metadata) iterator.next()).lookup(artifact);
- if (provider != null) { return provider; }
- }
- return null;
- }
-
- public EntityDescriptor lookup(String id) {
+ SAMLException;
- return lookup(id, true);
- }
+ public void signResponse(SAMLResponse response, RelyingParty relyingParty) throws SAMLException;
- public EntityDescriptor lookup(Artifact artifact) {
-
- return lookup(artifact, true);
- }
-
- public EntityDescriptor getRootEntity() {
-
- return null;
- }
-
- public EntitiesDescriptor getRootEntities() {
-
- return null;
- }
-
- public SAMLAttribute[] getReleaseAttributes(Principal principal, RelyingParty relyingParty, String requester,
- URL resource) throws AAException {
-
- try {
- URI[] potentialAttributes = arpEngine.listPossibleReleaseAttributes(principal, requester, resource);
- return getReleaseAttributes(principal, relyingParty, requester, resource, 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 SAMLAttribute[] getReleaseAttributes(Principal principal, RelyingParty relyingParty, String requester,
- URL resource, URI[] attributeNames) throws AAException {
-
- try {
- AAAttributeSet attributeSet = new AAAttributeSet();
- for (int i = 0; i < attributeNames.length; i++) {
-
- AAAttribute attribute = null;
- if (relyingParty.wantsSchemaHack()) {
- attribute = new AAAttribute(attributeNames[i].toString(), true);
- } else {
- attribute = new AAAttribute(attributeNames[i].toString(), false);
- }
-
- attributeSet.add(attribute);
- }
-
- return resolveAttributes(principal, requester, relyingParty.getIdentityProvider().getProviderId(),
- resource, attributeSet);
-
- } 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.");
- }
- }
+ /**
+ * Registered a metadata provider based on supplied XML configuration.
+ */
+ public void addMetadataProvider(Element element);
- public SAMLAttribute[] resolveAttributes(Principal principal, String requester, String responder, URL resource,
- AAAttributeSet attributeSet) throws ArpProcessingException {
+ public Collection<? extends SAMLAttribute> getReleaseAttributes(Principal principal, RelyingParty relyingParty,
+ String requester) throws AAException;
- resolver.resolveAttributes(principal, requester, responder, attributeSet);
- arpEngine.filterAttributes(attributeSet, principal, requester, resource);
- return attributeSet.getAttributes();
- }
+ public Collection<? extends SAMLAttribute> getReleaseAttributes(Principal principal, RelyingParty relyingParty,
+ String requester, Collection<URI> attributeNames) throws AAException;
- public SAMLAttribute[] resolveAttributesNoPolicies(Principal principal, String requester, String responder,
- URL resource, AAAttributeSet attributeSet) throws ArpProcessingException {
+ public Collection<? extends SAMLAttribute> resolveAttributes(Principal principal, String requester,
+ String responder, Map<String, AAAttribute> attributeSet) throws ArpProcessingException;
- resolver.resolveAttributes(principal, requester, responder, attributeSet);
- return attributeSet.getAttributes();
- }
+ public Collection<? extends SAMLAttribute> resolveAttributesNoPolicies(Principal principal, String requester,
+ String responder, Map<String, AAAttribute> attributeSet);
/**
* 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 Trust getTrust() {
-
- return trust;
- }
-
- private class Semaphore {
+ public void destroy();
- private int value;
+ public ArtifactMapper getArtifactMapper();
- public Semaphore(int value) {
-
- this.value = value;
- }
-
- public synchronized void enter() {
-
- --value;
- if (value < 0) {
- try {
- wait();
- } catch (InterruptedException e) {
- // squelch and continue
- }
- }
- }
+ /**
+ * Returns an OpenSAML2 Trust Engine implementation.
+ */
+ public TrustEngine<X509Credential> getTrustEngine();
- public synchronized void exit() {
+ /**
+ * Returns the number of active Metadata Providers.
+ */
+ public int providerCount();
- ++value;
- notify();
- }
- }
}
\ No newline at end of file