libzypp  17.31.31
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 env {
29  {
30  static bool val = [](){
31  const char * env = getenv("ZYPP_REPOMD_WITH_PKCS7");
32  return( env && zypp::str::strToBool( env, true ) );
33  }();
34  return val;
35  }
36  } // namespace env
37 
38 namespace repo
39 {
41  {
42  public:
44  typedef function<void( const Pathname & file_r )> PreCheckCB;
45 
47  {}
48 
50  : SignatureFileChecker( std::move(signature_r) )
51  {}
52 
53  void preCheckCB( PreCheckCB cb_r )
54  { _preCheckCB = std::move(cb_r); }
55 
56  void operator()( const Pathname & file_r ) const
57  {
58  if ( _preCheckCB )
59  _preCheckCB( file_r );
61  }
62 
63  private:
65  };
66 
67  // bsc#1184326: Check and handle extra gpg keys delivered with trusted signed master index.
68  void checkExtraKeysInRepomd( MediaSetAccess & media_r, const Pathname & destdir_r, const Pathname & repomd_r, SignatureFileChecker & sigchecker_r )
69  {
70  std::vector<std::pair<std::string,std::string>> keyhints { zypp::parser::yum::RepomdFileReader(repomd_r).keyhints() };
71  if ( keyhints.empty() )
72  return;
73  DBG << "Check keyhints: " << keyhints.size() << endl;
74 
75  auto keyRing { getZYpp()->keyRing() };
76  for ( const auto & p : keyhints ) try {
77  const std::string & file { p.first };
78  const std::string & keyid { p.second };
79 
80  if ( keyRing->trustedPublicKeyData( keyid ) ) {
81  DBG << "Keyhint is already trusted: " << keyid << " (" << file << ")" << endl;
82  continue; // already a trusted key
83  }
84 
85  DBG << "Keyhint search key " << keyid << " (" << file << ")" << endl;
86  PublicKeyData keyData = keyRing->publicKeyData( keyid );
87  if ( not keyData ) {
88  // try to get it from cache or download it...
89 
90  // TODO: Enhance the key caching in general...
91  const ZConfig & conf = ZConfig::instance();
92  Pathname cacheFile = conf.repoManagerRoot() / conf.pubkeyCachePath() / file;
93 
94  PublicKey key { PublicKey::noThrow( cacheFile ) };
95  if ( not key.fileProvidesKey( keyid ) ) {
96 
97  key = PublicKey::noThrow( media_r.provideOptionalFile( file ) );
98  if ( not key.fileProvidesKey( keyid ) ) {
99 
100  WAR << "Keyhint " << file << " does not contain a key with id " << keyid << ". Skipping it." << endl;
101  continue;
102  }
103  // Try to cache it...
104  filesystem::hardlinkCopy( key.path(), cacheFile );
105  }
106 
107  keyRing->importKey( key, false ); // store in general keyring (not trusted!)
108  keyData = keyRing->publicKeyData( keyid ); // fetch back from keyring in case it was a hidden key
109  }
110 
111  if ( not PublicKey::isSafeKeyId( keyid ) ) {
112  WAR << "Keyhint " << keyid << " for " << keyData << " is not strong enough for auto import. Just caching it." << endl;
113  continue;
114  }
115 
116  DBG << "Keyhint remember buddy " << keyData << endl;
117  sigchecker_r.addBuddyKey( keyid );
118  }
119  catch ( const Exception & exp )
120  { ZYPP_CAUGHT(exp); }
121  catch ( const std::exception & exp )
122  { ZYPP_CAUGHT(exp); }
123  catch (...)
124  { INT << "Oops!" << endl; }
125  MIL << "Check keyhints done. Buddy keys: " << sigchecker_r.buddyKeys().size() << endl;
126  }
127 
128 
130 {
131 }
132 Downloader::Downloader(const RepoInfo & repoinfo) : _repoinfo(repoinfo)
133 {
134 }
136 {
137 }
138 
140 {
141  WAR << "Non implemented" << endl;
142  return RepoStatus();
143 }
144 
146  const Pathname &dest_dir,
147  const ProgressData::ReceiverFnc & progress )
148 {
149  WAR << "Non implemented" << endl;
150 }
151 
152 void Downloader::defaultDownloadMasterIndex( MediaSetAccess & media_r, const Pathname & destdir_r, const Pathname & masterIndex_r )
153 {
154  // always download them, even if repoGpgCheck is disabled
155  Pathname sigpath = masterIndex_r.extend( ".asc" );
156  Pathname keypath = masterIndex_r.extend( ".key" );
157 
158  //enable precache for next start() call
159  setMediaSetAccess( media_r );
160  enqueue( OnMediaLocation( sigpath, 1 ).setOptional( true ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ) );
161  enqueue( OnMediaLocation( keypath, 1 ).setOptional( true ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ) );
162  if ( env::ZYPP_REPOMD_WITH_PKCS7() ) {
163  Pathname pkcs7path = masterIndex_r.extend( ".pkcs7" );
164  enqueue( OnMediaLocation( pkcs7path, 1 ).setOptional( true ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ) );
165  }
166  start( destdir_r );
167  reset();
168 
169  // The local files are in destdir_r, if they were present on the server
170  Pathname sigpathLocal { destdir_r/sigpath };
171  Pathname keypathLocal { destdir_r/keypath };
172 
173 
174  CompositeFileChecker checkers;
175 
177  checkers.add( _pluginRepoverification->getChecker( sigpathLocal, keypathLocal, repoInfo() ) );
178 
179  ExtraSignatureFileChecker sigchecker;
180  bool isSigned = PathInfo(sigpathLocal).isExist();
181  if ( repoInfo().repoGpgCheck() )
182  {
183  if ( isSigned || repoInfo().repoGpgCheckIsMandatory() )
184  {
185  // only add the signature if it exists
186  if ( isSigned )
187  sigchecker.signature( sigpathLocal );
188 
189  // only add the key if it exists
190  if ( PathInfo(keypathLocal).isExist() )
191  sigchecker.addPublicKey( keypathLocal );
192 
193  // set the checker context even if the key is not known
194  // (unsigned repo, key file missing; bnc #495977)
195  sigchecker.keyContext( repoInfo() );
196 
197  // bsc#1184326: Check and handle extra gpg keys delivered with trusted signed master index.
198  if ( masterIndex_r.basename() == "repomd.xml" ) {
199  sigchecker.preCheckCB( [&]( const Pathname & file_r )->void {
200  // Take care no exception escapes! Main job is the signature verification.
201  try {
202  checkExtraKeysInRepomd( media_r, destdir_r, file_r, sigchecker );
203  }
204  catch ( const Exception & exp )
205  { ZYPP_CAUGHT(exp); }
206  catch ( const std::exception & exp )
207  { ZYPP_CAUGHT(exp); }
208  catch (...)
209  { INT << "Oops!" << endl; }
210  });
211  }
212  checkers.add( std::ref(sigchecker) ); // ref() to the local sigchecker is important as we want back fileValidated!
213  }
214  else
215  {
216  WAR << "Accept unsigned repository because repoGpgCheck is not mandatory for " << repoInfo().alias() << endl;
217  }
218  }
219  else
220  {
221  WAR << "Signature checking disabled in config of repository " << repoInfo().alias() << endl;
222  }
223 
224  enqueue( OnMediaLocation( masterIndex_r, 1 ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ), checkers );
225  start( destdir_r, media_r );
226  reset();
227 
228  // Accepted!
229  _repoinfo.setMetadataPath( destdir_r );
230  if ( isSigned )
232  else
233  _repoinfo.setValidRepoSignature( indeterminate );
234 }
235 
236 
237 }// ns repo
238 } // ns zypp
void preCheckCB(PreCheckCB cb_r)
Definition: Downloader.cc:53
bool fileValidated() const
Whether the signature was actually successfully verified.
#define MIL
Definition: Logger.h:96
void checkExtraKeysInRepomd(MediaSetAccess &media_r, const Pathname &destdir_r, const Pathname &repomd_r, SignatureFileChecker &sigchecker_r)
Definition: Downloader.cc:68
void defaultDownloadMasterIndex(MediaSetAccess &media_r, const Pathname &destdir_r, const Pathname &masterIndex_r)
Common workflow downloading a (signed) master index file.
Definition: Downloader.cc:152
Describes a resource file located on a medium.
bool ZYPP_REPOMD_WITH_PKCS7()
Definition: Downloader.cc:28
static ZConfig & instance()
Singleton ctor.
Definition: ZConfig.cc:922
Checks for the validity of a signature.
Definition: FileChecker.h:70
Pathname provideOptionalFile(const Pathname &file, unsigned media_nr=1)
Provides an optional file from media media_nr.
ExtraSignatureFileChecker(Pathname signature_r)
Definition: Downloader.cc:49
void addPublicKey(const PublicKey &publickey_r)
Add a public key to the list of known keys.
Definition: FileChecker.cc:121
Store and operate with byte count.
Definition: ByteCount.h:30
std::optional< PluginRepoverification > _pluginRepoverification
Definition: Downloader.h:78
Class representing one GPG Public Keys data.
Definition: PublicKey.h:206
Pathname pubkeyCachePath() const
Path where the pubkey caches.
Definition: ZConfig.cc:1045
function< void(const Pathname &file_r)> PreCheckCB
Called after download but before verifying the file.
Definition: Downloader.cc:44
void operator()(const Pathname &file_r) const
Call KeyRing::verifyFileSignatureWorkflow to verify the file.
Definition: FileChecker.cc:124
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition: Pathname.h:173
#define INT
Definition: Logger.h:100
Definition: Arch.h:363
What is known about a repository.
Definition: RepoInfo.h:71
static const Unit MB
1000^2 Byte
Definition: ByteCount.h:60
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:128
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
Definition: progressdata.h:140
void setValidRepoSignature(TriBool value_r)
Set the value for validRepoSignature (or indeterminate if unsigned).
Definition: RepoInfo.cc:454
const KeyContext & keyContext() const
KeyContext passed to callbacks
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
Pathname repoManagerRoot() const
The RepoManager root directory.
Definition: ZConfig.cc:953
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
void operator()(const Pathname &file_r) const
Definition: Downloader.cc:56
const Pathname & signature() const
Detached signature or empty.
std::string alias() const
unique identifier for this source.
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:281
std::vector< std::pair< std::string, std::string > > keyhints() const
gpg key hits shipped in keywords (bsc#1184326)
void add(const FileChecker &checker)
Definition: FileChecker.cc:108
void reset()
Reset the transfer (jobs) list.
Definition: Fetcher.cc:898
Downloader()
Constructor.
Definition: Downloader.cc:129
Interim helper class to collect global options and settings.
Definition: ZConfig.h:63
#define WAR
Definition: Logger.h:97
void setMetadataPath(const Pathname &path)
Set the path where the local metadata is stored.
Definition: RepoInfo.cc:662
int hardlinkCopy(const Pathname &oldpath, const Pathname &newpath)
Create newpath as hardlink or copy of oldpath.
Definition: PathInfo.cc:883
const RepoInfo & repoInfo() const
Definition: Downloader.h:63
const BuddyKeys & buddyKeys() const
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:436
Checker composed of more checkers.
Definition: FileChecker.h:129
Class representing one GPG Public Key (PublicKeyData + ASCII armored in a tempfile).
Definition: PublicKey.h:358
Reads through a repomd.xml file and collects type, location, checksum and other data about metadata f...
Base class for Exception.
Definition: Exception.h:145
static bool isSafeKeyId(const std::string &id_r)
!<
Definition: PublicKey.h:426
virtual void download(MediaSetAccess &media, const Pathname &dest_dir, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
Download metadata to a local directory.
Definition: Downloader.cc:145
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
Definition: String.h:429
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:220
Interface of repomd.xml file reader.
Track changing files or directories.
Definition: RepoStatus.h:40
static PublicKey noThrow(const Pathname &keyFile_r)
Static ctor returning an empty PublicKey rather than throwing.
Definition: PublicKey.cc:639
virtual RepoStatus status(MediaSetAccess &media)
Status of the remote repository.
Definition: Downloader.cc:139
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
void addBuddyKey(std::string sid_r)
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
#define DBG
Definition: Logger.h:95