Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python requests print used cipher for HTTPS

I have developed a CherryPy REST service with SSL (TLSv1-TLSv1.2) and disabling ciphers and insecure protocols.

Now I have another piece of code using Python requests to connect to this service. I already have written an TLS HTTPAdapter and a request succeeds. I have only one problem:

I neither see what cipher was chosen on server side nor on client side. So in fact, I do not really know, if my security options took place. I could not find out how to get SSLSocket.cipher() from the builtin Python module called for CherryPy or requests.

Is there a simple way to get this information?

Here is an example:

import requests

from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager

class Tlsv1_2HttpAdapter(HTTPAdapter):
    """"Transport adapter" that allows us to use TLSv1.2"""

    def init_poolmanager(self, connections, maxsize, block=False):
        self.poolmanager = PoolManager(
            num_pools=connections, maxsize=maxsize,
            block=block, ssl_version=ssl.PROTOCOL_TLSv1_2)

con = "https://{}:{}".format(host, port)

tls = Tlsv1_2HttpAdapter()

try:
    s = requests.Session()
    s.mount(con, tls)
    r = s.get(con)
except requests.exceptions.SSLError as e:
    print(e, file=sys.stderr)
    sys.exit(1)

I want something like: print("Cipher used: {}".format(foo.cipher()))

Many thanks in advance for your help

like image 896
Christian Rößner Avatar asked Sep 05 '25 05:09

Christian Rößner


1 Answers

As a temporary solution for testing, the code below prints out the cipher suite (position 0) and protocol (position 1) like that:

('ECDHE-RSA-AES256-GCM-SHA384', 'TLSv1/SSLv3', 256)

Python 2.7 (tested):

from httplib import HTTPConnection


def request(self, method, url, body=None, headers={}):
    self._send_request(method, url, body, headers)
    print(self.sock.cipher())

HTTPConnection.request = request

Python 3 (tested on v3.8.9 by comment below):

from http.client import HTTPConnection


def request(self, method, url, body=None, headers={}, *,
            encode_chunked=False):
    self._send_request(method, url, body, headers, encode_chunked)
    print(self.sock.cipher())

HTTPConnection.request = request

This is monkey patching the request() method for the only reason of adding the print statement. You can replace the print function by a debug logger if you want more control over the output.

Import or paste this snippet at the beginning of your code so that it can monkey patch the method as early as possible.

like image 178
Iodnas Avatar answered Sep 07 '25 19:09

Iodnas