libzypp 17.31.32
KeyRing.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12#include <iostream>
13#include <fstream>
14#include <optional>
15#include <sys/file.h>
16#include <cstdio>
17#include <unistd.h>
18
19#include <zypp/TmpPath.h>
20#include <zypp/ZYppFactory.h>
21#include <zypp/ZYpp.h>
22
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>
30#include <zypp/KeyRing.h>
31#include <zypp/ExternalProgram.h>
32#include <zypp/TmpPath.h>
33#include <zypp/ZYppCallbacks.h> // JobReport::instance
34#include <zypp/KeyManager.h>
35
36using std::endl;
37
38#undef ZYPP_BASE_LOGGER_LOGGROUP
39#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::KeyRing"
40
42namespace zypp
43{
44
46
47 namespace
48 {
49 KeyRing::DefaultAccept _keyRingDefaultAccept( KeyRing::ACCEPT_NOTHING );
50 }
51
52 KeyRing::DefaultAccept KeyRing::defaultAccept()
53 { return _keyRingDefaultAccept; }
54
56 {
57 MIL << "Set new KeyRing::DefaultAccept: " << value_r << endl;
59 }
60
61 void KeyRingReport::infoVerify( const std::string & file_r, const PublicKeyData & keyData_r, const KeyContext & keycontext )
62 {}
63
66
76
77 bool KeyRingReport::askUserToAcceptUnknownKey( const std::string & file, const std::string & id, const KeyContext & keycontext )
79
82
84 {
86 data.set("PublicKey", key_r);
87 data.set("KeyContext", keycontext_r);
88 report(data);
89
90 if ( data.hasvalue("TrustKey") )
91 return data.get<bool>("TrustKey");
92 return false;
93 }
94
95 void KeyRingReport::reportNonImportedKeys(const std::set<Edition> &keys_r)
96 {
98 data.set("Keys", keys_r);
99 report(data);
100 }
101
102 void KeyRingReport::reportAutoImportKey( const std::list<PublicKeyData> & keyDataList_r,
104 const KeyContext &keyContext_r )
105 {
107 data.set( "KeyDataList", keyDataList_r );
108 data.set( "KeySigning", keySigning_r );
109 data.set( "KeyContext", keyContext_r );
110 report( data );
111 }
112
113 namespace
114 {
122 struct CachedPublicKeyData : private base::NonCopyable
123 {
124 const std::list<PublicKeyData> & operator()( const Pathname & keyring_r ) const
125 { return getData( keyring_r ); }
126
127 void setDirty( const Pathname & keyring_r )
128 { _cacheMap[keyring_r].setDirty(); }
129
136 struct Manip {
137 NON_COPYABLE_BUT_MOVE( Manip );
138 Manip( CachedPublicKeyData & cache_r, Pathname keyring_r )
139 : _cache { cache_r }
140 , _keyring { std::move(keyring_r) }
141 {}
142
143 KeyManagerCtx & keyManagerCtx() {
144 if ( not _context ) {
146 }
147 // frankly: don't remember why an explicit setDirty was introduced and
148 // why WatchFile was not enough. Maybe some corner case when the keyrings
149 // are created?
150 _cache.setDirty( _keyring );
151 return _context.value();
152 }
153
154 private:
155 CachedPublicKeyData & _cache;
156 Pathname _keyring;
157 std::optional<KeyManagerCtx> _context;
158 };
160
162 Manip manip( Pathname keyring_r ) { return Manip( *this, std::move(keyring_r) ); }
163
164 private:
165 struct Cache
166 {
167 Cache() {}
168
169 void setDirty()
170 {
171 _keyringK.reset();
172 _keyringP.reset();
173 }
174
175 void assertCache( const Pathname & keyring_r )
176 {
177 // .kbx since gpg2-2.1
178 if ( !_keyringK )
179 _keyringK.reset( new WatchFile( keyring_r/"pubring.kbx", WatchFile::NO_INIT ) );
180 if ( !_keyringP )
181 _keyringP.reset( new WatchFile( keyring_r/"pubring.gpg", WatchFile::NO_INIT ) );
182 }
183
184 bool hasChanged() const
185 {
186 bool k = _keyringK->hasChanged(); // be sure both files are checked
187 bool p = _keyringP->hasChanged();
188 return k || p;
189 }
190
191 std::list<PublicKeyData> _data;
192
193 private:
194
197 };
198
199 typedef std::map<Pathname,Cache> CacheMap;
200
201 const std::list<PublicKeyData> & getData( const Pathname & keyring_r ) const
202 {
203 Cache & cache( _cacheMap[keyring_r] );
204 // init new cache entry
205 cache.assertCache( keyring_r );
206 return getData( keyring_r, cache );
207 }
208
209 const std::list<PublicKeyData> & getData( const Pathname & keyring_r, Cache & cache_r ) const
210 {
211 if ( cache_r.hasChanged() ) {
212 cache_r._data = KeyManagerCtx::createForOpenPGP( keyring_r ).listKeys();
213 MIL << "Found keys: " << cache_r._data << endl;
214 }
215 return cache_r._data;
216 }
217
218 mutable CacheMap _cacheMap;
219 };
221
222
223 }
224
226 //
227 // CLASS NAME : KeyRing::Impl
228 //
231 {
233 : _trusted_tmp_dir( baseTmpDir, "zypp-trusted-kr" )
234 , _general_tmp_dir( baseTmpDir, "zypp-general-kr" )
236 {
237 MIL << "Current KeyRing::DefaultAccept: " << _keyRingDefaultAccept << endl;
238 }
239
240 void importKey( const PublicKey & key, bool trusted = false );
241 void multiKeyImport( const Pathname & keyfile_r, bool trusted_r = false );
242 void deleteKey( const std::string & id, bool trusted );
243
244 std::string readSignatureKeyId( const Pathname & signature );
245
246 bool isKeyTrusted( const std::string & id )
247 { return bool(publicKeyExists( id, trustedKeyRing() )); }
248 bool isKeyKnown( const std::string & id )
249 { return publicKeyExists( id, trustedKeyRing() ) || publicKeyExists( id, generalKeyRing() ); }
250
251 std::list<PublicKey> trustedPublicKeys()
252 { return publicKeys( trustedKeyRing() ); }
253 std::list<PublicKey> publicKeys()
254 { return publicKeys( generalKeyRing() ); }
255
256 const std::list<PublicKeyData> & trustedPublicKeyData()
257 { return publicKeyData( trustedKeyRing() ); }
258 const std::list<PublicKeyData> & publicKeyData()
259 { return publicKeyData( generalKeyRing() ); }
260
261 void dumpPublicKey( const std::string & id, bool trusted, std::ostream & stream )
262 { dumpPublicKey( id, ( trusted ? trustedKeyRing() : generalKeyRing() ), stream ); }
263
265 { return exportKey( keyData, generalKeyRing() ); }
267 { return exportKey( keyData, trustedKeyRing() ); }
268
270 {
271 // Assert result and return value are in sync
273 return context_r.fileAccepted();
274 }
276
277 bool verifyFileSignature( const Pathname & file, const Pathname & signature )
278 { return verifyFile( file, signature, generalKeyRing() ); }
279 bool verifyFileTrustedSignature( const Pathname & file, const Pathname & signature )
280 { return verifyFile( file, signature, trustedKeyRing() ); }
281
282 PublicKeyData publicKeyExists( const std::string & id )
283 { return publicKeyExists(id, generalKeyRing());}
284 PublicKeyData trustedPublicKeyExists( const std::string & id )
285 { return publicKeyExists(id, trustedKeyRing());}
286
287 bool provideAndImportKeyFromRepositoryWorkflow (const std::string &id_r , const RepoInfo &info_r );
288
291
292 private:
294 CachedPublicKeyData::Manip keyRingManip( const Pathname & keyring )
295 { return cachedPublicKeyData.manip( keyring ); }
296
297 bool verifyFile( const Pathname & file, const Pathname & signature, const Pathname & keyring );
298 void importKey( const Pathname & keyfile, const Pathname & keyring );
299
300 PublicKey exportKey( const std::string & id, const Pathname & keyring );
301 PublicKey exportKey( const PublicKeyData & keyData, const Pathname & keyring );
302 PublicKey exportKey( const PublicKey & key, const Pathname & keyring )
303 { return exportKey( key.keyData(), keyring ); }
304
305 void dumpPublicKey( const std::string & id, const Pathname & keyring, std::ostream & stream );
306 filesystem::TmpFile dumpPublicKeyToTmp( const std::string & id, const Pathname & keyring );
307
308 void deleteKey( const std::string & id, const Pathname & keyring );
309
310 std::list<PublicKey> publicKeys( const Pathname & keyring);
311 const std::list<PublicKeyData> & publicKeyData( const Pathname & keyring )
312 { return cachedPublicKeyData( keyring ); }
313
315 PublicKeyData publicKeyExists( const std::string & id, const Pathname & keyring );
317 void preloadCachedKeys();
318
320 { return _general_tmp_dir.path(); }
322 { return _trusted_tmp_dir.path(); }
323
324 // Used for trusted and untrusted keyrings
328 bool _allowPreload = false; //< General keyring may be preloaded with keys cached on the system.
329
330 private:
336 CachedPublicKeyData cachedPublicKeyData;
337 };
339
340 namespace
341 {
343 struct ImportKeyCBHelper
344 {
345 void operator()( const PublicKey & key_r )
346 {
347 try {
348 _rpmdbEmitSignal->trustedKeyAdded( key_r );
349 _emitSignal->trustedKeyAdded( key_r );
350 }
351 catch ( const Exception & excp )
352 {
353 ERR << "Could not import key into rpmdb: " << excp << endl;
354 // TODO: JobReport as hotfix for bsc#1057188; should bubble up and go through some callback
355 JobReport::error( excp.asUserHistory() );
356 }
357 }
358
359 private:
360 callback::SendReport<target::rpm::KeyRingSignals> _rpmdbEmitSignal;
361 callback::SendReport<KeyRingSignals> _emitSignal;
362 };
363 } // namespace
364
365
367 {
369 MIL << "Imported key " << key << " to " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
370
371 if ( trusted )
372 {
373 ImportKeyCBHelper emitSignal;
374 if ( key.hiddenKeys().empty() )
375 {
376 emitSignal( key );
377 }
378 else
379 {
380 // multiple keys: Export individual keys ascii armored to import in rpmdb
382 for ( const PublicKeyData & hkey : key.hiddenKeys() )
384 }
385 }
386 }
387
389 {
390 importKey( keyfile_r, trusted_r ? trustedKeyRing() : generalKeyRing() );
391 }
392
393 void KeyRing::Impl::deleteKey( const std::string & id, bool trusted )
394 {
395 PublicKeyData keyDataToDel( publicKeyExists( id, trusted ? trustedKeyRing() : generalKeyRing() ) );
396 if ( ! keyDataToDel )
397 {
398 WAR << "Key to delete [" << id << "] is not in " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
399 return;
400 }
401 deleteKey( id, trusted ? trustedKeyRing() : generalKeyRing() );
402 MIL << "Deleted key [" << id << "] from " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl;
403
404 if ( trusted )
405 try {
406 PublicKey key( keyDataToDel );
407
409 rpmdbEmitSignal->trustedKeyRemoved( key );
410
412 emitSignal->trustedKeyRemoved( key );
413 }
414 catch ( const Exception & excp )
415 {
416 ERR << "Could not delete key from rpmmdb: " << excp << endl;
417 // TODO: JobReport as hotfix for bsc#1057188; should bubble up and go through some callback
418 JobReport::error( excp.asUserHistory() );
419 }
420 }
421
422 PublicKeyData KeyRing::Impl::publicKeyExists( const std::string & id, const Pathname & keyring )
423 {
424 if ( _allowPreload && keyring == generalKeyRing() ) {
425 _allowPreload = false;
426 preloadCachedKeys();
427 }
428
430 for ( const PublicKeyData & key : publicKeyData( keyring ) )
431 {
432 if ( key.providesKey( id ) )
433 {
434 ret = key;
435 break;
436 }
437 }
438 DBG << (ret ? "Found" : "No") << " key [" << id << "] in keyring " << keyring << endl;
439 return ret;
440 }
441
443 {
444 MIL << "preloadCachedKeys into general keyring..." << endl;
445 CachedPublicKeyData::Manip manip { keyRingManip( generalKeyRing() ) }; // Provides the context if we want to manip a cached keyring.
446
447 // For now just load the 'gpg-pubkey-*.{asc,key}' files into the general keyring,
448 // if their id (derived from the filename) is not in the trusted ring.
449 // TODO: Head for a persistent general keyring.
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" );
457 }
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" );
461 }
462
463 std::map<std::string,Pathname> keyCandidates; // Collect one file path per keyid
464 const str::regex rx { "^gpg-pubkey-([[:xdigit:]]{8,})(-[[:xdigit:]]{8,})?\\.(asc|key)$" };
465 for ( const auto & cache : cachedirs ) {
466 dirForEach( cache,
467 [&rx,&keyCandidates]( const Pathname & dir_r, const char *const file_r )->bool {
468 str::smatch what;
469 if ( str::regex_match( file_r, what, rx ) ) {
470 Pathname & remember { keyCandidates[what[1]] };
471 if ( remember.empty() ) {
472 remember = dir_r / file_r;
473 }
474 }
475 return true;
476 }
477 );
478 }
479
480 for ( const auto & p : keyCandidates ) {
481 // Avoid checking the general keyring while it is flagged dirty.
482 // Checking the trusted ring is ok, and most keys will be there anyway.
483 const std::string & id { p.first };
484 const Pathname & path { p.second };
485 if ( isKeyTrusted(id) )
486 continue;
487 if ( manip.keyManagerCtx().importKey( path ) ) {
488 DBG << "preload key file " << path << endl;
489 }
490 else {
491 WAR << "Skipping: Can't preload key file " << path << endl;
492 }
493 }
494 }
495
496 PublicKey KeyRing::Impl::exportKey( const PublicKeyData & keyData, const Pathname & keyring )
497 {
498 return PublicKey( dumpPublicKeyToTmp( keyData.id(), keyring ), keyData );
499 }
500
501 PublicKey KeyRing::Impl::exportKey( const std::string & id, const Pathname & keyring )
502 {
503 PublicKeyData keyData( publicKeyExists( id, keyring ) );
504 if ( keyData )
505 return PublicKey( dumpPublicKeyToTmp( keyData.id(), keyring ), keyData );
506
507 // Here: key not found
508 WAR << "No key [" << id << "] to export from " << keyring << endl;
509 return PublicKey();
510 }
511
512
513 void KeyRing::Impl::dumpPublicKey( const std::string & id, const Pathname & keyring, std::ostream & stream )
514 {
515 KeyManagerCtx::createForOpenPGP( keyring ).exportKey(id, stream);
516 }
517
518 filesystem::TmpFile KeyRing::Impl::dumpPublicKeyToTmp( const std::string & id, const Pathname & keyring )
519 {
520 filesystem::TmpFile tmpFile( _base_dir, "pubkey-"+id+"-" );
521 MIL << "Going to export key [" << id << "] from " << keyring << " to " << tmpFile.path() << endl;
522
523 std::ofstream os( tmpFile.path().c_str() );
524 dumpPublicKey( id, keyring, os );
525 os.close();
526 return tmpFile;
527 }
528
530 {
531 context_r.resetResults();
532 const Pathname & file { context_r.file() };
533 const Pathname & signature { context_r.signature() };
534 const std::string & filedesc { context_r.shortFile() };
535 const KeyContext & keyContext { context_r.keyContext() };
536
538 MIL << "Going to verify signature for " << filedesc << " ( " << file << " ) with " << signature << endl;
539
540 // if signature does not exists, ask user if they want to accept unsigned file.
541 if( signature.empty() || (!PathInfo( signature ).isExist()) )
542 {
543 bool res = report->askUserToAcceptUnsignedFile( filedesc, keyContext );
544 MIL << "askUserToAcceptUnsignedFile: " << res << endl;
545 return res;
546 }
547
548 // get the id of the signature (it might be a subkey id!)
549 context_r.signatureId( readSignatureKeyId( signature ) );
550 const std::string & id = context_r.signatureId();
553
554 std::list<PublicKeyData> buddies; // Could be imported IFF the file is validated by a trusted key
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;
558 continue;
559 }
560 if ( trustedPublicKeyExists( sid ) ) {
561 MIL << "buddy " << sid << ": already in trusted key ring. Not needed." << endl;
562 continue;
563 }
564 auto pk = publicKeyExists( sid );
565 if ( not pk ) {
566 WAR << "buddy " << sid << ": not available in the public key ring. Skipping it." << endl;
567 continue;
568 }
569 if ( pk.providesKey(id) ) {
570 MIL << "buddy " << sid << ": is the signing key. Handled separately." << endl;
571 continue;
572 }
573 MIL << "buddy " << sid << ": candidate for auto import. Remeber it." << endl;
574 buddies.push_back( pk );
575 }
576
577 if ( !id.empty() ) {
578
579 // does key exists in trusted keyring
580 PublicKeyData trustedKeyData( publicKeyExists( id, trustedKeyRing() ) );
581 if ( trustedKeyData )
582 {
583 MIL << "Key is trusted: " << trustedKeyData << endl;
584
585 // lets look if there is an updated key in the
586 // general keyring
587 PublicKeyData generalKeyData( publicKeyExists( id, generalKeyRing() ) );
588 if ( generalKeyData )
589 {
590 // bnc #393160: Comment #30: Compare at least the fingerprint
591 // in case an attacker created a key the the same id.
592 //
593 // FIXME: bsc#1008325: For keys using subkeys, we'd actually need
594 // to compare the subkey sets, to tell whether a key was updated.
595 // because created() remains unchanged if the primary key is not touched.
596 // For now we wait until a new subkey signs the data and treat it as a
597 // new key (else part below).
598 if ( trustedKeyData.fingerprint() == generalKeyData.fingerprint()
599 && trustedKeyData.created() < generalKeyData.created() )
600 {
601 MIL << "Key was updated. Saving new version into trusted keyring: " << generalKeyData << endl;
602 importKey( exportKey( generalKeyData, generalKeyRing() ), true );
603 trustedKeyData = publicKeyExists( id, trustedKeyRing() ); // re-read: invalidated by import?
604 }
605 }
606
608 whichKeyring = trustedKeyRing();
609 }
610 else
611 {
612 PublicKeyData generalKeyData( publicKeyExists( id, generalKeyRing() ) );
613 if ( generalKeyData )
614 {
615 PublicKey key( exportKey( generalKeyData, generalKeyRing() ) );
616 MIL << "Key [" << id << "] " << key.name() << " is not trusted" << endl;
617
618 // ok the key is not trusted, ask the user to trust it or not
619 KeyRingReport::KeyTrust reply = report->askUserToAcceptKey( key, keyContext );
622 {
623 MIL << "User wants to trust key [" << id << "] " << key.name() << endl;
624
626 {
627 MIL << "User wants to import key [" << id << "] " << key.name() << endl;
628 importKey( key, true );
629 whichKeyring = trustedKeyRing();
630 }
631 else
632 whichKeyring = generalKeyRing();
633
635 }
636 else
637 {
638 MIL << "User does not want to trust key [" << id << "] " << key.name() << endl;
639 return false;
640 }
641 }
642 else if ( ! keyContext.empty() )
643 {
644 // try to find the key in the repository info
645 if ( provideAndImportKeyFromRepositoryWorkflow( id, keyContext.repoInfo() ) ) {
646 whichKeyring = trustedKeyRing();
647 foundKey = PublicKeyData( publicKeyExists( id, trustedKeyRing() ) );
648 }
649 }
650 }
651 }
652
653 if ( foundKey ) {
654 // it exists, is trusted, does it validate?
655 context_r.signatureIdTrusted( whichKeyring == trustedKeyRing() );
656 report->infoVerify( filedesc, foundKey, keyContext );
657 if ( verifyFile( file, signature, whichKeyring ) )
658 {
659 context_r.fileValidated( true );
660 if ( context_r.signatureIdTrusted() && not buddies.empty() ) {
661 // Check for buddy keys to be imported...
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 );
666 }
667 }
668 return context_r.fileValidated(); // signature is actually successfully validated!
669 }
670 else
671 {
672 bool res = report->askUserToAcceptVerificationFailed( filedesc, exportKey( foundKey, whichKeyring ), keyContext );
673 MIL << "askUserToAcceptVerificationFailed: " << res << endl;
674 return res;
675 }
676 } else {
677 // signed with an unknown key...
678 MIL << "File [" << file << "] ( " << filedesc << " ) signed with unknown key [" << id << "]" << endl;
679 bool res = report->askUserToAcceptUnknownKey( filedesc, id, keyContext );
680 MIL << "askUserToAcceptUnknownKey: " << res << endl;
681 return res;
682 }
683
684 return false;
685 }
686
688 {
689 if ( id_r.empty() )
690 return false;
691
692 const ZConfig &conf = ZConfig::instance();
693 Pathname cacheDir = conf.repoManagerRoot() / conf.pubkeyCachePath();
694
695 Pathname myKey = info_r.provideKey( id_r, cacheDir );
696 if ( myKey.empty() )
697 // if we did not find any keys, there is no point in checking again, break
698 return false;
699
701
702 PublicKey key;
703 try {
704 key = PublicKey( myKey );
705 } catch ( const Exception &e ) {
706 ZYPP_CAUGHT(e);
707 return false;
708 }
709
710 if ( !key.isValid() ) {
711 ERR << "Key [" << id_r << "] from cache: " << cacheDir << " is not valid" << endl;
712 return false;
713 }
714
715 MIL << "Key [" << id_r << "] " << key.name() << " loaded from cache" << endl;
716
718 context.setRepoInfo( info_r );
719 if ( ! report->askUserToAcceptPackageKey( key, context ) ) {
720 return false;
721 }
722
723 MIL << "User wants to import key [" << id_r << "] " << key.name() << " from cache" << endl;
724 try {
725 importKey( key, true );
726 } catch ( const KeyRingException &e ) {
727 ZYPP_CAUGHT(e);
728 ERR << "Failed to import key: "<<id_r;
729 return false;
730 }
731
732 return true;
733 }
734
735 std::list<PublicKey> KeyRing::Impl::publicKeys( const Pathname & keyring )
736 {
737 const std::list<PublicKeyData> & keys( publicKeyData( keyring ) );
738 std::list<PublicKey> ret;
739
740 for_( it, keys.begin(), keys.end() )
741 {
742 PublicKey key( exportKey( *it, keyring ) );
743 ret.push_back( key );
744 MIL << "Found key " << key << endl;
745 }
746 return ret;
747 }
748
749 void KeyRing::Impl::importKey( const Pathname & keyfile, const Pathname & keyring )
750 {
751 if ( ! PathInfo( keyfile ).isExist() )
752 // TranslatorExplanation first %s is key name, second is keyring name
753 ZYPP_THROW(KeyRingException( str::Format(_("Tried to import not existent key %s into keyring %s"))
754 % keyfile.asString()
755 % keyring.asString() ));
756
757 CachedPublicKeyData::Manip manip { keyRingManip( keyring ) }; // Provides the context if we want to manip a cached keyring.
758 if ( ! manip.keyManagerCtx().importKey( keyfile ) )
759 ZYPP_THROW(KeyRingException(_("Failed to import key.")));
760 }
761
762 void KeyRing::Impl::deleteKey( const std::string & id, const Pathname & keyring )
763 {
764 CachedPublicKeyData::Manip manip { keyRingManip( keyring ) }; // Provides the context if we want to manip a cached keyring.
765 if ( ! manip.keyManagerCtx().deleteKey( id ) )
766 ZYPP_THROW(KeyRingException(_("Failed to delete key.")));
767 }
768
769 std::string KeyRing::Impl::readSignatureKeyId( const Pathname & signature )
770 {
771 if ( ! PathInfo( signature ).isFile() )
772 ZYPP_THROW(KeyRingException( str::Format(_("Signature file %s not found")) % signature.asString() ));
773
774 MIL << "Determining key id of signature " << signature << endl;
775
776 std::list<std::string> fprs = KeyManagerCtx::createForOpenPGP().readSignatureFingerprints( signature );
777 if ( ! fprs.empty() ) {
778 std::string &id = fprs.back();
779 MIL << "Determined key id [" << id << "] for signature " << signature << endl;
780 return id;
781 }
782 return std::string();
783 }
784
785 bool KeyRing::Impl::verifyFile( const Pathname & file, const Pathname & signature, const Pathname & keyring )
786 {
787 return KeyManagerCtx::createForOpenPGP( keyring ).verify( file, signature );
788 }
789
791
793 //
794 // CLASS NAME : KeyRing
795 //
797
801
804
806 { _pimpl->allowPreload( yesno_r ); }
807
808
809 void KeyRing::importKey( const PublicKey & key, bool trusted )
810 { _pimpl->importKey( key, trusted ); }
811
813 { _pimpl->multiKeyImport( keyfile_r, trusted_r ); }
814
815 std::string KeyRing::readSignatureKeyId( const Pathname & signature )
816 { return _pimpl->readSignatureKeyId( signature ); }
817
818 void KeyRing::deleteKey( const std::string & id, bool trusted )
819 { _pimpl->deleteKey( id, trusted ); }
820
821 std::list<PublicKey> KeyRing::publicKeys()
822 { return _pimpl->publicKeys(); }
823
824 std:: list<PublicKey> KeyRing::trustedPublicKeys()
825 { return _pimpl->trustedPublicKeys(); }
826
827 std::list<PublicKeyData> KeyRing::publicKeyData()
828 { return _pimpl->publicKeyData(); }
829
830 std::list<PublicKeyData> KeyRing::trustedPublicKeyData()
831 { return _pimpl->trustedPublicKeyData(); }
832
834 { return _pimpl->publicKeyExists( id_r ); }
835
837 { return _pimpl->trustedPublicKeyExists( id_r ); }
838
839 bool KeyRing::verifyFileSignatureWorkflow( const Pathname & file, const std::string & filedesc, const Pathname & signature, bool & sigValid_r, const KeyContext & keycontext )
840 {
841 sigValid_r = false; // just in case....
842 keyring::VerifyFileContext context( file, signature );
843 context.shortFile( filedesc );
844 context.keyContext( keycontext );
846 sigValid_r = context.fileValidated();
847 return context.fileAccepted();
848 }
849
850 bool KeyRing::verifyFileSignatureWorkflow( const Pathname & file, const std::string filedesc, const Pathname & signature, const KeyContext & keycontext )
851 {
852 keyring::VerifyFileContext context( file, signature );
853 context.shortFile( filedesc );
854 context.keyContext( keycontext );
856 return context.fileAccepted();
857 }
858
860 { return _pimpl->verifyFileSignatureWorkflow( context_r ); }
861
862 bool KeyRing::verifyFileSignature( const Pathname & file, const Pathname & signature )
863 { return _pimpl->verifyFileSignature( file, signature ); }
864
865 bool KeyRing::verifyFileTrustedSignature( const Pathname & file, const Pathname & signature )
866 { return _pimpl->verifyFileTrustedSignature( file, signature ); }
867
868 bool KeyRing::provideAndImportKeyFromRepositoryWorkflow(const std::string &id, const RepoInfo &info)
869 {
870 return _pimpl->provideAndImportKeyFromRepositoryWorkflow( id, info );
871 }
872
873 void KeyRing::dumpPublicKey( const std::string & id, bool trusted, std::ostream & stream )
874 { _pimpl->dumpPublicKey( id, trusted, stream ); }
875
877 { return _pimpl->exportPublicKey( keyData ); }
878
880 { return _pimpl->exportTrustedPublicKey( keyData ); }
881
882 bool KeyRing::isKeyTrusted( const std::string & id )
883 { return _pimpl->isKeyTrusted( id ); }
884
885 bool KeyRing::isKeyKnown( const std::string & id )
886 { return _pimpl->isKeyKnown( id ); }
887
889} // namespace zypp
callback::SendReport< KeyRingSignals > _emitSignal
Definition KeyRing.cc:361
std::list< PublicKeyData > _data
Definition KeyRing.cc:191
scoped_ptr< WatchFile > _keyringK
Definition KeyRing.cc:195
CachedPublicKeyData & _cache
Definition KeyRing.cc:155
Pathname _keyring
Definition KeyRing.cc:156
scoped_ptr< WatchFile > _keyringP
Definition KeyRing.cc:196
std::optional< KeyManagerCtx > _context
Definition KeyRing.cc:157
callback::SendReport< target::rpm::KeyRingSignals > _rpmdbEmitSignal
Definition KeyRing.cc:360
CacheMap _cacheMap
Definition KeyRing.cc:218
Wrapper for GPGME.
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:94
Base class for Exception.
Definition Exception.h:146
static KeyManagerCtx createForOpenPGP()
Creates a new KeyManagerCtx for PGP using a volatile temp.
Gpg key handling.
Definition KeyRing.h:187
bool provideAndImportKeyFromRepositoryWorkflow(const std::string &id, const RepoInfo &info)
Try to find the id in key cache or repository specified in info.
Definition KeyRing.cc:868
bool isKeyKnown(const std::string &id)
true if the key id is knows, that means at least exist on the untrusted keyring
Definition KeyRing.cc:885
std::list< PublicKey > publicKeys()
Get a list of public keys in the keyring (incl.
Definition KeyRing.cc:821
std::list< PublicKey > trustedPublicKeys()
Get a list of trusted public keys in the keyring (incl.
Definition KeyRing.cc:824
static DefaultAccept defaultAccept()
Get the active accept bits.
Definition KeyRing.cc:52
void dumpPublicKey(const std::string &id, bool trusted, std::ostream &stream)
Definition KeyRing.cc:873
bool verifyFileSignature(const Pathname &file, const Pathname &signature)
Verifies a file against a signature, with no user interaction.
Definition KeyRing.cc:862
void multiKeyImport(const Pathname &keyfile_r, bool trusted_r=false)
Initial import from RpmDb.
Definition KeyRing.cc:812
KeyRing(const Pathname &baseTmpDir)
Default ctor.
Definition KeyRing.cc:798
~KeyRing()
Dtor.
Definition KeyRing.cc:802
PublicKey exportPublicKey(const PublicKeyData &keyData)
Export a public key identified by its key data.
Definition KeyRing.cc:876
std::string readSignatureKeyId(const Pathname &signature)
reads the public key id from a signature
Definition KeyRing.cc:815
void allowPreload(bool yesno_r)
The general keyring may be populated with known keys stored on the system.
Definition KeyRing.cc:805
bool verifyFileTrustedSignature(const Pathname &file, const Pathname &signature)
Definition KeyRing.cc:865
void importKey(const PublicKey &key, bool trusted=false)
imports a key from a file.
Definition KeyRing.cc:809
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.
Definition KeyRing.cc:839
RW_pointer< Impl > _pimpl
Pointer to implementation.
Definition KeyRing.h:366
void deleteKey(const std::string &id, bool trusted=false)
removes a key from the keyring.
Definition KeyRing.cc:818
std::list< PublicKeyData > trustedPublicKeyData()
Get a list of trusted public key data in the keyring (key data only)
Definition KeyRing.cc:830
static void setDefaultAccept(DefaultAccept value_r)
Set the active accept bits.
Definition KeyRing.cc:55
std::list< PublicKeyData > publicKeyData()
Get a list of public key data in the keyring (key data only)
Definition KeyRing.cc:827
@ TRUST_KEY_TEMPORARILY
Definition KeyRing.h:207
@ ACCEPT_VERIFICATION_FAILED
Definition KeyRing.h:209
@ ACCEPT_UNKNOWNKEY
Definition KeyRing.h:206
@ TRUST_AND_IMPORT_KEY
Definition KeyRing.h:208
@ ACCEPT_UNSIGNED_FILE
Definition KeyRing.h:205
PublicKey exportTrustedPublicKey(const PublicKeyData &keyData)
Export a trusted public key identified by its key data.
Definition KeyRing.cc:879
bool isKeyTrusted(const std::string &id)
true if the key id is trusted
Definition KeyRing.cc:882
Class representing one GPG Public Keys data.
Definition PublicKey.h:207
static bool isSafeKeyId(const std::string &id_r)
Whether this is a long id (64bit/16byte) or even better a fingerprint.
Definition PublicKey.h:302
std::string id() const
Key ID.
Definition PublicKey.cc:417
Class representing one GPG Public Key (PublicKeyData + ASCII armored in a tempfile).
Definition PublicKey.h:359
Pathname path() const
File containing the ASCII armored key.
Definition PublicKey.cc:645
const std::list< PublicKeyData > & hiddenKeys() const
Additional keys data in case the ASCII armored blob contains multiple keys.
Definition PublicKey.cc:648
std::string name() const
Definition PublicKey.cc:665
const PublicKeyData & keyData() const
The public keys data (.
Definition PublicKey.cc:642
bool isValid() const
Definition PublicKey.h:397
What is known about a repository.
Definition RepoInfo.h:72
Interim helper class to collect global options and settings.
Definition ZConfig.h:64
static ZConfig & instance()
Singleton ctor.
Definition ZConfig.cc:922
Typesafe passing of user data via callbacks.
Definition UserData.h:39
const Tp & get(const std::string &key_r) const
Pass back a const Tp & reference to key_r value.
Definition UserData.h:175
bool hasvalue(const std::string &key_r) const
Whether key_r is in data and value is not empty.
Definition UserData.h:101
bool set(const std::string &key_r, AnyType val_r)
Set the value for key (nonconst version always returns true).
Definition UserData.h:118
Wrapper class for stat/lstat.
Definition PathInfo.h:221
const std::string & asString() const
String representation.
Definition Pathname.h:91
Provide a new empty temporary directory and recursively delete it when no longer needed.
Definition TmpPath.h:178
Provide a new empty temporary file and delete it when no longer needed.
Definition TmpPath.h:128
Pathname path() const
Definition TmpPath.cc:146
I/O context for KeyRing::verifyFileSignatureWorkflow.
Regular expression.
Definition Regex.h:95
Regular expression match result.
Definition Regex.h:168
Definition Arch.h:364
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition NonCopyable.h:26
bool regex_match(const std::string &s, smatch &matches, const regex &regex)
\relates regex \ingroup ZYPP_STR_REGEX \relates regex \ingroup ZYPP_STR_REGEX
Definition Regex.h:70
Easy-to use interface to the ZYPP dependency resolver.
static bool error(const std::string &msg_r, const UserData &userData_r=UserData())
send error text
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.
Definition KeyRing.cc:61
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.
Definition KeyRing.cc:95
KeyTrust
User reply options for the askUserToTrustKey callback.
Definition KeyRing.h:52
@ KEY_TRUST_AND_IMPORT
Import the key.
Definition KeyRing.h:70
@ KEY_DONT_TRUST
User has chosen not to trust the key.
Definition KeyRing.h:56
@ KEY_TRUST_TEMPORARILY
This basically means, we knew the key, but it was not trusted.
Definition KeyRing.h:61
static constexpr const char * REPORT_AUTO_IMPORT_KEY
generic reports UserData::type
Definition KeyRing.h:149
virtual bool askUserToAcceptUnsignedFile(const std::string &file, const KeyContext &keycontext=KeyContext())
Definition KeyRing.cc:64
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.
Definition KeyRing.cc:83
static constexpr const char * ACCEPT_PACKAGE_KEY_REQUEST
generic reports UserData::type
Definition KeyRing.h:117
static constexpr const char * KEYS_NOT_IMPORTED_REPORT
generic reports UserData::type
Definition KeyRing.h:130
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.
Definition KeyRing.cc:102
virtual KeyTrust askUserToAcceptKey(const PublicKey &key, const KeyContext &keycontext=KeyContext())
Ask user to trust and/or import the key to trusted keyring.
Definition KeyRing.cc:68
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...
Definition KeyRing.cc:77
virtual bool askUserToAcceptVerificationFailed(const std::string &file, const PublicKey &key, const KeyContext &keycontext=KeyContext())
The file filedesc is signed but the verification failed.
Definition KeyRing.cc:80
KeyRing implementation.
Definition KeyRing.cc:231
void importKey(const PublicKey &key, bool trusted=false)
Definition KeyRing.cc:366
PublicKeyData trustedPublicKeyExists(const std::string &id)
Definition KeyRing.cc:284
void preloadCachedKeys()
Load key files cached on the system into the generalKeyRing.
Definition KeyRing.cc:442
bool provideAndImportKeyFromRepositoryWorkflow(const std::string &id_r, const RepoInfo &info_r)
Definition KeyRing.cc:687
std::list< PublicKey > trustedPublicKeys()
Definition KeyRing.cc:251
CachedPublicKeyData::Manip keyRingManip(const Pathname &keyring)
Impl helper providing on demand a KeyManagerCtx to manip a cached keyring.
Definition KeyRing.cc:294
PublicKeyData publicKeyExists(const std::string &id)
Definition KeyRing.cc:282
PublicKey exportKey(const std::string &id, const Pathname &keyring)
Definition KeyRing.cc:501
PublicKey exportPublicKey(const PublicKeyData &keyData)
Definition KeyRing.cc:264
bool verifyFileSignatureWorkflow(keyring::VerifyFileContext &context_r)
Definition KeyRing.cc:269
bool isKeyKnown(const std::string &id)
Definition KeyRing.cc:248
const std::list< PublicKeyData > & publicKeyData()
Definition KeyRing.cc:258
bool verifyFileTrustedSignature(const Pathname &file, const Pathname &signature)
Definition KeyRing.cc:279
void allowPreload(bool yesno_r)
Definition KeyRing.cc:289
PublicKey exportTrustedPublicKey(const PublicKeyData &keyData)
Definition KeyRing.cc:266
Impl(const Pathname &baseTmpDir)
Definition KeyRing.cc:232
bool verifyFile(const Pathname &file, const Pathname &signature, const Pathname &keyring)
Definition KeyRing.cc:785
const Pathname generalKeyRing() const
Definition KeyRing.cc:319
const std::list< PublicKeyData > & trustedPublicKeyData()
Definition KeyRing.cc:256
filesystem::TmpDir _general_tmp_dir
Definition KeyRing.cc:326
bool verifyFileSignature(const Pathname &file, const Pathname &signature)
Definition KeyRing.cc:277
CachedPublicKeyData cachedPublicKeyData
Functor returning the keyrings data (cached).
Definition KeyRing.cc:336
std::string readSignatureKeyId(const Pathname &signature)
Definition KeyRing.cc:769
void multiKeyImport(const Pathname &keyfile_r, bool trusted_r=false)
Definition KeyRing.cc:388
std::list< PublicKey > publicKeys()
Definition KeyRing.cc:253
const std::list< PublicKeyData > & publicKeyData(const Pathname &keyring)
Definition KeyRing.cc:311
void deleteKey(const std::string &id, bool trusted)
Definition KeyRing.cc:393
const Pathname trustedKeyRing() const
Definition KeyRing.cc:321
bool _verifyFileSignatureWorkflow(keyring::VerifyFileContext &context_r)
Definition KeyRing.cc:529
filesystem::TmpFile dumpPublicKeyToTmp(const std::string &id, const Pathname &keyring)
Definition KeyRing.cc:518
PublicKey exportKey(const PublicKey &key, const Pathname &keyring)
Definition KeyRing.cc:302
filesystem::TmpDir _trusted_tmp_dir
Definition KeyRing.cc:325
bool isKeyTrusted(const std::string &id)
Definition KeyRing.cc:246
void dumpPublicKey(const std::string &id, bool trusted, std::ostream &stream)
Definition KeyRing.cc:261
virtual void report(const UserData &userData_r=UserData())
The most generic way of sending/receiving data.
Definition Callback.h:155
Convenient building of std::string with boost::format.
Definition String.h:253
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:28
#define NON_COPYABLE_BUT_MOVE(CLASS)
Delete copy ctor and copy assign but enable default move.
Definition Easy.h:79
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:436
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:428
#define _(MSG)
Definition Gettext.h:37
#define DBG
Definition Logger.h:95
#define MIL
Definition Logger.h:96
#define ERR
Definition Logger.h:98
#define WAR
Definition Logger.h:97
#define IMPL_PTR_TYPE(NAME)