/* * Copyright 2012 The Netty Project * * The Netty Project licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package org.jboss.netty.handler.ipfilter; import org.jboss.netty.logging.InternalLogger; import org.jboss.netty.logging.InternalLoggerFactory; import org.jboss.netty.util.internal.StringUtil; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.regex.Pattern; /** * The Class PatternRule represents an IP filter rule using string patterns. * <br> * Rule Syntax: * <br> * <pre> * Rule ::= [n|i]:address n stands for computer name, i for ip address * address ::= <regex> | localhost * regex is a regular expression with '*' as multi character and '?' as single character wild card * </pre> * <br> * Example: allow localhost: * <br> * new PatternRule(true, "n:localhost") * <br> * Example: allow local lan: * <br> * new PatternRule(true, "i:192.168.0.*") * <br> * Example: block all * <br> * new PatternRule(false, "n:*") * <br> */ public class PatternRule implements IpFilterRule, Comparable<Object> { private static final InternalLogger logger = InternalLoggerFactory.getInstance(PatternRule.class); private Pattern ipPattern; private Pattern namePattern; private boolean isAllowRule = true; private boolean localhost; private final String pattern; /** * Instantiates a new pattern rule. * * @param allow indicates if this is an allow or block rule * @param pattern the filter pattern */ public PatternRule(boolean allow, String pattern) { isAllowRule = allow; this.pattern = pattern; parse(pattern); } /** * returns the pattern. * * @return the pattern */ public String getPattern() { return pattern; } public boolean isAllowRule() { return isAllowRule; } public boolean isDenyRule() { return !isAllowRule; } public boolean contains(InetAddress inetAddress) { if (localhost) { if (isLocalhost(inetAddress)) { return true; } } if (ipPattern != null) { if (ipPattern.matcher(inetAddress.getHostAddress()).matches()) { return true; } } if (namePattern != null) { if (namePattern.matcher(inetAddress.getHostName()).matches()) { return true; } } return false; } private void parse(String pattern) { if (pattern == null) { return; } String[] acls = StringUtil.split(pattern, ','); String ip = ""; String name = ""; for (String c : acls) { c = c.trim(); if ("n:localhost".equals(c)) { localhost = true; } else if (c.startsWith("n:")) { name = addRule(name, c.substring(2)); } else if (c.startsWith("i:")) { ip = addRule(ip, c.substring(2)); } } if (ip.length() != 0) { ipPattern = Pattern.compile(ip); } if (name.length() != 0) { namePattern = Pattern.compile(name); } } private static String addRule(String pattern, String rule) { if (rule == null || rule.length() == 0) { return pattern; } if (pattern.length() != 0) { pattern += "|"; } rule = rule.replaceAll("\\.", "\\\\."); rule = rule.replaceAll("\\*", ".*"); rule = rule.replaceAll("\\?", "."); pattern += '(' + rule + ')'; return pattern; } private static boolean isLocalhost(InetAddress address) { try { if (address.equals(InetAddress.getLocalHost())) { return true; } } catch (UnknownHostException e) { if (logger.isInfoEnabled()) { logger.info("error getting ip of localhost", e); } } try { InetAddress[] addrs = InetAddress.getAllByName("127.0.0.1"); for (InetAddress addr : addrs) { if (addr.equals(address)) { return true; } } } catch (UnknownHostException e) { if (logger.isInfoEnabled()) { logger.info("error getting ip of localhost", e); } } return false; } public int compareTo(Object o) { if (o == null) { return -1; } if (!(o instanceof PatternRule)) { return -1; } PatternRule p = (PatternRule) o; if (p.isAllowRule() && !isAllowRule) { return -1; } if (pattern == null && p.pattern == null) { return 0; } if (pattern != null) { return pattern.compareTo(p.getPattern()); } return -1; } }