rubygems-openpgp 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011, Grant T. Olson
1
+ Copyright (c) 2011, 2013 Grant T. Olson
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without
@@ -4,6 +4,7 @@ require 'rubygems/user_interaction'
4
4
  require 'shellwords'
5
5
  require 'open3'
6
6
  require 'tempfile'
7
+ require 'gpg_status_parser'
7
8
 
8
9
  # Exception for this class
9
10
  class Gem::OpenPGPException < RuntimeError; end
@@ -29,9 +30,51 @@ module Gem::OpenPGP
29
30
  homedir_flag = ""
30
31
  homedir_flag = "--homedir #{shellescape(homedir)}" if homedir
31
32
 
32
- cmd = "gpg #{key_flag} #{homedir_flag} --detach-sign --armor"
33
- sig, err = run_gpg_command cmd, data
34
- sig
33
+ gpg_args = "#{key_flag} #{homedir_flag} --detach-sign --armor"
34
+ gpg_results = run_gpg(gpg_args, data)
35
+ did_gpg_error? gpg_results
36
+
37
+ gpg_results[:stdout]
38
+ end
39
+
40
+ # Extract the info we care about, throw away the rest
41
+ def self.verify_extract_status_info message, status_info
42
+ case message.status
43
+ when :GOODSIG, :BADSIG, :ERRSIG
44
+ status_info[:good_or_bad] = message.status
45
+ status_info[:uid] = (message.args[:username] || "").strip
46
+
47
+ when :SIG_ID
48
+ when :VALIDSIG, :EXPSIG, :BADSIG
49
+ status_info[:sig_status] = message.status
50
+ status_info[:primary_key] = "0x#{message.args[:primary_key_fpr][-9..-1]}"
51
+ when :TRUST_UNDEFINED, :TRUST_NEVER, :TRUST_MARGINAL, :TRUST_FULLY, :TRUST_ULTIMATE
52
+ status_info[:trust_status] = message.status
53
+ when :NO_PUBKEY
54
+ status_info[:failure] = "You don't have the public key. Use --get-key to automagically retrieve from keyservers"
55
+ when :IMPORTED, :IMPORT_OK, :IMPORT_RES
56
+ #silently_ignore
57
+ when :KEYEXPIRED, :SIGEXPIRED
58
+ # recalculating trust db, ignore.
59
+ else
60
+ puts "unexpected message: #{message.status} #{message.args.inspect}"
61
+ end
62
+ end
63
+
64
+ # Print info about the sig, check that we like it, and possibly abort
65
+ def self.verify_check_sig status_info
66
+ sig_msg = "Signature for #{status_info[:file_name]} from user #{status_info[:uid]} key #{status_info[:primary_key]} is #{status_info[:good_or_bad]}, #{status_info[:sig_status]} and #{status_info[:trust_status]}"
67
+ if status_info[:trust_status] == :TRUST_NEVER
68
+ say add_color(sig_msg, :red)
69
+ raise Gem::OpenPGPException, "Never Trusted. Won't install."
70
+ elsif status_info[:trust_status] == :TRUST_UNDEFINED
71
+ say add_color(sig_msg, :yellow)
72
+ if options[:trust] && !options[:no_trust]
73
+ raise Gem::OpenPGPException, "Trust Undefined and you've specified --trust. Won't install."
74
+ end
75
+ else
76
+ say add_color(sig_msg , :green)
77
+ end
35
78
  end
36
79
 
37
80
  # Given a string containing data, and a string containing
@@ -39,7 +82,7 @@ module Gem::OpenPGP
39
82
  # then raise an exception.
40
83
  #
41
84
  # Optionally tell gpg to retrive the key if it's not provided
42
- def self.verify data, sig, get_key=false, homedir=nil
85
+ def self.verify file_name, data, sig, get_key=false, homedir=nil
43
86
  is_gpg_available
44
87
  is_homedir_valid homedir if homedir
45
88
 
@@ -51,10 +94,22 @@ module Gem::OpenPGP
51
94
 
52
95
  homedir_flags = ""
53
96
  homedir_flags = "--homedir #{homedir}" if homedir
54
-
55
- cmd = "gpg #{get_key_params} #{homedir_flags} --verify #{sig_file.path} #{data_file.path}"
56
- res, err = run_gpg_command cmd
57
- [err, res]
97
+
98
+ gpg_args = "#{get_key_params} #{homedir_flags} --verify #{sig_file.path} #{data_file.path}"
99
+
100
+ status_info = {:file_name => file_name}
101
+ gpg_results = run_gpg(gpg_args) { |message| verify_extract_status_info(message, status_info) }
102
+
103
+ if status_info[:failure]
104
+ say add_color(status_info[:failure], :red)
105
+ raise Gem::OpenPGPException, "Fail!"
106
+ else
107
+ verify_check_sig status_info
108
+ end
109
+
110
+ did_gpg_error? gpg_results
111
+
112
+ [gpg_results[:stderr], gpg_results[:status]]
58
113
  end
