@@ -827,6 +827,26 @@ class Session:
827827 _session : Any
828828
829829
830+ F = TypeVar ("F" , bound = Callable [..., Any ])
831+
832+
833+ def _require_not_used (f : F ) -> F :
834+ @wraps (f )
835+ def inner (self : Context , * args : Any , ** kwargs : Any ) -> Any :
836+ if self ._used :
837+ warnings .warn (
838+ (
839+ "Attempting to mutate a Context after a Connection was "
840+ "created. In the future, this will raise an exception"
841+ ),
842+ DeprecationWarning ,
843+ stacklevel = 2 ,
844+ )
845+ return f (self , * args , ** kwargs )
846+
847+ return typing .cast (F , inner )
848+
849+
830850class Context :
831851 """
832852 :class:`OpenSSL.SSL.Context` instances define the parameters for setting
@@ -870,6 +890,7 @@ def __init__(self, method: int) -> None:
870890 context = _ffi .gc (context , _lib .SSL_CTX_free )
871891
872892 self ._context = context
893+ self ._used = False
873894 self ._passphrase_helper : _PassphraseHelper | None = None
874895 self ._passphrase_callback : _PassphraseCallback [Any ] | None = None
875896 self ._passphrase_userdata : Any | None = None
@@ -898,6 +919,7 @@ def __init__(self, method: int) -> None:
898919 self .set_min_proto_version (version )
899920 self .set_max_proto_version (version )
900921
922+ @_require_not_used
901923 def set_min_proto_version (self , version : int ) -> None :
902924 """
903925 Set the minimum supported protocol version. Setting the minimum
@@ -911,6 +933,7 @@ def set_min_proto_version(self, version: int) -> None:
911933 _lib .SSL_CTX_set_min_proto_version (self ._context , version ) == 1
912934 )
913935
936+ @_require_not_used
914937 def set_max_proto_version (self , version : int ) -> None :
915938 """
916939 Set the maximum supported protocol version. Setting the maximum
@@ -924,6 +947,7 @@ def set_max_proto_version(self, version: int) -> None:
924947 _lib .SSL_CTX_set_max_proto_version (self ._context , version ) == 1
925948 )
926949
950+ @_require_not_used
927951 def load_verify_locations (
928952 self ,
929953 cafile : _StrOrBytesPath | None ,
@@ -971,6 +995,7 @@ def wrapper(size: int, verify: bool, userdata: Any) -> bytes:
971995 FILETYPE_PEM , wrapper , more_args = True , truncate = True
972996 )
973997
998+ @_require_not_used
974999 def set_passwd_cb (
9751000 self ,
9761001 callback : _PassphraseCallback [_T ],
@@ -1004,6 +1029,7 @@ def set_passwd_cb(
10041029 )
10051030 self ._passphrase_userdata = userdata
10061031
1032+ @_require_not_used
10071033 def set_default_verify_paths (self ) -> None :
10081034 """
10091035 Specify that the platform provided CA certificates are to be used for
@@ -1079,6 +1105,7 @@ def _fallback_default_verify_paths(
10791105 self .load_verify_locations (None , capath )
10801106 break
10811107
1108+ @_require_not_used
10821109 def use_certificate_chain_file (self , certfile : _StrOrBytesPath ) -> None :
10831110 """
10841111 Load a certificate chain from a file.
@@ -1096,6 +1123,7 @@ def use_certificate_chain_file(self, certfile: _StrOrBytesPath) -> None:
10961123 if not result :
10971124 _raise_current_error ()
10981125
1126+ @_require_not_used
10991127 def use_certificate_file (
11001128 self , certfile : _StrOrBytesPath , filetype : int = FILETYPE_PEM
11011129 ) -> None :
@@ -1120,6 +1148,7 @@ def use_certificate_file(
11201148 if not use_result :
11211149 _raise_current_error ()
11221150
1151+ @_require_not_used
11231152 def use_certificate (self , cert : X509 | x509 .Certificate ) -> None :
11241153 """
11251154 Load a certificate from a X509 object
@@ -1144,6 +1173,7 @@ def use_certificate(self, cert: X509 | x509.Certificate) -> None:
11441173 if not use_result :
11451174 _raise_current_error ()
11461175
1176+ @_require_not_used
11471177 def add_extra_chain_cert (self , certobj : X509 | x509 .Certificate ) -> None :
11481178 """
11491179 Add certificate to chain
@@ -1176,6 +1206,7 @@ def _raise_passphrase_exception(self) -> None:
11761206
11771207 _raise_current_error ()
11781208
1209+ @_require_not_used
11791210 def use_privatekey_file (
11801211 self , keyfile : _StrOrBytesPath , filetype : int = FILETYPE_PEM
11811212 ) -> None :
@@ -1200,6 +1231,7 @@ def use_privatekey_file(
12001231 if not use_result :
12011232 self ._raise_passphrase_exception ()
12021233
1234+ @_require_not_used
12031235 def use_privatekey (self , pkey : _PrivateKey | PKey ) -> None :
12041236 """
12051237 Load a private key from a PKey object
@@ -1234,6 +1266,7 @@ def check_privatekey(self) -> None:
12341266 if not _lib .SSL_CTX_check_private_key (self ._context ):
12351267 _raise_current_error ()
12361268
1269+ @_require_not_used
12371270 def load_client_ca (self , cafile : bytes ) -> None :
12381271 """
12391272 Load the trusted certificates that will be sent to the client. Does
@@ -1249,6 +1282,7 @@ def load_client_ca(self, cafile: bytes) -> None:
12491282 _openssl_assert (ca_list != _ffi .NULL )
12501283 _lib .SSL_CTX_set_client_CA_list (self ._context , ca_list )
12511284
1285+ @_require_not_used
12521286 def set_session_id (self , buf : bytes ) -> None :
12531287 """
12541288 Set the session id to *buf* within which a session can be reused for
@@ -1266,6 +1300,7 @@ def set_session_id(self, buf: bytes) -> None:
12661300 == 1
12671301 )
12681302
1303+ @_require_not_used
12691304 def set_session_cache_mode (self , mode : int ) -> int :
12701305 """
12711306 Set the behavior of the session cache used by all connections using
@@ -1293,6 +1328,7 @@ def get_session_cache_mode(self) -> int:
12931328 """
12941329 return _lib .SSL_CTX_get_session_cache_mode (self ._context )
12951330
1331+ @_require_not_used
12961332 def set_verify (
12971333 self , mode : int , callback : _VerifyCallback | None = None
12981334 ) -> None :
@@ -1330,6 +1366,7 @@ def set_verify(
13301366 self ._verify_callback = self ._verify_helper .callback
13311367 _lib .SSL_CTX_set_verify (self ._context , mode , self ._verify_callback )
13321368
1369+ @_require_not_used
13331370 def set_verify_depth (self , depth : int ) -> None :
13341371 """
13351372 Set the maximum depth for the certificate chain verification that shall
@@ -1361,6 +1398,7 @@ def get_verify_depth(self) -> int:
13611398 """
13621399 return _lib .SSL_CTX_get_verify_depth (self ._context )
13631400
1401+ @_require_not_used
13641402 def load_tmp_dh (self , dhfile : _StrOrBytesPath ) -> None :
13651403 """
13661404 Load parameters for Ephemeral Diffie-Hellman
@@ -1382,6 +1420,7 @@ def load_tmp_dh(self, dhfile: _StrOrBytesPath) -> None:
13821420 res = _lib .SSL_CTX_set_tmp_dh (self ._context , dh )
13831421 _openssl_assert (res == 1 )
13841422
1423+ @_require_not_used
13851424 def set_tmp_ecdh (self , curve : _EllipticCurve | ec .EllipticCurve ) -> None :
13861425 """
13871426 Select a curve to use for ECDHE key exchange.
@@ -1421,6 +1460,7 @@ def set_tmp_ecdh(self, curve: _EllipticCurve | ec.EllipticCurve) -> None:
14211460 ec = _ffi .gc (ec , _lib .EC_KEY_free )
14221461 _lib .SSL_CTX_set_tmp_ecdh (self ._context , ec )
14231462
1463+ @_require_not_used
14241464 def set_cipher_list (self , cipher_list : bytes ) -> None :
14251465 """
14261466 Set the list of ciphers to be used in this context.
@@ -1460,6 +1500,7 @@ def set_cipher_list(self, cipher_list: bytes) -> None:
14601500 ],
14611501 )
14621502
1503+ @_require_not_used
14631504 def set_client_ca_list (
14641505 self , certificate_authorities : Sequence [X509Name ]
14651506 ) -> None :
@@ -1497,6 +1538,7 @@ def set_client_ca_list(
14971538
14981539 _lib .SSL_CTX_set_client_CA_list (self ._context , name_stack )
14991540
1541+ @_require_not_used
15001542 def add_client_ca (
15011543 self , certificate_authority : X509 | x509 .Certificate
15021544 ) -> None :
@@ -1531,6 +1573,7 @@ def add_client_ca(
15311573 )
15321574 _openssl_assert (add_result == 1 )
15331575
1576+ @_require_not_used
15341577 def set_timeout (self , timeout : int ) -> None :
15351578 """
15361579 Set the timeout for newly created sessions for this Context object to
@@ -1554,6 +1597,7 @@ def get_timeout(self) -> int:
15541597 """
15551598 return _lib .SSL_CTX_get_timeout (self ._context )
15561599
1600+ @_require_not_used
15571601 def set_info_callback (
15581602 self , callback : Callable [[Connection , int , int ], None ]
15591603 ) -> None :
@@ -1579,6 +1623,7 @@ def wrapper(ssl, where, return_code): # type: ignore[no-untyped-def]
15791623 _lib .SSL_CTX_set_info_callback (self ._context , self ._info_callback )
15801624
15811625 @_requires_keylog
1626+ @_require_not_used
15821627 def set_keylog_callback (
15831628 self , callback : Callable [[Connection , bytes ], None ]
15841629 ) -> None :
@@ -1613,6 +1658,7 @@ def get_app_data(self) -> Any:
16131658 """
16141659 return self ._app_data
16151660
1661+ @_require_not_used
16161662 def set_app_data (self , data : Any ) -> None :
16171663 """
16181664 Set the application data (will be returned from get_app_data())
@@ -1639,6 +1685,7 @@ def get_cert_store(self) -> X509Store | None:
16391685 pystore ._store = store
16401686 return pystore
16411687
1688+ @_require_not_used
16421689 def set_options (self , options : int ) -> int :
16431690 """
16441691 Add options. Options set before are not cleared!
@@ -1652,6 +1699,7 @@ def set_options(self, options: int) -> int:
16521699
16531700 return _lib .SSL_CTX_set_options (self ._context , options )
16541701
1702+ @_require_not_used
16551703 def set_mode (self , mode : int ) -> int :
16561704 """
16571705 Add modes via bitmask. Modes set before are not cleared! This method
@@ -1665,6 +1713,7 @@ def set_mode(self, mode: int) -> int:
16651713
16661714 return _lib .SSL_CTX_set_mode (self ._context , mode )
16671715
1716+ @_require_not_used
16681717 def set_tlsext_servername_callback (
16691718 self , callback : Callable [[Connection ], None ]
16701719 ) -> None :
@@ -1690,6 +1739,7 @@ def wrapper(ssl, alert, arg): # type: ignore[no-untyped-def]
16901739 self ._context , self ._tlsext_servername_callback
16911740 )
16921741
1742+ @_require_not_used
16931743 def set_tlsext_use_srtp (self , profiles : bytes ) -> None :
16941744 """
16951745 Enable support for negotiating SRTP keying material.
@@ -1705,6 +1755,7 @@ def set_tlsext_use_srtp(self, profiles: bytes) -> None:
17051755 _lib .SSL_CTX_set_tlsext_use_srtp (self ._context , profiles ) == 0
17061756 )
17071757
1758+ @_require_not_used
17081759 def set_alpn_protos (self , protos : list [bytes ]) -> None :
17091760 """
17101761 Specify the protocols that the client is prepared to speak after the
@@ -1742,6 +1793,7 @@ def set_alpn_protos(self, protos: list[bytes]) -> None:
17421793 == 0
17431794 )
17441795
1796+ @_require_not_used
17451797 def set_alpn_select_callback (self , callback : _ALPNSelectCallback ) -> None :
17461798 """
17471799 Specify a callback function that will be called on the server when a
@@ -1786,6 +1838,7 @@ def _set_ocsp_callback(
17861838 rc = _lib .SSL_CTX_set_tlsext_status_arg (self ._context , self ._ocsp_data )
17871839 _openssl_assert (rc == 1 )
17881840
1841+ @_require_not_used
17891842 def set_ocsp_server_callback (
17901843 self ,
17911844 callback : _OCSPServerCallback [_T ],
@@ -1808,6 +1861,7 @@ def set_ocsp_server_callback(
18081861 helper = _OCSPServerCallbackHelper (callback )
18091862 self ._set_ocsp_callback (helper , data )
18101863
1864+ @_require_not_used
18111865 def set_ocsp_client_callback (
18121866 self ,
18131867 callback : _OCSPClientCallback [_T ],
@@ -1832,6 +1886,7 @@ def set_ocsp_client_callback(
18321886 helper = _OCSPClientCallbackHelper (callback )
18331887 self ._set_ocsp_callback (helper , data )
18341888
1889+ @_require_not_used
18351890 def set_cookie_generate_callback (
18361891 self , callback : _CookieGenerateCallback
18371892 ) -> None :
@@ -1841,6 +1896,7 @@ def set_cookie_generate_callback(
18411896 self ._cookie_generate_helper .callback ,
18421897 )
18431898
1899+ @_require_not_used
18441900 def set_cookie_verify_callback (
18451901 self , callback : _CookieVerifyCallback
18461902 ) -> None :
@@ -1869,6 +1925,8 @@ def __init__(
18691925 if not isinstance (context , Context ):
18701926 raise TypeError ("context must be a Context instance" )
18711927
1928+ context ._used = True
1929+
18721930 ssl = _lib .SSL_new (context ._context )
18731931 self ._ssl = _ffi .gc (ssl , _lib .SSL_free )
18741932 # We set SSL_MODE_AUTO_RETRY to handle situations where OpenSSL returns
@@ -2000,6 +2058,7 @@ def set_context(self, context: Context) -> None:
20002058
20012059 _lib .SSL_set_SSL_CTX (self ._ssl , context ._context )
20022060 self ._context = context
2061+ self ._context ._used = True
20032062
20042063 def get_servername (self ) -> bytes | None :
20052064 """
0 commit comments