Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSL verification issue with 1.25.4 (via requests) #1682

Closed
sbstp opened this issue Sep 19, 2019 · 29 comments
Closed

SSL verification issue with 1.25.4 (via requests) #1682

sbstp opened this issue Sep 19, 2019 · 29 comments

Comments

@sbstp
Copy link

sbstp commented Sep 19, 2019

Hi! I'm using requests 2.22.0 and urllib3 1.25.4.

In requests, I need to disable certificate verification because we use self signed certificates. I create a Session object and set its verify property to False, which used to worked perfectly fine until urllib3 1.25.4.

This is the stacktrace

venv/lib/python3.6/site-packages/urllib3-1.25.4-py3.6.egg/urllib3/connectionpool.py:672: in urlopen
    chunked=chunked,
venv/lib/python3.6/site-packages/urllib3-1.25.4-py3.6.egg/urllib3/connectionpool.py:376: in _make_request
    self._validate_conn(conn)
venv/lib/python3.6/site-packages/urllib3-1.25.4-py3.6.egg/urllib3/connectionpool.py:994: in _validate_conn
    conn.connect()
venv/lib/python3.6/site-packages/urllib3-1.25.4-py3.6.egg/urllib3/connection.py:394: in connect
    ssl_context=context,
venv/lib/python3.6/site-packages/urllib3-1.25.4-py3.6.egg/urllib3/util/ssl_.py:365: in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
/usr/lib/python3.6/ssl.py:407: in wrap_socket
    _context=self, _session=session)
/usr/lib/python3.6/ssl.py:817: in __init__
    self.do_handshake()
/usr/lib/python3.6/ssl.py:1077: in do_handshake
    self._sslobj.do_handshake()
/usr/lib/python3.6/ssl.py:689: in do_handshake
    self._sslobj.do_handshake()
E   ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852)

During handling of the above exception, another exception occurred:
venv/lib/python3.6/site-packages/requests-2.22.0-py3.6.egg/requests/adapters.py:449: in send
    timeout=timeout
venv/lib/python3.6/site-packages/urllib3-1.25.4-py3.6.egg/urllib3/connectionpool.py:720: in urlopen
    method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2]
venv/lib/python3.6/site-packages/urllib3-1.25.4-py3.6.egg/urllib3/util/retry.py:436: in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
E   urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='udb-config-dev.ubisoft.org', port=443): Max retries exceeded with url: /v1/config/users?name=backend_test_tool (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852)'),))

I tried installing urllib3 1.25.3 and there is no issue. It seems like the SSL error was introduced in 1.25.4.

@sethmlarson
Copy link
Member

I'm unable to reproduce your issue with urllib3 1.25.4 and requests 2.22.0:

