src/mercurialserver/refreshauth.py
changeset 74 9d2ae2841bf2
child 75 5af89523a9d3
equal deleted inserted replaced
73:5d81ec164e5d 74:9d2ae2841bf2
       
     1 # Copyright 2008-2009 LShift Ltd
       
     2 
       
     3 # WARNING
       
     4 # This hook completely destroys your ~/.ssh/authorized_keys
       
     5 # file every time it is run
       
     6 # WARNING
       
     7 
       
     8 import sys
       
     9 import os
       
    10 import os.path
       
    11 import pwd
       
    12 import subprocess
       
    13 from mercurialserver import ruleset, paths
       
    14 
       
    15 def refreshAuth():
       
    16     pentry = pwd.getpwuid(os.geteuid())
       
    17     if pentry.pw_name != "hg":
       
    18         # FIXME: re-execute
       
    19         print >>sys.stderr, "Must be run as the 'hg' user"
       
    20 
       
    21     akeyfile = pentry.pw_dir + "/.ssh/authorized_keys"
       
    22     wrappercommand = paths.getEtcPath() + "/hg-ssh-wrapper"
       
    23     keydirs = [paths.getEtcPath() + "/keys", pentry.pw_dir + "/repos/hgadmin/keys"]
       
    24     prefix='no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command='
       
    25 
       
    26     if os.path.exists(akeyfile):
       
    27         f = open(akeyfile)
       
    28         try:
       
    29             for l in f:
       
    30                 if not l.startswith(prefix):
       
    31                     raise Exception("Safety check failed, delete %s to continue" % akeyfile)
       
    32         finally:
       
    33             f.close()
       
    34 
       
    35     akeys = open(akeyfile + "_new", "w")
       
    36     for keyroot in keydirs:
       
    37         kr = keyroot + "/"
       
    38         #print "Processing keyroot", keyroot
       
    39         for root, dirs, files in os.walk(keyroot):
       
    40             for fn in files:
       
    41                 ffn = os.path.join(root, fn)
       
    42                 if not ffn.startswith(kr):
       
    43                     raise Exception("Inconsistent behaviour in os.walk, bailing")
       
    44                 #print "Processing file", ffn
       
    45                 keyname = ffn[len(kr):]
       
    46                 if not ruleset.goodpath(keyname):
       
    47                     # ignore any path that contains dodgy characters
       
    48                     #print "Ignoring file", ffn
       
    49                     continue
       
    50                 p = subprocess.Popen(("ssh-keygen", "-i", "-f", ffn), 
       
    51                     stdout=subprocess.PIPE, stderr=subprocess.PIPE)
       
    52                 newkey = p.communicate()[0]
       
    53                 if p.wait() == 0:
       
    54                     klines = [l.strip() for l in newkey.split("\n")]
       
    55                 else:
       
    56                     # Conversion failed, read it directly.
       
    57                     kf = open(ffn)
       
    58                     try:
       
    59                         klines = [l.strip() for l in kf]
       
    60                     finally:
       
    61                         kf.close()
       
    62                 for l in klines:
       
    63                     if len(l):
       
    64                         akeys.write('%s"%s %s" %s\n' % (prefix, wrappercommand, keyname, l))
       
    65 
       
    66     akeys.close()
       
    67 
       
    68     os.rename(akeyfile + "_new", akeyfile)