17 # enable importing on demand to reduce startup time |
17 # enable importing on demand to reduce startup time |
18 from mercurial import demandimport; demandimport.enable() |
18 from mercurial import demandimport; demandimport.enable() |
19 |
19 |
20 from mercurial import dispatch |
20 from mercurial import dispatch |
21 |
21 |
|
22 try: |
|
23 request = dispatch.request |
|
24 except AttributeError: |
|
25 request = list |
|
26 |
22 import sys, os, os.path |
27 import sys, os, os.path |
23 import base64 |
28 import base64 |
24 from mercurialserver import config, ruleset |
29 from mercurialserver import config, ruleset |
25 |
30 |
26 def fail(message): |
31 def fail(message): |
27 sys.stderr.write("mercurial-server: %s\n" % message) |
32 sys.stderr.write("mercurial-server: %s\n" % message) |
28 sys.exit(-1) |
33 sys.exit(-1) |
29 |
34 |
30 def checkDots(path): |
35 config.initExe() |
|
36 |
|
37 for k,v in config.getEnv(): |
|
38 os.environ[k.upper()] = v |
|
39 |
|
40 if len(sys.argv) == 3 and sys.argv[1] == "--base64": |
|
41 ruleset.rules.set(user = base64.b64decode(sys.argv[2])) |
|
42 elif len(sys.argv) == 2: |
|
43 ruleset.rules.set(user = sys.argv[1]) |
|
44 else: |
|
45 fail("hg-ssh wrongly called, is authorized_keys corrupt? (%s)" |
|
46 % sys.argv) |
|
47 |
|
48 os.chdir(config.getReposPath()) |
|
49 |
|
50 for f in config.getAccessPaths(): |
|
51 if os.path.isfile(f): |
|
52 ruleset.rules.readfile(f) |
|
53 |
|
54 alloweddots = config.getAllowedDots() |
|
55 |
|
56 def dotException(pathtail): |
|
57 for ex in alloweddots: |
|
58 splex = ex.split("/") |
|
59 if len(pathtail) >= len(splex) and pathtail[:len(splex)] == splex: |
|
60 return True |
|
61 return False |
|
62 |
|
63 def checkDots(path, pathtail = []): |
31 head, tail = os.path.split(path) |
64 head, tail = os.path.split(path) |
32 if tail.startswith("."): |
65 pathtail = [tail] + pathtail |
33 fail("paths cannot contain dot file components") |
66 if tail.startswith(".") and not dotException(pathtail): |
|
67 fail("paths cannot contain dot file components") |
34 if head: |
68 if head: |
35 checkDots(head) |
69 checkDots(head, pathtail) |
36 |
70 |
37 def getrepo(op, repo): |
71 def getrepo(op, repo): |
38 # First canonicalise, then check the string, then the rules |
72 # First canonicalise, then check the string, then the rules |
39 repo = repo.strip().rstrip("/") |
73 repo = repo.strip().rstrip("/") |
40 if len(repo) == 0: |
74 if len(repo) == 0: |
45 ruleset.rules.set(repo=repo) |
79 ruleset.rules.set(repo=repo) |
46 if not ruleset.rules.allow(op, branch=None, file=None): |
80 if not ruleset.rules.allow(op, branch=None, file=None): |
47 fail("access denied") |
81 fail("access denied") |
48 return repo |
82 return repo |
49 |
83 |
50 config.initExe() |
|
51 |
|
52 for k,v in config.getEnv(): |
|
53 os.environ[k.upper()] = v |
|
54 |
|
55 if len(sys.argv) == 3 and sys.argv[1] == "--base64": |
|
56 ruleset.rules.set(user = base64.b64decode(sys.argv[2])) |
|
57 elif len(sys.argv) == 2: |
|
58 ruleset.rules.set(user = sys.argv[1]) |
|
59 else: |
|
60 fail("hg-ssh wrongly called, is authorized_keys corrupt? (%s)" |
|
61 % sys.argv) |
|
62 |
|
63 os.chdir(config.getReposPath()) |
|
64 |
|
65 for f in config.getAccessPaths(): |
|
66 if os.path.isfile(f): |
|
67 ruleset.rules.readfile(f) |
|
68 |
|
69 cmd = os.environ.get('SSH_ORIGINAL_COMMAND', None) |
84 cmd = os.environ.get('SSH_ORIGINAL_COMMAND', None) |
70 if cmd is None: |
85 if cmd is None: |
71 fail("direct logins on the hg account prohibited") |
86 fail("direct logins on the hg account prohibited") |
72 elif cmd.startswith('hg -R ') and cmd.endswith(' serve --stdio'): |
87 elif cmd.startswith('hg -R ') and cmd.endswith(' serve --stdio'): |
73 repo = getrepo("read", cmd[6:-14]) |
88 repo = getrepo("read", cmd[6:-14]) |
74 if not os.path.isdir(repo + "/.hg"): |
89 if not os.path.isdir(repo + "/.hg"): |
75 fail("no such repository %s" % repo) |
90 fail("no such repository %s" % repo) |
76 dispatch.dispatch(['-R', repo, 'serve', '--stdio']) |
91 dispatch.dispatch(request(['-R', repo, 'serve', '--stdio'])) |
77 elif cmd.startswith('hg init '): |
92 elif cmd.startswith('hg init '): |
78 repo = getrepo("init", cmd[8:]) |
93 repo = getrepo("init", cmd[8:]) |
79 if os.path.exists(repo): |
94 if os.path.exists(repo): |
80 fail("%s exists" % repo) |
95 fail("%s exists" % repo) |
81 d = os.path.dirname(repo) |
96 d = os.path.dirname(repo) |
82 if d != "" and not os.path.isdir(d): |
97 if d != "" and not os.path.isdir(d): |
83 os.makedirs(d) |
98 os.makedirs(d) |
84 dispatch.dispatch(['init', repo]) |
99 dispatch.dispatch(request(['init', repo])) |
85 else: |
100 else: |
86 fail("illegal command %r" % cmd) |
101 fail("illegal command %r" % cmd) |
87 |
|