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 java.net.InetAddress;
20  import java.net.UnknownHostException;
21  import java.util.regex.Pattern;
22  
23  import org.jboss.netty.logging.InternalLogger;
24  import org.jboss.netty.logging.InternalLoggerFactory;
25  
26  /**
27   * The Class PatternRule represents an IP filter rule using string patterns.
28   * <br>
29   * Rule Syntax:
30   * <br>
31   * <pre>
32   * Rule ::= [n|i]:address          n stands for computer name, i for ip address
33   * address ::= &lt;regex&gt; | localhost
34   * regex is a regular expression with '*' as multi character and '?' as single character wild card
35   * </pre>
36   * <br>
37   * Example: allow localhost:
38   * <br>
39   * new PatternRule(true, "n:localhost")
40   * <br>
41   * Example: allow local lan:
42   * <br>
43   * new PatternRule(true, "i:192.168.0.*")
44   * <br>
45   * Example: block all
46   * <br>
47   * new PatternRule(false, "n:*")
48   * <br>
49   */
50  public class PatternRule implements IpFilterRule, Comparable<Object> {
51      private static final InternalLogger logger = InternalLoggerFactory.getInstance(PatternRule.class);
52  
53      private Pattern ipPattern;
54  
55      private Pattern namePattern;
56  
57      private boolean isAllowRule = true;
58  
59      private boolean localhost;
60  
61      private final String pattern;
62  
63      /**
64       * Instantiates a new pattern rule.
65       *
66       * @param allow   indicates if this is an allow or block rule
67       * @param pattern the filter pattern
68       */
69      public PatternRule(boolean allow, String pattern) {
70          isAllowRule = allow;
71          this.pattern = pattern;
72          parse(pattern);
73      }
74  
75      /**
76       * returns the pattern.
77       *
78       * @return the pattern
79       */
80      public String getPattern() {
81          return pattern;
82      }
83  
84      public boolean isAllowRule() {
85          return isAllowRule;
86      }
87  
88      public boolean isDenyRule() {
89          return !isAllowRule;
90      }
91  
92      public boolean contains(InetAddress inetAddress) {
93          if (localhost) {
94              if (isLocalhost(inetAddress)) {
95                  return true;
96              }
97          }
98          if (ipPattern != null) {
99              if (ipPattern.matcher(inetAddress.getHostAddress()).matches()) {
100                 return true;
101             }
102         }
103         if (namePattern != null) {
104             if (namePattern.matcher(inetAddress.getHostName()).matches()) {
105                 return true;
106             }
107         }
108         return false;
109     }
110 
111     private void parse(String pattern) {
112         if (pattern == null) {
113             return;
114         }
115 
116         String[] acls = pattern.split(",");
117 
118         String ip = "";
119         String name = "";
120         for (String c : acls) {
121             c = c.trim();
122             if (c.equals("n:localhost")) {
123                 localhost = true;
124             } else if (c.startsWith("n:")) {
125                 name = addRule(name, c.substring(2));
126             } else if (c.startsWith("i:")) {
127                 ip = addRule(ip, c.substring(2));
128             }
129         }
130         if (ip.length() != 0) {
131             ipPattern = Pattern.compile(ip);
132         }
133         if (name.length() != 0) {
134             namePattern = Pattern.compile(name);
135         }
136     }
137 
138     private static String addRule(String pattern, String rule) {
139         if (rule == null || rule.length() == 0) {
140             return pattern;
141         }
142         if (pattern.length() != 0) {
143             pattern += "|";
144         }
145         rule = rule.replaceAll("\\.", "\\\\.");
146         rule = rule.replaceAll("\\*", ".*");
147         rule = rule.replaceAll("\\?", ".");
148         pattern += "(" + rule + ")";
149         return pattern;
150     }
151 
152     private static boolean isLocalhost(InetAddress address) {
153         try {
154             if (address.equals(InetAddress.getLocalHost())) {
155                 return true;
156             }
157         } catch (UnknownHostException e) {
158             if (logger.isInfoEnabled()) {
159                 logger.info("error getting ip of localhost", e);
160             }
161         }
162         try {
163             InetAddress[] addrs = InetAddress.getAllByName("127.0.0.1");
164             for (InetAddress addr : addrs) {
165                 if (addr.equals(address)) {
166                     return true;
167                 }
168             }
169         } catch (UnknownHostException e) {
170             if (logger.isInfoEnabled()) {
171                 logger.info("error getting ip of localhost", e);
172             }
173         }
174         return false;
175 
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 }