16bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker/*
26bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker * Copyright (C) 2015 The Android Open Source Project
36bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker *
46bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker * Licensed under the Apache License, Version 2.0 (the "License");
56bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker * you may not use this file except in compliance with the License.
66bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker * You may obtain a copy of the License at
76bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker *
86bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker *      http://www.apache.org/licenses/LICENSE-2.0
96bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker *
106bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker * Unless required by applicable law or agreed to in writing, software
116bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker * distributed under the License is distributed on an "AS IS" BASIS,
126bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker * See the License for the specific language governing permissions and
146bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker * limitations under the License.
156bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker */
166bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
176bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerpackage android.security.net.config;
186bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
196bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerimport android.app.Activity;
2032d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubakerimport android.os.Build;
216bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerimport android.test.ActivityUnitTestCase;
226bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerimport android.util.ArraySet;
236bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerimport android.util.Pair;
2432d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubakerimport java.io.ByteArrayInputStream;
256bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerimport java.io.IOException;
266bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerimport java.net.Socket;
276bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerimport java.net.URL;
2832d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubakerimport java.security.cert.Certificate;
2932d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubakerimport java.security.cert.CertificateFactory;
3032d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubakerimport java.security.cert.X509Certificate;
316bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerimport java.util.ArrayList;
326bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerimport java.util.Collections;
3332d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubakerimport java.util.HashSet;
3432d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubakerimport java.util.Set;
356bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerimport javax.net.ssl.HttpsURLConnection;
366bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerimport javax.net.ssl.SSLContext;
376bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerimport javax.net.ssl.SSLHandshakeException;
386bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerimport javax.net.ssl.TrustManager;
396bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
4032d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubakerimport com.android.org.conscrypt.TrustedCertificateStore;
4132d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker
426bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubakerpublic class NetworkSecurityConfigTests extends ActivityUnitTestCase<Activity> {
436bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
446bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    public NetworkSecurityConfigTests() {
456bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        super(Activity.class);
466bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    }
476bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
486bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    // SHA-256 of the G2 intermediate CA for android.com (as of 10/2015).
496bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    private static final byte[] G2_SPKI_SHA256
506bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker            = hexToBytes("ec722969cb64200ab6638f68ac538e40abab5b19a6485661042a1061c4612776");
516bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
5232d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker    private static final byte[] TEST_CA_BYTES
5332d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            = hexToBytes(
5432d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    "3082036130820249a003020102020900bd54597d6750ea62300d06092a86"
5532d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "4886f70d01010b05003047310b3009060355040613025553310b30090603"
5632d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "5504080c0243413110300e060355040a0c07416e64726f69643119301706"
5732d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "035504030c104e53436f6e6669672054657374204341301e170d31363032"
5832d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "32343030313130325a170d3136303332353030313130325a3047310b3009"
5932d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "060355040613025553310b300906035504080c0243413110300e06035504"
6032d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "0a0c07416e64726f69643119301706035504030c104e53436f6e66696720"
6132d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "5465737420434130820122300d06092a864886f70d01010105000382010f"
6232d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "003082010a0282010100e15ce8fd5794029841e760d68d6e0159c9c67630"
6332d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "089775bc728d83dae7e29e23fe5f6e113b789f4c5b22f052300ec6d5faa5"
6432d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "724432e7bac96682792ef6e9617c939c4329dce8788cbdf3a11b621fac9e"
6532d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "2edbec2d7e5e07296bbb544b89263137a6a31573a2362e05ca8ff9c886bf"
6632d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "52df4ff93c45475145a40a83f2670e23669220a5a4bf2c6860edb78d3022"
6732d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "192fb5dc5e8c118f70870f89da292dfe522751462f020ed556653c8b07f8"
6832d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "89712a6e8196c457a637439e3073d7d917ab55aa51a146826367f7b5922a"
6932d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "64fb2f95099de21eb98341fa76faa79ffbda123fe5b8adc614b16174e8b0"
7032d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "dfdac2bbc4d526d2487ad2b009d53996ec23ffbd732112efa66b02030100"
7132d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "01a350304e301d0603551d0e04160414f66e1a95486c879edd60a5756bc2"
7232d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "f1f4677e128e301f0603551d23041830168014f66e1a95486c879edd60a5"
7332d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "756bc2f1f4677e128e300c0603551d13040530030101ff300d06092a8648"
7432d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "86f70d01010b05000382010100d2856130dccae24e5f8901900d94bc642f"
7532d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "85466ab7cfa1066399077a168cd4b56603a9e2af9d2e58aec13101e338a4"
7632d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "8e95e9c7a84d7991f0d381d4965eaada1b80fbbd8277445f449babe64f53"
7732d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "ba625387460b592a1a97b14b8251115e6610350021a6e716ae22b905f8d4"
7832d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "eae24e668e71b12ab51fd2f2bb600e074487dec720c3db14dbca504844b6"
7932d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "933bb0248283ea95464747689c37d706d4839c7d0e9bd86abf98ddce5d36"
8032d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "8b38bfe5062353e28d5be378827fade1caa6bba3df9cd9ebf83d839eae52"
8132d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "780181f31973f15f982686ba6d899f7b644fd1f26c8ebb99f4c986faaf4c"
8232d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    + "1b9e3d9d391943ce3fb9fa2e631bd66b8ef3d47fd85acf09ea3a30f15f");
8332d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker
8432d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker    private static final X509Certificate TEST_CA_CERT;
8532d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker
8632d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker    static {
8732d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker        try {
8832d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            CertificateFactory factory = CertificateFactory.getInstance("X.509");
8932d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            Certificate cert = factory.generateCertificate(new ByteArrayInputStream(TEST_CA_BYTES));
9032d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            TEST_CA_CERT = (X509Certificate) cert;
9132d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker        } catch (Exception e) {
9232d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            throw new RuntimeException(e);
9332d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker        }
9432d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker    }
9532d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker
9632d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker
976bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    private static byte[] hexToBytes(String s) {
986bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        int len = s.length();
996bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        byte[] data = new byte[len / 2];
1006bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        for (int i = 0; i < len; i += 2) {
1016bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(
1026bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                    s.charAt(i + 1), 16));
1036bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        }
1046bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        return data;
1056bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    }
1066bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
1076bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
1086bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    /**
1096bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker     * Return a NetworkSecurityConfig that has an empty TrustAnchor set. This should always cause a
1106bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker     * SSLHandshakeException when used for a connection.
1116bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker     */
1126bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    private NetworkSecurityConfig getEmptyConfig() {
11380a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        return new NetworkSecurityConfig.Builder().build();
1146bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    }
1156bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
1166bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    private NetworkSecurityConfig getSystemStoreConfig() {
11780a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        return new NetworkSecurityConfig.Builder()
11880a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .addCertificatesEntryRef(
11980a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                        new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
12080a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .build();
1216bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    }
1226bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
1236bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    public void testEmptyConfig() throws Exception {
1246bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
1256bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
1266bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        ConfigSource testSource =
1276bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                new TestConfigSource(domainMap, getEmptyConfig());
1285f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        SSLContext context = TestUtils.getSSLContext(testSource);
1295f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertConnectionFails(context, "android.com", 443);
1306bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    }
1316bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
1326bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    public void testEmptyPerNetworkSecurityConfig() throws Exception {
1336bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
1346bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
1356bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
1366bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                new Domain("android.com", true), getEmptyConfig()));
13780a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        NetworkSecurityConfig defaultConfig = getSystemStoreConfig();
1385f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        SSLContext context = TestUtils.getSSLContext(new TestConfigSource(domainMap, defaultConfig));
1395f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertConnectionFails(context, "android.com", 443);
1405f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertConnectionSucceeds(context, "google.com", 443);
1416bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    }
1426bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
1436bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    public void testBadPin() throws Exception {
1446bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        ArraySet<Pin> pins = new ArraySet<Pin>();
1456bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        pins.add(new Pin("SHA-256", new byte[0]));
14680a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
14780a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .setPinSet(new PinSet(pins, Long.MAX_VALUE))
14880a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .addCertificatesEntryRef(
14980a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                        new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
15080a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .build();
1516bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
1526bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
1536bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
1546bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                new Domain("android.com", true), domain));
1556bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        SSLContext context
1565f96702f582050c1598136ed2a748f76b981c94eChad Brubaker                = TestUtils.getSSLContext(new TestConfigSource(domainMap, getSystemStoreConfig()));
1575f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertConnectionFails(context, "android.com", 443);
1585f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertConnectionSucceeds(context, "google.com", 443);
1596bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    }
1606bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
1616bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    public void testGoodPin() throws Exception {
1626bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        ArraySet<Pin> pins = new ArraySet<Pin>();
1636bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        pins.add(new Pin("SHA-256", G2_SPKI_SHA256));
16480a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
16580a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .setPinSet(new PinSet(pins, Long.MAX_VALUE))
16680a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .addCertificatesEntryRef(
16780a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                        new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
16880a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .build();
1696bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
1706bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
1716bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
1726bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                new Domain("android.com", true), domain));
1736bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        SSLContext context
1745f96702f582050c1598136ed2a748f76b981c94eChad Brubaker                = TestUtils.getSSLContext(new TestConfigSource(domainMap, getEmptyConfig()));
1755f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertConnectionSucceeds(context, "android.com", 443);
1765f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertConnectionSucceeds(context, "developer.android.com", 443);
1776bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    }
1786bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
1796bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    public void testOverridePins() throws Exception {
1806bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        // Use a bad pin + granting the system CA store the ability to override pins.
1816bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        ArraySet<Pin> pins = new ArraySet<Pin>();
1826bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        pins.add(new Pin("SHA-256", new byte[0]));
18380a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
18480a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .setPinSet(new PinSet(pins, Long.MAX_VALUE))
18580a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .addCertificatesEntryRef(
18680a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                        new CertificatesEntryRef(SystemCertificateSource.getInstance(), true))
18780a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .build();
1886bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
1896bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
1906bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
1916bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                new Domain("android.com", true), domain));
1926bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        SSLContext context
1935f96702f582050c1598136ed2a748f76b981c94eChad Brubaker                = TestUtils.getSSLContext(new TestConfigSource(domainMap, getEmptyConfig()));
1945f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertConnectionSucceeds(context, "android.com", 443);
1956bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    }
1966bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
1976bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    public void testMostSpecificNetworkSecurityConfig() throws Exception {
1986bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
1996bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
2006bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
2016bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                new Domain("android.com", true), getEmptyConfig()));
2026bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
2036bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                new Domain("developer.android.com", false), getSystemStoreConfig()));
2046bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        SSLContext context
2055f96702f582050c1598136ed2a748f76b981c94eChad Brubaker                = TestUtils.getSSLContext(new TestConfigSource(domainMap, getEmptyConfig()));
2065f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertConnectionFails(context, "android.com", 443);
2075f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertConnectionSucceeds(context, "developer.android.com", 443);
2086bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    }
2096bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
2106bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    public void testSubdomainIncluded() throws Exception {
2116bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        // First try connecting to a subdomain of a domain entry that includes subdomains.
2126bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
2136bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
2146bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
2156bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                new Domain("android.com", true), getSystemStoreConfig()));
2166bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        SSLContext context
2175f96702f582050c1598136ed2a748f76b981c94eChad Brubaker                = TestUtils.getSSLContext(new TestConfigSource(domainMap, getEmptyConfig()));
2185f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertConnectionSucceeds(context, "developer.android.com", 443);
2196bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        // Now try without including subdomains.
2206bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        domainMap = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
2216bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
2226bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                new Domain("android.com", false), getSystemStoreConfig()));
2235f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        context = TestUtils.getSSLContext(new TestConfigSource(domainMap, getEmptyConfig()));
2245f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertConnectionFails(context, "developer.android.com", 443);
2256bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    }
2266bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker
22780a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker    public void testConfigBuilderUsesParents() throws Exception {
22880a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        // Check that a builder with a parent uses the parent's values when non is set.
22980a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        NetworkSecurityConfig config = new NetworkSecurityConfig.Builder()
23011e45075221680dcc25e3da1d3c32710e5a98603Todd Kennedy                .setParent(NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N, 1))
23180a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .build();
23280a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        assert(!config.getTrustAnchors().isEmpty());
23380a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker    }
23480a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker
23580a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker    public void testConfigBuilderParentLoop() throws Exception {
23680a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        NetworkSecurityConfig.Builder config1 = new NetworkSecurityConfig.Builder();
23780a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        NetworkSecurityConfig.Builder config2 = new NetworkSecurityConfig.Builder();
23880a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        config1.setParent(config2);
23980a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        try {
24080a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker            config2.setParent(config1);
24180a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker            fail("Loop in NetworkSecurityConfig parents");
24280a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        } catch (IllegalArgumentException expected) {
24380a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        }
24480a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker    }
24580a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker
2466bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    public void testWithUrlConnection() throws Exception {
2476bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        ArraySet<Pin> pins = new ArraySet<Pin>();
2486bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        pins.add(new Pin("SHA-256", G2_SPKI_SHA256));
24980a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker        NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
25080a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .setPinSet(new PinSet(pins, Long.MAX_VALUE))
25180a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .addCertificatesEntryRef(
25280a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                        new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
25380a73f5939364a07d8e83d3a90de6dc789e1b334Chad Brubaker                .build();
2546bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
2556bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                = new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
2566bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
2576bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker                new Domain("android.com", true), domain));
2586bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker        SSLContext context
2595f96702f582050c1598136ed2a748f76b981c94eChad Brubaker                = TestUtils.getSSLContext(new TestConfigSource(domainMap, getEmptyConfig()));
2605f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertUrlConnectionSucceeds(context, "android.com", 443);
2615f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertUrlConnectionSucceeds(context, "developer.android.com", 443);
2625f96702f582050c1598136ed2a748f76b981c94eChad Brubaker        TestUtils.assertUrlConnectionFails(context, "google.com", 443);
2636bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker    }
26432d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker
26532d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker    public void testUserAddedCaOptIn() throws Exception {
26632d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker        TrustedCertificateStore store = new TrustedCertificateStore();
26732d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker        try {
26832d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            // Install the test CA.
26932d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            store.installCertificate(TEST_CA_CERT);
27032d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            NetworkSecurityConfig preNConfig =
27111e45075221680dcc25e3da1d3c32710e5a98603Todd Kennedy                    NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.M, 1).build();
27232d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            NetworkSecurityConfig nConfig =
27311e45075221680dcc25e3da1d3c32710e5a98603Todd Kennedy                    NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N, 1).build();
27432d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            Set<TrustAnchor> preNAnchors = preNConfig.getTrustAnchors();
27532d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            Set<TrustAnchor> nAnchors = nConfig.getTrustAnchors();
27632d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            Set<X509Certificate> preNCerts = new HashSet<X509Certificate>();
27732d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            for (TrustAnchor anchor : preNAnchors) {
27832d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                preNCerts.add(anchor.certificate);
27932d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            }
28032d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            Set<X509Certificate> nCerts = new HashSet<X509Certificate>();
28132d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            for (TrustAnchor anchor : nAnchors) {
28232d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                nCerts.add(anchor.certificate);
28332d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            }
28432d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            assertTrue(preNCerts.contains(TEST_CA_CERT));
28532d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            assertFalse(nCerts.contains(TEST_CA_CERT));
28632d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker        } finally {
28732d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            // Delete the user added CA. We don't know the alias so just delete them all.
28832d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            for (String alias : store.aliases()) {
28932d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                if (store.isUser(alias)) {
29032d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    try {
29132d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                        store.deleteCertificateEntry(alias);
29232d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    } catch (Exception ignored) {
29332d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                    }
29432d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker                }
29532d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker            }
29632d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker        }
29732d2a1024f75f7e917f2aca18d34322a46d36bcbChad Brubaker    }
2986bc1e3966c4890ee3d47b5e527b800f2700ed627Chad Brubaker}
299