KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas_ejb > container > PermissionManager


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 2004 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * Initial developer: Florent BENOIT
22  * --------------------------------------------------------------------------
23  * $Id: PermissionManager.java,v 1.14 2005/07/26 17:17:46 benoitf Exp $
24  * --------------------------------------------------------------------------
25  */

26
27 package org.objectweb.jonas_ejb.container;
28
29 import java.net.URI JavaDoc;
30 import java.net.URL JavaDoc;
31 import java.security.CodeSource JavaDoc;
32 import java.security.PermissionCollection JavaDoc;
33 import java.security.Principal JavaDoc;
34 import java.security.ProtectionDomain JavaDoc;
35 import java.security.cert.Certificate JavaDoc;
36 import java.util.Iterator JavaDoc;
37
38 import javax.security.jacc.EJBMethodPermission JavaDoc;
39 import javax.security.jacc.EJBRoleRefPermission JavaDoc;
40 import javax.security.jacc.PolicyContext JavaDoc;
41 import javax.security.jacc.PolicyContextException JavaDoc;
42
43 import org.objectweb.jonas_ejb.deployment.api.BeanDesc;
44 import org.objectweb.jonas_ejb.deployment.api.DeploymentDesc;
45 import org.objectweb.jonas_ejb.deployment.api.ExcludeListDesc;
46 import org.objectweb.jonas_ejb.deployment.api.MethodPermissionDesc;
47 import org.objectweb.jonas_ejb.lib.EJBInvocation;
48
49 import org.objectweb.jonas_lib.deployment.api.SecurityRoleRefDesc;
50 import org.objectweb.jonas_lib.security.AbsPermissionManager;
51 import org.objectweb.jonas_lib.security.PermissionManagerException;
52
53 import org.objectweb.jonas.security.jacc.JPolicyContextHandlerCurrent;
54 import org.objectweb.jonas.security.jacc.JPolicyContextHandlerData;
55
56 import org.objectweb.security.context.SecurityContext;
57 import org.objectweb.security.context.SecurityCurrent;
58
59 import org.objectweb.util.monolog.api.BasicLevel;
60
61 /**
62  * Defines a PermissionManager class which will manage JACC permissions for an
63  * ejbjar
64  * @author Florent Benoit
65  */

