libzypp 17.38.9
KeyManager.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
9#include <iostream>
10#include "KeyManager.h"
11#include "KeyRingException.h"
12
18
19#include <boost/thread/once.hpp>
20#include <boost/interprocess/smart_ptr/scoped_ptr.hpp>
21#include <gpgme.h>
22
23#include <stdio.h>
24using std::endl;
25
26#undef ZYPP_BASE_LOGGER_LOGGROUP
27#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::gpg"
28
30namespace zypp
31{
33 namespace
34 {
35 // @TODO [threading]
36 // make sure to call the init code of gpgme only once
37 // this might need to be moved to a different location when
38 // threads are introduced into libzypp
39 boost::once_flag gpgme_init_once = BOOST_ONCE_INIT;
40
41 void initGpgme ()
42 {
43 const char *version = gpgme_check_version(NULL);
44 if ( version )
45 {
46 MIL << "Initialized libgpgme version: " << version << endl;
47 }
48 else
49 {
50 MIL << "Initialized libgpgme with unknown version" << endl;
51 }
52 }
53
54 //using boost::interprocess pointer because it allows a custom deleter
55 using GpgmeDataPtr = boost::interprocess::scoped_ptr<gpgme_data, boost::function<void (gpgme_data_t)>>;
56 using GpgmeKeyPtr = boost::interprocess::scoped_ptr<_gpgme_key, boost::function<void (gpgme_key_t)>>;
57 using FILEPtr = boost::interprocess::scoped_ptr<FILE, boost::function<int (FILE *)>>;
58
59 struct GpgmeErr
60 {
61 GpgmeErr( gpgme_error_t err_r = GPG_ERR_NO_ERROR )
62 : _err( err_r )
63 {}
64 operator gpgme_error_t() const { return _err; }
65 private:
66 gpgme_error_t _err;
67 };
68
69 std::ostream & operator<<( std::ostream & str, const GpgmeErr & obj )
70 { return str << "<" << gpgme_strsource(obj) << "> " << gpgme_strerror(obj); }
71
73 [[maybe_unused]] std::ostream & operator<<( std::ostream & str, const _gpgme_op_import_result & obj )
74 {
75 str << "gpgme_op_import_result {" << endl;
76 str << " " << obj.considered << " The total number of considered keys." << endl;
77 str << " " << obj.no_user_id << " The number of keys without user ID." << endl;
78 str << " " << obj.imported << " The total number of imported keys." << endl;
79 str << " " << obj.imported_rsa << " imported RSA keys." << endl;
80 str << " " << obj.unchanged << " unchanged keys." << endl;
81 str << " " << obj.new_user_ids << " new user IDs." << endl;
82 str << " " << obj.new_sub_keys << " new sub keys." << endl;
83 str << " " << obj.new_signatures << " new signatures." << endl;
84 str << " " << obj.new_revocations << " new revocations." << endl;
85 str << " " << obj.secret_read << " secret keys read." << endl;
86 str << " " << obj.secret_imported << " imported secret keys." << endl;
87 str << " " << obj.secret_unchanged << " unchanged secret keys." << endl;
88 str << " " << obj.not_imported << " keys not imported." << endl;
89 for ( gpgme_import_status_t p = obj.imports; p; p = p->next )
90 {
91 str << " - " << p->fpr << ": " << p->result << endl;
92 }
93 // In V.1.11: str << " " << obj.skipped_v3_keys << " skipped v3 keys." << endl;
94 return str << "}";
95 }
96
97 [[maybe_unused]] std::ostream & operator<<( std::ostream & str, const gpgme_sigsum_t & obj )
98 {
99 str << ((int)obj&(int)0xffff) << ":";
100#define OSC(V) if ( V & (unsigned)obj ) str << " " << #V;
101 OSC(GPGME_SIGSUM_VALID );
102 OSC(GPGME_SIGSUM_GREEN );
103 OSC(GPGME_SIGSUM_RED );
104 OSC(GPGME_SIGSUM_KEY_REVOKED );
105 OSC(GPGME_SIGSUM_KEY_EXPIRED );
106 OSC(GPGME_SIGSUM_SIG_EXPIRED );
107 OSC(GPGME_SIGSUM_KEY_MISSING );
108 OSC(GPGME_SIGSUM_CRL_MISSING );
109 OSC(GPGME_SIGSUM_CRL_TOO_OLD );
110 OSC(GPGME_SIGSUM_BAD_POLICY );
111 OSC(GPGME_SIGSUM_SYS_ERROR );
112 OSC(GPGME_SIGSUM_TOFU_CONFLICT);
113#undef OSC
114 return str;
115 }
116
117 [[maybe_unused]] std::ostream & operator<<( std::ostream & str, const gpgme_signature_t & obj )
118 {
119 str << "gpgme_signature_t " << (void *)obj << " {" << endl;
120 str << " next: " << (void *)obj->next << endl;
121 str << " summary: " << obj->summary << endl;
122 str << " fpr: " << obj->fpr << endl;
123 str << " status: " << obj->status << " " << GpgmeErr(obj->status) << endl;
124 str << " timestamp: " << obj->timestamp << endl;
125 str << " exp_timestamp: " << obj->exp_timestamp << endl;
126 str << " wrong_key_usage: " << obj->wrong_key_usage << endl;
127 str << " pka_trust: " << obj->pka_trust << endl;
128 str << " chain_model: " << obj->chain_model << endl;
129 str << " is_de_vs: " << obj->is_de_vs << endl;
130 str << " validity: " << obj->validity << endl;
131 str << " validity_reason: " << obj->validity_reason << " " << GpgmeErr(obj->validity_reason) << endl;
132 str << " pubkey_algo: " << obj->pubkey_algo << endl;
133 str << " hash_algo: " << obj->hash_algo << endl;
134 str << " pka_address: " << (obj->pka_address ? obj->pka_address : "") << endl;
135 return str;
136 }
137
138 } // namespace
140
142 {
143 GpgmeException( const std::string & in_r, const GpgmeErr & err_r )
144 : KeyRingException( str::Format( "libgpgme error in '%1%': %2%" ) % in_r % err_r )
145 {}
146 };
147
149 {
150 public:
152 { boost::call_once( gpgme_init_once, initGpgme ); }
153
154 Impl(const Impl &) = delete;
155 Impl(Impl &&) = delete;
156 Impl &operator=(const Impl &) = delete;
157 Impl &operator=(Impl &&) = delete;
158
160 if (_ctx)
161 gpgme_release(_ctx);
162 }
163
165 std::list<std::string> readSignaturesFprs( const Pathname & signature_r )
166 { return readSignaturesFprsOptVerify( signature_r ); }
167
169 std::list<std::string> readSignaturesFprs( const ByteArray & signature_r )
170 { return readSignaturesFprsOptVerify( signature_r ); }
171
173 bool verifySignaturesFprs( const Pathname & file_r, const Pathname & signature_r )
174 {
175 bool verify = false;
176 readSignaturesFprsOptVerify( signature_r, file_r, &verify );
177 return verify;
178 }
179
180 template< typename Callback >
181 bool importKey(GpgmeDataPtr &data, Callback &&calcDataSize );
182
183 gpgme_ctx_t _ctx { nullptr };
184 bool _volatile { false };
185
186 private:
192 std::list<std::string> readSignaturesFprsOptVerify( const Pathname & signature_r, const Pathname & file_r = "/dev/null", bool * verify_r = nullptr );
193 std::list<std::string> readSignaturesFprsOptVerify( const ByteArray& keyData_r, const Pathname & file_r = "/dev/null", bool * verify_r = nullptr );
194 std::list<std::string> readSignaturesFprsOptVerify( GpgmeDataPtr &sigData, const Pathname & file_r = "/dev/null", bool * verify_r = nullptr );
195 };
196
197std::list<std::string> KeyManagerCtx::Impl::readSignaturesFprsOptVerify( const Pathname & signature_r, const Pathname & file_r, bool * verify_r )
198{
199 //lets be pessimistic
200 if ( verify_r )
201 *verify_r = false;
202
203 if (!PathInfo( signature_r ).isExist())
204 return std::list<std::string>();
205
206 FILEPtr sigFile(fopen(signature_r.c_str(), "rb"), fclose);
207 if (!sigFile) {
208 ERR << "Unable to open signature file '" << signature_r << "'" <<endl;
209 return std::list<std::string>();
210 }
211
212 GpgmeDataPtr sigData(nullptr, gpgme_data_release);
213 GpgmeErr err = gpgme_data_new_from_stream (&sigData.get(), sigFile.get());
214 if (err) {
215 ERR << err << endl;
216 return std::list<std::string>();
217 }
218
219 return readSignaturesFprsOptVerify( sigData, file_r, verify_r );
220}
221
222std::list<std::string> KeyManagerCtx::Impl::readSignaturesFprsOptVerify( const ByteArray &keyData_r, const filesystem::Pathname &file_r, bool *verify_r )
223{
224 //lets be pessimistic
225 if ( verify_r )
226 *verify_r = false;
227
228 GpgmeDataPtr sigData(nullptr, gpgme_data_release);
229 GpgmeErr err = gpgme_data_new_from_mem(&sigData.get(), keyData_r.data(), keyData_r.size(), 1 );
230 if (err) {
231 ERR << err << endl;
232 return std::list<std::string>();
233 }
234
235 return readSignaturesFprsOptVerify( sigData, file_r, verify_r );
236}
237
238std::list<std::string> KeyManagerCtx::Impl::readSignaturesFprsOptVerify(GpgmeDataPtr &sigData, const filesystem::Pathname &file_r, bool *verify_r)
239{
240 //lets be pessimistic
241 if ( verify_r )
242 *verify_r = false;
243
244 FILEPtr dataFile(fopen(file_r.c_str(), "rb"), fclose);
245 if (!dataFile)
246 return std::list<std::string>();
247
248 GpgmeDataPtr fileData(nullptr, gpgme_data_release);
249 GpgmeErr err = gpgme_data_new_from_stream (&fileData.get(), dataFile.get());
250 if (err) {
251 ERR << err << endl;
252 return std::list<std::string>();
253 }
254
255 err = gpgme_op_verify(_ctx, sigData.get(), fileData.get(), NULL);
256 if (err != GPG_ERR_NO_ERROR) {
257 ERR << err << endl;
258 return std::list<std::string>();
259 }
260
261 gpgme_verify_result_t res = gpgme_op_verify_result(_ctx);
262 if (!res || !res->signatures) {
263 ERR << "Unable to read signature fingerprints" <<endl;
264 return std::list<std::string>();
265 }
266
267 bool foundBadSignature = false;
268 bool foundGoodSignature = false;
269 std::list<std::string> signatures;
270 for ( gpgme_signature_t sig = res->signatures; sig; sig = sig->next ) {
271 //DBG << "- " << sig << std::endl;
272 if ( sig->fpr )
273 {
274 // bsc#1100427: With libgpgme11-1.11.0 and if a recent gpg version was used
275 // to create the signature, the field may contain the full fingerprint, but
276 // we're expected to return the ID.
277 // [https://github.com/gpg/gpgme/commit/478d1650bbef84958ccce439fac982ef57b16cd0]
278 std::string id( sig->fpr );
279 if ( id.size() > 16 )
280 id = id.substr( id.size()-16 );
281
282 DBG << "Found signature with ID: " << id << " in " << file_r << std::endl;
283 signatures.push_back( std::move(id) );
284 }
285
286 if ( verify_r && sig->status != GPG_ERR_NO_ERROR ) {
287 const auto status = gpgme_err_code(sig->status);
288
289 // bsc#1180721: libgpgme started to return signatures of unknown keys, which breaks
290 // our workflow when verifying files that have multiple signatures, including some that are
291 // not in the trusted keyring. We should not fail if we have unknown or expired keys and at least a good one.
292 // We will however keep the behaviour of failing if we find a bad signatures even if others are good.
293 switch ( status ) {
294 case GPG_ERR_KEY_EXPIRED:
295 // for now treat expired keys as good signature
296 foundGoodSignature = true;
297 WAR << "Accept good signature from expired key: " << file_r << " " << GpgmeErr(sig->status) << endl;
298 break;
299
300 case GPG_ERR_NO_PUBKEY:
301 WAR << "Legacy: Ignore unknown key: " << file_r << " " << GpgmeErr(sig->status) << endl;
302 break;
303
304 default:
305 WAR << "Failed signature check: " << file_r << " " << GpgmeErr(sig->status) << endl;
306 if ( !foundBadSignature )
307 foundBadSignature = true;
308 break;
309 }
310 } else {
311 foundGoodSignature = true;
312 }
313 }
314
315 if ( verify_r )
316 *verify_r = (!foundBadSignature) && foundGoodSignature;
317 return signatures;
318}
319
323
325{
326 static Pathname tmppath( zypp::myTmpDir() / "PublicKey" );
327 filesystem::assert_dir( tmppath );
328
329 KeyManagerCtx ret { createForOpenPGP( tmppath ) };
330 ret._pimpl->_volatile = true; // readKeyFromFile workaround bsc#1140670
331 return ret;
332}
333
335{
336 // DBG << "createForOpenPGP(" << keyring_r << ")" << endl;
337
338 KeyManagerCtx ret;
339 gpgme_ctx_t & ctx { ret._pimpl->_ctx };
340
341 // create the context
342 GpgmeErr err = gpgme_new( &ctx );
343 if ( err != GPG_ERR_NO_ERROR )
344 ZYPP_THROW( GpgmeException( "gpgme_new", err ) );
345
346 // use OpenPGP
347 err = gpgme_set_protocol( ctx, GPGME_PROTOCOL_OpenPGP );
348 if ( err != GPG_ERR_NO_ERROR )
349 ZYPP_THROW( GpgmeException( "gpgme_set_protocol", err ) );
350
351 if ( !keyring_r.empty() ) {
352 // get engine information to read current state
353 gpgme_engine_info_t enginfo = gpgme_ctx_get_engine_info( ctx );
354 if ( !enginfo )
355 ZYPP_THROW( GpgmeException( "gpgme_ctx_get_engine_info", err ) );
356
357 err = gpgme_ctx_set_engine_info( ctx, GPGME_PROTOCOL_OpenPGP, enginfo->file_name, keyring_r.c_str() );
358 if ( err != GPG_ERR_NO_ERROR )
359 ZYPP_THROW( GpgmeException( "gpgme_ctx_set_engine_info", err ) );
360 }
361#if 0
362 DBG << "createForOpenPGP {" << endl;
363 for ( const auto & key : ret.listKeys() ) {
364 DBG << " " << key << endl;
365 }
366 DBG << "}" << endl;
367#endif
368 return ret;
369}
370
372{
373 Pathname ret;
374 if ( gpgme_engine_info_t enginfo = gpgme_ctx_get_engine_info( _pimpl->_ctx ) )
375 ret = enginfo->home_dir;
376 return ret;
377}
378
379std::list<PublicKeyData> KeyManagerCtx::listKeys()
380{
381 std::list<PublicKeyData> ret;
382 GpgmeErr err = GPG_ERR_NO_ERROR;
383
384 // Reset gpgme_keylist_mode on return!
385 AutoDispose<gpgme_keylist_mode_t> guard { gpgme_get_keylist_mode( _pimpl->_ctx ), bind( &gpgme_set_keylist_mode, _pimpl->_ctx, _1 ) };
386 // Let listed keys include signatures (required if PublicKeyData are created from the key)
387 if ( (err = gpgme_set_keylist_mode( _pimpl->_ctx, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_SIGS )) != GPG_ERR_NO_ERROR ) {
388 ERR << "gpgme_set_keylist_mode: " << err << endl;
389 return ret;
390 }
391
392 if ( (err = gpgme_op_keylist_start( _pimpl->_ctx, NULL, 0 )) != GPG_ERR_NO_ERROR ) {
393 ERR << "gpgme_op_keylist_start: " << err << endl;
394 return ret;
395 }
396 // Close list operation on return!
397 AutoDispose<gpgme_ctx_t> guard2 { _pimpl->_ctx, &gpgme_op_keylist_end };
398
399 AutoDispose<gpgme_key_t> key { nullptr, &gpgme_key_release };
400 for ( ; gpgme_op_keylist_next( _pimpl->_ctx, &(*key) ) == GPG_ERR_NO_ERROR; key.getDispose()( key ) ) {
402 if ( data )
403 ret.push_back( data );
404 }
405
406 return ret;
407}
408
409std::list<PublicKeyData> KeyManagerCtx::readKeyFromFile( const Pathname & keyfile_r )
410{
411 // bsc#1140670: GPGME does not support reading keys from a keyfile using
412 // gpgme_data_t and gpgme_op_keylist_from_data_start. Despite GPGME_KEYLIST_MODE_SIGS
413 // the signatures are missing, but we need them to create proper PublicKeyData objects.
414 // While this is not resolved, we read into a temp. keyring. Impl::_volatile helps
415 // to detect whether we can clear and import into the current context or need to
416 // create a temp. one.
417 std::list<PublicKeyData> ret;
418
419 if ( _pimpl->_volatile ) {
420 // in a volatile context we can simple clear the keyring...
422 if ( importKey( keyfile_r ) )
423 ret = listKeys();
424 } else {
425 // read in a volatile context
426 ret = createForOpenPGP().readKeyFromFile( keyfile_r );
427 }
428
429 return ret;
430}
431
432bool KeyManagerCtx::verify(const Pathname &file, const Pathname &signature)
433{
434 return _pimpl->verifySignaturesFprs(file, signature);
435}
436
437bool KeyManagerCtx::exportKey(const std::string &id, std::ostream &stream)
438{
439 GpgmeErr err = GPG_ERR_NO_ERROR;
440
441 GpgmeKeyPtr foundKey;
442
443 //search for requested key id
444 gpgme_key_t key = nullptr;
445 gpgme_op_keylist_start(_pimpl->_ctx, NULL, 0);
446 while (!(err = gpgme_op_keylist_next(_pimpl->_ctx, &key))) {
447 if (key->subkeys && id == str::asString(key->subkeys->keyid)) {
448 GpgmeKeyPtr(key, gpgme_key_release).swap(foundKey);
449 break;
450 }
451 gpgme_key_release(key);
452 }
453 gpgme_op_keylist_end(_pimpl->_ctx);
454
455 if (!foundKey) {
456 WAR << "Key " << id << "not found" << endl;
457 return false;
458 }
459
460 //function needs a array of keys to export
461 gpgme_key_t keyarray[2];
462 keyarray[0] = foundKey.get();
463 keyarray[1] = NULL;
464
465 GpgmeDataPtr out(nullptr, gpgme_data_release);
466 err = gpgme_data_new (&out.get());
467 if (err) {
468 ERR << err << endl;
469 return false;
470 }
471
472 //format as ascii armored
473 gpgme_set_armor (_pimpl->_ctx, 1);
474 // bsc#1179222: Remove outdated self signatures when exporting the key.
475 // The keyring does not order the signatures when multiple versions of the
476 // same key are imported. Rpm however uses the 1st to compute the -release
477 // of the gpg-pubkey. So we export only the latest to get a proper-release.
478 err = gpgme_op_export_keys (_pimpl->_ctx, keyarray, GPGME_EXPORT_MODE_MINIMAL, out.get());
479 if (!err) {
480 int ret = gpgme_data_seek (out.get(), 0, SEEK_SET);
481 if (ret) {
482 ERR << "Unable to seek in exported key data" << endl;
483 return false;
484 }
485
486 const int bufsize = 512;
487 char buf[bufsize + 1];
488 while ((ret = gpgme_data_read(out.get(), buf, bufsize)) > 0) {
489 stream.write(buf, ret);
490 }
491
492 //failed to read from buffer
493 if (ret < 0) {
494 ERR << "Unable to read exported key data" << endl;
495 return false;
496 }
497 } else {
498 ERR << "Error exporting key: "<< err << endl;
499 return false;
500 }
501
502 //if we reach this point export was successful
503 return true;
504}
505
507{
508 if ( !PathInfo( keyfile ).isExist() ) {
509 ERR << "Keyfile '" << keyfile << "' does not exist.";
510 return false;
511 }
512
513 GpgmeDataPtr data(nullptr, gpgme_data_release);
514 GpgmeErr err;
515
516 err = gpgme_data_new_from_file(&data.get(), keyfile.c_str(), 1);
517 if (err) {
518 ERR << "Error importing key: "<< err << endl;
519 return false;
520 }
521
522 return _pimpl->importKey( data, [&](){ return PathInfo(keyfile).size(); } );
523}
524
526{
527 GpgmeDataPtr data(nullptr, gpgme_data_release);
528 GpgmeErr err;
529
530 err = gpgme_data_new_from_mem( &data.get(), keydata.data(), keydata.size(), 1);
531 if (err) {
532 ERR << "Error importing key: "<< err << endl;
533 return false;
534 }
535
536 return _pimpl->importKey( data, [&](){ return keydata.size(); } );
537}
538
539template<typename Callback>
540bool KeyManagerCtx::Impl::importKey(GpgmeDataPtr &data, Callback &&calcDataSize)
541{
542 GpgmeErr err;
543 err = gpgme_op_import( _ctx, data.get() );
544 if (err) {
545 ERR << "Error importing key: "<< err << endl;
546 return false;
547 }
548
549 // Work around bsc#1127220 [libgpgme] no error upon incomplete import due to signal received.
550 // We need this error, otherwise RpmDb will report the missing keys as 'probably v3'.
551 if ( gpgme_import_result_t res = gpgme_op_import_result(_ctx) )
552 {
553 if ( ! res->considered && std::forward<Callback>(calcDataSize)() )
554 {
555 DBG << *res << endl;
556 ERR << "Error importing key: No keys considered (bsc#1127220, [libgpgme] signal received?)" << endl;
557 return false;
558 }
559 }
560
561 return (err == GPG_ERR_NO_ERROR);
562}
563
564bool KeyManagerCtx::deleteKey(const std::string &id)
565{
566 gpgme_key_t key = nullptr;
567 GpgmeErr err = GPG_ERR_NO_ERROR;
568
569 gpgme_op_keylist_start(_pimpl->_ctx, NULL, 0);
570
571 while (!(err = gpgme_op_keylist_next(_pimpl->_ctx, &key))) {
572 if (key->subkeys && id == str::asString(key->subkeys->keyid)) {
573 err = gpgme_op_delete(_pimpl->_ctx, key, 0);
574
575 gpgme_key_release(key);
576 gpgme_op_keylist_end(_pimpl->_ctx);
577
578 if (err) {
579 ERR << "Error deleting key: "<< err << endl;
580 return false;
581 }
582 return true;
583 }
584 gpgme_key_release(key);
585 }
586
587 gpgme_op_keylist_end(_pimpl->_ctx);
588 WAR << "Key: '"<< id << "' not found." << endl;
589 return false;
590}
591
592std::list<std::string> KeyManagerCtx::readSignatureFingerprints(const Pathname &signature)
593{ return _pimpl->readSignaturesFprs(signature); }
594
595std::list<std::string> KeyManagerCtx::readSignatureFingerprints(const ByteArray &keyData)
596{ return _pimpl->readSignaturesFprs(keyData); }
597
598} // namespace zypp
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
#define OSC(V)
#define DBG
Definition Logger.h:102
#define MIL
Definition Logger.h:103
#define ERR
Definition Logger.h:105
#define WAR
Definition Logger.h:104
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
const Dispose & getDispose() const
Return the current dispose function.
Impl & operator=(const Impl &)=delete
std::list< std::string > readSignaturesFprs(const Pathname &signature_r)
Return all fingerprints found in signature_r.
Impl(const Impl &)=delete
bool _volatile
readKeyFromFile workaround bsc#1140670
Impl & operator=(Impl &&)=delete
std::list< std::string > readSignaturesFprs(const ByteArray &signature_r)
Return all fingerprints found in signature_r.
std::list< std::string > readSignaturesFprsOptVerify(const Pathname &signature_r, const Pathname &file_r="/dev/null", bool *verify_r=nullptr)
Return all fingerprints found in signature_r and optionally verify the file_r on the fly.
bool verifySignaturesFprs(const Pathname &file_r, const Pathname &signature_r)
Tries to verify the file_r using signature_r.
bool importKey(GpgmeDataPtr &data, Callback &&calcDataSize)
bool exportKey(const std::string &id, std::ostream &stream)
Exports the key with id into the given stream, returns true on success.
std::list< PublicKeyData > listKeys()
Returns a list of all public keys found in the current keyring.
bool verify(const Pathname &file, const Pathname &signature)
Tries to verify file using signature, returns true on success.
static KeyManagerCtx createForOpenPGP()
Creates a new KeyManagerCtx for PGP using a volatile temp.
std::list< std::string > readSignatureFingerprints(const Pathname &signature)
Reads all fingerprints from the signature file , returns a list of all found fingerprints.
std::list< PublicKeyData > readKeyFromFile(const Pathname &file)
Returns a list of all PublicKeyData found in file.
RW_pointer< Impl > _pimpl
Pointer to implementation.
Definition KeyManager.h:88
bool deleteKey(const std::string &id)
Tries to delete a key specified by id, returns true on success.
Pathname homedir() const
Return the homedir/keyring.
bool importKey(const Pathname &keyfile)
Tries to import a key from keyfile, returns true on success.
KeyRingException()
Ctor taking message.
Class representing one GPG Public Keys data.
Definition PublicKey.h:201
static PublicKeyData fromGpgmeKey(_gpgme_key *data)
Definition PublicKey.cc:406
Wrapper class for stat/lstat.
Definition PathInfo.h:226
const char * c_str() const
String representation.
Definition Pathname.h:113
bool empty() const
Test for an empty path.
Definition Pathname.h:117
String related utilities and Regular expression matching.
int clean_dir(const Pathname &path)
Like 'rm -r DIR/ *'.
Definition PathInfo.cc:461
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition PathInfo.cc:338
const std::string & asString(const std::string &t)
Global asString() that works with std::string too.
Definition String.h:140
Easy-to use interface to the ZYPP dependency resolver.
Pathname myTmpDir()
Global access to the zypp.TMPDIR (created on demand, deleted when libzypp is unloaded).
Definition TmpPath.cc:276
std::ostream & operator<<(std::ostream &str, const Capabilities &obj)
relates: Capabilities Stream output
GpgmeException(const std::string &in_r, const GpgmeErr &err_r)