1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
From 5bedf76da0f76ab2d489972055a5d62066013427 Mon Sep 17 00:00:00 2001
From: Ian Stapleton Cordasco <graffatcolmingov@gmail.com>
Date: Sun, 3 Mar 2024 07:00:49 -0600
Subject: [PATCH] Use TLS settings in selecting connection pool
Previously, if someone made a request with `verify=False` then made a
request where they expected verification to be enabled to the same host,
they would potentially reuse a connection where TLS had not been
verified.
This fixes that issue.
Upstream-Status: Backport
[https://github.com/psf/requests/commit/a58d7f2ffb4d00b46dca2d70a3932a0b37e22fac]
CVE: CVE-2024-35195
Signed-off-by: Jiaying Song <jiaying.song.cn@windriver.com>
---
requests/adapters.py | 58 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 57 insertions(+), 1 deletion(-)
diff --git a/requests/adapters.py b/requests/adapters.py
index fe22ff4..7ff6998 100644
--- a/requests/adapters.py
+++ b/requests/adapters.py
@@ -10,6 +10,7 @@ and maintain connections.
import os.path
import socket
+import typing
from urllib3.poolmanager import PoolManager, proxy_from_url
from urllib3.response import HTTPResponse
@@ -47,12 +48,38 @@ except ImportError:
def SOCKSProxyManager(*args, **kwargs):
raise InvalidSchema("Missing dependencies for SOCKS support.")
+if typing.TYPE_CHECKING:
+ from .models import PreparedRequest
+
+
DEFAULT_POOLBLOCK = False
DEFAULT_POOLSIZE = 10
DEFAULT_RETRIES = 0
DEFAULT_POOL_TIMEOUT = None
+def _urllib3_request_context(
+ request: "PreparedRequest", verify: "bool | str | None"
+) -> "(typing.Dict[str, typing.Any], typing.Dict[str, typing.Any])":
+ host_params = {}
+ pool_kwargs = {}
+ parsed_request_url = urlparse(request.url)
+ scheme = parsed_request_url.scheme.lower()
+ port = parsed_request_url.port
+ cert_reqs = "CERT_REQUIRED"
+ if verify is False:
+ cert_reqs = "CERT_NONE"
+ if isinstance(verify, str):
+ pool_kwargs["ca_certs"] = verify
+ pool_kwargs["cert_reqs"] = cert_reqs
+ host_params = {
+ "scheme": scheme,
+ "host": parsed_request_url.hostname,
+ "port": port,
+ }
+ return host_params, pool_kwargs
+
+
class BaseAdapter(object):
"""The Base Transport Adapter"""
@@ -290,6 +317,35 @@ class HTTPAdapter(BaseAdapter):
return response
+ def _get_connection(self, request, verify, proxies=None):
+ # Replace the existing get_connection without breaking things and
+ # ensure that TLS settings are considered when we interact with
+ # urllib3 HTTP Pools
+ proxy = select_proxy(request.url, proxies)
+ try:
+ host_params, pool_kwargs = _urllib3_request_context(request, verify)
+ except ValueError as e:
+ raise InvalidURL(e, request=request)
+ if proxy:
+ proxy = prepend_scheme_if_needed(proxy, "http")
+ proxy_url = parse_url(proxy)
+ if not proxy_url.host:
+ raise InvalidProxyURL(
+ "Please check proxy URL. It is malformed "
+ "and could be missing the host."
+ )
+ proxy_manager = self.proxy_manager_for(proxy)
+ conn = proxy_manager.connection_from_host(
+ **host_params, pool_kwargs=pool_kwargs
+ )
+ else:
+ # Only scheme should be lower case
+ conn = self.poolmanager.connection_from_host(
+ **host_params, pool_kwargs=pool_kwargs
+ )
+
+ return conn
+
def get_connection(self, url, proxies=None):
"""Returns a urllib3 connection for the given URL. This should not be
called from user code, and is only exposed for use when subclassing the
@@ -410,7 +466,7 @@ class HTTPAdapter(BaseAdapter):
"""
try:
- conn = self.get_connection(request.url, proxies)
+ conn = self._get_connection(request, verify, proxies)
except LocationValueError as e:
raise InvalidURL(e, request=request)
--
2.25.1
|