#!/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 ofhg-admin-tools.This script is called by hg-ssh-wrapper with no arguments - everythingshould be in enviroment variables:HG_ACCESS_RULES_FILE identifies the path to the rules fileREMOTE_USER the remote user (which is the key used by ssh)SSH_ORIGINAL_COMMAND the command the user was trying to runIt uses SSH_ORIGINAL_COMMAND to determine what the user was trying todo and to what repository, and then checks each rule in the rule filein turn for a matching rule which decides what to do, defaulting todisallowing the action."""# enable importing on demand to reduce startup timefrom mercurial import demandimport; demandimport.enable()from mercurial import dispatchimport sys, osimport rulesetdef 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 pathdef 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(remoteuser = getpath(os.environ['REMOTE_USER']))rules.set(branch = None, file = None)todispatch = get_cmd(rules, os.environ.get('SSH_ORIGINAL_COMMAND', '?'))dispatch.dispatch(todispatch)