KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sslexplorer > security > actions > LogonAction


1 /*
2  * SSL-Explorer
3  *
4  * Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */

19             
20 package com.sslexplorer.security.actions;
21
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24
25 import javax.servlet.http.HttpServletRequest JavaDoc;
26 import javax.servlet.http.HttpServletResponse JavaDoc;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.struts.Globals;
31 import org.apache.struts.action.Action;
32 import org.apache.struts.action.ActionForm;
33 import org.apache.struts.action.ActionForward;
34 import org.apache.struts.action.ActionMapping;
35 import org.apache.struts.action.ActionMessage;
36 import org.apache.struts.action.ActionMessages;
37
38 import com.sslexplorer.boot.ContextHolder;
39 import com.sslexplorer.boot.ContextKey;
40 import com.sslexplorer.boot.KeyStoreManager;
41 import com.sslexplorer.boot.VersionInfo;
42 import com.sslexplorer.core.BundleActionMessage;
43 import com.sslexplorer.core.CoreException;
44 import com.sslexplorer.core.CoreUtil;
45 import com.sslexplorer.core.GlobalWarning;
46 import com.sslexplorer.core.RedirectWithMessages;
47 import com.sslexplorer.core.RequestParameterMap;
48 import com.sslexplorer.core.ServletRequestAdapter;
49 import com.sslexplorer.core.UserDatabaseManager;
50 import com.sslexplorer.extensions.ExtensionBundle;
51 import com.sslexplorer.extensions.store.ExtensionStore;
52 import com.sslexplorer.policyframework.PolicyDatabaseFactory;
53 import com.sslexplorer.policyframework.PolicyUtil;
54 import com.sslexplorer.properties.Property;
55 import com.sslexplorer.properties.impl.profile.ProfilePropertyKey;
56 import com.sslexplorer.properties.impl.systemconfig.SystemConfigKey;
57 import com.sslexplorer.properties.impl.userattributes.UserAttributeKey;
58 import com.sslexplorer.security.AccountLockedException;
59 import com.sslexplorer.security.AuthenticationModule;
60 import com.sslexplorer.security.AuthenticationScheme;
61 import com.sslexplorer.security.Constants;
62 import com.sslexplorer.security.Credentials;
63 import com.sslexplorer.security.InputRequiredException;
64 import com.sslexplorer.security.InvalidLoginCredentialsException;
65 import com.sslexplorer.security.LogonController;
66 import com.sslexplorer.security.LogonControllerFactory;
67 import com.sslexplorer.security.LogonStateAndCache;
68 import com.sslexplorer.security.PasswordCredentials;
69 import com.sslexplorer.security.SessionInfo;
70 import com.sslexplorer.security.User;
71 import com.sslexplorer.security.forms.LogonForm;
72
73 /**
74  * Logs a user into the SSL Explorer.
75  *
76  * @author Lee David Painter
77  */

