codekingpro/portable-devtools
115k
1from __future__ import annotations2 3import os4import socket5import sys6import typing7import warnings8from collections.abc import Sequence9from errno import errorcode10from functools import partial, wraps11from itertools import chain, count12from sys import platform13from typing import Any, Callable, Optional, TypeVar14from weakref import WeakValueDictionary15 16from cryptography import x50917from cryptography.hazmat.primitives.asymmetric import ec18 19from OpenSSL._util import (20 StrOrBytesPath as _StrOrBytesPath,21)22from OpenSSL._util import (23 exception_from_error_queue as _exception_from_error_queue,24)25from OpenSSL._util import (26 ffi as _ffi,27)28from OpenSSL._util import (29 lib as _lib,30)31from OpenSSL._util import (32 make_assert as _make_assert,33)34from OpenSSL._util import (35 no_zero_allocator as _no_zero_allocator,36)37from OpenSSL._util import (38 path_bytes as _path_bytes,39)40from OpenSSL._util import (41 text_to_bytes_and_warn as _text_to_bytes_and_warn,42)43from OpenSSL.crypto import (44 FILETYPE_PEM,45 X509,46 PKey,47 X509Name,48 X509Store,49 _EllipticCurve,50 _PassphraseHelper,51 _PrivateKey,52)53 54__all__ = [55 "DTLS_CLIENT_METHOD",56 "DTLS_METHOD",57 "DTLS_SERVER_METHOD",58 "MODE_RELEASE_BUFFERS",59 "NO_OVERLAPPING_PROTOCOLS",60 "OPENSSL_BUILT_ON",61 "OPENSSL_CFLAGS",62 "OPENSSL_DIR",63 "OPENSSL_PLATFORM",64 "OPENSSL_VERSION",65 "OPENSSL_VERSION_NUMBER",66 "OP_ALL",67 "OP_CIPHER_SERVER_PREFERENCE",68 "OP_DONT_INSERT_EMPTY_FRAGMENTS",69 "OP_EPHEMERAL_RSA",70 "OP_MICROSOFT_BIG_SSLV3_BUFFER",71 "OP_MICROSOFT_SESS_ID_BUG",72 "OP_MSIE_SSLV2_RSA_PADDING",73 "OP_NETSCAPE_CA_DN_BUG",74 "OP_NETSCAPE_CHALLENGE_BUG",75 "OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG",76 "OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG",77 "OP_NO_COMPRESSION",78 "OP_NO_QUERY_MTU",79 "OP_NO_TICKET",80 "OP_PKCS1_CHECK_1",81 "OP_PKCS1_CHECK_2",82 "OP_SINGLE_DH_USE",83 "OP_SINGLE_ECDH_USE",84 "OP_SSLEAY_080_CLIENT_DH_BUG",85 "OP_SSLREF2_REUSE_CERT_TYPE_BUG",86 "OP_TLS_BLOCK_PADDING_BUG",87 "OP_TLS_D5_BUG",88 "OP_TLS_ROLLBACK_BUG",89 "RECEIVED_SHUTDOWN",90 "SENT_SHUTDOWN",91 "SESS_CACHE_BOTH",92 "SESS_CACHE_CLIENT",93 "SESS_CACHE_NO_AUTO_CLEAR",94 "SESS_CACHE_NO_INTERNAL",95 "SESS_CACHE_NO_INTERNAL_LOOKUP",96 "SESS_CACHE_NO_INTERNAL_STORE",97 "SESS_CACHE_OFF",98 "SESS_CACHE_SERVER",99 "SSL3_VERSION",100 "SSLEAY_BUILT_ON",101 "SSLEAY_CFLAGS",102 "SSLEAY_DIR",103 "SSLEAY_PLATFORM",104 "SSLEAY_VERSION",105 "SSL_CB_ACCEPT_EXIT",106 "SSL_CB_ACCEPT_LOOP",107 "SSL_CB_ALERT",108 "SSL_CB_CONNECT_EXIT",109 "SSL_CB_CONNECT_LOOP",110 "SSL_CB_EXIT",111 "SSL_CB_HANDSHAKE_DONE",112 "SSL_CB_HANDSHAKE_START",113 "SSL_CB_LOOP",114 "SSL_CB_READ",115 "SSL_CB_READ_ALERT",116 "SSL_CB_WRITE",117 "SSL_CB_WRITE_ALERT",118 "SSL_ST_ACCEPT",119 "SSL_ST_CONNECT",120 "SSL_ST_MASK",121 "TLS1_1_VERSION",122 "TLS1_2_VERSION",123 "TLS1_3_VERSION",124 "TLS1_VERSION",125 "TLS_CLIENT_METHOD",126 "TLS_METHOD",127 "TLS_SERVER_METHOD",128 "VERIFY_CLIENT_ONCE",129 "VERIFY_FAIL_IF_NO_PEER_CERT",130 "VERIFY_NONE",131 "VERIFY_PEER",132 "Connection",133 "Context",134 "Error",135 "OP_NO_SSLv2",136 "OP_NO_SSLv3",137 "OP_NO_TLSv1",138 "OP_NO_TLSv1_1",139 "OP_NO_TLSv1_2",140 "OP_NO_TLSv1_3",141 "SSLeay_version",142 "SSLv23_METHOD",143 "Session",144 "SysCallError",145 "TLSv1_1_METHOD",146 "TLSv1_2_METHOD",147 "TLSv1_METHOD",148 "WantReadError",149 "WantWriteError",150 "WantX509LookupError",151 "X509VerificationCodes",152 "ZeroReturnError",153]154 155 156OPENSSL_VERSION_NUMBER: int = _lib.OPENSSL_VERSION_NUMBER157OPENSSL_VERSION: int = _lib.OPENSSL_VERSION158OPENSSL_CFLAGS: int = _lib.OPENSSL_CFLAGS159OPENSSL_PLATFORM: int = _lib.OPENSSL_PLATFORM160OPENSSL_DIR: int = _lib.OPENSSL_DIR161OPENSSL_BUILT_ON: int = _lib.OPENSSL_BUILT_ON162 163SSLEAY_VERSION = OPENSSL_VERSION164SSLEAY_CFLAGS = OPENSSL_CFLAGS165SSLEAY_PLATFORM = OPENSSL_PLATFORM166SSLEAY_DIR = OPENSSL_DIR167SSLEAY_BUILT_ON = OPENSSL_BUILT_ON168 169SENT_SHUTDOWN = _lib.SSL_SENT_SHUTDOWN170RECEIVED_SHUTDOWN = _lib.SSL_RECEIVED_SHUTDOWN171 172SSLv23_METHOD = 3173TLSv1_METHOD = 4174TLSv1_1_METHOD = 5175TLSv1_2_METHOD = 6176TLS_METHOD = 7177TLS_SERVER_METHOD = 8178TLS_CLIENT_METHOD = 9179DTLS_METHOD = 10180DTLS_SERVER_METHOD = 11181DTLS_CLIENT_METHOD = 12182 183SSL3_VERSION: int = _lib.SSL3_VERSION184TLS1_VERSION: int = _lib.TLS1_VERSION185TLS1_1_VERSION: int = _lib.TLS1_1_VERSION186TLS1_2_VERSION: int = _lib.TLS1_2_VERSION187TLS1_3_VERSION: int = _lib.TLS1_3_VERSION188 189OP_NO_SSLv2: int = _lib.SSL_OP_NO_SSLv2190OP_NO_SSLv3: int = _lib.SSL_OP_NO_SSLv3191OP_NO_TLSv1: int = _lib.SSL_OP_NO_TLSv1192OP_NO_TLSv1_1: int = _lib.SSL_OP_NO_TLSv1_1193OP_NO_TLSv1_2: int = _lib.SSL_OP_NO_TLSv1_2194OP_NO_TLSv1_3: int = _lib.SSL_OP_NO_TLSv1_3195 196MODE_RELEASE_BUFFERS: int = _lib.SSL_MODE_RELEASE_BUFFERS197 198OP_SINGLE_DH_USE: int = _lib.SSL_OP_SINGLE_DH_USE199OP_SINGLE_ECDH_USE: int = _lib.SSL_OP_SINGLE_ECDH_USE200OP_EPHEMERAL_RSA: int = _lib.SSL_OP_EPHEMERAL_RSA201OP_MICROSOFT_SESS_ID_BUG: int = _lib.SSL_OP_MICROSOFT_SESS_ID_BUG202OP_NETSCAPE_CHALLENGE_BUG: int = _lib.SSL_OP_NETSCAPE_CHALLENGE_BUG203OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: int = (204 _lib.SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG205)206OP_SSLREF2_REUSE_CERT_TYPE_BUG: int = _lib.SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG207OP_MICROSOFT_BIG_SSLV3_BUFFER: int = _lib.SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER208OP_MSIE_SSLV2_RSA_PADDING: int = _lib.SSL_OP_MSIE_SSLV2_RSA_PADDING209OP_SSLEAY_080_CLIENT_DH_BUG: int = _lib.SSL_OP_SSLEAY_080_CLIENT_DH_BUG210OP_TLS_D5_BUG: int = _lib.SSL_OP_TLS_D5_BUG211OP_TLS_BLOCK_PADDING_BUG: int = _lib.SSL_OP_TLS_BLOCK_PADDING_BUG212OP_DONT_INSERT_EMPTY_FRAGMENTS: int = _lib.SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS213OP_CIPHER_SERVER_PREFERENCE: int = _lib.SSL_OP_CIPHER_SERVER_PREFERENCE214OP_TLS_ROLLBACK_BUG: int = _lib.SSL_OP_TLS_ROLLBACK_BUG215OP_PKCS1_CHECK_1 = _lib.SSL_OP_PKCS1_CHECK_1216OP_PKCS1_CHECK_2: int = _lib.SSL_OP_PKCS1_CHECK_2217OP_NETSCAPE_CA_DN_BUG: int = _lib.SSL_OP_NETSCAPE_CA_DN_BUG218OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG: int = (219 _lib.SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG220)221OP_NO_COMPRESSION: int = _lib.SSL_OP_NO_COMPRESSION222 223OP_NO_QUERY_MTU: int = _lib.SSL_OP_NO_QUERY_MTU224try:225 OP_COOKIE_EXCHANGE: int | None = _lib.SSL_OP_COOKIE_EXCHANGE226 __all__.append("OP_COOKIE_EXCHANGE")227except AttributeError:228 OP_COOKIE_EXCHANGE = None229OP_NO_TICKET: int = _lib.SSL_OP_NO_TICKET230 231try:232 OP_NO_RENEGOTIATION: int = _lib.SSL_OP_NO_RENEGOTIATION233 __all__.append("OP_NO_RENEGOTIATION")234except AttributeError:235 pass236 237try:238 OP_IGNORE_UNEXPECTED_EOF: int = _lib.SSL_OP_IGNORE_UNEXPECTED_EOF239 __all__.append("OP_IGNORE_UNEXPECTED_EOF")240except AttributeError:241 pass242 243try:244 OP_LEGACY_SERVER_CONNECT: int = _lib.SSL_OP_LEGACY_SERVER_CONNECT245 __all__.append("OP_LEGACY_SERVER_CONNECT")246except AttributeError:247 pass248 249OP_ALL: int = _lib.SSL_OP_ALL250 251VERIFY_PEER: int = _lib.SSL_VERIFY_PEER252VERIFY_FAIL_IF_NO_PEER_CERT: int = _lib.SSL_VERIFY_FAIL_IF_NO_PEER_CERT253VERIFY_CLIENT_ONCE: int = _lib.SSL_VERIFY_CLIENT_ONCE254VERIFY_NONE: int = _lib.SSL_VERIFY_NONE255 256SESS_CACHE_OFF: int = _lib.SSL_SESS_CACHE_OFF257SESS_CACHE_CLIENT: int = _lib.SSL_SESS_CACHE_CLIENT258SESS_CACHE_SERVER: int = _lib.SSL_SESS_CACHE_SERVER259SESS_CACHE_BOTH: int = _lib.SSL_SESS_CACHE_BOTH260SESS_CACHE_NO_AUTO_CLEAR: int = _lib.SSL_SESS_CACHE_NO_AUTO_CLEAR261SESS_CACHE_NO_INTERNAL_LOOKUP: int = _lib.SSL_SESS_CACHE_NO_INTERNAL_LOOKUP262SESS_CACHE_NO_INTERNAL_STORE: int = _lib.SSL_SESS_CACHE_NO_INTERNAL_STORE263SESS_CACHE_NO_INTERNAL: int = _lib.SSL_SESS_CACHE_NO_INTERNAL264 265SSL_ST_CONNECT: int = _lib.SSL_ST_CONNECT266SSL_ST_ACCEPT: int = _lib.SSL_ST_ACCEPT267SSL_ST_MASK: int = _lib.SSL_ST_MASK268 269SSL_CB_LOOP: int = _lib.SSL_CB_LOOP270SSL_CB_EXIT: int = _lib.SSL_CB_EXIT271SSL_CB_READ: int = _lib.SSL_CB_READ272SSL_CB_WRITE: int = _lib.SSL_CB_WRITE273SSL_CB_ALERT: int = _lib.SSL_CB_ALERT274SSL_CB_READ_ALERT: int = _lib.SSL_CB_READ_ALERT275SSL_CB_WRITE_ALERT: int = _lib.SSL_CB_WRITE_ALERT276SSL_CB_ACCEPT_LOOP: int = _lib.SSL_CB_ACCEPT_LOOP277SSL_CB_ACCEPT_EXIT: int = _lib.SSL_CB_ACCEPT_EXIT278SSL_CB_CONNECT_LOOP: int = _lib.SSL_CB_CONNECT_LOOP279SSL_CB_CONNECT_EXIT: int = _lib.SSL_CB_CONNECT_EXIT280SSL_CB_HANDSHAKE_START: int = _lib.SSL_CB_HANDSHAKE_START281SSL_CB_HANDSHAKE_DONE: int = _lib.SSL_CB_HANDSHAKE_DONE282 283_Buffer = typing.Union[bytes, bytearray, memoryview]284_T = TypeVar("_T")285 286 287class _NoOverlappingProtocols:288 pass289 290 291NO_OVERLAPPING_PROTOCOLS = _NoOverlappingProtocols()292 293# Callback types.294_ALPNSelectCallback = Callable[295 [296 "Connection",297 typing.List[bytes],298 ],299 typing.Union[bytes, _NoOverlappingProtocols],300]301_CookieGenerateCallback = Callable[["Connection"], bytes]302_CookieVerifyCallback = Callable[["Connection", bytes], bool]303_OCSPClientCallback = Callable[["Connection", bytes, Optional[_T]], bool]304_OCSPServerCallback = Callable[["Connection", Optional[_T]], bytes]305_PassphraseCallback = Callable[[int, bool, Optional[_T]], bytes]306_VerifyCallback = Callable[["Connection", X509, int, int, int], bool]307 308 309class X509VerificationCodes:310 """311 Success and error codes for X509 verification, as returned by the312 underlying ``X509_STORE_CTX_get_error()`` function and passed by pyOpenSSL313 to verification callback functions.314 315 See `OpenSSL Verification Errors316 <https://www.openssl.org/docs/manmaster/man3/X509_verify_cert_error_string.html#ERROR-CODES>`_317 for details.318 """319 320 OK = _lib.X509_V_OK321 ERR_UNABLE_TO_GET_ISSUER_CERT = _lib.X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT322 ERR_UNABLE_TO_GET_CRL = _lib.X509_V_ERR_UNABLE_TO_GET_CRL323 ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE = (324 _lib.X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE325 )326 ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE = (327 _lib.X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE328 )329 ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY = (330 _lib.X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY331 )332 ERR_CERT_SIGNATURE_FAILURE = _lib.X509_V_ERR_CERT_SIGNATURE_FAILURE333 ERR_CRL_SIGNATURE_FAILURE = _lib.X509_V_ERR_CRL_SIGNATURE_FAILURE334 ERR_CERT_NOT_YET_VALID = _lib.X509_V_ERR_CERT_NOT_YET_VALID335 ERR_CERT_HAS_EXPIRED = _lib.X509_V_ERR_CERT_HAS_EXPIRED336 ERR_CRL_NOT_YET_VALID = _lib.X509_V_ERR_CRL_NOT_YET_VALID337 ERR_CRL_HAS_EXPIRED = _lib.X509_V_ERR_CRL_HAS_EXPIRED338 ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = (339 _lib.X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD340 )341 ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = (342 _lib.X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD343 )344 ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD = (345 _lib.X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD346 )347 ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = (348 _lib.X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD349 )350 ERR_OUT_OF_MEM = _lib.X509_V_ERR_OUT_OF_MEM351 ERR_DEPTH_ZERO_SELF_SIGNED_CERT = (352 _lib.X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT353 )354 ERR_SELF_SIGNED_CERT_IN_CHAIN = _lib.X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN355 ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = (356 _lib.X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY357 )358 ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = (359 _lib.X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE360 )361 ERR_CERT_CHAIN_TOO_LONG = _lib.X509_V_ERR_CERT_CHAIN_TOO_LONG362 ERR_CERT_REVOKED = _lib.X509_V_ERR_CERT_REVOKED363 ERR_INVALID_CA = _lib.X509_V_ERR_INVALID_CA364 ERR_PATH_LENGTH_EXCEEDED = _lib.X509_V_ERR_PATH_LENGTH_EXCEEDED365 ERR_INVALID_PURPOSE = _lib.X509_V_ERR_INVALID_PURPOSE366 ERR_CERT_UNTRUSTED = _lib.X509_V_ERR_CERT_UNTRUSTED367 ERR_CERT_REJECTED = _lib.X509_V_ERR_CERT_REJECTED368 ERR_SUBJECT_ISSUER_MISMATCH = _lib.X509_V_ERR_SUBJECT_ISSUER_MISMATCH369 ERR_AKID_SKID_MISMATCH = _lib.X509_V_ERR_AKID_SKID_MISMATCH370 ERR_AKID_ISSUER_SERIAL_MISMATCH = (371 _lib.X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH372 )373 ERR_KEYUSAGE_NO_CERTSIGN = _lib.X509_V_ERR_KEYUSAGE_NO_CERTSIGN374 ERR_UNABLE_TO_GET_CRL_ISSUER = _lib.X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER375 ERR_UNHANDLED_CRITICAL_EXTENSION = (376 _lib.X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION377 )378 ERR_KEYUSAGE_NO_CRL_SIGN = _lib.X509_V_ERR_KEYUSAGE_NO_CRL_SIGN379 ERR_UNHANDLED_CRITICAL_CRL_EXTENSION = (380 _lib.X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION381 )382 ERR_INVALID_NON_CA = _lib.X509_V_ERR_INVALID_NON_CA383 ERR_PROXY_PATH_LENGTH_EXCEEDED = _lib.X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED384 ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE = (385 _lib.X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE386 )387 ERR_PROXY_CERTIFICATES_NOT_ALLOWED = (388 _lib.X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED389 )390 ERR_INVALID_EXTENSION = _lib.X509_V_ERR_INVALID_EXTENSION391 ERR_INVALID_POLICY_EXTENSION = _lib.X509_V_ERR_INVALID_POLICY_EXTENSION392 ERR_NO_EXPLICIT_POLICY = _lib.X509_V_ERR_NO_EXPLICIT_POLICY393 ERR_DIFFERENT_CRL_SCOPE = _lib.X509_V_ERR_DIFFERENT_CRL_SCOPE394 ERR_UNSUPPORTED_EXTENSION_FEATURE = (395 _lib.X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE396 )397 ERR_UNNESTED_RESOURCE = _lib.X509_V_ERR_UNNESTED_RESOURCE398 ERR_PERMITTED_VIOLATION = _lib.X509_V_ERR_PERMITTED_VIOLATION399 ERR_EXCLUDED_VIOLATION = _lib.X509_V_ERR_EXCLUDED_VIOLATION400 ERR_SUBTREE_MINMAX = _lib.X509_V_ERR_SUBTREE_MINMAX401 ERR_UNSUPPORTED_CONSTRAINT_TYPE = (402 _lib.X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE403 )404 ERR_UNSUPPORTED_CONSTRAINT_SYNTAX = (405 _lib.X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX406 )407 ERR_UNSUPPORTED_NAME_SYNTAX = _lib.X509_V_ERR_UNSUPPORTED_NAME_SYNTAX408 ERR_CRL_PATH_VALIDATION_ERROR = _lib.X509_V_ERR_CRL_PATH_VALIDATION_ERROR409 ERR_HOSTNAME_MISMATCH = _lib.X509_V_ERR_HOSTNAME_MISMATCH410 ERR_EMAIL_MISMATCH = _lib.X509_V_ERR_EMAIL_MISMATCH411 ERR_IP_ADDRESS_MISMATCH = _lib.X509_V_ERR_IP_ADDRESS_MISMATCH412 ERR_APPLICATION_VERIFICATION = _lib.X509_V_ERR_APPLICATION_VERIFICATION413 414 415# Taken from https://golang.org/src/crypto/x509/root_linux.go416_CERTIFICATE_FILE_LOCATIONS = [417 "/etc/ssl/certs/ca-certificates.crt", # Debian/Ubuntu/Gentoo etc.418 "/etc/pki/tls/certs/ca-bundle.crt", # Fedora/RHEL 6419 "/etc/ssl/ca-bundle.pem", # OpenSUSE420 "/etc/pki/tls/cacert.pem", # OpenELEC421 "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", # CentOS/RHEL 7422]423 424_CERTIFICATE_PATH_LOCATIONS = [425 "/etc/ssl/certs", # SLES10/SLES11426]427 428# These values are compared to output from cffi's ffi.string so they must be429# byte strings.430_CRYPTOGRAPHY_MANYLINUX_CA_DIR = b"/opt/pyca/cryptography/openssl/certs"431_CRYPTOGRAPHY_MANYLINUX_CA_FILE = b"/opt/pyca/cryptography/openssl/cert.pem"432 433 434class Error(Exception):435 """436 An error occurred in an `OpenSSL.SSL` API.437 """438 439 440_raise_current_error = partial(_exception_from_error_queue, Error)441_openssl_assert = _make_assert(Error)442 443 444class WantReadError(Error):445 pass446 447 448class WantWriteError(Error):449 pass450 451 452class WantX509LookupError(Error):453 pass454 455 456class ZeroReturnError(Error):457 pass458 459 460class SysCallError(Error):461 pass462 463 464class _CallbackExceptionHelper:465 """466 A base class for wrapper classes that allow for intelligent exception467 handling in OpenSSL callbacks.468 469 :ivar list _problems: Any exceptions that occurred while executing in a470 context where they could not be raised in the normal way. Typically471 this is because OpenSSL has called into some Python code and requires a472 return value. The exceptions are saved to be raised later when it is473 possible to do so.474 """475 476 def __init__(self) -> None:477 self._problems: list[Exception] = []478 479 def raise_if_problem(self) -> None:480 """481 Raise an exception from the OpenSSL error queue or that was previously482 captured whe running a callback.483 """484 if self._problems:485 try:486 _raise_current_error()487 except Error:488 pass489 raise self._problems.pop(0)490 491 492class _VerifyHelper(_CallbackExceptionHelper):493 """494 Wrap a callback such that it can be used as a certificate verification495 callback.496 """497 498 def __init__(self, callback: _VerifyCallback) -> None:499 _CallbackExceptionHelper.__init__(self)500 501 @wraps(callback)502 def wrapper(ok, store_ctx): # type: ignore[no-untyped-def]503 x509 = _lib.X509_STORE_CTX_get_current_cert(store_ctx)504 _lib.X509_up_ref(x509)505 cert = X509._from_raw_x509_ptr(x509)506 error_number = _lib.X509_STORE_CTX_get_error(store_ctx)507 error_depth = _lib.X509_STORE_CTX_get_error_depth(store_ctx)508 509 index = _lib.SSL_get_ex_data_X509_STORE_CTX_idx()510 ssl = _lib.X509_STORE_CTX_get_ex_data(store_ctx, index)511 connection = Connection._reverse_mapping[ssl]512 513 try:514 result = callback(515 connection, cert, error_number, error_depth, ok516 )517 except Exception as e:518 self._problems.append(e)519 return 0520 else:521 if result:522 _lib.X509_STORE_CTX_set_error(store_ctx, _lib.X509_V_OK)523 return 1524 else:525 return 0526 527 self.callback = _ffi.callback(528 "int (*)(int, X509_STORE_CTX *)", wrapper529 )530 531 532class _ALPNSelectHelper(_CallbackExceptionHelper):533 """534 Wrap a callback such that it can be used as an ALPN selection callback.535 """536 537 def __init__(self, callback: _ALPNSelectCallback) -> None:538 _CallbackExceptionHelper.__init__(self)539 540 @wraps(callback)541 def wrapper(ssl, out, outlen, in_, inlen, arg): # type: ignore[no-untyped-def]542 try:543 conn = Connection._reverse_mapping[ssl]544 545 # The string passed to us is made up of multiple546 # length-prefixed bytestrings. We need to split that into a547 # list.548 instr = _ffi.buffer(in_, inlen)[:]549 protolist = []550 while instr:551 encoded_len = instr[0]552 proto = instr[1 : encoded_len + 1]553 protolist.append(proto)554 instr = instr[encoded_len + 1 :]555 556 # Call the callback557 outbytes = callback(conn, protolist)558 any_accepted = True559 if outbytes is NO_OVERLAPPING_PROTOCOLS:560 outbytes = b""561 any_accepted = False562 elif not isinstance(outbytes, bytes):563 raise TypeError(564 "ALPN callback must return a bytestring or the "565 "special NO_OVERLAPPING_PROTOCOLS sentinel value."566 )567 568 # Save our callback arguments on the connection object to make569 # sure that they don't get freed before OpenSSL can use them.570 # Then, return them in the appropriate output parameters.571 conn._alpn_select_callback_args = [572 _ffi.new("unsigned char *", len(outbytes)),573 _ffi.new("unsigned char[]", outbytes),574 ]575 outlen[0] = conn._alpn_select_callback_args[0][0]576 out[0] = conn._alpn_select_callback_args[1]577 if not any_accepted:578 return _lib.SSL_TLSEXT_ERR_NOACK579 return _lib.SSL_TLSEXT_ERR_OK580 except Exception as e:581 self._problems.append(e)582 return _lib.SSL_TLSEXT_ERR_ALERT_FATAL583 584 self.callback = _ffi.callback(585 (586 "int (*)(SSL *, unsigned char **, unsigned char *, "587 "const unsigned char *, unsigned int, void *)"588 ),589 wrapper,590 )591 592 593class _OCSPServerCallbackHelper(_CallbackExceptionHelper):594 """595 Wrap a callback such that it can be used as an OCSP callback for the server596 side.597 598 Annoyingly, OpenSSL defines one OCSP callback but uses it in two different599 ways. For servers, that callback is expected to retrieve some OCSP data and600 hand it to OpenSSL, and may return only SSL_TLSEXT_ERR_OK,601 SSL_TLSEXT_ERR_FATAL, and SSL_TLSEXT_ERR_NOACK. For clients, that callback602 is expected to check the OCSP data, and returns a negative value on error,603 0 if the response is not acceptable, or positive if it is. These are604 mutually exclusive return code behaviours, and they mean that we need two605 helpers so that we always return an appropriate error code if the user's606 code throws an exception.607 608 Given that we have to have two helpers anyway, these helpers are a bit more609 helpery than most: specifically, they hide a few more of the OpenSSL610 functions so that the user has an easier time writing these callbacks.611 612 This helper implements the server side.613 """614 615 def __init__(self, callback: _OCSPServerCallback[Any]) -> None:616 _CallbackExceptionHelper.__init__(self)617 618 @wraps(callback)619 def wrapper(ssl, cdata): # type: ignore[no-untyped-def]620 try:621 conn = Connection._reverse_mapping[ssl]622 623 # Extract the data if any was provided.624 if cdata != _ffi.NULL:625 data = _ffi.from_handle(cdata)626 else:627 data = None628 629 # Call the callback.630 ocsp_data = callback(conn, data)631 632 if not isinstance(ocsp_data, bytes):633 raise TypeError("OCSP callback must return a bytestring.")634 635 # If the OCSP data was provided, we will pass it to OpenSSL.636 # However, we have an early exit here: if no OCSP data was637 # provided we will just exit out and tell OpenSSL that there638 # is nothing to do.639 if not ocsp_data:640 return 3 # SSL_TLSEXT_ERR_NOACK641 642 # OpenSSL takes ownership of this data and expects it to have643 # been allocated by OPENSSL_malloc.644 ocsp_data_length = len(ocsp_data)645 data_ptr = _lib.OPENSSL_malloc(ocsp_data_length)646 _ffi.buffer(data_ptr, ocsp_data_length)[:] = ocsp_data647 648 _lib.SSL_set_tlsext_status_ocsp_resp(649 ssl, data_ptr, ocsp_data_length650 )651 652 return 0653 except Exception as e:654 self._problems.append(e)655 return 2 # SSL_TLSEXT_ERR_ALERT_FATAL656 657 self.callback = _ffi.callback("int (*)(SSL *, void *)", wrapper)658 659 660class _OCSPClientCallbackHelper(_CallbackExceptionHelper):661 """662 Wrap a callback such that it can be used as an OCSP callback for the client663 side.664 665 Annoyingly, OpenSSL defines one OCSP callback but uses it in two different666 ways. For servers, that callback is expected to retrieve some OCSP data and667 hand it to OpenSSL, and may return only SSL_TLSEXT_ERR_OK,668 SSL_TLSEXT_ERR_FATAL, and SSL_TLSEXT_ERR_NOACK. For clients, that callback669 is expected to check the OCSP data, and returns a negative value on error,670 0 if the response is not acceptable, or positive if it is. These are671 mutually exclusive return code behaviours, and they mean that we need two672 helpers so that we always return an appropriate error code if the user's673 code throws an exception.674 675 Given that we have to have two helpers anyway, these helpers are a bit more676 helpery than most: specifically, they hide a few more of the OpenSSL677 functions so that the user has an easier time writing these callbacks.678 679 This helper implements the client side.680 """681 682 def __init__(self, callback: _OCSPClientCallback[Any]) -> None:683 _CallbackExceptionHelper.__init__(self)684 685 @wraps(callback)686 def wrapper(ssl, cdata): # type: ignore[no-untyped-def]687 try:688 conn = Connection._reverse_mapping[ssl]689 690 # Extract the data if any was provided.691 if cdata != _ffi.NULL:692 data = _ffi.from_handle(cdata)693 else:694 data = None695 696 # Get the OCSP data.697 ocsp_ptr = _ffi.new("unsigned char **")698 ocsp_len = _lib.SSL_get_tlsext_status_ocsp_resp(ssl, ocsp_ptr)699 if ocsp_len < 0:700 # No OCSP data.701 ocsp_data = b""702 else:703 # Copy the OCSP data, then pass it to the callback.704 ocsp_data = _ffi.buffer(ocsp_ptr[0], ocsp_len)[:]705 706 valid = callback(conn, ocsp_data, data)707 708 # Return 1 on success or 0 on error.709 return int(bool(valid))710 711 except Exception as e:712 self._problems.append(e)713 # Return negative value if an exception is hit.714 return -1715 716 self.callback = _ffi.callback("int (*)(SSL *, void *)", wrapper)717 718 719class _CookieGenerateCallbackHelper(_CallbackExceptionHelper):720 def __init__(self, callback: _CookieGenerateCallback) -> None:721 _CallbackExceptionHelper.__init__(self)722 723 max_cookie_len = getattr(_lib, "DTLS1_COOKIE_LENGTH", 255)724 725 @wraps(callback)726 def wrapper(ssl, out, outlen): # type: ignore[no-untyped-def]727 try:728 conn = Connection._reverse_mapping[ssl]729 cookie = callback(conn)730 if len(cookie) > max_cookie_len:731 raise ValueError(732 f"Cookie too long (got {len(cookie)} bytes, "733 f"max {max_cookie_len})"734 )735 out[0 : len(cookie)] = cookie736 outlen[0] = len(cookie)737 return 1738 except Exception as e:739 self._problems.append(e)740 # "a zero return value can be used to abort the handshake"741 return 0742 743 self.callback = _ffi.callback(744 "int (*)(SSL *, unsigned char *, unsigned int *)",745 wrapper,746 )747 748 749class _CookieVerifyCallbackHelper(_CallbackExceptionHelper):750 def __init__(self, callback: _CookieVerifyCallback) -> None:751 _CallbackExceptionHelper.__init__(self)752 753 @wraps(callback)754 def wrapper(ssl, c_cookie, cookie_len): # type: ignore[no-untyped-def]755 try:756 conn = Connection._reverse_mapping[ssl]757 return callback(conn, bytes(c_cookie[0:cookie_len]))758 except Exception as e:759 self._problems.append(e)760 return 0761 762 self.callback = _ffi.callback(763 "int (*)(SSL *, unsigned char *, unsigned int)",764 wrapper,765 )766 767 768def _asFileDescriptor(obj: Any) -> int:769 fd = None770 if not isinstance(obj, int):771 meth = getattr(obj, "fileno", None)772 if meth is not None:773 obj = meth()774 775 if isinstance(obj, int):776 fd = obj777 778 if not isinstance(fd, int):779 raise TypeError("argument must be an int, or have a fileno() method.")780 elif fd < 0:781 raise ValueError(782 f"file descriptor cannot be a negative integer ({fd:i})"783 )784 785 return fd786 787 788def OpenSSL_version(type: int) -> bytes:789 """790 Return a string describing the version of OpenSSL in use.791 792 :param type: One of the :const:`OPENSSL_` constants defined in this module.793 """794 return _ffi.string(_lib.OpenSSL_version(type))795 796 797SSLeay_version = OpenSSL_version798 799 800def _make_requires(flag: int, error: str) -> Callable[[_T], _T]:801 """802 Builds a decorator that ensures that functions that rely on OpenSSL803 functions that are not present in this build raise NotImplementedError,804 rather than AttributeError coming out of cryptography.805 806 :param flag: A cryptography flag that guards the functions, e.g.807 ``Cryptography_HAS_NEXTPROTONEG``.808 :param error: The string to be used in the exception if the flag is false.809 """810 811 def _requires_decorator(func): # type: ignore[no-untyped-def]812 if not flag:813 814 @wraps(func)815 def explode(*args, **kwargs): # type: ignore[no-untyped-def]816 raise NotImplementedError(error)817 818 return explode819 else:820 return func821 822 return _requires_decorator823 824 825_requires_keylog = _make_requires(826 getattr(_lib, "Cryptography_HAS_KEYLOG", 0), "Key logging not available"827)828 829_requires_ssl_get0_group_name = _make_requires(830 getattr(_lib, "Cryptography_HAS_SSL_GET0_GROUP_NAME", 0),831 "Getting group name is not supported by the linked OpenSSL version",832)833 834_requires_ssl_cookie = _make_requires(835 getattr(_lib, "Cryptography_HAS_SSL_COOKIE", 0),836 "DTLS cookie support is not available",837)838 839 840class Session:841 """842 A class representing an SSL session. A session defines certain connection843 parameters which may be re-used to speed up the setup of subsequent844 connections.845 846 .. versionadded:: 0.14847 """848 849 _session: Any850 851 852F = TypeVar("F", bound=Callable[..., Any])853 854 855def _require_not_used(f: F) -> F:856 @wraps(f)857 def inner(self: Context, *args: Any, **kwargs: Any) -> Any:858 if self._used:859 raise ValueError(860 "Context has already been used to create a Connection, it "861 "cannot be mutated again"862 )863 return f(self, *args, **kwargs)864 865 return typing.cast(F, inner)866 867 868class Context:869 """870 :class:`OpenSSL.SSL.Context` instances define the parameters for setting871 up new SSL connections.872 873 :param method: One of TLS_METHOD, TLS_CLIENT_METHOD, TLS_SERVER_METHOD,874 DTLS_METHOD, DTLS_CLIENT_METHOD, or DTLS_SERVER_METHOD.875 SSLv23_METHOD, TLSv1_METHOD, etc. are deprecated and should876 not be used.877 """878 879 _methods: typing.ClassVar[880 dict[int, tuple[Callable[[], Any], int | None]]881 ] = {882 SSLv23_METHOD: (_lib.TLS_method, None),883 TLSv1_METHOD: (_lib.TLS_method, TLS1_VERSION),884 TLSv1_1_METHOD: (_lib.TLS_method, TLS1_1_VERSION),885 TLSv1_2_METHOD: (_lib.TLS_method, TLS1_2_VERSION),886 TLS_METHOD: (_lib.TLS_method, None),887 TLS_SERVER_METHOD: (_lib.TLS_server_method, None),888 TLS_CLIENT_METHOD: (_lib.TLS_client_method, None),889 DTLS_METHOD: (_lib.DTLS_method, None),890 DTLS_SERVER_METHOD: (_lib.DTLS_server_method, None),891 DTLS_CLIENT_METHOD: (_lib.DTLS_client_method, None),892 }893 894 def __init__(self, method: int) -> None:895 if not isinstance(method, int):896 raise TypeError("method must be an integer")897 898 try:899 method_func, version = self._methods[method]900 except KeyError:901 raise ValueError("No such protocol")902 903 method_obj = method_func()904 _openssl_assert(method_obj != _ffi.NULL)905 906 context = _lib.SSL_CTX_new(method_obj)907 _openssl_assert(context != _ffi.NULL)908 context = _ffi.gc(context, _lib.SSL_CTX_free)909 910 self._context = context911 self._used = False912 self._passphrase_helper: _PassphraseHelper | None = None913 self._passphrase_callback: _PassphraseCallback[Any] | None = None914 self._passphrase_userdata: Any | None = None915 self._verify_helper: _VerifyHelper | None = None916 self._verify_callback: _VerifyCallback | None = None917 self._info_callback = None918 self._keylog_callback = None919 self._tlsext_servername_callback = None920 self._app_data = None921 self._alpn_select_helper: _ALPNSelectHelper | None = None922 self._alpn_select_callback: _ALPNSelectCallback | None = None923 self._ocsp_helper: (924 _OCSPClientCallbackHelper | _OCSPServerCallbackHelper | None925 ) = None926 self._ocsp_callback: (927 _OCSPClientCallback[Any] | _OCSPServerCallback[Any] | None928 ) = None929 self._ocsp_data: Any | None = None930 self._cookie_generate_helper: _CookieGenerateCallbackHelper | None = (931 None932 )933 self._cookie_verify_helper: _CookieVerifyCallbackHelper | None = None934 935 self.set_mode(936 _lib.SSL_MODE_ENABLE_PARTIAL_WRITE937 | _lib.SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER938 )939 if version is not None:940 self.set_min_proto_version(version)941 self.set_max_proto_version(version)942 943 @_require_not_used944 def set_min_proto_version(self, version: int) -> None:945 """946 Set the minimum supported protocol version. Setting the minimum947 version to 0 will enable protocol versions down to the lowest version948 supported by the library.949 950 If the underlying OpenSSL build is missing support for the selected951 version, this method will raise an exception.952 """953 _openssl_assert(954 _lib.SSL_CTX_set_min_proto_version(self._context, version) == 1955 )956 957 @_require_not_used958 def set_max_proto_version(self, version: int) -> None:959 """960 Set the maximum supported protocol version. Setting the maximum961 version to 0 will enable protocol versions up to the highest version962 supported by the library.963 964 If the underlying OpenSSL build is missing support for the selected965 version, this method will raise an exception.966 """967 _openssl_assert(968 _lib.SSL_CTX_set_max_proto_version(self._context, version) == 1969 )970 971 @_require_not_used972 def load_verify_locations(973 self,974 cafile: _StrOrBytesPath | None,975 capath: _StrOrBytesPath | None = None,976 ) -> None:977 """978 Let SSL know where we can find trusted certificates for the certificate979 chain. Note that the certificates have to be in PEM format.980 981 If capath is passed, it must be a directory prepared using the982 ``c_rehash`` tool included with OpenSSL. Either, but not both, of983 *pemfile* or *capath* may be :data:`None`.984 985 :param cafile: In which file we can find the certificates (``bytes`` or986 ``str``).987 :param capath: In which directory we can find the certificates988 (``bytes`` or ``str``).989 990 :return: None991 """992 if cafile is None:993 cafile = _ffi.NULL994 else:995 cafile = _path_bytes(cafile)996 997 if capath is None:998 capath = _ffi.NULL999 else:1000 capath = _path_bytes(capath)1001 1002 load_result = _lib.SSL_CTX_load_verify_locations(1003 self._context, cafile, capath1004 )1005 if not load_result:1006 _raise_current_error()1007 1008 def _wrap_callback(1009 self, callback: _PassphraseCallback[_T]1010 ) -> _PassphraseHelper:1011 @wraps(callback)1012 def wrapper(size: int, verify: bool, userdata: Any) -> bytes:1013 return callback(size, verify, self._passphrase_userdata)1014 1015 return _PassphraseHelper(1016 FILETYPE_PEM, wrapper, more_args=True, truncate=True1017 )1018 1019 @_require_not_used1020 def set_passwd_cb(1021 self,1022 callback: _PassphraseCallback[_T],1023 userdata: _T | None = None,1024 ) -> None:1025 """1026 Set the passphrase callback. This function will be called1027 when a private key with a passphrase is loaded.1028 1029 :param callback: The Python callback to use. This must accept three1030 positional arguments. First, an integer giving the maximum length1031 of the passphrase it may return. If the returned passphrase is1032 longer than this, it will be truncated. Second, a boolean value1033 which will be true if the user should be prompted for the1034 passphrase twice and the callback should verify that the two values1035 supplied are equal. Third, the value given as the *userdata*1036 parameter to :meth:`set_passwd_cb`. The *callback* must return1037 a byte string. If an error occurs, *callback* should return a false1038 value (e.g. an empty string).1039 :param userdata: (optional) A Python object which will be given as1040 argument to the callback1041 :return: None1042 """1043 if not callable(callback):1044 raise TypeError("callback must be callable")1045 1046 self._passphrase_helper = self._wrap_callback(callback)1047 self._passphrase_callback = self._passphrase_helper.callback1048 _lib.SSL_CTX_set_default_passwd_cb(1049 self._context, self._passphrase_callback1050 )1051 self._passphrase_userdata = userdata1052 1053 @_require_not_used1054 def set_default_verify_paths(self) -> None:1055 """1056 Specify that the platform provided CA certificates are to be used for1057 verification purposes. This method has some caveats related to the1058 binary wheels that cryptography (pyOpenSSL's primary dependency) ships:1059 1060 * macOS will only load certificates using this method if the user has1061 the ``openssl@3`` `Homebrew <https://brew.sh>`_ formula installed1062 in the default location.1063 * Windows will not work.1064 * manylinux cryptography wheels will work on most common Linux1065 distributions in pyOpenSSL 17.1.0 and above. pyOpenSSL detects the1066 manylinux wheel and attempts to load roots via a fallback path.1067 1068 :return: None1069 """1070 # SSL_CTX_set_default_verify_paths will attempt to load certs from1071 # both a cafile and capath that are set at compile time. However,1072 # it will first check environment variables and, if present, load1073 # those paths instead1074 set_result = _lib.SSL_CTX_set_default_verify_paths(self._context)1075 _openssl_assert(set_result == 1)1076 # After attempting to set default_verify_paths we need to know whether1077 # to go down the fallback path.1078 # First we'll check to see if any env vars have been set. If so,1079 # we won't try to do anything else because the user has set the path1080 # themselves.1081 if not self._check_env_vars_set("SSL_CERT_DIR", "SSL_CERT_FILE"):1082 default_dir = _ffi.string(_lib.X509_get_default_cert_dir())1083 default_file = _ffi.string(_lib.X509_get_default_cert_file())1084 # Now we check to see if the default_dir and default_file are set1085 # to the exact values we use in our manylinux builds. If they are1086 # then we know to load the fallbacks1087 if (1088 default_dir == _CRYPTOGRAPHY_MANYLINUX_CA_DIR1089 and default_file == _CRYPTOGRAPHY_MANYLINUX_CA_FILE1090 ):1091 # This is manylinux, let's load our fallback paths1092 self._fallback_default_verify_paths(1093 _CERTIFICATE_FILE_LOCATIONS, _CERTIFICATE_PATH_LOCATIONS1094 )1095 1096 def _check_env_vars_set(self, dir_env_var: str, file_env_var: str) -> bool:1097 """1098 Check to see if the default cert dir/file environment vars are present.1099 1100 :return: bool1101 """1102 return (1103 os.environ.get(file_env_var) is not None1104 or os.environ.get(dir_env_var) is not None1105 )1106 1107 def _fallback_default_verify_paths(1108 self, file_path: list[str], dir_path: list[str]1109 ) -> None:1110 """1111 Default verify paths are based on the compiled version of OpenSSL.1112 However, when pyca/cryptography is compiled as a manylinux wheel1113 that compiled location can potentially be wrong. So, like Go, we1114 will try a predefined set of paths and attempt to load roots1115 from there.1116 1117 :return: None1118 """1119 for cafile in file_path:1120 if os.path.isfile(cafile):1121 self.load_verify_locations(cafile)1122 break1123 1124 for capath in dir_path:1125 if os.path.isdir(capath):1126 self.load_verify_locations(None, capath)1127 break1128 1129 @_require_not_used1130 def use_certificate_chain_file(self, certfile: _StrOrBytesPath) -> None:1131 """1132 Load a certificate chain from a file.1133 1134 :param certfile: The name of the certificate chain file (``bytes`` or1135 ``str``). Must be PEM encoded.1136 1137 :return: None1138 """1139 certfile = _path_bytes(certfile)1140 1141 result = _lib.SSL_CTX_use_certificate_chain_file(1142 self._context, certfile1143 )1144 if not result:1145 _raise_current_error()1146 1147 @_require_not_used1148 def use_certificate_file(1149 self, certfile: _StrOrBytesPath, filetype: int = FILETYPE_PEM1150 ) -> None:1151 """1152 Load a certificate from a file1153 1154 :param certfile: The name of the certificate file (``bytes`` or1155 ``str``).1156 :param filetype: (optional) The encoding of the file, which is either1157 :const:`FILETYPE_PEM` or :const:`FILETYPE_ASN1`. The default is1158 :const:`FILETYPE_PEM`.1159 1160 :return: None1161 """1162 certfile = _path_bytes(certfile)1163 if not isinstance(filetype, int):1164 raise TypeError("filetype must be an integer")1165 1166 use_result = _lib.SSL_CTX_use_certificate_file(1167 self._context, certfile, filetype1168 )1169 if not use_result:1170 _raise_current_error()1171 1172 @_require_not_used1173 def use_certificate(self, cert: X509 | x509.Certificate) -> None:1174 """1175 Load a certificate from a X509 object1176 1177 :param cert: The X509 object1178 :return: None1179 """1180 # Mirrored at Connection.use_certificate1181 if not isinstance(cert, X509):1182 cert = X509.from_cryptography(cert)1183 else:1184 warnings.warn(1185 (1186 "Passing pyOpenSSL X509 objects is deprecated. You "1187 "should use a cryptography.x509.Certificate instead."1188 ),1189 DeprecationWarning,1190 stacklevel=2,1191 )1192 1193 use_result = _lib.SSL_CTX_use_certificate(self._context, cert._x509)1194 if not use_result:1195 _raise_current_error()1196 1197 @_require_not_used1198 def add_extra_chain_cert(self, certobj: X509 | x509.Certificate) -> None:1199 """1200 Add certificate to chain