libzypp  17.31.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  // always download them, even if repoGpgCheck is disabled
144  Pathname sigpath = masterIndex_r.extend( ".asc" );
145  Pathname keypath = masterIndex_r.extend( ".key" );
146 
147  //enable precache for next start() call
148  setMediaSetAccess( media_r );
149  enqueue( OnMediaLocation( sigpath, 1 ).setOptional( true ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ) );
150  enqueue( OnMediaLocation( keypath, 1 ).setOptional( true ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ) );
151  start( destdir_r );
152  reset();
153 
154  // The local files are in destdir_r, if they were present on the server
155  Pathname sigpathLocal { destdir_r/sigpath };
156  Pathname keypathLocal { destdir_r/keypath };
157 
158 
159  CompositeFileChecker checkers;
160 
162  checkers.add( _pluginRepoverification->getChecker( sigpathLocal, keypathLocal, repoInfo() ) );
163 
164  ExtraSignatureFileChecker sigchecker;
165  bool isSigned = PathInfo(sigpathLocal).isExist();
166  if ( repoInfo().repoGpgCheck() )
167  {
168  if ( isSigned || repoInfo().repoGpgCheckIsMandatory() )
169  {
170  // only add the signature if it exists
171  if ( isSigned )
172  sigchecker.signature( sigpathLocal );
173 
174  // only add the key if it exists
175  if ( PathInfo(keypathLocal).isExist() )
176  sigchecker.addPublicKey( keypathLocal );
177 
178  // set the checker context even if the key is not known
179  // (unsigned repo, key file missing; bnc #495977)
180  sigchecker.keyContext( repoInfo() );
181 
182  // bsc#1184326: Check and handle extra gpg keys delivered with trusted signed master index.
183  if ( masterIndex_r.basename() == "repomd.xml" ) {
184  sigchecker.preCheckCB( [&]( const Pathname & file_r )->void {
185  // Take care no exception escapes! Main job is the signature verification.
186  try {
187  checkExtraKeysInRepomd( media_r, destdir_r, file_r, sigchecker );
188  }
189  catch ( const Exception & exp )
190  { ZYPP_CAUGHT(exp); }
191  catch ( const std::exception & exp )
192  { ZYPP_CAUGHT(exp); }
193  catch (...)
194  { INT << "Oops!" << endl; }
195  });
196  }
197  checkers.add( ref(sigchecker) ); // ref() to the local sigchecker is important as we want back fileValidated!
198  }
199  else
200  {
201  WAR << "Accept unsigned repository because repoGpgCheck is not mandatory for " << repoInfo().alias() << endl;
202  }
203  }
204  else
205  {
206  WAR << "Signature checking disabled in config of repository " << repoInfo().alias() << endl;
207  }
208 
209  enqueue( OnMediaLocation( masterIndex_r, 1 ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ), checkers );
210  start( destdir_r, media_r );
211  reset();
212 
213  // Accepted!
214  _repoinfo.setMetadataPath( destdir_r );
215  if ( isSigned )
217  else
218  _repoinfo.setValidRepoSignature( indeterminate );
219 }
220 
221 
222 }// ns repo
223 } // ns zypp
224 
225 
226 
void preCheckCB(PreCheckCB cb_r)
Definition: Downloader.cc:42
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:57
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
Describes a resource file located on a medium.
static ZConfig & instance()
Singleton ctor.
Definition: ZConfig.cc:823
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:38
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:946
function< void(const Pathname &file_r)> PreCheckCB
Called after download but before verifying the file.
Definition: Downloader.cc:33
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:351
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:139
void setValidRepoSignature(TriBool value_r)
Set the value for validRepoSignature (or indeterminate if unsigned).
Definition: RepoInfo.cc:453
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:854
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:45
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:118
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:661
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:134
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:128
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