From e9344acc3313f7f3beeadf4d96e1f5b580f38a23 Mon Sep 17 00:00:00 2001 From: Michael Andres Date: Wed, 31 Jul 2013 13:52:25 +0200 Subject: [PATCH] Reduce amount of gpg calls when importing/exporting keys. --- zypp/KeyRing.cc | 681 ++++++++++++++++++++++++++------------------------------ zypp/KeyRing.h | 34 ++- 2 files changed, 344 insertions(+), 371 deletions(-) diff --git a/zypp/KeyRing.cc b/zypp/KeyRing.cc index a4c7acf..bdee10e 100644 --- a/zypp/KeyRing.cc +++ b/zypp/KeyRing.cc @@ -21,18 +21,18 @@ #include "zypp/ZYppFactory.h" #include "zypp/ZYpp.h" -#include "zypp/base/Logger.h" +#include "zypp/base/LogTools.h" #include "zypp/base/IOStream.h" #include "zypp/base/String.h" #include "zypp/base/Regex.h" #include "zypp/base/Gettext.h" +#include "zypp/base/WatchFile.h" #include "zypp/PathInfo.h" #include "zypp/KeyRing.h" #include "zypp/ExternalProgram.h" #include "zypp/TmpPath.h" -using namespace std; -using namespace zypp::filesystem; +using std::endl; #undef ZYPP_BASE_LOGGER_LOGGROUP #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::KeyRing" @@ -59,11 +59,11 @@ namespace zypp _keyRingDefaultAccept = value_r; } - bool KeyRingReport::askUserToAcceptUnsignedFile( const string &file, const KeyContext &keycontext ) + bool KeyRingReport::askUserToAcceptUnsignedFile( const std::string & file, const KeyContext & keycontext ) { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_UNSIGNED_FILE ); } KeyRingReport::KeyTrust - KeyRingReport::askUserToAcceptKey( const PublicKey &key, const KeyContext &keycontext ) + KeyRingReport::askUserToAcceptKey( const PublicKey & key, const KeyContext & keycontext ) { if ( _keyRingDefaultAccept.testFlag( KeyRing::TRUST_KEY_TEMPORARILY ) ) return KEY_TRUST_TEMPORARILY; @@ -72,12 +72,91 @@ namespace zypp return KEY_DONT_TRUST; } - bool KeyRingReport::askUserToAcceptUnknownKey( const string &file, const string &id, const KeyContext &keycontext ) + bool KeyRingReport::askUserToAcceptUnknownKey( const std::string & file, const std::string & id, const KeyContext & keycontext ) { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_UNKNOWNKEY ); } - bool KeyRingReport::askUserToAcceptVerificationFailed( const string &file, const PublicKey &key, const KeyContext &keycontext ) + bool KeyRingReport::askUserToAcceptVerificationFailed( const std::string & file, const PublicKey & key, const KeyContext & keycontext ) { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_VERIFICATION_FAILED ); } + namespace + { + /////////////////////////////////////////////////////////////////// + /// \class CachedPublicKeyData + /// \brief Functor returning the keyrings data (cached). + /// \code + /// const std::list & cachedPublicKeyData( const Pathname & keyring ); + /// \endcode + /////////////////////////////////////////////////////////////////// + struct CachedPublicKeyData // : private base::NonCopyable - but KeyRing uses RWCOW though also NonCopyable :( + { + const std::list & operator()( const Pathname & keyring_r ) const + { return getData( keyring_r ); } + + private: + struct Cache + { + scoped_ptr _keyringP; + std::list _data; + + // Empty copy ctor to allow insert into std::map as + // scoped_ptr is noncopyable. + Cache() {} + Cache( const Cache & rhs ) {} + }; + + typedef std::map CacheMap; + + const std::list & getData( const Pathname & keyring_r ) const + { + Cache & cache( _cacheMap[keyring_r] ); + if ( ! cache._keyringP ) + { + // init new cache entry + cache._keyringP.reset( new WatchFile( keyring_r/"pubring.gpg", WatchFile::NO_INIT ) ); + } + return getData( keyring_r, cache ); + } + + const std::list & getData( const Pathname & keyring_r, Cache & cache_r ) const + { + if ( cache_r._keyringP->hasChanged() ) + { + const char* argv[] = + { + GPG_BINARY, + "--list-public-keys", + "--homedir", keyring_r.c_str(), + "--no-default-keyring", + "--quiet", + "--with-colons", + "--with-fingerprint", + "--with-sig-list", + "--no-tty", + "--no-greeting", + "--batch", + "--status-fd", "1", + NULL + }; + + PublicKeyScanner scanner; + ExternalProgram prog( argv ,ExternalProgram::Discard_Stderr, false, -1, true ); + for( std::string line = prog.receiveLine(); !line.empty(); line = prog.receiveLine() ) + { + scanner.scan( line ); + } + prog.close(); + + cache_r._data.swap( scanner._keys ); + MIL << "Found keys: " << cache_r._data << endl; + } + return cache_r._data; + } + + mutable CacheMap _cacheMap; + }; + /////////////////////////////////////////////////////////////////// + } + /////////////////////////////////////////////////////////////////// // // CLASS NAME : KeyRing::Impl @@ -93,56 +172,88 @@ namespace zypp MIL << "Current KeyRing::DefaultAccept: " << _keyRingDefaultAccept << endl; } - void importKey( const PublicKey &key, bool trusted = false); - void multiKeyImport( const Pathname & keyfile_r, bool trusted_r = false); - void deleteKey( const string &id, bool trusted ); + void importKey( const PublicKey & key, bool trusted = false ); + void multiKeyImport( const Pathname & keyfile_r, bool trusted_r = false ); + void deleteKey( const std::string & id, bool trusted ); - string readSignatureKeyId( const Pathname &signature ); + std::string readSignatureKeyId( const Pathname & signature ); - bool isKeyTrusted( const string &id); - bool isKeyKnown( const string &id ); + bool isKeyTrusted( const std::string & id ) + { return bool(publicKeyExists( id, trustedKeyRing() )); } + bool isKeyKnown( const std::string & id ) + { return publicKeyExists( id, trustedKeyRing() ) || publicKeyExists( id, generalKeyRing() ); } - list trustedPublicKeys(); - list publicKeys(); + std::list trustedPublicKeys() + { return publicKeys( trustedKeyRing() ); } + std::list publicKeys() + { return publicKeys( generalKeyRing() ); } - list trustedPublicKeyIds(); - list publicKeyIds(); + const std::list & trustedPublicKeyData() + { return publicKeyData( trustedKeyRing() ); } + const std::list & publicKeyData() + { return publicKeyData( generalKeyRing() ); } - void dumpPublicKey( const string &id, bool trusted, ostream &stream ); + void dumpPublicKey( const std::string & id, bool trusted, std::ostream & stream ) + { dumpPublicKey( id, ( trusted ? trustedKeyRing() : generalKeyRing() ), stream ); } + + PublicKey exportPublicKey( const PublicKeyData & keyData ) + { return exportKey( keyData, generalKeyRing() ); } + PublicKey exportTrustedPublicKey( const PublicKeyData & keyData ) + { return exportKey( keyData, trustedKeyRing() ); } bool verifyFileSignatureWorkflow( - const Pathname &file, - const string filedesc, - const Pathname &signature, - const KeyContext &keycontext = KeyContext()); + const Pathname & file, + const std::string & filedesc, + const Pathname & signature, + const KeyContext & keycontext = KeyContext()); + + bool verifyFileSignature( const Pathname & file, const Pathname & signature ) + { return verifyFile( file, signature, generalKeyRing() ); } + bool verifyFileTrustedSignature( const Pathname & file, const Pathname & signature ) + { return verifyFile( file, signature, trustedKeyRing() ); } - bool verifyFileSignature( const Pathname &file, const Pathname &signature); - bool verifyFileTrustedSignature( const Pathname &file, const Pathname &signature); private: - //mutable map translations; - bool verifyFile( const Pathname &file, const Pathname &signature, const Pathname &keyring); - void importKey( const Pathname &keyfile, const Pathname &keyring); - PublicKey exportKey( string id, const Pathname &keyring); - void dumpPublicKey( const string &id, const Pathname &keyring, ostream &stream ); - void deleteKey( const string &id, const Pathname &keyring ); + bool verifyFile( const Pathname & file, const Pathname & signature, const Pathname & keyring ); + void importKey( const Pathname & keyfile, const Pathname & keyring ); - list publicKeys(const Pathname &keyring); - list publicKeyIds(const Pathname &keyring); + PublicKey exportKey( const std::string & id, const Pathname & keyring ); + PublicKey exportKey( const PublicKeyData & keyData, const Pathname & keyring ); - bool publicKeyExists( string id, const Pathname &keyring); + void dumpPublicKey( const std::string & id, const Pathname & keyring, std::ostream & stream ); + filesystem::TmpFile dumpPublicKeyToTmp( const std::string & id, const Pathname & keyring ); - const Pathname generalKeyRing() const; - const Pathname trustedKeyRing() const; + void deleteKey( const std::string & id, const Pathname & keyring ); + + std::list publicKeys( const Pathname & keyring); + const std::list & publicKeyData( const Pathname & keyring ) + { return cachedPublicKeyData( keyring ); } + + /** Get \ref PublicKeyData for ID (\c false if ID is not found). */ + PublicKeyData publicKeyExists( const std::string & id, const Pathname & keyring ); + + const Pathname generalKeyRing() const + { return _general_tmp_dir.path(); } + const Pathname trustedKeyRing() const + { return _trusted_tmp_dir.path(); } // Used for trusted and untrusted keyrings - TmpDir _trusted_tmp_dir; - TmpDir _general_tmp_dir; + filesystem::TmpDir _trusted_tmp_dir; + filesystem::TmpDir _general_tmp_dir; Pathname _base_dir; + + private: + /** Functor returning the keyrings data (cached). + * \code + * const std::list & cachedPublicKeyData( const Pathname & keyring ); + * \endcode + */ + CachedPublicKeyData cachedPublicKeyData; + public: /** Offer default Impl. */ static shared_ptr nullimpl() { - static shared_ptr _nullimpl( new Impl( TmpPath::defaultLocation() ) ); + static shared_ptr _nullimpl( new Impl( filesystem::TmpPath::defaultLocation() ) ); return _nullimpl; } @@ -152,27 +263,18 @@ namespace zypp Impl * clone() const { return new Impl( *this ); } }; + /////////////////////////////////////////////////////////////////// - const Pathname KeyRing::Impl::generalKeyRing() const - { - return _general_tmp_dir.path(); - } - - const Pathname KeyRing::Impl::trustedKeyRing() const - { - return _trusted_tmp_dir.path(); - } - - void KeyRing::Impl::importKey( const PublicKey &key, bool trusted) + void KeyRing::Impl::importKey( const PublicKey & key, bool trusted ) { - callback::SendReport rpmdbEmitSignal; - callback::SendReport emitSignal; - importKey( key.path(), trusted ? trustedKeyRing() : generalKeyRing() ); if ( trusted ) { + callback::SendReport rpmdbEmitSignal; + callback::SendReport emitSignal; + rpmdbEmitSignal->trustedKeyAdded( key ); emitSignal->trustedKeyAdded( key ); } @@ -183,13 +285,13 @@ namespace zypp importKey( keyfile_r, trusted_r ? trustedKeyRing() : generalKeyRing() ); } - void KeyRing::Impl::deleteKey( const string &id, bool trusted) + void KeyRing::Impl::deleteKey( const std::string & id, bool trusted ) { PublicKey key; - if (trusted) + if ( trusted ) { - key = exportKey(id, trustedKeyRing()); + key = exportKey( id, trustedKeyRing() ); } deleteKey( id, trusted ? trustedKeyRing() : generalKeyRing() ); @@ -204,136 +306,84 @@ namespace zypp } } - list KeyRing::Impl::publicKeys() - { - return publicKeys( generalKeyRing() ); - } - - list KeyRing::Impl::trustedPublicKeys() - { - return publicKeys( trustedKeyRing() ); - } - - list KeyRing::Impl::publicKeyIds() - { - return publicKeyIds( generalKeyRing() ); - } - - list KeyRing::Impl::trustedPublicKeyIds() - { - return publicKeyIds( trustedKeyRing() ); - } - - bool KeyRing::Impl::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature) - { - return verifyFile( file, signature, trustedKeyRing() ); - } - - bool KeyRing::Impl::verifyFileSignature( const Pathname &file, const Pathname &signature) - { - return verifyFile( file, signature, generalKeyRing() ); - } - - bool KeyRing::Impl::isKeyTrusted( const string &id) - { - return publicKeyExists( id, trustedKeyRing() ); - } - - bool KeyRing::Impl::isKeyKnown( const string &id ) - { - MIL << endl; - if ( publicKeyExists( id, trustedKeyRing() ) ) - return true; - else - return publicKeyExists( id, generalKeyRing() ); - } - - bool KeyRing::Impl::publicKeyExists( string id, const Pathname &keyring) + PublicKeyData KeyRing::Impl::publicKeyExists( const std::string & id, const Pathname & keyring ) { MIL << "Searching key [" << id << "] in keyring " << keyring << endl; - list keys = publicKeys(keyring); - for (list::const_iterator it = keys.begin(); it != keys.end(); it++) + const std::list & keys( publicKeyData( keyring ) ); + for_( it, keys.begin(), keys.end() ) { if ( id == (*it).id() ) - - return true; + { + return *it; + } } - return false; + return PublicKeyData(); } - PublicKey KeyRing::Impl::exportKey( string id, const Pathname &keyring) + PublicKey KeyRing::Impl::exportKey( const PublicKeyData & keyData, const Pathname & keyring ) { - TmpFile tmp_file( _base_dir, "pubkey-"+id+"-" ); - MIL << "Going to export key " << id << " from " << keyring << " to " << tmp_file.path() << endl; - - try { - ofstream os(tmp_file.path().c_str()); - dumpPublicKey( id, keyring, os ); - os.close(); - return PublicKey( tmp_file ); - } - catch (BadKeyException &e) - { - ERR << "Cannot create public key " << id << " from " << keyring << " keyring to file " << e.keyFile() << endl; - // TranslatorExplanation first %s is key name, second is keyring name - // and third is keyfile name - ZYPP_THROW(Exception(boost::str(boost::format( - _("Cannot create public key %s from %s keyring to file %s")) - % id % keyring.asString() % e.keyFile().asString()))); - } - catch (exception &e) - { - ERR << "Cannot export key " << id << " from " << keyring << " keyring to file " << tmp_file.path() << endl; - } - return PublicKey(); + return PublicKey( dumpPublicKeyToTmp( keyData.id(), keyring ), keyData ); } - void KeyRing::Impl::dumpPublicKey( const string &id, bool trusted, ostream &stream ) + PublicKey KeyRing::Impl::exportKey( const std::string & id, const Pathname & keyring ) { - dumpPublicKey( id, ( trusted ? trustedKeyRing() : generalKeyRing() ), stream ); + PublicKeyData keyData( publicKeyExists( id, keyring ) ); + if ( keyData ) + return PublicKey( dumpPublicKeyToTmp( keyData.id(), keyring ), keyData ); + + // Here: key not found + WAR << "No key " << id << " to export from " << keyring << endl; + return PublicKey(); } - void KeyRing::Impl::dumpPublicKey( const string &id, const Pathname &keyring, ostream &stream ) + + void KeyRing::Impl::dumpPublicKey( const std::string & id, const Pathname & keyring, std::ostream & stream ) { const char* argv[] = { GPG_BINARY, + "-a", + "--export", + "--homedir", keyring.asString().c_str(), "--no-default-keyring", "--quiet", "--no-tty", "--no-greeting", "--no-permission-warning", "--batch", - "--homedir", - keyring.asString().c_str(), - "-a", - "--export", id.c_str(), NULL }; - ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true); - string line; - int count; - for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ ) + ExternalProgram prog( argv,ExternalProgram::Discard_Stderr, false, -1, true ); + for ( std::string line = prog.receiveLine(); !line.empty(); line = prog.receiveLine() ) { stream << line; } prog.close(); } + filesystem::TmpFile KeyRing::Impl::dumpPublicKeyToTmp( const std::string & id, const Pathname & keyring ) + { + filesystem::TmpFile tmpFile( _base_dir, "pubkey-"+id+"-" ); + MIL << "Going to export key " << id << " from " << keyring << " to " << tmpFile.path() << endl; + + std::ofstream os( tmpFile.path().c_str() ); + dumpPublicKey( id, keyring, os ); + os.close(); + return tmpFile; + } bool KeyRing::Impl::verifyFileSignatureWorkflow( - const Pathname &file, - const string filedesc, - const Pathname &signature, - const KeyContext &context) + const Pathname & file, + const std::string & filedesc, + const Pathname & signature, + const KeyContext & context ) { callback::SendReport report; - //callback::SendReport emitSignal; MIL << "Going to verify signature for " << filedesc << " ( " << file << " ) with " << signature << endl; // if signature does not exists, ask user if he wants to accept unsigned file. - if( signature.empty() || (!PathInfo(signature).isExist()) ) + if( signature.empty() || (!PathInfo( signature ).isExist()) ) { bool res = report->askUserToAcceptUnsignedFile( filedesc, context ); MIL << "User decision on unsigned file: " << res << endl; @@ -341,64 +391,69 @@ namespace zypp } // get the id of the signature - string id = readSignatureKeyId(signature); + std::string id = readSignatureKeyId( signature ); // doeskey exists in trusted keyring - if ( publicKeyExists( id, trustedKeyRing() ) ) + PublicKeyData trustedKeyData( publicKeyExists( id, trustedKeyRing() ) ); + if ( trustedKeyData ) { - PublicKey key = exportKey( id, trustedKeyRing() ); + MIL << "Key is trusted: " << trustedKeyData << endl; // lets look if there is an updated key in the // general keyring - if ( publicKeyExists( id, generalKeyRing() ) ) + PublicKeyData generalKeyData( publicKeyExists( id, generalKeyRing() ) ); + if ( generalKeyData ) { // bnc #393160: Comment #30: Compare at least the fingerprint // in case an attacker created a key the the same id. - PublicKey untkey = exportKey( id, generalKeyRing() ); - if ( untkey.fingerprint() == key.fingerprint() - && untkey.created() > key.created() ) + if ( trustedKeyData.fingerprint() == generalKeyData.fingerprint() + && trustedKeyData.created() < generalKeyData.created() ) { - MIL << "Key " << key << " was updated. Saving new version into trusted keyring." << endl; - importKey( untkey, true ); - key = untkey; - } + MIL << "Key was updated. Saving new version into trusted keyring: " << generalKeyData << endl; + importKey( exportKey( generalKeyData, generalKeyRing() ), true ); + trustedKeyData = generalKeyData = PublicKeyData(); // invalidated by import. + } } - MIL << "Key " << id << " " << key.name() << " is trusted" << endl; // it exists, is trusted, does it validates? if ( verifyFile( file, signature, trustedKeyRing() ) ) return true; else - return report->askUserToAcceptVerificationFailed( filedesc, key, context ); + { + if ( ! trustedKeyData ) // invalidated by previous import + trustedKeyData = publicKeyExists( id, trustedKeyRing() ); + return report->askUserToAcceptVerificationFailed( filedesc, exportKey( trustedKeyData, trustedKeyRing() ), context ); + } } else { - if ( publicKeyExists( id, generalKeyRing() ) ) + PublicKeyData generalKeyData( publicKeyExists( id, generalKeyRing() ) ); + if ( generalKeyData ) { - PublicKey key = exportKey( id, generalKeyRing()); + PublicKey key( exportKey( generalKeyData, generalKeyRing() ) ); MIL << "Exported key " << id << " to " << key.path() << endl; MIL << "Key " << id << " " << key.name() << " is not trusted" << endl; // ok the key is not trusted, ask the user to trust it or not - KeyRingReport::KeyTrust reply = report->askUserToAcceptKey(key, context); - if (reply == KeyRingReport::KEY_TRUST_TEMPORARILY || - reply == KeyRingReport::KEY_TRUST_AND_IMPORT) + KeyRingReport::KeyTrust reply = report->askUserToAcceptKey( key, context ); + if ( reply == KeyRingReport::KEY_TRUST_TEMPORARILY || + reply == KeyRingReport::KEY_TRUST_AND_IMPORT ) { MIL << "User wants to trust key " << id << " " << key.name() << endl; - //dumpFile(unKey.path()); + //dumpFile( unKey.path() ); - Pathname which_keyring; - if (reply == KeyRingReport::KEY_TRUST_AND_IMPORT) + Pathname whichKeyring; + if ( reply == KeyRingReport::KEY_TRUST_AND_IMPORT ) { MIL << "User wants to import key " << id << " " << key.name() << endl; importKey( key, true ); - which_keyring = trustedKeyRing(); + whichKeyring = trustedKeyRing(); } else - which_keyring = generalKeyRing(); + whichKeyring = generalKeyRing(); // emit key added - if ( verifyFile( file, signature, which_keyring ) ) + if ( verifyFile( file, signature, whichKeyring ) ) { MIL << "File signature is verified" << endl; return true; @@ -443,90 +498,23 @@ namespace zypp return false; } - list KeyRing::Impl::publicKeyIds(const Pathname &keyring) + std::list KeyRing::Impl::publicKeys( const Pathname & keyring ) { - static str::regex rxColons("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$"); - static str::regex rxColonsFpr("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$"); + const std::list & keys( publicKeyData( keyring ) ); + std::list ret; - list ids; - - const char* argv[] = + for_( it, keys.begin(), keys.end() ) { - GPG_BINARY, - "--no-default-keyring", - "--quiet", - "--list-public-keys", - "--with-colons", - "--with-fingerprint", - "--no-tty", - "--no-greeting", - "--batch", - "--status-fd", - "1", - "--homedir", - keyring.asString().c_str(), - NULL - }; - - ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true); - string line; - int count = 0; - - for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ ) - { - //MIL << line << endl; - str::smatch what; - if(str::regex_match(line, what, rxColons)) - { - string id; - string fingerprint; - if ( what[1] == "pub" ) - { - id = what[5]; - - string line2; - for(line2 = prog.receiveLine(); !line2.empty(); line2 = prog.receiveLine(), count++ ) - { - str::smatch what2; - if (str::regex_match(line2, what2, rxColonsFpr)) - { - if ( (what2[1] == "fpr") && (what2[1] != "pub") && (what2[1] !="sub")) - { - fingerprint = what2[10]; - break; - } - } - } - - ids.push_back(id); - MIL << "Found key " << "[" << id << "]" << endl; - } - //dumpRegexpResults(what); - } - } - prog.close(); - return ids; - } - - list KeyRing::Impl::publicKeys(const Pathname &keyring) - { - - list keys; - - list ids = publicKeyIds(keyring); - - for ( list::const_iterator it = ids.begin(); it != ids.end(); ++it ) - { - PublicKey key(exportKey( *it, keyring )); - keys.push_back(key); - MIL << "Found key " << "[" << key.id() << "]" << " [" << key.name() << "]" << " [" << key.fingerprint() << "]" << endl; + PublicKey key( exportKey( *it, keyring ) ); + ret.push_back( key ); + MIL << "Found key " << key << endl; } - return keys; + return ret; } - void KeyRing::Impl::importKey( const Pathname &keyfile, const Pathname &keyring) + void KeyRing::Impl::importKey( const Pathname & keyfile, const Pathname & keyring ) { - if ( ! PathInfo(keyfile).isExist() ) + if ( ! PathInfo( keyfile ).isExist() ) // TranslatorExplanation first %s is key name, second is keyring name ZYPP_THROW(KeyRingException(boost::str(boost::format( _("Tried to import not existent key %s into keyring %s")) @@ -535,44 +523,40 @@ namespace zypp const char* argv[] = { GPG_BINARY, + "--import", + "--homedir", keyring.asString().c_str(), "--no-default-keyring", "--quiet", "--no-tty", "--no-greeting", "--no-permission-warning", - "--status-fd", - "1", - "--homedir", - keyring.asString().c_str(), - "--import", + "--status-fd", "1", keyfile.asString().c_str(), NULL }; - ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true); + ExternalProgram prog( argv,ExternalProgram::Discard_Stderr, false, -1, true ); prog.close(); } - void KeyRing::Impl::deleteKey( const string &id, const Pathname &keyring ) + void KeyRing::Impl::deleteKey( const std::string & id, const Pathname & keyring ) { const char* argv[] = { GPG_BINARY, + "--delete-keys", + "--homedir", keyring.asString().c_str(), "--no-default-keyring", "--yes", "--quiet", "--no-tty", "--batch", - "--status-fd", - "1", - "--homedir", - keyring.asString().c_str(), - "--delete-keys", + "--status-fd", "1", id.c_str(), NULL }; - ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true); + ExternalProgram prog( argv,ExternalProgram::Discard_Stderr, false, -1, true ); int code = prog.close(); if ( code ) @@ -582,51 +566,49 @@ namespace zypp } - string KeyRing::Impl::readSignatureKeyId(const Pathname &signature ) + std::string KeyRing::Impl::readSignatureKeyId( const Pathname & signature ) { - if ( ! PathInfo(signature).isFile() ) + if ( ! PathInfo( signature ).isFile() ) ZYPP_THROW(Exception(boost::str(boost::format( _("Signature file %s not found"))% signature.asString()))); MIL << "Determining key id if signature " << signature << endl; // HACK create a tmp keyring with no keys - TmpDir dir(_base_dir, "fake-keyring"); + filesystem::TmpDir dir( _base_dir, "fake-keyring" ); const char* argv[] = { GPG_BINARY, + "--homedir", dir.path().asString().c_str(), "--no-default-keyring", "--quiet", "--no-tty", "--no-greeting", "--batch", - "--status-fd", - "1", - "--homedir", - dir.path().asString().c_str(), + "--status-fd", "1", signature.asString().c_str(), NULL }; - ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true); + ExternalProgram prog( argv,ExternalProgram::Discard_Stderr, false, -1, true ); - string line; + std::string line; int count = 0; - str::regex rxNoKey("^\\[GNUPG:\\] NO_PUBKEY (.+)\n$"); - string id; - for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ ) + str::regex rxNoKey( "^\\[GNUPG:\\] NO_PUBKEY (.+)\n$" ); + std::string id; + for( line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ ) { //MIL << "[" << line << "]" << endl; str::smatch what; - if(str::regex_match(line, what, rxNoKey)) + if( str::regex_match( line, what, rxNoKey ) ) { if ( what.size() >= 1 ) { id = what[1]; break; } - //dumpRegexpResults(what); + //dumpRegexpResults( what ); } } @@ -640,21 +622,19 @@ namespace zypp return id; } - bool KeyRing::Impl::verifyFile( const Pathname &file, const Pathname &signature, const Pathname &keyring) + bool KeyRing::Impl::verifyFile( const Pathname & file, const Pathname & signature, const Pathname & keyring ) { const char* argv[] = { GPG_BINARY, + "--verify", + "--homedir", keyring.asString().c_str(), "--no-default-keyring", "--quiet", "--no-tty", "--batch", "--no-greeting", - "--status-fd", - "1", - "--homedir", - keyring.asString().c_str(), - "--verify", + "--status-fd", "1", signature.asString().c_str(), file.asString().c_str(), NULL @@ -670,9 +650,9 @@ namespace zypp // [GNUPG:] ERRSIG A84EDAE89C800ACA 17 2 00 1143618744 9 // [GNUPG:] NO_PUBKEY A84EDAE89C800ACA - ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true); + ExternalProgram prog( argv,ExternalProgram::Discard_Stderr, false, -1, true ); - return (prog.close() == 0) ? true : false; + return ( prog.close() == 0 ) ? true : false; } /////////////////////////////////////////////////////////////////// @@ -683,112 +663,87 @@ namespace zypp // /////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////// - // - // METHOD NAME : KeyRing::KeyRing - // METHOD TYPE : Ctor - // - KeyRing::KeyRing(const Pathname &baseTmpDir) - : _pimpl( new Impl(baseTmpDir) ) + KeyRing::KeyRing( const Pathname & baseTmpDir ) + : _pimpl( new Impl( baseTmpDir ) ) {} - /////////////////////////////////////////////////////////////////// - // - // METHOD NAME : KeyRing::KeyRing - // METHOD TYPE : Ctor - // - //KeyRing::KeyRing( const Pathname &general_kr, const Pathname &trusted_kr ) - //: _pimpl( new Impl(general_kr, trusted_kr) ) - //{} - - /////////////////////////////////////////////////////////////////// - // - // METHOD NAME : KeyRing::~KeyRing - // METHOD TYPE : Dtor - // KeyRing::~KeyRing() {} - /////////////////////////////////////////////////////////////////// - // - // Forward to implementation: - // - /////////////////////////////////////////////////////////////////// - - void KeyRing::importKey( const PublicKey &key, bool trusted ) - { - _pimpl->importKey( key, trusted ); - } + void KeyRing::importKey( const PublicKey & key, bool trusted ) + { _pimpl->importKey( key, trusted ); } void KeyRing::multiKeyImport( const Pathname & keyfile_r, bool trusted_r ) - { - _pimpl->multiKeyImport( keyfile_r, trusted_r ); - } + { _pimpl->multiKeyImport( keyfile_r, trusted_r ); } - string KeyRing::readSignatureKeyId( const Pathname &signature ) - { - return _pimpl->readSignatureKeyId(signature); - } + std::string KeyRing::readSignatureKeyId( const Pathname & signature ) + { return _pimpl->readSignatureKeyId( signature ); } - void KeyRing::deleteKey( const string &id, bool trusted ) - { - _pimpl->deleteKey(id, trusted); - } + void KeyRing::deleteKey( const std::string & id, bool trusted ) + { _pimpl->deleteKey( id, trusted ); } - list KeyRing::publicKeys() - { - return _pimpl->publicKeys(); - } + std::list KeyRing::publicKeys() + { return _pimpl->publicKeys(); } - list KeyRing::trustedPublicKeys() - { - return _pimpl->trustedPublicKeys(); - } + std:: list KeyRing::trustedPublicKeys() + { return _pimpl->trustedPublicKeys(); } + + std::list KeyRing::publicKeyData() + { return _pimpl->publicKeyData(); } - list KeyRing::publicKeyIds() + std::list KeyRing::trustedPublicKeyData() + { return _pimpl->trustedPublicKeyData(); } + + std::list KeyRing::publicKeyIds() // deprecated: use publicKeyData { - return _pimpl->publicKeyIds(); + const std::list & keys( publicKeyData() ); + std::list ret; + for_( it, keys.begin(), keys.end() ) + { + ret.push_back( (*it).id() ); + } + return ret; } - list KeyRing::trustedPublicKeyIds() + std::list KeyRing::trustedPublicKeyIds() // deprecated: use trustedPublicKeyData { - return _pimpl->trustedPublicKeyIds(); + const std::list & keys( trustedPublicKeyData() ); + std::list ret; + for_( it, keys.begin(), keys.end() ) + { + ret.push_back( (*it).id() ); + } + return ret; } bool KeyRing::verifyFileSignatureWorkflow( - const Pathname &file, - const string filedesc, - const Pathname &signature, - const KeyContext &keycontext) - { - return _pimpl->verifyFileSignatureWorkflow(file, filedesc, signature, keycontext); - } + const Pathname & file, + const std::string filedesc, + const Pathname & signature, + const KeyContext & keycontext ) + { return _pimpl->verifyFileSignatureWorkflow( file, filedesc, signature, keycontext ); } - bool KeyRing::verifyFileSignature( const Pathname &file, const Pathname &signature) - { - return _pimpl->verifyFileSignature(file, signature); - } + bool KeyRing::verifyFileSignature( const Pathname & file, const Pathname & signature ) + { return _pimpl->verifyFileSignature( file, signature ); } - bool KeyRing::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature) - { - return _pimpl->verifyFileTrustedSignature(file, signature); - } + bool KeyRing::verifyFileTrustedSignature( const Pathname & file, const Pathname & signature ) + { return _pimpl->verifyFileTrustedSignature( file, signature ); } - void KeyRing::dumpPublicKey( const string &id, bool trusted, ostream &stream ) - { - _pimpl->dumpPublicKey( id, trusted, stream); - } + void KeyRing::dumpPublicKey( const std::string & id, bool trusted, std::ostream & stream ) + { _pimpl->dumpPublicKey( id, trusted, stream ); } - bool KeyRing::isKeyTrusted( const string &id ) - { - return _pimpl->isKeyTrusted(id); - } + PublicKey KeyRing::exportPublicKey( const PublicKeyData & keyData ) + { return _pimpl->exportPublicKey( keyData ); } - bool KeyRing::isKeyKnown( const string &id ) - { - return _pimpl->isKeyKnown(id); - } + PublicKey KeyRing::exportTrustedPublicKey( const PublicKeyData & keyData ) + { return _pimpl->exportTrustedPublicKey( keyData ); } + + bool KeyRing::isKeyTrusted( const std::string & id ) + { return _pimpl->isKeyTrusted( id ); } + + bool KeyRing::isKeyKnown( const std::string & id ) + { return _pimpl->isKeyKnown( id ); } ///////////////////////////////////////////////////////////////// } // namespace zypp diff --git a/zypp/KeyRing.h b/zypp/KeyRing.h index c5ce8a7..a1ad0cb 100644 --- a/zypp/KeyRing.h +++ b/zypp/KeyRing.h @@ -188,6 +188,12 @@ namespace zypp void dumpPublicKey( const std::string &id, bool trusted, std::ostream &stream ); + /** Export a public key identified by its key data. */ + PublicKey exportPublicKey( const PublicKeyData & keyData ); + + /** Export a trusted public key identified by its key data. */ + PublicKey exportTrustedPublicKey( const PublicKeyData & keyData ); + /** * reads the public key id from a signature */ @@ -196,7 +202,7 @@ namespace zypp /** * true if the key id is trusted */ - bool isKeyTrusted( const std::string &id); + bool isKeyTrusted( const std::string &id ); /** * true if the key id is knows, that means @@ -208,27 +214,39 @@ namespace zypp * removes a key from the keyring. * If trusted is true, Remove it from trusted keyring too. */ - void deleteKey( const std::string &id, bool trusted = false); + void deleteKey( const std::string &id, bool trusted = false ); /** - * Get a list of public keys in the keyring + * Get a list of public keys in the keyring (incl. ASCII armored keys in tmpfiles) */ std::list publicKeys(); /** - * Get a list of trusted public keys in the keyring + * Get a list of trusted public keys in the keyring (incl. ASCII armored keys in tmpfiles) */ std::list trustedPublicKeys(); /** + * Get a list of public key data in the keyring (key data only) + */ + std::list publicKeyData(); + + /** + * Get a list of trusted public key data in the keyring (key data only) + */ + std::list trustedPublicKeyData(); + + /** * Get a list of public key ids in the keyring + * \deprecated \ref publicKeyData is cheaper to retrieve and contains more key data */ - std::list publicKeyIds(); + std::list publicKeyIds() ZYPP_DEPRECATED; /** * Get a list of trusted public key ids in the keyring + * \deprecated \ref trustedPublicKeyData is cheaper to retrieve and contains more key data */ - std::list trustedPublicKeyIds(); + std::list trustedPublicKeyIds() ZYPP_DEPRECATED; /** * Follows a signature verification interacting with the user. @@ -267,9 +285,9 @@ namespace zypp * \param file Path of the file to be verified * \param signature Signature to verify the file against */ - bool verifyFileSignature( const Pathname &file, const Pathname &signature); + bool verifyFileSignature( const Pathname &file, const Pathname &signature ); - bool verifyFileTrustedSignature( const Pathname &file, const Pathname &signature); + bool verifyFileTrustedSignature( const Pathname &file, const Pathname &signature ); /** Dtor */ ~KeyRing(); -- 2.7.4