diff --git a/Makefile-libostree.am b/Makefile-libostree.am index 39dc0d14..0a4de6de 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -101,6 +101,7 @@ libostree_1_la_SOURCES = \ src/libostree/ostree-repo-checkout.c \ src/libostree/ostree-repo-commit.c \ src/libostree/ostree-repo-pull.c \ + src/libostree/ostree-repo-pull-private.h \ src/libostree/ostree-repo-libarchive.c \ src/libostree/ostree-repo-prune.c \ src/libostree/ostree-repo-refs.c \ diff --git a/apidoc/Makefile.am b/apidoc/Makefile.am index f3405fb0..d46eac78 100644 --- a/apidoc/Makefile.am +++ b/apidoc/Makefile.am @@ -83,6 +83,7 @@ IGNORE_HFILES= \ ostree-metalink.h \ ostree-repo-file-enumerator.h \ ostree-repo-private.h \ + ostree-repo-pull-private.h \ ostree-repo-static-delta-private.h \ ostree-sysroot-private.h \ ostree-tls-cert-interaction.h \ diff --git a/src/libostree/ostree-cmdprivate.c b/src/libostree/ostree-cmdprivate.c index 3e60b125..5637e98b 100644 --- a/src/libostree/ostree-cmdprivate.c +++ b/src/libostree/ostree-cmdprivate.c @@ -22,6 +22,7 @@ #include "ostree-cmdprivate.h" #include "ostree-repo-private.h" #include "ostree-core-private.h" +#include "ostree-repo-pull-private.h" #include "ostree-repo-static-delta-private.h" #include "ostree-sysroot.h" #include "ostree-bootloader-grub2.h" @@ -48,7 +49,8 @@ ostree_cmd__private__ (void) impl_ostree_generate_grub2_config, _ostree_repo_static_delta_dump, _ostree_repo_static_delta_query_exists, - _ostree_repo_static_delta_delete + _ostree_repo_static_delta_delete, + _ostree_repo_verify_bindings }; return &table; diff --git a/src/libostree/ostree-cmdprivate.h b/src/libostree/ostree-cmdprivate.h index f636ab15..2ba535ec 100644 --- a/src/libostree/ostree-cmdprivate.h +++ b/src/libostree/ostree-cmdprivate.h @@ -31,6 +31,7 @@ typedef struct { gboolean (* ostree_static_delta_dump) (OstreeRepo *repo, const char *delta_id, GCancellable *cancellable, GError **error); gboolean (* ostree_static_delta_query_exists) (OstreeRepo *repo, const char *delta_id, gboolean *out_exists, GCancellable *cancellable, GError **error); gboolean (* ostree_static_delta_delete) (OstreeRepo *repo, const char *delta_id, GCancellable *cancellable, GError **error); + gboolean (* ostree_repo_verify_bindings) (const char *collection_id, const char *ref_name, GVariant *commit, GError **error); } OstreeCmdPrivateVTable; /* Note this not really "public", we just export the symbol, but not the header */ diff --git a/src/libostree/ostree-repo-pull-private.h b/src/libostree/ostree-repo-pull-private.h new file mode 100644 index 00000000..ba30b153 --- /dev/null +++ b/src/libostree/ostree-repo-pull-private.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2017 Endless Mobile, 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. + */ + +#pragma once + +#include "ostree-core.h" + +G_BEGIN_DECLS + +gboolean +_ostree_repo_verify_bindings (const char *collection_id, + const char *ref_name, + GVariant *commit, + GError **error); + +G_END_DECLS diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 8ac48506..42d802b2 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -32,6 +32,7 @@ #include "ostree-core-private.h" #include "ostree-repo-private.h" +#include "ostree-repo-pull-private.h" #include "ostree-repo-static-delta-private.h" #include "ostree-metalink.h" #include "ostree-fetcher-util.h" @@ -1475,30 +1476,40 @@ get_remote_repo_collection_id (OtPullData *pull_data) } #endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ -/* Verify the ref and collection bindings. +#endif /* HAVE_LIBCURL_OR_LIBSOUP */ + +/** + * _ostree_repo_verify_bindings: + * @collection_id: (nullable): Locally specified collection ID for the remote + * the @commit was retrieved from, or %NULL if none is configured + * @ref_name: (nullable): Ref name the commit was retrieved using, or %NULL if + * the commit was retrieved by checksum + * @commit: Commit data to check + * @error: Return location for a #GError, or %NULL + * + * Verify the ref and collection bindings. * * The ref binding is verified only if it exists. But if we have the - * collection ID specified in the remote configuration then the ref - * binding must exist, otherwise the verification will fail. Parts of - * the verification can be skipped by passing NULL to the requested_ref - * parameter (in case we requested a checksum directly, without looking it up - * from a ref). + * collection ID specified in the remote configuration (@collection_id is + * non-%NULL) then the ref binding must exist, otherwise the verification will + * fail. Parts of the verification can be skipped by passing %NULL to the + * @ref_name parameter (in case we requested a checksum directly, without + * looking it up from a ref). * * The collection binding is verified only when we have collection ID * specified in the remote configuration. If it is specified, then the * binding must exist and must be equal to the remote repository * collection ID. + * + * Returns: %TRUE if bindings are correct, %FALSE otherwise + * Since: 2017.14 */ -static gboolean -verify_bindings (OtPullData *pull_data, - GVariant *commit, - const OstreeCollectionRef *requested_ref, - GError **error) +gboolean +_ostree_repo_verify_bindings (const char *collection_id, + const char *ref_name, + GVariant *commit, + GError **error) { - g_autofree char *remote_collection_id = NULL; -#ifdef OSTREE_ENABLE_EXPERIMENTAL_API - remote_collection_id = get_remote_repo_collection_id (pull_data); -#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ g_autoptr(GVariant) metadata = g_variant_get_child_value (commit, 0); g_autofree const char **refs = NULL; if (!g_variant_lookup (metadata, @@ -1510,7 +1521,7 @@ verify_bindings (OtPullData *pull_data, * we certainly will not verify the collection binding in the * commit. */ - if (remote_collection_id == NULL) + if (collection_id == NULL) return TRUE; return glnx_throw (error, @@ -1518,9 +1529,9 @@ verify_bindings (OtPullData *pull_data, "binding information, found none"); } - if (requested_ref != NULL) + if (ref_name != NULL) { - if (!g_strv_contains ((const char *const *) refs, requested_ref->ref_name)) + if (!g_strv_contains ((const char *const *) refs, ref_name)) { g_autoptr(GString) refs_dump = g_string_new (NULL); const char *refs_str; @@ -1545,33 +1556,35 @@ verify_bindings (OtPullData *pull_data, return glnx_throw (error, "commit has no requested ref ‘%s’ " "in ref binding metadata (%s)", - requested_ref->ref_name, refs_str); + ref_name, refs_str); } } - if (remote_collection_id != NULL) + if (collection_id != NULL) { #ifdef OSTREE_ENABLE_EXPERIMENTAL_API - const char *collection_id; + const char *collection_id_binding; if (!g_variant_lookup (metadata, OSTREE_COMMIT_META_KEY_COLLECTION_BINDING, "&s", - &collection_id)) + &collection_id_binding)) return glnx_throw (error, "expected commit metadata to have collection ID " "binding information, found none"); - if (!g_str_equal (collection_id, remote_collection_id)) + if (!g_str_equal (collection_id_binding, collection_id)) return glnx_throw (error, "commit has collection ID ‘%s’ in collection binding " "metadata, while the remote it came from has " "collection ID ‘%s’", - collection_id, remote_collection_id); + collection_id_binding, collection_id); #endif } return TRUE; } +#ifdef HAVE_LIBCURL_OR_LIBSOUP + /* Look at a commit object, and determine whether there are * more things to fetch. */ @@ -1626,7 +1639,13 @@ scan_commit_object (OtPullData *pull_data, /* If ref is non-NULL then the commit we fetched was requested through the * branch, otherwise we requested a commit checksum without specifying a branch. */ - if (!verify_bindings (pull_data, commit, ref, error)) + g_autofree char *remote_collection_id = NULL; +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API + remote_collection_id = get_remote_repo_collection_id (pull_data); +#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ + if (!_ostree_repo_verify_bindings (remote_collection_id, + (ref != NULL) ? ref->ref_name : NULL, + commit, error)) return glnx_prefix_error (error, "Commit %s", checksum); if (pull_data->timestamp_check)