Finished draft of the Shibboleth Trust Engine. Added a few more unit tests. Still...
authorwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Wed, 2 Aug 2006 21:23:32 +0000 (21:23 +0000)
committerwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Wed, 2 Aug 2006 21:23:32 +0000 (21:23 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@1989 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

data/metadata12.xml [new file with mode: 0644]
data/metadata13.xml [new file with mode: 0644]
src/edu/internet2/middleware/shibboleth/common/provider/ShibbolethTrustEngine.java
tests/edu/internet2/middleware/shibboleth/common/TrustTests.java

diff --git a/data/metadata12.xml b/data/metadata12.xml
new file mode 100644 (file)
index 0000000..48ca720
--- /dev/null
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<EntitiesDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" 
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+       xsi:schemaLocation="urn:oasis:names:tc:SAML:2.0:metadata ../schemas/sstc-saml-schema-metadata-2.0.xsd urn:mace:shibboleth:metadata:1.0 ../schemas/shibboleth-metadata-1.0.xsd" 
+       Name="urn-x:testFed1" validUntil="3010-01-01T00:00:00Z">
+                <Extensions>
+                       <KeyAuthority xmlns="urn:mace:shibboleth:metadata:1.0">
+                               <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+                                       <ds:X509Data>
+                                               <ds:X509Certificate>MIIC9zCCArQCBEJMcbswCwYHKoZIzjgEAwUAMGExCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJUTjEQ
+MA4GA1UEBxMHTWVtcGhpczENMAsGA1UEChMEVGVzdDENMAsGA1UECxMEVGVzdDEVMBMGA1UEAxMM
+V2FsdGVyIEhvZWhuMB4XDTA1MDMzMTIxNTUwN1oXDTA1MDYyOTIxNTUwN1owYTELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgTAlROMRAwDgYDVQQHEwdNZW1waGlzMQ0wCwYDVQQKEwRUZXN0MQ0wCwYDVQQL
+EwRUZXN0MRUwEwYDVQQDEwxXYWx0ZXIgSG9laG4wggG3MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9T
+gR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv
+8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HX
+Ku/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSv
+u/o66oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64e
+K7OmdZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBhAAC
+gYBGtD+qJdBIzaA/a0oeO/LhW06r9dsPz0LnBD7DLZAFaWpMbfaItwXWANCFleNPzou/mU8+bhOe
+FJ+fkGdW4zbg8lzLOOeRduELoO8srzOdyccmRIeRIkDVj0ckienw0skgKgAvilUWkDQcdpLvtfjl
+W7vFedSYzRQiLso+dFHanDALBgcqhkjOOAQDBQADMAAwLQIUU5z1Ppc7gbjkl3PhkiQghUoTm5YC
+FQCVg3Ej3Sdb8FpJwUXoqO4J6FU/UQ==</ds:X509Certificate>
+                                       </ds:X509Data>
+                               </ds:KeyInfo>
+                       </KeyAuthority>
+               </Extensions>
+       
+       <EntitiesDescriptor Name="urn-x:testFed2" validUntil="3010-01-01T00:00:00Z">
+               
+               <Extensions>
+                       <KeyAuthority xmlns="urn:mace:shibboleth:metadata:1.0">
+                               <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+                                       <ds:X509Data>
+                                               <ds:X509Certificate>MIIFljCCBH6gAwIBAgIKH/K2qwACAABIojANBgkqhkiG9w0BAQUFADCBizETMBEG
+CgmSJomT8ixkARkWA2NvbTEZMBcGCgmSJomT8ixkARkWCW1pY3Jvc29mdDEUMBIG
+CgmSJomT8ixkARkWBGNvcnAxFzAVBgoJkiaJk/IsZAEZFgdyZWRtb25kMSowKAYD
+VQQDEyFNaWNyb3NvZnQgU2VjdXJlIFNlcnZlciBBdXRob3JpdHkwHhcNMDYwMjI0
+MDQzMTQwWhcNMDcwMjIzMjM1OTAwWjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMK
+d2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDESMBAGA1UEChMJTWljcm9zb2Z0
+MQ4wDAYDVQQLEwVtc2NvbTEaMBgGA1UEAxMRd3d3Lm1pY3Jvc29mdC5jb20wgZ8w
+DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANuMj/J7Wx5HY9ZS4HWt8pDs8iw1omJB
+E3XXC6aVaIZGwO5PY3+bSzd/kW5qCp/wbzmnwO/ZKsoF388WqqR/CaIxVn2rtioa
+CvJrAQLvTMA11pIr/eucUxWwm3TBarKZ11eSXY7vbaiE1v5kQdKetsn5iFZq44Bq
+4Uv94vj4DYonAgMBAAGjggKUMIICkDALBgNVHQ8EBAMCBaAwRAYJKoZIhvcNAQkP
+BDcwNTAOBggqhkiG9w0DAgICAIAwDgYIKoZIhvcNAwQCAgCAMAcGBSsOAwIHMAoG
+CCqGSIb3DQMHMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAdBgNVHQ4E
+FgQUQ8Gx8LWwzk5b0GDKYl3sA8Q/iKYwHwYDVR0jBBgwFoAU3ywh0+MZc7xLYRMc
+YOpLveauIEQwga8GA1UdHwSBpzCBpDCBoaCBnqCBm4ZWaHR0cDovL2NybC5taWNy
+b3NvZnQuY29tL3BraS9tc2NvcnAvY3JsL01pY3Jvc29mdCUyMFNlY3VyZSUyMFNl
+cnZlciUyMEF1dGhvcml0eSgyKS5jcmyGQWh0dHA6Ly9jb3JwcGtpL2NybC9NaWNy
+b3NvZnQlMjBTZWN1cmUlMjBTZXJ2ZXIlMjBBdXRob3JpdHkoMikuY3JsMIG/Bggr
+BgEFBQcBAQSBsjCBrzBeBggrBgEFBQcwAoZSaHR0cDovL3d3dy5taWNyb3NvZnQu
+Y29tL3BraS9tc2NvcnAvTWljcm9zb2Z0JTIwU2VjdXJlJTIwU2VydmVyJTIwQXV0
+aG9yaXR5KDIpLmNydDBNBggrBgEFBQcwAoZBaHR0cDovL2NvcnBwa2kvYWlhL01p
+Y3Jvc29mdCUyMFNlY3VyZSUyMFNlcnZlciUyMEF1dGhvcml0eSgyKS5jcnQwPwYJ
+KwYBBAGCNxUHBDIwMAYoKwYBBAGCNxUIg8+JTa3yAoWhnwyC+sp9geH7dIFPg8Lt
+hQiOqdKFYwIBZAIBBTAnBgkrBgEEAYI3FQoEGjAYMAoGCCsGAQUFBwMCMAoGCCsG
+AQUFBwMBMA0GCSqGSIb3DQEBBQUAA4IBAQAmQtBEm56c8qB5rP2eHLU+RpnAVwny
+CKdJAxiYKb6CZMbKY12whT8ELobDVvMfjyUMPR6PMddmGAAntCF2sdmHub8VHalz
+N1vZbqLoh6/cR5OhKOCkZZl0C7vHDFaePjhJffhyRhieUVjpfk72/fVoILYspfsm
+p1awMRyErw9Pfy2NLyBWxp76sWvRPmXb1Ub/fkvbIRMLM7BeVhGEciyT6veUf68F
+jtrVS9AdClEqzf/vMCJq6mQgRUb54hlqRFU8h6P2tr8tX2LcQKMUT/GkwxF3i/Zk
+0tJpZJwwYV6UDe11KTDTLO205cI46Mnr4Va4Di7xd1jn7QobrSMN+Vfp</ds:X509Certificate>
+                                       </ds:X509Data>
+                               </ds:KeyInfo>
+                       </KeyAuthority>
+               </Extensions>
+               
+               <EntityDescriptor entityID="urn-x:testSP1">
+               
+               <SPSSODescriptor 
+                       protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol">
+                       <KeyDescriptor use="signing">
+                               <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+                                       <ds:KeyName>CN=Walter Hoehn, OU=Test, O=Test, L=Memphis, ST=TN, C=US</ds:KeyName>
+                               </ds:KeyInfo>
+                       </KeyDescriptor>
+                       <NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat>
+                       <AssertionConsumerService index="1" 
+                               Binding="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" 
+                               Location="https://www.example.org/Shibboleth.shire"/>
+               </SPSSODescriptor>
+               
+       </EntityDescriptor>
+       </EntitiesDescriptor>
+</EntitiesDescriptor>
\ No newline at end of file
diff --git a/data/metadata13.xml b/data/metadata13.xml
new file mode 100644 (file)
index 0000000..536ccba
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<EntitiesDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" 
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+       xsi:schemaLocation="urn:oasis:names:tc:SAML:2.0:metadata ../schemas/sstc-saml-schema-metadata-2.0.xsd urn:mace:shibboleth:metadata:1.0 ../schemas/shibboleth-metadata-1.0.xsd" 
+       Name="urn-x:testFed1" validUntil="3010-01-01T00:00:00Z">
+                <Extensions>
+                       <KeyAuthority xmlns="urn:mace:shibboleth:metadata:1.0">
+                               <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+                                       <ds:X509Data>
+                                               <ds:X509Certificate>MIIFljCCBH6gAwIBAgIKH/K2qwACAABIojANBgkqhkiG9w0BAQUFADCBizETMBEG
+CgmSJomT8ixkARkWA2NvbTEZMBcGCgmSJomT8ixkARkWCW1pY3Jvc29mdDEUMBIG
+CgmSJomT8ixkARkWBGNvcnAxFzAVBgoJkiaJk/IsZAEZFgdyZWRtb25kMSowKAYD
+VQQDEyFNaWNyb3NvZnQgU2VjdXJlIFNlcnZlciBBdXRob3JpdHkwHhcNMDYwMjI0
+MDQzMTQwWhcNMDcwMjIzMjM1OTAwWjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMK
+d2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDESMBAGA1UEChMJTWljcm9zb2Z0
+MQ4wDAYDVQQLEwVtc2NvbTEaMBgGA1UEAxMRd3d3Lm1pY3Jvc29mdC5jb20wgZ8w
+DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANuMj/J7Wx5HY9ZS4HWt8pDs8iw1omJB
+E3XXC6aVaIZGwO5PY3+bSzd/kW5qCp/wbzmnwO/ZKsoF388WqqR/CaIxVn2rtioa
+CvJrAQLvTMA11pIr/eucUxWwm3TBarKZ11eSXY7vbaiE1v5kQdKetsn5iFZq44Bq
+4Uv94vj4DYonAgMBAAGjggKUMIICkDALBgNVHQ8EBAMCBaAwRAYJKoZIhvcNAQkP
+BDcwNTAOBggqhkiG9w0DAgICAIAwDgYIKoZIhvcNAwQCAgCAMAcGBSsOAwIHMAoG
+CCqGSIb3DQMHMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAdBgNVHQ4E
+FgQUQ8Gx8LWwzk5b0GDKYl3sA8Q/iKYwHwYDVR0jBBgwFoAU3ywh0+MZc7xLYRMc
+YOpLveauIEQwga8GA1UdHwSBpzCBpDCBoaCBnqCBm4ZWaHR0cDovL2NybC5taWNy
+b3NvZnQuY29tL3BraS9tc2NvcnAvY3JsL01pY3Jvc29mdCUyMFNlY3VyZSUyMFNl
+cnZlciUyMEF1dGhvcml0eSgyKS5jcmyGQWh0dHA6Ly9jb3JwcGtpL2NybC9NaWNy
+b3NvZnQlMjBTZWN1cmUlMjBTZXJ2ZXIlMjBBdXRob3JpdHkoMikuY3JsMIG/Bggr
+BgEFBQcBAQSBsjCBrzBeBggrBgEFBQcwAoZSaHR0cDovL3d3dy5taWNyb3NvZnQu
+Y29tL3BraS9tc2NvcnAvTWljcm9zb2Z0JTIwU2VjdXJlJTIwU2VydmVyJTIwQXV0
+aG9yaXR5KDIpLmNydDBNBggrBgEFBQcwAoZBaHR0cDovL2NvcnBwa2kvYWlhL01p
+Y3Jvc29mdCUyMFNlY3VyZSUyMFNlcnZlciUyMEF1dGhvcml0eSgyKS5jcnQwPwYJ
+KwYBBAGCNxUHBDIwMAYoKwYBBAGCNxUIg8+JTa3yAoWhnwyC+sp9geH7dIFPg8Lt
+hQiOqdKFYwIBZAIBBTAnBgkrBgEEAYI3FQoEGjAYMAoGCCsGAQUFBwMCMAoGCCsG
+AQUFBwMBMA0GCSqGSIb3DQEBBQUAA4IBAQAmQtBEm56c8qB5rP2eHLU+RpnAVwny
+CKdJAxiYKb6CZMbKY12whT8ELobDVvMfjyUMPR6PMddmGAAntCF2sdmHub8VHalz
+N1vZbqLoh6/cR5OhKOCkZZl0C7vHDFaePjhJffhyRhieUVjpfk72/fVoILYspfsm
+p1awMRyErw9Pfy2NLyBWxp76sWvRPmXb1Ub/fkvbIRMLM7BeVhGEciyT6veUf68F
+jtrVS9AdClEqzf/vMCJq6mQgRUb54hlqRFU8h6P2tr8tX2LcQKMUT/GkwxF3i/Zk
+0tJpZJwwYV6UDe11KTDTLO205cI46Mnr4Va4Di7xd1jn7QobrSMN+Vfp</ds:X509Certificate>
+                                       </ds:X509Data>
+                               </ds:KeyInfo>
+                       </KeyAuthority>                 
+                       <KeyAuthority xmlns="urn:mace:shibboleth:metadata:1.0">
+                               <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+                                       <ds:X509Data>
+                                               <ds:X509Certificate>MIIC9zCCArQCBEJMcbswCwYHKoZIzjgEAwUAMGExCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJUTjEQ
+MA4GA1UEBxMHTWVtcGhpczENMAsGA1UEChMEVGVzdDENMAsGA1UECxMEVGVzdDEVMBMGA1UEAxMM
+V2FsdGVyIEhvZWhuMB4XDTA1MDMzMTIxNTUwN1oXDTA1MDYyOTIxNTUwN1owYTELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgTAlROMRAwDgYDVQQHEwdNZW1waGlzMQ0wCwYDVQQKEwRUZXN0MQ0wCwYDVQQL
+EwRUZXN0MRUwEwYDVQQDEwxXYWx0ZXIgSG9laG4wggG3MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9T
+gR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv
+8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HX
+Ku/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSv
+u/o66oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64e
+K7OmdZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBhAAC
+gYBGtD+qJdBIzaA/a0oeO/LhW06r9dsPz0LnBD7DLZAFaWpMbfaItwXWANCFleNPzou/mU8+bhOe
+FJ+fkGdW4zbg8lzLOOeRduELoO8srzOdyccmRIeRIkDVj0ckienw0skgKgAvilUWkDQcdpLvtfjl
+W7vFedSYzRQiLso+dFHanDALBgcqhkjOOAQDBQADMAAwLQIUU5z1Ppc7gbjkl3PhkiQghUoTm5YC
+FQCVg3Ej3Sdb8FpJwUXoqO4J6FU/UQ==</ds:X509Certificate>
+                                       </ds:X509Data>
+                               </ds:KeyInfo>
+                       </KeyAuthority>
+               </Extensions>
+       
+       <EntitiesDescriptor Name="urn-x:testFed2" validUntil="3010-01-01T00:00:00Z">
+               <EntityDescriptor entityID="urn-x:testSP1">
+               <SPSSODescriptor 
+                       protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol">
+                       <KeyDescriptor use="signing">
+                               <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+                                       <ds:KeyName>CN=Walter Hoehn, OU=Test, O=Test, L=Memphis, ST=TN, C=US</ds:KeyName>
+                               </ds:KeyInfo>
+                       </KeyDescriptor>
+                       <NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat>
+                       <AssertionConsumerService index="1" 
+                               Binding="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" 
+                               Location="https://www.example.org/Shibboleth.shire"/>
+               </SPSSODescriptor>
+               
+       </EntityDescriptor>
+       </EntitiesDescriptor>
+</EntitiesDescriptor>
\ No newline at end of file
index 159b22a..df287d8 100644 (file)
@@ -5,6 +5,7 @@ import java.security.cert.X509CRL;
 import java.security.cert.X509Certificate;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Set;
 
@@ -90,72 +91,34 @@ public class ShibbolethTrustEngine extends InlinePKIKeyTrustEngine implements Tr
 
                private class ShibPKIXMetadata implements Iterator<PKIXValidationInformation> {
 
-                       private EntityDescriptor root;
-                       private EntitiesDescriptor currentParent;
+                       private ExtensionPoint currentExtensionPointRoot;
 
                        private ShibPKIXMetadata(EntityDescriptor entity) {
 
-                               this.root = entity;
+                               currentExtensionPointRoot = new ExtensionPoint(entity);
                        }
 
-                       private ElementProxy getNextKeyAuthority(boolean consume) {
+                       public boolean hasNext() {
 
-                               Extensions extensions = null;
-System.err.println("entity part.");
-                               // Look for an unconsumed key authority on the entity descriptor first
-                               if (root != null) {
-                                       extensions = root.getExtensions();
-                                       if (consume) {
-                                               if (root.getParent() instanceof EntitiesDescriptor) {
-                                                       currentParent = (EntitiesDescriptor) root.getParent();
-                                               }
-                                               root = null;
-                                       }
-                               }
+                               return (getNextKeyAuthority(currentExtensionPointRoot, false) != null);
+                       }
 
-                               if (extensions != null) {
-                                       for (XMLObject extension : extensions.getUnknownXMLObjects()) {
-                                               if (extension.getElementQName().equals(KEY_AUTHORITY) && extension instanceof ElementProxy) {
-                                                       log.debug("Using Key Authority from entity descriptor.");
-                                                       return (ElementProxy) extension;
-                                               }
-                                       }
-                               }
-System.err.println("entities part.");
-                               // Alright, we didn't find one... try the parent
-                               while (currentParent != null) {
-System.err.println("foobar");
-                                       extensions = currentParent.getExtensions();
-                                       if (consume) {
-                                               if (currentParent.getParent() instanceof EntitiesDescriptor) {
-                                                       currentParent = (EntitiesDescriptor) currentParent.getParent();
-                                               }
-                                       }
+                       public PKIXValidationInformation next() {
 
-                                       if (extensions != null) {
-                                               for (XMLObject extension : extensions.getUnknownXMLObjects()) {
-                                                       if (extension.getElementQName().equals(KEY_AUTHORITY) && extension instanceof ElementProxy) {
-                                                               log.debug("Using Key Authority from entities descriptor.");
-                                                               return (ElementProxy) extension;
-                                                       }
-                                               }
-                                       }
-                               }
+                               // Construct PKIX validation information from Shib metadata
+                               ElementProxy keyAuthority = getNextKeyAuthority(currentExtensionPointRoot, true);
+                               if (keyAuthority == null) { throw new NoSuchElementException(); }
+
+                               return convertMetadatatoValidationInfo(keyAuthority);
 
-                               return null;
                        }
 
-                       public boolean hasNext() {
+                       public void remove() {
 
-                               System.err.println("hasNext()");
-                               return (getNextKeyAuthority(false) != null);
+                               throw new UnsupportedOperationException();
                        }
 
-                       public PKIXValidationInformation next() {
-System.err.println("next()");
-                               // Construct PKIX validation information from Shib metadata
-                               ElementProxy keyAuthority = getNextKeyAuthority(true);
-                               if (keyAuthority == null) { throw new NoSuchElementException(); }
+                       private PKIXValidationInformation convertMetadatatoValidationInfo(ElementProxy keyAuthority) {
 
                                // Find the verification depth for all anchors in this set
                                int verifyDepth = 1;
@@ -185,12 +148,81 @@ System.err.println("next()");
                                                + " Trust Anchors: " + trustAnchors.size() + " Revocation Lists: " + revocationLists.size()
                                                + ".");
                                return new PKIXValidationInformation(1, trustAnchors, revocationLists);
+                       }
+
+                       private ElementProxy getNextKeyAuthority(ExtensionPoint extensionPoint, boolean consume) {
 
+                               if (extensionPoint == null) { return null; } // Can't recurse further
+
+                               Extensions extensions = extensionPoint.getExtensions();
+
+                               // Check this descriptor for a key authority
+                               // The complication is that a particular descriptor can have more than one key authority, which is why
+                               // we need this "consumedIndex" business to keep track of which ones we've processed so far
+                               if (extensions != null) {
+                                       List<XMLObject> xmlObjects = extensions.getUnknownXMLObjects();
+                                       for (int i = extensionPoint.consumedIndex; i < xmlObjects.size(); i++) {
+
+                                               if (xmlObjects.get(i).getElementQName().equals(KEY_AUTHORITY)
+                                                               && xmlObjects.get(i) instanceof ElementProxy) {
+                                                       log.debug("Found Key Authority element in metadata.");
+                                                       if (consume && extensionPoint.consumedIndex == xmlObjects.size()) {
+                                                               currentExtensionPointRoot = new ExtensionPoint(extensionPoint.getParent());
+
+                                                       } else if (consume) {
+                                                               currentExtensionPointRoot = extensionPoint;
+                                                               extensionPoint.consumedIndex = i + 1;
+                                                       }
+                                                       return (ElementProxy) xmlObjects.get(i);
+                                               }
+                                       }
+                               }
+
+                               // If we don't find anything, recurse back through the parentso
+                               if (extensionPoint.getParent() != null) { return getNextKeyAuthority(new ExtensionPoint(extensionPoint
+                                               .getParent()), consume); }
+
+                               return null;
                        }
 
-                       public void remove() {
+                       class ExtensionPoint {
+
+                               private EntityDescriptor entity;
+                               private EntitiesDescriptor entities;
+                               int consumedIndex = 0;
+
+                               private ExtensionPoint(EntityDescriptor entity) {
+
+                                       this.entity = entity;
+                               }
+
+                               private ExtensionPoint(EntitiesDescriptor entities) {
+
+                                       this.entities = entities;
+                               }
+
+                               private Extensions getExtensions() {
+
+                                       if (entity != null) {
+                                               return entity.getExtensions();
+                                       } else if (entities != null) {
+                                               return entities.getExtensions();
+                                       } else {
+                                               return null;
+                                       }
+                               }
+
+                               private EntitiesDescriptor getParent() {
+
+                                       if (entity != null && entity.getParent() instanceof EntitiesDescriptor) {
+                                               return (EntitiesDescriptor) entity.getParent();
+                                       } else if (entities != null && entities.getParent() instanceof EntitiesDescriptor) {
+                                               return (EntitiesDescriptor) entities.getParent();
+                                       } else {
+                                               return null;
+                                       }
+                               }
 
-                               throw new UnsupportedOperationException();
                        }
 
                }
index 31521a3..59a703a 100644 (file)
@@ -51,7 +51,7 @@ public class TrustTests extends TestCase {
                super(name);
                BasicConfigurator.resetConfiguration();
                BasicConfigurator.configure();
-               Logger.getRootLogger().setLevel(Level.OFF);
+               Logger.getRootLogger().setLevel(Level.DEBUG);
        }
 
        public static void main(String[] args) {
@@ -244,6 +244,79 @@ public class TrustTests extends TestCase {
                }
        }
 
+       public void testPkixX509CertValidateRecurseEntitiesWBadFirst() {
+
+               try {
+                       // Pull the role descriptor from example metadata
+                       MetadataProvider metadata = new FilesystemMetadataProvider(new File("data/metadata12.xml"));
+                       EntityDescriptor entity = metadata.getEntityDescriptor("urn-x:testSP1");
+                       SPSSODescriptor role = (SPSSODescriptor) entity.getSPSSODescriptor("urn:oasis:names:tc:SAML:1.1:protocol");
+
+                       // Use a pre-defined cert
+                       KeyStore keyStore = KeyStore.getInstance("JKS");
+                       keyStore.load(new ShibResource(new File("data/trusttest.jks").toURL().toString()).getInputStream(),
+                                       new char[]{'t', 'e', 's', 't', '1', '2', '3'});
+                       X509Certificate cert = (X509Certificate) keyStore.getCertificate("inliine1");
+
+                       // Try to validate against the metadata
+                       TrustEngine<X509EntityCredential> validator = new ShibbolethTrustEngine();
+                       boolean successful = validator.validate(new SimpleX509EntityCredential(Arrays
+                                       .asList(new X509Certificate[]{cert})), role);
+                       if (!successful) {
+                               fail("Validation should have succeeded.");
+                       }
+
+               } catch (MetadataProviderException e) {
+                       fail("Error in test specification: " + e);
+               } catch (ResourceNotAvailableException e) {
+                       fail("Error in test specification: " + e);
+               } catch (IOException e) {
+                       fail("Error in test specification: " + e);
+               } catch (NoSuchAlgorithmException e) {
+                       fail("Error in test specification: " + e);
+               } catch (CertificateException e) {
+                       fail("Error in test specification: " + e);
+               } catch (KeyStoreException e) {
+                       fail("Error in test specification: " + e);
+               }
+       }
+       public void testPkixX509CertValidateRecurseEntitiesWMultipleKeyAuthoritiesOnOneDescriptor() {
+
+               try {
+                       // Pull the role descriptor from example metadata
+                       MetadataProvider metadata = new FilesystemMetadataProvider(new File("data/metadata13.xml"));
+                       EntityDescriptor entity = metadata.getEntityDescriptor("urn-x:testSP1");
+                       SPSSODescriptor role = (SPSSODescriptor) entity.getSPSSODescriptor("urn:oasis:names:tc:SAML:1.1:protocol");
+
+                       // Use a pre-defined cert
+                       KeyStore keyStore = KeyStore.getInstance("JKS");
+                       keyStore.load(new ShibResource(new File("data/trusttest.jks").toURL().toString()).getInputStream(),
+                                       new char[]{'t', 'e', 's', 't', '1', '2', '3'});
+                       X509Certificate cert = (X509Certificate) keyStore.getCertificate("inliine1");
+
+                       // Try to validate against the metadata
+                       TrustEngine<X509EntityCredential> validator = new ShibbolethTrustEngine();
+                       boolean successful = validator.validate(new SimpleX509EntityCredential(Arrays
+                                       .asList(new X509Certificate[]{cert})), role);
+                       if (!successful) {
+                               fail("Validation should have succeeded.");
+                       }
+
+               } catch (MetadataProviderException e) {
+                       fail("Error in test specification: " + e);
+               } catch (ResourceNotAvailableException e) {
+                       fail("Error in test specification: " + e);
+               } catch (IOException e) {
+                       fail("Error in test specification: " + e);
+               } catch (NoSuchAlgorithmException e) {
+                       fail("Error in test specification: " + e);
+               } catch (CertificateException e) {
+                       fail("Error in test specification: " + e);
+               } catch (KeyStoreException e) {
+                       fail("Error in test specification: " + e);
+               }
+       }
+
        public void testPkixX509CertValidateWithCAPath() {
 
                try {