From: Michael Stapelberg <michael+sup@stapelberg.de>
To: sup-devel <sup-devel@rubyforge.org>
Subject: [sup-devel] [PATCH] Implement inline GPG
Date: Thu, 18 Feb 2010 12:40:45 +0100 [thread overview]
Message-ID: <1266493070-sup-7733@midna.zekjur.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 319 bytes --]
Hi,
as my previous patch was not merged, I have updated the patch to apply against
the current code. Furthermore, it now correctly handles character sets for the
GPG encrypted part.
The patch has been tested by me and another user and seems to work fine.
Please merge it for the next release.
Best regards,
Michael
[-- Attachment #2: 0001-Implement-inline-GPG.patch --]
[-- Type: application/octet-stream, Size: 7629 bytes --]
From 87e8a9b90c9566710a03b6673b5e77459350683c Mon Sep 17 00:00:00 2001
From: Michael Stapelberg <michael@stapelberg.de>
Date: Wed, 17 Feb 2010 16:36:18 +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 | 31 +++++++++++++++++++++++++-
2 files changed, 69 insertions(+), 24 deletions(-)
diff --git a/lib/sup/crypto.rb b/lib/sup/crypto.rb
index 91652c7..4f75936 100644
--- a/lib/sup/crypto.rb
+++ b/lib/sup/crypto.rb
@@ -86,18 +86,24 @@ class CryptoManager
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 .*$)/
@@ -112,7 +118,7 @@ class CryptoManager
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"
@@ -142,24 +148,34 @@ class CryptoManager
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 a85cc0d..69ada67 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 = ""
@@ -512,6 +512,35 @@ private
## 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
+ lines = body.split("\n")
+
+ ## Check for inline-PGP
+ if body =~ /-----BEGIN PGP SIGNED MESSAGE-----/
+ sign_start = lines.index("-----BEGIN PGP SIGNED MESSAGE-----")
+ sign_end = lines.index("-----END PGP SIGNED MESSAGE-----") || lines.count
+ msg = RMail::Message.new
+ msg.body = lines[sign_start, sign_end+1].join("\n")
+
+ sign_end = lines.index("-----BEGIN PGP SIGNATURE-----") || sign_end
+ payload = RMail::Message.new
+ payload.body = lines[sign_start+1, sign_end-1].join("\n")
+ return [CryptoManager.verify(nil, msg, false), message_to_chunks(payload)].flatten.compact
+ end
+
+ if body =~ /-----BEGIN PGP MESSAGE-----/
+ signstart = lines.index("-----BEGIN PGP MESSAGE-----")
+ signend = lines.index("-----END PGP MESSAGE-----") || lines.count
+ msg = RMail::Message.new
+ msg.body = lines[signstart, signend+1].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
--
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 reply other threads:[~2010-02-18 11:40 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-18 11:40 Michael Stapelberg [this message]
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
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=1266493070-sup-7733@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