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.PrintStream;
20 import java.io.PrintWriter;
21 import java.security.AccessControlException;
22 import java.security.CodeSource;
23 import java.security.Permission;
24 import java.security.PermissionCollection;
25 import java.security.Permissions;
26 import java.security.Policy;
27 import java.security.Principal;
28 import java.security.ProtectionDomain;
29 import java.security.cert.Certificate;
30 import java.security.cert.CertificateException;
31 import java.util.Enumeration;
32 import java.util.HashSet;
33 import java.util.Iterator;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.concurrent.ConcurrentHashMap;
37
38 import org.eclipse.jetty.util.log.Log;
39 import org.eclipse.jetty.util.log.Logger;
40 import org.eclipse.jetty.util.security.CertificateValidator;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 public class JettyPolicy extends Policy
63 {
64 private static final Logger LOG = Log.getLogger(JettyPolicy.class);
65
66 private static boolean __DEBUG = false;
67 private static boolean __RELOAD = false;
68
69 private boolean _STARTED = false;
70
71 private String _policyDirectory;
72
73 private final Set<PolicyBlock> _grants = new HashSet<PolicyBlock>();
74
75
76
77
78 private final Map<Object, PermissionCollection> _cache = new ConcurrentHashMap<Object, PermissionCollection>();
79
80 private final static PolicyContext _context = new PolicyContext();
81
82 private CertificateValidator _validator = null;
83
84 private PolicyMonitor _policyMonitor = new PolicyMonitor()
85 {
86 @Override
87 public void onPolicyChange(PolicyBlock grant)
88 {
89 boolean setGrant = true;
90
91 if ( _validator != null )
92 {
93 if (grant.getCertificates() != null)
94 {
95 for ( Certificate cert : grant.getCertificates() )
96 {
97 try
98 {
99 _validator.validate(_context.getKeystore(), cert);
100 }
101 catch ( CertificateException ce )
102 {
103 setGrant = false;
104 }
105 }
106 }
107 }
108
109 if ( setGrant )
110 {
111 _grants.add( grant );
112 _cache.clear();
113 }
114 }
115 };
116
117 public JettyPolicy(String policyDirectory, Map<String, String> properties)
118 {
119 try
120 {
121 __RELOAD = Boolean.getBoolean("org.eclipse.jetty.policy.RELOAD");
122 __DEBUG = Boolean.getBoolean("org.eclipse.jetty.policy.DEBUG");
123 }
124 catch (AccessControlException ace)
125 {
126 __RELOAD = false;
127 __DEBUG = false;
128 }
129
130 _policyDirectory = policyDirectory;
131 _context.setProperties(properties);
132
133 try
134 {
135 _policyMonitor.setPolicyDirectory(_policyDirectory);
136
137 }
138 catch ( Exception e)
139 {
140 throw new PolicyException(e);
141 }
142 }
143
144
145
146 @Override
147 public void refresh()
148 {
149 if ( !_STARTED )
150 {
151 initialize();
152 }
153 }
154
155
156
157
158
159 public void initialize()
160 {
161 if ( _STARTED )
162 {
163 return;
164 }
165
166 try
167 {
168 _policyMonitor.start();
169 _policyMonitor.waitForScan();
170 }
171 catch (Exception e)
172 {
173 e.printStackTrace();
174 throw new PolicyException(e);
175 }
176
177 _STARTED = true;
178 }
179
180 @Override
181 public PermissionCollection getPermissions(ProtectionDomain domain)
182 {
183
184 if (!_STARTED)
185 {
186 throw new PolicyException("JettyPolicy must be started.");
187 }
188
189 synchronized (_cache)
190 {
191 if (_cache.containsKey(domain))
192 {
193 return copyOf(_cache.get(domain));
194 }
195
196 PermissionCollection perms = new Permissions();
197
198 for (Iterator<PolicyBlock> i = _grants.iterator(); i.hasNext();)
199 {
200 PolicyBlock policyBlock = i.next();
201 ProtectionDomain grantPD = policyBlock.toProtectionDomain();
202
203 if (__DEBUG)
204 {
205 debug("----START----");
206 debug("PDCS: " + policyBlock.getCodeSource());
207 debug("CS: " + domain.getCodeSource());
208
209 }
210
211
212
213 if (grantPD.getCodeSource() == null
214 ||
215 grantPD.getCodeSource().implies(domain.getCodeSource())
216 &&
217 grantPD.getPrincipals() == null
218 ||
219 grantPD.getCodeSource().implies(domain.getCodeSource())
220 &&
221 validate(grantPD.getPrincipals(),domain.getPrincipals()))
222
223 {
224
225 for (Enumeration<Permission> e = policyBlock.getPermissions().elements(); e.hasMoreElements();)
226 {
227 Permission perm = e.nextElement();
228 if (__DEBUG)
229 {
230 debug("D: " + perm);
231 }
232 perms.add(perm);
233 }
234 }
235 if (__DEBUG)
236 {
237 debug("----STOP----");
238 }
239 }
240
241 _cache.put(domain,perms);
242
243 return copyOf(perms);
244 }
245 }
246
247 @Override
248 public PermissionCollection getPermissions(CodeSource codesource)
249 {
250 if (!_STARTED)
251 {
252 throw new PolicyException("JettyPolicy must be started.");
253 }
254
255 synchronized (_cache)
256 {
257 if (_cache.containsKey(codesource))
258 {
259 return copyOf(_cache.get(codesource));
260 }
261
262 PermissionCollection perms = new Permissions();
263
264 for (Iterator<PolicyBlock> i = _grants.iterator(); i.hasNext();)
265 {
266 PolicyBlock policyBlock = i.next();
267 ProtectionDomain grantPD = policyBlock.toProtectionDomain();
268
269 if (grantPD.getCodeSource() == null
270 ||
271 grantPD.getCodeSource().implies(codesource))
272 {
273 if (__DEBUG)
274 {
275 debug("----START----");
276 debug("PDCS: " + grantPD.getCodeSource());
277 debug("CS: " + codesource);
278 }
279
280 for (Enumeration<Permission> e = policyBlock.getPermissions().elements(); e.hasMoreElements();)
281 {
282 Permission perm = e.nextElement();
283 if (__DEBUG)
284 {
285 debug("D: " + perm);
286 }
287 perms.add(perm);
288 }
289
290 if (__DEBUG)
291 {
292 debug("----STOP----");
293 }
294 }
295 }
296
297 _cache.put(codesource,perms);
298
299 return copyOf(perms);
300 }
301 }
302
303 @Override
304 public boolean implies(ProtectionDomain domain, Permission permission)
305 {
306 if (!_STARTED)
307 {
308 throw new PolicyException("JettyPolicy must be started.");
309 }
310
311 PermissionCollection pc = getPermissions(domain);
312
313 return (pc == null ? false : pc.implies(permission));
314 }
315
316
317 private static boolean validate(Principal[] permCerts, Principal[] classCerts)
318 {
319 if (classCerts == null)
320 {
321 return false;
322 }
323
324 for (int i = 0; i < permCerts.length; ++i)
325 {
326 boolean found = false;
327 for (int j = 0; j < classCerts.length; ++j)
328 {
329 if (permCerts[i].equals(classCerts[j]))
330 {
331 found = true;
332 break;
333 }
334 }
335
336 if (found == false)
337 {
338 return false;
339 }
340 }
341
342 return true;
343 }
344
345
346
347
348
349
350
351
352 public static PolicyContext getContext()
353 {
354 return _context;
355 }
356
357
358
359
360
361
362
363
364
365 private void debug( String message )
366 {
367 try
368 {
369 LOG.info(message);
370 }
371 catch ( AccessControlException ace )
372 {
373 System.out.println( "[DEBUG] " + message );
374 }
375 catch ( NoClassDefFoundError ace )
376 {
377 System.out.println( "[DEBUG] " + message );
378
379 }
380 }
381
382
383
384
385
386
387 private void log( String message )
388 {
389 log( message, null );
390 }
391
392
393
394
395
396
397
398 private void log( String message, Throwable t )
399 {
400 try
401 {
402 LOG.info(message, t);
403 }
404 catch ( AccessControlException ace )
405 {
406 System.out.println( message );
407 t.printStackTrace();
408 }
409 catch ( NoClassDefFoundError ace )
410 {
411 System.out.println( message );
412 t.printStackTrace();
413 }
414 }
415
416
417 public void dump(PrintStream out)
418 {
419 PrintWriter write = new PrintWriter(out);
420 write.println("JettyPolicy: policy settings dump");
421
422 synchronized (_cache)
423 {
424 for (Iterator<Object> i = _cache.keySet().iterator(); i.hasNext();)
425 {
426 Object o = i.next();
427 write.println(o.toString());
428 }
429 }
430 write.flush();
431 }
432
433 private PermissionCollection copyOf(final PermissionCollection in)
434 {
435 PermissionCollection out = new Permissions();
436 synchronized (in)
437 {
438 for (Enumeration<Permission> el = in.elements() ; el.hasMoreElements() ;)
439 {
440 out.add((Permission)el.nextElement());
441 }
442 }
443 return out;
444 }
445
446 public CertificateValidator getCertificateValidator()
447 {
448 return _validator;
449 }
450
451 public void setCertificateValidator(CertificateValidator validator)
452 {
453 if (_STARTED)
454 {
455 throw new PolicyException("JettyPolicy already started, unable to set validator on running policy");
456 }
457
458 _validator = validator;
459 }
460 }