/*
* Copyright © 2014 Cask Data, Inc.
*
* Licensed 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 co.cask.cdap.security.server;
import com.google.common.base.Throwables;
import org.eclipse.jetty.plus.jaas.spi.LdapLoginModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Hashtable;
import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.security.auth.spi.LoginModule;
/**
* A custom {@link LoginModule} that does LDAP authentication. It allows the disabling of SSL
* certificate verification for connections between the {@link ExternalAuthenticationServer} and an LDAP instance.
*/
public class LDAPLoginModule extends LdapLoginModule {
private static final Logger LOG = LoggerFactory.getLogger(LDAPLoginModule.class);
/**
* A {@link SocketFactory} that trusts all SSL certificates.
*/
public static class TrustAllSSLSocketFactory extends SocketFactory {
private final SocketFactory trustAllFactory;
private TrustAllSSLSocketFactory() {
TrustManager[] trustManagers = new TrustManager[] { new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
// no-op
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
// no-op
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}};
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustManagers, new SecureRandom());
trustAllFactory = sc.getSocketFactory();
} catch (GeneralSecurityException e) {
LOG.error("Could not disable certificate verification for connections to LDAP.", e);
throw Throwables.propagate(e);
}
}
/**
* @see SocketFactory#getDefault()
*/
public static SocketFactory getDefault() {
return new TrustAllSSLSocketFactory();
}
/**
* @see SocketFactory#createSocket(String, int)
*/
public Socket createSocket(String host, int port) throws IOException {
return trustAllFactory.createSocket(host, port);
}
/**
* @see SocketFactory#createSocket(InetAddress, int)
*/
public Socket createSocket(InetAddress address, int port) throws IOException {
return trustAllFactory.createSocket(address, port);
}
/**
* @see SocketFactory#createSocket(String, int, InetAddress, int)
*/
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
return trustAllFactory.createSocket(host, port, localHost, localPort);
}
/**
* @see SocketFactory#createSocket(InetAddress, int, InetAddress, int)
*/
public Socket createSocket(InetAddress address, int port,
InetAddress localAddress, int localPort) throws IOException {
return trustAllFactory.createSocket(address, port, localAddress, localPort);
}
}
@Override
public Hashtable<Object, Object> getEnvironment() {
Hashtable<Object, Object> table = super.getEnvironment();
if (!LDAPAuthenticationHandler.getLdapSSLVerifyCertificate()) {
table.put("java.naming.ldap.factory.socket", TrustAllSSLSocketFactory.class.getName());
}
return table;
}
}