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