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.PropsKeys;
022 import com.liferay.portal.kernel.util.PropsUtil;
023 import com.liferay.portal.kernel.util.ServerDetector;
024 import com.liferay.portal.kernel.util.SortedProperties;
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
029 import java.io.IOException;
030
031 import java.util.ArrayList;
032 import java.util.Comparator;
033 import java.util.List;
034 import java.util.Map;
035 import java.util.Properties;
036
037 import javax.servlet.http.HttpServletRequest;
038 import javax.servlet.http.HttpServletResponse;
039 import javax.servlet.http.HttpServletResponseWrapper;
040
041
046 public class SanitizedServletResponse extends HttpServletResponseWrapper {
047
048 public static HttpServletResponse getSanitizedServletResponse(
049 HttpServletRequest request, HttpServletResponse response) {
050
051 setXContentOptions(request, response);
052 setXFrameOptions(request, response);
053 setXXSSProtection(request, response);
054
055 if (ServerDetector.isResin()) {
056 response = new SanitizedServletResponse(response);
057 }
058
059 return response;
060 }
061
062 @Override
063 public void addHeader(String name, String value) {
064 super.addHeader(
065 HttpUtil.sanitizeHeader(name), HttpUtil.sanitizeHeader(value));
066 }
067
068 @Override
069 public void sendRedirect(String location) throws IOException {
070 super.sendRedirect(HttpUtil.sanitizeHeader(location));
071 }
072
073 @Override
074 public void setCharacterEncoding(String charset) {
075 super.setCharacterEncoding(HttpUtil.sanitizeHeader(charset));
076 }
077
078 @Override
079 public void setContentType(String type) {
080 super.setContentType(HttpUtil.sanitizeHeader(type));
081 }
082
083 @Override
084 public void setHeader(String name, String value) {
085 super.setHeader(
086 HttpUtil.sanitizeHeader(name), HttpUtil.sanitizeHeader(value));
087 }
088
089 protected static void setXContentOptions(
090 HttpServletRequest request, HttpServletResponse response) {
091
092 if (!_X_CONTENT_TYPE_OPTIONS) {
093 return;
094 }
095
096 if (_X_CONTENT_TYPE_OPTIONS_URLS_EXCLUDES.length > 0) {
097 String requestURI = request.getRequestURI();
098
099 for (String url : _X_CONTENT_TYPE_OPTIONS_URLS_EXCLUDES) {
100 if (requestURI.startsWith(url)) {
101 return;
102 }
103 }
104 }
105
106 response.setHeader(HttpHeaders.X_CONTENT_TYPE_OPTIONS, "nosniff");
107 }
108
109 protected static void setXFrameOptions(
110 HttpServletRequest request, HttpServletResponse response) {
111
112 if (!_X_FRAME_OPTIONS) {
113 return;
114 }
115
116 String requestURI = request.getRequestURI();
117
118 for (KeyValuePair _xFrameOptionKVP : _xFrameOptionKVPs) {
119 String url = _xFrameOptionKVP.getKey();
120
121 if (requestURI.startsWith(url)) {
122 response.setHeader(
123 HttpHeaders.X_FRAME_OPTIONS, _xFrameOptionKVP.getValue());
124
125 return;
126 }
127 }
128
129 response.setHeader(HttpHeaders.X_FRAME_OPTIONS, "DENY");
130 }
131
132 protected static void setXXSSProtection(
133 HttpServletRequest request, HttpServletResponse response) {
134
135 if (!_X_XSS_PROTECTION) {
136 return;
137 }
138
139 response.setHeader(HttpHeaders.X_XSS_PROTECTION, "1; mode=block");
140 }
141
142 private SanitizedServletResponse(HttpServletResponse response) {
143 super(response);
144 }
145
146 private static final boolean _X_CONTENT_TYPE_OPTIONS =
147 GetterUtil.getBoolean(
148 PropsUtil.get(PropsKeys.HTTP_HEADER_SECURE_X_CONTENT_TYPE_OPTIONS),
149 true);
150
151 private static final String[] _X_CONTENT_TYPE_OPTIONS_URLS_EXCLUDES =
152 PropsUtil.getArray(
153 PropsKeys.HTTP_HEADER_SECURE_X_CONTENT_TYPE_OPTIONS_URLS_EXCLUDES);
154
155 private static final boolean _X_FRAME_OPTIONS;
156
157 private static final boolean _X_XSS_PROTECTION = GetterUtil.getBoolean(
158 PropsUtil.get(PropsKeys.HTTP_HEADER_SECURE_X_XSS_PROTECTION), true);
159
160 private static final KeyValuePair[] _xFrameOptionKVPs;
161
162 static {
163 Properties properties = new SortedProperties(
164 new Comparator<String>() {
165
166 @Override
167 public int compare(String key1, String key2) {
168 return GetterUtil.getIntegerStrict(key1) -
169 GetterUtil.getIntegerStrict(key2);
170 }
171
172 },
173 PropsUtil.getProperties(
174 PropsKeys.HTTP_HEADER_SECURE_X_FRAME_OPTIONS +
175 StringPool.PERIOD,
176 true));
177
178 List<KeyValuePair> xFrameOptionKVPs = new ArrayList<KeyValuePair>(
179 properties.size());
180
181 for (Map.Entry<Object, Object> entry : properties.entrySet()) {
182 String propertyValue = (String)entry.getValue();
183
184 String[] propertyValueParts = StringUtil.split(
185 propertyValue, CharPool.COMMA);
186
187 if (propertyValueParts.length != 2) {
188 continue;
189 }
190
191 String url = StringUtil.trim(propertyValueParts[0]);
192
193 if (Validator.isNull(url)) {
194 continue;
195 }
196
197 String value = StringUtil.trim(propertyValueParts[1]);
198
199 if (Validator.isNull(value)) {
200 continue;
201 }
202
203 KeyValuePair x = new KeyValuePair(url, value);
204
205 xFrameOptionKVPs.add(x);
206 }
207
208 _xFrameOptionKVPs = xFrameOptionKVPs.toArray(
209 new KeyValuePair[xFrameOptionKVPs.size()]);
210
211 if (_xFrameOptionKVPs.length == 0) {
212 _X_FRAME_OPTIONS = false;
213 }
214 else {
215 _X_FRAME_OPTIONS = GetterUtil.getBoolean(
216 PropsUtil.get(PropsKeys.HTTP_HEADER_SECURE_X_FRAME_OPTIONS),
217 true);
218 }
219 }
220
221 }