Fleshed out the artifact code.
authorwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Wed, 16 Mar 2005 20:44:21 +0000 (20:44 +0000)
committerwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Wed, 16 Mar 2005 20:44:21 +0000 (20:44 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@1302 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/artifact/ArtifactMapper.java
src/edu/internet2/middleware/shibboleth/artifact/ArtifactMapping.java
src/edu/internet2/middleware/shibboleth/artifact/provider/BaseArtifactMapper.java
src/edu/internet2/middleware/shibboleth/artifact/provider/MemoryArtifactMapper.java
src/edu/internet2/middleware/shibboleth/idp/IdPProtocolSupport.java
src/edu/internet2/middleware/shibboleth/idp/provider/SAMLv1_1ArtifactQueryHandler.java
src/edu/internet2/middleware/shibboleth/idp/provider/ShibbolethV1SSOHandler.java

index 511e5db..a03ceeb 100644 (file)
@@ -26,6 +26,7 @@
 package edu.internet2.middleware.shibboleth.artifact;
 
 import org.opensaml.SAMLAssertion;
+import org.opensaml.artifact.Artifact;
 
 import edu.internet2.middleware.shibboleth.common.RelyingParty;
 
@@ -46,12 +47,15 @@ public interface ArtifactMapper {
         *            the relying party on behalf of which the artifact is being created
         * @return the artifact
         */
-       public String generateArtifact(SAMLAssertion assertion, RelyingParty relyingParty);
+       public Artifact generateArtifact(SAMLAssertion assertion, RelyingParty relyingParty);
 
        /**
+        * Recover an assertion that was previosly generated for a given artifact.
+        * 
         * @param artifact
-        * @return
+        *            the artifact in question
+        * @return a mapping to the assertion
         */
 
-       public ArtifactMapping recoverAssertion(String artifact);
+       public ArtifactMapping recoverAssertion(Artifact artifact);
 }
\ No newline at end of file
index 76bba7f..b250d44 100644 (file)
@@ -26,6 +26,7 @@
 package edu.internet2.middleware.shibboleth.artifact;
 
 import org.opensaml.SAMLAssertion;
+import org.opensaml.artifact.Artifact;
 
 import edu.internet2.middleware.shibboleth.common.ServiceProvider;
 
@@ -36,15 +37,16 @@ import edu.internet2.middleware.shibboleth.common.ServiceProvider;
  */
 public class ArtifactMapping {
 
-       private String                  assertionHandle;
-       private long                    expirationTime;
-       private SAMLAssertion   assertion;
-       private String                  serviceProviderId;
+       private Artifact artifact;
+       private long expirationTime;
+       private SAMLAssertion assertion;
+       private String serviceProviderId;
 
-       public ArtifactMapping(String assertionHandle, SAMLAssertion assertion, ServiceProvider sp) {
-               this.assertionHandle = assertionHandle;
+       public ArtifactMapping(Artifact artifact, SAMLAssertion assertion, ServiceProvider sp) {
+
+               this.artifact = artifact;
                this.assertion = assertion;
-               expirationTime = System.currentTimeMillis() + (1000 * 60 * 5); //in 5 minutes
+               expirationTime = System.currentTimeMillis() + (1000 * 60 * 5); // in 5 minutes
                serviceProviderId = sp.getProviderId();
        }
 
@@ -52,6 +54,7 @@ public class ArtifactMapping {
         * Boolean indication of whether the artifact is expired.
         */
        public boolean isExpired() {
+
                if (System.currentTimeMillis() > expirationTime) { return true; }
                return false;
        }
@@ -60,6 +63,7 @@ public class ArtifactMapping {
         * Boolean indication of whether the artifact was created on behalf of a specified SP.
         */
        public boolean isCorrectProvider(ServiceProvider sp) {
+
                if (sp.getProviderId().equals(serviceProviderId)) { return true; }
                return false;
        }
@@ -68,6 +72,7 @@ public class ArtifactMapping {
         * Retrieves the SAML assertion associated with the artifact.
         */
        public SAMLAssertion getAssertion() {
+
                return assertion;
        }
 
@@ -75,6 +80,7 @@ public class ArtifactMapping {
         * Retrieves the SP on behalf of which the artifact was originally created.
         */
        public String getServiceProviderId() {
+
                return serviceProviderId;
        }
 
index c8520f3..8d1b83b 100644 (file)
 
 package edu.internet2.middleware.shibboleth.artifact.provider;
 
-import java.io.IOException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
 
 import org.apache.log4j.Logger;
 import org.opensaml.SAMLAssertion;
+import org.opensaml.artifact.Artifact;
+import org.opensaml.artifact.SAMLArtifactType0001;
+import org.opensaml.artifact.Util;
 
-import sun.misc.BASE64Decoder;
-import sun.misc.BASE64Encoder;
 import edu.internet2.middleware.shibboleth.artifact.ArtifactMapper;
 import edu.internet2.middleware.shibboleth.artifact.ArtifactMapping;
 import edu.internet2.middleware.shibboleth.common.RelyingParty;
@@ -48,13 +47,12 @@ import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationExcepti
  */
 public abstract class BaseArtifactMapper implements ArtifactMapper {
 
-       private static Logger   log                     = Logger.getLogger(BaseArtifactMapper.class.getName());
-       private static byte[]   typeCode        = {0, 1};
+       private static Logger log = Logger.getLogger(BaseArtifactMapper.class.getName());
 
-       private SecureRandom    random          = new SecureRandom();
-       private MessageDigest   md;
+       private MessageDigest md;
 
        public BaseArtifactMapper() throws ShibbolethConfigurationException {
+
                try {
                        md = MessageDigest.getInstance("SHA-1");
                } catch (NoSuchAlgorithmException e) {
@@ -65,83 +63,27 @@ public abstract class BaseArtifactMapper implements ArtifactMapper {
 
        }
 
-       public ArtifactMapping recoverAssertion(String artifact) {
-
-               try {
-                       //Decode the artifact
-                       byte[] decoded = new BASE64Decoder().decodeBuffer(artifact);
-                       if (decoded.length != 42) {
-                               log.error("Invalid artifact length.");
-                               return null;
-                       }
-
-                       //Check the type
-                       if (decoded[0] != typeCode[0] || decoded[1] != typeCode[1]) {
-                               log.error("Incorrect artifact type code.");
-                               return null;
-                       }
-
-                       //Grab the assertion handle
-                       byte[] assertionHandle = new byte[20];
-                       for (int assertionHandleCount = 0, decodedCount = 22; assertionHandleCount < assertionHandle.length; assertionHandleCount++, decodedCount++) {
-                               assertionHandle[assertionHandleCount] = decoded[decodedCount];
-                       }
-                       String stringHandle = new String(assertionHandle);
-
-                       //delegate recovery to extenders
-                       return recoverAssertionImpl(stringHandle);
-
-               } catch (IOException e) {
-                       log.error("Artifact not properly Base64 encoded.");
-                       return null;
-               }
-       }
-
-       public String generateArtifact(SAMLAssertion assertion, RelyingParty relyingParty) {
-
-               byte[] allArtifactComponents = new byte[42];
+       public Artifact generateArtifact(SAMLAssertion assertion, RelyingParty relyingParty) {
 
-               // Add typecode
-               allArtifactComponents[0] = typeCode[0];
-               allArtifactComponents[1] = typeCode[1];
+               // TODO should the artifact type be configurable?
 
-               // Add SourceID
-               byte[] sourceID = new byte[20];
+               // Generate the artifact
+               Artifact artifact;
                synchronized (md) {
-                       sourceID = md.digest(relyingParty.getIdentityProvider().getProviderId().getBytes());
+                       artifact = new SAMLArtifactType0001(Util.generateSourceId(md, relyingParty.getIdentityProvider()
+                                       .getProviderId()));
                }
-               for (int sourceIdCount = 0, allComponentCount = 2; sourceIdCount < sourceID.length; sourceIdCount++, allComponentCount++) {
-                       allArtifactComponents[allComponentCount] = sourceID[sourceIdCount];
-               }
-
-               // Add Asserton Handle
-               byte[] buffer = new byte[20];
-               random.nextBytes(buffer);
-               for (int assertionHandleCount = 0, allComponentCount = 22; assertionHandleCount < buffer.length; assertionHandleCount++, allComponentCount++) {
-                       allArtifactComponents[allComponentCount] = buffer[assertionHandleCount];
-               }
-
-               // Cache the assertion handle
-               String assertionHandle = new String(buffer);
 
                // Delegate adding to extenders
-               addAssertionImpl(assertionHandle, new ArtifactMapping(assertionHandle, assertion, relyingParty));
+               addAssertionImpl(artifact, new ArtifactMapping(artifact, assertion, relyingParty));
 
                // Return the encoded artifact
-               return new BASE64Encoder().encode(allArtifactComponents);
+               return artifact;
        }
 
        /**
         * Subclasses should implement artifact storage with this method.
         */
-       protected abstract void addAssertionImpl(String assertionHandle, ArtifactMapping mapping);
-
-       /**
-        * Subclasses should implement artifact lookup with this method.
-        * 
-        * @param stringHandle
-        *            the artifact string
-        */
-       protected abstract ArtifactMapping recoverAssertionImpl(String artifact);
+       protected abstract void addAssertionImpl(Artifact artifact, ArtifactMapping mapping);
 
 }
\ No newline at end of file
index e28b526..b13860d 100644 (file)
@@ -30,6 +30,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.log4j.Logger;
+import org.opensaml.artifact.Artifact;
 
 import edu.internet2.middleware.shibboleth.artifact.ArtifactMapper;
 import edu.internet2.middleware.shibboleth.artifact.ArtifactMapping;
@@ -43,35 +44,25 @@ import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationExcepti
 public class MemoryArtifactMapper extends BaseArtifactMapper implements ArtifactMapper {
 
        public MemoryArtifactMapper() throws ShibbolethConfigurationException {
+
                super();
        }
 
-       //TODO need to cleanup stale artifacts
-       private static Logger   log                     = Logger.getLogger(MemoryArtifactMapper.class.getName());
-       private static Map              mappings        = Collections.synchronizedMap(new HashMap());
+       // TODO need to cleanup stale artifacts
+       private static Logger log = Logger.getLogger(MemoryArtifactMapper.class.getName());
+       private static Map mappings = Collections.synchronizedMap(new HashMap());
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see edu.internet2.middleware.shibboleth.artifact.provider.BaseArtifactMapper#recoverAssertionImpl(java.lang.String)
-        */
-       protected ArtifactMapping recoverAssertionImpl(String stringHandle) {
+       public ArtifactMapping recoverAssertion(Artifact artifact) {
 
-               //Load the assertion from memory
-               ArtifactMapping mapping = (ArtifactMapping) mappings.get(stringHandle);
-               mappings.remove(stringHandle);
+               ArtifactMapping mapping = (ArtifactMapping) mappings.get(artifact);
+               mappings.remove(artifact);
                if (mapping == null || mapping.isExpired()) { return null; }
                return mapping;
        }
 
-       /*
-        * (non-Javadoc)
-        * 
-        * @see edu.internet2.middleware.shibboleth.artifact.provider.BaseArtifactMapper#addAssertionImpl(java.lang.String,
-        *      edu.internet2.middleware.shibboleth.artifact.ArtifactMapping)
-        */
-       protected void addAssertionImpl(String assertionHandle, ArtifactMapping mapping) {
-               mappings.put(assertionHandle, mapping);
+       public void addAssertionImpl(Artifact artifact, ArtifactMapping mapping) {
+
+               mappings.put(artifact, mapping);
        }
 
 }
\ No newline at end of file
index 2346411..1c7aa68 100644 (file)
@@ -50,10 +50,13 @@ 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.artifact.provider.MemoryArtifactMapper;
 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.metadata.EntityDescriptor;
 import edu.internet2.middleware.shibboleth.metadata.Metadata;
 import edu.internet2.middleware.shibboleth.metadata.MetadataException;
@@ -75,9 +78,10 @@ public class IdPProtocolSupport implements Metadata {
        private ServiceProviderMapper spMapper;
        private ArpEngine arpEngine;
        private AttributeResolver resolver;
+       private ArtifactMapper artifactMapper;
 
        IdPProtocolSupport(IdPConfig config, Logger transactionLog, NameMapper nameMapper, ServiceProviderMapper spMapper,
-                       ArpEngine arpEngine, AttributeResolver resolver) {
+                       ArpEngine arpEngine, AttributeResolver resolver) throws ShibbolethConfigurationException {
 
                this.transactionLog = transactionLog;
                this.config = config;
@@ -86,11 +90,13 @@ public class IdPProtocolSupport implements Metadata {
                spMapper.setMetadata(this);
                this.arpEngine = arpEngine;
                this.resolver = resolver;
+               // TODO make this pluggable... and clean up memory impl
+               artifactMapper = new MemoryArtifactMapper();
        }
 
        public static void validateEngineData(HttpServletRequest req) throws InvalidClientDataException {
 
-               //TODO this should be pulled out into handlers
+               // TODO this should be pulled out into handlers
 
                if ((req.getRemoteAddr() == null) || (req.getRemoteAddr().equals(""))) { throw new InvalidClientDataException(
                                "Unable to obtain client address."); }
@@ -266,4 +272,9 @@ public class IdPProtocolSupport implements Metadata {
                resolver.destroy();
                arpEngine.destroy();
        }
+
+       public ArtifactMapper getArtifactMapper() {
+
+               return artifactMapper;
+       }
 }
\ No newline at end of file
index 6c1cff8..436cb3e 100644 (file)
@@ -40,12 +40,11 @@ import org.opensaml.SAMLAssertion;
 import org.opensaml.SAMLException;
 import org.opensaml.SAMLRequest;
 import org.opensaml.SAMLResponse;
+import org.opensaml.artifact.Artifact;
 import org.w3c.dom.Element;
 
 import sun.misc.BASE64Decoder;
-import edu.internet2.middleware.shibboleth.artifact.ArtifactMapper;
 import edu.internet2.middleware.shibboleth.artifact.ArtifactMapping;
-import edu.internet2.middleware.shibboleth.artifact.provider.MemoryArtifactMapper;
 import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
 import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
 import edu.internet2.middleware.shibboleth.idp.IdPProtocolSupport;
@@ -56,21 +55,14 @@ import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
  */
 public class SAMLv1_1ArtifactQueryHandler extends BaseServiceHandler implements IdPProtocolHandler {
 
-       // TODO figure out how to refactor this
-       private ArtifactMapper artifactMapper;
-
        private static Logger log = Logger.getLogger(SAMLv1_1ArtifactQueryHandler.class.getName());
 
        public SAMLv1_1ArtifactQueryHandler(Element config) throws ShibbolethConfigurationException {
 
                super(config);
-               // TODO move the mapper out into protocol support
-               artifactMapper = new MemoryArtifactMapper();
        }
 
        /*
-        * (non-Javadoc)
-        * 
         * @see edu.internet2.middleware.shibboleth.idp.ProtocolHandler#getHandlerName()
         */
        public String getHandlerName() {
@@ -85,9 +77,8 @@ public class SAMLv1_1ArtifactQueryHandler extends BaseServiceHandler implements
        public SAMLResponse processRequest(HttpServletRequest request, HttpServletResponse response,
                        SAMLRequest samlRequest, IdPProtocolSupport support) throws SAMLException, IOException, ServletException {
 
-               log.info("Recieved a request to dereference an assertion artifact.");
+               log.info("Recieved a request to dereference assertion artifacts.");
 
-               // TODO how about signatures on artifact dereferencing
                // Pull credential from request
                X509Certificate credential = getCredentialFromProvider(request);
                if (credential == null || credential.getSubjectX500Principal().getName(X500Principal.RFC2253).equals("")) {
@@ -102,24 +93,31 @@ public class SAMLv1_1ArtifactQueryHandler extends BaseServiceHandler implements
                ArrayList assertions = new ArrayList();
                Iterator artifacts = samlRequest.getArtifacts();
 
-               // TODO error if not artifacts
+               if (!artifacts.hasNext()) {
+                       log.error("Protocol Handler received a SAML Request, but is unable to handle it.  No "
+                                       + "artifacts were included in the request.");
+                       throw new SAMLException(SAMLException.REQUESTER, "General error processing request.");
+               }
 
                int queriedArtifacts = 0;
+               // for transaction log
                StringBuffer dereferencedArtifacts = new StringBuffer();
-               // for // transaction // log
+
                while (artifacts.hasNext()) {
                        queriedArtifacts++;
-                       String artifact = (String) artifacts.next();
-                       log.debug("Attempting to dereference artifact: (" + artifact + ").");
-                       ArtifactMapping mapping = artifactMapper.recoverAssertion(artifact);
+                       Artifact artifact = (Artifact) artifacts.next();
+                       log.debug("Attempting to dereference artifact: (" + artifact.toString() + ").");
+                       ArtifactMapping mapping = support.getArtifactMapper().recoverAssertion(artifact);
                        if (mapping != null) {
-                               SAMLAssertion assertion = mapping.getAssertion(); // See if we have metadata for this provider
+                               SAMLAssertion assertion = mapping.getAssertion();
+                               // See if we have metadata for this provider
                                EntityDescriptor provider = support.lookup(mapping.getServiceProviderId());
                                if (provider == null) {
                                        log.info("No metadata found for provider: (" + mapping.getServiceProviderId() + ").");
                                        throw new SAMLException(SAMLException.REQUESTER, "Invalid service provider.");
                                }
-                               // Make sure that the suppplied credential is valid for the // provider to which theartifact was issued
+
+                               // Make sure that the suppplied credential is valid for the provider to which the artifact was issued
                                if (!isValidCredential(provider, credential)) {
                                        log.error("Supplied credential ("
                                                        + credential.getSubjectX500Principal().getName(X500Principal.RFC2253)
@@ -131,12 +129,15 @@ public class SAMLv1_1ArtifactQueryHandler extends BaseServiceHandler implements
                                assertions.add(assertion);
                                dereferencedArtifacts.append("(" + artifact + ")");
                        }
-               } // The spec requires that if any artifacts are dereferenced, they must
+               }
+
+               // The spec requires that if any artifacts are dereferenced, they must
                // all be dereferenced
                if (assertions.size() > 0 && assertions.size() != queriedArtifacts) { throw new SAMLException(
                                SAMLException.REQUESTER, "Unable to successfully dereference all artifacts."); }
+
                // Create and send response
-               // The spec says that we should send "success" in the case where no // artifacts match
+               // The spec says that we should send "success" in the case where no artifacts match
                SAMLResponse samlResponse = new SAMLResponse(samlRequest.getId(), null, assertions, null);
                if (log.isDebugEnabled()) {
                        try {
index d4bd8aa..35289f6 100644 (file)
@@ -186,8 +186,7 @@ public class ShibbolethV1SSOHandler extends BaseHandler implements IdPProtocolHa
                                // Create artifacts for each assertion
                                ArrayList artifacts = new ArrayList();
                                for (int i = 0; i < assertions.length; i++) {
-                                       // TODO replace the artifact stuff here!!!
-                                       // artifacts.add(artifactMapper.generateArtifact(assertions[i], relyingParty));
+                                       artifacts.add(support.getArtifactMapper().generateArtifact(assertions[i], relyingParty));
                                }
 
                                // Assemble the query string