19 #include <zypp/TmpPath.h> 23 #include <zypp/base/LogTools.h> 24 #include <zypp/base/IOStream.h> 25 #include <zypp/base/String.h> 26 #include <zypp/base/Regex.h> 27 #include <zypp/base/Gettext.h> 28 #include <zypp-core/fs/WatchFile> 29 #include <zypp/PathInfo.h> 31 #include <zypp/ExternalProgram.h> 32 #include <zypp/TmpPath.h> 38 #undef ZYPP_BASE_LOGGER_LOGGROUP 39 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::KeyRing" 53 {
return _keyRingDefaultAccept; }
57 MIL <<
"Set new KeyRing::DefaultAccept: " << value_r << endl;
58 _keyRingDefaultAccept = value_r;
86 data.
set(
"PublicKey", key_r);
87 data.
set(
"KeyContext", keycontext_r);
91 return data.
get<
bool>(
"TrustKey");
98 data.
set(
"Keys", keys_r);
107 data.set(
"KeyDataList", keyDataList_r );
108 data.set(
"KeySigning", keySigning_r );
109 data.set(
"KeyContext", keyContext_r );
124 const std::list<PublicKeyData> & operator()(
const Pathname & keyring_r )
const 125 {
return getData( keyring_r ); }
127 void setDirty(
const Pathname & keyring_r )
138 Manip( CachedPublicKeyData & cache_r, Pathname keyring_r )
162 Manip manip( Pathname keyring_r ) {
return Manip( *
this, std::move(keyring_r) ); }
175 void assertCache(
const Pathname & keyring_r )
184 bool hasChanged()
const 199 typedef std::map<Pathname,Cache> CacheMap;
201 const std::list<PublicKeyData> & getData(
const Pathname & keyring_r )
const 205 cache.assertCache( keyring_r );
206 return getData( keyring_r, cache );
209 const std::list<PublicKeyData> & getData(
const Pathname & keyring_r, Cache & cache_r )
const 211 if ( cache_r.hasChanged() ) {
213 MIL <<
"Found keys: " << cache_r._data << endl;
215 return cache_r._data;
237 MIL <<
"Current KeyRing::DefaultAccept: " << _keyRingDefaultAccept << endl;
242 void deleteKey(
const std::string &
id,
bool trusted );
261 void dumpPublicKey(
const std::string &
id,
bool trusted, std::ostream & stream )
343 struct ImportKeyCBHelper
345 void operator()(
const PublicKey & key_r )
353 ERR <<
"Could not import key into rpmdb: " << excp << endl;
369 MIL <<
"Imported key " << key <<
" to " << (trusted ?
"trustedKeyRing" :
"generalKeyRing" ) << endl;
373 ImportKeyCBHelper emitSignal;
390 importKey( keyfile_r, trusted_r ? trustedKeyRing() : generalKeyRing() );
395 PublicKeyData keyDataToDel( publicKeyExists(
id, trusted ? trustedKeyRing() : generalKeyRing() ) );
396 if ( ! keyDataToDel )
398 WAR <<
"Key to delete [" <<
id <<
"] is not in " << (trusted ?
"trustedKeyRing" :
"generalKeyRing" ) << endl;
401 deleteKey(
id, trusted ? trustedKeyRing() : generalKeyRing() );
402 MIL <<
"Deleted key [" <<
id <<
"] from " << (trusted ?
"trustedKeyRing" :
"generalKeyRing" ) << endl;
409 rpmdbEmitSignal->trustedKeyRemoved( key );
412 emitSignal->trustedKeyRemoved( key );
416 ERR <<
"Could not delete key from rpmmdb: " << excp << endl;
424 if ( _allowPreload && keyring == generalKeyRing() ) {
425 _allowPreload =
false;
432 if ( key.providesKey(
id ) )
438 DBG << (ret ?
"Found" :
"No") <<
" key [" <<
id <<
"] in keyring " << keyring << endl;
444 MIL <<
"preloadCachedKeys into general keyring..." << endl;
445 CachedPublicKeyData::Manip manip { keyRingManip( generalKeyRing() ) };
450 std::set<Pathname> cachedirs;
452 cachedirs.insert( conf.pubkeyCachePath() );
453 cachedirs.insert(
"/usr/lib/rpm/gnupg/keys" );
454 if (
Pathname r = conf.systemRoot(); r !=
"/" && not r.
empty() ) {
455 cachedirs.insert( r / conf.pubkeyCachePath() );
456 cachedirs.insert( r /
"/usr/lib/rpm/gnupg/keys" );
458 if (
Pathname r = conf.repoManagerRoot(); r !=
"/" && not r.
empty() ) {
459 cachedirs.insert( r / conf.pubkeyCachePath() );
460 cachedirs.insert( r /
"/usr/lib/rpm/gnupg/keys" );
463 std::map<std::string,Pathname> keyCandidates;
464 const str::regex rx {
"^gpg-pubkey-([[:xdigit:]]{8,})(-[[:xdigit:]]{8,})?\\.(asc|key)$" };
465 for (
const auto & cache : cachedirs ) {
467 [&rx,&keyCandidates](
const Pathname & dir_r,
const char *
const file_r )->
bool {
470 Pathname & remember { keyCandidates[what[1]] };
471 if ( remember.empty() ) {
472 remember = dir_r / file_r;
480 for (
const auto & p : keyCandidates ) {
483 const std::string &
id { p.first };
487 if ( manip.keyManagerCtx().importKey( path ) ) {
488 DBG <<
"preload key file " << path << endl;
491 WAR <<
"Skipping: Can't preload key file " << path << endl;
498 return PublicKey( dumpPublicKeyToTmp( keyData.
id(), keyring ), keyData );
505 return PublicKey( dumpPublicKeyToTmp( keyData.
id(), keyring ), keyData );
508 WAR <<
"No key [" <<
id <<
"] to export from " << keyring << endl;
521 MIL <<
"Going to export key [" <<
id <<
"] from " << keyring <<
" to " << tmpFile.
path() << endl;
523 std::ofstream os( tmpFile.
path().
c_str() );
534 const std::string & filedesc { context_r.
shortFile() };
538 MIL <<
"Going to verify signature for " << filedesc <<
" ( " << file <<
" ) with " << signature << endl;
543 bool res = report->askUserToAcceptUnsignedFile( filedesc, keyContext );
544 MIL <<
"askUserToAcceptUnsignedFile: " << res << endl;
554 std::list<PublicKeyData> buddies;
555 for (
const auto & sid : context_r.
buddyKeys() ) {
557 WAR <<
"buddy " << sid <<
": key id is too short to safely identify a gpg key. Skipping it." << endl;
560 if ( trustedPublicKeyExists( sid ) ) {
561 MIL <<
"buddy " << sid <<
": already in trusted key ring. Not needed." << endl;
564 auto pk = publicKeyExists( sid );
566 WAR <<
"buddy " << sid <<
": not available in the public key ring. Skipping it." << endl;
569 if ( pk.providesKey(
id) ) {
570 MIL <<
"buddy " << sid <<
": is the signing key. Handled separately." << endl;
573 MIL <<
"buddy " << sid <<
": candidate for auto import. Remeber it." << endl;
574 buddies.push_back( pk );
580 PublicKeyData trustedKeyData( publicKeyExists(
id, trustedKeyRing() ) );
581 if ( trustedKeyData )
583 MIL <<
"Key is trusted: " << trustedKeyData << endl;
587 PublicKeyData generalKeyData( publicKeyExists(
id, generalKeyRing() ) );
588 if ( generalKeyData )
601 MIL <<
"Key was updated. Saving new version into trusted keyring: " << generalKeyData << endl;
602 importKey( exportKey( generalKeyData, generalKeyRing() ),
true );
603 trustedKeyData = publicKeyExists(
id, trustedKeyRing() );
607 foundKey = trustedKeyData;
608 whichKeyring = trustedKeyRing();
612 PublicKeyData generalKeyData( publicKeyExists(
id, generalKeyRing() ) );
613 if ( generalKeyData )
615 PublicKey key( exportKey( generalKeyData, generalKeyRing() ) );
616 MIL <<
"Key [" <<
id <<
"] " << key.
name() <<
" is not trusted" << endl;
623 MIL <<
"User wants to trust key [" <<
id <<
"] " << key.
name() << endl;
627 MIL <<
"User wants to import key [" <<
id <<
"] " << key.
name() << endl;
629 whichKeyring = trustedKeyRing();
632 whichKeyring = generalKeyRing();
634 foundKey = generalKeyData;
638 MIL <<
"User does not want to trust key [" <<
id <<
"] " << key.
name() << endl;
642 else if ( ! keyContext.empty() )
646 whichKeyring = trustedKeyRing();
647 foundKey =
PublicKeyData( publicKeyExists(
id, trustedKeyRing() ) );
656 report->infoVerify( filedesc, foundKey, keyContext );
657 if ( verifyFile( file, signature, whichKeyring ) )
662 MIL <<
"Validated with trusted key: importing buddy list..." << endl;
663 report->reportAutoImportKey( buddies, foundKey, keyContext );
664 for (
const auto & kd : buddies ) {
665 importKey( exportKey( kd, generalKeyRing() ),
true );
672 bool res = report->askUserToAcceptVerificationFailed( filedesc, exportKey( foundKey, whichKeyring ), keyContext );
673 MIL <<
"askUserToAcceptVerificationFailed: " << res << endl;
678 MIL <<
"File [" << file <<
"] ( " << filedesc <<
" ) signed with unknown key [" <<
id <<
"]" << endl;
679 bool res = report->askUserToAcceptUnknownKey( filedesc,
id, keyContext );
680 MIL <<
"askUserToAcceptUnknownKey: " << res << endl;
711 ERR <<
"Key [" << id_r <<
"] from cache: " << cacheDir <<
" is not valid" << endl;
715 MIL <<
"Key [" << id_r <<
"] " << key.
name() <<
" loaded from cache" << endl;
719 if ( ! report->askUserToAcceptPackageKey( key, context ) ) {
723 MIL <<
"User wants to import key [" << id_r <<
"] " << key.
name() <<
" from cache" << endl;
728 ERR <<
"Failed to import key: "<<id_r;
737 const std::list<PublicKeyData> & keys(
publicKeyData( keyring ) );
738 std::list<PublicKey> ret;
740 for_( it, keys.begin(), keys.end() )
742 PublicKey key( exportKey( *it, keyring ) );
743 ret.push_back( key );
744 MIL <<
"Found key " << key << endl;
751 if ( !
PathInfo( keyfile ).isExist() )
757 CachedPublicKeyData::Manip manip { keyRingManip( keyring ) };
758 if ( ! manip.keyManagerCtx().importKey( keyfile ) )
764 CachedPublicKeyData::Manip manip { keyRingManip( keyring ) };
765 if ( ! manip.keyManagerCtx().deleteKey(
id ) )
771 if ( !
PathInfo( signature ).isFile() )
774 MIL <<
"Determining key id of signature " << signature << endl;
777 if ( ! fprs.empty() ) {
778 std::string &
id = fprs.back();
779 MIL <<
"Determined key id [" <<
id <<
"] for signature " << signature << endl;
782 return std::string();
void allowPreload(bool yesno_r)
void importKey(const PublicKey &key, bool trusted=false)
imports a key from a file.
const std::list< PublicKeyData > & publicKeyData()
bool fileValidated() const
Whether the signature was actually successfully verified.
PublicKey exportTrustedPublicKey(const PublicKeyData &keyData)
Export a trusted public key identified by its key data.
static bool isSafeKeyId(const std::string &id_r)
Whether this is a long id (64bit/16byte) or even better a fingerprint.
PublicKey exportPublicKey(const PublicKeyData &keyData)
void dumpPublicKey(const std::string &id, bool trusted, std::ostream &stream)
void deleteKey(const std::string &id, bool trusted)
PublicKey exportKey(const std::string &id, const Pathname &keyring)
static bool error(const std::string &msg_r, const UserData &userData_r=UserData())
send error text
bool isKeyTrusted(const std::string &id)
const std::list< PublicKeyData > & hiddenKeys() const
Additional keys data in case the ASCII armored blob contains multiple keys.
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
const std::list< PublicKeyData > & trustedPublicKeyData()
const PublicKeyData & keyData() const
The public keys data (.
static ZConfig & instance()
Singleton ctor.
const std::string & signatureId() const
The id of the gpg key which signed the file.
CachedPublicKeyData & _cache
PublicKey exportKey(const PublicKey &key, const Pathname &keyring)
Pathname provideKey(const std::string &keyID_r, const Pathname &targetDirectory_r) const
downloads all configured gpg keys into the defined directory
This basically means, we knew the key, but it was not trusted.
PublicKey exportPublicKey(const PublicKeyData &keyData)
Export a public key identified by its key data.
Class representing one GPG Public Keys data.
Pathname pubkeyCachePath() const
Path where the pubkey caches.
bool isKeyKnown(const std::string &id)
void reportNonImportedKeys(const std::set< Edition > &keys_r)
Notify the user about keys that were not imported from the rpm key database into zypp keyring...
void dumpPublicKey(const std::string &id, bool trusted, std::ostream &stream)
int dirForEach(const Pathname &dir_r, const StrMatcher &matcher_r, function< bool(const Pathname &, const char *const)> fnc_r)
void multiKeyImport(const Pathname &keyfile_r, bool trusted_r=false)
std::list< PublicKey > trustedPublicKeys()
Get a list of trusted public keys in the keyring (incl.
bool verifyFile(const Pathname &file, const Pathname &signature, const Pathname &keyring)
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
virtual bool askUserToAcceptUnsignedFile(const std::string &file, const KeyContext &keycontext=KeyContext())
const char * c_str() const
String representation.
KeyRing(const Pathname &baseTmpDir)
Default ctor.
What is known about a repository.
I/O context for KeyRing::verifyFileSignatureWorkflow.
std::list< PublicKeyData > trustedPublicKeyData()
Get a list of trusted public key data in the keyring (key data only)
bool verifyFileSignatureWorkflow(const Pathname &file, const std::string &filedesc, const Pathname &signature, bool &sigValid_r, const KeyContext &keycontext=KeyContext())
Follows a signature verification interacting with the user.
bool askUserToAcceptPackageKey(const PublicKey &key_r, const KeyContext &keycontext_r=KeyContext())
Ask user to trust and/or import the package key to trusted keyring, using ReportBase::report.
bool verify(const Pathname &file, const Pathname &signature)
Tries to verify file using signature, returns true on success.
static KeyManagerCtx createForOpenPGP()
Creates a new KeyManagerCtx for PGP using a volatile temp.
Provide a new empty temporary file and delete it when no longer needed.
virtual bool askUserToAcceptUnknownKey(const std::string &file, const std::string &id, const KeyContext &keycontext=KeyContext())
we DONT know the key, only its id, but we have never seen it, the difference with trust key is that i...
CachedPublicKeyData cachedPublicKeyData
Functor returning the keyrings data (cached).
callback::SendReport< target::rpm::KeyRingSignals > _rpmdbEmitSignal
bool exportKey(const std::string &id, std::ostream &stream)
Exports the key with id into the given stream, returns true on success.
virtual void infoVerify(const std::string &file_r, const PublicKeyData &keyData_r, const KeyContext &keycontext=KeyContext())
Informal callback showing the trusted key that will be used for verification.
std::optional< KeyManagerCtx > _context
const KeyContext & keyContext() const
KeyContext passed to callbacks
bool signatureIdTrusted() const
Whether the SignatureId is in the trusted keyring (not temp.
void resetResults()
Reset all result values to safe defaults.
Pathname repoManagerRoot() const
The RepoManager root directory.
bool provideAndImportKeyFromRepositoryWorkflow(const std::string &id_r, const RepoInfo &info_r)
PublicKey exportTrustedPublicKey(const PublicKeyData &keyData)
virtual void report(const UserData &userData_r=UserData())
The most generic way of sending/receiving data.
KeyTrust
User reply options for the askUserToTrustKey callback.
bool empty() const
Test for an empty path.
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Date created() const
Creation / last modification date (latest selfsig).
const Pathname & signature() const
Detached signature or empty.
PublicKeyData trustedPublicKeyExists(const std::string &id)
static void setDefaultAccept(DefaultAccept value_r)
Set the active accept bits.
Provide a new empty temporary directory and recursively delete it when no longer needed.
filesystem::TmpDir _trusted_tmp_dir
bool verifyFileSignature(const Pathname &file, const Pathname &signature)
std::list< PublicKeyData > _data
bool set(const std::string &key_r, AnyType val_r)
Set the value for key (nonconst version always returns true).
const std::string & asString() const
String representation.
bool isExist() const
Return whether valid stat info exists.
bool verifyFileSignatureWorkflow(keyring::VerifyFileContext &context_r)
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
const Pathname generalKeyRing() const
filesystem::TmpFile dumpPublicKeyToTmp(const std::string &id, const Pathname &keyring)
Interim helper class to collect global options and settings.
IMPL_PTR_TYPE(Application)
std::list< PublicKey > trustedPublicKeys()
scoped_ptr< WatchFile > _keyringP
bool provideAndImportKeyFromRepositoryWorkflow(const std::string &id, const RepoInfo &info)
Try to find the id in key cache or repository specified in info.
void importKey(const PublicKey &key, bool trusted=false)
const Pathname & file() const
File to verify.
Impl(const Pathname &baseTmpDir)
const BuddyKeys & buddyKeys() const
bool isKeyKnown(const std::string &id)
true if the key id is knows, that means at least exist on the untrusted keyring
void multiKeyImport(const Pathname &keyfile_r, bool trusted_r=false)
Initial import from RpmDb.
User has chosen not to trust the key.
std::string fingerprint() const
Key fingerprint.
virtual KeyTrust askUserToAcceptKey(const PublicKey &key, const KeyContext &keycontext=KeyContext())
Ask user to trust and/or import the key to trusted keyring.
scoped_ptr< WatchFile > _keyringK
std::list< PublicKeyData > listKeys()
Returns a list of all public keys found in the current keyring.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
static DefaultAccept defaultAccept()
Get the active accept bits.
RW_pointer< Impl > _pimpl
Pointer to implementation.
Regular expression match result.
void preloadCachedKeys()
Load key files cached on the system into the generalKeyRing.
Class representing one GPG Public Key (PublicKeyData + ASCII armored in a tempfile).
std::list< PublicKeyData > publicKeyData()
Get a list of public key data in the keyring (key data only)
Base class for Exception.
Pathname path() const
File containing the ASCII armored key.
std::string id() const
Key ID.
const Tp & get(const std::string &key_r) const
Pass back a const Tp & reference to key_r value.
const Pathname trustedKeyRing() const
std::list< PublicKey > publicKeys()
Typesafe passing of user data via callbacks.
void deleteKey(const std::string &id, bool trusted=false)
removes a key from the keyring.
static constexpr const char * KEYS_NOT_IMPORTED_REPORT
void reportAutoImportKey(const std::list< PublicKeyData > &keyDataList_r, const PublicKeyData &keySigning_r, const KeyContext &keyContext_r)
Notify that a repository auto imported new package signing keys.
bool verifyFileTrustedSignature(const Pathname &file, const Pathname &signature)
bool verifyFileTrustedSignature(const Pathname &file, const Pathname &signature)
Wrapper class for ::stat/::lstat.
#define NON_COPYABLE_BUT_MOVE(CLASS)
Delete copy ctor and copy assign but enable default move.
bool regex_match(const std::string &s, smatch &matches, const regex ®ex)
regex ZYPP_STR_REGEX regex ZYPP_STR_REGEX
const std::list< PublicKeyData > & publicKeyData(const Pathname &keyring)
std::list< std::string > readSignatureFingerprints(const Pathname &signature)
Reads all fingerprints from the signature file , returns a list of all found fingerprints.
bool fileAccepted() const
May return true due to user interaction or global defaults even if the signature was not actually ver...
bool hasvalue(const std::string &key_r) const
Whether key_r is in data and value is not empty.
bool isKeyTrusted(const std::string &id)
true if the key id is trusted
void setRepoInfo(const RepoInfo &repoinfo)
static constexpr const char * REPORT_AUTO_IMPORT_KEY
void allowPreload(bool yesno_r)
The general keyring may be populated with known keys stored on the system.
Easy-to use interface to the ZYPP dependency resolver.
CachedPublicKeyData::Manip keyRingManip(const Pathname &keyring)
Impl helper providing on demand a KeyManagerCtx to manip a cached keyring.
callback::SendReport< KeyRingSignals > _emitSignal
PublicKeyData publicKeyExists(const std::string &id)
bool _verifyFileSignatureWorkflow(keyring::VerifyFileContext &context_r)
std::string shortFile() const
Short name for file (default: basename).
std::string readSignatureKeyId(const Pathname &signature)
reads the public key id from a signature
bool verifyFileSignature(const Pathname &file, const Pathname &signature)
Verifies a file against a signature, with no user interaction.
static constexpr const char * ACCEPT_PACKAGE_KEY_REQUEST
std::string readSignatureKeyId(const Pathname &signature)
virtual bool askUserToAcceptVerificationFailed(const std::string &file, const PublicKey &key, const KeyContext &keycontext=KeyContext())
The file filedesc is signed but the verification failed.
std::list< PublicKey > publicKeys()
Get a list of public keys in the keyring (incl.
filesystem::TmpDir _general_tmp_dir