7192189: Support endpoint identification algorithm in RFC 6125
Reviewed-by: xuelei, rhalade
This commit is contained in:
parent
288d1afc5a
commit
72e987e3b4
src/java.base/share/classes/sun/security/util
test/jdk/sun/security/util/HostnameChecker
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -178,7 +178,7 @@ public class HostnameChecker {
|
||||
* Certification Authorities are encouraged to use the dNSName instead.
|
||||
*
|
||||
* Matching is performed using the matching rules specified by
|
||||
* [RFC5280]. If more than one identity of a given type is present in
|
||||
* [RFC6125]. If more than one identity of a given type is present in
|
||||
* the certificate (e.g., more than one dNSName name, a match in any one
|
||||
* of the set is considered acceptable.)
|
||||
*/
|
||||
@ -262,7 +262,7 @@ public class HostnameChecker {
|
||||
/**
|
||||
* Returns true if name matches against template.<p>
|
||||
*
|
||||
* The matching is performed as per RFC 2818 rules for TLS and
|
||||
* The matching is performed as per RFC 2818/6125 rules for TLS and
|
||||
* RFC 2830 rules for LDAP.<p>
|
||||
*
|
||||
* The <code>name</code> parameter should represent a DNS name. The
|
||||
@ -299,9 +299,7 @@ public class HostnameChecker {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (checkType == TYPE_TLS) {
|
||||
return matchAllWildcards(name, template);
|
||||
} else if (checkType == TYPE_LDAP) {
|
||||
if (checkType == TYPE_TLS || checkType == TYPE_LDAP) {
|
||||
return matchLeftmostWildcard(name, template);
|
||||
} else {
|
||||
return false;
|
||||
@ -371,37 +369,6 @@ public class HostnameChecker {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if name matches against template.<p>
|
||||
*
|
||||
* According to RFC 2818, section 3.1 -
|
||||
* Names may contain the wildcard character * which is
|
||||
* considered to match any single domain name component
|
||||
* or component fragment.
|
||||
* E.g., *.a.com matches foo.a.com but not
|
||||
* bar.foo.a.com. f*.com matches foo.com but not bar.com.
|
||||
*/
|
||||
private static boolean matchAllWildcards(String name,
|
||||
String template) {
|
||||
name = name.toLowerCase(Locale.ENGLISH);
|
||||
template = template.toLowerCase(Locale.ENGLISH);
|
||||
StringTokenizer nameSt = new StringTokenizer(name, ".");
|
||||
StringTokenizer templateSt = new StringTokenizer(template, ".");
|
||||
|
||||
if (nameSt.countTokens() != templateSt.countTokens()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (nameSt.hasMoreTokens()) {
|
||||
if (!matchWildCards(nameSt.nextToken(),
|
||||
templateSt.nextToken())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if name matches against template.<p>
|
||||
*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,16 +23,19 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4514108
|
||||
* @summary Verify host name matching behaves as defined in RFC2818.
|
||||
* @bug 4514108 7192189
|
||||
* @summary Verify host name matching behaves as defined in RFC2818 and RFC6125.
|
||||
* @library /test/lib
|
||||
* @modules java.base/sun.security.util
|
||||
* @modules java.base/sun.security.util java.base/sun.security.x509
|
||||
*/
|
||||
|
||||
import java.security.cert.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.test.lib.security.CertUtils;
|
||||
import sun.security.util.*;
|
||||
import sun.security.x509.X509CertImpl;
|
||||
|
||||
/**
|
||||
* Certificate 1:
|
||||
@ -193,10 +196,17 @@ public class TestHostnameChecker {
|
||||
check(checker, "altfoo2.com", cert3, true);
|
||||
check(checker, "5.6.7.8", cert3, true);
|
||||
check(checker, "foo.bar.com", cert4, true);
|
||||
check(checker, "altfoo.bar.com", cert4, true);
|
||||
check(checker, "altfoo.bar.com", cert4, false);
|
||||
check(checker, "2001:db8:3c4d:15::1a2f:1a2b", cert5, true);
|
||||
check(checker, "2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b", cert5, true);
|
||||
check(checker, "2002:db8:3c4d:15::1a2f:1a2b", cert5, false);
|
||||
check(checker, "foo.bar.example.net", mock("foo.*.example.net"), false);
|
||||
check(checker, "baz1.example.net", mock("baz*.example.net"), true);
|
||||
check(checker, "foobaz.example.net", mock("*baz.example.net"), true);
|
||||
check(checker, "buzz.example.net", mock("b*z.example.net"), true);
|
||||
check(checker, "公司.example.net", mock("xn--5*.example.net"), false);
|
||||
check(checker, "公司.江利子.example.net",
|
||||
mock("*.xn--kcry6tjko.example.net"), true);
|
||||
|
||||
checker = HostnameChecker.getInstance(
|
||||
HostnameChecker.TYPE_LDAP);
|
||||
@ -214,6 +224,15 @@ public class TestHostnameChecker {
|
||||
check(checker, "altfoo.bar.com", cert4, false);
|
||||
}
|
||||
|
||||
private static X509Certificate mock(String domain) {
|
||||
return new X509CertImpl() {
|
||||
@Override
|
||||
public Collection<List<?>> getSubjectAlternativeNames() {
|
||||
return List.of(List.of(2, domain));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void check(HostnameChecker checker, String name,
|
||||
X509Certificate cert, boolean expectedResult)
|
||||
throws Exception {
|
||||
@ -224,7 +243,7 @@ public class TestHostnameChecker {
|
||||
}
|
||||
} catch (CertificateException e) {
|
||||
if (expectedResult == true) {
|
||||
throw e;
|
||||
throw new Exception("Failed valid test: " + name, e);
|
||||
}
|
||||
}
|
||||
System.out.println("OK: " + name);
|
Loading…
x
Reference in New Issue
Block a user