001    /**
002     * Copyright (c) 2000-2010 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.servlet.filters.sso.opensso;
016    
017    import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.util.StringBundler;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.StringUtil;
023    import com.liferay.portal.kernel.util.Validator;
024    import com.liferay.util.CookieUtil;
025    
026    import java.io.IOException;
027    import java.io.InputStream;
028    import java.io.InputStreamReader;
029    import java.io.OutputStreamWriter;
030    
031    import java.net.HttpURLConnection;
032    import java.net.MalformedURLException;
033    import java.net.URL;
034    
035    import java.util.ArrayList;
036    import java.util.HashMap;
037    import java.util.List;
038    import java.util.Map;
039    import java.util.concurrent.ConcurrentHashMap;
040    
041    import javax.servlet.http.HttpServletRequest;
042    
043    /**
044     * <p>
045     * See http://issues.liferay.com/browse/LEP-5943.
046     * </p>
047     *
048     * @author Prashant Dighe
049     * @author Brian Wing Shun Chan
050     * @author Wesley Gong
051     */
052    public class OpenSSOUtil {
053    
054            public static Map<String, String> getAttributes(
055                    HttpServletRequest request, String serviceUrl) {
056    
057                    return _instance._getAttributes(request, serviceUrl);
058            }
059    
060            public static String getSubjectId(
061                    HttpServletRequest request, String serviceUrl) {
062    
063                    return _instance._getSubjectId(request, serviceUrl);
064            }
065    
066            public static boolean isAuthenticated(
067                            HttpServletRequest request, String serviceUrl)
068                    throws IOException {
069    
070                    return _instance._isAuthenticated(request, serviceUrl);
071            }
072    
073            public static boolean isValidServiceUrl(String serviceUrl) {
074                    return _instance._isValidServiceUrl(serviceUrl);
075            }
076    
077            public static boolean isValidUrl(String url) {
078                    return _instance._isValidUrl(url);
079            }
080    
081            public static boolean isValidUrls(String[] urls) {
082                    return _instance._isValidUrls(urls);
083            }
084    
085            private OpenSSOUtil() {
086            }
087    
088            private Map<String, String> _getAttributes(
089                    HttpServletRequest request, String serviceUrl) {
090    
091                    Map<String, String> nameValues = new HashMap<String, String>();
092    
093                    String url = serviceUrl + _GET_ATTRIBUTES;
094    
095                    try {
096                            URL urlObj = new URL(url);
097    
098                            HttpURLConnection urlc = (HttpURLConnection)urlObj.openConnection();
099    
100                            urlc.setDoOutput(true);
101                            urlc.setRequestMethod("POST");
102                            urlc.setRequestProperty(
103                                    "Content-type", "application/x-www-form-urlencoded");
104    
105                            String[] cookieNames = _getCookieNames(serviceUrl);
106    
107                            _setCookieProperty(request, urlc, cookieNames);
108    
109                            OutputStreamWriter osw = new OutputStreamWriter(
110                                    urlc.getOutputStream());
111    
112                            osw.write("dummy");
113    
114                            osw.flush();
115    
116                            int responseCode = urlc.getResponseCode();
117    
118                            if (responseCode == HttpURLConnection.HTTP_OK) {
119                                    UnsyncBufferedReader unsyncBufferedReader =
120                                            new UnsyncBufferedReader(
121                                                    new InputStreamReader((InputStream)urlc.getContent()));
122    
123                                    String line = null;
124    
125                                    while ((line = unsyncBufferedReader.readLine()) != null) {
126                                            if (line.startsWith("userdetails.attribute.name=")) {
127                                                    String name = line.replaceFirst(
128                                                            "userdetails.attribute.name=", "");
129    
130                                                    line = unsyncBufferedReader.readLine();
131    
132                                                    if (line.startsWith("userdetails.attribute.value=")) {
133                                                            String value = line.replaceFirst(
134                                                                    "userdetails.attribute.value=", "");
135    
136                                                            nameValues.put(name, value);
137                                                    }
138                                            }
139                                    }
140                            }
141                            else if (_log.isDebugEnabled()) {
142                                    _log.debug("Attributes response code " + responseCode);
143                            }
144                    }
145                    catch (MalformedURLException mfue) {
146                            _log.error(mfue.getMessage());
147    
148                            if (_log.isDebugEnabled()) {
149                                    _log.debug(mfue, mfue);
150                            }
151                    }
152                    catch (IOException ioe) {
153                            _log.error(ioe.getMessage());
154    
155                            if (_log.isDebugEnabled()) {
156                                    _log.debug(ioe, ioe);
157                            }
158                    }
159    
160                    return nameValues;
161            }
162    
163            private String[] _getCookieNames(String serviceUrl) {
164                    String[] cookieNames = _cookieNamesMap.get(serviceUrl);
165    
166                    if (cookieNames != null) {
167                            return cookieNames;
168                    }
169    
170                    List<String> cookieNamesList = new ArrayList<String>();
171    
172                    try {
173                            String cookieName = null;
174    
175                            String url = serviceUrl + _GET_COOKIE_NAME;
176    
177                            URL urlObj = new URL(url);
178    
179                            HttpURLConnection urlc = (HttpURLConnection)urlObj.openConnection();
180    
181                            UnsyncBufferedReader unsyncBufferedReader =
182                                    new UnsyncBufferedReader(
183                                            new InputStreamReader((InputStream)urlc.getContent()));
184    
185                            int responseCode = urlc.getResponseCode();
186    
187                            if (responseCode != HttpURLConnection.HTTP_OK) {
188                                    if (_log.isDebugEnabled()) {
189                                            _log.debug(url + " has response code " + responseCode);
190                                    }
191                            }
192                            else {
193                                    String line = null;
194    
195                                    while ((line = unsyncBufferedReader.readLine()) != null) {
196                                            if (line.startsWith("string=")) {
197                                                    line = line.replaceFirst("string=", "");
198    
199                                                    cookieName = line;
200                                            }
201                                    }
202                            }
203    
204                            url = serviceUrl + _GET_COOKIE_NAMES;
205    
206                            urlObj = new URL(url);
207    
208                            urlc = (HttpURLConnection)urlObj.openConnection();
209    
210                            unsyncBufferedReader = new UnsyncBufferedReader(
211                                    new InputStreamReader((InputStream)urlc.getContent()));
212    
213                            if (urlc.getResponseCode() != HttpURLConnection.HTTP_OK) {
214                                    if (_log.isDebugEnabled()) {
215                                            _log.debug(url + " has response code " + responseCode);
216                                    }
217                            }
218                            else {
219                                    String line = null;
220    
221                                    while ((line = unsyncBufferedReader.readLine()) != null) {
222                                            if (line.startsWith("string=")) {
223                                                    line = line.replaceFirst("string=", "");
224    
225                                                    if (cookieName.equals(line)) {
226                                                            cookieNamesList.add(0, cookieName);
227                                                    }
228                                                    else {
229                                                            cookieNamesList.add(line);
230                                                    }
231                                            }
232                                    }
233                            }
234                    }
235                    catch (IOException ioe) {
236                            if (_log.isWarnEnabled()) {
237                                    _log.warn(ioe, ioe);
238                            }
239                    }
240    
241                    cookieNames = cookieNamesList.toArray(
242                            new String[cookieNamesList.size()]);
243    
244                    if (cookieNames.length > 0) {
245                            _cookieNamesMap.put(serviceUrl, cookieNames);
246                    }
247    
248                    return cookieNames;
249            }
250    
251            private String _getSubjectId(
252                    HttpServletRequest request, String serviceUrl) {
253    
254                    String cookieName = _getCookieNames(serviceUrl)[0];
255    
256                    return CookieUtil.get(request, cookieName);
257            }
258    
259            private boolean _isAuthenticated(
260                            HttpServletRequest request, String serviceUrl)
261                    throws IOException {
262    
263                    boolean authenticated = false;
264    
265                    String url = serviceUrl + _VALIDATE_TOKEN;
266    
267                    URL urlObj = new URL(url);
268    
269                    HttpURLConnection urlc = (HttpURLConnection)urlObj.openConnection();
270    
271                    urlc.setDoOutput(true);
272                    urlc.setRequestMethod("POST");
273                    urlc.setRequestProperty(
274                            "Content-type", "application/x-www-form-urlencoded");
275    
276                    String[] cookieNames = _getCookieNames(serviceUrl);
277    
278                    if (cookieNames.length == 0) {
279                            throw new IOException(
280                                    "Cookie names from OpenSSO service are not accessible");
281                    }
282    
283                    _setCookieProperty(request, urlc, cookieNames);
284    
285                    OutputStreamWriter osw = new OutputStreamWriter(urlc.getOutputStream());
286    
287                    osw.write("dummy");
288    
289                    osw.flush();
290    
291                    int responseCode = urlc.getResponseCode();
292    
293                    if (responseCode == HttpURLConnection.HTTP_OK) {
294                            String data = StringUtil.read(urlc.getInputStream());
295    
296                            if (data.toLowerCase().indexOf("boolean=true") != -1) {
297                                    authenticated = true;
298                            }
299                    }
300                    else if (_log.isDebugEnabled()) {
301                            _log.debug("Authentication response code " + responseCode);
302                    }
303    
304                    return authenticated;
305            }
306    
307            private boolean _isValidServiceUrl(String serviceUrl) {
308                    if (Validator.isNull(serviceUrl)) {
309                            return false;
310                    }
311    
312                    String[] cookieNames = _instance._getCookieNames(serviceUrl);
313    
314                    if (cookieNames.length == 0) {
315                            return false;
316                    }
317    
318                    return true;
319            }
320    
321            private boolean _isValidUrl(String url) {
322                    if (Validator.isNull(url)) {
323                            return false;
324                    }
325    
326                    try {
327                            URL urlObj = new URL(url);
328    
329                            HttpURLConnection urlc = (HttpURLConnection)urlObj.openConnection();
330    
331                            int responseCode = urlc.getResponseCode();
332    
333                            if (responseCode != HttpURLConnection.HTTP_OK) {
334                                    if (_log.isDebugEnabled()) {
335                                            _log.debug("Attributes response code " + responseCode);
336                                    }
337    
338                                    return false;
339                            }
340                    }
341                    catch (IOException ioe) {
342                            if (_log.isWarnEnabled()) {
343                                    _log.warn(ioe, ioe);
344                            }
345    
346                            return false;
347                    }
348    
349                    return true;
350            }
351    
352            private boolean _isValidUrls(String[] urls) {
353                    for (String url : urls) {
354                            if (!_isValidUrl(url)) {
355                                    return false;
356                            }
357                    }
358    
359                    return true;
360            }
361    
362            private void _setCookieProperty(
363                    HttpServletRequest request, HttpURLConnection urlc,
364                    String[] cookieNames) {
365    
366                    if (cookieNames.length == 0) {
367                            return;
368                    }
369    
370                    StringBundler sb = new StringBundler(cookieNames.length * 4);
371    
372                    for (String cookieName : cookieNames) {
373                            String cookieValue = CookieUtil.get(request, cookieName);
374    
375                            sb.append(cookieName);
376                            sb.append(StringPool.EQUAL);
377                            sb.append(StringPool.QUOTE);
378                            sb.append(cookieValue);
379                            sb.append(StringPool.QUOTE);
380                            sb.append(StringPool.SEMICOLON);
381                    }
382    
383                    urlc.setRequestProperty("Cookie", sb.toString());
384            }
385    
386            private static final String _GET_ATTRIBUTES = "/identity/attributes";
387    
388            private static final String _GET_COOKIE_NAME =
389                    "/identity/getCookieNameForToken";
390    
391            private static final String _GET_COOKIE_NAMES =
392                    "/identity/getCookieNamesToForward";
393    
394            private static final String _VALIDATE_TOKEN = "/identity/isTokenValid";
395    
396            private static Log _log = LogFactoryUtil.getLog(OpenSSOUtil.class);
397    
398            private static OpenSSOUtil _instance = new OpenSSOUtil();
399    
400            private Map<String, String[]> _cookieNamesMap =
401                    new ConcurrentHashMap<String, String[]>();
402    
403    }