org.opensaml.security.httpclient.HttpClientSecuritySupportTest.java Source code

Java tutorial

Introduction

Here is the source code for org.opensaml.security.httpclient.HttpClientSecuritySupportTest.java

Source

/*
 * Licensed to the University Corporation for Advanced Internet Development, 
 * Inc. (UCAID) under one or more contributor license agreements.  See the 
 * NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The UCAID licenses this file to You under the Apache 
 * License, Version 2.0 (the "License"); you may not use this file except in 
 * compliance with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.opensaml.security.httpclient;

import static org.opensaml.security.httpclient.HttpClientSecurityConstants.CONTEXT_KEY_CLIENT_TLS_CREDENTIAL;
import static org.opensaml.security.httpclient.HttpClientSecurityConstants.CONTEXT_KEY_CRITERIA_SET;
import static org.opensaml.security.httpclient.HttpClientSecurityConstants.CONTEXT_KEY_HOSTNAME_VERIFIER;
import static org.opensaml.security.httpclient.HttpClientSecurityConstants.CONTEXT_KEY_SERVER_TLS_CREDENTIAL_TRUSTED;
import static org.opensaml.security.httpclient.HttpClientSecurityConstants.CONTEXT_KEY_TLS_CIPHER_SUITES;
import static org.opensaml.security.httpclient.HttpClientSecurityConstants.CONTEXT_KEY_TLS_PROTOCOLS;
import static org.opensaml.security.httpclient.HttpClientSecurityConstants.CONTEXT_KEY_TRUST_ENGINE;

import java.io.File;
import java.net.URISyntaxException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLPeerUnverifiedException;

import net.shibboleth.utilities.java.support.logic.ConstraintViolationException;
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;

import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ssl.StrictHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.opensaml.security.SecurityException;
import org.opensaml.security.trust.TrustEngine;
import org.opensaml.security.x509.BasicX509Credential;
import org.opensaml.security.x509.X509Credential;
import org.opensaml.security.x509.X509Support;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import com.google.common.collect.Lists;

/**
 *
 */
public class HttpClientSecuritySupportTest {

    private X509Certificate cert;

    private String certDERPath = "/data/certificate.der";

    @BeforeClass
    public void generatedTestData()
            throws NoSuchAlgorithmException, NoSuchProviderException, CertificateException, URISyntaxException {
        cert = X509Support
                .decodeCertificate(new File(HttpClientSecuritySupportTest.class.getResource(certDERPath).toURI()));
    }

    @Test(expectedExceptions = ConstraintViolationException.class)
    public void testMarshalSecurityParametersNullContext() {
        HttpClientSecurityParameters params = new HttpClientSecurityParameters();
        HttpClientSecuritySupport.marshalSecurityParameters(null, params, false);
    }

    @Test
    public void testMarshalNullSecurityParameters() {
        HttpClientContext context = HttpClientContext.create();

        HttpClientSecuritySupport.marshalSecurityParameters(context, null, false);

        Assert.assertNull(context.getCredentialsProvider());
        Assert.assertNull(context.getAttribute(CONTEXT_KEY_TRUST_ENGINE));
        Assert.assertNull(context.getAttribute(CONTEXT_KEY_CRITERIA_SET));
        Assert.assertNull(context.getAttribute(CONTEXT_KEY_TLS_PROTOCOLS));
        Assert.assertNull(context.getAttribute(CONTEXT_KEY_TLS_CIPHER_SUITES));
        Assert.assertNull(context.getAttribute(CONTEXT_KEY_CLIENT_TLS_CREDENTIAL));
        Assert.assertNull(context.getAttribute(CONTEXT_KEY_HOSTNAME_VERIFIER));
    }

