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.secure;
16  
17  import com.liferay.portal.kernel.log.Log;
18  import com.liferay.portal.kernel.log.LogFactoryUtil;
19  import com.liferay.portal.kernel.servlet.HttpHeaders;
20  import com.liferay.portal.kernel.servlet.ProtectedServletRequest;
21  import com.liferay.portal.kernel.util.GetterUtil;
22  import com.liferay.portal.kernel.util.Http;
23  import com.liferay.portal.kernel.util.HttpUtil;
24  import com.liferay.portal.kernel.util.StringBundler;
25  import com.liferay.portal.kernel.util.StringPool;
26  import com.liferay.portal.kernel.util.StringUtil;
27  import com.liferay.portal.kernel.util.Validator;
28  import com.liferay.portal.servlet.filters.BasePortalFilter;
29  import com.liferay.portal.util.PortalUtil;
30  import com.liferay.portal.util.PropsUtil;
31  import com.liferay.portal.util.PropsValues;
32  
33  import java.util.HashSet;
34  import java.util.Set;
35  
36  import javax.servlet.FilterChain;
37  import javax.servlet.FilterConfig;
38  import javax.servlet.http.HttpServletRequest;
39  import javax.servlet.http.HttpServletResponse;
40  import javax.servlet.http.HttpSession;
41  
42  /**
43   * <a href="SecureFilter.java.html"><b><i>View Source</i></b></a>
44   *
45   * @author Brian Wing Shun Chan
46   * @author Raymond Augé
47   * @author Alexander Chow
48   */
49  public class SecureFilter extends BasePortalFilter {
50  
51      public void init(FilterConfig filterConfig) {
52          super.init(filterConfig);
53  
54          _basicAuthEnabled = GetterUtil.getBoolean(
55              filterConfig.getInitParameter("basic_auth"));
56  
57          String propertyPrefix =
58              filterConfig.getInitParameter("portal_property_prefix");
59  
60          String[] hostsAllowedArray = null;
61  
62          if (Validator.isNull(propertyPrefix)) {
63              hostsAllowedArray = StringUtil.split(
64                  filterConfig.getInitParameter("hosts.allowed"));
65              _httpsRequired = GetterUtil.getBoolean(
66                  filterConfig.getInitParameter("https.required"));
67          }
68          else {
69              hostsAllowedArray = PropsUtil.getArray(
70                  propertyPrefix + "hosts.allowed");
71              _httpsRequired = GetterUtil.getBoolean(
72                  PropsUtil.get(propertyPrefix + "https.required"));
73          }
74  
75          for (int i = 0; i < hostsAllowedArray.length; i++) {
76              _hostsAllowed.add(hostsAllowedArray[i]);
77          }
78      }
79  
80      protected boolean isAccessAllowed(HttpServletRequest request) {
81          String remoteAddr = request.getRemoteAddr();
82          String serverIp = PortalUtil.getComputerAddress();
83  
84          if ((_hostsAllowed.size() > 0) &&
85              (!_hostsAllowed.contains(remoteAddr))) {
86  
87              if ((serverIp.equals(remoteAddr)) &&
88                  (_hostsAllowed.contains(_SERVER_IP))) {
89  
90                  return true;
91              }
92  
93              return false;
94          }
95          else {
96              return true;
97          }
98      }
99  
100     protected void processFilter(
101             HttpServletRequest request, HttpServletResponse response,
102             FilterChain filterChain)
103         throws Exception {
104 
105         String remoteAddr = request.getRemoteAddr();
106 
107         if (isAccessAllowed(request)) {
108             if (_log.isDebugEnabled()) {
109                 _log.debug("Access allowed for " + remoteAddr);
110             }
111         }
112         else {
113             if (_log.isWarnEnabled()) {
114                 _log.warn("Access denied for " + remoteAddr);
115             }
116 
117             response.sendError(
118                 HttpServletResponse.SC_FORBIDDEN,
119                 "Access denied for " + remoteAddr);
120 
121             return;
122         }
123 
124         if (_log.isDebugEnabled()) {
125             if (_httpsRequired) {
126                 _log.debug("https is required");
127             }
128             else {
129                 _log.debug("https is not required");
130             }
131         }
132 
133         if (_httpsRequired && !request.isSecure()) {
134             if (_log.isDebugEnabled()) {
135                 String completeURL = HttpUtil.getCompleteURL(request);
136 
137                 _log.debug("Securing " + completeURL);
138             }
139 
140             StringBundler redirectURL = new StringBundler(5);
141 
142             redirectURL.append(Http.HTTPS_WITH_SLASH);
143             redirectURL.append(request.getServerName());
144             redirectURL.append(request.getServletPath());
145 
146             String queryString = request.getQueryString();
147 
148             if (Validator.isNotNull(queryString)) {
149                 redirectURL.append(StringPool.QUESTION);
150                 redirectURL.append(request.getQueryString());
151             }
152 
153             if (_log.isDebugEnabled()) {
154                 _log.debug("Redirect to " + redirectURL);
155             }
156 
157             response.sendRedirect(redirectURL.toString());
158         }
159         else {
160             if (_log.isDebugEnabled()) {
161                 String completeURL = HttpUtil.getCompleteURL(request);
162 
163                 _log.debug("Not securing " + completeURL);
164             }
165 
166             // This basic authentication should only be run if specified by
167             // web.xml and JAAS is disabled. Make sure to run this once per
168             // session and wrap the request if necessary.
169 
170             HttpSession session = request.getSession();
171 
172             long userId = GetterUtil.getLong(
173                 (String)session.getAttribute(_AUTHENTICATED_USER));
174 
175             if (_basicAuthEnabled && !PropsValues.PORTAL_JAAS_ENABLE) {
176                 if (userId > 0) {
177                     request = new ProtectedServletRequest(
178                         request, String.valueOf(userId));
179                 }
180                 else {
181                     try {
182                         userId = PortalUtil.getBasicAuthUserId(request);
183                     }
184                     catch (Exception e) {
185                         _log.error(e);
186                     }
187 
188                     if (userId > 0) {
189                         String userIdString = String.valueOf(userId);
190 
191                         request = new ProtectedServletRequest(
192                             request, userIdString);
193 
194                         session.setAttribute(_AUTHENTICATED_USER, userIdString);
195                     }
196                     else {
197                         response.setHeader(
198                             HttpHeaders.WWW_AUTHENTICATE, _PORTAL_REALM);
199                         response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
200 
201                         return;
202                     }
203                 }
204             }
205 
206             processFilter(SecureFilter.class, request, response, filterChain);
207         }
208     }
209 
210     private static final String _SERVER_IP = "SERVER_IP";
211 
212     private static final String _PORTAL_REALM = "Basic realm=\"PortalRealm\"";
213 
214     private static final String _AUTHENTICATED_USER =
215         SecureFilter.class + "_AUTHENTICATED_USER";
216 
217     private static Log _log = LogFactoryUtil.getLog(SecureFilter.class);
218 
219     private boolean _basicAuthEnabled;
220     private Set<String> _hostsAllowed = new HashSet<String>();
221     private boolean _httpsRequired;
222 
223 }