src/mercurialserver/refreshauth.py
changeset 74 9d2ae2841bf2
child 75 5af89523a9d3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mercurialserver/refreshauth.py	Fri Mar 06 12:51:07 2009 +0000
@@ -0,0 +1,68 @@
+# Copyright 2008-2009 LShift Ltd
+
+# WARNING
+# This hook completely destroys your ~/.ssh/authorized_keys
+# file every time it is run
+# WARNING
+
+import sys
+import os
+import os.path
+import pwd
+import subprocess
+from mercurialserver import ruleset, paths
+
+def refreshAuth():
+    pentry = pwd.getpwuid(os.geteuid())
+    if pentry.pw_name != "hg":
+        # FIXME: re-execute
+        print >>sys.stderr, "Must be run as the 'hg' user"
+
+    akeyfile = pentry.pw_dir + "/.ssh/authorized_keys"
+    wrappercommand = paths.getEtcPath() + "/hg-ssh-wrapper"
+    keydirs = [paths.getEtcPath() + "/keys", pentry.pw_dir + "/repos/hgadmin/keys"]
+    prefix='no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command='
+
+    if os.path.exists(akeyfile):
+        f = open(akeyfile)
+        try:
+            for l in f:
+                if not l.startswith(prefix):
+                    raise Exception("Safety check failed, delete %s to continue" % akeyfile)
+        finally:
+            f.close()
+
+    akeys = open(akeyfile + "_new", "w")
+    for keyroot in keydirs:
+        kr = keyroot + "/"
+        #print "Processing keyroot", keyroot
+        for root, dirs, files in os.walk(keyroot):
+            for fn in files:
+                ffn = os.path.join(root, fn)
+                if not ffn.startswith(kr):
+                    raise Exception("Inconsistent behaviour in os.walk, bailing")
+                #print "Processing file", ffn
+                keyname = ffn[len(kr):]
+                if not ruleset.goodpath(keyname):
+                    # ignore any path that contains dodgy characters
+                    #print "Ignoring file", ffn
+                    continue
+                p = subprocess.Popen(("ssh-keygen", "-i", "-f", ffn), 
+                    stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                newkey = p.communicate()[0]
+                if p.wait() == 0:
+                    klines = [l.strip() for l in newkey.split("\n")]
+                else:
+                    # Conversion failed, read it directly.
+                    kf = open(ffn)
+                    try:
+                        klines = [l.strip() for l in kf]
+                    finally:
+                        kf.close()
+                for l in klines:
+                    if len(l):
+                        akeys.write('%s"%s %s" %s\n' % (prefix, wrappercommand, keyname, l))
+
+    akeys.close()
+
+    os.rename(akeyfile + "_new", akeyfile)