diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py index c292d74f84a93c..b0673322f96540 100644 --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -426,6 +426,31 @@ def test_ftp_nonexisting(self): self.assertFalse(e.exception.filename) self.assertTrue(e.exception.reason) + def test_ftp_illegalhost(self): + # bpo-29606: reject newline character in FTP URL + illegal_ftp_urls = [ + 'ftp://foo:bar%0aINJECTED@example.net/file.png', + 'ftp://foo:bar%0d%0aINJECTED@example.net/file.png', + ] + + def check_exception_message(cmd): + msg = str(cm.exception) + self.assertTrue("ftp error: illegal newline character" in msg, msg) + + for url in illegal_ftp_urls: + # test URLopener.open_ftp() + opener = urllib.request.URLopener() + with self.assertRaises(urllib.error.URLError) as cm: + opener.open_ftp(url) + check_exception_message(cm) + + # test FTPHandler.ftp_open() + req = urllib.request.Request(url) + handler = urllib.request.FTPHandler() + with self.assertRaises(urllib.error.URLError) as cm: + handler.ftp_open(req) + check_exception_message(cm) + @patch.object(urllib.request, 'MAXFTPCACHE', 0) def test_ftp_cache_pruning(self): self.fakeftp() diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index a192d527d8bc9a..af8feea16af7a5 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -1502,6 +1502,8 @@ def ftp_open(self, req): host = req.host if not host: raise URLError('ftp error: no host given') + if '\n' in unquote(host): + raise URLError("ftp error: illegal newline character") host, port = splitport(host) if port is None: port = ftplib.FTP_PORT @@ -2010,6 +2012,8 @@ def open_ftp(self, url): if not isinstance(url, str): raise URLError('ftp error: proxy support for ftp protocol currently not implemented') import mimetypes + if '\n' in unquote(url): + raise URLError("ftp error: illegal newline character") host, path = splithost(url) if not host: raise URLError('ftp error: no host given') host, port = splitport(host) diff --git a/Misc/NEWS.d/next/Library/2017-07-21-12-05-23.bpo-29606.MPgBLH.rst b/Misc/NEWS.d/next/Library/2017-07-21-12-05-23.bpo-29606.MPgBLH.rst new file mode 100644 index 00000000000000..092e426b942a4a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-07-21-12-05-23.bpo-29606.MPgBLH.rst @@ -0,0 +1,3 @@ +FTPHandler.ftp_open() and URLOpener.open_ftp() of urllib.request now +raise an exception if the unquoted URL contains a newline character +(U+000A, "\n").