27
27
28
28
import javax .net .ssl .HostnameVerifier ;
29
29
import javax .net .ssl .KeyManager ;
30
+ import javax .net .ssl .KeyManagerFactory ;
30
31
import javax .net .ssl .SSLContext ;
31
32
import javax .net .ssl .TrustManager ;
32
33
import javax .net .ssl .TrustManagerFactory ;
33
34
import java .io .FileInputStream ;
35
+ import java .io .FileNotFoundException ;
34
36
import java .io .IOException ;
35
37
import java .security .KeyManagementException ;
36
38
import java .security .KeyStore ;
37
39
import java .security .KeyStoreException ;
38
40
import java .security .NoSuchAlgorithmException ;
39
41
import java .security .SecureRandom ;
42
+ import java .security .UnrecoverableKeyException ;
40
43
import java .security .cert .CertificateException ;
41
44
import java .util .Objects ;
42
45
@@ -60,10 +63,28 @@ class HttpsContextBuilder {
60
63
* Constructor.
61
64
* @param configuration client configuration instance.
62
65
*/
63
- HttpsContextBuilder (final Configuration configuration ) {
66
+ public HttpsContextBuilder (final Configuration configuration ) {
64
67
this .configuration = Objects .requireNonNull (configuration );
65
68
}
66
69
70
+ /**
71
+ * Properly configured SslSocketFactory based on client configuration.
72
+ * @return SslSocketFactory instance.
73
+ */
74
+ public LayeredConnectionSocketFactory createSslSocketFactory () {
75
+ // Emit an warning letting everyone know we're using an insecure configuration.
76
+ if (configuration .getIgnoreInvalidSslCertificates ()) {
77
+ logger .warn ("Using insecure configuration, skipping server-side certificate validation checks." );
78
+ }
79
+
80
+ return new SSLConnectionSocketFactory (
81
+ getSslContext (),
82
+ getSslProtocols (),
83
+ null ,
84
+ getHostnameVerifier ()
85
+ );
86
+ }
87
+
67
88
/**
68
89
* Get HostnameVerifier instance based on client configuration.
69
90
* @return HostnameVerifier instance.
@@ -83,28 +104,78 @@ HostnameVerifier getHostnameVerifier() {
83
104
* @return SSLContext instance.
84
105
*/
85
106
SSLContext getSslContext () {
86
- // Create default SSLContext
87
- final SSLContext sslcontext = SSLContexts .createDefault ();
107
+ try {
108
+ // Create default SSLContext
109
+ final SSLContext sslcontext = SSLContexts .createDefault ();
110
+
111
+ // Initialize ssl context with configured key and trust managers.
112
+ sslcontext .init (getKeyManagers (), getTrustManagers (), new SecureRandom ());
113
+
114
+ return sslcontext ;
115
+ } catch (final KeyManagementException e ) {
116
+ throw new RuntimeException (e .getMessage (), e );
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Based on client configuration, construct KeyManager instances to use.
122
+ * @return Array of 0 or more KeyManagers.
123
+ */
124
+ KeyManager [] getKeyManagers () {
125
+ // If not configured to use a KeyStore
126
+ if (configuration .getKeyStoreFile () == null ) {
127
+ // Return null array.
128
+ return new KeyManager [0 ];
129
+ }
130
+
131
+ // If configured to use a key store
132
+ try {
133
+ final KeyManagerFactory keyFactory = KeyManagerFactory .getInstance (KeyManagerFactory .getDefaultAlgorithm ());
134
+
135
+ // New JKS Keystore.
136
+ final KeyStore keyStore = KeyStore .getInstance ("JKS" );
137
+ final char [] password ;
138
+ if (configuration .getKeyStorePassword () == null ) {
139
+ password = new char [0 ];
140
+ } else {
141
+ password = configuration .getKeyStorePassword ().toCharArray ();
142
+ }
143
+
144
+ try (final FileInputStream keyStoreFileInput = new FileInputStream (configuration .getKeyStoreFile ())) {
145
+ keyStore .load (keyStoreFileInput , password );
146
+ }
147
+ keyFactory .init (keyStore , password );
148
+ return keyFactory .getKeyManagers ();
149
+ } catch (final FileNotFoundException exception ) {
150
+ throw new RuntimeException (
151
+ "Unable to find configured KeyStore file \" " + configuration .getKeyStoreFile () + "\" " ,
152
+ exception
153
+ );
154
+ } catch (final KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException e ) {
155
+ throw new RuntimeException (e .getMessage (), e );
156
+ }
157
+ }
88
158
159
+ /**
160
+ * Based on Client Configuration, construct TrustManager instances to use.
161
+ * @return Array of 0 or more TrustManager instances.
162
+ */
163
+ TrustManager [] getTrustManagers () {
89
164
try {
165
+ final TrustManagerFactory trustManagerFactory = TrustManagerFactory .getInstance (TrustManagerFactory .getDefaultAlgorithm ());
166
+
90
167
// If client configuration is set to ignore invalid certificates
91
168
if (configuration .getIgnoreInvalidSslCertificates ()) {
92
169
// Initialize ssl context with a TrustManager instance that just accepts everything blindly.
93
170
// HIGHLY INSECURE / NOT RECOMMENDED!
94
- sslcontext . init ( new KeyManager [ 0 ], new TrustManager []{new NoopTrustManager ()}, new SecureRandom ()) ;
171
+ return new TrustManager []{ new NoopTrustManager () } ;
95
172
96
173
// If client configuration has a trust store defined.
97
174
} else if (configuration .getTrustStoreFile () != null ) {
98
-
99
- final TrustManagerFactory trustManagerFactory = TrustManagerFactory
100
- .getInstance (TrustManagerFactory .getDefaultAlgorithm ());
101
-
102
-
103
- // New JKS Keystore.
104
- final KeyStore keyStore = KeyStore .getInstance ("JKS" );
105
-
106
175
// Attempt to read the trust store from disk.
107
176
try (final FileInputStream trustStoreFileInput = new FileInputStream (configuration .getTrustStoreFile ())) {
177
+ // New JKS Keystore.
178
+ final KeyStore keyStore = KeyStore .getInstance ("JKS" );
108
179
109
180
// If no trust store password is set.
110
181
if (configuration .getTrustStorePassword () == null ) {
@@ -114,15 +185,20 @@ SSLContext getSslContext() {
114
185
}
115
186
trustManagerFactory .init (keyStore );
116
187
}
117
-
118
- // Initialize ssl context with our custom loaded trust store.
119
- sslcontext .init (new KeyManager [0 ], trustManagerFactory .getTrustManagers (), new SecureRandom ());
188
+ return trustManagerFactory .getTrustManagers ();
189
+ } else {
190
+ // use default TrustManager instances
191
+ trustManagerFactory .init ((KeyStore ) null );
192
+ return trustManagerFactory .getTrustManagers ();
120
193
}
121
- } catch (final KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | KeyManagementException e ) {
122
- throw new RuntimeException (e .getMessage (), e );
194
+ } catch (final FileNotFoundException exception ) {
195
+ throw new RuntimeException (
196
+ "Unable to find configured TrustStore file \" " + configuration .getTrustStoreFile () + "\" " ,
197
+ exception
198
+ );
199
+ } catch (final KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException exception ) {
200
+ throw new RuntimeException (exception .getMessage (), exception );
123
201
}
124
-
125
- return sslcontext ;
126
202
}
127
203
128
204
/**
@@ -132,22 +208,4 @@ SSLContext getSslContext() {
132
208
private String [] getSslProtocols () {
133
209
return sslProtocols ;
134
210
}
135
-
136
- /**
137
- * Properly configured SslSocketFactory based on client configuration.
138
- * @return SslSocketFactory instance.
139
- */
140
- LayeredConnectionSocketFactory createSslSocketFactory () {
141
- // Emit an warning letting everyone know we're using an insecure configuration.
142
- if (configuration .getIgnoreInvalidSslCertificates ()) {
143
- logger .warn ("Using insecure configuration, skipping server-side certificate validation checks." );
144
- }
145
-
146
- return new SSLConnectionSocketFactory (
147
- getSslContext (),
148
- getSslProtocols (),
149
- null ,
150
- getHostnameVerifier ()
151
- );
152
- }
153
211
}
0 commit comments