1   /**
2    * Copyright (c) 2000-2007 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.action;
24  
25  import com.liferay.portal.CookieNotSupportedException;
26  import com.liferay.portal.NoSuchUserException;
27  import com.liferay.portal.PasswordExpiredException;
28  import com.liferay.portal.PortalException;
29  import com.liferay.portal.SendPasswordException;
30  import com.liferay.portal.SystemException;
31  import com.liferay.portal.UserEmailAddressException;
32  import com.liferay.portal.UserIdException;
33  import com.liferay.portal.UserLockoutException;
34  import com.liferay.portal.UserPasswordException;
35  import com.liferay.portal.UserScreenNameException;
36  import com.liferay.portal.captcha.CaptchaTextException;
37  import com.liferay.portal.captcha.CaptchaUtil;
38  import com.liferay.portal.kernel.servlet.HttpHeaders;
39  import com.liferay.portal.kernel.util.Constants;
40  import com.liferay.portal.kernel.util.GetterUtil;
41  import com.liferay.portal.kernel.util.ParamUtil;
42  import com.liferay.portal.kernel.util.StringMaker;
43  import com.liferay.portal.kernel.util.StringPool;
44  import com.liferay.portal.kernel.util.Validator;
45  import com.liferay.portal.model.Company;
46  import com.liferay.portal.model.User;
47  import com.liferay.portal.model.impl.CompanyImpl;
48  import com.liferay.portal.security.auth.AuthException;
49  import com.liferay.portal.security.auth.Authenticator;
50  import com.liferay.portal.service.UserLocalServiceUtil;
51  import com.liferay.portal.struts.ActionConstants;
52  import com.liferay.portal.struts.LastPath;
53  import com.liferay.portal.theme.ThemeDisplay;
54  import com.liferay.portal.util.CookieKeys;
55  import com.liferay.portal.util.PortalUtil;
56  import com.liferay.portal.util.PropsUtil;
57  import com.liferay.portal.util.WebKeys;
58  import com.liferay.util.CookieUtil;
59  import com.liferay.util.Encryptor;
60  import com.liferay.util.XSSUtil;
61  import com.liferay.util.servlet.SessionErrors;
62  import com.liferay.util.servlet.SessionMessages;
63  import com.liferay.util.servlet.SessionParameters;
64  
65  import java.util.ArrayList;
66  import java.util.Enumeration;
67  import java.util.HashMap;
68  import java.util.List;
69  import java.util.Map;
70  
71  import javax.servlet.http.Cookie;
72  import javax.servlet.http.HttpServletRequest;
73  import javax.servlet.http.HttpServletResponse;
74  import javax.servlet.http.HttpSession;
75  import javax.servlet.jsp.PageContext;
76  
77  import org.apache.commons.logging.Log;
78  import org.apache.commons.logging.LogFactory;
79  import org.apache.struts.action.Action;
80  import org.apache.struts.action.ActionForm;
81  import org.apache.struts.action.ActionForward;
82  import org.apache.struts.action.ActionMapping;
83  
84  /**
85   * <a href="LoginAction.java.html"><b><i>View Source</i></b></a>
86   *
87   * @author Brian Wing Shun Chan
88   * @author Scott Lee
89   *
90   */
91  public class LoginAction extends Action {
92  
93      public static String getLogin(
94              HttpServletRequest req, String paramName, Company company)
95          throws PortalException, SystemException {
96  
97          String login = req.getParameter(paramName);
98  
99          if ((login == null) || (login.equals(StringPool.NULL))) {
100             login = GetterUtil.getString(
101                 CookieUtil.get(req.getCookies(), CookieKeys.LOGIN));
102 
103             if (Validator.isNull(login) &&
104                 company.getAuthType().equals(CompanyImpl.AUTH_TYPE_EA)) {
105 
106                 login = "@" + company.getMx();
107             }
108         }
109 
110         login = XSSUtil.strip(login);
111 
112         return login;
113     }
114 
115     public static void login(
116             HttpServletRequest req, HttpServletResponse res, String login,
117             String password, boolean rememberMe)
118         throws Exception {
119 
120         CookieKeys.validateSupportCookie(req);
121 
122         HttpSession ses = req.getSession();
123 
124         long userId = GetterUtil.getLong(login);
125 
126         int authResult = Authenticator.FAILURE;
127 
128         Company company = PortalUtil.getCompany(req);
129 
130         Map headerMap = new HashMap();
131 
132         Enumeration enu1 = req.getHeaderNames();
133 
134         while (enu1.hasMoreElements()) {
135             String name = (String)enu1.nextElement();
136 
137             Enumeration enu2 = req.getHeaders(name);
138 
139             List headers = new ArrayList();
140 
141             while (enu2.hasMoreElements()) {
142                 String value = (String)enu2.nextElement();
143 
144                 headers.add(value);
145             }
146 
147             headerMap.put(name, (String[])headers.toArray(new String[0]));
148         }
149 
150         Map parameterMap = req.getParameterMap();
151 
152         if (company.getAuthType().equals(CompanyImpl.AUTH_TYPE_EA)) {
153             authResult = UserLocalServiceUtil.authenticateByEmailAddress(
154                 company.getCompanyId(), login, password, headerMap,
155                 parameterMap);
156 
157             userId = UserLocalServiceUtil.getUserIdByEmailAddress(
158                 company.getCompanyId(), login);
159         }
160         else if (company.getAuthType().equals(CompanyImpl.AUTH_TYPE_SN)) {
161             authResult = UserLocalServiceUtil.authenticateByScreenName(
162                 company.getCompanyId(), login, password, headerMap,
163                 parameterMap);
164 
165             userId = UserLocalServiceUtil.getUserIdByScreenName(
166                 company.getCompanyId(), login);
167         }
168         else if (company.getAuthType().equals(CompanyImpl.AUTH_TYPE_ID)) {
169             authResult = UserLocalServiceUtil.authenticateByUserId(
170                 company.getCompanyId(), userId, password, headerMap,
171                 parameterMap);
172         }
173 
174         if (authResult == Authenticator.SUCCESS) {
175             if (GetterUtil.getBoolean(PropsUtil.get(
176                     PropsUtil.SESSION_ENABLE_PHISHING_PROTECTION))) {
177 
178                 // Invalidate the previous session to prevent phishing
179 
180                 Boolean httpsInitial = (Boolean)ses.getAttribute(
181                     WebKeys.HTTPS_INITIAL);
182 
183                 LastPath lastPath = (LastPath)ses.getAttribute(
184                     WebKeys.LAST_PATH);
185 
186                 try {
187                     ses.invalidate();
188                 }
189                 catch (IllegalStateException ise) {
190 
191                     // This only happens in Geronimo
192 
193                     if (_log.isWarnEnabled()) {
194                         _log.warn(ise.getMessage());
195                     }
196                 }
197 
198                 ses = req.getSession(true);
199 
200                 if (httpsInitial != null) {
201                     ses.setAttribute(WebKeys.HTTPS_INITIAL, httpsInitial);
202                 }
203 
204                 if (lastPath != null) {
205                     ses.setAttribute(WebKeys.LAST_PATH, lastPath);
206                 }
207             }
208 
209             // Set cookies
210 
211             String domain = PropsUtil.get(PropsUtil.SESSION_COOKIE_DOMAIN);
212 
213             User user = UserLocalServiceUtil.getUserById(userId);
214 
215             String userIdString = String.valueOf(userId);
216 
217             ses.setAttribute("j_username", userIdString);
218             ses.setAttribute("j_password", user.getPassword());
219             ses.setAttribute("j_remoteuser", userIdString);
220 
221             ses.setAttribute(WebKeys.USER_PASSWORD, password);
222 
223             Cookie idCookie = new Cookie(
224                 CookieKeys.ID,
225                 UserLocalServiceUtil.encryptUserId(userIdString));
226 
227             if (Validator.isNotNull(domain)) {
228                 idCookie.setDomain(domain);
229             }
230 
231             idCookie.setPath(StringPool.SLASH);
232 
233             Cookie passwordCookie = new Cookie(
234                 CookieKeys.PASSWORD,
235                 Encryptor.encrypt(company.getKeyObj(), password));
236 
237             if (Validator.isNotNull(domain)) {
238                 passwordCookie.setDomain(domain);
239             }
240 
241             passwordCookie.setPath(StringPool.SLASH);
242 
243             int loginMaxAge = GetterUtil.getInteger(
244                 PropsUtil.get(PropsUtil.COMPANY_SECURITY_AUTO_LOGIN_MAX_AGE),
245                 CookieKeys.MAX_AGE);
246 
247             if (GetterUtil.getBoolean(
248                     PropsUtil.get(PropsUtil.SESSION_DISABLED))) {
249 
250                 rememberMe = true;
251             }
252 
253             if (rememberMe) {
254                 idCookie.setMaxAge(loginMaxAge);
255                 passwordCookie.setMaxAge(loginMaxAge);
256             }
257             else {
258                 idCookie.setMaxAge(0);
259                 passwordCookie.setMaxAge(0);
260             }
261 
262             Cookie loginCookie = new Cookie(CookieKeys.LOGIN, login);
263 
264             if (Validator.isNotNull(domain)) {
265                 loginCookie.setDomain(domain);
266             }
267 
268             loginCookie.setPath(StringPool.SLASH);
269             loginCookie.setMaxAge(loginMaxAge);
270 
271             Cookie screenNameCookie = new Cookie(
272                 CookieKeys.SCREEN_NAME,
273                 Encryptor.encrypt(company.getKeyObj(), user.getScreenName()));
274 
275             if (Validator.isNotNull(domain)) {
276                 screenNameCookie.setDomain(domain);
277             }
278 
279             screenNameCookie.setPath(StringPool.SLASH);
280             screenNameCookie.setMaxAge(loginMaxAge);
281 
282             CookieKeys.addCookie(res, idCookie);
283             CookieKeys.addCookie(res, passwordCookie);
284             CookieKeys.addCookie(res, loginCookie);
285             CookieKeys.addCookie(res, screenNameCookie);
286         }
287         else {
288             throw new AuthException();
289         }
290     }
291 
292     public ActionForward execute(
293             ActionMapping mapping, ActionForm form, HttpServletRequest req,
294             HttpServletResponse res)
295         throws Exception {
296 
297         boolean requiresHttps = GetterUtil.getBoolean(
298             PropsUtil.get(PropsUtil.COMPANY_SECURITY_AUTH_REQUIRES_HTTPS));
299 
300         if (requiresHttps && !req.isSecure()) {
301             ThemeDisplay themeDisplay =
302                 (ThemeDisplay)req.getAttribute(WebKeys.THEME_DISPLAY);
303 
304             StringMaker sm = new StringMaker();
305 
306             sm.append(PortalUtil.getPortalURL(req, true));
307             sm.append(themeDisplay.getURLSignIn());
308 
309             res.sendRedirect(sm.toString());
310 
311             return null;
312         }
313 
314         HttpSession ses = req.getSession();
315 
316         ThemeDisplay themeDisplay =
317             (ThemeDisplay)req.getAttribute(WebKeys.THEME_DISPLAY);
318 
319         if (ses.getAttribute("j_username") != null &&
320             ses.getAttribute("j_password") != null) {
321 
322             if (GetterUtil.getBoolean(
323                     PropsUtil.get(PropsUtil.PORTAL_JAAS_ENABLE))) {
324 
325                 return mapping.findForward("/portal/touch_protected.jsp");
326             }
327             else {
328                 res.sendRedirect(themeDisplay.getPathMain());
329 
330                 return null;
331             }
332         }
333 
334         String cmd = ParamUtil.getString(req, Constants.CMD);
335 
336         if (cmd.equals("already-registered")) {
337             try {
338                 login(req, res);
339 
340                 if (GetterUtil.getBoolean(
341                         PropsUtil.get(PropsUtil.PORTAL_JAAS_ENABLE))) {
342 
343                     return mapping.findForward("/portal/touch_protected.jsp");
344                 }
345                 else {
346                     String redirect = ParamUtil.getString(req, "redirect");
347 
348                     if (Validator.isNotNull(redirect)) {
349                         res.sendRedirect(redirect);
350                     }
351                     else {
352                         res.sendRedirect(themeDisplay.getPathMain());
353                     }
354 
355                     return null;
356                 }
357             }
358             catch (Exception e) {
359                 if (e instanceof AuthException) {
360                     Throwable cause = e.getCause();
361 
362                     if (cause instanceof PasswordExpiredException ||
363                         cause instanceof UserLockoutException) {
364 
365                         SessionErrors.add(req, cause.getClass().getName());
366                     }
367                     else {
368                         SessionErrors.add(req, e.getClass().getName());
369                     }
370 
371                     return mapping.findForward("portal.login");
372                 }
373                 else if (e instanceof CookieNotSupportedException ||
374                          e instanceof NoSuchUserException ||
375                          e instanceof PasswordExpiredException ||
376                          e instanceof UserEmailAddressException ||
377                          e instanceof UserIdException ||
378                          e instanceof UserLockoutException ||
379                          e instanceof UserPasswordException ||
380                          e instanceof UserScreenNameException) {
381 
382                     SessionErrors.add(req, e.getClass().getName());
383 
384                     return mapping.findForward("portal.login");
385                 }
386                 else {
387                     req.setAttribute(PageContext.EXCEPTION, e);
388 
389                     return mapping.findForward(ActionConstants.COMMON_ERROR);
390                 }
391             }
392         }
393         else if (cmd.equals("forgot-password")) {
394             try {
395                 sendPassword(req);
396 
397                 return mapping.findForward("portal.login");
398             }
399             catch (Exception e) {
400                 if (e instanceof CaptchaTextException ||
401                     e instanceof NoSuchUserException ||
402                     e instanceof SendPasswordException ||
403                     e instanceof UserEmailAddressException) {
404 
405                     SessionErrors.add(req, e.getClass().getName());
406 
407                     return mapping.findForward("portal.login");
408                 }
409                 else {
410                     req.setAttribute(PageContext.EXCEPTION, e);
411 
412                     return mapping.findForward(ActionConstants.COMMON_ERROR);
413                 }
414             }
415         }
416         else {
417             return mapping.findForward("portal.login");
418         }
419     }
420 
421     protected void login(HttpServletRequest req, HttpServletResponse res)
422         throws Exception {
423 
424         String login = ParamUtil.getString(req, "login").toLowerCase();
425         String password = ParamUtil.getString(
426             req, SessionParameters.get(req, "password"));
427         boolean rememberMe = ParamUtil.getBoolean(req, "rememberMe");
428 
429         login(req, res, login, password, rememberMe);
430     }
431 
432     protected void sendPassword(HttpServletRequest req) throws Exception {
433         ThemeDisplay themeDisplay =
434             (ThemeDisplay)req.getAttribute(WebKeys.THEME_DISPLAY);
435 
436         Company company = themeDisplay.getCompany();
437 
438         if (!company.isSendPassword()) {
439             return;
440         }
441 
442         CaptchaUtil.check(req);
443 
444         String emailAddress = ParamUtil.getString(req, "emailAddress");
445 
446         String remoteAddr = req.getRemoteAddr();
447         String remoteHost = req.getRemoteHost();
448         String userAgent = req.getHeader(HttpHeaders.USER_AGENT);
449 
450         UserLocalServiceUtil.sendPassword(
451             PortalUtil.getCompanyId(req), emailAddress, remoteAddr, remoteHost,
452             userAgent);
453 
454         SessionMessages.add(req, "request_processed", emailAddress);
455     }
456 
457     private static Log _log = LogFactory.getLog(LoginAction.class);
458 
459 }