~ubuntu-branches/ubuntu/oneiric/mercurial-server/oneiric

« back to all changes in this revision

Viewing changes to src/hg-ssh

  • Committer: Bazaar Package Importer
  • Author(s): Paul Crowley
  • Date: 2009-11-12 11:21:55 UTC
  • Revision ID: james.westby@ubuntu.com-20091112112155-j2sn4qphwukaffh0
Tags: upstream-0.9
ImportĀ upstreamĀ versionĀ 0.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
#
 
3
# Copyright 2008-2009 LShift Ltd
 
4
# Copyright 2005-2007 by Intevation GmbH <intevation@intevation.de>
 
5
# Authors:
 
6
# Paul Crowley <paul@lshift.net>
 
7
# Thomas Arendsen Hein <thomas@intevation.de>
 
8
# with ideas from  Mathieu PASQUET <kiorky@cryptelium.net>
 
9
#
 
10
# This software may be used and distributed according to the terms
 
11
# of the GNU General Public License, incorporated herein by reference.
 
12
 
 
13
"""
 
14
hg-ssh - limit access to hg repositories reached via ssh.  Part of
 
15
mercurial-server.
 
16
 
 
17
This script is called by hg-ssh-wrapper with no arguments - everything
 
18
should be in enviroment variables:
 
19
 
 
20
HG_ACCESS_RULES_PATH identifies the paths to the rule files
 
21
REMOTE_USER the remote user (which is the key used by ssh)
 
22
SSH_ORIGINAL_COMMAND the command the user was trying to run
 
23
 
 
24
It uses SSH_ORIGINAL_COMMAND to determine what the user was trying to
 
25
do and to what repository, and then checks each rule in the rule file
 
26
in turn for a matching rule which decides what to do, defaulting to
 
27
disallowing the action.
 
28
 
 
29
"""
 
30
 
 
31
# enable importing on demand to reduce startup time
 
32
from mercurial import demandimport; demandimport.enable()
 
33
 
 
34
from mercurial import dispatch
 
35
 
 
36
import sys, os, os.path
 
37
import base64
 
38
from mercurialserver import ruleset, paths
 
39
 
 
40
def fail(message):
 
41
    sys.stderr.write("mercurial-server: %s\n" % message)
 
42
    sys.exit(-1)
 
43
 
 
44
def checkDots(path):
 
45
    head, tail = os.path.split(path)
 
46
    if tail.startswith("."):
 
47
        fail("paths cannot contain dot file components")
 
48
    if head:
 
49
        checkDots(head)
 
50
 
 
51
def checkParents(path):
 
52
    path = os.path.dirname(path)
 
53
    if path == "":
 
54
        return
 
55
    if os.path.exists(path + "/.hg"):
 
56
        fail("Cannot create repo under existing repo")
 
57
    checkParents(path)
 
58
 
 
59
def getrepo(op, repo):
 
60
    # First canonicalise, then check the string, then the rules
 
61
    # and finally the filesystem.
 
62
    repo = repo.rstrip("/")
 
63
    if len(repo) == 0:
 
64
        fail("path to repository seems to be empty")
 
65
    if repo.startswith("/"):
 
66
        fail("absolute paths are not supported")
 
67
    checkDots(repo)
 
68
    ruleset.rules.set(repo=repo)
 
69
    if not ruleset.rules.allow(op, branch=None, file=None):
 
70
        fail("access denied")
 
71
    checkParents(repo)
 
72
    return repo
 
73
 
 
74
paths.setExePath()
 
75
 
 
76
if len(sys.argv) == 3 and sys.argv[1] == "--base64":
 
77
    ruleset.rules.set(user = base64.b64decode(sys.argv[2]))
 
78
elif len(sys.argv) == 2:
 
79
    ruleset.rules.set(user = sys.argv[1])
 
80
else:
 
81
    fail("hg-ssh wrongly called, is authorized_keys corrupt? (%s)" 
 
82
        % sys.argv)
 
83
 
 
84
# Use a different hgrc for remote pulls - this way you can set
 
85
# up access.py for everything at once without affecting local operations
 
86
 
 
87
os.environ['HGRCPATH'] = paths.getHgrcPaths()
 
88
 
 
89
os.chdir(paths.getReposPath())
 
90
 
 
91
for f in paths.getAccessPaths():
 
92
    if os.path.isfile(f):
 
93
        ruleset.rules.readfile(f)
 
94
 
 
95
cmd = os.environ.get('SSH_ORIGINAL_COMMAND', None)
 
96
if cmd is None:
 
97
    fail("direct logins on the hg account prohibited")
 
98
elif cmd.startswith('hg -R ') and cmd.endswith(' serve --stdio'):
 
99
    repo = getrepo("read", cmd[6:-14])
 
100
    if not os.path.isdir(repo + "/.hg"):
 
101
        fail("no such repository %s" % repo)
 
102
    dispatch.dispatch(['-R', repo, 'serve', '--stdio'])
 
103
elif cmd.startswith('hg init '):
 
104
    repo = getrepo("init", cmd[8:])
 
105
    if os.path.exists(repo):
 
106
        fail("%s exists" % repo)
 
107
    d = os.path.dirname(repo)
 
108
    if d != "" and not os.path.isdir(d):
 
109
        os.makedirs(d)
 
110
    dispatch.dispatch(['init', repo])
 
111
else:
 
112
    fail("illegal command %r" % cmd)
 
113