Using TLS1.2 with ftplib in python 2.7.* - python

I need to connect to a ftp server which requires TLS 1.2
the ftplib has an object called FTP_TLS.ssl_version but I can't choose ssl.PROTOCOL_TLSv1_2 because its available only in Python 3.4 and will be available at python 2.7.9 which is not released as of this post.
There is no way I can change my program to use Python 3.4 so what are my options?

One could assume that the default should already be to connect with the best TLS version possible. An explicit setting to TLS1.2 just means, that the client will not accept anything below TLS1.2 back from the server.
Unfortunately ftplib decided to hard code the version to TLSv1 and thus reduce the connection to TLS 1.0 even if the OpenSSL would support better versions. Since there is no way with older python versions to explicitly request TLS 1.1 or TLS 1.2 you need to request SSLv23 which automatically requests the best version possible:
import ssl
from ftplib import FTP_TLS
ftps = FTP_TLS('127.0.0.1')
## set protocol to SSLv23 to request best version
ftps.ssl_version = ssl.PROTOCOL_SSLv23;
ftps.login()
ftps.prot_p()
ftps.retrlines('LIST')
ftps.quit()
The only change to normal use of ftplib is to set ssl_version to ssl.PROTOCOL_SSLv23 and thus it will request the best version possible. If this will be TLS 1.2 depends on the server and on the supported versions in the client. With Ubuntu TLS 1.2 is disabled on the client side up to version 13.10, so it will use at most TLS 1.1. With Ubuntu 14.04 it will use TLS 1.2 if the server supports it.
A side effect of this change is that it will not send an AUTH TLS command to the FTP server, but instead the older AUTH SSL command, but most servers will probably not care. Another side effect is that it will also allow TLS 1.0 or SSL 3.0 if the server does not support anything better. If you don't want this you have to fiddle with the SSL context options, but it looks like this is only available with python3.

Related

How does urllib3 determine which TLS extensions to use?

I'd like to modify the Extensions that I send in the client Hello packet with python.
I've had a read of most of the source code found on GitHub for urllib3 but I still don't know how it determines which TLS extensions to use.
I am aware that it will be quite low level and the creators of urllib3 may just import another package to do this for them. If this is the case, which package do they use?
If not, how is this determined?
Thanks in advance for any assistance.
The HTTPS support in urllib3 uses the ssl package which uses the openssl C-library. ssl does not provide any way to directly fiddle with the TLS extension except for setting the hostname in the TLS handshake (i.e. server_name extension aka SNI).

Get available SSL/TLS protocols in Python 2.7

Avoiding trial-and-error, I would like to list which TLS/SSL protocols are available for use on the system (in a cross-platform way).
Python ssl module offers constants such as:
ssl.PROTOCOL_SSLv2
But these do not say anything about what the system actually supports when connecting to a server.
Additionally, is there a way to get from an SSLContext the supported protocols that will be used?
For example SSLv2 and SSLv3 are disabled when using ssl.create_default_contex(), would it be possible to somehow parse the SSLContext.options to list which protocols are supported?
EDIT:
For example on the latest Debian TLSv1 is disabled and connecting to TLSv1-only hosts will fail, yet ssl.PROTOCOL_TLSv1 is still available and also creating ssl.SSLContext(ssl.PROTOCOL_TLSv1) works.

Change SSL Protocol Torndao 2.3/Python 2.6

I'm running an older version of python (2.6) and tornado (2.3). In my program I have an instance of HTTPClient running fetch() requesting an https url on facebook. However, it's trying to make the request over SSLv3. Since Facebook disabled SSLv3 when POODLE happened, the request is throwing a handshake failure.
I can't figure out where to change the protocol, if I even can. Is there any way I can change it to use TLS with these older versions? This is a legacy application that I was just given to fix asap, so I'm not sure of the implication of updating any of the libraries.
Heres the error I'm receiving:
SSL Error on 16: [Errno 1] _ssl.c:492: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
Thanks!
In the end, I ended up upgrading tornado to version 3.2 since there was a change made to simple_httpclient that changed it's protocol from sslv3 to tlsv1, as stated here http://tornado.readthedocs.org/en/latest/releases/v3.2.0.html#tornado-simple-httpclient

How to disable SNI in Python Requests?

I'm attempting to use requests to access a remote server over SSL. Unfortunately it's misconfigured such that it responds with the error TLSV1_UNRECOGNIZED_NAME during the SNI handshake, which is ignored by browsers but raises an exception in requests.
This appears to be the same issue as this question, but in Python rather than Java: SSL handshake alert: unrecognized_name error since upgrade to Java 1.7.0`
The connection works perfectly in Python 2, which doesn't support SNI. How can I disable SNI in Python 3 so that the connection works?
I couldn't find a way to disable SNI on the requests level, but I found a hack that will trick it into thinking SNI isn't supported. Add this code before importing requests (not after, or it will be too late):
import ssl
ssl.HAS_SNI = False

patching python eventlet to workaround OpenSSL TLS 1.1 bug in Ubuntu 12.04

I've just ran into a bug in OpenSSL in Ubuntu 12.04 with TLS connections and I need to workaround it.
Bug brief - on Ubuntu 12.04 bug in OpenSSL implementation makes various calls to HTTPS with TLS 1.1 fail randomly.
The usual python workaround is also provided on that link above, and it basically enforces TLS 1.0 to be used instead of TLS 1.1. Yet that workaround doesn't work for me out of the box because I'm using eventlet lib that implements non-blocking HTTP requests.
As I understand - eventlet library redefines some classes related to the matter and particularly - the httplib.HTTPSConnection class that I need to patch to enforce TLS 1.0.
So the question is - what exactly I need to patch in eventlet or what to redefine to enforce TLS 1.0 connection for non-blocking HTTP calls via eventlet?
First, you should upgrade eventlet. As of 2013-09, the latest release is 0.14 and we have large number of bugs fixed since 0.9.16.
Second, the solution provided there is a bit too complicated and only fixes httplib. If they provided solution for ssl, it would also fix HTTPS and work with eventlet.
Here's a simpler version for Python 2.6+ that fixes all SSL sockets:
import functools
import ssl
old_init = ssl.SSLSocket.__init__
#functools.wraps(old_init)
def ubuntu_openssl_bug_965371(self, *args, **kwargs):
kwargs['ssl_version'] = ssl.PROTOCOL_TLSv1
old_init(self, *args, **kwargs)
ssl.SSLSocket.__init__ = ubuntu_openssl_bug_965371
I don't have access to broken system right now, so I can't really test it. Does not break good version of openssl.
A simple fix that worked for me was to override SSL's default protocol:
import ssl
ssl.PROTOCOL_SSLv23 = ssl.PROTOCOL_TLSv1

Categories

Resources