mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8201815: Use Mozilla Public Suffix List
Reviewed-by: michaelm, erikj, ihse
This commit is contained in:
parent
19f5116cd9
commit
60ff77bd97
13 changed files with 13920 additions and 928 deletions
637
src/java.base/share/classes/sun/security/util/DomainName.java
Normal file
637
src/java.base/share/classes/sun/security/util/DomainName.java
Normal file
|
@ -0,0 +1,637 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 2018, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import sun.security.ssl.SSLLogger;
|
||||
|
||||
/**
|
||||
* Allows public suffixes and registered domains to be determined from a
|
||||
* string that represents a target domain name. A database of known
|
||||
* registered suffixes is used to perform the determination.
|
||||
*
|
||||
* A public suffix is defined as the rightmost part of a domain name
|
||||
* that is not owned by an individual registrant. Examples of
|
||||
* public suffixes are:
|
||||
* com
|
||||
* edu
|
||||
* co.uk
|
||||
* k12.ak.us
|
||||
* com.tw
|
||||
* \u7db2\u8def.tw
|
||||
*
|
||||
* Public suffixes effectively denote registration authorities.
|
||||
*
|
||||
* A registered domain is a public suffix preceded by one domain label
|
||||
* and a ".". Examples are:
|
||||
* oracle.com
|
||||
* mit.edu
|
||||
*
|
||||
* The internal database is derived from the information maintained at
|
||||
* http://publicsuffix.org. The information is fixed for a particular
|
||||
* JDK installation, but may be updated in future releases or updates.
|
||||
*
|
||||
* Because of the large number of top-level domains (TLDs) and public
|
||||
* suffix rules, we only load the rules on demand -- from a Zip file
|
||||
* containing an entry for each TLD.
|
||||
*
|
||||
* As each entry is loaded, its data is stored permanently in a cache.
|
||||
*
|
||||
* The containment hierarchy for the data is shown below:
|
||||
*
|
||||
* Rules --> contains all the rules for a particular TLD
|
||||
* RuleSet --> contains all the rules that match 1 label
|
||||
* RuleSet --> contains all the rules that match 2 labels
|
||||
* RuleSet --> contains all the rules that match 3 labels
|
||||
* :
|
||||
* RuleSet --> contains all the rules that match N labels
|
||||
* HashSet of rules, where each rule is an exception rule, a "normal"
|
||||
* rule, a wildcard rule (rules that contain a wildcard prefix only),
|
||||
* or a LinkedList of "other" rules
|
||||
*
|
||||
* The general matching algorithm tries to find a longest match. So, the
|
||||
* search begins at the RuleSet with the most labels, and works backwards.
|
||||
*
|
||||
* Exceptions take priority over all other rules, and if a Rule contains
|
||||
* any exceptions, then even if we find a "normal" match, we search all
|
||||
* other RuleSets for exceptions. It is assumed that all other rules don't
|
||||
* intersect/overlap. If this happens, a match will be returned, but not
|
||||
* necessarily the expected one. For a further explanation of the rules,
|
||||
* see http://publicsuffix.org/list/.
|
||||
*
|
||||
* The "other" rules are for the (possible future) case where wildcards
|
||||
* are located in a rule any place other than the beginning.
|
||||
*/
|
||||
|
||||
class DomainName {
|
||||
/**
|
||||
* For efficiency, the set of rules for each TLD is kept
|
||||
* in text files and only loaded if needed.
|
||||
*/
|
||||
private static final Map<String, Rules> cache = new ConcurrentHashMap<>();
|
||||
|
||||
private DomainName() {}
|
||||
|
||||
/**
|
||||
* Returns the registered domain of the specified domain.
|
||||
*
|
||||
* @param domain the domain name
|
||||
* @return the registered domain, or null if not known or not registerable
|
||||
* @throws NullPointerException if domain is null
|
||||
*/
|
||||
public static RegisteredDomain registeredDomain(String domain) {
|
||||
Match match = getMatch(domain);
|
||||
return (match != null) ? match.registeredDomain() : null;
|
||||
}
|
||||
|
||||
private static Match getMatch(String domain) {
|
||||
if (domain == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
Rules rules = Rules.getRules(domain);
|
||||
return rules == null ? null : rules.match(domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Rules object contains a list of rules for a particular TLD.
|
||||
*
|
||||
* Rules are stored in a linked list of RuleSet objects. The list is
|
||||
* indexed according to the number of labels in the name (minus one)
|
||||
* such that all rules with the same number of labels are stored
|
||||
* in the same RuleSet.
|
||||
*
|
||||
* Doing this means we can find the longest match first, and also we
|
||||
* can stop comparing as soon as we find a match.
|
||||
*/
|
||||
private static class Rules {
|
||||
|
||||
private final LinkedList<RuleSet> ruleSets = new LinkedList<>();
|
||||
private final boolean hasExceptions;
|
||||
|
||||
private Rules(InputStream is) throws IOException {
|
||||
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
|
||||
BufferedReader reader = new BufferedReader(isr);
|
||||
boolean hasExceptions = false;
|
||||
|
||||
String line;
|
||||
int type = reader.read();
|
||||
while (type != -1 && (line = reader.readLine()) != null) {
|
||||
int numLabels = RuleSet.numLabels(line);
|
||||
if (numLabels != 0) {
|
||||
RuleSet ruleset = getRuleSet(numLabels - 1);
|
||||
ruleset.addRule(type, line);
|
||||
hasExceptions |= ruleset.hasExceptions;
|
||||
}
|
||||
type = reader.read();
|
||||
}
|
||||
this.hasExceptions = hasExceptions;
|
||||
}
|
||||
|
||||
static Rules getRules(String domain) {
|
||||
String tld = getTopLevelDomain(domain);
|
||||
if (tld.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return cache.computeIfAbsent(tld, k -> createRules(tld));
|
||||
}
|
||||
|
||||
private static String getTopLevelDomain(String domain) {
|
||||
int n = domain.lastIndexOf('.');
|
||||
if (n == -1) {
|
||||
return domain;
|
||||
}
|
||||
return domain.substring(n + 1);
|
||||
}
|
||||
|
||||
private static Rules createRules(String tld) {
|
||||
try (InputStream pubSuffixStream = getPubSuffixStream()) {
|
||||
if (pubSuffixStream == null) {
|
||||
return null;
|
||||
}
|
||||
return getRules(tld, new ZipInputStream(pubSuffixStream));
|
||||
} catch (IOException e) {
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
|
||||
SSLLogger.fine(
|
||||
"cannot parse public suffix data for " + tld +
|
||||
": " + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static InputStream getPubSuffixStream() {
|
||||
InputStream is = AccessController.doPrivileged(
|
||||
new PrivilegedAction<>() {
|
||||
@Override
|
||||
public InputStream run() {
|
||||
File f = new File(System.getProperty("java.home"),
|
||||
"lib/security/public_suffix_list.dat");
|
||||
try {
|
||||
return new FileInputStream(f);
|
||||
} catch (FileNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
if (is == null) {
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl") &&
|
||||
SSLLogger.isOn("trustmanager")) {
|
||||
SSLLogger.fine(
|
||||
"lib/security/public_suffix_list.dat not found");
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
private static Rules getRules(String tld,
|
||||
ZipInputStream zis) throws IOException {
|
||||
boolean found = false;
|
||||
ZipEntry ze = zis.getNextEntry();
|
||||
while (ze != null && !found) {
|
||||
if (ze.getName().equals(tld)) {
|
||||
found = true;
|
||||
} else {
|
||||
ze = zis.getNextEntry();
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
|
||||
SSLLogger.fine("Domain " + tld + " not found");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return new Rules(zis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the requested RuleSet. If it hasn't been created yet,
|
||||
* create it and any RuleSets leading up to it.
|
||||
*/
|
||||
private RuleSet getRuleSet(int index) {
|
||||
if (index < ruleSets.size()) {
|
||||
return ruleSets.get(index);
|
||||
}
|
||||
RuleSet r = null;
|
||||
for (int i = ruleSets.size(); i <= index; i++) {
|
||||
r = new RuleSet(i + 1);
|
||||
ruleSets.add(r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a match for the target string.
|
||||
*/
|
||||
Match match(String domain) {
|
||||
// Start at the end of the rules list, looking for longest match.
|
||||
// After we find a normal match, we only look for exceptions.
|
||||
Match possibleMatch = null;
|
||||
|
||||
Iterator<RuleSet> it = ruleSets.descendingIterator();
|
||||
while (it.hasNext()) {
|
||||
RuleSet ruleSet = it.next();
|
||||
Match match = ruleSet.match(domain);
|
||||
if (match != null) {
|
||||
if (match.type() == Rule.Type.EXCEPTION || !hasExceptions) {
|
||||
return match;
|
||||
}
|
||||
if (possibleMatch == null) {
|
||||
possibleMatch = match;
|
||||
}
|
||||
}
|
||||
}
|
||||
return possibleMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a set of rules with the same number of labels
|
||||
* and for a particular TLD.
|
||||
*
|
||||
* Examples:
|
||||
* numLabels = 2
|
||||
* names: co.uk, ac.uk
|
||||
* wildcards *.de (only "de" stored in HashSet)
|
||||
* exceptions: !foo.de (stored as "foo.de")
|
||||
*/
|
||||
private static class RuleSet {
|
||||
// the number of labels in this ruleset
|
||||
private final int numLabels;
|
||||
private final Set<Rule> rules = new HashSet<>();
|
||||
boolean hasExceptions = false;
|
||||
private static final RegisteredDomain.Type[] AUTHS =
|
||||
RegisteredDomain.Type.values();
|
||||
|
||||
RuleSet(int n) {
|
||||
numLabels = n;
|
||||
}
|
||||
|
||||
void addRule(int auth, String rule) {
|
||||
if (rule.startsWith("!")) {
|
||||
rules.add(new Rule(rule.substring(1), Rule.Type.EXCEPTION,
|
||||
AUTHS[auth]));
|
||||
hasExceptions = true;
|
||||
} else if (rule.startsWith("*.") &&
|
||||
rule.lastIndexOf('*') == 0) {
|
||||
rules.add(new Rule(rule.substring(2), Rule.Type.WILDCARD,
|
||||
AUTHS[auth]));
|
||||
} else if (rule.indexOf('*') == -1) {
|
||||
// a "normal" label
|
||||
rules.add(new Rule(rule, Rule.Type.NORMAL, AUTHS[auth]));
|
||||
} else {
|
||||
// There is a wildcard in a non-leading label. This case
|
||||
// doesn't currently exist, but we need to handle it anyway.
|
||||
rules.add(new OtherRule(rule, AUTHS[auth], split(rule)));
|
||||
}
|
||||
}
|
||||
|
||||
Match match(String domain) {
|
||||
Match match = null;
|
||||
for (Rule rule : rules) {
|
||||
switch (rule.type) {
|
||||
case NORMAL:
|
||||
if (match == null) {
|
||||
match = matchNormal(domain, rule);
|
||||
}
|
||||
break;
|
||||
case WILDCARD:
|
||||
if (match == null) {
|
||||
match = matchWildcard(domain, rule);
|
||||
}
|
||||
break;
|
||||
case OTHER:
|
||||
if (match == null) {
|
||||
match = matchOther(domain, rule);
|
||||
}
|
||||
break;
|
||||
case EXCEPTION:
|
||||
Match excMatch = matchException(domain, rule);
|
||||
if (excMatch != null) {
|
||||
return excMatch;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
private static LinkedList<String> split(String rule) {
|
||||
String[] labels = rule.split("\\.");
|
||||
return new LinkedList<>(Arrays.asList(labels));
|
||||
}
|
||||
|
||||
private static int numLabels(String rule) {
|
||||
if (rule.equals("")) {
|
||||
return 0;
|
||||
}
|
||||
int len = rule.length();
|
||||
int count = 0;
|
||||
int index = 0;
|
||||
while (index < len) {
|
||||
int pos;
|
||||
if ((pos = rule.indexOf('.', index)) == -1) {
|
||||
return count + 1;
|
||||
}
|
||||
index = pos + 1;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for a match with an explicit name rule or a wildcard rule
|
||||
* (i.e., a non-exception rule).
|
||||
*/
|
||||
private Match matchNormal(String domain, Rule rule) {
|
||||
int index = labels(domain, numLabels);
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check for explicit names.
|
||||
String substring = domain.substring(index);
|
||||
if (rule.domain.equals(substring)) {
|
||||
return new CommonMatch(domain, rule, index);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Match matchWildcard(String domain, Rule rule) {
|
||||
// Now check for wildcards. In this case, there is one fewer
|
||||
// label than numLabels.
|
||||
int index = labels(domain, numLabels - 1);
|
||||
if (index > 0) {
|
||||
String substring = domain.substring(index);
|
||||
|
||||
if (rule.domain.equals(substring)) {
|
||||
return new CommonMatch(domain, rule,
|
||||
labels(domain, numLabels));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for a match with an exception rule.
|
||||
*/
|
||||
private Match matchException(String domain, Rule rule) {
|
||||
int index = labels(domain, numLabels);
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
String substring = domain.substring(index);
|
||||
|
||||
if (rule.domain.equals(substring)) {
|
||||
return new CommonMatch(domain, rule,
|
||||
labels(domain, numLabels - 1));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A left-to-right comparison of labels.
|
||||
* The simplest approach to doing match() would be to
|
||||
* use a descending iterator giving a right-to-left comparison.
|
||||
* But, it's more efficient to do left-to-right compares
|
||||
* because the left most labels are the ones most likely to be
|
||||
* different. We just have to figure out which label to start at.
|
||||
*/
|
||||
private Match matchOther(String domain, Rule rule) {
|
||||
OtherRule otherRule = (OtherRule)rule;
|
||||
LinkedList<String> target = split(domain);
|
||||
|
||||
int diff = target.size() - numLabels;
|
||||
if (diff < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean found = true;
|
||||
for (int i = 0; i < numLabels; i++) {
|
||||
String ruleLabel = otherRule.labels.get(i);
|
||||
String targetLabel = target.get(i + diff);
|
||||
|
||||
if (ruleLabel.charAt(0) != '*' &&
|
||||
!ruleLabel.equalsIgnoreCase(targetLabel)) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
return new OtherMatch(rule, numLabels, target);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a substring (index) with the n right-most labels from s.
|
||||
* Returns -1 if s does not have at least n labels, 0, if the
|
||||
* substring is s.
|
||||
*/
|
||||
private static int labels(String s, int n) {
|
||||
if (n < 1) {
|
||||
return -1;
|
||||
}
|
||||
int index = s.length();
|
||||
for (int i = 0; i < n; i++) {
|
||||
int next = s.lastIndexOf('.', index);
|
||||
if (next == -1) {
|
||||
if (i == n - 1) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
index = next - 1;
|
||||
}
|
||||
return index + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Rule {
|
||||
enum Type { EXCEPTION, NORMAL, OTHER, WILDCARD }
|
||||
|
||||
String domain;
|
||||
Type type;
|
||||
RegisteredDomain.Type auth;
|
||||
Rule(String domain, Type type, RegisteredDomain.Type auth) {
|
||||
this.domain = domain;
|
||||
this.type = type;
|
||||
this.auth = auth;
|
||||
}
|
||||
}
|
||||
|
||||
private static class OtherRule extends Rule {
|
||||
List<String> labels;
|
||||
OtherRule(String domain, RegisteredDomain.Type auth,
|
||||
List<String> labels) {
|
||||
super(domain, Type.OTHER, auth);
|
||||
this.labels = labels;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a string's match with a rule in the public suffix list.
|
||||
*/
|
||||
private interface Match {
|
||||
RegisteredDomain registeredDomain();
|
||||
Rule.Type type();
|
||||
}
|
||||
|
||||
private static class RegisteredDomainImpl implements RegisteredDomain {
|
||||
private final String name;
|
||||
private final Type type;
|
||||
private final String publicSuffix;
|
||||
RegisteredDomainImpl(String name, Type type, String publicSuffix) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.publicSuffix = publicSuffix;
|
||||
}
|
||||
@Override
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
@Override
|
||||
public Type type() {
|
||||
return type;
|
||||
}
|
||||
@Override
|
||||
public String publicSuffix() {
|
||||
return publicSuffix;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a match against a standard rule in the public suffix list.
|
||||
* A standard rule is an explicit name, a wildcard rule with a wildcard
|
||||
* only in the leading label, or an exception rule.
|
||||
*/
|
||||
private static class CommonMatch implements Match {
|
||||
private String domain;
|
||||
private int publicSuffix; // index to
|
||||
private int registeredDomain; // index to
|
||||
private final Rule rule;
|
||||
|
||||
CommonMatch(String domain, Rule rule, int publicSuffix) {
|
||||
this.domain = domain;
|
||||
this.publicSuffix = publicSuffix;
|
||||
this.rule = rule;
|
||||
// now locate the previous label
|
||||
registeredDomain = domain.lastIndexOf('.', publicSuffix - 2);
|
||||
if (registeredDomain == -1) {
|
||||
registeredDomain = 0;
|
||||
} else {
|
||||
registeredDomain++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegisteredDomain registeredDomain() {
|
||||
if (publicSuffix == 0) {
|
||||
return null;
|
||||
}
|
||||
return new RegisteredDomainImpl(domain.substring(registeredDomain),
|
||||
rule.auth,
|
||||
domain.substring(publicSuffix));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rule.Type type() {
|
||||
return rule.type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a non-match with {@code NO_MATCH} or a match against
|
||||
* a non-standard rule in the public suffix list. A non-standard rule
|
||||
* is a wildcard rule that includes wildcards in a label other than
|
||||
* the leading label. The public suffix list doesn't currently have
|
||||
* such rules.
|
||||
*/
|
||||
private static class OtherMatch implements Match {
|
||||
private final Rule rule;
|
||||
private final int numLabels;
|
||||
private final LinkedList<String> target;
|
||||
|
||||
OtherMatch(Rule rule, int numLabels, LinkedList<String> target) {
|
||||
this.rule = rule;
|
||||
this.numLabels = numLabels;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegisteredDomain registeredDomain() {
|
||||
int nlabels = numLabels + 1;
|
||||
if (nlabels > target.size()) {
|
||||
// special case when registered domain is same as pub suff
|
||||
return null;
|
||||
}
|
||||
return new RegisteredDomainImpl(getSuffixes(nlabels),
|
||||
rule.auth, getSuffixes(numLabels));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rule.Type type() {
|
||||
return rule.type;
|
||||
}
|
||||
|
||||
private String getSuffixes(int n) {
|
||||
Iterator<String> targetIter = target.descendingIterator();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (n > 0 && targetIter.hasNext()) {
|
||||
String s = targetIter.next();
|
||||
sb.insert(0, s);
|
||||
if (n > 1) {
|
||||
sb.insert(0, '.');
|
||||
}
|
||||
n--;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@
|
|||
package sun.security.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.IDN;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.Principal;
|
||||
|
@ -261,6 +262,11 @@ public class HostnameChecker {
|
|||
*/
|
||||
private boolean isMatched(String name, String template,
|
||||
boolean chainsToPublicCA) {
|
||||
|
||||
// Normalize to Unicode, because PSL is in Unicode.
|
||||
name = IDN.toUnicode(IDN.toASCII(name));
|
||||
template = IDN.toUnicode(IDN.toASCII(template));
|
||||
|
||||
if (hasIllegalWildcard(name, template, chainsToPublicCA)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -271,7 +277,7 @@ public class HostnameChecker {
|
|||
// the domain name template validity.
|
||||
//
|
||||
// Using the checking implemented in SNIHostName
|
||||
SNIHostName sni = new SNIHostName(template.replace('*', 'x'));
|
||||
new SNIHostName(template.replace('*', 'x'));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// It would be nice to add debug log if not matching.
|
||||
return false;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2018, 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
|
||||
|
@ -74,20 +74,12 @@ public interface RegisteredDomain {
|
|||
* Returns an {@code Optional<RegisteredDomain>} representing the
|
||||
* registered part of the specified domain.
|
||||
*
|
||||
* {@implNote}
|
||||
* The default implementation is based on the legacy
|
||||
* {@code sun.net.RegisteredDomain} class which is no longer maintained.
|
||||
* It should be updated or replaced with an appropriate implementation.
|
||||
*
|
||||
* @param domain the domain name
|
||||
* @return an {@code Optional<RegisteredDomain>}; the {@code Optional} is
|
||||
* empty if the domain is unknown or not registerable
|
||||
* @throws NullPointerException if domain is null
|
||||
*/
|
||||
public static Optional<RegisteredDomain> from(String domain) {
|
||||
if (domain == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
return Optional.ofNullable(sun.net.RegisteredDomain.registeredDomain(domain));
|
||||
return Optional.ofNullable(DomainName.registeredDomain(domain));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue