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