diff options
Diffstat (limited to 'meta/recipes-devtools/python')
5 files changed, 385 insertions, 0 deletions
diff --git a/meta/recipes-devtools/python/python/python-2.7.3-CVE-2013-1752-ftplib-fix.patch b/meta/recipes-devtools/python/python/python-2.7.3-CVE-2013-1752-ftplib-fix.patch new file mode 100644 index 0000000000..97c890e777 --- /dev/null +++ b/meta/recipes-devtools/python/python/python-2.7.3-CVE-2013-1752-ftplib-fix.patch | |||
@@ -0,0 +1,149 @@ | |||
1 | |||
2 | # HG changeset patch | ||
3 | # User Serhiy Storchaka <storchaka@gmail.com> | ||
4 | # Date 1382277427 -10800 | ||
5 | # Node ID 44ac81e6d584758ee56a865a7c18d82505be0643 | ||
6 | # Parent 625ece68d79a27d376889579c414ed4b2d8a2649 | ||
7 | Issue #16038: CVE-2013-1752: ftplib: Limit amount of data read by | ||
8 | limiting the call to readline(). Original patch by Michał | ||
9 | Jastrzębski and Giampaolo Rodola. | ||
10 | |||
11 | diff --git a/Lib/ftplib.py b/Lib/ftplib.py | ||
12 | --- a/Lib/ftplib.py | ||
13 | +++ b/Lib/ftplib.py | ||
14 | @@ -55,6 +55,8 @@ MSG_OOB = 0x1 | ||
15 | |||
16 | # The standard FTP server control port | ||
17 | FTP_PORT = 21 | ||
18 | +# The sizehint parameter passed to readline() calls | ||
19 | +MAXLINE = 8192 | ||
20 | |||
21 | |||
22 | # Exception raised when an error or invalid response is received | ||
23 | @@ -101,6 +103,7 @@ class FTP: | ||
24 | debugging = 0 | ||
25 | host = '' | ||
26 | port = FTP_PORT | ||
27 | + maxline = MAXLINE | ||
28 | sock = None | ||
29 | file = None | ||
30 | welcome = None | ||
31 | @@ -180,7 +183,9 @@ class FTP: | ||
32 | # Internal: return one line from the server, stripping CRLF. | ||
33 | # Raise EOFError if the connection is closed | ||
34 | def getline(self): | ||
35 | - line = self.file.readline() | ||
36 | + line = self.file.readline(self.maxline + 1) | ||
37 | + if len(line) > self.maxline: | ||
38 | + raise Error("got more than %d bytes" % self.maxline) | ||
39 | if self.debugging > 1: | ||
40 | print '*get*', self.sanitize(line) | ||
41 | if not line: raise EOFError | ||
42 | @@ -432,7 +437,9 @@ class FTP: | ||
43 | conn = self.transfercmd(cmd) | ||
44 | fp = conn.makefile('rb') | ||
45 | while 1: | ||
46 | - line = fp.readline() | ||
47 | + line = fp.readline(self.maxline + 1) | ||
48 | + if len(line) > self.maxline: | ||
49 | + raise Error("got more than %d bytes" % self.maxline) | ||
50 | if self.debugging > 2: print '*retr*', repr(line) | ||
51 | if not line: | ||
52 | break | ||
53 | @@ -485,7 +492,9 @@ class FTP: | ||
54 | self.voidcmd('TYPE A') | ||
55 | conn = self.transfercmd(cmd) | ||
56 | while 1: | ||
57 | - buf = fp.readline() | ||
58 | + buf = fp.readline(self.maxline + 1) | ||
59 | + if len(buf) > self.maxline: | ||
60 | + raise Error("got more than %d bytes" % self.maxline) | ||
61 | if not buf: break | ||
62 | if buf[-2:] != CRLF: | ||
63 | if buf[-1] in CRLF: buf = buf[:-1] | ||
64 | @@ -710,7 +719,9 @@ else: | ||
65 | fp = conn.makefile('rb') | ||
66 | try: | ||
67 | while 1: | ||
68 | - line = fp.readline() | ||
69 | + line = fp.readline(self.maxline + 1) | ||
70 | + if len(line) > self.maxline: | ||
71 | + raise Error("got more than %d bytes" % self.maxline) | ||
72 | if self.debugging > 2: print '*retr*', repr(line) | ||
73 | if not line: | ||
74 | break | ||
75 | @@ -748,7 +759,9 @@ else: | ||
76 | conn = self.transfercmd(cmd) | ||
77 | try: | ||
78 | while 1: | ||
79 | - buf = fp.readline() | ||
80 | + buf = fp.readline(self.maxline + 1) | ||
81 | + if len(buf) > self.maxline: | ||
82 | + raise Error("got more than %d bytes" % self.maxline) | ||
83 | if not buf: break | ||
84 | if buf[-2:] != CRLF: | ||
85 | if buf[-1] in CRLF: buf = buf[:-1] | ||
86 | @@ -905,7 +918,9 @@ class Netrc: | ||
87 | fp = open(filename, "r") | ||
88 | in_macro = 0 | ||
89 | while 1: | ||
90 | - line = fp.readline() | ||
91 | + line = fp.readline(self.maxline + 1) | ||
92 | + if len(line) > self.maxline: | ||
93 | + raise Error("got more than %d bytes" % self.maxline) | ||
94 | if not line: break | ||
95 | if in_macro and line.strip(): | ||
96 | macro_lines.append(line) | ||
97 | diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py | ||
98 | --- a/Lib/test/test_ftplib.py | ||
99 | +++ b/Lib/test/test_ftplib.py | ||
100 | @@ -65,6 +65,7 @@ class DummyFTPHandler(asynchat.async_cha | ||
101 | self.last_received_data = '' | ||
102 | self.next_response = '' | ||
103 | self.rest = None | ||
104 | + self.next_retr_data = RETR_DATA | ||
105 | self.push('220 welcome') | ||
106 | |||
107 | def collect_incoming_data(self, data): | ||
108 | @@ -189,7 +190,7 @@ class DummyFTPHandler(asynchat.async_cha | ||
109 | offset = int(self.rest) | ||
110 | else: | ||
111 | offset = 0 | ||
112 | - self.dtp.push(RETR_DATA[offset:]) | ||
113 | + self.dtp.push(self.next_retr_data[offset:]) | ||
114 | self.dtp.close_when_done() | ||
115 | self.rest = None | ||
116 | |||
117 | @@ -203,6 +204,11 @@ class DummyFTPHandler(asynchat.async_cha | ||
118 | self.dtp.push(NLST_DATA) | ||
119 | self.dtp.close_when_done() | ||
120 | |||
121 | + def cmd_setlongretr(self, arg): | ||
122 | + # For testing. Next RETR will return long line. | ||
123 | + self.next_retr_data = 'x' * int(arg) | ||
124 | + self.push('125 setlongretr ok') | ||
125 | + | ||
126 | |||
127 | class DummyFTPServer(asyncore.dispatcher, threading.Thread): | ||
128 | |||
129 | @@ -558,6 +564,20 @@ class TestFTPClass(TestCase): | ||
130 | # IPv4 is in use, just make sure send_epsv has not been used | ||
131 | self.assertEqual(self.server.handler.last_received_cmd, 'pasv') | ||
132 | |||
133 | + def test_line_too_long(self): | ||
134 | + self.assertRaises(ftplib.Error, self.client.sendcmd, | ||
135 | + 'x' * self.client.maxline * 2) | ||
136 | + | ||
137 | + def test_retrlines_too_long(self): | ||
138 | + self.client.sendcmd('SETLONGRETR %d' % (self.client.maxline * 2)) | ||
139 | + received = [] | ||
140 | + self.assertRaises(ftplib.Error, | ||
141 | + self.client.retrlines, 'retr', received.append) | ||
142 | + | ||
143 | + def test_storlines_too_long(self): | ||
144 | + f = StringIO.StringIO('x' * self.client.maxline * 2) | ||
145 | + self.assertRaises(ftplib.Error, self.client.storlines, 'stor', f) | ||
146 | + | ||
147 | |||
148 | class TestIPv6Environment(TestCase): | ||
149 | |||
diff --git a/meta/recipes-devtools/python/python/python-2.7.3-CVE-2013-1752-imaplib-fix.patch b/meta/recipes-devtools/python/python/python-2.7.3-CVE-2013-1752-imaplib-fix.patch new file mode 100644 index 0000000000..f4bd84d831 --- /dev/null +++ b/meta/recipes-devtools/python/python/python-2.7.3-CVE-2013-1752-imaplib-fix.patch | |||
@@ -0,0 +1,37 @@ | |||
1 | Upstream-Status: Backport | ||
2 | |||
3 | CVE-2013-1752: Change use of readline in imaplib module to limit line length. Patch by Emil Lind. | ||
4 | |||
5 | Signed-off-by: Tudor Florea <tudor.florea@enea.com> | ||
6 | |||
7 | diff -r ce583eb0bec2 Lib/imaplib.py | ||
8 | --- a/Lib/imaplib.py Thu Feb 21 20:17:54 2013 +0200 | ||
9 | +++ b/Lib/imaplib.py Tue Feb 26 22:36:52 2013 +0100 | ||
10 | @@ -35,6 +35,15 @@ | ||
11 | IMAP4_SSL_PORT = 993 | ||
12 | AllowedVersions = ('IMAP4REV1', 'IMAP4') # Most recent first | ||
13 | |||
14 | +# Maximal line length when calling readline(). This is to prevent | ||
15 | +# reading arbitrary length lines. RFC 3501 and 2060 (IMAP 4rev1) | ||
16 | +# don't specify a line length. RFC 2683 however suggests limiting client | ||
17 | +# command lines to 1000 octets and server command lines to 8000 octets. | ||
18 | +# We have selected 10000 for some extra margin and since that is supposedly | ||
19 | +# also what UW and Panda IMAP does. | ||
20 | +_MAXLINE = 10000 | ||
21 | + | ||
22 | + | ||
23 | # Commands | ||
24 | |||
25 | Commands = { | ||
26 | @@ -237,7 +246,10 @@ | ||
27 | |||
28 | def readline(self): | ||
29 | """Read line from remote.""" | ||
30 | - return self.file.readline() | ||
31 | + line = self.file.readline(_MAXLINE + 1) | ||
32 | + if len(line) > _MAXLINE: | ||
33 | + raise self.error("got more than %d bytes" % _MAXLINE) | ||
34 | + return line | ||
35 | |||
36 | |||
37 | def send(self, data): | ||
diff --git a/meta/recipes-devtools/python/python/python-2.7.3-CVE-2013-1752-nntplib-fix.patch b/meta/recipes-devtools/python/python/python-2.7.3-CVE-2013-1752-nntplib-fix.patch new file mode 100644 index 0000000000..443e137ea5 --- /dev/null +++ b/meta/recipes-devtools/python/python/python-2.7.3-CVE-2013-1752-nntplib-fix.patch | |||
@@ -0,0 +1,105 @@ | |||
1 | Upstream-Status: Backport | ||
2 | |||
3 | CVE-2013-1752: nntplib: Limit maximum line lengths to 2048 to prevent | ||
4 | readline() calls from consuming too much memory. | ||
5 | Patch by Jyrki Pulliainen. | ||
6 | |||
7 | Signed-off-by: Tudor Florea <tudor.florea@enea.com> | ||
8 | |||
9 | diff -r 936621d33c38 Lib/nntplib.py | ||
10 | --- a/Lib/nntplib.py Wed Feb 20 18:19:55 2013 -0500 | ||
11 | +++ b/Lib/nntplib.py Mon Sep 30 23:42:09 2013 +0200 | ||
12 | @@ -37,6 +37,13 @@ | ||
13 | "error_reply","error_temp","error_perm","error_proto", | ||
14 | "error_data",] | ||
15 | |||
16 | +# maximal line length when calling readline(). This is to prevent | ||
17 | +# reading arbitrary length lines. RFC 3977 limits NNTP line length to | ||
18 | +# 512 characters, including CRLF. We have selected 2048 just to be on | ||
19 | +# the safe side. | ||
20 | +_MAXLINE = 2048 | ||
21 | + | ||
22 | + | ||
23 | # Exceptions raised when an error or invalid response is received | ||
24 | class NNTPError(Exception): | ||
25 | """Base class for all nntplib exceptions""" | ||
26 | @@ -200,7 +207,9 @@ | ||
27 | def getline(self): | ||
28 | """Internal: return one line from the server, stripping CRLF. | ||
29 | Raise EOFError if the connection is closed.""" | ||
30 | - line = self.file.readline() | ||
31 | + line = self.file.readline(_MAXLINE + 1) | ||
32 | + if len(line) > _MAXLINE: | ||
33 | + raise NNTPProtocolError('line too long') | ||
34 | if self.debugging > 1: | ||
35 | print '*get*', repr(line) | ||
36 | if not line: raise EOFError | ||
37 | diff -r 936621d33c38 Lib/test/test_nntplib.py | ||
38 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 | ||
39 | +++ b/Lib/test/test_nntplib.py Mon Sep 30 23:42:09 2013 +0200 | ||
40 | @@ -0,0 +1,65 @@ | ||
41 | +import socket | ||
42 | +import threading | ||
43 | +import nntplib | ||
44 | +import time | ||
45 | + | ||
46 | +from unittest import TestCase | ||
47 | +from test import test_support | ||
48 | + | ||
49 | +HOST = test_support.HOST | ||
50 | + | ||
51 | + | ||
52 | +def server(evt, serv, evil=False): | ||
53 | + serv.listen(5) | ||
54 | + try: | ||
55 | + conn, addr = serv.accept() | ||
56 | + except socket.timeout: | ||
57 | + pass | ||
58 | + else: | ||
59 | + if evil: | ||
60 | + conn.send("1 I'm too long response" * 3000 + "\n") | ||
61 | + else: | ||
62 | + conn.send("1 I'm OK response\n") | ||
63 | + conn.close() | ||
64 | + finally: | ||
65 | + serv.close() | ||
66 | + evt.set() | ||
67 | + | ||
68 | + | ||
69 | +class BaseServerTest(TestCase): | ||
70 | + def setUp(self): | ||
71 | + self.evt = threading.Event() | ||
72 | + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
73 | + self.sock.settimeout(3) | ||
74 | + self.port = test_support.bind_port(self.sock) | ||
75 | + threading.Thread( | ||
76 | + target=server, | ||
77 | + args=(self.evt, self.sock, self.evil)).start() | ||
78 | + time.sleep(.1) | ||
79 | + | ||
80 | + def tearDown(self): | ||
81 | + self.evt.wait() | ||
82 | + | ||
83 | + | ||
84 | +class ServerTests(BaseServerTest): | ||
85 | + evil = False | ||
86 | + | ||
87 | + def test_basic_connect(self): | ||
88 | + nntp = nntplib.NNTP('localhost', self.port) | ||
89 | + nntp.sock.close() | ||
90 | + | ||
91 | + | ||
92 | +class EvilServerTests(BaseServerTest): | ||
93 | + evil = True | ||
94 | + | ||
95 | + def test_too_long_line(self): | ||
96 | + self.assertRaises(nntplib.NNTPProtocolError, | ||
97 | + nntplib.NNTP, 'localhost', self.port) | ||
98 | + | ||
99 | + | ||
100 | +def test_main(verbose=None): | ||
101 | + test_support.run_unittest(EvilServerTests) | ||
102 | + test_support.run_unittest(ServerTests) | ||
103 | + | ||
104 | +if __name__ == '__main__': | ||
105 | + test_main() | ||
diff --git a/meta/recipes-devtools/python/python/python-2.7.3-CVE-2013-1752-poplib-fix.patch b/meta/recipes-devtools/python/python/python-2.7.3-CVE-2013-1752-poplib-fix.patch new file mode 100644 index 0000000000..15a5a2c63c --- /dev/null +++ b/meta/recipes-devtools/python/python/python-2.7.3-CVE-2013-1752-poplib-fix.patch | |||
@@ -0,0 +1,90 @@ | |||
1 | diff --git a/Lib/poplib.py b/Lib/poplib.py | ||
2 | --- a/Lib/poplib.py | ||
3 | +++ b/Lib/poplib.py | ||
4 | @@ -27,16 +27,22 @@ POP3_PORT = 110 | ||
5 | # POP SSL PORT | ||
6 | POP3_SSL_PORT = 995 | ||
7 | |||
8 | # Line terminators (we always output CRLF, but accept any of CRLF, LFCR, LF) | ||
9 | CR = '\r' | ||
10 | LF = '\n' | ||
11 | CRLF = CR+LF | ||
12 | |||
13 | +# maximal line length when calling readline(). This is to prevent | ||
14 | +# reading arbitrary length lines. RFC 1939 limits POP3 line length to | ||
15 | +# 512 characters, including CRLF. We have selected 2048 just to be on | ||
16 | +# the safe side. | ||
17 | +_MAXLINE = 2048 | ||
18 | + | ||
19 | |||
20 | class POP3: | ||
21 | |||
22 | """This class supports both the minimal and optional command sets. | ||
23 | Arguments can be strings or integers (where appropriate) | ||
24 | (e.g.: retr(1) and retr('1') both work equally well. | ||
25 | |||
26 | Minimal Command Set: | ||
27 | @@ -98,17 +104,19 @@ class POP3: | ||
28 | self._putline(line) | ||
29 | |||
30 | |||
31 | # Internal: return one line from the server, stripping CRLF. | ||
32 | # This is where all the CPU time of this module is consumed. | ||
33 | # Raise error_proto('-ERR EOF') if the connection is closed. | ||
34 | |||
35 | def _getline(self): | ||
36 | - line = self.file.readline() | ||
37 | + line = self.file.readline(_MAXLINE + 1) | ||
38 | + if len(line) > _MAXLINE: | ||
39 | + raise error_proto('line too long') | ||
40 | if self._debugging > 1: print '*get*', repr(line) | ||
41 | if not line: raise error_proto('-ERR EOF') | ||
42 | octets = len(line) | ||
43 | # server can send any combination of CR & LF | ||
44 | # however, 'readline()' returns lines ending in LF | ||
45 | # so only possibilities are ...LF, ...CRLF, CR...LF | ||
46 | if line[-2:] == CRLF: | ||
47 | return line[:-2], octets | ||
48 | @@ -360,16 +368,18 @@ else: | ||
49 | self.buffer += localbuf | ||
50 | |||
51 | def _getline(self): | ||
52 | line = "" | ||
53 | renewline = re.compile(r'.*?\n') | ||
54 | match = renewline.match(self.buffer) | ||
55 | while not match: | ||
56 | self._fillBuffer() | ||
57 | + if len(self.buffer) > _MAXLINE: | ||
58 | + raise error_proto('line too long') | ||
59 | match = renewline.match(self.buffer) | ||
60 | line = match.group(0) | ||
61 | self.buffer = renewline.sub('' ,self.buffer, 1) | ||
62 | if self._debugging > 1: print '*get*', repr(line) | ||
63 | |||
64 | octets = len(line) | ||
65 | if line[-2:] == CRLF: | ||
66 | return line[:-2], octets | ||
67 | diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py | ||
68 | --- a/Lib/test/test_poplib.py | ||
69 | +++ b/Lib/test/test_poplib.py | ||
70 | @@ -193,16 +193,20 @@ class TestPOP3Class(TestCase): | ||
71 | def test_retr(self): | ||
72 | expected = ('+OK 116 bytes', | ||
73 | ['From: postmaster@python.org', 'Content-Type: text/plain', | ||
74 | 'MIME-Version: 1.0', 'Subject: Dummy', | ||
75 | '', 'line1', 'line2', 'line3'], | ||
76 | 113) | ||
77 | self.assertEqual(self.client.retr('foo'), expected) | ||
78 | |||
79 | + def test_too_long_lines(self): | ||
80 | + self.assertRaises(poplib.error_proto, self.client._shortcmd, | ||
81 | + 'echo +%s' % ((poplib._MAXLINE + 10) * 'a')) | ||
82 | + | ||
83 | def test_dele(self): | ||
84 | self.assertOK(self.client.dele('foo')) | ||
85 | |||
86 | def test_noop(self): | ||
87 | self.assertOK(self.client.noop()) | ||
88 | |||
89 | def test_rpop(self): | ||
90 | self.assertOK(self.client.rpop('foo')) | ||
diff --git a/meta/recipes-devtools/python/python_2.7.3.bb b/meta/recipes-devtools/python/python_2.7.3.bb index 5e0181da56..42c43156b9 100644 --- a/meta/recipes-devtools/python/python_2.7.3.bb +++ b/meta/recipes-devtools/python/python_2.7.3.bb | |||
@@ -43,6 +43,10 @@ SRC_URI += "\ | |||
43 | file://ctypes-libffi-aarch64.patch \ | 43 | file://ctypes-libffi-aarch64.patch \ |
44 | file://libffi-aarch64.patch \ | 44 | file://libffi-aarch64.patch \ |
45 | file://python-2.7.3-CVE-2013-1752-httplib-fix.patch \ | 45 | file://python-2.7.3-CVE-2013-1752-httplib-fix.patch \ |
46 | file://python-2.7.3-CVE-2013-1752-ftplib-fix.patch \ | ||
47 | file://python-2.7.3-CVE-2013-1752-imaplib-fix.patch \ | ||
48 | file://python-2.7.3-CVE-2013-1752-nntplib-fix.patch \ | ||
49 | file://python-2.7.3-CVE-2013-1752-poplib-fix.patch \ | ||
46 | " | 50 | " |
47 | 51 | ||
48 | S = "${WORKDIR}/Python-${PV}" | 52 | S = "${WORKDIR}/Python-${PV}" |