libzypp 17.31.28
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
23using std::endl;
24
25namespace 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
38namespace 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
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}
132Downloader::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
152void 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 ) ) );
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
Interface of repomd.xml file reader.
Store and operate with byte count.
Definition: ByteCount.h:31
static const Unit MB
1000^2 Byte
Definition: ByteCount.h:60
Checker composed of more checkers.
Definition: FileChecker.h:130
void add(const FileChecker &checker)
Definition: FileChecker.cc:108
Base class for Exception.
Definition: Exception.h:146
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 reset()
Reset the transfer (jobs) list.
Definition: Fetcher.cc:898
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 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
Media access layer responsible for handling files distributed on a set of media with media change and...
Pathname provideOptionalFile(const Pathname &file, unsigned media_nr=1)
Provides an optional file from media media_nr.
Describes a resource file located on a medium.
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
Definition: progressdata.h:140
Class representing one GPG Public Keys data.
Definition: PublicKey.h:207
Class representing one GPG Public Key (PublicKeyData + ASCII armored in a tempfile).
Definition: PublicKey.h:359
static bool isSafeKeyId(const std::string &id_r)
!<
Definition: PublicKey.h:426
static PublicKey noThrow(const Pathname &keyFile_r)
Static ctor returning an empty PublicKey rather than throwing.
Definition: PublicKey.cc:639
What is known about a repository.
Definition: RepoInfo.h:72
void setValidRepoSignature(TriBool value_r)
Set the value for validRepoSignature (or indeterminate if unsigned).
Definition: RepoInfo.cc:454
void setMetadataPath(const Pathname &path)
Set the path where the local metadata is stored.
Definition: RepoInfo.cc:662
Track changing files or directories.
Definition: RepoStatus.h:41
Checks for the validity of a signature.
Definition: FileChecker.h:71
void operator()(const Pathname &file_r) const
Call KeyRing::verifyFileSignatureWorkflow to verify the file.
Definition: FileChecker.cc:124
void addPublicKey(const PublicKey &publickey_r)
Add a public key to the list of known keys.
Definition: FileChecker.cc:121
Interim helper class to collect global options and settings.
Definition: ZConfig.h:64
Pathname repoManagerRoot() const
The RepoManager root directory.
Definition: ZConfig.cc:953
static ZConfig & instance()
Singleton ctor.
Definition: ZConfig.cc:922
Pathname pubkeyCachePath() const
Path where the pubkey caches.
Definition: ZConfig.cc:1045
Wrapper class for stat/lstat.
Definition: PathInfo.h:221
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:281
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition: Pathname.h:173
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:128
bool fileValidated() const
Whether the signature was actually successfully verified.
const KeyContext & keyContext() const
KeyContext passed to callbacks
const BuddyKeys & buddyKeys() const
const Pathname & signature() const
Detached signature or empty.
void addBuddyKey(std::string sid_r)
Reads through a repomd.xml file and collects type, location, checksum and other data about metadata f...
std::vector< std::pair< std::string, std::string > > keyhints() const
gpg key hits shipped in keywords (bsc#1184326)
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
std::optional< PluginRepoverification > _pluginRepoverification
Definition: Downloader.h:78
const RepoInfo & repoInfo() const
Definition: Downloader.h:63
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
virtual RepoStatus status(MediaSetAccess &media)
Status of the remote repository.
Definition: Downloader.cc:139
Downloader()
Constructor.
Definition: Downloader.cc:129
void operator()(const Pathname &file_r) const
Definition: Downloader.cc:56
function< void(const Pathname &file_r)> PreCheckCB
Called after download but before verifying the file.
Definition: Downloader.cc:44
void preCheckCB(PreCheckCB cb_r)
Definition: Downloader.cc:53
ExtraSignatureFileChecker(Pathname signature_r)
Definition: Downloader.cc:49
std::string alias() const
unique identifier for this source.
Definition: Arch.h:364
bool ZYPP_REPOMD_WITH_PKCS7()
Definition: Downloader.cc:28
int hardlinkCopy(const Pathname &oldpath, const Pathname &newpath)
Create newpath as hardlink or copy of oldpath.
Definition: PathInfo.cc:883
void checkExtraKeysInRepomd(MediaSetAccess &media_r, const Pathname &destdir_r, const Pathname &repomd_r, SignatureFileChecker &sigchecker_r)
Definition: Downloader.cc:68
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
Definition: String.h:429
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:436
#define DBG
Definition: Logger.h:95
#define MIL
Definition: Logger.h:96
#define WAR
Definition: Logger.h:97
#define INT
Definition: Logger.h:100