|
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) |