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();
99 _dlContext->files().push_back( std::move(*sigFile) );
103 if ( expKeyId && !_dlContext->zyppContext()->keyRing()->isKeyKnown(*expKeyId) ) {
105 bool needsMirrorToFetchKey = _dlContext->repoInfo().baseUrlsEmpty() && _dlContext->repoInfo().mirrorListUrl().isValid() ;
106 if ( needsMirrorToFetchKey ) {
109 JobReportHelper( _dlContext->zyppContext() ).
warning(
_(
"Downloading signature key via mirrors, consider explicitly setting gpgKeyUrl via the repository configuration instead."));
117 _dlContext->files().push_back( std::move(keyFile));
135 _masterIndexFile = std::move(masterIndex);
140 |
and_then( std::bind( &DownloadMasterIndexLogic::pluginVerification,
this ) )
143 |
and_then( std::bind( &DownloadMasterIndexLogic::executeSigcheckPlugins,
this ) )
146 |
and_then( std::bind( &DownloadMasterIndexLogic::signatureCheck,
this ) )
151 _dlContext->repoInfo().setMetadataPath( _destdir );
152 _dlContext->repoInfo().setValidRepoSignature( _repoSigValidated );
155 _media = MediaHandle();
156 auto &allFiles = _dlContext->files();
159 allFiles.insert( allFiles.begin(), std::move(_masterIndexFile) );
166 ProvideRef provider () {
167 return _dlContext->zyppContext()->provider();
170 MaybeAwaitable<expected<void>> executeSigcheckPlugins()
173 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 () {
223 if ( _dlContext->repoInfo().repoGpgCheck() ) {
231 if ( isSigned || _dlContext->repoInfo().repoGpgCheckIsMandatory() ) {
237 verifyCtx.signature( sigpathLocal );
242 _dlContext->zyppContext()->keyRing()->importKey(
zypp::PublicKey(keypathLocal),
false );
250 verifyCtx.keyContext( _dlContext->repoInfo() );
252 return getExtraKeysInRepomd()
253 |
and_then([
this, vCtx = std::move(verifyCtx) ]()
mutable {
254 for (
const auto &keyData : _buddyKeys ) {
255 DBG <<
"Keyhint remember buddy " << keyData << std::endl;
256 vCtx.addBuddyKey( keyData.id() );
268 WAR <<
"Accept unsigned repository because repoGpgCheck is not mandatory for " << _dlContext->repoInfo().alias() << std::endl;
271 WAR <<
"Signature checking disabled in config of repository " << _dlContext->repoInfo().alias() << std::endl;
283 if ( _dlContext->pluginRepoverification() && _dlContext->pluginRepoverification()->isNeeded() ) {
287 auto kr = _dlContext->zyppContext()->keyRing();
291 MIL <<
"Failed to read signature from file: " << sigpathLocal << std::endl;
293 std::ofstream os( keypathLocal.
c_str() );
294 if ( kr->isKeyKnown(*expKeyId) ) {
297 kr->isKeyTrusted(*expKeyId),
304 _dlContext->pluginRepoverification()->getChecker( sigpathLocal, keypathLocal, _dlContext->repoInfo() )( masterIndexLocal );
316 MaybeAwaitable<expected<void>> getExtraKeysInRepomd () {
317 const zypp::Pathname masterIndexLocal { _destdir / _masterIndex };
319 if ( _masterIndex.basename() !=
"repomd.xml" ) {
324 if ( keyhints.empty() )
326 DBG <<
"Check keyhints: " << keyhints.size() << std::endl;
328 auto keyRing { _dlContext->zyppContext()->keyRing() };
329 return std::move( keyhints )
330 |
transform( [
this, keyRing]( std::pair<std::string, std::string> val ) {
332 const auto& [ file, keyid ] = val;
333 auto keyData = keyRing->trustedPublicKeyData( keyid );
335 DBG <<
"Keyhint is already trusted: " << keyid <<
" (" << file <<
")" << std::endl;
339 DBG <<
"Keyhint search key " << keyid <<
" (" << file <<
")" << std::endl;
341 keyData = keyRing->publicKeyData( keyid );
346 const zypp::ZConfig & conf = _dlContext->zyppContext()->config();
350 | [ keyid = keyid ](
auto &&key ){
351 if ( key.fileProvidesKey( keyid ) )
357 auto providerRef = _dlContext->zyppContext()->provider();
358 return providerRef->provide( _media, file,
ProvideFileSpec().setOptional(
true).setMirrorsAllowed(
false) )
363 _dlContext->files().push_back ( std::move(res) );
366 if ( not key.fileProvidesKey( keyid ) ) {
367 const std::string
str = (
zypp::str::Str() <<
"Keyhint " << file <<
" does not contain a key with id " << keyid <<
". Skipping it.");
374 return providerRef->copyFile( key.path(), cacheFile )
378 res->resetDispose ();
385 keyRing->importKey( key,
false );
391 if ( keyData && *keyData ) {
392 if ( not zypp::PublicKey::isSafeKeyId( keyData->id() ) ) {
393 WAR <<
"Keyhint " << keyData->id() <<
" for " << *keyData <<
" is not strong enough for auto import. Just caching it." << std::endl;
396 _buddyKeys.push_back ( std::move(keyData.get()) );
400 MIL <<
"Check keyhints done. Buddy keys: " << _buddyKeys.size() << std::endl;
405 repo::DownloadContextRef _dlContext;
415 std::vector<zypp::PublicKeyData> _buddyKeys;
424 DownloadMasterIndexLogic impl( std::move(dl), std::move(mediaHandle), std::move(masterIndex_r) );
425 zypp_co_return zypp_co_await( impl.execute() );
431 return dl->zyppContext()->provider()->attachMediaIfNeeded( mediaHandle )
439 auto statusImpl ( repo::DownloadContextRef dlCtx,
ProvideMediaHandle &&mediaHandle ) {
444 switch( dlCtx->repoInfo().type().toEnum()) {
460 return statusImpl( dl, std::move(mediaHandle) );
465 return dl->zyppContext()->provider()->attachMediaIfNeeded( mediaHandle )
472 auto downloadImpl ( repo::DownloadContextRef dlCtx,
ProvideMediaHandle &&mediaHandle, ProgressObserverRef &&progressObserver ) {
473 switch( dlCtx->repoInfo().type().toEnum()) {
475 return RpmmdWorkflows::download( std::move(dlCtx), std::forward<ProvideMediaHandle>(mediaHandle), std::move(progressObserver) );
477 return SuseTagsWorkflows::download( std::move(dlCtx), std::forward<ProvideMediaHandle>(mediaHandle), std::move(progressObserver) );
490 return downloadImpl( dl, std::move(mediaHandle), std::move(progressObserver) );
496 return dl->zyppContext()->provider()->attachMediaIfNeeded( mediaHandle )
498 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...