diff options
| author | 2011-12-27 17:02:32 -0500 | |
|---|---|---|
| committer | 2011-12-27 19:00:56 -0500 | |
| commit | 52cd299eef703030f8fcf7a92f413791301771cc (patch) | |
| tree | 3f866612ffa3c5b911c417071d8b994166aa5f2f | |
| parent | 2b072677538de979961b5bf527109fdab1713731 (diff) | |
Move the frameworks/base hostname verifier into libcore. Part 2/2
Bug: http://b/5619726
Change-Id: I165eb3befcef104ff56ffb466c87c60b632f3194
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"); - } - } -} |