    @Test
    public void testMarshalSecurityParametersEmptyContext() {
        HttpClientContext context = HttpClientContext.create();

        HttpClientSecurityParameters params = new HttpClientSecurityParameters();
        params.setCredentialsProvider(new BasicCredentialsProvider());
        params.setTLSTrustEngine(new MockTrustEngine());
        params.setTLSCriteriaSet(new CriteriaSet());
        params.setTLSProtocols(Lists.newArrayList("foo"));
        params.setTLSCipherSuites(Lists.newArrayList("foo"));
        params.setClientTLSCredential(new BasicX509Credential(cert));
        params.setHostnameVerifier(new StrictHostnameVerifier());

        HttpClientSecuritySupport.marshalSecurityParameters(context, params, false);

        Assert.assertSame(context.getCredentialsProvider(), params.getCredentialsProvider());
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_TRUST_ENGINE), params.getTLSTrustEngine());
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_CRITERIA_SET), params.getTLSCriteriaSet());
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_TLS_PROTOCOLS), params.getTLSProtocols());
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_TLS_CIPHER_SUITES), params.getTLSCipherSuites());
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_CLIENT_TLS_CREDENTIAL), params.getClientTLSCredential());
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_HOSTNAME_VERIFIER), params.getHostnameVerifier());
    }

    @Test
    public void testMarshalSecurityParametersWithReplacement() {
        HttpClientContext context = HttpClientContext.create();

        context.setCredentialsProvider(new BasicCredentialsProvider());
        context.setAttribute(CONTEXT_KEY_TRUST_ENGINE, new MockTrustEngine());
        context.setAttribute(CONTEXT_KEY_CRITERIA_SET, new CriteriaSet());
        context.setAttribute(CONTEXT_KEY_TLS_PROTOCOLS, Lists.newArrayList("foo"));
        context.setAttribute(CONTEXT_KEY_TLS_CIPHER_SUITES, Lists.newArrayList("foo"));
        context.setAttribute(CONTEXT_KEY_CLIENT_TLS_CREDENTIAL, new BasicX509Credential(cert));
        context.setAttribute(CONTEXT_KEY_HOSTNAME_VERIFIER, new StrictHostnameVerifier());

        HttpClientSecurityParameters params = new HttpClientSecurityParameters();
        params.setCredentialsProvider(new BasicCredentialsProvider());
        params.setTLSTrustEngine(new MockTrustEngine());
        params.setTLSCriteriaSet(new CriteriaSet());
        params.setTLSProtocols(Lists.newArrayList("foo"));
        params.setTLSCipherSuites(Lists.newArrayList("foo"));
        params.setClientTLSCredential(new BasicX509Credential(cert));
        params.setHostnameVerifier(new StrictHostnameVerifier());

        HttpClientSecuritySupport.marshalSecurityParameters(context, params, true);

        Assert.assertSame(context.getCredentialsProvider(), params.getCredentialsProvider());
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_TRUST_ENGINE), params.getTLSTrustEngine());
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_CRITERIA_SET), params.getTLSCriteriaSet());
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_TLS_PROTOCOLS), params.getTLSProtocols());
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_TLS_CIPHER_SUITES), params.getTLSCipherSuites());
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_CLIENT_TLS_CREDENTIAL), params.getClientTLSCredential());
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_HOSTNAME_VERIFIER), params.getHostnameVerifier());
    }

    @Test
    public void testMarshalSecurityParametersWithoutReplacement() {
        HttpClientContext context = HttpClientContext.create();

        CredentialsProvider credProvider = new BasicCredentialsProvider();
        TrustEngine<X509Credential> trustEngine = new MockTrustEngine();
        CriteriaSet criteriaSet = new CriteriaSet();
        List<String> protocols = Lists.newArrayList("foo");
        List<String> cipherSuites = Lists.newArrayList("foo");
        X509Credential clientTLSCred = new BasicX509Credential(cert);
        HostnameVerifier verifier = new StrictHostnameVerifier();

        context.setCredentialsProvider(credProvider);
        context.setAttribute(CONTEXT_KEY_TRUST_ENGINE, trustEngine);
        context.setAttribute(CONTEXT_KEY_CRITERIA_SET, criteriaSet);
        context.setAttribute(CONTEXT_KEY_TLS_PROTOCOLS, protocols);
        context.setAttribute(CONTEXT_KEY_TLS_CIPHER_SUITES, cipherSuites);
        context.setAttribute(CONTEXT_KEY_CLIENT_TLS_CREDENTIAL, clientTLSCred);
        context.setAttribute(CONTEXT_KEY_HOSTNAME_VERIFIER, verifier);

        HttpClientSecurityParameters params = new HttpClientSecurityParameters();
        params.setCredentialsProvider(new BasicCredentialsProvider());
        params.setTLSTrustEngine(new MockTrustEngine());
        params.setTLSCriteriaSet(new CriteriaSet());
        params.setTLSProtocols(Lists.newArrayList("foo"));
        params.setTLSCipherSuites(Lists.newArrayList("foo"));
        params.setClientTLSCredential(new BasicX509Credential(cert));
        params.setHostnameVerifier(new StrictHostnameVerifier());

        HttpClientSecuritySupport.marshalSecurityParameters(context, params, false);

        Assert.assertSame(context.getCredentialsProvider(), credProvider);
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_TRUST_ENGINE), trustEngine);
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_CRITERIA_SET), criteriaSet);
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_TLS_PROTOCOLS), protocols);
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_TLS_CIPHER_SUITES), cipherSuites);
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_CLIENT_TLS_CREDENTIAL), clientTLSCred);
        Assert.assertSame(context.getAttribute(CONTEXT_KEY_HOSTNAME_VERIFIER), verifier);
    }

    @Test
    public void testSetContextValue() {
        String attribName = "MyAttrib";
        HttpClientContext context = null;

        // Empty context
        context = HttpClientContext.create();
        HttpClientSecuritySupport.setContextValue(context, attribName, "foo", false);
        Assert.assertEquals(context.getAttribute(attribName), "foo");

        // Empty context, null value
        context = HttpClientContext.create();
        HttpClientSecuritySupport.setContextValue(context, attribName, null, false);
        Assert.assertNull(context.getAttribute(attribName));

        // Don't replace existing
        context = HttpClientContext.create();
        context.setAttribute(attribName, "bar");
        HttpClientSecuritySupport.setContextValue(context, attribName, "foo", false);
        Assert.assertEquals(context.getAttribute(attribName), "bar");

        // Replace existing
        context = HttpClientContext.create();
        context.setAttribute(attribName, "bar");
        HttpClientSecuritySupport.setContextValue(context, attribName, "foo", true);
        Assert.assertEquals(context.getAttribute(attribName), "foo");

        // Don't replace because null value
        context = HttpClientContext.create();
        context.setAttribute(attribName, "bar");
        HttpClientSecuritySupport.setContextValue(context, attribName, null, true);
        Assert.assertEquals(context.getAttribute(attribName), "bar");

        try {
            HttpClientSecuritySupport.setContextValue(null, attribName, "foo", false);
            Assert.fail("Null context value");
        } catch (ConstraintViolationException e) {
            // Expected
        }

        try {
            context = HttpClientContext.create();
            HttpClientSecuritySupport.setContextValue(context, null, "foo", false);
            Assert.fail("Null attribute name");
        } catch (ConstraintViolationException e) {
            // Expected
        }

    }

    @DataProvider
    private Object[][] tlsCredentialEvaluatedData() {
        MockTrustEngine trustEngine = new MockTrustEngine();
        return new Object[][] {
                // "Standard" HTTPS pass cases
                new Object[] { trustEngine, "https", Boolean.TRUE, true },
                new Object[] { trustEngine, "https", Boolean.FALSE, true },

                // HTTPS, no trust engine: pass
                new Object[] { null, "https", null, true }, new Object[] { null, "https", Boolean.TRUE, true },
                new Object[] { null, "https", Boolean.FALSE, true },

                // Non-HTTPS: pass
                new Object[] { trustEngine, "http", null, true },
                new Object[] { trustEngine, "http", Boolean.TRUE, true },
                new Object[] { trustEngine, "http", Boolean.FALSE, true },

                // No pass
                new Object[] { trustEngine, "https", null, false }, };
    }

    @Test(dataProvider = "tlsCredentialEvaluatedData")
    public void testCheckTLSCredentialEvaluated(MockTrustEngine trustEngine, String scheme, Boolean trusted,
            boolean shouldPass) {
        HttpClientContext context = new HttpClientContext();
        context.setAttribute(CONTEXT_KEY_TRUST_ENGINE, trustEngine);
        context.setAttribute(CONTEXT_KEY_SERVER_TLS_CREDENTIAL_TRUSTED, trusted);

        if (shouldPass) {
            try {
                HttpClientSecuritySupport.checkTLSCredentialEvaluated(context, scheme);
            } catch (SSLPeerUnverifiedException e) {
                Assert.fail("Exception thrown unexpectedly");
            }
        } else {
            try {
                HttpClientSecuritySupport.checkTLSCredentialEvaluated(context, scheme);
                Assert.fail("Exception was expected but not seen");
            } catch (SSLPeerUnverifiedException e) {
                // expected
            }
        }
    }

    // Helpers

    public static class MockTrustEngine implements TrustEngine<X509Credential> {
        public boolean validate(X509Credential token, CriteriaSet trustBasisCriteria) throws SecurityException {
            return false;
        }
    }

}