From 141c5e8c2437a9fed95a04c81e400ef725592a17 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Sat, 24 Feb 2018 21:10:57 +0100 Subject: bpo-24334: Cleanup SSLSocket (#5252) * The SSLSocket is no longer implemented on top of SSLObject to avoid an extra level of indirection. * Owner and session are now handled in the internal constructor. * _ssl._SSLSocket now uses the same method names as SSLSocket and SSLObject. * Channel binding type check is now handled in C code. Channel binding is always available. The patch also changes the signature of SSLObject.__init__(). In my opinion it's fine. A SSLObject is not a user-constructable object. SSLContext.wrap_bio() is the only valid factory. --- Lib/ssl.py | 116 +++++++++++---------- Lib/test/test_ssl.py | 4 + .../2018-01-20-23-17-25.bpo-24334.GZuQLv.rst | 4 + Modules/_ssl.c | 90 ++++++++++------ Modules/clinic/_ssl.c.h | 86 +++++++++------ 5 files changed, 183 insertions(+), 117 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst diff --git a/Lib/ssl.py b/Lib/ssl.py index ecdbb70..94ea35e 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -166,10 +166,7 @@ import warnings socket_error = OSError # keep that public name in module namespace -if _ssl.HAS_TLS_UNIQUE: - CHANNEL_BINDING_TYPES = ['tls-unique'] -else: - CHANNEL_BINDING_TYPES = [] +CHANNEL_BINDING_TYPES = ['tls-unique'] HAS_NEVER_CHECK_COMMON_NAME = hasattr(_ssl, 'HOSTFLAG_NEVER_CHECK_SUBJECT') @@ -407,11 +404,11 @@ class SSLContext(_SSLContext): server_hostname=None, session=None): # Need to encode server_hostname here because _wrap_bio() can only # handle ASCII str. - sslobj = self._wrap_bio( + return self.sslobject_class( incoming, outgoing, server_side=server_side, - server_hostname=self._encode_hostname(server_hostname) + server_hostname=self._encode_hostname(server_hostname), + session=session, _context=self, ) - return self.sslobject_class(sslobj, session=session) def set_npn_protocols(self, npn_protocols): protos = bytearray() @@ -616,12 +613,13 @@ class SSLObject: * The ``do_handshake_on_connect`` and ``suppress_ragged_eofs`` machinery. """ - def __init__(self, sslobj, owner=None, session=None): - self._sslobj = sslobj - # Note: _sslobj takes a weak reference to owner - self._sslobj.owner = owner or self - if session is not None: - self._sslobj.session = session + def __init__(self, incoming, outgoing, server_side=False, + server_hostname=None, session=None, _context=None): + self._sslobj = _context._wrap_bio( + incoming, outgoing, server_side=server_side, + server_hostname=server_hostname, + owner=self, session=session + ) @property def context(self): @@ -684,7 +682,7 @@ class SSLObject: Return None if no certificate was provided, {} if a certificate was provided, but not validated. """ - return self._sslobj.peer_certificate(binary_form) + return self._sslobj.getpeercert(binary_form) def selected_npn_protocol(self): """Return the currently selected NPN protocol as a string, or ``None`` @@ -732,13 +730,7 @@ class SSLObject: """Get channel binding data for current connection. Raise ValueError if the requested `cb_type` is not supported. Return bytes of the data or None if the data is not available (e.g. before the handshake).""" - if cb_type not in CHANNEL_BINDING_TYPES: - raise ValueError("Unsupported channel binding type") - if cb_type != "tls-unique": - raise NotImplementedError( - "{0} channel binding type not implemented" - .format(cb_type)) - return self._sslobj.tls_unique_cb() + return self._sslobj.get_channel_binding(cb_type) def version(self): """Return a string identifying the protocol version used by the @@ -832,10 +824,10 @@ class SSLSocket(socket): if connected: # create the SSL object try: - sslobj = self._context._wrap_socket(self, server_side, - self.server_hostname) - self._sslobj = SSLObject(sslobj, owner=self, - session=self._session) + self._sslobj = self._context._wrap_socket( + self, server_side, self.server_hostname, + owner=self, session=self._session, + ) if do_handshake_on_connect: timeout = self.gettimeout() if timeout == 0.0: @@ -895,10 +887,13 @@ class SSLSocket(socket): Return zero-length string on EOF.""" self._checkClosed() - if not self._sslobj: + if self._sslobj is None: raise ValueError("Read on closed or unwrapped SSL socket.") try: - return self._sslobj.read(len, buffer) + if buffer is not None: + return self._sslobj.read(len, buffer) + else: + return self._sslobj.read(len) except SSLError as x: if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs: if buffer is not None: @@ -913,7 +908,7 @@ class SSLSocket(socket): number of bytes of DATA actually transmitted.""" self._checkClosed() - if not self._sslobj: + if self._sslobj is None: raise ValueError("Write on closed or unwrapped SSL socket.") return self._sslobj.write(data) @@ -929,41 +924,42 @@ class SSLSocket(socket): def selected_npn_protocol(self): self._checkClosed() - if not self._sslobj or not _ssl.HAS_NPN: + if self._sslobj is None or not _ssl.HAS_NPN: return None else: return self._sslobj.selected_npn_protocol() def selected_alpn_protocol(self): self._checkClosed() - if not self._sslobj or not _ssl.HAS_ALPN: + if self._sslobj is None or not _ssl.HAS_ALPN: return None else: return self._sslobj.selected_alpn_protocol() def cipher(self): self._checkClosed() - if not self._sslobj: + if self._sslobj is None: return None else: return self._sslobj.cipher() def shared_ciphers(self): self._checkClosed() - if not self._sslobj: + if self._sslobj is None: return None - return self._sslobj.shared_ciphers() + else: + return self._sslobj.shared_ciphers() def compression(self): self._checkClosed() - if not self._sslobj: + if self._sslobj is None: return None else: return self._sslobj.compression() def send(self, data, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to send() on %s" % @@ -974,7 +970,7 @@ class SSLSocket(socket): def sendto(self, data, flags_or_addr, addr=None): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: raise ValueError("sendto not allowed on instances of %s" % self.__class__) elif addr is None: @@ -990,7 +986,7 @@ class SSLSocket(socket): def sendall(self, data, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to sendall() on %s" % @@ -1008,15 +1004,15 @@ class SSLSocket(socket): """Send a file, possibly by using os.sendfile() if this is a clear-text socket. Return the total number of bytes sent. """ - if self._sslobj is None: + if self._sslobj is not None: + return self._sendfile_use_send(file, offset, count) + else: # os.sendfile() works with plain sockets only return super().sendfile(file, offset, count) - else: - return self._sendfile_use_send(file, offset, count) def recv(self, buflen=1024, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to recv() on %s" % @@ -1031,7 +1027,7 @@ class SSLSocket(socket): nbytes = len(buffer) elif nbytes is None: nbytes = 1024 - if self._sslobj: + if self._sslobj is not None: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to recv_into() on %s" % @@ -1042,7 +1038,7 @@ class SSLSocket(socket): def recvfrom(self, buflen=1024, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: raise ValueError("recvfrom not allowed on instances of %s" % self.__class__) else: @@ -1050,7 +1046,7 @@ class SSLSocket(socket): def recvfrom_into(self, buffer, nbytes=None, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: raise ValueError("recvfrom_into not allowed on instances of %s" % self.__class__) else: @@ -1066,7 +1062,7 @@ class SSLSocket(socket): def pending(self): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: return self._sslobj.pending() else: return 0 @@ -1078,7 +1074,7 @@ class SSLSocket(socket): def unwrap(self): if self._sslobj: - s = self._sslobj.unwrap() + s = self._sslobj.shutdown() self._sslobj = None return s else: @@ -1096,6 +1092,11 @@ class SSLSocket(socket): if timeout == 0.0 and block: self.settimeout(None) self._sslobj.do_handshake() + if self.context.check_hostname: + if not self.server_hostname: + raise ValueError("check_hostname needs server_hostname " + "argument") + match_hostname(self.getpeercert(), self.server_hostname) finally: self.settimeout(timeout) @@ -1104,11 +1105,12 @@ class SSLSocket(socket): raise ValueError("can't connect in server-side mode") # Here we assume that the socket is client-side, and not # connected at the time of the call. We connect it, then wrap it. - if self._connected: + if self._connected or self._sslobj is not None: raise ValueError("attempt to connect already-connected SSLSocket!") - sslobj = self.context._wrap_socket(self, False, self.server_hostname) - self._sslobj = SSLObject(sslobj, owner=self, - session=self._session) + self._sslobj = self.context._wrap_socket( + self, False, self.server_hostname, + owner=self, session=self._session + ) try: if connect_ex: rc = super().connect_ex(addr) @@ -1151,18 +1153,24 @@ class SSLSocket(socket): if the requested `cb_type` is not supported. Return bytes of the data or None if the data is not available (e.g. before the handshake). """ - if self._sslobj is None: + if self._sslobj is not None: + return self._sslobj.get_channel_binding(cb_type) + else: + if cb_type not in CHANNEL_BINDING_TYPES: + raise ValueError( + "{0} channel binding type not implemented".format(cb_type) + ) return None - return self._sslobj.get_channel_binding(cb_type) def version(self): """ Return a string identifying the protocol version used by the current SSL channel, or None if there is no established channel. """ - if self._sslobj is None: + if self._sslobj is not None: + return self._sslobj.version() + else: return None - return self._sslobj.version() # Python does not support forward declaration of types. diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 7aa1123..3f2c50b 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -455,6 +455,8 @@ class BasicSocketTests(unittest.TestCase): self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1) self.assertRaises(OSError, ss.send, b'x') self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0)) + self.assertRaises(NotImplementedError, ss.sendmsg, + [b'x'], (), 0, ('0.0.0.0', 0)) def test_timeout(self): # Issue #8524: when creating an SSL socket, the timeout of the @@ -3381,11 +3383,13 @@ class ThreadedTests(unittest.TestCase): chatty=False) as server: with context.wrap_socket(socket.socket()) as s: self.assertIs(s.version(), None) + self.assertIs(s._sslobj, None) s.connect((HOST, server.port)) if ssl.OPENSSL_VERSION_INFO >= (1, 0, 2): self.assertEqual(s.version(), 'TLSv1.2') else: # 0.9.8 to 1.0.1 self.assertIn(s.version(), ('TLSv1', 'TLSv1.2')) + self.assertIs(s._sslobj, None) self.assertIs(s.version(), None) @unittest.skipUnless(ssl.HAS_TLSv1_3, diff --git a/Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst b/Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst new file mode 100644 index 0000000..2b4877f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst @@ -0,0 +1,4 @@ +Internal implementation details of ssl module were cleaned up. The SSLSocket +has one less layer of indirection. Owner and session information are now +handled by the SSLSocket and SSLObject constructor. Channel binding +implementation has been simplified. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index a0f8c1c..2136cbd 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -408,6 +408,8 @@ class _ssl.SSLSession "PySSLSession *" "&PySSLSession_Type" static int PySSL_select(PySocketSockObject *s, int writing, _PyTime_t timeout); +static int PySSL_set_owner(PySSLSocket *, PyObject *, void *); +static int PySSL_set_session(PySSLSocket *, PyObject *, void *); #define PySSLSocket_Check(v) (Py_TYPE(v) == &PySSLSocket_Type) #define PySSLMemoryBIO_Check(v) (Py_TYPE(v) == &PySSLMemoryBIO_Type) #define PySSLSession_Check(v) (Py_TYPE(v) == &PySSLSession_Type) @@ -799,6 +801,7 @@ static PySSLSocket * newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, enum py_ssl_server_or_client socket_type, char *server_hostname, + PyObject *owner, PyObject *session, PySSLMemoryBIO *inbio, PySSLMemoryBIO *outbio) { PySSLSocket *self; @@ -875,6 +878,18 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, return NULL; } } + if (owner && owner != Py_None) { + if (PySSL_set_owner(self, owner, NULL) == -1) { + Py_DECREF(self); + return NULL; + } + } + if (session && session != Py_None) { + if (PySSL_set_session(self, session, NULL) == -1) { + Py_DECREF(self); + return NULL; + } + } return self; } @@ -1677,7 +1692,7 @@ _ssl__test_decode_cert_impl(PyObject *module, PyObject *path) /*[clinic input] -_ssl._SSLSocket.peer_certificate +_ssl._SSLSocket.getpeercert der as binary_mode: bool = False / @@ -1693,8 +1708,8 @@ return the certificate even if it wasn't validated. [clinic start generated code]*/ static PyObject * -_ssl__SSLSocket_peer_certificate_impl(PySSLSocket *self, int binary_mode) -/*[clinic end generated code: output=f0dc3e4d1d818a1d input=8281bd1d193db843]*/ +_ssl__SSLSocket_getpeercert_impl(PySSLSocket *self, int binary_mode) +/*[clinic end generated code: output=1f0ab66dfb693c88 input=c0fbe802e57629b7]*/ { int verification; X509 *peer_cert; @@ -2395,13 +2410,11 @@ error: _ssl._SSLSocket.shutdown Does the SSL shutdown handshake with the remote end. - -Returns the underlying socket object. [clinic start generated code]*/ static PyObject * _ssl__SSLSocket_shutdown_impl(PySSLSocket *self) -/*[clinic end generated code: output=ca1aa7ed9d25ca42 input=ede2cc1a2ddf0ee4]*/ +/*[clinic end generated code: output=ca1aa7ed9d25ca42 input=11d39e69b0a2bf4a]*/ { int err, sockstate, nonblocking; int zeros = 0; @@ -2506,37 +2519,48 @@ error: } /*[clinic input] -_ssl._SSLSocket.tls_unique_cb +_ssl._SSLSocket.get_channel_binding + cb_type: str = "tls-unique" -Returns the 'tls-unique' channel binding data, as defined by RFC 5929. +Get channel binding data for current connection. -If the TLS handshake is not yet complete, None is returned. +Raise ValueError if the requested `cb_type` is not supported. Return bytes +of the data or None if the data is not available (e.g. before the handshake). +Only 'tls-unique' channel binding data from RFC 5929 is supported. [clinic start generated code]*/ static PyObject * -_ssl__SSLSocket_tls_unique_cb_impl(PySSLSocket *self) -/*[clinic end generated code: output=f3a832d603f586af input=439525c7b3d8d34d]*/ +_ssl__SSLSocket_get_channel_binding_impl(PySSLSocket *self, + const char *cb_type) +/*[clinic end generated code: output=34bac9acb6a61d31 input=08b7e43b99c17d41]*/ { - PyObject *retval = NULL; char buf[PySSL_CB_MAXLEN]; size_t len; - if (SSL_session_reused(self->ssl) ^ !self->socket_type) { - /* if session is resumed XOR we are the client */ - len = SSL_get_finished(self->ssl, buf, PySSL_CB_MAXLEN); + if (strcmp(cb_type, "tls-unique") == 0) { + if (SSL_session_reused(self->ssl) ^ !self->socket_type) { + /* if session is resumed XOR we are the client */ + len = SSL_get_finished(self->ssl, buf, PySSL_CB_MAXLEN); + } + else { + /* if a new session XOR we are the server */ + len = SSL_get_peer_finished(self->ssl, buf, PySSL_CB_MAXLEN); + } } else { - /* if a new session XOR we are the server */ - len = SSL_get_peer_finished(self->ssl, buf, PySSL_CB_MAXLEN); + PyErr_Format( + PyExc_ValueError, + "'%s' channel binding type not implemented", + cb_type + ); + return NULL; } /* It cannot be negative in current OpenSSL version as of July 2011 */ if (len == 0) Py_RETURN_NONE; - retval = PyBytes_FromStringAndSize(buf, len); - - return retval; + return PyBytes_FromStringAndSize(buf, len); } #ifdef OPENSSL_VERSION_1_1 @@ -2706,7 +2730,8 @@ static PyMethodDef PySSLMethods[] = { _SSL__SSLSOCKET_WRITE_METHODDEF _SSL__SSLSOCKET_READ_METHODDEF _SSL__SSLSOCKET_PENDING_METHODDEF - _SSL__SSLSOCKET_PEER_CERTIFICATE_METHODDEF + _SSL__SSLSOCKET_GETPEERCERT_METHODDEF + _SSL__SSLSOCKET_GET_CHANNEL_BINDING_METHODDEF _SSL__SSLSOCKET_CIPHER_METHODDEF _SSL__SSLSOCKET_SHARED_CIPHERS_METHODDEF _SSL__SSLSOCKET_VERSION_METHODDEF @@ -2714,7 +2739,6 @@ static PyMethodDef PySSLMethods[] = { _SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF _SSL__SSLSOCKET_COMPRESSION_METHODDEF _SSL__SSLSOCKET_SHUTDOWN_METHODDEF - _SSL__SSLSOCKET_TLS_UNIQUE_CB_METHODDEF {NULL, NULL} }; @@ -3810,13 +3834,17 @@ _ssl._SSLContext._wrap_socket sock: object(subclass_of="PySocketModule.Sock_Type") server_side: int server_hostname as hostname_obj: object = None + * + owner: object = None + session: object = None [clinic start generated code]*/ static PyObject * _ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, - int server_side, PyObject *hostname_obj) -/*[clinic end generated code: output=6973e4b60995e933 input=83859b9156ddfc63]*/ + int server_side, PyObject *hostname_obj, + PyObject *owner, PyObject *session) +/*[clinic end generated code: output=f103f238633940b4 input=957d5006183d1894]*/ { char *hostname = NULL; PyObject *res; @@ -3830,6 +3858,7 @@ _ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, res = (PyObject *) newPySSLSocket(self, (PySocketSockObject *)sock, server_side, hostname, + owner, session, NULL, NULL); if (hostname != NULL) PyMem_Free(hostname); @@ -3842,14 +3871,18 @@ _ssl._SSLContext._wrap_bio outgoing: object(subclass_of="&PySSLMemoryBIO_Type", type="PySSLMemoryBIO *") server_side: int server_hostname as hostname_obj: object = None + * + owner: object = None + session: object = None [clinic start generated code]*/ static PyObject * _ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming, PySSLMemoryBIO *outgoing, int server_side, - PyObject *hostname_obj) -/*[clinic end generated code: output=4fe4ba75ad95940d input=17725ecdac0bf220]*/ + PyObject *hostname_obj, PyObject *owner, + PyObject *session) +/*[clinic end generated code: output=5c5d6d9b41f99332 input=8cf22f4d586ac56a]*/ { char *hostname = NULL; PyObject *res; @@ -3862,6 +3895,7 @@ _ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming, } res = (PyObject *) newPySSLSocket(self, NULL, server_side, hostname, + owner, session, incoming, outgoing); PyMem_Free(hostname); @@ -5663,10 +5697,6 @@ PyInit__ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_SNI", r); - r = Py_True; - Py_INCREF(r); - PyModule_AddObject(m, "HAS_TLS_UNIQUE", r); - #ifdef OPENSSL_NO_ECDH r = Py_False; #else diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index d1a9afc..5b6c4af 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -45,8 +45,8 @@ exit: return return_value; } -PyDoc_STRVAR(_ssl__SSLSocket_peer_certificate__doc__, -"peer_certificate($self, der=False, /)\n" +PyDoc_STRVAR(_ssl__SSLSocket_getpeercert__doc__, +"getpeercert($self, der=False, /)\n" "--\n" "\n" "Returns the certificate for the peer.\n" @@ -59,23 +59,23 @@ PyDoc_STRVAR(_ssl__SSLSocket_peer_certificate__doc__, "peer certificate, or None if no certificate was provided. This will\n" "return the certificate even if it wasn\'t validated."); -#define _SSL__SSLSOCKET_PEER_CERTIFICATE_METHODDEF \ - {"peer_certificate", (PyCFunction)_ssl__SSLSocket_peer_certificate, METH_FASTCALL, _ssl__SSLSocket_peer_certificate__doc__}, +#define _SSL__SSLSOCKET_GETPEERCERT_METHODDEF \ + {"getpeercert", (PyCFunction)_ssl__SSLSocket_getpeercert, METH_FASTCALL, _ssl__SSLSocket_getpeercert__doc__}, static PyObject * -_ssl__SSLSocket_peer_certificate_impl(PySSLSocket *self, int binary_mode); +_ssl__SSLSocket_getpeercert_impl(PySSLSocket *self, int binary_mode); static PyObject * -_ssl__SSLSocket_peer_certificate(PySSLSocket *self, PyObject *const *args, Py_ssize_t nargs) +_ssl__SSLSocket_getpeercert(PySSLSocket *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int binary_mode = 0; - if (!_PyArg_ParseStack(args, nargs, "|p:peer_certificate", + if (!_PyArg_ParseStack(args, nargs, "|p:getpeercert", &binary_mode)) { goto exit; } - return_value = _ssl__SSLSocket_peer_certificate_impl(self, binary_mode); + return_value = _ssl__SSLSocket_getpeercert_impl(self, binary_mode); exit: return return_value; @@ -293,9 +293,7 @@ PyDoc_STRVAR(_ssl__SSLSocket_shutdown__doc__, "shutdown($self, /)\n" "--\n" "\n" -"Does the SSL shutdown handshake with the remote end.\n" -"\n" -"Returns the underlying socket object."); +"Does the SSL shutdown handshake with the remote end."); #define _SSL__SSLSOCKET_SHUTDOWN_METHODDEF \ {"shutdown", (PyCFunction)_ssl__SSLSocket_shutdown, METH_NOARGS, _ssl__SSLSocket_shutdown__doc__}, @@ -309,24 +307,39 @@ _ssl__SSLSocket_shutdown(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) return _ssl__SSLSocket_shutdown_impl(self); } -PyDoc_STRVAR(_ssl__SSLSocket_tls_unique_cb__doc__, -"tls_unique_cb($self, /)\n" +PyDoc_STRVAR(_ssl__SSLSocket_get_channel_binding__doc__, +"get_channel_binding($self, /, cb_type=\'tls-unique\')\n" "--\n" "\n" -"Returns the \'tls-unique\' channel binding data, as defined by RFC 5929.\n" +"Get channel binding data for current connection.\n" "\n" -"If the TLS handshake is not yet complete, None is returned."); +"Raise ValueError if the requested `cb_type` is not supported. Return bytes\n" +"of the data or None if the data is not available (e.g. before the handshake).\n" +"Only \'tls-unique\' channel binding data from RFC 5929 is supported."); -#define _SSL__SSLSOCKET_TLS_UNIQUE_CB_METHODDEF \ - {"tls_unique_cb", (PyCFunction)_ssl__SSLSocket_tls_unique_cb, METH_NOARGS, _ssl__SSLSocket_tls_unique_cb__doc__}, +#define _SSL__SSLSOCKET_GET_CHANNEL_BINDING_METHODDEF \ + {"get_channel_binding", (PyCFunction)_ssl__SSLSocket_get_channel_binding, METH_FASTCALL|METH_KEYWORDS, _ssl__SSLSocket_get_channel_binding__doc__}, static PyObject * -_ssl__SSLSocket_tls_unique_cb_impl(PySSLSocket *self); +_ssl__SSLSocket_get_channel_binding_impl(PySSLSocket *self, + const char *cb_type); static PyObject * -_ssl__SSLSocket_tls_unique_cb(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) +_ssl__SSLSocket_get_channel_binding(PySSLSocket *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _ssl__SSLSocket_tls_unique_cb_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = {"cb_type", NULL}; + static _PyArg_Parser _parser = {"|s:get_channel_binding", _keywords, 0}; + const char *cb_type = "tls-unique"; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &cb_type)) { + goto exit; + } + return_value = _ssl__SSLSocket_get_channel_binding_impl(self, cb_type); + +exit: + return return_value; } static PyObject * @@ -538,7 +551,8 @@ PyDoc_STRVAR(_ssl__SSLContext_load_dh_params__doc__, {"load_dh_params", (PyCFunction)_ssl__SSLContext_load_dh_params, METH_O, _ssl__SSLContext_load_dh_params__doc__}, PyDoc_STRVAR(_ssl__SSLContext__wrap_socket__doc__, -"_wrap_socket($self, /, sock, server_side, server_hostname=None)\n" +"_wrap_socket($self, /, sock, server_side, server_hostname=None, *,\n" +" owner=None, session=None)\n" "--\n" "\n"); @@ -547,23 +561,26 @@ PyDoc_STRVAR(_ssl__SSLContext__wrap_socket__doc__, static PyObject * _ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, - int server_side, PyObject *hostname_obj); + int server_side, PyObject *hostname_obj, + PyObject *owner, PyObject *session); static PyObject * _ssl__SSLContext__wrap_socket(PySSLContext *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"sock", "server_side", "server_hostname", NULL}; - static _PyArg_Parser _parser = {"O!i|O:_wrap_socket", _keywords, 0}; + static const char * const _keywords[] = {"sock", "server_side", "server_hostname", "owner", "session", NULL}; + static _PyArg_Parser _parser = {"O!i|O$OO:_wrap_socket", _keywords, 0}; PyObject *sock; int server_side; PyObject *hostname_obj = Py_None; + PyObject *owner = Py_None; + PyObject *session = Py_None; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - PySocketModule.Sock_Type, &sock, &server_side, &hostname_obj)) { + PySocketModule.Sock_Type, &sock, &server_side, &hostname_obj, &owner, &session)) { goto exit; } - return_value = _ssl__SSLContext__wrap_socket_impl(self, sock, server_side, hostname_obj); + return_value = _ssl__SSLContext__wrap_socket_impl(self, sock, server_side, hostname_obj, owner, session); exit: return return_value; @@ -571,7 +588,7 @@ exit: PyDoc_STRVAR(_ssl__SSLContext__wrap_bio__doc__, "_wrap_bio($self, /, incoming, outgoing, server_side,\n" -" server_hostname=None)\n" +" server_hostname=None, *, owner=None, session=None)\n" "--\n" "\n"); @@ -581,24 +598,27 @@ PyDoc_STRVAR(_ssl__SSLContext__wrap_bio__doc__, static PyObject * _ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming, PySSLMemoryBIO *outgoing, int server_side, - PyObject *hostname_obj); + PyObject *hostname_obj, PyObject *owner, + PyObject *session); static PyObject * _ssl__SSLContext__wrap_bio(PySSLContext *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"incoming", "outgoing", "server_side", "server_hostname", NULL}; - static _PyArg_Parser _parser = {"O!O!i|O:_wrap_bio", _keywords, 0}; + static const char * const _keywords[] = {"incoming", "outgoing", "server_side", "server_hostname", "owner", "session", NULL}; + static _PyArg_Parser _parser = {"O!O!i|O$OO:_wrap_bio", _keywords, 0}; PySSLMemoryBIO *incoming; PySSLMemoryBIO *outgoing; int server_side; PyObject *hostname_obj = Py_None; + PyObject *owner = Py_None; + PyObject *session = Py_None; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &PySSLMemoryBIO_Type, &incoming, &PySSLMemoryBIO_Type, &outgoing, &server_side, &hostname_obj)) { + &PySSLMemoryBIO_Type, &incoming, &PySSLMemoryBIO_Type, &outgoing, &server_side, &hostname_obj, &owner, &session)) { goto exit; } - return_value = _ssl__SSLContext__wrap_bio_impl(self, incoming, outgoing, server_side, hostname_obj); + return_value = _ssl__SSLContext__wrap_bio_impl(self, incoming, outgoing, server_side, hostname_obj, owner, session); exit: return return_value; @@ -1155,4 +1175,4 @@ exit: #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=84e1fd89aff9b0f7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d987411caeb106e7 input=a9049054013a1b77]*/ -- cgit v0.12