net.sf.taverna.t2.security.credentialmanager.impl.HTTPSConnectionAndTrustConfirmationIT.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.taverna.t2.security.credentialmanager.impl.HTTPSConnectionAndTrustConfirmationIT.java

Source

/*******************************************************************************
 * Copyright (C) 2008-2010 The University of Manchester   
 * 
 *  Modifications to the initial code base are copyright of their
 *  respective authors, or their employers as appropriate.
 * 
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2.1 of
 *  the License, or (at your option) any later version.
 *    
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *    
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 ******************************************************************************/
package net.sf.taverna.t2.security.credentialmanager.impl;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.TrustManagerFactory;

import net.sf.taverna.t2.security.credentialmanager.CMException;
import net.sf.taverna.t2.security.credentialmanager.MasterPasswordProvider;
import net.sf.taverna.t2.security.credentialmanager.TrustConfirmationProvider;

import org.apache.commons.io.FileUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
//import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class HTTPSConnectionAndTrustConfirmationIT {

    private static CredentialManagerImpl credentialManager;
    private static DummyMasterPasswordProvider masterPasswordProvider;
    private static File credentialManagerDirectory;
    //private static URL trustedCertficateFileURL = HTTPSConnectionAndTrustConfirmationIT.class.getResource("/security/tomcat_heater_certificate.pem");

    // Log4J Logger
    //private static Logger logger = Logger.getLogger(HTTPSConnectionAndTrustConfirmationIT.class);

    //   public static void main(String[] args){
    //      
    //      try {
    //         CredentialManagerOld.initialiseSSL();
    //         //CredentialManager.getInstance();
    //         //HttpsURLConnection.setDefaultSSLSocketFactory(CredentialManager.createTavernaSSLSocketFactory());
    //         URL url = new URL ("https://rpc103.cs.man.ac.uk:8443/wsrf/services/cagrid/SecureHelloWorld?wsdl");
    //         HttpsURLConnection httpsConnection = (HttpsURLConnection) url.openConnection();
    //         // user should be asked automatically if they want to trust the connection
    //         httpsConnection.connect();
    //         
    //      } catch (CMException e) {
    //         logger.error("", e);
    //      } catch (MalformedURLException e) {
    //         logger.error("", e);
    //      } catch (IOException e) {
    //         logger.error("", e);
    //      }
    //      catch(Exception ex){ // anything we did not expect
    //         logger.error("", ex);
    //      }
    //      
    //   }

    /**
     * @throws java.lang.Exception
     */
    @BeforeClass
    public static void setUpBeforeClass() throws Exception {

        // Just in case, add the BouncyCastle provider
        // It gets added from the CredentialManagerImpl constructor as well
        // but we may need some crypto operations before we invoke the Cred. Manager 
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * @throws java.lang.Exception
     */
    @Before
    public void setUp() throws Exception {

        try {
            credentialManager = new CredentialManagerImpl();
        } catch (CMException e) {
            System.out.println(e.getStackTrace());
        }
        Random randomGenerator = new Random();
        String credentialManagerDirectoryPath = System.getProperty("java.io.tmpdir")
                + System.getProperty("file.separator") + "taverna-security-" + randomGenerator.nextInt(1000000);
        System.out.println("Credential Manager's directory path: " + credentialManagerDirectoryPath);
        credentialManagerDirectory = new File(credentialManagerDirectoryPath);
        try {
            credentialManager.setConfigurationDirectoryPath(credentialManagerDirectory);
        } catch (CMException e) {
            System.out.println(e.getStackTrace());
        }

        // Create the dummy master password provider
        masterPasswordProvider = new DummyMasterPasswordProvider();
        masterPasswordProvider.setMasterPassword("uber");
        List<MasterPasswordProvider> masterPasswordProviders = new ArrayList<MasterPasswordProvider>();
        masterPasswordProviders.add(masterPasswordProvider);
        credentialManager.setMasterPasswordProviders(masterPasswordProviders);

        // Set an empty list for trust confirmation providers
        credentialManager.setTrustConfirmationProviders(new ArrayList<TrustConfirmationProvider>());
    }

    @After
    // Clean up the credentialManagerDirectory we created for testing
    public void cleanUp() throws NoSuchAlgorithmException, KeyManagementException, NoSuchProviderException,
            KeyStoreException, UnrecoverableKeyException, CertificateException, IOException {
        //      assertTrue(credentialManagerDirectory.exists());
        //      assertFalse(credentialManagerDirectory.listFiles().length == 0); // something was created there

        if (credentialManagerDirectory.exists()) {
            try {
                FileUtils.deleteDirectory(credentialManagerDirectory);
                System.out.println(
                        "Deleting Credential Manager's directory: " + credentialManagerDirectory.getAbsolutePath());
            } catch (IOException e) {
                System.out.println(e.getStackTrace());
            }
        }

        // Reset the SSLSocketFactory in JVM so we always have a clean start
        SSLContext sc = null;
        sc = SSLContext.getInstance("SSLv3");

        // Create a "default" JSSE X509KeyManager.
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509", "SunJSSE");
        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(null, null);
        kmf.init(ks, "blah".toCharArray());

        // Create a "default" JSSE X509TrustManager.
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509", "SunJSSE");
        KeyStore ts = KeyStore.getInstance("JKS");
        ts.load(null, null);
        tmf.init(ts);

        sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
        SSLContext.setDefault(sc);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }

    @Test
    public void testTrustConfirmationProvidersTrustAlways() throws IOException, CMException {
        // Initially trust provider list is empty, we only verify by what is in 
        // Credential Manager's Truststore (and it does not contains the certificate for https://heater.cs.man.ac.uk:7443/)

        // Do not forget to initialise Taverna's/Credential Manager's SSLSocketFactory
        credentialManager.initializeSSL();

        URL url = new URL("https://heater.cs.man.ac.uk:7443/");
        HttpsURLConnection conn;
        conn = (HttpsURLConnection) url.openConnection();
        try {
            // This should fail
            conn.connect();
            fail("Connection to https://heater.cs.man.ac.uk:7443/ should be untrusted at this point.");
        } catch (SSLHandshakeException sslex) {
            // expected to fail so all is good
            System.out.println(sslex.getStackTrace());
        } finally {
            conn.disconnect();
        }

        // Add the trust confirmation provider that trusts everyone
        List<TrustConfirmationProvider> trustProviders = new ArrayList<TrustConfirmationProvider>();
        trustProviders.add(new TrustAlwaysTrustConfirmationProvider());
        credentialManager.setTrustConfirmationProviders(trustProviders);

        HttpsURLConnection conn2 = (HttpsURLConnection) url.openConnection();
        // This should work now
        conn2.connect();
        System.out.println("Status header: " + conn2.getHeaderField(0));

        assertEquals("HTTP/1.1 200 OK", conn2.getHeaderField(0));
        conn2.disconnect();
    }

    @Test
    public void testTrustConfirmationProvidersTrustNever() throws IOException, CMException {
        // Initially trust provider list is empty, we only verify by what is in 
        // Credential Manager's Truststore (and it does not contains the certificate for https://heater.cs.man.ac.uk:7443/)

        // Do not forget to initialise Taverna's/Credential Manager's SSLSocketFactory
        credentialManager.initializeSSL();

        URL url = new URL("https://heater.cs.man.ac.uk:7443/");
        HttpsURLConnection conn;
        conn = (HttpsURLConnection) url.openConnection();
        try {
            // This should fail
            conn.connect();
            fail("Connection to https://heater.cs.man.ac.uk:7443/ should be untrusted at this point.");
        } catch (SSLHandshakeException sslex) {
            // expected to fail so all is good
        } finally {
            conn.disconnect();
        }

        // Add the trust confirmation provider that trusts no one
        List<TrustConfirmationProvider> trustProviders = new ArrayList<TrustConfirmationProvider>();
        credentialManager.setTrustConfirmationProviders(trustProviders);
        trustProviders = new ArrayList<TrustConfirmationProvider>();
        trustProviders.add(new TrustNeverTrustConfimationProvider());
        credentialManager.setTrustConfirmationProviders(trustProviders);

        HttpsURLConnection conn2 = (HttpsURLConnection) url.openConnection();
        try {
            // This should still fail as our trust providers are not trusting anyone
            // and we have not added heater's certificate to Credential Manager's Truststore
            conn2.connect();
            fail("Connection to https://heater.cs.man.ac.uk:7443/ should be untrusted at this point.");
        } catch (SSLHandshakeException sslex) {
            // expected to fail so all is good
        } finally {
            conn2.disconnect();
        }
    }

    @Test
    public void testTrustConfirmationAddDeleteCertificateDirectly()
            throws CMException, IOException, CertificateException {
        // Initially trust provider list is empty, we only verify by what is in 
        // Credential Manager's Truststore (and it does not contains the certificate for https://heater.cs.man.ac.uk:7443/)

        // Do not forget to initialise Taverna's/Credential Manager's SSLSocketFactory
        credentialManager.initializeSSL();

        URL url = new URL("https://heater.cs.man.ac.uk:7443/");
        HttpsURLConnection conn;
        conn = (HttpsURLConnection) url.openConnection();
        try {
            // This should fail
            conn.connect();
            fail("Connection to https://heater.cs.man.ac.uk:7443/ should be untrusted at this point.");
        } catch (SSLHandshakeException sslex) {
            // expected to fail so all is good
        } finally {
            conn.disconnect();
        }

        // Add heater's certificate directly to Credential Manager's Truststore

        // Load the test trusted certificate (belonging to heater.cs.man.ac.uk)
        X509Certificate trustedCertficate;
        URL trustedCertficateFileURL = getClass().getResource("/security/tomcat_heater_certificate.pem");
        System.out.println("testTrustConfirmationAddDeleteCertificateDirectly: trusted certficate file URL "
                + trustedCertficateFileURL);
        File trustedCertFile = new File(trustedCertficateFileURL.getPath());
        FileInputStream inStream = new FileInputStream(trustedCertFile);
        //InputStream inStream = getClass().getClassLoader().getResourceAsStream("security/tomcat_heater_certificate.pem");
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        trustedCertficate = (X509Certificate) certFactory.generateCertificate(inStream);
        try {
            inStream.close();
        } catch (Exception e) {
            // Ignore
        }
        String alias = credentialManager.addTrustedCertificate(trustedCertficate);

        HttpsURLConnection conn2 = (HttpsURLConnection) url.openConnection();
        // This should work now
        conn2.connect();
        //System.out.println(conn2.getHeaderField(0));

        assertEquals("HTTP/1.1 200 OK", conn2.getHeaderField(0));
        conn2.disconnect();

        // Now remove certificate and see if the "trust" changes
        credentialManager.deleteTrustedCertificate(alias);
        HttpsURLConnection conn3;
        conn3 = (HttpsURLConnection) url.openConnection();
        try {
            // This should fail
            conn3.connect();
            fail("Connection to https://heater.cs.man.ac.uk:7443/ should be untrusted at this point.");
        } catch (SSLHandshakeException sslex) {
            // expected to fail so all is good
        } finally {
            conn3.disconnect();
        }
    }
}