KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > security > acl > RoleMapper


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 package com.sun.enterprise.security.acl;
25
26 import java.util.*;
27 import java.lang.reflect.Constructor JavaDoc;
28 import java.security.Principal JavaDoc;
29 import java.security.AccessController JavaDoc;
30 import java.security.PrivilegedAction JavaDoc;
31 import com.sun.enterprise.deployment.Role;
32 import com.sun.enterprise.deployment.interfaces.SecurityRoleMapper;
33 import com.sun.enterprise.deployment.PrincipalImpl;
34 import com.sun.enterprise.deployment.Group;
35 import com.sun.enterprise.config.serverbeans.Server;
36 import com.sun.enterprise.config.serverbeans.ServerBeansFactory;
37 import com.sun.enterprise.config.serverbeans.SecurityService;
38 import com.sun.enterprise.config.ConfigContext;
39 import com.sun.enterprise.server.ApplicationServer;
40 import com.sun.enterprise.server.ServerContext;
41 import com.sun.enterprise.Switch;
42 import java.util.logging.*;
43 import com.sun.logging.*;
44 import javax.security.auth.Subject JavaDoc;
45
46
47 /** This Object maintains a mapping of users and groups to application
48  * specific Roles.
49  * Using this object this mapping information could be maintained and
50  * queried at a later time. This is a complete rewrite of the previous
51  * RoleMapper for JACC related changes.
52  * @author Harpreet Singh
53  */

54 public class RoleMapper implements java.io.Serializable JavaDoc, SecurityRoleMapper {
55     
56     private static Map ROLEMAPPER = new HashMap();
57     private static final String JavaDoc DEFAULT_ROLE_NAME = "ANYONE";
58     private static Role defaultRole = null;
59     private static String JavaDoc defaultRoleName = null;
60     private String JavaDoc appName;
61     private final Map roleToSubject = new HashMap(); // role->subject
62

63     // default mapper to emulate Servlet default p2r mapping semantics
64
private static String JavaDoc defaultP2RMappingClassName = null;
65     private DefaultRoleToSubjectMapping defaultRTSM =
66          new DefaultRoleToSubjectMapping();
67     
68     // the following 2 Maps are a copy of roleToSubject.
69
// This is added as a support for deployment.
70
// Should think of optimizing this
71
// role-to-principal
72
private final Map roleToPrincipal = new HashMap();
73     // role-to-group
74
private final Map roleToGroup = new HashMap();
75     
76     private static Logger _logger =
77     LogDomains.getLogger(LogDomains.SECURITY_LOGGER);
78     
79     private RoleMapper(String JavaDoc appName) {
80         this.appName = appName;
81         Switch sw = Switch.getSwitch();
82         if (sw.getContainerType() == Switch.EJBWEB_CONTAINER) { // 4735725
83
initDefaultRole();
84         }
85         if (defaultP2RMappingClassName==null)
86             defaultP2RMappingClassName = getDefaultP2RMappingClassName();
87     }
88     
89     private static synchronized void initDefaultRole() {
90         
91         if(defaultRole == null) {
92             
93             defaultRoleName = DEFAULT_ROLE_NAME;
94             
95             try {
96                 ConfigContext configContext =
97                 ApplicationServer.getServerContext().getConfigContext();
98                 assert(configContext != null);
99                 
100                 Server configBean =
101                 ServerBeansFactory.getServerBean(configContext);
102                 assert(configBean != null);
103                 
104                 SecurityService securityBean =
105                 ServerBeansFactory.getSecurityServiceBean(configContext);
106                 assert(securityBean != null);
107                 
108                 defaultRoleName = securityBean.getAnonymousRole();
109                 
110             } catch (Exception JavaDoc e) {
111                 _logger.log(Level.WARNING,
112                 "java_security.anonymous_role_reading_exception",
113                 e);
114             }
115             
116             if(_logger.isLoggable(Level.FINE)){
117                 _logger.log(Level.FINE, "Default role is: " + defaultRoleName);
118             }
119             defaultRole = new Role(defaultRoleName);
120         }
121     }
122     
123     /** Returns a RoleMapper corresponding to the AppName.
124      * @param appName Application Name of this RoleMapper.
125      * @return SecurityRoleMapper for the application
126      */

127     public static RoleMapper getRoleMapper(String JavaDoc appName) {
128         RoleMapper r = (RoleMapper)ROLEMAPPER.get(appName);
129         if(r == null){
130             r = new RoleMapper(appName);
131             synchronized(RoleMapper.class){
132                 ROLEMAPPER.put(appName,r);
133             }
134         }
135         return r;
136     }
137     
138     /** Set a RoleMapper for the application
139      * @param appName Application or module name
140      * @param rmap <I>SecurityRoleMapper</I> for the application or the module
141      */

142     public static void setRoleMapper(String JavaDoc appName, SecurityRoleMapper rmap) {
143         synchronized(RoleMapper.class){
144             ROLEMAPPER.put(appName, rmap);
145         }
146     }
147     
148     /**
149      * @param appName Application/module name.
150      */

151     public static void removeRoleMapper(String JavaDoc appName) {
152         
153         if( ROLEMAPPER.containsKey(appName)){
154             synchronized(RoleMapper.class){
155                 ROLEMAPPER.remove(appName);
156             }
157         }
158     }
159     
160     /**
161      * @return The application/module name for this RoleMapper
162      */

163     public String JavaDoc getName() {
164         return appName;
165     }
166
167     /**
168      * @param name The application/module name
169      */

170     public void setName(String JavaDoc name) {
171         this.appName = name;
172     }
173     
174     /**
175      * @param principal A principal that corresponds to the role
176      * @param role A role corresponding to this principal
177      */

178     private void addRoleToPrincipal(final Principal JavaDoc principal, String JavaDoc role){
179         assert roleToSubject != null;
180         Subject JavaDoc subject = (Subject JavaDoc)roleToSubject.get(role);
181         final Subject JavaDoc sub = (subject == null)?new Subject JavaDoc(): subject;
182         AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
183             public java.lang.Object JavaDoc run() {
184                 sub.getPrincipals().add(principal);
185                 return null;
186             }
187         });
188         roleToSubject.put(role, sub);
189     }
190        
191     /**
192      * Remove the given role-principal mapping
193      * @param role, Role object
194      * @param principal, the principal
195      */

