--- a/src/hg-ssh Mon Oct 12 12:08:49 2009 +0100
+++ b/src/hg-ssh Mon Oct 12 16:04:07 2009 +0100
@@ -33,40 +33,40 @@
from mercurial import dispatch
-import sys, os
+import sys, os, os.path
from mercurialserver import ruleset, paths
def fail(message):
- #logfile.write("Fail: %s\n" % message)
- sys.stderr.write(message + "\n")
+ sys.stderr.write("mercurial-server: %s\n" % message)
sys.exit(-1)
-def getpath(path):
- path = path.rstrip("/")
- if not ruleset.goodpath(path):
- fail("Disallowing path: %s" % path)
- return path
+def checkpath(path)
+ path = os.path.dirname(path)
+ if path == "":
+ return
+ if os.path.exists(path + "/.hg"):
+ raise ruleset.AccessException()
+ checkpath(path)
-def try_cmd(cmd):
- if cmd.startswith('hg -R ') and cmd.endswith(' serve --stdio'):
- repo = getpath(cmd[6:-14])
- ruleset.rules.set(repo=repo)
- if ruleset.rules.allow("read", branch=None, file=None):
- dispatch.dispatch(['-R', repo, 'serve', '--stdio'])
- return
- elif cmd.startswith('hg init '):
- repo = getpath(cmd[8:])
- ruleset.rules.set(repo=repo)
- if ruleset.rules.allow("init", branch=None, file=None):
- dispatch.dispatch(['init', repo])
- return
- fail("Illegal command %r" % cmd)
+def getrepo(op, repo):
+ repo = os.path.normcase(os.path.normpath(repo.rstrip("/")))
+ if len(repo) == 0:
+ fail("path to repository seems to be empty")
+ if repo.startswith("/"):
+ fail("absolute paths are not supported")
+ for component in repo.split("/"):
+ if component.startswith("."):
+ fail("paths cannot contain dot file components")
+ ruleset.rules.set(repo=repo)
+ ruleset.rules.check(op, branch=None, file=None)
+ checkpath(repo)
+ return repo
#logfile = open("/tmp/hg-ssh.%d.txt" % os.getpid(), "w")
#logfile.write("Started: %s\n" % sys.argv)
if len(sys.argv) != 2:
- fail("hg-ssh must have exactly one argument (%s)"
+ fail("hg-ssh wrongly called, is authorized_keys corrupt? (%s)"
% sys.argv)
paths.setExePath()
@@ -85,4 +85,25 @@
if os.path.isfile(f):
ruleset.rules.readfile(f)
-try_cmd(os.environ.get('SSH_ORIGINAL_COMMAND', '?'))
+cmd = os.environ.get('SSH_ORIGINAL_COMMAND', '')
+try:
+ if cmd.startswith('hg -R ') and cmd.endswith(' serve --stdio'):
+ repo = getrepo("read", cmd[6:-14])
+ if not os.path.isdir(repo + "/.hg")
+ fail("no such repository %s" % repo)
+ dispatch.dispatch(['-R', repo, 'serve', '--stdio'])
+ elif cmd.startswith('hg init '):
+ repo = getrepo("init", cmd[8:])
+ if os.path.exists(repo):
+ fail("%s exists" % repo)
+ d = os.path.dirname(repo)
+ if d != "" and not os.path.isdir(d):
+ os.makedirs(d)
+ dispatch.dispatch(['init', repo])
+ elif cmd == "":
+ fail("direct logins on the hg account prohibited ")
+ else:
+ fail("illegal command %r" % cmd)
+except ruleset.AccessException:
+ fail("access denied")
+