hg-ssh
author Paul Crowley <paul@lshift.net>
Thu, 05 Jun 2008 16:53:57 +0100
changeset 32 4059dbe9f26a
parent 25 9d78dca32325
permissions -rwxr-xr-x
new break-in system

#!/usr/bin/env python
#
# Copyright 2008 LShift Ltd
# Copyright 2005-2007 by Intevation GmbH <intevation@intevation.de>
# Authors:
# Paul Crowley <paul@lshift.net>
# Thomas Arendsen Hein <thomas@intevation.de>
# with ideas from  Mathieu PASQUET <kiorky@cryptelium.net>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.

"""
hg-ssh - limit access to hg repositories reached via ssh.  Part of
hg-admin-tools.

This script is called by hg-ssh-wrapper with no arguments - everything
should be in enviroment variables:

HG_ACCESS_RULES_FILE identifies the path to the rules file
REMOTE_USER the remote user (which is the key used by ssh)
SSH_ORIGINAL_COMMAND the command the user was trying to run

It uses SSH_ORIGINAL_COMMAND to determine what the user was trying to
do and to what repository, and then checks each rule in the rule file
in turn for a matching rule which decides what to do, defaulting to
disallowing the action.

"""

# enable importing on demand to reduce startup time
from mercurial import demandimport; demandimport.enable()

from mercurial import dispatch

import sys, os
import ruleset

def fail(message):
    #logfile.write("Fail: %s\n" % message)
    sys.stderr.write(message + "\n")
    sys.exit(-1)

def getpath(path):
    if path.endswith("/"):
        path = path[:-1]
    if not ruleset.goodpath(path):
        fail("Disallowing path: %s" % path)
    return path

def get_cmd(rules, cmd):
    if cmd.startswith('hg -R ') and cmd.endswith(' serve --stdio'):
        repo = getpath(cmd[6:-14])
        if rules.allow("read", repo=repo):
            os.environ["HG_REPO_PATH"] = repo
            return ['-R', repo, 'serve', '--stdio']
    elif cmd.startswith('hg init '):
        repo = getpath(cmd[8:])
        if rules.allow("init", repo=repo):
            os.environ["HG_REPO_PATH"] = repo
            return ['init', repo]
    fail("Illegal command %r" % cmd)

#logfile = open("/tmp/hg-ssh.%d.txt" % os.getpid(), "w")
#logfile.write("Started: %s\n" % sys.argv)

if len(sys.argv) != 1:
    fail("hg-ssh must have no arguments (%s)" 
        % sys.argv)

rules = ruleset.Ruleset.readfile(os.environ['HG_ACCESS_RULES_FILE'])
rules.set(user = getpath(os.environ['REMOTE_USER']))
rules.set(branch = None, file = None)
todispatch = get_cmd(rules, 
    os.environ.get('SSH_ORIGINAL_COMMAND', '?'))
dispatch.dispatch(todispatch)