196     public void unassignPrincipalFromRole(Role role, Principal JavaDoc principal){
197         assert roleToSubject != null;
198         String JavaDoc mrole = role.getName();
199         final Subject JavaDoc sub = (Subject JavaDoc)roleToSubject.get(mrole);
200         final Principal JavaDoc p = principal;
201         if (sub != null){
202             AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
203                 public java.lang.Object JavaDoc run() {
204                     sub.getPrincipals().remove(p);
205                     return null;
206                 }
207             });
208             roleToSubject.put(mrole, sub);
209         }
210         Map tmp = null; // shorthand
211
tmp = (principal instanceof Group)? roleToGroup: roleToPrincipal;
212         Vector v = (Vector)tmp.get(mrole);
213         if(v != null){
214             v.remove(principal);
215             tmp.put(mrole, v);
216         }
217     }
218
219     // @return true or false depending on activation of
220
// the mapping via domain.xml.
221
static boolean isDefaultRTSMActivated() {
222     return (defaultP2RMappingClassName!=null);
223     }
224     
225     /**
226      * Returns the RoleToSubjectMapping for the RoleMapping
227      * @return Map of role->subject mapping
228      */

229     public Map getRoleToSubjectMapping(){
230         assert roleToSubject != null;
231         if (roleToSubject.isEmpty() && isDefaultRTSMActivated()) {
232             return defaultRTSM;
233         }
234         return roleToSubject;
235     }
236     
237     /**
238      * Assigns a Principal to the specified role.
239      * @param The principal that needs to be assigned to the role.
240      * @param The Role the principal is being assigned to.
241      */

