8186143: keytool -ext option doesn't accept wildcards for DNS subject alternative names
Reviewed-by: jnimeh, weijun, mullan
This commit is contained in:
parent
a147636157
commit
0c9f8e472f
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -4193,9 +4193,10 @@ public final class Main {
|
|||||||
* Create a GeneralName object from known types
|
* Create a GeneralName object from known types
|
||||||
* @param t one of 5 known types
|
* @param t one of 5 known types
|
||||||
* @param v value
|
* @param v value
|
||||||
|
* @param exttype X.509 extension type
|
||||||
* @return which one
|
* @return which one
|
||||||
*/
|
*/
|
||||||
private GeneralName createGeneralName(String t, String v)
|
private GeneralName createGeneralName(String t, String v, int exttype)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
GeneralNameInterface gn;
|
GeneralNameInterface gn;
|
||||||
int p = oneOf(t, "EMAIL", "URI", "DNS", "IP", "OID");
|
int p = oneOf(t, "EMAIL", "URI", "DNS", "IP", "OID");
|
||||||
@ -4206,7 +4207,14 @@ public final class Main {
|
|||||||
switch (p) {
|
switch (p) {
|
||||||
case 0: gn = new RFC822Name(v); break;
|
case 0: gn = new RFC822Name(v); break;
|
||||||
case 1: gn = new URIName(v); break;
|
case 1: gn = new URIName(v); break;
|
||||||
case 2: gn = new DNSName(v); break;
|
case 2:
|
||||||
|
if (exttype == 3) {
|
||||||
|
// Allow wildcard only for SAN extension
|
||||||
|
gn = new DNSName(v, true);
|
||||||
|
} else {
|
||||||
|
gn = new DNSName(v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 3: gn = new IPAddressName(v); break;
|
case 3: gn = new IPAddressName(v); break;
|
||||||
default: gn = new OIDName(v); break; //4
|
default: gn = new OIDName(v); break; //4
|
||||||
}
|
}
|
||||||
@ -4492,7 +4500,7 @@ public final class Main {
|
|||||||
}
|
}
|
||||||
String t = item.substring(0, colonpos);
|
String t = item.substring(0, colonpos);
|
||||||
String v = item.substring(colonpos+1);
|
String v = item.substring(colonpos+1);
|
||||||
gnames.add(createGeneralName(t, v));
|
gnames.add(createGeneralName(t, v, exttype));
|
||||||
}
|
}
|
||||||
if (exttype == 3) {
|
if (exttype == 3) {
|
||||||
setExt(result, new SubjectAlternativeNameExtension(
|
setExt(result, new SubjectAlternativeNameExtension(
|
||||||
@ -4546,7 +4554,7 @@ public final class Main {
|
|||||||
oid = new ObjectIdentifier("1.3.6.1.5.5.7.48." + p);
|
oid = new ObjectIdentifier("1.3.6.1.5.5.7.48." + p);
|
||||||
}
|
}
|
||||||
accessDescriptions.add(new AccessDescription(
|
accessDescriptions.add(new AccessDescription(
|
||||||
oid, createGeneralName(t, v)));
|
oid, createGeneralName(t, v, exttype)));
|
||||||
}
|
}
|
||||||
if (exttype == 5) {
|
if (exttype == 5) {
|
||||||
setExt(result, new SubjectInfoAccessExtension(accessDescriptions));
|
setExt(result, new SubjectInfoAccessExtension(accessDescriptions));
|
||||||
@ -4569,7 +4577,7 @@ public final class Main {
|
|||||||
}
|
}
|
||||||
String t = item.substring(0, colonpos);
|
String t = item.substring(0, colonpos);
|
||||||
String v = item.substring(colonpos+1);
|
String v = item.substring(colonpos+1);
|
||||||
gnames.add(createGeneralName(t, v));
|
gnames.add(createGeneralName(t, v, exttype));
|
||||||
}
|
}
|
||||||
setExt(result, new CRLDistributionPointsExtension(
|
setExt(result, new CRLDistributionPointsExtension(
|
||||||
isCritical, Collections.singletonList(
|
isCritical, Collections.singletonList(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -69,9 +69,10 @@ public class DNSName implements GeneralNameInterface {
|
|||||||
* Create the DNSName object with the specified name.
|
* Create the DNSName object with the specified name.
|
||||||
*
|
*
|
||||||
* @param name the DNSName.
|
* @param name the DNSName.
|
||||||
* @throws IOException if the name is not a valid DNSName subjectAltName
|
* @param allowWildcard the flag for wildcard checking.
|
||||||
|
* @throws IOException if the name is not a valid DNSName
|
||||||
*/
|
*/
|
||||||
public DNSName(String name) throws IOException {
|
public DNSName(String name, boolean allowWildcard) throws IOException {
|
||||||
if (name == null || name.isEmpty())
|
if (name == null || name.isEmpty())
|
||||||
throw new IOException("DNSName must not be null or empty");
|
throw new IOException("DNSName must not be null or empty");
|
||||||
if (name.contains(" "))
|
if (name.contains(" "))
|
||||||
@ -91,9 +92,26 @@ public class DNSName implements GeneralNameInterface {
|
|||||||
if (endIndex - startIndex < 1)
|
if (endIndex - startIndex < 1)
|
||||||
throw new IOException("DNSName with empty components are not permitted");
|
throw new IOException("DNSName with empty components are not permitted");
|
||||||
|
|
||||||
// RFC 1123: DNSName components must begin with a letter or digit
|
if (allowWildcard) {
|
||||||
if (alphaDigits.indexOf(name.charAt(startIndex)) < 0)
|
// RFC 1123: DNSName components must begin with a letter or digit
|
||||||
throw new IOException("DNSName components must begin with a letter or digit");
|
// or RFC 4592: the first component of a DNSName can have only a wildcard
|
||||||
|
// character * (asterisk), i.e. *.example.com. Asterisks at other components
|
||||||
|
// will not be allowed as a wildcard.
|
||||||
|
if (alphaDigits.indexOf(name.charAt(startIndex)) < 0) {
|
||||||
|
// Checking to make sure the wildcard only appears in the first component,
|
||||||
|
// and it has to be at least 3-char long with the form of *.[alphaDigit]
|
||||||
|
if ((name.length() < 3) || (name.indexOf('*', 0) != 0) ||
|
||||||
|
(name.charAt(startIndex+1) != '.') ||
|
||||||
|
(alphaDigits.indexOf(name.charAt(startIndex+2)) < 0))
|
||||||
|
throw new IOException("DNSName components must begin with a letter, digit, "
|
||||||
|
+ "or the first component can have only a wildcard character *");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// RFC 1123: DNSName components must begin with a letter or digit
|
||||||
|
if (alphaDigits.indexOf(name.charAt(startIndex)) < 0)
|
||||||
|
throw new IOException("DNSName components must begin with a letter or digit");
|
||||||
|
}
|
||||||
|
|
||||||
//nonStartIndex: index for characters in the component beyond the first one
|
//nonStartIndex: index for characters in the component beyond the first one
|
||||||
for (int nonStartIndex=startIndex+1; nonStartIndex < endIndex; nonStartIndex++) {
|
for (int nonStartIndex=startIndex+1; nonStartIndex < endIndex; nonStartIndex++) {
|
||||||
char x = name.charAt(nonStartIndex);
|
char x = name.charAt(nonStartIndex);
|
||||||
@ -104,6 +122,15 @@ public class DNSName implements GeneralNameInterface {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the DNSName object with the specified name.
|
||||||
|
*
|
||||||
|
* @param name the DNSName.
|
||||||
|
* @throws IOException if the name is not a valid DNSName
|
||||||
|
*/
|
||||||
|
public DNSName(String name) throws IOException {
|
||||||
|
this(name, false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the type of the GeneralName.
|
* Return the type of the GeneralName.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -24,7 +24,7 @@
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary DNSName parsing tests
|
* @summary DNSName parsing tests
|
||||||
* @bug 8213952
|
* @bug 8213952 8186143
|
||||||
* @modules java.base/sun.security.x509
|
* @modules java.base/sun.security.x509
|
||||||
* @run testng DNSNameTest
|
* @run testng DNSNameTest
|
||||||
*/
|
*/
|
||||||
@ -53,6 +53,23 @@ public class DNSNameTest {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DataProvider(name = "goodSanNames")
|
||||||
|
public Object[][] goodSanNames() {
|
||||||
|
Object[][] data = {
|
||||||
|
{"abc.com"},
|
||||||
|
{"ABC.COM"},
|
||||||
|
{"a12.com"},
|
||||||
|
{"a1b2c3.com"},
|
||||||
|
{"1abc.com"},
|
||||||
|
{"123.com"},
|
||||||
|
{"abc.com-"}, // end with hyphen
|
||||||
|
{"a-b-c.com"}, // hyphens
|
||||||
|
{"*.domain.com"}, // wildcard in 1st level subdomain
|
||||||
|
{"*.com"},
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
@DataProvider(name = "badNames")
|
@DataProvider(name = "badNames")
|
||||||
public Object[][] badNames() {
|
public Object[][] badNames() {
|
||||||
Object[][] data = {
|
Object[][] data = {
|
||||||
@ -65,10 +82,34 @@ public class DNSNameTest {
|
|||||||
{"a."}, // end with .
|
{"a."}, // end with .
|
||||||
{""}, // empty
|
{""}, // empty
|
||||||
{" "}, // space only
|
{" "}, // space only
|
||||||
|
{"*.domain.com"}, // wildcard not allowed
|
||||||
|
{"a*.com"}, // only allow letter, digit, or hyphen
|
||||||
};
|
};
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DataProvider(name = "badSanNames")
|
||||||
|
public Object[][] badSanNames() {
|
||||||
|
Object[][] data = {
|
||||||
|
{" 1abc.com"}, // begin with space
|
||||||
|
{"1abc.com "}, // end with space
|
||||||
|
{"1a bc.com "}, // no space allowed
|
||||||
|
{"-abc.com"}, // begin with hyphen
|
||||||
|
{"a..b"}, // ..
|
||||||
|
{".a"}, // begin with .
|
||||||
|
{"a."}, // end with .
|
||||||
|
{""}, // empty
|
||||||
|
{" "}, // space only
|
||||||
|
{"*"}, // wildcard only
|
||||||
|
{"*a.com"}, // partial wildcard disallowed
|
||||||
|
{"abc.*.com"}, // wildcard not allowed in 2nd level
|
||||||
|
{"*.*.domain.com"}, // double wildcard not allowed
|
||||||
|
{"a*.com"}, // only allow letter, digit, or hyphen
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test(dataProvider = "goodNames")
|
@Test(dataProvider = "goodNames")
|
||||||
public void testGoodDNSName(String dnsNameString) {
|
public void testGoodDNSName(String dnsNameString) {
|
||||||
try {
|
try {
|
||||||
@ -78,6 +119,15 @@ public class DNSNameTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider = "goodSanNames")
|
||||||
|
public void testGoodSanDNSName(String dnsNameString) {
|
||||||
|
try {
|
||||||
|
DNSName dn = new DNSName(dnsNameString, true);
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("Unexpected IOException");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test(dataProvider = "badNames")
|
@Test(dataProvider = "badNames")
|
||||||
public void testBadDNSName(String dnsNameString) {
|
public void testBadDNSName(String dnsNameString) {
|
||||||
try {
|
try {
|
||||||
@ -88,4 +138,15 @@ public class DNSNameTest {
|
|||||||
fail("Unexpeceted message: " + e);
|
fail("Unexpeceted message: " + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider = "badSanNames")
|
||||||
|
public void testBadSanDNSName(String dnsNameString) {
|
||||||
|
try {
|
||||||
|
DNSName dn = new DNSName(dnsNameString, true);
|
||||||
|
fail("IOException expected");
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (!e.getMessage().contains("DNSName"))
|
||||||
|
fail("Unexpeceted message: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user