>>> import requests
>>> s = requests.Session()
>>> s.verify = False
>>> s.get("https://expired.badssl.com", verify=False)
/tmp/venv/lib/python3.8/site-packages/urllib3/connectionpool.py:997: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  warnings.warn(
<Response [200]>

Could you post a more complete reproducer along with Python version, etc?

@sbstp
Copy link
Author

sbstp commented Sep 19, 2019

Your example doesn't work for me. I tried expired.badssl.com and self-signed.badssl.com.

I'll give you more info about my environment, I'm using Python 3.6.8.

(venv) simon@mint: $ pip freeze
certifi==2019.9.11
chardet==3.0.4
idna==2.8
pkg-resources==0.0.0
requests==2.22.0
urllib3==1.25.4

(venv) simon@mint: $ python --version
Python 3.6.8

(venv) simon@mint: $ cat /etc/os-release 
NAME="Linux Mint"
VERSION="19.1 (Tessa)"
ID=linuxmint
ID_LIKE=ubuntu
PRETTY_NAME="Linux Mint 19.1"
VERSION_ID="19.1"
HOME_URL="https://www.linuxmint.com/"
SUPPORT_URL="https://forums.ubuntu.com/"
BUG_REPORT_URL="http://linuxmint-troubleshooting-guide.readthedocs.io/en/latest/"
PRIVACY_POLICY_URL="https://www.linuxmint.com/"
VERSION_CODENAME=tessa
UBUNTU_CODENAME=bionic

I see that you are using Python 3.8, I'll try reproducing the bug in a docker container with Python 3.8.

@adams-shaun
Copy link

FWIW, we are also having this issue....
latest alpine docker image w/ requests

@dgilland
Copy link

Same issue here. Can reproduce using alpine with:

docker run -it alpine sh -c "apk add python3 && pip3 install requests && python3 -c 'import requests; print(requests.post(\"https://expired.badssl.com\", verify=False))'"

$ docker run -it alpine sh -c "apk add python3 && pip3 install requests && python3 -c 'import requests; print(requests.post(\"https://expired.badssl.com\", verify=False))'"
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz
(1/11) Installing libbz2 (1.0.6-r7)
(2/11) Installing expat (2.2.7-r1)
(3/11) Installing libffi (3.2.1-r6)
(4/11) Installing gdbm (1.13-r1)
(5/11) Installing xz-libs (5.2.4-r0)
(6/11) Installing ncurses-terminfo-base (6.1_p20190518-r0)
(7/11) Installing ncurses-terminfo (6.1_p20190518-r0)
(8/11) Installing ncurses-libs (6.1_p20190518-r0)
(9/11) Installing readline (8.0.0-r0)
(10/11) Installing sqlite-libs (3.28.0-r0)
(11/11) Installing python3 (3.7.3-r0)
Executing busybox-1.30.1-r2.trigger
OK: 69 MiB in 25 packages
Collecting requests
  Downloading https://files.pythonhosted.org/packages/51/bd/23c926cd341ea6b7dd0b2a00aba99ae0f828be89d72b2190f27c11d4b7fb/requests-2.22.0-py2.py3-none-any.whl (57kB)
    100% |████████████████████████████████| 61kB 4.1MB/s
Collecting idna<2.9,>=2.5 (from requests)
  Downloading https://files.pythonhosted.org/packages/14/2c/cd551d81dbe15200be1cf41cd03869a46fe7226e7450af7a6545bfc474c9/idna-2.8-py2.py3-none-any.whl (58kB)
    100% |████████████████████████████████| 61kB 16.0MB/s
Collecting chardet<3.1.0,>=3.0.2 (from requests)
  Downloading https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl (133kB)
    100% |████████████████████████████████| 143kB 10.5MB/s
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 (from requests)
  Downloading https://files.pythonhosted.org/packages/91/0d/7777358f672a14b7ae0dfcd29f949f409f913e0578190d6bfa68eb55864b/urllib3-1.25.4-py2.py3-none-any.whl (125kB)
    100% |████████████████████████████████| 133kB 14.9MB/s
Collecting certifi>=2017.4.17 (from requests)
  Downloading https://files.pythonhosted.org/packages/18/b0/8146a4f8dd402f60744fa380bc73ca47303cccf8b9190fd16a827281eac2/certifi-2019.9.11-py2.py3-none-any.whl (154kB)
    100% |████████████████████████████████| 163kB 17.5MB/s
Installing collected packages: idna, chardet, urllib3, certifi, requests
Successfully installed certifi-2019.9.11 chardet-3.0.4 idna-2.8 requests-2.22.0 urllib3-1.25.4
You are using pip version 19.0.3, however version 19.2.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/urllib3/connectionpool.py", line 672, in urlopen
    chunked=chunked,
  File "/usr/lib/python3.7/site-packages/urllib3/connectionpool.py", line 376, in _make_request
    self._validate_conn(conn)
  File "/usr/lib/python3.7/site-packages/urllib3/connectionpool.py", line 994, in _validate_conn
    conn.connect()
  File "/usr/lib/python3.7/site-packages/urllib3/connection.py", line 394, in connect
    ssl_context=context,
  File "/usr/lib/python3.7/site-packages/urllib3/util/ssl_.py", line 365, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "/usr/lib/python3.7/ssl.py", line 412, in wrap_socket
    session=session
  File "/usr/lib/python3.7/ssl.py", line 853, in _create
    self.do_handshake()
  File "/usr/lib/python3.7/ssl.py", line 1117, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1056)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/requests/adapters.py", line 449, in send
    timeout=timeout
  File "/usr/lib/python3.7/site-packages/urllib3/connectionpool.py", line 720, in urlopen
    method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2]
  File "/usr/lib/python3.7/site-packages/urllib3/util/retry.py", line 436, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='expired.badssl.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1056)')))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.7/site-packages/requests/api.py", line 116, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/usr/lib/python3.7/site-packages/requests/api.py", line 60, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/lib/python3.7/site-packages/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/lib/python3.7/site-packages/requests/sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "/usr/lib/python3.7/site-packages/requests/adapters.py", line 514, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='expired.badssl.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1056)')))

