#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.
This commit is contained in:
Andrew Kuchling 2013-09-15 13:11:47 -04:00
parent ed9884b2d0
commit 503baf9ecd
3 changed files with 42 additions and 5 deletions

View File

@ -57,6 +57,7 @@ __all__ = ["SMTPException","SMTPServerDisconnected","SMTPResponseException",
SMTP_PORT = 25
SMTP_SSL_PORT = 465
CRLF="\r\n"
_MAXLINE = 8192 # more than 8 times larger than RFC 821, 4.5.3
OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I)
@ -170,10 +171,14 @@ else:
def __init__(self, sslobj):
self.sslobj = sslobj
def readline(self):
def readline(self, size=-1):
if size < 0:
size = None
str = ""
chr = None
while chr != "\n":
if size is not None and len(str) >= size:
break
chr = self.sslobj.read(1)
if not chr: break
str += chr
@ -334,11 +339,13 @@ class SMTP:
if self.file is None:
self.file = self.sock.makefile('rb')
while 1:
line = self.file.readline()
line = self.file.readline(_MAXLINE + 1)
if line == '':
self.close()
raise SMTPServerDisconnected("Connection unexpectedly closed")
if self.debuglevel > 0: print>>stderr, 'reply:', repr(line)
if self.debuglevel > 0: print >>stderr, 'reply:', repr(line)
if len(line) > _MAXLINE:
raise SMTPResponseException(500, "Line too long.")
resp.append(line[4:].strip())
code=line[:3]
# Check that the error code is syntactically correct.

View File

@ -273,6 +273,32 @@ class BadHELOServerTests(TestCase):
HOST, self.port, 'localhost', 3)
class TooLongLineTests(TestCase):
respdata = '250 OK' + ('.' * smtplib._MAXLINE * 2) + '\n'
def setUp(self):
self.old_stdout = sys.stdout
self.output = StringIO.StringIO()
sys.stdout = self.output
self.evt = threading.Event()
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.settimeout(15)
self.port = test_support.bind_port(self.sock)
servargs = (self.evt, self.respdata, self.sock)
threading.Thread(target=server, args=servargs).start()
self.evt.wait()
self.evt.clear()
def tearDown(self):
self.evt.wait()
sys.stdout = self.old_stdout
def testLineTooLong(self):
self.assertRaises(smtplib.SMTPResponseException, smtplib.SMTP,
HOST, self.port, 'localhost', 3)
sim_users = {'Mr.A@somewhere.com':'John A',
'Ms.B@somewhere.com':'Sally B',
'Mrs.C@somewhereesle.com':'Ruth C',
@ -482,7 +508,8 @@ class SMTPSimTests(TestCase):
def test_main(verbose=None):
test_support.run_unittest(GeneralTests, DebuggingServerTests,
NonConnectingTests,
BadHELOServerTests, SMTPSimTests)
BadHELOServerTests, SMTPSimTests,
TooLongLineTests)
if __name__ == '__main__':
test_main()

View File

@ -16,13 +16,16 @@ Library
- Issue #16248: Disable code execution from the user's home directory by
tkinter when the -E flag is passed to Python. Patch by Zachary Ware.
- Issue #16042: CVE-2013-1752: smtplib: Limit amount of data read by
limiting the call to readline(). Original patch by Christian Heimes.
Extension Modules
-----------------
- Issue #18709: Fix CVE-2013-4238. The SSL module now handles NULL bytes
inside subjectAltName correctly. Formerly the module has used OpenSSL's
GENERAL_NAME_print() function to get the string represention of ASN.1
strings for `rfc822Name` (email), `dNSName` (DNS) and
strings for `rfc822Name` (email), `dNSName` (DNS) and
`uniformResourceIdentifier` (URI).