summaryrefslogtreecommitdiffstats
path: root/luni
diff options
context:
space:
mode:
authorAlex Klyubin <klyubin@google.com>2014-07-24 09:40:56 -0700
committerAlex Klyubin <klyubin@google.com>2014-07-25 14:41:06 -0700
commit4fec20ecd901a10bd027f7bfdeca0337913feec3 (patch)
treec3c6da7cb83c72d4954e020f87e3a86928873da8 /luni
parent1fe89b7b72ff2469d8398426638ca594d2b42ef7 (diff)
downloadlibcore-4fec20ecd901a10bd027f7bfdeca0337913feec3.tar.gz
libcore-4fec20ecd901a10bd027f7bfdeca0337913feec3.tar.bz2
libcore-4fec20ecd901a10bd027f7bfdeca0337913feec3.zip
DO NOT MERGE: Add a way to get all values of an attribute of DN.
This is needed to switch Apache HTTP hostname verification from its own Distinguished Name (DN) parsing code to this library's DistinguishedNameParser. Bug: 16510257 (cherry picked from commit 7bbe7cb0a77527a8d4043315f70c156b2447b462) Change-Id: I4a20729dad557aebe0bd055736777e34b51167e8
Diffstat (limited to 'luni')
-rw-r--r--luni/src/main/java/javax/net/ssl/DistinguishedNameParser.java70
-rw-r--r--luni/src/test/java/libcore/javax/net/ssl/DistinguishedNameParserTest.java68
2 files changed, 138 insertions, 0 deletions
diff --git a/luni/src/main/java/javax/net/ssl/DistinguishedNameParser.java b/luni/src/main/java/javax/net/ssl/DistinguishedNameParser.java
index fa8ed1bf0..6d3659e75 100644
--- a/luni/src/main/java/javax/net/ssl/DistinguishedNameParser.java
+++ b/luni/src/main/java/javax/net/ssl/DistinguishedNameParser.java
@@ -17,6 +17,9 @@
package javax.net.ssl;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import javax.security.auth.x500.X500Principal;
/**
@@ -400,4 +403,71 @@ public final class DistinguishedNameParser {
}
}
}
+
+ /**
+ * Parses the DN and returns all values for an attribute type, in
+ * the order of decreasing significance (most significant first).
+ *
+ * @param attributeType attribute type to look for (e.g. "ca")
+ */
+ public List<String> getAllMostSpecificFirst(String attributeType) {
+ // Initialize internal state.
+ pos = 0;
+ beg = 0;
+ end = 0;
+ cur = 0;
+ chars = dn.toCharArray();
+ List<String> result = Collections.emptyList();
+
+ String attType = nextAT();
+ if (attType == null) {
+ return result;
+ }
+ while (pos < length) {
+ String attValue = "";
+
+ 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();
+ }
+
+ // Values are ordered from most specific to least specific
+ // due to the RFC2253 formatting. So take the first match
+ // we see.
+ if (attributeType.equalsIgnoreCase(attType)) {
+ if (result.isEmpty()) {
+ result = new ArrayList<String>();
+ }
+ result.add(attValue);
+ }
+
+ if (pos >= length) {
+ break;
+ }
+
+ if (chars[pos] == ',' || chars[pos] == ';') {
+ } else if (chars[pos] != '+') {
+ throw new IllegalStateException("Malformed DN: " + dn);
+ }
+
+ pos++;
+ attType = nextAT();
+ if (attType == null) {
+ throw new IllegalStateException("Malformed DN: " + dn);
+ }
+ }
+
+ return result;
+ }
}
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 000000000..f4b05cc97
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/net/ssl/DistinguishedNameParserTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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;
+import java.util.Arrays;
+
+public final class DistinguishedNameParserTest extends TestCase {
+ public void testGetCns() {
+ assertCns("");
+ assertCns("ou=xxx");
+ assertCns("ou=xxx,cn=xxx", "xxx");
+ assertCns("ou=xxx+cn=yyy,cn=zzz+cn=abc", "yyy", "zzz", "abc");
+ assertCns("cn=a,cn=b", "a", "b");
+ assertCns("cn=Cc,cn=Bb,cn=Aa", "Cc", "Bb", "Aa");
+ assertCns("cn=imap.gmail.com", "imap.gmail.com");
+ assertCns("l=\"abcn=a,b\", cn=c", "c");
+ }
+
+ public void testGetCnsWithOid() {
+ assertCns("2.5.4.3=a,ou=xxx", "a");
+ }
+
+ public void testGetCnsWithQuotedStrings() {
+ assertCns("cn=\"\\\" a ,=<>#;\"", "\" a ,=<>#;");
+ assertCns("cn=abc\\,def", "abc,def");
+ }
+
+ public void testGetCnsWithUtf8() {
+ assertCns("cn=Lu\\C4\\8Di\\C4\\87", "\u004c\u0075\u010d\u0069\u0107");
+ }
+
+ public void testGetCnsWithWhitespace() {
+ assertCns("ou=a, cn= a b ,o=x", "a b");
+ assertCns("cn=\" a b \" ,o=x", " a b ");
+ }
+
+ private void assertCns(String dn, String... expected) {
+ X500Principal principal = new X500Principal(dn);
+ DistinguishedNameParser parser = new DistinguishedNameParser(principal);
+
+ // Test getAllMostSpecificFirst
+ assertEquals(dn, Arrays.asList(expected), parser.getAllMostSpecificFirst("cn"));
+
+ // Test find
+ if (expected.length > 0) {
+ assertEquals(dn, expected[0], parser.find("cn"));
+ } else {
+ assertNull(dn, parser.find("cn"));
+ }
+ }
+}