Changeset - 3ee4ac068369
[Not reviewed]
stable
0 1 0
Mads Kiilerich - 7 years ago 2018-10-21 15:18:43
mads@kiilerich.com
Grafted from: f8196b330d10
hg: explicit handling of the 'batch' protocol command - consider it a "push" command if any of the batch commands are

This change mitigates some privilege escalation problems like CVE-2018-1000132
which was fixed in Mercurial 4.5.1 and currently is described on
https://www.mercurial-scm.org/wiki/WhatsNew#Mercurial_4.5.1_.2F_4.5.2_.282018-03-06.29 .
1 file changed with 30 insertions and 0 deletions:
0 comments (0 inline, 0 general)
kallithea/lib/middleware/simplehg.py
Show inline comments
 
@@ -31,6 +31,7 @@ Original author and date, and relevant c
 
import os
 
import logging
 
import traceback
 
import urllib
 

	
 
from paste.httpheaders import REMOTE_USER, AUTH_TYPE
 
from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \
 
@@ -66,6 +67,24 @@ def is_mercurial(environ):
 
    return ishg_path
 

	
 

	
 
def get_header_hgarg(environ):
 
    """Decode the special Mercurial encoding of big requests over multiple headers.
 
    >>> get_header_hgarg({})
 
    ''
 
    >>> get_header_hgarg({'HTTP_X_HGARG_0': ' ', 'HTTP_X_HGARG_1': 'a','HTTP_X_HGARG_2': '','HTTP_X_HGARG_3': 'b+c %20'})
 
    'ab+c %20'
 
    """
 
    chunks = []
 
    i = 1
 
    while True:
 
        v = environ.get('HTTP_X_HGARG_%d' % i)
 
        if v is None:
 
            break
 
        chunks.append(v)
 
        i += 1
 
    return ''.join(chunks)
 

	
 

	
 
class SimpleHg(BaseVCSController):
 

	
 
    def _handle_request(self, environ, start_response):
 
@@ -278,6 +297,17 @@ class SimpleHg(BaseVCSController):
 
            parts = qry.split('=', 1)
 
            if len(parts) == 2 and parts[0] == 'cmd':
 
                cmd = parts[1]
 
                if cmd == 'batch':
 
                    hgarg = get_header_hgarg(environ)
 
                    if not hgarg.startswith('cmds='):
 
                        return 'push' # paranoid and safe
 
                    for cmd_arg in hgarg[5:].split(';'):
 
                        cmd, _args = urllib.unquote_plus(cmd_arg).split(' ', 1)
 
                        op = mapping.get(cmd, 'pull')
 
                        if op != 'pull':
 
                            assert op == 'push'
 
                            return 'push'
 
                    return 'pull'
 
                return mapping.get(cmd, 'pull')
 

	
 
        raise Exception('Unable to detect pull/push action !!'
0 comments (0 inline, 0 general)