KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > jetty > interceptor > SecurityContextBeforeAfter


1 /**
2  *
3  * Copyright 2003-2004 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.geronimo.jetty.interceptor;
18
19 import java.io.IOException JavaDoc;
20 import java.security.AccessControlContext JavaDoc;
21 import java.security.AccessControlException JavaDoc;
22 import java.security.PermissionCollection JavaDoc;
23 import java.security.Principal JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.Set JavaDoc;
26 import javax.security.auth.Subject JavaDoc;
27 import javax.security.jacc.PolicyContext JavaDoc;
28 import javax.security.jacc.PolicyContextException JavaDoc;
29 import javax.security.jacc.WebResourcePermission JavaDoc;
30 import javax.security.jacc.WebUserDataPermission JavaDoc;
31 import javax.servlet.http.HttpServletRequest JavaDoc;
32
33 import org.apache.geronimo.common.GeronimoSecurityException;
34 import org.apache.geronimo.jetty.JAASJettyPrincipal;
35 import org.apache.geronimo.security.ContextManager;
36 import org.apache.geronimo.security.IdentificationPrincipal;
37 import org.apache.geronimo.security.SubjectId;
38 import org.apache.geronimo.security.deploy.DefaultPrincipal;
39 import org.apache.geronimo.security.util.ConfigurationUtil;
40 import org.mortbay.http.Authenticator;
41 import org.mortbay.http.HttpException;
42 import org.mortbay.http.HttpRequest;
43 import org.mortbay.http.HttpResponse;
44 import org.mortbay.http.SecurityConstraint;
45 import org.mortbay.http.UserRealm;
46 import org.mortbay.jetty.servlet.FormAuthenticator;
47 import org.mortbay.jetty.servlet.ServletHttpRequest;
48
49
50 /**
51  * @version $Rev: $ $Date: $
52  */

