diff --git a/core/src/main/java/org/springframework/security/remoting/dns/DnsEntryNotFoundException.java b/core/src/main/java/org/springframework/security/remoting/dns/DnsEntryNotFoundException.java index 04143f2ac1..b16c3d0890 100644 --- a/core/src/main/java/org/springframework/security/remoting/dns/DnsEntryNotFoundException.java +++ b/core/src/main/java/org/springframework/security/remoting/dns/DnsEntryNotFoundException.java @@ -18,22 +18,23 @@ package org.springframework.security.remoting.dns; /** - * This will be thrown, if no entry matches the specified DNS query + * This will be thrown if no entry matches the specified DNS query. + * * @author Mike Wiesner * @since 3.0 * @version $Id$ */ public class DnsEntryNotFoundException extends DnsLookupException { - private static final long serialVersionUID = -947232730426775162L; + private static final long serialVersionUID = -947232730426775162L; - public DnsEntryNotFoundException(String msg) { - super(msg); - } + public DnsEntryNotFoundException(String msg) { + super(msg); + } + + public DnsEntryNotFoundException(String msg, Throwable cause) { + super(msg, cause); + } - public DnsEntryNotFoundException(String msg, Throwable cause) { - super(msg, cause); - } - } diff --git a/core/src/main/java/org/springframework/security/remoting/dns/DnsLookupException.java b/core/src/main/java/org/springframework/security/remoting/dns/DnsLookupException.java index ca3937baa2..3913a8e13e 100644 --- a/core/src/main/java/org/springframework/security/remoting/dns/DnsLookupException.java +++ b/core/src/main/java/org/springframework/security/remoting/dns/DnsLookupException.java @@ -19,21 +19,22 @@ package org.springframework.security.remoting.dns; import org.springframework.dao.DataAccessException; /** - * This will be thrown for unknown DNS errors + * This will be thrown for unknown DNS errors. + * * @author Mike Wiesner * @since 3.0 * @version $Id$ */ public class DnsLookupException extends DataAccessException { - private static final long serialVersionUID = -7538424279394361310L; + private static final long serialVersionUID = -7538424279394361310L; - public DnsLookupException(String msg, Throwable cause) { - super(msg, cause); - } + public DnsLookupException(String msg, Throwable cause) { + super(msg, cause); + } - public DnsLookupException(String msg) { - super(msg); - } + public DnsLookupException(String msg) { + super(msg); + } } diff --git a/core/src/main/java/org/springframework/security/remoting/dns/DnsResolver.java b/core/src/main/java/org/springframework/security/remoting/dns/DnsResolver.java index 1903f63cb2..1184182c20 100644 --- a/core/src/main/java/org/springframework/security/remoting/dns/DnsResolver.java +++ b/core/src/main/java/org/springframework/security/remoting/dns/DnsResolver.java @@ -17,57 +17,58 @@ package org.springframework.security.remoting.dns; /** - * Helper class for DNS operations - * + * Helper class for DNS operations. + * * @author Mike Wiesner * @since 3.0 * @version $Id$ */ public interface DnsResolver { - /** - * Resolves the IP Address (A record) to the specified host name. - * Throws DnsEntryNotFoundException if there is no record. - * @param hostname The hostname for which you need the IP Address - * @return IP Address as a String - * @throws DnsEntryNotFoundException No record found - * @throws DnsLookupException Unknown DNS error - */ - public String resolveIpAddress(String hostname) throws DnsEntryNotFoundException, DnsLookupException; + /** + * Resolves the IP Address (A record) to the specified host name. + * Throws DnsEntryNotFoundException if there is no record. + * + * @param hostname The hostname for which you need the IP Address + * @return IP Address as a String + * @throws DnsEntryNotFoundException No record found + * @throws DnsLookupException Unknown DNS error + */ + public String resolveIpAddress(String hostname) throws DnsEntryNotFoundException, DnsLookupException; - /** - *

Resolves the host name for the specified service in the specified domain

- *

For example, if you need the host name for an LDAP server running in the - * domain springsource.com, you would call resolveServiceEntry("ldap", "springsource.com").

- * - *

The DNS server needs to provide the service records for this, in the example above, it - * would look like this: - * - *

_ldap._tcp.springsource.com IN SRV 10 0 88 ldap.springsource.com.
- * - * The method will return the record with highest priority (which means the lowest number in the DNS record) - * and if there are more than one records with the same priority, it will return the one with the highest weight. - * You will find more informatione about DNS service records at Wikipedia.

- * - * @param serviceType The service type you are searching for, e.g. ldap, kerberos, ... - * @param domain The domain, in which you are searching for the service - * @return The hostname of the service - * @throws DnsEntryNotFoundException No record found - * @throws DnsLookupException Unknown DNS error - */ - public String resolveServiceEntry(String serviceType, String domain) throws DnsEntryNotFoundException, DnsLookupException; + /** + *

Resolves the host name for the specified service in the specified domain

+ *

For example, if you need the host name for an LDAP server running in the + * domain springsource.com, you would call resolveServiceEntry("ldap", "springsource.com").

+ * + *

The DNS server needs to provide the service records for this, in the example above, it + * would look like this: + * + *

_ldap._tcp.springsource.com IN SRV 10 0 88 ldap.springsource.com.
+ * + * The method will return the record with highest priority (which means the lowest number in the DNS record) + * and if there are more than one records with the same priority, it will return the one with the highest weight. + * You will find more informatione about DNS service records at Wikipedia.

+ * + * @param serviceType The service type you are searching for, e.g. ldap, kerberos, ... + * @param domain The domain, in which you are searching for the service + * @return The hostname of the service + * @throws DnsEntryNotFoundException No record found + * @throws DnsLookupException Unknown DNS error + */ + public String resolveServiceEntry(String serviceType, String domain) throws DnsEntryNotFoundException, DnsLookupException; - /** - * Resolves the host name for the specified service and then the IP Address for this host in one call. - * - * @param serviceType The service type you are searching for, e.g. ldap, kerberos, ... - * @param domain The domain, in which you are searching for the service - * @return IP Address of the service - * @throws DnsEntryNotFoundException No record found - * @throws DnsLookupException Unknown DNS error - * @see #resolveServiceEntry(String, String) - * @see #resolveIpAddress(String) - */ - public String resolveServiceIpAddress(String serviceType, String domain) throws DnsEntryNotFoundException, DnsLookupException; + /** + * Resolves the host name for the specified service and then the IP Address for this host in one call. + * + * @param serviceType The service type you are searching for, e.g. ldap, kerberos, ... + * @param domain The domain, in which you are searching for the service + * @return IP Address of the service + * @throws DnsEntryNotFoundException No record found + * @throws DnsLookupException Unknown DNS error + * @see #resolveServiceEntry(String, String) + * @see #resolveIpAddress(String) + */ + public String resolveServiceIpAddress(String serviceType, String domain) throws DnsEntryNotFoundException, DnsLookupException; -} \ No newline at end of file +} diff --git a/core/src/main/java/org/springframework/security/remoting/dns/InitialContextFactory.java b/core/src/main/java/org/springframework/security/remoting/dns/InitialContextFactory.java index d1d99dc8de..2587a9f947 100644 --- a/core/src/main/java/org/springframework/security/remoting/dns/InitialContextFactory.java +++ b/core/src/main/java/org/springframework/security/remoting/dns/InitialContextFactory.java @@ -22,7 +22,7 @@ import javax.naming.directory.InitialDirContext; /** * This is used in JndiDnsResolver to get an InitialDirContext for DNS queries. - * + * * @author Mike Wiesner * @since 3.0 * @version $Id$ @@ -32,11 +32,11 @@ import javax.naming.directory.InitialDirContext; */ public interface InitialContextFactory { - - /** - * Must return a DirContext which can be used for DNS queries - * @return JNDI DirContext - */ - public DirContext getCtx(); + + /** + * Must return a DirContext which can be used for DNS queries + * @return JNDI DirContext + */ + public DirContext getCtx(); } diff --git a/core/src/main/java/org/springframework/security/remoting/dns/JndiDnsResolver.java b/core/src/main/java/org/springframework/security/remoting/dns/JndiDnsResolver.java index b1171c5d64..af85bc7c76 100644 --- a/core/src/main/java/org/springframework/security/remoting/dns/JndiDnsResolver.java +++ b/core/src/main/java/org/springframework/security/remoting/dns/JndiDnsResolver.java @@ -30,10 +30,10 @@ import javax.naming.directory.InitialDirContext; /** * Implementation of DnsResolver which uses JNDI for the DNS queries. - * + * * Uses an InitialContextFactory to get the JNDI DirContext. The default implementation * will just create a new Context with the context factory com.sun.jndi.dns.DnsContextFactory - * + * * @author Mike Wiesner * @since 3.0 * @version $Id$ @@ -41,133 +41,129 @@ import javax.naming.directory.InitialDirContext; * @see InitialContextFactory */ public class JndiDnsResolver implements DnsResolver { - - private InitialContextFactory ctxFactory = new DefaultInitialContextFactory(); - /** - * Allows to inject an own JNDI context factory. - * - * @param ctxFactory factory to use, when a DirContext is needed - * @see InitialDirContext - * @see DirContext - */ - public void setCtxFactory(InitialContextFactory ctxFactory) { - this.ctxFactory = ctxFactory; - } + private InitialContextFactory ctxFactory = new DefaultInitialContextFactory(); - /* (non-Javadoc) - * @see org.springframework.security.remoting.dns.DnsResolver#resolveIpAddress(java.lang.String) - */ - public String resolveIpAddress(String hostname) { - return resolveIpAddress(hostname, ctxFactory.getCtx()); - } - - /* (non-Javadoc) - * @see org.springframework.security.remoting.dns.DnsResolver#resolveServiceEntry(java.lang.String, java.lang.String) - */ - public String resolveServiceEntry(String serviceType, String domain) { - return resolveServiceEntry(serviceType, domain, ctxFactory.getCtx()); - } - - /* (non-Javadoc) - * @see org.springframework.security.remoting.dns.DnsResolver#resolveServiceIpAddress(java.lang.String, java.lang.String) - */ - public String resolveServiceIpAddress(String serviceType, String domain) { - DirContext ctx = ctxFactory.getCtx(); - String hostname = resolveServiceEntry(serviceType, domain, ctx); - return resolveIpAddress(hostname, ctx); - } - - + /** + * Allows to inject an own JNDI context factory. + * + * @param ctxFactory factory to use, when a DirContext is needed + * @see InitialDirContext + * @see DirContext + */ + public void setCtxFactory(InitialContextFactory ctxFactory) { + this.ctxFactory = ctxFactory; + } - // This method is needed, so that we can use only one DirContext for - // resolveServiceIpAddress(). - private String resolveIpAddress(String hostname, DirContext ctx) { - try { - Attribute dnsRecord = lookup(hostname, ctx, "A"); - // There should be only one A record, therefore it is save to return - // only the first. - return dnsRecord.get().toString(); - } catch (NamingException e) { - throw new DnsLookupException("DNS lookup failed for: "+ hostname, e); - } + /* (non-Javadoc) + * @see org.springframework.security.remoting.dns.DnsResolver#resolveIpAddress(java.lang.String) + */ + public String resolveIpAddress(String hostname) { + return resolveIpAddress(hostname, ctxFactory.getCtx()); + } - } + /* (non-Javadoc) + * @see org.springframework.security.remoting.dns.DnsResolver#resolveServiceEntry(java.lang.String, java.lang.String) + */ + public String resolveServiceEntry(String serviceType, String domain) { + return resolveServiceEntry(serviceType, domain, ctxFactory.getCtx()); + } - // This method is needed, so that we can use only one DirContext for - // resolveServiceIpAddress(). - private String resolveServiceEntry(String serviceType, String domain, DirContext ctx) { - String result = null; - try { - String query = new StringBuilder("_").append(serviceType).append("._tcp.").append(domain).toString(); - Attribute dnsRecord = lookup(query, ctx, "SRV"); - // There are maybe more records defined, we will return the one - // with the highest priority (lowest number) and the highest weight - // (highest number) - int highestPriority = -1; - int highestWeight = -1; - - for (NamingEnumeration recordEnum = dnsRecord.getAll(); recordEnum.hasMoreElements();) { - String[] record = recordEnum.next().toString().split(" "); - if (record.length != 4) { - throw new DnsLookupException("Wrong service record for query " + query + ": [" + record + "]"); - } - int priority = Integer.parseInt(record[0]); - int weight = Integer.parseInt(record[1]); - // we have a new highest Priority, so forget also the highest weight - if (priority < highestPriority || highestPriority == -1) { - highestPriority = priority; - highestWeight = weight; - result = record[3].trim(); - } - // same priority, but higher weight - if (priority == highestPriority && weight > highestWeight) { - highestWeight = weight; - result = record[3].trim(); - } - } - } catch (NamingException e) { - throw new DnsLookupException("DNS lookup failed for service " + serviceType + " at " + domain, e); - } - - // remove the "." at the end - if (result.endsWith(".")) { - result = result.substring(0, result.length() - 1); - } - return result; - } - - private Attribute lookup(String query, DirContext ictx, String recordType) { - try { - Attributes dnsResult = ictx.getAttributes(query, new String[] { recordType }); - Attribute dnsRecord = dnsResult.get(recordType); - return dnsRecord; - } catch (NamingException e) { - if (e instanceof NameNotFoundException) { - throw new DnsEntryNotFoundException("DNS entry not found for:" + query, e); - } - throw new DnsLookupException("DNS lookup failed for: " + query, e); - } - } - - - - private static class DefaultInitialContextFactory implements InitialContextFactory { - - public DirContext getCtx() { - Hashtable env = new Hashtable(); - env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory"); - env.put(Context.PROVIDER_URL, "dns:"); // This is needed for IBM JDK/JRE - InitialDirContext ictx; - try { - ictx = new InitialDirContext(env); - } catch (NamingException e) { - throw new DnsLookupException("Cannot create InitialDirContext for DNS lookup", e); - } - return ictx; - } - } + /* (non-Javadoc) + * @see org.springframework.security.remoting.dns.DnsResolver#resolveServiceIpAddress(java.lang.String, java.lang.String) + */ + public String resolveServiceIpAddress(String serviceType, String domain) { + DirContext ctx = ctxFactory.getCtx(); + String hostname = resolveServiceEntry(serviceType, domain, ctx); + return resolveIpAddress(hostname, ctx); + } + // This method is needed, so that we can use only one DirContext for + // resolveServiceIpAddress(). + private String resolveIpAddress(String hostname, DirContext ctx) { + try { + Attribute dnsRecord = lookup(hostname, ctx, "A"); + // There should be only one A record, therefore it is save to return + // only the first. + return dnsRecord.get().toString(); + } catch (NamingException e) { + throw new DnsLookupException("DNS lookup failed for: "+ hostname, e); + } + + } + + // This method is needed, so that we can use only one DirContext for + // resolveServiceIpAddress(). + private String resolveServiceEntry(String serviceType, String domain, DirContext ctx) { + String result = null; + try { + String query = new StringBuilder("_").append(serviceType).append("._tcp.").append(domain).toString(); + Attribute dnsRecord = lookup(query, ctx, "SRV"); + // There are maybe more records defined, we will return the one + // with the highest priority (lowest number) and the highest weight + // (highest number) + int highestPriority = -1; + int highestWeight = -1; + + for (NamingEnumeration recordEnum = dnsRecord.getAll(); recordEnum.hasMoreElements();) { + String[] record = recordEnum.next().toString().split(" "); + if (record.length != 4) { + throw new DnsLookupException("Wrong service record for query " + query + ": [" + record + "]"); + } + int priority = Integer.parseInt(record[0]); + int weight = Integer.parseInt(record[1]); + // we have a new highest Priority, so forget also the highest weight + if (priority < highestPriority || highestPriority == -1) { + highestPriority = priority; + highestWeight = weight; + result = record[3].trim(); + } + // same priority, but higher weight + if (priority == highestPriority && weight > highestWeight) { + highestWeight = weight; + result = record[3].trim(); + } + } + } catch (NamingException e) { + throw new DnsLookupException("DNS lookup failed for service " + serviceType + " at " + domain, e); + } + + // remove the "." at the end + if (result.endsWith(".")) { + result = result.substring(0, result.length() - 1); + } + return result; + } + + private Attribute lookup(String query, DirContext ictx, String recordType) { + try { + Attributes dnsResult = ictx.getAttributes(query, new String[] { recordType }); + Attribute dnsRecord = dnsResult.get(recordType); + return dnsRecord; + } catch (NamingException e) { + if (e instanceof NameNotFoundException) { + throw new DnsEntryNotFoundException("DNS entry not found for:" + query, e); + } + throw new DnsLookupException("DNS lookup failed for: " + query, e); + } + } + + + private static class DefaultInitialContextFactory implements InitialContextFactory { + + public DirContext getCtx() { + Hashtable env = new Hashtable(); + env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory"); + env.put(Context.PROVIDER_URL, "dns:"); // This is needed for IBM JDK/JRE + InitialDirContext ictx; + try { + ictx = new InitialDirContext(env); + } catch (NamingException e) { + throw new DnsLookupException("Cannot create InitialDirContext for DNS lookup", e); + } + return ictx; + } + } }