59
114
 
60
115
  # Signs an existing gemfile by iterating the tar'ed up contents,
@@ -128,7 +183,6 @@ module Gem::OpenPGP
128
183
 
129
184
  tar_files.keys.each do |file_name|
130
185
  next if file_name[-4..-1] == ".asc"
131
- say "Verifying #{file_name}..."
132
186
 
133
187
  sig_file_name = file_name + ".asc"
134
188
  if !tar_files.has_key? sig_file_name
@@ -137,10 +191,8 @@ module Gem::OpenPGP
137
191
  end
138
192
 
139
193
  begin
140
- err, res = Gem::OpenPGP.verify(tar_files[file_name], tar_files[sig_file_name], get_key, homedir)
194
+ err, res = Gem::OpenPGP.verify(file_name, tar_files[file_name], tar_files[sig_file_name], get_key, homedir)
141
195
 
142
- say add_color(err, :green)
143
- say add_color(res, :green)
144
196
  rescue Gem::OpenPGPException => ex
145
197
  color_code = "31"
146
198
  say add_color(ex.message, :red)
@@ -154,6 +206,14 @@ module Gem::OpenPGP
154
206
 
155
207
  private
156
208
 
209
+ def self.did_gpg_error? gpg_results
210
+ if gpg_results[:status] != 0
211
+ say add_color("gpg returned unexpected status code", :red)
212
+ say add_color(gpg_results[:stderr], :red)
213
+ raise Gem::OpenPGPException, "gpg returned unexpected error code #{gpg_results[:status]}"
214
+ end
215
+ end
216
+
157
217
  # Tests to see if gpg is installed and available.
158
218
  def self.is_gpg_available
159
219
  err_msg = "Unable to find a working gnupg installation. Make sure gnupg is installed and you can call 'gpg --version' from a command prompt."
@@ -177,18 +237,24 @@ private
177
237
  end
178
238
  end
179
239
 
180
- def self.run_gpg_command cmd, data=nil
240
+ def self.run_gpg args, data=nil, &block
181
241
  exit_status = nil
182
- stdout, stderr = Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
242
+ status_file = Tempfile.new("status")
243
+
244
+ full_gpg_command = "gpg --status-file #{status_file.path} #{args}"
245
+ gpg_results = Open3.popen3(full_gpg_command) do |stdin, stdout, stderr, wait_thr|
183
246
  stdin.write data if data
184
247
  stdin.close
185
248
  exit_status = wait_thr.value
249
+ GPGStatusParser.parse(status_file, &block)
186
250
  out = stdout.read()
187
251
  err = stderr.read()
188
- raise Gem::OpenPGPException, "#{err}" if exit_status != 0
189
- [out,err]
252
+ {:status => exit_status, :stdout => out, :err => err}
190
253
  end
191
- [stdout, stderr]
254
+ gpg_results
255
+ ensure
256
+ status_file.close
257
+ status_file.unlink
192
258
  end
193
259
 
194
260
  def self.create_tempfile data
@@ -203,6 +269,7 @@ private
203
269
  color_code = case color
204
270
  when :green then "32"
205
271
  when :red then "31"
272
+ when :yellow then "33"
206
273
  else raise RuntimeError, "Invalid color #{color.inspect}"
207
274
  end
208
275
 
