Mercurial > p > roundup > code
diff test/test_cgi.py @ 5220:14d8f61e6ef2
Reimplemented anti-csrf measures by raising exceptions rather than
returning booleans.
Redoing it using exceptions was the easiest way to return proper
xmlrpc fault messages to the clients.
Also this code should now properly make values set in the form
override values from the database. So no lost work under some
circumstances if the csrf requirements are not met.
Also this code does a better job of cleaning up old csrf tokens.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Wed, 05 Apr 2017 20:56:08 -0400 |
| parents | 44f7e6b958fe |
| children | 8743b7226dc7 |
line wrap: on
line diff
--- a/test/test_cgi.py Mon Mar 27 23:04:30 2017 -0400 +++ b/test/test_cgi.py Wed Apr 05 20:56:08 2017 -0400 @@ -923,6 +923,7 @@ # test with no headers and config by default requires 1 cl.inner_main() match_at=out[0].find('Unable to verify sufficient headers') + print "result of subtest 1:", out[0] self.assertNotEqual(match_at, -1) del(out[0]) @@ -931,6 +932,7 @@ cl.env['HTTP_REFERER'] = 'http://whoami.com/path/' cl.inner_main() match_at=out[0].find('Redirecting to <a href="http://whoami.com/path/issue1?@ok_message') + print "result of subtest 2:", out[0] self.assertEqual(match_at, 0) del(cl.env['HTTP_REFERER']) del(out[0]) @@ -938,6 +940,7 @@ cl.env['HTTP_ORIGIN'] = 'http://whoami.com' cl.inner_main() match_at=out[0].find('Redirecting to <a href="http://whoami.com/path/issue1?@ok_message') + print "result of subtest 3:", out[0] self.assertEqual(match_at, 0) del(cl.env['HTTP_ORIGIN']) del(out[0]) @@ -951,6 +954,7 @@ cl.env['HTTP_HOST'] = 'frontend1.whoami.net' cl.inner_main() match_at=out[0].find('Redirecting to <a href="http://whoami.com/path/issue1?@ok_message') + print "result of subtest 4:", out[0] self.assertNotEqual(match_at, -1) del(cl.env['HTTP_X-FORWARDED-HOST']) del(cl.env['HTTP_HOST']) @@ -959,6 +963,7 @@ cl.env['HTTP_HOST'] = 'whoami.com' cl.inner_main() match_at=out[0].find('Redirecting to <a href="http://whoami.com/path/issue1?@ok_message') + print "result of subtest 5:", out[0] self.assertEqual(match_at, 0) del(cl.env['HTTP_HOST']) del(out[0]) @@ -969,6 +974,7 @@ # it did the edit and tries to send mail. cl.inner_main() match_at=out[0].find('Invalid X-FORWARDED-HOST whoami.net') + print "result of subtest 6:", out[0] self.assertNotEqual(match_at, -1) del(cl.env['HTTP_X-FORWARDED-HOST']) del(out[0]) @@ -977,6 +983,15 @@ # check nonce handling. cl.env['HTTP_REFERER'] = 'http://whoami.com/path/' + # roundup will report a missing token. + cl.db.config['WEB_CSRF_ENFORCE_TOKEN'] = 'required' + cl.inner_main() + match_at=out[0].find('<p>Csrf token is missing.</p>') + print "result of subtest 6a:", out[0], match_at + self.assertEqual(match_at, 33) + del(out[0]) + cl.db.config['WEB_CSRF_ENFORCE_TOKEN'] = 'yes' + import copy form2 = copy.copy(form) form2.update({'@csrf': 'booogus'}) @@ -985,6 +1000,7 @@ cl.inner_main() match_at=out[0].find('Invalid csrf token found: booogus') + print "result of subtest 7:", out[0] self.assertEqual(match_at, 36) del(out[0]) @@ -993,6 +1009,9 @@ # verify that we can see the nonce otks = cl.db.getOTKManager() isitthere = otks.exists(nonce) + print "result of subtest 8:", isitthere + print "otks: user, session", otks.get(nonce, 'uid', default=None), \ + otks.get(nonce, 'session', default=None) self.assertEqual(isitthere, True) form2.update({'@csrf': nonce}) @@ -1001,6 +1020,7 @@ cl.inner_main() # csrf passes and redirects to the new issue. match_at=out[0].find('Redirecting to <a href="http://whoami.com/path/issue1?@ok_message') + print "result of subtest 9:", out[0] self.assertEqual(match_at, 0) del(out[0]) @@ -1009,6 +1029,7 @@ # This should fail as token was wiped by last run. match_at=out[0].find('Invalid csrf token found: %s'%nonce) print "replay of csrf after post use", out[0] + print "result of subtest 10:", out[0] self.assertEqual(match_at, 36) del(out[0]) @@ -1023,11 +1044,13 @@ cl.inner_main() # csrf passes but fail creating new issue because not a post match_at=out[0].find('<p>Invalid request</p>') + print "result of subtest 11:", out[0] self.assertEqual(match_at, 33) del(out[0]) # the token should be gone isitthere = otks.exists(nonce) + print "result of subtest 12:", isitthere self.assertEqual(isitthere, False) # change to post and should fail w/ invalid csrf @@ -1037,6 +1060,7 @@ cl.inner_main() match_at=out[0].find('Invalid csrf token found: %s'%nonce) print "post failure after get", out[0] + print "result of subtest 13:", out[0] self.assertEqual(match_at, 36) del(out[0]) @@ -1091,9 +1115,13 @@ self.assertEqual(out[0], answer) del(out[0]) - # remove the X-REQUESTED-WITH header and get a failure. + # remove the X-REQUESTED-WITH header and get an xmlrpc fault returned del(cl.env['HTTP_X-REQUESTED-WITH']) - self.assertRaises(UsageError,cl.handle_xmlrpc) + cl.handle_xmlrpc() + output="<?xml version='1.0'?>\n<methodResponse>\n<fault>\n<value><struct>\n<member>\n<name>faultCode</name>\n<value><int>1</int></value>\n</member>\n<member>\n<name>faultString</name>\n<value><string><class 'roundup.exceptions.UsageError'>:Required Header Missing</string></value>\n</member>\n</struct></value>\n</fault>\n</methodResponse>\n" + print out[0] + self.assertEqual(output,out[0]) + del(out[0]) # change config to not require X-REQUESTED-WITH header cl.db.config['WEB_CSRF_ENFORCE_HEADER_X-REQUESTED-WITH'] = 'logfailure'
