/* See LICENSE for licensing and NOTICE for copyright. */
package org.ldaptive.ssl;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import javax.net.ssl.X509TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Trust manager that delegates to {@link CertificateHostnameVerifier}. Any name that verifies passes this trust manager
* check.
*
* @author Middleware Services
*/
public class HostnameVerifyingTrustManager implements X509TrustManager
{
/** Logger for this class. */
protected final Logger logger = LoggerFactory.getLogger(getClass());
/** Hostnames to allow. */
private final String[] hostnames;
/** Hostname verifier to use for trust. */
private final CertificateHostnameVerifier hostnameVerifier;
/**
* Creates a new hostname verifying trust manager.
*
* @param verifier that establishes trust
* @param names to match against a certificate
*/
public HostnameVerifyingTrustManager(final CertificateHostnameVerifier verifier, final String... names)
{
hostnameVerifier = verifier;
hostnames = names;
}
@Override
public void checkClientTrusted(final X509Certificate[] chain, final String authType)
throws CertificateException
{
checkCertificateTrusted(chain[0]);
}
@Override
public void checkServerTrusted(final X509Certificate[] chain, final String authType)
throws CertificateException
{
checkCertificateTrusted(chain[0]);
}
/**
* Verifies the supplied certificate using the hostname verifier with each hostname.
*
* @param cert to verify
*
* @throws CertificateException if none of the hostnames verify
*/
private void checkCertificateTrusted(final X509Certificate cert)
throws CertificateException
{
for (String name : hostnames) {
if (hostnameVerifier.verify(name, cert)) {
logger.debug(
"checkCertificateTrusted for {} succeeded against {}",
hostnameVerifier,
cert != null ? cert.getSubjectX500Principal() : null);
return;
}
}
throw new CertificateException(
String.format(
"Hostname '%s' does not match the hostname in the server's " +
"certificate '%s'",
Arrays.toString(hostnames),
cert != null ? cert.getSubjectX500Principal() : null));
}
@Override
public X509Certificate[] getAcceptedIssuers()
{
return new X509Certificate[0];
}
@Override
public String toString()
{
return
String.format(
"[%s@%d::hostnameVerifier=%s, hostnames=%s]",
getClass().getName(),
hashCode(),
hostnameVerifier,
Arrays.toString(hostnames));
}
}