@@ -38,6 +38,21 @@ i.add_option("--verify",
38
38
  Gem::OpenPGP.options[:verify] = true
39
39
  end
40
40
 
41
+ i.add_option("--no-verify",
42
+ "Don't verify a gem, even if --verify has previously been specified") do |value, options|
43
+ Gem::OpenPGP.options[:no_verify] = true
44
+ end
45
+
46
+ i = Gem::CommandManager.instance[:install]
47
+ i.add_option("--trust",
48
+ 'Enforce gnupg trust settings. Only install if trusted.') do |value, options|
49
+ Gem::OpenPGP.options[:trust] = true
50
+ end
51
+
52
+ i.add_option("--no-trust",
53
+ "Ignoure gnupg trust settings, even if --trust has previously been specified") do |value, options|
54
+ Gem::OpenPGP.options[:no_trust] = true
55
+ end
41
56
 
42
57
  i.add_option('--get-key', "If the key is not available, download it from a keyserver") do |key, options|
43
58
  Gem::OpenPGP.options[:get_key] = true
@@ -45,7 +60,8 @@ end
45
60
 
46
61
  Gem.pre_install do |installer|
47
62
  begin
48
- if Gem::OpenPGP.options[:verify]
63
+ # --no-verify overrides --verify
64
+ if Gem::OpenPGP.options[:verify] && !Gem::OpenPGP.options[:no_verify]
49
65
  Gem::OpenPGP.verify_gem(installer.gem,
50
66
  Gem::OpenPGP.options[:get_key])
51
67
  end
data.tar.gz.asc CHANGED
@@ -1,11 +1,11 @@
1
1
  -----BEGIN PGP SIGNATURE-----
2
2
  Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
3
3
 
4
- iQEcBAABCgAGBQJRF6UkAAoJEP5F5V2hilTWp4EH/Ah94Ny5XMyjejkTuTAZPZw8
5
- 6jG5gQ0dl5l8c6VyXgLNwSDmCt0Rj5J1ZVvkz8LXj7xJpDyXu77Gk2FCDS30R7vH
6
- 4C3LbUdIGv5FhMGQ2CiVgPNbi8CRsNmnFg15otY782Uvu8sMbspkrVi31wFvWCz7
7
- Ik9tHle42aNwg5sYhYWi4gIHiLfQ3l+g6C2YJ38R/hKdU9J3Vu9RWxk3aAsSsuTp
8
- aEDxGvTkX+N9vUEdDIvpkZ7iuhATxiP4TpZo3vFORe0iwo44XQaZJQPb4jMKmnJt
9
- b9Q7a1o/WpmcPrnGDaHvsjPj4P5dFzaktDaafBCo7GUsws7JhN1sKZX1F4GSVjc=
10
- =FURw
4
+ iQEcBAABCgAGBQJRKNObAAoJEP5F5V2hilTWjFYH/RPGxYJA41R43Yrgqu56vtAU
5
+ iPY/pg041S42UnObIIFgA76fMeixzfFCdBkvFFnlDuqmbSLxtiJt0Q/ql5c/hFzA
6
+ S/rKibb1I9nlzOJ3p/GO78HzaD/M2Ja/jdrJtt+w7LVqSVtfDOyS+lPe3wxzf6SS
7
+ 7hgpycQv6GX3C5AEGY/nP0btkDxNtYMGGgcYz3WfrOEQFDIKS6IU4iZCj5c6Zw4n
8
+ yD2pAvHWoqdkYy0y+eUsi83E1zCL9fHEK3R/I+c9Kc4TQF2OXFmGZdc7wbYwtdPb
9
+ yDqlTNo8mbm+kxek1P4PobHJ7QADHRC7kOSBMOXVw80JALUThAt11Y+bHOHv3/Y=
10
+ =58pK
11
11
  -----END PGP SIGNATURE-----
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: rubygems-openpgp
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.3.0
5
+ version: 0.4.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Grant Olson
@@ -10,10 +10,20 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2013-02-10 00:00:00 Z
14
- dependencies: []
15
-
16
- description: Digitally sign gems via OpenPGP instead of OpenSSL
13
+ date: 2013-02-23 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: gpg_status_parser
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.3.0
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ description: Digitally sign gems via OpenPGP.
17
27
  email: kgo@grant-olson.net
18
28
  executables: []
19
29
 
metadata.gz.asc CHANGED
@@ -1,11 +1,11 @@
1
1
  -----BEGIN PGP SIGNATURE-----
2
2
  Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
3
3
 
4
- iQEcBAABCgAGBQJRF6UqAAoJEP5F5V2hilTW4WgIAL4AJ1PPxZv+AuAwxBOFgIqR
5
- m8tM5N9bNM+KVwBplbIpl1cP/VJFN6onDeNlEY0YlCSR/EHuCOvtjCB8AFquAy72
6
- +zNxniM0d9zcEL0JRx2SLl44EBQOaFAYZ6VgLbkox9OuwUjSeEfdo66gfMtgdkHN
7
- +Tl5XKjnu5cnszfBXqfHKLdSjhAYbk0TeGRicffFDLMn7jzwwmOd9uLMmG3CrPg0
8
- mZiZpYWoazFPDnQ+KKj12ojcUCjFc/D8Xy77e2G2PP8kVOKb79Gn6Fd+npJuXL1X
9
- /8Uzkrpwc3EGCpMzT0/q4EyHc35CkaFtdbAhd4n33Rob4j+yIhi0j72tttfv1Jk=
10
- =VFwb
4
+ iQEcBAABCgAGBQJRKNOhAAoJEP5F5V2hilTWcBgIAIob5FD4SK6UxfnXQk0U+5nP
5
+ huK6hsanhLbH3m3fqz2BkB/WBVonF0sqO2zNIw+qxnIl/r426iXmxTfNYF3F+0Ri
6
+ mP7YF+HBNfuElraRBBKUXSCQoB0yxqLpx3mcDwjB//0Q9CWXdeCLzefbs7+4ca4q
7
+ rBezyxSxRXun2qBMBs7FSZYkC6rsP58EgTi555WfxymiqEZ9fEi1r4rEM37F+z2w
8
+ FBMlYjTJhATOIhHTi8nFQoGgjFcQG9a7cgABHGZwB9IR6k5O6IeTHVXCQvOlg4au
9
+ cj6HKS8YKpJGZPlPIJVpLmW9UhUQukg4AwTpPAHIeIiwZYahitQtm0Ra5MnSJtc=
10
+ =bh2W
11
11
  -----END PGP SIGNATURE-----