001
014
015 package com.liferay.portal.kernel.servlet;
016
017 import com.liferay.portal.kernel.util.CharPool;
018 import com.liferay.portal.kernel.util.GetterUtil;
019 import com.liferay.portal.kernel.util.HttpUtil;
020 import com.liferay.portal.kernel.util.KeyValuePair;
021 import com.liferay.portal.kernel.util.PropertiesUtil;
022 import com.liferay.portal.kernel.util.ServerDetector;
023 import com.liferay.portal.kernel.util.SortedProperties;
024 import com.liferay.portal.kernel.util.StringPool;
025 import com.liferay.portal.kernel.util.StringUtil;
026 import com.liferay.portal.kernel.util.SystemProperties;
027 import com.liferay.portal.kernel.util.Validator;
028 import com.liferay.portal.util.PortalUtil;
029
030 import java.io.IOException;
031
032 import java.util.ArrayList;
033 import java.util.Comparator;
034 import java.util.List;
035 import java.util.Map;
036 import java.util.Properties;
037
038 import javax.portlet.PortletRequest;
039 import javax.portlet.PortletResponse;
040
041 import javax.servlet.http.HttpServletRequest;
042 import javax.servlet.http.HttpServletResponse;
043 import javax.servlet.http.HttpServletResponseWrapper;
044 import javax.servlet.http.HttpSession;
045
046
051 public class SanitizedServletResponse extends HttpServletResponseWrapper {
052
053 public static void disableXSSAuditor(HttpServletResponse response) {
054 response.setHeader(HttpHeaders.X_XSS_PROTECTION, "0");
055 }
056
057 public static void disableXSSAuditor(PortletResponse portletResponse) {
058 disableXSSAuditor(PortalUtil.getHttpServletResponse(portletResponse));
059 }
060
061 public static void disableXSSAuditorOnNextRequest(
062 HttpServletRequest request) {
063
064 HttpSession session = request.getSession();
065
066 session.setAttribute(_DISABLE_XSS_AUDITOR, Boolean.TRUE);
067 }
068
069 public static void disableXSSAuditorOnNextRequest(
070 PortletRequest portletRequest) {
071
072 disableXSSAuditorOnNextRequest(
073 PortalUtil.getHttpServletRequest(portletRequest));
074 }
075
076 public static HttpServletResponse getSanitizedServletResponse(
077 HttpServletRequest request, HttpServletResponse response) {
078
079 setXContentOptions(request, response);
080 setXFrameOptions(request, response);
081 setXXSSProtection(request, response);
082
083 if (ServerDetector.isResin()) {
084 response = new SanitizedServletResponse(response);
085 }
086
087 return response;
088 }
089
090 @Override
091 public void addHeader(String name, String value) {
092 super.addHeader(
093 HttpUtil.sanitizeHeader(name), HttpUtil.sanitizeHeader(value));
094 }
095
096 @Override
097 public void sendRedirect(String location) throws IOException {
098 super.sendRedirect(HttpUtil.sanitizeHeader(location));
099 }
100
101 @Override
102 public void setCharacterEncoding(String charset) {
103 super.setCharacterEncoding(HttpUtil.sanitizeHeader(charset));
104 }
105
106 @Override
107 public void setContentType(String type) {
108 super.setContentType(HttpUtil.sanitizeHeader(type));
109 }
110
111 @Override
112 public void setHeader(String name, String value) {
113 super.setHeader(
114 HttpUtil.sanitizeHeader(name), HttpUtil.sanitizeHeader(value));
115 }
116
117 protected static void setXContentOptions(
118 HttpServletRequest request, HttpServletResponse response) {
119
120 if (!_X_CONTENT_TYPE_OPTIONS) {
121 return;
122 }
123
124 if (_X_CONTENT_TYPE_OPTIONS_URLS_EXCLUDES.length > 0) {
125 String requestURI = request.getRequestURI();
126
127 for (String url : _X_CONTENT_TYPE_OPTIONS_URLS_EXCLUDES) {
128 if (requestURI.startsWith(url)) {
129 return;
130 }
131 }
132 }
133
134 response.setHeader(HttpHeaders.X_CONTENT_TYPE_OPTIONS, "nosniff");
135 }
136
137 protected static void setXFrameOptions(
138 HttpServletRequest request, HttpServletResponse response) {
139
140 if (!_X_FRAME_OPTIONS) {
141 return;
142 }
143
144 String requestURI = request.getRequestURI();
145
146 for (KeyValuePair xFrameOptionKVP : _xFrameOptionKVPs) {
147 String url = xFrameOptionKVP.getKey();
148 String value = xFrameOptionKVP.getValue();
149
150 if (requestURI.startsWith(url)) {
151 if (value != null) {
152 response.setHeader(
153 HttpHeaders.X_FRAME_OPTIONS,
154 xFrameOptionKVP.getValue());
155 }
156
157 return;
158 }
159 }
160
161 response.setHeader(HttpHeaders.X_FRAME_OPTIONS, "DENY");
162 }
163
164 protected static void setXXSSProtection(
165 HttpServletRequest request, HttpServletResponse response) {
166
167 HttpSession session = request.getSession(false);
168
169 if ((session != null) &&
170 (session.getAttribute(_DISABLE_XSS_AUDITOR) != null)) {
171
172 session.removeAttribute(_DISABLE_XSS_AUDITOR);
173
174 response.setHeader(HttpHeaders.X_XSS_PROTECTION, "0");
175
176 return;
177 }
178
179 if (Validator.isNull(_X_XSS_PROTECTION)) {
180 return;
181 }
182
183 response.setHeader(HttpHeaders.X_XSS_PROTECTION, _X_XSS_PROTECTION);
184 }
185
186 private SanitizedServletResponse(HttpServletResponse response) {
187 super(response);
188 }
189
190 private static final String _DISABLE_XSS_AUDITOR =
191 SanitizedServletResponse.class.getName() + "DISABLE_XSS_AUDITOR";
192
193 private static final boolean _X_CONTENT_TYPE_OPTIONS =
194 GetterUtil.getBoolean(
195 SystemProperties.get("http.header.secure.x.content.type.options"),
196 true);
197
198 private static final String[] _X_CONTENT_TYPE_OPTIONS_URLS_EXCLUDES =
199 StringUtil.split(
200 SystemProperties.get(
201 "http.header.secure.x.content.type.options.urls.excludes"));
202
203 private static final boolean _X_FRAME_OPTIONS;
204
205 private static final String _X_XSS_PROTECTION = SystemProperties.get(
206 "http.header.secure.x.xss.protection");
207
208 private static final KeyValuePair[] _xFrameOptionKVPs;
209
210 static {
211 String httpHeaderSecureXFrameOptionsKey =
212 "http.header.secure.x.frame.options";
213
214 Properties properties = new SortedProperties(
215 new Comparator<String>() {
216
217 @Override
218 public int compare(String key1, String key2) {
219 return GetterUtil.getIntegerStrict(key1) -
220 GetterUtil.getIntegerStrict(key2);
221 }
222
223 },
224 PropertiesUtil.getProperties(
225 SystemProperties.getProperties(),
226 httpHeaderSecureXFrameOptionsKey.concat(StringPool.PERIOD),
227 true));
228
229 List<KeyValuePair> xFrameOptionKVPs = new ArrayList<KeyValuePair>(
230 properties.size());
231
232 for (Map.Entry<Object, Object> entry : properties.entrySet()) {
233 String propertyValue = (String)entry.getValue();
234
235 String[] propertyValueParts = StringUtil.split(
236 propertyValue, CharPool.PIPE);
237
238 if (propertyValueParts.length > 2) {
239 continue;
240 }
241
242 String url = StringUtil.trim(propertyValueParts[0]);
243
244 if (Validator.isNull(url)) {
245 continue;
246 }
247
248 if (propertyValueParts.length == 1) {
249 xFrameOptionKVPs.add(new KeyValuePair(url, null));
250
251 continue;
252 }
253
254 String value = StringUtil.trim(propertyValueParts[1]);
255
256 if (Validator.isNull(value)) {
257 value = null;
258 }
259
260 xFrameOptionKVPs.add(new KeyValuePair(url, value));
261 }
262
263 _xFrameOptionKVPs = xFrameOptionKVPs.toArray(
264 new KeyValuePair[xFrameOptionKVPs.size()]);
265
266 if (_xFrameOptionKVPs.length == 0) {
267 _X_FRAME_OPTIONS = false;
268 }
269 else {
270 _X_FRAME_OPTIONS = GetterUtil.getBoolean(
271 SystemProperties.get(httpHeaderSecureXFrameOptionsKey), true);
272 }
273 }
274
275 }