Sign query request per CredentialUse/RelyingParty configuration
authorgilbert <gilbert@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Fri, 8 Jul 2005 17:37:27 +0000 (17:37 +0000)
committergilbert <gilbert@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Fri, 8 Jul 2005 17:37:27 +0000 (17:37 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@1694 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/serviceprovider/AttributeRequestor.java
src/edu/internet2/middleware/shibboleth/serviceprovider/ServiceProviderConfig.java

index 1ba72e9..ee1bede 100644 (file)
  */
 package edu.internet2.middleware.shibboleth.serviceprovider;
 
+import java.security.Key;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
 
 import org.apache.log4j.Logger;
+import org.apache.xml.security.signature.XMLSignature;
 import org.opensaml.SAMLAssertion;
 import org.opensaml.SAMLAttributeQuery;
 import org.opensaml.SAMLAuthenticationStatement;
@@ -73,6 +77,8 @@ import org.opensaml.SAMLResponse;
 import org.opensaml.SAMLSubject;
 import org.opensaml.XML;
 
+import edu.internet2.middleware.shibboleth.common.Credential;
+import edu.internet2.middleware.shibboleth.common.Credentials;
 import edu.internet2.middleware.shibboleth.metadata.AttributeAuthorityDescriptor;
 import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
 import edu.internet2.middleware.shibboleth.serviceprovider.ServiceProviderConfig.ApplicationInfo;
@@ -160,6 +166,9 @@ public class AttributeRequestor {
             return false;
         }
                
+        String credentialId = appinfo.getCredentialIdForEntity(entity);
+        if (credentialId!=null)
+            possiblySignRequest(config.getCredentials(), request, credentialId);
                
                // ShibBinding will extract URLs from the Metadata and build
                // parameters so SAML can create the session. It also interfaces
@@ -202,4 +211,38 @@ public class AttributeRequestor {
                return true;
        }
 
+    /**
+     * Given a credentialId from the CredentialUse/RelyingParty stuff,
+     * find a corresponding Credential element and use its Key/Cert to 
+     * sign the Request. 
+     * 
+     * @oaran credentials Credentials object from config file
+     * @param request SAML AA Query request
+     * @param credentialId Siging Id from CredentialUse
+     */
+       private static void possiblySignRequest(
+            Credentials credentials, 
+               SAMLRequest request,
+               String credentialId) {
+        
+        
+           if (credentials==null) {
+            log.error("No Credentials Element in SP Config file.");
+               return;
+        }
+           Credential credential = credentials.getCredential(credentialId);
+           if (credential==null) {
+            log.error("No credential found for id "+credentialId);
+               return;
+        }
+           Key key = credential.getPrivateKey();
+           X509Certificate[] certificateChain = credential.getX509CertificateChain();
+           try {
+               request.sign(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1,key,Arrays.asList(certificateChain));
+               log.debug("Attribute Request signed with "+credentialId);
+           } catch (SAMLException e) {
+               log.error("Unable to sign Attribute Request", e);
+           }
+       }
+
 }
index c444735..03e396c 100644 (file)
@@ -176,6 +176,8 @@ import x0.maceShibbolethTargetConfig1.SPConfigType;
 import x0.maceShibbolethTargetConfig1.ShibbolethTargetConfigDocument;
 import x0.maceShibbolethTargetConfig1.ApplicationDocument.Application;
 import x0.maceShibbolethTargetConfig1.ApplicationsDocument.Applications;
+import x0.maceShibbolethTargetConfig1.CredentialUseDocument.CredentialUse;
+import x0.maceShibbolethTargetConfig1.CredentialUseDocument.CredentialUse.RelyingParty;
 import x0.maceShibbolethTargetConfig1.HostDocument.Host;
 import x0.maceShibbolethTargetConfig1.HostDocument.Host.Scheme.Enum;
 import x0.maceShibbolethTargetConfig1.PathDocument.Path;
@@ -965,6 +967,61 @@ public class ServiceProviderConfig {
             return sessions.getTimeout();
         }
         
+        /**
+         * Given the EntityDescriptor of an IdP, find the RelyingParty
+         * element of the CredentialsUse section that matches the 
+         * Entity name or one of its parent group names and return
+         * the signing credential that should be used with it. If
+         * no specific match occurs, return the default siging
+         * credential. 
+         * 
+         * @param entity
+         * @return
+         */
+        String getCredentialIdForEntity(EntityDescriptor entity) {
+            
+            // Get the ID URI of the Entity and all its parent groups
+            EntitiesDescriptor entitiesDescriptor = entity.getEntitiesDescriptor();
+            ArrayList idlist = new ArrayList();
+            idlist.add(entity.getId());
+            // An EntityDescriptor must have a name, while groups may have names
+            while (entitiesDescriptor!=null) {
+                String edname = entitiesDescriptor.getName();
+                if (edname!=null)
+                    idlist.add(edname);
+                // Chain up to parent Element, until none left
+                entitiesDescriptor=entitiesDescriptor.getEntitiesDescriptor();
+            }
+            
+            // Get the default signing Credential ID and the RelyingParty overrides
+            CredentialUse credentialUse = applicationConfig.getCredentialUse();
+            if (credentialUse==null) {
+                // An <Application> may not have one, so look to the enclosing <Applications>
+                credentialUse = defaultApplicationInfo.applicationConfig.getCredentialUse();
+            }
+            if (credentialUse == null)
+                return null;  // If there is no CredentialsUse there is no signing
+            String defaultCredentialId = credentialUse.getSigning();
+            // If no signing= attribute (null), then don't sign
+            RelyingParty[] relyingPartyArray = credentialUse.getRelyingPartyArray();
+
+            // Search for a match of Entity/Group ID against an overriding RelyingParty
+            Iterator iterator = idlist.iterator();
+            while (iterator.hasNext()) {
+                String id = (String) iterator.next();
+                for (int i =0;i<relyingPartyArray.length;i++) {
+                    if (relyingPartyArray[i].getName().equals(id)) {
+                        // We have matched a RelyingParty override 
+                        String signingCredName = relyingPartyArray[i].getSigning();
+                        // If no signing= attribute (null), then don't sign
+                        return signingCredName;
+                    }
+                }
+            }
+            // No RelyingParty match, so use the default
+            return defaultCredentialId;
+        }
+        
                /**
                 * Return the current array of objects that implement the
                 * ...metadata.Metadata interface