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