/* * 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-unique * @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; } }