src/hg-ssh
branchdebian
changeset 313 f597eb3b5aaf
parent 306 f832a8aeef44
child 374 7a1d6b228af6
equal deleted inserted replaced
294:31d5c6236f71 313:f597eb3b5aaf
    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