242     public void assignRole(Principal JavaDoc p, Role r) {
243         String JavaDoc role = r.getName();
244         Map tmp_map = null;
245         if(_logger.isLoggable(Level.FINE)){
246             _logger.log(Level.FINE, "SECURITY:RoleMapper Assigning Role "+ role +
247                 " to "+ p.getName());
248         }
249         addRoleToPrincipal(p, role);
250         // tmp_map will never ever be null
251
tmp_map = (p instanceof Group)? roleToGroup:roleToPrincipal;
252         Vector _principals = (Vector)tmp_map.get(role) ;
253         if(_principals == null) {
254             _principals = new Vector();
255         }
256         _principals.add(p);
257         tmp_map.put(role, _principals);
258     }
259      
260     /**
261      * Returns an enumeration of roles for this rolemapper.
262      */

263     public Iterator getRoles() {
264         assert roleToSubject != null;
265         return roleToSubject.keySet().iterator(); // All the roles
266
}
267         
268     /**
269      * Returns an enumeration of Groups assigned to the given role
270      * @param The Role to which the groups are assigned to.
271      */

272     public Enumeration getGroupsAssignedTo(Role r) {
273         assert roleToGroup != null;
274         Vector v = (Vector)roleToGroup.get(r.getName());
275         v = (v == null)? new Vector(): v;
276         return v.elements();
277     }
278     
279     /**
280      * Returns an enumeration of Principals assigned to the given role
281      * @param The Role to which the principals are assigned to.
282      */

283     public Enumeration getUsersAssignedTo(Role r) {
284         assert roleToPrincipal != null;
285         Vector v = (Vector)roleToPrincipal.get(r.getName());
286         v = (v == null)? new Vector(): v;
287         return v.elements();
288     }
289     
290     public void unassignRole(Role r) {
291         if (r != null){
292             String JavaDoc role = r.getName();
293             roleToSubject.remove(role);
294             roleToPrincipal.remove(role);
295             roleToGroup.remove(role);
296         }
297     }
298
299
300     /**
301      * @return String. String representation of the RoleToPrincipal Mapping
302      */

303     public String JavaDoc toString() {
304         
305         StringBuffer JavaDoc s = new StringBuffer JavaDoc("RoleMapper:");
306         for (Iterator e = this.getRoles(); e.hasNext();) {
307             String JavaDoc r = (String JavaDoc) e.next();
308             s.append("\n\tRole (" + r + ") has Principals(");
309             Subject JavaDoc sub = (Subject JavaDoc)roleToSubject.get(r);
310             Iterator it = sub.getPrincipals().iterator();
311             for(; it.hasNext(); ){
312                 Principal JavaDoc p = (Principal JavaDoc) it.next();
313                 s.append(p.getName()+" ");
314             }
315             s.append(")");
316         }
317         if(_logger.isLoggable(Level.FINER)){
318             _logger.log(Level.FINER,s.toString());
319         }
320         return s.toString();
321     }
322     
323     
324     /** Copy constructor. This is called from the JSR88 implementation.
325      * This is not stored into the internal rolemapper maps.
326      */

327     public RoleMapper(RoleMapper r){
328         this.appName = r.getName();
329         for(Iterator it = r.getRoles();it.hasNext(); ){
330             String JavaDoc role = (String JavaDoc) it.next();
331             // recover groups
332
Enumeration groups = r.getGroupsAssignedTo(new Role(role));
333             Vector groupsToRole = new Vector();
334             for(;groups.hasMoreElements(); ){
335                 Group gp = (Group) groups.nextElement();
336                 groupsToRole.add(new Group(gp.getName()));
337                 addRoleToPrincipal(gp,role);
338             }
339             this.roleToGroup.put(role,groupsToRole);
340             
341             // recover principles
342
Enumeration users = r.getUsersAssignedTo(new Role(role));
343             Vector usersToRole = new Vector();
344             for(;users.hasMoreElements(); ){
345                 PrincipalImpl gp = (PrincipalImpl) users.nextElement();
346                 usersToRole.add(new PrincipalImpl(gp.getName()));
347                 addRoleToPrincipal(gp,role);
348             }
349             this.roleToPrincipal.put(role,usersToRole);
350         }
351     }
352
353     /**
354      * @returns the class name used for default Principal to role mapping
355      * return null if default P2R mapping is not supported.
356      */

