Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

SSLSocket.shared_ciphers() does not documentNone is returned on session reuse #106344

Labels
3.11only security fixes3.12only security fixes3.13bugs and security fixesdocsDocumentation in the Doc dirtopic-SSL
@kevinAlbs

Description

@kevinAlbs

Documentation

SSLSocket.shared_ciphers() does not documentNone is returned on session reuse

Summary

The fix of#96931 resulted in a change inSSLSocket.shared_ciphers().
If the session is reused,SSLSocket.shared_ciphers() returnsNone
Proposal: update documentation ofSSLSocket.shared_ciphers() to noteNone is returned on session reuse.

Background & Motivation

As an example, here is a sampleserver.py andclient.py scripts to show the behavior change in Python 3.11.2 and 3.11.3:

# server.pyimportsocketimportsslimportplatformcontext=ssl.create_default_context(ssl.Purpose.CLIENT_AUTH,cafile="ca.pem")context.load_cert_chain(certfile="server.pem")port=12345bindsocket=socket.socket()bindsocket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)bindsocket.bind(("localhost",port))bindsocket.listen(5)print("Python version: {}".format(platform.python_version()))print("server listening on port {}".format(port))whileTrue:newsocket,fromaddr=bindsocket.accept()connstream:ssl.SSLContext.sslsocket_class=context.wrap_socket(newsocket,server_side=True,do_handshake_on_connect=True)print("server got connection on address: {}".format(fromaddr))print("server shared ciphers: {}".format(connstream.shared_ciphers()))print("server session reused? {}".format(connstream.session_reused))data=connstream.recv(1024)whiledata:print("server got data {}".format(data))data=connstream.recv(1024)print("server finished with client")connstream.close()
# client.pyimportsocketimportsslport=12345"""Use TLS 1.2 so session ticket is sent.https://docs.python.org/3/library/ssl.html#ssl-session describes:> Session tickets are no longer sent as part of the initial handshake and are handled differently. SSLSocket.session and SSLSession are not compatible with TLS 1.3."""context=ssl.SSLContext(protocol=ssl.PROTOCOL_TLSv1_2)context.load_verify_locations(cafile="ca.pem")conn:ssl.SSLSocket=context.wrap_socket(socket.socket(socket.AF_INET),server_hostname="localhost")conn.connect(("localhost",port))conn.write(b"foo")assertnotconn.session_reusedsession=conn.sessionconn.close()# Connect again and reuse the session.conn=context.wrap_socket(socket.socket(socket.AF_INET),server_hostname="localhost",session=session)conn.connect(("localhost",port))conn.write(b"foo")assertconn.session_reusedconn.close()

Here is the output ofserver.py on Python 3.11.2:

Python version: 3.11.2server listening on port 12345server got connection on address: ('127.0.0.1', 64310)server shared ciphers: [('TLS_AES_256_GCM_SHA384', 'TLSv1.3', 256), ('TLS_CHACHA20_POLY1305_SHA256', 'TLSv1.3', 256), ('TLS_AES_128_GCM_SHA256', 'TLSv1.3', 128), ('ECDHE-ECDSA-AES256-GCM-SHA384', 'TLSv1.2', 256), ('ECDHE-RSA-AES256-GCM-SHA384', 'TLSv1.2', 256), ('ECDHE-ECDSA-AES128-GCM-SHA256', 'TLSv1.2', 128), ('ECDHE-RSA-AES128-GCM-SHA256', 'TLSv1.2', 128), ('ECDHE-ECDSA-CHACHA20-POLY1305', 'TLSv1.2', 256), ('ECDHE-RSA-CHACHA20-POLY1305', 'TLSv1.2', 256), ('ECDHE-ECDSA-AES256-SHA384', 'TLSv1.2', 256), ('ECDHE-RSA-AES256-SHA384', 'TLSv1.2', 256), ('ECDHE-ECDSA-AES128-SHA256', 'TLSv1.2', 128), ('ECDHE-RSA-AES128-SHA256', 'TLSv1.2', 128), ('DHE-RSA-AES256-GCM-SHA384', 'TLSv1.2', 256), ('DHE-RSA-AES128-GCM-SHA256', 'TLSv1.2', 128), ('DHE-RSA-AES256-SHA256', 'TLSv1.2', 256), ('DHE-RSA-AES128-SHA256', 'TLSv1.2', 128)]server session reused? Falseserver got data b'foo'server finished with clientserver got connection on address: ('127.0.0.1', 64311)server shared ciphers: [('TLS_AES_256_GCM_SHA384', 'TLSv1.3', 256), ('TLS_CHACHA20_POLY1305_SHA256', 'TLSv1.3', 256), ('TLS_AES_128_GCM_SHA256', 'TLSv1.3', 128), ('ECDHE-ECDSA-AES256-GCM-SHA384', 'TLSv1.2', 256), ('ECDHE-RSA-AES256-GCM-SHA384', 'TLSv1.2', 256), ('ECDHE-ECDSA-AES128-GCM-SHA256', 'TLSv1.2', 128), ('ECDHE-RSA-AES128-GCM-SHA256', 'TLSv1.2', 128), ('ECDHE-ECDSA-CHACHA20-POLY1305', 'TLSv1.2', 256), ('ECDHE-RSA-CHACHA20-POLY1305', 'TLSv1.2', 256), ('ECDHE-ECDSA-AES256-SHA384', 'TLSv1.2', 256), ('ECDHE-RSA-AES256-SHA384', 'TLSv1.2', 256), ('ECDHE-ECDSA-AES128-SHA256', 'TLSv1.2', 128), ('ECDHE-RSA-AES128-SHA256', 'TLSv1.2', 128), ('DHE-RSA-AES256-GCM-SHA384', 'TLSv1.2', 256), ('DHE-RSA-AES128-GCM-SHA256', 'TLSv1.2', 128), ('DHE-RSA-AES256-SHA256', 'TLSv1.2', 256), ('DHE-RSA-AES128-SHA256', 'TLSv1.2', 128)]server session reused? Trueserver got data b'foo'server finished with client

