Extend Trust checking to the SSL session to the AA
authorgilbert <gilbert@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Wed, 18 May 2005 20:45:45 +0000 (20:45 +0000)
committergilbert <gilbert@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Wed, 18 May 2005 20:45:45 +0000 (20:45 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@1523 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/serviceprovider/AttributeRequestor.java
src/edu/internet2/middleware/shibboleth/serviceprovider/ServiceProviderConfig.java
src/edu/internet2/middleware/shibboleth/serviceprovider/ShibBinding.java
src/edu/internet2/middleware/shibboleth/serviceprovider/ShibHttpHook.java [new file with mode: 0644]

index 12b11b9..432cb85 100644 (file)
@@ -163,7 +163,7 @@ public class AttributeRequestor {
                SAMLResponse response = null;
                try {
             ShibBinding binding = new ShibBinding(session.getApplicationId());
-                       response = binding.send(request,aa,null,null);
+                       response = binding.send(request,aa,null,null,appinfo);
                } catch (SAMLException e) {;} // response will be null
                if (response==null) {
                        log.error("AttributeRequestor Query to remote AA returned no response from "+session.getEntityId());
index 3d20bfb..4eaf6cb 100644 (file)
@@ -1159,5 +1159,11 @@ public class ServiceProviderConfig {
                super();
            }
        }
+
+
+
+    public Credentials getCredentials() {
+        return credentials;
+    }
        
 }
index 176dcff..a97f047 100644 (file)
@@ -33,8 +33,11 @@ import org.opensaml.SAMLBindingFactory;
 import org.opensaml.SAMLException;
 import org.opensaml.SAMLRequest;
 import org.opensaml.SAMLResponse;
+import org.opensaml.SAMLSOAPHTTPBinding;
 import org.opensaml.TrustException;
+import org.opensaml.provider.SOAPHTTPBindingProvider;
 
+import edu.internet2.middleware.shibboleth.common.Trust;
 import edu.internet2.middleware.shibboleth.metadata.AttributeAuthorityDescriptor;
 import edu.internet2.middleware.shibboleth.metadata.Endpoint;
 import edu.internet2.middleware.shibboleth.serviceprovider.ServiceProviderConfig.ApplicationInfo;
@@ -100,7 +103,8 @@ public class ShibBinding {
                        SAMLRequest req,
                        AttributeAuthorityDescriptor role,
                        String[] audiences,
-                       SAMLAuthorityBinding[] bindings) 
+                       SAMLAuthorityBinding[] bindings,
+            Trust trust) 
        throws SAMLException {
                
                // For the duration of the request, get local references to
@@ -147,6 +151,10 @@ public class ShibBinding {
                     prevBinding = endpoint.getBinding();
                     sbinding = SAMLBindingFactory.getInstance(endpoint.getBinding());
                 }
+                if (sbinding instanceof SAMLSOAPHTTPBinding) {
+                    SAMLSOAPHTTPBinding httpbind = (SAMLSOAPHTTPBinding)sbinding;
+                    httpbind.addHook(new ShibHttpHook(role,trust));
+                }
                 resp=sbinding.send(endpoint.getLocation(),req);
                 validateResponseSignatures(role, appinfo, resp);
                 return resp;
diff --git a/src/edu/internet2/middleware/shibboleth/serviceprovider/ShibHttpHook.java b/src/edu/internet2/middleware/shibboleth/serviceprovider/ShibHttpHook.java
new file mode 100644 (file)
index 0000000..04b3ca1
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * ShibHttpHook - Receive callbacks from OpenSAML HTTP Session processing.
+ * --------------------
+ * Copyright 2002, 2004 
+ * University Corporation for Advanced Internet Development, Inc. 
+ * All rights reserved
+ * [Thats all we have to say to protect ourselves]
+ * Your permission to use this code is governed by "The Shibboleth License".
+ * A copy may be found at http://shibboleth.internet2.edu/license.html
+ * [Nothing in copyright law requires license text in every file.]
+ * 
+ */
+package edu.internet2.middleware.shibboleth.serviceprovider;
+
+import java.net.HttpURLConnection;
+import java.net.Socket;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509KeyManager;
+import javax.net.ssl.X509TrustManager;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+import org.opensaml.SAMLException;
+import org.opensaml.SAMLSOAPHTTPBinding.HTTPHook;
+
+import edu.internet2.middleware.shibboleth.common.Credential;
+import edu.internet2.middleware.shibboleth.common.Credentials;
+import edu.internet2.middleware.shibboleth.common.Trust;
+import edu.internet2.middleware.shibboleth.metadata.AttributeAuthorityDescriptor;
+
+/**
+ * A callback object added to the SAML Binding by Shib. During
+ * HTTP session establishment and Request/Response processing 
+ * to the AA, SAML calls these exists. This code traps HTTPS
+ * sessions and adds a JSSE TrustManager to process Certificates.
+ * 
+ * @author Howard Gilbert
+ *
+ */
+public class ShibHttpHook implements HTTPHook {
+
+    private static Logger log = Logger.getLogger(HTTPHook.class);
+    
+    ServiceProviderContext context = ServiceProviderContext.getInstance();
+    ServiceProviderConfig config = context.getServiceProviderConfig();
+    Credentials credentials = config.getCredentials();
+    AttributeAuthorityDescriptor role;
+    Trust trust;
+    
+    /**
+     * @param role
+     */
+    public ShibHttpHook(AttributeAuthorityDescriptor role, Trust trust) {
+        super();
+        this.role = role;
+        this.trust = trust;
+    }
+
+    public boolean incoming(HttpServletRequest r, Object globalCtx,
+            Object callCtx) throws SAMLException {
+        // Not used
+        return true;
+    }
+
+    public boolean outgoing(HttpServletResponse r, Object globalCtx,
+            Object callCtx) throws SAMLException {
+        // Not used
+        return true;
+    }
+
+    public boolean incoming(HttpURLConnection conn, Object globalCtx,
+            Object callCtx) throws SAMLException {
+        // Not used
+        return true;
+    }
+
+    /**
+     * After the URLConnection has been initialized and before 
+     * the connect() method is called, this exit has a chance to
+     * do additional processing.
+     * 
+     * <p>If this is an HTTPS session, configure the SocketFactory
+     * to use a custom TrustManager for Certificate processing.</p>
+     */
+    public boolean outgoing(HttpURLConnection conn, Object globalCtx,
+            Object callCtx) throws SAMLException {
+        if (!(conn instanceof HttpsURLConnection)) {
+            return true; // http: sessions need no processing
+        }
+        HttpsURLConnection sslconn = (HttpsURLConnection) conn;
+        SSLContext sslContext = null;
+        try {
+            sslContext = SSLContext.getInstance("SSL");
+        } catch (NoSuchAlgorithmException e) {
+            log.error("Cannot find required SSL support");
+            return true;
+        }
+        TrustManager[] tms = new TrustManager[] {new ShibTrustManager()};
+        KeyManager[] kms = new KeyManager[] {new ShibKeyManager()};
+        try {
+            sslContext.init(kms,tms,new java.security.SecureRandom());
+        } catch (KeyManagementException e) {
+            return false;
+        }
+        SSLSocketFactory socketFactory = sslContext.getSocketFactory();
+        sslconn.setSSLSocketFactory(socketFactory);
+        return true;
+    }
+    
+    /**
+     * Called to select the Client Certificate the SP will present to 
+     * the AA.
+     * 
+     * <p>Normally a user KeyManager extends some class backed by a 
+     * KeyStore. It just chooses an alias, and lets the parent class 
+     * do the dirty work of extracting the Certificate chain from the 
+     * backing file. However, in Shibboleth the SP Credentials come
+     * from the configuration file and are in memory. There is no
+     * meaningful alias, so we make one up.
+     */
+    class ShibKeyManager implements X509KeyManager {
+        
+        public String fred ="Fred";
+        public String[] freds = {fred};
+
+        public String[] getClientAliases(String arg0, Principal[] arg1) {
+            return freds;
+        }
+
+        public String chooseClientAlias(String[] arg0, Principal[] arg1, Socket arg2) {
+            return fred;
+        }
+
+        public String[] getServerAliases(String arg0, Principal[] arg1) {
+            return freds;
+        }
+
+        public String chooseServerAlias(String arg0, Principal[] arg1, Socket arg2) {
+            return fred;
+        }
+
+        public X509Certificate[] getCertificateChain(String arg0) {
+            Credential credential = credentials.getCredential();
+            X509Certificate[] certificateChain = credential.getX509CertificateChain();
+            return certificateChain;
+        }
+
+        public PrivateKey getPrivateKey(String arg0) {
+            // TODO Get the SP Private Key from the Credentials object.
+            Credential credential = credentials.getCredential();
+            PrivateKey privateKey = credential.getPrivateKey();
+            return privateKey;
+        }
+        
+    }
+    
+    /**
+     * Called to approve or reject the Server Certificate of the AA.
+     */
+    class ShibTrustManager  implements X509TrustManager {
+
+        public X509Certificate[] getAcceptedIssuers() {
+            // Not needed, the Server has only one Certificate to send us.
+            return new X509Certificate[0]; 
+        }
+        
+        public void checkClientTrusted(X509Certificate[] arg0, String arg1) 
+            throws CertificateException {
+            // Not used, we are the client
+        }
+
+        public void checkServerTrusted(X509Certificate[] certs, String arg1) 
+            throws CertificateException {
+            if (trust.validate(certs[0],certs,role))
+                return;
+            //throw new CertificateException("Cannot validate AA Server Certificate in Metadata");
+            
+        }
+        
+    }
+
+}