From 3ffaf6b09fb4e9290950d606af598f98ff067c00 Mon Sep 17 00:00:00 2001 From: vangheem Date: Sat, 26 Sep 2015 05:46:54 -0500 Subject: [PATCH] patch pluggable auth csrf with marmoset --- CHANGES.rst | 5 +++++ README.rst | 11 +++++++++++ plone/protect/configure.zcml | 18 +----------------- plone/protect/monkey.py | 15 +++++++++++++++ plone/protect/tests/testPatches.py | 27 +++++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 17 deletions(-) create mode 100644 plone/protect/tests/testPatches.py diff --git a/CHANGES.rst b/CHANGES.rst index e10e034..a163246 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,11 @@ Changelog 3.0.9 (unreleased) ------------------ +- patch pluggable auth with marmoset patch because + the patch would not apply otherwise depending on + somewhat-random import order + [vangheem] + - get auto-csrf protection working on the zope root [vangheem] diff --git a/README.rst b/README.rst index a70a915..ff68f08 100644 --- a/README.rst +++ b/README.rst @@ -195,3 +195,14 @@ To disable all automatic CSRF protection, set the environment variable WARNING! It is very dangerous to do this. Do not do this unless the zeo client with this setting is not public and you know what you are doing. + + +Notes +===== + +This package monkey patches a number of modules in order to better handle CSRF +protection:: + + - Archetypes add forms, add csrf + - Zope2 object locking support + - pluggable auth csrf protection diff --git a/plone/protect/configure.zcml b/plone/protect/configure.zcml index 6adc474..d824e6e 100644 --- a/plone/protect/configure.zcml +++ b/plone/protect/configure.zcml @@ -59,20 +59,4 @@ replacement=".monkey.wl_lockmapping" preserveOriginal="True" /> - - - - - + \ No newline at end of file diff --git a/plone/protect/monkey.py b/plone/protect/monkey.py index 45b2763..06c8dae 100644 --- a/plone/protect/monkey.py +++ b/plone/protect/monkey.py @@ -1,5 +1,7 @@ from urlparse import urlparse, urljoin from plone.protect.auto import safeWrite +import inspect +from Products.PluggableAuthService import utils as pluggable_utils def RedirectTo__call__(self, controller_state): @@ -51,3 +53,16 @@ def pluggableauth__checkCSRFToken(request, token='csrf_token', raises=True): let plone.protect do it's job """ pass + + +def marmoset_patch(func, replacement): + source = inspect.getsource(replacement) + exec source in func.func_globals + func.func_code = replacement.func_code + + +# otherwise the patches do not get applied in some cases +if hasattr(pluggable_utils, 'checkCSRFToken'): + marmoset_patch(pluggable_utils.checkCSRFToken, pluggableauth__checkCSRFToken) +if hasattr(pluggable_utils, 'getCSRFToken'): + marmoset_patch(pluggable_utils.getCSRFToken, pluggableauth__getCSRFToken) \ No newline at end of file diff --git a/plone/protect/tests/testPatches.py b/plone/protect/tests/testPatches.py new file mode 100644 index 0000000..af1778c --- /dev/null +++ b/plone/protect/tests/testPatches.py @@ -0,0 +1,27 @@ +from plone.app.testing import SITE_OWNER_NAME +from plone.app.testing import SITE_OWNER_PASSWORD +from plone.protect.testing import PROTECT_FUNCTIONAL_TESTING +from plone.testing.z2 import Browser +import unittest2 as unittest + + +class TestCSRF(unittest.TestCase): + layer = PROTECT_FUNCTIONAL_TESTING + + def setUp(self): + self.portal = self.layer['portal'] + self.browser = Browser(self.layer['app']) + self.request = self.layer['request'] + self.browser.addHeader( + 'Authorization', 'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)) + + def test_change_password_on_root_does_not_throw_other_csrf_protection(self): + self.browser.open('%s/acl_users/users/manage_users?user_id=%s&passwd=1' % ( + self.layer['app'].absolute_url(), SITE_OWNER_NAME)) + self.browser.getControl(name='password').value = SITE_OWNER_PASSWORD + self.browser.getControl(name='confirm').value = SITE_OWNER_PASSWORD + self.browser.getForm().submit() + self.assertEquals( + self.browser.url, + '%s/acl_users/users/manage_users?manage_tabs_message=password+updated' % ( + self.layer['app'].absolute_url())) \ No newline at end of file