blob: 16b4400310a2d213a7433ec8442f214d5447c434 [file] [log] [blame]
/*
* Copyright (c) 2020, Azul Systems, Inc. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8245527
* @library lib/ /test/lib
* @run main/othervm LdapCBPropertiesTest true true com.sun.jndi.ldap.tls.cbtype tls-server-end-point
* @run main/othervm LdapCBPropertiesTest false false com.sun.jndi.ldap.tls.cbtype tls-server-end-point
* @run main/othervm LdapCBPropertiesTest true true com.sun.jndi.ldap.tls.cbtype tls-server-end-point com.sun.jndi.ldap.connect.timeout 2000
* @run main/othervm LdapCBPropertiesTest false false com.sun.jndi.ldap.tls.cbtype tls-server-end-point com.sun.jndi.ldap.connect.timeout 2000
* @run main/othervm LdapCBPropertiesTest false true com.sun.jndi.ldap.tls.cbtype tls-unknown
* @run main/othervm LdapCBPropertiesTest false true jdk.internal.sasl.tlschannelbinding value
* @summary test new JNDI property to control the Channel Binding data
*/
import javax.naming.AuthenticationException;
import javax.naming.CommunicationException;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import java.net.InetAddress;
import java.net.URI;
import java.util.Hashtable;
import org.ietf.jgss.GSSException;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.security.sasl.SaslException;
import jdk.test.lib.net.URIBuilder;
public class LdapCBPropertiesTest {
/*
* Where do we find the keystores?
*/
static String pathToStores = "../../../../javax/net/ssl/etc";
static String keyStoreFile = "keystore";
static String trustStoreFile = "truststore";
static String passwd = "passphrase";
static boolean debug = false;
public static void main(String[] args) throws Exception {
String keyFilename =
System.getProperty("test.src", "./") + "/" + pathToStores +
"/" + keyStoreFile;
String trustFilename =
System.getProperty("test.src", "./") + "/" + pathToStores +
"/" + trustStoreFile;
System.setProperty("javax.net.ssl.keyStore", keyFilename);
System.setProperty("javax.net.ssl.keyStorePassword", passwd);
System.setProperty("javax.net.ssl.trustStore", trustFilename);
System.setProperty("javax.net.ssl.trustStorePassword", passwd);
if (debug)
System.setProperty("javax.net.debug", "all");
/*
* Start the tests.
*/
new LdapCBPropertiesTest(args);
}
/*
* Primary constructor, used to drive remainder of the test.
*/
LdapCBPropertiesTest(String[] args) throws Exception {
InetAddress loopback = InetAddress.getLoopbackAddress();
SSLServerSocketFactory sslssf =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslServerSocket =
(SSLServerSocket) sslssf.createServerSocket(0, 0, loopback);
int serverPort = sslServerSocket.getLocalPort();
try (var ignore = new BaseLdapServer(sslServerSocket).start()) {
doClientSide(serverPort, args);
}
}
/*
* Define the client side of the test.
*
* The server should start at this time already
*/
void doClientSide(int serverPort, String[] args) throws Exception {
boolean passed = false;
boolean shouldPass = Boolean.parseBoolean(args[0]);
boolean shouldConnect = Boolean.parseBoolean(args[1]);
// set disableEndpointIdentification to disable hostname verification
if (shouldConnect) {
System.setProperty(
"com.sun.jndi.ldap.object.disableEndpointIdentification", "true");
}
// Set up the environment for creating the initial context
Hashtable env = new Hashtable();
URI uri = URIBuilder.newBuilder()
.scheme("ldaps")
.loopback()
.port(serverPort)
.build();
env.put(Context.PROVIDER_URL, uri.toString());
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
// read properties
for (int i = 2; i < args.length; i += 2) {
env.put(args[i], args[i + 1]);
if (debug)
System.out.println("Env=" + args[i] + "=" + args[i + 1]);
}
try {
DirContext ctx = new InitialDirContext(env);
passed = shouldPass;
ctx.close();
} catch (NamingException ne) {
// only NamingException is allowed
if (debug)
System.out.println("Exception=" + ne + " cause=" + ne.getRootCause());
passed = handleNamingException(ne, shouldPass, shouldConnect);
} catch(Exception e) {
System.err.println("Failed: caught an unexpected Exception - " + e);
throw e;
} finally {
// test if internal property accessible to application
if(shouldPass &&
env.get("jdk.internal.sasl.tlschannelbinding") != null) {
throw new Exception(
"Test FAILED: jdk.internal.sasl.tlschannelbinding should not be accessible");
}
}
if (!passed) {
throw new Exception(
"Test FAILED: NamingException exception should be thrown");
}
System.out.println("Test PASSED");
}
private static boolean handleNamingException(NamingException ne, boolean shouldPass, boolean shouldConnect)
throws NamingException {
if (ne instanceof AuthenticationException &&
ne.getRootCause() instanceof SaslException) {
SaslException saslEx = (SaslException) ne.getRootCause();
if (shouldConnect && saslEx.getCause() instanceof GSSException) {
// SSL connection successful, expected exception from SaslClient
if (shouldPass)
return true;
}
}
if (!shouldConnect) {
// SSL handshake fails
Exception ex = ne;
while(ex != null && !(ex instanceof CommunicationException)) {
ex = (Exception)ex.getCause();
}
if (ex != null) {
if (ex.getCause() instanceof SSLException) {
if (!shouldPass)
return true;
}
}
}
if (!shouldPass && ne.getRootCause() == null) {
// Expected exception caused by Channel Binding parameter inconsistency
return true;
}
throw ne;
}
}