Categories:
Audio (13)
Biotech (29)
Bytecode (36)
Database (77)
Framework (7)
Game (7)
General (507)
Graphics (53)
I/O (35)
IDE (2)
JAR Tools (102)
JavaBeans (21)
JDBC (121)
JDK (426)
JSP (20)
Logging (108)
Mail (58)
Messaging (8)
Network (84)
PDF (97)
Report (7)
Scripting (84)
Security (32)
Server (121)
Servlet (26)
SOAP (24)
Testing (54)
Web (15)
XML (322)
Collections:
Other Resources:
JDK 17 java.base.jmod - Base Module
JDK 17 java.base.jmod is the JMOD file for JDK 17 Base module.
JDK 17 Base module compiled class files are stored in \fyicenter\jdk-17.0.5\jmods\java.base.jmod.
JDK 17 Base module compiled class files are also linked and stored in the \fyicenter\jdk-17.0.5\lib\modules JImage file.
JDK 17 Base module source code files are stored in \fyicenter\jdk-17.0.5\lib\src.zip\java.base.
You can click and view the content of each source code file in the list below.
✍: FYIcenter
⏎ sun/security/util/HostnameChecker.java
/*
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package sun.security.util;
import java.io.IOException;
import java.net.IDN;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.Principal;
import java.security.cert.*;
import java.text.Normalizer;
import java.util.*;
import javax.security.auth.x500.X500Principal;
import javax.net.ssl.SNIHostName;
import sun.net.util.IPAddressUtil;
import sun.security.x509.X500Name;
import sun.security.ssl.SSLLogger;
/**
* Class to check hostnames against the names specified in a certificate as
* required for TLS and LDAP.
*
*/
public class HostnameChecker {
// Constant for a HostnameChecker for TLS
public static final byte TYPE_TLS = 1;
private static final HostnameChecker INSTANCE_TLS =
new HostnameChecker(TYPE_TLS);
// Constant for a HostnameChecker for LDAP
public static final byte TYPE_LDAP = 2;
private static final HostnameChecker INSTANCE_LDAP =
new HostnameChecker(TYPE_LDAP);
// constants for subject alt names of type DNS and IP
private static final int ALTNAME_DNS = 2;
private static final int ALTNAME_IP = 7;
// the algorithm to follow to perform the check. Currently unused.
private final byte checkType;
private HostnameChecker(byte checkType) {
this.checkType = checkType;
}
/**
* Get a HostnameChecker instance. checkType should be one of the
* TYPE_* constants defined in this class.
*/
public static HostnameChecker getInstance(byte checkType) {
if (checkType == TYPE_TLS) {
return INSTANCE_TLS;
} else if (checkType == TYPE_LDAP) {
return INSTANCE_LDAP;
}
throw new IllegalArgumentException("Unknown check type: " + checkType);
}
/**
* Perform the check.
*
* @param expectedName the expected host name or ip address
* @param cert the certificate to check against
* @param chainsToPublicCA true if the certificate chains to a public
* root CA (as pre-installed in the cacerts file)
* @throws CertificateException if the name does not match any of
* the names specified in the certificate
*/
public void match(String expectedName, X509Certificate cert,
boolean chainsToPublicCA) throws CertificateException {
if (expectedName == null) {
throw new CertificateException("Hostname or IP address is " +
"undefined.");
}
if (isIpAddress(expectedName)) {
matchIP(expectedName, cert);
} else {
matchDNS(expectedName, cert, chainsToPublicCA);
}
}
public void match(String expectedName, X509Certificate cert)
throws CertificateException {
match(expectedName, cert, false);
}
/**
* Test whether the given hostname looks like a literal IPv4 or IPv6
* address. The hostname does not need to be a fully qualified name.
*
* This is not a strict check that performs full input validation.
* That means if the method returns true, name need not be a correct
* IP address, rather that it does not represent a valid DNS hostname.
* Likewise for IP addresses when it returns false.
*/
private static boolean isIpAddress(String name) {
if (IPAddressUtil.isIPv4LiteralAddress(name) ||
IPAddressUtil.isIPv6LiteralAddress(name)) {
return true;
} else {
return false;
}
}
/**
* Check if the certificate allows use of the given IP address.
*
* From RFC2818:
* In some cases, the URI is specified as an IP address rather than a
* hostname. In this case, the iPAddress subjectAltName must be present
* in the certificate and must exactly match the IP in the URI.
*/
private static void matchIP(String expectedIP, X509Certificate cert)
throws CertificateException {
Collection<List<?>> subjAltNames = cert.getSubjectAlternativeNames();
if (subjAltNames == null) {
throw new CertificateException
("No subject alternative names present");
}
for (List<?> next : subjAltNames) {
// For IP address, it needs to be exact match
if (((Integer)next.get(0)).intValue() == ALTNAME_IP) {
String ipAddress = (String)next.get(1);
if (expectedIP.equalsIgnoreCase(ipAddress)) {
return;
} else {
// compare InetAddress objects in order to ensure
// equality between a long IPv6 address and its
// abbreviated form.
try {
if (InetAddress.getByName(expectedIP).equals(
InetAddress.getByName(ipAddress))) {
return;
}
} catch (UnknownHostException e) {
} catch (SecurityException e) {}
}
}
}
throw new CertificateException("No subject alternative " +
"names matching " + "IP address " +
expectedIP + " found");
}
/**
* Check if the certificate allows use of the given DNS name.
*
* From RFC2818:
* If a subjectAltName extension of type dNSName is present, that MUST
* be used as the identity. Otherwise, the (most specific) Common Name
* field in the Subject field of the certificate MUST be used. Although
* the use of the Common Name is existing practice, it is deprecated and
* 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
* the certificate (e.g., more than one dNSName name, a match in any one
* of the set is considered acceptable.)
*/
private void matchDNS(String expectedName, X509Certificate cert,
boolean chainsToPublicCA)
throws CertificateException {
// Check that the expected name is a valid domain name.
try {
// Using the checking implemented in SNIHostName
SNIHostName sni = new SNIHostName(expectedName);
} catch (IllegalArgumentException iae) {
throw new CertificateException(
"Illegal given domain name: " + expectedName, iae);
}
Collection<List<?>> subjAltNames = cert.getSubjectAlternativeNames();
if (subjAltNames != null) {
boolean foundDNS = false;
for (List<?> next : subjAltNames) {
if (((Integer)next.get(0)).intValue() == ALTNAME_DNS) {
foundDNS = true;
String dnsName = (String)next.get(1);
if (isMatched(expectedName, dnsName, chainsToPublicCA)) {
return;
}
}
}
if (foundDNS) {
// if certificate contains any subject alt names of type DNS
// but none match, reject
throw new CertificateException("No subject alternative DNS "
+ "name matching " + expectedName + " found.");
}
}
X500Name subjectName = getSubjectX500Name(cert);
DerValue derValue = subjectName.findMostSpecificAttribute
(X500Name.commonName_oid);
if (derValue != null) {
try {
String cname = derValue.getAsString();
if (!Normalizer.isNormalized(cname, Normalizer.Form.NFKC)) {
throw new CertificateException("Not a formal name "
+ cname);
}
if (isMatched(expectedName, cname, chainsToPublicCA)) {
return;
}
} catch (IOException e) {
// ignore
}
}
String msg = "No name matching " + expectedName + " found";
throw new CertificateException(msg);
}
/**
* Return the subject of a certificate as X500Name, by reparsing if
* necessary. X500Name should only be used if access to name components
* is required, in other cases X500Principal is to be preferred.
*
* This method is currently used from within JSSE, do not remove.
*/
@SuppressWarnings("deprecation")
public static X500Name getSubjectX500Name(X509Certificate cert)
throws CertificateParsingException {
try {
Principal subjectDN = cert.getSubjectDN();
if (subjectDN instanceof X500Name) {
return (X500Name)subjectDN;
} else {
X500Principal subjectX500 = cert.getSubjectX500Principal();
return new X500Name(subjectX500.getEncoded());
}
} catch (IOException e) {
throw(CertificateParsingException)
new CertificateParsingException().initCause(e);
}
}
/**
* Returns true if name matches against template.<p>
*
* The matching is performed as per RFC 2818 rules for TLS and
* RFC 2830 rules for LDAP.<p>
*
* The <code>name</code> parameter should represent a DNS name. The
* <code>template</code> parameter may contain the wildcard character '*'.
*/
private boolean isMatched(String name, String template,
boolean chainsToPublicCA) {
// Normalize to Unicode, because PSL is in Unicode.
try {
name = IDN.toUnicode(IDN.toASCII(name));
template = IDN.toUnicode(IDN.toASCII(template));
} catch (RuntimeException re) {
if (SSLLogger.isOn) {
SSLLogger.fine("Failed to normalize to Unicode: " + re);
}
return false;
}
if (hasIllegalWildcard(template, chainsToPublicCA)) {
return false;
}
// check the validity of the domain name template.
try {
// Replacing wildcard character '*' with 'z' so as to check
// the domain name template validity.
//
// Using the checking implemented in SNIHostName
new SNIHostName(template.replace('*', 'z'));
} catch (IllegalArgumentException iae) {
// It would be nice to add debug log if not matching.
return false;
}
if (checkType == TYPE_TLS) {
return matchAllWildcards(name, template);
} else if (checkType == TYPE_LDAP) {
return matchLeftmostWildcard(name, template);
} else {
return false;
}
}
/**
* Returns true if the template contains an illegal wildcard character.
*/
private static boolean hasIllegalWildcard(
String template, boolean chainsToPublicCA) {
// not ok if it is a single wildcard character or "*."
if (template.equals("*") || template.equals("*.")) {
if (SSLLogger.isOn) {
SSLLogger.fine(
"Certificate domain name has illegal single " +
"wildcard character: " + template);
}
return true;
}
int lastWildcardIndex = template.lastIndexOf("*");
// ok if it has no wildcard character
if (lastWildcardIndex == -1) {
return false;
}
String afterWildcard = template.substring(lastWildcardIndex);
int firstDotIndex = afterWildcard.indexOf(".");
// not ok if there is no dot after wildcard (ex: "*com")
if (firstDotIndex == -1) {
if (SSLLogger.isOn) {
SSLLogger.fine(
"Certificate domain name has illegal wildcard, " +
"no dot after wildcard character: " + template);
}
return true;
}
if (!chainsToPublicCA) {
return false; // skip check for non-public certificates
}
// If the wildcarded domain is a top-level domain under which names
// can be registered, then a wildcard is not allowed.
String wildcardedDomain = afterWildcard.substring(firstDotIndex + 1);
String templateDomainSuffix =
RegisteredDomain.from("z." + wildcardedDomain)
.filter(d -> d.type() == RegisteredDomain.Type.ICANN)
.map(RegisteredDomain::publicSuffix).orElse(null);
if (templateDomainSuffix == null) {
return false; // skip check if not known public suffix
}
// Is it a top-level domain?
if (wildcardedDomain.equalsIgnoreCase(templateDomainSuffix)) {
if (SSLLogger.isOn) {
SSLLogger.fine(
"Certificate domain name has illegal " +
"wildcard for top-level public suffix: " + template);
}
return true;
}
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>
*
* As per RFC 2830, section 3.6 -
* The "*" wildcard character is allowed. If present, it applies only
* to the left-most name component.
* E.g. *.bar.com would match a.bar.com, b.bar.com, etc. but not
* bar.com.
*/
private static boolean matchLeftmostWildcard(String name,
String template) {
name = name.toLowerCase(Locale.ENGLISH);
template = template.toLowerCase(Locale.ENGLISH);
// Retrieve leftmost component
int templateIdx = template.indexOf(".");
int nameIdx = name.indexOf(".");
if (templateIdx == -1)
templateIdx = template.length();
if (nameIdx == -1)
nameIdx = name.length();
if (matchWildCards(name.substring(0, nameIdx),
template.substring(0, templateIdx))) {
// match rest of the name
return template.substring(templateIdx).equals(
name.substring(nameIdx));
} else {
return false;
}
}
/**
* Returns true if the name matches against the template that may
* contain wildcard char * <p>
*/
private static boolean matchWildCards(String name, String template) {
int wildcardIdx = template.indexOf("*");
if (wildcardIdx == -1)
return name.equals(template);
boolean isBeginning = true;
String beforeWildcard = "";
String afterWildcard = template;
while (wildcardIdx != -1) {
// match in sequence the non-wildcard chars in the template.
beforeWildcard = afterWildcard.substring(0, wildcardIdx);
afterWildcard = afterWildcard.substring(wildcardIdx + 1);
int beforeStartIdx = name.indexOf(beforeWildcard);
if ((beforeStartIdx == -1) ||
(isBeginning && beforeStartIdx != 0)) {
return false;
}
isBeginning = false;
// update the match scope
name = name.substring(beforeStartIdx + beforeWildcard.length());
wildcardIdx = afterWildcard.indexOf("*");
}
return name.endsWith(afterWildcard);
}
}
⏎ sun/security/util/HostnameChecker.java
Or download all of them as a single archive file:
File name: java.base-17.0.5-src.zip File size: 8883851 bytes Release date: 2022-09-13 Download
2023-09-26, ≈439🔥, 1💬
Popular Posts:
How to read XML document with XML Schema validation from socket connections with the socket\DelayedI...
JDK 17 java.sql.rowset.jmod is the JMOD file for JDK 17 SQL Rowset module. JDK 17 SQL Rowset module ...
The Jakarta-ORO Java classes are a set of text-processing Java classes that provide Perl5 compatible...
Xalan-Java, Version 2.7.1, is an XSLT processor for transforming XML documents into HTML, text, or o...
JBrowser Source Code Files are provided in the source package file. You can download JBrowser source...