/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed 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 android.security.net.config;

import android.app.Activity;
import android.os.Build;
import android.test.ActivityUnitTestCase;
import android.util.ArraySet;
import android.util.Pair;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.URL;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.TrustManager;

import com.android.org.conscrypt.TrustedCertificateStore;

public class NetworkSecurityConfigTests extends ActivityUnitTestCase<Activity> {

    public NetworkSecurityConfigTests() {
        super(Activity.class);
    }

    // SHA-256 of the G2 intermediate CA for android.com (as of 10/2015).
    private static final byte[] G2_SPKI_SHA256
            = hexToBytes("ec722969cb64200ab6638f68ac538e40abab5b19a6485661042a1061c4612776");

    private static final byte[] TEST_CA_BYTES
            = hexToBytes(
                    "3082036130820249a003020102020900bd54597d6750ea62300d06092a86"
                    + "4886f70d01010b05003047310b3009060355040613025553310b30090603"
                    + "5504080c0243413110300e060355040a0c07416e64726f69643119301706"
                    + "035504030c104e53436f6e6669672054657374204341301e170d31363032"
                    + "32343030313130325a170d3136303332353030313130325a3047310b3009"
                    + "060355040613025553310b300906035504080c0243413110300e06035504"
                    + "0a0c07416e64726f69643119301706035504030c104e53436f6e66696720"
                    + "5465737420434130820122300d06092a864886f70d01010105000382010f"
                    + "003082010a0282010100e15ce8fd5794029841e760d68d6e0159c9c67630"
                    + "089775bc728d83dae7e29e23fe5f6e113b789f4c5b22f052300ec6d5faa5"
                    + "724432e7bac96682792ef6e9617c939c4329dce8788cbdf3a11b621fac9e"
                    + "2edbec2d7e5e07296bbb544b89263137a6a31573a2362e05ca8ff9c886bf"
                    + "52df4ff93c45475145a40a83f2670e23669220a5a4bf2c6860edb78d3022"
                    + "192fb5dc5e8c118f70870f89da292dfe522751462f020ed556653c8b07f8"
                    + "89712a6e8196c457a637439e3073d7d917ab55aa51a146826367f7b5922a"
                    + "64fb2f95099de21eb98341fa76faa79ffbda123fe5b8adc614b16174e8b0"
                    + "dfdac2bbc4d526d2487ad2b009d53996ec23ffbd732112efa66b02030100"
                    + "01a350304e301d0603551d0e04160414f66e1a95486c879edd60a5756bc2"
                    + "f1f4677e128e301f0603551d23041830168014f66e1a95486c879edd60a5"
                    + "756bc2f1f4677e128e300c0603551d13040530030101ff300d06092a8648"
                    + "86f70d01010b05000382010100d2856130dccae24e5f8901900d94bc642f"
                    + "85466ab7cfa1066399077a168cd4b56603a9e2af9d2e58aec13101e338a4"
                    + "8e95e9c7a84d7991f0d381d4965eaada1b80fbbd8277445f449babe64f53"
                    + "ba625387460b592a1a97b14b8251115e6610350021a6e716ae22b905f8d4"
                    + "eae24e668e71b12ab51fd2f2bb600e074487dec720c3db14dbca504844b6"
                    + "933bb0248283ea95464747689c37d706d4839c7d0e9bd86abf98ddce5d36"
                    + "8b38bfe5062353e28d5be378827fade1caa6bba3df9cd9ebf83d839eae52"
                    + "780181f31973f15f982686ba6d899f7b644fd1f26c8ebb99f4c986faaf4c"
                    + "1b9e3d9d391943ce3fb9fa2e631bd66b8ef3d47fd85acf09ea3a30f15f");

    private static final X509Certificate TEST_CA_CERT;

    static {
        try {
            CertificateFactory factory = CertificateFactory.getInstance("X.509");
            Certificate cert = factory.generateCertificate(new ByteArrayInputStream(TEST_CA_BYTES));
            TEST_CA_CERT = (X509Certificate) cert;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    private static byte[] hexToBytes(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(
                    s.charAt(i + 1), 16));
        }
        return data;
    }


    /**
     * Return a NetworkSecurityConfig that has an empty TrustAnchor set. This should always cause a
     * SSLHandshakeException when used for a connection.
     */
    private NetworkSecurityConfig getEmptyConfig() {
        return new NetworkSecurityConfig.Builder().build();
    }

