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