commit 16901db9836d2c07d8143c7acf5975cc411904bb
parent c62aec33a8c98ceb90d052e211574fa54d701bd7
Author: Matthieu Rakotojaona <matthieu.rakotojaona@gmail.com>
Date: Sun, 25 Jan 2015 11:39:54 +0100
Add key binding for fetching key and re-verifying message
Diffstat:
4 files changed, 58 insertions(+), 4 deletions(-)
diff --git a/lib/sup/crypto.rb b/lib/sup/crypto.rb
@@ -16,6 +16,9 @@ class CryptoManager
[:encrypt, "Encrypt only"]
)
+ KEY_PATTERN = /(-----BEGIN PGP PUBLIC KEY BLOCK.*-----END PGP PUBLIC KEY BLOCK)/m
+ KEYSERVER_URL = "http://pool.sks-keyservers.net:11371/pks/lookup"
+
HookManager.register "gpg-options", <<EOS
Runs before gpg is called, allowing you to modify the options (most
likely you would want to add something to certain commands, like
@@ -212,9 +215,10 @@ EOS
unknown = false
all_output_lines = []
all_trusted = true
+ unknown_fingerprint = nil
verify_result.signatures.each do |signature|
- output_lines, trusted = sig_output_lines signature
+ output_lines, trusted, unknown_fingerprint = sig_output_lines signature
all_output_lines << output_lines
all_output_lines.flatten!
all_trusted &&= trusted
@@ -242,6 +246,8 @@ EOS
end
elsif !unknown
Chunk::CryptoNotice.new(:invalid, summary_line, all_output_lines)
+ elsif unknown_fingerprint
+ Chunk::CryptoNotice.new(:unknown_key, "Unable to determine validity of cryptographic signature", all_output_lines, unknown_fingerprint)
else
unknown_status all_output_lines
end
@@ -351,6 +357,24 @@ EOS
[notice, sig, msg]
end
+ def retrieve fingerprint
+ require 'net/http'
+ uri = URI(KEYSERVER_URL)
+ fingerprint = "0x" + fingerprint unless fingerprint[0..1] == "0x"
+ params = {op: "get", search: fingerprint}
+ uri.query = URI.encode_www_form(params)
+
+ res = Net::HTTP.get_response(uri)
+ return "Couldn't contact keyserver pool" unless res.is_a?(Net::HTTPSuccess)
+
+ match = KEY_PATTERN.match(res.body)
+ return "No key found" unless match && match.length > 0
+
+ GPGME::Key.import(match[0])
+
+ return nil
+ end
+
private
def unknown_status lines=[]
@@ -394,6 +418,7 @@ private
rescue EOFError
from_key = nil
first_sig = "No public key available for #{signature.fingerprint}"
+ unknown_fpr = signature.fingerprint
end
time_line = "Signature made " + signature.timestamp.strftime("%a %d %b %Y %H:%M:%S %Z") +
@@ -422,7 +447,7 @@ private
output_lines << HookManager.run("sig-output",
{:signature => signature, :from_key => from_key})
end
- return output_lines, trusted
+ return output_lines, trusted, unknown_fpr
end
def key_type key, fpr
diff --git a/lib/sup/message.rb b/lib/sup/message.rb
@@ -279,6 +279,12 @@ class Message
end
end
+ def reload_from_source!
+ @chunks = nil
+ load_from_source!
+ end
+
+
def error_message
<<EOS
#@snippet...
diff --git a/lib/sup/message_chunks.rb b/lib/sup/message_chunks.rb
@@ -307,12 +307,13 @@ EOS
end
class CryptoNotice
- attr_reader :lines, :status, :patina_text
+ attr_reader :lines, :status, :patina_text, :unknown_fingerprint
- def initialize status, description, lines=[]
+ def initialize status, description, lines=[], unknown_fingerprint=nil
@status = status
@patina_text = description
@lines = lines
+ @unknown_fingerprint = unknown_fingerprint
end
def patina_color
diff --git a/lib/sup/modes/thread_view_mode.rb b/lib/sup/modes/thread_view_mode.rb
@@ -89,6 +89,7 @@ EOS
k.add :toggle_wrap, "Toggle wrapping of text", 'w'
k.add :goto_uri, "Goto uri under cursor", 'g'
+ k.add :fetch_and_verify, "Fetch the PGP key on poolserver and re-verify message", "v"
k.add_multi "(a)rchive/(d)elete/mark as (s)pam/mark as u(N)read:", '.' do |kk|
kk.add :archive_and_kill, "Archive this thread and kill buffer", 'a'
@@ -793,6 +794,27 @@ EOS
BufferManager.flash "No URI found." unless found
end
+ def fetch_and_verify
+ message = @message_lines[curpos]
+ crypto_chunk = message.chunks.select {|chunk| chunk.is_a?(Chunk::CryptoNotice)}.first
+ return unless crypto_chunk
+ return unless crypto_chunk.unknown_fingerprint
+
+ BufferManager.flash "Retrieving key #{crypto_chunk.unknown_fingerprint} ..."
+
+ error = CryptoManager.retrieve crypto_chunk.unknown_fingerprint
+
+ if error
+ BufferManager.flash "Couldn't retrieve key: #{error.to_s}"
+ else
+ BufferManager.flash "Key #{crypto_chunk.unknown_fingerprint} successfully retrieved !"
+ end
+
+ # Re-trigger gpg verification
+ message.reload_from_source!
+ update
+ end
+
private
def initial_state_for m