diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 87c138d8..1eef5da7 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -269,6 +269,7 @@ ostree_repo_load_file ostree_repo_load_object_stream ostree_repo_query_object_storage_size ostree_repo_import_object_from +ostree_repo_import_object_from_with_trust ostree_repo_delete_object OstreeRepoCommitFilterResult OstreeRepoCommitFilter diff --git a/src/libostree/libostree.sym b/src/libostree/libostree.sym index 7f10b75d..47015e14 100644 --- a/src/libostree/libostree.sym +++ b/src/libostree/libostree.sym @@ -328,8 +328,7 @@ global: * NOTE NOTE NOTE */ -/* UNCOMMENT WITH NEW SYMBOLS HERE: LIBOSTREE_2016.5 { global: + ostree_repo_import_object_from_with_trust; } LIBOSTREE_2016.4; -*/ diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index ecbd7386..26284806 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -93,6 +93,7 @@ typedef struct { gboolean is_mirror; gboolean is_commit_only; + gboolean is_untrusted; char *dir; gboolean commitpartial_exists; @@ -473,9 +474,9 @@ scan_dirtree_object (OtPullData *pull_data, if (!file_is_stored && pull_data->remote_repo_local) { - if (!ostree_repo_import_object_from (pull_data->repo, pull_data->remote_repo_local, - OSTREE_OBJECT_TYPE_FILE, file_checksum, - cancellable, error)) + if (!ostree_repo_import_object_from_with_trust (pull_data->repo, pull_data->remote_repo_local, + OSTREE_OBJECT_TYPE_FILE, file_checksum, !pull_data->is_untrusted, + cancellable, error)) goto out; } else if (!file_is_stored && !g_hash_table_lookup (pull_data->requested_content, file_checksum)) @@ -1189,9 +1190,9 @@ scan_one_metadata_object_c (OtPullData *pull_data, if (pull_data->remote_repo_local) { if (!is_stored && - !ostree_repo_import_object_from (pull_data->repo, pull_data->remote_repo_local, - objtype, tmp_checksum, - cancellable, error)) + !ostree_repo_import_object_from_with_trust (pull_data->repo, pull_data->remote_repo_local, + objtype, tmp_checksum, !pull_data->is_untrusted, + cancellable, error)) goto out; is_stored = TRUE; is_requested = TRUE; @@ -1931,6 +1932,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, pull_data->is_mirror = (flags & OSTREE_REPO_PULL_FLAGS_MIRROR) > 0; pull_data->is_commit_only = (flags & OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY) > 0; + pull_data->is_untrusted = (flags & OSTREE_REPO_PULL_FLAGS_UNTRUSTED) > 0; if (error) pull_data->async_error = &pull_data->cached_async_error; diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 09791c6a..a5d0bb2d 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -3310,24 +3310,37 @@ import_one_object_copy (OstreeRepo *self, OstreeRepo *source, const char *checksum, OstreeObjectType objtype, + gboolean trusted, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; guint64 length; - g_autoptr(GInputStream) object = NULL; + g_autoptr(GInputStream) object_stream = NULL; if (!ostree_repo_load_object_stream (source, objtype, checksum, - &object, &length, + &object_stream, &length, cancellable, error)) goto out; if (objtype == OSTREE_OBJECT_TYPE_FILE) { - if (!ostree_repo_write_content_trusted (self, checksum, - object, length, - cancellable, error)) - goto out; + if (trusted) + { + if (!ostree_repo_write_content_trusted (self, checksum, + object_stream, length, + cancellable, error)) + goto out; + } + else + { + g_autofree guchar *real_csum = NULL; + if (!ostree_repo_write_content (self, checksum, + object_stream, length, + &real_csum, + cancellable, error)) + goto out; + } } else { @@ -3336,10 +3349,29 @@ import_one_object_copy (OstreeRepo *self, if (!copy_detached_metadata (self, source, checksum, cancellable, error)) goto out; } - if (!ostree_repo_write_metadata_stream_trusted (self, objtype, - checksum, object, length, - cancellable, error)) - goto out; + + if (trusted) + { + if (!ostree_repo_write_metadata_stream_trusted (self, objtype, + checksum, object_stream, length, + cancellable, error)) + goto out; + } + else + { + g_autofree guchar *real_csum = NULL; + g_autoptr(GVariant) variant = NULL; + + if (!ostree_repo_load_variant (source, objtype, checksum, + &variant, error)) + goto out; + + if (!ostree_repo_write_metadata (self, objtype, + checksum, variant, + &real_csum, + cancellable, error)) + goto out; + } } ret = TRUE; @@ -3419,11 +3451,43 @@ ostree_repo_import_object_from (OstreeRepo *self, const char *checksum, GCancellable *cancellable, GError **error) +{ + return + ostree_repo_import_object_from_with_trust (self, source, objtype, + checksum, TRUE, cancellable, error); +} + +/** + * ostree_repo_import_object_from_with_trust: + * @self: Destination repo + * @source: Source repo + * @objtype: Object type + * @checksum: checksum + * @trusted: If %TRUE, assume the source repo is valid and trusted + * @cancellable: Cancellable + * @error: Error + * + * Copy object named by @objtype and @checksum into @self from the + * source repository @source. If both repositories are of the same + * type and on the same filesystem, this will simply be a fast Unix + * hard link operation. + * + * Otherwise, a copy will be performed. + */ +gboolean +ostree_repo_import_object_from_with_trust (OstreeRepo *self, + OstreeRepo *source, + OstreeObjectType objtype, + const char *checksum, + gboolean trusted, + GCancellable *cancellable, + GError **error) { gboolean ret = FALSE; gboolean hardlink_was_supported = FALSE; - - if (self->mode == source->mode) + + if (trusted && /* Don't hardlink into untrusted remotes */ + self->mode == source->mode) { if (!import_one_object_link (self, source, checksum, objtype, &hardlink_was_supported, @@ -3438,10 +3502,10 @@ ostree_repo_import_object_from (OstreeRepo *self, if (!ostree_repo_has_object (self, objtype, checksum, &has_object, cancellable, error)) goto out; - + if (!has_object) { - if (!import_one_object_copy (self, source, checksum, objtype, + if (!import_one_object_copy (self, source, checksum, objtype, trusted, cancellable, error)) goto out; } @@ -3452,6 +3516,7 @@ ostree_repo_import_object_from (OstreeRepo *self, return ret; } + /** * ostree_repo_query_object_storage_size: * @self: Repo diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 07e76aa8..f83aef23 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -423,6 +423,14 @@ gboolean ostree_repo_import_object_from (OstreeRepo *self, const char *checksum, GCancellable *cancellable, GError **error); +_OSTREE_PUBLIC +gboolean ostree_repo_import_object_from_with_trust (OstreeRepo *self, + OstreeRepo *source, + OstreeObjectType objtype, + const char *checksum, + gboolean trusted, + GCancellable *cancellable, + GError **error); _OSTREE_PUBLIC gboolean ostree_repo_delete_object (OstreeRepo *self, @@ -891,11 +899,13 @@ gboolean ostree_repo_prune (OstreeRepo *self, * @OSTREE_REPO_PULL_FLAGS_NONE: No special options for pull * @OSTREE_REPO_PULL_FLAGS_MIRROR: Write out refs suitable for mirrors * @OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY: Fetch only the commit metadata + * @OSTREE_REPO_PULL_FLAGS_UNTRUSTED: Don't trust local remote */ typedef enum { OSTREE_REPO_PULL_FLAGS_NONE, OSTREE_REPO_PULL_FLAGS_MIRROR = (1 << 0), - OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY = (1 << 1) + OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY = (1 << 1), + OSTREE_REPO_PULL_FLAGS_UNTRUSTED = (1 << 2) } OstreeRepoPullFlags; _OSTREE_PUBLIC