libzypp 17.31.23
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{
27namespace 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
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}
121Downloader::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
141void 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( std::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
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:134
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:141
virtual RepoStatus status(MediaSetAccess &media)
Status of the remote repository.
Definition: Downloader.cc:128
Downloader()
Constructor.
Definition: Downloader.cc:118
void operator()(const Pathname &file_r) const
Definition: Downloader.cc:45
function< void(const Pathname &file_r)> PreCheckCB
Called after download but before verifying the file.
Definition: Downloader.cc:33
void preCheckCB(PreCheckCB cb_r)
Definition: Downloader.cc:42
ExtraSignatureFileChecker(Pathname signature_r)
Definition: Downloader.cc:38
std::string alias() const
unique identifier for this source.
Definition: Arch.h:361
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:57
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