--- /dev/null 2017-02-01 16:51:28.944000060 +0000 +++ new/test/com/sun/jndi/ldap/LdapDnsProviderTest.java 2017-02-01 20:04:03.274007677 +0000 @@ -0,0 +1,244 @@ +import java.net.Socket; +import java.net.ServerSocket; +import java.io.*; +import javax.naming.*; +import javax.naming.directory.*; +import java.security.Permission; +import java.util.Hashtable; +import java.util.concurrent.*; + +/** + * @test + * @compile TestDnsProvider.java + * @run main/othervm LdapDnsProviderTest + * @modules java.naming/com.sun.jndi.ldap + * @bug 8160768 + * @summary ctx provider tests for ldap + */ + +class DNSSecurityManager extends SecurityManager { + + private boolean perm = false; + + public void allowSetFactory() { + perm = true; + } + + @Override + public void checkPermission(Permission p) { + if (p.getName().equals("setFactory") && !perm) { + throw new SecurityException(p.getName()); + } + } +} + +class ProviderTest implements Callable { + + private final String expected; + private final ScheduledExecutorService killSwitchPool; + private final LdapTestServer server; + private final Hashtable env = new Hashtable(11); + private final int HANGING_TEST_TIMEOUT = 1000; + + public ProviderTest(LdapTestServer server, + ScheduledExecutorService killSwitchPool, + String expected) + throws IOException + { + this.server = server; + this.killSwitchPool = killSwitchPool; + this.expected = expected; + env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + } + + public ProviderTest(LdapTestServer server, + ScheduledExecutorService killSwitchPool, + String expected, + String dnsProvider) + throws IOException + { + this(server, killSwitchPool, expected); + env.put("com.sun.jndi.ldap.dnsProvider", dnsProvider); + } + + boolean shutItDown(InitialContext ctx) { + try { + if (ctx != null) ctx.close(); + return true; + } catch (NamingException ex) { + return false; + } + } + + public Boolean call() { + boolean passed; + InitialContext ctx = null; + ScheduledFuture killer = null; + // String providerUrl = "ldap://localhost:" + server.getLocalPort(); + String providerUrl = "ldap:///dc=example,dc=com"; + + try { + while(!server.accepting()) { + Thread.sleep(200); // allow the server to start up + } + Thread.sleep(200); // to be sure + + // if this is a hanging test, scheduled a thread to + // interrupt after a certain time + if (killSwitchPool != null) { + final Thread current = Thread.currentThread(); + killer = killSwitchPool.schedule( + (Callable) () -> { + current.interrupt(); + return null; + }, HANGING_TEST_TIMEOUT, TimeUnit.MILLISECONDS); + } + + env.put(Context.PROVIDER_URL, providerUrl); + + try { + ctx = new InitialDirContext(env); + SearchControls scl = new SearchControls(); + scl.setSearchScope(SearchControls.SUBTREE_SCOPE); + ((InitialDirContext)ctx).search( + "ou=People,o=Test", "(objectClass=*)", scl); + throw new RuntimeException("Search should not complete"); + } catch (NamingException e) { + System.err.println(e); + passed = e.toString().indexOf(expected) > -1; + } finally { + if (killer != null && !killer.isDone()) { + killer.cancel(true); + } + shutItDown(ctx); + server.close(); + } + return passed; + } catch (IOException|InterruptedException e) { + throw new RuntimeException(e); + } + } +} + + +class LdapTestServer extends Thread { + ServerSocket serverSock; + boolean accepting = false; + private byte[] bindResponse = { + 0x30, 0x0C, 0x02, 0x01, 0x01, 0x61, 0x07, 0x0A, + 0x01, 0x00, 0x04, 0x00, 0x04, 0x00 + }; + + public LdapTestServer() throws IOException { + this.serverSock = new ServerSocket(0); + start(); + } + + public int getLocalPort() { + return serverSock.getLocalPort(); + } + + public boolean accepting() { + return accepting; + } + + public void close() throws IOException { + serverSock.close(); + } + + public void run() { + try { + accepting = true; + Socket socket = serverSock.accept(); + InputStream in = socket.getInputStream(); + OutputStream out = socket.getOutputStream(); + + // Read the LDAP BindRequest + while (in.read() != -1) { + in.skip(in.available()); + break; + } + + // Write an LDAP BindResponse + out.write(bindResponse); + out.flush(); + } catch (IOException e) { + // ignore + } + } +} + +public class LdapDnsProviderTest { + + private static final ExecutorService testPool = + Executors.newFixedThreadPool(1); + private static final ScheduledExecutorService killSwitchPool = + Executors.newScheduledThreadPool(1); + private static DNSSecurityManager sm = new DNSSecurityManager(); + + public static void main(String[] args) throws Exception { + LdapTestServer server = new LdapTestServer(); + try { + // TestDnsProvider, no SecurityManager + runTest(server, "yupyupyup:389", TestDnsProvider.class.getName()); + // DefaultDnsProvider, no SecurityManager + runTest(server, "localhost:389", "com.sun.jndi.ldap.DefaultLdapDnsProvider"); + // no (default) dnsProvider, no SecurityManager + runTest(server, "localhost:389", ""); + // no dnsProvider context property, no SecurityManager + runTest(server, "localhost:389"); + + System.setSecurityManager(sm); + + // TestDnsProvider with SecurityManager and no permissions + runTest(server, + "setFactory", + TestDnsProvider.class.getName()); + + sm.allowSetFactory(); + + // TestDnsProvider with SecurityManager and correct permissions + runTest(server, + "yupyupyup:389", + TestDnsProvider.class.getName()); + } finally { + LdapDnsProviderTest.killSwitchPool.shutdown(); + LdapDnsProviderTest.testPool.shutdown(); + } + } + + private static boolean runTest(LdapTestServer server, + String expected) + throws IOException, InterruptedException, ExecutionException + { + Future test = testPool.submit( + new ProviderTest( + server, killSwitchPool, expected)); + + while (!test.isDone()) { + if ((Boolean) test.get()) { + return true; + } + } + throw new AssertionError("FAILED: " + expected); + } + + private static boolean runTest(LdapTestServer server, + String expected, + String dnsProvider) + throws IOException, InterruptedException, ExecutionException + { + Future test = testPool.submit( + new ProviderTest( + server, killSwitchPool, expected, dnsProvider)); + + while (!test.isDone()) { + if ((Boolean) test.get()) { + return true; + } + } + throw new AssertionError("FAILED: " + expected + ", " + dnsProvider); + } + +} +