mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8368032: Enhance Certificate Checking
Reviewed-by: ahgross, coffeys, rhalade, mullan, abarashev
This commit is contained in:
parent
82e5771b0b
commit
07f981f6b0
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2025, 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
|
||||
@ -29,6 +29,7 @@ import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLConnection;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@ -48,8 +49,11 @@ import java.security.cert.X509CRL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import sun.security.x509.AccessDescription;
|
||||
import sun.security.x509.GeneralNameInterface;
|
||||
@ -58,6 +62,8 @@ import sun.security.util.Cache;
|
||||
import sun.security.util.Debug;
|
||||
import sun.security.util.SecurityProperties;
|
||||
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
/**
|
||||
* A <code>CertStore</code> that retrieves <code>Certificates</code> or
|
||||
* <code>CRL</code>s from a URI, for example, as specified in an X.509
|
||||
@ -182,6 +188,166 @@ class URICertStore extends CertStoreSpi {
|
||||
return timeoutVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumeration for the allowed schemes we support when following a
|
||||
* URI from an authorityInfoAccess extension on a certificate.
|
||||
*/
|
||||
private enum AllowedScheme {
|
||||
HTTP(HttpFtpRuleMatcher.HTTP),
|
||||
HTTPS(HttpFtpRuleMatcher.HTTPS),
|
||||
LDAP(LdapRuleMatcher.LDAP),
|
||||
LDAPS(LdapRuleMatcher.LDAPS),
|
||||
FTP(HttpFtpRuleMatcher.FTP);
|
||||
|
||||
final URIRuleMatcher ruleMatcher;
|
||||
|
||||
AllowedScheme(URIRuleMatcher matcher) {
|
||||
ruleMatcher = matcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an {@code AllowedScheme} based on a case-insensitive match
|
||||
* @param name the scheme name to be matched
|
||||
* @return the {@code AllowedScheme} that corresponds to the
|
||||
* {@code name} provided, or null if there is no match.
|
||||
*/
|
||||
static AllowedScheme nameOf(String name) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return AllowedScheme.valueOf(name.toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException _) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<URI> CA_ISS_URI_FILTERS = null;
|
||||
private static final boolean CA_ISS_ALLOW_ANY;
|
||||
|
||||
static {
|
||||
boolean allowAny = false;
|
||||
try {
|
||||
if (Builder.USE_AIA) {
|
||||
CA_ISS_URI_FILTERS = new LinkedHashSet<>();
|
||||
String aiaPropVal = Optional.ofNullable(
|
||||
SecurityProperties.getOverridableProperty(
|
||||
"com.sun.security.allowedAIALocations")).
|
||||
map(String::trim).orElse("");
|
||||
if (aiaPropVal.equalsIgnoreCase("any")) {
|
||||
allowAny = true;
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: Warning: " +
|
||||
"Allow-All URI filtering enabled!");
|
||||
}
|
||||
} else {
|
||||
// Load all the valid rules from the Security property
|
||||
if (!aiaPropVal.isEmpty()) {
|
||||
String[] aiaUriStrs = aiaPropVal.trim().split("\\s+");
|
||||
addCaIssUriFilters(aiaUriStrs);
|
||||
}
|
||||
|
||||
if (CA_ISS_URI_FILTERS.isEmpty()) {
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: Warning: " +
|
||||
"No valid filters found. Deny-all URI " +
|
||||
"filtering is active.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
CA_ISS_ALLOW_ANY = allowAny;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the filter collection from the list of AIA CA issuer URIs
|
||||
* found in the {@code com.sun.security.allowedAIALocations} security
|
||||
* or system property.
|
||||
*
|
||||
* @param aiaUriStrs array containing String URI filters
|
||||
*/
|
||||
private static void addCaIssUriFilters(String[] aiaUriStrs) {
|
||||
for (String aiaStr : aiaUriStrs) {
|
||||
if (aiaStr != null && !aiaStr.isEmpty()) {
|
||||
try {
|
||||
AllowedScheme scheme;
|
||||
URI aiaUri = new URI(aiaStr).normalize();
|
||||
// It must be absolute and non-opaque
|
||||
if (!aiaUri.isAbsolute() || aiaUri.isOpaque()) {
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: Skipping " +
|
||||
"non-absolute or opaque URI " + aiaUri);
|
||||
}
|
||||
} else if (aiaUri.getHost() == null) {
|
||||
// We do not allow rules with URIs that omit a hostname
|
||||
// or address.
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: Skipping " +
|
||||
"URI rule with no hostname or address: " +
|
||||
aiaUri);
|
||||
}
|
||||
} else if ((scheme = AllowedScheme.nameOf(
|
||||
aiaUri.getScheme())) != null) {
|
||||
// When it is an LDAP type, we can check the path
|
||||
// portion (the DN) for proper structure and reject
|
||||
// the rule early if it isn't correct.
|
||||
if (scheme == AllowedScheme.LDAP ||
|
||||
scheme == AllowedScheme.LDAPS) {
|
||||
try {
|
||||
new X500Principal(aiaUri.getPath().
|
||||
replaceFirst("^/+", ""));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: " +
|
||||
"Skipping LDAP rule: " + iae);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// When a URI has a non-null query or fragment
|
||||
// warn the user upon adding the rule that those
|
||||
// components will be ignored
|
||||
if (aiaUri.getQuery() != null) {
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: " +
|
||||
"Rule will ignore non-null query");
|
||||
}
|
||||
}
|
||||
if (aiaUri.getFragment() != null) {
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: " +
|
||||
"Rule will ignore non-null fragment");
|
||||
}
|
||||
}
|
||||
|
||||
CA_ISS_URI_FILTERS.add(aiaUri);
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: Added " +
|
||||
aiaUri + " to URI filters");
|
||||
}
|
||||
} else {
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: Disallowed " +
|
||||
"filter URI scheme: " +
|
||||
aiaUri.getScheme());
|
||||
}
|
||||
}
|
||||
} catch (URISyntaxException urise) {
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: Skipping " +
|
||||
"filter URI entry " + aiaStr +
|
||||
": parse failure at index " + urise.getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a URICertStore.
|
||||
*
|
||||
@ -244,6 +410,39 @@ class URICertStore extends CertStoreSpi {
|
||||
return null;
|
||||
}
|
||||
URI uri = ((URIName) gn).getURI();
|
||||
|
||||
// Before performing any instantiation make sure that
|
||||
// the URI passes any filtering rules. This processing should
|
||||
// only occur if the com.sun.security.enableAIAcaIssuers is true
|
||||
// and the "any" rule has not been specified.
|
||||
if (Builder.USE_AIA && !CA_ISS_ALLOW_ANY) {
|
||||
URI normAIAUri = uri.normalize();
|
||||
AllowedScheme scheme = AllowedScheme.nameOf(normAIAUri.getScheme());
|
||||
|
||||
if (scheme == null) {
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: No matching ruleset " +
|
||||
"for scheme " + normAIAUri.getScheme());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Go through each of the filter rules and see if any will
|
||||
// make a positive match against the caIssuer URI. If nothing
|
||||
// matches then we won't instantiate a URICertStore.
|
||||
if (CA_ISS_URI_FILTERS.stream().noneMatch(rule ->
|
||||
scheme.ruleMatcher.matchRule(rule, normAIAUri))) {
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: Warning - " +
|
||||
"The caIssuer URI " + normAIAUri +
|
||||
" in the AuthorityInfoAccess extension is denied " +
|
||||
"access. Use the com.sun.security.allowedAIALocations" +
|
||||
" security/system property to allow access.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return URICertStore.getInstance(new URICertStoreParameters(uri));
|
||||
} catch (Exception ex) {
|
||||
@ -270,7 +469,7 @@ class URICertStore extends CertStoreSpi {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized Collection<X509Certificate> engineGetCertificates
|
||||
(CertSelector selector) throws CertStoreException {
|
||||
(CertSelector selector) throws CertStoreException {
|
||||
|
||||
if (ldap) {
|
||||
// caching mechanism, see the class description for more info.
|
||||
@ -462,4 +661,159 @@ class URICertStore extends CertStoreSpi {
|
||||
super(spi, p, type, params);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* URIRuleMatcher - abstract base class for the rule sets used for
|
||||
* various URI schemes.
|
||||
*/
|
||||
static abstract class URIRuleMatcher {
|
||||
protected final int wellKnownPort;
|
||||
|
||||
protected URIRuleMatcher(int port) {
|
||||
wellKnownPort = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to match the scheme, host and port between a filter
|
||||
* rule URI and a URI coming from an AIA extension.
|
||||
*
|
||||
* @param filterRule the filter rule to match against
|
||||
* @param caIssuer the AIA URI being compared
|
||||
* @return true if the scheme, host and port numbers match, false if
|
||||
* any of the components do not match. If a port number is omitted in
|
||||
* either the filter rule or AIA URI, the well-known port for that
|
||||
* scheme is used in the comparison.
|
||||
*/
|
||||
boolean schemeHostPortCheck(URI filterRule, URI caIssuer) {
|
||||
if (!filterRule.getScheme().equalsIgnoreCase(
|
||||
caIssuer.getScheme())) {
|
||||
return false;
|
||||
} else if (!filterRule.getHost().equalsIgnoreCase(
|
||||
caIssuer.getHost())) {
|
||||
return false;
|
||||
} else {
|
||||
try {
|
||||
// Check for port matching, taking into consideration
|
||||
// default ports
|
||||
int fPort = (filterRule.getPort() == -1) ? wellKnownPort :
|
||||
filterRule.getPort();
|
||||
int caiPort = (caIssuer.getPort() == -1) ? wellKnownPort :
|
||||
caIssuer.getPort();
|
||||
if (fPort != caiPort) {
|
||||
return false;
|
||||
}
|
||||
} catch (IllegalArgumentException iae) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to match an AIA URI against a specific filter rule. The
|
||||
* specific rules to apply are implementation dependent.
|
||||
*
|
||||
* @param filterRule the filter rule to match against
|
||||
* @param caIssuer the AIA URI being compared
|
||||
* @return true if all matching rules pass, false if any fail.
|
||||
*/
|
||||
abstract boolean matchRule(URI filterRule, URI caIssuer);
|
||||
}
|
||||
|
||||
static class HttpFtpRuleMatcher extends URIRuleMatcher {
|
||||
static final HttpFtpRuleMatcher HTTP = new HttpFtpRuleMatcher(80);
|
||||
static final HttpFtpRuleMatcher HTTPS = new HttpFtpRuleMatcher(443);
|
||||
static final HttpFtpRuleMatcher FTP = new HttpFtpRuleMatcher(21);
|
||||
|
||||
private HttpFtpRuleMatcher(int port) {
|
||||
super(port);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean matchRule(URI filterRule, URI caIssuer) {
|
||||
// Check for scheme/host/port matching
|
||||
if (!schemeHostPortCheck(filterRule, caIssuer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the path component to make sure the filter is at
|
||||
// least a root of the AIA caIssuer URI's path. It must be
|
||||
// a case-sensitive match for all platforms.
|
||||
if (!isRootOf(filterRule, caIssuer)) {
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: Match failed: " +
|
||||
"AIA URI is not within the rule's path hierarchy.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a hierarchical containment check, ensuring that the
|
||||
* base URI's path is a root component of the candidate path. The
|
||||
* path comparison is case-sensitive. If the base path ends in a
|
||||
* slash (/) then all candidate paths that begin with the base
|
||||
* path are allowed. If it does not end in a slash, then it is
|
||||
* assumed that the leaf node in the base path is a file component
|
||||
* and both paths must match exactly.
|
||||
*
|
||||
* @param base the URI that contains the root path
|
||||
* @param candidate the URI that contains the path being evaluated
|
||||
* @return true if {@code candidate} is a child path of {@code base},
|
||||
* false otherwise.
|
||||
*/
|
||||
private static boolean isRootOf(URI base, URI candidate) {
|
||||
// Note: The URIs have already been normalized at this point and
|
||||
// HTTP URIs cannot have null paths. If it's an empty path
|
||||
// then consider the path to be "/".
|
||||
String basePath = Optional.of(base.getPath()).
|
||||
filter(p -> !p.isEmpty()).orElse("/");
|
||||
String candPath = Optional.of(candidate.getPath()).
|
||||
filter(p -> !p.isEmpty()).orElse("/");
|
||||
return (basePath.endsWith("/")) ? candPath.startsWith(basePath) :
|
||||
candPath.equals(basePath);
|
||||
}
|
||||
}
|
||||
|
||||
static class LdapRuleMatcher extends URIRuleMatcher {
|
||||
static final LdapRuleMatcher LDAP = new LdapRuleMatcher(389);
|
||||
static final LdapRuleMatcher LDAPS = new LdapRuleMatcher(636);
|
||||
|
||||
private LdapRuleMatcher(int port) {
|
||||
super(port);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean matchRule(URI filterRule, URI caIssuer) {
|
||||
// Check for scheme/host/port matching
|
||||
if (!schemeHostPortCheck(filterRule, caIssuer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Obtain the base DN component and compare
|
||||
try {
|
||||
X500Principal filterBaseDn = new X500Principal(
|
||||
filterRule.getPath().replaceFirst("^/+", ""));
|
||||
X500Principal caIssBaseDn = new X500Principal(
|
||||
caIssuer.getPath().replaceFirst("^/+", ""));
|
||||
if (!filterBaseDn.equals(caIssBaseDn)) {
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: Match failed: " +
|
||||
"Base DN mismatch (" + filterBaseDn + " vs " +
|
||||
caIssBaseDn + ")");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} catch (IllegalArgumentException iae) {
|
||||
if (debug != null) {
|
||||
debug.println("allowedAIALocations: Match failed on DN: " +
|
||||
iae);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1655,3 +1655,48 @@ jdk.tls.alpnCharset=ISO_8859_1
|
||||
# withEncryption method.
|
||||
#
|
||||
jdk.epkcs8.defaultAlgorithm=PBEWithHmacSHA256AndAES_128
|
||||
|
||||
#
|
||||
# X.509 AuthorityInfoAccess caIssuer URI Filtering
|
||||
#
|
||||
# This property defines a whitespace-separated list of filters that
|
||||
# are applied to URIs found in the authorityInfoAccess extension in
|
||||
# X.509 certificates. Any caIssuers URIs in X.509 certificates are only
|
||||
# followed when the com.sun.security.enableAIAcaIssuers System property is
|
||||
# enabled and the filter allows the URI. By default this property imposes a
|
||||
# deny-all ruleset. This property may be overridden by a System property
|
||||
# of the same name.
|
||||
#
|
||||
# The filters must take the form of absolute, hierarchical URIs as defined by
|
||||
# the java.net.URI class. Additionally, only the following protocols are
|
||||
# allowed as filters: http, https, ldap and ftp.
|
||||
# See RFC 5280, section 4.2.2.1 for details about the types of URIs allowed for
|
||||
# the extension and their specific requirements.
|
||||
# The filter matching rules are applied to each CA issuer URI as follows:
|
||||
# 1. The scheme must match (case-insensitive).
|
||||
# 2. A hostname or address must be specified in the filter URI. It must match
|
||||
# the host or address in the caIssuers URI (case-insensitive). No name
|
||||
# resolution is performed on hostnames to match IP addresses.
|
||||
# 3. The port number must match. For filter and caIssuer URIs, when a port
|
||||
# number is omitted, the well-known port for that scheme will be used in the
|
||||
# comparison.
|
||||
# 4. For hierarchical filesystem schemes (e.g. http[s], ftp):
|
||||
# a. The normalized path portion of the filter URI is matched in a
|
||||
# case-sensitive manner. If the final component of the path does not end
|
||||
# in a slash (/), it is considered to be a file path component and must
|
||||
# be an exact match of the caIssuer's URI file path component. If the
|
||||
# final filter component ends in a slash, then it must either match or be
|
||||
# a prefix of the caIssuer's URI path component (e.g. a filter path of
|
||||
# /ab/cd/ will match a caIssuer path of /ab/cd/, /ab/cd/ef and
|
||||
# /ab/cd/ef/ghi).
|
||||
# b. Query strings will be ignored in filter rules and caIssuer URIs.
|
||||
# c. Fragments will be ignored in filter rules and caIssuer URIs.
|
||||
# 5. For ldap URIs:
|
||||
# a. The base DN must be an exact match (case-insensitive).
|
||||
# b. Any query string in the rule, if specified, is ignored.
|
||||
# 6. A single value "any" (case-insensitive) will create an allow-all rule.
|
||||
#
|
||||
# As an example, here is a valid filter policy consisting of two rules:
|
||||
# com.sun.security.allowedAIALocations=http://some.company.com/cacert \
|
||||
# ldap://ldap.company.com/dc=company,dc=com?caCertificate;binary
|
||||
com.sun.security.allowedAIALocations=
|
||||
|
||||
@ -47,6 +47,7 @@ import com.sun.net.httpserver.*;
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.security.Security;
|
||||
import java.security.cert.*;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
@ -69,6 +70,7 @@ public class AIACertTimeout {
|
||||
private static X509Certificate eeCert;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Security.setProperty("com.sun.security.allowedAIALocations", "any");
|
||||
int servTimeoutMsec = (args != null && args.length >= 1) ?
|
||||
Integer.parseInt(args[0]) : -1;
|
||||
boolean expectedPass = args != null && args.length >= 2 &&
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2025, 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
|
||||
@ -38,6 +38,7 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.security.Security;
|
||||
import java.security.cert.CertPath;
|
||||
import java.security.cert.CertPathValidator;
|
||||
import java.security.cert.CertPathValidatorException;
|
||||
@ -47,7 +48,6 @@ import java.security.cert.PKIXParameters;
|
||||
import java.security.cert.TrustAnchor;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@ -67,25 +67,27 @@ public class ExtensionsWithLDAP {
|
||||
* Not After : Jan 17 18:03:59 2043 GMT
|
||||
* Subject: CN=Root
|
||||
*/
|
||||
private static final String CA_CERT = ""
|
||||
+ "-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIIC8TCCAdmgAwIBAgIJAJsSNtj5wdqqMA0GCSqGSIb3DQEBDQUAMA8xDTALBgNV\n"
|
||||
+ "BAMMBFJvb3QwHhcNMTUwOTAxMTgwMzU5WhcNNDMwMTE3MTgwMzU5WjAPMQ0wCwYD\n"
|
||||
+ "VQQDDARSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvj892vPm\n"
|
||||
+ "bB++x9QqqyBveP+ZqQ2B1stV7vh5JmDnOTevkZUOcemp3SXu/esNLSbpL+fARYXH\n"
|
||||
+ "V5ubnrfip6RbvcxPfVIIDJrRTLIIsU6W7M6/LJLbLkEVGy4ZV4IHkOw9W2O92rcv\n"
|
||||
+ "BkoqhzZnOTGR6uT3rRcKx4RevEKBKhZO+OPPf//lnckOybmYL7t7yQrajzHro76b\n"
|
||||
+ "QTXYjAUq/DKhglXfC7vF/JzlAvG2IunGmIfjGcnuDo/9X3Bxef/q5TxCS35fvb7t\n"
|
||||
+ "svC+g2QhTcBkQh4uNW2jSjlTIVp1uErCfP5aCjLaez5mqmb1hxPIlcvsNR23HwU6\n"
|
||||
+ "bQO7z7NBo9Do6QIDAQABo1AwTjAdBgNVHQ4EFgQUmLZNOBBkqdYoElyxklPYHmAb\n"
|
||||
+ "QXIwHwYDVR0jBBgwFoAUmLZNOBBkqdYoElyxklPYHmAbQXIwDAYDVR0TBAUwAwEB\n"
|
||||
+ "/zANBgkqhkiG9w0BAQ0FAAOCAQEAYV4fOhDi5q7+XNXCxO8Eil2frR9jqdP4LaQp\n"
|
||||
+ "3L0evW0gvPX68s2WmkPWzIu4TJcpdGFQqxyQFSXuKBXjthyiln77QItGTHWeafES\n"
|
||||
+ "q5ESrKdSaJZq1bTIrrReCIP74f+fY/F4Tnb3dCqzaljXfzpdbeRsIW6gF71xcOUQ\n"
|
||||
+ "nnPEjGVPLUegN+Wn/jQpeLxxIB7FmNXncdRUfMfZ43xVSKuMCy1UUYqJqTa/pXZj\n"
|
||||
+ "jCMeRPThRjRqHlJ69jStfWUQATbLyj9KN09rUaJxzmUSt61UqJi7sjcGySaCjAJc\n"
|
||||
+ "IcCdVmX/DmRLsdv8W36O3MgrvpT1zR3kaAlv2d8HppnBqcL3xg==\n"
|
||||
+ "-----END CERTIFICATE-----";
|
||||
private static final String CA_CERT =
|
||||
"""
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC8TCCAdmgAwIBAgIJAJsSNtj5wdqqMA0GCSqGSIb3DQEBDQUAMA8xDTALBgNV
|
||||
BAMMBFJvb3QwHhcNMTUwOTAxMTgwMzU5WhcNNDMwMTE3MTgwMzU5WjAPMQ0wCwYD
|
||||
VQQDDARSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvj892vPm
|
||||
bB++x9QqqyBveP+ZqQ2B1stV7vh5JmDnOTevkZUOcemp3SXu/esNLSbpL+fARYXH
|
||||
V5ubnrfip6RbvcxPfVIIDJrRTLIIsU6W7M6/LJLbLkEVGy4ZV4IHkOw9W2O92rcv
|
||||
BkoqhzZnOTGR6uT3rRcKx4RevEKBKhZO+OPPf//lnckOybmYL7t7yQrajzHro76b
|
||||
QTXYjAUq/DKhglXfC7vF/JzlAvG2IunGmIfjGcnuDo/9X3Bxef/q5TxCS35fvb7t
|
||||
svC+g2QhTcBkQh4uNW2jSjlTIVp1uErCfP5aCjLaez5mqmb1hxPIlcvsNR23HwU6
|
||||
bQO7z7NBo9Do6QIDAQABo1AwTjAdBgNVHQ4EFgQUmLZNOBBkqdYoElyxklPYHmAb
|
||||
QXIwHwYDVR0jBBgwFoAUmLZNOBBkqdYoElyxklPYHmAbQXIwDAYDVR0TBAUwAwEB
|
||||
/zANBgkqhkiG9w0BAQ0FAAOCAQEAYV4fOhDi5q7+XNXCxO8Eil2frR9jqdP4LaQp
|
||||
3L0evW0gvPX68s2WmkPWzIu4TJcpdGFQqxyQFSXuKBXjthyiln77QItGTHWeafES
|
||||
q5ESrKdSaJZq1bTIrrReCIP74f+fY/F4Tnb3dCqzaljXfzpdbeRsIW6gF71xcOUQ
|
||||
nnPEjGVPLUegN+Wn/jQpeLxxIB7FmNXncdRUfMfZ43xVSKuMCy1UUYqJqTa/pXZj
|
||||
jCMeRPThRjRqHlJ69jStfWUQATbLyj9KN09rUaJxzmUSt61UqJi7sjcGySaCjAJc
|
||||
IcCdVmX/DmRLsdv8W36O3MgrvpT1zR3kaAlv2d8HppnBqcL3xg==
|
||||
-----END CERTIFICATE-----
|
||||
""";
|
||||
|
||||
/*
|
||||
* Certificate:
|
||||
@ -106,39 +108,41 @@ public class ExtensionsWithLDAP {
|
||||
* Authority Information Access:
|
||||
* CA Issuers - URI:ldap://ldap.host.for.aia/dc=Root?cACertificate
|
||||
*/
|
||||
private static final String EE_CERT = ""
|
||||
+ "-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIIDHTCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQ0FADAPMQ0wCwYDVQQDDARSb290\n"
|
||||
+ "MB4XDTE1MDkwMTE4MDM1OVoXDTQzMDExNzE4MDM1OVowDTELMAkGA1UEAwwCRUUw\n"
|
||||
+ "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpyz97liuWPDYcLH9TX8Bi\n"
|
||||
+ "T78olCmAfmevvch6ncXUVuCzbdaKuKXwn4EVbDszsVJLoK5zdtP+X3iDhutj+IgK\n"
|
||||
+ "mLhuczF3M9VIcWr+JJUyTH4+3h/RT8cjCDZOmk9iXkb5ifruVsLqzb9g+Vp140Oz\n"
|
||||
+ "7leikne7KmclHvTfvFd0WDI7Gb9vo4f5rT717BXJ/n+M6pNk8DLpLiEu6eziYvXR\n"
|
||||
+ "v5x+t5Go3x0eCXdaxEQUf2j876Wfr2qHRJK7lDfFe1DDsMg/KpKGiILYZ+g2qtVM\n"
|
||||
+ "ZSxtp5BZEtfB5qV/IE5kWO+mCIAGpXSZIdbERR6pZUq8GLEe1T9e+sO6H24w2F19\n"
|
||||
+ "AgMBAAGjgYUwgYIwNAYDVR0fBC0wKzApoCegJYYjbGRhcDovL2xkYXAuaG9zdC5m\n"
|
||||
+ "b3IuY3JsZHAvbWFpbi5jcmwwSgYIKwYBBQUHAQEEPjA8MDoGCCsGAQUFBzAChi5s\n"
|
||||
+ "ZGFwOi8vbGRhcC5ob3N0LmZvci5haWEvZGM9Um9vdD9jQUNlcnRpZmljYXRlMA0G\n"
|
||||
+ "CSqGSIb3DQEBDQUAA4IBAQBWDfZHpuUx0yn5d3+BuztFqoks1MkGdk+USlH0TB1/\n"
|
||||
+ "gWWBd+4S4PCKlpSur0gj2rMW4fP5HQfNlHci8JV8/bG4KuKRAXW56dg1818Hl3pc\n"
|
||||
+ "iIrUSRn8uUjH3p9qb+Rb/u3mmVQRyJjN2t/zceNsO8/+Dd808OB9aEwGs8lMT0nn\n"
|
||||
+ "ZYaaAqYz1GIY/Ecyx1vfEZEQ1ljo6i/r70C3igbypBUShxSiGsleiVTLOGNA+MN1\n"
|
||||
+ "/a/Qh0bkaQyTGqK3bwvzzMeQVqWu2EWTBD/PmND5ExkpRICdv8LBVXfLnpoBr4lL\n"
|
||||
+ "hnxn9+e0Ah+t8dS5EKfn44w5bI5PCu2bqxs6RCTxNjcY\n"
|
||||
+ "-----END CERTIFICATE-----";
|
||||
private static final String EE_CERT =
|
||||
"""
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDHTCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQ0FADAPMQ0wCwYDVQQDDARSb290
|
||||
MB4XDTE1MDkwMTE4MDM1OVoXDTQzMDExNzE4MDM1OVowDTELMAkGA1UEAwwCRUUw
|
||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpyz97liuWPDYcLH9TX8Bi
|
||||
T78olCmAfmevvch6ncXUVuCzbdaKuKXwn4EVbDszsVJLoK5zdtP+X3iDhutj+IgK
|
||||
mLhuczF3M9VIcWr+JJUyTH4+3h/RT8cjCDZOmk9iXkb5ifruVsLqzb9g+Vp140Oz
|
||||
7leikne7KmclHvTfvFd0WDI7Gb9vo4f5rT717BXJ/n+M6pNk8DLpLiEu6eziYvXR
|
||||
v5x+t5Go3x0eCXdaxEQUf2j876Wfr2qHRJK7lDfFe1DDsMg/KpKGiILYZ+g2qtVM
|
||||
ZSxtp5BZEtfB5qV/IE5kWO+mCIAGpXSZIdbERR6pZUq8GLEe1T9e+sO6H24w2F19
|
||||
AgMBAAGjgYUwgYIwNAYDVR0fBC0wKzApoCegJYYjbGRhcDovL2xkYXAuaG9zdC5m
|
||||
b3IuY3JsZHAvbWFpbi5jcmwwSgYIKwYBBQUHAQEEPjA8MDoGCCsGAQUFBzAChi5s
|
||||
ZGFwOi8vbGRhcC5ob3N0LmZvci5haWEvZGM9Um9vdD9jQUNlcnRpZmljYXRlMA0G
|
||||
CSqGSIb3DQEBDQUAA4IBAQBWDfZHpuUx0yn5d3+BuztFqoks1MkGdk+USlH0TB1/
|
||||
gWWBd+4S4PCKlpSur0gj2rMW4fP5HQfNlHci8JV8/bG4KuKRAXW56dg1818Hl3pc
|
||||
iIrUSRn8uUjH3p9qb+Rb/u3mmVQRyJjN2t/zceNsO8/+Dd808OB9aEwGs8lMT0nn
|
||||
ZYaaAqYz1GIY/Ecyx1vfEZEQ1ljo6i/r70C3igbypBUShxSiGsleiVTLOGNA+MN1
|
||||
/a/Qh0bkaQyTGqK3bwvzzMeQVqWu2EWTBD/PmND5ExkpRICdv8LBVXfLnpoBr4lL
|
||||
hnxn9+e0Ah+t8dS5EKfn44w5bI5PCu2bqxs6RCTxNjcY
|
||||
-----END CERTIFICATE-----""";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String extension = args[0];
|
||||
String targetHost = args[1];
|
||||
|
||||
Security.setProperty("com.sun.security.allowedAIALocations",
|
||||
"ldap://" + targetHost + "/dc=Root");
|
||||
X509Certificate trustedCert = loadCertificate(CA_CERT);
|
||||
X509Certificate eeCert = loadCertificate(EE_CERT);
|
||||
|
||||
Set<TrustAnchor> trustedCertsSet = new HashSet<>();
|
||||
trustedCertsSet.add(new TrustAnchor(trustedCert, null));
|
||||
|
||||
CertPath cp = (CertPath) CertificateFactory.getInstance("X509")
|
||||
.generateCertPath(Arrays.asList(eeCert));
|
||||
CertPath cp = CertificateFactory.getInstance("X509")
|
||||
.generateCertPath(List.of(eeCert));
|
||||
|
||||
// CertPath validator should try to parse CRLDP and AIA extensions,
|
||||
// and load CRLs/certs which they point to.
|
||||
@ -151,7 +155,7 @@ public class ExtensionsWithLDAP {
|
||||
= (InetSocketAddress) socket.getRemoteSocketAddress();
|
||||
hosts.add(remoteAddress.getHostName());
|
||||
};
|
||||
try (SocksProxy proxy = SocksProxy.startProxy(socketConsumer)) {
|
||||
try (SocksProxy _ = SocksProxy.startProxy(socketConsumer)) {
|
||||
CertPathValidator.getInstance("PKIX").validate(cp,
|
||||
new PKIXParameters(trustedCertsSet));
|
||||
throw new RuntimeException("CertPathValidatorException not thrown");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user