Here is the output ofserver.py on Python 3.11.3:

Python version: 3.11.3server listening on port 12345server got connection on address: ('127.0.0.1', 64316)server shared ciphers: [('ECDHE-ECDSA-AES256-GCM-SHA384', 'TLSv1.2', 256), ('ECDHE-RSA-AES256-GCM-SHA384', 'TLSv1.2', 256), ('ECDHE-ECDSA-AES128-GCM-SHA256', 'TLSv1.2', 128), ('ECDHE-RSA-AES128-GCM-SHA256', 'TLSv1.2', 128), ('ECDHE-ECDSA-CHACHA20-POLY1305', 'TLSv1.2', 256), ('ECDHE-RSA-CHACHA20-POLY1305', 'TLSv1.2', 256), ('ECDHE-ECDSA-AES256-SHA384', 'TLSv1.2', 256), ('ECDHE-RSA-AES256-SHA384', 'TLSv1.2', 256), ('ECDHE-ECDSA-AES128-SHA256', 'TLSv1.2', 128), ('ECDHE-RSA-AES128-SHA256', 'TLSv1.2', 128), ('DHE-RSA-AES256-GCM-SHA384', 'TLSv1.2', 256), ('DHE-RSA-AES128-GCM-SHA256', 'TLSv1.2', 128), ('DHE-RSA-AES256-SHA256', 'TLSv1.2', 256), ('DHE-RSA-AES128-SHA256', 'TLSv1.2', 128)]server session reused? Falseserver got data b'foo'server finished with clientserver got connection on address: ('127.0.0.1', 64317)server shared ciphers: Noneserver session reused? Trueserver got data b'foo'server finished with client

In 3.11.3, after the session is reused, the return ofshared_ciphers() isNone. The scripts and test certificates arelocated here.

Alternatives

openssl/openssl#4295 suggest alternative API to use in OpenSSL:

Ah, the shared ciphers would only be computed when negotiation is performed (i.e., not resumption), yes. Hopefully you can update to a supported version of OpenSSL and pick up the needed funcitonality.

An alternative implementation could be to useSSL_CTX_set_client_hello_cb to obtain the list of ciphers sent in the ClientHello. Store the list of ciphers for retrieval inshared_ciphers().#110902 implements this change but is (at present) left as draft. Storing the ciphers requires additional memory per socket and may not provide much value to users. Instead,#106345 proposes a documentation only change to inform users.

Known Impact

TheNone return resulted in a bug report in PyKMIP. The call toshared_ciphers was not checking for theNone return value:OpenKMIP/PyKMIP#700

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.11only security fixes3.12only security fixes3.13bugs and security fixesdocsDocumentation in the Doc dirtopic-SSL

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp