lib/sup/crypto.rb in sup-0.8.1 vs lib/sup/crypto.rb in sup-0.9
- old
+ new
@@ -11,21 +11,19 @@
[:encrypt, "Encrypt only"]
)
def initialize
@mutex = Mutex.new
- self.class.i_am_the_instance self
bin = `which gpg`.chomp
-
@cmd =
case bin
when /\S/
- Redwood::log "crypto: detected gpg binary in #{bin}"
+ debug "crypto: detected gpg binary in #{bin}"
"#{bin} --quiet --batch --no-verbose --logger-fd 1 --use-agent"
else
- Redwood::log "crypto: no gpg binary detected"
+ debug "crypto: no gpg binary detected"
nil
end
end
def have_crypto?; !@cmd.nil? end
@@ -114,40 +112,55 @@
payload_fn.close
output = run_gpg "--decrypt #{payload_fn.path}"
if $?.success?
- decrypted_payload, sig_lines =
- if output =~ /\A(.*?)((^gpg: .*$)+)\Z/m
- [$1, $2]
+ decrypted_payload, sig_lines = if output =~ /\A(.*?)((^gpg: .*$)+)\Z/m
+ [$1, $2]
+ else
+ [output, nil]
+ end
+
+ sig = if sig_lines # encrypted & signed
+ if sig_lines =~ /^gpg: (Good signature from .*$)/
+ Chunk::CryptoNotice.new :valid, $1, sig_lines.split("\n")
else
- [output, nil]
+ Chunk::CryptoNotice.new :invalid, $1, sig_lines.split("\n")
end
-
- sig =
- if sig_lines # encrypted & signed
- if sig_lines =~ /^gpg: (Good signature from .*$)/
- Chunk::CryptoNotice.new :valid, $1, sig_lines.split("\n")
- else
- Chunk::CryptoNotice.new :invalid, $1, sig_lines.split("\n")
- end
- end
+ 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(decrypted_payload)
+ if msg.header.content_type =~ %r{^multipart/} and not msg.multipart?
+ decrypted_payload = "MIME-Version: 1.0\n" + decrypted_payload
+ msg = RMail::Parser.read(decrypted_payload)
+ end
notice = Chunk::CryptoNotice.new :valid, "This message has been decrypted for display"
- [RMail::Parser.read(decrypted_payload), sig, notice]
+ [notice, sig, msg]
else
- notice = Chunk::CryptoNotice.new :invalid, "This message could not be decrypted", output.split("\n")
- [nil, nil, notice]
+ Chunk::CryptoNotice.new :invalid, "This message could not be decrypted", output.split("\n")
end
end
private
def unknown_status lines=[]
Chunk::CryptoNotice.new :unknown, "Unable to determine validity of cryptographic signature", lines
end
-
+
def cant_find_binary
["Can't find gpg binary in path."]
end
## here's where we munge rmail output into the format that signed/encrypted
@@ -156,12 +169,10 @@
payload.to_s.gsub(/(^|[^\r])\n/, "\\1\r\n").gsub(/^MIME-Version: .*\r\n/, "")
end
def run_gpg args
cmd = "#{@cmd} #{args} 2> /dev/null"
- #Redwood::log "crypto: running: #{cmd}"
output = `#{cmd}`
- #Redwood::log "crypto: output: #{output.inspect}" unless $?.success?
output
end
end
end