(
_cls: &Py<PyType>,
proto_version: Self::Args,
vm: &VirtualMachine,
)
| 912 | type Args = i32; |
| 913 | |
| 914 | fn py_new( |
| 915 | _cls: &Py<PyType>, |
| 916 | proto_version: Self::Args, |
| 917 | vm: &VirtualMachine, |
| 918 | ) -> PyResult<Self> { |
| 919 | let proto = SslVersion::try_from(proto_version) |
| 920 | .map_err(|_| vm.new_value_error("invalid protocol version"))?; |
| 921 | let method = match proto { |
| 922 | // SslVersion::Ssl3 => unsafe { ssl::SslMethod::from_ptr(sys::SSLv3_method()) }, |
| 923 | SslVersion::Tls => ssl::SslMethod::tls(), |
| 924 | SslVersion::Tls1 => ssl::SslMethod::tls(), |
| 925 | SslVersion::Tls1_1 => ssl::SslMethod::tls(), |
| 926 | SslVersion::Tls1_2 => ssl::SslMethod::tls(), |
| 927 | SslVersion::TlsClient => ssl::SslMethod::tls_client(), |
| 928 | SslVersion::TlsServer => ssl::SslMethod::tls_server(), |
| 929 | _ => return Err(vm.new_value_error("invalid protocol version")), |
| 930 | }; |
| 931 | let mut builder = |
| 932 | SslContextBuilder::new(method).map_err(|e| convert_openssl_error(vm, e))?; |
| 933 | |
| 934 | #[cfg(target_os = "android")] |
| 935 | android::load_client_ca_list(vm, &mut builder)?; |
| 936 | |
| 937 | let check_hostname = proto == SslVersion::TlsClient; |
| 938 | builder.set_verify(if check_hostname { |
| 939 | SslVerifyMode::PEER | SslVerifyMode::FAIL_IF_NO_PEER_CERT |
| 940 | } else { |
| 941 | SslVerifyMode::NONE |
| 942 | }); |
| 943 | |
| 944 | // Start with OP_ALL but remove options that CPython doesn't include by default |
| 945 | let mut options = SslOptions::ALL & !SslOptions::DONT_INSERT_EMPTY_FRAGMENTS; |
| 946 | if proto != SslVersion::Ssl2 { |
| 947 | options |= SslOptions::NO_SSLV2; |
| 948 | } |
| 949 | if proto != SslVersion::Ssl3 { |
| 950 | options |= SslOptions::NO_SSLV3; |
| 951 | } |
| 952 | options |= SslOptions::NO_COMPRESSION; |
| 953 | options |= SslOptions::CIPHER_SERVER_PREFERENCE; |
| 954 | options |= SslOptions::SINGLE_DH_USE; |
| 955 | options |= SslOptions::SINGLE_ECDH_USE; |
| 956 | options |= SslOptions::ENABLE_MIDDLEBOX_COMPAT; |
| 957 | builder.set_options(options); |
| 958 | // Remove NO_TLSv1 and NO_TLSv1_1 which newer OpenSSL adds to OP_ALL |
| 959 | builder.clear_options(SslOptions::NO_TLSV1 | SslOptions::NO_TLSV1_1); |
| 960 | |
| 961 | let mode = ssl::SslMode::ACCEPT_MOVING_WRITE_BUFFER | ssl::SslMode::AUTO_RETRY; |
| 962 | builder.set_mode(mode); |
| 963 | |
| 964 | #[cfg(ossl111)] |
| 965 | unsafe { |
| 966 | sys::SSL_CTX_set_post_handshake_auth(builder.as_ptr(), 0); |
| 967 | } |
| 968 | |
| 969 | // Note: Unlike some other implementations, we do NOT set session_id_context at the |
| 970 | // context level. CPython sets it only on individual SSL objects (server-side only). |
| 971 | // This matches CPython's behavior in _ssl.c where SSL_set_session_id_context is called |
nothing calls this directly
no test coverage detected