diff -r 7e659a6870de -r dcd195f3e52c hg-ssh --- a/hg-ssh Tue Apr 15 18:30:43 2008 +0100 +++ b/hg-ssh Wed Apr 16 12:43:21 2008 +0100 @@ -1,34 +1,24 @@ #!/usr/bin/env python # # Copyright 2008 LShift Ltd -# Modified by Paul Crowley -# with ideas from Mathieu PASQUET # Copyright 2005-2007 by Intevation GmbH # Author(s): +# Paul Crowley # Thomas Arendsen Hein +# with ideas from Mathieu PASQUET # # This software may be used and distributed according to the terms # of the GNU General Public License, incorporated herein by reference. """ -hg-ssh - a wrapper for ssh access to a limited set of mercurial repos +hg-ssh - limit access to hg repositories reached via ssh. Part of hg-admin-tools. -DO NOT USE WITHOUT READING THE SOURCE! In particular note that we HARDWIRE -the path to hgadmin/hg-ssh-access.conf. +This script is called by hg-ssh-wrapper with two arguments: -To be used in ~/.ssh/authorized_keys with the "command" option, see sshd(8): -command="hg-ssh keyid" ssh-dss ... -(probably together with these other useful options: - no-port-forwarding,no-X11-forwarding,no-agent-forwarding) - -This allows pull/push over ssh to to the repositories given as arguments. +hg-ssh -If all your repositories are subdirectories of a common directory, you can -allow shorter paths with: -command="cd path/to/my/repositories && hg-ssh repo1 subdir/repo2" - -You can use pattern matching of your normal shell, e.g.: -command="cd repos && hg-ssh user/thomas/* projects/{mercurial,foo}" +It expects to find the command the SSH user was trying to run in the environment variable +SSH_ORIGINAL_COMMAND, and uses it 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 @@ -49,7 +39,6 @@ if goodpathre.match(path) is None: fail("Disallowing path: %s" % path) - # Don't put anything except *A-Za-z0-9_- in rule globs or # you'll probably break security. No regexp metachars, not even . # We may fix this later. @@ -61,10 +50,10 @@ pattern = pattern.replace("*", "[%s]*" % allowedchars) return re.compile(pattern + "$").match(match) is not None -def testrule(keyname, path, applicable): +def testrule(rulefile keyname, path, applicable): goodpath(keyname) goodpath(path) - f = open("hgadmin/hg-ssh-access.conf") + f = open(rulefile) try: for l in f: l = l.strip() @@ -78,26 +67,26 @@ finally: f.close() -def get_cmd(keyname, cmd): +def get_cmd(rulefile, keyname, cmd): if cmd.startswith('hg -R ') and cmd.endswith(' serve --stdio'): path = cmd[6:-14] - if testrule(keyname, path, set(["allow", "init"])): + if testrule(rulefile, keyname, path, set(["allow", "init"])): return ['-R', path, 'serve', '--stdio'] elif cmd.startswith('hg init '): path = cmd[8:] - if testrule(keyname, path, set(["init"])): + if testrule(rulefile, keyname, path, set(["init"])): return ['init', path] 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) != 2: - fail("Error in hg-ssh configuration in .ssh/authorized_keys: too many arguments (%s)" +if len(sys.argv) != 3: + fail("hg-ssh must have exactly two arguments (%s)" % sys.argv) -keyname = sys.argv[1] -todispatch = get_cmd(keyname, os.environ.get('SSH_ORIGINAL_COMMAND', '?')) -os.environ["HG_ACL_USER"] = keyname +rulefile = sys.argv[1] +keyname = sys.argv[2] +todispatch = get_cmd(rulefile, keyname, os.environ.get('SSH_ORIGINAL_COMMAND', '?')) dispatch.dispatch(todispatch)