summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jesse Wilson <jessewilson@google.com> 2011-12-27 17:02:32 -0500
committer Jesse Wilson <jessewilson@google.com> 2011-12-27 19:00:56 -0500
commit52cd299eef703030f8fcf7a92f413791301771cc (patch)
tree3f866612ffa3c5b911c417071d8b994166aa5f2f
parent2b072677538de979961b5bf527109fdab1713731 (diff)
Move the frameworks/base hostname verifier into libcore. Part 2/2
Bug: http://b/5619726 Change-Id: I165eb3befcef104ff56ffb466c87c60b632f3194
-rw-r--r--core/java/android/net/http/CertificateChainValidator.java28
-rw-r--r--core/java/com/android/internal/net/DNParser.java450
-rw-r--r--core/java/com/android/internal/net/DomainNameValidator.java260
-rw-r--r--core/tests/coretests/res/raw/alt_ip_only.crt17
-rw-r--r--core/tests/coretests/res/raw/subject_alt_only.crt17
-rw-r--r--core/tests/coretests/res/raw/subject_only.crt18
-rw-r--r--core/tests/coretests/res/raw/subject_with_alt_names.crt19
-rw-r--r--core/tests/coretests/res/raw/subject_with_wild_alt_name.crt18
-rw-r--r--core/tests/coretests/res/raw/wild_alt_name_only.crt17
-rw-r--r--core/tests/coretests/src/com/android/internal/net/DNParserTest.java51
-rw-r--r--core/tests/coretests/src/com/android/internal/net/DomainNameValidatorTest.java401
11 files changed, 11 insertions, 1285 deletions
diff --git a/core/java/android/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java
index 92be37392912..f94d3207f23d 100644
--- a/core/java/android/net/http/CertificateChainValidator.java
+++ b/core/java/android/net/http/CertificateChainValidator.java
@@ -17,32 +17,20 @@
package android.net.http;
-import com.android.internal.net.DomainNameValidator;
-
-import org.apache.harmony.security.provider.cert.X509CertImpl;
-import org.apache.harmony.xnet.provider.jsse.SSLParametersImpl;
-
import java.io.IOException;
-
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.util.Date;
-
+import javax.net.ssl.DefaultHostnameVerifier;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
+import org.apache.harmony.security.provider.cert.X509CertImpl;
+import org.apache.harmony.xnet.provider.jsse.SSLParametersImpl;
/**
* Class responsible for all server certificate validation functionality
- *
+ *
* {@hide}
*/
class CertificateChainValidator {
@@ -53,6 +41,9 @@ class CertificateChainValidator {
private static final CertificateChainValidator sInstance
= new CertificateChainValidator();
+ private static final DefaultHostnameVerifier sVerifier
+ = new DefaultHostnameVerifier();
+
/**
* @return The singleton instance of the certificates chain validator
*/
@@ -147,7 +138,10 @@ class CertificateChainValidator {
throw new IllegalArgumentException("certificate for this site is null");
}
- if (!DomainNameValidator.match(currCertificate, domain)) {
+ boolean valid = domain != null
+ && !domain.isEmpty()
+ && sVerifier.verify(domain, currCertificate);
+ if (!valid) {
if (HttpLog.LOGV) {
HttpLog.v("certificate not for this host: " + domain);
}
diff --git a/core/java/com/android/internal/net/DNParser.java b/core/java/com/android/internal/net/DNParser.java
deleted file mode 100644
index 5254207cd78e..000000000000
--- a/core/java/com/android/internal/net/DNParser.java
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.net;
-
-
-import android.util.Log;
-
-import java.io.IOException;
-
-import javax.security.auth.x500.X500Principal;
-
-/**
- * A simple distinguished name(DN) parser.
- *
- * <p>This class is based on org.apache.harmony.security.x509.DNParser. It's customized to remove
- * external references which are unnecessary for our requirements.
- *
- * <p>This class is only meant for extracting a string value from a DN. e.g. it doesn't support
- * values in the hex-string style.
- *
- * <p>This class is used by {@link DomainNameValidator} only. However, in order to make this
- * class visible from unit tests, it's made public.
- *
- * @hide
- */
-public final class DNParser {
- private static final String TAG = "DNParser";
-
- /** DN to be parsed. */
- private final String dn;
-
- // length of distinguished name string
- private final int length;
-
- private int pos, beg, end;
-
- // tmp vars to store positions of the currently parsed item
- private int cur;
-
- // distinguished name chars
- private char[] chars;
-
- /**
- * Exception message thrown when we failed to parse DN, which shouldn't happen because we
- * only handle DNs that {@link X500Principal#getName} returns, which shouldn't be malformed.
- */
- private static final String ERROR_PARSE_ERROR = "Failed to parse DN";
-
- /**
- * Constructor.
- *
- * @param principal - {@link X500Principal} to be parsed
- */
- public DNParser(X500Principal principal) {
- this.dn = principal.getName(X500Principal.RFC2253);
- this.length = dn.length();
- }
-
- // gets next attribute type: (ALPHA 1*keychar) / oid
- private String nextAT() throws IOException {
-
- // skip preceding space chars, they can present after
- // comma or semicolon (compatibility with RFC 1779)
- for (; pos < length && chars[pos] == ' '; pos++) {
- }
- if (pos == length) {
- return null; // reached the end of DN
- }
-
- // mark the beginning of attribute type
- beg = pos;
-
- // attribute type chars
- pos++;
- for (; pos < length && chars[pos] != '=' && chars[pos] != ' '; pos++) {
- // we don't follow exact BNF syntax here:
- // accept any char except space and '='
- }
- if (pos >= length) {
- // unexpected end of DN
- throw new IOException(ERROR_PARSE_ERROR);
- }
-
- // mark the end of attribute type
- end = pos;
-
- // skip trailing space chars between attribute type and '='
- // (compatibility with RFC 1779)
- if (chars[pos] == ' ') {
- for (; pos < length && chars[pos] != '=' && chars[pos] == ' '; pos++) {
- }
-
- if (chars[pos] != '=' || pos == length) {
- // unexpected end of DN
- throw new IOException(ERROR_PARSE_ERROR);
- }
- }
-
- pos++; //skip '=' char
-
- // skip space chars between '=' and attribute value
- // (compatibility with RFC 1779)
- for (; pos < length && chars[pos] == ' '; pos++) {
- }
-
- // in case of oid attribute type skip its prefix: "oid." or "OID."
- // (compatibility with RFC 1779)
- if ((end - beg > 4) && (chars[beg + 3] == '.')
- && (chars[beg] == 'O' || chars[beg] == 'o')
- && (chars[beg + 1] == 'I' || chars[beg + 1] == 'i')
- && (chars[beg + 2] == 'D' || chars[beg + 2] == 'd')) {
- beg += 4;
- }
-
- return new String(chars, beg, end - beg);
- }
-
- // gets quoted attribute value: QUOTATION *( quotechar / pair ) QUOTATION
- private String quotedAV() throws IOException {
-
- pos++;
- beg = pos;
- end = beg;
- while (true) {
-
- if (pos == length) {
- // unexpected end of DN
- throw new IOException(ERROR_PARSE_ERROR);
- }
-
- if (chars[pos] == '"') {
- // enclosing quotation was found
- pos++;
- break;
- } else if (chars[pos] == '\\') {
- chars[end] = getEscaped();
- } else {
- // shift char: required for string with escaped chars
- chars[end] = chars[pos];
- }
- pos++;
- end++;
- }
-
- // skip trailing space chars before comma or semicolon.
- // (compatibility with RFC 1779)
- for (; pos < length && chars[pos] == ' '; pos++) {
- }
-
- return new String(chars, beg, end - beg);
- }
-
- // gets hex string attribute value: "#" hexstring
- private String hexAV() throws IOException {
-
- if (pos + 4 >= length) {
- // encoded byte array must be not less then 4 c
- throw new IOException(ERROR_PARSE_ERROR);
- }
-
- beg = pos; // store '#' position
- pos++;
- while (true) {
-
- // check for end of attribute value
- // looks for space and component separators
- if (pos == length || chars[pos] == '+' || chars[pos] == ','
- || chars[pos] == ';') {
- end = pos;
- break;
- }
-
- if (chars[pos] == ' ') {
- end = pos;
- pos++;
- // skip trailing space chars before comma or semicolon.
- // (compatibility with RFC 1779)
- for (; pos < length && chars[pos] == ' '; pos++) {
- }
- break;
- } else if (chars[pos] >= 'A' && chars[pos] <= 'F') {
- chars[pos] += 32; //to low case
- }
-
- pos++;
- }
-
- // verify length of hex string
- // encoded byte array must be not less then 4 and must be even number
- int hexLen = end - beg; // skip first '#' char
- if (hexLen < 5 || (hexLen & 1) == 0) {
- throw new IOException(ERROR_PARSE_ERROR);
- }
-
- // get byte encoding from string representation
- byte[] encoded = new byte[hexLen / 2];
- for (int i = 0, p = beg + 1; i < encoded.length; p += 2, i++) {
- encoded[i] = (byte) getByte(p);
- }
-
- return new String(chars, beg, hexLen);
- }
-
- // gets string attribute value: *( stringchar / pair )
- private String escapedAV() throws IOException {
-
- beg = pos;
- end = pos;
- while (true) {
-
- if (pos >= length) {
- // the end of DN has been found
- return new String(chars, beg, end - beg);
- }
-
- switch (chars[pos]) {
- case '+':
- case ',':
- case ';':
- // separator char has beed found
- return new String(chars, beg, end - beg);
- case '\\':
- // escaped char
- chars[end++] = getEscaped();
- pos++;
- break;
- case ' ':
- // need to figure out whether space defines
- // the end of attribute value or not
- cur = end;
-
- pos++;
- chars[end++] = ' ';
-
- for (; pos < length && chars[pos] == ' '; pos++) {
- chars[end++] = ' ';
- }
- if (pos == length || chars[pos] == ',' || chars[pos] == '+'
- || chars[pos] == ';') {
- // separator char or the end of DN has beed found
- return new String(chars, beg, cur - beg);
- }
- break;
- default:
- chars[end++] = chars[pos];
- pos++;
- }
- }
- }
-
- // returns escaped char
- private char getEscaped() throws IOException {
-
- pos++;
- if (pos == length) {
- throw new IOException(ERROR_PARSE_ERROR);
- }
-
- switch (chars[pos]) {
- case '"':
- case '\\':
- case ',':
- case '=':
- case '+':
- case '<':
- case '>':
- case '#':
- case ';':
- case ' ':
- case '*':
- case '%':
- case '_':
- //FIXME: escaping is allowed only for leading or trailing space char
- return chars[pos];
- default:
- // RFC doesn't explicitly say that escaped hex pair is
- // interpreted as UTF-8 char. It only contains an example of such DN.
- return getUTF8();
- }
- }
-
- // decodes UTF-8 char
- // see http://www.unicode.org for UTF-8 bit distribution table
- private char getUTF8() throws IOException {
-
- int res = getByte(pos);
- pos++; //FIXME tmp
-
- if (res < 128) { // one byte: 0-7F
- return (char) res;
- } else if (res >= 192 && res <= 247) {
-
- int count;
- if (res <= 223) { // two bytes: C0-DF
- count = 1;
- res = res & 0x1F;
- } else if (res <= 239) { // three bytes: E0-EF
- count = 2;
- res = res & 0x0F;
- } else { // four bytes: F0-F7
- count = 3;
- res = res & 0x07;
- }
-
- int b;
- for (int i = 0; i < count; i++) {
- pos++;
- if (pos == length || chars[pos] != '\\') {
- return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
- }
- pos++;
-
- b = getByte(pos);
- pos++; //FIXME tmp
- if ((b & 0xC0) != 0x80) {
- return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
- }
-
- res = (res << 6) + (b & 0x3F);
- }
- return (char) res;
- } else {
- return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
- }
- }
-
- // Returns byte representation of a char pair
- // The char pair is composed of DN char in
- // specified 'position' and the next char
- // According to BNF syntax:
- // hexchar = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
- // / "a" / "b" / "c" / "d" / "e" / "f"
- private int getByte(int position) throws IOException {
-
- if ((position + 1) >= length) {
- // to avoid ArrayIndexOutOfBoundsException
- throw new IOException(ERROR_PARSE_ERROR);
- }
-
- int b1, b2;
-
- b1 = chars[position];
- if (b1 >= '0' && b1 <= '9') {
- b1 = b1 - '0';
- } else if (b1 >= 'a' && b1 <= 'f') {
- b1 = b1 - 87; // 87 = 'a' - 10
- } else if (b1 >= 'A' && b1 <= 'F') {
- b1 = b1 - 55; // 55 = 'A' - 10
- } else {
- throw new IOException(ERROR_PARSE_ERROR);
- }
-
- b2 = chars[position + 1];
- if (b2 >= '0' && b2 <= '9') {
- b2 = b2 - '0';
- } else if (b2 >= 'a' && b2 <= 'f') {
- b2 = b2 - 87; // 87 = 'a' - 10
- } else if (b2 >= 'A' && b2 <= 'F') {
- b2 = b2 - 55; // 55 = 'A' - 10
- } else {
- throw new IOException(ERROR_PARSE_ERROR);
- }
-
- return (b1 << 4) + b2;
- }
-
- /**
- * Parses the DN and returns the attribute value for an attribute type.
- *
- * @param attributeType attribute type to look for (e.g. "ca")
- * @return value of the attribute that first found, or null if none found
- */
- public String find(String attributeType) {
- try {
- // Initialize internal state.
- pos = 0;
- beg = 0;
- end = 0;
- cur = 0;
- chars = dn.toCharArray();
-
- String attType = nextAT();
- if (attType == null) {
- return null;
- }
- while (true) {
- String attValue = "";
-
- if (pos == length) {
- return null;
- }
-
- switch (chars[pos]) {
- case '"':
- attValue = quotedAV();
- break;
- case '#':
- attValue = hexAV();
- break;
- case '+':
- case ',':
- case ';': // compatibility with RFC 1779: semicolon can separate RDNs
- //empty attribute value
- break;
- default:
- attValue = escapedAV();
- }
-
- if (attributeType.equalsIgnoreCase(attType)) {
- return attValue;
- }
-
- if (pos >= length) {
- return null;
- }
-
- if (chars[pos] == ',' || chars[pos] == ';') {
- } else if (chars[pos] != '+') {
- throw new IOException(ERROR_PARSE_ERROR);
- }
-
- pos++;
- attType = nextAT();
- if (attType == null) {
- throw new IOException(ERROR_PARSE_ERROR);
- }
- }
- } catch (IOException e) {
- // Parse error shouldn't happen, because we only handle DNs that
- // X500Principal.getName() returns, which shouldn't be malformed.
- Log.e(TAG, "Failed to parse DN: " + dn);
- return null;
- }
- }
-}
diff --git a/core/java/com/android/internal/net/DomainNameValidator.java b/core/java/com/android/internal/net/DomainNameValidator.java
deleted file mode 100644
index 3950655c6fd0..000000000000
--- a/core/java/com/android/internal/net/DomainNameValidator.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * 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.internal.net;
-
-import android.net.NetworkUtils;
-import android.util.Log;
-
-import java.net.InetAddress;
-import java.security.cert.CertificateParsingException;
-import java.security.cert.X509Certificate;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-import javax.security.auth.x500.X500Principal;
-
-/** @hide */
-public class DomainNameValidator {
- private final static String TAG = "DomainNameValidator";
-
- private static final boolean DEBUG = false;
- private static final boolean LOG_ENABLED = false;
-
- private static final int ALT_DNS_NAME = 2;
- private static final int ALT_IPA_NAME = 7;
-
- /**
- * Checks the site certificate against the domain name of the site being visited
- * @param certificate The certificate to check
- * @param thisDomain The domain name of the site being visited
- * @return True iff if there is a domain match as specified by RFC2818
- */
- public static boolean match(X509Certificate certificate, String thisDomain) {
- if (certificate == null || thisDomain == null || thisDomain.length() == 0) {
- return false;
- }
-
- thisDomain = thisDomain.toLowerCase();
- if (!isIpAddress(thisDomain)) {
- return matchDns(certificate, thisDomain);
- } else {
- return matchIpAddress(certificate, thisDomain);
- }
- }
-
- /**
- * @return True iff the domain name is specified as an IP address
- */
- private static boolean isIpAddress(String domain) {
- boolean rval = (domain != null && domain.length() != 0);
- if (rval) {
- try {
- // do a quick-dirty IP match first to avoid DNS lookup
- rval = domain.equals(
- NetworkUtils.numericToInetAddress(domain).getHostAddress());
- } catch (IllegalArgumentException e) {
- if (LOG_ENABLED) {
- Log.v(TAG, "DomainNameValidator.isIpAddress(): " + e);
- }
-
- rval = false;
- }
- }
-
- return rval;
- }
-
- /**
- * Checks the site certificate against the IP domain name of the site being visited
- * @param certificate The certificate to check
- * @param thisDomain The DNS domain name of the site being visited
- * @return True iff if there is a domain match as specified by RFC2818
- */
- private static boolean matchIpAddress(X509Certificate certificate, String thisDomain) {
- if (LOG_ENABLED) {
- Log.v(TAG, "DomainNameValidator.matchIpAddress(): this domain: " + thisDomain);
- }
-
- try {
- Collection subjectAltNames = certificate.getSubjectAlternativeNames();
- if (subjectAltNames != null) {
- Iterator i = subjectAltNames.iterator();
- while (i.hasNext()) {
- List altNameEntry = (List)(i.next());
- if (altNameEntry != null && 2 <= altNameEntry.size()) {
- Integer altNameType = (Integer)(altNameEntry.get(0));
- if (altNameType != null) {
- if (altNameType.intValue() == ALT_IPA_NAME) {
- String altName = (String)(altNameEntry.get(1));
- if (altName != null) {
- if (LOG_ENABLED) {
- Log.v(TAG, "alternative IP: " + altName);
- }
- if (thisDomain.equalsIgnoreCase(altName)) {
- return true;
- }
- }
- }
- }
- }
- }
- }
- } catch (CertificateParsingException e) {}
-
- return false;
- }
-
- /**
- * Checks the site certificate against the DNS domain name of the site being visited
- * @param certificate The certificate to check
- * @param thisDomain The DNS domain name of the site being visited
- * @return True iff if there is a domain match as specified by RFC2818
- */
- private static boolean matchDns(X509Certificate certificate, String thisDomain) {
- boolean hasDns = false;
- try {
- Collection subjectAltNames = certificate.getSubjectAlternativeNames();
- if (subjectAltNames != null) {
- Iterator i = subjectAltNames.iterator();
- while (i.hasNext()) {
- List altNameEntry = (List)(i.next());
- if (altNameEntry != null && 2 <= altNameEntry.size()) {
- Integer altNameType = (Integer)(altNameEntry.get(0));
- if (altNameType != null) {
- if (altNameType.intValue() == ALT_DNS_NAME) {
- hasDns = true;
- String altName = (String)(altNameEntry.get(1));
- if (altName != null) {
- if (matchDns(thisDomain, altName)) {
- return true;
- }
- }
- }
- }
- }
- }
- }
- } catch (CertificateParsingException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "failed to parse certificate";
- }
-
- Log.w(TAG, "DomainNameValidator.matchDns(): " + errorMessage);
- return false;
- }
-
- if (!hasDns) {
- final String cn = new DNParser(certificate.getSubjectX500Principal())
- .find("cn");
- if (LOG_ENABLED) {
- Log.v(TAG, "Validating subject: DN:"
- + certificate.getSubjectX500Principal().getName(X500Principal.CANONICAL)
- + " CN:" + cn);
- }
- if (cn != null) {
- return matchDns(thisDomain, cn);
- }
- }
-
- return false;
- }
-
- /**
- * @param thisDomain The domain name of the site being visited
- * @param thatDomain The domain name from the certificate
- * @return True iff thisDomain matches thatDomain as specified by RFC2818
- */
- // not private for testing
- public static boolean matchDns(String thisDomain, String thatDomain) {
- if (LOG_ENABLED) {
- Log.v(TAG, "DomainNameValidator.matchDns():" +
- " this domain: " + thisDomain +
- " that domain: " + thatDomain);
- }
-
- if (thisDomain == null || thisDomain.length() == 0 ||
- thatDomain == null || thatDomain.length() == 0) {
- return false;
- }
-
- thatDomain = thatDomain.toLowerCase();
-
- // (a) domain name strings are equal, ignoring case: X matches X
- boolean rval = thisDomain.equals(thatDomain);
- if (!rval) {
- String[] thisDomainTokens = thisDomain.split("\\.");
- String[] thatDomainTokens = thatDomain.split("\\.");
-
- int thisDomainTokensNum = thisDomainTokens.length;
- int thatDomainTokensNum = thatDomainTokens.length;
-
- // (b) OR thatHost is a '.'-suffix of thisHost: Z.Y.X matches X
- if (thisDomainTokensNum >= thatDomainTokensNum) {
- for (int i = thatDomainTokensNum - 1; i >= 0; --i) {
- rval = thisDomainTokens[i].equals(thatDomainTokens[i]);
- if (!rval) {
- // (c) OR we have a special *-match:
- // *.Y.X matches Z.Y.X but *.X doesn't match Z.Y.X
- rval = (i == 0 && thisDomainTokensNum == thatDomainTokensNum);
- if (rval) {
- rval = thatDomainTokens[0].equals("*");
- if (!rval) {
- // (d) OR we have a *-component match:
- // f*.com matches foo.com but not bar.com
- rval = domainTokenMatch(
- thisDomainTokens[0], thatDomainTokens[0]);
- }
- }
- break;
- }
- }
- } else {
- // (e) OR thatHost has a '*.'-prefix of thisHost:
- // *.Y.X matches Y.X
- rval = thatDomain.equals("*." + thisDomain);
- }
- }
-
- return rval;
- }
-
- /**
- * @param thisDomainToken The domain token from the current domain name
- * @param thatDomainToken The domain token from the certificate
- * @return True iff thisDomainToken matches thatDomainToken, using the
- * wildcard match as specified by RFC2818-3.1. For example, f*.com must
- * match foo.com but not bar.com
- */
- private static boolean domainTokenMatch(String thisDomainToken, String thatDomainToken) {
- if (thisDomainToken != null && thatDomainToken != null) {
- int starIndex = thatDomainToken.indexOf('*');
- if (starIndex >= 0) {
- if (thatDomainToken.length() - 1 <= thisDomainToken.length()) {
- String prefix = thatDomainToken.substring(0, starIndex);
- String suffix = thatDomainToken.substring(starIndex + 1);
-
- return thisDomainToken.startsWith(prefix) && thisDomainToken.endsWith(suffix);
- }
- }
- }
-
- return false;
- }
-}
diff --git a/core/tests/coretests/res/raw/alt_ip_only.crt b/core/tests/coretests/res/raw/alt_ip_only.crt
deleted file mode 100644
index 3ac9f5a40400..000000000000
--- a/core/tests/coretests/res/raw/alt_ip_only.crt
+++ /dev/null
@@ -1,17 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICsjCCAZqgAwIBAgIJALrC37YAXFIeMA0GCSqGSIb3DQEBBQUAMA0xCzAJBgNV
-BAYTAkpQMCAXDTEwMDExMjIxMzk0NloYDzIwNjQxMDE1MjEzOTQ2WjANMQswCQYD
-VQQGEwJKUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALr8s/4Abpby
-IYks5YCJE2nbWH7kj6XbwnRzsVP9RVC33bPoQ1M+2ZY24HqkigjQS/HEXR0s0bYh
-dewNUnTj1uGyGs6cYzsbu7x114vmVYqjxUo3hKjwfYiPeF6f3IE1vpLI7I2G32gq
-Zwm9c1/vXNHIdWQxCpFcuPA8P3YGfoApFX4pQPFplBUNAQqnjdmA68cbxxMC+1F3
-mX42D7iIEVwyVpah5HjyxjIZQlf3X7QBj0bCmkL+ibIHTALrkNNwNM6i4xzYLz/5
-14GkN9ncHY87eSOk6r53ptER6mQMhCe9qPRjSHnpWTTyj6IXTaYe+dDQw657B80w
-cSHL7Ed25zUCAwEAAaMTMBEwDwYDVR0RBAgwBocEwKgKATANBgkqhkiG9w0BAQUF
-AAOCAQEAgrwrtOWZT3fbi1AafpGaAiOBWSJqYqRhtQy0AfiZBxv1U0XaYqmZmpnq
-DVAqr0NkljowD28NBrxIFO5gBNum2ZOPDl2/5vjFn+IirUCJ9u9wS7zYkTCW2lQR
-xE7Ic3mfWv7wUbKDfjlWqP1IDHUxwkrBTAl+HnwOPiaKKk1ttwcrgS8AHlqASe03
-mlwnvJ+Stk54IneRaegL0L93sNAy63RZqnPCTxGz7eHcFwX8Jdr4sbxTxQqV6pIc
-WPjHQcWfpkFzAF5wyOq0kveVfx0g5xPhOVDd+U+q7WastbXICpCoHp9FxISmZVik
-sAyifp8agkYdzaSh55fFmKXlFnRsQw==
------END CERTIFICATE-----
diff --git a/core/tests/coretests/res/raw/subject_alt_only.crt b/core/tests/coretests/res/raw/subject_alt_only.crt
deleted file mode 100644
index d5808fb6e437..000000000000
--- a/core/tests/coretests/res/raw/subject_alt_only.crt
+++ /dev/null
@@ -1,17 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICvTCCAaWgAwIBAgIJALbA0TZk2YmNMA0GCSqGSIb3DQEBBQUAMA0xCzAJBgNV
-BAYTAkpQMCAXDTEwMDExMjIwNTg1NFoYDzIwNjQxMDE1MjA1ODU0WjANMQswCQYD
-VQQGEwJKUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMEg6acVC9V4
-xNGoLNVLPbqBc8IvMvcsc88dF6MW3d9VagX3aeWU8c79tI/KOV/1AOakH7WYxw/w
-yD8aOX7+9BK1Hu0qKKKbSM+ycqaMthXd6xytrNDsIx5WiGUz8zTko0Gk3orIR7p7
-rPcNzB/zwtESkscqPv85aEn7S/yClNkzLfEzm3CtaYOc0tfhBMyzi/ipXzGMxUmx
-PvOLr3v/Oz5pZEQw7Kxlm4+tAtn7bJlHziQ1UW4WPIy+T3hySBEpODFiqZi7Ok3X
-Zjxdii62fgo5B2Ee7q5Amo0mUIwcQTDjJ2CLAqzYnSh3tpiPJGjEIjmRyCoMQ1bx
-7D+y7nSPIq8CAwEAAaMeMBwwGgYDVR0RBBMwEYIPd3d3LmV4YW1wbGUuY29tMA0G
-CSqGSIb3DQEBBQUAA4IBAQBsGEh+nHc0l9FJTzWqvG3qs7i6XoJZdtThCDx4HjKJ
-8GMrJtreNN4JvIxn7KC+alVbnILjzCRO+c3rsnpxKBi5cp2imjuw5Kf/x2Seimb9
-UvZbaJvBVOzy4Q1IGef9bLy3wZzy2/WfBFyvPTAkgkRaX7LN2jnYOYVhNoNFrwqe
-EWxkA6fzrpyseUEFeGFFjGxRSRCDcQ25Eq6d9rkC1x21zNtt4QwZBO0wHrTy155M
-JPRynf9244Pn0Sr/wsnmdsTRFIFYynrc51hQ7DkwbUxpcaewkZzilru/SwZ3+pPT
-9JSqm5hJ1pg5WDlPkW7c/1VA0/141N52Q8MIU+2ZpuOj
------END CERTIFICATE-----
diff --git a/core/tests/coretests/res/raw/subject_only.crt b/core/tests/coretests/res/raw/subject_only.crt
deleted file mode 100644
index 11b34e7ea3f9..000000000000
--- a/core/tests/coretests/res/raw/subject_only.crt
+++ /dev/null
@@ -1,18 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIC0TCCAbmgAwIBAgIJANCQbJPPw31SMA0GCSqGSIb3DQEBBQUAMCcxCzAJBgNV
-BAYTAkpQMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wIBcNMTAwMTEyMjA1ODE4
-WhgPMjA2NDEwMTUyMDU4MThaMCcxCzAJBgNVBAYTAkpQMRgwFgYDVQQDEw93d3cu
-ZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDsdUJk
-4KxADA3vlDHxNbyC27Ozw4yiSVzPTHUct471YmdDRW3orO2P5a5hRnUGV70gjH9X
-MU4oeOdWYAgXB9pxfLyr6621k1+uNrmaZtzp0ECH9twcwxNJJFDZsN7o9vt7V6Ej
-NN9weeqDr/aeQXo07a12vyVfR6jWO8jHB0e4aemwZNoYjNvM69fivQTse2ZoRVfj
-eSHhjRTX6I8ry4a31Hwt+fT1QiWWNN6o7+WOtpJAhX3eg4smhSD1svi2kOT8tdUe
-NS4hWlmXmumU9G4tI8PBurcLNTm7PB2lUlbn/IV18WavqKE/Uy/1WgAx+a1EJNdp
-i07AG1PsqaONKkf1AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAJrNsuL7fZZNC8gL
-BdePJ7DYW2e7mXANU3bCBe2BZqmXKQxKwibZnEsqA+yMLqcSd8uxISlyHY2tw9wT
-4wB9KPIttfNLbwn/rk+MbOTHpvyF60d9WhJJVUkPBl8D4VuPSl+VnlA54kU9dtZN
-+ZYdxYbNtSsI/Flz9SCoOV79W9GhN+uYJhv6RwyIMIHeMpZpyX1xSUVx5dZlmerQ
-WAUvghDH3fFRt2ZdnA4OXoKkTAaM3Pv7PUMsnah8bux6MQi0AuLMWFWOI1H34koH
-rs2oQLwOLnuifH52ey9+tJguabo+brlYYigAuWWFEzJfBzikDkIwnE/L7wlrypIk
-taXDWI4=
------END CERTIFICATE-----
diff --git a/core/tests/coretests/res/raw/subject_with_alt_names.crt b/core/tests/coretests/res/raw/subject_with_alt_names.crt
deleted file mode 100644
index 6963c7ebec1e..000000000000
--- a/core/tests/coretests/res/raw/subject_with_alt_names.crt
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDBDCCAeygAwIBAgIJALv14qjcuhw9MA0GCSqGSIb3DQEBBQUAMCcxCzAJBgNV
-BAYTAkpQMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wIBcNMTAwMTEyMjA1OTM4
-WhgPMjA2NDEwMTUyMDU5MzhaMCcxCzAJBgNVBAYTAkpQMRgwFgYDVQQDEw93d3cu
-ZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCiTVgU
-kBO9KNYZZLmiPR0eBrk8u61CLnm35BGKW8EFpDaINLbbIFIQvqOMekURON/N+xFY
-D8roo7aFZVuHWAUqFcOJ4e6NmviK5qocLihtzAexsw4f4AzZxM3A8kcLlWLyAt7e
-EVLxhcMHogY7GaF6q+33Z8p+zp6x3tj07mwyPrriCLse2PeRsRunZl/fp/VvRlr6
-YbC7CbRrhnIv5nqohs8BsbBiiFpxQftsMQmiXhY2LUzqY2RXUIOw24fHjoQkHTL2
-4z5nUM3b6ueQe+CBnobUS6fzK/36Nct4dRpev9i/ORdRLuIDKJ+QR16G1V/BJYBR
-dAK+3iXvg6z8vP1XAgMBAAGjMTAvMC0GA1UdEQQmMCSCEHd3dzIuZXhhbXBsZS5j
-b22CEHd3dzMuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQEFBQADggEBAJQNf38uXm3h
-0vsF+Yd6/HqM48Su7tWnTDAfTXnQZZkzjzITq3JXzquMXICktAVN2cLnT9zPfRAE
-8V8A3BNO5zXiR5W3o/mJP5HQ3/WxpzBGM2N+YmDCJyBoQrIVaAZaXAZUaBBvn5A+
-kEVfGWquwIFuvA67xegbJOCRLD4eUzRdNsn5+NFiakWO1tkFqEzqyQ0PNPviRjgu
-z9NxdPvd1JQOhydkucsPKJzlEBbGyL5QL/Jkot3Qy+FOeuNzgQUfAGtQgzRrsZDK
-hrTVypLSoRXuTB2aWilu4p6aNh84xTdyqo2avtNr2MiQMZIcdamBq8LdBIAShFXI
-h5G2eVGXH/Y=
------END CERTIFICATE-----
diff --git a/core/tests/coretests/res/raw/subject_with_wild_alt_name.crt b/core/tests/coretests/res/raw/subject_with_wild_alt_name.crt
deleted file mode 100644
index 19b11744e629..000000000000
--- a/core/tests/coretests/res/raw/subject_with_wild_alt_name.crt
+++ /dev/null
@@ -1,18 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIC8DCCAdigAwIBAgIJAL/oWJ64VAdXMA0GCSqGSIb3DQEBBQUAMCcxCzAJBgNV
-BAYTAkpQMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wIBcNMTAwMTEyMjEwMDAx
-WhgPMjA2NDEwMTUyMTAwMDFaMCcxCzAJBgNVBAYTAkpQMRgwFgYDVQQDEw93d3cu
-ZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbx1QB
-92iea7VybLYICA4MX4LWipYrRsgXUXQrcIQ3YLTQ9rH0VwScrHL4O4JDxgXCQnR+
-4VOzD42q1KXHJAqzqGUYCNPyvZEzkGCnQ4FBIUEmxZd5SNEefJVH3Z6GizYJomTh
-p78yDcoqymD9umxRC2cWFu8GscfFGMVyhsqLlOofu7UWOs22mkXPo43jDx+VOAoV
-n48YP3P57a2Eo0gcd4zVL00y62VegqBO/1LW38aTS7teiCBFc1TkNYa5I40yN9lP
-rB9ICHYQWyzf/7OxU9iauEK2w6DmSsQoLs9JzEhgeNZddkcc77ciSUCo2Hx0VpOJ
-BFyf2rbryJeAk+FDAgMBAAGjHTAbMBkGA1UdEQQSMBCCDiouZXhhbXBsZTIuY29t
-MA0GCSqGSIb3DQEBBQUAA4IBAQA2a14pRL+4laJ8sscQlucaDB/oSdb0cwhk4IkE
-kKl/ZKr6rKwPZ81sJRgzvI4imLbUAKt4AJHdpI9cIQUq1gw9bzil7LKwmFtFSPmC
-MYb1iadaYrvp7RE4yXrWCcSbU0hup9JQLHTrHLlqLtRuU48NHMvWYThBcS9Q/hQp
-nJ/JxYy3am99MHALWLAfuRxQXhE4C5utDmBwI2KD6A8SA30s+CnuegmkYScuSqBu
-Y3R0HZvKzNIU3pwAm69HCJoG+/9MZEIDJb0WJc5UygxDT45XE9zQMQe4dBOTaNXT
-+ntgaB62kE10HzrzpqXAgoAWxWK4RzFcUpBWw9qYq9xOCewJ
------END CERTIFICATE-----
diff --git a/core/tests/coretests/res/raw/wild_alt_name_only.crt b/core/tests/coretests/res/raw/wild_alt_name_only.crt
deleted file mode 100644
index fafdebfb32bd..000000000000
--- a/core/tests/coretests/res/raw/wild_alt_name_only.crt
+++ /dev/null
@@ -1,17 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICuzCCAaOgAwIBAgIJAP82tgcvmAGxMA0GCSqGSIb3DQEBBQUAMA0xCzAJBgNV
-BAYTAkpQMCAXDTEwMDExMjIxMDAyN1oYDzIwNjQxMDE1MjEwMDI3WjANMQswCQYD
-VQQGEwJKUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALs528EQbcB1
-x4BwxthQBZrgDJzoO7KPV3dhGYoeP8EnRjapZm+T/sj9P/O4HvfxjnB+fsjYSdmE
-WWUtnFrP7wtG9DUC748Ea2PMV8WFhOG58dqBNIko5XzkHB7SxkNZD5S/0KQYMGLr
-rchDsDlmsEf2Qb6qiqpNEU70aSkExZJcH+B9nWdeBpsVFu7wtezwSWEc2NUa2bhW
-gcXQ/aafwHZ4o2PyGwy0sgS/UifqO9tEllC2tPleSNJOmYsVudv5Bz4Q0GG38BSz
-Pc0IcOoln0ZWpXbGr03V2vlXWCwzaFAl3I1T3O7YVqDiaSWoP+d0tHZzmw8aJLXd
-B+KaUUGxRPsCAwEAAaMcMBowGAYDVR0RBBEwD4INKi5leGFtcGxlLmNvbTANBgkq
-hkiG9w0BAQUFAAOCAQEAJbVan4QgJ0cvpJnK9UWIVJNC+UbP87RC5go2fQiTnmGv
-prOrIuMqz1+vGcpIheLTLctJRHPoadXq0+UbQEIaU3pQbY6C4nNdfl+hcvmJeqrt
-kOCcvmIamO68iNvTSeszuHuu4O38PefrW2Xd0nn7bjFZrzBzHFhTudmnqNliP3ue
-KKQpqkUt5lCytnH8V/u/UCWdvVx5LnUa2XFGVLi3ongBIojW5fvF+yxn9ADqxdrI
-va++ow5r1VxQXFJc0ZPzsDo+6TlktoDHaRQJGMqQomqHWT4i7F5UZgf6BHGfEUPU
-qep+GsF3QRHSBtpObWkVDZNFvky3a1iZ2q25+hFIqQ==
------END CERTIFICATE-----
diff --git a/core/tests/coretests/src/com/android/internal/net/DNParserTest.java b/core/tests/coretests/src/com/android/internal/net/DNParserTest.java
deleted file mode 100644
index 9b490a329d57..000000000000
--- a/core/tests/coretests/src/com/android/internal/net/DNParserTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.internal.net;
-
-import com.android.internal.net.DNParser;
-
-import javax.security.auth.x500.X500Principal;
-
-import junit.framework.TestCase;
-
-public class DNParserTest extends TestCase {
- public void testFind() {
- checkFind("", "cn", null);
- checkFind("ou=xxx", "cn", null);
- checkFind("ou=xxx,cn=xxx", "cn", "xxx");
- checkFind("ou=xxx+cn=yyy,cn=zzz+cn=abc", "cn", "yyy");
- checkFind("2.5.4.3=a,ou=xxx", "cn", "a"); // OID
- checkFind("cn=a,cn=b", "cn", "a");
- checkFind("ou=Cc,ou=Bb,ou=Aa", "ou", "Cc");
- checkFind("cn=imap.gmail.com", "cn", "imap.gmail.com");
-
- // Quoted string (see http://www.ietf.org/rfc/rfc2253.txt)
- checkFind("o=\"\\\" a ,=<>#;\"", "o", "\" a ,=<>#;");
- checkFind("o=abc\\,def", "o", "abc,def");
-
- // UTF-8 (example in rfc 2253)
- checkFind("cn=Lu\\C4\\8Di\\C4\\87", "cn", "\u004c\u0075\u010d\u0069\u0107");
-
- // whitespaces
- checkFind("ou=a, o= a b ,cn=x", "o", "a b");
- checkFind("o=\" a b \" ,cn=x", "o", " a b ");
- }
-
- private void checkFind(String dn, String attrType, String expected) {
- String actual = new DNParser(new X500Principal(dn)).find(attrType);
- assertEquals("dn:" + dn + " attr:" + attrType, expected, actual);
- }
-}
diff --git a/core/tests/coretests/src/com/android/internal/net/DomainNameValidatorTest.java b/core/tests/coretests/src/com/android/internal/net/DomainNameValidatorTest.java
deleted file mode 100644
index f0d581e855ae..000000000000
--- a/core/tests/coretests/src/com/android/internal/net/DomainNameValidatorTest.java
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * 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.internal.net;
-
-import com.android.internal.net.DomainNameValidator;
-import com.android.frameworks.coretests.R;
-import com.android.frameworks.coretests.R.raw;
-
-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");
- }
- }
-}