diff options
author | Brian Carlstrom <bdc@google.com> | 2012-12-21 14:21:40 -0800 |
---|---|---|
committer | Paul Kocialkowski <contact@paulk.fr> | 2014-11-16 13:52:28 +0100 |
commit | 4417e2559ac202e01f9d795970df5319ea31f83d (patch) | |
tree | a442ab9da2ecc6c7af518c76c8a2d46052b36af9 | |
parent | 7687ea60d46816c65832d061780fb5b02e5e4d7a (diff) | |
download | libcore-4417e2559ac202e01f9d795970df5319ea31f83d.zip libcore-4417e2559ac202e01f9d795970df5319ea31f83d.tar.gz libcore-4417e2559ac202e01f9d795970df5319ea31f83d.tar.bz2 |
Should favor last CN when working with distinguished names
Bug: 7894348
Bug: http://code.google.com/p/android/issues/detail?id=41662
Change-Id: I3814d653b628f6af12ce1ba59b39b1c7cc45e124
4 files changed, 68 insertions, 41 deletions
diff --git a/luni/src/main/java/javax/net/ssl/DefaultHostnameVerifier.java b/luni/src/main/java/javax/net/ssl/DefaultHostnameVerifier.java index e68baca..fa11371 100644 --- a/luni/src/main/java/javax/net/ssl/DefaultHostnameVerifier.java +++ b/luni/src/main/java/javax/net/ssl/DefaultHostnameVerifier.java @@ -80,7 +80,8 @@ public final class DefaultHostnameVerifier implements HostnameVerifier { if (!hasDns) { X500Principal principal = certificate.getSubjectX500Principal(); - String cn = new DistinguishedNameParser(principal).find("cn"); + // RFC 2818 advises using the most specific name for matching. + String cn = new DistinguishedNameParser(principal).findMostSpecific("cn"); if (cn != null) { return verifyHostName(hostName, cn); } diff --git a/luni/src/main/java/javax/net/ssl/DistinguishedNameParser.java b/luni/src/main/java/javax/net/ssl/DistinguishedNameParser.java index fa8ed1b..6280baa 100644 --- a/luni/src/main/java/javax/net/ssl/DistinguishedNameParser.java +++ b/luni/src/main/java/javax/net/ssl/DistinguishedNameParser.java @@ -340,12 +340,12 @@ public final class DistinguishedNameParser { } /** - * Parses the DN and returns the attribute value for an attribute type. + * Parses the DN and returns the most significant attribute value + * for an attribute type, or null if none found. * * @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) { + public String findMostSpecific(String attributeType) { // Initialize internal state. pos = 0; beg = 0; @@ -357,11 +357,15 @@ public final class DistinguishedNameParser { if (attType == null) { return null; } + // Values are ordered from least specific to most specific. We + // remember the most recent choice in result and return it + // when we reach the end of the input. + String result = null; while (true) { String attValue = ""; if (pos == length) { - return null; + return result; } switch (chars[pos]) { @@ -381,11 +385,11 @@ public final class DistinguishedNameParser { } if (attributeType.equalsIgnoreCase(attType)) { - return attValue; + result = attValue; } if (pos >= length) { - return null; + return result; } if (chars[pos] == ',' || chars[pos] == ';') { diff --git a/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java b/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java index 7cb7792..69ae1c1 100644 --- a/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java +++ b/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java @@ -31,7 +31,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Set; import javax.net.ssl.DefaultHostnameVerifier; -import javax.net.ssl.DistinguishedNameParser; import javax.security.auth.x500.X500Principal; import junit.framework.TestCase; @@ -42,39 +41,6 @@ public final class DefaultHostnameVerifierTest extends TestCase { private final DefaultHostnameVerifier verifier = new DefaultHostnameVerifier(); - public void testGetFirstCn() { - assertFirstCn("", null); - assertFirstCn("ou=xxx", null); - assertFirstCn("ou=xxx,cn=xxx", "xxx"); - assertFirstCn("ou=xxx+cn=yyy,cn=zzz+cn=abc", "yyy"); - assertFirstCn("cn=a,cn=b", "a"); - assertFirstCn("cn=Cc,cn=Bb,cn=Aa", "Cc"); - assertFirstCn("cn=imap.gmail.com", "imap.gmail.com"); - } - - public void testGetFirstCnWithOid() { - assertFirstCn("2.5.4.3=a,ou=xxx", "a"); - } - - public void testGetFirstCnWithQuotedStrings() { - assertFirstCn("cn=\"\\\" a ,=<>#;\"", "\" a ,=<>#;"); - assertFirstCn("cn=abc\\,def", "abc,def"); - } - - public void testGetFirstCnWithUtf8() { - assertFirstCn("cn=Lu\\C4\\8Di\\C4\\87", "\u004c\u0075\u010d\u0069\u0107"); - } - - public void testGetFirstCnWithWhitespace() { - assertFirstCn("ou=a, cn= a b ,o=x", "a b"); - assertFirstCn("cn=\" a b \" ,o=x", " a b "); - } - - private void assertFirstCn(String dn, String expected) { - X500Principal principal = new X500Principal(dn); - assertEquals("dn:" + dn, expected, new DistinguishedNameParser(principal).find("cn")); - } - public void testVerify() { assertTrue(verifier.verify("imap.g.com", new StubX509Certificate("cn=imap.g.com"))); assertFalse(verifier.verify("imap.g.com", new StubX509Certificate("cn=imap2.g.com"))); diff --git a/luni/src/test/java/libcore/javax/net/ssl/DistinguishedNameParserTest.java b/luni/src/test/java/libcore/javax/net/ssl/DistinguishedNameParserTest.java new file mode 100644 index 0000000..19430de --- /dev/null +++ b/luni/src/test/java/libcore/javax/net/ssl/DistinguishedNameParserTest.java @@ -0,0 +1,56 @@ +/* + * 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 libcore.javax.net.ssl; + +import javax.net.ssl.DistinguishedNameParser; +import javax.security.auth.x500.X500Principal; +import junit.framework.TestCase; + +public final class DistinguishedNameParserTest extends TestCase { + public void testGetLastCn() { + assertLastCn("", null); + assertLastCn("ou=xxx", null); + assertLastCn("ou=xxx,cn=xxx", "xxx"); + assertLastCn("ou=xxx+cn=yyy,cn=zzz+cn=abc", "abc"); + assertLastCn("cn=a,cn=b", "b"); + assertLastCn("cn=Cc,cn=Bb,cn=Aa", "Aa"); + assertLastCn("cn=imap.gmail.com", "imap.gmail.com"); + } + + public void testGetFirstCnWithOid() { + assertLastCn("2.5.4.3=a,ou=xxx", "a"); + } + + public void testGetFirstCnWithQuotedStrings() { + assertLastCn("cn=\"\\\" a ,=<>#;\"", "\" a ,=<>#;"); + assertLastCn("cn=abc\\,def", "abc,def"); + } + + public void testGetFirstCnWithUtf8() { + assertLastCn("cn=Lu\\C4\\8Di\\C4\\87", "\u004c\u0075\u010d\u0069\u0107"); + } + + public void testGetFirstCnWithWhitespace() { + assertLastCn("ou=a, cn= a b ,o=x", "a b"); + assertLastCn("cn=\" a b \" ,o=x", " a b "); + } + + private void assertLastCn(String dn, String expected) { + X500Principal principal = new X500Principal(dn); + assertEquals(dn, expected, new DistinguishedNameParser(principal).findMostSpecific("cn")); + } +} |