But will pass using python:3.7-alpine with:

docker run -it python:3.7-alpine sh -c "pip3 install requests && python3 -c 'import requests; print(requests.post(\"https://expired.badssl.com\", verify=False))'"

$ docker run -it python:3.7-alpine sh -c "pip3 install requests && python3 -c 'import requests; print(requests.post(\"https://expired.badssl.com\", verify=False))'"
Collecting requests
  Downloading https://files.pythonhosted.org/packages/51/bd/23c926cd341ea6b7dd0b2a00aba99ae0f828be89d72b2190f27c11d4b7fb/requests-2.22.0-py2.py3-none-any.whl (57kB)
     |████████████████████████████████| 61kB 3.8MB/s
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 (from requests)
  Downloading https://files.pythonhosted.org/packages/91/0d/7777358f672a14b7ae0dfcd29f949f409f913e0578190d6bfa68eb55864b/urllib3-1.25.4-py2.py3-none-any.whl (125kB)
     |████████████████████████████████| 133kB 11.0MB/s
Collecting idna<2.9,>=2.5 (from requests)
  Downloading https://files.pythonhosted.org/packages/14/2c/cd551d81dbe15200be1cf41cd03869a46fe7226e7450af7a6545bfc474c9/idna-2.8-py2.py3-none-any.whl (58kB)
     |████████████████████████████████| 61kB 15.6MB/s
Collecting chardet<3.1.0,>=3.0.2 (from requests)
  Downloading https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl (133kB)
     |████████████████████████████████| 143kB 17.7MB/s
Collecting certifi>=2017.4.17 (from requests)
  Downloading https://files.pythonhosted.org/packages/18/b0/8146a4f8dd402f60744fa380bc73ca47303cccf8b9190fd16a827281eac2/certifi-2019.9.11-py2.py3-none-any.whl (154kB)
     |████████████████████████████████| 163kB 18.1MB/s
Installing collected packages: urllib3, idna, chardet, certifi, requests
Successfully installed certifi-2019.9.11 chardet-3.0.4 idna-2.8 requests-2.22.0 urllib3-1.25.4
/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py:1004: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning,
<Response [405]>

@sethmlarson
Copy link
Member

So does this issue only affect 3.6? I'll try on different Python versions.

@sethmlarson
Copy link
Member

sethmlarson commented Sep 19, 2019

Python 3.5.7 works for me but Python 3.6.9 does not work but then Python 3.7.4 works again.

@adams-shaun
Copy link

Hmmm, was seeing this issue w/ 3.7.3

Python version: 3.7.3 (default, May 3 2019, 11:24:39) [GCC 8.3.0]

@pxtxs
Copy link

pxtxs commented Sep 19, 2019

I have the same problem in the exact same environment !!

@dgilland
Copy link

dgilland commented Sep 19, 2019

Found that python:3.7.3-alpine fails while python:3.7.4-alpine passes:

  • python:3.7.4-alpine:
$ docker run -it python:3.7.4-alpine sh -c "pip3 install requests && python3 -c 'import requests; print(requests.post(\"https://expired.badssl.com\", verify=False))'"
Unable to find image 'python:3.7.4-alpine' locally
3.7.4-alpine: Pulling from library/python
Digest: sha256:9363cb46e52894a22ba87ebec0845d30f4c27efd6b907705ba9a27192b45e797
Status: Downloaded newer image for python:3.7.4-alpine
Collecting requests
  Downloading https://files.pythonhosted.org/packages/51/bd/23c926cd341ea6b7dd0b2a00aba99ae0f828be89d72b2190f27c11d4b7fb/requests-2.22.0-py2.py3-none-any.whl (57kB)
     |████████████████████████████████| 61kB 3.8MB/s
Collecting chardet<3.1.0,>=3.0.2 (from requests)
  Downloading https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl (133kB)
     |████████████████████████████████| 143kB 11.8MB/s
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 (from requests)
  Downloading https://files.pythonhosted.org/packages/91/0d/7777358f672a14b7ae0dfcd29f949f409f913e0578190d6bfa68eb55864b/urllib3-1.25.4-py2.py3-none-any.whl (125kB)
     |████████████████████████████████| 133kB 18.1MB/s
