wireprotoserver: check permissions in main dispatch function
authorGregory Szorc <gregory.szorc@gmail.com>
Tue, 06 Mar 2018 15:08:33 -0800
changeset 36799 c638a13093cf
parent 36798 7574c8173d5e
child 36800 0b18604db95e
wireprotoserver: check permissions in main dispatch function The permissions checking code merged from stable is out of place in the refactored hgweb_mod module. This commit moves the main call to wireprotoserver. We still have some lingering code in hgweb_mod. This will get addressed later. Differential Revision: https://phab.mercurial-scm.org/D2717
mercurial/hgweb/hgweb_mod.py
mercurial/wireprotoserver.py
--- a/mercurial/hgweb/hgweb_mod.py	Tue Mar 06 15:02:53 2018 -0800
+++ b/mercurial/hgweb/hgweb_mod.py	Tue Mar 06 15:08:33 2018 -0800
@@ -357,22 +357,15 @@
         protohandler = wireprotoserver.parsehttprequest(rctx.repo, req, query)
 
         if protohandler:
-            cmd = protohandler['cmd']
             try:
                 if query:
                     raise ErrorResponse(HTTP_NOT_FOUND)
 
                 # TODO fold this into parsehttprequest
-                req.checkperm = lambda op: self.check_perm(rctx, req, op)
-                protohandler['proto'].checkperm = req.checkperm
+                checkperm = lambda op: self.check_perm(rctx, req, op)
+                protohandler['proto'].checkperm = checkperm
 
-                # Assume commands with no defined permissions are writes /
-                # for pushes. This is the safest from a security perspective
-                # because it doesn't allow commands with undefined semantics
-                # from bypassing permissions checks.
-                req.checkperm(perms.get(cmd, 'push'))
-
-                return protohandler['dispatch']()
+                return protohandler['dispatch'](checkperm)
             except ErrorResponse as inst:
                 return protohandler['handleerror'](inst)
 
--- a/mercurial/wireprotoserver.py	Tue Mar 06 15:02:53 2018 -0800
+++ b/mercurial/wireprotoserver.py	Tue Mar 06 15:08:33 2018 -0800
@@ -179,7 +179,8 @@
     return {
         'cmd': cmd,
         'proto': proto,
-        'dispatch': lambda: _callhttp(repo, req, proto, cmd),
+        'dispatch': lambda checkperm: _callhttp(repo, req, proto, cmd,
+                                                checkperm),
         'handleerror': lambda ex: _handlehttperror(ex, req, cmd),
     }
 
@@ -223,7 +224,7 @@
     opts = {'level': ui.configint('server', 'zliblevel')}
     return HGTYPE, util.compengines['zlib'], opts
 
-def _callhttp(repo, req, proto, cmd):
+def _callhttp(repo, req, proto, cmd, checkperm):
     def genversion2(gen, engine, engineopts):
         # application/mercurial-0.2 always sends a payload header
         # identifying the compression engine.
@@ -241,6 +242,12 @@
                            'over HTTP'))
         return []
 
+    # Assume commands with no defined permissions are writes /
+    # for pushes. This is the safest from a security perspective
+    # because it doesn't allow commands with undefined semantics
+    # from bypassing permissions checks.
+    checkperm(wireproto.permissions.get(cmd, 'push'))
+
     rsp = wireproto.dispatch(repo, proto, cmd)
 
     if isinstance(rsp, bytes):