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.secure;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.servlet.HttpHeaders;
020    import com.liferay.portal.kernel.servlet.ProtectedServletRequest;
021    import com.liferay.portal.kernel.util.GetterUtil;
022    import com.liferay.portal.kernel.util.Http;
023    import com.liferay.portal.kernel.util.HttpUtil;
024    import com.liferay.portal.kernel.util.StringBundler;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.util.StringUtil;
027    import com.liferay.portal.kernel.util.Validator;
028    import com.liferay.portal.servlet.filters.BasePortalFilter;
029    import com.liferay.portal.util.PortalUtil;
030    import com.liferay.portal.util.PropsUtil;
031    import com.liferay.portal.util.PropsValues;
032    
033    import java.util.HashSet;
034    import java.util.Set;
035    
036    import javax.servlet.FilterChain;
037    import javax.servlet.FilterConfig;
038    import javax.servlet.http.HttpServletRequest;
039    import javax.servlet.http.HttpServletResponse;
040    import javax.servlet.http.HttpSession;
041    
042    /**
043     * @author Brian Wing Shun Chan
044     * @author Raymond Augé
045     * @author Alexander Chow
046     */
047    public class SecureFilter extends BasePortalFilter {
048    
049            public void init(FilterConfig filterConfig) {
050                    super.init(filterConfig);
051    
052                    _basicAuthEnabled = GetterUtil.getBoolean(
053                            filterConfig.getInitParameter("basic_auth"));
054    
055                    String propertyPrefix =
056                            filterConfig.getInitParameter("portal_property_prefix");
057    
058                    String[] hostsAllowedArray = null;
059    
060                    if (Validator.isNull(propertyPrefix)) {
061                            hostsAllowedArray = StringUtil.split(
062                                    filterConfig.getInitParameter("hosts.allowed"));
063                            _httpsRequired = GetterUtil.getBoolean(
064                                    filterConfig.getInitParameter("https.required"));
065                    }
066                    else {
067                            hostsAllowedArray = PropsUtil.getArray(
068                                    propertyPrefix + "hosts.allowed");
069                            _httpsRequired = GetterUtil.getBoolean(
070                                    PropsUtil.get(propertyPrefix + "https.required"));
071                    }
072    
073                    for (int i = 0; i < hostsAllowedArray.length; i++) {
074                            _hostsAllowed.add(hostsAllowedArray[i]);
075                    }
076            }
077    
078            protected boolean isAccessAllowed(HttpServletRequest request) {
079                    String remoteAddr = request.getRemoteAddr();
080                    String serverIp = PortalUtil.getComputerAddress();
081    
082                    if ((_hostsAllowed.size() > 0) &&
083                            (!_hostsAllowed.contains(remoteAddr))) {
084    
085                            if ((serverIp.equals(remoteAddr)) &&
086                                    (_hostsAllowed.contains(_SERVER_IP))) {
087    
088                                    return true;
089                            }
090    
091                            return false;
092                    }
093                    else {
094                            return true;
095                    }
096            }
097    
098            protected void processFilter(
099                            HttpServletRequest request, HttpServletResponse response,
100                            FilterChain filterChain)
101                    throws Exception {
102    
103                    String remoteAddr = request.getRemoteAddr();
104    
105                    if (isAccessAllowed(request)) {
106                            if (_log.isDebugEnabled()) {
107                                    _log.debug("Access allowed for " + remoteAddr);
108                            }
109                    }
110                    else {
111                            if (_log.isWarnEnabled()) {
112                                    _log.warn("Access denied for " + remoteAddr);
113                            }
114    
115                            response.sendError(
116                                    HttpServletResponse.SC_FORBIDDEN,
117                                    "Access denied for " + remoteAddr);
118    
119                            return;
120                    }
121    
122                    if (_log.isDebugEnabled()) {
123                            if (_httpsRequired) {
124                                    _log.debug("https is required");
125                            }
126                            else {
127                                    _log.debug("https is not required");
128                            }
129                    }
130    
131                    if (_httpsRequired && !request.isSecure()) {
132                            if (_log.isDebugEnabled()) {
133                                    String completeURL = HttpUtil.getCompleteURL(request);
134    
135                                    _log.debug("Securing " + completeURL);
136                            }
137    
138                            StringBundler redirectURL = new StringBundler(5);
139    
140                            redirectURL.append(Http.HTTPS_WITH_SLASH);
141                            redirectURL.append(request.getServerName());
142                            redirectURL.append(request.getServletPath());
143    
144                            String queryString = request.getQueryString();
145    
146                            if (Validator.isNotNull(queryString)) {
147                                    redirectURL.append(StringPool.QUESTION);
148                                    redirectURL.append(request.getQueryString());
149                            }
150    
151                            if (_log.isDebugEnabled()) {
152                                    _log.debug("Redirect to " + redirectURL);
153                            }
154    
155                            response.sendRedirect(redirectURL.toString());
156                    }
157                    else {
158                            if (_log.isDebugEnabled()) {
159                                    String completeURL = HttpUtil.getCompleteURL(request);
160    
161                                    _log.debug("Not securing " + completeURL);
162                            }
163    
164                            // This basic authentication should only be run if specified by
165                            // web.xml and JAAS is disabled. Make sure to run this once per
166                            // session and wrap the request if necessary.
167    
168                            HttpSession session = request.getSession();
169    
170                            long userId = GetterUtil.getLong(
171                                    (String)session.getAttribute(_AUTHENTICATED_USER));
172    
173                            if (_basicAuthEnabled && !PropsValues.PORTAL_JAAS_ENABLE) {
174                                    if (userId > 0) {
175                                            request = new ProtectedServletRequest(
176                                                    request, String.valueOf(userId));
177                                    }
178                                    else {
179                                            try {
180                                                    userId = PortalUtil.getBasicAuthUserId(request);
181                                            }
182                                            catch (Exception e) {
183                                                    _log.error(e);
184                                            }
185    
186                                            if (userId > 0) {
187                                                    String userIdString = String.valueOf(userId);
188    
189                                                    request = new ProtectedServletRequest(
190                                                            request, userIdString);
191    
192                                                    session.setAttribute(_AUTHENTICATED_USER, userIdString);
193                                            }
194                                            else {
195                                                    response.setHeader(
196                                                            HttpHeaders.WWW_AUTHENTICATE, _PORTAL_REALM);
197                                                    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
198    
199                                                    return;
200                                            }
201                                    }
202                            }
203    
204                            processFilter(SecureFilter.class, request, response, filterChain);
205                    }
206            }
207    
208            private static final String _SERVER_IP = "SERVER_IP";
209    
210            private static final String _PORTAL_REALM = "Basic realm=\"PortalRealm\"";
211    
212            private static final String _AUTHENTICATED_USER =
213                    SecureFilter.class + "_AUTHENTICATED_USER";
214    
215            private static Log _log = LogFactoryUtil.getLog(SecureFilter.class);
216    
217            private boolean _basicAuthEnabled;
218            private Set<String> _hostsAllowed = new HashSet<String>();
219            private boolean _httpsRequired;
220    
221    }