Skip to content

Commit 19800d3

Browse files
committed
My testing was with dbm backends which do an automatic commit on the
otk database. My tests used a mock for the otk database because I don't now how to get a real db into the test, so they didn't test the rdbms code paths. Once I committed to upstream I updated my sqlite based production tracker and boom. Couldn't log in with csrf_enforce = required. I was missing calls to commit to the db which is required for rdbms backends. Added those and also removed redundant code where I was deleting the otk in a few places. Once it's used and I have retrieved data from it, I don't need it. Nuke it upstream from all the code paths that will exit the routine so I don't have to delete in each code path.
1 parent b77d60c commit 19800d3

File tree

2 files changed

+10
-7
lines changed

2 files changed

+10
-7
lines changed

roundup/cgi/client.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,11 +1050,12 @@ def handle_csrf(self, xmlrpc=False):
10501050
if "@csrf" not in self.form:
10511051
if enforce == 'required':
10521052
self.add_error_message(self._("No csrf token found"))
1053+
logger.error(self._("required csrf field missing for user%s"), user)
10531054
return False
10541055
else:
10551056
if enforce == 'logfailure':
10561057
# FIXME include url
1057-
logger.warning(self._("csrf field missing for user%s"), user)
1058+
logger.warning(self._("required csrf field missing for user%s"), user)
10581059
return True
10591060

10601061
key=self.form['@csrf'].value
@@ -1093,28 +1094,29 @@ def handle_csrf(self, xmlrpc=False):
10931094
self.form["@action"].value == "Login":
10941095
if header_pass > 0:
10951096
otks.destroy(key)
1097+
self.db.commit()
10961098
return True
10971099
else:
10981100
self.add_error_message("Reload window before logging in.")
10991101
'''
11001102

1103+
# The key has been used or compromised. Delete it to prevent replay.
1104+
otks.destroy(key)
1105+
self.db.commit()
1106+
11011107
if uid != user:
11021108
if enforce in ('required', "yes"):
11031109
self.add_error_message(self._("Invalid csrf token found: %s")%key)
1104-
otks.destroy(key)
11051110
return False
11061111
elif enforce == 'logfailure':
11071112
logger.warning(self._("csrf uid mismatch for user%s."), user)
1108-
if self.session_api._sid != sid:
1113+
if current_session != sid:
11091114
if enforce in ('required', "yes"):
11101115
self.add_error_message(self._(
11111116
"Invalid csrf session found: %s")%key)
1112-
otks.destroy(key)
11131117
return False
11141118
elif enforce == 'logfailure':
11151119
logger.warning(self._("csrf session mismatch for user%s."), user)
1116-
# Remove the key so a previous csrf key can't be replayed.
1117-
otks.destroy(key)
11181120
return True
11191121

11201122
def opendb(self, username):

roundup/cgi/templating.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def anti_csrf_nonce(self, client, lifetime=None):
8383
# is unpredicatable (depends on number of previous connections etc.)
8484
key = '%s%s%s'%(random.random(),id(self),time.time())
8585
key = hashlib.sha256(key).hexdigest()
86-
86+
8787
while otks.exists(key):
8888
key = '%s%s%s'%(random.random(),id(self),time.time())
8989
key = hashlib.sha256(key).hexdigest()
@@ -103,6 +103,7 @@ def anti_csrf_nonce(self, client, lifetime=None):
103103
otks.set(key, uid=client.db.getuid(),
104104
sid=client.session_api._sid,
105105
__timestamp=time.time() + ((lifetime - 10800) * 60) )
106+
client.db.commit()
106107
return key
107108

108109
### templating

0 commit comments

Comments
 (0)