/** * Copyright (c) 2010-2016 by the respective copyright holders. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.binding.ihc.ws; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.http.client.CookieStore; import org.apache.http.client.HttpClient; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Custom HTTP connection pool, which install all-trusting trust manager. * * @author Pauli Anttila * @since 1.7.0 */ public class IhcConnectionPool { private static final Logger logger = LoggerFactory.getLogger(IhcConnectionPool.class); private static IhcConnectionPool instance = null; /** * Controller TLS certificate is self signed, which means that certificate * need to be manually added to java key store as a trusted certificate. * This is special SSL context which will be configured to trust all * certificates and manual work is not required. */ private SSLContext sslContext = null; /** Holds and share cookie information (session id) from authentication procedure */ private CookieStore cookieStore = null; private HttpClientBuilder httpClientBuilder = null; private HttpClientContext localContext = null; protected IhcConnectionPool() { init(); } public static IhcConnectionPool getInstance() { if (instance == null) { synchronized (IhcConnectionPool.class) { if (instance == null) { instance = new IhcConnectionPool(); } } } return instance; } private void init() { // Create a local instance of cookie store cookieStore = new BasicCookieStore(); // Create local HTTP context localContext = HttpClientContext.create(); // Bind custom cookie store to the local context localContext.setCookieStore(cookieStore); httpClientBuilder = HttpClientBuilder.create(); // Setup a Trust Strategy that allows all certificates. logger.debug("Initialize SSL context"); // Create a trust manager that does not validate certificate chains, // but accept all. TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { logger.trace("Trusting server cert: " + certs[0].getIssuerDN()); } } }; // Install the all-trusting trust manager try { // Controller supports only SSLv3 and TLSv1 sslContext = SSLContext.getInstance("TLSv1"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); } catch (NoSuchAlgorithmException e) { logger.warn("Exception", e); } catch (KeyManagementException e) { logger.warn("Exception", e); } httpClientBuilder.setSslcontext(sslContext); // Controller accepts only HTTPS connections and because normally IP // address are used on home network rather than DNS names, create custom // host name verifier. HostnameVerifier hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String arg0, SSLSession arg1) { logger.trace("HostnameVerifier: arg0 = " + arg0); logger.trace("HostnameVerifier: arg1 = " + arg1); return true; } }; // Create an SSL Socket Factory, to use our weakened "trust strategy" SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, new String[] { "TLSv1" }, null, hostnameVerifier); Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create() .register("https", sslSocketFactory).build(); // Create connection-manager using our Registry. Allows multi-threaded // use PoolingHttpClientConnectionManager connMngr = new PoolingHttpClientConnectionManager(socketFactoryRegistry); // Increase max connection counts connMngr.setMaxTotal(20); connMngr.setDefaultMaxPerRoute(6); httpClientBuilder.setConnectionManager(connMngr); } public HttpClient getHttpClient() { return httpClientBuilder.build(); } public HttpClientContext getHttpContext() { return localContext; } }