1 package org.eclipse.jetty.policy;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.io.File;
20 import java.io.FileFilter;
21 import java.io.FileInputStream;
22 import java.io.IOException;
23 import java.io.PrintStream;
24 import java.io.PrintWriter;
25 import java.security.AccessControlException;
26 import java.security.CodeSource;
27 import java.security.Permission;
28 import java.security.PermissionCollection;
29 import java.security.Permissions;
30 import java.security.Policy;
31 import java.security.Principal;
32 import java.security.ProtectionDomain;
33 import java.util.ArrayList;
34 import java.util.Enumeration;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.Iterator;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Set;
41
42 import org.eclipse.jetty.policy.loader.DefaultPolicyLoader;
43 import org.eclipse.jetty.util.Scanner;
44 import org.eclipse.jetty.util.log.Log;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public class JettyPolicy extends Policy
66 {
67 private static boolean __DEBUG = false;
68 private static boolean __RELOAD = false;
69
70
71 private final Set<String> _policies;
72
73 private final Set<PolicyBlock> _grants = new HashSet<PolicyBlock>();
74
75 private final Map<Object, PermissionCollection> _cache = new HashMap<Object, PermissionCollection>();
76
77 private final PolicyContext _context = new PolicyContext();
78
79 private Boolean _initialized = false;
80
81 private Scanner _scanner;
82
83 public JettyPolicy(Set<String> policies, Map<String, String> properties)
84 {
85 try
86 {
87 __RELOAD = Boolean.getBoolean("org.eclipse.jetty.policy.RELOAD");
88 __DEBUG = Boolean.getBoolean("org.eclipse.jetty.policy.DEBUG");
89 }
90 catch (AccessControlException ace)
91 {
92 __RELOAD = false;
93 __DEBUG = false;
94 }
95
96 _policies = resolvePolicyFiles(policies);
97 _context.setProperties(properties);
98 }
99
100 @Override
101 public PermissionCollection getPermissions(ProtectionDomain domain)
102 {
103
104 synchronized (_initialized)
105 {
106 if (!_initialized)
107 {
108 refresh();
109 }
110 }
111
112 synchronized (_cache)
113 {
114 if (_cache.containsKey(domain))
115 {
116 return copyOf(_cache.get(domain));
117 }
118
119 PermissionCollection perms = new Permissions();
120
121 for (Iterator<PolicyBlock> i = _grants.iterator(); i.hasNext();)
122 {
123 PolicyBlock policyBlock = i.next();
124 ProtectionDomain grantPD = policyBlock.toProtectionDomain();
125
126 if (__DEBUG)
127 {
128 debug("----START----");
129 debug("PDCS: " + policyBlock.getCodeSource());
130 debug("CS: " + domain.getCodeSource());
131 }
132
133
134
135
136 if (grantPD.getCodeSource() == null
137 ||
138 grantPD.getCodeSource().implies(domain.getCodeSource())
139 &&
140 grantPD.getPrincipals() == null
141 ||
142 grantPD.getCodeSource().implies(domain.getCodeSource())
143 &&
144 validate(grantPD.getPrincipals(),domain.getPrincipals()))
145 {
146
147 for (Enumeration<Permission> e = policyBlock.getPermissions().elements(); e.hasMoreElements();)
148 {
149 Permission perm = e.nextElement();
150 if (__DEBUG)
151 {
152 debug("D: " + perm);
153 }
154 perms.add(perm);
155 }
156 }
157 if (__DEBUG)
158 {
159 debug("----STOP----");
160 }
161 }
162
163 _cache.put(domain,perms);
164
165 return copyOf(perms);
166 }
167 }
168
169 @Override
170 public PermissionCollection getPermissions(CodeSource codesource)
171 {
172 synchronized (_initialized)
173 {
174 if (!_initialized)
175 {
176 refresh();
177 }
178 }
179
180 synchronized (_cache)
181 {
182 if (_cache.containsKey(codesource))
183 {
184 return copyOf(_cache.get(codesource));
185 }
186
187 PermissionCollection perms = new Permissions();
188
189 for (Iterator<PolicyBlock> i = _grants.iterator(); i.hasNext();)
190 {
191 PolicyBlock policyBlock = i.next();
192 ProtectionDomain grantPD = policyBlock.toProtectionDomain();
193
194 if (grantPD.getCodeSource() == null
195 ||
196 grantPD.getCodeSource().implies(codesource))
197 {
198 if (__DEBUG)
199 {
200 debug("----START----");
201 debug("PDCS: " + grantPD.getCodeSource());
202 debug("CS: " + codesource);
203 }
204
205 for (Enumeration<Permission> e = policyBlock.getPermissions().elements(); e.hasMoreElements();)
206 {
207 Permission perm = e.nextElement();
208 if (__DEBUG)
209 {
210 debug("D: " + perm);
211 }
212 perms.add(perm);
213 }
214
215 if (__DEBUG)
216 {
217 debug("----STOP----");
218 }
219 }
220 }
221
222 _cache.put(codesource,perms);
223
224 return copyOf(perms);
225 }
226 }
227
228 @Override
229 public boolean implies(ProtectionDomain domain, Permission permission)
230 {
231 PermissionCollection pc = getPermissions(domain);
232
233 return (pc == null ? false : pc.implies(permission));
234 }
235
236
237 private static boolean validate(Principal[] permCerts, Principal[] classCerts)
238 {
239 if (classCerts == null)
240 {
241 return false;
242 }
243
244 for (int i = 0; i < permCerts.length; ++i)
245 {
246 boolean found = false;
247 for (int j = 0; j < classCerts.length; ++j)
248 {
249 if (permCerts[i].equals(classCerts[j]))
250 {
251 found = true;
252 break;
253 }
254 }
255
256 if (found == false)
257 {
258 return false;
259 }
260 }
261
262 return true;
263 }
264
265
266
267
268
269
270 @Override
271 public synchronized void refresh()
272 {
273
274 try
275 {
276
277 if (__RELOAD && _scanner == null)
278 {
279 initializeReloading();
280 }
281
282 if (__DEBUG)
283 {
284 synchronized (_cache)
285 {
286 for (Iterator<Object> i = _cache.keySet().iterator(); i.hasNext();)
287 {
288 log(i.next().toString());
289 }
290 }
291 }
292
293 Set<PolicyBlock> clean = new HashSet<PolicyBlock>();
294
295 for (Iterator<String> i = _policies.iterator(); i.hasNext();)
296 {
297 File policyFile = new File(i.next());
298
299 clean.addAll(DefaultPolicyLoader.load(new FileInputStream(policyFile),_context));
300 }
301
302 synchronized (_cache)
303 {
304 _grants.clear();
305 _grants.addAll(clean);
306 _cache.clear();
307 }
308 _initialized = true;
309 }
310 catch (Exception e)
311 {
312 e.printStackTrace();
313 }
314 }
315
316
317
318
319
320
321 private void initializeReloading() throws Exception
322 {
323 _scanner = new Scanner();
324
325 List<File> scanDirs = new ArrayList<File>();
326
327 for (Iterator<String> i = _policies.iterator(); i.hasNext();)
328 {
329 File policyFile = new File(i.next());
330 scanDirs.add(policyFile.getParentFile());
331 }
332
333 _scanner.addListener(new Scanner.DiscreteListener()
334 {
335
336 public void fileRemoved(String filename) throws Exception
337 {
338
339 }
340
341
342 public void fileChanged(String filename) throws Exception
343 {
344 if (filename.endsWith("policy"))
345 {
346 log("JettyPolicy: refreshing policy files");
347 refresh();
348 log("JettyPolicy: finished refreshing policies");
349 }
350 }
351
352 public void fileAdded(String filename) throws Exception
353 {
354
355 }
356 });
357
358 _scanner.setScanDirs(scanDirs);
359 _scanner.start();
360 _scanner.setScanInterval(10);
361 }
362
363 public void dump(PrintStream out)
364 {
365 PrintWriter write = new PrintWriter(out);
366 write.println("JettyPolicy: policy settings dump");
367
368 synchronized (_cache)
369 {
370 for (Iterator<Object> i = _cache.keySet().iterator(); i.hasNext();)
371 {
372 Object o = i.next();
373 write.println(o.toString());
374 }
375 }
376 write.flush();
377 }
378
379 public PermissionCollection copyOf(final PermissionCollection in)
380 {
381 PermissionCollection out = new Permissions();
382 synchronized (in)
383 {
384 for (Enumeration<Permission> el = in.elements() ; el.hasMoreElements() ;)
385 {
386 out.add((Permission)el.nextElement());
387 }
388 }
389 return out;
390 }
391
392
393
394
395
396 public Set<String> getKnownPolicyFiles()
397 {
398 return _policies;
399 }
400
401
402
403
404
405
406
407 private Set<String> resolvePolicyFiles( Set<String> policyInputs )
408 {
409 Set<String> policyFiles = new HashSet<String>();
410
411 try
412 {
413 for ( String policyInput : policyInputs )
414 {
415 File check = new File(policyInput);
416
417 if ( check.isDirectory() )
418 {
419 File[] foundFiles = check.listFiles(new FileFilter()
420 {
421 public boolean accept(File pathname)
422 {
423 if ( pathname.getName().toLowerCase().endsWith("policy") )
424 {
425 return true;
426 }
427 else
428 {
429 return false;
430 }
431 }
432 });
433
434 for( File policyFile : foundFiles )
435 {
436 policyFiles.add(policyFile.getCanonicalPath());
437 }
438 }
439 else
440 {
441 policyFiles.add(check.getCanonicalPath());
442 }
443 }
444 }
445 catch ( IOException ioe )
446 {
447 throw new IllegalArgumentException( "JettyPolicy: unable to resolve policy files.", ioe );
448 }
449 return policyFiles;
450 }
451
452
453
454
455
456
457
458 private void debug( String message )
459 {
460 try
461 {
462 Log.debug(message);
463 }
464 catch ( AccessControlException ace )
465 {
466 System.out.println( "[DEBUG] " + message );
467 }
468 }
469
470
471
472
473
474
475 private void log( String message )
476 {
477 log( message, null );
478 }
479
480
481
482
483
484
485
486 private void log( String message, Throwable t )
487 {
488 try
489 {
490 Log.info(message, t);
491 }
492 catch ( AccessControlException ace )
493 {
494 System.out.println( message );
495 t.printStackTrace();
496 }
497 }
498
499 }