libzypp  17.28.0
Downloader.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
9 
10 #include <fstream>
11 #include <zypp/base/String.h>
12 #include <zypp/base/Logger.h>
13 #include <zypp/base/Gettext.h>
14 
15 #include "Downloader.h"
16 #include <zypp/KeyContext.h>
17 #include <zypp/ZConfig.h>
18 #include <zypp/ZYppFactory.h>
19 #include <zypp/ZYppCallbacks.h>
20 
22 
23 using std::endl;
24 
25 namespace zypp
26 {
27 namespace repo
28 {
30  {
31  public:
33  typedef function<void( const Pathname & file_r )> PreCheckCB;
34 
36  {}
37 
39  : SignatureFileChecker( std::move(signature_r) )
40  {}
41 
42  void preCheckCB( PreCheckCB cb_r )
43  { _preCheckCB = std::move(cb_r); }
44 
45  void operator()( const Pathname & file_r ) const
46  {
47  if ( _preCheckCB )
48  _preCheckCB( file_r );
50  }
51 
52  private:
54  };
55 
56  // bsc#1184326: Check and handle extra gpg keys delivered with trusted signed master index.
57  void checkExtraKeysInRepomd( MediaSetAccess & media_r, const Pathname & destdir_r, const Pathname & repomd_r, SignatureFileChecker & sigchecker_r )
58  {
59  std::vector<std::pair<std::string,std::string>> keyhints { zypp::parser::yum::RepomdFileReader(repomd_r).keyhints() };
60  if ( keyhints.empty() )
61  return;
62  DBG << "Check keyhints: " << keyhints.size() << endl;
63 
64  auto keyRing { getZYpp()->keyRing() };
65  for ( const auto & p : keyhints ) try {
66  const std::string & file { p.first };
67  const std::string & keyid { p.second };
68 
69  if ( keyRing->trustedPublicKeyData( keyid ) ) {
70  DBG << "Keyhint is already trusted: " << keyid << " (" << file << ")" << endl;
71  continue; // already a trusted key
72  }
73 
74  DBG << "Keyhint search key " << keyid << " (" << file << ")" << endl;
75  PublicKeyData keyData = keyRing->publicKeyData( keyid );
76  if ( not keyData ) {
77  // try to get it from cache or download it...
78 
79  // TODO: Enhance the key caching in general...
80  const ZConfig & conf = ZConfig::instance();
81  Pathname cacheFile = conf.repoManagerRoot() / conf.pubkeyCachePath() / file;
82 
83  PublicKey key { PublicKey::noThrow( cacheFile ) };
84  if ( not key.fileProvidesKey( keyid ) ) {
85 
86  key = PublicKey::noThrow( media_r.provideOptionalFile( file ) );
87  if ( not key.fileProvidesKey( keyid ) ) {
88 
89  WAR << "Keyhint " << file << " does not contain a key with id " << keyid << ". Skipping it." << endl;
90  continue;
91  }
92  // Try to cache it...
93  filesystem::hardlinkCopy( key.path(), cacheFile );
94  }
95 
96  keyRing->importKey( key, false ); // store in general keyring (not trusted!)
97  keyData = keyRing->publicKeyData( keyid ); // fetch back from keyring in case it was a hidden key
98  }
99 
100  if ( not PublicKey::isSafeKeyId( keyid ) ) {
101  WAR << "Keyhint " << keyid << " for " << keyData << " is not strong enough for auto import. Just caching it." << endl;
102  continue;
103  }
104 
105  DBG << "Keyhint remember buddy " << keyData << endl;
106  sigchecker_r.addBuddyKey( keyid );
107  }
108  catch ( const Exception & exp )
109  { ZYPP_CAUGHT(exp); }
110  catch ( const std::exception & exp )
111  { ZYPP_CAUGHT(exp); }
112  catch (...)
113  { INT << "Oops!" << endl; }
114  MIL << "Check keyhints done. Buddy keys: " << sigchecker_r.buddyKeys().size() << endl;
115  }
116 
117 
119 {
120 }
121 Downloader::Downloader(const RepoInfo & repoinfo) : _repoinfo(repoinfo)
122 {
123 }
125 {
126 }
127 
129 {
130  WAR << "Non implemented" << endl;
131  return RepoStatus();
132 }
133 
135  const Pathname &dest_dir,
136  const ProgressData::ReceiverFnc & progress )
137 {
138  WAR << "Non implemented" << endl;
139 }
140 
141 void Downloader::defaultDownloadMasterIndex( MediaSetAccess & media_r, const Pathname & destdir_r, const Pathname & masterIndex_r )
142 {
143  Pathname sigpath = masterIndex_r.extend( ".asc" );
144  Pathname keypath = masterIndex_r.extend( ".key" );
145 
146  // always download them, even if repoGpgCheck is disabled
147 
148  //enable precache for next start() call
149  setMediaSetAccess( media_r );
150  enqueue( OnMediaLocation( sigpath, 1 ).setOptional( true ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ) );
151  enqueue( OnMediaLocation( keypath, 1 ).setOptional( true ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ) );
152  start( destdir_r );
153  reset();
154 
155  FileChecker checker; // set to sigchecker if appropriate, else Null.
156  ExtraSignatureFileChecker sigchecker;
157  bool isSigned = PathInfo(destdir_r / sigpath).isExist();
158 
159  if ( repoInfo().repoGpgCheck() )
160  {
161  if ( isSigned || repoInfo().repoGpgCheckIsMandatory() )
162  {
163  // only add the signature if it exists
164  if ( isSigned )
165  sigchecker.signature( destdir_r / sigpath );
166 
167  // only add the key if it exists
168  if ( PathInfo(destdir_r / keypath).isExist() )
169  sigchecker.addPublicKey( destdir_r / keypath );
170 
171  // set the checker context even if the key is not known
172  // (unsigned repo, key file missing; bnc #495977)
173  sigchecker.keyContext( repoInfo() );
174 
175  // bsc#1184326: Check and handle extra gpg keys delivered with trusted signed master index.
176  if ( masterIndex_r.basename() == "repomd.xml" ) {
177  sigchecker.preCheckCB( [&]( const Pathname & file_r )->void {
178  // Take care no exception escapes! Main job is the signature verification.
179  try {
180  checkExtraKeysInRepomd( media_r, destdir_r, file_r, sigchecker );
181  }
182  catch ( const Exception & exp )
183  { ZYPP_CAUGHT(exp); }
184  catch ( const std::exception & exp )
185  { ZYPP_CAUGHT(exp); }
186  catch (...)
187  { INT << "Oops!" << endl; }
188  });
189  }
190  checker = FileChecker( ref(sigchecker) ); // ref() to the local sigchecker is important as we want back fileValidated!
191  }
192  else
193  {
194  WAR << "Accept unsigned repository because repoGpgCheck is not mandatory for " << repoInfo().alias() << endl;
195  }
196  }
197  else
198  {
199  WAR << "Signature checking disabled in config of repository " << repoInfo().alias() << endl;
200  }
201 
202  enqueue( OnMediaLocation( masterIndex_r, 1 ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ), checker ? checker : FileChecker(NullFileChecker()) );
203  start( destdir_r, media_r );
204  reset();
205 
206  // Accepted!
207  _repoinfo.setMetadataPath( destdir_r );
208  if ( isSigned )
210  else
211  _repoinfo.setValidRepoSignature( indeterminate );
212 }
213 
214 
215 }// ns repo
216 } // ns zypp
217 
218 
219 
MIL
#define MIL
Definition: Logger.h:96
Downloader.h
zypp::RepoStatus
Track changing files or directories.
Definition: RepoStatus.h:41
zypp::MediaSetAccess::provideOptionalFile
Pathname provideOptionalFile(const Pathname &file, unsigned media_nr=1)
Provides an optional file from media media_nr.
Definition: MediaSetAccess.cc:182
zypp::repo::ExtraSignatureFileChecker::ExtraSignatureFileChecker
ExtraSignatureFileChecker()
Definition: Downloader.cc:35
KeyContext.h
zypp::filesystem::PathInfo::isExist
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:279
zypp::repo::ExtraSignatureFileChecker::ExtraSignatureFileChecker
ExtraSignatureFileChecker(Pathname signature_r)
Definition: Downloader.cc:38
ZYppFactory.h
zypp::Exception
Base class for Exception.
Definition: Exception.h:146
zypp::RepoInfo
What is known about a repository.
Definition: RepoInfo.h:72
zypp::repo::Downloader::status
virtual RepoStatus status(MediaSetAccess &media)
Status of the remote repository.
Definition: Downloader.cc:128
zypp::repo::Downloader::Downloader
Downloader()
Constructor.
Definition: Downloader.cc:118
zypp::repo::ExtraSignatureFileChecker::preCheckCB
void preCheckCB(PreCheckCB cb_r)
Definition: Downloader.cc:42
zypp::parser::yum::RepomdFileReader::keyhints
std::vector< std::pair< std::string, std::string > > keyhints() const
gpg key hits shipped in keywords (bsc#1184326)
Definition: RepomdFileReader.cc:209
ZConfig.h
zypp::repo::Downloader::repoInfo
const RepoInfo & repoInfo() const
Definition: Downloader.h:58
zypp::PublicKeyData
Class representing one GPG Public Keys data.
Definition: PublicKey.h:140
INT
#define INT
Definition: Logger.h:100
WAR
#define WAR
Definition: Logger.h:97
zypp::OnMediaLocation
Describes a resource file located on a medium.
Definition: OnMediaLocation.h:39
zypp::SignatureFileChecker
Checks for the validity of a signature.
Definition: FileChecker.h:94
zypp::Fetcher::start
void start(const Pathname &dest_dir, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
start the transfer to a destination directory dest_dir The media has to be provides with setMediaSetA...
Definition: Fetcher.cc:908
ZYPP_CAUGHT
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:396
zypp::keyring::VerifyFileContext::signature
const Pathname & signature() const
Detached signature or empty.
Definition: KeyRingContexts.cc:79
zypp::ByteCount::MB
static const Unit MB
1000^2 Byte
Definition: ByteCount.h:60
zypp::repo::ExtraSignatureFileChecker::PreCheckCB
function< void(const Pathname &file_r)> PreCheckCB
Called after download but before verifying the file.
Definition: Downloader.cc:33
zypp::repo::Downloader::download
virtual void download(MediaSetAccess &media, const Pathname &dest_dir, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
Download metadata to a local directory.
Definition: Downloader.cc:134
zypp::keyring::VerifyFileContext::keyContext
const KeyContext & keyContext() const
KeyContext passed to callbacks
Definition: KeyRingContexts.cc:91
zypp::repo::ExtraSignatureFileChecker::operator()
void operator()(const Pathname &file_r) const
Definition: Downloader.cc:45
zypp::NullFileChecker
Checks for nothing Used as the default checker.
Definition: FileChecker.h:133
zypp::ZConfig::repoManagerRoot
Pathname repoManagerRoot() const
The RepoManager root directory.
Definition: ZConfig.cc:835
zypp::ByteCount
Store and operate with byte count.
Definition: ByteCount.h:31
zypp::repo::ExtraSignatureFileChecker
Definition: Downloader.cc:30
zypp::RepoInfo::setMetadataPath
void setMetadataPath(const Pathname &path)
Set the path where the local metadata is stored.
Definition: RepoInfo.cc:661
zypp::filesystem::PathInfo
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:219
zypp::keyring::VerifyFileContext::addBuddyKey
void addBuddyKey(std::string sid_r)
Definition: KeyRingContexts.cc:100
RepomdFileReader.h
Interface of repomd.xml file reader.
zypp::repo::RepoInfoBase::alias
std::string alias() const
unique identifier for this source.
Definition: RepoInfoBase.cc:111
ZYppCallbacks.h
zypp::keyring::VerifyFileContext::buddyKeys
const BuddyKeys & buddyKeys() const
Definition: KeyRingContexts.cc:97
zypp::ZConfig::instance
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:126
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
zypp::ZConfig
Interim helper class to collect global options and settings.
Definition: ZConfig.h:62
zypp::RepoInfo::setValidRepoSignature
void setValidRepoSignature(TriBool value_r)
Set the value for validRepoSignature (or indeterminate if unsigned).
Definition: RepoInfo.cc:453
zypp::repo::Downloader::_repoinfo
RepoInfo _repoinfo
Definition: Downloader.h:65
zypp::keyring::VerifyFileContext::fileValidated
bool fileValidated() const
Whether the signature was actually successfully verified.
Definition: KeyRingContexts.cc:113
zypp::PublicKey::isSafeKeyId
static bool isSafeKeyId(const std::string &id_r)
!<
Definition: PublicKey.h:351
DBG
#define DBG
Definition: Logger.h:95
zypp::SignatureFileChecker::addPublicKey
void addPublicKey(const PublicKey &publickey_r)
Add a public key to the list of known keys.
Definition: FileChecker.cc:121
zypp::Fetcher::setMediaSetAccess
void setMediaSetAccess(MediaSetAccess &media)
Sets the media set access that will be used to precache and to download the files when start is calle...
Definition: Fetcher.cc:903
zypp::ProgressData::ReceiverFnc
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
Definition: ProgressData.h:139
zypp::ZConfig::pubkeyCachePath
Pathname pubkeyCachePath() const
Path where the pubkey caches.
Definition: ZConfig.cc:927
zypp::SignatureFileChecker::operator()
void operator()(const Pathname &file_r) const
Call KeyRing::verifyFileSignatureWorkflow to verify the file.
Definition: FileChecker.cc:124
zypp::PublicKey
Class representing one GPG Public Key (PublicKeyData + ASCII armored in a tempfile).
Definition: PublicKey.h:284
std
Definition: Arch.h:348
zypp::filesystem::Pathname::extend
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition: Pathname.h:170
zypp::parser::yum::RepomdFileReader
Reads through a repomd.xml file and collects type, location, checksum and other data about metadata f...
Definition: RepomdFileReader.h:39
zypp::Fetcher::reset
void reset()
Reset the transfer (jobs) list.
Definition: Fetcher.cc:898
zypp::filesystem::Pathname
Pathname.
Definition: Pathname.h:45
zypp::FileChecker
function< void(const Pathname &file)> FileChecker
Functor signature used to check files.
Definition: FileChecker.h:28
zypp::Fetcher::enqueue
void enqueue(const OnMediaLocation &resource, const FileChecker &checker=FileChecker())
Enqueue a object for transferal, they will not be transferred until start() is called.
Definition: Fetcher.cc:887
zypp::repo::Downloader::~Downloader
virtual ~Downloader()
Definition: Downloader.cc:124
zypp::filesystem::Pathname::basename
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:128
zypp::repo::checkExtraKeysInRepomd
void checkExtraKeysInRepomd(MediaSetAccess &media_r, const Pathname &destdir_r, const Pathname &repomd_r, SignatureFileChecker &sigchecker_r)
Definition: Downloader.cc:57
zypp::MediaSetAccess
Media access layer responsible for handling files distributed on a set of media with media change and...
Definition: MediaSetAccess.h:81
zypp::repo::Downloader::defaultDownloadMasterIndex
void defaultDownloadMasterIndex(MediaSetAccess &media_r, const Pathname &destdir_r, const Pathname &masterIndex_r)
Common workflow downloading a (signed) master index file.
Definition: Downloader.cc:141
zypp::filesystem::hardlinkCopy
int hardlinkCopy(const Pathname &oldpath, const Pathname &newpath)
Create newpath as hardlink or copy of oldpath.
Definition: PathInfo.cc:823
zypp::PublicKey::noThrow
static PublicKey noThrow(const Pathname &keyFile_r)
Static ctor returning an empty PublicKey rather than throwing.
Definition: PublicKey.cc:535
zypp::repo::ExtraSignatureFileChecker::_preCheckCB
PreCheckCB _preCheckCB
Definition: Downloader.cc:53