Fix FeedServlet Vulnerabilities
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / onap / dmaap / datarouter / provisioning / FeedServlet.java
1 /*******************************************************************************
2  * ============LICENSE_START==================================================
3  * * org.onap.dmaap
4  * * ===========================================================================
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6  * * ===========================================================================
7  * * Licensed under the Apache License, Version 2.0 (the "License");
8  * * you may not use this file except in compliance with the License.
9  * * You may obtain a copy of the License at
10  * *
11  *  *      http://www.apache.org/licenses/LICENSE-2.0
12  * *
13  *  * Unless required by applicable law or agreed to in writing, software
14  * * distributed under the License is distributed on an "AS IS" BASIS,
15  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * * See the License for the specific language governing permissions and
17  * * limitations under the License.
18  * * ============LICENSE_END====================================================
19  * *
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  * *
22  ******************************************************************************/
23
24
25 package org.onap.dmaap.datarouter.provisioning;
26
27 import java.io.IOException;
28 import java.io.InvalidObjectException;
29
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpServletResponse;
32
33 import org.json.JSONException;
34 import org.json.JSONObject;
35 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
36 import org.onap.dmaap.datarouter.provisioning.beans.EventLogRecord;
37 import org.onap.dmaap.datarouter.provisioning.beans.Feed;
38 import org.onap.dmaap.datarouter.provisioning.eelf.EelfMsgs;
39
40 import com.att.eelf.configuration.EELFLogger;
41 import com.att.eelf.configuration.EELFManager;
42
43 import static org.onap.dmaap.datarouter.provisioning.utils.HttpServletUtils.sendResponseError;
44
45 /**
46  * This servlet handles provisioning for the <feedURL> which is generated by the provisioning
47  * server to handle a particular feed. It supports DELETE to mark the feed as deleted,
48  * and GET to retrieve information about the feed, and PUT to modify the feed.
49  *
50  * @author Robert Eby
51  * @version $Id$
52  */
53 @SuppressWarnings("serial")
54 public class FeedServlet extends ProxyServlet {
55
56     //Adding EELF Logger Rally:US664892
57     private static EELFLogger eelflogger = EELFManager.getInstance().getLogger("org.onap.dmaap.datarouter.provisioning.FeedServlet");
58
59     /**
60      * Delete the Feed at the address /feed/<feednumber>.
61      * See the <i>Deleting a Feed</i> section in the <b>Provisioning API</b>
62      * document for details on how this method should be invoked.
63      */
64     @Override
65     public void doDelete(HttpServletRequest req, HttpServletResponse resp) {
66         setIpAndFqdnForEelf("doDelete");
67         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_FEEDID, req.getHeader(BEHALF_HEADER),getIdFromPath(req)+"");
68         EventLogRecord elr = new EventLogRecord(req);
69         String message = isAuthorizedForProvisioning(req);
70         if (message != null) {
71             elr.setMessage(message);
72             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
73             eventlogger.info(elr);
74             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
75             return;
76         }
77         if (isProxyServer()) {
78             try {
79                 super.doDelete(req, resp);
80             } catch (IOException ioe) {
81                 eventlogger.error("IOException" + ioe.getMessage());
82             }
83             return;
84         }
85         String bhdr = req.getHeader(BEHALF_HEADER);
86         if (bhdr == null) {
87             message = "Missing "+BEHALF_HEADER+" header.";
88             elr.setMessage(message);
89             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
90             eventlogger.info(elr);
91             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
92             return;
93         }
94         int feedid = getIdFromPath(req);
95         if (feedid < 0) {
96             message = "Missing or bad feed number.";
97             elr.setMessage(message);
98             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
99             eventlogger.info(elr);
100             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
101             return;
102         }
103         Feed feed = Feed.getFeedById(feedid);
104         if (feed == null || feed.isDeleted()) {
105             message = "Missing or bad feed number.";
106             elr.setMessage(message);
107             elr.setResult(HttpServletResponse.SC_NOT_FOUND);
108             eventlogger.info(elr);
109             sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
110             return;
111         }
112         // Check with the Authorizer
113         AuthorizationResponse aresp = authz.decide(req);
114         if (! aresp.isAuthorized()) {
115             message = "Policy Engine disallows access.";
116             elr.setMessage(message);
117             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
118             eventlogger.info(elr);
119             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
120             return;
121         }
122
123         // Delete FEED table entry (set DELETED flag)
124         feed.setDeleted(true);
125         if (doUpdate(feed)) {
126             activeFeeds--;
127             // send response
128             elr.setResult(HttpServletResponse.SC_NO_CONTENT);
129             eventlogger.info(elr);
130             resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
131             provisioningDataChanged();
132         } else {
133             // Something went wrong with the UPDATE
134             elr.setResult(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
135             eventlogger.info(elr);
136             sendResponseError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, DB_PROBLEM_MSG, eventlogger);
137         }
138     }
139     /**
140      * Get information on the feed at the address /feed/&lt;feednumber&gt;.
141      * See the <i>Retrieving Information about a Feed</i> section in the <b>Provisioning API</b>
142      * document for details on how this method should be invoked.
143      */
144     @Override
145     public void doGet(HttpServletRequest req, HttpServletResponse resp) {
146         setIpAndFqdnForEelf("doGet");
147         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_FEEDID, req.getHeader(BEHALF_HEADER),getIdFromPath(req)+"");
148         EventLogRecord elr = new EventLogRecord(req);
149         String message = isAuthorizedForProvisioning(req);
150         if (message != null) {
151             elr.setMessage(message);
152             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
153             eventlogger.info(elr);
154             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
155             return;
156         }
157         if (isProxyServer()) {
158             try {
159                 super.doGet(req, resp);
160             } catch (IOException ioe) {
161                 eventlogger.error("IOException" + ioe.getMessage());
162             }
163             return;
164         }
165         String bhdr = req.getHeader(BEHALF_HEADER);
166         if (bhdr == null) {
167             message = "Missing "+BEHALF_HEADER+" header.";
168             elr.setMessage(message);
169             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
170             eventlogger.info(elr);
171             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
172             return;
173         }
174         int feedid = getIdFromPath(req);
175         if (feedid < 0) {
176             message = "Missing or bad feed number.";
177             elr.setMessage(message);
178             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
179             eventlogger.info(elr);
180             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
181             return;
182         }
183         Feed feed = Feed.getFeedById(feedid);
184         if (feed == null || feed.isDeleted()) {
185             message = "Missing or bad feed number.";
186             elr.setMessage(message);
187             elr.setResult(HttpServletResponse.SC_NOT_FOUND);
188             eventlogger.info(elr);
189             sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
190             return;
191         }
192         // Check with the Authorizer
193         AuthorizationResponse aresp = authz.decide(req);
194         if (! aresp.isAuthorized()) {
195             message = "Policy Engine disallows access.";
196             elr.setMessage(message);
197             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
198             eventlogger.info(elr);
199             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
200             return;
201         }
202
203         // send response
204         elr.setResult(HttpServletResponse.SC_OK);
205         eventlogger.info(elr);
206         resp.setStatus(HttpServletResponse.SC_OK);
207         resp.setContentType(FEEDFULL_CONTENT_TYPE);
208         try {
209             resp.getOutputStream().print(feed.asJSONObject(true).toString());
210         } catch (IOException ioe) {
211             eventlogger.error("IOException" + ioe.getMessage());
212         }
213     }
214     /**
215      * PUT on the &lt;feedURL&gt; for a feed.
216      * See the <i>Modifying a Feed</i> section in the <b>Provisioning API</b>
217      * document for details on how this method should be invoked.
218      */
219     @Override
220     public void doPut(HttpServletRequest req, HttpServletResponse resp) {
221         setIpAndFqdnForEelf("doPut");
222         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_FEEDID, req.getHeader(BEHALF_HEADER),getIdFromPath(req)+"");
223         EventLogRecord elr = new EventLogRecord(req);
224         String message = isAuthorizedForProvisioning(req);
225         if (message != null) {
226             elr.setMessage(message);
227             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
228             eventlogger.info(elr);
229             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
230             return;
231         }
232         if (isProxyServer()) {
233             try {
234                 super.doPut(req, resp);
235             } catch (IOException ioe) {
236                 eventlogger.error("IOException" + ioe.getMessage());
237             }
238             return;
239         }
240         String bhdr = req.getHeader(BEHALF_HEADER);
241         if (bhdr == null) {
242             message = "Missing "+BEHALF_HEADER+" header.";
243             elr.setMessage(message);
244             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
245             eventlogger.info(elr);
246             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
247             return;
248         }
249         int feedid = getIdFromPath(req);
250         if (feedid < 0) {
251             message = "Missing or bad feed number.";
252             elr.setMessage(message);
253             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
254             eventlogger.info(elr);
255             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
256             return;
257         }
258         Feed oldFeed = Feed.getFeedById(feedid);
259         if (oldFeed == null || oldFeed.isDeleted()) {
260             message = "Missing or bad feed number.";
261             elr.setMessage(message);
262             elr.setResult(HttpServletResponse.SC_NOT_FOUND);
263             eventlogger.info(elr);
264             sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
265             return;
266         }
267         // check content type is FEED_CONTENT_TYPE, version 1.0
268         ContentHeader ch = getContentHeader(req);
269         String ver = ch.getAttribute("version");
270         if (!ch.getType().equals(FEED_BASECONTENT_TYPE) || !(ver.equals("1.0") || ver.equals("2.0"))) {
271             message = "Incorrect content-type";
272             elr.setMessage(message);
273             elr.setResult(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
274             eventlogger.info(elr);
275             sendResponseError(resp, HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, message, eventlogger);
276             return;
277         }
278         JSONObject jo = getJSONfromInput(req);
279         if (jo == null) {
280             message = "Badly formed JSON";
281             elr.setMessage(message);
282             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
283             eventlogger.info(elr);
284             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
285             return;
286         }
287         if (intlogger.isDebugEnabled())
288             intlogger.debug(jo.toString());
289         Feed feed = null;
290         try {
291             feed = new Feed(jo);
292         } catch (InvalidObjectException e) {
293             message = e.getMessage();
294             elr.setMessage(message);
295             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
296             eventlogger.info(elr);
297             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
298             return;
299         }
300         feed.setFeedid(feedid);
301         feed.setPublisher(bhdr);    // set from X-ATT-DR-ON-BEHALF-OF header
302
303         String subjectgroup = (req.getHeader("X-ATT-DR-ON-BEHALF-OF-GROUP"));  //Adding for group feature:Rally US708115
304         if (!oldFeed.getPublisher().equals(feed.getPublisher()) && subjectgroup == null) {
305             message = "This feed must be modified by the same publisher that created it.";
306             elr.setMessage(message);
307             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
308             eventlogger.info(elr);
309             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
310             return;
311         }
312         if (!oldFeed.getName().equals(feed.getName())) {
313             message = "The name of the feed may not be updated.";
314             elr.setMessage(message);
315             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
316             eventlogger.info(elr);
317             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
318             return;
319         }
320         if (!oldFeed.getVersion().equals(feed.getVersion())) {
321             message = "The version of the feed may not be updated.";
322             elr.setMessage(message);
323             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
324             eventlogger.info(elr);
325             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
326             return;
327         }
328         // Check with the Authorizer
329         AuthorizationResponse aresp = authz.decide(req);
330         if (! aresp.isAuthorized()) {
331             message = "Policy Engine disallows access.";
332             elr.setMessage(message);
333             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
334             eventlogger.info(elr);
335             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
336             return;
337         }
338
339         // Update FEEDS table entries
340         if (doUpdate(feed)) {
341             // send response
342             elr.setResult(HttpServletResponse.SC_OK);
343             eventlogger.info(elr);
344             resp.setStatus(HttpServletResponse.SC_OK);
345             resp.setContentType(FEEDFULL_CONTENT_TYPE);
346             try {
347                 resp.getOutputStream().print(feed.asLimitedJSONObject().toString());
348             } catch (IOException ioe) {
349                 eventlogger.error("IOException" + ioe.getMessage());
350             }
351
352
353             /**Change Owner ship of Feed //Adding for group feature:Rally US708115*/
354             if (jo.has("changeowner") && subjectgroup != null) {
355                 try {
356                     Boolean changeowner = (Boolean) jo.get("changeowner");
357                     if (changeowner != null && changeowner.equals(true)) {
358                         feed.setPublisher(req.getHeader(BEHALF_HEADER));
359                         feed.changeOwnerShip();
360                     }
361                 } catch (JSONException je) {
362                     eventlogger.error("JSONException" + je.getMessage());
363                 }
364             }
365             /***End of change ownership*/
366
367             provisioningDataChanged();
368         } else {
369             // Something went wrong with the UPDATE
370             elr.setResult(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
371             eventlogger.info(elr);
372             sendResponseError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, DB_PROBLEM_MSG, eventlogger);
373         }
374     }
375     /**
376      * POST on the &lt;feedURL&gt; -- not supported.
377      */
378     @Override
379     public void doPost(HttpServletRequest req, HttpServletResponse resp) {
380         setIpAndFqdnForEelf("doPost");
381         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF, req.getHeader(BEHALF_HEADER));
382         String message = "POST not allowed for the feedURL.";
383         EventLogRecord elr = new EventLogRecord(req);
384         elr.setMessage(message);
385         elr.setResult(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
386         eventlogger.info(elr);
387         sendResponseError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED, message, eventlogger);
388     }
389 }