51ebcd00469b63c83215d47e8dd549002b4984fb
[platform/upstream/libzypp.git] / zypp / KeyRing.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/KeyRing.cc
10  *
11 */
12 #include <iostream>
13 #include <fstream>
14 #include <sys/file.h>
15 #include <cstdio>
16 #include <unistd.h>
17
18 #include "zypp/TmpPath.h"
19 #include "zypp/ZYppFactory.h"
20 #include "zypp/ZYpp.h"
21
22 #include "zypp/base/LogTools.h"
23 #include "zypp/base/IOStream.h"
24 #include "zypp/base/String.h"
25 #include "zypp/base/Regex.h"
26 #include "zypp/base/Gettext.h"
27 #include "zypp/base/WatchFile.h"
28 #include "zypp/PathInfo.h"
29 #include "zypp/KeyRing.h"
30 #include "zypp/ExternalProgram.h"
31 #include "zypp/TmpPath.h"
32 #include "zypp/ZYppCallbacks.h"       // JobReport::instance
33 #include "zypp/KeyManager.h"
34
35 using std::endl;
36
37 #undef  ZYPP_BASE_LOGGER_LOGGROUP
38 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::KeyRing"
39
40 ///////////////////////////////////////////////////////////////////
41 namespace zypp
42 { /////////////////////////////////////////////////////////////////
43
44   IMPL_PTR_TYPE(KeyRing);
45
46   namespace
47   {
48     KeyRing::DefaultAccept _keyRingDefaultAccept( KeyRing::ACCEPT_NOTHING );
49   }
50
51   KeyRing::DefaultAccept KeyRing::defaultAccept()
52   { return _keyRingDefaultAccept; }
53
54   void KeyRing::setDefaultAccept( DefaultAccept value_r )
55   {
56     MIL << "Set new KeyRing::DefaultAccept: " << value_r << endl;
57     _keyRingDefaultAccept = value_r;
58   }
59
60   void KeyRingReport::infoVerify( const std::string & file_r, const PublicKeyData & keyData_r, const KeyContext & keycontext )
61   {}
62
63   bool KeyRingReport::askUserToAcceptUnsignedFile( const std::string & file, const KeyContext & keycontext )
64   { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_UNSIGNED_FILE ); }
65
66   KeyRingReport::KeyTrust
67   KeyRingReport::askUserToAcceptKey( const PublicKey & key, const KeyContext & keycontext )
68   {
69     if ( _keyRingDefaultAccept.testFlag( KeyRing::TRUST_KEY_TEMPORARILY ) )
70       return KEY_TRUST_TEMPORARILY;
71     if ( _keyRingDefaultAccept.testFlag( KeyRing::TRUST_AND_IMPORT_KEY ) )
72       return KEY_TRUST_AND_IMPORT;
73     return KEY_DONT_TRUST;
74   }
75
76   bool KeyRingReport::askUserToAcceptUnknownKey( const std::string & file, const std::string & id, const KeyContext & keycontext )
77   { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_UNKNOWNKEY ); }
78
79   bool KeyRingReport::askUserToAcceptVerificationFailed( const std::string & file, const PublicKey & key, const KeyContext & keycontext )
80   { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_VERIFICATION_FAILED ); }
81
82   bool KeyRingReport::askUserToAcceptPackageKey(const PublicKey &key_r, const KeyContext &keycontext_r)
83   {
84     UserData data(ACCEPT_PACKAGE_KEY_REQUEST);
85     data.set("PublicKey", key_r);
86     data.set("KeyContext", keycontext_r);
87     report(data);
88
89     if ( data.hasvalue("TrustKey") )
90       return data.get<bool>("TrustKey");
91     return false;
92   }
93
94   void KeyRingReport::reportNonImportedKeys(const std::set<Edition> &keys_r)
95   {
96     UserData data(KEYS_NOT_IMPORTED_REPORT);
97     data.set("Keys", keys_r);
98     report(data);
99   }
100
101   namespace
102   {
103     ///////////////////////////////////////////////////////////////////
104     /// \class CachedPublicKeyData
105     /// \brief Functor returning the keyrings data (cached).
106     /// \code
107     ///   const std::list<PublicKeyData> & cachedPublicKeyData( const Pathname & keyring );
108     /// \endcode
109     ///////////////////////////////////////////////////////////////////
110     struct CachedPublicKeyData : private base::NonCopyable
111     {
112       const std::list<PublicKeyData> & operator()( const Pathname & keyring_r ) const
113       { return getData( keyring_r ); }
114
115       void setDirty( const Pathname & keyring_r )
116       { _cacheMap[keyring_r].setDirty(); }
117
118     private:
119       struct Cache
120       {
121         Cache() {}
122
123         void setDirty()
124         {
125           _keyringK.reset();
126           _keyringP.reset();
127         }
128
129         void assertCache( const Pathname & keyring_r )
130         {
131           // .kbx since gpg2-2.1
132           if ( !_keyringK )
133             _keyringK.reset( new WatchFile( keyring_r/"pubring.kbx", WatchFile::NO_INIT ) );
134           if ( !_keyringP )
135             _keyringP.reset( new WatchFile( keyring_r/"pubring.gpg", WatchFile::NO_INIT ) );
136         }
137
138         bool hasChanged() const
139         {
140           bool k = _keyringK->hasChanged();     // be sure both files are checked
141           bool p = _keyringP->hasChanged();
142           return k || p;
143         }
144
145         std::list<PublicKeyData> _data;
146
147       private:
148         scoped_ptr<WatchFile> _keyringK;
149         scoped_ptr<WatchFile> _keyringP;
150       };
151
152       typedef std::map<Pathname,Cache> CacheMap;
153
154       const std::list<PublicKeyData> & getData( const Pathname & keyring_r ) const
155       {
156         Cache & cache( _cacheMap[keyring_r] );
157         // init new cache entry
158         cache.assertCache( keyring_r );
159         return getData( keyring_r, cache );
160       }
161
162       const std::list<PublicKeyData> & getData( const Pathname & keyring_r, Cache & cache_r ) const
163       {
164         if ( cache_r.hasChanged() ) {
165           shared_ptr<KeyManagerCtx> ctx = KeyManagerCtx::createForOpenPGP();
166           if (ctx) {
167             if (ctx->setHomedir(keyring_r)) {
168               std::list<PublicKeyData> foundKeys = ctx->listKeys();
169               cache_r._data.swap(foundKeys);
170             }
171           }
172           MIL << "Found keys: " << cache_r._data  << endl;
173         }
174         return cache_r._data;
175       }
176
177       mutable CacheMap _cacheMap;
178     };
179     ///////////////////////////////////////////////////////////////////
180   }
181
182   ///////////////////////////////////////////////////////////////////
183   //
184   //    CLASS NAME : KeyRing::Impl
185   //
186   /** KeyRing implementation. */
187   struct KeyRing::Impl
188   {
189     Impl( const Pathname & baseTmpDir )
190     : _trusted_tmp_dir( baseTmpDir, "zypp-trusted-kr" )
191     , _general_tmp_dir( baseTmpDir, "zypp-general-kr" )
192     , _base_dir( baseTmpDir )
193     {
194       MIL << "Current KeyRing::DefaultAccept: " << _keyRingDefaultAccept << endl;
195     }
196
197     void importKey( const PublicKey & key, bool trusted = false );
198     void multiKeyImport( const Pathname & keyfile_r, bool trusted_r = false );
199     void deleteKey( const std::string & id, bool trusted );
200
201     std::string readSignatureKeyId( const Pathname & signature );
202
203     bool isKeyTrusted( const std::string & id )
204     { return bool(publicKeyExists( id, trustedKeyRing() )); }
205     bool isKeyKnown( const std::string & id )
206     { return publicKeyExists( id, trustedKeyRing() ) || publicKeyExists( id, generalKeyRing() ); }
207
208     std::list<PublicKey> trustedPublicKeys()
209     { return publicKeys( trustedKeyRing() ); }
210     std::list<PublicKey> publicKeys()
211     { return publicKeys( generalKeyRing() ); }
212
213     const std::list<PublicKeyData> & trustedPublicKeyData()
214     { return publicKeyData( trustedKeyRing() ); }
215     const std::list<PublicKeyData> & publicKeyData()
216     { return publicKeyData( generalKeyRing() ); }
217
218     void dumpPublicKey( const std::string & id, bool trusted, std::ostream & stream )
219     { dumpPublicKey( id, ( trusted ? trustedKeyRing() : generalKeyRing() ), stream ); }
220
221     PublicKey exportPublicKey( const PublicKeyData & keyData )
222     { return exportKey( keyData, generalKeyRing() ); }
223     PublicKey exportTrustedPublicKey( const PublicKeyData & keyData )
224     { return exportKey( keyData, trustedKeyRing() ); }
225
226     bool verifyFileSignatureWorkflow( const Pathname & file, const std::string & filedesc, const Pathname & signature, bool & sigValid_r, const KeyContext & keycontext = KeyContext());
227
228     bool verifyFileSignature( const Pathname & file, const Pathname & signature )
229     { return verifyFile( file, signature, generalKeyRing() ); }
230     bool verifyFileTrustedSignature( const Pathname & file, const Pathname & signature )
231     { return verifyFile( file, signature, trustedKeyRing() ); }
232
233     PublicKeyData trustedPublicKeyExists( const std::string & id )
234     { return publicKeyExists(id, trustedKeyRing());}
235
236     bool provideAndImportKeyFromRepositoryWorkflow (const std::string &id_r , const RepoInfo &info_r );
237
238   private:
239     bool verifyFile( const Pathname & file, const Pathname & signature, const Pathname & keyring );
240     void importKey( const Pathname & keyfile, const Pathname & keyring );
241
242     PublicKey exportKey( const std::string & id, const Pathname & keyring );
243     PublicKey exportKey( const PublicKeyData & keyData, const Pathname & keyring );
244     PublicKey exportKey( const PublicKey & key, const Pathname & keyring )
245     { return exportKey( key.keyData(), keyring ); }
246
247     void dumpPublicKey( const std::string & id, const Pathname & keyring, std::ostream & stream );
248     filesystem::TmpFile dumpPublicKeyToTmp( const std::string & id, const Pathname & keyring );
249
250     void deleteKey( const std::string & id, const Pathname & keyring );
251
252     std::list<PublicKey> publicKeys( const Pathname & keyring);
253     const std::list<PublicKeyData> & publicKeyData( const Pathname & keyring )
254     { return cachedPublicKeyData( keyring ); }
255
256     /** Get \ref PublicKeyData for ID (\c false if ID is not found). */
257     PublicKeyData publicKeyExists( const std::string & id, const Pathname & keyring );
258
259     const Pathname generalKeyRing() const
260     { return _general_tmp_dir.path(); }
261     const Pathname trustedKeyRing() const
262     { return _trusted_tmp_dir.path(); }
263
264     // Used for trusted and untrusted keyrings
265     filesystem::TmpDir _trusted_tmp_dir;
266     filesystem::TmpDir _general_tmp_dir;
267     Pathname _base_dir;
268
269   private:
270     /** Functor returning the keyrings data (cached).
271      * \code
272      *  const std::list<PublicKeyData> & cachedPublicKeyData( const Pathname & keyring );
273      * \endcode
274      */
275     CachedPublicKeyData cachedPublicKeyData;
276   };
277   ///////////////////////////////////////////////////////////////////
278
279   namespace
280   {
281     /// Handle signal emission from within KeyRing::Impl::importKey
282     struct ImportKeyCBHelper
283     {
284       void operator()( const PublicKey & key_r )
285       {
286         try {
287           _rpmdbEmitSignal->trustedKeyAdded( key_r );
288           _emitSignal->trustedKeyAdded( key_r );
289         }
290         catch ( const Exception & excp )
291         {
292           ERR << "Could not import key into rpmdb: " << excp << endl;
293           // TODO: JobReport as hotfix for bsc#1057188; should bubble up and go through some callback
294           JobReport::error( excp.asUserHistory() );
295         }
296       }
297
298     private:
299       callback::SendReport<target::rpm::KeyRingSignals> _rpmdbEmitSignal;
300       callback::SendReport<KeyRingSignals>              _emitSignal;
301     };
302   } // namespace
303
304
305   void KeyRing::Impl::importKey( const PublicKey & key, bool trusted )
306   {
307     importKey( key.path(), trusted ? trustedKeyRing() : generalKeyRing() );
308     MIL << "Imported key " << key << " to " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
309
310     if ( trusted )
311     {
312       ImportKeyCBHelper emitSignal;
313       if ( key.hiddenKeys().empty() )
314       {
315         emitSignal( key );
316       }
317       else
318       {
319         // multiple keys: Export individual keys ascii armored to import in rpmdb
320         emitSignal( exportKey( key, trustedKeyRing() ) );
321         for ( const PublicKeyData & hkey : key.hiddenKeys() )
322           emitSignal( exportKey( hkey, trustedKeyRing() ) );
323       }
324     }
325   }
326
327   void KeyRing::Impl::multiKeyImport( const Pathname & keyfile_r, bool trusted_r )
328   {
329     importKey( keyfile_r, trusted_r ? trustedKeyRing() : generalKeyRing() );
330   }
331
332   void KeyRing::Impl::deleteKey( const std::string & id, bool trusted )
333   {
334     PublicKeyData keyDataToDel( publicKeyExists( id, trusted ? trustedKeyRing() : generalKeyRing() ) );
335     if ( ! keyDataToDel )
336     {
337       WAR << "Key to delete [" << id << "] is not in " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
338       return;
339     }
340     deleteKey( id, trusted ? trustedKeyRing() : generalKeyRing() );
341     MIL << "Deleted key [" << id << "] from " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
342
343     if ( trusted )
344     try {
345       PublicKey key( keyDataToDel );
346
347       callback::SendReport<target::rpm::KeyRingSignals> rpmdbEmitSignal;
348       rpmdbEmitSignal->trustedKeyRemoved( key );
349
350       callback::SendReport<KeyRingSignals> emitSignal;
351       emitSignal->trustedKeyRemoved( key );
352     }
353     catch ( const Exception & excp )
354     {
355       ERR << "Could not delete key from rpmmdb: " << excp << endl;
356       // TODO: JobReport as hotfix for bsc#1057188; should bubble up and go through some callback
357       JobReport::error( excp.asUserHistory() );
358     }
359   }
360
361   PublicKeyData KeyRing::Impl::publicKeyExists( const std::string & id, const Pathname & keyring )
362   {
363     PublicKeyData ret;
364     for ( const PublicKeyData & key : publicKeyData( keyring ) )
365     {
366       if ( key.providesKey( id ) )
367       {
368         ret = key;
369         break;
370       }
371     }
372     MIL << (ret ? "Found" : "No") << " key [" << id << "] in keyring " << keyring << endl;
373     return ret;
374   }
375
376   PublicKey KeyRing::Impl::exportKey( const PublicKeyData & keyData, const Pathname & keyring )
377   {
378     return PublicKey( dumpPublicKeyToTmp( keyData.id(), keyring ), keyData );
379   }
380
381   PublicKey KeyRing::Impl::exportKey( const std::string & id, const Pathname & keyring )
382   {
383     PublicKeyData keyData( publicKeyExists( id, keyring ) );
384     if ( keyData )
385       return PublicKey( dumpPublicKeyToTmp( keyData.id(), keyring ), keyData );
386
387     // Here: key not found
388     WAR << "No key [" << id << "] to export from " << keyring << endl;
389     return PublicKey();
390   }
391
392
393   void KeyRing::Impl::dumpPublicKey( const std::string & id, const Pathname & keyring, std::ostream & stream )
394   {
395     KeyManagerCtx::Ptr ctx = KeyManagerCtx::createForOpenPGP();
396     if (!ctx || !ctx->setHomedir(keyring))
397       return;
398     ctx->exportKey(id, stream);
399   }
400
401   filesystem::TmpFile KeyRing::Impl::dumpPublicKeyToTmp( const std::string & id, const Pathname & keyring )
402   {
403     filesystem::TmpFile tmpFile( _base_dir, "pubkey-"+id+"-" );
404     MIL << "Going to export key [" << id << "] from " << keyring << " to " << tmpFile.path() << endl;
405
406     std::ofstream os( tmpFile.path().c_str() );
407     dumpPublicKey( id, keyring, os );
408     os.close();
409     return tmpFile;
410   }
411
412   bool KeyRing::Impl::verifyFileSignatureWorkflow( const Pathname & file, const std::string & filedesc, const Pathname & signature, bool & sigValid_r, const KeyContext & context )
413   {
414     sigValid_r = false; // set true if signature is actually successfully validated!
415
416     callback::SendReport<KeyRingReport> report;
417     MIL << "Going to verify signature for " << filedesc << " ( " << file << " ) with " << signature << endl;
418
419     // if signature does not exists, ask user if he wants to accept unsigned file.
420     if( signature.empty() || (!PathInfo( signature ).isExist()) )
421     {
422       bool res = report->askUserToAcceptUnsignedFile( filedesc, context );
423       MIL << "askUserToAcceptUnsignedFile: " << res << endl;
424       return res;
425     }
426
427     // get the id of the signature (it might be a subkey id!)
428     std::string id = readSignatureKeyId( signature );
429
430     PublicKeyData foundKey;
431     Pathname whichKeyring;
432
433     if ( !id.empty() ) {
434
435       // does key exists in trusted keyring
436       PublicKeyData trustedKeyData( publicKeyExists( id, trustedKeyRing() ) );
437       if ( trustedKeyData )
438       {
439         MIL << "Key is trusted: " << trustedKeyData << endl;
440
441         // lets look if there is an updated key in the
442         // general keyring
443         PublicKeyData generalKeyData( publicKeyExists( id, generalKeyRing() ) );
444         if ( generalKeyData )
445         {
446           // bnc #393160: Comment #30: Compare at least the fingerprint
447           // in case an attacker created a key the the same id.
448           //
449           // FIXME: bsc#1008325: For keys using subkeys, we'd actually need
450           // to compare the subkey sets, to tell whether a key was updated.
451           // because created() remains unchanged if the primary key is not touched.
452           // For now we wait until a new subkey signs the data and treat it as a
453           //  new key (else part below).
454           if ( trustedKeyData.fingerprint() == generalKeyData.fingerprint()
455              && trustedKeyData.created() < generalKeyData.created() )
456           {
457             MIL << "Key was updated. Saving new version into trusted keyring: " << generalKeyData << endl;
458             importKey( exportKey( generalKeyData, generalKeyRing() ), true );
459             trustedKeyData = publicKeyExists( id, trustedKeyRing() ); // re-read: invalidated by import?
460           }
461         }
462
463         foundKey = trustedKeyData;
464         whichKeyring = trustedKeyRing();
465       }
466       else
467       {
468         PublicKeyData generalKeyData( publicKeyExists( id, generalKeyRing() ) );
469         if ( generalKeyData )
470         {
471           PublicKey key( exportKey( generalKeyData, generalKeyRing() ) );
472           MIL << "Key [" << id << "] " << key.name() << " is not trusted" << endl;
473
474           // ok the key is not trusted, ask the user to trust it or not
475           KeyRingReport::KeyTrust reply = report->askUserToAcceptKey( key, context );
476           if ( reply == KeyRingReport::KEY_TRUST_TEMPORARILY ||
477               reply == KeyRingReport::KEY_TRUST_AND_IMPORT )
478           {
479             MIL << "User wants to trust key [" << id << "] " << key.name() << endl;
480
481             if ( reply == KeyRingReport::KEY_TRUST_AND_IMPORT )
482             {
483               MIL << "User wants to import key [" << id << "] " << key.name() << endl;
484               importKey( key, true );
485               whichKeyring = trustedKeyRing();
486             }
487             else
488               whichKeyring = generalKeyRing();
489
490             foundKey = generalKeyData;
491           }
492           else
493           {
494             MIL << "User does not want to trust key [" << id << "] " << key.name() << endl;
495             return false;
496           }
497         }
498         else if ( ! context.empty() )
499         {
500           // try to find the key in the repository info
501           if ( provideAndImportKeyFromRepositoryWorkflow( id, context.repoInfo() ) ) {
502             whichKeyring = trustedKeyRing();
503             foundKey = PublicKeyData( publicKeyExists( id, trustedKeyRing() ) );
504           }
505         }
506       }
507     }
508
509     if ( foundKey ) {
510       // it exists, is trusted, does it validate?
511       report->infoVerify( filedesc, foundKey, context );
512       if ( verifyFile( file, signature, whichKeyring ) )
513       {
514         return (sigValid_r=true);       // signature is actually successfully validated!
515       }
516       else
517       {
518         bool res = report->askUserToAcceptVerificationFailed( filedesc, exportKey( foundKey, whichKeyring ), context );
519         MIL << "askUserToAcceptVerificationFailed: " << res << endl;
520         return res;
521       }
522     } else {
523       // signed with an unknown key...
524       MIL << "File [" << file << "] ( " << filedesc << " ) signed with unknown key [" << id << "]" << endl;
525       bool res = report->askUserToAcceptUnknownKey( filedesc, id, context );
526       MIL << "askUserToAcceptUnknownKey: " << res << endl;
527       return res;
528     }
529
530     return false;
531   }
532
533   bool KeyRing::Impl::provideAndImportKeyFromRepositoryWorkflow(const std::string &id_r, const RepoInfo &info_r)
534   {
535     if ( id_r.empty() )
536       return false;
537
538     const ZConfig &conf = ZConfig::instance();
539     Pathname cacheDir = conf.repoManagerRoot() / conf.pubkeyCachePath();
540
541     Pathname myKey = info_r.provideKey( id_r, cacheDir );
542     if ( myKey.empty()  )
543       // if we did not find any keys, there is no point in checking again, break
544       return false;
545
546     callback::SendReport<KeyRingReport> report;
547
548     PublicKey key;
549     try {
550       key = PublicKey( myKey );
551     } catch ( const Exception &e ) {
552       ZYPP_CAUGHT(e);
553       return false;
554     }
555
556     if ( !key.isValid() ) {
557       ERR << "Key [" << id_r << "] from cache: " << cacheDir << " is not valid" << endl;
558       return false;
559     }
560
561     MIL << "Key [" << id_r << "] " << key.name() << " loaded from cache" << endl;
562
563     KeyContext context;
564     context.setRepoInfo( info_r );
565     if ( ! report->askUserToAcceptPackageKey( key, context ) ) {
566       return false;
567     }
568
569     MIL << "User wants to import key [" << id_r << "] " << key.name() << " from cache" << endl;
570     try {
571       importKey( key, true );
572     } catch ( const KeyRingException &e ) {
573       ZYPP_CAUGHT(e);
574       ERR << "Failed to import key: "<<id_r;
575       return false;
576     }
577
578     return true;
579   }
580
581   std::list<PublicKey> KeyRing::Impl::publicKeys( const Pathname & keyring )
582   {
583     const std::list<PublicKeyData> & keys( publicKeyData( keyring ) );
584     std::list<PublicKey> ret;
585
586     for_( it, keys.begin(), keys.end() )
587     {
588       PublicKey key( exportKey( *it, keyring ) );
589       ret.push_back( key );
590       MIL << "Found key " << key << endl;
591     }
592     return ret;
593   }
594
595   void KeyRing::Impl::importKey( const Pathname & keyfile, const Pathname & keyring )
596   {
597     if ( ! PathInfo( keyfile ).isExist() )
598       // TranslatorExplanation first %s is key name, second is keyring name
599       ZYPP_THROW(KeyRingException( str::Format(_("Tried to import not existent key %s into keyring %s"))
600                                    % keyfile.asString()
601                                    % keyring.asString() ));
602
603     KeyManagerCtx::Ptr ctx = KeyManagerCtx::createForOpenPGP();
604     if(!ctx || !ctx->setHomedir(keyring))
605       ZYPP_THROW(KeyRingException(_("Failed to import key.")));
606
607     cachedPublicKeyData.setDirty( keyring );
608     if(!ctx->importKey(keyfile))
609       ZYPP_THROW(KeyRingException(_("Failed to import key.")));
610   }
611
612   void KeyRing::Impl::deleteKey( const std::string & id, const Pathname & keyring )
613   {
614     KeyManagerCtx::Ptr ctx = KeyManagerCtx::createForOpenPGP();
615     if(!ctx) {
616       ZYPP_THROW(KeyRingException(_("Failed to delete key.")));
617     }
618
619     if(!ctx->setHomedir(keyring)) {
620       ZYPP_THROW(KeyRingException(_("Failed to delete key.")));
621     }
622
623     if(!ctx->deleteKey(id)){
624       ZYPP_THROW(KeyRingException(_("Failed to delete key.")));
625     }
626
627     cachedPublicKeyData.setDirty( keyring );
628   }
629
630   std::string KeyRing::Impl::readSignatureKeyId( const Pathname & signature )
631   {
632     if ( ! PathInfo( signature ).isFile() )
633       ZYPP_THROW(KeyRingException( str::Format(_("Signature file %s not found")) % signature.asString() ));
634
635     MIL << "Determining key id of signature " << signature << endl;
636
637     KeyManagerCtx::Ptr ctx = KeyManagerCtx::createForOpenPGP();
638     if(!ctx) {
639       return std::string();
640     }
641
642     std::list<std::string> fprs = ctx->readSignatureFingerprints(signature);
643     if (fprs.size()) {
644       std::string &id = fprs.back();
645       MIL << "Determined key id [" << id << "] for signature " << signature << endl;
646       return id;
647     }
648     return std::string();
649   }
650
651   bool KeyRing::Impl::verifyFile( const Pathname & file, const Pathname & signature, const Pathname & keyring )
652   {
653     KeyManagerCtx::Ptr ctx = KeyManagerCtx::createForOpenPGP();
654     if (!ctx || !ctx->setHomedir(keyring))
655       return false;
656
657     return ctx->verify(file, signature);
658   }
659
660   ///////////////////////////////////////////////////////////////////
661
662   ///////////////////////////////////////////////////////////////////
663   //
664   //    CLASS NAME : KeyRing
665   //
666   ///////////////////////////////////////////////////////////////////
667
668   KeyRing::KeyRing( const Pathname & baseTmpDir )
669   : _pimpl( new Impl( baseTmpDir ) )
670   {}
671
672   KeyRing::~KeyRing()
673   {}
674
675
676   void KeyRing::importKey( const PublicKey & key, bool trusted )
677   { _pimpl->importKey( key, trusted ); }
678
679   void KeyRing::multiKeyImport( const Pathname & keyfile_r, bool trusted_r )
680   { _pimpl->multiKeyImport( keyfile_r, trusted_r ); }
681
682   std::string KeyRing::readSignatureKeyId( const Pathname & signature )
683   { return _pimpl->readSignatureKeyId( signature ); }
684
685   void KeyRing::deleteKey( const std::string & id, bool trusted )
686   { _pimpl->deleteKey( id, trusted ); }
687
688   std::list<PublicKey> KeyRing::publicKeys()
689   { return _pimpl->publicKeys(); }
690
691   std:: list<PublicKey> KeyRing::trustedPublicKeys()
692   { return _pimpl->trustedPublicKeys(); }
693
694   std::list<PublicKeyData> KeyRing::publicKeyData()
695   { return _pimpl->publicKeyData(); }
696
697   std::list<PublicKeyData> KeyRing::trustedPublicKeyData()
698   { return _pimpl->trustedPublicKeyData(); }
699
700   PublicKeyData KeyRing::trustedPublicKeyData(const std::string &id_r)
701   { return _pimpl->trustedPublicKeyExists( id_r ); }
702
703   bool KeyRing::verifyFileSignatureWorkflow( const Pathname & file, const std::string & filedesc, const Pathname & signature, bool & sigValid_r, const KeyContext & keycontext )
704   { return _pimpl->verifyFileSignatureWorkflow( file, filedesc, signature, sigValid_r, keycontext ); }
705
706   bool KeyRing::verifyFileSignatureWorkflow( const Pathname & file, const std::string filedesc, const Pathname & signature, const KeyContext & keycontext )
707   { bool unused; return _pimpl->verifyFileSignatureWorkflow( file, filedesc, signature, unused, keycontext ); }
708
709   bool KeyRing::verifyFileSignature( const Pathname & file, const Pathname & signature )
710   { return _pimpl->verifyFileSignature( file, signature ); }
711
712   bool KeyRing::verifyFileTrustedSignature( const Pathname & file, const Pathname & signature )
713   { return _pimpl->verifyFileTrustedSignature( file, signature ); }
714
715   bool KeyRing::provideAndImportKeyFromRepositoryWorkflow(const std::string &id, const RepoInfo &info)
716   {
717     return _pimpl->provideAndImportKeyFromRepositoryWorkflow( id, info );
718   }
719
720   void KeyRing::dumpPublicKey( const std::string & id, bool trusted, std::ostream & stream )
721   { _pimpl->dumpPublicKey( id, trusted, stream ); }
722
723   PublicKey KeyRing::exportPublicKey( const PublicKeyData & keyData )
724   { return _pimpl->exportPublicKey( keyData ); }
725
726   PublicKey KeyRing::exportTrustedPublicKey( const PublicKeyData & keyData )
727   { return _pimpl->exportTrustedPublicKey( keyData ); }
728
729   bool KeyRing::isKeyTrusted( const std::string & id )
730   { return _pimpl->isKeyTrusted( id ); }
731
732   bool KeyRing::isKeyKnown( const std::string & id )
733   { return _pimpl->isKeyKnown( id ); }
734
735   /////////////////////////////////////////////////////////////////
736 } // namespace zypp
737 ///////////////////////////////////////////////////////////////////