Collecting certifi>=2017.4.17 (from requests)
  Downloading https://files.pythonhosted.org/packages/18/b0/8146a4f8dd402f60744fa380bc73ca47303cccf8b9190fd16a827281eac2/certifi-2019.9.11-py2.py3-none-any.whl (154kB)
     |████████████████████████████████| 163kB 21.6MB/s
Collecting idna<2.9,>=2.5 (from requests)
  Downloading https://files.pythonhosted.org/packages/14/2c/cd551d81dbe15200be1cf41cd03869a46fe7226e7450af7a6545bfc474c9/idna-2.8-py2.py3-none-any.whl (58kB)
     |████████████████████████████████| 61kB 10.6MB/s
Installing collected packages: chardet, urllib3, certifi, idna, requests
Successfully installed certifi-2019.9.11 chardet-3.0.4 idna-2.8 requests-2.22.0 urllib3-1.25.4
/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py:1004: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning,
<Response [405]>
  • python:3.7.3-alpine
$ docker run -it python:3.7.3-alpine sh -c "pip3 install requests && python3 -c 'import requests; print(requests.post(\"https://expired.badssl.com\", verify=False))'"
Unable to find image 'python:3.7.3-alpine' locally
3.7.3-alpine: Pulling from library/python
921b31ab772b: Pull complete
1a0c422ed526: Pull complete
ec0818a7bbe4: Pull complete
b53197ee35ff: Pull complete
8b25717b4dbf: Pull complete
Digest: sha256:93b2b24b95cf74229b41237126e22420580f05f51c76de015986fbd79d8d7e42
Status: Downloaded newer image for python:3.7.3-alpine
Collecting requests
  Downloading https://files.pythonhosted.org/packages/51/bd/23c926cd341ea6b7dd0b2a00aba99ae0f828be89d72b2190f27c11d4b7fb/requests-2.22.0-py2.py3-none-any.whl (57kB)
     |████████████████████████████████| 61kB 4.0MB/s
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 (from requests)
  Downloading https://files.pythonhosted.org/packages/91/0d/7777358f672a14b7ae0dfcd29f949f409f913e0578190d6bfa68eb55864b/urllib3-1.25.4-py2.py3-none-any.whl (125kB)
     |████████████████████████████████| 133kB 11.3MB/s
Collecting certifi>=2017.4.17 (from requests)
  Downloading https://files.pythonhosted.org/packages/18/b0/8146a4f8dd402f60744fa380bc73ca47303cccf8b9190fd16a827281eac2/certifi-2019.9.11-py2.py3-none-any.whl (154kB)
     |████████████████████████████████| 163kB 10.4MB/s
Collecting chardet<3.1.0,>=3.0.2 (from requests)
  Downloading https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl (133kB)
     |████████████████████████████████| 143kB 15.5MB/s
Collecting idna<2.9,>=2.5 (from requests)
  Downloading https://files.pythonhosted.org/packages/14/2c/cd551d81dbe15200be1cf41cd03869a46fe7226e7450af7a6545bfc474c9/idna-2.8-py2.py3-none-any.whl (58kB)
     |████████████████████████████████| 61kB 20.7MB/s
Installing collected packages: urllib3, certifi, chardet, idna, requests
Successfully installed certifi-2019.9.11 chardet-3.0.4 idna-2.8 requests-2.22.0 urllib3-1.25.4
WARNING: You are using pip version 19.1.1, however version 19.2.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 672, in urlopen
    chunked=chunked,
  File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 376, in _make_request
    self._validate_conn(conn)
  File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 994, in _validate_conn
    conn.connect()
  File "/usr/local/lib/python3.7/site-packages/urllib3/connection.py", line 394, in connect
    ssl_context=context,
  File "/usr/local/lib/python3.7/site-packages/urllib3/util/ssl_.py", line 365, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "/usr/local/lib/python3.7/ssl.py", line 412, in wrap_socket
    session=session
  File "/usr/local/lib/python3.7/ssl.py", line 853, in _create
    self.do_handshake()
  File "/usr/local/lib/python3.7/ssl.py", line 1117, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1056)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/requests/adapters.py", line 449, in send
    timeout=timeout
  File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 720, in urlopen
    method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2]
  File "/usr/local/lib/python3.7/site-packages/urllib3/util/retry.py", line 436, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='expired.badssl.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1056)')))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/requests/api.py", line 116, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/requests/api.py", line 60, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.7/site-packages/requests/sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/requests/adapters.py", line 514, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='expired.badssl.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1056)')))

