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.kernel.util.StringUtil;
025    import com.liferay.portal.model.Company;
026    import com.liferay.portal.model.User;
027    import com.liferay.portal.service.UserLocalServiceUtil;
028    import com.liferay.portal.service.http.TunnelUtil;
029    import com.liferay.portal.util.PortalUtil;
030    import com.liferay.util.Encryptor;
031    import com.liferay.util.EncryptorException;
032    
033    import java.io.IOException;
034    import java.io.ObjectOutputStream;
035    
036    import java.util.Properties;
037    import java.util.StringTokenizer;
038    
039    import javax.servlet.http.HttpServletRequest;
040    import javax.servlet.http.HttpServletResponse;
041    
042    /**
043     * @author Zsolt Berentey
044     */
045    public class TunnelingServletAuthVerifier implements AuthVerifier {
046    
047            @Override
048            public String getAuthType() {
049                    return HttpServletRequest.BASIC_AUTH;
050            }
051    
052            @Override
053            public AuthVerifierResult verify(
054                            AccessControlContext accessControlContext, Properties properties)
055                    throws AuthException {
056    
057                    AuthVerifierResult authVerifierResult = new AuthVerifierResult();
058    
059                    try {
060                            String[] credentials = verify(accessControlContext.getRequest());
061    
062                            if (credentials != null) {
063                                    authVerifierResult.setPassword(credentials[1]);
064                                    authVerifierResult.setState(AuthVerifierResult.State.SUCCESS);
065                                    authVerifierResult.setUserId(Long.valueOf(credentials[0]));
066                            }
067                    }
068                    catch (AuthException ae) {
069                            if (_log.isDebugEnabled()) {
070                                    _log.debug(ae);
071                            }
072    
073                            HttpServletResponse response = accessControlContext.getResponse();
074    
075                            try {
076                                    ObjectOutputStream objectOutputStream = new ObjectOutputStream(
077                                            response.getOutputStream());
078    
079                                    objectOutputStream.writeObject(ae);
080    
081                                    objectOutputStream.flush();
082    
083                                    objectOutputStream.close();
084    
085                                    authVerifierResult.setState(
086                                            AuthVerifierResult.State.INVALID_CREDENTIALS);
087                            }
088                            catch (IOException ioe) {
089                                    _log.error(ioe, ioe);
090    
091                                    throw ae;
092                            }
093                    }
094    
095                    return authVerifierResult;
096            }
097    
098            protected String[] verify(HttpServletRequest request) throws AuthException {
099                    String authorization = request.getHeader("Authorization");
100    
101                    if (authorization == null) {
102                            return null;
103                    }
104    
105                    StringTokenizer st = new StringTokenizer(authorization);
106    
107                    if (!st.hasMoreTokens()) {
108                            return null;
109                    }
110    
111                    String basic = st.nextToken();
112    
113                    if (!StringUtil.equalsIgnoreCase(
114                                    basic, HttpServletRequest.BASIC_AUTH)) {
115    
116                            return null;
117                    }
118    
119                    String encodedCredentials = st.nextToken();
120    
121                    if (_log.isDebugEnabled()) {
122                            _log.debug("Encoded credentials " + encodedCredentials);
123                    }
124    
125                    String decodedCredentials = new String(
126                            Base64.decode(encodedCredentials));
127    
128                    if (_log.isDebugEnabled()) {
129                            _log.debug("Decoded credentials " + decodedCredentials);
130                    }
131    
132                    int index = decodedCredentials.indexOf(CharPool.COLON);
133    
134                    if (index == -1) {
135                            return null;
136                    }
137    
138                    String login = GetterUtil.getString(
139                            decodedCredentials.substring(0, index));
140                    String password = decodedCredentials.substring(index + 1);
141    
142                    String expectedPassword = null;
143    
144                    try {
145                            expectedPassword = Encryptor.encrypt(
146                                    TunnelUtil.getSharedSecretKey(), login);
147                    }
148                    catch (EncryptorException ee) {
149                            AuthException authException = new RemoteAuthException(ee);
150    
151                            authException.setType(AuthException.INTERNAL_SERVER_ERROR);
152    
153                            throw authException;
154                    }
155                    catch (AuthException ae) {
156                            AuthException authException = new RemoteAuthException();
157    
158                            authException.setType(ae.getType());
159    
160                            throw authException;
161                    }
162    
163                    if (!password.equals(expectedPassword)) {
164                            AuthException authException = new RemoteAuthException();
165    
166                            authException.setType(RemoteAuthException.WRONG_SHARED_SECRET);
167    
168                            throw authException;
169                    }
170    
171                    User user = null;
172    
173                    try {
174                            user = UserLocalServiceUtil.fetchUser(GetterUtil.getLong(login));
175    
176                            if (user == null) {
177                                    Company company = PortalUtil.getCompany(request);
178    
179                                    user = UserLocalServiceUtil.fetchUserByEmailAddress(
180                                            company.getCompanyId(), login);
181    
182                                    if (user == null) {
183                                            user = UserLocalServiceUtil.fetchUserByScreenName(
184                                                    company.getCompanyId(), login);
185                                    }
186                            }
187                    }
188                    catch (PortalException pe) {
189                            if (_log.isWarnEnabled()) {
190                                    _log.warn("Unable to find company", pe);
191                            }
192                    }
193                    catch (SystemException se) {
194                            if (_log.isWarnEnabled()) {
195                                    _log.warn("Unable to find user", se);
196                            }
197                    }
198    
199                    if (user == null) {
200                            AuthException authException = new RemoteAuthException();
201    
202                            authException.setType(AuthException.INTERNAL_SERVER_ERROR);
203    
204                            throw authException;
205                    }
206    
207                    String[] credentials = new String[2];
208    
209                    credentials[0] = String.valueOf(user.getUserId());
210                    credentials[1] = password;
211    
212                    return credentials;
213            }
214    
215            private static Log _log = LogFactoryUtil.getLog(
216                    TunnelingServletAuthVerifier.class);
217    
218    }