gpgme-loongson 2.0.18

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,208 @@
1
+ module GPGME
2
+
3
+ ##
4
+ # A class whose purpose is to unify the way we work with the data (both input
5
+ # and output). Most of the calls expect instances of this class, or will try
6
+ # to create one from your parameters.
7
+ #
8
+ # Read the {#read}, {#write} and {#seek} methods for the most commonly used
9
+ # methods.
10
+ class Data
11
+
12
+ BLOCK_SIZE = 4096
13
+
14
+ class << self
15
+
16
+ ##
17
+ # We implement +self.new+ instead of initialize because objects are actually
18
+ # instantiated through the C API with stuff like +gpgme_data_new+.
19
+ #
20
+ # We try to create a {GPGME::Data} smartly depending on the object passed, and if
21
+ # another {GPGME::Data} object is passed, it just returns it, so when in
22
+ # doubt, you can always pass a {GPGME::Data} object.
23
+ #
24
+ # @example empty
25
+ # data = GPGME::Data.new
26
+ # data.write("stuff")
27
+ #
28
+ # @example from a string
29
+ # data = GPGME::Data.new("From a string")
30
+ #
31
+ # @example from a file
32
+ # data = GPGME::Data.new(File.open("secure.pass"))
33
+ #
34
+ # @example from a file descriptor
35
+ # data = GPGME::Data.new(0) # Standard input
36
+ # data = GPGME::Data.new(1) # Standard output
37
+ #
38
+ # file = File.open("secure.pass")
39
+ # data = GPGME::Data.new(file.fileno) # file descriptor
40
+ #
41
+ def new(object = nil)
42
+ if object.nil?
43
+ empty!
44
+ elsif object.is_a?(Data)
45
+ object
46
+ elsif object.is_a?(Integer)
47
+ from_fd(object)
48
+ elsif object.respond_to? :to_str
49
+ from_str(object.to_str)
50
+ elsif object.respond_to? :to_io
51
+ from_io(object.to_io)
52
+ elsif object.respond_to? :open
53
+ from_io(object.open)
54
+ elsif defined?(StringIO) and object.is_a?(StringIO)
55
+ from_io(object)
56
+ end
57
+ end
58
+
59
+ # Create a new instance with an empty buffer.
60
+ def empty!
61
+ rdh = []
62
+ err = GPGME::gpgme_data_new(rdh)
63
+ exc = GPGME::error_to_exception(err)
64
+ raise exc if exc
65
+ rdh.first
66
+ end
67
+
68
+ # Create a new instance with internal buffer.
69
+ def from_str(string)
70
+ rdh = []
71
+ err = GPGME::gpgme_data_new_from_mem(rdh, string, string.bytesize)
72
+ exc = GPGME::error_to_exception(err)
73
+ raise exc if exc
74
+ rdh.first
75
+ end
76
+
77
+ # Create a new instance associated with a given IO.
78
+ def from_io(io)
79
+ from_callbacks(IOCallbacks.new(io))
80
+ end
81
+
82
+ # Create a new instance from the specified file descriptor.
83
+ def from_fd(fd)
84
+ rdh = []
85
+ err = GPGME::gpgme_data_new_from_fd(rdh, fd)
86
+ exc = GPGME::error_to_exception(err)
87
+ raise exc if exc
88
+ rdh.first
89
+ end
90
+
91
+ # Create a new instance from the specified callbacks.
92
+ def from_callbacks(callbacks, hook_value = nil)
93
+ rdh = []
94
+ err = GPGME::gpgme_data_new_from_cbs(rdh, callbacks, hook_value)
95
+ exc = GPGME::error_to_exception(err)
96
+ raise exc if exc
97
+ rdh.first
98
+ end
99
+ end # class << self
100
+
101
+ # Read at most +length+ bytes from the data object, or to the end
102
+ # of file if +length+ is omitted or is +nil+.
103
+ #
104
+ # @example
105
+ # data = GPGME::Data.new("From a string")
106
+ # data.read # => "From a string"
107
+ #
108
+ # @example
109
+ # data = GPGME::Data.new("From a string")
110
+ # data.read(4) # => "From"
111
+ #
112
+ def read(length = nil)
113
+ if length
114
+ GPGME::gpgme_data_read(self, length)
115
+ else
116
+ buf = String.new
117
+ loop do
118
+ s = GPGME::gpgme_data_read(self, BLOCK_SIZE)
119
+ break unless s
120
+ buf << s
121
+ end
122
+ buf
123
+ end
124
+ end
125
+
126
+ ##
127
+ # Seek to a given +offset+ in the data object according to the
128
+ # value of +whence+.
129
+ #
130
+ # @example going to the beginning of the buffer after writing something
131
+ # data = GPGME::Data.new("Some data")
132
+ # data.read # => "Some data"
133
+ # data.read # => ""
134
+ # data.seek 0
135
+ # data.read # => "Some data"
136
+ #
137
+ def seek(offset, whence = IO::SEEK_SET)
138
+ GPGME::gpgme_data_seek(self, offset, IO::SEEK_SET)
139
+ end
140
+
141
+ ##
142
+ # Writes +length+ bytes from +buffer+ into the data object.
143
+ # Writes the full buffer if no length passed.
144
+ #
145
+ # @example
146
+ # data = GPGME::Data.new
147
+ # data.write "hola"
148
+ # data.seek 0
149
+ # data.read # => "hola"
150
+ #
151
+ # @example
152
+ # data = GPGME::Data.new
153
+ # data.write "hola", 2
154
+ # data.seek 0
155
+ # data.read # => "ho"
156
+ #
157
+ def write(buffer, length = buffer.length)
158
+ GPGME::gpgme_data_write(self, buffer, length)
159
+ end
160
+
161
+ ##
162
+ # Return the encoding of the underlying data.
163
+ def encoding
164
+ GPGME::gpgme_data_get_encoding(self)
165
+ end
166
+
167
+ ##
168
+ # Sets the encoding for this buffer. Accepts only values in one of the
169
+ # DATA_ENCODING_* constants.
170
+ #
171
+ # @raise [GPGME::Error::InvalidValue] if the value isn't accepted.
172
+ def encoding=(encoding)
173
+ err = GPGME::gpgme_data_set_encoding(self, encoding)
174
+ exc = GPGME::error_to_exception(err)
175
+ raise exc if exc
176
+ encoding
177
+ end
178
+
179
+ ##
180
+ # Return the file name of the underlying data.
181
+ def file_name
182
+ GPGME::gpgme_data_get_file_name(self)
183
+ end
184
+
185
+ ##
186
+ # Sets the file name for this buffer.
187
+ #
188
+ # @raise [GPGME::Error::InvalidValue] if the value isn't accepted.
189
+ def file_name=(file_name)
190
+ err = GPGME::gpgme_data_set_file_name(self, file_name)
191
+ exc = GPGME::error_to_exception(err)
192
+ raise exc if exc
193
+ file_name
194
+ end
195
+
196
+ ##
197
+ # Return the entire content of the data object as string.
198
+ def to_s
199
+ pos = seek(0, IO::SEEK_CUR)
200
+ begin
201
+ seek(0)
202
+ read
203
+ ensure
204
+ seek(pos)
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,87 @@
1
+ module GPGME
2
+
3
+ ##
4
+ # Convenience methods to check different aspects of the gpg system
5
+ # installation.
6
+ module Engine
7
+ class << self
8
+
9
+ ##
10
+ # Verify that the engine implementing the protocol +proto+ is installed in
11
+ # the system. Can be one of +PROTOCOL_OpenPGP+ or +PROTOCOL_CMS+.
12
+ #
13
+ # @return [Boolean] true if the engine is installed.
14
+ #
15
+ # @example
16
+ # GPGME::Engine.check_version(GPGME::PROTOCOL_OpenPGP) # => true
17
+ #
18
+ def check_version(proto)
19
+ err = GPGME::gpgme_engine_check_version(proto)
20
+ exc = GPGME::error_to_exception(err)
21
+ !exc
22
+ end
23
+
24
+ ##
25
+ # Return an array of {GPGME::EngineInfo} structures of enabled engines.
26
+ #
27
+ # @example
28
+ # GPGME::Engine.info.first
29
+ # # => #<GPGME::EngineInfo:0x00000100d4fbd8
30
+ # @file_name="/usr/local/bin/gpg",
31
+ # @protocol=0,
32
+ # @req_version="1.3.0",
33
+ # @version="1.4.11">
34
+ #
35
+ def info
36
+ rinfo = []
37
+ GPGME::gpgme_get_engine_info(rinfo)
38
+ rinfo
39
+ end
40
+
41
+ ##
42
+ # Change the default configuration of the crypto engine implementing
43
+ # protocol +proto+.
44
+ #
45
+ # @param proto
46
+ # Can be one of +PROTOCOL_OpenPGP+ or +PROTOCOL_CMS+.
47
+ #
48
+ # @param file_name
49
+ # The file name of the executable program implementing the protocol.
50
+ #
51
+ # @param home_dir
52
+ # The directory name of the configuration directory.
53
+ #
54
+ # @example
55
+ # GPGME::Engine.set
56
+ #
57
+ def set_info(proto, file_name, home_dir)
58
+ err = GPGME::gpgme_set_engine_info(proto, file_name, home_dir)
59
+ exc = GPGME::error_to_exception(err)
60
+ raise exc if exc
61
+ end
62
+
63
+ ##
64
+ # Sets the home dir for the configuration options. This way one could,
65
+ # for example, load the keys from a customized keychain.
66
+ #
67
+ # @example
68
+ # GPGME::Engine.home_dir = '/tmp'
69
+ #
70
+ def home_dir=(home_dir)
71
+ current = info.first
72
+ set_info current.protocol, current.file_name, home_dir
73
+ end
74
+
75
+ ##
76
+ # Return the default configuration.
77
+ #
78
+ # @example
79
+ # GPGME::Engine.dirinfo('homedir')
80
+ # # => '/home/user/.gnupg"
81
+ #
82
+ def dirinfo(what)
83
+ GPGME::gpgme_get_dirinfo(what)
84
+ end
85
+ end # class << self
86
+ end # class Engine
87
+ end # module GPGME
@@ -0,0 +1,66 @@
1
+ module GPGME
2
+ class Error < StandardError
3
+ def initialize(error)
4
+ @error = error
5
+ end
6
+ attr_reader :error
7
+
8
+ # Return the error code.
9
+ #
10
+ # The error code indicates the type of an error, or the reason why
11
+ # an operation failed.
12
+ def code
13
+ GPGME::gpgme_err_code(@error)
14
+ end
15
+
16
+ # Return the error source.
17
+ #
18
+ # The error source has not a precisely defined meaning. Sometimes
19
+ # it is the place where the error happened, sometimes it is the
20
+ # place where an error was encoded into an error value. Usually
21
+ # the error source will give an indication to where to look for
22
+ # the problem. This is not always true, but it is attempted to
23
+ # achieve this goal.
24
+ def source
25
+ GPGME::gpgme_err_source(@error)
26
+ end
27
+
28
+ # Return a description of the error code.
29
+ def message
30
+ GPGME::gpgme_strerror(@error)
31
+ end
32
+
33
+ class General < self; end
34
+ class InvalidValue < self; end
35
+ class UnusablePublicKey < self
36
+ attr_accessor :keys
37
+ end
38
+ class UnusableSecretKey < self
39
+ attr_accessor :keys
40
+ end
41
+ class NoData < self; end
42
+ class Conflict < self; end
43
+ class NotImplemented < self; end
44
+ class DecryptFailed < self; end
45
+ class BadPassphrase < self; end
46
+ class Canceled < self; end
47
+ class InvalidEngine < self; end
48
+ class AmbiguousName < self; end
49
+ class WrongKeyUsage < self
50
+ attr_accessor :key_usage
51
+ end
52
+ class CertificateRevoked < self; end
53
+ class CertificateExpired < self; end
54
+ class NoCRLKnown < self; end
55
+ class NoPolicyMatch < self; end
56
+ class NoSecretKey < self; end
57
+ class MissingCertificate < self; end
58
+ class BadCertificateChain < self; end
59
+ class UnsupportedAlgorithm < self
60
+ attr_accessor :algorithm
61
+ end
62
+ class BadSignature < self; end
63
+ class NoPublicKey < self; end
64
+ class InvalidVersion < self; end
65
+ end
66
+ end
@@ -0,0 +1,21 @@
1
+ module GPGME
2
+ class IOCallbacks
3
+ def initialize(io)
4
+ @io = io
5
+ end
6
+
7
+ def read(hook, length)
8
+ @io.read(length)
9
+ end
10
+
11
+ def write(hook, buffer, length)
12
+ @io.write(buffer[0 .. length])
13
+ end
14
+
15
+ def seek(hook, offset, whence)
16
+ return @io.pos if offset == 0 && whence == IO::SEEK_CUR
17
+ @io.seek(offset, whence)
18
+ @io.pos
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,248 @@
1
+ module GPGME
2
+
3
+ ##
4
+ # A ruby representation of a public or a secret key.
5
+ #
6
+ # Every key has two instances of {GPGME::SubKey}, accessible through
7
+ # {.subkeys}, and with a {.primary_subkey} where most attributes are
8
+ # derived from, like the +fingerprint+.
9
+ #
10
+ # Also, every key has at least a {GPGME::UserID}, accessible through
11
+ # {.uids}, with a {.primary_uid}, where other attributes are derived from,
12
+ # like +email+ or +name+
13
+ class Key
14
+ private_class_method :new
15
+
16
+ attr_reader :keylist_mode, :protocol, :owner_trust
17
+ attr_reader :issuer_serial, :issuer_name, :chain_id
18
+ attr_reader :subkeys, :uids
19
+
20
+ include KeyCommon
21
+
22
+ class << self
23
+
24
+ ##
25
+ # Returns an array of {GPGME::Key} objects that match the parameters.
26
+ # * +secret+ set to +:secret+ to get only secret keys, or to +:public+ to
27
+ # get only public keys.
28
+ # * +keys_or_names+ an array or an item that can be either {GPGME::Key}
29
+ # elements, or string identifiers like the email or the sha. Leave
30
+ # blank to get all.
31
+ # * +purposes+ get only keys that are usable for any of these purposes.
32
+ # See {GPGME::Key} for a list of possible key capabilities.
33
+ #
34
+ # @example
35
+ # GPGME::Key.find :secret # => first secret key found
36
+ #
37
+ # @example
38
+ # GPGME::Key.find(:public, "mrsimo@example.com")
39
+ # # => return only public keys that match mrsimo@example.com
40
+ #
41
+ # @example
42
+ # GPGME::Key.find(:public, "mrsimo@example.com", :sign)
43
+ # # => return the public keys that match mrsimo@example.com and are
44
+ # # capable of signing
45
+ def find(secret, keys_or_names = nil, purposes = [])
46
+ secret = (secret == :secret)
47
+ keys_or_names = [""] if keys_or_names.nil? || (keys_or_names.is_a?(Array) && keys_or_names.empty?)
48
+ keys_or_names = [keys_or_names].flatten
49
+ purposes = [purposes].flatten.compact.uniq
50
+
51
+ keys = []
52
+ keys_or_names.each do |key_or_name|
53
+ case key_or_name
54
+ when Key then keys << key_or_name
55
+ when String
56
+ GPGME::Ctx.new do |ctx|
57
+ keys += ctx.keys(key_or_name, secret).select do |k|
58
+ k.usable_for?(purposes)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ keys
64
+ end
65
+
66
+ def get(fingerprint)
67
+ Ctx.new do |ctx|
68
+ ctx.get_key(fingerprint)
69
+ end
70
+ end
71
+
72
+ # Exports public keys
73
+ #
74
+ # GPGME::Key.export pattern, options
75
+ #
76
+ # Private keys cannot be exported due to GPGME restrictions.
77
+ #
78
+ # @param pattern
79
+ # Identifier of the key to export.
80
+ #
81
+ # @param [Hash] options
82
+ # * +:output+ specify where to write the key to. It will be converted to
83
+ # a {GPGME::Data}, so it could be a file, for example.
84
+ # * Any other option accepted by {GPGME::Ctx.new}
85
+ #
86
+ # @return [GPGME::Data] the exported key.
87
+ #
88
+ # @example
89
+ # key = GPGME::Key.export "mrsimo@example.com"
90
+ #
91
+ # @example writing to a file
92
+ # out = File.open("my.key", "w+")
93
+ # GPGME::Key.export "mrsimo@example.com", :output => out
94
+ #
95
+ def export(pattern, options = {})
96
+ output = Data.new(options[:output])
97
+
98
+ GPGME::Ctx.new(options) do |ctx|
99
+ ctx.export_keys(pattern, output)
100
+ end
101
+
102
+ output.seek(0)
103
+ output
104
+ end
105
+
106
+ # Imports a key
107
+ #
108
+ # GPGME::Key.import keydata, options
109
+ #
110
+ # @param keydata
111
+ # The key to import. It will be converted to a {GPGME::Data} object,
112
+ # so could be a file, for example.
113
+ # @param options
114
+ # Any other option accepted by {GPGME::Ctx.new}
115
+ #
116
+ # @example
117
+ # GPGME::Key.import(File.open("my.key"))
118
+ #
119
+ def import(keydata, options = {})
120
+ GPGME::Ctx.new(options) do |ctx|
121
+ ctx.import_keys(Data.new(keydata))
122
+ ctx.import_result
123
+ end
124
+ end
125
+ end
126
+
127
+ ##
128
+ # Exports this key. Accepts the same options as {GPGME::Ctx.new}, and
129
+ # +options[:output]+, where you can specify something that can become a
130
+ # {GPGME::Data}, where the output will go.
131
+ #
132
+ # @example
133
+ # key.export(:armor => true)
134
+ # # => GPGME::Data you can read with ASCII armored format
135
+ #
136
+ # @example
137
+ # file = File.open("key.asc", "w+")
138
+ # key.export(:output => file)
139
+ # # => the key will be written to the file.
140
+ #
141
+ def export(options = {})
142
+ Key.export self.sha, options
143
+ end
144
+
145
+ ##
146
+ # Delete this key. If it's public, and has a secret one it will fail unless
147
+ # +allow_secret+ is specified as true.
148
+ def delete!(allow_secret = false)
149
+ GPGME::Ctx.new do |ctx|
150
+ ctx.delete_key self, allow_secret
151
+ end
152
+ end
153
+
154
+ ##
155
+ # Returns true if the key has an expiry date else false
156
+ def expires?
157
+ primary_subkey.expires?
158
+ end
159
+
160
+ ##
161
+ # Returns the expiry date for this key
162
+ def expires
163
+ primary_subkey.expires
164
+ end
165
+
166
+ ##
167
+ # Returns true if the key is expired
168
+ def expired
169
+ subkeys.any?(&:expired)
170
+ end
171
+
172
+ def primary_subkey
173
+ @primary_subkey ||= subkeys.first
174
+ end
175
+
176
+ ##
177
+ # Short descriptive value. Can be used to identify the key.
178
+ def sha
179
+ primary_subkey.sha
180
+ end
181
+
182
+ ##
183
+ # Longer descriptive value. Can be used to identify the key.
184
+ def fingerprint
185
+ primary_subkey.fingerprint
186
+ end
187
+
188
+ ##
189
+ # Returns the main {GPGME::UserID} for this key.
190
+ def primary_uid
191
+ uids.first
192
+ end
193
+
194
+ ##
195
+ # Returns the email for this key.
196
+ def email
197
+ primary_uid.email
198
+ end
199
+
200
+ ##
201
+ # Returns the issuer name for this key.
202
+ def name
203
+ primary_uid.name
204
+ end
205
+
206
+ ##
207
+ # Returns the issuer comment for this key.
208
+ def comment
209
+ primary_uid.comment
210
+ end
211
+
212
+ def ==(another_key)
213
+ self.class === another_key and fingerprint == another_key.fingerprint
214
+ end
215
+
216
+ def inspect
217
+ sprintf("#<#{self.class} %s %4d%s/%s %s trust=%s, owner_trust=%s, \
218
+ capability=%s, subkeys=%s, uids=%s>",
219
+ primary_subkey.secret? ? 'sec' : 'pub',
220
+ primary_subkey.length,
221
+ primary_subkey.pubkey_algo_letter,
222
+ primary_subkey.fingerprint[-8 .. -1],
223
+ primary_subkey.timestamp.strftime('%Y-%m-%d'),
224
+ trust.inspect,
225
+ VALIDITY_NAMES[@owner_trust].inspect,
226
+ capability.inspect,
227
+ subkeys.inspect,
228
+ uids.inspect)
229
+ end
230
+
231
+ def to_s
232
+ primary_subkey = subkeys[0]
233
+ s = sprintf("%s %4d%s/%s %s\n",
234
+ primary_subkey.secret? ? 'sec' : 'pub',
235
+ primary_subkey.length,
236
+ primary_subkey.pubkey_algo_letter,
237
+ primary_subkey.fingerprint[-8 .. -1],
238
+ primary_subkey.timestamp.strftime('%Y-%m-%d'))
239
+ uids.each do |user_id|
240
+ s << "uid\t\t#{user_id.name} <#{user_id.email}>\n"
241
+ end
242
+ subkeys.each do |subkey|
243
+ s << subkey.to_s
244
+ end
245
+ s
246
+ end
247
+ end
248
+ end