# 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"
sys.exit(-1)
akeyfile = pentry.pw_dir + "/.ssh/authorized_keys"
wrappercommand = paths.getExePath() + "/hg-ssh"
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)
def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
refreshAuth()