1 /*******************************************************************************
2 * ============LICENSE_START========================================================================
3 * ONAP : ccsdk feature sdnr wt
4 * =================================================================================================
5 * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6 * =================================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software distributed under the License
13 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14 * or implied. See the License for the specific language governing permissions and limitations under
16 * ============LICENSE_END==========================================================================
17 ******************************************************************************/
18 package org.onap.ccsdk.features.sdnr.wt.devicemanager.base.http;
20 import java.io.ByteArrayInputStream;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27 import java.net.HttpURLConnection;
29 import java.net.URLConnection;
30 import java.nio.charset.Charset;
31 import java.nio.charset.StandardCharsets;
32 import java.nio.file.Files;
33 import java.security.KeyFactory;
34 import java.security.KeyManagementException;
35 import java.security.KeyStore;
36 import java.security.KeyStoreException;
37 import java.security.NoSuchAlgorithmException;
38 import java.security.UnrecoverableKeyException;
39 import java.security.cert.Certificate;
40 import java.security.cert.CertificateException;
41 import java.security.cert.CertificateFactory;
42 import java.security.cert.X509Certificate;
43 import java.security.interfaces.RSAPrivateKey;
44 import java.security.spec.InvalidKeySpecException;
45 import java.security.spec.PKCS8EncodedKeySpec;
46 import java.util.Base64;
48 import javax.annotation.Nonnull;
49 import javax.net.ssl.HostnameVerifier;
50 import javax.net.ssl.HttpsURLConnection;
51 import javax.net.ssl.KeyManager;
52 import javax.net.ssl.KeyManagerFactory;
53 import javax.net.ssl.SSLContext;
54 import javax.net.ssl.TrustManager;
55 import javax.xml.bind.DatatypeConverter;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
59 public class BaseHTTPClient {
61 private static Logger LOG = LoggerFactory.getLogger(BaseHTTPClient.class);
62 private static final int SSLCERT_NONE = -1;
63 private static final int SSLCERT_PCKS = 0;
64 private static final int SSLCERT_PEM = 1;
65 private static final int BUFSIZE = 1024;
66 private static final Charset CHARSET = StandardCharsets.UTF_8;
67 private static final String SSLCONTEXT = "TLSv1.2";
68 private static final int DEFAULT_HTTP_TIMEOUT_MS = 30000; // in ms
70 private final boolean trustAll;
71 private final String baseUrl;
73 private int timeout = DEFAULT_HTTP_TIMEOUT_MS;
74 private SSLContext sc = null;
76 public BaseHTTPClient(String base) {
80 public BaseHTTPClient(String base, boolean trustAllCerts) {
81 this(base, trustAllCerts, null, null, SSLCERT_NONE);
84 public BaseHTTPClient(String base, boolean trustAllCerts, String certFilename, String passphrase, int sslCertType) {
86 this.trustAll = trustAllCerts;
88 sc = setupSsl(trustAll, certFilename, passphrase, sslCertType);
89 } catch (KeyManagementException | NoSuchAlgorithmException | UnrecoverableKeyException | CertificateException
90 | KeyStoreException | IOException | InvalidKeySpecException e) {
91 LOG.warn("problem ssl setup: " + e.getMessage());
95 protected @Nonnull BaseHTTPResponse sendRequest(String uri, String method, String body, Map<String, String> headers)
97 return this.sendRequest(uri, method, body != null ? body.getBytes(CHARSET) : null, headers);
100 protected @Nonnull BaseHTTPResponse sendRequest(String uri, String method, byte[] body, Map<String, String> headers)
105 String surl = this.baseUrl;
106 if (!surl.endsWith("/") && uri.length() > 0) {
109 if (uri.startsWith("/")) {
110 uri = uri.substring(1);
113 LOG.debug("try to send request with url=" + this.baseUrl + uri + " as method=" + method);
114 LOG.trace("body:" + (body == null ? "null" : new String(body, CHARSET)));
115 URL url = new URL(surl);
116 URLConnection http = url.openConnection();
117 http.setConnectTimeout(this.timeout);
118 if (surl.toString().startsWith("https")) {
120 ((HttpsURLConnection) http).setSSLSocketFactory(sc.getSocketFactory());
122 LOG.debug("trusting all certs");
123 HostnameVerifier allHostsValid = (hostname, session) -> true;
124 ((HttpsURLConnection) http).setHostnameVerifier(allHostsValid);
126 } else // Should never happen
128 LOG.warn("No SSL context available");
129 return new BaseHTTPResponse(-1, "");
132 ((HttpURLConnection) http).setRequestMethod(method);
133 http.setDoOutput(true);
134 if (headers != null && headers.size() > 0) {
135 for (String key : headers.keySet()) {
136 http.setRequestProperty(key, headers.get(key));
137 LOG.trace("set http header " + key + ": " + headers.get(key));
140 byte[] buffer = new byte[BUFSIZE];
141 int len = 0, lensum = 0;
143 // Send the message to destination
144 if (!method.equals("GET") && body != null && body.length > 0) {
145 try (OutputStream output = http.getOutputStream()) {
150 int responseCode = ((HttpURLConnection) http).getResponseCode();
151 String sresponse = "";
152 InputStream response = null;
154 if (responseCode >= 200 && responseCode < 300) {
155 response = http.getInputStream();
157 response = ((HttpURLConnection) http).getErrorStream();
158 if (response == null) {
159 response = http.getInputStream();
162 if (response != null) {
164 len = response.read(buffer, 0, BUFSIZE);
169 sresponse += new String(buffer, 0, len, CHARSET);
172 LOG.debug("response is null");
174 } catch (Exception e) {
175 LOG.debug("No response. ", e);
177 if (response != null) {
181 LOG.debug("ResponseCode: " + responseCode);
182 LOG.trace("Response (len:{}): {}", String.valueOf(lensum), sresponse);
183 return new BaseHTTPResponse(responseCode, sresponse);
186 public static SSLContext setupSsl(boolean trustall)
187 throws NoSuchAlgorithmException, KeyManagementException, CertificateException, FileNotFoundException,
188 IOException, UnrecoverableKeyException, KeyStoreException, InvalidKeySpecException {
190 return setupSsl(trustall, null, null, SSLCERT_NONE);
194 * @param keyFilename filename for key file
195 * @param certFilename filename for cert file
196 * @throws NoSuchAlgorithmException
197 * @throws KeyManagementException
198 * @throws IOException
199 * @throws FileNotFoundException
200 * @throws CertificateException
201 * @throws KeyStoreException
202 * @throws UnrecoverableKeyException
203 * @throws InvalidKeySpecException
206 * Setup of SSLContext
208 * @param trustall true to switch of certificate verification
209 * @param certFilename filename for certificate file
210 * @param passPhrase for certificate
211 * @param certType of certificate
212 * @return SSL Context according to parameters
213 * @throws NoSuchAlgorithmException according name
214 * @throws KeyManagementException according name
215 * @throws CertificateException according name
216 * @throws FileNotFoundException according name
217 * @throws IOException according name
218 * @throws UnrecoverableKeyException according name
219 * @throws KeyStoreException according name
220 * @throws InvalidKeySpecException according name
222 public static SSLContext setupSsl(boolean trustall, String certFilename, String passPhrase, int certType)
223 throws NoSuchAlgorithmException, KeyManagementException, CertificateException, FileNotFoundException,
224 IOException, UnrecoverableKeyException, KeyStoreException, InvalidKeySpecException {
226 SSLContext sc = SSLContext.getInstance(SSLCONTEXT);
227 TrustManager[] trustCerts = null;
229 trustCerts = new TrustManager[] {new javax.net.ssl.X509TrustManager() {
231 public java.security.cert.X509Certificate[] getAcceptedIssuers() {
236 public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
239 public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
243 KeyManager[] kms = null;
244 if (certFilename != null && passPhrase != null && !certFilename.isEmpty() && !passPhrase.isEmpty()) {
245 if (certType == SSLCERT_PCKS) {
246 LOG.debug("try to load pcks file " + certFilename + " with passphrase=" + passPhrase);
247 KeyStore keyStore = KeyStore.getInstance("PKCS12");
248 FileInputStream fileInputStream = new FileInputStream(certFilename);
249 keyStore.load(fileInputStream, passPhrase.toCharArray());
250 KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
251 kmf.init(keyStore, passPhrase.toCharArray());
252 kms = kmf.getKeyManagers();
253 fileInputStream.close();
254 LOG.debug("successful");
256 } else if (certType == SSLCERT_PEM) {
257 LOG.debug("try to load pem files cert=" + certFilename + " key=" + passPhrase);
258 File fCert = new File(certFilename);
259 File fKey = new File(passPhrase);
260 KeyStore keyStore = KeyStore.getInstance("JKS");
262 byte[] certBytes = parseDERFromPEM(Files.readAllBytes(fCert.toPath()), "-----BEGIN CERTIFICATE-----",
263 "-----END CERTIFICATE-----");
264 byte[] keyBytes = parseDERFromPEM(Files.readAllBytes(fKey.toPath()), "-----BEGIN PRIVATE KEY-----",
265 "-----END PRIVATE KEY-----");
267 X509Certificate cert = generateCertificateFromDER(certBytes);
268 RSAPrivateKey key = generatePrivateKeyFromDER(keyBytes);
269 keyStore.setCertificateEntry("cert-alias", cert);
270 keyStore.setKeyEntry("key-alias", key, "changeit".toCharArray(), new Certificate[] {cert});
272 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
273 kmf.init(keyStore, "changeit".toCharArray());
274 kms = kmf.getKeyManagers();
275 LOG.debug("successful");
278 // Init the SSLContext with a TrustManager[] and SecureRandom()
279 sc.init(kms, trustCerts, new java.security.SecureRandom());
283 protected static byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter) {
284 String data = new String(pem);
285 String[] tokens = data.split(beginDelimiter);
286 tokens = tokens[1].split(endDelimiter);
287 return DatatypeConverter.parseBase64Binary(tokens[0]);
290 protected static RSAPrivateKey generatePrivateKeyFromDER(byte[] keyBytes)
291 throws InvalidKeySpecException, NoSuchAlgorithmException {
292 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
294 KeyFactory factory = KeyFactory.getInstance("RSA");
296 return (RSAPrivateKey) factory.generatePrivate(spec);
299 protected static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException {
300 CertificateFactory factory = CertificateFactory.getInstance("X.509");
302 return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes));
305 public static String getAuthorizationHeaderValue(String username, String password) {
306 return "Basic " + new String(Base64.getEncoder().encode((username + ":" + password).getBytes()));
309 public void setTimeout(int timeout) {
310 this.timeout = timeout;
313 public static int getSslCertPcks() {
317 public static int getSslCertNone() {
321 public static int getSslCertPEM() {