diff options
author | Dianne Hackborn <hackbod@google.com> | 2010-02-24 19:54:22 -0800 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2010-02-25 11:39:33 -0800 |
commit | 2269d1572e5fcfb725ea55f5764d8c3280d69f6d (patch) | |
tree | 7ce0788be6d85972d42ee7135cdce82aa323fcc7 /tests/AndroidTests/src/com/android/unit_tests/DomainNameValidatorTest.java | |
parent | e46145f7c114b9ac6d19c6a7886e9239463f91e1 (diff) | |
download | frameworks_base-2269d1572e5fcfb725ea55f5764d8c3280d69f6d.zip frameworks_base-2269d1572e5fcfb725ea55f5764d8c3280d69f6d.tar.gz frameworks_base-2269d1572e5fcfb725ea55f5764d8c3280d69f6d.tar.bz2 |
Re-arrange android-common so framework no longer links with it.
This is the framework part, moving classes around so the framework
no longer needs to link to android-common. Makes some APIs public,
others that didn't need to be public are private in the framework,
some small things are copied.
Diffstat (limited to 'tests/AndroidTests/src/com/android/unit_tests/DomainNameValidatorTest.java')
-rw-r--r-- | tests/AndroidTests/src/com/android/unit_tests/DomainNameValidatorTest.java | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/tests/AndroidTests/src/com/android/unit_tests/DomainNameValidatorTest.java b/tests/AndroidTests/src/com/android/unit_tests/DomainNameValidatorTest.java new file mode 100644 index 0000000..1754dbe --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/DomainNameValidatorTest.java @@ -0,0 +1,399 @@ +/* + * Copyright (C) 2010 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 com.android.unit_tests; + +import com.android.internal.net.DomainNameValidator; + +import android.test.AndroidTestCase; + +import java.io.InputStream; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Principal; +import java.security.PublicKey; +import java.security.SignatureException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateFactory; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import javax.security.auth.x500.X500Principal; + +public class DomainNameValidatorTest extends AndroidTestCase { + private static final int ALT_UNKNOWN = 0; + private static final int ALT_DNS_NAME = 2; + private static final int ALT_IPA_NAME = 7; + + /** + * Tests {@link DomainNameValidator#match}, using a simple {@link X509Certificate} + * implementation. + */ + public void testMatch() { + checkMatch("11", new StubX509Certificate("cn=imap.g.com"), "imap.g.com", true); + checkMatch("12", new StubX509Certificate("cn=imap2.g.com"), "imap.g.com", false); + checkMatch("13", new StubX509Certificate("cn=sub.imap.g.com"), "imap.g.com", false); + + // If a subjectAltName extension of type dNSName is present, that MUST + // be used as the identity + checkMatch("21", new StubX509Certificate("") + .addSubjectAlternativeName(ALT_DNS_NAME, "a.y.com") + , "imap.g.com", false); + checkMatch("22", new StubX509Certificate("cn=imap.g.com") // This cn should be ignored + .addSubjectAlternativeName(ALT_DNS_NAME, "a.y.com") + , "imap.g.com", false); + checkMatch("23", new StubX509Certificate("") + .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com") + , "imap.g.com", true); + + // With wildcards + checkMatch("24", new StubX509Certificate("") + .addSubjectAlternativeName(ALT_DNS_NAME, "*.g.com") + , "imap.g.com", true); + + // host name is ip address + checkMatch("31", new StubX509Certificate("") + .addSubjectAlternativeName(ALT_IPA_NAME, "1.2.3.4") + , "1.2.3.4", true); + checkMatch("32", new StubX509Certificate("") + .addSubjectAlternativeName(ALT_IPA_NAME, "1.2.3.4") + , "1.2.3.5", false); + checkMatch("32", new StubX509Certificate("") + .addSubjectAlternativeName(ALT_IPA_NAME, "1.2.3.4") + .addSubjectAlternativeName(ALT_IPA_NAME, "192.168.100.1") + , "192.168.100.1", true); + + // Has unknown subject alternative names + checkMatch("41", new StubX509Certificate("") + .addSubjectAlternativeName(ALT_UNKNOWN, "random string 1") + .addSubjectAlternativeName(ALT_UNKNOWN, "random string 2") + .addSubjectAlternativeName(ALT_DNS_NAME, "a.b.c.d") + .addSubjectAlternativeName(ALT_DNS_NAME, "*.google.com") + .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com") + .addSubjectAlternativeName(ALT_IPA_NAME, "2.33.44.55") + .addSubjectAlternativeName(ALT_UNKNOWN, "random string 3") + , "imap.g.com", true); + + checkMatch("42", new StubX509Certificate("") + .addSubjectAlternativeName(ALT_UNKNOWN, "random string 1") + .addSubjectAlternativeName(ALT_UNKNOWN, "random string 2") + .addSubjectAlternativeName(ALT_DNS_NAME, "a.b.c.d") + .addSubjectAlternativeName(ALT_DNS_NAME, "*.google.com") + .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com") + .addSubjectAlternativeName(ALT_IPA_NAME, "2.33.44.55") + .addSubjectAlternativeName(ALT_UNKNOWN, "random string 3") + , "2.33.44.55", true); + + checkMatch("43", new StubX509Certificate("") + .addSubjectAlternativeName(ALT_UNKNOWN, "random string 1") + .addSubjectAlternativeName(ALT_UNKNOWN, "random string 2") + .addSubjectAlternativeName(ALT_DNS_NAME, "a.b.c.d") + .addSubjectAlternativeName(ALT_DNS_NAME, "*.google.com") + .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com") + .addSubjectAlternativeName(ALT_IPA_NAME, "2.33.44.55") + .addSubjectAlternativeName(ALT_UNKNOWN, "random string 3") + , "g.com", false); + + checkMatch("44", new StubX509Certificate("") + .addSubjectAlternativeName(ALT_UNKNOWN, "random string 1") + .addSubjectAlternativeName(ALT_UNKNOWN, "random string 2") + .addSubjectAlternativeName(ALT_DNS_NAME, "a.b.c.d") + .addSubjectAlternativeName(ALT_DNS_NAME, "*.google.com") + .addSubjectAlternativeName(ALT_DNS_NAME, "imap.g.com") + .addSubjectAlternativeName(ALT_IPA_NAME, "2.33.44.55") + .addSubjectAlternativeName(ALT_UNKNOWN, "random string 3") + , "2.33.44.1", false); + } + + private void checkMatch(String message, X509Certificate certificate, String thisDomain, + boolean expected) { + Boolean actual = DomainNameValidator.match(certificate, thisDomain); + assertEquals(message, (Object) expected, (Object) actual); + } + + /** + * Tests {@link DomainNameValidator#matchDns} + */ + public void testMatchDns() { + checkMatchDns("11", "a.b.c.d", "a.b.c.d", true); + checkMatchDns("12", "a.b.c.d", "*.b.c.d", true); + checkMatchDns("13", "b.c.d", "*.b.c.d", true); + checkMatchDns("14", "b.c.d", "b*.c.d", true); + + checkMatchDns("15", "a.b.c.d", "*.*.c.d", false); + checkMatchDns("16", "a.b.c.d", "*.c.d", false); + + checkMatchDns("21", "imap.google.com", "imap.google.com", true); + checkMatchDns("22", "imap2.google.com", "imap.google.com", false); + checkMatchDns("23", "imap.google.com", "*.google.com", true); + checkMatchDns("24", "imap2.google.com", "*.google.com", true); + checkMatchDns("25", "imap.google.com", "*.googl.com", false); + checkMatchDns("26", "imap2.google2.com", "*.google3.com", false); + checkMatchDns("27", "imap.google.com", "ima*.google.com", true); + checkMatchDns("28", "imap.google.com", "imap*.google.com", true); + checkMatchDns("29", "imap.google.com", "*.imap.google.com", true); + + checkMatchDns("41", "imap.google.com", "a*.google.com", false); + checkMatchDns("42", "imap.google.com", "ix*.google.com", false); + + checkMatchDns("51", "imap.google.com", "iMap.Google.Com", true); + } + + private void checkMatchDns(String message, String thisDomain, String thatDomain, + boolean expected) { + boolean actual = DomainNameValidator.matchDns(thisDomain, thatDomain); + assertEquals(message, expected, actual); + } + + /** + * Test {@link DomainNameValidator#match} with actual certificates. + */ + public void testWithActualCert() throws Exception { + // subject_only + // + // subject: C=JP, CN=www.example.com + // subject alt names: n/a + checkWithActualCert("11", R.raw.subject_only, "www.example.com", true); + checkWithActualCert("12", R.raw.subject_only, "www2.example.com", false); + + // subject_alt_only + // + // subject: C=JP (no CN) + // subject alt names: DNS:www.example.com + checkWithActualCert("21", R.raw.subject_alt_only, "www.example.com", true); + checkWithActualCert("22", R.raw.subject_alt_only, "www2.example.com", false); + + // subject_with_alt_names + // + // subject: C=JP, CN=www.example.com + // subject alt names: DNS:www2.example.com, DNS:www3.example.com + // * Subject should be ignored, because it has subject alt names. + checkWithActualCert("31", R.raw.subject_with_alt_names, "www.example.com", false); + checkWithActualCert("32", R.raw.subject_with_alt_names, "www2.example.com", true); + checkWithActualCert("33", R.raw.subject_with_alt_names, "www3.example.com", true); + checkWithActualCert("34", R.raw.subject_with_alt_names, "www4.example.com", false); + + // subject_with_wild_alt_name + // + // subject: C=JP, CN=www.example.com + // subject alt names: DNS:*.example2.com + // * Subject should be ignored, because it has subject alt names. + checkWithActualCert("41", R.raw.subject_with_wild_alt_name, "www.example.com", false); + checkWithActualCert("42", R.raw.subject_with_wild_alt_name, "www2.example.com", false); + checkWithActualCert("43", R.raw.subject_with_wild_alt_name, "www.example2.com", true); + checkWithActualCert("44", R.raw.subject_with_wild_alt_name, "abc.example2.com", true); + checkWithActualCert("45", R.raw.subject_with_wild_alt_name, "www.example3.com", false); + + // wild_alt_name_only + // + // subject: C=JP + // subject alt names: DNS:*.example.com + checkWithActualCert("51", R.raw.wild_alt_name_only, "www.example.com", true); + checkWithActualCert("52", R.raw.wild_alt_name_only, "www2.example.com", true); + checkWithActualCert("53", R.raw.wild_alt_name_only, "www.example2.com", false); + + // wild_alt_name_only + // + // subject: C=JP + // subject alt names: IP Address:192.168.10.1 + checkWithActualCert("61", R.raw.alt_ip_only, "192.168.10.1", true); + checkWithActualCert("61", R.raw.alt_ip_only, "192.168.10.2", false); + } + + private void checkWithActualCert(String message, int resId, String domain, + boolean expected) throws Exception { + CertificateFactory factory = CertificateFactory.getInstance("X509"); + InputStream certStream = getContext().getResources().openRawResource(resId); + X509Certificate certificate = (X509Certificate) factory.generateCertificate(certStream); + + checkMatch(message, certificate, domain, expected); + } + + /** + * Minimal {@link X509Certificate} implementation for {@link DomainNameValidator}. + */ + private static class StubX509Certificate extends X509Certificate { + private final X500Principal subjectX500Principal; + private Collection<List<?>> subjectAlternativeNames; + + public StubX509Certificate(String subjectDn) { + subjectX500Principal = new X500Principal(subjectDn); + subjectAlternativeNames = null; + } + + public StubX509Certificate addSubjectAlternativeName(int type, String name) { + if (subjectAlternativeNames == null) { + subjectAlternativeNames = new ArrayList<List<?>>(); + } + LinkedList<Object> entry = new LinkedList<Object>(); + entry.add(type); + entry.add(name); + subjectAlternativeNames.add(entry); + return this; + } + + @Override + public Collection<List<?>> getSubjectAlternativeNames() throws CertificateParsingException { + return subjectAlternativeNames; + } + + @Override + public X500Principal getSubjectX500Principal() { + return subjectX500Principal; + } + + @Override + public void checkValidity() throws CertificateExpiredException, + CertificateNotYetValidException { + throw new RuntimeException("Method not implemented"); + } + + @Override + public void checkValidity(Date date) throws CertificateExpiredException, + CertificateNotYetValidException { + throw new RuntimeException("Method not implemented"); + } + + @Override + public int getBasicConstraints() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public Principal getIssuerDN() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public boolean[] getIssuerUniqueID() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public boolean[] getKeyUsage() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public Date getNotAfter() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public Date getNotBefore() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public BigInteger getSerialNumber() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public String getSigAlgName() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public String getSigAlgOID() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public byte[] getSigAlgParams() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public byte[] getSignature() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public Principal getSubjectDN() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public boolean[] getSubjectUniqueID() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public byte[] getTBSCertificate() throws CertificateEncodingException { + throw new RuntimeException("Method not implemented"); + } + + @Override + public int getVersion() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public byte[] getEncoded() throws CertificateEncodingException { + throw new RuntimeException("Method not implemented"); + } + + @Override + public PublicKey getPublicKey() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public String toString() { + throw new RuntimeException("Method not implemented"); + } + + @Override + public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, + InvalidKeyException, NoSuchProviderException, SignatureException { + throw new RuntimeException("Method not implemented"); + } + + @Override + public void verify(PublicKey key, String sigProvider) throws CertificateException, + NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, + SignatureException { + throw new RuntimeException("Method not implemented"); + } + + public Set<String> getCriticalExtensionOIDs() { + throw new RuntimeException("Method not implemented"); + } + + public byte[] getExtensionValue(String oid) { + throw new RuntimeException("Method not implemented"); + } + + public Set<String> getNonCriticalExtensionOIDs() { + throw new RuntimeException("Method not implemented"); + } + + public boolean hasUnsupportedCriticalExtension() { + throw new RuntimeException("Method not implemented"); + } + } +} |