@sethmlarson
Copy link
Member

Yep, I'm seeing the same thing @dgilland. Looks like we have something to go on :)

@sbstp
Copy link
Author

sbstp commented Sep 19, 2019

I tried using the debian-based Python image on DockerHub, I do not get the bug with 3.8-rc or 3.7.x.
I get it in 3.6.9 which is the latest version in the 3.6 branch, but not anything below it. Which is weird because my OS has 3.6.8 and I get the bug there.

I get with with 3.6.8-alpine but not 3.6.8-stretch, maybe the Debian base image has patched something?

@sethmlarson
Copy link
Member

So I have a script here:

import requests
s = requests.Session()
s.verify = False
try:
    s.request("GET", "https://expired.badssl.com")
except Exception as e:
    print(e)
pools = s.adapters["https://"].poolmanager.pools
key = pools.keys()[0]
cp = pools[key]
conn = cp._get_conn()
try:
    conn.connect()
except Exception as e:
    print(e)
print(conn.ssl_context.verify_mode, conn.ssl_context.check_hostname)

Which makes the request then goes down into the urllib3 poolmanager and inspects a single connection's SSLContext object. On both working and non-working versions I'm getting the expected values CERT_NONE for verify_mode and False for check_hostname. I'm not sure where to go from there.

@sethmlarson
Copy link
Member

sethmlarson commented Sep 19, 2019

I discovered the issue, it's this line here within create_urllib3_context():

    # Enable post-handshake authentication for TLS 1.3, see GH #1634. PHA is
    # necessary for conditional client cert authentication with TLS 1.3.
    # The attribute is None for OpenSSL <= 1.1.0 or does not exist in older
    # versions of Python.
    if getattr(context, "post_handshake_auth", None) is not None:
        context.post_handshake_auth = True

@tiran Is this a bug that setting this value to True will make verification of server certificates be on instead of disabled?

@tiran
Copy link
Contributor

tiran commented Sep 19, 2019

It's a bug in old versions of Python that only occurs when Python's ssl module is compiled with OpenSSL 1.1.1. The problem is fixed in recent versions:

  • Python 2.7 and 3.5 are not affected because they don't support PHA
  • Python 3.6 is affected and cannot be fixed, because 3.6 in security bug-only mode.
  • Python 3.7.4 is fixed. 3.7.3 and earlier are affected.
  • 3.8-beta is fine.

@sethmlarson
Copy link
Member

Perhaps we won't enable the flag unless we have certificate verification enabled. I can't think of a world where you want to use a client cert and disable server cert verification.

@tiran
Copy link
Contributor

tiran commented Sep 19, 2019

Guess how I found the bug in Python's ssl module. It's exactly that world...

@sethmlarson
Copy link
Member

