Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disabling SSLv3 support #67124

Closed
kroeckx mannequin opened this issue Nov 24, 2014 · 30 comments
Closed

Disabling SSLv3 support #67124

kroeckx mannequin opened this issue Nov 24, 2014 · 30 comments
Labels
build The build process and cross-build release-blocker

Comments

@kroeckx
Copy link
Mannequin

kroeckx mannequin commented Nov 24, 2014

BPO 22935
Nosy @malemburg, @doko42, @pitrou, @vstinner, @larryhastings, @giampaolo, @tiran, @benjaminp, @ned-deily, @alex, @dstufft
Files
  • python2.7-nossl3.patch
  • get_server_certificate_sslv3.patch
  • get_server_certificate_sslv23.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2015-01-06.12:41:26.627>
    created_at = <Date 2014-11-24.22:14:20.290>
    labels = ['build', 'release-blocker']
    title = 'Disabling SSLv3 support'
    updated_at = <Date 2015-01-06.15:03:50.345>
    user = 'https://bugs.python.org/kroeckx'

    bugs.python.org fields:

    activity = <Date 2015-01-06.15:03:50.345>
    actor = 'berker.peksag'
    assignee = 'none'
    closed = True
    closed_date = <Date 2015-01-06.12:41:26.627>
    closer = 'vstinner'
    components = ['Build']
    creation = <Date 2014-11-24.22:14:20.290>
    creator = 'kroeckx'
    dependencies = []
    files = ['37268', '37423', '37424']
    hgrepos = []
    issue_num = 22935
    keywords = ['patch']
    message_count = 30.0
    messages = ['231624', '231625', '231626', '231627', '231813', '231815', '231911', '231942', '232236', '232238', '232315', '232522', '232525', '232526', '232527', '232528', '232530', '232542', '232543', '232545', '232546', '232547', '232548', '232551', '232552', '233447', '233448', '233522', '233523', '233533']
    nosy_count = 14.0
    nosy_names = ['lemburg', 'doko', 'janssen', 'pitrou', 'vstinner', 'larry', 'giampaolo.rodola', 'christian.heimes', 'benjamin.peterson', 'ned.deily', 'alex', 'python-dev', 'dstufft', 'kroeckx']
    pr_nums = []
    priority = 'release blocker'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'compile error'
    url = 'https://bugs.python.org/issue22935'
    versions = ['Python 2.7', 'Python 3.4', 'Python 3.5']

    @kroeckx
    Copy link
    Mannequin Author

    kroeckx mannequin commented Nov 24, 2014

    Hi,

    The attached patch makes python work when openssl doesn't have SSLv3 support. It also updates the documentation, which has already improved a lot since my original patch.

    The current upstream openssl when compiled with no-ssl2 it defines OPENSSL_NO_SSL2, drops the SSLv2_* method and drops support for SSLv2 in the SSLv23_* methods. When build with no-ssl3 it defines OPENSSL_NO_SSL3 and currently just drops supports for SSLv3 in the SSLv23_method, it does not yet drop the SSLv3_* methods. It's still being argued whether no-ssl3 should drop those symbols or that a new option will be used instead.

    So that means that with OPENSSL_NO_SSL3 defined it could be that the SSLv3_* methods still exist and that you can create a socket that only support SSLv3.

    I made the SSLv3 methods go away in python if OPENSSL_NO_SSL3 is defined. This at least makes things easier for the test suite so that you know you can test a combination like v3 with v23 or not.

    This patch is for 2.7. Please let me know if you need a patch for a different version.

    @alex
    Copy link
    Member

    alex commented Nov 24, 2014

    FWIW, Debian expiremental appears to be using a different #define for this. Here's how we handled it in pyca/cryptography: pyca/cryptography@04a3f1f

    @kroeckx
    Copy link
    Mannequin Author

    kroeckx mannequin commented Nov 24, 2014

    I know what I uploaded to Debian experimental. And I can't promise that I'll keep that define. I suggest you assume that NO_SSL3 will disable both.

    @alex
    Copy link
    Member

    alex commented Nov 24, 2014

    Good to know, thanks.

    @pitrou pitrou added the build The build process and cross-build label Nov 24, 2014
    @vstinner
    Copy link
    Member

    FYI LibreSSL also disabled SSLv2 and SSLv3.

    @doko42
    Copy link
    Member

    doko42 commented Nov 28, 2014

    maybe it's time to generalise this one, still found on all branches:

    # Issue python/cpython#53661: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
    def skip_if_broken_ubuntu_ssl(func):

    @ned-deily
    Copy link
    Member

    Clearly we need to support openssl's without SSLv3 so I think some version of this needs to be applied to all branches (preferably in time for 2.7.9, Benjamin?). Kurt, if you haven't already, could you sign the contributor agreement so we can use the patch (https://www.python.org/psf/contrib/contrib-form/)? And I guess it would be nice to generalize the SSLv2 checks as doko suggests.

    @ned-deily ned-deily added the build The build process and cross-build label Nov 30, 2014
    @kroeckx
    Copy link
    Mannequin Author

    kroeckx mannequin commented Dec 1, 2014

    I've just signed the contributor agreement

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Dec 6, 2014

    New changeset 49d267a58cc2 by Benjamin Peterson in branch '2.7':
    allow ssl module to compile if openssl doesn't support SSL 3 (closes bpo-22935)
    https://hg.python.org/cpython/rev/49d267a58cc2

    New changeset 4077e0cd8d48 by Benjamin Peterson in branch '3.4':
    allow ssl module to compile if openssl doesn't support SSL 3 (closes bpo-22935)
    https://hg.python.org/cpython/rev/4077e0cd8d48

    New changeset fbf3747e721c by Benjamin Peterson in branch 'default':
    merge 3.4 (bpo-22935)
    https://hg.python.org/cpython/rev/fbf3747e721c

    @python-dev python-dev mannequin closed this as completed Dec 6, 2014
    @vstinner
    Copy link
    Member

    vstinner commented Dec 6, 2014

    The documentation should be modified to explain that SSLv2 and SSLv3 are
    not always available.

    @kroeckx
    Copy link
    Mannequin Author

    kroeckx mannequin commented Dec 8, 2014

    I did update the documentation to mention that, but it seems none of my documentation changes got applied.

    @ned-deily
    Copy link
    Member

    The changes for 3.4 are incomplete:

    >>> import ssl
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/py/dev/34/source/Lib/ssl.py", line 122, in <module>
        from _ssl import PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1
    ImportError: cannot import name 'PROTOCOL_SSLv3'

    For the default (3.5) branch, f776771ab0ee for bpo-21068 changed ssl.py to handle missing SSLv3 support; 3.4 needs something similar.

    @ned-deily ned-deily reopened this Dec 12, 2014
    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Dec 12, 2014

    New changeset 773e55c95703 by Victor Stinner in branch '3.4':
    Issue bpo-22935: Fix ssl module when SSLv3 protocol is not supported
    https://hg.python.org/cpython/rev/773e55c95703

    New changeset fb1ffd40d33e by Victor Stinner in branch 'default':
    Issue bpo-22935: Fix test_ssl when the SSLv3 protocol is not supported
    https://hg.python.org/cpython/rev/fb1ffd40d33e

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Dec 12, 2014

    New changeset f0297263a1e8 by Victor Stinner in branch '3.4':
    Issue bpo-22935: Fix test_ssl when the SSLv3 protocol is not supported
    https://hg.python.org/cpython/rev/f0297263a1e8

    @vstinner
    Copy link
    Member

    The changes for 3.4 are incomplete

    Ok, I fixed most obvious issues. There is a major severe issue in Lib/ssl.py:

        def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None):
            ...

    This line fails if PROTOCOL_SSLv3 name does not exist. I propose to use PROTOCOL_SSLv23 by default if PROTOCOL_SSLv3 does not exist, as done in Python 3.5. See attached patch.

    A better option (more secure?) is to use PROTOCOL_SSLv23 by default.

    What do you think? I prefer to switch to PROTOCOL_SSLv23 by default in Python 3.4.

    @vstinner
    Copy link
    Member

    Oh, in Python 3.4, create_default_context() uses PROTOCOL_SSLv23, SSLSocket, wrap_socket() and _create_unverified_context() use PROTOCOL_SSLv23 by default.

    In Python 3.5, get_server_certificate() now uses PROTOCOL_SSLv23 by default because test_ssl failed on the host svn.python.org: see issue bpo-20896.

    changeset: 90360:55f62fa5bebc
    user: Antoine Pitrou <solipsis@pitrou.net>
    date: Wed Apr 16 18:56:28 2014 +0200
    files: Doc/library/ssl.rst Lib/ssl.py Lib/test/test_ssl.py Misc/NEWS
    description:
    Issue bpo-20896: ssl.get_server_certificate() now uses PROTOCOL_SSLv23, not PROTOCOL_SSLv3, for maximum compatibility.

    @vstinner
    Copy link
    Member

    get_server_certificate_sslv23.patch: Patch to use PROTOCOL_SSLv23 by default in get_server_certificate(), as done in Python 2.7 and 3.5.

    @malemburg
    Copy link
    Member

    Please always use PROTOCOL_SSLv23 since this is the only forward compatible way of telling OpenSSL to use the best protocol available.

    Any of the other options such as PROTOCOL_TLSv1 will fix the protocol version to that one protocol version, whereas PROTOCOL_SSLv23 means to use any protocol starting with SSLv2. In the context options you can then disable SSLv2 and SSLv3 to e.g. have the connection use TLS 1.0 or later.

    @kroeckx
    Copy link
    Mannequin Author

    kroeckx mannequin commented Dec 12, 2014

    So this seems to be a function that just gets the certificate? You need to be careful with this since a server could perfectly decide to send a different certificate depending on the client hello it receives. Like if you support ECDSA it might decide to send you the ECDSA certificate instead of the RSA certificate. Or maybe you're even connecting to a different IP address?

    In any case, you should always use SSLv23, stop supporting anything else.

    @vstinner
    Copy link
    Member

    So this seems to be a function that just gets the certificate? You need to be careful with this since a server could perfectly decide to send a different certificate depending on the client hello it receives. (...) In any case, you should always use SSLv23, stop supporting anything else.

    I don't understand. You say that depending on the protocol, you may get a different certificate, and then that we should stop supporting multiple protocol. Does it mean that you ask to remove a Python feature?

    Even if it is technically possible to return a different certificate, I don't think that much servers will return a different certificate if the client uses SSLv23 instead of SSLv3.

    @vstinner
    Copy link
    Member

    Any of the other options such as PROTOCOL_TLSv1 will fix the protocol version to that one protocol version, whereas PROTOCOL_SSLv23 means to use any protocol starting with SSLv2. In the context options you can then disable SSLv2 and SSLv3 to e.g. have the connection use TLS 1.0 or later.

    get_server_certificate() uses _create_unverified_context() (In Python
    2.7, 3.4 & 3.5) which explicitly disable SSLv2 and SSLv3. I still have
    trouble to understand which protocol will be negociated. We use SSLv3
    and disable SSLv3, so the server can only use SSLv23. Am I right?
    https://docs.python.org/dev/library/ssl.html#ssl.wrap_socket

    @kroeckx
    Copy link
    Mannequin Author

    kroeckx mannequin commented Dec 12, 2014

    SSLv3 does not support the TLS extensions so it's going to send a totally different Client Hello. It will for instance not indicate with elliptic curves it supports. So yes the behavior for SSLv3 and SSLv23 can be totally different. But even with both SSLv23 and a different cipher list you can get a different certificate.

    So what I'm really saying is that if you have an API to get a certificate that creates a new connection and you can set the options for that connection too that you need to document that properly that you might get a different certificate.

    @vstinner
    Copy link
    Member

    Do you have an example of server returning a different certificate depending on the protocol?

    @malemburg
    Copy link
    Member

    STINNER Victor added the comment:

    > Any of the other options such as PROTOCOL_TLSv1 will fix the protocol version to that one protocol version, whereas PROTOCOL_SSLv23 means to use any protocol starting with SSLv2. In the context options you can then disable SSLv2 and SSLv3 to e.g. have the connection use TLS 1.0 or later.

    get_server_certificate() uses _create_unverified_context() (In Python
    2.7, 3.4 & 3.5) which explicitly disable SSLv2 and SSLv3. I still have
    trouble to understand which protocol will be negociated. We use SSLv3
    and disable SSLv3, so the server can only use SSLv23. Am I right?
    https://docs.python.org/dev/library/ssl.html#ssl.wrap_socket

    I'm not sure what OpenSSL will do if you tell it to use protocol
    SSLv3 and then disable this via the options again. This sounds like
    it won't connect at all, since PROTOCOL_SSLv3 means: only support
    SSLv3 :-)

    The logic used for protocol selection in OpenSSL is, well, weird.
    You have the choice between fixing one single protocol version or
    selecting a range and then disabling certain protocol versions
    when configuring the context options.

    FWIW: The ssl_version parameter in _create_unverified_context()
    already uses the correct default; IMO, exposing the parameter
    in get_server_certificate() is fairly useless, unless you want
    to (ab)use the function to test supported protocol versions :-)

    @kroeckx
    Copy link
    Mannequin Author

    kroeckx mannequin commented Dec 12, 2014

    Most such sites actually seem to have dropped support for SSLv3.

    One site where it depends on the cipher string is bugs.cdburnerxp.se

    @ned-deily
    Copy link
    Member

    Setting to release blocker since this needs to be resolved for 3.4.3. FYI, the OS X x86 Tiger 3.4 buildbot has been updated to use a local copy of OpenSSL 1.0.1j with SSLv3 disabled and multiple tests now fail (2.7 and default do not fail, as expected).

    http://buildbot.python.org/all/builders/x86%20Tiger%203.4

    @vstinner
    Copy link
    Member

    vstinner commented Jan 5, 2015

    I'm going to commit get_server_certificate_sslv23.patch into Python 3.4, so Python 3.4 will just behave like Python 2.7 and 3.5, except if someone complains :-)

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Jan 6, 2015

    New changeset a8c4925e2359 by Victor Stinner in branch '3.4':
    Issue bpo-20896, bpo-22935: The ssl.get_server_certificate() function now uses the
    https://hg.python.org/cpython/rev/a8c4925e2359

    @vstinner
    Copy link
    Member

    vstinner commented Jan 6, 2015

    Ok, I commited my change to Python 3.4. I'm now waiting for the following buildbot before closing the issue:
    http://buildbot.python.org/all/builders/x86%20Tiger%203.4

    @vstinner
    Copy link
    Member

    vstinner commented Jan 6, 2015

    I'm now waiting for the following buildbot before closing the issue:
    http://buildbot.python.org/all/builders/x86%20Tiger%203.4

    Before my change, test_ssl because with "NameError: name 'PROTOCOL_SSLv3' is not defined". With my change, test_ssl now pass. I close the issue.

    Python 2.7, 3.4 and 3.5 all now have the same behaviour.

    @vstinner vstinner closed this as completed Jan 6, 2015
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    build The build process and cross-build release-blocker
    Projects
    None yet
    Development

    No branches or pull requests

    6 participants