.. toctree::
:maxdepth: 2
+ releases/v3.2.2
releases/v3.2.1
releases/v3.2.0
releases/v3.1.1
--- /dev/null
+What's new in Tornado 3.2.2
+===========================
+
+June 3, 2014
+------------
+
+Security fixes
+~~~~~~~~~~~~~~
+
+* The XSRF token is now encoded with a random mask on each request.
+ This makes it safe to include in compressed pages without being
+ vulnerable to the `BREACH attack <http://breachattack.com>`_.
+ This applies to most applications that use both the ``xsrf_cookies``
+ and ``gzip`` options (or have gzip applied by a proxy).
+
+Backwards-compatibility notes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* If Tornado 3.2.2 is run at the same time as older versions on the same
+ domain, there is some potential for issues with the differing cookie
+ versions. The `.Application` setting ``xsrf_cookie_version=1`` can
+ be used for a transitional period to generate the older cookie format
+ on newer servers.
+
+Other changes
+~~~~~~~~~~~~~
+
+* ``tornado.platform.asyncio`` is now compatible with ``trollius`` version 0.3.
.. autoattribute:: RequestHandler.settings
.. automethod:: RequestHandler.static_url
.. automethod:: RequestHandler.xsrf_form_html
+ .. autoattribute:: RequestHandler.xsrf_token
to this url if the user is not logged in. Can be further
customized by overriding `RequestHandler.get_login_url`
* ``xsrf_cookies``: If true, :ref:`xsrf` will be enabled.
+ * ``xsrf_cookie_version``: Controls the version of new XSRF
+ cookies produced by this server. Should generally be left
+ at the default (which will always be the highest supported
+ version), but may be set to a lower value temporarily
+ during version transitions. New in Tornado 3.2.2, which
+ introduced XSRF cookie version 2.
* ``twitter_consumer_key``, ``twitter_consumer_secret``,
``friendfeed_consumer_key``, ``friendfeed_consumer_secret``,
``google_consumer_key``, ``google_consumer_secret``,
as a potential forgery.
See http://en.wikipedia.org/wiki/Cross-site_request_forgery
+
+ .. versionchanged:: 3.2.2
+ The xsrf token will now be have a random mask applied in every
+ request, which makes it safe to include the token in pages
+ that are compressed. See http://breachattack.com for more
+ information on the issue fixed by this change. Old (version 1)
+ cookies will be converted to version 2 when this method is called
+ unless the ``xsrf_cookie_version`` `Application` setting is
+ set to 1.
"""
if not hasattr(self, "_xsrf_token"):
version, token, timestamp = self._get_raw_xsrf_token()
return self._xsrf_token
def _get_raw_xsrf_token(self):
+ """Read or generate the xsrf token in its raw form.
+
+ The raw_xsrf_token is a tuple containing:
+
+ * version: the version of the cookie from which this token was read,
+ or None if we generated a new token in this request.
+ * token: the raw token data; random (non-ascii) bytes.
+ * timestamp: the time this token was generated (will not be accurate
+ for version 1 cookies)
+ """
if not hasattr(self, '_raw_xsrf_token'):
cookie = self.get_cookie("_xsrf")
if cookie:
return self._raw_xsrf_token
def _decode_xsrf_token(self, cookie):
+ """Convert a cookie string into a the tuple form returned by
+ _get_raw_xsrf_token.
+ """
m = _signed_value_version_re.match(utf8(cookie))
if m:
version = int(m.group(1))
information please see
http://www.djangoproject.com/weblog/2011/feb/08/security/
http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails
+
+ .. versionchanged:: 3.2.2
+ Added support for cookie version 2. Both versions 1 and 2 are
+ supported.
"""
token = (self.get_argument("_xsrf", None) or
self.request.headers.get("X-Xsrftoken") or