1 package org.opendaylight.mwtn.base.http;
3 import java.io.ByteArrayInputStream;
5 import java.io.FileInputStream;
6 import java.io.FileNotFoundException;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.OutputStream;
10 import java.net.HttpURLConnection;
12 import java.net.URLConnection;
13 import java.nio.charset.Charset;
14 import java.nio.charset.StandardCharsets;
15 import java.nio.file.Files;
16 import java.security.KeyFactory;
17 import java.security.KeyManagementException;
18 import java.security.KeyStore;
19 import java.security.KeyStoreException;
20 import java.security.NoSuchAlgorithmException;
21 import java.security.UnrecoverableKeyException;
22 import java.security.cert.Certificate;
23 import java.security.cert.CertificateException;
24 import java.security.cert.CertificateFactory;
25 import java.security.cert.X509Certificate;
26 import java.security.interfaces.RSAPrivateKey;
27 import java.security.spec.InvalidKeySpecException;
28 import java.security.spec.PKCS8EncodedKeySpec;
29 import java.util.Base64;
32 import javax.net.ssl.HostnameVerifier;
33 import javax.net.ssl.HttpsURLConnection;
34 import javax.net.ssl.KeyManager;
35 import javax.net.ssl.KeyManagerFactory;
36 import javax.net.ssl.SSLContext;
37 import javax.net.ssl.SSLSession;
38 import javax.net.ssl.TrustManager;
39 import javax.xml.bind.DatatypeConverter;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
44 public class BaseHTTPClient {
46 private static Logger LOG = LoggerFactory.getLogger(BaseHTTPClient.class);
47 public static int SSLCERT_NONE=-1;
48 public static int SSLCERT_PCKS=0;
49 public static int SSLCERT_PEM=1;
50 private SSLContext sc=null;
51 private static final int BUFSIZE = 1024;
52 private static final Charset CHARSET = StandardCharsets.UTF_8;
53 private static final String SSLCONTEXT = "TLSv1.2";
54 private static final int DEFAULT_HTTP_TIMEOUT = 30000; //in ms
55 private boolean TRUSTALL;
56 private final String baseUrl;
57 private int timeout = DEFAULT_HTTP_TIMEOUT;
59 public BaseHTTPClient(String base) {
62 public BaseHTTPClient(String base, boolean trustAllCerts)
64 this(base,trustAllCerts,null,null,SSLCERT_NONE);
66 public BaseHTTPClient(String base, boolean trustAllCerts,String certFilename,String passphrase,int sslCertType) {
68 this.TRUSTALL = trustAllCerts;
70 sc = setupSsl(TRUSTALL,certFilename,passphrase,sslCertType);
71 } catch (KeyManagementException | NoSuchAlgorithmException | UnrecoverableKeyException | CertificateException | KeyStoreException | IOException | InvalidKeySpecException e) {
72 LOG.warn("problem ssl setup: " + e.getMessage());
76 protected BaseHTTPResponse sendRequest(String uri, String method, String body, Map<String, String> headers)
78 return this.sendRequest(uri, method, body != null ? body.getBytes(CHARSET) : null, headers);
81 protected BaseHTTPResponse sendRequest(String uri, String method, byte[] body, Map<String, String> headers)
85 String surl = this.baseUrl;
86 if(!surl.endsWith("/") && uri.length()>0)
88 if(uri.startsWith("/"))
91 LOG.debug("try to send request with url=" + this.baseUrl + uri + " as method=" + method);
92 LOG.trace("body:" + (body==null?"null": new String(body, CHARSET)));
93 URL url = new URL(surl);
94 URLConnection http = url.openConnection();
95 http.setConnectTimeout(this.timeout);
96 if (surl.toString().startsWith("https"))
100 ((HttpsURLConnection) http).setSSLSocketFactory(sc.getSocketFactory());
102 LOG.debug("trusting all certs");
103 HostnameVerifier allHostsValid = new HostnameVerifier() {
104 public boolean verify(String hostname, SSLSession session) {
108 ((HttpsURLConnection) http).setHostnameVerifier(allHostsValid);
110 } else //Should never happen
112 LOG.warn("No SSL context available");
113 return new BaseHTTPResponse(-1, "");
116 ((HttpURLConnection) http).setRequestMethod(method);
117 http.setDoOutput(true);
118 if (headers != null && headers.size() > 0) {
119 for (String key : headers.keySet()) {
120 http.setRequestProperty(key, headers.get(key));
121 LOG.trace("set http header "+ key+": "+headers.get(key));
124 byte[] buffer = new byte[BUFSIZE];
125 int len = 0, lensum = 0;
127 // Send the message to destination
128 if (!method.equals("GET") && body != null && body.length > 0) {
129 try (OutputStream output = http.getOutputStream()) {
133 int responseCode = ((HttpURLConnection) http).getResponseCode();
135 InputStream response;
136 if (responseCode >= 200 && responseCode < 300)
137 response = http.getInputStream();
139 response = ((HttpURLConnection) http).getErrorStream();
140 if (response == null)
141 response = http.getInputStream();
143 String sresponse = "";
144 if (response != null) {
146 len = response.read(buffer, 0, BUFSIZE);
150 sresponse += new String(buffer, 0, len, CHARSET);
154 LOG.debug("response is null");
155 LOG.debug("ResponseCode: " + responseCode);
156 LOG.trace("Response (len:{}): {}",String.valueOf(lensum),sresponse);
158 return new BaseHTTPResponse(responseCode, sresponse);
161 public static SSLContext setupSsl(boolean trustall)
162 throws NoSuchAlgorithmException, KeyManagementException, CertificateException, FileNotFoundException,
163 IOException, UnrecoverableKeyException, KeyStoreException, InvalidKeySpecException {
165 return setupSsl(trustall, null, null, SSLCERT_NONE);
171 * @param certFilename
172 * @throws NoSuchAlgorithmException
173 * @throws KeyManagementException
174 * @throws IOException
175 * @throws FileNotFoundException
176 * @throws CertificateException
177 * @throws KeyStoreException
178 * @throws UnrecoverableKeyException
179 * @throws InvalidKeySpecException
181 public static SSLContext setupSsl(boolean trustall, String certFilename, String passPhrase,int certType) throws NoSuchAlgorithmException, KeyManagementException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyStoreException, InvalidKeySpecException {
183 SSLContext sc = SSLContext.getInstance(SSLCONTEXT);
184 TrustManager[] trustCerts = null;
186 trustCerts = new TrustManager[] { new javax.net.ssl.X509TrustManager() {
187 public java.security.cert.X509Certificate[] getAcceptedIssuers() {
191 public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
194 public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
199 KeyManager[] kms=null;
200 if(certFilename!=null && passPhrase!=null && !certFilename.isEmpty() && !passPhrase.isEmpty())
202 if(certType==SSLCERT_PCKS)
204 LOG.debug("try to load pcks file "+certFilename+ " with passphrase="+passPhrase);
205 KeyStore keyStore = KeyStore.getInstance("PKCS12");
206 keyStore.load(new FileInputStream(certFilename), passPhrase.toCharArray());
207 KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
208 kmf.init(keyStore, passPhrase.toCharArray());
209 kms = kmf.getKeyManagers();
210 LOG.debug("successful");
213 else if(certType==SSLCERT_PEM)
215 LOG.debug("try to load pem files cert="+certFilename+ " key="+passPhrase);
216 File fCert = new File(certFilename);
217 File fKey = new File(passPhrase);
218 KeyStore keyStore = KeyStore.getInstance("JKS");
220 byte[] certBytes = parseDERFromPEM(Files.readAllBytes(fCert.toPath()), "-----BEGIN CERTIFICATE-----",
221 "-----END CERTIFICATE-----");
222 byte[] keyBytes = parseDERFromPEM(Files.readAllBytes(fKey.toPath()), "-----BEGIN PRIVATE KEY-----",
223 "-----END PRIVATE KEY-----");
225 X509Certificate cert = generateCertificateFromDER(certBytes);
226 RSAPrivateKey key = generatePrivateKeyFromDER(keyBytes);
227 keyStore.setCertificateEntry("cert-alias", cert);
228 keyStore.setKeyEntry("key-alias", key, "changeit".toCharArray(), new Certificate[] {cert});
230 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
231 kmf.init(keyStore, "changeit".toCharArray());
232 kms = kmf.getKeyManagers();
233 LOG.debug("successful");
236 // Init the SSLContext with a TrustManager[] and SecureRandom()
237 sc.init(kms, trustCerts, new java.security.SecureRandom());
240 protected static byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter) {
241 String data = new String(pem);
242 String[] tokens = data.split(beginDelimiter);
243 tokens = tokens[1].split(endDelimiter);
244 return DatatypeConverter.parseBase64Binary(tokens[0]);
247 protected static RSAPrivateKey generatePrivateKeyFromDER(byte[] keyBytes) throws InvalidKeySpecException, NoSuchAlgorithmException {
248 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
250 KeyFactory factory = KeyFactory.getInstance("RSA");
252 return (RSAPrivateKey)factory.generatePrivate(spec);
255 protected static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException {
256 CertificateFactory factory = CertificateFactory.getInstance("X.509");
258 return (X509Certificate)factory.generateCertificate(new ByteArrayInputStream(certBytes));
260 public static String getAuthorizationHeaderValue(String username, String password) {
261 return "Basic " + new String(Base64.getEncoder().encode((username+":"+password).getBytes()));
263 public void setTimeout(int timeout) {
264 this.timeout =timeout;