1   /**
2    * Copyright (c) 2000-2008 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.servlet.SessionErrors;
40  import com.liferay.portal.kernel.servlet.SessionMessages;
41  import com.liferay.portal.kernel.util.Constants;
42  import com.liferay.portal.kernel.util.GetterUtil;
43  import com.liferay.portal.kernel.util.ParamUtil;
44  import com.liferay.portal.kernel.util.StringPool;
45  import com.liferay.portal.kernel.util.Validator;
46  import com.liferay.portal.model.Company;
47  import com.liferay.portal.model.CompanyConstants;
48  import com.liferay.portal.model.User;
49  import com.liferay.portal.security.auth.AuthException;
50  import com.liferay.portal.security.auth.Authenticator;
51  import com.liferay.portal.service.UserLocalServiceUtil;
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.PropsValues;
57  import com.liferay.portal.util.WebKeys;
58  import com.liferay.util.Encryptor;
59  import com.liferay.util.servlet.SessionParameters;
60  
61  import java.util.ArrayList;
62  import java.util.Enumeration;
63  import java.util.HashMap;
64  import java.util.List;
65  import java.util.Map;
66  
67  import javax.servlet.http.Cookie;
68  import javax.servlet.http.HttpServletRequest;
69  import javax.servlet.http.HttpServletResponse;
70  import javax.servlet.http.HttpSession;
71  
72  import org.apache.commons.logging.Log;
73  import org.apache.commons.logging.LogFactory;
74  import org.apache.struts.action.Action;
75  import org.apache.struts.action.ActionForm;
76  import org.apache.struts.action.ActionForward;
77  import org.apache.struts.action.ActionMapping;
78  
79  /**
80   * <a href="LoginAction.java.html"><b><i>View Source</i></b></a>
81   *
82   * @author Brian Wing Shun Chan
83   * @author Scott Lee
84   *
85   */
86  public class LoginAction extends Action {
87  
88      public static String getLogin(
89              HttpServletRequest request, String paramName, Company company)
90          throws PortalException, SystemException {
91  
92          String login = request.getParameter(paramName);
93  
94          if ((login == null) || (login.equals(StringPool.NULL))) {
95              login = GetterUtil.getString(
96                  CookieKeys.getCookie(request, CookieKeys.LOGIN));
97  
98              if (Validator.isNull(login) &&
99                  company.getAuthType().equals(CompanyConstants.AUTH_TYPE_EA)) {
100 
101                 login = "@" + company.getMx();
102             }
103         }
104 
105         return login;
106     }
107 
108     public static void login(
109             HttpServletRequest request, HttpServletResponse response,
110             String login, String password, boolean rememberMe)
111         throws Exception {
112 
113         CookieKeys.validateSupportCookie(request);
114 
115         HttpSession session = request.getSession();
116 
117         long userId = GetterUtil.getLong(login);
118 
119         int authResult = Authenticator.FAILURE;
120 
121         Company company = PortalUtil.getCompany(request);
122 
123         Map<String, String[]> headerMap = new HashMap<String, String[]>();
124 
125         Enumeration<String> enu1 = request.getHeaderNames();
126 
127         while (enu1.hasMoreElements()) {
128             String name = enu1.nextElement();
129 
130             Enumeration<String> enu2 = request.getHeaders(name);
131 
132             List<String> headers = new ArrayList<String>();
133 
134             while (enu2.hasMoreElements()) {
135                 String value = enu2.nextElement();
136 
137                 headers.add(value);
138             }
139 
140             headerMap.put(name, headers.toArray(new String[headers.size()]));
141         }
142 
143         Map<String, String[]> parameterMap = request.getParameterMap();
144 
145         if (company.getAuthType().equals(CompanyConstants.AUTH_TYPE_EA)) {
146             authResult = UserLocalServiceUtil.authenticateByEmailAddress(
147                 company.getCompanyId(), login, password, headerMap,
148                 parameterMap);
149 
150             userId = UserLocalServiceUtil.getUserIdByEmailAddress(
151                 company.getCompanyId(), login);
152         }
153         else if (company.getAuthType().equals(CompanyConstants.AUTH_TYPE_SN)) {
154             authResult = UserLocalServiceUtil.authenticateByScreenName(
155                 company.getCompanyId(), login, password, headerMap,
156                 parameterMap);
157 
158             userId = UserLocalServiceUtil.getUserIdByScreenName(
159                 company.getCompanyId(), login);
160         }
161         else if (company.getAuthType().equals(CompanyConstants.AUTH_TYPE_ID)) {
162             authResult = UserLocalServiceUtil.authenticateByUserId(
163                 company.getCompanyId(), userId, password, headerMap,
164                 parameterMap);
165         }
166 
167         if (authResult == Authenticator.SUCCESS) {
168             if (PropsValues.SESSION_ENABLE_PHISHING_PROTECTION) {
169 
170                 // Invalidate the previous session to prevent phishing
171 
172                 Boolean httpsInitial = (Boolean)session.getAttribute(
173                     WebKeys.HTTPS_INITIAL);
174 
175                 LastPath lastPath = (LastPath)session.getAttribute(
176                     WebKeys.LAST_PATH);
177 
178                 try {
179                     session.invalidate();
180                 }
181                 catch (IllegalStateException ise) {
182 
183                     // This only happens in Geronimo
184 
185                     if (_log.isWarnEnabled()) {
186                         _log.warn(ise.getMessage());
187                     }
188                 }
189 
190                 session = request.getSession(true);
191 
192                 if (httpsInitial != null) {
193                     session.setAttribute(WebKeys.HTTPS_INITIAL, httpsInitial);
194                 }
195 
196                 if (lastPath != null) {
197                     session.setAttribute(WebKeys.LAST_PATH, lastPath);
198                 }
199             }
200 
201             // Set cookies
202 
203             String domain = CookieKeys.getDomain(request);
204 
205             User user = UserLocalServiceUtil.getUserById(userId);
206 
207             String userIdString = String.valueOf(userId);
208 
209             session.setAttribute("j_username", userIdString);
210             session.setAttribute("j_password", user.getPassword());
211             session.setAttribute("j_remoteuser", userIdString);
212 
213             session.setAttribute(WebKeys.USER_PASSWORD, password);
214 
215             Cookie companyIdCookie = new Cookie(
216                 CookieKeys.COMPANY_ID, String.valueOf(company.getCompanyId()));
217 
218             if (Validator.isNotNull(domain)) {
219                 companyIdCookie.setDomain(domain);
220             }
221 
222             companyIdCookie.setPath(StringPool.SLASH);
223 
224             Cookie idCookie = new Cookie(
225                 CookieKeys.ID,
226                 UserLocalServiceUtil.encryptUserId(userIdString));
227 
228             if (Validator.isNotNull(domain)) {
229                 idCookie.setDomain(domain);
230             }
231 
232             idCookie.setPath(StringPool.SLASH);
233 
234             Cookie passwordCookie = new Cookie(
235                 CookieKeys.PASSWORD,
236                 Encryptor.encrypt(company.getKeyObj(), password));
237 
238             if (Validator.isNotNull(domain)) {
239                 passwordCookie.setDomain(domain);
240             }
241 
242             passwordCookie.setPath(StringPool.SLASH);
243 
244             Cookie rememberMeCookie = new Cookie(
245                 CookieKeys.REMEMBER_ME, Boolean.TRUE.toString());
246 
247             if (Validator.isNotNull(domain)) {
248                 rememberMeCookie.setDomain(domain);
249             }
250 
251             rememberMeCookie.setPath(StringPool.SLASH);
252 
253             int loginMaxAge = PropsValues.COMPANY_SECURITY_AUTO_LOGIN_MAX_AGE;
254 
255             if (PropsValues.SESSION_DISABLED) {
256                 rememberMe = true;
257             }
258 
259             if (rememberMe) {
260                 companyIdCookie.setMaxAge(loginMaxAge);
261                 idCookie.setMaxAge(loginMaxAge);
262                 passwordCookie.setMaxAge(loginMaxAge);
263                 rememberMeCookie.setMaxAge(loginMaxAge);
264             }
265             else {
266 
267                 // This was explicitly changed from 0 to -1 so that the cookie
268                 // lasts as long as the browser. This allows an external servlet
269                 // wrapped in AutoLoginFilter to work throughout the client
270                 // connection. The cookies ARE removed on an actual logout, so
271                 // there is no security issue. See LEP-4678 and LEP-5177.
272 
273                 companyIdCookie.setMaxAge(-1);
274                 idCookie.setMaxAge(-1);
275                 passwordCookie.setMaxAge(-1);
276                 rememberMeCookie.setMaxAge(0);
277             }
278 
279             Cookie loginCookie = new Cookie(CookieKeys.LOGIN, login);
280 
281             if (Validator.isNotNull(domain)) {
282                 loginCookie.setDomain(domain);
283             }
284 
285             loginCookie.setMaxAge(loginMaxAge);
286             loginCookie.setPath(StringPool.SLASH);
287 
288             Cookie screenNameCookie = new Cookie(
289                 CookieKeys.SCREEN_NAME,
290                 Encryptor.encrypt(company.getKeyObj(), user.getScreenName()));
291 
292             if (Validator.isNotNull(domain)) {
293                 screenNameCookie.setDomain(domain);
294             }
295 
296             screenNameCookie.setMaxAge(loginMaxAge);
297             screenNameCookie.setPath(StringPool.SLASH);
298 
299             CookieKeys.addCookie(response, companyIdCookie);
300             CookieKeys.addCookie(response, idCookie);
301             CookieKeys.addCookie(response, passwordCookie);
302             CookieKeys.addCookie(response, rememberMeCookie);
303             CookieKeys.addCookie(response, loginCookie);
304             CookieKeys.addCookie(response, screenNameCookie);
305         }
306         else {
307             throw new AuthException();
308         }
309     }
310 
311     public ActionForward execute(
312             ActionMapping mapping, ActionForm form, HttpServletRequest request,
313             HttpServletResponse response)
314         throws Exception {
315 
316         if (PropsValues.COMPANY_SECURITY_AUTH_REQUIRES_HTTPS &&
317             !request.isSecure()) {
318 
319             ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
320                 WebKeys.THEME_DISPLAY);
321 
322             StringBuilder sb = new StringBuilder();
323 
324             sb.append(PortalUtil.getPortalURL(request, true));
325             sb.append(themeDisplay.getURLSignIn());
326 
327             response.sendRedirect(sb.toString());
328 
329             return null;
330         }
331 
332         HttpSession session = request.getSession();
333 
334         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
335             WebKeys.THEME_DISPLAY);
336 
337         if (session.getAttribute("j_username") != null &&
338             session.getAttribute("j_password") != null) {
339 
340             if (PropsValues.PORTAL_JAAS_ENABLE) {
341                 return mapping.findForward("/portal/touch_protected.jsp");
342             }
343             else {
344                 response.sendRedirect(themeDisplay.getPathMain());
345 
346                 return null;
347             }
348         }
349 
350         String cmd = ParamUtil.getString(request, Constants.CMD);
351 
352         if (cmd.equals("already-registered")) {
353             try {
354                 login(request, response);
355 
356                 if (PropsValues.PORTAL_JAAS_ENABLE) {
357                     return mapping.findForward("/portal/touch_protected.jsp");
358                 }
359                 else {
360                     String redirect = ParamUtil.getString(request, "redirect");
361 
362                     if (Validator.isNotNull(redirect)) {
363                         response.sendRedirect(redirect);
364                     }
365                     else {
366                         response.sendRedirect(themeDisplay.getPathMain());
367                     }
368 
369                     return null;
370                 }
371             }
372             catch (Exception e) {
373                 if (e instanceof AuthException) {
374                     Throwable cause = e.getCause();
375 
376                     if (cause instanceof PasswordExpiredException ||
377                         cause instanceof UserLockoutException) {
378 
379                         SessionErrors.add(request, cause.getClass().getName());
380                     }
381                     else {
382                         SessionErrors.add(request, e.getClass().getName());
383                     }
384 
385                     return mapping.findForward("portal.login");
386                 }
387                 else if (e instanceof CookieNotSupportedException ||
388                          e instanceof NoSuchUserException ||
389                          e instanceof PasswordExpiredException ||
390                          e instanceof UserEmailAddressException ||
391                          e instanceof UserIdException ||
392                          e instanceof UserLockoutException ||
393                          e instanceof UserPasswordException ||
394                          e instanceof UserScreenNameException) {
395 
396                     SessionErrors.add(request, e.getClass().getName());
397 
398                     return mapping.findForward("portal.login");
399                 }
400                 else {
401                     PortalUtil.sendError(e, request, response);
402 
403                     return null;
404                 }
405             }
406         }
407         else if (cmd.equals("forgot-password")) {
408             try {
409                 sendPassword(request);
410 
411                 return mapping.findForward("portal.login");
412             }
413             catch (Exception e) {
414                 if (e instanceof CaptchaTextException ||
415                     e instanceof NoSuchUserException ||
416                     e instanceof SendPasswordException ||
417                     e instanceof UserEmailAddressException) {
418 
419                     SessionErrors.add(request, e.getClass().getName());
420 
421                     return mapping.findForward("portal.login");
422                 }
423                 else {
424                     PortalUtil.sendError(e, request, response);
425 
426                     return null;
427                 }
428             }
429         }
430         else {
431             String authLoginURL = PortalUtil.getCommunityLoginURL(themeDisplay);
432 
433             if (Validator.isNull(authLoginURL)) {
434                 authLoginURL = PropsValues.AUTH_LOGIN_URL;
435             }
436 
437             if (Validator.isNotNull(authLoginURL)) {
438                 response.sendRedirect(authLoginURL);
439 
440                 return null;
441             }
442             else {
443                 return mapping.findForward("portal.login");
444             }
445         }
446     }
447 
448     protected void login(
449             HttpServletRequest request, HttpServletResponse response)
450         throws Exception {
451 
452         String login = ParamUtil.getString(request, "login").toLowerCase();
453         String password = ParamUtil.getString(
454             request, SessionParameters.get(request, "password"));
455         boolean rememberMe = ParamUtil.getBoolean(request, "rememberMe");
456 
457         login(request, response, login, password, rememberMe);
458     }
459 
460     protected void sendPassword(HttpServletRequest request) throws Exception {
461         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
462             WebKeys.THEME_DISPLAY);
463 
464         Company company = themeDisplay.getCompany();
465 
466         if (!company.isSendPassword()) {
467             return;
468         }
469 
470         if (PropsValues.CAPTCHA_CHECK_PORTAL_SEND_PASSWORD) {
471             CaptchaUtil.check(request);
472         }
473 
474         String emailAddress = ParamUtil.getString(request, "emailAddress");
475 
476         String remoteAddr = request.getRemoteAddr();
477         String remoteHost = request.getRemoteHost();
478         String userAgent = request.getHeader(HttpHeaders.USER_AGENT);
479 
480         UserLocalServiceUtil.sendPassword(
481             PortalUtil.getCompanyId(request), emailAddress, remoteAddr,
482             remoteHost, userAgent);
483 
484         SessionMessages.add(request, "request_processed", emailAddress);
485     }
486 
487     private static Log _log = LogFactory.getLog(LoginAction.class);
488 
489 }