78 public class LogonAction extends Action {
79
80     private static Log log = LogFactory.getLog(LogonAction.class);
81
82     public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response)
83                     throws Exception JavaDoc {
84
85         ActionMessages msgs = new ActionMessages();
86
87         if (request.getSession().getAttribute(Constants.SESSION_LOCKED) == null
88                         && LogonControllerFactory.getInstance().hasClientLoggedOn(request, response) == LogonController.LOGGED_ON) {
89             if (log.isDebugEnabled())
90                 log.debug(request.getRemoteHost() + " is already authenticated");
91
92             return mapping.findForward("success");
93         }
94
95         /*
96          * Get the authentication session and module to use to validate this
97          * authentication attempt
98          */

99         AuthenticationScheme scheme = (AuthenticationScheme) request.getSession().getAttribute(Constants.AUTH_SESSION);
100         LogonStateAndCache logonStateMachine = (LogonStateAndCache) request.getSession().getAttribute(
101                         LogonStateAndCache.LOGON_STATE_MACHINE);
102
103         if (logonStateMachine == null) {
104             logonStateMachine = new LogonStateAndCache(LogonStateAndCache.STATE_STARTED, request.getSession());
105             request.getSession().setAttribute(LogonStateAndCache.LOGON_STATE_MACHINE, logonStateMachine);
106         }
107         if (scheme == null) {
108
109             ActionForward fwd = null;
110             try {
111                 fwd = ShowLogonAction.checkAuthSession(null, false, mapping, request, response, logonStateMachine);
112             } catch(CoreException ce) {
113                 
114             } catch (Throwable JavaDoc e) {
115                 log.error("Logon not allowed.", e);
116                 ActionMessages errs = new ActionMessages();
117                 if(e instanceof CoreException) {
118                     errs.add(Globals.ERROR_KEY, ((CoreException)e).getBundleActionMessage());
119                 }
120                 else {
121                     errs.add(Globals.ERROR_KEY, new ActionMessage("login.logonNotAllowed",
122                                     "Please contact your administrator."));
123                 }
124                 saveErrors(request, errs);
125                 request.getSession().removeAttribute(LogonStateAndCache.LOGON_STATE_MACHINE);
126                 if (form != null)
127                     form.reset(mapping, request);
128                 return new RedirectWithMessages(mapping.findForward("failed"), request);
129             }
130             if (fwd != null) {
131                 scheme = (AuthenticationScheme) request.getSession().getAttribute(Constants.AUTH_SESSION);
132             }
133         }
134
135         if (scheme != null) {
136             AuthenticationModule module = scheme.currentAuthenticationModule();
137             if (module == null) {
138                 log.error("No authentication module.");
139                 request.getSession().removeAttribute(Constants.AUTH_SESSION);
140                 return mapping.findForward("logon");
141             }
142
143             try {
144                 // If there is no user in the scheme then it is an invalid login
145
if(scheme.getUser() == null) {
146                     throw new InvalidLoginCredentialsException();
147                 }
148                 
149                 // Check the account is enabled and not locked
150
if(!PolicyUtil.isEnabled(scheme.getUser())) {
151                     throw new AccountLockedException(scheme.getUsername(), "Account disabled.", true, 0);
152                 }
153                 
154                 // Check for locks
155
LogonControllerFactory.getInstance().checkForAccountLock(scheme.getUsername(), scheme.getUser().getRealm().getResourceName());
156
157                 // Authenticate
158
authenticate(scheme, request);
159
160                 // Check logon is currently allowed
161
String JavaDoc logonNotAllowedReason = LogonControllerFactory.getInstance().checkLogonAllowed(
162                                 scheme.getUser());
163
164                 if (logonNotAllowedReason != null) {
165                     log.warn("Logon not allowed because '" + logonNotAllowedReason + "'");
166                     msgs.add(Globals.ERROR_KEY, new ActionMessage("login.logonNotAllowed", logonNotAllowedReason));
167                     saveErrors(request, msgs);
168                     return new RedirectWithMessages(mapping.findForward("logon"), request);
169                 }
170
171                 // Check for the next authentication modules
172
AuthenticationModule nextModule = scheme.nextAuthenticationModule();
173                 if (nextModule != null && request.getSession().getAttribute(Constants.SESSION_LOCKED) == null) {
174                     if (log.isDebugEnabled())
175                         log.debug("There are more authentication modules to satisfy (current mapping = " + mapping.getPath());
176                     ActionForward fw = new RedirectWithMessages(mapping.findForward("logon"), request);
177                     return fw;
178                 }
179
180                 return finishAuthentication(scheme, request, response);
181             } catch (InputRequiredException ex) {
182                 // The page wants to display or redirect somewhere
183
if(ex.getForward()==null)
184                     return mapping.findForward("logon");
185                 else
186                     return ex.getForward();
187             } catch (AccountLockedException ale) {
188                 return accountLocked(mapping, request, ale, msgs);
189             } catch (InvalidLoginCredentialsException ex) {
190                 log.error("[" + request.getRemoteHost()
191                     + "] authentication failed", ex);
192                 
193                 request.getSession().removeAttribute(LogonStateAndCache.LOGON_STATE_MACHINE);
194                 request.getSession().removeAttribute(Constants.AUTH_SESSION);
195
196                 try {
197                     scheme.setAccountLock(LogonControllerFactory.getInstance().logonFailed(((LogonForm)form).getUsername(),
198                                     ((LogonForm)form).getRealmName(), scheme.getAccountLock()));
199                 } catch (AccountLockedException ale) {
200                     return accountLocked(mapping, request, ale, msgs);
201                 }
202
203                 msgs.add(Globals.ERROR_KEY, new ActionMessage("login.invalidCredentials"));
204                 saveErrors(request, msgs);
205                 return new RedirectWithMessages(mapping.findForward("logon"), request);
206             } catch (Exception JavaDoc e) {
207                 log.error("Internal error authenticating.", e);
208                 msgs.add(Globals.ERROR_KEY, new BundleActionMessage("security", "login.error", e.getMessage()));
209                 saveErrors(request, msgs);
210                 request.getSession().setAttribute(Constants.EXCEPTION, e);
211                 request.getSession().removeAttribute(LogonStateAndCache.LOGON_STATE_MACHINE);
212                 request.getSession().removeAttribute(Constants.AUTH_SESSION);
213                 return new RedirectWithMessages(mapping.findForward("logon"), request);
214             }
215         } else {
216             ActionMessages errs = new ActionMessages();
217             errs.add(Globals.MESSAGE_KEY, new BundleActionMessage("security", "login.logonNotAllowed", "No scheme available."));
218             saveErrors(request, errs);
219             request.getSession().removeAttribute(LogonStateAndCache.LOGON_STATE_MACHINE);
220             request.getSession().removeAttribute(Constants.AUTH_SESSION);
221             if (form != null)
222                 form.reset(mapping, request);
223             return new RedirectWithMessages(mapping.findForward("logon"), request);
224         }
225     }
226
227     /**
228      * Complete the authentication process.
229      *
230      * @param scheme scheme
231      * @param request request
232      * @param response response
233      * @return forward to
234      * @throws Exception on any error
235      */

