View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  
17  package org.jboss.netty.handler.ipfilter;
18  
19  import org.jboss.netty.logging.InternalLogger;
20  import org.jboss.netty.logging.InternalLoggerFactory;
21  import org.jboss.netty.util.internal.StringUtil;
22  
23  import java.net.InetAddress;
24  import java.net.UnknownHostException;
25  import java.util.regex.Pattern;
26  
27  /**
28   * The Class PatternRule represents an IP filter rule using string patterns.
29   * <br>
30   * Rule Syntax:
31   * <br>
32   * <pre>
33   * Rule ::= [n|i]:address          n stands for computer name, i for ip address
34   * address ::= &lt;regex&gt; | localhost
35   * regex is a regular expression with '*' as multi character and '?' as single character wild card
36   * </pre>
37   * <br>
38   * Example: allow localhost:
39   * <br>
40   * new PatternRule(true, "n:localhost")
41   * <br>
42   * Example: allow local lan:
43   * <br>
44   * new PatternRule(true, "i:192.168.0.*")
45   * <br>
46   * Example: block all
47   * <br>
48   * new PatternRule(false, "n:*")
49   * <br>
50   */
51  public class PatternRule implements IpFilterRule, Comparable<Object> {
52      private static final InternalLogger logger = InternalLoggerFactory.getInstance(PatternRule.class);
53  
54      private Pattern ipPattern;
55  
56      private Pattern namePattern;
57  
58      private boolean isAllowRule = true;
59  
60      private boolean localhost;
61  
62      private final String pattern;
63  
64      /**
65       * Instantiates a new pattern rule.
66       *
67       * @param allow   indicates if this is an allow or block rule
68       * @param pattern the filter pattern
69       */
70      public PatternRule(boolean allow, String pattern) {
71          isAllowRule = allow;
72          this.pattern = pattern;
73          parse(pattern);
74      }
75  
76      /**
77       * returns the pattern.
78       *
79       * @return the pattern
80       */
81      public String getPattern() {
82          return pattern;
83      }
84  
85      public boolean isAllowRule() {
86          return isAllowRule;
87      }
88  
89      public boolean isDenyRule() {
90          return !isAllowRule;
91      }
92  
93      public boolean contains(InetAddress inetAddress) {
94          if (localhost) {
95              if (isLocalhost(inetAddress)) {
96                  return true;
97              }
98          }
99          if (ipPattern != null) {
100             if (ipPattern.matcher(inetAddress.getHostAddress()).matches()) {
101                 return true;
102             }
103         }
104         if (namePattern != null) {
105             if (namePattern.matcher(inetAddress.getHostName()).matches()) {
106                 return true;
107             }
108         }
109         return false;
110     }
111 
112     private void parse(String pattern) {
113         if (pattern == null) {
114             return;
115         }
116 
117         String[] acls = StringUtil.split(pattern, ',');
118 
119         String ip = "";
120         String name = "";
121         for (String c : acls) {
122             c = c.trim();
123             if ("n:localhost".equals(c)) {
124                 localhost = true;
125             } else if (c.startsWith("n:")) {
126                 name = addRule(name, c.substring(2));
127             } else if (c.startsWith("i:")) {
128                 ip = addRule(ip, c.substring(2));
129             }
130         }
131         if (ip.length() != 0) {
132             ipPattern = Pattern.compile(ip);
133         }
134         if (name.length() != 0) {
135             namePattern = Pattern.compile(name);
136         }
137     }
138 
139     private static String addRule(String pattern, String rule) {
140         if (rule == null || rule.length() == 0) {
141             return pattern;
142         }
143         if (pattern.length() != 0) {
144             pattern += "|";
145         }
146         rule = rule.replaceAll("\\.", "\\\\.");
147         rule = rule.replaceAll("\\*", ".*");
148         rule = rule.replaceAll("\\?", ".");
149         pattern += '(' + rule + ')';
150         return pattern;
151     }
152 
153     private static boolean isLocalhost(InetAddress address) {
154         try {
155             if (address.equals(InetAddress.getLocalHost())) {
156                 return true;
157             }
158         } catch (UnknownHostException e) {
159             if (logger.isInfoEnabled()) {
160                 logger.info("error getting ip of localhost", e);
161             }
162         }
163         try {
164             InetAddress[] addrs = InetAddress.getAllByName("127.0.0.1");
165             for (InetAddress addr : addrs) {
166                 if (addr.equals(address)) {
167                     return true;
168                 }
169             }
170         } catch (UnknownHostException e) {
171             if (logger.isInfoEnabled()) {
172                 logger.info("error getting ip of localhost", e);
173             }
174         }
175         return false;
176     }
177 
178     public int compareTo(Object o) {
179         if (o == null) {
180             return -1;
181         }
182         if (!(o instanceof PatternRule)) {
183             return -1;
184         }
185         PatternRule p = (PatternRule) o;
186         if (p.isAllowRule() && !isAllowRule) {
187             return -1;
188         }
189         if (pattern == null && p.pattern == null) {
190             return 0;
191         }
192         if (pattern != null) {
193             return pattern.compareTo(p.getPattern());
194         }
195         return -1;
196     }
197 
198 }