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