warzone2100/tools/trac/plugins/TracHttpOnlyAuthCookie.py

98 lines
3.4 KiB
Python
Raw Normal View History

# vim: set et sts=4 sw=4 encoding=utf8:
#
# Copyright (c) 2008-2009, Giel van Schijndel
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the Warzone 2100 Project nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from trac.core import *
from trac.web.api import Request
from Cookie import Morsel, _semispacejoin, _getdate
__all__ = ['TracHttpOnlyAuthCookie']
# Python 2.6 already has support for the httponly attribute in Morsel
import sys
if sys.version_info < (2, 6):
# Add the 'httponly' attribute
Morsel._reserved['httponly'] = 'httponly'
# Replacement for Morsel.OutputString that properly handles 'httponly' attributes
def tmp_func(self, attrs=None):
# Build up our result
#
result = []
RA = result.append
# First, the key=value pair
RA("%s=%s" % (self.key, self.coded_value))
# Now add any defined attributes
if attrs is None:
attrs = self._reserved
items = self.items()
items.sort()
for K,V in items:
if V == "": continue
if K not in attrs: continue
if K == "expires" and type(V) == type(1):
RA("%s=%s" % (self._reserved[K], _getdate(V)))
elif K == "max-age" and type(V) == type(1):
RA("%s=%d" % (self._reserved[K], V))
elif K == "secure":
RA(str(self._reserved[K]))
elif K == "httponly":
RA(str(self._reserved[K]))
else:
RA("%s=%s" % (self._reserved[K], V))
# Return the result
return _semispacejoin(result)
# end OutputString
Morsel.OutputString = tmp_func
del sys
class TracHttpOnlyAuthCookie(Component):
"""Adds the 'HttpOnly' cookie attribute to the trac_auth cookie.
This should provide for some additional level of safety by preventing
access to this cookie from JavaScript code."""
pass
_old_end_headers = Request.end_headers
# Hack up Request.end_headers such that it adds a 'httponly' cookie
# attribute to the 'trac_auth' cookie.
def end_headers(self):
for cookie in ['trac_auth']:
if cookie in self.outcookie:
self.outcookie[cookie]['httponly'] = True
_old_end_headers(self)
Request.end_headers = end_headers