#include <cstdio>
#include <unistd.h>
-#include <boost/format.hpp>
-
#include "zypp/TmpPath.h"
#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"
+#include "zypp/ZYppCallbacks.h" // JobReport::instance
+#include "zypp/KeyManager.h"
-using namespace std;
-using namespace zypp::filesystem;
+using std::endl;
#undef ZYPP_BASE_LOGGER_LOGGROUP
#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::KeyRing"
-#define GPG_BINARY "/usr/bin/gpg2"
-
///////////////////////////////////////////////////////////////////
namespace zypp
{ /////////////////////////////////////////////////////////////////
_keyRingDefaultAccept = value_r;
}
- bool KeyRingReport::askUserToAcceptUnsignedFile( const string &file, const KeyContext &keycontext )
+ void KeyRingReport::infoVerify( const std::string & file_r, const PublicKeyData & keyData_r, 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;
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<PublicKeyData> & cachedPublicKeyData( const Pathname & keyring );
+ /// \endcode
+ ///////////////////////////////////////////////////////////////////
+ struct CachedPublicKeyData : private base::NonCopyable
+ {
+ const std::list<PublicKeyData> & operator()( const Pathname & keyring_r ) const
+ { return getData( keyring_r ); }
+
+ void setDirty( const Pathname & keyring_r )
+ { _cacheMap[keyring_r].setDirty(); }
+
+ private:
+ struct Cache
+ {
+ Cache() {}
+
+ void setDirty()
+ {
+ _keyringK.reset();
+ _keyringP.reset();
+ }
+
+ void assertCache( const Pathname & keyring_r )
+ {
+ // .kbx since gpg2-2.1
+ if ( !_keyringK )
+ _keyringK.reset( new WatchFile( keyring_r/"pubring.kbx", WatchFile::NO_INIT ) );
+ if ( !_keyringP )
+ _keyringP.reset( new WatchFile( keyring_r/"pubring.gpg", WatchFile::NO_INIT ) );
+ }
+
+ bool hasChanged() const
+ {
+ bool k = _keyringK->hasChanged(); // be sure both files are checked
+ bool p = _keyringP->hasChanged();
+ return k || p;
+ }
+
+ std::list<PublicKeyData> _data;
+
+ private:
+ scoped_ptr<WatchFile> _keyringK;
+ scoped_ptr<WatchFile> _keyringP;
+ };
+
+ typedef std::map<Pathname,Cache> CacheMap;
+
+ const std::list<PublicKeyData> & getData( const Pathname & keyring_r ) const
+ {
+ Cache & cache( _cacheMap[keyring_r] );
+ // init new cache entry
+ cache.assertCache( keyring_r );
+ return getData( keyring_r, cache );
+ }
+
+ const std::list<PublicKeyData> & getData( const Pathname & keyring_r, Cache & cache_r ) const
+ {
+ if ( cache_r.hasChanged() ) {
+ shared_ptr<KeyManagerCtx> ctx = KeyManagerCtx::createForOpenPGP();
+ if (ctx) {
+ if (ctx->setHomedir(keyring_r)) {
+ std::list<PublicKeyData> foundKeys = ctx->listKeys();
+ cache_r._data.swap(foundKeys);
+ }
+ }
+ MIL << "Found keys: " << cache_r._data << endl;
+ }
+ return cache_r._data;
+ }
+
+ mutable CacheMap _cacheMap;
+ };
+ ///////////////////////////////////////////////////////////////////
+ }
+
///////////////////////////////////////////////////////////////////
//
// CLASS NAME : KeyRing::Impl
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<PublicKey> trustedPublicKeys();
- list<PublicKey> publicKeys();
+ std::list<PublicKey> trustedPublicKeys()
+ { return publicKeys( trustedKeyRing() ); }
+ std::list<PublicKey> publicKeys()
+ { return publicKeys( generalKeyRing() ); }
- list<string> trustedPublicKeyIds();
- list<string> publicKeyIds();
+ const std::list<PublicKeyData> & trustedPublicKeyData()
+ { return publicKeyData( trustedKeyRing() ); }
+ const std::list<PublicKeyData> & 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 ); }
- bool verifyFileSignatureWorkflow(
- const Pathname &file,
- const string filedesc,
- const Pathname &signature,
- const KeyContext &keycontext = KeyContext());
+ PublicKey exportPublicKey( const PublicKeyData & keyData )
+ { return exportKey( keyData, generalKeyRing() ); }
+ PublicKey exportTrustedPublicKey( const PublicKeyData & keyData )
+ { return exportKey( keyData, trustedKeyRing() ); }
+
+ bool verifyFileSignatureWorkflow( const Pathname & file, const std::string & filedesc, const Pathname & signature, bool & sigValid_r, 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<Locale, string> 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 );
+
+ PublicKey exportKey( const std::string & id, const Pathname & keyring );
+ PublicKey exportKey( const PublicKeyData & keyData, const Pathname & keyring );
+ PublicKey exportKey( const PublicKey & key, const Pathname & keyring )
+ { return exportKey( key.keyData(), keyring ); }
+
+ void dumpPublicKey( const std::string & id, const Pathname & keyring, std::ostream & stream );
+ filesystem::TmpFile dumpPublicKeyToTmp( const std::string & id, const Pathname & keyring );
- list<PublicKey> publicKeys(const Pathname &keyring);
- list<string> publicKeyIds(const Pathname &keyring);
+ void deleteKey( const std::string & id, const Pathname & keyring );
- bool publicKeyExists( string id, const Pathname &keyring);
+ std::list<PublicKey> publicKeys( const Pathname & keyring);
+ const std::list<PublicKeyData> & publicKeyData( const Pathname & keyring )
+ { return cachedPublicKeyData( keyring ); }
- const Pathname generalKeyRing() const;
- const Pathname trustedKeyRing() const;
+ /** 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;
- public:
- /** Offer default Impl. */
- static shared_ptr<Impl> nullimpl()
- {
- static shared_ptr<Impl> _nullimpl( new Impl( TmpPath::defaultLocation() ) );
- return _nullimpl;
- }
private:
- friend Impl * rwcowClone<Impl>( const Impl * rhs );
- /** clone for RWCOW_pointer */
- Impl * clone() const
- { return new Impl( *this ); }
+ /** Functor returning the keyrings data (cached).
+ * \code
+ * const std::list<PublicKeyData> & cachedPublicKeyData( const Pathname & keyring );
+ * \endcode
+ */
+ CachedPublicKeyData cachedPublicKeyData;
};
+ ///////////////////////////////////////////////////////////////////
-
- const Pathname KeyRing::Impl::generalKeyRing() const
+ namespace
{
- return _general_tmp_dir.path();
- }
+ /// Handle signal emission from within KeyRing::Impl::importKey
+ struct ImportKeyCBHelper
+ {
+ void operator()( const PublicKey & key_r )
+ {
+ try {
+ _rpmdbEmitSignal->trustedKeyAdded( key_r );
+ _emitSignal->trustedKeyAdded( key_r );
+ }
+ catch ( const Exception & excp )
+ {
+ ERR << "Could not import key into rpmdb: " << excp << endl;
+ // TODO: JobReport as hotfix for bsc#1057188; should bubble up and go through some callback
+ JobReport::error( excp.asUserHistory() );
+ }
+ }
- const Pathname KeyRing::Impl::trustedKeyRing() const
- {
- return _trusted_tmp_dir.path();
- }
+ private:
+ callback::SendReport<target::rpm::KeyRingSignals> _rpmdbEmitSignal;
+ callback::SendReport<KeyRingSignals> _emitSignal;
+ };
+ } // namespace
- void KeyRing::Impl::importKey( const PublicKey &key, bool trusted)
- {
- callback::SendReport<target::rpm::KeyRingSignals> rpmdbEmitSignal;
- callback::SendReport<KeyRingSignals> emitSignal;
+ void KeyRing::Impl::importKey( const PublicKey & key, bool trusted )
+ {
importKey( key.path(), trusted ? trustedKeyRing() : generalKeyRing() );
+ MIL << "Imported key " << key << " to " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
if ( trusted )
{
- rpmdbEmitSignal->trustedKeyAdded( key );
- emitSignal->trustedKeyAdded( key );
+ ImportKeyCBHelper emitSignal;
+ if ( key.hiddenKeys().empty() )
+ {
+ emitSignal( key );
+ }
+ else
+ {
+ // multiple keys: Export individual keys ascii armored to import in rpmdb
+ emitSignal( exportKey( key, trustedKeyRing() ) );
+ for ( const PublicKeyData & hkey : key.hiddenKeys() )
+ emitSignal( exportKey( hkey, trustedKeyRing() ) );
+ }
}
}
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)
+ PublicKeyData keyDataToDel( publicKeyExists( id, trusted ? trustedKeyRing() : generalKeyRing() ) );
+ if ( ! keyDataToDel )
{
- key = exportKey(id, trustedKeyRing());
+ WAR << "Key to delete [" << id << "] is not in " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
+ return;
}
-
deleteKey( id, trusted ? trustedKeyRing() : generalKeyRing() );
+ MIL << "Deleted key [" << id << "] from " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
if ( trusted )
- {
- callback::SendReport<target::rpm::KeyRingSignals> rpmdbEmitSignal;
- callback::SendReport<KeyRingSignals> emitSignal;
+ try {
+ PublicKey key( keyDataToDel );
+ callback::SendReport<target::rpm::KeyRingSignals> rpmdbEmitSignal;
rpmdbEmitSignal->trustedKeyRemoved( key );
+
+ callback::SendReport<KeyRingSignals> emitSignal;
emitSignal->trustedKeyRemoved( key );
}
+ catch ( const Exception & excp )
+ {
+ ERR << "Could not delete key from rpmmdb: " << excp << endl;
+ // TODO: JobReport as hotfix for bsc#1057188; should bubble up and go through some callback
+ JobReport::error( excp.asUserHistory() );
+ }
}
- list<PublicKey> KeyRing::Impl::publicKeys()
- {
- return publicKeys( generalKeyRing() );
- }
-
- list<PublicKey> KeyRing::Impl::trustedPublicKeys()
- {
- return publicKeys( trustedKeyRing() );
- }
-
- list<string> KeyRing::Impl::publicKeyIds()
- {
- return publicKeyIds( generalKeyRing() );
- }
-
- list<string> KeyRing::Impl::trustedPublicKeyIds()
+ PublicKeyData KeyRing::Impl::publicKeyExists( const std::string & id, const Pathname & keyring )
{
- return publicKeyIds( trustedKeyRing() );
+ PublicKeyData ret;
+ for ( const PublicKeyData & key : publicKeyData( keyring ) )
+ {
+ if ( key.providesKey( id ) )
+ {
+ ret = key;
+ break;
+ }
+ }
+ MIL << (ret ? "Found" : "No") << " key [" << id << "] in keyring " << keyring << endl;
+ return ret;
}
- bool KeyRing::Impl::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature)
+ PublicKey KeyRing::Impl::exportKey( const PublicKeyData & keyData, const Pathname & keyring )
{
- return verifyFile( file, signature, trustedKeyRing() );
+ return PublicKey( dumpPublicKeyToTmp( keyData.id(), keyring ), keyData );
}
- bool KeyRing::Impl::verifyFileSignature( const Pathname &file, const Pathname &signature)
+ PublicKey KeyRing::Impl::exportKey( const std::string & id, const Pathname & keyring )
{
- return verifyFile( file, signature, generalKeyRing() );
- }
+ PublicKeyData keyData( publicKeyExists( id, keyring ) );
+ if ( keyData )
+ return PublicKey( dumpPublicKeyToTmp( keyData.id(), keyring ), keyData );
- bool KeyRing::Impl::isKeyTrusted( const string &id)
- {
- return publicKeyExists( id, trustedKeyRing() );
+ // Here: key not found
+ WAR << "No key [" << id << "] to export from " << keyring << endl;
+ return PublicKey();
}
- 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)
+ void KeyRing::Impl::dumpPublicKey( const std::string & id, const Pathname & keyring, std::ostream & stream )
{
- MIL << "Searching key [" << id << "] in keyring " << keyring << endl;
- list<PublicKey> keys = publicKeys(keyring);
- for (list<PublicKey>::const_iterator it = keys.begin(); it != keys.end(); it++)
- {
- if ( id == (*it).id() )
-
- return true;
- }
- return false;
+ KeyManagerCtx::Ptr ctx = KeyManagerCtx::createForOpenPGP();
+ if (!ctx || !ctx->setHomedir(keyring))
+ return;
+ ctx->exportKey(id, stream);
}
- PublicKey KeyRing::Impl::exportKey( string id, const Pathname &keyring)
+ filesystem::TmpFile KeyRing::Impl::dumpPublicKeyToTmp( const std::string & id, 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();
- }
+ filesystem::TmpFile tmpFile( _base_dir, "pubkey-"+id+"-" );
+ MIL << "Going to export key [" << id << "] from " << keyring << " to " << tmpFile.path() << endl;
- void KeyRing::Impl::dumpPublicKey( const string &id, bool trusted, ostream &stream )
- {
- dumpPublicKey( id, ( trusted ? trustedKeyRing() : generalKeyRing() ), stream );
+ std::ofstream os( tmpFile.path().c_str() );
+ dumpPublicKey( id, keyring, os );
+ os.close();
+ return tmpFile;
}
- void KeyRing::Impl::dumpPublicKey( const string &id, const Pathname &keyring, ostream &stream )
+ bool KeyRing::Impl::verifyFileSignatureWorkflow( const Pathname & file, const std::string & filedesc, const Pathname & signature, bool & sigValid_r, const KeyContext & context )
{
- const char* argv[] =
- {
- GPG_BINARY,
- "--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++ )
- {
- stream << line;
- }
- prog.close();
- }
+ sigValid_r = false; // set true if signature is actually successfully validated!
-
- bool KeyRing::Impl::verifyFileSignatureWorkflow(
- const Pathname &file,
- const string filedesc,
- const Pathname &signature,
- const KeyContext &context)
- {
callback::SendReport<KeyRingReport> report;
- //callback::SendReport<KeyRingSignals> 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;
+ MIL << "askUserToAcceptUnsignedFile: " << res << endl;
return res;
}
- // get the id of the signature
- string id = readSignatureKeyId(signature);
+ // get the id of the signature (it might be a subkey id!)
+ std::string id = readSignatureKeyId( signature );
- // doeskey exists in trusted keyring
- if ( publicKeyExists( id, trustedKeyRing() ) )
+ // does key exists in trusted keyring
+ 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() )
+ //
+ // FIXME: bsc#1008325: For keys using subkeys, we'd actually need
+ // to compare the subkey sets, to tell whether a key was updated.
+ // because created() remains unchanged if the primary key is not touched.
+ // For now we wait until a new subkey signs the data and treat it as a
+ // new key (else part below).
+ 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 = publicKeyExists( id, trustedKeyRing() ); // re-read: invalidated by import?
+ }
}
- MIL << "Key " << id << " " << key.name() << " is trusted" << endl;
- // it exists, is trusted, does it validates?
+ // it exists, is trusted, does it validate?
+ report->infoVerify( filedesc, trustedKeyData, context );
if ( verifyFile( file, signature, trustedKeyRing() ) )
- return true;
+ {
+ return (sigValid_r=true); // signature is actually successfully validated!
+ }
else
- return report->askUserToAcceptVerificationFailed( filedesc, key, context );
+ {
+ bool res = report->askUserToAcceptVerificationFailed( filedesc, exportKey( trustedKeyData, trustedKeyRing() ), context );
+ MIL << "askUserToAcceptVerificationFailed: " << res << endl;
+ return res;
+ }
}
else
{
- if ( publicKeyExists( id, generalKeyRing() ) )
+ PublicKeyData generalKeyData( publicKeyExists( id, generalKeyRing() ) );
+ if ( generalKeyData )
{
- PublicKey key = exportKey( id, generalKeyRing());
- MIL << "Exported key " << id << " to " << key.path() << endl;
- MIL << "Key " << id << " " << key.name() << " is not trusted" << endl;
+ PublicKey key( exportKey( generalKeyData, generalKeyRing() ) );
+ 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());
+ MIL << "User wants to trust key [" << id << "] " << key.name() << endl;
- 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;
+ 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 ) )
+ // does it validate?
+ report->infoVerify( filedesc, generalKeyData, context );
+ if ( verifyFile( file, signature, whichKeyring ) )
{
- MIL << "File signature is verified" << endl;
- return true;
+ return (sigValid_r=true); // signature is actually successfully validated!
}
else
{
- MIL << "File signature check fails" << endl;
- if ( report->askUserToAcceptVerificationFailed( filedesc, key, context ) )
- {
- MIL << "User continues anyway." << endl;
- return true;
- }
- else
- {
- MIL << "User does not want to continue" << endl;
- return false;
- }
+ bool res = report->askUserToAcceptVerificationFailed( filedesc, key, context );
+ MIL << "askUserToAcceptVerificationFailed: " << res << endl;
+ return res;
}
}
else
{
- MIL << "User does not want to trust key " << id << " " << key.name() << endl;
+ MIL << "User does not want to trust key [" << id << "] " << key.name() << endl;
return false;
}
}
else
{
- // unknown key...
+ // signed with an unknown key...
MIL << "File [" << file << "] ( " << filedesc << " ) signed with unknown key [" << id << "]" << endl;
- if ( report->askUserToAcceptUnknownKey( filedesc, id, context ) )
- {
- MIL << "User wants to accept unknown key " << id << endl;
- return true;
- }
- else
- {
- MIL << "User does not want to accept unknown key " << id << endl;
- return false;
- }
+ bool res = report->askUserToAcceptUnknownKey( filedesc, id, context );
+ MIL << "askUserToAcceptUnknownKey: " << res << endl;
+ return res;
}
}
return false;
}
- list<string> KeyRing::Impl::publicKeyIds(const Pathname &keyring)
- {
- static str::regex rxColons("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
- static str::regex rxColonsFpr("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
-
- list<string> ids;
-
- const char* argv[] =
- {
- 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<PublicKey> KeyRing::Impl::publicKeys(const Pathname &keyring)
+ std::list<PublicKey> KeyRing::Impl::publicKeys( const Pathname & keyring )
{
+ const std::list<PublicKeyData> & keys( publicKeyData( keyring ) );
+ std::list<PublicKey> ret;
- list<PublicKey> keys;
-
- list<string> ids = publicKeyIds(keyring);
-
- for ( list<string>::const_iterator it = ids.begin(); it != ids.end(); ++it )
+ for_( it, keys.begin(), keys.end() )
{
- 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 existant key %s into keyring %s"))
- % keyfile.asString() % keyring.asString())));
+ ZYPP_THROW(KeyRingException( str::Format(_("Tried to import not existent key %s into keyring %s"))
+ % keyfile.asString()
+ % keyring.asString() ));
- const char* argv[] =
- {
- GPG_BINARY,
- "--no-default-keyring",
- "--quiet",
- "--no-tty",
- "--no-greeting",
- "--no-permission-warning",
- "--status-fd",
- "1",
- "--homedir",
- keyring.asString().c_str(),
- "--import",
- keyfile.asString().c_str(),
- NULL
- };
+ KeyManagerCtx::Ptr ctx = KeyManagerCtx::createForOpenPGP();
+ if(!ctx || !ctx->setHomedir(keyring))
+ ZYPP_THROW(KeyRingException(_("Failed to import key.")));
- ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
- prog.close();
+ cachedPublicKeyData.setDirty( keyring );
+ if(!ctx->importKey(keyfile))
+ ZYPP_THROW(KeyRingException(_("Failed to import key.")));
}
- 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,
- "--no-default-keyring",
- "--yes",
- "--quiet",
- "--no-tty",
- "--batch",
- "--status-fd",
- "1",
- "--homedir",
- keyring.asString().c_str(),
- "--delete-keys",
- id.c_str(),
- NULL
- };
+ KeyManagerCtx::Ptr ctx = KeyManagerCtx::createForOpenPGP();
+ if(!ctx) {
+ ZYPP_THROW(KeyRingException(_("Failed to delete key.")));
+ }
- ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
+ if(!ctx->setHomedir(keyring)) {
+ ZYPP_THROW(KeyRingException(_("Failed to delete key.")));
+ }
- int code = prog.close();
- if ( code )
- ZYPP_THROW(Exception(_("Failed to delete key.")));
- else
- MIL << "Deleted key " << id << " from keyring " << keyring << endl;
- }
+ if(!ctx->deleteKey(id)){
+ ZYPP_THROW(KeyRingException(_("Failed to delete key.")));
+ }
+ cachedPublicKeyData.setDirty( keyring );
+ }
- string KeyRing::Impl::readSignatureKeyId(const Pathname &signature )
+ std::string KeyRing::Impl::readSignatureKeyId( const Pathname & signature )
{
- 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");
+ if ( ! PathInfo( signature ).isFile() )
+ ZYPP_THROW(KeyRingException( str::Format(_("Signature file %s not found")) % signature.asString() ));
- const char* argv[] =
- {
- GPG_BINARY,
- "--no-default-keyring",
- "--quiet",
- "--no-tty",
- "--no-greeting",
- "--batch",
- "--status-fd",
- "1",
- "--homedir",
- dir.path().asString().c_str(),
- signature.asString().c_str(),
- NULL
- };
-
- ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
-
- string line;
- int count = 0;
+ MIL << "Determining key id of signature " << signature << endl;
- str::regex rxNoKey("^\\[GNUPG:\\] NO_PUBKEY (.+)\n$");
- 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 ( what.size() >= 1 )
- {
- id = what[1];
- break;
- }
- //dumpRegexpResults(what);
- }
+ KeyManagerCtx::Ptr ctx = KeyManagerCtx::createForOpenPGP();
+ if(!ctx) {
+ return std::string();
}
- if ( count == 0 )
- {
- MIL << "no output" << endl;
+ std::list<std::string> fprs = ctx->readSignatureFingerprints(signature);
+ if (fprs.size()) {
+ std::string &id = fprs.back();
+ MIL << "Determined key id [" << id << "] for signature " << signature << endl;
+ return id;
}
-
- MIL << "Determined key id [" << id << "] for signature " << signature << endl;
- prog.close();
- return id;
+ return std::string();
}
- 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,
- "--no-default-keyring",
- "--quiet",
- "--no-tty",
- "--batch",
- "--no-greeting",
- "--status-fd",
- "1",
- "--homedir",
- keyring.asString().c_str(),
- "--verify",
- signature.asString().c_str(),
- file.asString().c_str(),
- NULL
- };
-
- // no need to parse output for now
- // [GNUPG:] SIG_ID yCc4u223XRJnLnVAIllvYbUd8mQ 2006-03-29 1143618744
- // [GNUPG:] GOODSIG A84EDAE89C800ACA SuSE Package Signing Key <build@suse.de>
- // gpg: Good signature from "SuSE Package Signing Key <build@suse.de>"
- // [GNUPG:] VALIDSIG 79C179B2E1C820C1890F9994A84EDAE89C800ACA 2006-03-29 1143618744 0 3 0 17 2 00 79C179B2E1C820C1890F9994A84EDAE89C800ACA
- // [GNUPG:] TRUST_UNDEFINED
+ KeyManagerCtx::Ptr ctx = KeyManagerCtx::createForOpenPGP();
+ if (!ctx || !ctx->setHomedir(keyring))
+ return false;
- // [GNUPG:] ERRSIG A84EDAE89C800ACA 17 2 00 1143618744 9
- // [GNUPG:] NO_PUBKEY A84EDAE89C800ACA
-
- ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
-
- return (prog.close() == 0) ? true : false;
+ return ctx->verify(file, signature);
}
///////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////
- //
- // 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<PublicKey> KeyRing::publicKeys()
- {
- return _pimpl->publicKeys();
- }
+ std::list<PublicKey> KeyRing::publicKeys()
+ { return _pimpl->publicKeys(); }
- list<PublicKey> KeyRing::trustedPublicKeys()
- {
- return _pimpl->trustedPublicKeys();
- }
+ std:: list<PublicKey> KeyRing::trustedPublicKeys()
+ { return _pimpl->trustedPublicKeys(); }
- list<string> KeyRing::publicKeyIds()
- {
- return _pimpl->publicKeyIds();
- }
+ std::list<PublicKeyData> KeyRing::publicKeyData()
+ { return _pimpl->publicKeyData(); }
- list<string> KeyRing::trustedPublicKeyIds()
- {
- return _pimpl->trustedPublicKeyIds();
- }
+ std::list<PublicKeyData> KeyRing::trustedPublicKeyData()
+ { return _pimpl->trustedPublicKeyData(); }
- bool KeyRing::verifyFileSignatureWorkflow(
- const Pathname &file,
- const string filedesc,
- const Pathname &signature,
- const KeyContext &keycontext)
- {
- return _pimpl->verifyFileSignatureWorkflow(file, filedesc, signature, keycontext);
- }
+ bool KeyRing::verifyFileSignatureWorkflow( const Pathname & file, const std::string & filedesc, const Pathname & signature, bool & sigValid_r, const KeyContext & keycontext )
+ { return _pimpl->verifyFileSignatureWorkflow( file, filedesc, signature, sigValid_r, keycontext ); }
- bool KeyRing::verifyFileSignature( const Pathname &file, const Pathname &signature)
- {
- return _pimpl->verifyFileSignature(file, signature);
- }
+ bool KeyRing::verifyFileSignatureWorkflow( const Pathname & file, const std::string filedesc, const Pathname & signature, const KeyContext & keycontext )
+ { bool unused; return _pimpl->verifyFileSignatureWorkflow( file, filedesc, signature, unused, keycontext ); }
- bool KeyRing::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature)
- {
- return _pimpl->verifyFileTrustedSignature(file, signature);
- }
+ bool KeyRing::verifyFileSignature( const Pathname & file, const Pathname & signature )
+ { return _pimpl->verifyFileSignature( file, signature ); }
- void KeyRing::dumpPublicKey( const string &id, bool trusted, ostream &stream )
- {
- _pimpl->dumpPublicKey( id, trusted, stream);
- }
+ bool KeyRing::verifyFileTrustedSignature( const Pathname & file, const Pathname & signature )
+ { return _pimpl->verifyFileTrustedSignature( file, signature ); }
- bool KeyRing::isKeyTrusted( const string &id )
- {
- return _pimpl->isKeyTrusted(id);
- }
+ void KeyRing::dumpPublicKey( const std::string & id, bool trusted, std::ostream & stream )
+ { _pimpl->dumpPublicKey( id, trusted, stream ); }
- bool KeyRing::isKeyKnown( const string &id )
- {
- return _pimpl->isKeyKnown(id);
- }
+ PublicKey KeyRing::exportPublicKey( const PublicKeyData & keyData )
+ { return _pimpl->exportPublicKey( keyData ); }
+
+ 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