Noooo :-( What heuristic should I use to not set that flag? If verify is set to CERT_NONE should I skip trying to set it all together? It's an optional behavior and the client cert is still sent, just a larger handshake?

@tiran
Copy link
Contributor

tiran commented Sep 19, 2019

if CERT_REQUIRED or sys.version_info > (3, 7, 4) ?

@sethmlarson
Copy link
Member

This is closed in v1.25.5.

@sbstp
Copy link
Author

sbstp commented Sep 20, 2019

Thanks everyone for the quick resolution!

abadger added a commit to abadger/ansible that referenced this issue Sep 20, 2019
urllib3-1.25.4 breaks k8s due to this bug:
urllib3/urllib3#1682
abadger added a commit to abadger/ansible that referenced this issue Sep 20, 2019
urllib3-1.25.4 breaks k8s due to this bug:
urllib3/urllib3#1682
(cherry picked from commit d3dfea9)

Co-authored-by: Toshio Kuratomi <a.badger@gmail.com>
@AyJayHam
Copy link

AyJayHam commented Nov 4, 2019

So as it seems for me it is not fixxed in 1.25.5 nor 1.25.6 for ubuntu systems.
If verification is active it throws on certain sites the following missing certi: _ssl.c:1056.
if i enable vertification again it works.

It works on Windows but not on Ubuntu. Both running Py 3.7.3

@mukteshkrmishra
Copy link

This still exists in python 3.7..6.

@mkmozgawa
Copy link

Still exists in Python 3.8.5 (via gql that uses urllib3 1.25.8)

@sethmlarson
Copy link
Member

@mkmozgawa You'll have to be more specific about your environment as I wasn't able to reproduce on Linux + Python 3.8.5 and OpenSSL 1.1.1d. Could you run this script and provide me the output:

import ssl
import platform
import requests
import urllib3

print("OS", platform.system(), platform.version())
print("Python", platform.python_version())
print("OpenSSL", ssl.OPENSSL_VERSION)
print("Requests", requests.__version__)
print("Urllib3", urllib3.__version__)

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
s = requests.Session()
s.verify = False
try:
    s.request("GET", "https://expired.badssl.com")
except Exception as e:
    print("Issue detected")
    print(e)
else:
    print("Issue not detected")

pools = s.adapters["https://"].poolmanager.pools
key = pools.keys()[0]
cp = pools[key]
conn = cp._get_conn()
print("SSLContext", conn.ssl_context.verify_mode, conn.ssl_context.check_hostname)

For me this outputs:

OS Linux #46~18.04.1-Ubuntu SMP Fri Jul 10 07:21:24 UTC 2020
Python 3.8.5
OpenSSL OpenSSL 1.1.1d  10 Sep 2019
Requests 2.24.0
Urllib3 1.25.10
Issue not detected
SSLContext VerifyMode.CERT_NONE False

@mkmozgawa
Copy link

Hi @sethmlarson, thanks for your quick response. I ran your script and it seems that the output here is as expected:

OS Darwin Darwin Kernel Version 18.7.0
Python 3.8.5
OpenSSL OpenSSL 1.1.1g  21 Apr 2020
Requests 2.24.0
Urllib3 1.25.10
Issue not detected
SSLContext VerifyMode.CERT_NONE False

Seems like it's another issue on my side, then. Thank you for your help.

@ahills
Copy link

ahills commented May 24, 2021

This appeared again on Python 3.8.6 with OpenSSL 1.1.1g (el8):

OS Linux #1 SMP Tue Apr 13 18:55:45 EDT 2021
Python 3.8.6
OpenSSL OpenSSL 1.1.1g FIPS  21 Apr 2020
Requests 2.25.1
Urllib3 1.26.4
Issue detected
HTTPSConnectionPool(host='expired.badssl.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1124)')))
Traceback (most recent call last):
  File "/usr/local/bin/python-urllib-ssl.py", line 30, in <module>
    print("SSLContext", conn.ssl_context.verify_mode, conn.ssl_context.check_hostname)
AttributeError: 'NoneType' object has no attribute 'verify_mode'

And on Python 3.9.5 with OpenSSL 1.1.1k (Fedora 34):

OS Linux #1-Alpine SMP Tue, 04 May 2021 23:08:11 +0000
Python 3.9.5
OpenSSL OpenSSL 1.1.1k  FIPS 25 Mar 2021
Requests 2.25.1
Urllib3 1.26.4
Issue detected
HTTPSConnectionPool(host='expired.badssl.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1129)')))
Traceback (most recent call last):
  File "/usr/local/bin/python-urllib-ssl.py", line 30, in <module>
    print("SSLContext", conn.ssl_context.verify_mode, conn.ssl_context.check_hostname)
AttributeError: 'NoneType' object has no attribute 'verify_mode'

@sethmlarson
Copy link
Member

@ahills Can't help but notice both of those OpenSSL versions you posted are FIPS, could that have something to do with it? Also it looks like conn.ssl_context is None in those examples too, wonder how that happened?

@pghole
Copy link

pghole commented Jul 15, 2021

@SethMichaelLarson I still see this issue on requests version 2.20.0, urllib3 version - 1.24.2, OpenSSL 1.1.1 FIPS and python3.6.8

@sethmlarson
Copy link
Member

@pghole @ahills Could one of you open a separate issue for FIPS and using the latest version of urllib3? We're not going to be making releases to 1.24.x. This will take someone investigating. Until then I'm locking this issue as it's been resolved, what you're seeing is likely not the same issue.

@urllib3 urllib3 locked as resolved and limited conversation to collaborators Jul 15, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests