package org.bouncycastle.cert.dane.fetcher;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import org.bouncycastle.cert.dane.DANEEntry;
import org.bouncycastle.cert.dane.DANEEntryFetcher;
import org.bouncycastle.cert.dane.DANEEntryFetcherFactory;
import org.bouncycastle.cert.dane.DANEException;
public class JndiDANEFetcherFactory
implements DANEEntryFetcherFactory
{
private static final String DANE_TYPE = "53";
private List dnsServerList = new ArrayList();
private boolean isAuthoritative;
public JndiDANEFetcherFactory usingDNSServer(String dnsServer)
{
this.dnsServerList.add(dnsServer);
return this;
}
public JndiDANEFetcherFactory setAuthoritative(boolean isAuthoritative)
{
this.isAuthoritative = isAuthoritative;
return this;
}
public DANEEntryFetcher build(final String domainName)
{
final Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
env.put(Context.AUTHORITATIVE, isAuthoritative ? "true" : "false");
if (dnsServerList.size() > 0)
{
StringBuffer dnsServers = new StringBuffer();
for (Iterator it = dnsServerList.iterator(); it.hasNext(); )
{
if (dnsServers.length() > 0)
{
dnsServers.append(" ");
}
dnsServers.append("dns://" + it.next());
}
env.put(Context.PROVIDER_URL, dnsServers.toString());
}
return new DANEEntryFetcher()
{
public List getEntries()
throws DANEException
{
List entries = new ArrayList();
try
{
DirContext ctx = new InitialDirContext(env);
NamingEnumeration bindings;
if (domainName.indexOf("_smimecert.") > 0)
{
Attributes attrs = ctx.getAttributes(domainName, new String[]{DANE_TYPE});
Attribute smimeAttr = attrs.get(DANE_TYPE);
if (smimeAttr != null)
{
addEntries(entries, domainName, smimeAttr);
}
}
else
{
bindings = ctx.listBindings("_smimecert." + domainName);
while (bindings.hasMore())
{
Binding b = (Binding)bindings.next();
DirContext sc = (DirContext)b.getObject();
String name = sc.getNameInNamespace().substring(1, sc.getNameInNamespace().length() - 1);
Attributes attrs = ctx.getAttributes(name, new String[]{DANE_TYPE});
Attribute smimeAttr = attrs.get(DANE_TYPE);
if (smimeAttr != null)
{
String fullName = sc.getNameInNamespace();
String domainName = fullName.substring(1, fullName.length() - 1);
addEntries(entries, domainName, smimeAttr);
}
}
}
return entries;
}
catch (NamingException e)
{
throw new DANEException("Exception dealing with DNS: " + e.getMessage(), e);
}
}
};
}
private void addEntries(List entries, String domainName, Attribute smimeAttr)
throws NamingException, DANEException
{
for (int index = 0; index != smimeAttr.size(); index++)
{
byte[] data = (byte[])smimeAttr.get(index);
if (DANEEntry.isValidCertificate(data))
{
try
{
entries.add(new DANEEntry(domainName, data));
}
catch (IOException e)
{
throw new DANEException("Exception parsing entry: " + e.getMessage(), e);
}
}
}
}
}