357     static private String JavaDoc getDefaultP2RMappingClassName() {
358         if (defaultP2RMappingClassName != null )
359             return defaultP2RMappingClassName;
360
361         String JavaDoc className=null;
362         try {
363             ServerContext serverContext = ApplicationServer.getServerContext();
364             if (serverContext != null) {
365                 ConfigContext configContext = serverContext.getConfigContext();
366                 if (configContext != null) {
367                     SecurityService securityService =
368                         ServerBeansFactory.getSecurityServiceBean(configContext);
369                     if (securityService != null &&
370                         securityService.isActivateDefaultPrincipalToRoleMapping()==true) {
371                         className = securityService.getMappedPrincipalClass();
372                         if (className==null || "".equals(className))
373                 className = "com.sun.enterprise.deployment.Group";
374                     }
375                 }
376             }
377             if (className==null)
378                 return null;
379             Class JavaDoc clazz = Class.forName(className);
380             Class JavaDoc[] argClasses = new Class JavaDoc[] { String JavaDoc.class };
381             Object JavaDoc[] arg = new Object JavaDoc[] { "anystring" };
382             Constructor JavaDoc c = clazz.getConstructor(argClasses);
383             Principal JavaDoc principal = (Principal JavaDoc) c.newInstance(arg);
384                   //verify that this class is a Principal class and has a constructor(string)
385
return className;
386         } catch (Exception JavaDoc e) {
387             _logger.log(Level.SEVERE,"pc.getDefaultP2RMappingClass: " + e);
388             return null;
389         }
390     }
391
392     class DefaultRoleToSubjectMapping extends HashMap {
393         private HashMap roleMap = new HashMap();
394
395         DefaultRoleToSubjectMapping() {
396             super();
397         }
398
399         Principal JavaDoc getSameNamedPrincipal(String JavaDoc roleName) {
400             Subject JavaDoc subject = new Subject JavaDoc();
401             try {
402                 Class JavaDoc clazz = Class.forName(defaultP2RMappingClassName);
403                 Class JavaDoc[] argClasses = new Class JavaDoc[] { String JavaDoc.class };
404                 Object JavaDoc[] arg = new Object JavaDoc[] { new String JavaDoc(roleName) };
405                 Constructor JavaDoc c = clazz.getConstructor(argClasses);
406                 Principal JavaDoc principal = (Principal JavaDoc) c.newInstance(arg);
407                 return principal;
408             } catch (Exception JavaDoc e) {
409                 _logger.log(Level.SEVERE,"rm.getSameNamedPrincipal", new Object JavaDoc[]{roleName, e});
410                 throw new RuntimeException JavaDoc("Unable to get principal by default p2r mapping");
411             }
412         }
413
414         public Object JavaDoc get(Object JavaDoc key) {
415             assert key instanceof String JavaDoc;
416             synchronized (roleMap) {
417                 Subject JavaDoc s = (Subject JavaDoc)roleMap.get(key);
418                 if (s == null && key instanceof String JavaDoc) {
419                     final Subject JavaDoc fs = new Subject JavaDoc();
420                     final String JavaDoc roleName = (String JavaDoc) key;
421                     AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
422                         public java.lang.Object JavaDoc run() {
423                             fs.getPrincipals().add(getSameNamedPrincipal(roleName));
424                             return null;
425                         }
426                     });
427                     roleMap.put(key,fs);
428                     s = fs;
429                 }
430                 return s;
431             }
432         }
433     }
434 }
435
Popular Tags