mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Chris Ridd
30.50.2016 8a6e3b7ae9c25f31a5e48034171aff0e9a9ec2c2
OPENDJ-2855 Check Subject Alt Names in the CheckHostName TrustManager

The behaviour in RFC 4513 surrounding the criticality flag for the SAN extension is not clear.

This change checks the SAN first, and will hard fail if the SAN is critical and either doesn't match the hostname, or contains uncheckable GeneralNames.

The fallback to the popular (but very deprecated) hack of looking for the lowest CN in the subjectDN is only performed if the SAN is non-critical and does not match.

InetAddressValidator is added from the Apache Validator project.
15 files added
2 files modified
965 ■■■■■ changed files
opendj-core/src/main/java/org/forgerock/opendj/ldap/InetAddressValidator.java 217 ●●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/ldap/TrustManagers.java 282 ●●●● patch | view | raw | blame | history
opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties 9 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/ldap/TrustManagersTestCase.java 218 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert1.pem 18 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert10.pem 18 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert11.pem 19 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert12.pem 18 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert13.pem 20 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert2.pem 19 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert3.pem 18 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert4.pem 18 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert5.pem 18 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert6.pem 18 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert7.pem 18 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert8.pem 18 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert9.pem 19 ●●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/ldap/InetAddressValidator.java
New file
@@ -0,0 +1,217 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Portions copyright 2016 ForgeRock AS.
 */
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.forgerock.opendj.ldap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * <p><b>InetAddress</b> validation and conversion routines (<code>java.net.InetAddress</code>).</p>
 *
 * <p>This class provides methods to validate a candidate IP address.
 *
 * @since Validator 1.4
 */