    private NetworkSecurityConfig getSystemStoreConfig() {
        return new NetworkSecurityConfig.Builder()
                .addCertificatesEntryRef(
                        new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
                .build();
    }

    public void testEmptyConfig() throws Exception {
        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
        ConfigSource testSource =
                new TestConfigSource(domainMap, getEmptyConfig());
        SSLContext context = TestUtils.getSSLContext(testSource);
        TestUtils.assertConnectionFails(context, "android.com", 443);
    }

    public void testEmptyPerNetworkSecurityConfig() throws Exception {
        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
                new Domain("android.com", true), getEmptyConfig()));
        NetworkSecurityConfig defaultConfig = getSystemStoreConfig();
        SSLContext context = TestUtils.getSSLContext(new TestConfigSource(domainMap, defaultConfig));
        TestUtils.assertConnectionFails(context, "android.com", 443);
        TestUtils.assertConnectionSucceeds(context, "google.com", 443);
    }

    public void testBadPin() throws Exception {
        ArraySet<Pin> pins = new ArraySet<Pin>();
        pins.add(new Pin("SHA-256", new byte[0]));
        NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
                .setPinSet(new PinSet(pins, Long.MAX_VALUE))
                .addCertificatesEntryRef(
                        new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
                .build();
        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
                new Domain("android.com", true), domain));
        SSLContext context
                = TestUtils.getSSLContext(new TestConfigSource(domainMap, getSystemStoreConfig()));
        TestUtils.assertConnectionFails(context, "android.com", 443);
        TestUtils.assertConnectionSucceeds(context, "google.com", 443);
    }

    public void testGoodPin() throws Exception {
        ArraySet<Pin> pins = new ArraySet<Pin>();
        pins.add(new Pin("SHA-256", G2_SPKI_SHA256));
        NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
                .setPinSet(new PinSet(pins, Long.MAX_VALUE))
                .addCertificatesEntryRef(
                        new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
                .build();
        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
                new Domain("android.com", true), domain));
        SSLContext context
                = TestUtils.getSSLContext(new TestConfigSource(domainMap, getEmptyConfig()));
        TestUtils.assertConnectionSucceeds(context, "android.com", 443);
        TestUtils.assertConnectionSucceeds(context, "developer.android.com", 443);
    }

    public void testOverridePins() throws Exception {
        // Use a bad pin + granting the system CA store the ability to override pins.
        ArraySet<Pin> pins = new ArraySet<Pin>();
        pins.add(new Pin("SHA-256", new byte[0]));
        NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
                .setPinSet(new PinSet(pins, Long.MAX_VALUE))
                .addCertificatesEntryRef(
                        new CertificatesEntryRef(SystemCertificateSource.getInstance(), true))
                .build();
        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
                new Domain("android.com", true), domain));
        SSLContext context
                = TestUtils.getSSLContext(new TestConfigSource(domainMap, getEmptyConfig()));
        TestUtils.assertConnectionSucceeds(context, "android.com", 443);
    }

    public void testMostSpecificNetworkSecurityConfig() throws Exception {
        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
                new Domain("android.com", true), getEmptyConfig()));
        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
                new Domain("developer.android.com", false), getSystemStoreConfig()));
        SSLContext context
                = TestUtils.getSSLContext(new TestConfigSource(domainMap, getEmptyConfig()));
        TestUtils.assertConnectionFails(context, "android.com", 443);
        TestUtils.assertConnectionSucceeds(context, "developer.android.com", 443);
    }

    public void testSubdomainIncluded() throws Exception {
        // First try connecting to a subdomain of a domain entry that includes subdomains.
        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
                new Domain("android.com", true), getSystemStoreConfig()));
        SSLContext context
                = TestUtils.getSSLContext(new TestConfigSource(domainMap, getEmptyConfig()));
        TestUtils.assertConnectionSucceeds(context, "developer.android.com", 443);
        // Now try without including subdomains.
        domainMap = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
                new Domain("android.com", false), getSystemStoreConfig()));
        context = TestUtils.getSSLContext(new TestConfigSource(domainMap, getEmptyConfig()));
        TestUtils.assertConnectionFails(context, "developer.android.com", 443);
    }

    public void testConfigBuilderUsesParents() throws Exception {
        // Check that a builder with a parent uses the parent's values when non is set.
        NetworkSecurityConfig config = new NetworkSecurityConfig.Builder()
                .setParent(NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N, 1))
                .build();
        assert(!config.getTrustAnchors().isEmpty());
    }

    public void testConfigBuilderParentLoop() throws Exception {
        NetworkSecurityConfig.Builder config1 = new NetworkSecurityConfig.Builder();
        NetworkSecurityConfig.Builder config2 = new NetworkSecurityConfig.Builder();
        config1.setParent(config2);
        try {
            config2.setParent(config1);
            fail("Loop in NetworkSecurityConfig parents");
        } catch (IllegalArgumentException expected) {
        }
    }

    public void testWithUrlConnection() throws Exception {
        ArraySet<Pin> pins = new ArraySet<Pin>();
        pins.add(new Pin("SHA-256", G2_SPKI_SHA256));
        NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
                .setPinSet(new PinSet(pins, Long.MAX_VALUE))
                .addCertificatesEntryRef(
                        new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
                .build();
        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
                new Domain("android.com", true), domain));
        SSLContext context
                = TestUtils.getSSLContext(new TestConfigSource(domainMap, getEmptyConfig()));
        TestUtils.assertUrlConnectionSucceeds(context, "android.com", 443);
        TestUtils.assertUrlConnectionSucceeds(context, "developer.android.com", 443);
        TestUtils.assertUrlConnectionFails(context, "google.com", 443);
    }

    public void testUserAddedCaOptIn() throws Exception {
        TrustedCertificateStore store = new TrustedCertificateStore();
        try {
            // Install the test CA.
            store.installCertificate(TEST_CA_CERT);
            NetworkSecurityConfig preNConfig =
                    NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.M, 1).build();
            NetworkSecurityConfig nConfig =
                    NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N, 1).build();
            Set<TrustAnchor> preNAnchors = preNConfig.getTrustAnchors();
            Set<TrustAnchor> nAnchors = nConfig.getTrustAnchors();
            Set<X509Certificate> preNCerts = new HashSet<X509Certificate>();
            for (TrustAnchor anchor : preNAnchors) {
                preNCerts.add(anchor.certificate);
            }
            Set<X509Certificate> nCerts = new HashSet<X509Certificate>();
            for (TrustAnchor anchor : nAnchors) {
                nCerts.add(anchor.certificate);
            }
            assertTrue(preNCerts.contains(TEST_CA_CERT));
            assertFalse(nCerts.contains(TEST_CA_CERT));
        } finally {
            // Delete the user added CA. We don't know the alias so just delete them all.
            for (String alias : store.aliases()) {
                if (store.isUser(alias)) {
                    try {
                        store.deleteCertificateEntry(alias);
                    } catch (Exception ignored) {
                    }
                }
            }
        }
    }
}
