build require libproxy
[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 <boost/format.hpp>
19
20 #include "zypp/TmpPath.h"
21 #include "zypp/ZYppFactory.h"
22 #include "zypp/ZYpp.h"
23
24 #include "zypp/base/Logger.h"
25 #include "zypp/base/IOStream.h"
26 #include "zypp/base/String.h"
27 #include "zypp/base/Regex.h"
28 #include "zypp/base/Gettext.h"
29 #include "zypp/PathInfo.h"
30 #include "zypp/KeyRing.h"
31 #include "zypp/ExternalProgram.h"
32 #include "zypp/TmpPath.h"
33
34 using namespace std;
35 using namespace zypp::filesystem;
36
37 #undef  ZYPP_BASE_LOGGER_LOGGROUP
38 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::KeyRing"
39
40 #define GPG_BINARY "/usr/bin/gpg2"
41
42 ///////////////////////////////////////////////////////////////////
43 namespace zypp
44 { /////////////////////////////////////////////////////////////////
45
46   IMPL_PTR_TYPE(KeyRing);
47
48   namespace
49   {
50     KeyRing::DefaultAccept _keyRingDefaultAccept( KeyRing::ACCEPT_NOTHING );
51   }
52
53   KeyRing::DefaultAccept KeyRing::defaultAccept()
54   { return _keyRingDefaultAccept; }
55
56   void KeyRing::setDefaultAccept( DefaultAccept value_r )
57   {
58     MIL << "Set new KeyRing::DefaultAccept: " << value_r << endl;
59     _keyRingDefaultAccept = value_r;
60   }
61
62   bool KeyRingReport::askUserToAcceptUnsignedFile( const string &file, const KeyContext &keycontext )
63   { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_UNSIGNED_FILE ); }
64
65   KeyRingReport::KeyTrust
66   KeyRingReport::askUserToAcceptKey( const PublicKey &key, const KeyContext &keycontext )
67   {
68     if ( _keyRingDefaultAccept.testFlag( KeyRing::TRUST_KEY_TEMPORARILY ) )
69       return KEY_TRUST_TEMPORARILY;
70     if ( _keyRingDefaultAccept.testFlag( KeyRing::TRUST_AND_IMPORT_KEY ) )
71       return KEY_TRUST_AND_IMPORT;
72     return KEY_DONT_TRUST;
73   }
74
75   bool KeyRingReport::askUserToAcceptUnknownKey( const string &file, const string &id, const KeyContext &keycontext )
76   { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_UNKNOWNKEY ); }
77
78   bool KeyRingReport::askUserToAcceptVerificationFailed( const string &file, const PublicKey &key, const KeyContext &keycontext )
79   { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_VERIFICATION_FAILED ); }
80
81   ///////////////////////////////////////////////////////////////////
82   //
83   //    CLASS NAME : KeyRing::Impl
84   //
85   /** KeyRing implementation. */
86   struct KeyRing::Impl
87   {
88     Impl( const Pathname & baseTmpDir )
89     : _trusted_tmp_dir( baseTmpDir, "zypp-trusted-kr" )
90     , _general_tmp_dir( baseTmpDir, "zypp-general-kr" )
91     , _base_dir( baseTmpDir )
92     {
93       MIL << "Current KeyRing::DefaultAccept: " << _keyRingDefaultAccept << endl;
94     }
95
96     void importKey( const PublicKey &key, bool trusted = false);
97     void multiKeyImport( const Pathname & keyfile_r, bool trusted_r = false);
98     void deleteKey( const string &id, bool trusted );
99
100     string readSignatureKeyId( const Pathname &signature );
101
102     bool isKeyTrusted( const string &id);
103     bool isKeyKnown( const string &id );
104
105     list<PublicKey> trustedPublicKeys();
106     list<PublicKey> publicKeys();
107
108     list<string> trustedPublicKeyIds();
109     list<string> publicKeyIds();
110
111     void dumpPublicKey( const string &id, bool trusted, ostream &stream );
112
113     bool verifyFileSignatureWorkflow(
114         const Pathname &file,
115         const string filedesc,
116         const Pathname &signature,
117         const KeyContext &keycontext = KeyContext());
118
119     bool verifyFileSignature( const Pathname &file, const Pathname &signature);
120     bool verifyFileTrustedSignature( const Pathname &file, const Pathname &signature);
121   private:
122     //mutable map<Locale, string> translations;
123     bool verifyFile( const Pathname &file, const Pathname &signature, const Pathname &keyring);
124     void importKey( const Pathname &keyfile, const Pathname &keyring);
125     PublicKey exportKey( string id, const Pathname &keyring);
126     void dumpPublicKey( const string &id, const Pathname &keyring, ostream &stream );
127     void deleteKey( const string &id, const Pathname &keyring );
128
129     list<PublicKey> publicKeys(const Pathname &keyring);
130     list<string> publicKeyIds(const Pathname &keyring);
131
132     bool publicKeyExists( string id, const Pathname &keyring);
133
134     const Pathname generalKeyRing() const;
135     const Pathname trustedKeyRing() const;
136
137     // Used for trusted and untrusted keyrings
138     TmpDir _trusted_tmp_dir;
139     TmpDir _general_tmp_dir;
140     Pathname _base_dir;
141   public:
142     /** Offer default Impl. */
143     static shared_ptr<Impl> nullimpl()
144     {
145       static shared_ptr<Impl> _nullimpl( new Impl( TmpPath::defaultLocation() ) );
146       return _nullimpl;
147     }
148
149   private:
150     friend Impl * rwcowClone<Impl>( const Impl * rhs );
151     /** clone for RWCOW_pointer */
152     Impl * clone() const
153     { return new Impl( *this ); }
154   };
155
156
157   const Pathname KeyRing::Impl::generalKeyRing() const
158   {
159     return _general_tmp_dir.path();
160   }
161
162   const Pathname KeyRing::Impl::trustedKeyRing() const
163   {
164     return _trusted_tmp_dir.path();
165   }
166
167   void KeyRing::Impl::importKey( const PublicKey &key, bool trusted)
168   {
169     callback::SendReport<target::rpm::KeyRingSignals> rpmdbEmitSignal;
170     callback::SendReport<KeyRingSignals> emitSignal;
171
172     importKey( key.path(), trusted ? trustedKeyRing() : generalKeyRing() );
173
174     if ( trusted )
175     {
176       rpmdbEmitSignal->trustedKeyAdded( key );
177       emitSignal->trustedKeyAdded( key );
178     }
179   }
180
181   void KeyRing::Impl::multiKeyImport( const Pathname & keyfile_r, bool trusted_r )
182   {
183     importKey( keyfile_r, trusted_r ? trustedKeyRing() : generalKeyRing() );
184   }
185
186   void KeyRing::Impl::deleteKey( const string &id, bool trusted)
187   {
188     PublicKey key;
189
190     if (trusted)
191     {
192         key = exportKey(id, trustedKeyRing());
193     }
194
195     deleteKey( id, trusted ? trustedKeyRing() : generalKeyRing() );
196
197     if ( trusted )
198     {
199       callback::SendReport<target::rpm::KeyRingSignals> rpmdbEmitSignal;
200       callback::SendReport<KeyRingSignals> emitSignal;
201
202       rpmdbEmitSignal->trustedKeyRemoved( key );
203       emitSignal->trustedKeyRemoved( key );
204     }
205   }
206
207   list<PublicKey> KeyRing::Impl::publicKeys()
208   {
209     return publicKeys( generalKeyRing() );
210   }
211
212   list<PublicKey> KeyRing::Impl::trustedPublicKeys()
213   {
214     return publicKeys( trustedKeyRing() );
215   }
216
217   list<string> KeyRing::Impl::publicKeyIds()
218   {
219     return publicKeyIds( generalKeyRing() );
220   }
221
222   list<string> KeyRing::Impl::trustedPublicKeyIds()
223   {
224     return publicKeyIds( trustedKeyRing() );
225   }
226
227   bool KeyRing::Impl::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature)
228   {
229     return verifyFile( file, signature, trustedKeyRing() );
230   }
231
232   bool KeyRing::Impl::verifyFileSignature( const Pathname &file, const Pathname &signature)
233   {
234     return verifyFile( file, signature, generalKeyRing() );
235   }
236
237   bool KeyRing::Impl::isKeyTrusted( const string &id)
238   {
239     return publicKeyExists( id, trustedKeyRing() );
240   }
241
242   bool KeyRing::Impl::isKeyKnown( const string &id )
243   {
244     MIL << endl;
245     if ( publicKeyExists( id, trustedKeyRing() ) )
246       return true;
247     else
248       return publicKeyExists( id, generalKeyRing() );
249   }
250
251   bool KeyRing::Impl::publicKeyExists( string id, const Pathname &keyring)
252   {
253     MIL << "Searching key [" << id << "] in keyring " << keyring << endl;
254     list<PublicKey> keys = publicKeys(keyring);
255     for (list<PublicKey>::const_iterator it = keys.begin(); it != keys.end(); it++)
256     {
257       if ( id == (*it).id() )
258
259         return true;
260     }
261     return false;
262   }
263
264   PublicKey KeyRing::Impl::exportKey( string id, const Pathname &keyring)
265   {
266     TmpFile tmp_file( _base_dir, "pubkey-"+id+"-" );
267     MIL << "Going to export key " << id << " from " << keyring << " to " << tmp_file.path() << endl;
268
269     try {
270       ofstream os(tmp_file.path().c_str());
271       dumpPublicKey( id, keyring, os );
272       os.close();
273       return PublicKey( tmp_file );
274     }
275     catch (BadKeyException &e)
276     {
277       ERR << "Cannot create public key " << id << " from " << keyring << " keyring  to file " << e.keyFile() << endl;
278       // TranslatorExplanation first %s is key name, second is keyring name
279       // and third is keyfile name
280       ZYPP_THROW(Exception(boost::str(boost::format(
281           _("Cannot create public key %s from %s keyring to file %s"))
282           % id % keyring.asString() % e.keyFile().asString())));
283     }
284     catch (exception &e)
285     {
286       ERR << "Cannot export key " << id << " from " << keyring << " keyring  to file " << tmp_file.path() << endl;
287     }
288     return PublicKey();
289   }
290
291   void KeyRing::Impl::dumpPublicKey( const string &id, bool trusted, ostream &stream )
292   {
293      dumpPublicKey( id, ( trusted ? trustedKeyRing() : generalKeyRing() ), stream );
294   }
295
296   void KeyRing::Impl::dumpPublicKey( const string &id, const Pathname &keyring, ostream &stream )
297   {
298     const char* argv[] =
299     {
300       GPG_BINARY,
301       "--no-default-keyring",
302       "--quiet",
303       "--no-tty",
304       "--no-greeting",
305       "--no-permission-warning",
306       "--batch",
307       "--homedir",
308       keyring.asString().c_str(),
309       "-a",
310       "--export",
311       id.c_str(),
312       NULL
313     };
314     ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
315     string line;
316     int count;
317     for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
318     {
319       stream << line;
320     }
321     prog.close();
322   }
323
324
325   bool KeyRing::Impl::verifyFileSignatureWorkflow(
326       const Pathname &file,
327       const string filedesc,
328       const Pathname &signature,
329       const KeyContext &context)
330   {
331     callback::SendReport<KeyRingReport> report;
332     //callback::SendReport<KeyRingSignals> emitSignal;
333     MIL << "Going to verify signature for " << filedesc << " ( " << file << " ) with " << signature << endl;
334
335     // if signature does not exists, ask user if he wants to accept unsigned file.
336     if( signature.empty() || (!PathInfo(signature).isExist()) )
337     {
338       bool res = report->askUserToAcceptUnsignedFile( filedesc, context );
339       MIL << "User decision on unsigned file: " << res << endl;
340       return res;
341     }
342
343     // get the id of the signature
344     string id = readSignatureKeyId(signature);
345
346     // doeskey exists in trusted keyring
347     if ( publicKeyExists( id, trustedKeyRing() ) )
348     {
349       PublicKey key = exportKey( id, trustedKeyRing() );
350
351       // lets look if there is an updated key in the
352       // general keyring
353       if ( publicKeyExists( id, generalKeyRing() ) )
354       {
355         // bnc #393160: Comment #30: Compare at least the fingerprint
356         // in case an attacker created a key the the same id.
357         PublicKey untkey = exportKey( id, generalKeyRing() );
358         if ( untkey.fingerprint() == key.fingerprint()
359              && untkey.created() > key.created() )
360         {
361           MIL << "Key " << key << " was updated. Saving new version into trusted keyring." << endl;
362           importKey( untkey, true );
363           key = untkey;
364         }
365       }
366
367       MIL << "Key " << id << " " << key.name() << " is trusted" << endl;
368       // it exists, is trusted, does it validates?
369       if ( verifyFile( file, signature, trustedKeyRing() ) )
370         return true;
371       else
372         return report->askUserToAcceptVerificationFailed( filedesc, key, context );
373     }
374     else
375     {
376       if ( publicKeyExists( id, generalKeyRing() ) )
377       {
378         PublicKey key =  exportKey( id, generalKeyRing());
379         MIL << "Exported key " << id << " to " << key.path() << endl;
380         MIL << "Key " << id << " " << key.name() << " is not trusted" << endl;
381
382         // ok the key is not trusted, ask the user to trust it or not
383         KeyRingReport::KeyTrust reply = report->askUserToAcceptKey(key, context);
384         if (reply == KeyRingReport::KEY_TRUST_TEMPORARILY ||
385             reply == KeyRingReport::KEY_TRUST_AND_IMPORT)
386         {
387           MIL << "User wants to trust key " << id << " " << key.name() << endl;
388           //dumpFile(unKey.path());
389
390           Pathname which_keyring;
391           if (reply == KeyRingReport::KEY_TRUST_AND_IMPORT)
392           {
393             MIL << "User wants to import key " << id << " " << key.name() << endl;
394             importKey( key, true );
395             which_keyring = trustedKeyRing();
396           }
397           else
398             which_keyring = generalKeyRing();
399
400           // emit key added
401           if ( verifyFile( file, signature, which_keyring ) )
402           {
403             MIL << "File signature is verified" << endl;
404             return true;
405           }
406           else
407           {
408             MIL << "File signature check fails" << endl;
409             if ( report->askUserToAcceptVerificationFailed( filedesc, key, context ) )
410             {
411               MIL << "User continues anyway." << endl;
412               return true;
413             }
414             else
415             {
416               MIL << "User does not want to continue" << endl;
417               return false;
418             }
419           }
420         }
421         else
422         {
423           MIL << "User does not want to trust key " << id << " " << key.name() << endl;
424           return false;
425         }
426       }
427       else
428       {
429         // unknown key...
430         MIL << "File [" << file << "] ( " << filedesc << " ) signed with unknown key [" << id << "]" << endl;
431         if ( report->askUserToAcceptUnknownKey( filedesc, id, context ) )
432         {
433           MIL << "User wants to accept unknown key " << id << endl;
434           return true;
435         }
436         else
437         {
438           MIL << "User does not want to accept unknown key " << id << endl;
439           return false;
440         }
441       }
442     }
443     return false;
444   }
445
446   list<string> KeyRing::Impl::publicKeyIds(const Pathname &keyring)
447   {
448     static str::regex rxColons("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
449     static str::regex rxColonsFpr("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
450
451     list<string> ids;
452
453     const char* argv[] =
454     {
455       GPG_BINARY,
456       "--no-default-keyring",
457       "--quiet",
458       "--list-public-keys",
459       "--with-colons",
460       "--with-fingerprint",
461       "--no-tty",
462       "--no-greeting",
463       "--batch",
464       "--status-fd",
465       "1",
466       "--homedir",
467       keyring.asString().c_str(),
468       NULL
469     };
470
471     ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
472     string line;
473     int count = 0;
474
475     for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
476     {
477       //MIL << line << endl;
478       str::smatch what;
479       if(str::regex_match(line, what, rxColons))
480       {
481         string id;
482         string fingerprint;
483         if ( what[1] == "pub" )
484         {
485           id = what[5];
486
487           string line2;
488           for(line2 = prog.receiveLine(); !line2.empty(); line2 = prog.receiveLine(), count++ )
489           {
490             str::smatch what2;
491             if (str::regex_match(line2, what2, rxColonsFpr))
492             {
493               if ( (what2[1] == "fpr") && (what2[1] != "pub") && (what2[1] !="sub"))
494               {
495                 fingerprint = what2[10];
496                 break;
497               }
498             }
499           }
500
501           ids.push_back(id);
502           MIL << "Found key " << "[" << id << "]" << endl;
503         }
504         //dumpRegexpResults(what);
505       }
506     }
507     prog.close();
508     return ids;
509   }
510
511   list<PublicKey> KeyRing::Impl::publicKeys(const Pathname &keyring)
512   {
513
514     list<PublicKey> keys;
515
516     list<string> ids = publicKeyIds(keyring);
517
518     for ( list<string>::const_iterator it = ids.begin(); it != ids.end(); ++it )
519     {
520       PublicKey key(exportKey( *it, keyring ));
521       keys.push_back(key);
522       MIL << "Found key " << "[" << key.id() << "]" << " [" << key.name() << "]" << " [" << key.fingerprint() << "]" << endl;
523     }
524     return keys;
525   }
526
527   void KeyRing::Impl::importKey( const Pathname &keyfile, const Pathname &keyring)
528   {
529     if ( ! PathInfo(keyfile).isExist() )
530       // TranslatorExplanation first %s is key name, second is keyring name
531       ZYPP_THROW(KeyRingException(boost::str(boost::format(
532           _("Tried to import not existant key %s into keyring %s"))
533           % keyfile.asString() % keyring.asString())));
534
535     const char* argv[] =
536     {
537       GPG_BINARY,
538       "--no-default-keyring",
539       "--quiet",
540       "--no-tty",
541       "--no-greeting",
542       "--no-permission-warning",
543       "--status-fd",
544       "1",
545       "--homedir",
546       keyring.asString().c_str(),
547       "--import",
548       keyfile.asString().c_str(),
549       NULL
550     };
551
552     int code;
553     ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
554     code = prog.close();
555
556     //if ( code != 0 )
557     //  ZYPP_THROW(Exception("failed to import key"));
558   }
559
560   void KeyRing::Impl::deleteKey( const string &id, const Pathname &keyring )
561   {
562     const char* argv[] =
563     {
564       GPG_BINARY,
565       "--no-default-keyring",
566       "--yes",
567       "--quiet",
568       "--no-tty",
569       "--batch",
570       "--status-fd",
571       "1",
572       "--homedir",
573       keyring.asString().c_str(),
574       "--delete-keys",
575       id.c_str(),
576       NULL
577     };
578
579     ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
580
581     int code = prog.close();
582     if ( code )
583       ZYPP_THROW(Exception(_("Failed to delete key.")));
584     else
585       MIL << "Deleted key " << id << " from keyring " << keyring << endl;
586   }
587
588
589   string KeyRing::Impl::readSignatureKeyId(const Pathname &signature )
590   {
591     if ( ! PathInfo(signature).isFile() )
592       ZYPP_THROW(Exception(boost::str(boost::format(
593           _("Signature file %s not found"))% signature.asString())));
594
595     MIL << "Determining key id if signature " << signature << endl;
596     // HACK create a tmp keyring with no keys
597     TmpDir dir(_base_dir, "fake-keyring");
598
599     const char* argv[] =
600     {
601       GPG_BINARY,
602       "--no-default-keyring",
603       "--quiet",
604       "--no-tty",
605       "--no-greeting",
606       "--batch",
607       "--status-fd",
608       "1",
609       "--homedir",
610       dir.path().asString().c_str(),
611       signature.asString().c_str(),
612       NULL
613     };
614
615     ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
616
617     string line;
618     int count = 0;
619
620     str::regex rxNoKey("^\\[GNUPG:\\] NO_PUBKEY (.+)\n$");
621     string id;
622     for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
623     {
624       //MIL << "[" << line << "]" << endl;
625       str::smatch what;
626       if(str::regex_match(line, what, rxNoKey))
627       {
628         if ( what.size() >= 1 )
629         {
630           id = what[1];
631           break;
632         }
633         //dumpRegexpResults(what);
634       }
635     }
636
637     if ( count == 0 )
638     {
639       MIL << "no output" << endl;
640     }
641
642     MIL << "Determined key id [" << id << "] for signature " << signature << endl;
643     prog.close();
644     return id;
645   }
646
647   bool KeyRing::Impl::verifyFile( const Pathname &file, const Pathname &signature, const Pathname &keyring)
648   {
649     const char* argv[] =
650     {
651       GPG_BINARY,
652       "--no-default-keyring",
653       "--quiet",
654       "--no-tty",
655       "--batch",
656       "--no-greeting",
657       "--status-fd",
658       "1",
659       "--homedir",
660       keyring.asString().c_str(),
661       "--verify",
662       signature.asString().c_str(),
663       file.asString().c_str(),
664       NULL
665     };
666
667     // no need to parse output for now
668     //     [GNUPG:] SIG_ID yCc4u223XRJnLnVAIllvYbUd8mQ 2006-03-29 1143618744
669     //     [GNUPG:] GOODSIG A84EDAE89C800ACA SuSE Package Signing Key <build@suse.de>
670     //     gpg: Good signature from "SuSE Package Signing Key <build@suse.de>"
671     //     [GNUPG:] VALIDSIG 79C179B2E1C820C1890F9994A84EDAE89C800ACA 2006-03-29 1143618744 0 3 0 17 2 00 79C179B2E1C820C1890F9994A84EDAE89C800ACA
672     //     [GNUPG:] TRUST_UNDEFINED
673
674     //     [GNUPG:] ERRSIG A84EDAE89C800ACA 17 2 00 1143618744 9
675     //     [GNUPG:] NO_PUBKEY A84EDAE89C800ACA
676
677     ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
678
679     return (prog.close() == 0) ? true : false;
680   }
681
682   ///////////////////////////////////////////////////////////////////
683
684   ///////////////////////////////////////////////////////////////////
685   //
686   //    CLASS NAME : KeyRing
687   //
688   ///////////////////////////////////////////////////////////////////
689
690   ///////////////////////////////////////////////////////////////////
691   //
692   //    METHOD NAME : KeyRing::KeyRing
693   //    METHOD TYPE : Ctor
694   //
695   KeyRing::KeyRing(const Pathname &baseTmpDir)
696   : _pimpl( new Impl(baseTmpDir) )
697   {}
698
699   ///////////////////////////////////////////////////////////////////
700   //
701   //    METHOD NAME : KeyRing::KeyRing
702   //    METHOD TYPE : Ctor
703   //
704   //KeyRing::KeyRing( const Pathname &general_kr, const Pathname &trusted_kr )
705   //: _pimpl( new Impl(general_kr, trusted_kr) )
706   //{}
707
708   ///////////////////////////////////////////////////////////////////
709   //
710   //    METHOD NAME : KeyRing::~KeyRing
711   //    METHOD TYPE : Dtor
712   //
713   KeyRing::~KeyRing()
714   {}
715
716   ///////////////////////////////////////////////////////////////////
717   //
718   // Forward to implementation:
719   //
720   ///////////////////////////////////////////////////////////////////
721
722
723   void KeyRing::importKey( const PublicKey &key, bool trusted )
724   {
725     _pimpl->importKey( key, trusted );
726   }
727
728   void KeyRing::multiKeyImport( const Pathname & keyfile_r, bool trusted_r )
729   {
730     _pimpl->multiKeyImport( keyfile_r, trusted_r );
731   }
732
733   string KeyRing::readSignatureKeyId( const Pathname &signature )
734   {
735     return _pimpl->readSignatureKeyId(signature);
736   }
737
738   void KeyRing::deleteKey( const string &id, bool trusted )
739   {
740     _pimpl->deleteKey(id, trusted);
741   }
742
743   list<PublicKey> KeyRing::publicKeys()
744   {
745     return _pimpl->publicKeys();
746   }
747
748   list<PublicKey> KeyRing::trustedPublicKeys()
749   {
750     return _pimpl->trustedPublicKeys();
751   }
752
753   list<string> KeyRing::publicKeyIds()
754   {
755     return _pimpl->publicKeyIds();
756   }
757
758   list<string> KeyRing::trustedPublicKeyIds()
759   {
760     return _pimpl->trustedPublicKeyIds();
761   }
762
763   bool KeyRing::verifyFileSignatureWorkflow(
764       const Pathname &file,
765       const string filedesc,
766       const Pathname &signature,
767       const KeyContext &keycontext)
768   {
769     return _pimpl->verifyFileSignatureWorkflow(file, filedesc, signature, keycontext);
770   }
771
772   bool KeyRing::verifyFileSignature( const Pathname &file, const Pathname &signature)
773   {
774     return _pimpl->verifyFileSignature(file, signature);
775   }
776
777   bool KeyRing::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature)
778   {
779     return _pimpl->verifyFileTrustedSignature(file, signature);
780   }
781
782   void KeyRing::dumpPublicKey( const string &id, bool trusted, ostream &stream )
783   {
784     _pimpl->dumpPublicKey( id, trusted, stream);
785   }
786
787   bool KeyRing::isKeyTrusted( const string &id )
788   {
789     return _pimpl->isKeyTrusted(id);
790   }
791
792   bool KeyRing::isKeyKnown( const string &id )
793   {
794     return _pimpl->isKeyKnown(id);
795   }
796
797   /////////////////////////////////////////////////////////////////
798 } // namespace zypp
799 ///////////////////////////////////////////////////////////////////