001    /**
002     * Copyright (c) 2000-2013 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.portal.security.auth;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.util.Base64;
022    import com.liferay.portal.kernel.util.CharPool;
023    import com.liferay.portal.kernel.util.GetterUtil;
024    import com.liferay.portal.model.Company;
025    import com.liferay.portal.model.User;
026    import com.liferay.portal.service.UserLocalServiceUtil;
027    import com.liferay.portal.service.http.TunnelUtil;
028    import com.liferay.portal.util.PortalUtil;
029    import com.liferay.util.Encryptor;
030    import com.liferay.util.EncryptorException;
031    
032    import java.security.InvalidKeyException;
033    
034    import java.util.Properties;
035    import java.util.StringTokenizer;
036    
037    import javax.servlet.http.HttpServletRequest;
038    
039    /**
040     * @author Zsolt Berentey
041     */
042    public class TunnelingServletAuthVerifier implements AuthVerifier {
043    
044            @Override
045            public String getAuthType() {
046                    return HttpServletRequest.BASIC_AUTH;
047            }
048    
049            @Override
050            public AuthVerifierResult verify(
051                            AccessControlContext accessControlContext, Properties properties)
052                    throws AuthException {
053    
054                    AuthVerifierResult authVerifierResult = new AuthVerifierResult();
055    
056                    String[] credentials = verify(accessControlContext.getRequest());
057    
058                    if (credentials != null) {
059                            authVerifierResult.setPassword(credentials[1]);
060                            authVerifierResult.setState(AuthVerifierResult.State.SUCCESS);
061                            authVerifierResult.setUserId(Long.valueOf(credentials[0]));
062                    }
063    
064                    return authVerifierResult;
065            }
066    
067            protected String[] verify(HttpServletRequest request) throws AuthException {
068                    String authorization = request.getHeader("Authorization");
069    
070                    if (authorization == null) {
071                            return null;
072                    }
073    
074                    StringTokenizer st = new StringTokenizer(authorization);
075    
076                    if (!st.hasMoreTokens()) {
077                            return null;
078                    }
079    
080                    String basic = st.nextToken();
081    
082                    if (!basic.equalsIgnoreCase(HttpServletRequest.BASIC_AUTH)) {
083                            return null;
084                    }
085    
086                    String encodedCredentials = st.nextToken();
087    
088                    if (_log.isDebugEnabled()) {
089                            _log.debug("Encoded credentials " + encodedCredentials);
090                    }
091    
092                    String decodedCredentials = new String(
093                            Base64.decode(encodedCredentials));
094    
095                    if (_log.isDebugEnabled()) {
096                            _log.debug("Decoded credentials " + decodedCredentials);
097                    }
098    
099                    int index = decodedCredentials.indexOf(CharPool.COLON);
100    
101                    if (index == -1) {
102                            return null;
103                    }
104    
105                    String login = GetterUtil.getString(
106                            decodedCredentials.substring(0, index));
107                    String password = decodedCredentials.substring(index + 1);
108    
109                    String expectedPassword = null;
110    
111                    try {
112                            expectedPassword = Encryptor.encrypt(
113                                    TunnelUtil.getSharedSecretKey(), login);
114                    }
115                    catch (EncryptorException ee) {
116                            throw new AuthException("Unable to decrypt login.", ee);
117                    }
118                    catch (InvalidKeyException ike) {
119                            throw new AuthException(ike);
120                    }
121    
122                    if (!password.equals(expectedPassword)) {
123                            throw new AuthException(
124                                    "Tunneling servlet shared secrets do not match");
125                    }
126    
127                    User user = null;
128    
129                    try {
130                            user = UserLocalServiceUtil.fetchUser(GetterUtil.getLong(login));
131    
132                            if (user == null) {
133                                    Company company = PortalUtil.getCompany(request);
134    
135                                    user = UserLocalServiceUtil.fetchUserByEmailAddress(
136                                            company.getCompanyId(), login);
137    
138                                    if (user == null) {
139                                            user = UserLocalServiceUtil.fetchUserByScreenName(
140                                                    company.getCompanyId(), login);
141                                    }
142                            }
143                    }
144                    catch (PortalException pe) {
145                            if (_log.isWarnEnabled()) {
146                                    _log.warn("Unable to find company", pe);
147                            }
148                    }
149                    catch (SystemException se) {
150                            if (_log.isWarnEnabled()) {
151                                    _log.warn("Unable to find user", se);
152                            }
153                    }
154    
155                    if (user == null) {
156                            throw new AuthException();
157                    }
158    
159                    String[] credentials = new String[2];
160    
161                    credentials[0] = String.valueOf(user.getUserId());
162                    credentials[1] = password;
163    
164                    return credentials;
165            }
166    
167            private static Log _log = LogFactoryUtil.getLog(
168                    TunnelingServletAuthVerifier.class);
169    
170    }