diff options
-rw-r--r-- | app/xdg-app-builtins-install.c | 17 | ||||
-rw-r--r-- | common/xdg-app-dir.c | 109 | ||||
-rw-r--r-- | common/xdg-app-dir.h | 7 | ||||
-rw-r--r-- | common/xdg-app-utils.c | 105 | ||||
-rw-r--r-- | common/xdg-app-utils.h | 8 | ||||
-rw-r--r-- | lib/xdg-app-installation.c | 17 |
6 files changed, 133 insertions, 130 deletions
diff --git a/app/xdg-app-builtins-install.c b/app/xdg-app-builtins-install.c index e8634a6..66aaf1d 100644 --- a/app/xdg-app-builtins-install.c +++ b/app/xdg-app-builtins-install.c @@ -171,13 +171,16 @@ install_bundle (XdgAppDir *dir, /* From here we need to goto out on error, to clean up */ added_remote = TRUE; - if (!xdg_app_dir_pull_from_bundle (dir, - file, - remote, - ref, - gpg_data != NULL, - cancellable, - error)) + if (!xdg_app_dir_ensure_repo (dir, cancellable, error)) + goto out; + + if (!xdg_app_pull_from_bundle (xdg_app_dir_get_repo (dir), + file, + remote, + ref, + gpg_data != NULL, + cancellable, + error)) goto out; if (!xdg_app_dir_lock (dir, &lock, diff --git a/common/xdg-app-dir.c b/common/xdg-app-dir.c index 8b97437..f0571ab 100644 --- a/common/xdg-app-dir.c +++ b/common/xdg-app-dir.c @@ -995,115 +995,6 @@ xdg_app_dir_pull (XdgAppDir *self, return ret; } -gboolean -xdg_app_dir_pull_from_bundle (XdgAppDir *self, - GFile *file, - const char *remote, - const char *ref, - gboolean require_gpg_signature, - GCancellable *cancellable, - GError **error) -{ - g_autofree char *metadata_contents = NULL; - g_autofree char *to_checksum = NULL; - g_autoptr(GFile) root = NULL; - g_autoptr(GFile) metadata_file = NULL; - g_autoptr(GInputStream) in = NULL; - g_autoptr(OstreeGpgVerifyResult) gpg_result = NULL; - g_autoptr(GError) my_error = NULL; - g_autoptr(GVariant) metadata = NULL; - gboolean metadata_valid; - - if (!xdg_app_dir_ensure_repo (self, cancellable, error)) - return FALSE; - - if (!xdg_app_supports_bundles (self->repo)) - return xdg_app_fail (error, "Your version of ostree is too old to support single-file bundles"); - - metadata = xdg_app_bundle_load (file, &to_checksum, NULL, NULL, NULL, NULL, error); - if (metadata == NULL) - return FALSE; - - g_variant_lookup (metadata, "metadata", "s", &metadata_contents); - - if (!ostree_repo_prepare_transaction (self->repo, NULL, cancellable, error)) - return FALSE; - - ostree_repo_transaction_set_ref (self->repo, remote, ref, to_checksum); - - if (!ostree_repo_static_delta_execute_offline (self->repo, - file, - FALSE, - cancellable, - error)) - return FALSE; - - gpg_result = ostree_repo_verify_commit_ext (self->repo, to_checksum, - NULL, NULL, cancellable, &my_error); - if (gpg_result == NULL) - { - /* NOT_FOUND means no gpg signature, we ignore this *if* there - * is no gpg key specified in the bundle or by the user */ - if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && - !require_gpg_signature) - g_clear_error (&my_error); - else - { - g_propagate_error (error, g_steal_pointer (&my_error)); - return FALSE; - } - } - else - { - /* If there is no valid gpg signature we fail, unless there is no gpg - key specified (on the command line or in the file) because then we - trust the source bundle. */ - if (ostree_gpg_verify_result_count_valid (gpg_result) == 0 && - require_gpg_signature) - return xdg_app_fail (error, "GPG signatures found, but none are in trusted keyring"); - } - - if (!ostree_repo_read_commit (self->repo, to_checksum, &root, NULL, NULL, error)) - return FALSE; - - if (!ostree_repo_commit_transaction (self->repo, NULL, cancellable, error)) - return FALSE; - - /* We ensure that the actual installed metadata matches the one in the - header, because you may have made decisions on wheter to install it or not - based on that data. */ - metadata_file = g_file_resolve_relative_path (root, "metadata"); - in = (GInputStream*)g_file_read (metadata_file, cancellable, NULL); - if (in != NULL) - { - g_autoptr(GMemoryOutputStream) data_stream = (GMemoryOutputStream*)g_memory_output_stream_new_resizable (); - - if (g_output_stream_splice (G_OUTPUT_STREAM (data_stream), in, - G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE, - cancellable, error) < 0) - return FALSE; - - /* Null terminate */ - g_output_stream_write (G_OUTPUT_STREAM (data_stream), "\0", 1, NULL, NULL); - - metadata_valid = - metadata_contents != NULL && - strcmp (metadata_contents, g_memory_output_stream_get_data (data_stream)) == 0; - } - else - metadata_valid = (metadata_contents == NULL); - - if (!metadata_valid) - { - /* Immediately remove this broken commit */ - ostree_repo_set_ref_immediate (self->repo, remote, ref, NULL, cancellable, error); - return xdg_app_fail (error, "Metadata in header and app are inconsistent"); - } - - return TRUE; -} - - char * xdg_app_dir_current_ref (XdgAppDir *self, const char *name, diff --git a/common/xdg-app-dir.h b/common/xdg-app-dir.h index 2816de1..7665fc7 100644 --- a/common/xdg-app-dir.h +++ b/common/xdg-app-dir.h @@ -157,13 +157,6 @@ gboolean xdg_app_dir_pull (XdgAppDir *self, OstreeAsyncProgress *progress, GCancellable *cancellable, GError **error); -gboolean xdg_app_dir_pull_from_bundle (XdgAppDir *self, - GFile *file, - const char *remote, - const char *ref, - gboolean require_gpg_signature, - GCancellable *cancellable, - GError **error); gboolean xdg_app_dir_list_refs_for_name (XdgAppDir *self, const char *kind, const char *name, diff --git a/common/xdg-app-utils.c b/common/xdg-app-utils.c index 4406a56..cf055ed 100644 --- a/common/xdg-app-utils.c +++ b/common/xdg-app-utils.c @@ -2673,3 +2673,108 @@ xdg_app_bundle_load (GFile *file, g_variant_get_size (metadata)), FALSE); } + +gboolean +xdg_app_pull_from_bundle (OstreeRepo *repo, + GFile *file, + const char *remote, + const char *ref, + gboolean require_gpg_signature, + GCancellable *cancellable, + GError **error) +{ + g_autofree char *metadata_contents = NULL; + g_autofree char *to_checksum = NULL; + g_autoptr(GFile) root = NULL; + g_autoptr(GFile) metadata_file = NULL; + g_autoptr(GInputStream) in = NULL; + g_autoptr(OstreeGpgVerifyResult) gpg_result = NULL; + g_autoptr(GError) my_error = NULL; + g_autoptr(GVariant) metadata = NULL; + gboolean metadata_valid; + + if (!xdg_app_supports_bundles (repo)) + return xdg_app_fail (error, "Your version of ostree is too old to support single-file bundles"); + + metadata = xdg_app_bundle_load (file, &to_checksum, NULL, NULL, NULL, NULL, error); + if (metadata == NULL) + return FALSE; + + g_variant_lookup (metadata, "metadata", "s", &metadata_contents); + + if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error)) + return FALSE; + + ostree_repo_transaction_set_ref (repo, remote, ref, to_checksum); + + if (!ostree_repo_static_delta_execute_offline (repo, + file, + FALSE, + cancellable, + error)) + return FALSE; + + gpg_result = ostree_repo_verify_commit_ext (repo, to_checksum, + NULL, NULL, cancellable, &my_error); + if (gpg_result == NULL) + { + /* NOT_FOUND means no gpg signature, we ignore this *if* there + * is no gpg key specified in the bundle or by the user */ + if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && + !require_gpg_signature) + g_clear_error (&my_error); + else + { + g_propagate_error (error, g_steal_pointer (&my_error)); + return FALSE; + } + } + else + { + /* If there is no valid gpg signature we fail, unless there is no gpg + key specified (on the command line or in the file) because then we + trust the source bundle. */ + if (ostree_gpg_verify_result_count_valid (gpg_result) == 0 && + require_gpg_signature) + return xdg_app_fail (error, "GPG signatures found, but none are in trusted keyring"); + } + + if (!ostree_repo_read_commit (repo, to_checksum, &root, NULL, NULL, error)) + return FALSE; + + if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error)) + return FALSE; + + /* We ensure that the actual installed metadata matches the one in the + header, because you may have made decisions on wheter to install it or not + based on that data. */ + metadata_file = g_file_resolve_relative_path (root, "metadata"); + in = (GInputStream*)g_file_read (metadata_file, cancellable, NULL); + if (in != NULL) + { + g_autoptr(GMemoryOutputStream) data_stream = (GMemoryOutputStream*)g_memory_output_stream_new_resizable (); + + if (g_output_stream_splice (G_OUTPUT_STREAM (data_stream), in, + G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE, + cancellable, error) < 0) + return FALSE; + + /* Null terminate */ + g_output_stream_write (G_OUTPUT_STREAM (data_stream), "\0", 1, NULL, NULL); + + metadata_valid = + metadata_contents != NULL && + strcmp (metadata_contents, g_memory_output_stream_get_data (data_stream)) == 0; + } + else + metadata_valid = (metadata_contents == NULL); + + if (!metadata_valid) + { + /* Immediately remove this broken commit */ + ostree_repo_set_ref_immediate (repo, remote, ref, NULL, cancellable, error); + return xdg_app_fail (error, "Metadata in header and app are inconsistent"); + } + + return TRUE; +} diff --git a/common/xdg-app-utils.h b/common/xdg-app-utils.h index 106627f..b1b7936 100644 --- a/common/xdg-app-utils.h +++ b/common/xdg-app-utils.h @@ -191,6 +191,14 @@ GVariant * xdg_app_bundle_load (GFile *file, GBytes **gpg_keys, GError **error); +gboolean xdg_app_pull_from_bundle (OstreeRepo *repo, + GFile *file, + const char *remote, + const char *ref, + gboolean require_gpg_signature, + GCancellable *cancellable, + GError **error); + typedef struct { char *id; diff --git a/lib/xdg-app-installation.c b/lib/xdg-app-installation.c index d97f7c0..c6ab372 100644 --- a/lib/xdg-app-installation.c +++ b/lib/xdg-app-installation.c @@ -868,13 +868,16 @@ xdg_app_installation_install_bundle (XdgAppInstallation *self, /* Pull, prune, etc are not threadsafe, so we work on a copy */ dir_clone = xdg_app_dir_clone (priv->dir); - if (!xdg_app_dir_pull_from_bundle (dir_clone, - file, - remote, - ref, - gpg_data != NULL, - cancellable, - error)) + if (!xdg_app_dir_ensure_repo (dir_clone, cancellable, error)) + goto out; + + if (!xdg_app_pull_from_bundle (xdg_app_dir_get_repo (dir_clone), + file, + remote, + ref, + gpg_data != NULL, + cancellable, + error)) goto out; if (!xdg_app_dir_lock (dir_clone, &lock, |