File: test_helper.rb

package info (click to toggle)
ruby-mail-gpg 0.4.4-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 328 kB
  • sloc: ruby: 2,289; makefile: 6
file content (149 lines) | stat: -rw-r--r-- 3,782 bytes parent folder | download
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