(
*,
method: Method,
min_version: Version,
max_version: Version,
cipher_list: tuple[str, ...] | None,
ecdh_curve: EllipticCurve | None,
chain_file: Path | None,
alpn_select_callback: Callable[[SSL.Connection, list[bytes]], Any] | None,
request_client_cert: bool,
extra_chain_certs: tuple[certs.Cert, ...],
dhparams: certs.DHParams,
)
| 239 | |
| 240 | @lru_cache(256) |
| 241 | def create_client_proxy_context( |
| 242 | *, |
| 243 | method: Method, |
| 244 | min_version: Version, |
| 245 | max_version: Version, |
| 246 | cipher_list: tuple[str, ...] | None, |
| 247 | ecdh_curve: EllipticCurve | None, |
| 248 | chain_file: Path | None, |
| 249 | alpn_select_callback: Callable[[SSL.Connection, list[bytes]], Any] | None, |
| 250 | request_client_cert: bool, |
| 251 | extra_chain_certs: tuple[certs.Cert, ...], |
| 252 | dhparams: certs.DHParams, |
| 253 | ) -> SSL.Context: |
| 254 | context: SSL.Context = _create_ssl_context( |
| 255 | method=method, |
| 256 | min_version=min_version, |
| 257 | max_version=max_version, |
| 258 | cipher_list=cipher_list, |
| 259 | ecdh_curve=ecdh_curve, |
| 260 | ) |
| 261 | |
| 262 | if chain_file is not None: |
| 263 | try: |
| 264 | context.load_verify_locations(str(chain_file), None) |
| 265 | except SSL.Error as e: |
| 266 | raise RuntimeError(f"Cannot load certificate chain ({chain_file}).") from e |
| 267 | |
| 268 | if alpn_select_callback is not None: |
| 269 | assert callable(alpn_select_callback) |
| 270 | context.set_alpn_select_callback(alpn_select_callback) |
| 271 | |
| 272 | if request_client_cert: |
| 273 | # The request_client_cert argument requires some explanation. We're |
| 274 | # supposed to be able to do this with no negative effects - if the |
| 275 | # client has no cert to present, we're notified and proceed as usual. |
| 276 | # Unfortunately, Android seems to have a bug (tested on 4.2.2) - when |
| 277 | # an Android client is asked to present a certificate it does not |
| 278 | # have, it hangs up, which is frankly bogus. Some time down the track |
| 279 | # we may be able to make the proper behaviour the default again, but |
| 280 | # until then we're conservative. |
| 281 | context.set_verify(Verify.VERIFY_PEER.value, accept_all) |
| 282 | else: |
| 283 | context.set_verify(Verify.VERIFY_NONE.value, None) |
| 284 | |
| 285 | for i in extra_chain_certs: |
| 286 | context.add_extra_chain_cert(i.to_cryptography()) |
| 287 | |
| 288 | if dhparams: |
| 289 | res = SSL._lib.SSL_CTX_set_tmp_dh(context._context, dhparams) # type: ignore |
| 290 | SSL._openssl_assert(res == 1) # type: ignore |
| 291 | |
| 292 | return context |
| 293 | |
| 294 | |
| 295 | def accept_all( |
nothing calls this directly
no test coverage detected
searching dependent graphs…