Create a client TLS configuration This abstracts the complex rustls ClientConfig building logic, matching SSL_CTX initialization for client sockets.
(options: ClientConfigOptions)
| 862 | /// This abstracts the complex rustls ClientConfig building logic, |
| 863 | /// matching SSL_CTX initialization for client sockets. |
| 864 | pub(super) fn create_client_config(options: ClientConfigOptions) -> Result<ClientConfig, String> { |
| 865 | // Ensure default CryptoProvider is installed |
| 866 | ensure_default_provider(); |
| 867 | |
| 868 | // Create custom crypto provider using helper function |
| 869 | let custom_provider = create_custom_crypto_provider( |
| 870 | options.protocol_settings.cipher_suites.clone(), |
| 871 | options.protocol_settings.kx_groups.clone(), |
| 872 | ); |
| 873 | |
| 874 | // Step 1: Build the appropriate verifier based on verification settings |
| 875 | let verifier: Arc<dyn rustls::client::danger::ServerCertVerifier> = if options |
| 876 | .verify_server_cert |
| 877 | { |
| 878 | // Verify server certificates |
| 879 | let root_store = options |
| 880 | .root_store |
| 881 | .ok_or("Root store required for server verification")?; |
| 882 | |
| 883 | let root_store_arc = Arc::new(root_store); |
| 884 | |
| 885 | // Check if root_store is empty (no CA certs loaded) |
| 886 | // CPython allows this and fails during handshake with SSLCertVerificationError |
| 887 | if root_store_arc.is_empty() { |
| 888 | // Use EmptyRootStoreVerifier - always fails with UnknownIssuer during handshake |
| 889 | use crate::ssl::cert::EmptyRootStoreVerifier; |
| 890 | Arc::new(EmptyRootStoreVerifier) |
| 891 | } else { |
| 892 | // Calculate has_crls once for both hostname verification paths |
| 893 | let has_crls = !options.crls.is_empty(); |
| 894 | |
| 895 | if options.check_hostname { |
| 896 | // Default behavior: verify both certificate chain and hostname |
| 897 | let base_verifier = build_webpki_verifier_with_crls( |
| 898 | root_store_arc.clone(), |
| 899 | options.crls, |
| 900 | options.verify_flags, |
| 901 | )?; |
| 902 | |
| 903 | // Apply CRL and Strict verifier wrappers using helper function |
| 904 | apply_verifier_wrappers( |
| 905 | base_verifier, |
| 906 | options.verify_flags, |
| 907 | has_crls, |
| 908 | options.ca_certs_der.clone(), |
| 909 | ) |
| 910 | } else { |
| 911 | // check_hostname=False: verify certificate chain but ignore hostname |
| 912 | use crate::ssl::cert::HostnameIgnoringVerifier; |
| 913 | |
| 914 | // Build verifier with CRL support using helper function |
| 915 | let webpki_verifier = build_webpki_verifier_with_crls( |
| 916 | root_store_arc.clone(), |
| 917 | options.crls, |
| 918 | options.verify_flags, |
| 919 | )?; |
| 920 | |
| 921 | // Apply CRL verifier wrapper if needed (without Strict wrapper yet) |
no test coverage detected