/* * Copyright (C) 2009 Camptocamp * * This file is part of MapFish Server * * MapFish Server is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MapFish Server is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with MapFish Server. If not, see <http://www.gnu.org/licenses/>. */ package org.mapfish.print.config; import org.apache.log4j.Logger; import java.net.*; import java.util.Arrays; /** * Allows to check that a given URL matches an IP address (numeric format) */ public abstract class InetHostMatcher extends HostMatcher { public static final Logger LOGGER = Logger.getLogger(InetHostMatcher.class); protected byte[][] authorizedIPs = null; public boolean validate(URI uri) throws UnknownHostException, SocketException, MalformedURLException { final InetAddress maskAddress = getMaskAddress(); final InetAddress[] requestedIPs; try { requestedIPs = InetAddress.getAllByName(uri.getHost()); } catch (UnknownHostException ex) { return false; } boolean oneMatching = false; for (int i = 0; i < requestedIPs.length; ++i) { InetAddress requestedIP = requestedIPs[i]; if (isInAuthorized(requestedIP, maskAddress)) { oneMatching = true; break; } } return oneMatching && super.validate(uri); } private boolean isInAuthorized(InetAddress requestedIP, InetAddress mask) throws UnknownHostException, SocketException { byte[] rBytes = mask(requestedIP, mask); final byte[][] authorizedIPs = getAuthorizedIPs(mask); for (int i = 0; i < authorizedIPs.length; ++i) { byte[] authorizedIP = authorizedIPs[i]; if (compareIP(rBytes, authorizedIP)) { return true; } } LOGGER.debug("Address not in the authorizeds: " + requestedIP); return false; } private boolean compareIP(byte[] rBytes, byte[] authorizedIP) { if (rBytes.length != authorizedIP.length) { return false; } for (int j = 0; j < authorizedIP.length; ++j) { byte bA = authorizedIP[j]; byte bR = rBytes[j]; if (bA != bR) { return false; } } return true; } private byte[] mask(InetAddress address, InetAddress mask) { byte[] aBytes = address.getAddress(); if (mask != null) { byte[] mBytes = mask.getAddress(); if (aBytes.length != mBytes.length) { LOGGER.warn("Cannot mask address [" + address + "] with :" + mask); return aBytes; } else { final byte[] result = new byte[aBytes.length]; for (int i = 0; i < result.length; ++i) { result[i] = (byte) (aBytes[i] & mBytes[i]); } return result; } } else { return aBytes; } } protected abstract InetAddress getMaskAddress() throws UnknownHostException; protected void buildMaskedAuthorizedIPs(InetAddress[] ips) throws UnknownHostException { final InetAddress maskAddress = getMaskAddress(); authorizedIPs = new byte[ips.length][]; for (int i = 0; i < ips.length; ++i) { authorizedIPs[i] = mask(ips[i], maskAddress); } } protected abstract byte[][] getAuthorizedIPs(InetAddress mask) throws UnknownHostException, SocketException; @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + Arrays.hashCode(authorizedIPs); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; InetHostMatcher other = (InetHostMatcher) obj; if (!Arrays.equals(authorizedIPs, other.authorizedIPs)) return false; return true; } }