from trac.env import open_environment
from trac.perm import PermissionCache, NoPermissionCache, PermissionError
-from trac.util import reversed, get_last_traceback
+from trac.util import reversed, get_last_traceback
from trac.util.datefmt import format_datetime, http_date
from trac.util.html import Markup
from trac.util.text import to_unicode
# Protect against CSRF attacks.
if (req.method == 'POST' and
req.args.get('__FORM_TOKEN') != req.form_token):
- raise TracError('Missing or invalid form token '
+ raise TracError('Missing or invalid form token '
'Do you have cookies enabled?')
resp = chosen_handler.process_request(req)
def _get_form_token(self, req):
"""Used to protect against CSRF.
- The 'trac_auth' cookie is a good and strong shared secret, only
- known by the user it belongs to and Trac itself.
- The session id is our second best option, not as reliable since
- it will change on each request if the user has cookies disabled in
+ The 'form_token' is strong shared secret stored in a user cookie.
+ By requiring that every POST form to contain this value we're
+ able to protect against CSRF attacks. Since this value is only known
+ by the user and not by an attacker.
+ If the the user does not have a `trac_form_token` cookie a new
- if req.incookie.has_key('trac_auth'):
- return req.incookie['trac_auth'].value
+ if req.incookie.has_key('trac_form_token'):
+ return req.incookie['trac_form_token'].value
+ req.outcookie['trac_form_token'] = hex_entropy(24)
+ req.outcookie['trac_form_token']['path'] = req.base_path
+ req.outcookie['trac_form_token']['expires'] = 3600*24*90 # 90 days
+ return req.outcookie['trac_form_token'].value
def dispatch_request(environ, start_response):
"""Main entry point for the Trac web interface.