18f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki/*
28f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki * Copyright (C) 2010 The Android Open Source Project
38f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki *
48f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki * Licensed under the Apache License, Version 2.0 (the "License");
58f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki * you may not use this file except in compliance with the License.
68f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki * You may obtain a copy of the License at
78f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki *
88f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki *      http://www.apache.org/licenses/LICENSE-2.0
98f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki *
108f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki * Unless required by applicable law or agreed to in writing, software
118f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki * distributed under the License is distributed on an "AS IS" BASIS,
128f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki * See the License for the specific language governing permissions and
148f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki * limitations under the License.
158f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki */
160dc59e78e18493aecd37427531d093e800846c3eBrett Chabotpackage com.android.internal.net;
178f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
182269d1572e5fcfb725ea55f5764d8c3280d69f6dDianne Hackbornimport com.android.internal.net.DomainNameValidator;
190dc59e78e18493aecd37427531d093e800846c3eBrett Chabotimport com.android.frameworks.coretests.R;
200dc59e78e18493aecd37427531d093e800846c3eBrett Chabotimport com.android.frameworks.coretests.R.raw;
21691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki
22691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onukiimport android.test.AndroidTestCase;
23691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki
24691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onukiimport java.io.InputStream;
258f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.math.BigInteger;
268f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.security.InvalidKeyException;
278f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.security.NoSuchAlgorithmException;
288f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.security.NoSuchProviderException;
298f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.security.Principal;
308f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.security.PublicKey;
318f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.security.SignatureException;
328f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.security.cert.CertificateEncodingException;
338f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.security.cert.CertificateException;
348f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.security.cert.CertificateExpiredException;
35691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onukiimport java.security.cert.CertificateFactory;
368f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.security.cert.CertificateNotYetValidException;
378f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.security.cert.CertificateParsingException;
388f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.security.cert.X509Certificate;
398f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.util.ArrayList;
408f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.util.Collection;
418f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.util.Date;
428f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.util.LinkedList;
438f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.util.List;
448f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport java.util.Set;
458f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
468f028a94fc533e75077485a7d11a04e4de820335Makoto Onukiimport javax.security.auth.x500.X500Principal;
478f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
48691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onukipublic class DomainNameValidatorTest extends AndroidTestCase {
498f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    private static final int ALT_UNKNOWN = 0;
508f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    private static final int ALT_DNS_NAME = 2;
518f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    private static final int ALT_IPA_NAME = 7;
528f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
538f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    /**
54691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki     * Tests {@link DomainNameValidator#match}, using a simple {@link X509Certificate}
55691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki     * implementation.
568f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki     */
578f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    public void testMatch() {
588f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatch("11", new StubX509Certificate("cn=imap.g.com"), "imap.g.com", true);
598f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatch("12", new StubX509Certificate("cn=imap2.g.com"), "imap.g.com", false);
608f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatch("13", new StubX509Certificate("cn=sub.imap.g.com"), "imap.g.com", false);
618f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
628f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        // If a subjectAltName extension of type dNSName is present, that MUST
638f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        // be used as the identity
648f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatch("21", new StubX509Certificate("")
658f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "a.y.com")
668f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                , "imap.g.com", false);
678f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatch("22", new StubX509Certificate("cn=imap.g.com") // This cn should be ignored
688f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "a.y.com")
698f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                , "imap.g.com", false);
708f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatch("23", new StubX509Certificate("")
718f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com")
728f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                , "imap.g.com", true);
738f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
748f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        // With wildcards
758f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatch("24", new StubX509Certificate("")
768f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "*.g.com")
778f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                , "imap.g.com", true);
788f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
798f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        // host name is ip address
808f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatch("31", new StubX509Certificate("")
818f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_IPA_NAME, "1.2.3.4")
828f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                , "1.2.3.4", true);
838f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatch("32", new StubX509Certificate("")
848f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_IPA_NAME, "1.2.3.4")
858f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                , "1.2.3.5", false);
868f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatch("32", new StubX509Certificate("")
878f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_IPA_NAME, "1.2.3.4")
888f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_IPA_NAME, "192.168.100.1")
898f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                , "192.168.100.1", true);
908f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
918f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        // Has unknown subject alternative names
928f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatch("41", new StubX509Certificate("")
938f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 1")
948f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_UNKNOWN,  "random string 2")
958f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "a.b.c.d")
968f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "*.google.com")
978f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com")
988f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_IPA_NAME, "2.33.44.55")
998f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 3")
1008f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                , "imap.g.com", true);
1018f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
1028f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatch("42", new StubX509Certificate("")
1038f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 1")
1048f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 2")
1058f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "a.b.c.d")
1068f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "*.google.com")
1078f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com")
1088f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_IPA_NAME, "2.33.44.55")
1098f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 3")
1108f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                , "2.33.44.55", true);
1118f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
1128f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatch("43", new StubX509Certificate("")
1138f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 1")
1148f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 2")
1158f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "a.b.c.d")
1168f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "*.google.com")
1178f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com")
1188f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_IPA_NAME, "2.33.44.55")
1198f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 3")
1208f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                , "g.com", false);
1218f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
1228f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatch("44", new StubX509Certificate("")
1238f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 1")
1248f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 2")
1258f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "a.b.c.d")
1268f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "*.google.com")
1278f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com")
1288f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_IPA_NAME, "2.33.44.55")
1298f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                .addSubjectAlternativeName(ALT_UNKNOWN, "random string 3")
1308f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                , "2.33.44.1", false);
1318f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    }
1328f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
1338f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    private void checkMatch(String message, X509Certificate certificate, String thisDomain,
1348f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            boolean expected) {
1358f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        Boolean actual = DomainNameValidator.match(certificate, thisDomain);
1368f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        assertEquals(message, (Object) expected, (Object) actual);
1378f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    }
1388f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
1398f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    /**
1408f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki     * Tests {@link DomainNameValidator#matchDns}
1418f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki     */
1428f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    public void testMatchDns() {
1438f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("11", "a.b.c.d", "a.b.c.d", true);
1448f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("12", "a.b.c.d", "*.b.c.d", true);
1458f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("13", "b.c.d", "*.b.c.d", true);
1468f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("14", "b.c.d", "b*.c.d", true);
1478f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
1488f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("15", "a.b.c.d", "*.*.c.d", false);
1498f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("16", "a.b.c.d", "*.c.d", false);
1508f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
1518f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("21", "imap.google.com", "imap.google.com", true);
1528f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("22", "imap2.google.com", "imap.google.com", false);
1538f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("23", "imap.google.com", "*.google.com", true);
1548f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("24", "imap2.google.com", "*.google.com", true);
1558f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("25", "imap.google.com", "*.googl.com", false);
1568f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("26", "imap2.google2.com", "*.google3.com", false);
1578f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("27", "imap.google.com", "ima*.google.com", true);
1588f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("28", "imap.google.com", "imap*.google.com", true);
1598f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("29", "imap.google.com", "*.imap.google.com", true);
1608f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
1618f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("41", "imap.google.com", "a*.google.com", false);
1628f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("42", "imap.google.com", "ix*.google.com", false);
1638f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
1648f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        checkMatchDns("51", "imap.google.com", "iMap.Google.Com", true);
1658f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    }
1668f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
1678f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    private void checkMatchDns(String message, String thisDomain, String thatDomain,
1688f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            boolean expected) {
1698f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        boolean actual = DomainNameValidator.matchDns(thisDomain, thatDomain);
1708f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        assertEquals(message, expected, actual);
1718f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    }
1728f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
1738f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    /**
174691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki     * Test {@link DomainNameValidator#match} with actual certificates.
175691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki     */
176691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki    public void testWithActualCert() throws Exception {
177691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject_only
178691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        //
179691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject: C=JP, CN=www.example.com
180691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject alt names: n/a
181691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("11", R.raw.subject_only, "www.example.com", true);
182691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("12", R.raw.subject_only, "www2.example.com", false);
183691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki
184691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject_alt_only
185691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        //
186691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject: C=JP (no CN)
187691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject alt names: DNS:www.example.com
188691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("21", R.raw.subject_alt_only, "www.example.com", true);
189691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("22", R.raw.subject_alt_only, "www2.example.com", false);
190691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki
191691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject_with_alt_names
192691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        //
193691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject: C=JP, CN=www.example.com
194691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject alt names: DNS:www2.example.com, DNS:www3.example.com
195691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // * Subject should be ignored, because it has subject alt names.
196691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("31", R.raw.subject_with_alt_names, "www.example.com", false);
197691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("32", R.raw.subject_with_alt_names, "www2.example.com", true);
198691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("33", R.raw.subject_with_alt_names, "www3.example.com", true);
199691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("34", R.raw.subject_with_alt_names, "www4.example.com", false);
200691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki
201691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject_with_wild_alt_name
202691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        //
203691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject: C=JP, CN=www.example.com
204691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject alt names: DNS:*.example2.com
205691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // * Subject should be ignored, because it has subject alt names.
206691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("41", R.raw.subject_with_wild_alt_name, "www.example.com", false);
207691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("42", R.raw.subject_with_wild_alt_name, "www2.example.com", false);
208691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("43", R.raw.subject_with_wild_alt_name, "www.example2.com", true);
209691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("44", R.raw.subject_with_wild_alt_name, "abc.example2.com", true);
210691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("45", R.raw.subject_with_wild_alt_name, "www.example3.com", false);
211691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki
212691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // wild_alt_name_only
213691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        //
214691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject: C=JP
215691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject alt names: DNS:*.example.com
216691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("51", R.raw.wild_alt_name_only, "www.example.com", true);
217691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("52", R.raw.wild_alt_name_only, "www2.example.com", true);
218691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("53", R.raw.wild_alt_name_only, "www.example2.com", false);
219691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki
220691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // wild_alt_name_only
221691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        //
222691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject: C=JP
223691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        // subject alt names: IP Address:192.168.10.1
224691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("61", R.raw.alt_ip_only, "192.168.10.1", true);
225691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkWithActualCert("61", R.raw.alt_ip_only, "192.168.10.2", false);
226691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki    }
227691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki
228691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki    private void checkWithActualCert(String message, int resId, String domain,
229691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki            boolean expected) throws Exception {
230691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        CertificateFactory factory = CertificateFactory.getInstance("X509");
231691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        InputStream certStream = getContext().getResources().openRawResource(resId);
232691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        X509Certificate certificate = (X509Certificate) factory.generateCertificate(certStream);
233691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki
234691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki        checkMatch(message, certificate, domain, expected);
235691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki    }
236691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki
237691c07031ab2d53e3e0942c7148927af61ae21b1Makoto Onuki    /**
2388f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki     * Minimal {@link X509Certificate} implementation for {@link DomainNameValidator}.
2398f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki     */
2408f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    private static class StubX509Certificate extends X509Certificate {
2418f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        private final X500Principal subjectX500Principal;
2428f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        private Collection<List<?>> subjectAlternativeNames;
2438f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
2448f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public StubX509Certificate(String subjectDn) {
2458f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            subjectX500Principal = new X500Principal(subjectDn);
2468f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            subjectAlternativeNames = null;
2478f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
2488f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
2498f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public StubX509Certificate addSubjectAlternativeName(int type, String name) {
2508f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            if (subjectAlternativeNames == null) {
2518f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                subjectAlternativeNames = new ArrayList<List<?>>();
2528f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            }
2538f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            LinkedList<Object> entry = new LinkedList<Object>();
2548f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            entry.add(type);
2558f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            entry.add(name);
2568f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            subjectAlternativeNames.add(entry);
2578f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            return this;
2588f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
2598f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
2608f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
2618f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public Collection<List<?>> getSubjectAlternativeNames() throws CertificateParsingException {
2628f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            return subjectAlternativeNames;
2638f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
2648f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
2658f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
2668f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public X500Principal getSubjectX500Principal() {
2678f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            return subjectX500Principal;
2688f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
2698f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
2708f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
2718f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public void checkValidity() throws CertificateExpiredException,
2728f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                CertificateNotYetValidException {
2738f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
2748f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
2758f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
2768f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
2778f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public void checkValidity(Date date) throws CertificateExpiredException,
2788f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                CertificateNotYetValidException {
2798f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
2808f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
2818f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
2828f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
2838f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public int getBasicConstraints() {
2848f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
2858f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
2868f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
2878f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
2888f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public Principal getIssuerDN() {
2898f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
2908f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
2918f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
2928f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
2938f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public boolean[] getIssuerUniqueID() {
2948f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
2958f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
2968f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
2978f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
2988f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public boolean[] getKeyUsage() {
2998f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3008f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3018f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3028f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3038f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public Date getNotAfter() {
3048f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3058f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3068f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3078f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3088f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public Date getNotBefore() {
3098f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3108f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3118f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3128f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3138f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public BigInteger getSerialNumber() {
3148f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3158f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3168f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3178f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3188f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public String getSigAlgName() {
3198f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3208f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3218f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3228f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3238f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public String getSigAlgOID() {
3248f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3258f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3268f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3278f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3288f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public byte[] getSigAlgParams() {
3298f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3308f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3318f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3328f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3338f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public byte[] getSignature() {
3348f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3358f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3368f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3378f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3388f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public Principal getSubjectDN() {
3398f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3408f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3418f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3428f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3438f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public boolean[] getSubjectUniqueID() {
3448f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3458f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3468f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3478f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3488f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public byte[] getTBSCertificate() throws CertificateEncodingException {
3498f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3508f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3518f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3528f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3538f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public int getVersion() {
3548f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3558f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3568f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3578f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3588f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public byte[] getEncoded() throws CertificateEncodingException {
3598f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3608f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3618f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3628f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3638f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public PublicKey getPublicKey() {
3648f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3658f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3668f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3678f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3688f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public String toString() {
3698f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3708f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3718f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3728f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3738f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException,
3748f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                InvalidKeyException, NoSuchProviderException, SignatureException {
3758f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3768f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3778f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3788f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        @Override
3798f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public void verify(PublicKey key, String sigProvider) throws CertificateException,
3808f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException,
3818f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki                SignatureException {
3828f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3838f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3848f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3858f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public Set<String> getCriticalExtensionOIDs() {
3868f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3878f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3888f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3898f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public byte[] getExtensionValue(String oid) {
3908f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3918f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3928f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3938f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public Set<String> getNonCriticalExtensionOIDs() {
3948f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3958f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
3968f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
3978f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        public boolean hasUnsupportedCriticalExtension() {
3988f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki            throw new RuntimeException("Method not implemented");
3998f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki        }
4008f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki    }
4018f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki}
402