KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > security > jacc > DelegatingPolicy


1 /*
2 * JBoss, the OpenSource J2EE webOS
3 *
4 * Distributable under LGPL license.
5 * See terms of license at gnu.org.
6 */

7 package org.jboss.security.jacc;
8
9 import java.security.CodeSource JavaDoc;
10 import java.security.Permission JavaDoc;
11 import java.security.PermissionCollection JavaDoc;
12 import java.security.Policy JavaDoc;
13 import java.security.ProtectionDomain JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.Enumeration JavaDoc;
16 import javax.security.jacc.EJBMethodPermission JavaDoc;
17 import javax.security.jacc.EJBRoleRefPermission JavaDoc;
18 import javax.security.jacc.PolicyConfiguration JavaDoc;
19 import javax.security.jacc.PolicyContext JavaDoc;
20 import javax.security.jacc.PolicyContextException JavaDoc;
21 import javax.security.jacc.WebResourcePermission JavaDoc;
22 import javax.security.jacc.WebRoleRefPermission JavaDoc;
23 import javax.security.jacc.WebUserDataPermission JavaDoc;
24 import javax.security.auth.Subject JavaDoc;
25
26 import org.jboss.logging.Logger;
27 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
28
29 /**
30  * A JAAC Policy provider implementation that delegates any non-JACC permissions
31  * to the java.security.Policy either passed in to the ctor, or the pre existing
32  * Policy.getPolicy value.
33  * @author Scott.Stark@jboss.org
34  * @version $Revision: 1.5.4.7 $
35  */

