Hello community, here is the log from the commit of package python3-tornado for openSUSE:Factory checked in at 2016-10-10 16:17:05 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python3-tornado (Old) and /work/SRC/openSUSE:Factory/.python3-tornado.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python3-tornado" Changes: -------- --- /work/SRC/openSUSE:Factory/python3-tornado/python3-tornado.changes 2016-07-27 16:30:26.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python3-tornado.new/python3-tornado.changes 2016-10-10 16:17:04.000000000 +0200 @@ -1,0 +2,18 @@ +Sun Oct 2 15:53:26 UTC 2016 - [email protected] + +- update to version 4.4.2: + * Security fixes + + A difference in cookie parsing between Tornado and web browsers + (especially when combined with Google Analytics) could allow an + attacker to set arbitrary cookies and bypass XSRF + protection. The cookie parser has been rewritten to fix this + attack. + * Backwards-compatibility notes + + Cookies containing certain special characters (in particular + semicolon and square brackets) are now parsed differently. + + If the cookie header contains a combination of valid and invalid + cookies, the valid ones will be returned (older versions of + Tornado would reject the entire header for a single invalid + cookie). + +------------------------------------------------------------------- Old: ---- tornado-4.4.1.tar.gz New: ---- tornado-4.4.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python3-tornado.spec ++++++ --- /var/tmp/diff_new_pack.hgUB8G/_old 2016-10-10 16:17:05.000000000 +0200 +++ /var/tmp/diff_new_pack.hgUB8G/_new 2016-10-10 16:17:05.000000000 +0200 @@ -17,7 +17,7 @@ Name: python3-tornado -Version: 4.4.1 +Version: 4.4.2 Release: 0 Url: http://www.tornadoweb.org Summary: Open source version of scalable, non-blocking web server that power FriendFeed ++++++ tornado-4.4.1.tar.gz -> tornado-4.4.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tornado-4.4.1/PKG-INFO new/tornado-4.4.2/PKG-INFO --- old/tornado-4.4.1/PKG-INFO 2016-07-23 18:28:12.000000000 +0200 +++ new/tornado-4.4.2/PKG-INFO 2016-10-01 00:48:19.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: tornado -Version: 4.4.1 +Version: 4.4.2 Summary: Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. Home-page: http://www.tornadoweb.org/ Author: Facebook diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tornado-4.4.1/docs/releases/v4.4.2.rst new/tornado-4.4.2/docs/releases/v4.4.2.rst --- old/tornado-4.4.1/docs/releases/v4.4.2.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/tornado-4.4.2/docs/releases/v4.4.2.rst 2016-10-01 00:43:58.000000000 +0200 @@ -0,0 +1,22 @@ +What's new in Tornado 4.4.2 +=========================== + +Oct 1, 2016 +------------ + +Security fixes +~~~~~~~~~~~~~~ + +* A difference in cookie parsing between Tornado and web browsers + (especially when combined with Google Analytics) could allow an + attacker to set arbitrary cookies and bypass XSRF protection. The + cookie parser has been rewritten to fix this attack. + +Backwards-compatibility notes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Cookies containing certain special characters (in particular semicolon + and square brackets) are now parsed differently. +* If the cookie header contains a combination of valid and invalid cookies, + the valid ones will be returned (older versions of Tornado would reject the + entire header for a single invalid cookie). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tornado-4.4.1/docs/releases.rst new/tornado-4.4.2/docs/releases.rst --- old/tornado-4.4.1/docs/releases.rst 2016-07-23 18:25:07.000000000 +0200 +++ new/tornado-4.4.2/docs/releases.rst 2016-10-01 00:43:58.000000000 +0200 @@ -4,6 +4,7 @@ .. toctree:: :maxdepth: 2 + releases/v4.4.2 releases/v4.4.1 releases/v4.4.0 releases/v4.3.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tornado-4.4.1/setup.py new/tornado-4.4.2/setup.py --- old/tornado-4.4.1/setup.py 2016-07-23 18:25:15.000000000 +0200 +++ new/tornado-4.4.2/setup.py 2016-10-01 00:43:58.000000000 +0200 @@ -103,7 +103,7 @@ kwargs = {} -version = "4.4.1" +version = "4.4.2" with open('README.rst') as f: kwargs['long_description'] = f.read() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tornado-4.4.1/tornado/__init__.py new/tornado-4.4.2/tornado/__init__.py --- old/tornado-4.4.1/tornado/__init__.py 2016-07-23 18:25:20.000000000 +0200 +++ new/tornado-4.4.2/tornado/__init__.py 2016-10-01 00:43:58.000000000 +0200 @@ -25,5 +25,5 @@ # is zero for an official release, positive for a development branch, # or negative for a release candidate or beta (after the base version # number has been incremented) -version = "4.4.1" -version_info = (4, 4, 1, 0) +version = "4.4.2" +version_info = (4, 4, 2, 0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tornado-4.4.1/tornado/httputil.py new/tornado-4.4.2/tornado/httputil.py --- old/tornado-4.4.1/tornado/httputil.py 2016-07-15 17:00:52.000000000 +0200 +++ new/tornado-4.4.2/tornado/httputil.py 2016-10-01 00:43:58.000000000 +0200 @@ -379,10 +379,18 @@ self._cookies = Cookie.SimpleCookie() if "Cookie" in self.headers: try: - self._cookies.load( - native_str(self.headers["Cookie"])) + parsed = parse_cookie(self.headers["Cookie"]) except Exception: - self._cookies = {} + pass + else: + for k, v in parsed.items(): + try: + self._cookies[k] = v + except Exception: + # SimpleCookie imposes some restrictions on keys; + # parse_cookie does not. Discard any cookies + # with disallowed keys. + pass return self._cookies def write(self, chunk, callback=None): @@ -909,3 +917,82 @@ host = netloc port = None return (host, port) + +_OctalPatt = re.compile(r"\\[0-3][0-7][0-7]") +_QuotePatt = re.compile(r"[\\].") +_nulljoin = ''.join + +def _unquote_cookie(str): + """Handle double quotes and escaping in cookie values. + + This method is copied verbatim from the Python 3.5 standard + library (http.cookies._unquote) so we don't have to depend on + non-public interfaces. + """ + # If there aren't any doublequotes, + # then there can't be any special characters. See RFC 2109. + if str is None or len(str) < 2: + return str + if str[0] != '"' or str[-1] != '"': + return str + + # We have to assume that we must decode this string. + # Down to work. + + # Remove the "s + str = str[1:-1] + + # Check for special sequences. Examples: + # \012 --> \n + # \" --> " + # + i = 0 + n = len(str) + res = [] + while 0 <= i < n: + o_match = _OctalPatt.search(str, i) + q_match = _QuotePatt.search(str, i) + if not o_match and not q_match: # Neither matched + res.append(str[i:]) + break + # else: + j = k = -1 + if o_match: + j = o_match.start(0) + if q_match: + k = q_match.start(0) + if q_match and (not o_match or k < j): # QuotePatt matched + res.append(str[i:k]) + res.append(str[k+1]) + i = k + 2 + else: # OctalPatt matched + res.append(str[i:j]) + res.append(chr(int(str[j+1:j+4], 8))) + i = j + 4 + return _nulljoin(res) + + +def parse_cookie(cookie): + """Parse a ``Cookie`` HTTP header into a dict of name/value pairs. + + This function attempts to mimic browser cookie parsing behavior; + it specifically does not follow any of the cookie-related RFCs + (because browsers don't either). + + The algorithm used is identical to that used by Django version 1.9.10. + + .. versionadded:: 4.4.2 + """ + cookiedict = {} + for chunk in cookie.split(str(';')): + if str('=') in chunk: + key, val = chunk.split(str('='), 1) + else: + # Assume an empty name per + # https://bugzilla.mozilla.org/show_bug.cgi?id=169091 + key, val = str(''), chunk + key, val = key.strip(), val.strip() + if key or val: + # unquote using Python's algorithm. + cookiedict[key] = _unquote_cookie(val) + return cookiedict diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tornado-4.4.1/tornado/netutil.py new/tornado-4.4.2/tornado/netutil.py --- old/tornado-4.4.1/tornado/netutil.py 2016-07-15 17:00:52.000000000 +0200 +++ new/tornado-4.4.2/tornado/netutil.py 2016-08-26 04:06:04.000000000 +0200 @@ -129,7 +129,7 @@ ``flags`` is a bitmask of AI_* flags to `~socket.getaddrinfo`, like ``socket.AI_PASSIVE | socket.AI_NUMERICHOST``. - ``resuse_port`` option sets ``SO_REUSEPORT`` option for every socket + ``reuse_port`` option sets ``SO_REUSEPORT`` option for every socket in the list. If your platform doesn't support this option ValueError will be raised. """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tornado-4.4.1/tornado/platform/asyncio.py new/tornado-4.4.2/tornado/platform/asyncio.py --- old/tornado-4.4.1/tornado/platform/asyncio.py 2016-07-15 17:00:52.000000000 +0200 +++ new/tornado-4.4.2/tornado/platform/asyncio.py 2016-10-01 00:43:58.000000000 +0200 @@ -14,9 +14,9 @@ .. note:: - Tornado requires the `~asyncio.BaseEventLoop.add_reader` family of methods, - so it is not compatible with the `~asyncio.ProactorEventLoop` on Windows. - Use the `~asyncio.SelectorEventLoop` instead. + Tornado requires the `~asyncio.AbstractEventLoop.add_reader` family of + methods, so it is not compatible with the `~asyncio.ProactorEventLoop` on + Windows. Use the `~asyncio.SelectorEventLoop` instead. """ from __future__ import absolute_import, division, print_function, with_statement diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tornado-4.4.1/tornado/test/httputil_test.py new/tornado-4.4.2/tornado/test/httputil_test.py --- old/tornado-4.4.1/tornado/test/httputil_test.py 2016-07-15 17:00:52.000000000 +0200 +++ new/tornado-4.4.2/tornado/test/httputil_test.py 2016-10-01 00:43:58.000000000 +0200 @@ -1,8 +1,9 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- from __future__ import absolute_import, division, print_function, with_statement -from tornado.httputil import url_concat, parse_multipart_form_data, HTTPHeaders, format_timestamp, HTTPServerRequest, parse_request_start_line +from tornado.httputil import url_concat, parse_multipart_form_data, HTTPHeaders, format_timestamp, HTTPServerRequest, parse_request_start_line, parse_cookie from tornado.escape import utf8, native_str from tornado.log import gen_log from tornado.testing import ExpectLog @@ -378,3 +379,53 @@ self.assertEqual(parsed_start_line.method, self.METHOD) self.assertEqual(parsed_start_line.path, self.PATH) self.assertEqual(parsed_start_line.version, self.VERSION) + + +class ParseCookieTest(unittest.TestCase): + # These tests copied from Django: + # https://github.com/django/django/pull/6277/commits/da810901ada1cae9fc1f018f879f11a7fb467b28 + def test_python_cookies(self): + """ + Test cases copied from Python's Lib/test/test_http_cookies.py + """ + self.assertEqual(parse_cookie('chips=ahoy; vienna=finger'), {'chips': 'ahoy', 'vienna': 'finger'}) + # Here parse_cookie() differs from Python's cookie parsing in that it + # treats all semicolons as delimiters, even within quotes. + self.assertEqual( + parse_cookie('keebler="E=mc2; L=\\"Loves\\"; fudge=\\012;"'), + {'keebler': '"E=mc2', 'L': '\\"Loves\\"', 'fudge': '\\012', '': '"'} + ) + # Illegal cookies that have an '=' char in an unquoted value. + self.assertEqual(parse_cookie('keebler=E=mc2'), {'keebler': 'E=mc2'}) + # Cookies with ':' character in their name. + self.assertEqual(parse_cookie('key:term=value:term'), {'key:term': 'value:term'}) + # Cookies with '[' and ']'. + self.assertEqual(parse_cookie('a=b; c=[; d=r; f=h'), {'a': 'b', 'c': '[', 'd': 'r', 'f': 'h'}) + + def test_cookie_edgecases(self): + # Cookies that RFC6265 allows. + self.assertEqual(parse_cookie('a=b; Domain=example.com'), {'a': 'b', 'Domain': 'example.com'}) + # parse_cookie() has historically kept only the last cookie with the + # same name. + self.assertEqual(parse_cookie('a=b; h=i; a=c'), {'a': 'c', 'h': 'i'}) + + def test_invalid_cookies(self): + """ + Cookie strings that go against RFC6265 but browsers will send if set + via document.cookie. + """ + # Chunks without an equals sign appear as unnamed values per + # https://bugzilla.mozilla.org/show_bug.cgi?id=169091 + self.assertIn('django_language', parse_cookie('abc=def; unnamed; django_language=en').keys()) + # Even a double quote may be an unamed value. + self.assertEqual(parse_cookie('a=b; "; c=d'), {'a': 'b', '': '"', 'c': 'd'}) + # Spaces in names and values, and an equals sign in values. + self.assertEqual(parse_cookie('a b c=d e = f; gh=i'), {'a b c': 'd e = f', 'gh': 'i'}) + # More characters the spec forbids. + self.assertEqual(parse_cookie('a b,c<>@:/[]?{}=d " =e,f g'), {'a b,c<>@:/[]?{}': 'd " =e,f g'}) + # Unicode characters. The spec only allows ASCII. + self.assertEqual(parse_cookie('saint=André Bessette'), {'saint': native_str('André Bessette')}) + # Browsers don't send extra whitespace or semicolons in Cookie headers, + # but parse_cookie() should parse whitespace the same way + # document.cookie parses whitespace. + self.assertEqual(parse_cookie(' = b ; ; = ; c = ; '), {'': 'b', 'c': ''}) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tornado-4.4.1/tornado/test/web_test.py new/tornado-4.4.2/tornado/test/web_test.py --- old/tornado-4.4.1/tornado/test/web_test.py 2016-07-23 18:14:04.000000000 +0200 +++ new/tornado-4.4.2/tornado/test/web_test.py 2016-10-01 00:43:58.000000000 +0200 @@ -279,8 +279,8 @@ data = [('foo=a=b', 'a=b'), ('foo="a=b"', 'a=b'), - ('foo="a;b"', 'a;b'), - # ('foo=a\\073b', 'a;b'), # even encoded, ";" is a delimiter + ('foo="a;b"', '"a'), # even quoted, ";" is a delimiter + ('foo=a\\073b', 'a\\073b'), # escapes only decoded in quotes ('foo="a\\073b"', 'a;b'), ('foo="a\\"b"', 'a"b'), ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tornado-4.4.1/tornado.egg-info/PKG-INFO new/tornado-4.4.2/tornado.egg-info/PKG-INFO --- old/tornado-4.4.1/tornado.egg-info/PKG-INFO 2016-07-23 18:28:00.000000000 +0200 +++ new/tornado-4.4.2/tornado.egg-info/PKG-INFO 2016-10-01 00:48:18.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: tornado -Version: 4.4.1 +Version: 4.4.2 Summary: Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. Home-page: http://www.tornadoweb.org/ Author: Facebook diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tornado-4.4.1/tornado.egg-info/SOURCES.txt new/tornado-4.4.2/tornado.egg-info/SOURCES.txt --- old/tornado-4.4.1/tornado.egg-info/SOURCES.txt 2016-07-23 18:28:11.000000000 +0200 +++ new/tornado-4.4.2/tornado.egg-info/SOURCES.txt 2016-10-01 00:48:19.000000000 +0200 @@ -136,6 +136,7 @@ docs/releases/v4.3.0.rst docs/releases/v4.4.0.rst docs/releases/v4.4.1.rst +docs/releases/v4.4.2.rst tornado/__init__.py tornado/_locale_data.py tornado/auth.py
