bf09c12232bdcd2372d43929be52a9376fe37748
[portal.git] / ecomp-portal-BE-os / src / main / java / org / onap / portalapp / filter / SecurityXssFilter.java
1
2 /*-
3  * ============LICENSE_START==========================================
4  * ONAP Portal
5  * ===================================================================
6  * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
7  * ===================================================================
8  *
9  * Unless otherwise specified, all software contained herein is licensed
10  * under the Apache License, Version 2.0 (the "License");
11  * you may not use this software except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *             http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  * Unless otherwise specified, all documentation contained herein is licensed
23  * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
24  * you may not use this documentation except in compliance with the License.
25  * You may obtain a copy of the License at
26  *
27  *             https://creativecommons.org/licenses/by/4.0/
28  *
29  * Unless required by applicable law or agreed to in writing, documentation
30  * distributed under the License is distributed on an "AS IS" BASIS,
31  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32  * See the License for the specific language governing permissions and
33  * limitations under the License.
34  *
35  * ============LICENSE_END============================================
36  *
37  * 
38  */
39 package org.onap.portalapp.filter;
40
41 import java.io.BufferedReader;
42 import java.io.ByteArrayInputStream;
43 import java.io.ByteArrayOutputStream;
44 import java.io.IOException;
45 import java.io.InputStreamReader;
46 import java.nio.charset.StandardCharsets;
47
48 import javax.servlet.FilterChain;
49 import javax.servlet.ReadListener;
50 import javax.servlet.ServletException;
51 import javax.servlet.ServletInputStream;
52 import javax.servlet.http.HttpServletRequest;
53 import javax.servlet.http.HttpServletRequestWrapper;
54 import javax.servlet.http.HttpServletResponse;
55
56 import org.apache.commons.io.IOUtils;
57 import org.apache.commons.lang.StringUtils;
58 import org.apache.http.HttpStatus;
59 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
60 import org.springframework.web.filter.OncePerRequestFilter;
61
62 public class SecurityXssFilter extends OncePerRequestFilter {
63
64         private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SecurityXssFilter.class);
65
66         private static final String APPLICATION_JSON = "application/json";
67
68         private static final String ERROR_BAD_REQUEST = "{\"error\":\"BAD_REQUEST\"}";
69
70         private SecurityXssValidator validator = SecurityXssValidator.getInstance();
71
72         public class RequestWrapper extends HttpServletRequestWrapper {
73
74                 private ByteArrayOutputStream cachedBytes;
75
76                 public RequestWrapper(HttpServletRequest request) {
77                         super(request);
78                 }
79
80                 @Override
81                 public ServletInputStream getInputStream() throws IOException {
82                         if (cachedBytes == null)
83                                 cacheInputStream();
84
85                         return new CachedServletInputStream();
86                 }
87
88                 @Override
89                 public BufferedReader getReader() throws IOException {
90                         return new BufferedReader(new InputStreamReader(getInputStream()));
91                 }
92
93                 private void cacheInputStream() throws IOException {
94                         cachedBytes = new ByteArrayOutputStream();
95                         IOUtils.copy(super.getInputStream(), cachedBytes);
96                 }
97
98                 public class CachedServletInputStream extends ServletInputStream {
99                         private ByteArrayInputStream input;
100
101                         public CachedServletInputStream() {
102                                 input = new ByteArrayInputStream(cachedBytes.toByteArray());
103                         }
104
105                         @Override
106                         public int read() throws IOException {
107                                 return input.read();
108                         }
109
110                         @Override
111                         public boolean isFinished() {
112                                 return false;
113                         }
114
115                         @Override
116                         public boolean isReady() {
117                                 return false;
118                         }
119
120                         @Override
121                         public void setReadListener(ReadListener readListener) {
122
123                         }
124
125                 }
126         }
127
128         @Override
129         protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
130                         throws ServletException, IOException {
131                 if (validateRequestType(request)) {
132                         request = new RequestWrapper(request);
133                         String requestData = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8.toString());
134                         try {
135                                 if (StringUtils.isNotBlank(requestData) && validator.denyXSS(requestData)) {
136                                         response.setContentType(APPLICATION_JSON);
137                                         response.setStatus(HttpStatus.SC_BAD_REQUEST);
138                                         response.getWriter().write(ERROR_BAD_REQUEST);
139                                         throw new SecurityException(ERROR_BAD_REQUEST);
140                                 }
141                         } catch (Exception e) {
142                                 logger.error(EELFLoggerDelegate.errorLogger, "doFilterInternal() failed due to BAD_REQUEST", e);
143                                 response.getWriter().close();
144                                 return;
145                         }
146                         filterChain.doFilter(request, response);
147
148                 } else {
149                         filterChain.doFilter(request, response);
150                 }
151
152         }
153
154         private boolean validateRequestType(HttpServletRequest request) {
155                 return (request.getMethod().equalsIgnoreCase("POST") || request.getMethod().equalsIgnoreCase("PUT")
156                                 || request.getMethod().equalsIgnoreCase("DELETE"));
157         }
158 }