moksha/middleware/csrf.py | 51 +++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 16 deletions(-)
New commits: commit 3251b70579662a9f53cde4c7ca634d9743eb3010 Author: John (J5) Palmieri johnp@redhat.com Date: Mon Apr 20 19:04:05 2009 -0400
fix how we append the csrf token during login so we don't munch the query string
diff --git a/moksha/middleware/csrf.py b/moksha/middleware/csrf.py index ddab4e1..d107eb2 100644 --- a/moksha/middleware/csrf.py +++ b/moksha/middleware/csrf.py @@ -32,16 +32,45 @@ from paste.httpexceptions import HTTPFound from paste.request import parse_formvars, parse_dict_querystring from paste.response import replace_header from urlparse import urlparse, urlunparse +from urllib import urlencode from repoze.who.interfaces import IMetadataProvider from zope.interface import implements
try: + from urlparse import parse_qs +except: + from cgi import parse_qs + +try: from hashlib import sha1 except ImportError: from sha import sha as sha1
log = logging.getLogger(__name__)
+def update_qs(uri, d): + """ + Helper function for updating query string values. Similar to calling + update on a dictionary except we modify the query string of the uri + instead of another dictionary. + """ + loc = list(urlparse(uri)) + query_dict = parse_qs(loc[4]) + query_dict.update(d) + + # seems that we have to sanitize a bit here + query_list = [] + for k, v in query_dict.items(): + if isinstance(v, list): + for item in v: + query_list.append((k, item)) + else: + query_list.append((k, v)) + + loc[4] = urlencode(query_list) + + return urlunparse(loc) + class CSRFProtectionMiddleware(object): """ CSRF Protection WSGI Middleware. @@ -153,14 +182,9 @@ class CSRFProtectionMiddleware(object): if environ.get(self.auth_state): log.debug("CSRF_AUTH_STATE; rewriting headers") token = environ.get('repoze.who.identity', {}).get(self.csrf_token_id) - path = [] - for part in urlparse(response.location): - if part.startswith(self.csrf_token_id): - path.append('') - else: - path.append(part) - path[4] += self.csrf_token_id + '=' + token - response.location = urlunparse(path) + + loc = update_qs(response.location, {self.csrf_token_id: str(token)}) + response.location = loc log.debug("response.location = %s" % response.location) environ[self.auth_state] = None
@@ -254,14 +278,9 @@ class CSRFMetadataProvider(object): # This occurs during login in some application configurations if isinstance(app, HTTPFound) and environ.get(self.auth_state): log.debug('Got HTTPFound(302) from repoze.who.application') - path = [] - for part in urlparse(app.location()): - if part.startswith(self.csrf_token_id): - path.append('') - else: - path.append(part) - path[4] += self.csrf_token_id + '=' + str(token) - replace_header(app.headers, 'location', urlunparse(path)) + loc = update_qs(app.location(), {self.csrf_token_id: str(token)}) + + replace_header(app.headers, 'location', loc) log.debug('Altered headers: %s' % str(app.headers)) else: log.warning("Invalid session cookie %r, not setting CSRF token!" %session_id)