Can wolfssl context be used with requests http adaptor?
#!/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
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'
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
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
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