ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/experimental/server/ACL/ACL.java
Revision: 1.8
Committed: Mon Dec 31 02:57:00 2001 UTC (22 years, 4 months ago) by tdb
Branch: MAIN
Changes since 1.7: +1 -0 lines
Log Message:
Added an ACLDatagramSocket. Operation is much the same as the
ACLServerSocket. Also tweaked the toString() to keep the i-scream bits as
well as the more useful stuff.

File Contents

# Content
1 //---PACKAGE DECLARATION---
2 //package uk.org.iscream.cms.server.util;
3
4 //---IMPORTS---
5 import uk.org.iscream.cms.server.util.*;
6 import java.util.ArrayList;
7 import java.util.StringTokenizer;
8 import java.net.InetAddress;
9 import java.io.Serializable;
10
11 /**
12 * Access Control List for use primarily
13 * with the ACLServerSocket. It could, however
14 * have other uses as it has a fairly generic
15 * behaviour. Rules are added using the add
16 * method, and then checks can be made using
17 * the relevant check method.
18 *
19 * @author $Author: tdb $
20 * @version $Id: ACL.java,v 1.5 2001/12/23 01:05:35 tdb Exp $
21 */
22 public class ACL implements Serializable {
23
24 //---FINAL ATTRIBUTES---
25
26 /**
27 * The current CVS revision of this class
28 */
29 public static final String REVISION = "$Revision: 1.5 $";
30
31 /**
32 * static to be used when adding an ALLOW rule to the ACL.
33 */
34 public static final boolean ALLOW = true;
35
36 /**
37 * static to be used when adding a DENY rule to the ACL.
38 */
39 public static final boolean DENY = false;
40
41 //---STATIC METHODS---
42
43 //---CONSTRUCTORS---
44
45 /**
46 * Construct a new Access Control List. The default
47 * mode is to ALLOW anything that isn't explicitly
48 * blocked by a rule.
49 */
50 public ACL() {
51 // default to ACL.ALLOW
52 this(ACL.ALLOW);
53 }
54
55 /**
56 * Construct a new Access Control List with a given
57 * default mode. This mode specifies what should
58 * happen if a check does not match any rules.
59 *
60 * @param defaultMode the default mode for non-matched checks
61 */
62 public ACL(boolean defaultMode) {
63 _defaultMode = defaultMode;
64 }
65
66 //---PUBLIC METHODS---
67
68 /**
69 * Add a new rule to the ACL immediately after the
70 * previous rule. The rule can either be an ACL.ALLOW
71 * rule, or an ACL.DENY rule. The expression can
72 * contain a wildcard (a * only). Rules can only be
73 * added to the end of the list.
74 *
75 * param allow whether this is an ALLOW or DENY rule
76 * param expression what this rule matches using wildcards
77 */
78 public void add(boolean allow, String expression) {
79 // default to expecting it to be an IP
80 // we will try to disprove this :)
81 boolean ip = true;
82 short[] ipaddr = {-1, -1, -1, -1};
83 int i = 0;
84 String s = "";
85 // tokenize the expression on fullstops, so we can break
86 // up the quads of an IP (if it's an IP!)
87 StringTokenizer st = new StringTokenizer(expression, ".");
88 while(st.hasMoreTokens() && i++ < 4) {
89 s = st.nextToken();
90 // if it's a wildcard, we'll skip to the next one
91 // as no more checks are required
92 if(s.equals("*")) {
93 continue;
94 }
95 // attempt to parse it into a short
96 try {
97 short n = Short.parseShort(s);
98 // if it's an int but outside of the
99 // valid range, it can't be an IP
100 if(n < 0 || n > 255) {
101 ip = false;
102 // give up checking further
103 break;
104 }
105 ipaddr[i-1] = n;
106 }
107 // if it didn't parse as an int it can't be an IP
108 catch (NumberFormatException e) {
109 ip = false;
110 // give up checking further
111 break;
112 }
113 }
114 // we've done 4 parts, so if there's any
115 // more this can't be an IP
116 if(st.hasMoreTokens()) {
117 ip = false;
118 }
119 // if we've done less than 4, see if the last one
120 // was a wildcard - if it isn't then it's not an IP
121 // -- this allows 129.12.*
122 if(i < 4 && !s.equals("*")) {
123 ip = false;
124 }
125 // if we had one or less entries it can't be an IP
126 // -- this disallows * matching as an IP due
127 // to the rule above
128 if(i <= 1) {
129 ip = false;
130 }
131 // finally print out what we've found.
132 System.out.println("IP("+ip+"): "+expression);
133 if(ip) {
134 for(int j=0; j < ipaddr.length; j++) {
135 System.out.print(ipaddr[j] + " ");
136 }
137 System.out.println();
138 }
139 _acl.add(new ACLRule(allow, expression, ipaddr, ip));
140 }
141
142 /**
143 * Check to see if a string is permitted by the
144 * ACL. Useful for testing, and non-Socket uses
145 * of this class.
146 *
147 * @param address the string to check
148 * @return whether the address was permitted by the ACL
149 */
150 public boolean check(String address) {
151 for(int i=0; i < _acl.size(); i++) {
152 ACLRule rule = (ACLRule) _acl.get(i);
153 if(StringUtils.wildcardCheck(address, rule._expression)) {
154 return rule._allow;
155 }
156 }
157 return _defaultMode;
158 }
159
160 /**
161 * Check to see if an InetAddress is permitted
162 * by the ACL. Perfect for Socket uses of this
163 * class. It should be made clear that this will
164 * check both the hostname AND IP address against
165 * each rule in turn. The hostname will always be
166 * checked BEFORE the IP address.
167 *
168 * @param address the InetAddress to check
169 * @return whether the InetAddress was permitted by the ACL
170 */
171 public boolean check(InetAddress address) {
172 String hostname = address.getHostName();
173 String ip = address.getHostAddress();
174 short[] ipaddr = ipStringToShort(ip);
175 for(int i=0; i < _acl.size(); i++) {
176 ACLRule rule = (ACLRule) _acl.get(i);
177 if(rule._iprule) {
178 System.out.println("checking ip rule "+rule._expression);
179 //if(StringUtils.wildcardCheck(ip, rule._expression)) {
180 if(compareShorts(ipaddr, rule._ipaddr)) {
181 return rule._allow;
182 }
183 }
184 else {
185 System.out.println("checking name rule: "+rule._expression);
186 if(StringUtils.wildcardCheck(hostname, rule._expression)) {
187 return rule._allow;
188 }
189 }
190
191 }
192 return _defaultMode;
193 }
194
195 /**
196 * Gives a String representation of this ACL.
197 *
198 * @return A String representation of this ACL.
199 */
200 public String toString() {
201 StringBuffer acl = new StringBuffer();
202 acl.append(FormatName.getName(_name, getClass().getName(), REVISION));
203 acl.append("{");
204 for(int i=0; i < _acl.size(); i++) {
205 acl.append((ACLRule) _acl.get(i));
206 acl.append(",");
207 }
208 if(_defaultMode) {
209 acl.append("DEFAULT=ALLOW");
210 }
211 else {
212 acl.append("DEFAULT=DENY");
213 }
214 acl.append("}");
215 return acl.toString();
216 }
217
218 //---PRIVATE METHODS---
219
220 private short[] ipStringToShort(String ip) {
221 short[] ipaddr = {-1, -1, -1, -1};
222 StringTokenizer st = new StringTokenizer(ip, ".");
223 for(int i=0; i < 4 && st.hasMoreTokens(); i++) {
224 try {
225 ipaddr[i] = Short.parseShort(st.nextToken());
226 }
227 catch(NumberFormatException e) {
228 // do nothing?
229 }
230 }
231 return ipaddr;
232 }
233
234 private boolean compareShorts(short[] first, short[] second) {
235 if(first.length != second.length) {
236 System.out.println("not equal length");
237 return false;
238 }
239 for(int i=0; i < first.length; i++) {
240 // -- might want to consider specify which is the wildcard one?
241 System.out.println(i + ":" + first[i] + "," + second[i]);
242 if(first[i] == -1 || second[i] == -1) {
243 continue;
244 }
245 if(first[i] != second[i]) {
246 System.out.println("not equal");
247 return false;
248 }
249 }
250 System.out.println("equal");
251 return true;
252 }
253
254 //---ACCESSOR/MUTATOR METHODS---
255
256 //---ATTRIBUTES---
257
258 /**
259 * This is the friendly identifier of the
260 * component this class is running in.
261 * eg, a Filter may be called "filter1",
262 * If this class does not have an owning
263 * component, a name from the configuration
264 * can be placed here. This name could also
265 * be changed to null for utility classes.
266 */
267 private String _name = null;
268
269 /**
270 * The ACL is stored in this ArrayList.
271 */
272 private ArrayList _acl = new ArrayList();
273
274 /**
275 * The default mode of this ACL.
276 */
277 private boolean _defaultMode;
278
279 //---STATIC ATTRIBUTES---
280
281 //---INNER CLASSES---
282
283 /**
284 * Wrapper class for an ACL rule.
285 */
286 private class ACLRule implements Serializable {
287
288 /**
289 * Construct an ACL rule.
290 *
291 * @param allow whether this is an ALLOW or DENY rule
292 * @param expression what this rule matches
293 * @param iprule whether this is an IP rule
294 */
295 private ACLRule(boolean allow, String expression, short[] ipaddr, boolean iprule) {
296 _allow = allow;
297 _expression = expression;
298 _ipaddr = ipaddr;
299 _iprule = iprule;
300 }
301
302 /**
303 * Returns a String representation of this rule.
304 *
305 * @return A String representation of this rule.
306 */
307 public String toString() {
308 if(_allow) {
309 return _expression + "=ALLOW";
310 }
311 else {
312 return _expression + "=DENY";
313 }
314 }
315
316 /**
317 * Whether this is an ALLOW or DENY rule.
318 */
319 private boolean _allow;
320
321 /**
322 * What this rule matches.
323 */
324 private String _expression;
325
326 private short[] _ipaddr;
327
328 /**
329 * Whether this is an IP rule.
330 */
331 private boolean _iprule;
332
333 }
334
335 }