236     public static ActionForward finishAuthentication(AuthenticationScheme scheme, HttpServletRequest JavaDoc request,
237                     HttpServletResponse JavaDoc response) throws Exception JavaDoc {
238
239         // Check we have a user object
240
if (scheme.getUser() == null) {
241             throw new Exception JavaDoc("No authentication module provided a user.");
242         }
243
244         // now add the policies associated with this scheme to the http session
245
// if the property says so.
246
if (Property.getPropertyBoolean(new SystemConfigKey("security.enforce.policy.resource.access"))) {
247             List JavaDoc signOnPolicies = PolicyDatabaseFactory.getInstance().getPoliciesAttachedToResource(scheme,
248                             scheme.getUser().getRealm());
249             scheme.getServletSession().setAttribute("auth.scheme.policies", signOnPolicies);
250         }
251
252         // If the user is a manager, check if there is a new SSL-Explorer
253
// version, or if there any exension updates
254
if (PolicyDatabaseFactory.getInstance().isAnyAccessRightAllowed(scheme.getUser(), true, true, false)) {
255             
256             if ("false".equals(Property.getProperty(new ContextKey("webServer.disableCertificateWarning")))
257                             && !KeyStoreManager.getInstance(KeyStoreManager.DEFAULT_KEY_STORE).isCertificateTrusted(
258                                             Property.getProperty(new ContextKey("webServer.alias")))) {
259                 CoreUtil.addMultipleGlobalWarning(GlobalWarning.MANAGEMENT_USERS, new BundleActionMessage("keystore",
260                                 "keyStore.untrustedCertificate.warning"));
261             }
262             
263         }
264
265         /*
266          * Each authentication module needs to be informed that authentication
267          * is now complete so it may perform any last minute checks
268          */

269         scheme.authenticationComplete(request, response);
270
271         // Allow the home page to be redirected.
272
request.getSession().setAttribute(Constants.REDIRECT_HOME, "true");
273
274         // Authenitcation sequence complete
275
if (log.isDebugEnabled())
276             log.debug(scheme.getUsername() + " [" + request.getRemoteHost() + "] has been authenticated");
277
278         // Forward control to the specified success URI (possibly from the
279
// initial unautenticated request)
280
String JavaDoc originalRequest = (String JavaDoc) request.getSession().getAttribute(Constants.ORIGINAL_REQUEST);
281         ActionForward forward = null;
282
283         // Where next?
284
List JavaDoc profiles = (List JavaDoc)request.getSession().getAttribute(Constants.PROFILES);
285         int selectProfileAtLogin = -1;
286         try {
287             selectProfileAtLogin = Property.getPropertyInt(new UserAttributeKey(scheme.getUser(), User.USER_STARTUP_PROFILE));
288         }
289         catch(NumberFormatException JavaDoc nfe) {
290         }
291         if (selectProfileAtLogin == -1 && profiles != null && profiles.size() > 1) {
292             // Prompt for the profile
293
forward = new ActionForward("/showSelectPropertyProfile.do");
294         } else {
295             if(null == originalRequest || "/showHome.do".equals(originalRequest) || "".equals(originalRequest)) {
296                 boolean admin = LogonControllerFactory.getInstance().isAdministrator(scheme.getUser());
297                 if (admin) {
298                     originalRequest = "/showSystemConfiguration.do";
299                 } else {
300                     originalRequest = "/showHome.do";
301                 }
302                 request.getSession().removeAttribute(Constants.ORIGINAL_REQUEST);
303             }
304             if (Property.getPropertyBoolean(new ProfilePropertyKey("client.autoStart"))) {
305                 request.getSession().removeAttribute(Constants.ORIGINAL_REQUEST);
306                 request.getSession().setAttribute(Constants.REQ_ATTR_LAUNCH_AGENT_REFERER, originalRequest);
307                 forward = new ActionForward("/launchAgent.do", false);
308             } else {
309                 forward = new ActionForward(originalRequest, true);
310             }
311         }
312         return forward;
313
314     }
315
316     /**
317      * Start the authentication process.
318      *
319      * @param scheme scheme
320      * @param request request
321      * @throws Exception on any error
322      */

