View Javadoc
1   /*
2    * Copyright 2014 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  
17  package io.netty.handler.ssl;
18  
19  import java.security.KeyStore;
20  import java.security.Provider;
21  import javax.net.ssl.KeyManager;
22  import javax.net.ssl.KeyManagerFactory;
23  import javax.net.ssl.SSLContext;
24  import javax.net.ssl.SSLException;
25  import javax.net.ssl.SSLSessionContext;
26  import javax.net.ssl.TrustManager;
27  import javax.net.ssl.TrustManagerFactory;
28  import java.io.File;
29  import java.security.PrivateKey;
30  import java.security.SecureRandom;
31  import java.security.cert.X509Certificate;
32  
33  /**
34   * A client-side {@link SslContext} which uses JDK's SSL/TLS implementation.
35   *
36   * @deprecated Use {@link SslContextBuilder} to create {@link JdkSslContext} instances and only
37   * use {@link JdkSslContext} in your code.
38   */
39  @Deprecated
40  public final class JdkSslClientContext extends JdkSslContext {
41  
42      /**
43       * Creates a new instance.
44       *
45       * @deprecated use {@link SslContextBuilder}
46       */
47      @Deprecated
48      public JdkSslClientContext() throws SSLException {
49          this(null, null);
50      }
51  
52      /**
53       * Creates a new instance.
54       *
55       * @param certChainFile an X.509 certificate chain file in PEM format.
56       *                      {@code null} to use the system default
57       * @deprecated use {@link SslContextBuilder}
58       */
59      @Deprecated
60      public JdkSslClientContext(File certChainFile) throws SSLException {
61          this(certChainFile, null);
62      }
63  
64      /**
65       * Creates a new instance.
66       *
67       * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
68       *                            that verifies the certificates sent from servers.
69       *                            {@code null} to use the default.
70       * @deprecated use {@link SslContextBuilder}
71       */
72      @Deprecated
73      public JdkSslClientContext(TrustManagerFactory trustManagerFactory) throws SSLException {
74          this(null, trustManagerFactory);
75      }
76  
77      /**
78       * Creates a new instance.
79       *
80       * @param certChainFile an X.509 certificate chain file in PEM format.
81       *                      {@code null} to use the system default
82       * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
83       *                            that verifies the certificates sent from servers.
84       *                            {@code null} to use the default.
85       * @deprecated use {@link SslContextBuilder}
86       */
87      @Deprecated
88      public JdkSslClientContext(File certChainFile, TrustManagerFactory trustManagerFactory) throws SSLException {
89          this(certChainFile, trustManagerFactory, null, IdentityCipherSuiteFilter.INSTANCE,
90                  JdkDefaultApplicationProtocolNegotiator.INSTANCE, 0, 0);
91      }
92  
93      /**
94       * Creates a new instance.
95       *
96       * @param certChainFile an X.509 certificate chain file in PEM format.
97       *                      {@code null} to use the system default
98       * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
99       *                            that verifies the certificates sent from servers.
100      *                            {@code null} to use the default.
101      * @param ciphers the cipher suites to enable, in the order of preference.
102      *                {@code null} to use the default cipher suites.
103      * @param nextProtocols the application layer protocols to accept, in the order of preference.
104      *                      {@code null} to disable TLS NPN/ALPN extension.
105      * @param sessionCacheSize the size of the cache used for storing SSL session objects.
106      *                         {@code 0} to use the default value.
107      * @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
108      *                       {@code 0} to use the default value.
109      * @deprecated use {@link SslContextBuilder}
110      */
111     @Deprecated
112     public JdkSslClientContext(
113             File certChainFile, TrustManagerFactory trustManagerFactory,
114             Iterable<String> ciphers, Iterable<String> nextProtocols,
115             long sessionCacheSize, long sessionTimeout) throws SSLException {
116         this(certChainFile, trustManagerFactory, ciphers, IdentityCipherSuiteFilter.INSTANCE,
117              toNegotiator(toApplicationProtocolConfig(nextProtocols), false), sessionCacheSize, sessionTimeout);
118     }
119 
120     /**
121      * Creates a new instance.
122      *
123      * @param certChainFile an X.509 certificate chain file in PEM format.
124      *                      {@code null} to use the system default
125      * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
126      *                            that verifies the certificates sent from servers.
127      *                            {@code null} to use the default.
128      * @param ciphers the cipher suites to enable, in the order of preference.
129      *                {@code null} to use the default cipher suites.
130      * @param cipherFilter a filter to apply over the supplied list of ciphers
131      * @param apn Provides a means to configure parameters related to application protocol negotiation.
132      * @param sessionCacheSize the size of the cache used for storing SSL session objects.
133      *                         {@code 0} to use the default value.
134      * @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
135      *                       {@code 0} to use the default value.
136      * @deprecated use {@link SslContextBuilder}
137      */
138     @Deprecated
139     public JdkSslClientContext(
140             File certChainFile, TrustManagerFactory trustManagerFactory,
141             Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
142             long sessionCacheSize, long sessionTimeout) throws SSLException {
143         this(certChainFile, trustManagerFactory, ciphers, cipherFilter,
144                 toNegotiator(apn, false), sessionCacheSize, sessionTimeout);
145     }
146 
147     /**
148      * Creates a new instance.
149      *
150      * @param certChainFile an X.509 certificate chain file in PEM format.
151      *                      {@code null} to use the system default
152      * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
153      *                            that verifies the certificates sent from servers.
154      *                            {@code null} to use the default.
155      * @param ciphers the cipher suites to enable, in the order of preference.
156      *                {@code null} to use the default cipher suites.
157      * @param cipherFilter a filter to apply over the supplied list of ciphers
158      * @param apn Application Protocol Negotiator object.
159      * @param sessionCacheSize the size of the cache used for storing SSL session objects.
160      *                         {@code 0} to use the default value.
161      * @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
162      *                       {@code 0} to use the default value.
163      * @deprecated use {@link SslContextBuilder}
164      */
165     @Deprecated
166     public JdkSslClientContext(
167             File certChainFile, TrustManagerFactory trustManagerFactory,
168             Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
169             long sessionCacheSize, long sessionTimeout) throws SSLException {
170         this(null, certChainFile, trustManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
171     }
172 
173     JdkSslClientContext(Provider provider,
174                         File trustCertCollectionFile, TrustManagerFactory trustManagerFactory,
175                         Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
176                         long sessionCacheSize, long sessionTimeout) throws SSLException {
177         super(newSSLContext(provider, toX509CertificatesInternal(trustCertCollectionFile),
178                 trustManagerFactory, null, null,
179                 null, null, sessionCacheSize, sessionTimeout, null, KeyStore.getDefaultType(), null), true,
180                 ciphers, cipherFilter, apn, ClientAuth.NONE, null, false);
181     }
182 
183     /**
184      * Creates a new instance.
185      * @param trustCertCollectionFile an X.509 certificate collection file in PEM format.
186      *                      {@code null} to use the system default
187      * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
188      *                            that verifies the certificates sent from servers.
189      *                            {@code null} to use the default or the results of parsing
190      *                            {@code trustCertCollectionFile}
191      * @param keyCertChainFile an X.509 certificate chain file in PEM format.
192      *                      This provides the public key for mutual authentication.
193      *                      {@code null} to use the system default
194      * @param keyFile a PKCS#8 private key file in PEM format.
195      *                      This provides the private key for mutual authentication.
196      *                      {@code null} for no mutual authentication.
197      * @param keyPassword the password of the {@code keyFile}.
198      *                    {@code null} if it's not password-protected.
199      *                    Ignored if {@code keyFile} is {@code null}.
200      * @param keyManagerFactory the {@link KeyManagerFactory} that provides the {@link KeyManager}s
201      *                          that is used to encrypt data being sent to servers.
202      *                          {@code null} to use the default or the results of parsing
203      *                          {@code keyCertChainFile} and {@code keyFile}.
204      * @param ciphers the cipher suites to enable, in the order of preference.
205      *                {@code null} to use the default cipher suites.
206      * @param cipherFilter a filter to apply over the supplied list of ciphers
207      * @param apn Provides a means to configure parameters related to application protocol negotiation.
208      * @param sessionCacheSize the size of the cache used for storing SSL session objects.
209      *                         {@code 0} to use the default value.
210      * @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
211      *                       {@code 0} to use the default value.
212      * @deprecated use {@link SslContextBuilder}
213      */
214     @Deprecated
215     public JdkSslClientContext(File trustCertCollectionFile, TrustManagerFactory trustManagerFactory,
216             File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
217             Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
218             long sessionCacheSize, long sessionTimeout) throws SSLException {
219         this(trustCertCollectionFile, trustManagerFactory, keyCertChainFile, keyFile, keyPassword, keyManagerFactory,
220                 ciphers, cipherFilter, toNegotiator(apn, false), sessionCacheSize, sessionTimeout);
221     }
222 
223     /**
224      * Creates a new instance.
225      * @param trustCertCollectionFile an X.509 certificate collection file in PEM format.
226      *                      {@code null} to use the system default
227      * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
228      *                            that verifies the certificates sent from servers.
229      *                            {@code null} to use the default or the results of parsing
230      *                            {@code trustCertCollectionFile}
231      * @param keyCertChainFile an X.509 certificate chain file in PEM format.
232      *                      This provides the public key for mutual authentication.
233      *                      {@code null} to use the system default
234      * @param keyFile a PKCS#8 private key file in PEM format.
235      *                      This provides the private key for mutual authentication.
236      *                      {@code null} for no mutual authentication.
237      * @param keyPassword the password of the {@code keyFile}.
238      *                    {@code null} if it's not password-protected.
239      *                    Ignored if {@code keyFile} is {@code null}.
240      * @param keyManagerFactory the {@link KeyManagerFactory} that provides the {@link KeyManager}s
241      *                          that is used to encrypt data being sent to servers.
242      *                          {@code null} to use the default or the results of parsing
243      *                          {@code keyCertChainFile} and {@code keyFile}.
244      * @param ciphers the cipher suites to enable, in the order of preference.
245      *                {@code null} to use the default cipher suites.
246      * @param cipherFilter a filter to apply over the supplied list of ciphers
247      * @param apn Application Protocol Negotiator object.
248      * @param sessionCacheSize the size of the cache used for storing SSL session objects.
249      *                         {@code 0} to use the default value.
250      * @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
251      *                       {@code 0} to use the default value.
252      * @deprecated use {@link SslContextBuilder}
253      */
254     @Deprecated
255     public JdkSslClientContext(File trustCertCollectionFile, TrustManagerFactory trustManagerFactory,
256             File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
257             Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
258             long sessionCacheSize, long sessionTimeout) throws SSLException {
259         super(newSSLContext(null, toX509CertificatesInternal(
260                 trustCertCollectionFile), trustManagerFactory,
261                 toX509CertificatesInternal(keyCertChainFile), toPrivateKeyInternal(keyFile, keyPassword),
262                 keyPassword, keyManagerFactory, sessionCacheSize, sessionTimeout,
263                         null, KeyStore.getDefaultType(), null), true,
264                 ciphers, cipherFilter, apn, ClientAuth.NONE, null, false);
265     }
266 
267     JdkSslClientContext(Provider sslContextProvider,
268                         X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
269                         X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
270                         KeyManagerFactory keyManagerFactory, Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
271                         ApplicationProtocolConfig apn, String[] protocols, long sessionCacheSize, long sessionTimeout,
272                         SecureRandom secureRandom, String keyStoreType, String endpointIdentificationAlgorithm,
273                         ResumptionController resumptionController)
274             throws SSLException {
275         super(newSSLContext(sslContextProvider, trustCertCollection, trustManagerFactory,
276                             keyCertChain, key, keyPassword, keyManagerFactory, sessionCacheSize,
277                             sessionTimeout, secureRandom, keyStoreType, resumptionController),
278                 true, ciphers, cipherFilter, toNegotiator(apn, false), ClientAuth.NONE, protocols, false,
279                 endpointIdentificationAlgorithm, resumptionController);
280     }
281 
282     private static SSLContext newSSLContext(Provider sslContextProvider,
283                                             X509Certificate[] trustCertCollection,
284                                             TrustManagerFactory trustManagerFactory, X509Certificate[] keyCertChain,
285                                             PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
286                                             long sessionCacheSize, long sessionTimeout,
287                                             SecureRandom secureRandom, String keyStore,
288                                             ResumptionController resumptionController) throws SSLException {
289         try {
290             if (trustCertCollection != null) {
291                 trustManagerFactory = buildTrustManagerFactory(trustCertCollection, trustManagerFactory, keyStore);
292             }
293             if (keyCertChain != null) {
294                 keyManagerFactory = buildKeyManagerFactory(keyCertChain, null,
295                         key, keyPassword, keyManagerFactory, keyStore);
296             }
297             SSLContext ctx = sslContextProvider == null ? SSLContext.getInstance(PROTOCOL)
298                 : SSLContext.getInstance(PROTOCOL, sslContextProvider);
299             ctx.init(keyManagerFactory == null ? null : keyManagerFactory.getKeyManagers(),
300                      trustManagerFactory == null ? null :
301                              wrapIfNeeded(trustManagerFactory.getTrustManagers(), resumptionController),
302                      secureRandom);
303 
304             SSLSessionContext sessCtx = ctx.getClientSessionContext();
305             if (sessionCacheSize > 0) {
306                 sessCtx.setSessionCacheSize((int) Math.min(sessionCacheSize, Integer.MAX_VALUE));
307             }
308             if (sessionTimeout > 0) {
309                 sessCtx.setSessionTimeout((int) Math.min(sessionTimeout, Integer.MAX_VALUE));
310             }
311             return ctx;
312         } catch (Exception e) {
313             if (e instanceof SSLException) {
314                 throw (SSLException) e;
315             }
316             throw new SSLException("failed to initialize the client-side SSL context", e);
317         }
318     }
319 
320     private static TrustManager[] wrapIfNeeded(TrustManager[] tms, ResumptionController resumptionController) {
321         if (resumptionController != null) {
322             for (int i = 0; i < tms.length; i++) {
323                 tms[i] = resumptionController.wrapIfNeeded(tms[i]);
324             }
325         }
326         return tms;
327     }
328 }