45
45
"TLS_METHOD" ,
46
46
"TLS_SERVER_METHOD" ,
47
47
"TLS_CLIENT_METHOD" ,
48
+ "DTLS_METHOD" ,
49
+ "DTLS_SERVER_METHOD" ,
50
+ "DTLS_CLIENT_METHOD" ,
48
51
"SSL3_VERSION" ,
49
52
"TLS1_VERSION" ,
50
53
"TLS1_1_VERSION" ,
80
83
"OP_NO_QUERY_MTU" ,
81
84
"OP_COOKIE_EXCHANGE" ,
82
85
"OP_NO_TICKET" ,
86
+ "OP_NO_RENEGOTIATION" ,
83
87
"OP_ALL" ,
84
88
"VERIFY_PEER" ,
85
89
"VERIFY_FAIL_IF_NO_PEER_CERT" ,
@@ -149,6 +153,9 @@ class _buffer(object):
149
153
TLS_METHOD = 7
150
154
TLS_SERVER_METHOD = 8
151
155
TLS_CLIENT_METHOD = 9
156
+ DTLS_METHOD = 10
157
+ DTLS_SERVER_METHOD = 11
158
+ DTLS_CLIENT_METHOD = 12
152
159
153
160
try :
154
161
SSL3_VERSION = _lib .SSL3_VERSION
@@ -206,6 +213,11 @@ class _buffer(object):
206
213
OP_COOKIE_EXCHANGE = _lib .SSL_OP_COOKIE_EXCHANGE
207
214
OP_NO_TICKET = _lib .SSL_OP_NO_TICKET
208
215
216
+ try :
217
+ OP_NO_RENEGOTIATION = _lib .SSL_OP_NO_RENEGOTIATION
218
+ except AttributeError :
219
+ pass
220
+
209
221
OP_ALL = _lib .SSL_OP_ALL
210
222
211
223
VERIFY_PEER = _lib .SSL_VERIFY_PEER
@@ -547,6 +559,48 @@ def wrapper(ssl, cdata):
547
559
self .callback = _ffi .callback ("int (*)(SSL *, void *)" , wrapper )
548
560
549
561
562
+ class _CookieGenerateCallbackHelper (_CallbackExceptionHelper ):
563
+ def __init__ (self , callback ):
564
+ _CallbackExceptionHelper .__init__ (self )
565
+
566
+ @wraps (callback )
567
+ def wrapper (ssl , out , outlen ):
568
+ try :
569
+ conn = Connection ._reverse_mapping [ssl ]
570
+ cookie = callback (conn )
571
+ out [0 : len (cookie )] = cookie
572
+ outlen [0 ] = len (cookie )
573
+ return 1
574
+ except Exception as e :
575
+ self ._problems .append (e )
576
+ # "a zero return value can be used to abort the handshake"
577
+ return 0
578
+
579
+ self .callback = _ffi .callback (
580
+ "int (*)(SSL *, unsigned char *, unsigned int *)" ,
581
+ wrapper ,
582
+ )
583
+
584
+
585
+ class _CookieVerifyCallbackHelper (_CallbackExceptionHelper ):
586
+ def __init__ (self , callback ):
587
+ _CallbackExceptionHelper .__init__ (self )
588
+
589
+ @wraps (callback )
590
+ def wrapper (ssl , c_cookie , cookie_len ):
591
+ try :
592
+ conn = Connection ._reverse_mapping [ssl ]
593
+ return callback (conn , bytes (c_cookie [0 :cookie_len ]))
594
+ except Exception as e :
595
+ self ._problems .append (e )
596
+ return 0
597
+
598
+ self .callback = _ffi .callback (
599
+ "int (*)(SSL *, unsigned char *, unsigned int)" ,
600
+ wrapper ,
601
+ )
602
+
603
+
550
604
def _asFileDescriptor (obj ):
551
605
fd = None
552
606
if not isinstance (obj , int ):
@@ -628,7 +682,8 @@ class Context(object):
628
682
:class:`OpenSSL.SSL.Context` instances define the parameters for setting
629
683
up new SSL connections.
630
684
631
- :param method: One of TLS_METHOD, TLS_CLIENT_METHOD, or TLS_SERVER_METHOD.
685
+ :param method: One of TLS_METHOD, TLS_CLIENT_METHOD, TLS_SERVER_METHOD,
686
+ DTLS_METHOD, DTLS_CLIENT_METHOD, or DTLS_SERVER_METHOD.
632
687
SSLv23_METHOD, TLSv1_METHOD, etc. are deprecated and should
633
688
not be used.
634
689
"""
@@ -643,6 +698,9 @@ class Context(object):
643
698
TLS_METHOD : "TLS_method" ,
644
699
TLS_SERVER_METHOD : "TLS_server_method" ,
645
700
TLS_CLIENT_METHOD : "TLS_client_method" ,
701
+ DTLS_METHOD : "DTLS_method" ,
702
+ DTLS_SERVER_METHOD : "DTLS_server_method" ,
703
+ DTLS_CLIENT_METHOD : "DTLS_client_method" ,
646
704
}
647
705
_methods = dict (
648
706
(identifier , getattr (_lib , name ))
@@ -687,6 +745,8 @@ def __init__(self, method):
687
745
self ._ocsp_helper = None
688
746
self ._ocsp_callback = None
689
747
self ._ocsp_data = None
748
+ self ._cookie_generate_helper = None
749
+ self ._cookie_verify_helper = None
690
750
691
751
self .set_mode (_lib .SSL_MODE_ENABLE_PARTIAL_WRITE )
692
752
@@ -1527,6 +1587,20 @@ def set_ocsp_client_callback(self, callback, data=None):
1527
1587
helper = _OCSPClientCallbackHelper (callback )
1528
1588
self ._set_ocsp_callback (helper , data )
1529
1589
1590
+ def set_cookie_generate_callback (self , callback ):
1591
+ self ._cookie_generate_helper = _CookieGenerateCallbackHelper (callback )
1592
+ _lib .SSL_CTX_set_cookie_generate_cb (
1593
+ self ._context ,
1594
+ self ._cookie_generate_helper .callback ,
1595
+ )
1596
+
1597
+ def set_cookie_verify_callback (self , callback ):
1598
+ self ._cookie_verify_helper = _CookieVerifyCallbackHelper (callback )
1599
+ _lib .SSL_CTX_set_cookie_verify_cb (
1600
+ self ._context ,
1601
+ self ._cookie_verify_helper .callback ,
1602
+ )
1603
+
1530
1604
1531
1605
class Connection (object ):
1532
1606
_reverse_mapping = WeakValueDictionary ()
@@ -1564,6 +1638,10 @@ def __init__(self, context, socket=None):
1564
1638
self ._verify_helper = context ._verify_helper
1565
1639
self ._verify_callback = context ._verify_callback
1566
1640
1641
+ # And likewise for the cookie callbacks
1642
+ self ._cookie_generate_helper = context ._cookie_generate_helper
1643
+ self ._cookie_verify_helper = context ._cookie_verify_helper
1644
+
1567
1645
self ._reverse_mapping [self ._ssl ] = self
1568
1646
1569
1647
if socket is None :
@@ -1672,6 +1750,35 @@ def get_servername(self):
1672
1750
1673
1751
return _ffi .string (name )
1674
1752
1753
+ def set_ciphertext_mtu (self , mtu ):
1754
+ """
1755
+ For DTLS, set the maximum UDP payload size (*not* including IP/UDP
1756
+ overhead).
1757
+
1758
+ Note that you might have to set :data:`OP_NO_QUERY_MTU` to prevent
1759
+ OpenSSL from spontaneously clearing this.
1760
+
1761
+ :param mtu: An integer giving the maximum transmission unit.
1762
+
1763
+ .. versionadded:: 21.1
1764
+ """
1765
+ _lib .SSL_set_mtu (self ._ssl , mtu )
1766
+
1767
+ def get_cleartext_mtu (self ):
1768
+ """
1769
+ For DTLS, get the maximum size of unencrypted data you can pass to
1770
+ :meth:`write` without exceeding the MTU (as passed to
1771
+ :meth:`set_ciphertext_mtu`).
1772
+
1773
+ :return: The effective MTU as an integer.
1774
+
1775
+ .. versionadded:: 21.1
1776
+ """
1777
+
1778
+ if not hasattr (_lib , "DTLS_get_data_mtu" ):
1779
+ raise NotImplementedError ("requires OpenSSL 1.1.1 or better" )
1780
+ return _lib .DTLS_get_data_mtu (self ._ssl )
1781
+
1675
1782
def set_tlsext_host_name (self , name ):
1676
1783
"""
1677
1784
Set the value of the servername extension to send in the client hello.
@@ -1957,6 +2064,32 @@ def accept(self):
1957
2064
conn .set_accept_state ()
1958
2065
return (conn , addr )
1959
2066
2067
+ def DTLSv1_listen (self ):
2068
+ """
2069
+ Call the OpenSSL function DTLSv1_listen on this connection. See the
2070
+ OpenSSL manual for more details.
2071
+
2072
+ :return: None
2073
+ """
2074
+ # Possible future extension: return the BIO_ADDR in some form.
2075
+ bio_addr = _lib .BIO_ADDR_new ()
2076
+ try :
2077
+ result = _lib .DTLSv1_listen (self ._ssl , bio_addr )
2078
+ finally :
2079
+ _lib .BIO_ADDR_free (bio_addr )
2080
+ # DTLSv1_listen is weird. A zero return value means 'didn't find a
2081
+ # ClientHello with valid cookie, but keep trying'. So basically
2082
+ # WantReadError. But it doesn't work correctly with _raise_ssl_error.
2083
+ # So we raise it manually instead.
2084
+ if self ._cookie_generate_helper is not None :
2085
+ self ._cookie_generate_helper .raise_if_problem ()
2086
+ if self ._cookie_verify_helper is not None :
2087
+ self ._cookie_verify_helper .raise_if_problem ()
2088
+ if result == 0 :
2089
+ raise WantReadError ()
2090
+ if result < 0 :
2091
+ self ._raise_ssl_error (self ._ssl , result )
2092
+
1960
2093
def bio_shutdown (self ):
1961
2094
"""
1962
2095
If the Connection was created with a memory BIO, this method can be
0 commit comments