1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
require 'open3'
require 'test/unit'
require 'shoulda/context'
require 'mail-gpg'
require 'action_mailer'
require 'securerandom'
require 'byebug'
Mail.defaults do
delivery_method :test
end
ActionMailer::Base.delivery_method = :test
class MailGpgTestCase < Test::Unit::TestCase
def setup
@gpg_utils = GPGTestUtils.new(ENV['GPG_BIN'])
@gpg_utils.setup
end
def set_passphrase(*args)
@gpg_utils.set_passphrase(*args)
end
end
class GPGTestUtils
attr_reader :gpg_engine
def initialize(gpg_bin = nil)
@home = File.join File.dirname(__FILE__), 'gpghome'
@gpg_bin = gpg_bin
ENV['GPG_AGENT_INFO'] = '' # disable gpg agent
ENV['GNUPGHOME'] = @home
if @gpg_bin
GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, @gpg_bin, @home)
else
GPGME::Engine.home_dir = @home
end
@gpg_engine = GPGME::Engine.info.find {|e| e.protocol == GPGME::PROTOCOL_OpenPGP }
@gpg_bin ||= @gpg_engine.file_name
if Gem::Version.new(@gpg_engine.version) >= Gem::Version.new("2.1.0")
@preset_passphrases = true
else
@preset_passphrases = false
end
end
def preset_passphrases?
!!@preset_passphrases
end
def setup
gen_keys unless File.directory? @home
if @preset_passphrases
libexecdir = `gpgconf --list-dir`.lines.grep(/^libexecdir:/).first.split(':').last.strip
@gpp_bin = File.join(libexecdir, 'gpg-preset-passphrase')
@keygrip_jane = get_keygrip('jane@foo.bar')
@keygrip_joe = get_keygrip('joe@foo.bar')
end
end
def gen_keys
puts "setting up keydir #{@home}"
FileUtils.mkdir_p @home
(File.open(File.join(@home, "gpg-agent.conf"), "wb") << "allow-preset-passphrase\nbatch\n").close
GPGME::Ctx.new do |gpg|
gpg.generate_key <<-END
<GnupgKeyParms format="internal">
Key-Type: DSA
Key-Length: 1024
Subkey-Type: ELG-E
Subkey-Length: 1024
Name-Real: Joe Tester
Name-Comment: with stupid passphrase
Name-Email: joe@foo.bar
Expire-Date: 0
Passphrase: abc
</GnupgKeyParms>
END
gpg.generate_key <<-END
<GnupgKeyParms format="internal">
Key-Type: DSA
Key-Length: 1024
Subkey-Type: ELG-E
Subkey-Length: 1024
Name-Real: Jane Doe
Name-Comment: with stupid passphrase
Name-Email: jane@foo.bar
Expire-Date: 0
Passphrase: abc
</GnupgKeyParms>
END
end
end
# Put passphrase into gpg-agent (required with GnuPG v2).
def set_passphrase(passphrase)
if preset_passphrases?
ensure_gpg_agent
call_gpp(@keygrip_jane, passphrase)
call_gpp(@keygrip_joe, passphrase)
end
end
private
def get_keygrip(uid)
output = `#{@gpg_bin} --list-secret-keys --with-keygrip --with-colons #{uid} 2>&1`
if line = output.lines.grep(/^grp/).first
line.split(':')[9]
else
puts "malformed key list output:\n#{output}"
raise
end
end
def ensure_gpg_agent
# Make sure the gpg-agent is running (doesn't start automatically when
# gpg-preset-passphrase is calling).
output = `gpgconf --launch gpg-agent 2>&1`
if ! output.empty?
$stderr.puts "Launching gpg-agent returned: #{output}"
end
end
def call_gpp(keygrip, passphrase)
output, status = Open3.capture2e(@gpp_bin, '--homedir', ENV['GNUPGHOME'], '--preset', keygrip, {stdin_data: passphrase})
if ! output.empty?
$stderr.puts "#{@gpp_bin} returned status #{status.exitstatus}: #{output}"
end
end
end
gpg_utils = GPGTestUtils.new(ENV['GPG_BIN'])
v = Gem::Version.new(gpg_utils.gpg_engine.version)
if v >= Gem::Version.new("2.1.0")
puts "Running with GPG >= 2.1"
elsif v >= Gem::Version.new("2.0.0")
puts "Running with GPG 2.0, this isn't going well since we cannot set passphrases non-interactively"
else
puts "Running with GPG < 2.0"
end
gpg_utils.setup
|