1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.servlet.filters.secure;
24  
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.servlet.HttpHeaders;
28  import com.liferay.portal.kernel.servlet.ProtectedServletRequest;
29  import com.liferay.portal.kernel.util.GetterUtil;
30  import com.liferay.portal.kernel.util.Http;
31  import com.liferay.portal.kernel.util.HttpUtil;
32  import com.liferay.portal.kernel.util.StringPool;
33  import com.liferay.portal.kernel.util.StringUtil;
34  import com.liferay.portal.kernel.util.Validator;
35  import com.liferay.portal.servlet.filters.BasePortalFilter;
36  import com.liferay.portal.util.PortalUtil;
37  import com.liferay.portal.util.PropsUtil;
38  import com.liferay.portal.util.PropsValues;
39  
40  import java.util.HashSet;
41  import java.util.Set;
42  
43  import javax.servlet.FilterChain;
44  import javax.servlet.FilterConfig;
45  import javax.servlet.http.HttpServletRequest;
46  import javax.servlet.http.HttpServletResponse;
47  import javax.servlet.http.HttpSession;
48  
49  /**
50   * <a href="SecureFilter.java.html"><b><i>View Source</i></b></a>
51   *
52   * @author Brian Wing Shun Chan
53   * @author Raymond Augé
54   * @author Alexander Chow
55   */
56  public class SecureFilter extends BasePortalFilter {
57  
58      public void init(FilterConfig filterConfig) {
59          super.init(filterConfig);
60  
61          _basicAuthEnabled = GetterUtil.getBoolean(
62              filterConfig.getInitParameter("basic_auth"));
63  
64          String propertyPrefix =
65              filterConfig.getInitParameter("portal_property_prefix");
66  
67          String[] hostsAllowedArray = null;
68  
69          if (Validator.isNull(propertyPrefix)) {
70              hostsAllowedArray = StringUtil.split(
71                  filterConfig.getInitParameter("hosts.allowed"));
72              _httpsRequired = GetterUtil.getBoolean(
73                  filterConfig.getInitParameter("https.required"));
74          }
75          else {
76              hostsAllowedArray = PropsUtil.getArray(
77                  propertyPrefix + "hosts.allowed");
78              _httpsRequired = GetterUtil.getBoolean(
79                  PropsUtil.get(propertyPrefix + "https.required"));
80          }
81  
82          for (int i = 0; i < hostsAllowedArray.length; i++) {
83              _hostsAllowed.add(hostsAllowedArray[i]);
84          }
85      }
86  
87      protected boolean isAccessAllowed(HttpServletRequest request) {
88          String remoteAddr = request.getRemoteAddr();
89          String serverIp = PortalUtil.getComputerAddress();
90  
91          if ((_hostsAllowed.size() > 0) &&
92              (!_hostsAllowed.contains(remoteAddr))) {
93  
94              if ((serverIp.equals(remoteAddr)) &&
95                  (_hostsAllowed.contains(_SERVER_IP))) {
96  
97                  return true;
98              }
99  
100             return false;
101         }
102         else {
103             return true;
104         }
105     }
106 
107     protected void processFilter(
108             HttpServletRequest request, HttpServletResponse response,
109             FilterChain filterChain)
110         throws Exception {
111 
112         String remoteAddr = request.getRemoteAddr();
113 
114         if (isAccessAllowed(request)) {
115             if (_log.isDebugEnabled()) {
116                 _log.debug("Access allowed for " + remoteAddr);
117             }
118         }
119         else {
120             if (_log.isWarnEnabled()) {
121                 _log.warn("Access denied for " + remoteAddr);
122             }
123 
124             response.sendError(
125                 HttpServletResponse.SC_FORBIDDEN,
126                 "Access denied for " + remoteAddr);
127 
128             return;
129         }
130 
131         if (_log.isDebugEnabled()) {
132             if (_httpsRequired) {
133                 _log.debug("https is required");
134             }
135             else {
136                 _log.debug("https is not required");
137             }
138         }
139 
140         if (_httpsRequired && !request.isSecure()) {
141             if (_log.isDebugEnabled()) {
142                 String completeURL = HttpUtil.getCompleteURL(request);
143 
144                 _log.debug("Securing " + completeURL);
145             }
146 
147             StringBuilder redirectURL = new StringBuilder();
148 
149             redirectURL.append(Http.HTTPS_WITH_SLASH);
150             redirectURL.append(request.getServerName());
151             redirectURL.append(request.getServletPath());
152 
153             String queryString = request.getQueryString();
154 
155             if (Validator.isNotNull(queryString)) {
156                 redirectURL.append(StringPool.QUESTION);
157                 redirectURL.append(request.getQueryString());
158             }
159 
160             if (_log.isDebugEnabled()) {
161                 _log.debug("Redirect to " + redirectURL);
162             }
163 
164             response.sendRedirect(redirectURL.toString());
165         }
166         else {
167             if (_log.isDebugEnabled()) {
168                 String completeURL = HttpUtil.getCompleteURL(request);
169 
170                 _log.debug("Not securing " + completeURL);
171             }
172 
173             // This basic authentication should only be run if specified by
174             // web.xml and JAAS is disabled. Make sure to run this once per
175             // session and wrap the request if necessary.
176 
177             HttpSession session = request.getSession();
178 
179             long userId = GetterUtil.getLong(
180                 (String)session.getAttribute(_AUTHENTICATED_USER));
181 
182             if (_basicAuthEnabled && !PropsValues.PORTAL_JAAS_ENABLE) {
183                 if (userId > 0) {
184                     request = new ProtectedServletRequest(
185                         request, String.valueOf(userId));
186                 }
187                 else {
188                     try {
189                         userId = PortalUtil.getBasicAuthUserId(request);
190                     }
191                     catch (Exception e) {
192                         _log.error(e);
193                     }
194 
195                     if (userId > 0) {
196                         String userIdString = String.valueOf(userId);
197 
198                         request = new ProtectedServletRequest(
199                             request, userIdString);
200 
201                         session.setAttribute(_AUTHENTICATED_USER, userIdString);
202                     }
203                     else {
204                         response.setHeader(
205                             HttpHeaders.WWW_AUTHENTICATE, _PORTAL_REALM);
206                         response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
207 
208                         return;
209                     }
210                 }
211             }
212 
213             processFilter(SecureFilter.class, request, response, filterChain);
214         }
215     }
216 
217     private static final String _SERVER_IP = "SERVER_IP";
218 
219     private static final String _PORTAL_REALM = "Basic realm=\"PortalRealm\"";
220 
221     private static final String _AUTHENTICATED_USER =
222         SecureFilter.class + "_AUTHENTICATED_USER";
223 
224     private static Log _log = LogFactoryUtil.getLog(SecureFilter.class);
225 
226     private boolean _basicAuthEnabled;
227     private Set<String> _hostsAllowed = new HashSet<String>();
228     private boolean _httpsRequired;
229 
230 }