Mercurial > p > roundup > code
comparison test/test_cgi.py @ 5203:9f490cc0effe
Also rename test to testCsrfProtection
Add tests that include valid and invalid @csrf nonce
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Sat, 18 Mar 2017 22:19:51 -0400 |
| parents | a9ace22e0a2f |
| children | 23b8eeaf9864 |
comparison
equal
deleted
inserted
replaced
| 5202:47bd81998ddc | 5203:9f490cc0effe |
|---|---|
| 10 | 10 |
| 11 import unittest, os, shutil, errno, sys, difflib, cgi, re, StringIO | 11 import unittest, os, shutil, errno, sys, difflib, cgi, re, StringIO |
| 12 | 12 |
| 13 from roundup.cgi import client, actions, exceptions | 13 from roundup.cgi import client, actions, exceptions |
| 14 from roundup.cgi.exceptions import FormError | 14 from roundup.cgi.exceptions import FormError |
| 15 from roundup.cgi.templating import HTMLItem, HTMLRequest, NoTemplate | 15 from roundup.cgi.templating import HTMLItem, HTMLRequest, NoTemplate, anti_csrf_nonce |
| 16 from roundup.cgi.templating import HTMLProperty, _HTMLItem | 16 from roundup.cgi.templating import HTMLProperty, _HTMLItem |
| 17 from roundup.cgi.form_parser import FormParser | 17 from roundup.cgi.form_parser import FormParser |
| 18 from roundup import init, instance, password, hyperdb, date | 18 from roundup import init, instance, password, hyperdb, date |
| 19 | 19 |
| 20 # For testing very simple rendering | 20 # For testing very simple rendering |
| 855 <p><input type="text" name="superseder" value="5000" size="30"></p> | 855 <p><input type="text" name="superseder" value="5000" size="30"></p> |
| 856 </body> | 856 </body> |
| 857 </html> | 857 </html> |
| 858 """.strip ()) | 858 """.strip ()) |
| 859 | 859 |
| 860 def testCsrfHeaderProtection(self): | 860 def testCsrfProtection(self): |
| 861 # need to set SENDMAILDEBUG to prevent | 861 # need to set SENDMAILDEBUG to prevent |
| 862 # downstream issue when email is sent on successful | 862 # downstream issue when email is sent on successful |
| 863 # issue creation. Also delete the file afterwards | 863 # issue creation. Also delete the file afterwards |
| 864 # just tomake sure that someother test looking for | 864 # just tomake sure that someother test looking for |
| 865 # SENDMAILDEBUG won't trip over ours. | 865 # SENDMAILDEBUG won't trip over ours. |
| 892 ':action': 'edit'} | 892 ':action': 'edit'} |
| 893 cl = self.setupClient(form, 'issue', '1') | 893 cl = self.setupClient(form, 'issue', '1') |
| 894 pt = RoundupPageTemplate() | 894 pt = RoundupPageTemplate() |
| 895 pt.pt_edit(page_template, 'text/html') | 895 pt.pt_edit(page_template, 'text/html') |
| 896 out = [] | 896 out = [] |
| 897 print "out1: ", id(out), out | |
| 898 def wh(s): | 897 def wh(s): |
| 899 out.append(s) | 898 out.append(s) |
| 900 cl.write_html = wh | 899 cl.write_html = wh |
| 901 # Enable the following if we get a templating error: | 900 # Enable the following if we get a templating error: |
| 902 #def send_error (*args, **kw): | 901 #def send_error (*args, **kw): |
| 921 HTMLProperty.is_edit_ok = lambda x : True | 920 HTMLProperty.is_edit_ok = lambda x : True |
| 922 | 921 |
| 923 # test with no headers and config by default requires 1 | 922 # test with no headers and config by default requires 1 |
| 924 cl.inner_main() | 923 cl.inner_main() |
| 925 match_at=out[0].find('Unable to verify sufficient headers') | 924 match_at=out[0].find('Unable to verify sufficient headers') |
| 926 print out[0] | |
| 927 self.assertNotEqual(match_at, -1) | 925 self.assertNotEqual(match_at, -1) |
| 928 del(out[0]) | 926 del(out[0]) |
| 929 | 927 |
| 930 # all the rest of these allow at least one header to pass | 928 # all the rest of these allow at least one header to pass |
| 931 # and the edit happens with a redirect back to issue 1 | 929 # and the edit happens with a redirect back to issue 1 |
| 969 # this raises an error as the header check passes and | 967 # this raises an error as the header check passes and |
| 970 # it did the edit and tries to send mail. | 968 # it did the edit and tries to send mail. |
| 971 cl.inner_main() | 969 cl.inner_main() |
| 972 match_at=out[0].find('Invalid X-FORWARDED-HOST whoami.net') | 970 match_at=out[0].find('Invalid X-FORWARDED-HOST whoami.net') |
| 973 self.assertNotEqual(match_at, -1) | 971 self.assertNotEqual(match_at, -1) |
| 972 del(cl.env['HTTP_X-FORWARDED-HOST']) | |
| 973 del(out[0]) | |
| 974 | |
| 975 import copy | |
| 976 | |
| 977 form2 = copy.copy(form) | |
| 978 form2.update({'@csrf': 'booogus'}) | |
| 979 # add a bogus csrf field to the form and rerun the inner_main | |
| 980 cl.form = makeForm(form2) | |
| 981 | |
| 982 cl.env['HTTP_REFERER'] = 'http://whoami.com/path/' | |
| 983 cl.inner_main() | |
| 984 match_at=out[0].find('Invalid csrf token found: booogus') | |
| 985 self.assertEqual(match_at, 36) | |
| 986 del(out[0]) | |
| 987 | |
| 988 form2 = copy.copy(form) | |
| 989 nonce = anti_csrf_nonce(cl, cl) | |
| 990 form2.update({'@csrf': nonce}) | |
| 991 # add a real csrf field to the form and rerun the inner_main | |
| 992 cl.form = makeForm(form2) | |
| 993 cl.inner_main() | |
| 994 # csrf passes and redirects to the new issue. | |
| 995 match_at=out[0].find('Redirecting to <a href="http://whoami.com/path/issue1?@ok_message') | |
| 996 self.assertEqual(match_at, 0) | |
| 997 del(cl.env['HTTP_REFERER']) | |
| 974 del(out[0]) | 998 del(out[0]) |
| 975 | 999 |
| 976 # clean up from email log | 1000 # clean up from email log |
| 977 if os.path.exists(SENDMAILDEBUG): | 1001 if os.path.exists(SENDMAILDEBUG): |
| 978 os.remove(SENDMAILDEBUG) | 1002 os.remove(SENDMAILDEBUG) |