323     public static void authenticate(AuthenticationScheme scheme, HttpServletRequest JavaDoc request) throws Exception JavaDoc {
324         AuthenticationModule module = scheme.currentAuthenticationModule();
325         if (module == null) {
326             throw new Exception JavaDoc("No current authentication module");
327         }
328         RequestParameterMap params = new RequestParameterMap(new ServletRequestAdapter(request));
329         User currentUser = scheme.getUser();
330         LogonStateAndCache logonStateMachine = (LogonStateAndCache) request.getSession().getAttribute(
331                         LogonStateAndCache.LOGON_STATE_MACHINE);
332
333         if (logonStateMachine == null) {
334             logonStateMachine = new LogonStateAndCache(LogonStateAndCache.STATE_STARTED, request.getSession());
335         }
336
337         if (logonStateMachine.getState() == LogonStateAndCache.STATE_KNOWN_USERNAME_NO_SCHEME_SPOOF_PASSWORD_ENTRY) {
338             scheme.addCredentials(new PasswordCredentials("", "".toCharArray()));
339         } else if (logonStateMachine.getState() == LogonStateAndCache.STATE_UNKNOWN_USERNAME_PROMPT_FOR_PASSWORD) {
340             Credentials creds = module.authenticate(request, params);
341             if(creds!=null)
342                 scheme.addCredentials(creds);
343         } else {
344             Credentials creds = module.authenticate(request, params);
345             if(creds!=null)
346                 scheme.addCredentials(creds);
347             logonStateMachine.setState(LogonStateAndCache.STATE_VALID_LOGON);
348             // Check we have a user object
349
if (currentUser == null && scheme.getUser() == null) {
350                 throw new Exception JavaDoc("The first authentication did not provide a user.");
351             }
352         }
353
354         PolicyUtil.checkLogin(scheme.getUser());
355     }
356
357     /**
358      * Set an account to be locked and create the appropriate error messages
359      *
360      * @param mapping mapping
361      * @param request request
362      * @param ale lock exception
363      * @param msgs messages
364      * @return forward
365      */

366     ActionForward accountLocked(ActionMapping mapping, HttpServletRequest JavaDoc request, AccountLockedException ale,
367                                                 ActionMessages msgs) {
368
369         request.getSession().removeAttribute(Constants.AUTH_SESSION);
370         request.getSession().removeAttribute(LogonStateAndCache.LOGON_STATE_MACHINE);
371         msgs.add(Globals.ERROR_KEY, new ActionMessage(ale.isDisabled() ? "login.accountDisabled" : "login.accountLocked",
372                         String.valueOf(((ale.getTimeLeft() / 1000) + 59) / 60)));
373         log.warn(ale.getUsername() + " [" + request.getRemoteHost() + "] account locked", ale);
374         saveErrors(request, msgs);
375         return new RedirectWithMessages(mapping.findForward("logon"), request);
376     }
377
378 }
Popular Tags