66 public class PermissionManager extends AbsPermissionManager {
67
68     /**
69      * Deployment desc of the module
70      */

71     private DeploymentDesc ejbDeploymentDesc = null;
72
73     /**
74      * Default Constructor
75      * @param ejbDeploymentDesc EJB deployment Descriptor
76      * @param contextId context ID used for PolicyContext
77      * @throws PermissionManagerException if permissions can't be set
78      */

79     public PermissionManager(DeploymentDesc ejbDeploymentDesc, String JavaDoc contextId) throws PermissionManagerException {
80         super(contextId);
81         this.ejbDeploymentDesc = ejbDeploymentDesc;
82     }
83
84     /**
85      * 3.1.5 Translating EJB Deployment Descriptors A reference to a
86      * PolicyConfiguration object must be obtained by calling the
87      * getPolicyConfiguration method on the PolicyConfigurationFactory
88      * implementation class of the provider configured into the container. The
89      * policy context identifier used in the call to getPolicyConfiguration must
90      * be a String that satisfies the requirements described in Section 3.1.4,
91      * EJB Policy Context Identifiers, on page 28. The value true must be passed
92      * as the second parameter in the call to getPolicyConfiguration to ensure
93      * that any and all policy statements are removed from the policy context
94      * associated with the returned PolicyConfiguration. The method-permission,
95      * exclude-list, and security-role-ref elements appearing in the deployment
96      * descriptor must be translated into permissions and added to the
97      * PolicyConfiguration object to yield an equivalent translation as that
98      * defined in the following sections and such that every EJB method for
99      * which the container performs pre-dispatch access decisions is implied by
100      * at least one permission resulting from the translation.
101      * @throws PermissionManagerException if permissions can't be set
102      */

103     public void translateEjbDeploymentDescriptor() throws PermissionManagerException {
104         translateEjbMethodPermission();
105         translateEjbExcludeList();
106         translateEjbSecurityRoleRef();
107     }
108
109     /**
110      * 3.1.5.1 Translating EJB method-permission Elements For each method
111      * element of each method-permission element, an EJBMethodPermission object
112      * translated from the method element must be added to the policy statements
113      * of the PolicyConfiguration object. The name of each such
114      * EJBMethodPermission object must be the ejb-name from the corresponding
115      * method element, and the actions must be established by translating the
116      * method element into a method specification according to the methodSpec
117      * syntax defined in the documentation of the EJBMethodPermission class. The
118      * actions translation must preserve the degree of specificity with respect
119      * to method-name, method-intf, and method-params inherent in the method
120      * element. If the method-permission element contains the unchecked element,
121      * then the deployment tools must call the addToUncheckedPolicy method to
122      * add the permissions resulting from the translation to the
123      * PolicyConfiguration object. Alternatively, if the method-permission
124      * element contains one or more role-name elements, then the deployment
125      * tools must call the addToRole method to add the permissions resulting
126      * from the translation to the corresponding roles of the
127      * PolicyConfiguration object.
128      * @throws PermissionManagerException if permissions can't be set
129      */

130     protected void translateEjbMethodPermission() throws PermissionManagerException {
131         if (ejbDeploymentDesc == null || getPolicyConfiguration() == null) {
132             throw new PermissionManagerException("PolicyConfiguration or ejbDeploymentDesc is null");
133         }
134
135         MethodPermissionDesc methodPermissionDesc = null;
136         PermissionCollection JavaDoc permissionCollection = null;
137
138         for (Iterator JavaDoc it = ejbDeploymentDesc.getMethodPermissionsDescList().iterator(); it.hasNext();) {
139             methodPermissionDesc = (MethodPermissionDesc) it.next();
140             permissionCollection = methodPermissionDesc.getEJBMethodPermissions();
141             try {
142                 // unchecked or roles
143
if (methodPermissionDesc.isUnchecked()) {
144                     getPolicyConfiguration().addToUncheckedPolicy(permissionCollection);
145                 } else {
146                     for (Iterator JavaDoc rolesIt = methodPermissionDesc.getRoleNameList().iterator(); rolesIt.hasNext();) {
147                         getPolicyConfiguration().addToRole((String JavaDoc) rolesIt.next(), permissionCollection);
148                     }
149                 }
150             } catch (PolicyContextException JavaDoc pce) {
151                 throw new PermissionManagerException("Can not add add excluded policy", pce);
152             }
153         }
154     }
155
156     /**
157      * 3.1.5.2 Translating the EJB exclude-list An EJBMethodPermission object
158      * must be created for each method element occurring in the exclude-list
159      * element of the deployment descriptor. The name and actions of each
160      * EJBMethodPermission must be established as described in Section 3.1.5.1,
161      * Translating EJB method-permission Elements. The deployment tools must use
162      * the addToExcludedPolicy method to add the EJBMethodPermission objects
163      * resulting from the translation of the exclude-list to the excluded policy
164      * statements of the PolicyConfiguration object.
165      * @throws PermissionManagerException if permissions can't be set
166      */

167     protected void translateEjbExcludeList() throws PermissionManagerException {
168         if (ejbDeploymentDesc == null || getPolicyConfiguration() == null) {
169             throw new PermissionManagerException("PolicyConfiguration or ejbDeploymentDesc is null");
170         }
171         ExcludeListDesc excludeListDesc = ejbDeploymentDesc.getExcludeListDesc();
172         if (excludeListDesc != null) {
173             try {
174                 getPolicyConfiguration().addToExcludedPolicy(excludeListDesc.getEJBMethodPermissions());
175             } catch (PolicyContextException JavaDoc pce) {
176                 throw new PermissionManagerException("Can not add add excluded policy", pce);
177             }
178         }
179     }
180
181     /**
182      * 3.1.5.3 Translating EJB security-role-ref Elements For each
183      * security-role-ref element appearing in the deployment descriptor, a
184      * corresponding EJBRoleRefPermission must be created. The name of each
185      * EJBRoleRefPermission must be obtained as described for
186      * EJBMethodPermission objects. The actions used to construct the permission
187      * must be the value of the role-name (that is the reference), appearing in
188      * the security-role-ref. The deployment tools must call the addToRole
189      * method on the PolicyConfiguration object to add a policy statement
190      * corresponding to the EJBRoleRefPermission to the role identified in the
191      * rolelink appearing in the security-role-ref.
192      * @throws PermissionManagerException if permissions can't be set
193      */

194     public void translateEjbSecurityRoleRef() throws PermissionManagerException {
195         if (ejbDeploymentDesc == null || getPolicyConfiguration() == null) {
196             throw new PermissionManagerException("PolicyConfiguration or ejbDeploymentDesc is null");
197         }
198
199         SecurityRoleRefDesc securityRoleRefDesc = null;
200         BeanDesc beanDesc = null;
201
202         // Add EJBRoleRefPermission for each bean
203
for (Iterator JavaDoc itEjb = ejbDeploymentDesc.getBeanDescIterator(); itEjb.hasNext();) {
204             beanDesc = (BeanDesc) itEjb.next();
205             for (Iterator JavaDoc it = beanDesc.getSecurityRoleRefDescList().iterator(); it.hasNext();) {
206                 securityRoleRefDesc = (SecurityRoleRefDesc) it.next();
207                 try {
208                     getPolicyConfiguration().addToRole(securityRoleRefDesc.getRoleLink(),
209                             securityRoleRefDesc.getEJBRoleRefPermission());
210                 } catch (PolicyContextException JavaDoc pce) {
211                     throw new PermissionManagerException("Can not add add excluded policy", pce);
212                 }
213             }
214         }
215     }
216
217     /**
218      * Check the security for a given EJB signature method and for an EJB
219      * @param ejbName name of the EJB
220      * @param ejbInv object containing security signature of the method, args of
221      * method, etc
222      * @param inRunAs bean calling this method is running in run-as mode or not ?
223      * @return true if access to specific method is granted, else false.
224      */

225     public boolean checkSecurity(String JavaDoc ejbName, EJBInvocation ejbInv, boolean inRunAs) {
226         try {
227             PolicyContext.setContextID(getContextId());
228             String JavaDoc methodSignature = ejbInv.methodPermissionSignature;
229
230             if (TraceEjb.isDebugSecurity()) {
231                 TraceEjb.security.log(BasicLevel.DEBUG, "EjbName = " + ejbName + ", methodSignature = " + methodSignature);
232             }
233
234             // Set the information for the Policy provider
235
JPolicyContextHandlerData jPolicyContextHandlerData = JPolicyContextHandlerCurrent.getCurrent()
236                     .getJPolicyContextHandlerData();
237             if (jPolicyContextHandlerData == null) {
238                 TraceEjb.security.log(BasicLevel.ERROR, "The Handler data retrieved is null !");
239                 return false;
240             }
241             jPolicyContextHandlerData.setEjbArguments(ejbInv.arguments);
242             jPolicyContextHandlerData.setProcessingBean(ejbInv.bean);
243
244             PolicyContext.setHandlerData(jPolicyContextHandlerData);
245
246             // Build Protection Domain with a codesource and array of principal
247
URI JavaDoc uri = new URI JavaDoc("file://" + getContextId());
248             CodeSource JavaDoc codesource = new CodeSource JavaDoc(new URL JavaDoc(uri.toString()), (Certificate JavaDoc[]) null);
249             SecurityCurrent current = SecurityCurrent.getCurrent();
250             final SecurityContext sctx = current.getSecurityContext();
251             if (TraceEjb.isDebugSecurity()) {
252                 TraceEjb.security.log(BasicLevel.DEBUG, "Security Context = " + sctx);
253                 if (sctx != null) {
254                     TraceEjb.security.log(BasicLevel.DEBUG, "sctx.getCallerPrincipalRoles() = " + sctx.getCallerPrincipalRoles(inRunAs));
255                 }
256             }
257
258
259             String JavaDoc runAsRole = null;
260
261             Principal JavaDoc[] principals = null;
262             String JavaDoc[] runAsPrincipalRoles = null;
263             String JavaDoc[] principalRoles = null;
264             if (sctx != null) {
265                 synchronized (sctx) {
266                     runAsRole = sctx.peekRunAsRole();
267                     runAsPrincipalRoles = sctx.peekRunAsPrincipalRoles();
268                     principalRoles = sctx.getCallerPrincipalRoles(inRunAs);
269                 }
270                 if (runAsRole != null) {
271                     principals = new Principal JavaDoc[runAsPrincipalRoles.length];
272                     for (int k = 0; k < runAsPrincipalRoles.length; k++) {
273                         principals[k] = new org.objectweb.jonas.security.auth.JPrincipal(
274                                 runAsPrincipalRoles[k]);
275                     }
276                 } else {
277                     principals = new Principal JavaDoc[principalRoles.length];
278                     for (int k = 0; k < principalRoles.length; k++) {
279                         principals[k] = new org.objectweb.jonas.security.auth.JPrincipal(
280                                 principalRoles[k]);
281                     }
282                }
283             } else {
284                 if (TraceEjb.isDebugSecurity()) {
285                     TraceEjb.security.log(BasicLevel.DEBUG, "Security context is null");
286                 }
287             }
288             ProtectionDomain JavaDoc protectionDomain = new ProtectionDomain JavaDoc(codesource, null, null, principals);
289
290             //TODO : cache ejbName/methodSignature to avoid creation of a new
291
// EJBMethodPermission each time
292
// See JACC 4.12
293
EJBMethodPermission JavaDoc ejbMethodPermission = new EJBMethodPermission JavaDoc(ejbName, methodSignature);
294             boolean accessOK = getPolicy().implies(protectionDomain, ejbMethodPermission);
295             if (TraceEjb.isDebugSecurity()) {
296                 TraceEjb.security.log(BasicLevel.DEBUG, "Policy.implies result = " + accessOK);
297             }
298             jPolicyContextHandlerData = null;
299             return accessOK;
300
301         } catch (Exception JavaDoc e) {
302             TraceEjb.security.log(BasicLevel.ERROR, "Cannot check security", e);
303             return false;
304         }
305
306     }
307
308     /**
309      * Test if the caller has a given role. EJBRoleRefPermission object must be
310      * created with ejbName and actions equal to roleName
311      * @see section 4.3.2 of JACC
312      * @param ejbName The name of the EJB on wich look role
313      * @param roleName The name of the security role. The role must be one of
314      * the security-role-ref that is defined in the deployment
315      * descriptor.
316      * @param inRunAs bean calling this method is running in run-as mode or not ?
317      * @return True if the caller has the specified role.
318      */

319     public boolean isCallerInRole(String JavaDoc ejbName, String JavaDoc roleName, boolean inRunAs) {
320         try {
321             PolicyContext.setContextID(getContextId());
322             if (TraceEjb.isDebugSecurity()) {
323                 TraceEjb.security.log(BasicLevel.DEBUG, "roleName = " + roleName);
324             }
325
326             // Build Protection Domain with a codesource and array of principal
327
URI JavaDoc uri = new URI JavaDoc("file://" + getContextId());
328             CodeSource JavaDoc codesource = new CodeSource JavaDoc(new URL JavaDoc(uri.toString()), (Certificate JavaDoc[]) null);
329             SecurityCurrent current = SecurityCurrent.getCurrent();
330             final SecurityContext sctx = current.getSecurityContext();
331             if (TraceEjb.isDebugSecurity()) {
332                 TraceEjb.security.log(BasicLevel.DEBUG, "Security Context = " + sctx);
333                 TraceEjb.security.log(BasicLevel.DEBUG, "sctx.getCallerPrincipalRoles() = "
334                         + sctx.getCallerPrincipalRoles(inRunAs));
335             }
336             Principal JavaDoc[] principals = null;
337             if (sctx != null) {
338                 principals = new Principal JavaDoc[sctx.getCallerPrincipalRoles(inRunAs).length];
339                 for (int k = 0; k < sctx.getCallerPrincipalRoles(inRunAs).length; k++) {
340                     principals[k] = new org.objectweb.jonas.security.auth.JPrincipal(sctx.getCallerPrincipalRoles(inRunAs)[k]);
341                 }
342             } else {
343                 if (TraceEjb.isDebugSecurity()) {
344                     TraceEjb.security.log(BasicLevel.DEBUG, "Security context is null");
345                 }
346             }
347             ProtectionDomain JavaDoc protectionDomain = new ProtectionDomain JavaDoc(codesource, null, null, principals);
348
349             //TODO :add cache mechanism
350
// See JACC 4.12
351
EJBRoleRefPermission JavaDoc ejbRoleRefPermission = new EJBRoleRefPermission JavaDoc(ejbName, roleName);
352             boolean isInRole = getPolicy().implies(protectionDomain, ejbRoleRefPermission);
353             if (TraceEjb.isDebugSecurity()) {
354                 TraceEjb.security.log(BasicLevel.DEBUG, "Policy.implies result = " + isInRole);
355             }
356             return isInRole;
357
358         } catch (Exception JavaDoc e) {
359             TraceEjb.security.log(BasicLevel.ERROR, "Cannot check isCallerInRole", e);
360             return false;
361         }
362
363     }
364
365     /**
366      * Reset Deployment Descriptor
367      */

368     protected void resetDeploymentDesc() {
369         ejbDeploymentDesc = null;
370     }
371
372 }
Popular Tags