001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.geronimo.openejb.deployment;
018:
019: import java.security.Permission;
020: import java.security.PermissionCollection;
021: import java.security.Permissions;
022: import java.util.Enumeration;
023: import java.util.List;
024: import java.util.Map;
025:
026: import javax.security.jacc.EJBMethodPermission;
027: import javax.security.jacc.EJBRoleRefPermission;
028:
029: import org.apache.geronimo.common.DeploymentException;
030: import org.apache.geronimo.security.jacc.ComponentPermissions;
031: import org.apache.openejb.jee.AssemblyDescriptor;
032: import org.apache.openejb.jee.ExcludeList;
033: import org.apache.openejb.jee.Method;
034: import org.apache.openejb.jee.MethodPermission;
035: import org.apache.openejb.jee.SecurityRoleRef;
036:
037: public class SecurityBuilder {
038: /**
039: * Fill the container moduleBuilder with the security information that it needs
040: * to create the proper interceptors. A <code>SecurityConfiguration</code>
041: * is also filled with permissions that need to be used to fill the JACC
042: * policy configuration.
043: *
044: * @param defaultRole default role for otherwise unassigned permissions
045: * @param notAssigned the set of all possible permissions. These will be
046: * culled so that all that are left are those that have
047: * not been assigned roles.
048: * @param assemblyDescriptor the assembly descriptor
049: * @param ejbName the name of the EJB
050: * @param securityRoleRefs the EJB's role references
051: * @param componentPermissions the holder for the ejb's permissions
052: * @throws DeploymentException if any constraints are violated
053: */
054: public void addComponentPermissions(String defaultRole,
055: PermissionCollection notAssigned,
056: AssemblyDescriptor assemblyDescriptor, String ejbName,
057: List<SecurityRoleRef> securityRoleRefs,
058: ComponentPermissions componentPermissions)
059: throws DeploymentException {
060:
061: PermissionCollection uncheckedPermissions = componentPermissions
062: .getUncheckedPermissions();
063: PermissionCollection excludedPermissions = componentPermissions
064: .getExcludedPermissions();
065: Map<String, PermissionCollection> rolePermissions = componentPermissions
066: .getRolePermissions();
067:
068: //this can occur in an ear when one ejb module has security and one doesn't. In this case we still need
069: //to make the non-secure one completely unchecked.
070: if (assemblyDescriptor != null) {
071: /**
072: * JACC v1.0 section 3.1.5.1
073: */
074: for (MethodPermission methodPermission : assemblyDescriptor
075: .getMethodPermission()) {
076: List<String> roleNames = methodPermission.getRoleName();
077: boolean unchecked = methodPermission.getUnchecked();
078:
079: for (Method method : methodPermission.getMethod()) {
080: if (!ejbName.equals(method.getEjbName())) {
081: continue;
082: }
083:
084: // method name
085: String methodName = method.getMethodName();
086: if ("*".equals(methodName)) {
087: // jacc uses null instead of *
088: methodName = null;
089: }
090: // method interface
091: String methodIntf = method.getMethodIntf() == null ? null
092: : method.getMethodIntf().toString();
093:
094: // method parameters
095: String[] methodParams;
096: if (method.getMethodParams() != null) {
097: List<String> paramList = method
098: .getMethodParams().getMethodParam();
099: methodParams = paramList
100: .toArray(new String[paramList.size()]);
101: } else {
102: methodParams = null;
103: }
104:
105: // create the permission object
106: EJBMethodPermission permission = new EJBMethodPermission(
107: ejbName, methodName, methodIntf,
108: methodParams);
109: notAssigned = cullPermissions(notAssigned,
110: permission);
111:
112: // if this is unchecked, mark it as unchecked; otherwise assign the roles
113: if (unchecked) {
114: uncheckedPermissions.add(permission);
115: } else {
116: for (String roleName : roleNames) {
117: Permissions permissions = (Permissions) rolePermissions
118: .get(roleName);
119: if (permissions == null) {
120: permissions = new Permissions();
121: rolePermissions.put(roleName,
122: permissions);
123: }
124: permissions.add(permission);
125: }
126: }
127: }
128:
129: }
130:
131: /**
132: * JACC v1.0 section 3.1.5.2
133: */
134: ExcludeList excludeList = assemblyDescriptor
135: .getExcludeList();
136: if (excludeList != null) {
137: for (Method method : excludeList.getMethod()) {
138: if (!ejbName.equals(method.getEjbName())) {
139: continue;
140: }
141:
142: // method name
143: String methodName = method.getMethodName();
144: // method interface
145: String methodIntf = method.getMethodIntf() == null ? null
146: : method.getMethodIntf().toString();
147:
148: // method parameters
149: String[] methodParams;
150: if (method.getMethodParams() != null) {
151: List<String> paramList = method
152: .getMethodParams().getMethodParam();
153: methodParams = paramList
154: .toArray(new String[paramList.size()]);
155: } else {
156: methodParams = null;
157: }
158:
159: // create the permission object
160: EJBMethodPermission permission = new EJBMethodPermission(
161: ejbName, methodName, methodIntf,
162: methodParams);
163:
164: excludedPermissions.add(permission);
165: notAssigned = cullPermissions(notAssigned,
166: permission);
167: }
168: }
169:
170: /**
171: * JACC v1.0 section 3.1.5.3
172: */
173: for (SecurityRoleRef securityRoleRef : securityRoleRefs) {
174:
175: String roleLink = securityRoleRef.getRoleLink() == null ? securityRoleRef
176: .getRoleName()
177: : securityRoleRef.getRoleLink();
178:
179: PermissionCollection roleLinks = rolePermissions
180: .get(roleLink);
181: if (roleLinks == null) {
182: roleLinks = new Permissions();
183: rolePermissions.put(roleLink, roleLinks);
184:
185: }
186: roleLinks.add(new EJBRoleRefPermission(ejbName,
187: securityRoleRef.getRoleName()));
188: }
189: }
190:
191: /**
192: * EJB v2.1 section 21.3.2
193: * <p/>
194: * It is possible that some methods are not assigned to any security
195: * roles nor contained in the <code>exclude-list</code> element. In
196: * this case, it is the responsibility of the Deployer to assign method
197: * permissions for all of the unspecified methods, either by assigning
198: * them to security roles, or by marking them as <code>unchecked</code>.
199: */
200: PermissionCollection permissions;
201: if (defaultRole == null) {
202: permissions = uncheckedPermissions;
203: } else {
204: permissions = rolePermissions.get(defaultRole);
205: if (permissions == null) {
206: permissions = new Permissions();
207: rolePermissions.put(defaultRole, permissions);
208: }
209: }
210:
211: Enumeration e = notAssigned.elements();
212: while (e.hasMoreElements()) {
213: Permission p = (Permission) e.nextElement();
214: permissions.add(p);
215: }
216:
217: }
218:
219: /**
220: * Generate all the possible permissions for a bean's interface.
221: * <p/>
222: * Method permissions are defined in the deployment descriptor as a binary
223: * relation from the set of security roles to the set of methods of the
224: * home, component, and/or web service endpoint interfaces of session and
225: * entity beans, including all their superinterfaces (including the methods
226: * of the <code>EJBHome</code> and <code>EJBObject</code> interfaces and/or
227: * <code>EJBLocalHome</code> and <code>EJBLocalObject</code> interfaces).
228: *
229: * @param permissions the permission set to be extended
230: * @param ejbName the name of the EJB
231: * @param methodInterface the EJB method interface
232: * @param interfaceClass the class name of the interface to be used to generate the permissions
233: * @param classLoader the class loader to be used in obtaining the interface class
234: * @throws org.apache.geronimo.common.DeploymentException in case a class could not be found
235: */
236: public void addToPermissions(PermissionCollection permissions,
237: String ejbName, String methodInterface,
238: String interfaceClass, ClassLoader classLoader)
239: throws DeploymentException {
240:
241: if (interfaceClass == null) {
242: return;
243: }
244:
245: try {
246: Class clazz = Class.forName(interfaceClass, false,
247: classLoader);
248: for (java.lang.reflect.Method method : clazz.getMethods()) {
249: permissions.add(new EJBMethodPermission(ejbName,
250: methodInterface, method));
251: }
252: } catch (ClassNotFoundException e) {
253: throw new DeploymentException(e);
254: }
255:
256: }
257:
258: /**
259: * Removes permissions from <code>toBeChecked</code> that are implied by
260: * <code>permission</code>.
261: *
262: * @param toBeChecked the permissions that are to be checked and possibly culled
263: * @param permission the permission that is to be used for culling
264: * @return the culled set of permissions that are not implied by <code>permission</code>
265: */
266: private Permissions cullPermissions(
267: PermissionCollection toBeChecked, Permission permission) {
268: Permissions result = new Permissions();
269:
270: for (Enumeration e = toBeChecked.elements(); e
271: .hasMoreElements();) {
272: Permission test = (Permission) e.nextElement();
273: if (!permission.implies(test)) {
274: result.add(test);
275: }
276: }
277:
278: return result;
279: }
280: }
|