rubygems-openpgp 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -1
- data/lib/rubygems/gem_openpgp.rb +84 -17
- data/lib/rubygems_plugin.rb +17 -1
- data.tar.gz.asc +7 -7
- metadata +15 -5
- metadata.gz.asc +7 -7
data/LICENSE
CHANGED
data/lib/rubygems/gem_openpgp.rb
CHANGED
@@ -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
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
56
|
-
|
57
|
-
|
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.
|
240
|
+
def self.run_gpg args, data=nil, &block
|
181
241
|
exit_status = nil
|
182
|
-
|
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
|
-
|
189
|
-
[out,err]
|
252
|
+
{:status => exit_status, :stdout => out, :err => err}
|
190
253
|
end
|
191
|
-
|
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
|
|
data/lib/rubygems_plugin.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
=
|
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.
|
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-
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
|
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
|
-
|
5
|
-
|
6
|
-
+
|
7
|
-
+
|
8
|
-
|
9
|
-
|
10
|
-
=
|
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-----
|