Validate Signatures
authorgilbert <gilbert@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 12 Apr 2005 18:26:05 +0000 (18:26 +0000)
committergilbert <gilbert@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 12 Apr 2005 18:26:05 +0000 (18:26 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@1397 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/common/provider/BasicTrust.java
src/edu/internet2/middleware/shibboleth/common/provider/ShibbolethTrust.java

index e383026..5fd3d62 100644 (file)
@@ -25,6 +25,7 @@
 
 package edu.internet2.middleware.shibboleth.common.provider;
 
+import java.security.PublicKey;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
@@ -33,6 +34,7 @@ import java.util.Iterator;
 import org.apache.log4j.Logger;
 import org.apache.xml.security.keys.KeyInfo;
 import org.apache.xml.security.keys.keyresolver.KeyResolverException;
+import org.opensaml.SAMLException;
 import org.opensaml.SAMLSignedObject;
 
 import edu.internet2.middleware.shibboleth.common.Trust;
@@ -104,13 +106,29 @@ public class BasicTrust implements Trust {
      * @see edu.internet2.middleware.shibboleth.common.Trust#validate(org.opensaml.SAMLSignedObject, edu.internet2.middleware.shibboleth.metadata.RoleDescriptor)
      */
     public boolean validate(SAMLSignedObject token, RoleDescriptor descriptor) {
-        // TODO Auto-generated method stub
-        
-        /*
-         * Proposed algorithm for this is just to walk each KeyDescriptor with keyUse of signing
-         * and try and extract a public key to use and try and verify the token. If it works, we're
-         * done.
-         */ 
+               /*
+                * Run through the Role Metadata testing Public Keys 
+                */
+               Iterator ikeyDescriptors = descriptor.getKeyDescriptors();
+               while (ikeyDescriptors.hasNext()) {
+                       KeyDescriptor keyDescriptor = (KeyDescriptor) ikeyDescriptors.next();
+                       if (keyDescriptor.getUse()!=KeyDescriptor.ENCRYPTION) {
+                               // KeyInfo can be used for signing
+                               KeyInfo keyInfo = keyDescriptor.getKeyInfo();
+                               try {
+                                       // XMLSEC drills down to extract a Public Key
+                                       PublicKey publicKey = keyInfo.getPublicKey();
+                                       try {
+                                               token.verify(publicKey);
+                                               return true;
+                                       } catch(SAMLException e) {
+                                               continue;
+                                       }
+                               } catch (KeyResolverException e) {
+                                       continue;
+                               }
+                       }
+               }
         return false;
     }
 }
\ No newline at end of file
index 63da40b..b70e435 100644 (file)
@@ -59,6 +59,7 @@ import org.apache.xml.security.keys.content.KeyName;
 import org.apache.xml.security.keys.content.X509Data;
 import org.apache.xml.security.keys.content.x509.XMLX509CRL;
 import org.apache.xml.security.keys.content.x509.XMLX509Certificate;
+import org.opensaml.SAMLException;
 import org.opensaml.SAMLSignedObject;
 
 import edu.internet2.middleware.shibboleth.common.Trust;
@@ -92,16 +93,42 @@ public class ShibbolethTrust extends BasicTrust implements Trust {
      * @see edu.internet2.middleware.shibboleth.common.Trust#validate(org.opensaml.SAMLSignedObject, edu.internet2.middleware.shibboleth.metadata.RoleDescriptor)
      */
     public boolean validate(SAMLSignedObject token, RoleDescriptor descriptor) {
-        // TODO Auto-generated method stub
-        
-        /*
-         * Proposed algorithm for this (will modify C++ to match:
-         * 
-         * - get the certificates from the token
-         * - iterate over them in order, until one verifies the signature
-         * - pass that as the EE cert to the other validate method, with the full set as a chain
-         */ 
-        return false;
+               if (super.validate(token,descriptor))
+                       return true;
+               
+               /* Certificates supplied with the signed object */
+               ArrayList/*<X509Certificate>*/ certificates = new ArrayList/*<X509Certificate>*/();
+               X509Certificate certificateEE = null;
+               
+               /* Iterate to count the certificates, and look for the signer */
+               Iterator icertificates;
+               try {
+                       icertificates = token.getX509Certificates();
+               } catch (SAMLException e1) {
+                       return false;
+               }
+               while (icertificates.hasNext()) {
+                       X509Certificate certificate = (X509Certificate) icertificates.next();
+                       try {
+                               token.verify(certificate);
+                               // This is the certificate that signed the object
+                               certificateEE = certificate;
+                               certificates.add(certificate);
+                       } catch (SAMLException e) {
+                               certificates.add(certificate);
+                       }
+               }
+               
+               if (certificateEE==null)
+                       return false; // No key validates the signature
+               
+               // With a count we can now build a typed array
+               X509Certificate[] certificateChain = new X509Certificate[certificates.size()];
+               int i=0;
+               for (icertificates = certificates.iterator();icertificates.hasNext();) {
+                       certificateChain[i++]=(X509Certificate) icertificates.next();
+               }
+               return validate(certificateEE, certificateChain, descriptor);   
     }
 
     /*