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