final class InetAddressValidator {
    private static final int IPV4_MAX_OCTET_VALUE = 255;
    private static final int MAX_UNSIGNED_SHORT = 0xffff;
    private static final int BASE_16 = 16;
    private static final String IPV4_REGEX = "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
    // Max number of hex groups (separated by :) in an IPV6 address
    private static final int IPV6_MAX_HEX_GROUPS = 8;
    // Max hex digits in each IPv6 group
    private static final int IPV6_MAX_HEX_DIGITS_PER_GROUP = 4;
    /** IPv4 regex pattern. */
    private static final Pattern IPV4_PATTERN = Pattern.compile(IPV4_REGEX);
    /** Private constructor. */
    private InetAddressValidator() {
    }
    /**
     * Checks if the specified string is a valid IP address.
     * @param inetAddress the string to validate
     * @return true if the string validates as an IP address
     */
    public static boolean isValid(String inetAddress) {
        return isValidInet4Address(inetAddress) || isValidInet6Address(inetAddress);
    }
    /**
     * Validates an IPv4 address. Returns true if valid.
     * @param inet4Address the IPv4 address to validate
     * @return true if the argument contains a valid IPv4 address
     */
    public static boolean isValidInet4Address(String inet4Address) {
        // verify that address conforms to generic IPv4 format
        String[] groups = match(inet4Address);
        if (groups == null) {
            return false;
        }
        // verify that address subgroups are legal
        for (String ipSegment : groups) {
            if (ipSegment == null || ipSegment.length() == 0) {
                return false;
            }
            int iIpSegment;
            try {
                iIpSegment = Integer.parseInt(ipSegment);
            } catch (NumberFormatException e) {
                return false;
            }
            if (iIpSegment > IPV4_MAX_OCTET_VALUE) {
                return false;
            }
            if (ipSegment.length() > 1 && ipSegment.startsWith("0")) {
                return false;
            }
        }
        return true;
    }
    /**
     * Validate a value against the set of regular expressions returning the array of matched groups. From the Apache
     * RegexValidator class.
     *
     * @param value  The value to validate
     * @return  String array of the matched groups, of {@code null} if invalid.
     */
    private static String[] match(String value) {
        if (value == null) {
            return null;
        }
        Matcher matcher = IPV4_PATTERN.matcher(value);
        if (matcher.matches()) {
            int count = matcher.groupCount();
            String[] groups = new String[count];
            for (int j = 0; j < count; j++) {
                groups[j] = matcher.group(j + 1);
            }
            return groups;
        }
        return null;
    }
    /**
     * Validates an IPv6 address. Returns true if valid.
     * @param inet6Address the IPv6 address to validate
     * @return true if the argument contains a valid IPv6 address
     *
     * @since 1.4.1
     */
    public static boolean isValidInet6Address(String inet6Address) {
        boolean containsCompressedZeroes = inet6Address.contains("::");
        if (containsCompressedZeroes && (inet6Address.indexOf("::") != inet6Address.lastIndexOf("::"))) {
            return false;
        }
        if ((inet6Address.startsWith(":") && !inet6Address.startsWith("::"))
                || (inet6Address.endsWith(":") && !inet6Address.endsWith("::"))) {
            return false;
        }
        String[] octets = inet6Address.split(":");
        if (containsCompressedZeroes) {
            List<String> octetList = new ArrayList<>(Arrays.asList(octets));
            if (inet6Address.endsWith("::")) {
                // String.split() drops ending empty segments
                octetList.add("");
            } else if (inet6Address.startsWith("::") && !octetList.isEmpty()) {
                octetList.remove(0);
            }
            octets = octetList.toArray(new String[octetList.size()]);
        }
        if (octets.length > IPV6_MAX_HEX_GROUPS) {
            return false;
        }
        int validOctets = 0;
        int emptyOctets = 0;
        for (int index = 0; index < octets.length; index++) {
            String octet = octets[index];
            if (octet.length() == 0) {
                emptyOctets++;
                if (emptyOctets > 1) {
                    return false;
                }
            } else {
                emptyOctets = 0;
                if (octet.contains(".")) { // contains is Java 1.5+
                    if (!inet6Address.endsWith(octet)) {
                        return false;
                    }
                    if (index > octets.length - 1 || index > 6) {  // CHECKSTYLE IGNORE MagicNumber
                        // IPV4 occupies last two octets
                        return false;
                    }
                    if (!isValidInet4Address(octet)) {
                        return false;
                    }
                    validOctets += 2;
                    continue;
                }
                if (octet.length() > IPV6_MAX_HEX_DIGITS_PER_GROUP) {
                    return false;
                }
                int octetInt;
                try {
                    octetInt = Integer.valueOf(octet, BASE_16);
                } catch (NumberFormatException e) {
                    return false;
                }
                if (octetInt < 0 || octetInt > MAX_UNSIGNED_SHORT) {
                    return false;
                }
            }
            validOctets++;
        }
        if (validOctets < IPV6_MAX_HEX_GROUPS && !containsCompressedZeroes) {
            return false;
        }
        return true;
    }
}
opendj-core/src/main/java/org/forgerock/opendj/ldap/TrustManagers.java
@@ -19,30 +19,48 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.List;
import java.util.Set;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import javax.security.auth.x500.X500Principal;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldap.schema.Schema;
import org.forgerock.util.Reject;
import static com.forgerock.opendj.ldap.CoreMessages.ERR_CERT_NO_MATCH_IP;
import static com.forgerock.opendj.ldap.CoreMessages.ERR_CERT_NO_MATCH_DNS;
import static com.forgerock.opendj.ldap.CoreMessages.ERR_CERT_NO_MATCH_ALLOTHERS;
import static com.forgerock.opendj.ldap.CoreMessages.ERR_CERT_NO_MATCH_SUBJECT;
/** This class contains methods for creating common types of trust manager. */
public final class TrustManagers {
    private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
    /**
     * An X509TrustManager which rejects certificate chains whose subject DN
     * does not match a specified host name.
     * An X509TrustManager which rejects certificate chains whose subject alternative names do not match the specified
     * host name or IP address. The check may fall back to checking a hostname in the left-most CN of the certificate
     * subject for backwards compatibility.
     */
    private static final class CheckHostName implements X509TrustManager {
@@ -75,15 +93,191 @@
        }
        /**
         * Checks whether a host name matches the provided pattern. It accepts
         * the use of wildcards in the pattern, e.g. {@code *.example.com}.
         * Look in the SubjectAlternativeName for DNS names (wildcards are allowed) and IP addresses, and potentially
         * fall back to checking CN in the subjectDN.
         * <p>
         * If DNS names and IP addresses do not match, and other SubjectAlternativeNames are present and critical, do
         * not fall back checking CN.
         * </p>
         * <p>
         * If DNS names and IP addresses do not match and the SubjectAlternativeNames are non-critical, fall back to
         * checking CN.
         * </p>
         * @param chain X.509 certificate chain from the server
         */
        private void verifyHostName(final X509Certificate[] chain) throws CertificateException {
            final X500Principal principal = chain[0].getSubjectX500Principal();
            try {
                final List<String> dnsNamePatterns = new ArrayList<>(0);
                final List<String> ipAddresses = new ArrayList<>(0);
                final List<Object> allOthers = new ArrayList<>(0);
                getSanGeneralNames(chain[0], dnsNamePatterns, ipAddresses, allOthers);
                final boolean sanIsCritical = getSanCriticality(chain[0]);
                final InetAddress hostAddress = toIpAddress(hostName);
                if (hostAddress != null) {
                    if (verifyIpAddresses(hostAddress, ipAddresses, principal, sanIsCritical)) {
                        return;
                    }
                } else {
                    if (verifyDnsNamePatterns(hostName, dnsNamePatterns, principal, sanIsCritical)) {
                        return;
                    }
                }
                if (!allOthers.isEmpty() && sanIsCritical) {
                    throw new CertificateException(ERR_CERT_NO_MATCH_ALLOTHERS.get(principal, hostName).toString());
                }
                final DN dn = DN.valueOf(principal.getName(), Schema.getCoreSchema());
                final String certSubjectHostName = getLowestCommonName(dn);
                /* Backwards compatibility: check wildcards in cn */
                if (hostNameMatchesPattern(hostName, certSubjectHostName)) {
                    return;
                }
                throw new CertificateException(ERR_CERT_NO_MATCH_SUBJECT.get(principal, hostName).toString());
            } catch (final CertificateException e) {
                logger.warn(LocalizableMessage.raw("Certificate verification problem for: " + principal), e);
                throw e;
            }
        }
        /**
         * Collect the general names from a certificate's SubjectAlternativeName extension.
         *
         * General Names can contain: dnsNames, ipAddresses, rfc822Names, x400Addresses, directoryNames, ediPartyNames,
         * uniformResourceIdentifiers, registeredIDs (OID), or otherNames (anything). See
         * {@link X509Certificate#getSubjectAlternativeNames()} for details on how these values are encoded. We separate
         * the dnsNames and ipAddresses (which we can try to match) from everything else (which we do not try to match.)
         *
         * @param subject  certificate
         * @param dnsNames  list where the dnsNames will be added (may be empty)
         * @param ipAddresses  list where the ipAddresses will be added (may be empty)
         * @param allOthers  list where all other general names will be added (may be empty)
         */
        private void getSanGeneralNames(X509Certificate subject,
                                        List<String> dnsNames, List<String> ipAddresses,
                                        List<Object> allOthers) {
            try {
                Collection<List<?>> sans = subject.getSubjectAlternativeNames();
                if (sans == null) {
                    return;
                }
                for (List<?> san : sans) {
                    switch ((Integer) san.get(0)) {
                    case 2:
                        dnsNames.add((String) san.get(1));
                        break;
                    case 7:
                        ipAddresses.add((String) san.get(1));
                        break;
                    default:
                        allOthers.add(san.get(1));
                        break;
                    }
                }
            } catch (CertificateParsingException e) {
                /* do nothing */
            }
        }
        /**
         * Get the ASN.1 criticality of the SubjectAlternativeName extension.
         *
         * @param subject X509Certificate to check
         * @return {@code true} if a subject alt name was found and was marked critical, {@code false} otherwise.
         */
        private boolean getSanCriticality(X509Certificate subject) {
            Set<String> critSet = subject.getCriticalExtensionOIDs();
            return critSet != null && critSet.contains("2.5.29.17");
        }
        /**
         * Convert to an IP address without performing a DNS lookup.
         *
         * @param hostName  either an IP address string, or a host name
         * @return {@code InetAddress} if hostName was an IPv4 or IPv6 address, or {@code null}
         */
        private static InetAddress toIpAddress(String hostName) {
            try {
                if (InetAddressValidator.isValid(hostName)) {
                    return InetAddress.getByName(hostName);
                }
            } catch (UnknownHostException e) {
                /* do nothing */
            }
            return null;
        }
        /**
         * Verify an IP address in the list of IP addresses.
         *
         * @param hostAddress  IP address from the user
         * @param ipAddresses  List of IP addresses from the certificate (may be empty)
         * @param principal  Subject name from the certificate
         * @param failureIsCritical  Should a verification failure throw a {@link CertificateException}
         * @return {@code true} if the address is verified, {@code false} if the address was not verified.
         * @throws CertificateException  if verification fails and {@code failureIsCritical} is {@code true}.
         */
        private boolean verifyIpAddresses(InetAddress hostAddress, List<String> ipAddresses, X500Principal principal,
                                          boolean failureIsCritical) throws CertificateException {
            if (!ipAddresses.isEmpty()) {
                for (String address : ipAddresses) {
                    try {
                        if (InetAddress.getByName(address).equals(hostAddress)) {
                            return true;
                        }
                    } catch (UnknownHostException e) {
                        // do nothing
                    }
                }
                if (failureIsCritical) {
                    // RFC 5280 mentions:
                            /* If the subject field
                             * contains an empty sequence, then the issuing CA MUST include a
                             * subjectAltName extension that is marked as critical.  When including
                             * the subjectAltName extension in a certificate that has a non-empty
                             * subject distinguished name, conforming CAs SHOULD mark the
                             * subjectAltName extension as non-critical.
                             */
                    // Since SAN is critical, the subject is empty, so we cannot perform the next check anyway
                    throw new CertificateException(ERR_CERT_NO_MATCH_IP.get(principal, hostName).toString());
                }
            }
            return false;
        }
        /**
         * Verify a hostname in the list of DNS name patterns.
         *
         * @param hostName  Host name from the user
         * @param dnsNamePatterns  List of DNS name patterns from the certificate (may be empty)
         * @param principal  Subject name from the certificate
         * @param failureIsCritical  Should a verification failure throw a {@link CertificateException}
         * @return {@code true} if the address is verified, {@code false} if the address was not verified.
         * @throws CertificateException  If verification fails and {@code failureIsCritical} is {@code true}
         */
        private boolean verifyDnsNamePatterns(String hostName, List<String> dnsNamePatterns, X500Principal principal,
                              boolean failureIsCritical) throws CertificateException {
            for (String namePattern : dnsNamePatterns) {
                if (hostNameMatchesPattern(hostName, namePattern)) {
                    return true;
                }
            }
            if (failureIsCritical) {
                throw new CertificateException(ERR_CERT_NO_MATCH_DNS.get(principal, hostName).toString());
            }
            return false;
        }
        /**
         * Checks whether a host name matches the provided pattern. It accepts the use of wildcards in the pattern,
         * e.g. {@code *.example.com}.
         *
         * @param hostName
         *            The host name.
         * @param pattern
         *            The host name pattern, which may contain wild cards.
         * @return {@code true} if the host name matched the pattern, otherwise
         *         {@code false}.
         *            The host name pattern, which may contain wildcards.
         * @return {@code true} if the host name matched the pattern, otherwise {@code false}.
         */
        private boolean hostNameMatchesPattern(final String hostName, final String pattern) {
            final String[] nameElements = hostName.split("\\.");
@@ -100,24 +294,22 @@
            return hostMatch;
        }
        private void verifyHostName(final X509Certificate[] chain) {
            try {
                // TODO: NPE if root DN.
                final DN dn =
                        DN.valueOf(chain[0].getSubjectX500Principal().getName(), Schema
                                .getCoreSchema());
                final String certSubjectHostName =
                        dn.iterator().next().iterator().next().getAttributeValue().toString();
                if (!hostNameMatchesPattern(hostName, certSubjectHostName)) {
                    throw new CertificateException(
                            "The host name contained in the certificate chain subject DN \'"
                                    + chain[0].getSubjectX500Principal()
                                    + "' does not match the host name \'" + hostName + "'");
        /**
         * Find the lowest (left-most) cn in the DN, and return its value.
         *
         * @param subject the DN being searched
         * @return the cn value, or {@code null} if no cn was found
         */
        private String getLowestCommonName(DN subject) {
            AttributeType cn = Schema.getDefaultSchema().getAttributeType("cn");
            for (RDN rdn : subject) {
                for (AVA ava : rdn) {
                    if (ava.getAttributeType().equals(cn)) {
                        return ava.getAttributeValue().toString();
                    }
                }
            } catch (final Throwable t) {
                LOG.log(Level.WARNING, "Error parsing subject dn: "
                        + chain[0].getSubjectX500Principal(), t);
            }
            return null;
        }
    }
@@ -155,16 +347,14 @@
                try {
                    c.checkValidity(currentDate);
                } catch (final CertificateExpiredException e) {
                    LOG.log(Level.WARNING, "Refusing to trust security" + " certificate \""
                            + c.getSubjectDN().getName() + "\" because it" + " expired on "
                            + String.valueOf(c.getNotAfter()));
                    logger.warn(LocalizableMessage.raw(
                            "Refusing to trust security certificate \'%s\' because it expired on %s",
                            c.getSubjectDN().getName(), String.valueOf(c.getNotAfter())));
                    throw e;
                } catch (final CertificateNotYetValidException e) {
                    LOG.log(Level.WARNING, "Refusing to trust security" + " certificate \""
                            + c.getSubjectDN().getName() + "\" because it" + " is not valid until "
                            + String.valueOf(c.getNotBefore()));
                    logger.warn(LocalizableMessage.raw(
                            "Refusing to trust security  certificate \'%s\' because it is not valid until %s",
                            c.getSubjectDN().getName(), String.valueOf(c.getNotBefore())));
                    throw e;
                }
            }
@@ -226,23 +416,29 @@
        }
    }
    private static final Logger LOG = Logger.getLogger(TrustManagers.class.getName());
    /**
     * Wraps the provided {@code X509TrustManager} by adding additional
     * validation which rejects certificate chains whose subject DN does not
     * match the specified host name pattern. The pattern may contain
     * wild-cards, for example {@code *.example.com}.
     * Wraps the provided {@code X509TrustManager} by adding additional validation which rejects certificate chains
     * whose subject alternative names do not match the specified host name or IP address. The check may fall back to
     * checking a hostname in the left-most CN of the subjectDN for backwards compatibility.
     *
     * If the {@code hostName} is an IP address, only the {@code ipAddresses} field of the subject alternative name
     * will be checked. Similarly if {@code hostName} is not an IP address, only the {@code dnsNames} of the subject
     * alternative name will be checked.
     *
     * Host names can be matched using wild cards, for example {@code *.example.com}.
     *
     * If a critical subject alternative name doesn't match, verification will not fall back to checking the subjectDN
     * and will <b>fail</b>. If a critical subject alternative name doesn't match and it contains other kinds of general
     * names that cannot be checked verification will also <b>fail</b>.
     *
     * @param hostName
     *            A host name which the RDN value contained in
     *            certificate subject DNs must match.
     *            The IP address or hostname used to connect to the LDAP server which will be matched against the
     *            subject alternative name and possibly the subjectDN as described above.
     * @param trustManager
     *            The trust manager to be wrapped.
     * @return The wrapped trust manager.
     * @throws NullPointerException
     *             If {@code trustManager} or {@code hostNamePattern} was
     *             {@code null}.
     *             If {@code trustManager} or {@code hostName} was {@code null}.
     */
    public static X509TrustManager checkHostName(final String hostName,
            final X509TrustManager trustManager) {
opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
@@ -1681,3 +1681,12 @@
 because the connection timeout period of %d ms was exceeded
LOAD_BALANCER_EVENT_LISTENER_LOG_ONLINE=Connection factory '%s' is now operational
LOAD_BALANCER_EVENT_LISTENER_LOG_OFFLINE=Connection factory '%s' is no longer operational: %s
ERR_CERT_NO_MATCH_IP=The IP addresses in the critical subject alt name extension for '%s' \
  do not match the address '%s'
ERR_CERT_NO_MATCH_DNS=The DNS names in the critical subject alt name extension for '%s' \
  do not match the host name '%s'
ERR_CERT_NO_MATCH_ALLOTHERS=None of the remaining names in the critical subject alt name extension for '%s' \
  can be matched against '%s'
ERR_CERT_NO_MATCH_SUBJECT=The host name contained in the subject DN '%s' \
  does not match the host name '%s'
opendj-core/src/test/java/org/forgerock/opendj/ldap/TrustManagersTestCase.java
New file
@@ -0,0 +1,218 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2016 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.Assert;
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.logging.Level;
/**
 * This class defines a set of tests for the
 * {@link org.forgerock.opendj.ldap.TrustManagers} class.
 */
@SuppressWarnings("javadoc")
public class TrustManagersTestCase extends SdkTestCase  {
    /**
     * X509TrustManager test data provider with a variety of hostnames in subjects and subject alt names.
     *
     * @return The array of test data.
     */
    @DataProvider(name = "hostnameTestData")
    public Object[][] createHostnameTestData() throws Exception {
        // see comments in test cases for descriptions
        X509Certificate cert1 = getTestCertificate("cert1.pem");
        X509Certificate cert2 = getTestCertificate("cert2.pem");
        X509Certificate cert3 = getTestCertificate("cert3.pem");
        X509Certificate cert4 = getTestCertificate("cert4.pem");
        X509Certificate cert5 = getTestCertificate("cert5.pem");
        X509Certificate cert6 = getTestCertificate("cert6.pem");
        X509Certificate cert7 = getTestCertificate("cert7.pem");
        X509Certificate cert8 = getTestCertificate("cert8.pem");
        X509Certificate cert9 = getTestCertificate("cert9.pem");
        X509Certificate cert10 = getTestCertificate("cert10.pem");
        X509Certificate cert11 = getTestCertificate("cert11.pem");
        X509Certificate cert12 = getTestCertificate("cert12.pem");
        X509Certificate cert13 = getTestCertificate("cert13.pem");
        // @formatter:off
        return new Object[][] {
             /*
              * cert1:
              *   subject "cn=ldap.example.com,o=OpenDJ"
              *   san (none)
              */
            { cert1, "ldap.example.com", true },
            { cert1, "ldap2.example.com", false },
            { cert1, "192.168.0.1", false },
            { cert1, "2001:db8::1:0:0:1", false },
            { cert1, "*.example.com", false },
             /*
              * cert2:
              *   subject "email=info,cn=ldap.example.com,o=OpenDJ"
              *   san (none)
              */
            { cert2, "ldap.example.com", true },
            { cert2, "ldap2.example.com", false },
            { cert2, "192.168.0.1", false },
            { cert2, "2001:db8::1:0:0:1", false },
            { cert2, "info", false },
             /*
              * cert3:
              *   subject "cn=ldap.example.com,o=OpenDJ"
              *   san [ dnsName "ldap.example.org"] critical
              */
            { cert3, "ldap.example.org", true },
            { cert3, "ldap.example.com", false }, // critical so no fall back to testing subject DN
            { cert3, "ldap2.example.org", false },
            { cert3, "192.168.0.1", false },
            { cert3, "2001:db8::1:0:0:1", false },
             /*
              * cert4:
              *   subject "cn=ldap.example.com,o=OpenDJ"
              *   san [ dnsName "ldap.example.org"] non-critical
              */
            { cert4, "ldap.example.org", true },
            { cert4, "ldap.example.com", true }, // falls back to testing subject DN
            { cert4, "ldap2.example.org", false },
            { cert4, "192.168.0.1", false },
            { cert4, "2001:db8::1:0:0:1", false },
             /*
              * cert5:
              *   subject "cn=server,o=OpenDJ"
              *   san [ dnsName "ldap1.example.com", "ldap2.example.com" ] critical
              */
            { cert5, "ldap.example.com", false },
            { cert5, "server", false },
            { cert5, "ldap1.example.com", true },
            { cert5, "ldap2.example.com", true },
             /*
              * cert6:
              *   subject "cn=server,o=OpenDJ"
              *   san [ dnsName "*.example.com" ] critical
              */
            { cert6, "ldap.example.com", true },
            { cert6, "ldap10.example.com", true },
            { cert6, "ldap.dev.example.com", false },
            { cert6, "server", false },
             /*
              * cert7:
              *   subject "cn=*.example.com,o=OpenDJ"
              *   san (none)
              */
            { cert7, "ldap1.example.com", true },
            { cert7, "ldap2.example.com", true },
            { cert7, "ldap.dev.example.com", false },
            { cert7, "192.168.0.1", false },
            { cert7, "2001:db8::1:0:0:1", false },
            { cert7, "ldap.example.org", false },
             /*
              * cert8:
              *   subject "cn=server,o=OpenDJ"
              *   san [ dnsName "ldap.example.com", ip "192.168.0.1" ] critical
              */
            { cert8, "ldap.example.com", true },
            { cert8, "192.168.0.1", true },
            { cert8, "ldap2.example.com", false },
            { cert8, "192.168.0.2", false },
            { cert8, "2001:db8::1:0:0:1", false },
            { cert8, "server", false },
             /*
              * cert9:
              *   subject "cn=server,o=OpenDJ"
              *   san [ ip "2001:db8::1:0:0:1" ] critical
              */
            { cert9, "2001:db8::1:0:0:1", true },
            { cert9, "ldap.example.com", false },
            { cert9, "server", false },
             /*
              * cert10:
              *   subject "cn=server,o=OpenDJ"
              *   san [ email "info@forgerock.org" ] critical
              */
            { cert10, "ldap.example.com", false },
            { cert10, "server", false },
             /*
              * cert11:
              *   subject "cn=ldap.example.com,o=OpenDJ"
              *   san [ uri "ldap://ldap.example.com ] critical
              */
            { cert11, "ldap.example.com", false },
             /*
              * cert12:
              *   subject "cn=server,o=OpenDJ"
              *   san [ dns "ldap.example.com", uri "ldap://ldap.example.com" ] non-critical
              */
            { cert12, "ldap.example.com", true },
            { cert12, "server", true },
             /*
              * cert13:
              *  subject ""
              *  san [ dns "ldap.example.com" ] critical
              */
            { cert13, "ldap.example.com", true },
            { cert13, "server", false },
        };
        // @formatter:on
    }
    /**
     * Disables logging before the tests.
     */
    @BeforeClass
    public void disableLogging() {
        TestCaseUtils.setDefaultLogLevel(Level.SEVERE);
    }
    /**
     * Re-enable logging after the tests.
     */
    @AfterClass
    public void enableLogging() {
        TestCaseUtils.setDefaultLogLevel(Level.INFO);
    }
    private X509Certificate getTestCertificate(String filename) throws Exception {
        String path = TestCaseUtils.getTestFilePath("org.forgerock.opendj.ldap.TrustManagers" + File.separator
                + filename);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        try (InputStream is = new FileInputStream(path)) {
            return (X509Certificate) cf.generateCertificate(is);
        }
    }
    @Test(dataProvider = "hostnameTestData")
    public void testHostnames(X509Certificate subject, String hostname, boolean expectedResult)
            throws Exception {
        X509TrustManager mgr = TrustManagers.checkHostName(hostname, TrustManagers.trustAll());
        try {
            mgr.checkServerTrusted(new X509Certificate[] { subject }, "RSA");
            Assert.assertTrue(expectedResult);
        } catch (CertificateException ce) {
            Assert.assertFalse(expectedResult);
        }
    }
}
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert1.pem
New file
@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC1DCCAbygAwIBAgIEV3pVNjANBgkqhkiG9w0BAQsFADAsMQ8wDQYDVQQKDAZP
cGVuREoxGTAXBgNVBAMMEGxkYXAuZXhhbXBsZS5jb20wHhcNMTYwNzA0MTIyMzM4
WhcNMTcwNzA0MTIyMzM4WjAsMQ8wDQYDVQQKDAZPcGVuREoxGTAXBgNVBAMMEGxk
YXAuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCA
Z4cWPDd5Usv6InfpewuYN2UQE20JvHmWT35OlObXxogk4SDncmuxqux8YozkA/5U
Pa9hYFroVVpsa84x173tg01AsiBotxjBzdDfmue7NF/hDdlg6mYYuIDAi94f84Pi
Y7z+/Sm0vFfKRZoRXJtmjnGZJBFzPi5L5xEzb94YvMhdqJPNRI2ihNSG4fGFRyq6
1S4y2p8Hj6AeCwVjFVOjwtry4IG469EQbqrz5ZbPa4iJ0zNZNE51mGXDJA5B/ht9
8DAGGae8rB3Eab5VGERjPJpyNNnU+irJVlr6Uef6iCguPoZyYc1LPOkaIynUey54
RWLyPXvvxiXUIpNMotaTAgMBAAEwDQYJKoZIhvcNAQELBQADggEBABoPGkJAiEpg
buPJsltgY4mfKLzRZw0RmTIh+zhm8aI06owAOtdN9x7tnh5bb7ZEPv3toP2AoCNl
aWb2Y3EqpZvITXhDHw9F40UwW6sQapnlGjGZMgmttD2z/5ozeYhKWyNQgg/7nwMd
atsZNmd4s/ePRPQzq2DoXQs+8Hp/jhvlVdU6/B8pUO4M6tT4gGGVHrB4cb0oBqW/
xeoXYAhiHiYx6KNxXoRy6y9/TbIock0nd6BoXTepl4vziPVnHFW3Mw6CKUnzUC5A
wKTmAR5Ja5Nu0grcJjrLvUDH6nSlVHR3xORH4Xbbqt8cUXgebWWiz6VoRnVa8iLs
UbwVVuiYQrs=
-----END CERTIFICATE-----
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert10.pem
New file
@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC5jCCAc6gAwIBAgIEV3pryzANBgkqhkiG9w0BAQsFADAiMQ8wDQYDVQQKDAZP
cGVuREoxDzANBgNVBAMMBnNlcnZlcjAeFw0xNjA3MDQxNDAwMjVaFw0xNzA3MDQx
NDAwMjVaMCIxDzANBgNVBAoMBk9wZW5ESjEPMA0GA1UEAwwGc2VydmVyMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlLXw1BOnRttU0MnIm56yBubRgyIp
HqC2EZXwbqAb6WpFe72P7CsN1+UbpzfHJl6JV7bpKNbHXB1nA1e1W9zdTBy/j+GJ
VYctZuXJQ453ehi8c3C8iv3SkFDgcw0+B8d3JWpFVTTaEMCJpwN/z06/3Kh9dDBM
qelQqYOY2skRpMErJB7KJGqxhhoiBDl32b2hICszH0+637RlywfACe42CytBR2/i
yzvRULN8fccGpHDvDg3XPZKP+wNcImJT70u0meCvN4HG3jdm1zakCQ5+6fHvzJp9
rIzRZ6J7KDbC1oT/NUCWTeB+S2IexuS+8+KULNmWu2JQGyVEXTyI/7+/QQIDAQAB
oyQwIjAgBgNVHREBAf8EFjAUgRJpbmZvQGZvcmdlcm9jay5vcmcwDQYJKoZIhvcN
AQELBQADggEBAGrzyIPsp6fMHz3lfvY9uTO3+6J4FiXq5073WjdW100tO97lGvhW
DyyCBDhDQHtvIqiNSkyE11vtuvVqxQAXujwsuzfSKhXZai7BSpfoz28QefV3Kn7F
+5gR+YG6e0xrBgsNO6ZupiHxGq0jocsge/HHRXYjZutqK+LUZFUBtAuaeJ6+Nqkw
f8cMNWjQbqNKokqhK71NMnG4GLXg0/7lqlX8I0zs8jgKonlgsd1gQzWadqFSUjcW
4g2xN8oHsCR4Z5K3hkqnrwuwNn2ca9byo3qU6vLRm/ShPphZ1I+Le9l9TZRNko33
hccRusqQau4Rd2p0Un5cl5sSVS7Si0JUBZQ=
-----END CERTIFICATE-----
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert11.pem
New file
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIC/zCCAeegAwIBAgIEV3qLJTANBgkqhkiG9w0BAQsFADAsMQ8wDQYDVQQKDAZP
cGVuREoxGTAXBgNVBAMMEGxkYXAuZXhhbXBsZS5jb20wHhcNMTYwNzA0MTYxNDE3
WhcNMTcwNzA0MTYxNDE3WjAsMQ8wDQYDVQQKDAZPcGVuREoxGTAXBgNVBAMMEGxk
YXAuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6
EJt4dE7WU1Wi91Wvuy7fo33knGHJpPbLAmkBptRnJebKfpcz6Aiq9/P6ZTcPni/U
2b8JF7PW3TioASx48ns3cpeLLSpG6oveWmf6SSjnrUn6yaOE607inULVCW8Slhrh
5fU6gTppWqB3Ar2xeNLZI7HQBhoAKtFb4KNr5dhI++hMxA5W9u1rZ1xAMNavFn70
XA/WBYM/DlAqSrbIICTNMuXdrYA6uvCv8ZM6U9Brms7qKDArLUUNDkRT64xJ3ajg
AkaJ9KoPfRRx/T/VWDV7i3H5l+hrOBQ+tsc0I19XUvBam+BZFesQa6ImB555iTfb
Ft9uBeoQ8ZyZGT2xdEshAgMBAAGjKTAnMCUGA1UdEQEB/wQbMBmGF2xkYXA6Ly9s
ZGFwLmV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQBw220f176kgZeDf3Pq
/KIR0F32e4d1V1lgQmgqYkyuYWRTK2NLnDA1IytgCttdLHJgpOGT2FqqC3GDUiGY
MOQBt3ktSoxFGm9aIgLvD4Vu2i/szKaA8WyVexExGLsuYCaRx8NVHPgpVf2xAuWV
8qpkkAlyqk9epHrxsIKttu8H44DY/bxSbYsWOBMIXnLnZiKvD/UIzTyX2yg1mZsD
UvF4Gpo0vgUMKE1qhLxh+9bgEoOMWb2BeTvdeJUimd7DdYC1sb7WvC+IeigACtVm
/J19maobzW+GkHq79Oyx4i7cwTc5Fo6wYDIuAgN49NO9SzjVchtSI78VQ6DuyiER
ztUD
-----END CERTIFICATE-----
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert12.pem
New file
@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC+jCCAeKgAwIBAgIEV3qL4jANBgkqhkiG9w0BAQsFADAiMQ8wDQYDVQQKDAZP
cGVuREoxDzANBgNVBAMMBnNlcnZlcjAeFw0xNjA3MDQxNjE4MDdaFw0xNzA3MDQx
NjE4MDdaMCIxDzANBgNVBAoMBk9wZW5ESjEPMA0GA1UEAwwGc2VydmVyMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAohD42B3LG+3SntrBn4a5rxcDfcTG
HZadjScjwFZ4qosB0lGw+bO6UKLhHCKMbdoXMYqSWIxPiu/hySae8ecM7++PQsYN
GZb4zn/cpJWJizlknhzhG4byUG+xsarGeV6/ayu8zLHMgelWWExvgeKmjeUCWgLs
xDm23U7m34tbrN+nfyrx3yzc1gtczPehwd7Y3jY+JY4FiOCsHpaitqDKZM2nEg+K
JuXjx0mhENh1qLOcUQax0AWCRh6B5nXCPSV469ed8zz9QyZfR7Lb5WcWOE95PSZM
aEMJBR9vDZfxGjE2k4WipOCKhGjPBUsR4zazGvRfgNeyRsblCChE/enTgwIDAQAB
ozgwNjA0BgNVHREELTArghBsZGFwLmV4YW1wbGUuY29thhdsZGFwOi8vbGRhcC5l
eGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAbvL8blsqkZ+qF8qM1o5G6cCY
w49+4PQGh2mkseJokj7e4w7lfFk3o5jNMEWktig15qir2QWGSecHtBJajWTkw9Fe
/OF74ptdKgBYKxsAF7IFQdozs+NUOc0q7tMp2L4g9rpOTk46EPRHT7zTo0sViNBR
9/0vRsIsBx5HtC9h5f0cucF8ykB7Sibk6wCmubBZWbpm5Hk5aPfq4ui03/SAe79/
e5Cu+1dBx6qJSA5XTG4D1IDizQVKRRTglVwV/jVuG49GDekIg/lVBYTDTD0Ld42+
gCslJrRnw9QbbmejWyn2oZxIVwnCQwCzTZ4NunnOx4fD6OLzAMNDLMWloagAqw==
-----END CERTIFICATE-----
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert13.pem
New file
@@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDLTCCAhWgAwIBAgIJALfTcCMjgUSOMA0GCSqGSIb3DQEBCwUAMD0xCzAJBgNV
BAYTAkdCMQ0wCwYDVQQIDARBdm9uMRIwEAYDVQQKDAlGb3JnZVJvY2sxCzAJBgNV
BAMMAkNBMB4XDTE2MDcwNjE0MzExMVoXDTE3MDcwNjE0MzExMVowADCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN3Y2kkWv0wVNfhVowOCl+4crxsYRAaf
RHPJERTfsLpAhdpHS4VdUTCcwfTmqGn3YQ427wnnl07DDN5YRokfRJArdnfifuoT
/0UWa434AjK5CO9YiZ5BGt9bAoA4jdJqCR5pbW07dA0dAb5XEwirWWW5w/d4N3Eq
26vRMXh7iDLYzuJ2rLDauq4gkdqvYwRi0WfuP7dl41nfxufGdt5vOMot/8akXO2t
kqBJFCpdw5GKILQRo8sf4GaqTYdG0+eplO/rf+JOMWWO9bD6oEzxXk2gYyM5dvbd
h/cv9AE+wBnYXvsW2tK0/emCt1dbVj8i4tPIRBD5IVW+SpO4MKo86AkCAwEAAaNt
MGswCQYDVR0TBAIwADAdBgNVHQ4EFgQUD27k4aisMchWtHCnAFhHa03malYwHwYD
VR0jBBgwFoAUl/cZwoNkFVFCD3lJ6lxuyNxMi0UwHgYDVR0RAQH/BBQwEoIQbGRh
cC5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAXj+Hx2EVswhqpdyW1jN0
E3dxNDCeG3DHJsHmcbPMbTtpPT2xvT/6SNr8+FoLZAtw+ibDR+NFU1H7UGK+bpjh
CfUkArmzbYun3FOkLYliMW/ffqr8lMpeqTuRkrOpAkqqo0dCrT2/ucraFkOhypfk
scaeQq7pTLnjICZ8g9Yu2ru78q4nd5a7s5p/xQ1Om2oy/L+as4fcrNImHomvhfAg
IPr0sX1G8ftlvRRfIzaZORqXB1raeLCXvVt6opyrxTyeWz8Lld3w+FkKwt3YXFA8
Td6tR4JA9TTMlnwaR8dbBSfaPuVrVfoBh5KDOVXji/fER/gKUPaiH48h1rJVucF4
Yg==
-----END CERTIFICATE-----
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert2.pem
New file
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDITCCAgmgAwIBAgIESjmh0DANBgkqhkiG9w0BAQsFADBBMQ8wDQYDVQQKEwZP
cGVuREoxGTAXBgNVBAMTEGxkYXAuZXhhbXBsZS5jb20xEzARBgkqhkiG9w0BCQEW
BGluZm8wHhcNMTYwNzA0MTMxMzIwWhcNMTYxMDAyMTMxMzIwWjBBMQ8wDQYDVQQK
EwZPcGVuREoxGTAXBgNVBAMTEGxkYXAuZXhhbXBsZS5jb20xEzARBgkqhkiG9w0B
CQEWBGluZm8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjYZcndShB
ByrBA80MRnW2RNMbGWCkxDZthpAFwsqQQPXxlKZ7gA/dbIG8ijQximW638mfjcu4
YdViJ2XTafG0G0r1rKD+wl8IQPbWokMBSYWYrXcxN9KEediSL53CAyBqGHJ5TrZD
S0mI5xiWWPxlSuCBdxCvAip8vOuFoLnkeiOdntGkG7lJDkT+3hPIJ0d/ol1ZB7VI
YYkuxJcWZIQw/vhxYFsZ7aBhyxyyMqczhhMKJySwSr3o/Fe/HciLnALMDLXBrifz
BOAjlp3uC6miUPSqUZJGNPR+eaMe7Tj6jTwa1C0EZ3sLmFCt+BUVr2+PrA4AoGDt
9g7r3bkvIpyBAgMBAAGjITAfMB0GA1UdDgQWBBRQn86+hZEpcuM9o+xiDkQA0zHu
dzANBgkqhkiG9w0BAQsFAAOCAQEAQxUaRbsig9JC0HaXlB1gAsy4NYBKMtcOrNhl
eG0SCGGaW2SyWbLOgtfC/256J/CU42RhD6QpMuNQgq701NzkpxOl3rQC3jCLocge
ECAKOe6T20pBhjY7ihgPyJFmsuGZe5bi2Qc0ZLsAe1rKn3t5Gas2WNrU6KwqmsbS
QwKJJ9wAW4SP+GmHZ16Kz+xuZLxE5DY5dw4MOd25w4bagmMrr61JxXblTT76466q
hfBtuEvxzSn2E7DGj7xP0h7X4nfixME8O+qnE+Xd9mIjZNhd5DkXjKy8ZsOzsdFR
qLZmcpcyMFIgrN9/mjRvaNgf19B8lcgx9fM9frzIeOiv+lYFMw==
-----END CERTIFICATE-----
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert3.pem
New file
@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC+DCCAeCgAwIBAgIEV3pVWTANBgkqhkiG9w0BAQsFADAsMQ8wDQYDVQQKDAZP
cGVuREoxGTAXBgNVBAMMEGxkYXAuZXhhbXBsZS5jb20wHhcNMTYwNzA0MTIyNDM1
WhcNMTcwNzA0MTIyNDM1WjAsMQ8wDQYDVQQKDAZPcGVuREoxGTAXBgNVBAMMEGxk
YXAuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCI
+e9AysfcqtTpz78ULs4zs61UmxpflvysBKgc4Vo+fQFEfxLDb2q1i8Pf3Mv40Q9t
9xCcSDYV8FFbKRinv15vVLZ/nHa1V7q2yqWuDF7P0pyEDjnVgmOOL+/VMHCz80GE
UKpLvmHjOJoPJ1Xz+x5rhWFrOQAYrAsJBWEDJJ7kL9ixjajFK6z2iK7ufTvoks3B
AYEYpPj8e7ngM4UpcPM9KsWU91QlV91Skfxyv5vH/JmdItYnGbv7o/6rTAdfkhZl
6fS8ToK4rWxjl/W9Y9fQcPX1/jB1C5x8GQDFsiSzGosP4L6Rh8rwOArv2cDN/Igp
T92Iv5fN1Sn/t4jWjVl5AgMBAAGjIjAgMB4GA1UdEQEB/wQUMBKCEGxkYXAuZXhh
bXBsZS5vcmcwDQYJKoZIhvcNAQELBQADggEBADKziDxHdbMLfAglpGxpHvU68/9F
yqUSFLamRxAYM+bnxskVf6vJG4Htq0XHrNOGBTpEIacd9txMJkyuqaTcNE9xQmPS
xMnv5nTQumq65AD3MJvXBFpG+kumVv5PKvHVIfWykAatvQ2M7w/dDwvjLkB6LdrY
Y1sW3fyri9GhDzXR996Cdlfx+MOpB9f/hmDJzzCbYEwopVJ1tTl0JrqR8Rwih2MS
Kiv7ECkubGnphgwN6+ztLepmbDG2sCevWNAewp49NeCiZBwg3uhpvuxqjFn8zzkB
VhuXCNfVkXZIv3tVnr8cdyKqIG/WOchhho00gfdI7S76aOlF6kvCAUPEP5k=
-----END CERTIFICATE-----
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert4.pem
New file
@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC9TCCAd2gAwIBAgIEV3pdzTANBgkqhkiG9w0BAQsFADAsMQ8wDQYDVQQKDAZP
cGVuREoxGTAXBgNVBAMMEGxkYXAuZXhhbXBsZS5jb20wHhcNMTYwNzA0MTMwMDMw
WhcNMTcwNzA0MTMwMDMwWjAsMQ8wDQYDVQQKDAZPcGVuREoxGTAXBgNVBAMMEGxk
YXAuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCP
Dbagq6CxseV2HqrjKjj2Er/qsDqk9CVncEZsJL6kV2/S8Umj6w/vOxtsw06DiAV6
Yvs64JDptSPg2ip0pI8CxqO2b7DOA7qwwp8ng0Uw4U6WYGn4tt5zFC/F9hORwFTC
uN3Qm2k+hwCQdIJq5yTEAoq8qNJvUUqCJ7bCcJbNp4qQuFh7gUcqjAAYjc42ABOw
C4NVnfqpHnFa0GibIGZZgQaPWatCWC/+KScJZavH+I6I+kNHqP+0XEvkFYBp/BM/
s8Bg+2rNrrsK1ikq4oS9zOfjcOU2a+1CDKidazxdVYc0Y1p326o74bVYE0vcPE1e
cgb8Sc91wgXml7DDbN9PAgMBAAGjHzAdMBsGA1UdEQQUMBKCEGxkYXAuZXhhbXBs
ZS5vcmcwDQYJKoZIhvcNAQELBQADggEBACio2XKfLsmOH3e1uYhBiqE9+CbuQz6u
nyMO2BaRK69rg1703AI+G6tYf9rC32Lqmt9wGd/IOHcucytPXcq9LQE99f5CP8Pt
D82mBjhbNA4fb/Xf++DprfmywTqU92U5uMUyaGw0DN7v4qqRUeG45O5Mbi/7kAqb
cxYlxwVE5wy816X8wDCa1PvkOFvVO8pVdzhxx7L0jRhEAuqEyCpvlZbDHpvF/K+6
vskoLM42ctrUBi+rFj/5oHw/qw7jhEulMJoQ5sDXxr9+eMbvzszeVJ695ILnBPDQ
7J7Dmodsk2LMF6r1AJX+f7jmOjGn9uw2upSRTkdI+TIAZKhvGjiQw00=
-----END CERTIFICATE-----
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert5.pem
New file
@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC+DCCAeCgAwIBAgIEV3peTjANBgkqhkiG9w0BAQsFADAiMQ8wDQYDVQQKDAZP
cGVuREoxDzANBgNVBAMMBnNlcnZlcjAeFw0xNjA3MDQxMzAyNTNaFw0xNzA3MDQx
MzAyNTNaMCIxDzANBgNVBAoMBk9wZW5ESjEPMA0GA1UEAwwGc2VydmVyMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApxPO9rpEUKWOGJmOW6lqPEkYR8C6
C/NCB+qR7+oPYRMyllaAN8zqc2FZ1gKeDkv4QmI0T8Eg+9tHbRpjkc72tE9nkPFw
IWjhUpfxcbdBmQST7gPlEYj/AVdmd1m25BOJg9YNuMYftyHTRli1ULYOz7AWwTpi
w8v9uT7q2dwMxkbkECa5Y5E0zyuIadlvZKz1GnH1O6/5PKSgMk9qP6X3Bx+QYyq2
X3SfPSrJ5V16h/mIaVgz17OIm8aVOAPaC+b/a9PsIWBF1IapQeBodLc9E+1uvjjI
AyyBibKJreditG8LRiAr+0bqMPrtYm5X7vKtq6Q+l0ryB5T+V8x92eBrAwIDAQAB
ozYwNDAyBgNVHREBAf8EKDAmghFsZGFwMS5leGFtcGxlLmNvbYIRbGRhcDIuZXhh
bXBsZS5jb20wDQYJKoZIhvcNAQELBQADggEBAABh4JgGss1aZ3qc6SmkvYSalmFp
rQJahuwzGBaxDiAKpkfhPRy7g09xzHyWy/3zrYXTURwqqJnWujPfv4h/tJQt3ptl
MW9AzmAYVVBY4u14TdJ/zl67iRukS6SKtN94r67e+lwECxWCD/jheJVbl5/mGcvO
O6uGTc/cXahpwb31Osv8qGQyJLi+rc6x7vMMG3tvAss45RmSkWiKzmITNa9eWqOS
EOercFRlLdaTQ/0FpnMpsO0Ejl1w71I4XXeZ7Ay2fHclBm6S016nMgWqUU9QziFG
wc1mrBP6RKmP+1v0sCO8gXlbzuhnqDSDTBlw4xGZ++Ej3mpIxaX9ZOkqz4k=
-----END CERTIFICATE-----
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert6.pem
New file
@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC4TCCAcmgAwIBAgIEV3peuzANBgkqhkiG9w0BAQsFADAiMQ8wDQYDVQQKDAZP
cGVuREoxDzANBgNVBAMMBnNlcnZlcjAeFw0xNjA3MDQxMzA0MjJaFw0xNzA3MDQx
MzA0MjJaMCIxDzANBgNVBAoMBk9wZW5ESjEPMA0GA1UEAwwGc2VydmVyMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAg5KTCDHu3LhIF/9XlRaVvgFFjfc4
D+npzCFYLujbNmY1G/I9s5o7Be0/9W/1OPZjGO4Wb8fAMfV1qgMGE4XR40+UGtmx
MkBPmVPSV8mgCrGRPYGXkSgvJv8X3lVf3ldbqJOKcaF70AwLrATlqNbCyWweoby8
PSzjlDSDGTUAa1XTj7ACgdcrqq6OdL8N2sqM4C+vnC7GAaqdCq/wQaPpshC6c3gB
lo9+t2hqy3ob/ltnsRA4hvmyB5JJ9LNsfmvhzIGpX/fX1bc13+Katfk9sXIEcn0A
zTUKY9vVppsxpSbhaaM2x0neBhcJDT/BnGBA7NO/42uc8njciyqhuevOUwIDAQAB
ox8wHTAbBgNVHREBAf8EETAPgg0qLmV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUA
A4IBAQB3wyyQjHIU2YCTG59d8C1D8Y6Mb5loodCYkTFqZU4HPaGi8qsBLdzeYvkZ
ntaVogm0jRGAgWlgKwo2IS5a9smctWGK65bLb1Ts3h65Ft0mhMZk4MNUli/yKM+v
zQqRymRRHgj50juaJYiKLWICH6l66AwUPnuZ2pGLDUSxdWTRvmVsfzamySOba+yz
u577MQMXXwybZVhWs6ZZbJ5yVqkXEkFzKgBRPOI5y+reeLRqEfWEb0J+N0h3rYIE
lj01B7EdUQBqle0slB/TUqZkFH+WOv5DX7TwRHOb/qAgIl9EraLxOM/UI/UVUKA6
97y8hmW/nDrEz1rqEYDr/Fj4/s5l
-----END CERTIFICATE-----
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert7.pem
New file
@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIICzjCCAbagAwIBAgIEV3pfHDANBgkqhkiG9w0BAQsFADApMQ8wDQYDVQQKDAZP
cGVuREoxFjAUBgNVBAMMDSouZXhhbXBsZS5jb20wHhcNMTYwNzA0MTMwNTQ3WhcN
MTcwNzA0MTMwNTQ3WjApMQ8wDQYDVQQKDAZPcGVuREoxFjAUBgNVBAMMDSouZXhh
bXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCLrepSmClz
yVV5IYWQ8DGq3K4VgfithXm6pY4ruoH5nwfJ3NbOQukyOOJ8VLvPvbSGMFDeSvtp
dzKfNeYB06mVV7ASvOJZPzD+Teemr6p2+sT/KosstxkrtgWJHRsyVajyMIYNtLh9
2EpLBGYdM4LpzVWmOjNep7it3zH7xqL6IGesI7DVKfv2dQy0RnMV2+B2etDpE5Gi
duxnVHUxBUrC1FxbIvWoAG0H1ijgP2YqGlZCaOGRsBSajGs1Vfhz8hTarzTY/Bgz
66ZDB8t9PM2L7LN73S9QRSGiblloBNLPdbE+cus5t46mNgXswnCv4C9zHqtY+yPf
MYYzSDzJm1dbAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAAgS3k/+GL7JC20KYzkk
jvhDjRCT8xmNNHOsJEPBjGDmj+24s4TwqQdJJ6GmyNM5h5bCPbDaUBExZaagTurl
LLTbqT0UhnlICsFye8/CqP1H9zRneZxVE9U6XIZQCvuhUcvxaGUqYFwa8Fj31R0i
tQQO0WaghxduMDaXb/WVCA94PuTpuPtzLcchdTogO+2nPOvG7AG0YeWhvWkpn/Go
a9FoCx0+BM37UV0eG6rqmrt8dQTx/IdoickNfCuu4qQFzvM2ct0SJrmb4VWMPP2J
QemHQ1nPRFtZenPEc29bSsYbhmauX5Z4N4+soAzGR0Q5By4/11On+w2oAGcz31eg
NuA=
-----END CERTIFICATE-----
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert8.pem
New file
@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC6jCCAdKgAwIBAgIEV3pfizANBgkqhkiG9w0BAQsFADAiMQ8wDQYDVQQKDAZP
cGVuREoxDzANBgNVBAMMBnNlcnZlcjAeFw0xNjA3MDQxMzA4MDNaFw0xNzA3MDQx
MzA4MDNaMCIxDzANBgNVBAoMBk9wZW5ESjEPMA0GA1UEAwwGc2VydmVyMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqceuUbp2niP3eAla+fMlzX+Kt/zA
Xfo/UiY/C+qdcryvuINm4d37+EVW8PUTr9uBKUvsWBUHJ36r7LGCSDlU+3aS+/Du
OFBArKwfayAb8oLwcbWbFRuG406yqBAIIOTFpON/5PATZ1oljyYGEUbPMjPCN5K4
pBSIbLU/yugWPWg0Kx1VtwrRIiRydSu5QVvGA8vDX4+IsDH2UQSgzz8suRLQvbKk
4NroCEzjsmRUQhs0z4vuVPM+4ybMvD13IIrL18SCr8b1drMgeBhXtcD1Z62v/tm0
+qFq3JLc+9Gsf2uJACFOtTwuI8LkUAODbVy7UWL1vW3X02GXq27JXYTZfQIDAQAB
oygwJjAkBgNVHREBAf8EGjAYghBsZGFwLmV4YW1wbGUuY29thwTAqAABMA0GCSqG
SIb3DQEBCwUAA4IBAQAYdVC67IoywXFAUqsCVh2gxSA7Sfu7MCcccJyjG+XxkJYx
S6xuEbvLf8IdG1/VRpO6V07AHSsUz/O2XOwNudfyb59Syvz+Y/OTZaw0w68N+eZp
/F5RWrfzY6anDRRcRDy/uG5PAz7IEdgYyfwCITIOZimHzH1GkBfuGgHSRDktH4q7
pvRrxqJ5S4NDqcUYu0KWvTbkFZeh+a0h5FRdlCW2B9HhXkb6OpoZmHVKpwfOanPQ
x4ztQkGgGJpSHv5cqFNvmpTFxA07ZXFXBWnRQS59pjOgbLiLUxvTyY4a0yfKDIrU
7yj7TEow4LBs2r1zXPVuEIs1bt+4W1pmyUHf463V
-----END CERTIFICATE-----
opendj-core/src/test/resources/org.forgerock.opendj.ldap.TrustManagers/cert9.pem
New file
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDAzCCAeugAwIBAgIEJkgy6zANBgkqhkiG9w0BAQsFADAiMQ8wDQYDVQQKEwZP
cGVuREoxDzANBgNVBAMTBnNlcnZlcjAeFw0xNjA3MDQxMzQ3MTNaFw0xNjEwMDIx
MzQ3MTNaMCIxDzANBgNVBAoTBk9wZW5ESjEPMA0GA1UEAxMGc2VydmVyMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl63LuujQxWqIy7DiDsEDIKDuSTrx
Bw3F0qsn5XoIpXpTqye9z5Ux/CA4GzSTJFiTEGnThqBQUiegz8XHxQRXg0WPddsB
tQVrxRZ1SGnpv0rqX0izdz8Wl1kN6cczzyU06A4Fyx5uDUBfa6vQcLzcRM87Ycsn
cENnB2JUA0G/RRP7dxrpMtln7+iEFr3thAHdmbXodJ9WTpi3tXSYzzPaSLWAbycc
dooMdiQi0rdbYhz6s4FWN22w2i39rIuQKNiiDntJSW+psFXEKCa4exAktEM3vZ/V
WKZGQasN2Ja2BNf9BSq8c1LGuBlPh1eCjFhxKLrdZl7dfxr7Snk8TLZbjwIDAQAB
o0EwPzAeBgNVHREBAf8EFDAShxAgAQ24AAAAAAABAAAAAAABMB0GA1UdDgQWBBQ7
y7Tq2SHqsFQGFA5QjvLJ3hkj3TANBgkqhkiG9w0BAQsFAAOCAQEAbZtb1IMVogE/
ZJcdgRked8pknyhAun2xtaL6ob3PEWHFqeK8WThbvRO5j8FWvcVYMX9OXOJCQJVu
iAvRxZQcRvbu2ApefrvoYQKYFr5Wr9cf8lKe3ggbeqcj48SNNOF/WMq+q4Yv9C8G
cBlxJQvRR4lubXd3FC/xM+YElPJxldMqSZsz4TvtEJYd+lfI3fR0PW8D7svNdUEp
7osvwsA5re2/s9/yyVM/dNUr2ud1lbnA0U5ECRyIHn0V32E0Qmg+yk9rayu1mmbp
Y2M8f3DXVm8tLlpSyV4qKnotgQ09Ip5sQAcKB2k8fuDkjtxJKf/lo4EuXim4skYZ
xP+LN/FvNw==
-----END CERTIFICATE-----