Fix Werrors with GCC-14.1.0
[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           cache_r._data = KeyManagerCtx::createForOpenPGP( keyring_r ).listKeys();
166           MIL << "Found keys: " << cache_r._data  << endl;
167         }
168         return cache_r._data;
169       }
170
171       mutable CacheMap _cacheMap;
172     };
173     ///////////////////////////////////////////////////////////////////
174   }
175
176   ///////////////////////////////////////////////////////////////////
177   //
178   //    CLASS NAME : KeyRing::Impl
179   //
180   /** KeyRing implementation. */
181   struct KeyRing::Impl
182   {
183     Impl( const Pathname & baseTmpDir )
184     : _trusted_tmp_dir( baseTmpDir, "zypp-trusted-kr" )
185     , _general_tmp_dir( baseTmpDir, "zypp-general-kr" )
186     , _base_dir( baseTmpDir )
187     {
188       MIL << "Current KeyRing::DefaultAccept: " << _keyRingDefaultAccept << endl;
189     }
190
191     void importKey( const PublicKey & key, bool trusted = false );
192     void multiKeyImport( const Pathname & keyfile_r, bool trusted_r = false );
193     void deleteKey( const std::string & id, bool trusted );
194
195     std::string readSignatureKeyId( const Pathname & signature );
196
197     bool isKeyTrusted( const std::string & id )
198     { return bool(publicKeyExists( id, trustedKeyRing() )); }
199     bool isKeyKnown( const std::string & id )
200     { return publicKeyExists( id, trustedKeyRing() ) || publicKeyExists( id, generalKeyRing() ); }
201
202     std::list<PublicKey> trustedPublicKeys()
203     { return publicKeys( trustedKeyRing() ); }
204     std::list<PublicKey> publicKeys()
205     { return publicKeys( generalKeyRing() ); }
206
207     const std::list<PublicKeyData> & trustedPublicKeyData()
208     { return publicKeyData( trustedKeyRing() ); }
209     const std::list<PublicKeyData> & publicKeyData()
210     { return publicKeyData( generalKeyRing() ); }
211
212     void dumpPublicKey( const std::string & id, bool trusted, std::ostream & stream )
213     { dumpPublicKey( id, ( trusted ? trustedKeyRing() : generalKeyRing() ), stream ); }
214
215     PublicKey exportPublicKey( const PublicKeyData & keyData )
216     { return exportKey( keyData, generalKeyRing() ); }
217     PublicKey exportTrustedPublicKey( const PublicKeyData & keyData )
218     { return exportKey( keyData, trustedKeyRing() ); }
219
220     bool verifyFileSignatureWorkflow( const Pathname & file, const std::string & filedesc, const Pathname & signature, bool & sigValid_r, const KeyContext & keycontext = KeyContext());
221
222     bool verifyFileSignature( const Pathname & file, const Pathname & signature )
223     { return verifyFile( file, signature, generalKeyRing() ); }
224     bool verifyFileTrustedSignature( const Pathname & file, const Pathname & signature )
225     { return verifyFile( file, signature, trustedKeyRing() ); }
226
227     PublicKeyData trustedPublicKeyExists( const std::string & id )
228     { return publicKeyExists(id, trustedKeyRing());}
229
230     bool provideAndImportKeyFromRepositoryWorkflow (const std::string &id_r , const RepoInfo &info_r );
231
232   private:
233     bool verifyFile( const Pathname & file, const Pathname & signature, const Pathname & keyring );
234     void importKey( const Pathname & keyfile, const Pathname & keyring );
235
236     PublicKey exportKey( const std::string & id, const Pathname & keyring );
237     PublicKey exportKey( const PublicKeyData & keyData, const Pathname & keyring );
238     PublicKey exportKey( const PublicKey & key, const Pathname & keyring )
239     { return exportKey( key.keyData(), keyring ); }
240
241     void dumpPublicKey( const std::string & id, const Pathname & keyring, std::ostream & stream );
242     filesystem::TmpFile dumpPublicKeyToTmp( const std::string & id, const Pathname & keyring );
243
244     void deleteKey( const std::string & id, const Pathname & keyring );
245
246     std::list<PublicKey> publicKeys( const Pathname & keyring);
247     const std::list<PublicKeyData> & publicKeyData( const Pathname & keyring )
248     { return cachedPublicKeyData( keyring ); }
249
250     /** Get \ref PublicKeyData for ID (\c false if ID is not found). */
251     PublicKeyData publicKeyExists( const std::string & id, const Pathname & keyring );
252
253     const Pathname generalKeyRing() const
254     { return _general_tmp_dir.path(); }
255     const Pathname trustedKeyRing() const
256     { return _trusted_tmp_dir.path(); }
257
258     // Used for trusted and untrusted keyrings
259     filesystem::TmpDir _trusted_tmp_dir;
260     filesystem::TmpDir _general_tmp_dir;
261     Pathname _base_dir;
262
263   private:
264     /** Functor returning the keyrings data (cached).
265      * \code
266      *  const std::list<PublicKeyData> & cachedPublicKeyData( const Pathname & keyring );
267      * \endcode
268      */
269     CachedPublicKeyData cachedPublicKeyData;
270   };
271   ///////////////////////////////////////////////////////////////////
272
273   namespace
274   {
275     /// Handle signal emission from within KeyRing::Impl::importKey
276     struct ImportKeyCBHelper
277     {
278       void operator()( const PublicKey & key_r )
279       {
280         try {
281           _rpmdbEmitSignal->trustedKeyAdded( key_r );
282           _emitSignal->trustedKeyAdded( key_r );
283         }
284         catch ( const Exception & excp )
285         {
286           ERR << "Could not import key into rpmdb: " << excp << endl;
287           // TODO: JobReport as hotfix for bsc#1057188; should bubble up and go through some callback
288           JobReport::error( excp.asUserHistory() );
289         }
290       }
291
292     private:
293       callback::SendReport<target::rpm::KeyRingSignals> _rpmdbEmitSignal;
294       callback::SendReport<KeyRingSignals>              _emitSignal;
295     };
296   } // namespace
297
298
299   void KeyRing::Impl::importKey( const PublicKey & key, bool trusted )
300   {
301     importKey( key.path(), trusted ? trustedKeyRing() : generalKeyRing() );
302     MIL << "Imported key " << key << " to " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
303
304     if ( trusted )
305     {
306       ImportKeyCBHelper emitSignal;
307       if ( key.hiddenKeys().empty() )
308       {
309         emitSignal( key );
310       }
311       else
312       {
313         // multiple keys: Export individual keys ascii armored to import in rpmdb
314         emitSignal( exportKey( key, trustedKeyRing() ) );
315         for ( const PublicKeyData & hkey : key.hiddenKeys() )
316           emitSignal( exportKey( hkey, trustedKeyRing() ) );
317       }
318     }
319   }
320
321   void KeyRing::Impl::multiKeyImport( const Pathname & keyfile_r, bool trusted_r )
322   {
323     importKey( keyfile_r, trusted_r ? trustedKeyRing() : generalKeyRing() );
324   }
325
326   void KeyRing::Impl::deleteKey( const std::string & id, bool trusted )
327   {
328     PublicKeyData keyDataToDel( publicKeyExists( id, trusted ? trustedKeyRing() : generalKeyRing() ) );
329     if ( ! keyDataToDel )
330     {
331       WAR << "Key to delete [" << id << "] is not in " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
332       return;
333     }
334     deleteKey( id, trusted ? trustedKeyRing() : generalKeyRing() );
335     MIL << "Deleted key [" << id << "] from " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
336
337     if ( trusted )
338     try {
339       PublicKey key( keyDataToDel );
340
341       callback::SendReport<target::rpm::KeyRingSignals> rpmdbEmitSignal;
342       rpmdbEmitSignal->trustedKeyRemoved( key );
343
344       callback::SendReport<KeyRingSignals> emitSignal;
345       emitSignal->trustedKeyRemoved( key );
346     }
347     catch ( const Exception & excp )
348     {
349       ERR << "Could not delete key from rpmmdb: " << excp << endl;
350       // TODO: JobReport as hotfix for bsc#1057188; should bubble up and go through some callback
351       JobReport::error( excp.asUserHistory() );
352     }
353   }
354
355   PublicKeyData KeyRing::Impl::publicKeyExists( const std::string & id, const Pathname & keyring )
356   {
357     PublicKeyData ret;
358     for ( const PublicKeyData & key : publicKeyData( keyring ) )
359     {
360       if ( key.providesKey( id ) )
361       {
362         ret = key;
363         break;
364       }
365     }
366     MIL << (ret ? "Found" : "No") << " key [" << id << "] in keyring " << keyring << endl;
367     return ret;
368   }
369
370   PublicKey KeyRing::Impl::exportKey( const PublicKeyData & keyData, const Pathname & keyring )
371   {
372     return PublicKey( dumpPublicKeyToTmp( keyData.id(), keyring ), keyData );
373   }
374
375   PublicKey KeyRing::Impl::exportKey( const std::string & id, const Pathname & keyring )
376   {
377     PublicKeyData keyData( publicKeyExists( id, keyring ) );
378     if ( keyData )
379       return PublicKey( dumpPublicKeyToTmp( keyData.id(), keyring ), keyData );
380
381     // Here: key not found
382     WAR << "No key [" << id << "] to export from " << keyring << endl;
383     return PublicKey();
384   }
385
386
387   void KeyRing::Impl::dumpPublicKey( const std::string & id, const Pathname & keyring, std::ostream & stream )
388   {
389     KeyManagerCtx::createForOpenPGP( keyring ).exportKey(id, stream);
390   }
391
392   filesystem::TmpFile KeyRing::Impl::dumpPublicKeyToTmp( const std::string & id, const Pathname & keyring )
393   {
394     filesystem::TmpFile tmpFile( _base_dir, "pubkey-"+id+"-" );
395     MIL << "Going to export key [" << id << "] from " << keyring << " to " << tmpFile.path() << endl;
396
397     std::ofstream os( tmpFile.path().c_str() );
398     dumpPublicKey( id, keyring, os );
399     os.close();
400     return tmpFile;
401   }
402
403   bool KeyRing::Impl::verifyFileSignatureWorkflow( const Pathname & file, const std::string & filedesc, const Pathname & signature, bool & sigValid_r, const KeyContext & context )
404   {
405     sigValid_r = false; // set true if signature is actually successfully validated!
406
407     callback::SendReport<KeyRingReport> report;
408     MIL << "Going to verify signature for " << filedesc << " ( " << file << " ) with " << signature << endl;
409
410     // if signature does not exists, ask user if he wants to accept unsigned file.
411     if( signature.empty() || (!PathInfo( signature ).isExist()) )
412     {
413       bool res = report->askUserToAcceptUnsignedFile( filedesc, context );
414       MIL << "askUserToAcceptUnsignedFile: " << res << endl;
415       return res;
416     }
417
418     // get the id of the signature (it might be a subkey id!)
419     std::string id = readSignatureKeyId( signature );
420
421     PublicKeyData foundKey;
422     Pathname whichKeyring;
423
424     if ( !id.empty() ) {
425
426       // does key exists in trusted keyring
427       PublicKeyData trustedKeyData( publicKeyExists( id, trustedKeyRing() ) );
428       if ( trustedKeyData )
429       {
430         MIL << "Key is trusted: " << trustedKeyData << endl;
431
432         // lets look if there is an updated key in the
433         // general keyring
434         PublicKeyData generalKeyData( publicKeyExists( id, generalKeyRing() ) );
435         if ( generalKeyData )
436         {
437           // bnc #393160: Comment #30: Compare at least the fingerprint
438           // in case an attacker created a key the the same id.
439           //
440           // FIXME: bsc#1008325: For keys using subkeys, we'd actually need
441           // to compare the subkey sets, to tell whether a key was updated.
442           // because created() remains unchanged if the primary key is not touched.
443           // For now we wait until a new subkey signs the data and treat it as a
444           //  new key (else part below).
445           if ( trustedKeyData.fingerprint() == generalKeyData.fingerprint()
446              && trustedKeyData.created() < generalKeyData.created() )
447           {
448             MIL << "Key was updated. Saving new version into trusted keyring: " << generalKeyData << endl;
449             importKey( exportKey( generalKeyData, generalKeyRing() ), true );
450             trustedKeyData = publicKeyExists( id, trustedKeyRing() ); // re-read: invalidated by import?
451           }
452         }
453
454         foundKey = trustedKeyData;
455         whichKeyring = trustedKeyRing();
456       }
457       else
458       {
459         PublicKeyData generalKeyData( publicKeyExists( id, generalKeyRing() ) );
460         if ( generalKeyData )
461         {
462           PublicKey key( exportKey( generalKeyData, generalKeyRing() ) );
463           MIL << "Key [" << id << "] " << key.name() << " is not trusted" << endl;
464
465           // ok the key is not trusted, ask the user to trust it or not
466           KeyRingReport::KeyTrust reply = report->askUserToAcceptKey( key, context );
467           if ( reply == KeyRingReport::KEY_TRUST_TEMPORARILY ||
468               reply == KeyRingReport::KEY_TRUST_AND_IMPORT )
469           {
470             MIL << "User wants to trust key [" << id << "] " << key.name() << endl;
471
472             if ( reply == KeyRingReport::KEY_TRUST_AND_IMPORT )
473             {
474               MIL << "User wants to import key [" << id << "] " << key.name() << endl;
475               importKey( key, true );
476               whichKeyring = trustedKeyRing();
477             }
478             else
479               whichKeyring = generalKeyRing();
480
481             foundKey = generalKeyData;
482           }
483           else
484           {
485             MIL << "User does not want to trust key [" << id << "] " << key.name() << endl;
486             return false;
487           }
488         }
489         else if ( ! context.empty() )
490         {
491           // try to find the key in the repository info
492           if ( provideAndImportKeyFromRepositoryWorkflow( id, context.repoInfo() ) ) {
493             whichKeyring = trustedKeyRing();
494             foundKey = PublicKeyData( publicKeyExists( id, trustedKeyRing() ) );
495           }
496         }
497       }
498     }
499
500     if ( foundKey ) {
501       // it exists, is trusted, does it validate?
502       report->infoVerify( filedesc, foundKey, context );
503       if ( verifyFile( file, signature, whichKeyring ) )
504       {
505         return (sigValid_r=true);       // signature is actually successfully validated!
506       }
507       else
508       {
509         bool res = report->askUserToAcceptVerificationFailed( filedesc, exportKey( foundKey, whichKeyring ), context );
510         MIL << "askUserToAcceptVerificationFailed: " << res << endl;
511         return res;
512       }
513     } else {
514       // signed with an unknown key...
515       MIL << "File [" << file << "] ( " << filedesc << " ) signed with unknown key [" << id << "]" << endl;
516       bool res = report->askUserToAcceptUnknownKey( filedesc, id, context );
517       MIL << "askUserToAcceptUnknownKey: " << res << endl;
518       return res;
519     }
520
521     return false;
522   }
523
524   bool KeyRing::Impl::provideAndImportKeyFromRepositoryWorkflow(const std::string &id_r, const RepoInfo &info_r)
525   {
526     if ( id_r.empty() )
527       return false;
528
529     const ZConfig &conf = ZConfig::instance();
530     Pathname cacheDir = conf.repoManagerRoot() / conf.pubkeyCachePath();
531
532     Pathname myKey = info_r.provideKey( id_r, cacheDir );
533     if ( myKey.empty()  )
534       // if we did not find any keys, there is no point in checking again, break
535       return false;
536
537     callback::SendReport<KeyRingReport> report;
538
539     PublicKey key;
540     try {
541       key = PublicKey( myKey );
542     } catch ( const Exception &e ) {
543       ZYPP_CAUGHT(e);
544       return false;
545     }
546
547     if ( !key.isValid() ) {
548       ERR << "Key [" << id_r << "] from cache: " << cacheDir << " is not valid" << endl;
549       return false;
550     }
551
552     MIL << "Key [" << id_r << "] " << key.name() << " loaded from cache" << endl;
553
554     KeyContext context;
555     context.setRepoInfo( info_r );
556     if ( ! report->askUserToAcceptPackageKey( key, context ) ) {
557       return false;
558     }
559
560     MIL << "User wants to import key [" << id_r << "] " << key.name() << " from cache" << endl;
561     try {
562       importKey( key, true );
563     } catch ( const KeyRingException &e ) {
564       ZYPP_CAUGHT(e);
565       ERR << "Failed to import key: "<<id_r;
566       return false;
567     }
568
569     return true;
570   }
571
572   std::list<PublicKey> KeyRing::Impl::publicKeys( const Pathname & keyring )
573   {
574     const std::list<PublicKeyData> & keys( publicKeyData( keyring ) );
575     std::list<PublicKey> ret;
576
577     for_( it, keys.begin(), keys.end() )
578     {
579       PublicKey key( exportKey( *it, keyring ) );
580       ret.push_back( key );
581       MIL << "Found key " << key << endl;
582     }
583     return ret;
584   }
585
586   void KeyRing::Impl::importKey( const Pathname & keyfile, const Pathname & keyring )
587   {
588     if ( ! PathInfo( keyfile ).isExist() )
589       // TranslatorExplanation first %s is key name, second is keyring name
590       ZYPP_THROW(KeyRingException( str::Format(_("Tried to import not existent key %s into keyring %s"))
591                                    % keyfile.asString()
592                                    % keyring.asString() ));
593
594     cachedPublicKeyData.setDirty( keyring );
595     if ( ! KeyManagerCtx::createForOpenPGP( keyring ).importKey( keyfile ) )
596       ZYPP_THROW(KeyRingException(_("Failed to import key.")));
597   }
598
599   void KeyRing::Impl::deleteKey( const std::string & id, const Pathname & keyring )
600   {
601     cachedPublicKeyData.setDirty( keyring );
602     if ( ! KeyManagerCtx::createForOpenPGP( keyring ).deleteKey( id ) )
603       ZYPP_THROW(KeyRingException(_("Failed to delete key.")));
604   }
605
606   std::string KeyRing::Impl::readSignatureKeyId( const Pathname & signature )
607   {
608     if ( ! PathInfo( signature ).isFile() )
609       ZYPP_THROW(KeyRingException( str::Format(_("Signature file %s not found")) % signature.asString() ));
610
611     MIL << "Determining key id of signature " << signature << endl;
612
613     std::list<std::string> fprs = KeyManagerCtx::createForOpenPGP().readSignatureFingerprints( signature );
614     if ( ! fprs.empty() ) {
615       std::string &id = fprs.back();
616       MIL << "Determined key id [" << id << "] for signature " << signature << endl;
617       return id;
618     }
619     return std::string();
620   }
621
622   bool KeyRing::Impl::verifyFile( const Pathname & file, const Pathname & signature, const Pathname & keyring )
623   {
624     return KeyManagerCtx::createForOpenPGP( keyring ).verify( file, signature );
625   }
626
627   ///////////////////////////////////////////////////////////////////
628
629   ///////////////////////////////////////////////////////////////////
630   //
631   //    CLASS NAME : KeyRing
632   //
633   ///////////////////////////////////////////////////////////////////
634
635   KeyRing::KeyRing( const Pathname & baseTmpDir )
636   : _pimpl( new Impl( baseTmpDir ) )
637   {}
638
639   KeyRing::~KeyRing()
640   {}
641
642
643   void KeyRing::importKey( const PublicKey & key, bool trusted )
644   { _pimpl->importKey( key, trusted ); }
645
646   void KeyRing::multiKeyImport( const Pathname & keyfile_r, bool trusted_r )
647   { _pimpl->multiKeyImport( keyfile_r, trusted_r ); }
648
649   std::string KeyRing::readSignatureKeyId( const Pathname & signature )
650   { return _pimpl->readSignatureKeyId( signature ); }
651
652   void KeyRing::deleteKey( const std::string & id, bool trusted )
653   { _pimpl->deleteKey( id, trusted ); }
654
655   std::list<PublicKey> KeyRing::publicKeys()
656   { return _pimpl->publicKeys(); }
657
658   std:: list<PublicKey> KeyRing::trustedPublicKeys()
659   { return _pimpl->trustedPublicKeys(); }
660
661   std::list<PublicKeyData> KeyRing::publicKeyData()
662   { return _pimpl->publicKeyData(); }
663
664   std::list<PublicKeyData> KeyRing::trustedPublicKeyData()
665   { return _pimpl->trustedPublicKeyData(); }
666
667   PublicKeyData KeyRing::trustedPublicKeyData(const std::string &id_r)
668   { return _pimpl->trustedPublicKeyExists( id_r ); }
669
670   bool KeyRing::verifyFileSignatureWorkflow( const Pathname & file, const std::string & filedesc, const Pathname & signature, bool & sigValid_r, const KeyContext & keycontext )
671   { return _pimpl->verifyFileSignatureWorkflow( file, filedesc, signature, sigValid_r, keycontext ); }
672
673   bool KeyRing::verifyFileSignatureWorkflow( const Pathname & file, const std::string filedesc, const Pathname & signature, const KeyContext & keycontext )
674   { bool unused; return _pimpl->verifyFileSignatureWorkflow( file, filedesc, signature, unused, keycontext ); }
675
676   bool KeyRing::verifyFileSignature( const Pathname & file, const Pathname & signature )
677   { return _pimpl->verifyFileSignature( file, signature ); }
678
679   bool KeyRing::verifyFileTrustedSignature( const Pathname & file, const Pathname & signature )
680   { return _pimpl->verifyFileTrustedSignature( file, signature ); }
681
682   bool KeyRing::provideAndImportKeyFromRepositoryWorkflow(const std::string &id, const RepoInfo &info)
683   {
684     return _pimpl->provideAndImportKeyFromRepositoryWorkflow( id, info );
685   }
686
687   void KeyRing::dumpPublicKey( const std::string & id, bool trusted, std::ostream & stream )
688   { _pimpl->dumpPublicKey( id, trusted, stream ); }
689
690   PublicKey KeyRing::exportPublicKey( const PublicKeyData & keyData )
691   { return _pimpl->exportPublicKey( keyData ); }
692
693   PublicKey KeyRing::exportTrustedPublicKey( const PublicKeyData & keyData )
694   { return _pimpl->exportTrustedPublicKey( keyData ); }
695
696   bool KeyRing::isKeyTrusted( const std::string & id )
697   { return _pimpl->isKeyTrusted( id ); }
698
699   bool KeyRing::isKeyKnown( const std::string & id )
700   { return _pimpl->isKeyKnown( id ); }
701
702   /////////////////////////////////////////////////////////////////
703 } // namespace zypp
704 ///////////////////////////////////////////////////////////////////