summaryrefslogtreecommitdiffstats
path: root/meta-python/recipes-devtools/python/python3-twisted
diff options
context:
space:
mode:
Diffstat (limited to 'meta-python/recipes-devtools/python/python3-twisted')
-rw-r--r--meta-python/recipes-devtools/python/python3-twisted/CVE-2023-46137.patch196
1 files changed, 196 insertions, 0 deletions
diff --git a/meta-python/recipes-devtools/python/python3-twisted/CVE-2023-46137.patch b/meta-python/recipes-devtools/python/python3-twisted/CVE-2023-46137.patch
new file mode 100644
index 0000000000..d504448885
--- /dev/null
+++ b/meta-python/recipes-devtools/python/python3-twisted/CVE-2023-46137.patch
@@ -0,0 +1,196 @@
1From 1e6e9d23cac59689760558dcb6634285e694b04c Mon Sep 17 00:00:00 2001
2From: Glyph <glyph@twistedmatrix.com>
3Date: Tue Sep 12 11:32:55 2023 -0700
4Subject: [PATCH] 11976 stop processing pipelined HTTP/1.1 requests that are
5 received together (#11979)
6
7CVE: CVE-2023-46137
8
9Upstream-Status: Backport [https://github.com/twisted/twisted/commit/1e6e9d23cac59689760558dcb6634285e694b04c]
10
11Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
12---
13 src/twisted/web/http.py | 32 +++++++--
14 src/twisted/web/newsfragments/11976.bugfix | 7 ++
15 src/twisted/web/test/test_web.py | 81 +++++++++++++++++++++-
16 3 files changed, 114 insertions(+), 6 deletions(-)
17 create mode 100644 src/twisted/web/newsfragments/11976.bugfix
18
19diff --git a/src/twisted/web/http.py b/src/twisted/web/http.py
20index 96a1335..b99480f 100644
21--- a/src/twisted/web/http.py
22+++ b/src/twisted/web/http.py
23@@ -2366,14 +2366,38 @@ class HTTPChannel(basic.LineReceiver, policies.TimeoutMixin):
24
25 self._handlingRequest = True
26
27+ # We go into raw mode here even though we will be receiving lines next
28+ # in the protocol; however, this data will be buffered and then passed
29+ # back to line mode in the setLineMode call in requestDone.
30+ self.setRawMode()
31+
32 req = self.requests[-1]
33 req.requestReceived(command, path, version)
34
35- def dataReceived(self, data):
36+ def rawDataReceived(self, data: bytes) -> None:
37 """
38- Data was received from the network. Process it.
39+ This is called when this HTTP/1.1 parser is in raw mode rather than
40+ line mode.
41+
42+ It may be in raw mode for one of two reasons:
43+
44+ 1. All the headers of a request have been received and this
45+ L{HTTPChannel} is currently receiving its body.
46+
47+ 2. The full content of a request has been received and is currently
48+ being processed asynchronously, and this L{HTTPChannel} is
49+ buffering the data of all subsequent requests to be parsed
50+ later.
51+
52+ In the second state, the data will be played back later.
53+
54+ @note: This isn't really a public API, and should be invoked only by
55+ L{LineReceiver}'s line parsing logic. If you wish to drive an
56+ L{HTTPChannel} from a custom data source, call C{dataReceived} on
57+ it directly.
58+
59+ @see: L{LineReceive.rawDataReceived}
60 """
61- # If we're currently handling a request, buffer this data.
62 if self._handlingRequest:
63 self._dataBuffer.append(data)
64 if (
65@@ -2385,9 +2409,7 @@ class HTTPChannel(basic.LineReceiver, policies.TimeoutMixin):
66 # ready. See docstring for _optimisticEagerReadSize above.
67 self._networkProducer.pauseProducing()
68 return
69- return basic.LineReceiver.dataReceived(self, data)
70
71- def rawDataReceived(self, data):
72 self.resetTimeout()
73
74 try:
75diff --git a/src/twisted/web/newsfragments/11976.bugfix b/src/twisted/web/newsfragments/11976.bugfix
76new file mode 100644
77index 0000000..8ac292b
78--- /dev/null
79+++ b/src/twisted/web/newsfragments/11976.bugfix
80@@ -0,0 +1,7 @@
81+In Twisted 16.3.0, we changed twisted.web to stop dispatching HTTP/1.1
82+pipelined requests to application code. There was a bug in this change which
83+still allowed clients which could send multiple full HTTP requests in a single
84+TCP segment to trigger asynchronous processing of later requests, which could
85+lead to out-of-order responses. This has now been corrected and twisted.web
86+should never process a pipelined request over HTTP/1.1 until the previous
87+request has fully completed.
88diff --git a/src/twisted/web/test/test_web.py b/src/twisted/web/test/test_web.py
89index 3eb35a9..b2b2ad7 100644
90--- a/src/twisted/web/test/test_web.py
91+++ b/src/twisted/web/test/test_web.py
92@@ -8,6 +8,7 @@ Tests for various parts of L{twisted.web}.
93 import os
94 import zlib
95 from io import BytesIO
96+from typing import List
97
98 from zope.interface import implementer
99 from zope.interface.verify import verifyObject
100@@ -17,10 +18,13 @@ from twisted.internet.address import IPv4Address, IPv6Address
101 from twisted.internet.task import Clock
102 from twisted.logger import LogLevel, globalLogPublisher
103 from twisted.python import failure, reflect
104+from twisted.python.compat import iterbytes
105 from twisted.python.filepath import FilePath
106-from twisted.test.proto_helpers import EventLoggingObserver
107+from twisted.test.proto_helpers import EventLoggingObserver, StringTransport
108 from twisted.trial import unittest
109 from twisted.web import error, http, iweb, resource, server
110+from twisted.web.resource import Resource
111+from twisted.web.server import NOT_DONE_YET, Request, Site
112 from twisted.web.static import Data
113 from twisted.web.test.requesthelper import DummyChannel, DummyRequest
114 from ._util import assertIsFilesystemTemporary
115@@ -1849,3 +1853,78 @@ class ExplicitHTTPFactoryReactor(unittest.TestCase):
116
117 factory = http.HTTPFactory()
118 self.assertIs(factory.reactor, reactor)
119+
120+
121+class QueueResource(Resource):
122+ """
123+ Add all requests to an internal queue,
124+ without responding to the requests.
125+ You can access the requests from the queue and handle their response.
126+ """
127+
128+ isLeaf = True
129+
130+ def __init__(self) -> None:
131+ super().__init__()
132+ self.dispatchedRequests: List[Request] = []
133+
134+ def render_GET(self, request: Request) -> int:
135+ self.dispatchedRequests.append(request)
136+ return NOT_DONE_YET
137+
138+
139+class TestRFC9112Section932(unittest.TestCase):
140+ """
141+ Verify that HTTP/1.1 request ordering is preserved.
142+ """
143+
144+ def test_multipleRequestsInOneSegment(self) -> None:
145+ """
146+ Twisted MUST NOT respond to a second HTTP/1.1 request while the first
147+ is still pending.
148+ """
149+ qr = QueueResource()
150+ site = Site(qr)
151+ proto = site.buildProtocol(None)
152+ serverTransport = StringTransport()
153+ proto.makeConnection(serverTransport)
154+ proto.dataReceived(
155+ b"GET /first HTTP/1.1\r\nHost: a\r\n\r\n"
156+ b"GET /second HTTP/1.1\r\nHost: a\r\n\r\n"
157+ )
158+ # The TCP data contains 2 requests,
159+ # but only 1 request was dispatched,
160+ # as the first request was not yet finalized.
161+ self.assertEqual(len(qr.dispatchedRequests), 1)
162+ # The first request is finalized and the
163+ # second request is dispatched right away.
164+ qr.dispatchedRequests[0].finish()
165+ self.assertEqual(len(qr.dispatchedRequests), 2)
166+
167+ def test_multipleRequestsInDifferentSegments(self) -> None:
168+ """
169+ Twisted MUST NOT respond to a second HTTP/1.1 request while the first
170+ is still pending, even if the second request is received in a separate
171+ TCP package.
172+ """
173+ qr = QueueResource()
174+ site = Site(qr)
175+ proto = site.buildProtocol(None)
176+ serverTransport = StringTransport()
177+ proto.makeConnection(serverTransport)
178+ raw_data = (
179+ b"GET /first HTTP/1.1\r\nHost: a\r\n\r\n"
180+ b"GET /second HTTP/1.1\r\nHost: a\r\n\r\n"
181+ )
182+ # Just go byte by byte for the extreme case in which each byte is
183+ # received in a separate TCP package.
184+ for chunk in iterbytes(raw_data):
185+ proto.dataReceived(chunk)
186+ # The TCP data contains 2 requests,
187+ # but only 1 request was dispatched,
188+ # as the first request was not yet finalized.
189+ self.assertEqual(len(qr.dispatchedRequests), 1)
190+ # The first request is finalized and the
191+ # second request is dispatched right away.
192+ qr.dispatchedRequests[0].finish()
193+ self.assertEqual(len(qr.dispatchedRequests), 2)
194--
1952.40.0
196