Skip to content
Permalink
Browse files

Move JNDI provider to inner class to avoid CNE on Android

  • Loading branch information
ibauersachs committed Nov 10, 2019
1 parent cb30bfa commit bc58efc71b818cd7f9e1068cb954d591b2ea641c
Showing with 63 additions and 32 deletions.
  1. +63 −32 src/main/java/org/xbill/DNS/config/JndiContextResolverConfigProvider.java
@@ -5,12 +5,14 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Hashtable;
import java.util.List;
import java.util.StringTokenizer;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import lombok.extern.slf4j.Slf4j;
import org.xbill.DNS.Name;
import org.xbill.DNS.SimpleResolver;

/**
@@ -19,49 +21,78 @@
* Provider</a>.
*/
@Slf4j
public class JndiContextResolverConfigProvider extends BaseResolverConfigProvider {
public void initialize() {
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
// http://mail.openjdk.java.net/pipermail/net-dev/2017-March/010695.html
env.put("java.naming.provider.url", "dns://");
public class JndiContextResolverConfigProvider implements ResolverConfigProvider {
private InnerJndiContextResolverConfigProvider inner;

String servers = null;
try {
DirContext ctx = new InitialDirContext(env);
servers = (String) ctx.getEnvironment().get("java.naming.provider.url");
ctx.close();
} catch (NamingException e) {
// ignore
public JndiContextResolverConfigProvider() {
if (!System.getProperty("java.vendor").contains("Android")) {
try {
inner = new InnerJndiContextResolverConfigProvider();
} catch (NoClassDefFoundError e) {
log.debug("JNDI DNS not available");
}
}
}

if (servers != null) {
StringTokenizer st = new StringTokenizer(servers, " ");
while (st.hasMoreTokens()) {
String server = st.nextToken();
try {
URI serverUri = new URI(server);
String host = serverUri.getHost();
if (host == null || host.isEmpty()) {
// skip the fallback server to localhost
continue;
}
private static class InnerJndiContextResolverConfigProvider extends BaseResolverConfigProvider {
public void initialize() {
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
// http://mail.openjdk.java.net/pipermail/net-dev/2017-March/010695.html
env.put("java.naming.provider.url", "dns://");

int port = serverUri.getPort();
if (port == -1) {
port = SimpleResolver.DEFAULT_PORT;
}
String servers = null;
try {
DirContext ctx = new InitialDirContext(env);
servers = (String) ctx.getEnvironment().get("java.naming.provider.url");
ctx.close();
} catch (NamingException e) {
// ignore
}

if (servers != null) {
StringTokenizer st = new StringTokenizer(servers, " ");
while (st.hasMoreTokens()) {
String server = st.nextToken();
try {
URI serverUri = new URI(server);
String host = serverUri.getHost();
if (host == null || host.isEmpty()) {
// skip the fallback server to localhost
continue;
}

int port = serverUri.getPort();
if (port == -1) {
port = SimpleResolver.DEFAULT_PORT;
}

addNameserver(new InetSocketAddress(host, port));
} catch (URISyntaxException e) {
log.debug("Could not parse {} as a dns server, ignoring", server, e);
addNameserver(new InetSocketAddress(host, port));
} catch (URISyntaxException e) {
log.debug("Could not parse {} as a dns server, ignoring", server, e);
}
}
}
}
}

@Override
public void initialize() {
inner.initialize();
}

@Override
public List<InetSocketAddress> servers() {
return inner.servers();
}

@Override
public List<Name> searchPaths() {
return inner.searchPaths();
}

@Override
public boolean isEnabled() {
return !System.getProperty("java.vendor").contains("Android");
return inner != null;
}
}

0 comments on commit bc58efc

Please sign in to comment.
You can’t perform that action at this time.