Fix NodeServlet Vulnerabilities
[dmaap/datarouter.git] / datarouter-node / src / main / java / org / onap / dmaap / datarouter / node / NodeUtils.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.node;
26
27 import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
28 import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS;
29 import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
30
31 import com.att.eelf.configuration.EELFLogger;
32 import com.att.eelf.configuration.EELFManager;
33 import java.io.FileInputStream;
34 import java.io.IOException;
35 import java.net.InetAddress;
36 import java.security.KeyStore;
37 import java.security.MessageDigest;
38 import java.security.cert.X509Certificate;
39 import java.text.SimpleDateFormat;
40 import java.util.Date;
41 import java.util.Enumeration;
42 import java.util.TimeZone;
43 import org.apache.commons.codec.binary.Base64;
44 import org.apache.log4j.Logger;
45 import org.onap.dmaap.datarouter.node.eelf.EelfMsgs;
46 import org.slf4j.MDC;
47
48 import javax.servlet.http.HttpServletResponse;
49
50 /**
51  * Utility functions for the data router node
52  */
53 public class NodeUtils {
54
55     private static EELFLogger eelfLogger = EELFManager.getInstance()
56         .getLogger("org.onap.dmaap.datarouter.node.NodeUtils");
57     private static Logger nodeUtilsLogger = Logger.getLogger("org.onap.dmaap.datarouter.node.NodeUtils");
58     private static SimpleDateFormat logDate;
59
60     static {
61         logDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
62         logDate.setTimeZone(TimeZone.getTimeZone("GMT"));
63     }
64
65     private NodeUtils() {
66     }
67
68     /**
69      * Base64 encode a byte array
70      *
71      * @param raw The bytes to be encoded
72      * @return The encoded string
73      */
74     public static String base64Encode(byte[] raw) {
75         return (Base64.encodeBase64String(raw));
76     }
77
78     /**
79      * Given a user and password, generate the credentials
80      *
81      * @param user User name
82      * @param password User password
83      * @return Authorization header value
84      */
85     public static String getAuthHdr(String user, String password) {
86         if (user == null || password == null) {
87             return (null);
88         }
89         return ("Basic " + base64Encode((user + ":" + password).getBytes()));
90     }
91
92     /**
93      * Given a node name, generate the credentials
94      *
95      * @param node Node name
96      */
97     public static String getNodeAuthHdr(String node, String key) {
98         try {
99             MessageDigest md = MessageDigest.getInstance("SHA");
100             md.update(key.getBytes());
101             md.update(node.getBytes());
102             md.update(key.getBytes());
103             return (getAuthHdr(node, base64Encode(md.digest())));
104         } catch (Exception exception) {
105             nodeUtilsLogger
106                 .error("Exception in generating Credentials for given node name:= " + exception.toString(), exception);
107             return (null);
108         }
109     }
110
111     /**
112      * Given a keystore file and its password, return the value of the CN of the first private key entry with a
113      * certificate.
114      *
115      * @param kstype The type of keystore
116      * @param ksfile The file name of the keystore
117      * @param kspass The password of the keystore
118      * @return CN of the certificate subject or null
119      */
120     public static String getCanonicalName(String kstype, String ksfile, String kspass) {
121         KeyStore ks;
122         try {
123             ks = KeyStore.getInstance(kstype);
124             try (FileInputStream fileInputStream = new FileInputStream(ksfile)) {
125                 ks.load(fileInputStream, kspass.toCharArray());
126             } catch (IOException ioException) {
127                 nodeUtilsLogger.error("IOException occurred while opening FileInputStream: " + ioException.getMessage(),
128                     ioException);
129                 return (null);
130             }
131         } catch (Exception e) {
132             setIpAndFqdnForEelf("getCanonicalName");
133             eelfLogger.error(EelfMsgs.MESSAGE_KEYSTORE_LOAD_ERROR, ksfile, e.toString());
134             nodeUtilsLogger.error("NODE0401 Error loading my keystore file + " + ksfile + " " + e.toString(), e);
135             return (null);
136         }
137         return (getCanonicalName(ks));
138     }
139
140     /**
141      * Given a keystore, return the value of the CN of the first private key entry with a certificate.
142      *
143      * @param ks The KeyStore
144      * @return CN of the certificate subject or null
145      */
146     public static String getCanonicalName(KeyStore ks) {
147         try {
148             Enumeration<String> aliases = ks.aliases();
149             while (aliases.hasMoreElements()) {
150                 String s = aliases.nextElement();
151                 if (ks.entryInstanceOf(s, KeyStore.PrivateKeyEntry.class)) {
152                     X509Certificate c = (X509Certificate) ks.getCertificate(s);
153                     if (c != null) {
154                         String subject = c.getSubjectX500Principal().getName();
155                         String[] parts = subject.split(",");
156                         if (parts.length < 1) {
157                             return (null);
158                         }
159                         subject = parts[5].trim();
160                         if (!subject.startsWith("CN=")) {
161                             return (null);
162
163                         }
164                         return (subject.substring(3));
165                     }
166                 }
167             }
168         } catch (Exception e) {
169             nodeUtilsLogger.error("NODE0402 Error extracting my name from my keystore file " + e.toString(), e);
170         }
171         return (null);
172     }
173
174     /**
175      * Given a string representation of an IP address, get the corresponding byte array
176      *
177      * @param ip The IP address as a string
178      * @return The IP address as a byte array or null if the address is invalid
179      */
180     public static byte[] getInetAddress(String ip) {
181         try {
182             return (InetAddress.getByName(ip).getAddress());
183         } catch (Exception exception) {
184             nodeUtilsLogger
185                 .error("Exception in generating byte array for given IP address := " + exception.toString(), exception);
186         }
187         return (null);
188     }
189
190     /**
191      * Given a uri with parameters, split out the feed ID and file ID
192      */
193     public static String[] getFeedAndFileID(String uriandparams) {
194         int end = uriandparams.length();
195         int i = uriandparams.indexOf('#');
196         if (i != -1 && i < end) {
197             end = i;
198         }
199         i = uriandparams.indexOf('?');
200         if (i != -1 && i < end) {
201             end = i;
202         }
203         end = uriandparams.lastIndexOf('/', end);
204         if (end < 2) {
205             return (null);
206         }
207         i = uriandparams.lastIndexOf('/', end - 1);
208         if (i == -1) {
209             return (null);
210         }
211         return (new String[]{uriandparams.substring(i + 1, end), uriandparams.substring(end + 1)});
212     }
213
214     /**
215      * Escape fields that might contain vertical bar, backslash, or newline by replacing them with backslash p,
216      * backslash e and backslash n.
217      */
218     public static String loge(String s) {
219         if (s == null) {
220             return (s);
221         }
222         return (s.replaceAll("\\\\", "\\\\e").replaceAll("\\|", "\\\\p").replaceAll("\n", "\\\\n"));
223     }
224
225     /**
226      * Undo what loge does.
227      */
228     public static String unloge(String s) {
229         if (s == null) {
230             return (s);
231         }
232         return (s.replaceAll("\\\\p", "\\|").replaceAll("\\\\n", "\n").replaceAll("\\\\e", "\\\\"));
233     }
234
235     /**
236      * Format a logging timestamp as yyyy-mm-ddThh:mm:ss.mmmZ
237      */
238     public static String logts(long when) {
239         return (logts(new Date(when)));
240     }
241
242     /**
243      * Format a logging timestamp as yyyy-mm-ddThh:mm:ss.mmmZ
244      */
245     public static synchronized String logts(Date when) {
246         return (logDate.format(when));
247     }
248
249     /* Method prints method name, server FQDN and IP Address of the machine in EELF logs
250      * @Method - setIpAndFqdnForEelf - Rally:US664892
251      * @Params - method, prints method name in EELF log.
252      */
253     public static void setIpAndFqdnForEelf(String method) {
254         MDC.clear();
255         MDC.put(MDC_SERVICE_NAME, method);
256         try {
257             MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName());
258             MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
259         } catch (Exception exception) {
260             nodeUtilsLogger
261                 .error("Exception in generating byte array for given IP address := " + exception.toString(), exception);
262         }
263
264     }
265
266     public static void sendResponseError(HttpServletResponse response, int errorCode, Logger intlogger) {
267         try {
268             response.sendError(errorCode);
269         } catch (IOException ioe) {
270             intlogger.error("IOException" + ioe.getMessage());
271         }
272     }
273
274
275 }