53 public class SecurityContextBeforeAfter implements BeforeAfter {
54
55     private final BeforeAfter next;
56     private final int policyContextIDIndex;
57     private final int webAppContextIndex;
58     private final String JavaDoc policyContextID;
59     private final static ThreadLocal JavaDoc currentWebAppContext = new ThreadLocal JavaDoc();
60     private final Map JavaDoc roleDesignates;
61     private final JAASJettyPrincipal defaultPrincipal;
62
63     private final String JavaDoc formLoginPath;
64
65     private final PermissionCollection JavaDoc checked;
66     private final PermissionCollection JavaDoc excludedPermissions;
67     private final Authenticator authenticator;
68
69     private final UserRealm realm;
70
71     public SecurityContextBeforeAfter(BeforeAfter next,
72                                       int policyContextIDIndex,
73                                       int webAppContextIndex,
74                                       String JavaDoc policyContextID,
75                                       DefaultPrincipal defaultPrincipal,
76                                       Authenticator authenticator,
77                                       PermissionCollection JavaDoc checkedPermissions,
78                                       PermissionCollection JavaDoc excludedPermissions,
79                                       Map JavaDoc roleDesignates,
80                                       UserRealm realm) {
81         this.next = next;
82         this.policyContextIDIndex = policyContextIDIndex;
83         this.webAppContextIndex = webAppContextIndex;
84         this.policyContextID = policyContextID;
85
86         this.defaultPrincipal = generateDefaultPrincipal(defaultPrincipal);
87         this.roleDesignates = roleDesignates;
88         this.checked = checkedPermissions;
89         this.excludedPermissions = excludedPermissions;
90
91         if (authenticator instanceof FormAuthenticator) {
92             String JavaDoc formLoginPath = ((FormAuthenticator) authenticator).getLoginPage();
93             if (formLoginPath.indexOf('?') > 0) {
94                 formLoginPath = formLoginPath.substring(0, formLoginPath.indexOf('?'));
95             }
96             this.formLoginPath = formLoginPath;
97         } else {
98             formLoginPath = null;
99         }
100
101         this.authenticator = authenticator;
102         /**
103          * Register our default principal with the ContextManager
104          */

105         Subject JavaDoc defaultSubject = this.defaultPrincipal.getSubject();
106         ContextManager.registerSubject(defaultSubject);
107         SubjectId id = ContextManager.getSubjectId(defaultSubject);
108         defaultSubject.getPrincipals().add(new IdentificationPrincipal(id));
109
110 // log.debug("Default subject " + id + " for JACC policy '" + policyContextID + "' registered.");
111

112
113         this.realm = realm;
114 // log.info("JettyWebAppJACCContext started with JACC policy '" + policyContextID + "'");
115
}
116
117     public void stop() {
118         Subject JavaDoc defaultSubject = this.defaultPrincipal.getSubject();
119         ContextManager.unregisterSubject(defaultSubject);
120     }
121
122     public void before(Object JavaDoc[] context, HttpRequest httpRequest, HttpResponse httpResponse) {
123         context[policyContextIDIndex] = PolicyContext.getContextID();
124         context[webAppContextIndex] = getCurrentSecurityInterceptor();
125
126         PolicyContext.setContextID(policyContextID);
127         setCurrentSecurityInterceptor(this);
128
129         if (httpRequest != null){
130             ServletHttpRequest request = (ServletHttpRequest)httpRequest.getWrapper();
131             PolicyContext.setHandlerData((HttpServletRequest JavaDoc)request);
132         }
133
134         if (next != null) {
135             next.before(context, httpRequest, httpResponse);
136         }
137     }
138
139     public void after(Object JavaDoc[] context, HttpRequest httpRequest, HttpResponse httpResponse) {
140         if (next != null) {
141             next.after(context, httpRequest, httpResponse);
142         }
143         setCurrentSecurityInterceptor((SecurityContextBeforeAfter) context[webAppContextIndex]);
144         PolicyContext.setContextID((String JavaDoc) context[policyContextIDIndex]);
145     }
146
147     private static void setCurrentSecurityInterceptor(SecurityContextBeforeAfter context) {
148         SecurityManager JavaDoc sm = System.getSecurityManager();
149         if (sm != null) sm.checkPermission(ContextManager.SET_CONTEXT);
150
151         currentWebAppContext.set(context);
152     }
153
154     private static SecurityContextBeforeAfter getCurrentSecurityInterceptor() {
155         SecurityManager JavaDoc sm = System.getSecurityManager();
156         if (sm != null) sm.checkPermission(ContextManager.GET_CONTEXT);
157
158         return (SecurityContextBeforeAfter) currentWebAppContext.get();
159     }
160
161     public static Subject JavaDoc getCurrentRoleDesignate(String JavaDoc role) {
162         return getCurrentSecurityInterceptor().getRoleDesignate(role);
163     }
164
165     private Subject JavaDoc getRoleDesignate(String JavaDoc roleName) {
166         return (Subject JavaDoc) roleDesignates.get(roleName);
167     }
168
169     //security check methods, delegated from WebAppContext
170

171     /**
172      * Check the security constraints using JACC.
173      *
174      * @param pathInContext path in context
175      * @param request HTTP request
176      * @param response HTTP response
177      * @return true if the path in context passes the security check,
178      * false if it fails or a redirection has occured during authentication.
179      */

180     public boolean checkSecurityConstraints(String JavaDoc pathInContext, HttpRequest request, HttpResponse response) throws HttpException, IOException JavaDoc {
181         if (formLoginPath != null) {
182             String JavaDoc pathToBeTested = (pathInContext.indexOf('?') > 0 ? pathInContext.substring(0, pathInContext.indexOf('?')) : pathInContext);
183
184             if (pathToBeTested.equals(formLoginPath)) {
185                 return true;
186             }
187         }
188
189         try {
190             Principal JavaDoc user = obtainUser(pathInContext, request, response);
191
192             if (user == null) {
193                 return false;
194             }
195             if (user == SecurityConstraint.__NOBODY) {
196                 return true;
197             }
198
199             AccessControlContext JavaDoc acc = ContextManager.getCurrentContext();
200             ServletHttpRequest servletHttpRequest = (ServletHttpRequest) request.getWrapper();
201
202             /**
203              * JACC v1.0 secion 4.1.1
204              */

205
206             String JavaDoc transportType;
207             if (request.isConfidential()) {
208                 transportType = "CONFIDENTIAL";
209             } else if (request.isIntegral()) {
210                 transportType = "INTEGRAL";
211             } else {
212                 transportType = "NONE";
213             }
214             WebUserDataPermission JavaDoc wudp = new WebUserDataPermission JavaDoc(servletHttpRequest.getServletPath(), new String JavaDoc[]{servletHttpRequest.getMethod()}, transportType);
215             acc.checkPermission(wudp);
216
217             /**
218              * JACC v1.0 secion 4.1.2
219              */

220             acc.checkPermission(new WebResourcePermission JavaDoc(servletHttpRequest));
221         } catch (HttpException he) {
222             response.sendError(he.getCode(), he.getReason());
223             return false;
224         } catch (AccessControlException JavaDoc ace) {
225             response.sendError(HttpResponse.__403_Forbidden);
226             return false;
227         }
228         return true;
229     }
230
231     /**
232      * Obtain an authenticated user, if one is required. Otherwise return the
233      * default principal.
234      * <p/>
235      * Also set the current caller for JACC security checks for the default
236      * principal. This is automatically done by <code>JAASJettyRealm</code>.
237      *
238      * @param pathInContext path in context
239      * @param request HTTP request
240      * @param response HTTP response
241      * @return <code>null</code> if there is no authenticated user at the moment
242      * and security checking should not proceed and servlet handling should also
243      * not proceed, e.g. redirect. <code>SecurityConstraint.__NOBODY</code> if
244      * security checking should not proceed and servlet handling should proceed,
245      * e.g. login page.
246      */

247     private Principal JavaDoc obtainUser(String JavaDoc pathInContext, HttpRequest request, HttpResponse response) throws IOException JavaDoc, IOException JavaDoc {
248         ServletHttpRequest servletHttpRequest = (ServletHttpRequest) request.getWrapper();
249         WebResourcePermission JavaDoc resourcePermission = new WebResourcePermission JavaDoc(servletHttpRequest);
250         WebUserDataPermission JavaDoc dataPermission = new WebUserDataPermission JavaDoc(servletHttpRequest);
251         boolean unauthenticated = !(checked.implies(resourcePermission) || checked.implies(dataPermission));
252         boolean forbidden = excludedPermissions.implies(resourcePermission) || excludedPermissions.implies(dataPermission);
253
254 // Authenticator authenticator = getAuthenticator();
255
Principal JavaDoc user = null;
256         if (!unauthenticated && !forbidden) {
257             if (realm == null) {
258 // log.warn("Realm Not Configured");
259
throw new HttpException(HttpResponse.__500_Internal_Server_Error, "Realm Not Configured");
260             }
261
262
263             // Handle pre-authenticated request
264
if (authenticator != null) {
265                 // User authenticator.
266
user = authenticator.authenticate(realm, pathInContext, request, response);
267             } else {
268                 // don't know how authenticate
269
// log.warn("Mis-configured Authenticator for " + request.getPath());
270
throw new HttpException(HttpResponse.__500_Internal_Server_Error, "Mis-configured Authenticator for " + request.getPath());
271             }
272
273             return user;
274         } else if (authenticator instanceof FormAuthenticator && pathInContext.endsWith(FormAuthenticator.__J_SECURITY_CHECK)) {
275             /**
276              * This could be a post request to __J_SECURITY_CHECK.
277              */

278             if (realm == null) {
279 // log.warn("Realm Not Configured");
280
throw new HttpException(HttpResponse.__500_Internal_Server_Error, "Realm Not Configured");
281             }
282             return authenticator.authenticate(realm, pathInContext, request, response);
283         }
284
285         /**
286          * No authentication is required. Return the defaultPrincipal.
287          */

288         ContextManager.setCurrentCaller(defaultPrincipal.getSubject());
289         return defaultPrincipal;
290     }
291
292
293     /**
294      * Generate the default principal from the security config.
295      *
296      * @param defaultPrincipal The Geronimo security configuration.
297      * @return the default principal
298      */

299     protected JAASJettyPrincipal generateDefaultPrincipal(DefaultPrincipal defaultPrincipal) throws GeronimoSecurityException {
300
301         if (defaultPrincipal == null) {
302             throw new GeronimoSecurityException("Unable to generate default principal");
303         }
304
305         JAASJettyPrincipal result = new JAASJettyPrincipal("default");
306         Subject JavaDoc defaultSubject = ConfigurationUtil.generateDefaultSubject(defaultPrincipal);
307
308         result.setSubject(defaultSubject);
309
310         return result;
311     }
312
313 }
314
Popular Tags