wolfssl-py icon indicating copy to clipboard operation
wolfssl-py copied to clipboard

Can wolfssl context be used with requests http adaptor?

Open VeNoMouS opened this issue 6 years ago • 4 comments

#!/usr/bin/python3
import requests
import wolfssl

from collections import OrderedDict
from requests.adapters import HTTPAdapter


class CipherSuiteAdapter(HTTPAdapter):

    def __init__(self, **kwargs):

        wolfssl.WolfSSL.enable_debug()
        self.ssl_context = wolfssl.SSLContext(wolfssl.PROTOCOL_TLSv1_2)
        self.ssl_context.verify_mode = wolfssl.CERT_NONE
        self.ssl_context.set_ciphers('ECDHE-RSA-AES128-GCM-SHA256')

        super(CipherSuiteAdapter, self).__init__(**kwargs)

    # ------------------------------------------------------------------------------- #

    def init_poolmanager(self, *args, **kwargs):
        kwargs['ssl_context'] = self.ssl_context
        return super(CipherSuiteAdapter, self).init_poolmanager(*args, **kwargs)

    # ------------------------------------------------------------------------------- #

    def proxy_manager_for(self, *args, **kwargs):
        kwargs['ssl_context'] = self.ssl_context
        return super(CipherSuiteAdapter, self).proxy_manager_for(*args, **kwargs)

# ------------------------------------------------------------------------------- #


session = requests.session()
session.mount('https://', CipherSuiteAdapter())
session.headers = OrderedDict([
    ("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0"),
    ("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"),
    ("Accept-Language", "en-US,en;q=0.5"),
    ("Accept-Encoding", "gzip, deflate")
])

print(session.get('https://somewebsite/', verify=False).status_code)

The following results in..

Traceback (most recent call last):
  File "./wolf.py", line 54, in <module>
    print(session.get('https://somewebsite', verify=False).status_code)
  File "/usr/local/lib/python3.7/dist-packages/requests/sessions.py", line 546, in get
    return self.request('GET', url, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.7/dist-packages/requests/sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/requests/adapters.py", line 449, in send
    timeout=timeout
  File "/usr/local/lib/python3.7/dist-packages/urllib3/connectionpool.py", line 603, in urlopen
    chunked=chunked)
  File "/usr/local/lib/python3.7/dist-packages/urllib3/connectionpool.py", line 344, in _make_request
    self._validate_conn(conn)
  File "/usr/local/lib/python3.7/dist-packages/urllib3/connectionpool.py", line 843, in _validate_conn
    conn.connect()
  File "/usr/local/lib/python3.7/dist-packages/urllib3/connection.py", line 370, in connect
    ssl_context=context)
  File "/usr/local/lib/python3.7/dist-packages/urllib3/util/ssl_.py", line 355, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "/usr/local/lib/python3.7/dist-packages/wolfssl/__init__.py", line 243, in wrap_socket
    _context=self, server_hostname=server_hostname)
  File "/usr/local/lib/python3.7/dist-packages/wolfssl/__init__.py", line 396, in __init__
    self._context.use_sni(server_hostname)
  File "/usr/local/lib/python3.7/dist-packages/wolfssl/__init__.py", line 263, in use_sni
    server_hostname, len(server_hostname))
TypeError: initializer for ctype 'void *' must be a cdata pointer, not str

VeNoMouS avatar Aug 04 '19 04:08 VeNoMouS

applying the PR 8560c6574886669a721a89d89684253ed5bb0e31 we get a new error


Traceback (most recent call last):
  File "./wolf.py", line 54, in <module>
    print(session.get('https://somewebsite', verify=False).status_code)
  File "/usr/local/lib/python3.7/dist-packages/requests/sessions.py", line 546, in get
    return self.request('GET', url, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.7/dist-packages/requests/sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/requests/adapters.py", line 449, in send
    timeout=timeout
  File "/usr/local/lib/python3.7/dist-packages/urllib3/connectionpool.py", line 603, in urlopen
    chunked=chunked)
  File "/usr/local/lib/python3.7/dist-packages/urllib3/connectionpool.py", line 373, in _make_request
    conn.sock.settimeout(read_timeout)
AttributeError: 'SSLSocket' object has no attribute 'settimeout'

VeNoMouS avatar Aug 04 '19 04:08 VeNoMouS

Monkey patching the above, just creates another issue..

    httplib_response = conn.getresponse()
  File "/usr/lib/python3.7/http/client.py", line 1317, in getresponse
    response = self.response_class(self.sock, method=self._method)
  File "/usr/lib/python3.7/http/client.py", line 234, in __init__
    self.fp = sock.makefile("rb")
AttributeError: 'SSLSocket' object has no attribute 'makefile'

So I guess this is not capable of being used in requests ... too many incompatibilities

VeNoMouS avatar Aug 04 '19 05:08 VeNoMouS

Hi @VeNoMouS,

Thank you so much for reaching out to wolfSSL with your questions. For best response times feel free to email us anytime at [email protected].

Can you tell us a bit about the project you are interested in using wolfSSL in and end goals of that project? I can confirm we have not tested using wolfSSL with https://pypi.org/project/requests/ yet. Would you like us to add it to our desired features list?

Desired features are features we work on for free between funded efforts. Desired features have no associated timeline but they can be accelerated at anytime if a need arrises, just let us know you'd like to accelerate a given feature and we can put you in touch with the resources to help get that done!

Warmest Regards,

K

kaleb-himes avatar Dec 11 '19 22:12 kaleb-himes

applying the PR 8560c65 we get a new error

Traceback (most recent call last):
  File "./wolf.py", line 54, in <module>
    print(session.get('https://somewebsite', verify=False).status_code)
  File "/usr/local/lib/python3.7/dist-packages/requests/sessions.py", line 546, in get
    return self.request('GET', url, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.7/dist-packages/requests/sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/requests/adapters.py", line 449, in send
    timeout=timeout
  File "/usr/local/lib/python3.7/dist-packages/urllib3/connectionpool.py", line 603, in urlopen
    chunked=chunked)
  File "/usr/local/lib/python3.7/dist-packages/urllib3/connectionpool.py", line 373, in _make_request
    conn.sock.settimeout(read_timeout)
AttributeError: 'SSLSocket' object has no attribute 'settimeout'

I am trying also to use wolfssl in standard HTTPServer, and received similar error. To correct it, I added missing method to class SSLSocket and rebuilt wolfssl-py: def makefile(self,mode='r', buffering=None, *, encoding=None, errors=None, newline=None): return self._sock.makefile(mode, buffering) After that lib started to work, however, another issue encountered - handshake and writing to socket is performed properly, but reading from socket does not apply ciphering. I think it can be difficult to overcome. It seems that context is properly passed, but when standard socket library is trying to read from buffered I/O, it uses standard socket class instead of WolfSSL socket. I was testing using Python 3.9 and 3.11, not sure if going to higher version would help.

P.S. Apparently, we cannot call self._sock.makefile(), instead a copy of socket.makefile() shall be added and adapted as override method in class SSLSocket

nkosmynin avatar Dec 12 '23 10:12 nkosmynin