Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 503baf9

Browse files
committed
python#16042: CVE-2013-1752: Limit amount of data read by limiting the call to readline().
The SSLFakeFile.readline() method needs to support limiting readline() as well. It's not a full emulation of readline()'s signature, but this class is only used by smtplib's code, so it doesn't have to be. Modified version of original patch by Christian Heimes.
1 parent ed9884b commit 503baf9

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

Lib/smtplib.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
SMTP_PORT = 25
5858
SMTP_SSL_PORT = 465
5959
CRLF="\r\n"
60+
_MAXLINE = 8192 # more than 8 times larger than RFC 821, 4.5.3
6061

6162
OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I)
6263

@@ -170,10 +171,14 @@ class SSLFakeFile:
170171
def __init__(self, sslobj):
171172
self.sslobj = sslobj
172173

173-
def readline(self):
174+
def readline(self, size=-1):
175+
if size < 0:
176+
size = None
174177
str = ""
175178
chr = None
176179
while chr != "\n":
180+
if size is not None and len(str) >= size:
181+
break
177182
chr = self.sslobj.read(1)
178183
if not chr: break
179184
str += chr
@@ -334,11 +339,13 @@ def getreply(self):
334339
if self.file is None:
335340
self.file = self.sock.makefile('rb')
336341
while 1:
337-
line = self.file.readline()
342+
line = self.file.readline(_MAXLINE + 1)
338343
if line == '':
339344
self.close()
340345
raise SMTPServerDisconnected("Connection unexpectedly closed")
341-
if self.debuglevel > 0: print>>stderr, 'reply:', repr(line)
346+
if self.debuglevel > 0: print >>stderr, 'reply:', repr(line)
347+
if len(line) > _MAXLINE:
348+
raise SMTPResponseException(500, "Line too long.")
342349
resp.append(line[4:].strip())
343350
code=line[:3]
344351
# Check that the error code is syntactically correct.

Lib/test/test_smtplib.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,32 @@ def testFailingHELO(self):
273273
HOST, self.port, 'localhost', 3)
274274

275275

276+
class TooLongLineTests(TestCase):
277+
respdata = '250 OK' + ('.' * smtplib._MAXLINE * 2) + '\n'
278+
279+
def setUp(self):
280+
self.old_stdout = sys.stdout
281+
self.output = StringIO.StringIO()
282+
sys.stdout = self.output
283+
284+
self.evt = threading.Event()
285+
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
286+
self.sock.settimeout(15)
287+
self.port = test_support.bind_port(self.sock)
288+
servargs = (self.evt, self.respdata, self.sock)
289+
threading.Thread(target=server, args=servargs).start()
290+
self.evt.wait()
291+
self.evt.clear()
292+
293+
def tearDown(self):
294+
self.evt.wait()
295+
sys.stdout = self.old_stdout
296+
297+
def testLineTooLong(self):
298+
self.assertRaises(smtplib.SMTPResponseException, smtplib.SMTP,
299+
HOST, self.port, 'localhost', 3)
300+
301+
276302
sim_users = {'[email protected]':'John A',
277303
'[email protected]':'Sally B',
278304
'[email protected]':'Ruth C',
@@ -482,7 +508,8 @@ def testAUTH_CRAM_MD5(self):
482508
def test_main(verbose=None):
483509
test_support.run_unittest(GeneralTests, DebuggingServerTests,
484510
NonConnectingTests,
485-
BadHELOServerTests, SMTPSimTests)
511+
BadHELOServerTests, SMTPSimTests,
512+
TooLongLineTests)
486513

487514
if __name__ == '__main__':
488515
test_main()

Misc/NEWS

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@ Library
1616
- Issue #16248: Disable code execution from the user's home directory by
1717
tkinter when the -E flag is passed to Python. Patch by Zachary Ware.
1818

19+
- Issue #16042: CVE-2013-1752: smtplib: Limit amount of data read by
20+
limiting the call to readline(). Original patch by Christian Heimes.
21+
1922
Extension Modules
2023
-----------------
2124

2225
- Issue #18709: Fix CVE-2013-4238. The SSL module now handles NULL bytes
2326
inside subjectAltName correctly. Formerly the module has used OpenSSL's
2427
GENERAL_NAME_print() function to get the string represention of ASN.1
25-
strings for `rfc822Name` (email), `dNSName` (DNS) and
28+
strings for `rfc822Name` (email), `dNSName` (DNS) and
2629
`uniformResourceIdentifier` (URI).
2730

2831

0 commit comments

Comments
 (0)