KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > web > tomcat > security > authorization > delegates > WebJACCPolicyModuleDelegate


1 /*
2  * JBoss, Home of Professional Open Source
3  * Copyright 2005, JBoss Inc., and individual contributors as indicated
4  * by the @authors tag. See the copyright.txt in the distribution for a
5  * full listing of individual contributors.
6  *
7  * This is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this software; if not, write to the Free
19  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21  */

22 package org.jboss.web.tomcat.security.authorization.delegates;
23
24 import java.io.IOException JavaDoc;
25 import java.security.CodeSource JavaDoc;
26 import java.security.Permission JavaDoc;
27 import java.security.Policy JavaDoc;
28 import java.security.Principal JavaDoc;
29 import java.security.ProtectionDomain JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Set JavaDoc;
32
33 import javax.security.auth.Subject JavaDoc;
34 import javax.security.jacc.WebResourcePermission JavaDoc;
35 import javax.security.jacc.WebRoleRefPermission JavaDoc;
36 import javax.security.jacc.WebUserDataPermission JavaDoc;
37 import javax.servlet.http.HttpServletRequest JavaDoc;
38
39 import org.apache.catalina.Context;
40 import org.apache.catalina.connector.Request;
41 import org.apache.catalina.connector.Response;
42 import org.apache.catalina.deploy.SecurityConstraint;
43 import org.jboss.logging.Logger;
44 import org.jboss.security.authorization.AuthorizationContext;
45 import org.jboss.security.authorization.PolicyRegistration;
46 import org.jboss.security.authorization.Resource;
47 import org.jboss.security.authorization.ResourceKeys;
48 import org.jboss.security.authorization.modules.AuthorizationModuleDelegate;
49 import org.jboss.web.tomcat.security.JaccContextValve;
50
51
52 //$Id: WebJACCPolicyModuleDelegate.java 46512 2006-07-26 03:35:54Z asaldhana $
53

54 /**
55  * JACC based authorization module helper that deals with the web layer
56  * authorization decisions
57  * @author <a HREF="mailto:Anil.Saldhana@jboss.org">Anil Saldhana</a>
58  * @since July 7, 2006
59  * @version $Revision: 46512 $
60  */