36 public class DelegatingPolicy extends Policy JavaDoc
37 {
38    private static Logger log = Logger.getLogger(DelegatingPolicy.class);
39    private static DelegatingPolicy instance;
40
41    /**
42     * The system Policy we delegate non-JACC checks to
43     */

44    private Policy JavaDoc delegate;
45    /**
46     * Map<String, ContextPolicy> for the JACC context IDs that have been
47     * committed.
48     */

49    private ConcurrentReaderHashMap activePolicies = new ConcurrentReaderHashMap();
50    /**
51     * Map<String, ContextPolicy> for the JACC policies that are in the open
52     * state and should be excluded from the active permission set.
53     */

54    private ConcurrentReaderHashMap openPolicies = new ConcurrentReaderHashMap();
55    /**
56     * Flag indicating if our category is at trace level for logging
57     */

58    private boolean trace;
59    /**
60     * The Policy proxy returned via the PolicyProxy attribute
61     */

62    private PolicyProxy policyProxy = new PolicyProxy(this);
63
64    public synchronized static DelegatingPolicy getInstance()
65    {
66       if (instance == null)
67       {
68          instance = new DelegatingPolicy();
69       }
70       return instance;
71    }
72
73    public DelegatingPolicy()
74    {
75       this(null);
76    }
77
78    public DelegatingPolicy(Policy JavaDoc delegate)
79    {
80       if (delegate == null)
81          delegate = Policy.getPolicy();
82       this.delegate = delegate;
83       this.trace = log.isTraceEnabled();
84       if (instance == null)
85          instance = this;
86       /* When run with a security manager the act of class loading can trigger
87       security checks which in turn causes this classes implies method to be
88       called as soon as the this class is installed as the Policy implementation.
89       The implies method cannot cause class loading to occur before there is
90       the delegation to the non-JACC Policy provider or else an infinite
91       recursion scenario arises where entrance into implies triggers class
92       loading which recurses into implies. Here we load the JACC permission
93       classes to ensure we get to the point of being able to delegate non-JACC
94       permission to the delegate policy. This is the same type of statement
95       performed at the start of implies which was causing the JACC permissions
96       to be loaded. See [JBAS-1363].
97       */

98       Permission JavaDoc permission = new RuntimePermission JavaDoc("test");
99       boolean loadedPerms = !(permission instanceof EJBMethodPermission JavaDoc
100          || permission instanceof EJBRoleRefPermission JavaDoc
101          || permission instanceof WebResourcePermission JavaDoc
102          || permission instanceof WebRoleRefPermission JavaDoc
103          || permission instanceof WebUserDataPermission JavaDoc);
104       if (trace)
105          log.trace("Loaded JACC permissions: " + loadedPerms);
106       Class JavaDoc c = PolicyContext JavaDoc.class;
107    }
108
109    public PermissionCollection JavaDoc getPermissions(ProtectionDomain JavaDoc domain)
110    {
111       PermissionCollection JavaDoc pc = super.getPermissions(domain);
112       PermissionCollection JavaDoc delegated = delegate.getPermissions(domain);
113       for (Enumeration JavaDoc e = delegated.elements(); e.hasMoreElements();)
114       {
115          Permission JavaDoc p = (Permission JavaDoc) e.nextElement();
116          pc.add(p);
117       }
118       return pc;
119    }
120
121    public boolean implies(ProtectionDomain JavaDoc domain, Permission JavaDoc permission)
122    {
123       boolean isJaccPermission = permission instanceof EJBMethodPermission JavaDoc
124          || permission instanceof EJBRoleRefPermission JavaDoc
125          || permission instanceof WebResourcePermission JavaDoc
126          || permission instanceof WebRoleRefPermission JavaDoc
127          || permission instanceof WebUserDataPermission JavaDoc;
128       if (trace)
129       {
130          log.trace("implies, domain=" + domain + ", permission=" + permission
131             + ", isJaccPermission=" + isJaccPermission);
132          try
133          {
134             Subject JavaDoc caller = (Subject JavaDoc) PolicyContext.getContext("javax.security.auth.Subject.container");
135             log.trace("implies javax.security.auth.Subject.container: "+caller);
136          }
137          catch(Throwable JavaDoc e)
138          {
139             log.trace("Failed to access Subject context", e);
140          }
141       }
142       boolean implied = false;
143       if (isJaccPermission == false)
144       {
145          // Let the delegate policy handle the check
146
implied = delegate.implies(domain, permission);
147       }
148       else
149       {
150          String JavaDoc contextID = PolicyContext.getContextID();
151          ContextPolicy contextPolicy = (ContextPolicy) activePolicies.get(contextID);
152          if (contextPolicy != null)
153             implied = contextPolicy.implies(domain, permission);
154          else if (trace)
155             log.trace("No PolicyContext found for contextID=" + contextID);
156       }
157       if (trace)
158       {
159          log.trace("implied=" + implied);
160       }
161       return implied;
162    }
163
164    /**
165     * Return the permission collection associated with the cs.
166     * If there is no active JACC PolicyContext then the delegate value for
167     * getPermissions(CodeSource) is returned. Otherwise the JACC policy context
168     * permissions are returned.
169     *
170     * @todo We should probably merge the PolicyContext permissions with the
171     * delegate permission?
172     *
173     * @param cs - the CodeSource
174     * @return the associated permission collection
175     */

176    public PermissionCollection JavaDoc getPermissions(CodeSource JavaDoc cs)
177    {
178       PermissionCollection JavaDoc pc = null;
179       String JavaDoc contextID = PolicyContext.getContextID();
180       if (contextID == null)
181       {
182          pc = delegate.getPermissions(cs);
183       }
184       else
185       {
186          ContextPolicy policy = (ContextPolicy) activePolicies.get(contextID);
187          if (policy != null)
188          {
189             pc = policy.getPermissions();
190          }
191          else
192          {
193             pc = delegate.getPermissions(cs);
194          }
195       }
196       return pc;
197    }
198
199    /**
200     * We dynamically manage the active policies on commit so refresh is a noop.
201     * Its not clear from the spec whether committed policies should not be visible
202     * until a refresh.
203     */

204    public void refresh()
205    {
206       
207    }
208
209    /**
210     * @return A proxy for our Policy interface
211     */

212    public Policy JavaDoc getPolicyProxy()
213    {
214       return policyProxy;
215    }
216
217    // Policy configuration methods used by the PolicyConfiguration impl
218

219    /**
220     * Access the current ContextPolicy instances
221     * @return Map<String, ContextPolicy> of the contextID to policy mappings
222     */

223    public String JavaDoc listContextPolicies()
224    {
225       StringBuffer JavaDoc tmp = new StringBuffer JavaDoc("<ActiveContextPolicies>");
226       Iterator JavaDoc iter = activePolicies.keySet().iterator();
227       while (iter.hasNext())
228       {
229          String JavaDoc contextID = (String JavaDoc) iter.next();
230          ContextPolicy cp = (ContextPolicy) activePolicies.get(contextID);
231          tmp.append(cp);
232          tmp.append('\n');
233       }
234       tmp.append("</ActiveContextPolicies>");
235
236       tmp.append("<OpenContextPolicies>");
237       iter = openPolicies.keySet().iterator();
238       while (iter.hasNext())
239       {
240          String JavaDoc contextID = (String JavaDoc) iter.next();
241          ContextPolicy cp = (ContextPolicy) openPolicies.get(contextID);
242          tmp.append(cp);
243          tmp.append('\n');
244       }
245       tmp.append("</OpenContextPolicies>");
246
247       return tmp.toString();
248    }
249
250    synchronized ContextPolicy getContextPolicy(String JavaDoc contextID)
251       throws PolicyContextException JavaDoc
252    {
253       ContextPolicy policy = (ContextPolicy) openPolicies.get(contextID);
254       if (policy == null)
255          throw new PolicyContextException JavaDoc("No ContextPolicy exists for contextID=" + contextID);
256       return policy;
257    }
258
259    /**
260     * Create or update a ContextPolicy for contextID. This moves any active
261     * policy to the openPolicies map until its committed.
262     *
263     * @param contextID
264     * @param remove
265     * @throws PolicyContextException
266     */

267    synchronized void initPolicyConfiguration(String JavaDoc contextID, boolean remove)
268       throws PolicyContextException JavaDoc
269    {
270       // Remove from the active policy map
271
ContextPolicy policy = (ContextPolicy) activePolicies.remove(contextID);
272       if( policy == null )
273          policy = (ContextPolicy) openPolicies.get(contextID);
274       if (policy == null)
275       {
276          policy = new ContextPolicy(contextID);
277       }
278       // Add to the open policy map
279
openPolicies.put(contextID, policy);
280       if (remove == true)
281          policy.clear();
282    }
283
284    void addToExcludedPolicy(String JavaDoc contextID, Permission JavaDoc permission)
285       throws PolicyContextException JavaDoc
286    {
287       ContextPolicy policy = getContextPolicy(contextID);
288       policy.addToExcludedPolicy(permission);
289    }
290
291    void addToExcludedPolicy(String JavaDoc contextID, PermissionCollection JavaDoc permissions)
292       throws PolicyContextException JavaDoc
293    {
294       ContextPolicy policy = getContextPolicy(contextID);
295       policy.addToExcludedPolicy(permissions);
296    }
297
298    void addToRole(String JavaDoc contextID, String JavaDoc roleName, Permission JavaDoc permission)
299       throws PolicyContextException JavaDoc
300    {
301       ContextPolicy policy = getContextPolicy(contextID);
302       policy.addToRole(roleName, permission);
303    }
304
305    void addToRole(String JavaDoc contextID, String JavaDoc roleName, PermissionCollection JavaDoc permissions)
306       throws PolicyContextException JavaDoc
307    {
308       ContextPolicy policy = getContextPolicy(contextID);
309       policy.addToRole(roleName, permissions);
310    }
311
312    void addToUncheckedPolicy(String JavaDoc contextID, Permission JavaDoc permission)
313       throws PolicyContextException JavaDoc
314    {
315       ContextPolicy policy = getContextPolicy(contextID);
316       policy.addToUncheckedPolicy(permission);
317    }
318
319    void addToUncheckedPolicy(String JavaDoc contextID, PermissionCollection JavaDoc permissions)
320       throws PolicyContextException JavaDoc
321    {
322       ContextPolicy policy = getContextPolicy(contextID);
323       policy.addToUncheckedPolicy(permissions);
324    }
325
326    void linkConfiguration(String JavaDoc contextID, PolicyConfiguration JavaDoc link)
327       throws PolicyContextException JavaDoc
328    {
329       ContextPolicy policy = getContextPolicy(contextID);
330       ContextPolicy linkPolicy = getContextPolicy(link.getContextID());
331       policy.linkConfiguration(linkPolicy);
332    }
333
334    /**
335     * May need to make this synchronized to allow the move from the open to
336     * active policy map atomic. Right now the assumption is that a single thread
337     * is active for a given contextID.
338     *
339     * @param contextID
340     * @throws PolicyContextException
341     */

342    public void commit(String JavaDoc contextID)
343       throws PolicyContextException JavaDoc
344    {
345       ContextPolicy policy = getContextPolicy(contextID);
346       openPolicies.remove(contextID);
347       activePolicies.put(contextID, policy);
348       policy.commit();
349    }
350
351    public void delete(String JavaDoc contextID)
352       throws PolicyContextException JavaDoc
353    {
354       ContextPolicy policy = (ContextPolicy) activePolicies.remove(contextID);
355       if( policy == null )
356          policy = (ContextPolicy) openPolicies.remove(contextID);
357       if( policy != null )
358          policy.delete();
359    }
360
361    void removeExcludedPolicy(String JavaDoc contextID)
362       throws PolicyContextException JavaDoc
363    {
364       ContextPolicy policy = getContextPolicy(contextID);
365       policy.removeExcludedPolicy();
366    }
367
368    void removeRole(String JavaDoc contextID, String JavaDoc roleName)
369       throws PolicyContextException JavaDoc
370    {
371       ContextPolicy policy = getContextPolicy(contextID);
372       policy.removeRole(roleName);
373    }
374
375    void removeUncheckedPolicy(String JavaDoc contextID)
376       throws PolicyContextException JavaDoc
377    {
378       ContextPolicy policy = getContextPolicy(contextID);
379       policy.removeUncheckedPolicy();
380    }
381
382    /**
383     * This proxy wrapper restricts the visible methods to only those from the
384     * Policy base class.
385     */

386    private static class PolicyProxy extends Policy JavaDoc
387    {
388       private Policy JavaDoc delegate;
389
390       PolicyProxy(Policy JavaDoc delegate)
391       {
392          this.delegate = delegate;
393       }
394
395       public void refresh()
396       {
397          delegate.refresh();
398       }
399
400       public PermissionCollection JavaDoc getPermissions(CodeSource JavaDoc codesource)
401       {
402          return delegate.getPermissions(codesource);
403       }
404
405       public boolean implies(ProtectionDomain JavaDoc domain, Permission JavaDoc permission)
406       {
407          return delegate.implies(domain, permission);
408       }
409
410       public PermissionCollection JavaDoc getPermissions(ProtectionDomain JavaDoc domain)
411       {
412          return delegate.getPermissions(domain);
413       }
414    }
415 }
416
Popular Tags