HostNameOnDemandAddressChecker.java

package com.ziesemer.utils.web.addressFilter.conditions;

import java.net.InetAddress;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Mark A. Ziesemer
 * 	<a href="http://www.ziesemer.com.">&lt;www.ziesemer.com&gt;</a>
 */
public class HostNameOnDemandAddressChecker implements IAddressChecker{
	
	protected static final Logger LOGGER = LoggerFactory.getLogger(HostNameOnDemandAddressChecker.class);
	
	protected IStringMatcher hostName;
	
	public HostNameOnDemandAddressChecker(final IStringMatcher hostName){
		this.hostName = hostName;
	}
	
	public boolean matches(final InetAddress ip, final String hostName) throws Exception{
		// If able to do a direct DNS lookup (have a non-wildcard hostname):
		
		if(this.hostName instanceof StringMatcherExact){
			final String exactHostName = ((StringMatcherExact)this.hostName).getValue();
			for(final InetAddress addr : InetAddress.getAllByName(exactHostName)){
				if(ip.equals(addr)){
					return true;
				}
			}
			return false;
		}
		
		// Otherwise, need to securely resolve IP to hostname to compare to a wildcard hostname:
		
		final String aHost;
		if(!ip.equals(hostName)){
			// Use provided hostname to save a potential DNS lookup.
			aHost = hostName;
		}else{
			aHost = ip.getCanonicalHostName();
		}
		
		// http://en.wikipedia.org./wiki/Forward_Confirmed_reverse_DNS
		boolean forwardMatch = false;
		for(final InetAddress addr : InetAddress.getAllByName(aHost)){
			if(ip.equals(addr)){
				forwardMatch = true;
				if(this.hostName.matches(aHost)){
					return true;
				}
			}
		}
		if(!forwardMatch){
			LOGGER.warn("Problem verifying that IP {} belongs to host name {} to match {} through forward DNS resolution."
					+ "  This will result in a non-match where the result possibly should have been a match."
					+ "  Please check both your forward- and reverse-DNS configurations."
					+ "  Please also note that this may possibily indicate a circumvention attempt.",
				ip, aHost, hostName);
		}
		
		return false;
	}
	
	public IStringMatcher getHostName(){
		return hostName;
	}
	
}