summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Crute <mcrute@gmail.com>2010-05-05 23:25:17 -0400
committerMike Crute <mcrute@gmail.com>2010-05-05 23:25:17 -0400
commit5651f6658e5055ba43aee1d30884d949938ca1a4 (patch)
treec4100052f59a0c8d12564cf655c6bd79b8a55903
parent5b8234f27f00ad135d24063dd430de35db43e42f (diff)
downloadhg_sshsign-5651f6658e5055ba43aee1d30884d949938ca1a4.tar.bz2
hg_sshsign-5651f6658e5055ba43aee1d30884d949938ca1a4.tar.xz
hg_sshsign-5651f6658e5055ba43aee1d30884d949938ca1a4.zip
Getting signing working!
-rw-r--r--__init__.py (renamed from ssh.py)40
-rw-r--r--keys.py4
-rw-r--r--sshagent.py10
3 files changed, 39 insertions, 15 deletions
diff --git a/ssh.py b/__init__.py
index 0c60cb0..a783fc3 100644
--- a/ssh.py
+++ b/__init__.py
@@ -26,36 +26,49 @@ from mercurial import node as hgnode
26from mercurial.i18n import _ 26from mercurial.i18n import _
27 27
28 28
29def absolute_path(path):
30 path = os.path.expandvars(path)
31 return os.path.expanduser(path)
32
33
34class SSHAuthority(object): 29class SSHAuthority(object):
35 30
36 @classmethod 31 @classmethod
37 def from_ui(cls, ui): 32 def from_ui(cls, ui):
38 public_key = absolute_path(ui.config("sshsign", "public_key")) 33 public_key = absolute_path(ui.config("sshsign", "public_key"))
39 private_key = absolute_path(ui.config("sshsign", "private_key"))
40 manifest_file = absolute_path(ui.config("sshsign", "manifest_file"))
41
42 manifest = KeyManifest.from_file(manifest_file)
43 public_key = keys.PublicKey.from_file(public_key) 34 public_key = keys.PublicKey.from_file(public_key)
44 35
36 manifest_file = ui.config("sshsign", "manifest_file")
37 if manifest_file:
38 manifest = KeyManifest.from_file(absolute_path(manifest_file))
39 else:
40 manifest = None
41 ui.write(_("No key manifest set. You will not be able to verify"
42 " signatures.\n"))
43
44 private_key = ui.config("sshsign", "private_key", None)
45 agent_socket = os.environ.get(SSHAgent.AGENT_SOCK_NAME)
46 if private_key:
47 private_key = keys.load_private_key(absolute_path(private_key))
48 elif agent_socket:
49 private_key = SSHAgent(agent_socket, key=public_key.blob)
50 else:
51 raise util.Abort(_("No private key set and no agent running."))
52
53 return cls(public_key, manifest, private_key)
54
45 def __init__(self, public_key, key_manifest=None, private_key=None): 55 def __init__(self, public_key, key_manifest=None, private_key=None):
46 self.public_key = public_key 56 self.public_key = public_key
47 self.key_manifest = key_manifest 57 self.key_manifest = key_manifest
48 self.private_key = private_key 58 self.private_key = private_key
49 59
50 def verify(self, data, signature, whom): 60 def verify(self, data, signature, whom):
51 key = self.key_manifest[whom] # XXX: More elegant error handling. 61 try:
62 key = self.key_manifest[whom] # XXX: More elegant error handling.
63 except KeyError:
64 raise util.Abort(_("No key found for %s" % whom))
65
52 return key.verify(data, signature) 66 return key.verify(data, signature)
53 67
54 def sign(self, data): 68 def sign(self, data):
55 return self.private_key.sign(data) 69 return self.private_key.sign(data)
56 70
57 71
58
59def node2txt(repo, node, ver): 72def node2txt(repo, node, ver):
60 """map a manifest into some text""" 73 """map a manifest into some text"""
61 if ver != "0": 74 if ver != "0":
@@ -64,6 +77,11 @@ def node2txt(repo, node, ver):
64 return "%s\n" % hgnode.hex(node) 77 return "%s\n" % hgnode.hex(node)
65 78
66 79
80def absolute_path(path):
81 path = os.path.expandvars(path)
82 return os.path.expanduser(path)
83
84
67def sign(ui, repo, *revs, **opts): 85def sign(ui, repo, *revs, **opts):
68 """add a signature for the current or given revision 86 """add a signature for the current or given revision
69 87
diff --git a/keys.py b/keys.py
index 33cb98e..d15af08 100644
--- a/keys.py
+++ b/keys.py
@@ -35,7 +35,7 @@ class PublicKey(object):
35 def sign(self, data): 35 def sign(self, data):
36 return self.instance.sign(data) 36 return self.instance.sign(data)
37 37
38 @property 38 @classmethod
39 def from_string(cls, key): 39 def from_string(cls, key):
40 """ 40 """
41 Loads an RFC 4716 formatted public key. 41 Loads an RFC 4716 formatted public key.
@@ -58,7 +58,7 @@ class PublicKey(object):
58 58
59 return pubkey 59 return pubkey
60 60
61 @property 61 @classmethod
62 def from_file(cls, filename): 62 def from_file(cls, filename):
63 fp = open(filename) 63 fp = open(filename)
64 try: 64 try:
diff --git a/sshagent.py b/sshagent.py
index 6803b89..cd5fa20 100644
--- a/sshagent.py
+++ b/sshagent.py
@@ -25,7 +25,7 @@ class SSHAgent(object):
25 SSH2_AGENT_SIGN_RESPONSE = 14 25 SSH2_AGENT_SIGN_RESPONSE = 14
26 SSH2_AGENTC_SIGN_REQUEST = 13 26 SSH2_AGENTC_SIGN_REQUEST = 13
27 27
28 def __init__(self, socket_path=None): 28 def __init__(self, socket_path=None, key=None):
29 default_path = os.environ.get(SSHAgent.AGENT_SOCK_NAME) 29 default_path = os.environ.get(SSHAgent.AGENT_SOCK_NAME)
30 socket_path = default_path if not socket_path else socket_path 30 socket_path = default_path if not socket_path else socket_path
31 31
@@ -33,6 +33,7 @@ class SSHAgent(object):
33 raise ValueError("Could not find an ssh agent.") 33 raise ValueError("Could not find an ssh agent.")
34 34
35 self.socket_path = socket_path 35 self.socket_path = socket_path
36 self.public_key = key
36 self.socket = None 37 self.socket = None
37 38
38 def connect(self): 39 def connect(self):
@@ -51,10 +52,15 @@ class SSHAgent(object):
51 52
52 return packet 53 return packet
53 54
54 def sign(self, data, key): 55 def sign(self, data, key=None):
55 if not self.socket: 56 if not self.socket:
56 self.connect() 57 self.connect()
57 58
59 if not key and self.public_key:
60 key = self.public_key
61 else:
62 raise Exception("No key specified!")
63
58 packet = self._build_packet(data, key) 64 packet = self._build_packet(data, key)
59 65
60 remaining = 0 66 remaining = 0