changeset 1573:1453513eaa7e

use tickets for editing, cfg.edit_ticketing, make tickets more safe, invalidate old tickets
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Mon, 18 Sep 2006 21:54:59 +0200
parents f6136eb3b021
children 7a5aa14c6c00
files MoinMoin/PageEditor.py MoinMoin/PageGraphicalEditor.py MoinMoin/action/__init__.py MoinMoin/action/edit.py MoinMoin/config/multiconfig.py MoinMoin/userform.py MoinMoin/wikiutil.py
diffstat 7 files changed, 38 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/PageEditor.py	Mon Sep 18 21:31:27 2006 +0200
+++ b/MoinMoin/PageEditor.py	Mon Sep 18 21:54:59 2006 +0200
@@ -304,6 +304,9 @@
         # Send revision of the page our edit is based on
         self.request.write('<input type="hidden" name="rev" value="%d">' % (rev,))
 
+        # Create and send a ticket, so we can check the POST
+        self.request.write('<input type="hidden" name="ticket" value="%s">' % wikiutil.createTicket(self.request))
+
         # Save backto in a hidden input
         backto = form.get('backto', [None])[0]
         if backto:
--- a/MoinMoin/PageGraphicalEditor.py	Mon Sep 18 21:31:27 2006 +0200
+++ b/MoinMoin/PageGraphicalEditor.py	Mon Sep 18 21:54:59 2006 +0200
@@ -208,6 +208,9 @@
         # Send revision of the page our edit is based on
         self.request.write('<input type="hidden" name="rev" value="%d">' % (rev,))
 
+        # Create and send a ticket, so we can check the POST
+        self.request.write('<input type="hidden" name="ticket" value="%s">' % wikiutil.createTicket(self.request))
+
         # Save backto in a hidden input
         backto = form.get('backto', [None])[0]
         if backto:
--- a/MoinMoin/action/__init__.py	Mon Sep 18 21:31:27 2006 +0200
+++ b/MoinMoin/action/__init__.py	Mon Sep 18 21:54:59 2006 +0200
@@ -83,7 +83,7 @@
         # Require a valid ticket. Make outside attacks harder by
         # requiring two full HTTP transactions
         ticket = self.form.get('ticket', [''])[0]
-        return wikiutil.checkTicket(ticket)
+        return wikiutil.checkTicket(self.request, ticket)
 
     # UI ---------------------------------------------------------------------
     def get_form_html(self, buttons_html):
@@ -122,7 +122,7 @@
         buttons_html = "".join(buttons_html)
 
         if self.use_ticket:
-            ticket_html = '<input type="hidden" name="ticket" value="%s">' % wikiutil.createTicket()
+            ticket_html = '<input type="hidden" name="ticket" value="%s">' % wikiutil.createTicket(self.request)
         else:
             ticket_html = ''
 
--- a/MoinMoin/action/edit.py	Mon Sep 18 21:31:27 2006 +0200
+++ b/MoinMoin/action/edit.py	Mon Sep 18 21:54:59 2006 +0200
@@ -78,6 +78,13 @@
     # did user hit cancel button?
     cancelled = request.form.has_key('button_cancel')
 
+    if request.cfg.edit_ticketing:
+        ticket = request.form.get('ticket', [''])[0]
+        if not wikiutil.checkTicket(request, ticket):
+            msg = _('Please use the interactive user interface to use action %(actionname)s!') % {'actionname': 'edit' }
+            pg.send_page(request, msg=msg)
+            return
+
     # convert input from Graphical editor
     from MoinMoin.converter.text_html_text_moin_wiki import convert, ConvertError
     try:
--- a/MoinMoin/config/multiconfig.py	Mon Sep 18 21:31:27 2006 +0200
+++ b/MoinMoin/config/multiconfig.py	Mon Sep 18 21:54:59 2006 +0200
@@ -275,6 +275,7 @@
 """),
     }
     edit_locking = 'warn 10' # None, 'warn <timeout mins>', 'lock <timeout mins>'
+    edit_ticketing = True
     edit_rows = 20
 
     hacks = {} # { 'feature1': value1, ... }
--- a/MoinMoin/userform.py	Mon Sep 18 21:31:27 2006 +0200
+++ b/MoinMoin/userform.py	Mon Sep 18 21:54:59 2006 +0200
@@ -154,7 +154,7 @@
 
         # Select user profile (su user) - only works with cookie auth active.
         if form.has_key('select_user'):
-            if (wikiutil.checkTicket(self.request.form['ticket'][0]) and
+            if (wikiutil.checkTicket(self.request, self.request.form['ticket'][0]) and
                 self.request.request_method == 'POST' and
                 self.request.user.isSuperUser()):
                 su_user = form.get('selected_user', [''])[0]
@@ -467,7 +467,7 @@
         self.make_form()
 
         if self.request.user.isSuperUser():
-            ticket = wikiutil.createTicket()
+            ticket = wikiutil.createTicket(self.request)
             self.make_row(_('Select User'), [self._user_select()])
             self._form.append(html.INPUT(type="hidden", name="ticket", value="%s" % ticket))
             buttons = [("select_user", _('Select User'))]
--- a/MoinMoin/wikiutil.py	Mon Sep 18 21:31:27 2006 +0200
+++ b/MoinMoin/wikiutil.py	Mon Sep 18 21:54:59 2006 +0200
@@ -1560,25 +1560,38 @@
 ### Tickets - used by RenamePage and DeletePage
 ########################################################################
 
-def createTicket(tm=None):
+def createTicket(request, tm=None):
     """Create a ticket using a site-specific secret (the config)"""
     import sha
     ticket = tm or "%010x" % time.time()
     digest = sha.new()
     digest.update(ticket)
 
-    cfgvars = vars(config)
-    for var in cfgvars.values():
-        if isinstance(var, str):
+    varnames = ['data_dir', 'data_underlay_dir', 'language_default',
+                'mail_smarthost', 'mail_from', 'page_front_page',
+                'theme_default', 'sitename', 'logo_string',
+                'interwikiname', 'user_homewiki', 'acl_rights_before', ]
+    for varname in varnames:
+        var = getattr(request.cfg, varname, None)
+        if isinstance(var, (str, unicode)):
             digest.update(repr(var))
 
     return "%s.%s" % (ticket, digest.hexdigest())
 
 
-def checkTicket(ticket):
+def checkTicket(request, ticket):
     """Check validity of a previously created ticket"""
-    timestamp = ticket.split('.')[0]
-    ourticket = createTicket(timestamp)
+    try:
+        timestamp_str = ticket.split('.')[0]
+        timestamp = int(timestamp_str, 16)
+    except ValueError:
+        # invalid or empty ticket
+        return False
+    now = time.time()
+    if timestamp < now - 10*3600:
+        # we don't accept tickets older than 10h
+        return False
+    ourticket = createTicket(request, timestamp_str)
     return ticket == ourticket