15#include <zypp-media/ng/ProvideSpec>
21#include <zypp/ng/Context>
22#include <zypp/ng/media/Provide>
23#include <zypp/ng/repo/Downloader>
38#undef ZYPP_BASE_LOGGER_LOGGROUP
39#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::repomanager"
47 struct DownloadMasterIndexLogic
53 DownloadMasterIndexLogic( repo::DownloadContextRef &&ctxRef, MediaHandle &&mediaHandle,
zypp::filesystem::Pathname &&masterIndex_r )
54 : _dlContext( std::move(ctxRef) )
55 , _media(std::move( mediaHandle ))
56 , _masterIndex(std::move( masterIndex_r ))
60 MaybeAwaitable<expected<repo::DownloadContextRef>> execute( ) {
64 _sigpath = _masterIndex.extend(
".asc" );
65 _keypath = _masterIndex.extend(
".key" );
66 _destdir = _dlContext->destDir();
68 static const std::string rinfoSigcheckTag {
"repo_sigcheck_plugin" };
70 zypp::Pathname rmRoot { _dlContext->zyppContext()->config().repoManagerRoot() };
71 zypp::Pathname plugindir { _dlContext->zyppContext()->config().pluginsPath() };
73 if ( _sigcheckPlugins ) {
75 _sigcheckPlugins.launch( rmRoot );
82 auto providerRef = _dlContext->zyppContext()->provider();
98 _dlContext->files().push_back( std::move(*sigFile) );
102 if ( expKeyId && !_dlContext->zyppContext()->keyRing()->isKeyKnown(*expKeyId) ) {
104 bool needsMirrorToFetchKey = _dlContext->repoInfo().baseUrlsEmpty() && _dlContext->repoInfo().mirrorListUrl().isValid() ;
105 if ( needsMirrorToFetchKey ) {
108 JobReportHelper( _dlContext->zyppContext() ).
warning(
_(
"Downloading signature key via mirrors, consider explicitly setting gpgKeyUrl via the repository configuration instead."));
116 _dlContext->files().push_back( std::move(keyFile));
134 _masterIndexFile = std::move(masterIndex);
139 |
and_then( std::bind( &DownloadMasterIndexLogic::pluginVerification,
this ) )
142 |
and_then( std::bind( &DownloadMasterIndexLogic::executeSigcheckPlugins,
this ) )
145 |
and_then( std::bind( &DownloadMasterIndexLogic::signatureCheck,
this ) )
150 _dlContext->repoInfo().setMetadataPath( _destdir );
151 _dlContext->repoInfo().setValidRepoSignature( _repoSigValidated );
154 _media = MediaHandle();
155 auto &allFiles = _dlContext->files();
158 allFiles.insert( allFiles.begin(), std::move(_masterIndexFile) );
165 ProvideRef provider () {
166 return _dlContext->zyppContext()->provider();
169 MaybeAwaitable<expected<void>> executeSigcheckPlugins()
172 if ( !_sigcheckPlugins ) {
179 for (
auto & plugin : _sigcheckPlugins.plugins() ) {
180 auto * pluginPtr = &plugin;
181 for (
const auto & ext : { plugin.sigExtension(), plugin.keyExtension() } ) {
188 chain = std::move(chain) |
and_then([
this, extpath, extdest, pluginPtr]() {
189 return provider()->provide( _media, extpath,
ProvideFileSpec().setOptional(
false ).setMirrorsAllowed(
false ) )
192 _dlContext->files().push_back( std::move(downloaded_r) );
199 chain = std::move(chain) |
and_then([
this, pluginPtr]() {
200 const zypp::Pathname masterIndexLocal { _destdir / _masterIndex };
202 if ( not pluginPtr->sigExtension().empty() ) {
203 sig = _destdir / _masterIndex.
extend( pluginPtr->sigExtension() );
206 if ( not pluginPtr->keyExtension().empty() ) {
207 key = _destdir / _masterIndex.
extend( pluginPtr->keyExtension() );
210 pluginPtr->sigcheck( masterIndexLocal, sig, key );
221 MaybeAwaitable<expected<void>> signatureCheck () {
224 if ( _dlContext->repoInfo().repoGpgCheck() ) {
232 if ( isSigned || _dlContext->repoInfo().repoGpgCheckIsMandatory() ) {
238 verifyCtx.signature( sigpathLocal );
243 _dlContext->zyppContext()->keyRing()->importKey(
zypp::PublicKey(keypathLocal),
false );
251 verifyCtx.keyContext( _dlContext->repoInfo() );
253 return getExtraKeysInRepomd()
254 |
and_then([
this, vCtx = std::move(verifyCtx) ]()
mutable {
255 for (
const auto &keyData : _buddyKeys ) {
256 DBG <<
"Keyhint remember buddy " << keyData << std::endl;
257 vCtx.addBuddyKey( keyData.id() );
269 WAR <<
"Accept unsigned repository because repoGpgCheck is not mandatory for " << _dlContext->repoInfo().alias() << std::endl;
272 WAR <<
"Signature checking disabled in config of repository " << _dlContext->repoInfo().alias() << std::endl;
284 if ( _dlContext->pluginRepoverification() && _dlContext->pluginRepoverification()->isNeeded() ) {
288 auto kr = _dlContext->zyppContext()->keyRing();
292 MIL <<
"Failed to read signature from file: " << sigpathLocal << std::endl;
294 std::ofstream os( keypathLocal.
c_str() );
295 if ( kr->isKeyKnown(*expKeyId) ) {
298 kr->isKeyTrusted(*expKeyId),
305 _dlContext->pluginRepoverification()->getChecker( sigpathLocal, keypathLocal, _dlContext->repoInfo() )( masterIndexLocal );
317 MaybeAwaitable<expected<void>> getExtraKeysInRepomd () {
319 const zypp::Pathname masterIndexLocal { _destdir / _masterIndex };
321 if ( _masterIndex.basename() !=
"repomd.xml" ) {
326 if ( keyhints.empty() )
328 DBG <<
"Check keyhints: " << keyhints.size() << std::endl;
330 auto keyRing { _dlContext->zyppContext()->keyRing() };
331 return std::move( keyhints )
332 |
transform( [
this, keyRing]( std::pair<std::string, std::string> val ) {
334 const auto& [ file, keyid ] = val;
335 auto keyData = keyRing->trustedPublicKeyData( keyid );
337 DBG <<
"Keyhint is already trusted: " << keyid <<
" (" << file <<
")" << std::endl;
341 DBG <<
"Keyhint search key " << keyid <<
" (" << file <<
")" << std::endl;
343 keyData = keyRing->publicKeyData( keyid );
348 const zypp::ZConfig & conf = _dlContext->zyppContext()->config();
352 | [ keyid = keyid ](
auto &&key ){
353 if ( key.fileProvidesKey( keyid ) )
359 auto providerRef = _dlContext->zyppContext()->provider();
360 return providerRef->provide( _media, file,
ProvideFileSpec().setOptional(
true).setMirrorsAllowed(
false) )
365 _dlContext->files().push_back ( std::move(res) );
368 if ( not key.fileProvidesKey( keyid ) ) {
369 const std::string
str = (
zypp::str::Str() <<
"Keyhint " << file <<
" does not contain a key with id " << keyid <<
". Skipping it.");
376 return providerRef->copyFile( key.path(), cacheFile )
380 res->resetDispose ();
387 keyRing->importKey( key,
false );
393 if ( keyData && *keyData ) {
394 if ( not zypp::PublicKey::isSafeKeyId( keyData->id() ) ) {
395 WAR <<
"Keyhint " << keyData->id() <<
" for " << *keyData <<
" is not strong enough for auto import. Just caching it." << std::endl;
398 _buddyKeys.push_back ( std::move(keyData.get()) );
402 MIL <<
"Check keyhints done. Buddy keys: " << _buddyKeys.size() << std::endl;
407 repo::DownloadContextRef _dlContext;
417 std::vector<zypp::PublicKeyData> _buddyKeys;
426 DownloadMasterIndexLogic impl( std::move(dl), std::move(mediaHandle), std::move(masterIndex_r) );
427 zypp_co_return zypp_co_await( impl.execute() );
433 return dl->zyppContext()->provider()->attachMediaIfNeeded( mediaHandle )
441 auto statusImpl ( repo::DownloadContextRef dlCtx,
ProvideMediaHandle &&mediaHandle ) {
446 switch( dlCtx->repoInfo().type().toEnum()) {
462 return statusImpl( dl, std::move(mediaHandle) );
467 return dl->zyppContext()->provider()->attachMediaIfNeeded( mediaHandle )
474 auto downloadImpl ( repo::DownloadContextRef dlCtx,
ProvideMediaHandle &&mediaHandle, ProgressObserverRef &&progressObserver ) {
475 switch( dlCtx->repoInfo().type().toEnum()) {
477 return RpmmdWorkflows::download( std::move(dlCtx), std::forward<ProvideMediaHandle>(mediaHandle), std::move(progressObserver) );
479 return SuseTagsWorkflows::download( std::move(dlCtx), std::forward<ProvideMediaHandle>(mediaHandle), std::move(progressObserver) );
492 return downloadImpl( dl, std::move(mediaHandle), std::move(progressObserver) );
498 return dl->zyppContext()->provider()->attachMediaIfNeeded( mediaHandle )
500 return downloadImpl( dl, std::move(handle), std::move(po) );
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
#define ZYPP_FWD_CURRENT_EXCPT()
Drops a logline and returns the current Exception as a std::exception_ptr.
Interface of repomd.xml file reader.
Store and operate with byte count.
static const Unit MB
1000^2 Byte
Base class for Exception.
std::string readSignatureKeyId(const Pathname &signature)
reads the public key id from a signature
Class representing one GPG Public Key (PublicKeyData + ASCII armored in a tempfile).
static PublicKey noThrow(const Pathname &keyFile_r)
Static ctor returning an empty PublicKey rather than throwing.
What is known about a repository.
bool hasExtraValue(const std::string &key_r) const
Whether an extra value for key_r is set.
std::string extraValue(const std::string &key_r) const
Return extra value for key_r or throws std::out_of_range.
Track changing files or directories.
Handle a bunch of SigcheckPlugins.
Interim helper class to collect global options and settings.
Pathname repoManagerRoot() const
The RepoManager root directory.
Pathname pubkeyCachePath() const
Path where the pubkey caches.
Wrapper class for stat/lstat.
bool isExist() const
Return whether valid stat info exists.
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Pathname dirname() const
Return all but the last component od this path.
const char * c_str() const
String representation.
I/O context for KeyRing::verifyFileSignatureWorkflow.
bool fileValidated() const
Whether the signature was actually successfully verified.
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)
thrown when it was impossible to determine this repo type.
bool warning(std::string msg_r, UserData userData_r=UserData())
send warning text
static auto copyResultToDest(ProvideRef provider, const zypp::Pathname &targetPath)
ProvideMediaHandle MediaHandle
static expected success(ConsParams &&...params)
static expected error(ConsParams &&...params)
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
String related utilities and Regular expression matching.
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
MaybeAwaitable< expected< repo::DownloadContextRef > > download(repo::DownloadContextRef dl, ProvideMediaHandle mediaHandle, ProgressObserverRef progressObserver)
MaybeAwaitable< expected< zypp::RepoStatus > > repoStatus(repo::DownloadContextRef dl, ProvideMediaHandle mediaHandle)
MaybeAwaitable< expected< zypp::RepoStatus > > repoStatus(repo::DownloadContextRef dl, ProvideMediaHandle mediaHandle)
MaybeAwaitable< expected< repo::DownloadContextRef > > download(repo::DownloadContextRef dl, ProvideMediaHandle mediaHandle, ProgressObserverRef progressObserver=nullptr)
MaybeAwaitable< expected< repo::DownloadContextRef > > downloadMasterIndex(repo::DownloadContextRef dl, ProvideMediaHandle mediaHandle, zypp::filesystem::Pathname masterIndex_r)
MaybeAwaitable< expected< void > > fetchGpgKeys(ContextRef ctx, zypp::RepoInfo info)
MaybeAwaitable< expected< repo::DownloadContextRef > > download(repo::DownloadContextRef dl, ProvideMediaHandle mediaHandle, ProgressObserverRef progressObserver)
MaybeAwaitable< expected< zypp::RepoStatus > > repoStatus(repo::DownloadContextRef dl, ProvideMediaHandle mediaHandle)
MaybeAwaitable< expected< zypp::keyring::VerifyFileContext > > verifySignature(ContextRef ctx, zypp::keyring::VerifyFileContext context)
auto and_then(Fun &&function)
static expected< std::decay_t< Type >, Err > make_expected_success(Type &&t)
ResultType or_else(const expected< T, E > &exp, Function &&f)
ResultType and_then(const expected< T, E > &exp, Function &&f)
auto transform(Container< Msg, CArgs... > &&val, Transformation &&transformation)
auto mtry(F &&f, Args &&...args)
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...