1 /* 2 * Copyright (c) 2009, 2020, Oracle and/or its affiliates. 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 6449574 27 * @summary Invalid ldap filter is accepted and processed 28 */ 29 30 import java.io.*; 31 import javax.naming.*; 32 import javax.naming.directory.*; 33 import java.util.Properties; 34 import java.util.Hashtable; 35 36 import java.net.Socket; 37 import java.net.ServerSocket; 38 39 public class BalancedParentheses { 40 // Should we run the client or server in a separate thread? 41 // 42 // Both sides can throw exceptions, but do you have a preference 43 // as to which side should be the main thread. 44 static boolean separateServerThread = true; 45 46 // use any free port by default 47 volatile int serverPort = 0; 48 49 // Is the server ready to serve? 50 volatile static boolean serverReady = false; 51 52 // Define the server side of the test. 53 // 54 // If the server prematurely exits, serverReady will be set to true 55 // to avoid infinite hangs. 56 void doServerSide() throws Exception { 57 ServerSocket serverSock = new ServerSocket(serverPort); 58 59 // signal client, it's ready to accecpt connection 60 serverPort = serverSock.getLocalPort(); 61 serverReady = true; 62 63 // accept a connection 64 Socket socket = serverSock.accept(); 65 System.out.println("Server: Connection accepted"); 66 67 InputStream is = socket.getInputStream(); 68 OutputStream os = socket.getOutputStream(); 69 70 // read the bindRequest 71 while (is.read() != -1) { 72 // ignore 73 is.skip(is.available()); 74 break; 75 } 76 77 byte[] bindResponse = {0x30, 0x0C, 0x02, 0x01, 0x01, 0x61, 0x07, 0x0A, 78 0x01, 0x00, 0x04, 0x00, 0x04, 0x00}; 79 // write bindResponse 80 os.write(bindResponse); 81 os.flush(); 82 83 // ignore any more request. 84 while (is.read() != -1) { 85 // ignore 86 is.skip(is.available()); 87 } 88 89 is.close(); 90 os.close(); 91 socket.close(); 92 serverSock.close(); 93 } 94 95 // Define the client side of the test. 96 // 97 // If the server prematurely exits, serverReady will be set to true 98 // to avoid infinite hangs. 99 void doClientSide() throws Exception { 100 // Wait for server to get started. 101 while (!serverReady) { 102 Thread.sleep(50); 103 } 104 105 // set up the environment for creating the initial context 106 Hashtable<Object, Object> env = new Hashtable<>(); 107 env.put(Context.INITIAL_CONTEXT_FACTORY, 108 "com.sun.jndi.ldap.LdapCtxFactory"); 109 env.put(Context.PROVIDER_URL, "ldap://localhost:" + serverPort); 110 env.put("com.sun.jndi.ldap.read.timeout", "1000"); 111 112 // env.put(Context.SECURITY_AUTHENTICATION, "simple"); 113 // env.put(Context.SECURITY_PRINCIPAL,"cn=root"); 114 // env.put(Context.SECURITY_CREDENTIALS,"root"); 115 116 // create initial context 117 DirContext context = new InitialDirContext(env); 118 119 // searching 120 SearchControls scs = new SearchControls(); 121 scs.setSearchScope(SearchControls.SUBTREE_SCOPE); 122 123 try { 124 NamingEnumeration<?> answer = context.search( 125 "o=sun,c=us", "(&(cn=Bob)))", scs); 126 } catch (InvalidSearchFilterException isfe) { 127 // ignore, it is the expected filter exception. 128 System.out.println("Expected exception: " + isfe.getMessage()); 129 } catch (NamingException ne) { 130 // maybe a read timeout exception, as the server does not response. 131 throw new Exception("Expect a InvalidSearchFilterException", ne); 132 } 133 134 try { 135 NamingEnumeration<?> answer = context.search( 136 "o=sun,c=us", ")(&(cn=Bob)", scs); 137 } catch (InvalidSearchFilterException isfe) { 138 // ignore, it is the expected filter exception. 139 System.out.println("Expected exception: " + isfe.getMessage()); 140 } catch (NamingException ne) { 141 // maybe a read timeout exception, as the server does not response. 142 throw new Exception("Expect a InvalidSearchFilterException", ne); 143 } 144 145 try { 146 NamingEnumeration<?> answer = context.search( 147 "o=sun,c=us", "(&(cn=Bob))", scs); 148 } catch (InvalidSearchFilterException isfe) { 149 // ignore, it is the expected filter exception. 150 throw new Exception("Unexpected ISFE", isfe); 151 } catch (NamingException ne) { 152 // maybe a read timeout exception, as the server does not response. 153 System.out.println("Expected exception: " + ne.getMessage()); 154 } 155 156 context.close(); 157 } 158 159 /* 160 * ============================================================ 161 * The remainder is just support stuff 162 */ 163 164 // client and server thread 165 Thread clientThread = null; 166 Thread serverThread = null; 167 168 // client and server exceptions 169 volatile Exception serverException = null; 170 volatile Exception clientException = null; 171 172 void startServer(boolean newThread) throws Exception { 173 if (newThread) { 174 serverThread = new Thread() { 175 public void run() { 176 try { 177 doServerSide(); 178 } catch (Exception e) { 179 /* 180 * Our server thread just died. 181 * 182 * Release the client, if not active already... 183 */ 184 System.err.println("Server died..."); 185 System.err.println(e); 186 serverReady = true; 187 serverException = e; 188 } 189 } 190 }; 191 serverThread.start(); 192 } else { 193 doServerSide(); 194 } 195 } 196 197 void startClient(boolean newThread) throws Exception { 198 if (newThread) { 199 clientThread = new Thread() { 200 public void run() { 201 try { 202 doClientSide(); 203 } catch (Exception e) { 204 /* 205 * Our client thread just died. 206 */ 207 System.err.println("Client died..."); 208 clientException = e; 209 } 210 } 211 }; 212 clientThread.start(); 213 } else { 214 doClientSide(); 215 } 216 } 217 218 // Primary constructor, used to drive remainder of the test. 219 BalancedParentheses() throws Exception { 220 if (separateServerThread) { 221 startServer(true); 222 startClient(false); 223 } else { 224 startClient(true); 225 startServer(false); 226 } 227 228 /* 229 * Wait for other side to close down. 230 */ 231 if (separateServerThread) { 232 serverThread.join(); 233 } else { 234 clientThread.join(); 235 } 236 237 /* 238 * When we get here, the test is pretty much over. 239 * 240 * If the main thread excepted, that propagates back 241 * immediately. If the other thread threw an exception, we 242 * should report back. 243 */ 244 if (serverException != null) { 245 System.out.print("Server Exception:"); 246 throw serverException; 247 } 248 if (clientException != null) { 249 System.out.print("Client Exception:"); 250 throw clientException; 251 } 252 } 253 254 public static void main(String[] args) throws Exception { 255 // start the test 256 new BalancedParentheses(); 257 } 258 259 }