diff options
author | Mike Crute <mcrute@gmail.com> | 2010-05-05 23:25:17 -0400 |
---|---|---|
committer | Mike Crute <mcrute@gmail.com> | 2010-05-05 23:25:17 -0400 |
commit | 5651f6658e5055ba43aee1d30884d949938ca1a4 (patch) | |
tree | c4100052f59a0c8d12564cf655c6bd79b8a55903 | |
parent | 5b8234f27f00ad135d24063dd430de35db43e42f (diff) | |
download | hg_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.py | 4 | ||||
-rw-r--r-- | sshagent.py | 10 |
3 files changed, 39 insertions, 15 deletions
@@ -26,36 +26,49 @@ from mercurial import node as hgnode | |||
26 | from mercurial.i18n import _ | 26 | from mercurial.i18n import _ |
27 | 27 | ||
28 | 28 | ||
29 | def absolute_path(path): | ||
30 | path = os.path.expandvars(path) | ||
31 | return os.path.expanduser(path) | ||
32 | |||
33 | |||
34 | class SSHAuthority(object): | 29 | class 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 | |||
59 | def node2txt(repo, node, ver): | 72 | def 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 | ||
80 | def absolute_path(path): | ||
81 | path = os.path.expandvars(path) | ||
82 | return os.path.expanduser(path) | ||
83 | |||
84 | |||
67 | def sign(ui, repo, *revs, **opts): | 85 | def 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 | ||
@@ -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 |