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