Get available SSL/TLS protocols in Python 2.7 - python

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.

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).

Python SSL Error - cert issues vs. SSL disabled

I'm using Python 3.5.2 to create a script to simply check if SSLv3 is enabled on a given host/port. Unfortunately, it seems ssl.SSLContext.wrap_socket() returns the same error
(SSLV3_ALERT_HANDSHAKE_FAILURE)
under the following two conditions:
SSLv3 is disabled on the host or
certificate hostname mismatch or other problems exist.
Is there a way to differentiate these? I don't care about the SNI type problems in the current application. Are there other conditions that will return the same error as well?

Connect to web socket (wss) with standard modules in Python?

I have used Python external package, websocket-client to connect to a RESTful service that sends events.
from websocket import create_connection
ws = create_connection("wss://machine:port/servicename/subscribe")
for event in ws:
print event
...getting events printed
I wonder whether the same functionality can be implemented using the core Python 2.7 or Python 3.5, without installing the external websocket-client package or any other 3rd party Python package.
I have searched the Internet and those examples of code using Python socket module I've seen, refer to connections via http or tcp whereas I need to establish connection via wss.
Very late, but for anyone who might stumble here...Web Sockets protocol is built on TCP so it is expected that implementations of the protocol establish connections via TCP. Also, Web Socket's opening handshake is done following HTTP. This would also explain why Alex saw HTTP connections. If you want to see how to implement one from scratch, install web socket modules (autobahn, which in turn would lead to installing and reading Twisted and asyncio modules, or wampy) and dive into the code. Would recommend reading the Web Sockets protocol specifications at https://www.rfc-editor.org/rfc/rfc6455 before tackling the modules.

Using TLS1.2 with ftplib in python 2.7.*

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.

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

Categories

Resources