1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.servlet.filters.sso.opensso;
16  
17  import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
18  import com.liferay.portal.kernel.log.Log;
19  import com.liferay.portal.kernel.log.LogFactoryUtil;
20  import com.liferay.portal.kernel.util.StringBundler;
21  import com.liferay.portal.kernel.util.StringPool;
22  import com.liferay.portal.kernel.util.StringUtil;
23  import com.liferay.util.CookieUtil;
24  
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.InputStreamReader;
28  import java.io.OutputStreamWriter;
29  
30  import java.net.HttpURLConnection;
31  import java.net.MalformedURLException;
32  import java.net.URL;
33  
34  import java.util.ArrayList;
35  import java.util.HashMap;
36  import java.util.List;
37  import java.util.Map;
38  import java.util.concurrent.ConcurrentHashMap;
39  
40  import javax.servlet.http.HttpServletRequest;
41  
42  /**
43   * <a href="OpenSSOUtil.java.html"><b><i>View Source</i></b></a>
44   *
45   * <p>
46   * See http://issues.liferay.com/browse/LEP-5943.
47   * </p>
48   *
49   * @author Prashant Dighe
50   * @author Brian Wing Shun Chan
51   */
52  public class OpenSSOUtil {
53  
54      public static Map<String, String> getAttributes(
55          HttpServletRequest request, String serviceUrl) {
56  
57          return _instance._getAttributes(request, serviceUrl);
58      }
59  
60      public static String getSubjectId(
61          HttpServletRequest request, String serviceUrl) {
62  
63          return _instance._getSubjectId(request, serviceUrl);
64      }
65  
66      public static boolean isAuthenticated(
67              HttpServletRequest request, String serviceUrl)
68          throws IOException {
69  
70          return _instance._isAuthenticated(request, serviceUrl);
71      }
72  
73      private OpenSSOUtil() {
74      }
75  
76      private Map<String, String> _getAttributes(
77          HttpServletRequest request, String serviceUrl) {
78  
79          Map<String, String> nameValues = new HashMap<String, String>();
80  
81          String url = serviceUrl + _GET_ATTRIBUTES;
82  
83          try {
84              URL urlObj = new URL(url);
85  
86              HttpURLConnection urlc = (HttpURLConnection)urlObj.openConnection();
87  
88              urlc.setDoOutput(true);
89              urlc.setRequestMethod("POST");
90              urlc.setRequestProperty(
91                  "Content-type", "application/x-www-form-urlencoded");
92  
93              String[] cookieNames = _getCookieNames(serviceUrl);
94  
95              _setCookieProperty(request, urlc, cookieNames);
96  
97              OutputStreamWriter osw = new OutputStreamWriter(
98                  urlc.getOutputStream());
99  
100             osw.write("dummy");
101 
102             osw.flush();
103 
104             int responseCode = urlc.getResponseCode();
105 
106             if (responseCode == HttpURLConnection.HTTP_OK) {
107                 UnsyncBufferedReader unsyncBufferedReader =
108                     new UnsyncBufferedReader(
109                         new InputStreamReader((InputStream)urlc.getContent()));
110 
111                 String line = null;
112 
113                 while ((line = unsyncBufferedReader.readLine()) != null) {
114                     if (line.startsWith("userdetails.attribute.name=")) {
115                         String name = line.replaceFirst(
116                             "userdetails.attribute.name=", "");
117 
118                         line = unsyncBufferedReader.readLine();
119 
120                         if (line.startsWith("userdetails.attribute.value=")) {
121                             String value = line.replaceFirst(
122                                 "userdetails.attribute.value=", "");
123 
124                             nameValues.put(name, value);
125                         }
126                     }
127                 }
128             }
129             else if (_log.isDebugEnabled()) {
130                 _log.debug("Attributes response code " + responseCode);
131             }
132         }
133         catch (MalformedURLException mfue) {
134             _log.error(mfue.getMessage());
135 
136             if (_log.isDebugEnabled()) {
137                 _log.debug(mfue, mfue);
138             }
139         }
140         catch (IOException ioe) {
141             _log.error(ioe.getMessage());
142 
143             if (_log.isDebugEnabled()) {
144                 _log.debug(ioe, ioe);
145             }
146         }
147 
148         return nameValues;
149     }
150 
151     private String[] _getCookieNames(String serviceUrl) {
152         String[] cookieNames = _cookieNamesMap.get(serviceUrl);
153 
154         if (cookieNames != null) {
155             return cookieNames;
156         }
157 
158         List<String> cookieNamesList = new ArrayList<String>();
159 
160         try {
161             String cookieName = null;
162 
163             String url = serviceUrl + _GET_COOKIE_NAME;
164 
165             URL urlObj = new URL(url);
166 
167             HttpURLConnection urlc = (HttpURLConnection)urlObj.openConnection();
168 
169             UnsyncBufferedReader unsyncBufferedReader =
170                 new UnsyncBufferedReader(
171                     new InputStreamReader((InputStream)urlc.getContent()));
172 
173             int responseCode = urlc.getResponseCode();
174 
175             if (responseCode != HttpURLConnection.HTTP_OK) {
176                 if (_log.isDebugEnabled()) {
177                     _log.debug(url + " has response code " + responseCode);
178                 }
179             }
180             else {
181                 String line = null;
182 
183                 while ((line = unsyncBufferedReader.readLine()) != null) {
184                     if (line.startsWith("string=")) {
185                         line = line.replaceFirst("string=", "");
186 
187                         cookieName = line;
188                     }
189                 }
190             }
191 
192             url = serviceUrl + _GET_COOKIE_NAMES;
193 
194             urlObj = new URL(url);
195 
196             urlc = (HttpURLConnection)urlObj.openConnection();
197 
198             unsyncBufferedReader = new UnsyncBufferedReader(
199                 new InputStreamReader((InputStream)urlc.getContent()));
200 
201             if (urlc.getResponseCode() != HttpURLConnection.HTTP_OK) {
202                 if (_log.isDebugEnabled()) {
203                     _log.debug(url + " has response code " + responseCode);
204                 }
205             }
206             else {
207                 String line = null;
208 
209                 while ((line = unsyncBufferedReader.readLine()) != null) {
210                     if (line.startsWith("string=")) {
211                         line = line.replaceFirst("string=", "");
212 
213                         if (cookieName.equals(line)) {
214                             cookieNamesList.add(0, cookieName);
215                         }
216                         else {
217                             cookieNamesList.add(line);
218                         }
219                     }
220                 }
221             }
222         }
223         catch (IOException ioe) {
224             if (_log.isWarnEnabled()) {
225                 _log.warn(ioe, ioe);
226             }
227         }
228 
229         cookieNames = cookieNamesList.toArray(
230             new String[cookieNamesList.size()]);
231 
232         _cookieNamesMap.put(serviceUrl, cookieNames);
233 
234         return cookieNames;
235     }
236 
237     private String _getSubjectId(
238         HttpServletRequest request, String serviceUrl) {
239 
240         String cookieName = _getCookieNames(serviceUrl)[0];
241 
242         return CookieUtil.get(request, cookieName);
243     }
244 
245     private boolean _isAuthenticated(
246             HttpServletRequest request, String serviceUrl)
247         throws IOException {
248 
249         boolean authenticated = false;
250 
251         String url = serviceUrl + _VALIDATE_TOKEN;
252 
253         URL urlObj = new URL(url);
254 
255         HttpURLConnection urlc = (HttpURLConnection)urlObj.openConnection();
256 
257         urlc.setDoOutput(true);
258         urlc.setRequestMethod("POST");
259         urlc.setRequestProperty(
260             "Content-type", "application/x-www-form-urlencoded");
261 
262         String[] cookieNames = _getCookieNames(serviceUrl);
263 
264         _setCookieProperty(request, urlc, cookieNames);
265 
266         OutputStreamWriter osw = new OutputStreamWriter(urlc.getOutputStream());
267 
268         osw.write("dummy");
269 
270         osw.flush();
271 
272         int responseCode = urlc.getResponseCode();
273 
274         if (responseCode == HttpURLConnection.HTTP_OK) {
275             String data = StringUtil.read(urlc.getInputStream());
276 
277             if (data.toLowerCase().indexOf("boolean=true") != -1) {
278                 authenticated = true;
279             }
280         }
281         else if (_log.isDebugEnabled()) {
282             _log.debug("Authentication response code " + responseCode);
283         }
284 
285         return authenticated;
286     }
287 
288     private void _setCookieProperty(
289         HttpServletRequest request, HttpURLConnection urlc,
290         String[] cookieNames) {
291 
292         if (cookieNames.length == 0) {
293             return;
294         }
295 
296         StringBundler sb = new StringBundler(cookieNames.length * 4);
297 
298         for (String cookieName : cookieNames) {
299             String cookieValue = CookieUtil.get(request, cookieName);
300 
301             sb.append(cookieName);
302             sb.append(StringPool.EQUAL);
303             sb.append(cookieValue);
304             sb.append(StringPool.SEMICOLON);
305         }
306 
307         urlc.setRequestProperty("Cookie", sb.toString());
308     }
309 
310     private static final String _GET_ATTRIBUTES = "/identity/attributes";
311 
312     private static final String _GET_COOKIE_NAME =
313         "/identity/getCookieNameForToken";
314 
315     private static final String _GET_COOKIE_NAMES =
316         "/identity/getCookieNamesToForward";
317 
318     private static final String _VALIDATE_TOKEN = "/identity/isTokenValid";
319 
320     private static Log _log = LogFactoryUtil.getLog(OpenSSOUtil.class);
321 
322     private static OpenSSOUtil _instance = new OpenSSOUtil();
323 
324     private Map<String, String[]> _cookieNamesMap =
325         new ConcurrentHashMap<String, String[]>();
326 
327 }