]> git.basschouten.com Git - openhab-addons.git/blob
b02301101e41e89b261c87060c37025e20e3b915
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.ihc.internal.ws.http;
14
15 import java.security.KeyManagementException;
16 import java.security.NoSuchAlgorithmException;
17 import java.security.SecureRandom;
18 import java.security.cert.X509Certificate;
19
20 import javax.net.ssl.HostnameVerifier;
21 import javax.net.ssl.SSLContext;
22 import javax.net.ssl.SSLSession;
23 import javax.net.ssl.TrustManager;
24 import javax.net.ssl.X509TrustManager;
25
26 import org.apache.http.client.CookieStore;
27 import org.apache.http.client.HttpClient;
28 import org.apache.http.client.protocol.HttpClientContext;
29 import org.apache.http.config.Registry;
30 import org.apache.http.config.RegistryBuilder;
31 import org.apache.http.conn.socket.ConnectionSocketFactory;
32 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
33 import org.apache.http.impl.client.BasicCookieStore;
34 import org.apache.http.impl.client.HttpClientBuilder;
35 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
36 import org.openhab.binding.ihc.internal.ws.exeptions.IhcFatalExecption;
37 import org.openhab.binding.ihc.internal.ws.exeptions.IhcTlsExecption;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * Custom HTTP connection pool, which install all-trusting trust manager.
43  *
44  * @author Pauli Anttila - Initial contribution
45  */
46 public class IhcConnectionPool {
47
48     private final Logger logger = LoggerFactory.getLogger(IhcConnectionPool.class);
49     private static final String DEFAULT_TLS_VER = "TLSv1";
50
51     /**
52      * Controller TLS certificate is self signed, which means that certificate
53      * need to be manually added to java key store as a trusted certificate.
54      * This is special SSL context which will be configured to trust all
55      * certificates and manual work is not required.
56      */
57     private SSLContext sslContext;
58
59     /** Holds and share cookie information (session id) from authentication procedure */
60     private CookieStore cookieStore;
61
62     private HttpClientBuilder httpClientBuilder;
63     private HttpClientContext localContext;
64     private String tlsVersion = DEFAULT_TLS_VER;
65
66     public IhcConnectionPool() throws IhcFatalExecption {
67         this(DEFAULT_TLS_VER);
68     }
69
70     public IhcConnectionPool(String tlsVersion) throws IhcFatalExecption {
71         if (!tlsVersion.isEmpty()) {
72             this.tlsVersion = tlsVersion;
73         }
74         init();
75     }
76
77     private void init() throws IhcFatalExecption {
78         try {
79             // Create a local instance of cookie store
80             cookieStore = new BasicCookieStore();
81
82             // Create local HTTP context
83             localContext = HttpClientContext.create();
84
85             // Bind custom cookie store to the local context
86             localContext.setCookieStore(cookieStore);
87
88             httpClientBuilder = HttpClientBuilder.create();
89
90             // Setup a Trust Strategy that allows all certificates.
91
92             logger.debug("Initialize SSL context");
93
94             // Create a trust manager that does not validate certificate chains, but accept all.
95             TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
96
97                 @Override
98                 public X509Certificate[] getAcceptedIssuers() {
99                     return null;
100                 }
101
102                 @Override
103                 public void checkClientTrusted(X509Certificate[] certs, String authType) {
104                 }
105
106                 @Override
107                 public void checkServerTrusted(X509Certificate[] certs, String authType) {
108                     logger.trace("Trusting server cert: {}", certs[0].getIssuerDN());
109                 }
110             } };
111
112             // Install the all-trusting trust manager
113
114             // Old controller FW supports only SSLv3 and TLSv1, never controller TLSv1.2
115             sslContext = SSLContext.getInstance(tlsVersion);
116             logger.debug("Using TLS version {}", sslContext.getProtocol());
117             sslContext.init(null, trustAllCerts, new SecureRandom());
118
119             // Controller accepts only HTTPS connections and because normally IP address are used on home network rather
120             // than DNS names, create custom host name verifier.
121             HostnameVerifier hostnameVerifier = new HostnameVerifier() {
122
123                 @Override
124                 public boolean verify(String arg0, SSLSession arg1) {
125                     logger.trace("HostnameVerifier: arg0 = {}, arg1 = {}", arg0, arg1);
126                     return true;
127                 }
128             };
129
130             // Create an SSL Socket Factory, to use our weakened "trust strategy"
131             SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext,
132                     new String[] { tlsVersion }, null, hostnameVerifier);
133
134             Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
135                     .register("https", sslSocketFactory).build();
136
137             // Create connection-manager using our Registry. Allows multi-threaded use
138             PoolingHttpClientConnectionManager connMngr = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
139
140             // Increase max connection counts
141             connMngr.setMaxTotal(20);
142             connMngr.setDefaultMaxPerRoute(6);
143
144             httpClientBuilder.setConnectionManager(connMngr);
145         } catch (KeyManagementException e) {
146             throw new IhcFatalExecption(e);
147         } catch (NoSuchAlgorithmException e) {
148             throw new IhcTlsExecption(e);
149         }
150     }
151
152     public HttpClient getHttpClient() {
153         return httpClientBuilder.build();
154     }
155
156     public HttpClientContext getHttpContext() {
157         return localContext;
158     }
159 }