1 module hunt.net.secure.conscrypt.SSLParametersImpl;
2 
3 // dfmt off
4 version(WITH_HUNT_SECURITY):
5 // dfmt on
6 
7 import hunt.net.secure.conscrypt.AbstractSessionContext;
8 import hunt.net.secure.conscrypt.ApplicationProtocolSelectorAdapter;
9 import hunt.net.secure.conscrypt.ClientSessionContext;
10 import hunt.net.secure.conscrypt.NativeCrypto;
11 import hunt.net.secure.conscrypt.ServerSessionContext;
12 import hunt.net.secure.conscrypt.SSLUtils;
13 
14 // import hunt.net.ssl.KeyManager;
15 // import hunt.net.ssl.KeyManagerFactory;
16 // import hunt.net.ssl.X509KeyManager;
17 // import hunt.net.ssl.X509TrustManager;
18 import hunt.net.KeyCertOptions;
19 
20 // import hunt.security.Key;
21 // import hunt.security.cert.X509Certificate;
22 // import hunt.security.x500.X500Principal;
23 
24 import hunt.Exceptions;
25 import hunt.logging;
26 import hunt.util.Common;
27 import hunt.util.ObjectUtils;
28 
29 /**
30  * The instances of this class encapsulate all the info
31  * about enabled cipher suites and protocols,
32  * as well as the information about client/server mode of
33  * ssl socket, whether it require/want client authentication or not,
34  * and controls whether new SSL sessions may be established by this
35  * socket or not.
36  */
37 final class SSLParametersImpl : Cloneable {
38 
39     // // default source of X.509 certificate based authentication keys
40     // private static X509KeyManager defaultX509KeyManager;
41     // default source of X.509 certificate based authentication trust decisions
42     // private static X509TrustManager defaultX509TrustManager;
43 
44     // default SSL parameters
45     // private static SSLParametersImpl defaultParameters;
46 
47     // client session context contains the set of reusable
48     // client-side SSL sessions
49     private ClientSessionContext clientSessionContext;
50     // server session context contains the set of reusable
51     // server-side SSL sessions
52     private ServerSessionContext serverSessionContext;
53     // source of X.509 certificate based authentication keys or null if not provided
54     // private X509KeyManager x509KeyManager;
55     // source of Pre-Shared Key (PSK) authentication keys or null if not provided.
56     // @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package
57     // private PSKKeyManager pskKeyManager;
58     // source of X.509 certificate based authentication trust decisions or null if not provided
59     // private X509TrustManager x509TrustManager;
60 
61     // protocols enabled for SSL connection
62     string[] enabledProtocols;
63     // set to indicate when obsolete protocols are filtered
64     bool isEnabledProtocolsFiltered;
65     // cipher suites enabled for SSL connection
66     string[] enabledCipherSuites;
67 
68     // if the peer with this parameters tuned to work in client mode
69     private bool client_mode = true;
70     // if the peer with this parameters tuned to require client authentication
71     private bool need_client_auth = false;
72     // if the peer with this parameters tuned to request client authentication
73     private bool want_client_auth = false;
74     // if the peer with this parameters allowed to cteate new SSL session
75     private bool enable_session_creation = true;
76     // Endpoint identification algorithm (e.g., HTTPS)
77     private string endpointIdentificationAlgorithm;
78     // Whether to use the local cipher suites order
79     private bool useCipherSuitesOrder;
80 
81     // client-side only, bypasses the property based configuration, used for tests
82     private bool ctVerificationEnabled;
83 
84     // server-side only. SCT and OCSP data to send to clients which request it
85     byte[] sctExtension;
86     byte[] ocspResponse;
87 
88     ubyte[] applicationProtocols = [];
89     ApplicationProtocolSelectorAdapter applicationProtocolSelector;
90     bool useSessionTickets;
91     private bool useSni;
92 
93     private KeyCertOptions _keyCertOptions;
94 
95     /**
96      * Whether the TLS Channel ID extension is enabled. This field is
97      * server-side only.
98      */
99     bool channelIdEnabled;
100 
101     private this() {
102         // It's only used for the creation in reflection.
103     }
104 
105     /**
106      * Initializes the parameters. Naturally this constructor is used
107      * in SSLContextImpl.engineInit method which directly passes its
108      * parameters. In other words this constructor holds all
109      * the functionality provided by SSLContext.init method.
110      * See {@link javax.net.ssl.SSLContext#init(KeyManager[],TrustManager[],
111      * SecureRandom)} for more information
112      */
113     this(KeyCertOptions options, ClientSessionContext clientSessionContext,
114             ServerSessionContext serverSessionContext, string[] protocols) {
115         _keyCertOptions = options;
116         this.serverSessionContext = serverSessionContext;
117         this.clientSessionContext = clientSessionContext;
118     }
119 //     this(KeyManager[] kms, TrustManager[] tms, ClientSessionContext clientSessionContext,
120 //             ServerSessionContext serverSessionContext, string[] protocols) {
121 //         this.serverSessionContext = serverSessionContext;
122 //         this.clientSessionContext = clientSessionContext;
123 
124 // version(Have_boringssl) {
125 //         // initialize key managers
126 //         if (kms is null) {
127 //             x509KeyManager = getDefaultX509KeyManager();
128 //             // There's no default PSK key manager
129 //             // pskKeyManager = null;
130 //         } else {
131 //             x509KeyManager = findFirstX509KeyManager(kms);
132 //             // pskKeyManager = findFirstPSKKeyManager(kms);
133 //         }
134 
135 //         // initialize x509TrustManager
136 //         if (tms is null) {
137 //             x509TrustManager = getDefaultX509TrustManager();
138 //         } else {
139 //             x509TrustManager = findFirstX509TrustManager(tms);
140 //         }
141 
142 //         // initialize the list of cipher suites and protocols enabled by default
143 //         enabledProtocols = NativeCrypto.checkEnabledProtocols(
144 //                 protocols is null ? NativeCrypto.DEFAULT_PROTOCOLS : protocols).dup;
145 //         bool x509CipherSuitesNeeded = (x509KeyManager !is null) || (x509TrustManager !is null);
146 //         bool pskCipherSuitesNeeded = false; // pskKeyManager !is null;
147 //         enabledCipherSuites = getDefaultCipherSuites(
148 //                 x509CipherSuitesNeeded, pskCipherSuitesNeeded);
149 // }
150 //         // We ignore the SecureRandom passed in by the caller. The native code below
151 //         // directly accesses /dev/urandom, which makes it irrelevant.
152 //     }
153 
154     KeyCertOptions getKeyCertOptions() {
155         return _keyCertOptions;
156     }
157 
158     /**
159      * Returns the appropriate session context.
160      */
161     AbstractSessionContext getSessionContext() {
162         return client_mode ? clientSessionContext : serverSessionContext;
163     }
164 
165     /**
166      * @return client session context
167      */
168     ClientSessionContext getClientSessionContext() {
169         return clientSessionContext;
170     }
171 
172     /**
173      * @return X.509 key manager or {@code null} for none.
174      */
175     // X509KeyManager getX509KeyManager() {
176     //     return x509KeyManager;
177     // }
178 
179     // /**
180     //  * @return Pre-Shared Key (PSK) key manager or {@code null} for none.
181     //  */
182     // @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package
183     // PSKKeyManager getPSKKeyManager() {
184     //     return pskKeyManager;
185     // }
186 
187     // /**
188     //  * @return X.509 trust manager or {@code null} for none.
189     //  */
190     // X509TrustManager getX509TrustManager() {
191     //     return x509TrustManager;
192     // }
193 
194     /**
195      * @return the names of enabled cipher suites
196      */
197     string[] getEnabledCipherSuites() {
198         return enabledCipherSuites.dup;
199     }
200 
201     /**
202      * Sets the enabled cipher suites after filtering through OpenSSL.
203      */
204     void setEnabledCipherSuites(string[] cipherSuites) {
205         enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(cipherSuites).dup;
206     }
207 
208     /**
209      * @return the set of enabled protocols
210      */
211     string[] getEnabledProtocols() {
212         return enabledProtocols.dup;
213     }
214 
215     /**
216      * Sets the list of available protocols for use in SSL connection.
217      * @throws IllegalArgumentException if {@code protocols is null}
218      */
219     void setEnabledProtocols(string[] protocols) {
220         if (protocols is null) {
221             throw new IllegalArgumentException("protocols is null");
222         }
223         string[] filteredProtocols =
224                 filterFromProtocols(protocols, NativeCrypto.OBSOLETE_PROTOCOL_SSLV3);
225         isEnabledProtocolsFiltered = protocols.length != filteredProtocols.length;
226         enabledProtocols = NativeCrypto.checkEnabledProtocols(filteredProtocols).dup;
227     }
228 
229     /**
230      * Sets the list of ALPN protocols.
231      *
232      * @param protocols the list of ALPN protocols
233      */
234     void setApplicationProtocols(string[] protocols) {
235         this.applicationProtocols = cast(ubyte[])SSLUtils.encodeProtocols(protocols);
236     }
237 
238     string[] getApplicationProtocols() {
239         return SSLUtils.decodeProtocols(applicationProtocols);
240     }
241 
242     /**
243      * Used for server-mode only. Sets or clears the application-provided ALPN protocol selector.
244      * If set, will override the protocol list provided by {@link #setApplicationProtocols(string[])}.
245      */
246     void setApplicationProtocolSelector(ApplicationProtocolSelectorAdapter applicationProtocolSelector) {
247         this.applicationProtocolSelector = applicationProtocolSelector;
248     }
249 
250     /**
251      * Tunes the peer holding this parameters to work in client mode.
252      * @param   mode if the peer is configured to work in client mode
253      */
254     void setUseClientMode(bool mode) {
255         client_mode = mode;
256     }
257 
258     /**
259      * Returns the value indicating if the parameters configured to work
260      * in client mode.
261      */
262     bool getUseClientMode() {
263         return client_mode;
264     }
265 
266     /**
267      * Tunes the peer holding this parameters to require client authentication
268      */
269     void setNeedClientAuth(bool need) {
270         need_client_auth = need;
271         // reset the want_client_auth setting
272         want_client_auth = false;
273     }
274 
275     /**
276      * Returns the value indicating if the peer with this parameters tuned
277      * to require client authentication
278      */
279     bool getNeedClientAuth() {
280         return need_client_auth;
281     }
282 
283     /**
284      * Tunes the peer holding this parameters to request client authentication
285      */
286     void setWantClientAuth(bool want) {
287         want_client_auth = want;
288         // reset the need_client_auth setting
289         need_client_auth = false;
290     }
291 
292     /**
293      * Returns the value indicating if the peer with this parameters
294      * tuned to request client authentication
295      */
296     bool getWantClientAuth() {
297         return want_client_auth;
298     }
299 
300     /**
301      * Allows/disallows the peer holding this parameters to
302      * create new SSL session
303      */
304     void setEnableSessionCreation(bool flag) {
305         enable_session_creation = flag;
306     }
307 
308     /**
309      * Returns the value indicating if the peer with this parameters
310      * allowed to cteate new SSL session
311      */
312     bool getEnableSessionCreation() {
313         return enable_session_creation;
314     }
315 
316     void setUseSessionTickets(bool useSessionTickets) {
317         this.useSessionTickets = useSessionTickets;
318     }
319 
320     /**
321      * Whether connections using this SSL connection should use the TLS
322      * extension Server Name Indication (SNI).
323      */
324     void setUseSni(bool flag) {
325         useSni = flag;
326     }
327 
328     /**
329      * Returns whether connections using this SSL connection should use the TLS
330      * extension Server Name Indication (SNI).
331      */
332     bool getUseSni() {
333         return useSni ? useSni : isSniEnabledByDefault();
334     }
335 
336     /**
337      * For testing only.
338      */
339     void setCTVerificationEnabled(bool enabled) {
340         ctVerificationEnabled = enabled;
341     }
342 
343     /**
344      * For testing only.
345      */
346     void setSCTExtension(byte[] extension) {
347         sctExtension = extension;
348     }
349 
350     /**
351      * For testing only.
352      */
353     void setOCSPResponse(byte[] response) {
354         ocspResponse = response;
355     }
356 
357     byte[] getOCSPResponse() {
358         return ocspResponse;
359     }
360 
361     /**
362      * This filters {@code obsoleteProtocol} from the list of {@code protocols}
363      * down to help with app compatibility.
364      */
365     private static string[] filterFromProtocols(string[] protocols, string obsoleteProtocol) {
366         if (protocols.length == 1 && obsoleteProtocol == protocols[0]) {
367             return [];
368         }
369 
370         string[] newProtocols;
371         foreach (string protocol ; protocols) {
372             if (obsoleteProtocol != protocol) {
373                 newProtocols ~= protocol;
374             }
375         }
376         return newProtocols;
377     }
378 
379     /**
380      * Returns whether Server Name Indication (SNI) is enabled by default for
381      * sockets. For more information on SNI, see RFC 6066 section 3.
382      */
383     private bool isSniEnabledByDefault() {
384         return false;
385         // try {
386         //     string enableSNI = System.getProperty("jsse.enableSNIExtension", "true");
387         //     if ("true".equalsIgnoreCase(enableSNI)) {
388         //         return true;
389         //     } else if ("false".equalsIgnoreCase(enableSNI)) {
390         //         return false;
391         //     } else {
392         //         throw new RuntimeException(
393         //                 "Can only set \"jsse.enableSNIExtension\" to \"true\" or \"false\"");
394         //     }
395         // } catch (SecurityException e) {
396         //     return true;
397         // }
398     }
399 
400     /**
401      * Returns the clone of this object.
402      * @return the clone.
403      */
404     mixin CloneMemberTemplate!(typeof(this), TopLevel.no, (typeof(this) from, typeof(this) to) {
405         // FIXME: Needing refactor or cleanup -@zxp at 6/10/2019, 3:22:38 PM
406         // need to check this
407     });
408 
409 
410     // private static X509KeyManager getDefaultX509KeyManager()  {
411     //     X509KeyManager result = defaultX509KeyManager;
412     //     if (result is null) {
413     //         // single-check idiom
414     //         defaultX509KeyManager = result = createDefaultX509KeyManager();
415     //     }
416     //     return result;
417     // }
418 
419     // private static X509KeyManager createDefaultX509KeyManager()  {
420     //     try {
421     //         // string algorithm = KeyManagerFactory.getDefaultAlgorithm();
422     //         // KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
423     //         // kmf.init(null, null);
424     //         // KeyManager[] kms = kmf.getKeyManagers();
425     //         // X509KeyManager result = findFirstX509KeyManager(kms);
426     //         // if (result is null) {
427     //         //     throw new KeyManagementException("No X509KeyManager among default KeyManagers: "
428     //         //             ~ kms.to!string());
429     //         // }
430     //         // return result;
431     //         implementationMissing(false);
432     //         return null;
433     //     } catch (NoSuchAlgorithmException e) {
434     //         throw new KeyManagementException(e);
435     //     } catch (KeyStoreException e) {
436     //         throw new KeyManagementException(e);
437     //     } catch (UnrecoverableKeyException e) {
438     //         throw new KeyManagementException(e);
439     //     }
440     // }
441 
442     /**
443      * Finds the first {@link X509KeyManager} element in the provided array.
444      *
445      * @return the first {@code X509KeyManager} or {@code null} if not found.
446      */
447     // private static X509KeyManager findFirstX509KeyManager(KeyManager[] kms) {
448     //     foreach (KeyManager km ; kms) {
449     //         X509KeyManager m = cast(X509KeyManager)km;
450     //         if (m !is null) {
451     //             return m;
452     //         }
453     //     }
454     //     warning("X509KeyManager is null");
455     //     return null;
456     // }
457 
458     // /**
459     //  * Finds the first {@link PSKKeyManager} element in the provided array.
460     //  *
461     //  * @return the first {@code PSKKeyManager} or {@code null} if not found.
462     //  */
463     // @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package
464     // private static PSKKeyManager findFirstPSKKeyManager(KeyManager[] kms) {
465     //     for (KeyManager km : kms) {
466     //         if (km instanceof PSKKeyManager) {
467     //             return (PSKKeyManager)km;
468     //         } else if (km !is null) {
469     //             try {
470     //                 return DuckTypedPSKKeyManager.getInstance(km);
471     //             } catch (NoSuchMethodException ignored) {}
472     //         }
473     //     }
474     //     return null;
475     // }
476 
477     /**
478      * Gets the default X.509 trust manager.
479      */
480     // static X509TrustManager getDefaultX509TrustManager()
481     //          {
482     //     X509TrustManager result = defaultX509TrustManager;
483     //     if (result is null) {
484     //         // single-check idiom
485     //         // defaultX509TrustManager = result = createDefaultX509TrustManager();
486     //     }
487     //     return result;
488     // }
489 
490     // private static X509TrustManager createDefaultX509TrustManager()
491     //          {
492     //     try {
493     //         string algorithm = TrustManagerFactory.getDefaultAlgorithm();
494     //         TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
495     //         tmf.init((KeyStore) null);
496     //         TrustManager[] tms = tmf.getTrustManagers();
497     //         X509TrustManager trustManager = findFirstX509TrustManager(tms);
498     //         if (trustManager is null) {
499     //             throw new KeyManagementException(
500     //                     "No X509TrustManager in among default TrustManagers: "
501     //                             + Arrays.toString(tms));
502     //         }
503     //         return trustManager;
504     //     } catch (NoSuchAlgorithmException e) {
505     //         throw new KeyManagementException(e);
506     //     } catch (KeyStoreException e) {
507     //         throw new KeyManagementException(e);
508     //     }
509     // }
510 
511     /**
512      * Finds the first {@link X509TrustManager} element in the provided array.
513      *
514      * @return the first {@code X509ExtendedTrustManager} or
515      *         {@code X509TrustManager} or {@code null} if not found.
516      */
517     // private static X509TrustManager findFirstX509TrustManager(TrustManager[] tms) {
518     //     foreach (TrustManager tm ; tms) {
519     //         X509TrustManager m = cast(X509TrustManager) tm; 
520     //         if (m !is null) {
521     //             return m;
522     //         }
523     //     }
524     //     return null;
525     // }
526 
527     // string getEndpointIdentificationAlgorithm() {
528     //     return endpointIdentificationAlgorithm;
529     // }
530 
531     // void setEndpointIdentificationAlgorithm(string endpointIdentificationAlgorithm) {
532     //     this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm;
533     // }
534 
535     // bool getUseCipherSuitesOrder() {
536     //     return useCipherSuitesOrder;
537     // }
538 
539     // void setUseCipherSuitesOrder(bool useCipherSuitesOrder) {
540     //     this.useCipherSuitesOrder = useCipherSuitesOrder;
541     // }
542 
543     private static string[] getDefaultCipherSuites(
544             bool x509CipherSuitesNeeded,
545             bool pskCipherSuitesNeeded) {
546         if (x509CipherSuitesNeeded) {
547             // X.509 based cipher suites need to be listed.
548             if (pskCipherSuitesNeeded) {
549                 // Both X.509 and PSK based cipher suites need to be listed. Because TLS-PSK is not
550                 // normally used, we assume that when PSK cipher suites are requested here they
551                 // should be preferred over other cipher suites. Thus, we give PSK cipher suites
552                 // higher priority than X.509 cipher suites.
553                 // NOTE: There are cipher suites that use both X.509 and PSK (e.g., those based on
554                 // RSA_PSK key exchange). However, these cipher suites are not currently supported.
555                 return NativeCrypto.DEFAULT_PSK_CIPHER_SUITES ~
556                         NativeCrypto.DEFAULT_X509_CIPHER_SUITES ~
557                         [ NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ];
558             } else {
559                 // Only X.509 cipher suites need to be listed.
560                 return NativeCrypto.DEFAULT_X509_CIPHER_SUITES ~
561                     [ NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ];
562             }
563         } else if (pskCipherSuitesNeeded) {
564             // Only PSK cipher suites need to be listed.
565             return NativeCrypto.DEFAULT_PSK_CIPHER_SUITES ~
566                    [ NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ];
567         } else {
568             // Neither X.509 nor PSK cipher suites need to be listed.
569             return [ NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ];
570         }
571     }
572 
573     // private static string[] concat(string[]... arrays) {
574     //     int resultLength = 0;
575     //     for (string[] array : arrays) {
576     //         resultLength += array.length;
577     //     }
578     //     string[] result = new string[resultLength];
579     //     int resultOffset = 0;
580     //     for (string[] array : arrays) {
581     //         System.arraycopy(array, 0, result, resultOffset, array.length);
582     //         resultOffset += array.length;
583     //     }
584     //     return result;
585     // }
586 
587     /**
588      * Check if SCT verification is enforced for a given hostname.
589      */
590     bool isCTVerificationEnabled(string hostname) {
591         if (hostname is null) {
592             return false;
593         }
594 
595         // Bypass the check. This is used for testing only
596         if (ctVerificationEnabled) {
597             return true;
598         }
599         // return Platform.isCTVerificationRequired(hostname);
600         implementationMissing();
601 return false;
602     }
603 }
604 
605 
606 /**
607 * For abstracting the X509KeyManager calls between
608 * {@link X509KeyManager#chooseClientAlias(string[], java.security.Principal[], java.net.Socket)}
609 * and
610 * {@link X509ExtendedKeyManager#chooseEngineClientAlias(string[], java.security.Principal[], javax.net.ssl.SSLEngine)}
611 */
612 // interface AliasChooser {
613 //     string chooseClientAlias(X509KeyManager keyManager, X500Principal[] issuers,
614 //             string[] keyTypes);
615 
616 //     string chooseServerAlias(X509KeyManager keyManager, string keyType);
617 // }
618 
619 /**
620 * For abstracting the {@code PSKKeyManager} calls between those taking an {@code SSLSocket} and
621 * those taking an {@code SSLEngine}.
622 */
623 // @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package
624 // interface PSKCallbacks {
625 //     // string chooseServerPSKIdentityHint(PSKKeyManager keyManager);
626 //     // string chooseClientPSKIdentity(PSKKeyManager keyManager, string identityHint);
627 //     // SecretKey getPSKKey(PSKKeyManager keyManager, string identityHint, string identity);
628 // }