1 /* 2 * Copyright (c) 2020, Azul Systems, Inc. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @bug 8245527 27 * @library lib/ /test/lib 28 * @run main/othervm LdapCBPropertiesTest true true com.sun.jndi.ldap.tls.cbtype tls-server-end-point 29 * @run main/othervm LdapCBPropertiesTest false false com.sun.jndi.ldap.tls.cbtype tls-server-end-point 30 * @run main/othervm LdapCBPropertiesTest true true com.sun.jndi.ldap.tls.cbtype tls-server-end-point com.sun.jndi.ldap.connect.timeout 2000 31 * @run main/othervm LdapCBPropertiesTest false false com.sun.jndi.ldap.tls.cbtype tls-server-end-point com.sun.jndi.ldap.connect.timeout 2000 32 * @run main/othervm LdapCBPropertiesTest false true com.sun.jndi.ldap.tls.cbtype tls-unique 33 * @run main/othervm LdapCBPropertiesTest false true com.sun.jndi.ldap.tls.cbtype tls-unknown 34 * @run main/othervm LdapCBPropertiesTest false true jdk.internal.sasl.tlschannelbinding value 35 * @summary test new JNDI property to control the Channel Binding data 36 */ 37 38 import javax.naming.AuthenticationException; 39 import javax.naming.CommunicationException; 40 import javax.naming.Context; 41 import javax.naming.NamingException; 42 import javax.naming.directory.DirContext; 43 import javax.naming.directory.InitialDirContext; 44 import java.net.InetAddress; 45 import java.net.URI; 46 import java.util.Hashtable; 47 48 import org.ietf.jgss.GSSException; 49 50 import javax.net.ssl.SSLException; 51 import javax.net.ssl.SSLServerSocket; 52 import javax.net.ssl.SSLServerSocketFactory; 53 import javax.security.sasl.SaslException; 54 55 import jdk.test.lib.net.URIBuilder; 56 57 public class LdapCBPropertiesTest { 58 /* 59 * Where do we find the keystores? 60 */ 61 static String pathToStores = "../../../../javax/net/ssl/etc"; 62 static String keyStoreFile = "keystore"; 63 static String trustStoreFile = "truststore"; 64 static String passwd = "passphrase"; 65 66 static boolean debug = false; 67 68 public static void main(String[] args) throws Exception { 69 String keyFilename = 70 System.getProperty("test.src", "./") + "/" + pathToStores + 71 "/" + keyStoreFile; 72 String trustFilename = 73 System.getProperty("test.src", "./") + "/" + pathToStores + 74 "/" + trustStoreFile; 75 76 System.setProperty("javax.net.ssl.keyStore", keyFilename); 77 System.setProperty("javax.net.ssl.keyStorePassword", passwd); 78 System.setProperty("javax.net.ssl.trustStore", trustFilename); 79 System.setProperty("javax.net.ssl.trustStorePassword", passwd); 80 81 if (debug) 82 System.setProperty("javax.net.debug", "all"); 83 84 /* 85 * Start the tests. 86 */ 87 new LdapCBPropertiesTest(args); 88 } 89 90 /* 91 * Primary constructor, used to drive remainder of the test. 92 */ 93 LdapCBPropertiesTest(String[] args) throws Exception { 94 InetAddress loopback = InetAddress.getLoopbackAddress(); 95 SSLServerSocketFactory sslssf = 96 (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); 97 SSLServerSocket sslServerSocket = 98 (SSLServerSocket) sslssf.createServerSocket(0, 0, loopback); 99 int serverPort = sslServerSocket.getLocalPort(); 100 101 try (var ignore = new BaseLdapServer(sslServerSocket).start()) { 102 doClientSide(serverPort, args); 103 } 104 } 105 106 /* 107 * Define the client side of the test. 108 * 109 * The server should start at this time already 110 */ 111 void doClientSide(int serverPort, String[] args) throws Exception { 112 boolean passed = false; 113 boolean shouldPass = Boolean.parseBoolean(args[0]); 114 boolean shouldConnect = Boolean.parseBoolean(args[1]); 115 // set disableEndpointIdentification to disable hostname verification 116 if (shouldConnect) { 117 System.setProperty( 118 "com.sun.jndi.ldap.object.disableEndpointIdentification", "true"); 119 } 120 121 // Set up the environment for creating the initial context 122 Hashtable env = new Hashtable(); 123 URI uri = URIBuilder.newBuilder() 124 .scheme("ldaps") 125 .loopback() 126 .port(serverPort) 127 .build(); 128 env.put(Context.PROVIDER_URL, uri.toString()); 129 env.put(Context.INITIAL_CONTEXT_FACTORY, 130 "com.sun.jndi.ldap.LdapCtxFactory"); 131 env.put(Context.SECURITY_AUTHENTICATION, "GSSAPI"); 132 133 // read properties 134 for (int i = 2; i < args.length; i += 2) { 135 env.put(args[i], args[i + 1]); 136 if (debug) 137 System.out.println("Env=" + args[i] + "=" + args[i + 1]); 138 } 139 140 try { 141 DirContext ctx = new InitialDirContext(env); 142 passed = shouldPass; 143 ctx.close(); 144 } catch (NamingException ne) { 145 // only NamingException is allowed 146 if (debug) 147 System.out.println("Exception=" + ne + " cause=" + ne.getRootCause()); 148 passed = handleNamingException(ne, shouldPass, shouldConnect); 149 } catch(Exception e) { 150 System.err.println("Failed: caught an unexpected Exception - " + e); 151 throw e; 152 } finally { 153 // test if internal property accessible to application 154 if(shouldPass && 155 env.get("jdk.internal.sasl.tlschannelbinding") != null) { 156 throw new Exception( 157 "Test FAILED: jdk.internal.sasl.tlschannelbinding should not be accessible"); 158 } 159 } 160 if (!passed) { 161 throw new Exception( 162 "Test FAILED: NamingException exception should be thrown"); 163 } 164 System.out.println("Test PASSED"); 165 } 166 167 private static boolean handleNamingException(NamingException ne, boolean shouldPass, boolean shouldConnect) 168 throws NamingException { 169 if (ne instanceof AuthenticationException && 170 ne.getRootCause() instanceof SaslException) { 171 SaslException saslEx = (SaslException) ne.getRootCause(); 172 if (shouldConnect && saslEx.getCause() instanceof GSSException) { 173 // SSL connection successful, expected exception from SaslClient 174 if (shouldPass) 175 return true; 176 } 177 } 178 if (!shouldConnect) { 179 // SSL handshake fails 180 Exception ex = ne; 181 while(ex != null && !(ex instanceof CommunicationException)) { 182 ex = (Exception)ex.getCause(); 183 } 184 if (ex != null) { 185 if (ex.getCause() instanceof SSLException) { 186 if (!shouldPass) 187 return true; 188 } 189 } 190 } 191 if (!shouldPass && ne.getRootCause() == null) { 192 // Expected exception caused by Channel Binding parameter inconsistency 193 return true; 194 } 195 throw ne; 196 } 197 }