001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.login.util;
016    
017    import com.liferay.portal.kernel.cluster.ClusterExecutorUtil;
018    import com.liferay.portal.kernel.cluster.ClusterNode;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.json.JSONFactoryUtil;
022    import com.liferay.portal.kernel.json.JSONObject;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.messaging.DestinationNames;
026    import com.liferay.portal.kernel.messaging.MessageBusUtil;
027    import com.liferay.portal.kernel.servlet.SessionMessages;
028    import com.liferay.portal.kernel.util.CookieKeys;
029    import com.liferay.portal.kernel.util.GetterUtil;
030    import com.liferay.portal.kernel.util.MapUtil;
031    import com.liferay.portal.kernel.util.ParamUtil;
032    import com.liferay.portal.kernel.util.StringPool;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.liveusers.LiveUsers;
035    import com.liferay.portal.model.Company;
036    import com.liferay.portal.model.CompanyConstants;
037    import com.liferay.portal.model.User;
038    import com.liferay.portal.model.UserTracker;
039    import com.liferay.portal.security.auth.AuthException;
040    import com.liferay.portal.security.auth.AuthenticatedUserUUIDStoreUtil;
041    import com.liferay.portal.security.auth.Authenticator;
042    import com.liferay.portal.service.CompanyLocalServiceUtil;
043    import com.liferay.portal.service.ServiceContext;
044    import com.liferay.portal.service.ServiceContextFactory;
045    import com.liferay.portal.service.UserLocalServiceUtil;
046    import com.liferay.portal.theme.ThemeDisplay;
047    import com.liferay.portal.util.PortalUtil;
048    import com.liferay.portal.util.PortletKeys;
049    import com.liferay.portal.util.PropsValues;
050    import com.liferay.portal.util.WebKeys;
051    import com.liferay.portlet.PortletURLFactoryUtil;
052    import com.liferay.util.Encryptor;
053    
054    import java.util.ArrayList;
055    import java.util.Enumeration;
056    import java.util.HashMap;
057    import java.util.List;
058    import java.util.Map;
059    
060    import javax.portlet.ActionRequest;
061    import javax.portlet.PortletMode;
062    import javax.portlet.PortletModeException;
063    import javax.portlet.PortletPreferences;
064    import javax.portlet.PortletRequest;
065    import javax.portlet.PortletURL;
066    import javax.portlet.WindowState;
067    import javax.portlet.WindowStateException;
068    
069    import javax.servlet.http.Cookie;
070    import javax.servlet.http.HttpServletRequest;
071    import javax.servlet.http.HttpServletResponse;
072    import javax.servlet.http.HttpSession;
073    
074    /**
075     * @author Brian Wing Shun Chan
076     * @author Scott Lee
077     */
078    public class LoginUtil {
079    
080            public static long getAuthenticatedUserId(
081                            HttpServletRequest request, String login, String password,
082                            String authType)
083                    throws PortalException, SystemException {
084    
085                    long userId = GetterUtil.getLong(login);
086    
087                    Company company = PortalUtil.getCompany(request);
088    
089                    String requestURI = request.getRequestURI();
090    
091                    String contextPath = PortalUtil.getPathContext();
092    
093                    if (requestURI.startsWith(contextPath.concat("/api/liferay"))) {
094    
095                            // Tunnel requests are serialized objects and cannot manipulate the
096                            // request input stream in any way. Do not use the auth pipeline to
097                            // authenticate tunnel requests.
098    
099                            long companyId = company.getCompanyId();
100    
101                            userId = UserLocalServiceUtil.authenticateForBasic(
102                                    companyId, CompanyConstants.AUTH_TYPE_EA, login, password);
103    
104                            if (userId > 0) {
105                                    return userId;
106                            }
107    
108                            userId = UserLocalServiceUtil.authenticateForBasic(
109                                    companyId, CompanyConstants.AUTH_TYPE_SN, login, password);
110    
111                            if (userId > 0) {
112                                    return userId;
113                            }
114    
115                            userId = UserLocalServiceUtil.authenticateForBasic(
116                                    companyId, CompanyConstants.AUTH_TYPE_ID, login, password);
117    
118                            if (userId <= 0) {
119                                    throw new AuthException();
120                            }
121                    }
122                    else {
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(
141                                            name, headers.toArray(new String[headers.size()]));
142                            }
143    
144                            Map<String, String[]> parameterMap = request.getParameterMap();
145                            Map<String, Object> resultsMap = new HashMap<String, Object>();
146    
147                            if (Validator.isNull(authType)) {
148                                    authType = company.getAuthType();
149                            }
150    
151                            int authResult = Authenticator.FAILURE;
152    
153                            if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
154                                    authResult = UserLocalServiceUtil.authenticateByEmailAddress(
155                                            company.getCompanyId(), login, password, headerMap,
156                                            parameterMap, resultsMap);
157    
158                                    userId = MapUtil.getLong(resultsMap, "userId", userId);
159                            }
160                            else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
161                                    authResult = UserLocalServiceUtil.authenticateByScreenName(
162                                            company.getCompanyId(), login, password, headerMap,
163                                            parameterMap, resultsMap);
164    
165                                    userId = MapUtil.getLong(resultsMap, "userId", userId);
166                            }
167                            else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
168                                    authResult = UserLocalServiceUtil.authenticateByUserId(
169                                            company.getCompanyId(), userId, password, headerMap,
170                                            parameterMap, resultsMap);
171                            }
172    
173                            if (authResult != Authenticator.SUCCESS) {
174                                    throw new AuthException();
175                            }
176                    }
177    
178                    return userId;
179            }
180    
181            public static String getEmailFromAddress(
182                            PortletPreferences preferences, long companyId)
183                    throws SystemException {
184    
185                    return PortalUtil.getEmailFromAddress(
186                            preferences, companyId, PropsValues.LOGIN_EMAIL_FROM_ADDRESS);
187            }
188    
189            public static String getEmailFromName(
190                            PortletPreferences preferences, long companyId)
191                    throws SystemException {
192    
193                    return PortalUtil.getEmailFromName(
194                            preferences, companyId, PropsValues.LOGIN_EMAIL_FROM_NAME);
195            }
196    
197            public static String getLogin(
198                            HttpServletRequest request, String paramName, Company company)
199                    throws SystemException {
200    
201                    String login = request.getParameter(paramName);
202    
203                    if ((login == null) || login.equals(StringPool.NULL)) {
204                            login = GetterUtil.getString(
205                                    CookieKeys.getCookie(request, CookieKeys.LOGIN, false));
206    
207                            if (PropsValues.COMPANY_LOGIN_PREPOPULATE_DOMAIN &&
208                                    Validator.isNull(login) &&
209                                    company.getAuthType().equals(CompanyConstants.AUTH_TYPE_EA)) {
210    
211                                    login = "@" + company.getMx();
212                            }
213                    }
214    
215                    return login;
216            }
217    
218            public static PortletURL getLoginURL(HttpServletRequest request, long plid)
219                    throws PortletModeException, WindowStateException {
220    
221                    PortletURL portletURL = PortletURLFactoryUtil.create(
222                            request, PortletKeys.LOGIN, plid, PortletRequest.RENDER_PHASE);
223    
224                    portletURL.setWindowState(WindowState.MAXIMIZED);
225                    portletURL.setPortletMode(PortletMode.VIEW);
226    
227                    portletURL.setParameter("saveLastPath", "0");
228                    portletURL.setParameter("struts_action", "/login/login");
229    
230                    return portletURL;
231            }
232    
233            public static void login(
234                            HttpServletRequest request, HttpServletResponse response,
235                            String login, String password, boolean rememberMe, String authType)
236                    throws Exception {
237    
238                    CookieKeys.validateSupportCookie(request);
239    
240                    HttpSession session = request.getSession();
241    
242                    Company company = PortalUtil.getCompany(request);
243    
244                    long userId = getAuthenticatedUserId(
245                            request, login, password, authType);
246    
247                    if (!PropsValues.AUTH_SIMULTANEOUS_LOGINS) {
248                            Map<String, UserTracker> sessionUsers = LiveUsers.getSessionUsers(
249                                    company.getCompanyId());
250    
251                            List<UserTracker> userTrackers = new ArrayList<UserTracker>(
252                                    sessionUsers.values());
253    
254                            for (UserTracker userTracker : userTrackers) {
255                                    if (userId != userTracker.getUserId()) {
256                                            continue;
257                                    }
258    
259                                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
260    
261                                    ClusterNode clusterNode =
262                                            ClusterExecutorUtil.getLocalClusterNode();
263    
264                                    if (clusterNode != null) {
265                                            jsonObject.put(
266                                                    "clusterNodeId", clusterNode.getClusterNodeId());
267                                    }
268    
269                                    jsonObject.put("command", "signOut");
270    
271                                    long companyId = CompanyLocalServiceUtil.getCompanyIdByUserId(
272                                            userId);
273    
274                                    jsonObject.put("companyId", companyId);
275                                    jsonObject.put("sessionId", userTracker.getSessionId());
276                                    jsonObject.put("userId", userId);
277    
278                                    MessageBusUtil.sendMessage(
279                                            DestinationNames.LIVE_USERS, jsonObject.toString());
280                            }
281                    }
282    
283                    if (PropsValues.SESSION_ENABLE_PHISHING_PROTECTION) {
284    
285                            // Invalidate the previous session to prevent phishing
286    
287                            String[] protectedAttributeNames =
288                                    PropsValues.SESSION_PHISHING_PROTECTED_ATTRIBUTES;
289    
290                            Map<String, Object> protectedAttributes =
291                                    new HashMap<String, Object>();
292    
293                            for (String protectedAttributeName : protectedAttributeNames) {
294                                    Object protectedAttributeValue = session.getAttribute(
295                                            protectedAttributeName);
296    
297                                    if (protectedAttributeValue == null) {
298                                            continue;
299                                    }
300    
301                                    protectedAttributes.put(
302                                            protectedAttributeName, protectedAttributeValue);
303                            }
304    
305                            try {
306                                    session.invalidate();
307                            }
308                            catch (IllegalStateException ise) {
309    
310                                    // This only happens in Geronimo
311    
312                                    if (_log.isWarnEnabled()) {
313                                            _log.warn(ise.getMessage());
314                                    }
315                            }
316    
317                            session = request.getSession(true);
318    
319                            for (String protectedAttributeName : protectedAttributeNames) {
320                                    Object protectedAttributeValue = protectedAttributes.get(
321                                            protectedAttributeName);
322    
323                                    if (protectedAttributeValue == null) {
324                                            continue;
325                                    }
326    
327                                    session.setAttribute(
328                                            protectedAttributeName, protectedAttributeValue);
329                            }
330                    }
331    
332                    // Set cookies
333    
334                    String domain = CookieKeys.getDomain(request);
335    
336                    User user = UserLocalServiceUtil.getUserById(userId);
337    
338                    String userIdString = String.valueOf(userId);
339    
340                    session.setAttribute("j_username", userIdString);
341                    session.setAttribute("j_password", user.getPassword());
342                    session.setAttribute("j_remoteuser", userIdString);
343    
344                    if (PropsValues.SESSION_STORE_PASSWORD) {
345                            session.setAttribute(WebKeys.USER_PASSWORD, password);
346                    }
347    
348                    Cookie companyIdCookie = new Cookie(
349                            CookieKeys.COMPANY_ID, String.valueOf(company.getCompanyId()));
350    
351                    if (Validator.isNotNull(domain)) {
352                            companyIdCookie.setDomain(domain);
353                    }
354    
355                    companyIdCookie.setPath(StringPool.SLASH);
356    
357                    Cookie idCookie = new Cookie(
358                            CookieKeys.ID,
359                            Encryptor.encrypt(company.getKeyObj(), userIdString));
360    
361                    if (Validator.isNotNull(domain)) {
362                            idCookie.setDomain(domain);
363                    }
364    
365                    idCookie.setPath(StringPool.SLASH);
366    
367                    Cookie passwordCookie = new Cookie(
368                            CookieKeys.PASSWORD,
369                            Encryptor.encrypt(company.getKeyObj(), password));
370    
371                    if (Validator.isNotNull(domain)) {
372                            passwordCookie.setDomain(domain);
373                    }
374    
375                    passwordCookie.setPath(StringPool.SLASH);
376    
377                    Cookie rememberMeCookie = new Cookie(
378                            CookieKeys.REMEMBER_ME, Boolean.TRUE.toString());
379    
380                    if (Validator.isNotNull(domain)) {
381                            rememberMeCookie.setDomain(domain);
382                    }
383    
384                    rememberMeCookie.setPath(StringPool.SLASH);
385    
386                    int loginMaxAge = PropsValues.COMPANY_SECURITY_AUTO_LOGIN_MAX_AGE;
387    
388                    String userUUID = userIdString.concat(StringPool.PERIOD).concat(
389                            String.valueOf(System.nanoTime()));
390    
391                    Cookie userUUIDCookie = new Cookie(
392                            CookieKeys.USER_UUID,
393                            Encryptor.encrypt(company.getKeyObj(), userUUID));
394    
395                    userUUIDCookie.setPath(StringPool.SLASH);
396    
397                    session.setAttribute(WebKeys.USER_UUID, userUUID);
398    
399                    if (PropsValues.SESSION_DISABLED) {
400                            rememberMe = true;
401                    }
402    
403                    if (rememberMe) {
404                            companyIdCookie.setMaxAge(loginMaxAge);
405                            idCookie.setMaxAge(loginMaxAge);
406                            passwordCookie.setMaxAge(loginMaxAge);
407                            rememberMeCookie.setMaxAge(loginMaxAge);
408                            userUUIDCookie.setMaxAge(loginMaxAge);
409                    }
410                    else {
411    
412                            // This was explicitly changed from 0 to -1 so that the cookie lasts
413                            // as long as the browser. This allows an external servlet wrapped
414                            // in AutoLoginFilter to work throughout the client connection. The
415                            // cookies ARE removed on an actual logout, so there is no security
416                            // issue. See LEP-4678 and LEP-5177.
417    
418                            companyIdCookie.setMaxAge(-1);
419                            idCookie.setMaxAge(-1);
420                            passwordCookie.setMaxAge(-1);
421                            rememberMeCookie.setMaxAge(0);
422                            userUUIDCookie.setMaxAge(-1);
423                    }
424    
425                    Cookie loginCookie = new Cookie(CookieKeys.LOGIN, login);
426    
427                    if (Validator.isNotNull(domain)) {
428                            loginCookie.setDomain(domain);
429                    }
430    
431                    loginCookie.setMaxAge(loginMaxAge);
432                    loginCookie.setPath(StringPool.SLASH);
433    
434                    Cookie screenNameCookie = new Cookie(
435                            CookieKeys.SCREEN_NAME,
436                            Encryptor.encrypt(company.getKeyObj(), user.getScreenName()));
437    
438                    if (Validator.isNotNull(domain)) {
439                            screenNameCookie.setDomain(domain);
440                    }
441    
442                    screenNameCookie.setMaxAge(loginMaxAge);
443                    screenNameCookie.setPath(StringPool.SLASH);
444    
445                    boolean secure = request.isSecure();
446    
447                    if (secure) {
448                            Boolean httpsInitial = (Boolean)session.getAttribute(
449                                    WebKeys.HTTPS_INITIAL);
450    
451                            if ((httpsInitial == null) || !httpsInitial.booleanValue()) {
452                                    secure = false;
453                            }
454                    }
455    
456                    CookieKeys.addCookie(request, response, companyIdCookie, secure);
457                    CookieKeys.addCookie(request, response, idCookie, secure);
458                    CookieKeys.addCookie(request, response, userUUIDCookie, secure);
459    
460                    if (rememberMe) {
461                            CookieKeys.addCookie(request, response, loginCookie, secure);
462                            CookieKeys.addCookie(request, response, passwordCookie, secure);
463                            CookieKeys.addCookie(request, response, rememberMeCookie, secure);
464                            CookieKeys.addCookie(request, response, screenNameCookie, secure);
465                    }
466    
467                    AuthenticatedUserUUIDStoreUtil.register(userUUID);
468            }
469    
470            public static void sendPassword(ActionRequest actionRequest)
471                    throws Exception {
472    
473                    String toAddress = ParamUtil.getString(actionRequest, "emailAddress");
474    
475                    sendPassword(actionRequest, null, null, toAddress, null, null);
476            }
477    
478            public static void sendPassword(
479                            ActionRequest actionRequest, String fromName, String fromAddress,
480                            String toAddress, String subject, String body)
481                    throws Exception {
482    
483                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
484                            actionRequest);
485    
486                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
487                            WebKeys.THEME_DISPLAY);
488    
489                    Company company = themeDisplay.getCompany();
490    
491                    if (!company.isSendPassword() && !company.isSendPasswordResetLink()) {
492                            return;
493                    }
494    
495                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
496                            User.class.getName(), actionRequest);
497    
498                    UserLocalServiceUtil.sendPassword(
499                            company.getCompanyId(), toAddress, fromName, fromAddress, subject,
500                            body, serviceContext);
501    
502                    SessionMessages.add(actionRequest, "request_processed", toAddress);
503            }
504    
505            private static Log _log = LogFactoryUtil.getLog(LoginUtil.class);
506    
507    }