From: Michael Stapelberg <michael+sup@stapelberg.de>
To: sup-devel <sup-devel@rubyforge.org>
Subject: Re: [sup-devel] [PATCH] Implement inline GPG (updated)
Date: Wed, 10 Mar 2010 22:23:26 +0100 [thread overview]
Message-ID: <1268256145-sup-8174@midna.zekjur.net> (raw)
In-Reply-To: <1268152912-sup-4673@midna.zekjur.net>
[-- Attachment #1: Type: text/plain, Size: 286 bytes --]
Hi,
Excerpts from Michael Stapelberg's message of Di Mär 09 17:43:03 +0100 2010:
> Alright, tested it and reworked my patch. The latest version is attached.
Updated it once again after testing with a user on sup-talk. See attachment
and please merge it now :).
Best regards,
Michael
[-- Attachment #2: 0001-Implement-inline-GPG.patch --]
[-- Type: application/octet-stream, Size: 7925 bytes --]
From 9c3de457828827b0ba9a3d98ca1870325eb6d21d Mon Sep 17 00:00:00 2001
From: Michael Stapelberg <michael@stapelberg.de>
Date: Tue, 9 Mar 2010 17:40:48 +0100
Subject: [PATCH] Implement inline GPG
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The SIG_PATTERN had to be changed because GPG, when clearsigning (which
is what happens when you send inline GPG messages), kind of escapes
lines beginning with dashes (so that the -----BEGIN PGP MESSAGE-----
lines don’t get messed up). Therefore, signatures, starting with "-- "
will be escaped as "- -- ". The manpage of GPG states that the process
of clearsigning is not reversible. Thus, there is no method in GPG to
get the original message.
---
lib/sup/crypto.rb | 62 ++++++++++++++++++++++++++++++++-------------------
lib/sup/message.rb | 42 ++++++++++++++++++++++++++++++++--
2 files changed, 78 insertions(+), 26 deletions(-)
diff --git a/lib/sup/crypto.rb b/lib/sup/crypto.rb
index 5ece6d9..abbcb98 100644
--- a/lib/sup/crypto.rb
+++ b/lib/sup/crypto.rb
@@ -97,18 +97,24 @@ EOS
encrypt from, to, payload, true
end
- def verify payload, signature # both RubyMail::Message objects
+ def verify payload, signature, detached=true # both RubyMail::Message objects
return unknown_status(cant_find_binary) unless @cmd
- payload_fn = Tempfile.new "redwood.payload"
- payload_fn.write format_payload(payload)
- payload_fn.close
+ if detached
+ payload_fn = Tempfile.new "redwood.payload"
+ payload_fn.write format_payload(payload)
+ payload_fn.close
+ end
signature_fn = Tempfile.new "redwood.signature"
signature_fn.write signature.decode
signature_fn.close
- output = run_gpg "--verify #{signature_fn.path} #{payload_fn.path}"
+ if detached
+ output = run_gpg "--verify #{signature_fn.path} #{payload_fn.path}"
+ else
+ output = run_gpg "--verify #{signature_fn.path}"
+ end
output_lines = output.split(/\n/)
if output =~ /^gpg: (.* signature from .*$)/
@@ -123,7 +129,7 @@ EOS
end
## returns decrypted_message, status, desc, lines
- def decrypt payload # a RubyMail::Message object
+ def decrypt payload, armor=false # a RubyMail::Message object
return unknown_status(cant_find_binary) unless @cmd
payload_fn = Tempfile.new "redwood.payload"
@@ -153,24 +159,34 @@ EOS
Chunk::CryptoNotice.new :invalid, $1, message.split("\n")
end
- # This is gross. This decrypted payload could very well be a multipart
- # element itself, as opposed to a simple payload. For example, a
- # multipart/signed element, like those generated by Mutt when encrypting
- # and signing a message (instead of just clearsigning the body).
- # Supposedly, decrypted_payload being a multipart element ought to work
- # out nicely because Message::multipart_encrypted_to_chunks() runs the
- # decrypted message through message_to_chunks() again to get any
- # children. However, it does not work as intended because these inner
- # payloads need not carry a MIME-Version header, yet they are fed to
- # RMail as a top-level message, for which the MIME-Version header is
- # required. This causes for the part not to be detected as multipart,
- # hence being shown as an attachment. If we detect this is happening,
- # we force the decrypted payload to be interpreted as MIME.
- msg = RMail::Parser.read output
- if msg.header.content_type =~ %r{^multipart/} && !msg.multipart?
- output = "MIME-Version: 1.0\n" + output
- output.force_encoding Encoding::ASCII_8BIT if output.respond_to? :force_encoding
+ if armor
+ msg = RMail::Message.new
+ # Look for Charset, they are put before the base64 crypted part
+ charsets = payload.body.split("\n").grep(/^Charset:/)
+ if !charsets.empty? and charsets[0] =~ /^Charset: (.+)$/
+ output = Iconv.easy_decode($encoding, $1, output)
+ end
+ msg.body = output
+ else
+ # This is gross. This decrypted payload could very well be a multipart
+ # element itself, as opposed to a simple payload. For example, a
+ # multipart/signed element, like those generated by Mutt when encrypting
+ # and signing a message (instead of just clearsigning the body).
+ # Supposedly, decrypted_payload being a multipart element ought to work
+ # out nicely because Message::multipart_encrypted_to_chunks() runs the
+ # decrypted message through message_to_chunks() again to get any
+ # children. However, it does not work as intended because these inner
+ # payloads need not carry a MIME-Version header, yet they are fed to
+ # RMail as a top-level message, for which the MIME-Version header is
+ # required. This causes for the part not to be detected as multipart,
+ # hence being shown as an attachment. If we detect this is happening,
+ # we force the decrypted payload to be interpreted as MIME.
msg = RMail::Parser.read output
+ if msg.header.content_type =~ %r{^multipart/} && !msg.multipart?
+ output = "MIME-Version: 1.0\n" + output
+ output.force_encoding Encoding::ASCII_8BIT if output.respond_to? :force_encoding
+ msg = RMail::Parser.read output
+ end
end
notice = Chunk::CryptoNotice.new :valid, "This message has been decrypted for display"
[notice, sig, msg]
diff --git a/lib/sup/message.rb b/lib/sup/message.rb
index ebc73fc..7a19f27 100644
--- a/lib/sup/message.rb
+++ b/lib/sup/message.rb
@@ -26,7 +26,7 @@ class Message
QUOTE_PATTERN = /^\s{0,4}[>|\}]/
BLOCK_QUOTE_PATTERN = /^-----\s*Original Message\s*----+$/
- SIG_PATTERN = /(^-- ?$)|(^\s*----------+\s*$)|(^\s*_________+\s*$)|(^\s*--~--~-)|(^\s*--\+\+\*\*==)/
+ SIG_PATTERN = /(^(- )*-- ?$)|(^\s*----------+\s*$)|(^\s*_________+\s*$)|(^\s*--~--~-)|(^\s*--\+\+\*\*==)/
MAX_SIG_DISTANCE = 15 # lines from the end
DEFAULT_SUBJECT = ""
@@ -511,8 +511,44 @@ private
## if there's no charset, use the current encoding as the charset.
## this ensures that the body is normalized to avoid non-displayable
## characters
- body = Iconv.easy_decode($encoding, m.charset || $encoding, m.decode) if m.body
- text_to_chunks((body || "").normalize_whitespace.split("\n"), encrypted)
+ if m.body
+ body = Iconv.easy_decode($encoding, m.charset || $encoding, m.decode)
+ else
+ body = ""
+ end
+ lines = body.split("\n")
+
+ ## Check for inline-PGP
+ msg_start = "^-----BEGIN PGP SIGNED MESSAGE-----$"
+ msg_end = "^-----END PGP SIGNED MESSAGE-----$"
+ gpg = lines.select { |l| true if l =~ /#{msg_start}/ .. l =~ /#{msg_end}/ }
+ if !gpg.empty?
+ msg = RMail::Message.new
+ msg.body = gpg.join("\n")
+
+ sig_start = "^-----BEGIN PGP SIGNATURE-----$"
+ sig = lines.select { |l| true if l =~ /#{msg_start}/ .. l =~ /#{sig_start}/ }
+ payload = RMail::Message.new
+ payload.body = sig[1, sig.count-2].join("\n")
+ return [CryptoManager.verify(nil, msg, false), message_to_chunks(payload)].flatten.compact
+ end
+
+ msg_start = "^-----BEGIN PGP MESSAGE-----$"
+ msg_end = "^-----END PGP MESSAGE-----$"
+ gpg = lines.select { |l| true if l =~ /#{msg_start}/ .. l =~ /#{msg_end}/ }
+ if !gpg.empty?
+ msg = RMail::Message.new
+ msg.body = gpg.join("\n")
+ notice, sig, decryptedm = CryptoManager.decrypt msg, true
+ if decryptedm # managed to decrypt
+ children = message_to_chunks(decryptedm, true)
+ return [notice, sig].compact + children
+ else
+ return [notice]
+ end
+ end
+
+ text_to_chunks(body.normalize_whitespace.split("\n"), encrypted)
end
end
end
--
1.6.5
[-- Attachment #3: Type: text/plain, Size: 143 bytes --]
_______________________________________________
Sup-devel mailing list
Sup-devel@rubyforge.org
http://rubyforge.org/mailman/listinfo/sup-devel
next prev parent reply other threads:[~2010-03-10 21:24 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-18 11:40 [sup-devel] [PATCH] Implement inline GPG Michael Stapelberg
2010-02-26 21:24 ` Rich Lane
2010-02-27 13:11 ` Michael Stapelberg
2010-02-27 18:05 ` Rich Lane
2010-03-01 13:45 ` Michael Stapelberg
2010-03-01 14:36 ` Christian Dietrich
2010-03-01 16:49 ` Michael Stapelberg
2010-03-01 17:46 ` Christian Dietrich
2010-03-09 16:43 ` [sup-devel] [PATCH] Implement inline GPG (updated) Michael Stapelberg
2010-03-10 21:23 ` Michael Stapelberg [this message]
2010-03-12 4:43 ` Rich Lane
2010-03-12 11:02 ` Michael Stapelberg
2010-03-15 5:19 ` Rich Lane
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1268256145-sup-8174@midna.zekjur.net \
--to=michael+sup@stapelberg.de \
--cc=sup-devel@rubyforge.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox