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 io.netty.util.internal.PlatformDependent;
20  import io.netty.util.internal.SuppressJava6Requirement;
21  
22  import java.security.KeyStore;
23  import java.security.Provider;
24  import javax.net.ssl.KeyManager;
25  
26  import javax.net.ssl.KeyManagerFactory;
27  import javax.net.ssl.SSLContext;
28  import javax.net.ssl.SSLException;
29  import javax.net.ssl.SSLSessionContext;
30  import javax.net.ssl.TrustManager;
31  import javax.net.ssl.TrustManagerFactory;
32  import javax.net.ssl.X509ExtendedTrustManager;
33  import java.io.File;
34  import java.security.PrivateKey;
35  import java.security.cert.X509Certificate;
36  
37  /**
38   * A server-side {@link SslContext} which uses JDK's SSL/TLS implementation.
39   *
40   * @deprecated Use {@link SslContextBuilder} to create {@link JdkSslContext} instances and only
41   * use {@link JdkSslContext} in your code.
42   */
43  @Deprecated
44  public final class JdkSslServerContext extends JdkSslContext {
45  
46      /**
47       * Creates a new instance.
48       *
49       * @param certChainFile an X.509 certificate chain file in PEM format
50       * @param keyFile a PKCS#8 private key file in PEM format
51       * @deprecated use {@link SslContextBuilder}
52       */
53      @Deprecated
54      public JdkSslServerContext(File certChainFile, File keyFile) throws SSLException {
55          this(null, certChainFile, keyFile, null, null, IdentityCipherSuiteFilter.INSTANCE,
56                  JdkDefaultApplicationProtocolNegotiator.INSTANCE, 0, 0, null);
57      }
58  
59      /**
60       * Creates a new instance.
61       *
62       * @param certChainFile an X.509 certificate chain file in PEM format
63       * @param keyFile a PKCS#8 private key file in PEM format
64       * @param keyPassword the password of the {@code keyFile}.
65       *                    {@code null} if it's not password-protected.
66       * @deprecated use {@link SslContextBuilder}
67       */
68      @Deprecated
69      public JdkSslServerContext(File certChainFile, File keyFile, String keyPassword) throws SSLException {
70          this(certChainFile, keyFile, keyPassword, null, IdentityCipherSuiteFilter.INSTANCE,
71                  JdkDefaultApplicationProtocolNegotiator.INSTANCE, 0, 0);
72      }
73  
74      /**
75       * Creates a new instance.
76       *
77       * @param certChainFile an X.509 certificate chain file in PEM format
78       * @param keyFile a PKCS#8 private key file in PEM format
79       * @param keyPassword the password of the {@code keyFile}.
80       *                    {@code null} if it's not password-protected.
81       * @param ciphers the cipher suites to enable, in the order of preference.
82       *                {@code null} to use the default cipher suites.
83       * @param nextProtocols the application layer protocols to accept, in the order of preference.
84       *                      {@code null} to disable TLS NPN/ALPN extension.
85       * @param sessionCacheSize the size of the cache used for storing SSL session objects.
86       *                         {@code 0} to use the default value.
87       * @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
88       *                       {@code 0} to use the default value.
89       * @deprecated use {@link SslContextBuilder}
90       */
91      @Deprecated
92      public JdkSslServerContext(
93              File certChainFile, File keyFile, String keyPassword,
94              Iterable<String> ciphers, Iterable<String> nextProtocols,
95              long sessionCacheSize, long sessionTimeout) throws SSLException {
96          this(null, certChainFile, keyFile, keyPassword, ciphers, IdentityCipherSuiteFilter.INSTANCE,
97                  toNegotiator(toApplicationProtocolConfig(nextProtocols), true), sessionCacheSize,
98                  sessionTimeout, KeyStore.getDefaultType());
99      }
100 
101     /**
102      * Creates a new instance.
103      *
104      * @param certChainFile an X.509 certificate chain file in PEM format
105      * @param keyFile a PKCS#8 private key file in PEM format
106      * @param keyPassword the password of the {@code keyFile}.
107      *                    {@code null} if it's not password-protected.
108      * @param ciphers the cipher suites to enable, in the order of preference.
109      *                {@code null} to use the default cipher suites.
110      * @param cipherFilter a filter to apply over the supplied list of ciphers
111      * @param apn Provides a means to configure parameters related to application protocol negotiation.
112      * @param sessionCacheSize the size of the cache used for storing SSL session objects.
113      *                         {@code 0} to use the default value.
114      * @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
115      *                       {@code 0} to use the default value.
116      * @deprecated use {@link SslContextBuilder}
117      */
118     @Deprecated
119     public JdkSslServerContext(
120             File certChainFile, File keyFile, String keyPassword,
121             Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
122             long sessionCacheSize, long sessionTimeout) throws SSLException {
123         this(null, certChainFile, keyFile, keyPassword, ciphers, cipherFilter,
124                 toNegotiator(apn, true), sessionCacheSize, sessionTimeout, KeyStore.getDefaultType());
125     }
126 
127     /**
128      * Creates a new instance.
129      *
130      * @param certChainFile an X.509 certificate chain file in PEM format
131      * @param keyFile a PKCS#8 private key file in PEM format
132      * @param keyPassword the password of the {@code keyFile}.
133      *                    {@code null} if it's not password-protected.
134      * @param ciphers the cipher suites to enable, in the order of preference.
135      *                {@code null} to use the default cipher suites.
136      * @param cipherFilter a filter to apply over the supplied list of ciphers
137      * @param apn Application Protocol Negotiator object.
138      * @param sessionCacheSize the size of the cache used for storing SSL session objects.
139      *                         {@code 0} to use the default value.
140      * @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
141      *                       {@code 0} to use the default value.
142      * @deprecated use {@link SslContextBuilder}
143      */
144     @Deprecated
145     public JdkSslServerContext(
146             File certChainFile, File keyFile, String keyPassword,
147             Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
148             long sessionCacheSize, long sessionTimeout) throws SSLException {
149         this(null, certChainFile, keyFile, keyPassword, ciphers, cipherFilter, apn,
150                 sessionCacheSize, sessionTimeout, KeyStore.getDefaultType());
151     }
152 
153     JdkSslServerContext(Provider provider,
154                         File certChainFile, File keyFile, String keyPassword,
155                         Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
156                         long sessionCacheSize, long sessionTimeout, String keyStore) throws SSLException {
157         super(newSSLContext(provider, null, null,
158                 toX509CertificatesInternal(certChainFile), toPrivateKeyInternal(keyFile, keyPassword),
159                 keyPassword, null, sessionCacheSize, sessionTimeout, keyStore), false,
160                 ciphers, cipherFilter, apn, ClientAuth.NONE, null, false);
161     }
162 
163     /**
164      * Creates a new instance.
165      * @param trustCertCollectionFile an X.509 certificate collection file in PEM format.
166      *                      This provides the certificate collection used for mutual authentication.
167      *                      {@code null} to use the system default
168      * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
169      *                            that verifies the certificates sent from clients.
170      *                            {@code null} to use the default or the results of parsing
171      *                            {@code trustCertCollectionFile}.
172      * @param keyCertChainFile an X.509 certificate chain file in PEM format
173      * @param keyFile a PKCS#8 private key file in PEM format
174      * @param keyPassword the password of the {@code keyFile}.
175      *                    {@code null} if it's not password-protected.
176      * @param keyManagerFactory the {@link KeyManagerFactory} that provides the {@link KeyManager}s
177      *                          that is used to encrypt data being sent to clients.
178      *                          {@code null} to use the default or the results of parsing
179      *                          {@code keyCertChainFile} and {@code keyFile}.
180      * @param ciphers the cipher suites to enable, in the order of preference.
181      *                {@code null} to use the default cipher suites.
182      * @param cipherFilter a filter to apply over the supplied list of ciphers
183      *                Only required if {@code provider} is {@link SslProvider#JDK}
184      * @param apn Provides a means to configure parameters related to application protocol negotiation.
185      * @param sessionCacheSize the size of the cache used for storing SSL session objects.
186      *                         {@code 0} to use the default value.
187      * @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
188      *                       {@code 0} to use the default value.
189      * @deprecated use {@link SslContextBuilder}
190      */
191     @Deprecated
192     public JdkSslServerContext(File trustCertCollectionFile, TrustManagerFactory trustManagerFactory,
193                                File keyCertChainFile, File keyFile, String keyPassword,
194                                KeyManagerFactory keyManagerFactory,
195                                Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
196                                long sessionCacheSize, long sessionTimeout) throws SSLException {
197         super(newSSLContext(null, toX509CertificatesInternal(trustCertCollectionFile), trustManagerFactory,
198                 toX509CertificatesInternal(keyCertChainFile), toPrivateKeyInternal(keyFile, keyPassword),
199                 keyPassword, keyManagerFactory, sessionCacheSize, sessionTimeout, null), false,
200                 ciphers, cipherFilter, apn, ClientAuth.NONE, null, false);
201     }
202 
203     /**
204      * Creates a new instance.
205      * @param trustCertCollectionFile an X.509 certificate collection file in PEM format.
206      *                      This provides the certificate collection used for mutual authentication.
207      *                      {@code null} to use the system default
208      * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
209      *                            that verifies the certificates sent from clients.
210      *                            {@code null} to use the default or the results of parsing
211      *                            {@code trustCertCollectionFile}
212      * @param keyCertChainFile an X.509 certificate chain file in PEM format
213      * @param keyFile a PKCS#8 private key file in PEM format
214      * @param keyPassword the password of the {@code keyFile}.
215      *                    {@code null} if it's not password-protected.
216      * @param keyManagerFactory the {@link KeyManagerFactory} that provides the {@link KeyManager}s
217      *                          that is used to encrypt data being sent to clients.
218      *                          {@code null} to use the default or the results of parsing
219      *                          {@code keyCertChainFile} and {@code keyFile}.
220      * @param ciphers the cipher suites to enable, in the order of preference.
221      *                {@code null} to use the default cipher suites.
222      * @param cipherFilter a filter to apply over the supplied list of ciphers
223      *                Only required if {@code provider} is {@link SslProvider#JDK}
224      * @param apn Application Protocol Negotiator object.
225      * @param sessionCacheSize the size of the cache used for storing SSL session objects.
226      *                         {@code 0} to use the default value.
227      * @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
228      *                       {@code 0} to use the default value
229      * @deprecated use {@link SslContextBuilder}
230      */
231     @Deprecated
232     public JdkSslServerContext(File trustCertCollectionFile, TrustManagerFactory trustManagerFactory,
233                                File keyCertChainFile, File keyFile, String keyPassword,
234                                KeyManagerFactory keyManagerFactory,
235                                Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
236                                 JdkApplicationProtocolNegotiator apn,
237                                long sessionCacheSize, long sessionTimeout) throws SSLException {
238         super(newSSLContext(null, toX509CertificatesInternal(trustCertCollectionFile), trustManagerFactory,
239                 toX509CertificatesInternal(keyCertChainFile), toPrivateKeyInternal(keyFile, keyPassword),
240                 keyPassword, keyManagerFactory, sessionCacheSize, sessionTimeout, KeyStore.getDefaultType()), false,
241                 ciphers, cipherFilter, apn, ClientAuth.NONE, null, false);
242     }
243 
244     JdkSslServerContext(Provider provider,
245                         X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
246                         X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
247                         KeyManagerFactory keyManagerFactory, Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
248                         ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout,
249                         ClientAuth clientAuth, String[] protocols, boolean startTls,
250                         String keyStore) throws SSLException {
251         super(newSSLContext(provider, trustCertCollection, trustManagerFactory, keyCertChain, key,
252                 keyPassword, keyManagerFactory, sessionCacheSize, sessionTimeout, keyStore), false,
253                 ciphers, cipherFilter, toNegotiator(apn, true), clientAuth, protocols, startTls);
254     }
255 
256     private static SSLContext newSSLContext(Provider sslContextProvider, X509Certificate[] trustCertCollection,
257                                      TrustManagerFactory trustManagerFactory, X509Certificate[] keyCertChain,
258                                      PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
259                                      long sessionCacheSize, long sessionTimeout, String keyStore)
260             throws SSLException {
261         if (key == null && keyManagerFactory == null) {
262             throw new NullPointerException("key, keyManagerFactory");
263         }
264 
265         try {
266             if (trustCertCollection != null) {
267                 trustManagerFactory = buildTrustManagerFactory(trustCertCollection, trustManagerFactory, keyStore);
268             } else if (trustManagerFactory == null) {
269                 // Mimic the way SSLContext.getInstance(KeyManager[], null, null) works
270                 trustManagerFactory = TrustManagerFactory.getInstance(
271                         TrustManagerFactory.getDefaultAlgorithm());
272                 trustManagerFactory.init((KeyStore) null);
273             }
274 
275             if (key != null) {
276                 keyManagerFactory = buildKeyManagerFactory(keyCertChain, null,
277                         key, keyPassword, keyManagerFactory, null);
278             }
279 
280             // Initialize the SSLContext to work with our key managers.
281             SSLContext ctx = sslContextProvider == null ? SSLContext.getInstance(PROTOCOL)
282                 : SSLContext.getInstance(PROTOCOL, sslContextProvider);
283             ctx.init(keyManagerFactory.getKeyManagers(),
284                     wrapTrustManagerIfNeeded(trustManagerFactory.getTrustManagers()),
285                      null);
286 
287             SSLSessionContext sessCtx = ctx.getServerSessionContext();
288             if (sessionCacheSize > 0) {
289                 sessCtx.setSessionCacheSize((int) Math.min(sessionCacheSize, Integer.MAX_VALUE));
290             }
291             if (sessionTimeout > 0) {
292                 sessCtx.setSessionTimeout((int) Math.min(sessionTimeout, Integer.MAX_VALUE));
293             }
294             return ctx;
295         } catch (Exception e) {
296             if (e instanceof SSLException) {
297                 throw (SSLException) e;
298             }
299             throw new SSLException("failed to initialize the server-side SSL context", e);
300         }
301     }
302 
303     @SuppressJava6Requirement(reason = "Guarded by java version check")
304     private static TrustManager[] wrapTrustManagerIfNeeded(TrustManager[] trustManagers) {
305         if (PlatformDependent.javaVersion() >= 7) {
306             for (int i = 0; i < trustManagers.length; i++) {
307                 TrustManager tm = trustManagers[i];
308                 if (tm instanceof X509ExtendedTrustManager) {
309                     // Wrap the TrustManager to provide a better exception message for users to debug hostname
310                     // validation failures.
311                     trustManagers[i] = new EnhancingX509ExtendedTrustManager((X509ExtendedTrustManager) tm);
312                 }
313             }
314         }
315         return trustManagers;
316     }
317 }