00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <fstream>
00014 #include <sys/file.h>
00015 #include <cstdio>
00016 #include <unistd.h>
00017
00018 #include <boost/format.hpp>
00019
00020 #include "zypp/TmpPath.h"
00021 #include "zypp/ZYppFactory.h"
00022 #include "zypp/ZYpp.h"
00023
00024 #include "zypp/base/Logger.h"
00025 #include "zypp/base/IOStream.h"
00026 #include "zypp/base/String.h"
00027 #include "zypp/base/Regex.h"
00028 #include "zypp/base/Gettext.h"
00029 #include "zypp/PathInfo.h"
00030 #include "zypp/KeyRing.h"
00031 #include "zypp/ExternalProgram.h"
00032 #include "zypp/TmpPath.h"
00033
00034 using namespace std;
00035 using namespace zypp::filesystem;
00036
00037 #undef ZYPP_BASE_LOGGER_LOGGROUP
00038 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::KeyRing"
00039
00040 #define GPG_BINARY "/usr/bin/gpg2"
00041
00043 namespace zypp
00044 {
00045
00046 IMPL_PTR_TYPE(KeyRing);
00047
00048 namespace
00049 {
00050 KeyRing::DefaultAccept _keyRingDefaultAccept( KeyRing::ACCEPT_NOTHING );
00051 }
00052
00053 KeyRing::DefaultAccept KeyRing::defaultAccept()
00054 { return _keyRingDefaultAccept; }
00055
00056 void KeyRing::setDefaultAccept( DefaultAccept value_r )
00057 {
00058 MIL << "Set new KeyRing::DefaultAccept: " << value_r << endl;
00059 _keyRingDefaultAccept = value_r;
00060 }
00061
00062 bool KeyRingReport::askUserToAcceptUnsignedFile( const string &file, const KeyContext &keycontext )
00063 { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_UNSIGNED_FILE ); }
00064
00065 KeyRingReport::KeyTrust
00066 KeyRingReport::askUserToAcceptKey( const PublicKey &key, const KeyContext &keycontext )
00067 {
00068 if ( _keyRingDefaultAccept.testFlag( KeyRing::TRUST_KEY_TEMPORARILY ) )
00069 return KEY_TRUST_TEMPORARILY;
00070 if ( _keyRingDefaultAccept.testFlag( KeyRing::TRUST_AND_IMPORT_KEY ) )
00071 return KEY_TRUST_AND_IMPORT;
00072 return KEY_DONT_TRUST;
00073 }
00074
00075 bool KeyRingReport::askUserToAcceptUnknownKey( const string &file, const string &id, const KeyContext &keycontext )
00076 { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_UNKNOWNKEY ); }
00077
00078 bool KeyRingReport::askUserToAcceptVerificationFailed( const string &file, const PublicKey &key, const KeyContext &keycontext )
00079 { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_VERIFICATION_FAILED ); }
00080
00082
00083
00084
00086 struct KeyRing::Impl
00087 {
00088 Impl( const Pathname & baseTmpDir )
00089 : _trusted_tmp_dir( baseTmpDir, "zypp-trusted-kr" )
00090 , _general_tmp_dir( baseTmpDir, "zypp-general-kr" )
00091 , _base_dir( baseTmpDir )
00092 {
00093 MIL << "Current KeyRing::DefaultAccept: " << _keyRingDefaultAccept << endl;
00094 }
00095
00096 void importKey( const PublicKey &key, bool trusted = false);
00097 void multiKeyImport( const Pathname & keyfile_r, bool trusted_r = false);
00098 void deleteKey( const string &id, bool trusted );
00099
00100 string readSignatureKeyId( const Pathname &signature );
00101
00102 bool isKeyTrusted( const string &id);
00103 bool isKeyKnown( const string &id );
00104
00105 list<PublicKey> trustedPublicKeys();
00106 list<PublicKey> publicKeys();
00107
00108 list<string> trustedPublicKeyIds();
00109 list<string> publicKeyIds();
00110
00111 void dumpPublicKey( const string &id, bool trusted, ostream &stream );
00112
00113 bool verifyFileSignatureWorkflow(
00114 const Pathname &file,
00115 const string filedesc,
00116 const Pathname &signature,
00117 const KeyContext &keycontext = KeyContext());
00118
00119 bool verifyFileSignature( const Pathname &file, const Pathname &signature);
00120 bool verifyFileTrustedSignature( const Pathname &file, const Pathname &signature);
00121 private:
00122
00123 bool verifyFile( const Pathname &file, const Pathname &signature, const Pathname &keyring);
00124 void importKey( const Pathname &keyfile, const Pathname &keyring);
00125 PublicKey exportKey( string id, const Pathname &keyring);
00126 void dumpPublicKey( const string &id, const Pathname &keyring, ostream &stream );
00127 void deleteKey( const string &id, const Pathname &keyring );
00128
00129 list<PublicKey> publicKeys(const Pathname &keyring);
00130 list<string> publicKeyIds(const Pathname &keyring);
00131
00132 bool publicKeyExists( string id, const Pathname &keyring);
00133
00134 const Pathname generalKeyRing() const;
00135 const Pathname trustedKeyRing() const;
00136
00137
00138 TmpDir _trusted_tmp_dir;
00139 TmpDir _general_tmp_dir;
00140 Pathname _base_dir;
00141 public:
00143 static shared_ptr<Impl> nullimpl()
00144 {
00145 static shared_ptr<Impl> _nullimpl( new Impl( TmpPath::defaultLocation() ) );
00146 return _nullimpl;
00147 }
00148
00149 private:
00150 friend Impl * rwcowClone<Impl>( const Impl * rhs );
00152 Impl * clone() const
00153 { return new Impl( *this ); }
00154 };
00155
00156
00157 const Pathname KeyRing::Impl::generalKeyRing() const
00158 {
00159 return _general_tmp_dir.path();
00160 }
00161
00162 const Pathname KeyRing::Impl::trustedKeyRing() const
00163 {
00164 return _trusted_tmp_dir.path();
00165 }
00166
00167 void KeyRing::Impl::importKey( const PublicKey &key, bool trusted)
00168 {
00169 callback::SendReport<target::rpm::KeyRingSignals> rpmdbEmitSignal;
00170 callback::SendReport<KeyRingSignals> emitSignal;
00171
00172 importKey( key.path(), trusted ? trustedKeyRing() : generalKeyRing() );
00173
00174 if ( trusted )
00175 {
00176 rpmdbEmitSignal->trustedKeyAdded( key );
00177 emitSignal->trustedKeyAdded( key );
00178 }
00179 }
00180
00181 void KeyRing::Impl::multiKeyImport( const Pathname & keyfile_r, bool trusted_r )
00182 {
00183 importKey( keyfile_r, trusted_r ? trustedKeyRing() : generalKeyRing() );
00184 }
00185
00186 void KeyRing::Impl::deleteKey( const string &id, bool trusted)
00187 {
00188 PublicKey key;
00189
00190 if (trusted)
00191 {
00192 key = exportKey(id, trustedKeyRing());
00193 }
00194
00195 deleteKey( id, trusted ? trustedKeyRing() : generalKeyRing() );
00196
00197 if ( trusted )
00198 {
00199 callback::SendReport<target::rpm::KeyRingSignals> rpmdbEmitSignal;
00200 callback::SendReport<KeyRingSignals> emitSignal;
00201
00202 rpmdbEmitSignal->trustedKeyRemoved( key );
00203 emitSignal->trustedKeyRemoved( key );
00204 }
00205 }
00206
00207 list<PublicKey> KeyRing::Impl::publicKeys()
00208 {
00209 return publicKeys( generalKeyRing() );
00210 }
00211
00212 list<PublicKey> KeyRing::Impl::trustedPublicKeys()
00213 {
00214 return publicKeys( trustedKeyRing() );
00215 }
00216
00217 list<string> KeyRing::Impl::publicKeyIds()
00218 {
00219 return publicKeyIds( generalKeyRing() );
00220 }
00221
00222 list<string> KeyRing::Impl::trustedPublicKeyIds()
00223 {
00224 return publicKeyIds( trustedKeyRing() );
00225 }
00226
00227 bool KeyRing::Impl::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature)
00228 {
00229 return verifyFile( file, signature, trustedKeyRing() );
00230 }
00231
00232 bool KeyRing::Impl::verifyFileSignature( const Pathname &file, const Pathname &signature)
00233 {
00234 return verifyFile( file, signature, generalKeyRing() );
00235 }
00236
00237 bool KeyRing::Impl::isKeyTrusted( const string &id)
00238 {
00239 return publicKeyExists( id, trustedKeyRing() );
00240 }
00241
00242 bool KeyRing::Impl::isKeyKnown( const string &id )
00243 {
00244 MIL << endl;
00245 if ( publicKeyExists( id, trustedKeyRing() ) )
00246 return true;
00247 else
00248 return publicKeyExists( id, generalKeyRing() );
00249 }
00250
00251 bool KeyRing::Impl::publicKeyExists( string id, const Pathname &keyring)
00252 {
00253 MIL << "Searching key [" << id << "] in keyring " << keyring << endl;
00254 list<PublicKey> keys = publicKeys(keyring);
00255 for (list<PublicKey>::const_iterator it = keys.begin(); it != keys.end(); it++)
00256 {
00257 if ( id == (*it).id() )
00258
00259 return true;
00260 }
00261 return false;
00262 }
00263
00264 PublicKey KeyRing::Impl::exportKey( string id, const Pathname &keyring)
00265 {
00266 TmpFile tmp_file( _base_dir, "pubkey-"+id+"-" );
00267 MIL << "Going to export key " << id << " from " << keyring << " to " << tmp_file.path() << endl;
00268
00269 try {
00270 ofstream os(tmp_file.path().c_str());
00271 dumpPublicKey( id, keyring, os );
00272 os.close();
00273 return PublicKey( tmp_file );
00274 }
00275 catch (BadKeyException &e)
00276 {
00277 ERR << "Cannot create public key " << id << " from " << keyring << " keyring to file " << e.keyFile() << endl;
00278
00279
00280 ZYPP_THROW(Exception(boost::str(boost::format(
00281 _("Cannot create public key %s from %s keyring to file %s"))
00282 % id % keyring.asString() % e.keyFile().asString())));
00283 }
00284 catch (exception &e)
00285 {
00286 ERR << "Cannot export key " << id << " from " << keyring << " keyring to file " << tmp_file.path() << endl;
00287 }
00288 return PublicKey();
00289 }
00290
00291 void KeyRing::Impl::dumpPublicKey( const string &id, bool trusted, ostream &stream )
00292 {
00293 dumpPublicKey( id, ( trusted ? trustedKeyRing() : generalKeyRing() ), stream );
00294 }
00295
00296 void KeyRing::Impl::dumpPublicKey( const string &id, const Pathname &keyring, ostream &stream )
00297 {
00298 const char* argv[] =
00299 {
00300 GPG_BINARY,
00301 "--no-default-keyring",
00302 "--quiet",
00303 "--no-tty",
00304 "--no-greeting",
00305 "--no-permission-warning",
00306 "--batch",
00307 "--homedir",
00308 keyring.asString().c_str(),
00309 "-a",
00310 "--export",
00311 id.c_str(),
00312 NULL
00313 };
00314 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
00315 string line;
00316 int count;
00317 for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
00318 {
00319 stream << line;
00320 }
00321 prog.close();
00322 }
00323
00324
00325 bool KeyRing::Impl::verifyFileSignatureWorkflow(
00326 const Pathname &file,
00327 const string filedesc,
00328 const Pathname &signature,
00329 const KeyContext &context)
00330 {
00331 callback::SendReport<KeyRingReport> report;
00332
00333 MIL << "Going to verify signature for " << filedesc << " ( " << file << " ) with " << signature << endl;
00334
00335
00336 if( signature.empty() || (!PathInfo(signature).isExist()) )
00337 {
00338 bool res = report->askUserToAcceptUnsignedFile( filedesc, context );
00339 MIL << "User decision on unsigned file: " << res << endl;
00340 return res;
00341 }
00342
00343
00344 string id = readSignatureKeyId(signature);
00345
00346
00347 if ( publicKeyExists( id, trustedKeyRing() ) )
00348 {
00349 PublicKey key = exportKey( id, trustedKeyRing() );
00350
00351
00352
00353 if ( publicKeyExists( id, generalKeyRing() ) )
00354 {
00355
00356
00357 PublicKey untkey = exportKey( id, generalKeyRing() );
00358 if ( untkey.fingerprint() == key.fingerprint()
00359 && untkey.created() > key.created() )
00360 {
00361 MIL << "Key " << key << " was updated. Saving new version into trusted keyring." << endl;
00362 importKey( untkey, true );
00363 key = untkey;
00364 }
00365 }
00366
00367 MIL << "Key " << id << " " << key.name() << " is trusted" << endl;
00368
00369 if ( verifyFile( file, signature, trustedKeyRing() ) )
00370 return true;
00371 else
00372 return report->askUserToAcceptVerificationFailed( filedesc, key, context );
00373 }
00374 else
00375 {
00376 if ( publicKeyExists( id, generalKeyRing() ) )
00377 {
00378 PublicKey key = exportKey( id, generalKeyRing());
00379 MIL << "Exported key " << id << " to " << key.path() << endl;
00380 MIL << "Key " << id << " " << key.name() << " is not trusted" << endl;
00381
00382
00383 KeyRingReport::KeyTrust reply = report->askUserToAcceptKey(key, context);
00384 if (reply == KeyRingReport::KEY_TRUST_TEMPORARILY ||
00385 reply == KeyRingReport::KEY_TRUST_AND_IMPORT)
00386 {
00387 MIL << "User wants to trust key " << id << " " << key.name() << endl;
00388
00389
00390 Pathname which_keyring;
00391 if (reply == KeyRingReport::KEY_TRUST_AND_IMPORT)
00392 {
00393 MIL << "User wants to import key " << id << " " << key.name() << endl;
00394 importKey( key, true );
00395 which_keyring = trustedKeyRing();
00396 }
00397 else
00398 which_keyring = generalKeyRing();
00399
00400
00401 if ( verifyFile( file, signature, which_keyring ) )
00402 {
00403 MIL << "File signature is verified" << endl;
00404 return true;
00405 }
00406 else
00407 {
00408 MIL << "File signature check fails" << endl;
00409 if ( report->askUserToAcceptVerificationFailed( filedesc, key, context ) )
00410 {
00411 MIL << "User continues anyway." << endl;
00412 return true;
00413 }
00414 else
00415 {
00416 MIL << "User does not want to continue" << endl;
00417 return false;
00418 }
00419 }
00420 }
00421 else
00422 {
00423 MIL << "User does not want to trust key " << id << " " << key.name() << endl;
00424 return false;
00425 }
00426 }
00427 else
00428 {
00429
00430 MIL << "File [" << file << "] ( " << filedesc << " ) signed with unknown key [" << id << "]" << endl;
00431 if ( report->askUserToAcceptUnknownKey( filedesc, id, context ) )
00432 {
00433 MIL << "User wants to accept unknown key " << id << endl;
00434 return true;
00435 }
00436 else
00437 {
00438 MIL << "User does not want to accept unknown key " << id << endl;
00439 return false;
00440 }
00441 }
00442 }
00443 return false;
00444 }
00445
00446 list<string> KeyRing::Impl::publicKeyIds(const Pathname &keyring)
00447 {
00448 static str::regex rxColons("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
00449 static str::regex rxColonsFpr("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
00450
00451 list<string> ids;
00452
00453 const char* argv[] =
00454 {
00455 GPG_BINARY,
00456 "--no-default-keyring",
00457 "--quiet",
00458 "--list-public-keys",
00459 "--with-colons",
00460 "--with-fingerprint",
00461 "--no-tty",
00462 "--no-greeting",
00463 "--batch",
00464 "--status-fd",
00465 "1",
00466 "--homedir",
00467 keyring.asString().c_str(),
00468 NULL
00469 };
00470
00471 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
00472 string line;
00473 int count = 0;
00474
00475 for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
00476 {
00477
00478 str::smatch what;
00479 if(str::regex_match(line, what, rxColons))
00480 {
00481 string id;
00482 string fingerprint;
00483 if ( what[1] == "pub" )
00484 {
00485 id = what[5];
00486
00487 string line2;
00488 for(line2 = prog.receiveLine(); !line2.empty(); line2 = prog.receiveLine(), count++ )
00489 {
00490 str::smatch what2;
00491 if (str::regex_match(line2, what2, rxColonsFpr))
00492 {
00493 if ( (what2[1] == "fpr") && (what2[1] != "pub") && (what2[1] !="sub"))
00494 {
00495 fingerprint = what2[10];
00496 break;
00497 }
00498 }
00499 }
00500
00501 ids.push_back(id);
00502 MIL << "Found key " << "[" << id << "]" << endl;
00503 }
00504
00505 }
00506 }
00507 prog.close();
00508 return ids;
00509 }
00510
00511 list<PublicKey> KeyRing::Impl::publicKeys(const Pathname &keyring)
00512 {
00513
00514 list<PublicKey> keys;
00515
00516 list<string> ids = publicKeyIds(keyring);
00517
00518 for ( list<string>::const_iterator it = ids.begin(); it != ids.end(); ++it )
00519 {
00520 PublicKey key(exportKey( *it, keyring ));
00521 keys.push_back(key);
00522 MIL << "Found key " << "[" << key.id() << "]" << " [" << key.name() << "]" << " [" << key.fingerprint() << "]" << endl;
00523 }
00524 return keys;
00525 }
00526
00527 void KeyRing::Impl::importKey( const Pathname &keyfile, const Pathname &keyring)
00528 {
00529 if ( ! PathInfo(keyfile).isExist() )
00530
00531 ZYPP_THROW(KeyRingException(boost::str(boost::format(
00532 _("Tried to import not existant key %s into keyring %s"))
00533 % keyfile.asString() % keyring.asString())));
00534
00535 const char* argv[] =
00536 {
00537 GPG_BINARY,
00538 "--no-default-keyring",
00539 "--quiet",
00540 "--no-tty",
00541 "--no-greeting",
00542 "--no-permission-warning",
00543 "--status-fd",
00544 "1",
00545 "--homedir",
00546 keyring.asString().c_str(),
00547 "--import",
00548 keyfile.asString().c_str(),
00549 NULL
00550 };
00551
00552 int code;
00553 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
00554 code = prog.close();
00555
00556
00557
00558 }
00559
00560 void KeyRing::Impl::deleteKey( const string &id, const Pathname &keyring )
00561 {
00562 const char* argv[] =
00563 {
00564 GPG_BINARY,
00565 "--no-default-keyring",
00566 "--yes",
00567 "--quiet",
00568 "--no-tty",
00569 "--batch",
00570 "--status-fd",
00571 "1",
00572 "--homedir",
00573 keyring.asString().c_str(),
00574 "--delete-keys",
00575 id.c_str(),
00576 NULL
00577 };
00578
00579 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
00580
00581 int code = prog.close();
00582 if ( code )
00583 ZYPP_THROW(Exception(_("Failed to delete key.")));
00584 else
00585 MIL << "Deleted key " << id << " from keyring " << keyring << endl;
00586 }
00587
00588
00589 string KeyRing::Impl::readSignatureKeyId(const Pathname &signature )
00590 {
00591 if ( ! PathInfo(signature).isFile() )
00592 ZYPP_THROW(Exception(boost::str(boost::format(
00593 _("Signature file %s not found"))% signature.asString())));
00594
00595 MIL << "Determining key id if signature " << signature << endl;
00596
00597 TmpDir dir(_base_dir, "fake-keyring");
00598
00599 const char* argv[] =
00600 {
00601 GPG_BINARY,
00602 "--no-default-keyring",
00603 "--quiet",
00604 "--no-tty",
00605 "--no-greeting",
00606 "--batch",
00607 "--status-fd",
00608 "1",
00609 "--homedir",
00610 dir.path().asString().c_str(),
00611 signature.asString().c_str(),
00612 NULL
00613 };
00614
00615 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
00616
00617 string line;
00618 int count = 0;
00619
00620 str::regex rxNoKey("^\\[GNUPG:\\] NO_PUBKEY (.+)\n$");
00621 string id;
00622 for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
00623 {
00624
00625 str::smatch what;
00626 if(str::regex_match(line, what, rxNoKey))
00627 {
00628 if ( what.size() >= 1 )
00629 {
00630 id = what[1];
00631 break;
00632 }
00633
00634 }
00635 }
00636
00637 if ( count == 0 )
00638 {
00639 MIL << "no output" << endl;
00640 }
00641
00642 MIL << "Determined key id [" << id << "] for signature " << signature << endl;
00643 prog.close();
00644 return id;
00645 }
00646
00647 bool KeyRing::Impl::verifyFile( const Pathname &file, const Pathname &signature, const Pathname &keyring)
00648 {
00649 const char* argv[] =
00650 {
00651 GPG_BINARY,
00652 "--no-default-keyring",
00653 "--quiet",
00654 "--no-tty",
00655 "--batch",
00656 "--no-greeting",
00657 "--status-fd",
00658 "1",
00659 "--homedir",
00660 keyring.asString().c_str(),
00661 "--verify",
00662 signature.asString().c_str(),
00663 file.asString().c_str(),
00664 NULL
00665 };
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
00678
00679 return (prog.close() == 0) ? true : false;
00680 }
00681
00683
00685
00686
00687
00689
00691
00692
00693
00694
00695 KeyRing::KeyRing(const Pathname &baseTmpDir)
00696 : _pimpl( new Impl(baseTmpDir) )
00697 {}
00698
00700
00701
00702
00703
00704
00705
00706
00707
00709
00710
00711
00712
00713 KeyRing::~KeyRing()
00714 {}
00715
00717
00718
00719
00721
00722
00723 void KeyRing::importKey( const PublicKey &key, bool trusted )
00724 {
00725 _pimpl->importKey( key, trusted );
00726 }
00727
00728 void KeyRing::multiKeyImport( const Pathname & keyfile_r, bool trusted_r )
00729 {
00730 _pimpl->multiKeyImport( keyfile_r, trusted_r );
00731 }
00732
00733 string KeyRing::readSignatureKeyId( const Pathname &signature )
00734 {
00735 return _pimpl->readSignatureKeyId(signature);
00736 }
00737
00738 void KeyRing::deleteKey( const string &id, bool trusted )
00739 {
00740 _pimpl->deleteKey(id, trusted);
00741 }
00742
00743 list<PublicKey> KeyRing::publicKeys()
00744 {
00745 return _pimpl->publicKeys();
00746 }
00747
00748 list<PublicKey> KeyRing::trustedPublicKeys()
00749 {
00750 return _pimpl->trustedPublicKeys();
00751 }
00752
00753 list<string> KeyRing::publicKeyIds()
00754 {
00755 return _pimpl->publicKeyIds();
00756 }
00757
00758 list<string> KeyRing::trustedPublicKeyIds()
00759 {
00760 return _pimpl->trustedPublicKeyIds();
00761 }
00762
00763 bool KeyRing::verifyFileSignatureWorkflow(
00764 const Pathname &file,
00765 const string filedesc,
00766 const Pathname &signature,
00767 const KeyContext &keycontext)
00768 {
00769 return _pimpl->verifyFileSignatureWorkflow(file, filedesc, signature, keycontext);
00770 }
00771
00772 bool KeyRing::verifyFileSignature( const Pathname &file, const Pathname &signature)
00773 {
00774 return _pimpl->verifyFileSignature(file, signature);
00775 }
00776
00777 bool KeyRing::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature)
00778 {
00779 return _pimpl->verifyFileTrustedSignature(file, signature);
00780 }
00781
00782 void KeyRing::dumpPublicKey( const string &id, bool trusted, ostream &stream )
00783 {
00784 _pimpl->dumpPublicKey( id, trusted, stream);
00785 }
00786
00787 bool KeyRing::isKeyTrusted( const string &id )
00788 {
00789 return _pimpl->isKeyTrusted(id);
00790 }
00791
00792 bool KeyRing::isKeyKnown( const string &id )
00793 {
00794 return _pimpl->isKeyKnown(id);
00795 }
00796
00798 }