Update to 1.18.0
Resolves: RHEL-126038 Resolves: RHEL-92123 Resolves: RHEL-165631 Resolves: RHEL-170158
This commit is contained in:
parent
b99c73432a
commit
7da9e0d25b
1
.gitignore
vendored
1
.gitignore
vendored
@ -117,3 +117,4 @@
|
||||
/flatpak-1.16.0.tar.xz
|
||||
/flatpak-1.17.2.tar.xz
|
||||
/flatpak-1.17.3.tar.xz
|
||||
/flatpak-1.18.0.tar.xz
|
||||
|
||||
970
flatpak-oci-Retry-on-401-with-FlatpakTokenProvider.patch
Normal file
970
flatpak-oci-Retry-on-401-with-FlatpakTokenProvider.patch
Normal file
@ -0,0 +1,970 @@
|
||||
From 7ccc155aa363f389f52c7676b353ad5c9d6dcfc5 Mon Sep 17 00:00:00 2001
|
||||
From: Luigi Pavan <lpavan@redhat.com>
|
||||
Date: Thu, 14 May 2026 12:27:57 +0200
|
||||
Subject: [PATCH 1/3] oci: Retry on 401 with FlatpakTokenProvider
|
||||
|
||||
When a bearer token expires mid-transaction, OCI registry HTTP requests
|
||||
fail with 401 Unauthorized, causing the entire transaction to fail. This
|
||||
is particularly problematic for long-running transactions where the
|
||||
token lifetime is shorter than the total operation time.
|
||||
|
||||
Add a token refresh mechanism that allows the OCI registry layer to
|
||||
transparently retry a failed HTTP request after obtaining a fresh token
|
||||
via a FlatpakTokenProvider object provided by the transaction layer.
|
||||
|
||||
FlatpakTokenProvider is a GObject that encapsulates the ability to
|
||||
obtain and refresh bearer tokens. It holds references to the transaction
|
||||
and the current operation, and its refresh_token method re-invokes
|
||||
request_tokens_for_remote() to get a fresh token from the authenticator.
|
||||
Its get_token method returns the current token from the operation,
|
||||
providing a live view that reflects any refresh.
|
||||
|
||||
FlatpakTokenProvider replaces the const char *token parameter on the
|
||||
OCI code path functions, while leaving OSTree-only functions unchanged.
|
||||
At registry creation points, the provider is set on the registry so it
|
||||
can be used for retry on 401.
|
||||
|
||||
At the FlatpakOciRegistry level, a token_provider field is added. On
|
||||
401, the three HTTP call sites (remote_load_file, download_blob,
|
||||
mirror_blob) attempt one token refresh and retry, defensively resetting
|
||||
any output streams before the retry.
|
||||
---
|
||||
common/flatpak-common-types-private.h | 1 +
|
||||
common/flatpak-dir-private.h | 43 ++++----
|
||||
common/flatpak-dir.c | 80 +++++++-------
|
||||
common/flatpak-image-source-private.h | 10 +-
|
||||
common/flatpak-image-source.c | 20 ++--
|
||||
common/flatpak-oci-registry-private.h | 2 +
|
||||
common/flatpak-oci-registry.c | 104 ++++++++++++++++---
|
||||
common/flatpak-transaction.c | 144 +++++++++++++++++++-------
|
||||
8 files changed, 288 insertions(+), 116 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-common-types-private.h b/common/flatpak-common-types-private.h
|
||||
index cb09d78e6d..49bb8bbeeb 100644
|
||||
--- a/common/flatpak-common-types-private.h
|
||||
+++ b/common/flatpak-common-types-private.h
|
||||
@@ -59,5 +59,6 @@ typedef struct _FlatpakImageSource FlatpakImageSource;
|
||||
typedef struct FlatpakOciRegistry FlatpakOciRegistry;
|
||||
typedef struct _FlatpakOciManifest FlatpakOciManifest;
|
||||
typedef struct _FlatpakOciImage FlatpakOciImage;
|
||||
+typedef struct _FlatpakTokenProvider FlatpakTokenProvider;
|
||||
|
||||
#endif /* __FLATPAK_COMMON_TYPES_H__ */
|
||||
diff --git a/common/flatpak-dir-private.h b/common/flatpak-dir-private.h
|
||||
index 9a9f8a12a6..431bb96c1a 100644
|
||||
--- a/common/flatpak-dir-private.h
|
||||
+++ b/common/flatpak-dir-private.h
|
||||
@@ -62,6 +62,13 @@ GType flatpak_deploy_get_type (void);
|
||||
|
||||
typedef struct _PolkitSubject PolkitSubject;
|
||||
|
||||
+#define FLATPAK_TYPE_TOKEN_PROVIDER flatpak_token_provider_get_type ()
|
||||
+G_DECLARE_FINAL_TYPE (FlatpakTokenProvider, flatpak_token_provider, FLATPAK, TOKEN_PROVIDER, GObject)
|
||||
+
|
||||
+const char *flatpak_token_provider_get_token (FlatpakTokenProvider *self);
|
||||
+gboolean flatpak_token_provider_refresh_token (FlatpakTokenProvider *self,
|
||||
+ GCancellable *cancellable);
|
||||
+
|
||||
typedef struct
|
||||
{
|
||||
FlatpakDecomposed *ref;
|
||||
@@ -160,25 +167,25 @@ gboolean flatpak_remote_state_lookup_sparse_cache (FlatpakRemoteState *self,
|
||||
const char *ref,
|
||||
VarMetadataRef *out_metadata,
|
||||
GError **error);
|
||||
-GVariant *flatpak_remote_state_load_ref_commit (FlatpakRemoteState *self,
|
||||
- FlatpakDir *dir,
|
||||
- const char *ref,
|
||||
- const char *opt_commit,
|
||||
- const char *token,
|
||||
- char **out_commit,
|
||||
- GCancellable *cancellable,
|
||||
- GError **error);
|
||||
+GVariant *flatpak_remote_state_load_ref_commit (FlatpakRemoteState *self,
|
||||
+ FlatpakDir *dir,
|
||||
+ const char *ref,
|
||||
+ const char *opt_commit,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
+ char **out_commit,
|
||||
+ GCancellable *cancellable,
|
||||
+ GError **error);
|
||||
void flatpak_remote_state_add_sideload_dir (FlatpakRemoteState *self,
|
||||
GFile *path);
|
||||
void flatpak_remote_state_add_sideload_image_collection (FlatpakRemoteState *self,
|
||||
FlatpakImageCollection *image_collection);
|
||||
-FlatpakImageSource * flatpak_remote_state_fetch_image_source (FlatpakRemoteState *self,
|
||||
- FlatpakDir *dir,
|
||||
- const char *ref,
|
||||
- const char *opt_rev,
|
||||
- const char *token,
|
||||
- GCancellable *cancellable,
|
||||
- GError **error);
|
||||
+FlatpakImageSource * flatpak_remote_state_fetch_image_source (FlatpakRemoteState *self,
|
||||
+ FlatpakDir *dir,
|
||||
+ const char *ref,
|
||||
+ const char *opt_rev,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
+ GCancellable *cancellable,
|
||||
+ GError **error);
|
||||
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakDir, g_object_unref)
|
||||
@@ -611,7 +618,7 @@ gboolean flatpak_dir_pull (Fla
|
||||
GFile *sideload_repo,
|
||||
FlatpakImageSource *opt_image_source,
|
||||
GBytes *require_metadata,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
OstreeRepo *repo,
|
||||
FlatpakPullFlags flatpak_flags,
|
||||
OstreeRepoPullFlags flags,
|
||||
@@ -735,7 +742,7 @@ gboolean flatpak_dir_install (Fla
|
||||
GFile *sideload_repo,
|
||||
FlatpakImageSource *opt_image_source,
|
||||
GBytes *require_metadata,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
FlatpakProgress *progress,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
@@ -783,7 +790,7 @@ gboolean flatpak_dir_update (Fla
|
||||
GFile *sideload_repo,
|
||||
FlatpakImageSource *opt_image_source,
|
||||
GBytes *require_metadata,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
FlatpakProgress *progress,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
|
||||
index 73118e1127..da96153eb1 100644
|
||||
--- a/common/flatpak-dir.c
|
||||
+++ b/common/flatpak-dir.c
|
||||
@@ -116,7 +116,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (AutoPolkitSubject, g_object_unref)
|
||||
|
||||
static FlatpakOciRegistry *flatpak_dir_create_system_child_oci_registry (FlatpakDir *self,
|
||||
GLnxLockFile *file_lock,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
GError **error);
|
||||
|
||||
static OstreeRepo * flatpak_dir_create_child_repo (FlatpakDir *self,
|
||||
@@ -135,7 +135,7 @@ static gboolean flatpak_dir_mirror_oci (FlatpakDir *self,
|
||||
const char *ref,
|
||||
const char *opt_rev,
|
||||
FlatpakImageSource *opt_image_source,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
FlatpakProgress *progress,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
@@ -1209,7 +1209,7 @@ flatpak_remote_state_new_image_source (FlatpakRemoteState *self,
|
||||
FlatpakDir *dir,
|
||||
const char *oci_repository,
|
||||
const char *digest,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
@@ -1229,7 +1229,7 @@ flatpak_remote_state_new_image_source (FlatpakRemoteState *self,
|
||||
image_source = flatpak_image_source_new_remote (registry_uri,
|
||||
oci_repository,
|
||||
digest,
|
||||
- token,
|
||||
+ token_provider,
|
||||
signature_lookaside,
|
||||
NULL, error);
|
||||
if (image_source == NULL)
|
||||
@@ -1243,7 +1243,7 @@ flatpak_remote_state_fetch_image_source (FlatpakRemoteState *self,
|
||||
FlatpakDir *dir,
|
||||
const char *ref,
|
||||
const char *opt_rev,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
@@ -1277,7 +1277,7 @@ flatpak_remote_state_fetch_image_source (FlatpakRemoteState *self,
|
||||
|
||||
oci_digest = g_strconcat ("sha256:", opt_rev ? opt_rev : latest_rev, NULL);
|
||||
|
||||
- image_source = flatpak_remote_state_new_image_source (self, dir, oci_repository, oci_digest, token, cancellable, error);
|
||||
+ image_source = flatpak_remote_state_new_image_source (self, dir, oci_repository, oci_digest, token_provider, cancellable, error);
|
||||
if (image_source == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -1302,13 +1302,13 @@ flatpak_remote_state_fetch_commit_object_oci (FlatpakRemoteState *self,
|
||||
FlatpakDir *dir,
|
||||
const char *ref,
|
||||
const char *checksum,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(FlatpakImageSource) image_source = NULL;
|
||||
|
||||
- image_source = flatpak_remote_state_fetch_image_source (self, dir, ref, checksum, token, cancellable, error);
|
||||
+ image_source = flatpak_remote_state_fetch_image_source (self, dir, ref, checksum, token_provider, cancellable, error);
|
||||
if (image_source == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -1430,7 +1430,7 @@ flatpak_remote_state_load_ref_commit (FlatpakRemoteState *self,
|
||||
FlatpakDir *dir,
|
||||
const char *ref,
|
||||
const char *opt_commit,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
char **out_commit,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
@@ -1481,11 +1481,16 @@ flatpak_remote_state_load_ref_commit (FlatpakRemoteState *self,
|
||||
}
|
||||
|
||||
if (flatpak_dir_get_remote_oci (dir, self->remote_name))
|
||||
- commit_data = flatpak_remote_state_fetch_commit_object_oci (self, dir, ref, commit, token,
|
||||
- cancellable, error);
|
||||
+ {
|
||||
+ commit_data = flatpak_remote_state_fetch_commit_object_oci (self, dir, ref, commit, token_provider,
|
||||
+ cancellable, error);
|
||||
+ }
|
||||
else
|
||||
- commit_data = flatpak_remote_state_fetch_commit_object (self, dir, ref, commit, token,
|
||||
- cancellable, error);
|
||||
+ {
|
||||
+ const char *token = token_provider ? flatpak_token_provider_get_token (token_provider) : NULL;
|
||||
+ commit_data = flatpak_remote_state_fetch_commit_object (self, dir, ref, commit, token,
|
||||
+ cancellable, error);
|
||||
+ }
|
||||
|
||||
out:
|
||||
if (out_commit)
|
||||
@@ -6317,7 +6322,7 @@ flatpak_dir_setup_extra_data (FlatpakDir *self,
|
||||
OstreeRepo *repo,
|
||||
const char *ref,
|
||||
const char *rev,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
FlatpakPullFlags flatpak_flags,
|
||||
FlatpakProgress *progress,
|
||||
GCancellable *cancellable,
|
||||
@@ -6362,7 +6367,7 @@ flatpak_dir_setup_extra_data (FlatpakDir *self,
|
||||
g_autoptr(GVariant) extra_data_sources = NULL;
|
||||
|
||||
commitv = flatpak_remote_state_load_ref_commit (state, self, ref, rev,
|
||||
- token, NULL, cancellable, error);
|
||||
+ token_provider, NULL, cancellable, error);
|
||||
if (commitv == NULL)
|
||||
return FALSE;
|
||||
|
||||
@@ -6838,7 +6843,7 @@ flatpak_dir_mirror_oci (FlatpakDir *self,
|
||||
const char *ref,
|
||||
const char *opt_rev,
|
||||
FlatpakImageSource *opt_image_source,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
FlatpakProgress *progress,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
@@ -6852,7 +6857,7 @@ flatpak_dir_mirror_oci (FlatpakDir *self,
|
||||
if (!image_source)
|
||||
{
|
||||
image_source = flatpak_remote_state_fetch_image_source (state, self,
|
||||
- ref, opt_rev, token,
|
||||
+ ref, opt_rev, token_provider,
|
||||
cancellable, error);
|
||||
if (image_source == NULL)
|
||||
return FALSE;
|
||||
@@ -6887,7 +6892,7 @@ flatpak_dir_pull_oci (FlatpakDir *self,
|
||||
OstreeRepo *repo,
|
||||
FlatpakPullFlags flatpak_flags,
|
||||
OstreeRepoPullFlags flags,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
FlatpakProgress *progress,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
@@ -6907,7 +6912,7 @@ flatpak_dir_pull_oci (FlatpakDir *self,
|
||||
if (!image_source)
|
||||
{
|
||||
image_source = flatpak_remote_state_fetch_image_source (state, self,
|
||||
- ref, opt_rev, token,
|
||||
+ ref, opt_rev, token_provider,
|
||||
cancellable, error);
|
||||
if (image_source == NULL)
|
||||
return FALSE;
|
||||
@@ -6935,7 +6940,7 @@ flatpak_dir_pull_oci (FlatpakDir *self,
|
||||
g_info ("Imported OCI image as checksum %s", checksum);
|
||||
|
||||
if (!flatpak_dir_setup_extra_data (self, state, repo,
|
||||
- ref, checksum, token,
|
||||
+ ref, checksum, token_provider,
|
||||
flatpak_flags,
|
||||
progress,
|
||||
cancellable,
|
||||
@@ -6976,7 +6981,7 @@ flatpak_dir_pull (FlatpakDir *self,
|
||||
GFile *sideload_repo,
|
||||
FlatpakImageSource *opt_image_source,
|
||||
GBytes *require_metadata,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
OstreeRepo *repo,
|
||||
FlatpakPullFlags flatpak_flags,
|
||||
OstreeRepoPullFlags flags,
|
||||
@@ -6992,6 +6997,7 @@ flatpak_dir_pull (FlatpakDir *self,
|
||||
g_auto(GLnxLockFile) lock = { 0, };
|
||||
g_autofree char *name = NULL;
|
||||
g_autofree char *current_checksum = NULL;
|
||||
+ const char *token = token_provider ? flatpak_token_provider_get_token (token_provider) : NULL;
|
||||
|
||||
if (!flatpak_dir_ensure_repo (self, cancellable, error))
|
||||
return FALSE;
|
||||
@@ -7007,7 +7013,7 @@ flatpak_dir_pull (FlatpakDir *self,
|
||||
|
||||
if (opt_image_source || flatpak_dir_get_remote_oci (self, state->remote_name))
|
||||
return flatpak_dir_pull_oci (self, state, ref, opt_rev, opt_image_source, repo, flatpak_flags,
|
||||
- flags, token, progress, cancellable, error);
|
||||
+ flags, token_provider, progress, cancellable, error);
|
||||
|
||||
if (!ostree_repo_remote_get_url (self->repo,
|
||||
state->remote_name,
|
||||
@@ -7057,7 +7063,7 @@ flatpak_dir_pull (FlatpakDir *self,
|
||||
/* Setup extra data information before starting to pull, so we can have precise
|
||||
* progress reports */
|
||||
if (!flatpak_dir_setup_extra_data (self, state, repo,
|
||||
- ref, rev, token,
|
||||
+ ref, rev, token_provider,
|
||||
flatpak_flags,
|
||||
progress,
|
||||
cancellable,
|
||||
@@ -10483,7 +10489,7 @@ rewrite_dynamic_launchers (FlatpakDecomposed *ref,
|
||||
static FlatpakOciRegistry *
|
||||
flatpak_dir_create_system_child_oci_registry (FlatpakDir *self,
|
||||
GLnxLockFile *file_lock,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GFile) cache_dir = NULL;
|
||||
@@ -10518,7 +10524,11 @@ flatpak_dir_create_system_child_oci_registry (FlatpakDir *self,
|
||||
if (new_registry == NULL)
|
||||
return NULL;
|
||||
|
||||
- flatpak_oci_registry_set_token (new_registry, token);
|
||||
+ if (token_provider)
|
||||
+ {
|
||||
+ flatpak_oci_registry_set_token (new_registry, flatpak_token_provider_get_token (token_provider));
|
||||
+ flatpak_oci_registry_set_token_provider (new_registry, token_provider);
|
||||
+ }
|
||||
|
||||
return g_steal_pointer (&new_registry);
|
||||
}
|
||||
@@ -10800,7 +10810,7 @@ flatpak_dir_install (FlatpakDir *self,
|
||||
GFile *sideload_repo,
|
||||
FlatpakImageSource *opt_image_source,
|
||||
GBytes *require_metadata,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
FlatpakProgress *progress,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
@@ -10855,7 +10865,7 @@ flatpak_dir_install (FlatpakDir *self,
|
||||
g_autoptr(FlatpakOciRegistry) registry = NULL;
|
||||
g_autoptr(GFile) registry_file = NULL;
|
||||
|
||||
- registry = flatpak_dir_create_system_child_oci_registry (self, &child_repo_lock, token, error);
|
||||
+ registry = flatpak_dir_create_system_child_oci_registry (self, &child_repo_lock, token_provider, error);
|
||||
if (registry == NULL)
|
||||
return FALSE;
|
||||
|
||||
@@ -10864,7 +10874,7 @@ flatpak_dir_install (FlatpakDir *self,
|
||||
child_repo_path = g_file_get_path (registry_file);
|
||||
|
||||
if (!flatpak_dir_mirror_oci (self, registry, state, flatpak_decomposed_get_ref (ref),
|
||||
- opt_commit, opt_image_source, token, progress, cancellable, error))
|
||||
+ opt_commit, opt_image_source, token_provider, progress, cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
else if (!gpg_verify_summary || !gpg_verify)
|
||||
@@ -10958,7 +10968,7 @@ flatpak_dir_install (FlatpakDir *self,
|
||||
|
||||
flatpak_flags |= FLATPAK_PULL_FLAGS_SIDELOAD_EXTRA_DATA;
|
||||
|
||||
- if (!flatpak_dir_pull (self, state, flatpak_decomposed_get_ref (ref), opt_commit, subpaths, sideload_repo, NULL, require_metadata, token,
|
||||
+ if (!flatpak_dir_pull (self, state, flatpak_decomposed_get_ref (ref), opt_commit, subpaths, sideload_repo, NULL, require_metadata, token_provider,
|
||||
child_repo,
|
||||
flatpak_flags,
|
||||
0,
|
||||
@@ -11037,7 +11047,7 @@ flatpak_dir_install (FlatpakDir *self,
|
||||
if (!no_pull)
|
||||
{
|
||||
if (!flatpak_dir_pull (self, state, flatpak_decomposed_get_ref (ref), opt_commit, opt_subpaths,
|
||||
- sideload_repo, opt_image_source, require_metadata, token, NULL,
|
||||
+ sideload_repo, opt_image_source, require_metadata, token_provider, NULL,
|
||||
flatpak_flags, OSTREE_REPO_PULL_FLAGS_NONE,
|
||||
progress, cancellable, error))
|
||||
return FALSE;
|
||||
@@ -11512,7 +11522,7 @@ flatpak_dir_update (FlatpakDir *self,
|
||||
GFile *sideload_repo,
|
||||
FlatpakImageSource *opt_image_source,
|
||||
GBytes *require_metadata,
|
||||
- const char *token,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
FlatpakProgress *progress,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
@@ -11589,7 +11599,7 @@ flatpak_dir_update (FlatpakDir *self,
|
||||
g_autoptr(FlatpakOciRegistry) registry = NULL;
|
||||
g_autoptr(GFile) registry_file = NULL;
|
||||
|
||||
- registry = flatpak_dir_create_system_child_oci_registry (self, &child_repo_lock, token, error);
|
||||
+ registry = flatpak_dir_create_system_child_oci_registry (self, &child_repo_lock, token_provider, error);
|
||||
if (registry == NULL)
|
||||
return FALSE;
|
||||
|
||||
@@ -11598,7 +11608,7 @@ flatpak_dir_update (FlatpakDir *self,
|
||||
child_repo_path = g_file_get_path (registry_file);
|
||||
|
||||
if (!flatpak_dir_mirror_oci (self, registry, state, flatpak_decomposed_get_ref (ref),
|
||||
- commit, opt_image_source, token, progress, cancellable, error))
|
||||
+ commit, opt_image_source, token_provider, progress, cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
else if (!gpg_verify_summary || !gpg_verify)
|
||||
@@ -11678,7 +11688,7 @@ flatpak_dir_update (FlatpakDir *self,
|
||||
|
||||
flatpak_flags |= FLATPAK_PULL_FLAGS_SIDELOAD_EXTRA_DATA;
|
||||
if (!flatpak_dir_pull (self, state, flatpak_decomposed_get_ref (ref),
|
||||
- commit, subpaths, sideload_repo, NULL, require_metadata, token,
|
||||
+ commit, subpaths, sideload_repo, NULL, require_metadata, token_provider,
|
||||
child_repo,
|
||||
flatpak_flags, 0,
|
||||
progress, cancellable, error))
|
||||
@@ -11744,7 +11754,7 @@ flatpak_dir_update (FlatpakDir *self,
|
||||
if (!no_pull)
|
||||
{
|
||||
if (!flatpak_dir_pull (self, state, flatpak_decomposed_get_ref (ref),
|
||||
- commit, subpaths, sideload_repo, opt_image_source, require_metadata, token,
|
||||
+ commit, subpaths, sideload_repo, opt_image_source, require_metadata, token_provider,
|
||||
NULL, flatpak_flags, OSTREE_REPO_PULL_FLAGS_NONE,
|
||||
progress, cancellable, error))
|
||||
return FALSE;
|
||||
diff --git a/common/flatpak-image-source-private.h b/common/flatpak-image-source-private.h
|
||||
index 1259c1348d..92f6ea7df2 100644
|
||||
--- a/common/flatpak-image-source-private.h
|
||||
+++ b/common/flatpak-image-source-private.h
|
||||
@@ -42,11 +42,11 @@ FlatpakImageSource *flatpak_image_source_new_local (GFile *file,
|
||||
const char *reference,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
-FlatpakImageSource *flatpak_image_source_new_remote (const char *uri,
|
||||
- const char *oci_repository,
|
||||
- const char *digest,
|
||||
- const char *token,
|
||||
- const char *signature_lookaside,
|
||||
+FlatpakImageSource *flatpak_image_source_new_remote (const char *uri,
|
||||
+ const char *oci_repository,
|
||||
+ const char *digest,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
+ const char *signature_lookaside,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
FlatpakImageSource *flatpak_image_source_new_for_location (const char *location,
|
||||
diff --git a/common/flatpak-image-source.c b/common/flatpak-image-source.c
|
||||
index eab92a1b8e..adb81947a1 100644
|
||||
--- a/common/flatpak-image-source.c
|
||||
+++ b/common/flatpak-image-source.c
|
||||
@@ -180,13 +180,13 @@ flatpak_image_source_new_local (GFile *file,
|
||||
}
|
||||
|
||||
FlatpakImageSource *
|
||||
-flatpak_image_source_new_remote (const char *uri,
|
||||
- const char *oci_repository,
|
||||
- const char *digest,
|
||||
- const char *token,
|
||||
- const char *signature_lookaside,
|
||||
- GCancellable *cancellable,
|
||||
- GError **error)
|
||||
+flatpak_image_source_new_remote (const char *uri,
|
||||
+ const char *oci_repository,
|
||||
+ const char *digest,
|
||||
+ FlatpakTokenProvider *token_provider,
|
||||
+ const char *signature_lookaside,
|
||||
+ GCancellable *cancellable,
|
||||
+ GError **error)
|
||||
{
|
||||
g_autoptr(FlatpakOciRegistry) registry = NULL;
|
||||
|
||||
@@ -194,7 +194,11 @@ flatpak_image_source_new_remote (const char *uri,
|
||||
if (!registry)
|
||||
return NULL;
|
||||
|
||||
- flatpak_oci_registry_set_token (registry, token);
|
||||
+ if (token_provider)
|
||||
+ {
|
||||
+ flatpak_oci_registry_set_token (registry, flatpak_token_provider_get_token (token_provider));
|
||||
+ flatpak_oci_registry_set_token_provider (registry, token_provider);
|
||||
+ }
|
||||
flatpak_oci_registry_set_signature_lookaside (registry, signature_lookaside);
|
||||
|
||||
return flatpak_image_source_new (registry, oci_repository, digest, cancellable, error);
|
||||
diff --git a/common/flatpak-oci-registry-private.h b/common/flatpak-oci-registry-private.h
|
||||
index ca56eab396..2fc75bc2c8 100644
|
||||
--- a/common/flatpak-oci-registry-private.h
|
||||
+++ b/common/flatpak-oci-registry-private.h
|
||||
@@ -61,6 +61,8 @@ FlatpakOciRegistry * flatpak_oci_registry_new_for_archive (GFile *archi
|
||||
GError **error);
|
||||
void flatpak_oci_registry_set_token (FlatpakOciRegistry *self,
|
||||
const char *token);
|
||||
+void flatpak_oci_registry_set_token_provider (FlatpakOciRegistry *self,
|
||||
+ FlatpakTokenProvider *provider);
|
||||
void flatpak_oci_registry_set_signature_lookaside (FlatpakOciRegistry *self,
|
||||
const char *signature_lookaside);
|
||||
gboolean flatpak_oci_registry_is_local (FlatpakOciRegistry *self);
|
||||
diff --git a/common/flatpak-oci-registry.c b/common/flatpak-oci-registry.c
|
||||
index 3a3fec3d46..429c32d244 100644
|
||||
--- a/common/flatpak-oci-registry.c
|
||||
+++ b/common/flatpak-oci-registry.c
|
||||
@@ -74,6 +74,7 @@ struct FlatpakOciRegistry
|
||||
GFile *archive;
|
||||
int tmp_dfd;
|
||||
char *token;
|
||||
+ FlatpakTokenProvider *token_provider;
|
||||
char *signature_lookaside;
|
||||
|
||||
/* Local repos */
|
||||
@@ -138,6 +139,7 @@ flatpak_oci_registry_finalize (GObject *object)
|
||||
g_clear_pointer (&self->base_uri, g_uri_unref);
|
||||
g_clear_pointer (&self->uri, g_free);
|
||||
g_clear_pointer (&self->token, g_free);
|
||||
+ g_clear_object (&self->token_provider);
|
||||
g_clear_object (&self->archive);
|
||||
g_clear_pointer (&self->tmp_dir, glnx_tmpdir_free);
|
||||
g_clear_pointer (&self->certificates, flatpak_certificates_free);
|
||||
@@ -291,6 +293,29 @@ flatpak_oci_registry_set_token (FlatpakOciRegistry *self,
|
||||
0, NULL, NULL);
|
||||
}
|
||||
|
||||
+void
|
||||
+flatpak_oci_registry_set_token_provider (FlatpakOciRegistry *self,
|
||||
+ FlatpakTokenProvider *provider)
|
||||
+{
|
||||
+ g_set_object (&self->token_provider, provider);
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+flatpak_oci_registry_try_refresh_token (FlatpakOciRegistry *self,
|
||||
+ GCancellable *cancellable)
|
||||
+{
|
||||
+ if (self->token_provider == NULL)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ g_info ("Refreshing registry token for %s", self->uri);
|
||||
+
|
||||
+ if (!flatpak_token_provider_refresh_token (self->token_provider, cancellable))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ flatpak_oci_registry_set_token (self, flatpak_token_provider_get_token (self->token_provider));
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
void
|
||||
flatpak_oci_registry_set_signature_lookaside (FlatpakOciRegistry *self,
|
||||
const char *signature_lookaside)
|
||||
@@ -384,6 +409,18 @@ remote_load_file (FlatpakOciRegistry *self,
|
||||
NULL, self->token,
|
||||
NULL, NULL, NULL, out_content_type, NULL,
|
||||
cancellable, error);
|
||||
+ if (bytes == NULL
|
||||
+ && g_error_matches (*error, FLATPAK_HTTP_ERROR, FLATPAK_HTTP_ERROR_UNAUTHORIZED)
|
||||
+ && flatpak_oci_registry_try_refresh_token (self, cancellable))
|
||||
+ {
|
||||
+ g_clear_error (error);
|
||||
+ bytes = flatpak_load_uri_full (self->http_session,
|
||||
+ uri_s, self->certificates, FLATPAK_HTTP_FLAGS_ACCEPT_OCI,
|
||||
+ NULL, self->token,
|
||||
+ NULL, NULL, NULL, out_content_type, NULL,
|
||||
+ cancellable, error);
|
||||
+ }
|
||||
+
|
||||
if (bytes == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -1016,13 +1053,34 @@ flatpak_oci_registry_download_blob (FlatpakOciRegistry *self,
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
- if (!flatpak_download_http_uri (self->http_session, uri_s,
|
||||
- self->certificates,
|
||||
- FLATPAK_HTTP_FLAGS_ACCEPT_OCI,
|
||||
- out_stream,
|
||||
- self->token,
|
||||
- progress_cb, user_data,
|
||||
- cancellable, error))
|
||||
+ gboolean download_ok;
|
||||
+
|
||||
+ download_ok = flatpak_download_http_uri (self->http_session, uri_s,
|
||||
+ self->certificates,
|
||||
+ FLATPAK_HTTP_FLAGS_ACCEPT_OCI,
|
||||
+ out_stream,
|
||||
+ self->token,
|
||||
+ progress_cb, user_data,
|
||||
+ cancellable, error);
|
||||
+ if (!download_ok
|
||||
+ && g_error_matches (*error, FLATPAK_HTTP_ERROR, FLATPAK_HTTP_ERROR_UNAUTHORIZED)
|
||||
+ && flatpak_oci_registry_try_refresh_token (self, cancellable))
|
||||
+ {
|
||||
+ g_clear_error (error);
|
||||
+ g_clear_object (&out_stream);
|
||||
+ ftruncate (fd, 0);
|
||||
+ lseek (fd, 0, SEEK_SET);
|
||||
+ out_stream = g_unix_output_stream_new (fd, FALSE);
|
||||
+
|
||||
+ download_ok = flatpak_download_http_uri (self->http_session, uri_s,
|
||||
+ self->certificates,
|
||||
+ FLATPAK_HTTP_FLAGS_ACCEPT_OCI,
|
||||
+ out_stream,
|
||||
+ self->token,
|
||||
+ progress_cb, user_data,
|
||||
+ cancellable, error);
|
||||
+ }
|
||||
+ if (!download_ok)
|
||||
return -1;
|
||||
|
||||
if (!g_output_stream_close (out_stream, cancellable, error))
|
||||
@@ -1107,14 +1165,34 @@ flatpak_oci_registry_mirror_blob (FlatpakOciRegistry *self,
|
||||
if (uri_s == NULL)
|
||||
return FALSE;
|
||||
|
||||
+ gboolean download_ok;
|
||||
+
|
||||
out_stream = g_unix_output_stream_new (tmpf.fd, FALSE);
|
||||
|
||||
- if (!flatpak_download_http_uri (source_registry->http_session,
|
||||
- uri_s, source_registry->certificates,
|
||||
- FLATPAK_HTTP_FLAGS_ACCEPT_OCI, out_stream,
|
||||
- self->token,
|
||||
- progress_cb, user_data,
|
||||
- cancellable, error))
|
||||
+ download_ok = flatpak_download_http_uri (source_registry->http_session,
|
||||
+ uri_s, source_registry->certificates,
|
||||
+ FLATPAK_HTTP_FLAGS_ACCEPT_OCI, out_stream,
|
||||
+ self->token,
|
||||
+ progress_cb, user_data,
|
||||
+ cancellable, error);
|
||||
+ if (!download_ok
|
||||
+ && g_error_matches (*error, FLATPAK_HTTP_ERROR, FLATPAK_HTTP_ERROR_UNAUTHORIZED)
|
||||
+ && flatpak_oci_registry_try_refresh_token (self, cancellable))
|
||||
+ {
|
||||
+ g_clear_error (error);
|
||||
+ g_clear_object (&out_stream);
|
||||
+ ftruncate (tmpf.fd, 0);
|
||||
+ lseek (tmpf.fd, 0, SEEK_SET);
|
||||
+ out_stream = g_unix_output_stream_new (tmpf.fd, FALSE);
|
||||
+
|
||||
+ download_ok = flatpak_download_http_uri (source_registry->http_session,
|
||||
+ uri_s, source_registry->certificates,
|
||||
+ FLATPAK_HTTP_FLAGS_ACCEPT_OCI, out_stream,
|
||||
+ self->token,
|
||||
+ progress_cb, user_data,
|
||||
+ cancellable, error);
|
||||
+ }
|
||||
+ if (!download_ok)
|
||||
return FALSE;
|
||||
|
||||
if (!g_output_stream_close (out_stream, cancellable, error))
|
||||
diff --git a/common/flatpak-transaction.c b/common/flatpak-transaction.c
|
||||
index 5d1460ce60..cc17d58786 100644
|
||||
--- a/common/flatpak-transaction.c
|
||||
+++ b/common/flatpak-transaction.c
|
||||
@@ -164,6 +164,25 @@ typedef struct {
|
||||
GVariant *results;
|
||||
} RequestData;
|
||||
|
||||
+/* Pointers are not ref'd; the provider never outlives the transaction or op. */
|
||||
+struct _FlatpakTokenProvider {
|
||||
+ GObject parent;
|
||||
+ FlatpakTransaction *transaction;
|
||||
+ FlatpakTransactionOperation *op;
|
||||
+};
|
||||
+
|
||||
+G_DEFINE_TYPE (FlatpakTokenProvider, flatpak_token_provider, G_TYPE_OBJECT)
|
||||
+
|
||||
+static void
|
||||
+flatpak_token_provider_class_init (FlatpakTokenProviderClass *klass)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+flatpak_token_provider_init (FlatpakTokenProvider *self)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
typedef struct _FlatpakTransactionPrivate
|
||||
{
|
||||
GObject parent;
|
||||
@@ -244,6 +263,8 @@ enum {
|
||||
};
|
||||
|
||||
static gboolean op_may_need_token (FlatpakTransactionOperation *op);
|
||||
+static FlatpakTokenProvider *flatpak_token_provider_new_for_op (FlatpakTransaction *transaction,
|
||||
+ FlatpakTransactionOperation *op);
|
||||
|
||||
static void flatpak_transaction_normalize_ops (FlatpakTransaction *self);
|
||||
static gboolean request_required_tokens (FlatpakTransaction *self,
|
||||
@@ -3910,9 +3931,12 @@ resolve_ops (FlatpakTransaction *self,
|
||||
flatpak_remote_state_lookup_ref (state, flatpak_decomposed_get_ref (op->ref),
|
||||
NULL, NULL, &op->summary_metadata, NULL, NULL, NULL);
|
||||
|
||||
+ g_autoptr(FlatpakTokenProvider) token_provider =
|
||||
+ flatpak_token_provider_new_for_op (self, op);
|
||||
+
|
||||
commit_data = flatpak_remote_state_load_ref_commit (state, priv->dir,
|
||||
flatpak_decomposed_get_ref (op->ref),
|
||||
- checksum, /* initially NULL */ op->resolved_token,
|
||||
+ checksum, token_provider,
|
||||
NULL, NULL, &local_error);
|
||||
if (commit_data == NULL)
|
||||
{
|
||||
@@ -4351,6 +4375,7 @@ request_tokens_for_remote (FlatpakTransaction *self,
|
||||
|
||||
/* Allow sending empty tokens to mean no token needed */
|
||||
|
||||
+ g_free (op->resolved_token);
|
||||
op->resolved_token = *token == 0 ? NULL : g_strdup (token);
|
||||
op->requested_token = TRUE;
|
||||
}
|
||||
@@ -4358,6 +4383,41 @@ request_tokens_for_remote (FlatpakTransaction *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+static FlatpakTokenProvider *
|
||||
+flatpak_token_provider_new_for_op (FlatpakTransaction *transaction,
|
||||
+ FlatpakTransactionOperation *op)
|
||||
+{
|
||||
+ FlatpakTokenProvider *self = g_object_new (FLATPAK_TYPE_TOKEN_PROVIDER, NULL);
|
||||
+
|
||||
+ self->transaction = transaction;
|
||||
+ self->op = op;
|
||||
+
|
||||
+ return self;
|
||||
+}
|
||||
+
|
||||
+const char *
|
||||
+flatpak_token_provider_get_token (FlatpakTokenProvider *self)
|
||||
+{
|
||||
+ return self->op->resolved_token;
|
||||
+}
|
||||
+
|
||||
+gboolean
|
||||
+flatpak_token_provider_refresh_token (FlatpakTokenProvider *self,
|
||||
+ GCancellable *cancellable)
|
||||
+{
|
||||
+ GList op_list = { .data = self->op, .next = NULL, .prev = NULL };
|
||||
+ g_autoptr(GError) local_error = NULL;
|
||||
+
|
||||
+ if (!request_tokens_for_remote (self->transaction, self->op->remote,
|
||||
+ &op_list, cancellable, &local_error))
|
||||
+ {
|
||||
+ g_info ("Token refresh failed: %s", local_error->message);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
static gboolean
|
||||
request_required_tokens (FlatpakTransaction *self,
|
||||
const char *optional_remote, /* else all remotes */
|
||||
@@ -5093,24 +5153,29 @@ _run_op_kind (FlatpakTransaction *self,
|
||||
op->resolved_metakey, &local_error))
|
||||
res = FALSE;
|
||||
else
|
||||
- res = flatpak_dir_install (priv->dir,
|
||||
- priv->no_pull,
|
||||
- priv->no_deploy,
|
||||
- priv->disable_static_deltas,
|
||||
- priv->reinstall,
|
||||
- priv->max_op >= APP_UPDATE,
|
||||
- op->pin_on_deploy,
|
||||
- op->update_preinstalled_on_deploy,
|
||||
- remote_state, op->ref,
|
||||
- op->resolved_commit,
|
||||
- (const char **) op->subpaths,
|
||||
- (const char **) op->previous_ids,
|
||||
- op->resolved_sideload_path,
|
||||
- op->resolved_image_source,
|
||||
- op->resolved_metadata,
|
||||
- op->resolved_token,
|
||||
- progress->progress_obj,
|
||||
- cancellable, &local_error);
|
||||
+ {
|
||||
+ g_autoptr(FlatpakTokenProvider) token_provider =
|
||||
+ flatpak_token_provider_new_for_op (self, op);
|
||||
+
|
||||
+ res = flatpak_dir_install (priv->dir,
|
||||
+ priv->no_pull,
|
||||
+ priv->no_deploy,
|
||||
+ priv->disable_static_deltas,
|
||||
+ priv->reinstall,
|
||||
+ priv->max_op >= APP_UPDATE,
|
||||
+ op->pin_on_deploy,
|
||||
+ op->update_preinstalled_on_deploy,
|
||||
+ remote_state, op->ref,
|
||||
+ op->resolved_commit,
|
||||
+ (const char **) op->subpaths,
|
||||
+ (const char **) op->previous_ids,
|
||||
+ op->resolved_sideload_path,
|
||||
+ op->resolved_image_source,
|
||||
+ op->resolved_metadata,
|
||||
+ token_provider,
|
||||
+ progress->progress_obj,
|
||||
+ cancellable, &local_error);
|
||||
+ }
|
||||
|
||||
flatpak_transaction_progress_done (progress);
|
||||
|
||||
@@ -5167,24 +5232,29 @@ _run_op_kind (FlatpakTransaction *self,
|
||||
(const char **) op->previous_ids,
|
||||
cancellable, &local_error);
|
||||
else
|
||||
- res = flatpak_dir_update (priv->dir,
|
||||
- priv->no_pull,
|
||||
- priv->no_deploy,
|
||||
- priv->disable_static_deltas,
|
||||
- op->commit != NULL, /* Allow downgrade if we specify commit */
|
||||
- priv->max_op >= APP_UPDATE,
|
||||
- priv->max_op == APP_INSTALL || priv->max_op == RUNTIME_INSTALL,
|
||||
- remote_state,
|
||||
- op->ref,
|
||||
- op->resolved_commit,
|
||||
- (const char **) op->subpaths,
|
||||
- (const char **) op->previous_ids,
|
||||
- op->resolved_sideload_path,
|
||||
- op->resolved_image_source,
|
||||
- op->resolved_metadata,
|
||||
- op->resolved_token,
|
||||
- progress->progress_obj,
|
||||
- cancellable, &local_error);
|
||||
+ {
|
||||
+ g_autoptr(FlatpakTokenProvider) token_provider =
|
||||
+ flatpak_token_provider_new_for_op (self, op);
|
||||
+
|
||||
+ res = flatpak_dir_update (priv->dir,
|
||||
+ priv->no_pull,
|
||||
+ priv->no_deploy,
|
||||
+ priv->disable_static_deltas,
|
||||
+ op->commit != NULL, /* Allow downgrade if we specify commit */
|
||||
+ priv->max_op >= APP_UPDATE,
|
||||
+ priv->max_op == APP_INSTALL || priv->max_op == RUNTIME_INSTALL,
|
||||
+ remote_state,
|
||||
+ op->ref,
|
||||
+ op->resolved_commit,
|
||||
+ (const char **) op->subpaths,
|
||||
+ (const char **) op->previous_ids,
|
||||
+ op->resolved_sideload_path,
|
||||
+ op->resolved_image_source,
|
||||
+ op->resolved_metadata,
|
||||
+ token_provider,
|
||||
+ progress->progress_obj,
|
||||
+ cancellable, &local_error);
|
||||
+ }
|
||||
flatpak_transaction_progress_done (progress);
|
||||
|
||||
/* Handle noop-updates */
|
||||
|
||||
From 4ae3855f058d4aeed6f50298268d40dcb0c75375 Mon Sep 17 00:00:00 2001
|
||||
From: Luigi Pavan <lpavan@redhat.com>
|
||||
Date: Tue, 19 May 2026 11:55:00 +0200
|
||||
Subject: [PATCH 2/3] oci: Fix crash when error parameter is NULL in 401 retry
|
||||
logic
|
||||
|
||||
The 401 retry logic added in the previous commit dereferences the
|
||||
GError **error parameter with *error without first checking that error
|
||||
is non-NULL. When callers pass NULL for error (e.g. the _deltaindex
|
||||
lookup), this causes a SIGSEGV.
|
||||
|
||||
Add error != NULL guards to all three retry sites in remote_load_file,
|
||||
flatpak_oci_registry_download_blob, and flatpak_oci_registry_mirror_blob.
|
||||
---
|
||||
common/flatpak-oci-registry.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/common/flatpak-oci-registry.c b/common/flatpak-oci-registry.c
|
||||
index 429c32d244..5ff45995f4 100644
|
||||
--- a/common/flatpak-oci-registry.c
|
||||
+++ b/common/flatpak-oci-registry.c
|
||||
@@ -410,6 +410,7 @@ remote_load_file (FlatpakOciRegistry *self,
|
||||
NULL, NULL, NULL, out_content_type, NULL,
|
||||
cancellable, error);
|
||||
if (bytes == NULL
|
||||
+ && error != NULL
|
||||
&& g_error_matches (*error, FLATPAK_HTTP_ERROR, FLATPAK_HTTP_ERROR_UNAUTHORIZED)
|
||||
&& flatpak_oci_registry_try_refresh_token (self, cancellable))
|
||||
{
|
||||
@@ -1063,6 +1064,7 @@ flatpak_oci_registry_download_blob (FlatpakOciRegistry *self,
|
||||
progress_cb, user_data,
|
||||
cancellable, error);
|
||||
if (!download_ok
|
||||
+ && error != NULL
|
||||
&& g_error_matches (*error, FLATPAK_HTTP_ERROR, FLATPAK_HTTP_ERROR_UNAUTHORIZED)
|
||||
&& flatpak_oci_registry_try_refresh_token (self, cancellable))
|
||||
{
|
||||
@@ -1176,6 +1178,7 @@ flatpak_oci_registry_mirror_blob (FlatpakOciRegistry *self,
|
||||
progress_cb, user_data,
|
||||
cancellable, error);
|
||||
if (!download_ok
|
||||
+ && error != NULL
|
||||
&& g_error_matches (*error, FLATPAK_HTTP_ERROR, FLATPAK_HTTP_ERROR_UNAUTHORIZED)
|
||||
&& flatpak_oci_registry_try_refresh_token (self, cancellable))
|
||||
{
|
||||
|
||||
From 7fc7350f6d1e24abef3e18cf6da792e28751c746 Mon Sep 17 00:00:00 2001
|
||||
From: Luigi Pavan <lpavan@redhat.com>
|
||||
Date: Mon, 8 Jun 2026 18:55:15 +0200
|
||||
Subject: [PATCH 3/3] oci: Fix download_blob 401 retry writing to O_RDONLY fd
|
||||
|
||||
The retry path after a 401 discarded the O_WRONLY out_stream and
|
||||
wrapped the O_RDONLY fd as a new write stream. ftruncate() silently
|
||||
failed on the read-only descriptor and subsequent writes returned
|
||||
EBADF, leaving the temp file empty. checksum_fd() then computed the
|
||||
SHA-256 of zero bytes, causing a digest mismatch and a failed install.
|
||||
|
||||
Fix by using g_unix_output_stream_get_fd() to reach the O_WRONLY fd,
|
||||
resetting it in place, and reusing the existing stream. Apply the
|
||||
same truncate-and-seek pattern to mirror_blob, where the stream
|
||||
destroy-and-recreate roundtrip was unnecessary.
|
||||
---
|
||||
common/flatpak-oci-registry.c | 9 +++------
|
||||
1 file changed, 3 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-oci-registry.c b/common/flatpak-oci-registry.c
|
||||
index 5ff45995f4..10d96049b5 100644
|
||||
--- a/common/flatpak-oci-registry.c
|
||||
+++ b/common/flatpak-oci-registry.c
|
||||
@@ -1069,10 +1069,9 @@ flatpak_oci_registry_download_blob (FlatpakOciRegistry *self,
|
||||
&& flatpak_oci_registry_try_refresh_token (self, cancellable))
|
||||
{
|
||||
g_clear_error (error);
|
||||
- g_clear_object (&out_stream);
|
||||
- ftruncate (fd, 0);
|
||||
- lseek (fd, 0, SEEK_SET);
|
||||
- out_stream = g_unix_output_stream_new (fd, FALSE);
|
||||
+ int write_fd = g_unix_output_stream_get_fd (G_UNIX_OUTPUT_STREAM (out_stream));
|
||||
+ ftruncate (write_fd, 0);
|
||||
+ lseek (write_fd, 0, SEEK_SET);
|
||||
|
||||
download_ok = flatpak_download_http_uri (self->http_session, uri_s,
|
||||
self->certificates,
|
||||
@@ -1183,10 +1182,8 @@ flatpak_oci_registry_mirror_blob (FlatpakOciRegistry *self,
|
||||
&& flatpak_oci_registry_try_refresh_token (self, cancellable))
|
||||
{
|
||||
g_clear_error (error);
|
||||
- g_clear_object (&out_stream);
|
||||
ftruncate (tmpf.fd, 0);
|
||||
lseek (tmpf.fd, 0, SEEK_SET);
|
||||
- out_stream = g_unix_output_stream_new (tmpf.fd, FALSE);
|
||||
|
||||
download_ok = flatpak_download_http_uri (source_registry->http_session,
|
||||
uri_s, source_registry->certificates,
|
||||
@ -0,0 +1,457 @@
|
||||
From d439efe6dd66f623aca58d58ed981520f300113d Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Thu, 11 Jun 2026 17:24:11 +0200
|
||||
Subject: [PATCH 1/4] oci-registry: Load the certificates from an ImageSource
|
||||
|
||||
---
|
||||
common/flatpak-oci-registry.c | 30 ++++++++++++++++--------------
|
||||
1 file changed, 16 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-oci-registry.c b/common/flatpak-oci-registry.c
|
||||
index 3a3fec3d46..0a442cd407 100644
|
||||
--- a/common/flatpak-oci-registry.c
|
||||
+++ b/common/flatpak-oci-registry.c
|
||||
@@ -2405,23 +2405,28 @@ remote_load_signatures (FlatpakOciRegistry *self,
|
||||
}
|
||||
|
||||
static FlatpakOciSignatures *
|
||||
-flatpak_oci_registry_load_signatures (FlatpakOciRegistry *self,
|
||||
- const char *oci_repository,
|
||||
- const char *digest,
|
||||
- GCancellable *cancellable,
|
||||
- GError **error)
|
||||
+load_signatures (FlatpakImageSource *image_source,
|
||||
+ GCancellable *cancellable,
|
||||
+ GError **error)
|
||||
{
|
||||
- if (self->dfd != -1)
|
||||
+ FlatpakOciRegistry *registry = flatpak_image_source_get_registry (image_source);
|
||||
+
|
||||
+ if (registry->dfd != -1)
|
||||
{
|
||||
g_autoptr(FlatpakOciSignatures) signatures = flatpak_oci_signatures_new ();
|
||||
|
||||
- if (!flatpak_oci_signatures_load_from_dfd (signatures, self->dfd, cancellable, error))
|
||||
+ if (!flatpak_oci_signatures_load_from_dfd (signatures, registry->dfd, cancellable, error))
|
||||
return NULL;
|
||||
|
||||
return g_steal_pointer (&signatures);
|
||||
}
|
||||
else
|
||||
- return remote_load_signatures (self, oci_repository, digest, cancellable, error);
|
||||
+ {
|
||||
+ const char *oci_repository = flatpak_image_source_get_oci_repository (image_source);
|
||||
+ const char *digest = flatpak_image_source_get_digest (image_source);
|
||||
+
|
||||
+ return remote_load_signatures (registry, oci_repository, digest, cancellable, error);
|
||||
+ }
|
||||
}
|
||||
|
||||
static const char *
|
||||
@@ -3283,8 +3288,7 @@ flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry,
|
||||
if (!flatpak_oci_registry_save_index (dst_registry, index, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
- signatures = flatpak_oci_registry_load_signatures (registry, oci_repository, digest,
|
||||
- cancellable, error);
|
||||
+ signatures = load_signatures (image_source, cancellable, error);
|
||||
if (!signatures)
|
||||
return FALSE;
|
||||
|
||||
@@ -3339,10 +3343,8 @@ flatpak_pull_from_oci (OstreeRepo *repo,
|
||||
|
||||
g_assert (g_str_has_prefix (digest, "sha256:"));
|
||||
|
||||
- signatures = flatpak_oci_registry_load_signatures (dst_registry,
|
||||
- dest_oci_repository,
|
||||
- digest,
|
||||
- cancellable, error);
|
||||
+ signatures = load_signatures (opt_dst_image_source ? opt_dst_image_source : image_source,
|
||||
+ cancellable, error);
|
||||
if (!signatures)
|
||||
return FALSE;
|
||||
|
||||
|
||||
From 780916961cb935b74c2fcaeed6e88b30e35d04e1 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Thu, 11 Jun 2026 17:27:47 +0200
|
||||
Subject: [PATCH 2/4] oci-registry: Check signatures from mirrored repo in the
|
||||
system helper
|
||||
|
||||
In flatpak_pull_from_oci we can be in in the system helper where we pull
|
||||
the mirrored OCI image into the system repo. However, to fetch the
|
||||
signatures in GPG signed repos, we used a remote OciImageSource created
|
||||
through `flatpak_remote_state_fetch_image_source`. This caused fetching
|
||||
some data from the registry which we don't want in the deploy method,
|
||||
and also fails if a token is required to access the repo.
|
||||
|
||||
This change fetches the signatures from the mirrored OCI repo instead of
|
||||
pulling them from the remote OciImageSource. The signatures can come from
|
||||
anywhere because we verify them against the GPG key in the system repo.
|
||||
|
||||
The important bit is the change in `flatpak_pull_from_oci` where we now
|
||||
pass in the local image_source to fetch the signatures from, and in the
|
||||
system helper, where we get the right metadata to check the signatures
|
||||
against (eventually ends up in `flatpak_oci_signatures_verify`).
|
||||
---
|
||||
app/flatpak-builtins-build-import-bundle.c | 2 +-
|
||||
common/flatpak-dir.c | 2 +-
|
||||
common/flatpak-oci-registry-private.h | 3 ++-
|
||||
common/flatpak-oci-registry.c | 16 ++++++-------
|
||||
system-helper/flatpak-system-helper.c | 28 ++++++++++++++--------
|
||||
5 files changed, 29 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/app/flatpak-builtins-build-import-bundle.c b/app/flatpak-builtins-build-import-bundle.c
|
||||
index 6b06073f30..5455bb5348 100644
|
||||
--- a/app/flatpak-builtins-build-import-bundle.c
|
||||
+++ b/app/flatpak-builtins-build-import-bundle.c
|
||||
@@ -68,7 +68,7 @@ import_oci (OstreeRepo *repo, GFile *file,
|
||||
|
||||
ref = flatpak_image_source_get_ref (image_source);
|
||||
|
||||
- commit_checksum = flatpak_pull_from_oci (repo, image_source, NULL, NULL,
|
||||
+ commit_checksum = flatpak_pull_from_oci (repo, image_source, NULL, NULL, NULL,
|
||||
ref, FLATPAK_PULL_FLAGS_NONE,
|
||||
NULL, NULL, cancellable, error);
|
||||
if (commit_checksum == NULL)
|
||||
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
|
||||
index 73118e1127..36d9b4314c 100644
|
||||
--- a/common/flatpak-dir.c
|
||||
+++ b/common/flatpak-dir.c
|
||||
@@ -6926,7 +6926,7 @@ flatpak_dir_pull_oci (FlatpakDir *self,
|
||||
|
||||
g_info ("Pulling OCI image %s", oci_digest);
|
||||
|
||||
- checksum = flatpak_pull_from_oci (repo, image_source, NULL,
|
||||
+ checksum = flatpak_pull_from_oci (repo, image_source, NULL, NULL,
|
||||
state->remote_name, ref, flatpak_flags, oci_pull_progress_cb, progress, cancellable, error);
|
||||
|
||||
if (checksum == NULL)
|
||||
diff --git a/common/flatpak-oci-registry-private.h b/common/flatpak-oci-registry-private.h
|
||||
index ca56eab396..451f770861 100644
|
||||
--- a/common/flatpak-oci-registry-private.h
|
||||
+++ b/common/flatpak-oci-registry-private.h
|
||||
@@ -194,7 +194,8 @@ typedef void (*FlatpakOciPullProgress) (guint64 total_size,
|
||||
|
||||
char * flatpak_pull_from_oci (OstreeRepo *repo,
|
||||
FlatpakImageSource *image_source,
|
||||
- FlatpakImageSource *opt_dst_image_source,
|
||||
+ const char *opt_sigcheck_repository,
|
||||
+ const char *opt_sigcheck_registry_uri,
|
||||
const char *remote,
|
||||
const char *ref,
|
||||
FlatpakPullFlags flags,
|
||||
diff --git a/common/flatpak-oci-registry.c b/common/flatpak-oci-registry.c
|
||||
index 0a442cd407..07b194e0c8 100644
|
||||
--- a/common/flatpak-oci-registry.c
|
||||
+++ b/common/flatpak-oci-registry.c
|
||||
@@ -3301,7 +3301,8 @@ flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry,
|
||||
char *
|
||||
flatpak_pull_from_oci (OstreeRepo *repo,
|
||||
FlatpakImageSource *image_source,
|
||||
- FlatpakImageSource *opt_dst_image_source,
|
||||
+ const char *opt_sigcheck_repository,
|
||||
+ const char *opt_sigcheck_registry_uri,
|
||||
const char *remote,
|
||||
const char *ref,
|
||||
FlatpakPullFlags flags,
|
||||
@@ -3334,23 +3335,20 @@ flatpak_pull_from_oci (OstreeRepo *repo,
|
||||
g_autoptr(GVariantBuilder) metadata_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
|
||||
g_autoptr(GVariant) metadata = NULL;
|
||||
g_autoptr(FlatpakOciSignatures) signatures = NULL;
|
||||
- FlatpakOciRegistry *dst_registry = opt_dst_image_source ?
|
||||
- flatpak_image_source_get_registry (opt_dst_image_source) : registry;
|
||||
- const char *dest_oci_repository = opt_dst_image_source ?
|
||||
- flatpak_image_source_get_oci_repository (opt_dst_image_source) : oci_repository;
|
||||
+ const char *sigcheck_registry_uri = opt_sigcheck_registry_uri ? opt_sigcheck_registry_uri : registry->uri;
|
||||
+ const char *sigcheck_repository = opt_sigcheck_repository ? opt_sigcheck_repository : oci_repository;
|
||||
int n_layers;
|
||||
int i;
|
||||
|
||||
g_assert (g_str_has_prefix (digest, "sha256:"));
|
||||
|
||||
- signatures = load_signatures (opt_dst_image_source ? opt_dst_image_source : image_source,
|
||||
- cancellable, error);
|
||||
+ signatures = load_signatures (image_source, cancellable, error);
|
||||
if (!signatures)
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_oci_signatures_verify (signatures, repo, remote,
|
||||
- dst_registry->uri,
|
||||
- dest_oci_repository,
|
||||
+ sigcheck_registry_uri,
|
||||
+ sigcheck_repository,
|
||||
digest,
|
||||
error))
|
||||
return FALSE;
|
||||
diff --git a/system-helper/flatpak-system-helper.c b/system-helper/flatpak-system-helper.c
|
||||
index 81c0801628..f6156b70a2 100644
|
||||
--- a/system-helper/flatpak-system-helper.c
|
||||
+++ b/system-helper/flatpak-system-helper.c
|
||||
@@ -492,6 +492,9 @@ handle_deploy (FlatpakSystemHelper *object,
|
||||
const char *verified_digest;
|
||||
g_autofree char *upstream_url = NULL;
|
||||
g_autoptr(FlatpakImageSource) system_image_source = NULL;
|
||||
+ g_autoptr(GVariant) metadata = NULL;
|
||||
+ const char *sigcheck_repository = NULL;
|
||||
+ g_autofree char *sigcheck_registry_uri = NULL;
|
||||
|
||||
if (!ostree_repo_remote_get_url (flatpak_dir_get_repo (system),
|
||||
arg_origin,
|
||||
@@ -546,21 +549,26 @@ handle_deploy (FlatpakSystemHelper *object,
|
||||
return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
|
||||
- system_image_source =
|
||||
- flatpak_remote_state_fetch_image_source (state,
|
||||
- system,
|
||||
- arg_ref,
|
||||
- verified_digest,
|
||||
- NULL,
|
||||
- NULL, &error);
|
||||
- if (!system_image_source)
|
||||
+ flatpak_remote_state_lookup_ref (state, arg_ref,
|
||||
+ NULL, NULL,
|
||||
+ &metadata,
|
||||
+ NULL, NULL, NULL);
|
||||
+
|
||||
+ if (!g_variant_lookup (metadata, "xa.oci-repository", "s", &sigcheck_repository))
|
||||
+ {
|
||||
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
||||
+ "Can't get the OCI repository from the summary");
|
||||
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
+ }
|
||||
+
|
||||
+ if (!ostree_repo_remote_get_url (flatpak_dir_get_repo (system), arg_origin, &sigcheck_registry_uri, NULL))
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
||||
- "Can't fetch image source: %s", error->message);
|
||||
+ "Can't get the OCI registry URI");
|
||||
return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
|
||||
- checksum = flatpak_pull_from_oci (flatpak_dir_get_repo (system), image_source, system_image_source,
|
||||
+ checksum = flatpak_pull_from_oci (flatpak_dir_get_repo (system), image_source, sigcheck_repository, sigcheck_registry_uri,
|
||||
arg_origin, arg_ref, FLATPAK_PULL_FLAGS_NONE, NULL, NULL, NULL, &error);
|
||||
if (checksum == NULL)
|
||||
{
|
||||
|
||||
From ef6554153e801311cf1e76c2ddb5fc1dbcc22121 Mon Sep 17 00:00:00 2001
|
||||
From: Luigi Pavan <lpavan@redhat.com>
|
||||
Date: Thu, 11 Jun 2026 12:50:26 +0200
|
||||
Subject: [PATCH 3/4] tests/oci-registry: Add bearer token auth support to the
|
||||
mock OCI registry
|
||||
|
||||
Add infrastructure for testing OCI installations from auth-protected
|
||||
registries. The mock server now supports requiring a bearer token on all
|
||||
/v2/ requests, configurable via a new POST /testing-auth/configure admin
|
||||
endpoint. The client gains a corresponding 'configure-auth' subcommand.
|
||||
|
||||
Assisted-by: Cursor
|
||||
---
|
||||
tests/oci-registry-client.py | 17 +++++++++++++++++
|
||||
tests/oci-registry-server.py | 25 +++++++++++++++++++++++++
|
||||
2 files changed, 42 insertions(+)
|
||||
|
||||
diff --git a/tests/oci-registry-client.py b/tests/oci-registry-client.py
|
||||
index 3855af5454..a80fe1973c 100755
|
||||
--- a/tests/oci-registry-client.py
|
||||
+++ b/tests/oci-registry-client.py
|
||||
@@ -82,6 +82,19 @@ def run_delete_sig(args):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
+def run_configure_auth(args):
|
||||
+ params = {"token": args.token}
|
||||
+ query = urllib.parse.urlencode(params)
|
||||
+ conn = get_conn(args)
|
||||
+ path = "/testing-auth/configure?{query}".format(query=query)
|
||||
+ conn.request("POST", path)
|
||||
+ response = conn.getresponse()
|
||||
+ if response.status != 200:
|
||||
+ print(response.read(), file=sys.stderr)
|
||||
+ print("Failed: status={}".format(response.status), file=sys.stderr)
|
||||
+ sys.exit(1)
|
||||
+
|
||||
+
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--url", required=True)
|
||||
parser.add_argument("--cacert")
|
||||
@@ -114,5 +127,9 @@ def run_delete_sig(args):
|
||||
delete_sig_parser.add_argument("digest")
|
||||
delete_sig_parser.set_defaults(func=run_delete_sig)
|
||||
|
||||
+configure_auth_parser = subparsers.add_parser("configure-auth")
|
||||
+configure_auth_parser.add_argument("--token", required=True)
|
||||
+configure_auth_parser.set_defaults(func=run_configure_auth)
|
||||
+
|
||||
args = parser.parse_args()
|
||||
args.func(args)
|
||||
diff --git a/tests/oci-registry-server.py b/tests/oci-registry-server.py
|
||||
index 497d7ca011..a890a097b1 100755
|
||||
--- a/tests/oci-registry-server.py
|
||||
+++ b/tests/oci-registry-server.py
|
||||
@@ -15,6 +15,8 @@
|
||||
icons = {}
|
||||
signatures = {}
|
||||
|
||||
+required_token = None
|
||||
+
|
||||
|
||||
def get_index():
|
||||
results = []
|
||||
@@ -81,6 +83,15 @@ def check_route(self, route):
|
||||
|
||||
return True
|
||||
|
||||
+ def check_auth(self):
|
||||
+ """Return True if auth is not required or the Authorization: Bearer header matches the required token."""
|
||||
+ if required_token is None:
|
||||
+ return True
|
||||
+ auth_header = self.headers.get("Authorization", "")
|
||||
+ if not auth_header.startswith("Bearer "):
|
||||
+ return False
|
||||
+ return auth_header[len("Bearer "):] == required_token
|
||||
+
|
||||
def do_GET(self):
|
||||
response = 404
|
||||
response_string = b""
|
||||
@@ -97,10 +108,18 @@ def get_file_contents(repo_name, type, ref):
|
||||
return 404, b""
|
||||
|
||||
if self.check_route("/v2/@repo_name/blobs/@digest"):
|
||||
+ if not self.check_auth():
|
||||
+ self.send_response(401)
|
||||
+ self.end_headers()
|
||||
+ return
|
||||
repo_name = self.matches["repo_name"]
|
||||
digest = self.matches["digest"]
|
||||
response, response_string = get_file_contents(repo_name, "blobs", digest)
|
||||
elif self.check_route("/v2/@repo_name/manifests/@ref"):
|
||||
+ if not self.check_auth():
|
||||
+ self.send_response(401)
|
||||
+ self.end_headers()
|
||||
+ return
|
||||
repo_name = self.matches["repo_name"]
|
||||
ref = self.matches["ref"]
|
||||
response, response_string = get_file_contents(repo_name, "manifests", ref)
|
||||
@@ -234,6 +253,12 @@ def do_POST(self):
|
||||
ref = f"{repo_name}@{digest}"
|
||||
sigs = signatures.setdefault(ref, [])
|
||||
sigs.append(signature_bytes)
|
||||
+ self.send_response(200)
|
||||
+ self.end_headers()
|
||||
+ elif self.check_route("/testing-auth/configure"):
|
||||
+ global required_token
|
||||
+ required_token = self.query.get("token", [None])[0]
|
||||
+
|
||||
self.send_response(200)
|
||||
self.end_headers()
|
||||
else:
|
||||
|
||||
From 35efa19c2e4f46359ede239057bde3783e50267d Mon Sep 17 00:00:00 2001
|
||||
From: Luigi Pavan <lpavan@redhat.com>
|
||||
Date: Thu, 11 Jun 2026 12:50:26 +0200
|
||||
Subject: [PATCH 4/4] tests: Add test for installing from an auth-protected OCI
|
||||
registry
|
||||
|
||||
Add a regression test that installs from an auth-protected OCI registry.
|
||||
The registry requires a bearer token for all /v2/ requests; the client
|
||||
authenticates via the mock test authenticator and the installation
|
||||
completes successfully. The test runs for both user and system install
|
||||
paths.
|
||||
|
||||
Assisted-by: Cursor
|
||||
---
|
||||
tests/meson.build | 1 +
|
||||
tests/test-oci-auth.sh | 69 ++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 70 insertions(+)
|
||||
create mode 100755 tests/test-oci-auth.sh
|
||||
|
||||
diff --git a/tests/meson.build b/tests/meson.build
|
||||
index 43d1493b73..d0b4f29e06 100644
|
||||
--- a/tests/meson.build
|
||||
+++ b/tests/meson.build
|
||||
@@ -396,6 +396,7 @@ tests = {
|
||||
'system,http',
|
||||
'system,https',
|
||||
]},
|
||||
+ 'oci-auth': {'wrap': ['user', 'system']},
|
||||
'update-remote-configuration': {'wrap': ['newsummary', 'oldsummary']},
|
||||
'override': {},
|
||||
'update-portal': {'wrap': ['user', 'system']},
|
||||
diff --git a/tests/test-oci-auth.sh b/tests/test-oci-auth.sh
|
||||
new file mode 100755
|
||||
index 0000000000..33c2271f09
|
||||
--- /dev/null
|
||||
+++ b/tests/test-oci-auth.sh
|
||||
@@ -0,0 +1,69 @@
|
||||
+#!/bin/bash
|
||||
+#
|
||||
+# Copyright (C) 2026 Red Hat, Inc.
|
||||
+#
|
||||
+# This library is free software; you can redistribute it and/or
|
||||
+# modify it under the terms of the GNU Lesser General Public
|
||||
+# License as published by the Free Software Foundation; either
|
||||
+# version 2 of the License, or (at your option) any later version.
|
||||
+#
|
||||
+# This library is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+# Lesser General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU Lesser General Public
|
||||
+# License along with this library; if not, write to the
|
||||
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
+# Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+set -euo pipefail
|
||||
+
|
||||
+# shellcheck source=libtest.sh
|
||||
+. "$(dirname "$0")/libtest.sh"
|
||||
+
|
||||
+skip_without_bwrap
|
||||
+
|
||||
+echo "1..1"
|
||||
+
|
||||
+# Start the fake OCI registry server
|
||||
+
|
||||
+httpd oci-registry-server.py --dir=.
|
||||
+port=$(cat httpd-port)
|
||||
+
|
||||
+# shellcheck disable=SC2154
|
||||
+client="python3 ${test_srcdir}/oci-registry-client.py --url=http://127.0.0.1:${port}"
|
||||
+
|
||||
+setup_repo_no_add oci
|
||||
+
|
||||
+# Build OCI bundles and upload them to the registry
|
||||
+
|
||||
+${FLATPAK} build-bundle --runtime --oci $FL_GPGARGS repos/oci oci/platform-image org.test.Platform >&2
|
||||
+$client add platform latest "$(pwd)/oci/platform-image"
|
||||
+
|
||||
+${FLATPAK} build-bundle --oci $FL_GPGARGS repos/oci oci/app-image org.test.Hello >&2
|
||||
+$client add hello latest "$(pwd)/oci/app-image"
|
||||
+
|
||||
+# Add OCI remote configured to use the mock test authenticator.
|
||||
+# The default authenticator for OCI remotes is org.flatpak.Authenticator.Oci;
|
||||
+# we override it to use the mock authenticator that reads its token from
|
||||
+# $XDG_RUNTIME_DIR/required-token on every call.
|
||||
+
|
||||
+${FLATPAK} remote-add ${U} oci-auth-registry "oci+http://127.0.0.1:${port}" \
|
||||
+ --authenticator-name org.flatpak.Authenticator.test >&2
|
||||
+
|
||||
+# Test: install from an auth-protected OCI registry
|
||||
+#
|
||||
+# The registry requires a bearer token for all /v2/ requests. The client
|
||||
+# authenticates via the mock authenticator and completes the installation
|
||||
+# successfully.
|
||||
+
|
||||
+echo -n "token-1" > "${XDG_RUNTIME_DIR}/required-token"
|
||||
+$client configure-auth --token token-1
|
||||
+
|
||||
+${FLATPAK} ${U} install -y oci-auth-registry org.test.Hello >&2
|
||||
+
|
||||
+run org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a sandbox$'
|
||||
+
|
||||
+ok "install from auth-protected OCI registry"
|
||||
@ -1,4 +1,4 @@
|
||||
From 5f5aeea8d8be071468fb8e9640554518fb65885e Mon Sep 17 00:00:00 2001
|
||||
From 33de26dbeeda858042683db5f8d848a319622098 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Tue, 16 Dec 2025 17:15:32 +0100
|
||||
Subject: [PATCH] run: Enable FIPS crypto policy if it is enabled on the host
|
||||
@ -6,17 +6,17 @@ Subject: [PATCH] run: Enable FIPS crypto policy if it is enabled on the host
|
||||
This is a close copy of what podman/containers does to support FIPS. Any
|
||||
other crypto policy is ignored for now.
|
||||
---
|
||||
common/flatpak-run.c | 87 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 87 insertions(+)
|
||||
common/flatpak-run.c | 95 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 95 insertions(+)
|
||||
|
||||
diff --git ./common/flatpak-run.c ../common/flatpak-run.c
|
||||
index 6c319231..b51cc637 100644
|
||||
--- ./common/flatpak-run.c
|
||||
+++ ../common/flatpak-run.c
|
||||
@@ -2215,6 +2215,91 @@ flatpak_run_setup_usr_links (FlatpakBwrap *bwrap,
|
||||
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||
index 5ea1250..7a9bf3c 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -2312,6 +2312,91 @@ flatpak_run_setup_usr_links (FlatpakBwrap *bwrap,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+static void
|
||||
+flatpak_run_setup_fips (FlatpakBwrap *bwrap,
|
||||
+ GFile *runtime_files)
|
||||
@ -105,15 +105,22 @@ index 6c319231..b51cc637 100644
|
||||
/* Directories in /sys to share with the sandbox if accessible. */
|
||||
static const char *const sysfs_dirs[] =
|
||||
{
|
||||
@@ -2405,6 +2490,8 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
@@ -2524,6 +2609,16 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
}
|
||||
}
|
||||
|
||||
+ flatpak_run_setup_fips (bwrap, runtime_files);
|
||||
|
||||
+ if (runtime_fd >= 0)
|
||||
+ {
|
||||
+ g_autofree char *runtime_path = flatpak_get_path_for_fd (runtime_fd, NULL);
|
||||
+ if (runtime_path != NULL)
|
||||
+ {
|
||||
+ g_autoptr(GFile) runtime_files = g_file_new_for_path (runtime_path);
|
||||
+ flatpak_run_setup_fips (bwrap, runtime_files);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (app_id_dir != NULL)
|
||||
{
|
||||
g_autoptr(GFile) app_cache_dir = g_file_get_child (app_id_dir, "cache");
|
||||
--
|
||||
2.51.0
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
15
flatpak.spec
15
flatpak.spec
@ -12,7 +12,7 @@
|
||||
%bcond malcontent %[!0%{?rhel}]
|
||||
|
||||
Name: flatpak
|
||||
Version: 1.17.3
|
||||
Version: 1.18.0
|
||||
Release: 1%{?dist}
|
||||
Summary: Application deployment framework for desktop apps
|
||||
|
||||
@ -33,6 +33,10 @@ Source2: flatpak.sysusers.conf
|
||||
Patch1: flatpak-for-registry.redhat.io-get-certificates-from-etc-pki.patch
|
||||
# Enable FIPS support
|
||||
Patch2: flatpak-run-Enable-FIPS-crypto-policy-if-it-is-enabled-on-th.patch
|
||||
# Retry on 401 with FlatpakTokenProvider (https://github.com/flatpak/flatpak/pull/6662)
|
||||
Patch3: flatpak-oci-Retry-on-401-with-FlatpakTokenProvider.patch
|
||||
# Check signatures from mirrored repo in system helper (https://github.com/flatpak/flatpak/pull/6682)
|
||||
Patch4: flatpak-oci-registry-Check-signatures-from-mirrored-repo-in.patch
|
||||
|
||||
# ostree not on i686 for RHEL 10
|
||||
# https://github.com/containers/composefs/pull/229#issuecomment-1838735764
|
||||
@ -293,7 +297,7 @@ fi
|
||||
|
||||
%files selinux
|
||||
%{_datadir}/selinux/packages/flatpak.pp.bz2
|
||||
%{_datadir}/selinux/devel/include/contrib/flatpak.if
|
||||
%{_datadir}/selinux/devel/include/distributed/flatpak.if
|
||||
|
||||
%files session-helper
|
||||
%license COPYING
|
||||
@ -308,6 +312,13 @@ fi
|
||||
|
||||
|
||||
%changelog
|
||||
* Thu Jun 11 2026 Jan Grulich <jgrulich@redhat.com> - 1.18.0-1
|
||||
- Update to 1.18.0
|
||||
Resolves: RHEL-126038
|
||||
Resolves: RHEL-92123
|
||||
Resolves: RHEL-165631
|
||||
Resolves: RHEL-170158
|
||||
|
||||
* Tue Mar 17 2026 Jan Grulich <jgrulich@redhat.com> - 1.17.3-1
|
||||
- 1.17.3
|
||||
Resolves: RHEL-126038
|
||||
|
||||
2
sources
2
sources
@ -1 +1 @@
|
||||
SHA512 (flatpak-1.17.3.tar.xz) = 889213e5babafbfc3bc2525d36351d0703a6f5da013c04010f1622236a59c8cea3cdef9430e31599dc0950c2da9621c172d2f6a359b5642273977787b9df1409
|
||||
SHA512 (flatpak-1.18.0.tar.xz) = 0dbfef463e3d2e7f9fd9db6c301804f1fd37450ef224936f9e68ed2d86bcbe5feaba99ead923bcd5f303bfc6376b858beb951c9f70afbbd65c4a0585ad2abc02
|
||||
|
||||
Loading…
Reference in New Issue
Block a user