61 public class WebJACCPolicyModuleDelegate extends AuthorizationModuleDelegate
62 {
63    private Policy JavaDoc policy = Policy.getPolicy();
64
65    public WebJACCPolicyModuleDelegate()
66    {
67       log = Logger.getLogger(WebJACCPolicyModuleDelegate.class);
68       trace = log.isTraceEnabled();
69    }
70
71    /**
72     * @see AuthorizationModuleDelegate#authorize(Resource)
73     */

74    public int authorize(Resource resource)
75    {
76       //Get the contextual map
77
Map JavaDoc map = resource.getMap();
78       if(map == null)
79          throw new IllegalStateException JavaDoc("Map from the Resource is null");
80
81       if(map.size() == 0)
82          throw new IllegalStateException JavaDoc("Map from the Resource is size zero");
83       //Get the Catalina Request Object
84
Request JavaDoc request = (Request JavaDoc)map.get(ResourceKeys.WEB_REQUEST);
85       Response response = (Response)map.get(ResourceKeys.WEB_RESPONSE);
86       SecurityConstraint[] constraints = (SecurityConstraint[])
87                                     map.get(ResourceKeys.WEB_SECURITY_CONSTRAINTS);
88       Context context = (Context)map.get(ResourceKeys.WEB_CONTEXT);
89       //Obtained by establishing subject context
90
Subject JavaDoc callerSubject = (Subject JavaDoc)map.get(ResourceKeys.CALLER_SUBJECT);
91       String JavaDoc roleName = (String JavaDoc)map.get(ResourceKeys.ROLENAME);
92       Principal JavaDoc principal = (Principal JavaDoc)map.get(ResourceKeys.HASROLE_PRINCIPAL);
93       Set JavaDoc roles = (Set JavaDoc)map.get(ResourceKeys.PRINCIPAL_ROLES);
94       String JavaDoc servletName = (String JavaDoc)map.get(ResourceKeys.SERVLET_NAME);
95       Boolean JavaDoc resourceCheck = checkBooleanValue((Boolean JavaDoc)map.get(ResourceKeys.RESOURCE_PERM_CHECK));
96       Boolean JavaDoc userDataCheck = checkBooleanValue((Boolean JavaDoc)map.get(ResourceKeys.USERDATA_PERM_CHECK));
97       Boolean JavaDoc roleRefCheck = checkBooleanValue((Boolean JavaDoc)map.get(ResourceKeys.ROLEREF_PERM_CHECK));
98       
99       validatePermissionChecks(resourceCheck,userDataCheck,roleRefCheck);
100       
101       boolean decision = false;
102       
103       try
104       {
105          if(resourceCheck)
106             decision = this.hasResourcePermission(request, response, constraints, context, callerSubject);
107          else
108             if(userDataCheck)
109                decision = this.hasUserDataPermission(request, response, constraints);
110             else
111                if(roleRefCheck)
112                  decision = this.hasRole(principal, roleName, roles, servletName);
113                else
114                   if(trace)
115                      log.trace("Check is not for resourcePerm, userDataPerm or roleRefPerm.");
116       }
117       catch(IOException JavaDoc ioe)
118       {
119          if(trace)
120             log.trace("IOException:",ioe);
121       }
122       return decision ? AuthorizationContext.PERMIT : AuthorizationContext.DENY;
123    }
124
125    /**
126     * @see AuthorizationModuleDelegate#setPolicyRegistrationManager(PolicyRegistration)
127     */

128    public void setPolicyRegistrationManager(PolicyRegistration authzM)
129    {
130      this.authzManager = authzM;
131    }
132    
133    /**
134     * Get the canonical request uri from the request mapping data requestPath
135     * @param request
136     * @return the request URI path
137     */

138    static String JavaDoc requestURI(Request JavaDoc request)
139    {
140       String JavaDoc uri = request.getMappingData().requestPath.getString();
141       if( uri == null || uri.equals("/") )
142       {
143          uri = "";
144       }
145       return uri;
146    }
147
148    //****************************************************************************
149
// PRIVATE METHODS
150
//****************************************************************************
151
/** See if the given JACC permission is implied using the caller as
152     * obtained from either the
153     * PolicyContext.getContext(javax.security.auth.Subject.container) or
154     * the info associated with the requestPrincipal.
155     *
156     * @param perm - the JACC permission to check
157     * @param requestPrincpal - the http request getPrincipal
158     * @param caller the authenticated subject obtained by establishSubjectContext
159     * @return true if the permission is allowed, false otherwise
160     */

161    private boolean checkSecurityAssociation(Permission JavaDoc perm, Principal JavaDoc requestPrincpal,
162          Subject JavaDoc caller)
163    {
164       // Get the caller principals, its null if there is no caller
165
Principal JavaDoc[] principals = null;
166       if( caller != null )
167       {
168          if( trace )
169             log.trace("No active subject found, using ");
170          Set JavaDoc principalsSet = caller.getPrincipals();
171          principals = new Principal JavaDoc[principalsSet.size()];
172          principalsSet.toArray(principals);
173       }
174       return checkSecurityAssociation(perm, principals);
175    }
176    
177    
178    /** See if the given permission is implied by the Policy. This calls
179     * Policy.implies(pd, perm) with the ProtectionDomain built from the
180     * active CodeSource set by the JaccContextValve, and the given
181     * principals.
182     *
183     * @param perm - the JACC permission to evaluate
184     * @param principals - the possibly null set of principals for the caller
185     * @return true if the permission is allowed, false otherwise
186     */

187    private boolean checkSecurityAssociation(Permission JavaDoc perm, Principal JavaDoc[] principals)
188    {
189       CodeSource JavaDoc webCS = (CodeSource JavaDoc) JaccContextValve.activeCS.get();
190       ProtectionDomain JavaDoc pd = new ProtectionDomain JavaDoc(webCS, null, null, principals);
191       boolean allowed = policy.implies(pd, perm);
192       if( trace )
193       {
194          String JavaDoc msg = (allowed ? "Allowed: " : "Denied: ") +perm;
195          log.trace(msg);
196       }
197       return allowed;
198    }
199    
200    /**
201     * Ensure that the bool is a valid value
202     * @param bool
203     * @return bool or Boolean.FALSE (when bool is null)
204     */

205    private Boolean JavaDoc checkBooleanValue(Boolean JavaDoc bool)
206    {
207       if(bool == null)
208          return Boolean.FALSE;
209       return bool;
210    }
211
212    
213    /**
214     * Perform hasResourcePermission Check
215     * @param request
216     * @param response
217     * @param securityConstraints
218     * @param context
219     * @param caller
220     * @return
221     * @throws IOException
222     */

223    private boolean hasResourcePermission(Request JavaDoc request, Response response,
224          SecurityConstraint[] securityConstraints, Context context, Subject JavaDoc caller)
225    throws IOException JavaDoc
226    {
227       Principal JavaDoc requestPrincipal = request.getPrincipal();
228       HttpServletRequest JavaDoc httpRequest = request.getRequest();
229       String JavaDoc uri = requestURI(request);
230       WebResourcePermission JavaDoc perm = new WebResourcePermission JavaDoc(uri, httpRequest.getMethod());
231       boolean allowed = checkSecurityAssociation(perm, requestPrincipal, caller );
232       if( trace )
233          log.trace("hasResourcePermission, perm="+perm+", allowed="+allowed);
234       return allowed;
235    }
236
237    /**
238     * Perform hasRole check
239     * @param principal
240     * @param role
241     * @param roles
242     * @return
243     */

244    private boolean hasRole(Principal JavaDoc principal, String JavaDoc roleName, Set JavaDoc roles, String JavaDoc servletName)
245    {
246       WebRoleRefPermission JavaDoc perm = new WebRoleRefPermission JavaDoc(servletName, roleName);
247       Principal JavaDoc[] principals = {principal};
248       if( roles != null )
249       {
250          principals = new Principal JavaDoc[roles.size()];
251          roles.toArray(principals);
252       }
253       boolean allowed = checkSecurityAssociation(perm, principals);
254       if( trace )
255          log.trace("hasRole, perm="+perm+", allowed="+allowed);
256       return allowed;
257    }
258
259    /**
260     * Perform hasUserDataPermission check for the realm.
261     * If this module returns false, the base class (Realm) will
262     * make the decision as to whether a redirection to the ssl
263     * port needs to be done
264     * @param request
265     * @param response
266     * @param constraints
267     * @return
268     * @throws IOException
269     */

270    private boolean hasUserDataPermission(Request JavaDoc request, Response response,
271          SecurityConstraint[] constraints) throws IOException JavaDoc
272    {
273       HttpServletRequest JavaDoc httpRequest = request.getRequest();
274       String JavaDoc uri = requestURI(request);
275       WebUserDataPermission JavaDoc perm = new WebUserDataPermission JavaDoc(uri, httpRequest.getMethod());
276       if( trace )
277          log.trace("hasUserDataPermission, p="+perm);
278       boolean ok = false;
279       try
280       {
281          Principal JavaDoc[] principals = null;
282          ok = checkSecurityAssociation(perm, principals);
283       }
284       catch(Exception JavaDoc e)
285       {
286          if( trace )
287             log.trace("Failed to checkSecurityAssociation", e);
288       }
289       return ok;
290    }
291
292    /**
293     * Validate that the access check is made only for one of the
294     * following
295     * @param resourceCheck
296     * @param userDataCheck
297     * @param roleRefCheck
298     */

299    private void validatePermissionChecks(Boolean JavaDoc resourceCheck,
300          Boolean JavaDoc userDataCheck, Boolean JavaDoc roleRefCheck)
301    {
302       if(trace)
303          log.trace("resourceCheck="+resourceCheck + " : userDataCheck=" + userDataCheck
304                + " : roleRefCheck=" + roleRefCheck);
305       if((resourceCheck == Boolean.TRUE && userDataCheck == Boolean.TRUE && roleRefCheck == Boolean.TRUE )
306            || (resourceCheck == Boolean.TRUE && userDataCheck == Boolean.TRUE)
307            || (userDataCheck == Boolean.TRUE && roleRefCheck == Boolean.TRUE))
308          throw new IllegalStateException JavaDoc("Permission checks must be different");
309    }
310 }
311
Popular Tags