Mercurial > kallithea
changeset 7715:a444c46a0649
middleware: fix handling of Git 'info/refs' command to give correct access control
For a pull, the Git client first sends an 'info/refs' command with a
'service=git-upload-pack' query, then it sends the actual 'git-upload-pack'
command.
For a push, the Git client first sends an 'info/refs' command with a
'service=git-receive-pack' query, then it sends the actual 'git-receive-pack'
command.
Before, the 'info/refs' commands would fall back to the default of trying to
use the action of the previous request. That seems wrong.
Instead, authorize the 'info/refs' command just like the actual command it
references.
path_info will now be checked more than before. Mainly because that is more
correct and more explicit and "better" to do it that way. It might also give
some safety.
author | Mads Kiilerich <mads@kiilerich.com> |
---|---|
date | Mon, 07 Jan 2019 01:58:16 +0100 |
parents | ce2a4ef8cd5f |
children | a4a4bcc09ac5 |
files | kallithea/lib/middleware/simplegit.py |
diffstat | 1 files changed, 18 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/kallithea/lib/middleware/simplegit.py Mon Jan 07 01:50:56 2019 +0100 +++ b/kallithea/lib/middleware/simplegit.py Mon Jan 07 01:58:16 2019 +0100 @@ -148,22 +148,25 @@ def __get_action(self, environ): """ - Maps Git request commands into a pull or push command. - - :param environ: + Maps Git request commands into 'pull' or 'push'. """ - service = environ['QUERY_STRING'].split('=') - - if len(service) > 1: - service_cmd = service[1] - mapping = { - 'git-receive-pack': 'push', - 'git-upload-pack': 'pull', - } - op = mapping[service_cmd] - self._git_stored_op = op - # try to fallback to stored variable as we don't know if the last - # operation is pull/push + mapping = { + 'git-receive-pack': 'push', + 'git-upload-pack': 'pull', + } + path_info = environ.get('PATH_INFO', '') + m = GIT_PROTO_PAT.match(path_info) + if m is not None: + cmd = m.group(2) + if cmd == 'info/refs': + service = environ['QUERY_STRING'].split('=') + cmd = service[1] if len(service) > 1 else None + if cmd in mapping: + self._git_stored_op = mapping[cmd] + elif cmd in mapping: + self._git_stored_op = mapping[cmd] + # fallback to stored variable as we don't know if the last + # operation is pull/push return self._git_stored_op def _handle_githooks(self, repo_name, action, baseui, environ):