From c09df184544ccd1921855abd072dcf186712376f Mon Sep 17 00:00:00 2001 From: Denis Pynkin Date: Fri, 2 Aug 2019 02:16:56 +0300 Subject: [PATCH] lib/sign: enable verification for pulling Signed-off-by: Denis Pynkin --- src/libostree/ostree-repo-pull.c | 92 ++++++++++++++++++++++++++--- src/libostree/ostree-sign-dummy.c | 1 - src/libostree/ostree-sign-ed25519.c | 1 - 3 files changed, 83 insertions(+), 11 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 381cce47..507bcc2e 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -54,6 +54,8 @@ #include #endif +#include "ostree-sign.h" + #define OSTREE_MESSAGE_FETCH_COMPLETE_ID SD_ID128_MAKE(75,ba,3d,eb,0a,f0,41,a9,a4,62,72,ff,85,d9,e7,3e) #define OSTREE_REPO_PULL_CONTENT_PRIORITY (OSTREE_FETCHER_DEFAULT_PRIORITY) @@ -105,6 +107,7 @@ typedef struct { gboolean gpg_verify; gboolean gpg_verify_summary; + gboolean sign_verify; gboolean require_static_deltas; gboolean disable_static_deltas; gboolean has_tombstone_commits; @@ -1500,6 +1503,38 @@ ostree_verify_unwritten_commit (OtPullData *pull_data, } #endif /* OSTREE_DISABLE_GPGME */ + if (pull_data->sign_verify) + { + gboolean ret = FALSE; + g_autoptr(GBytes) signed_data = g_variant_get_data_as_bytes (commit); + /* list all signature types in detached metadata and check if signed by any? */ + GStrv names = ostree_sign_list_names(); + for (guint i=0; i < g_strv_length (names); i++) + { + g_autoptr (OstreeSign) sign = ostree_sign_get_by_name (names[i], error); + g_autoptr(GVariant) signatures = NULL; + g_autofree gchar *signature_key = ostree_sign_metadata_key (sign); + g_autofree GVariantType *signature_format = (GVariantType *) ostree_sign_metadata_format (sign); + + signatures = g_variant_lookup_value (detached_metadata, + signature_key, + signature_format); + + /* Set return to true if any sign fit */ + if (!signatures) + continue; + + if (ostree_sign_metadata_verify (sign, + signed_data, + signatures, + error + )) + ret = TRUE; + } + g_strfreev(names); + return ret; + } + return TRUE; } @@ -1829,6 +1864,28 @@ scan_commit_object (OtPullData *pull_data, } #endif /* OSTREE_DISABLE_GPGME */ + if (pull_data->sign_verify && + !g_hash_table_contains (pull_data->verified_commits, checksum)) + { + gboolean ret = FALSE; + /* list all signature types in detached metadata and check if signed by any? */ + GStrv names = ostree_sign_list_names(); + for (guint i=0; i < g_strv_length (names); i++) + { + g_autoptr (OstreeSign) sign = ostree_sign_get_by_name (names[i], error); + + if (ostree_sign_commit_verify (sign, + pull_data->repo, + checksum, + cancellable, + error)) + ret = TRUE; + } + g_strfreev(names); + if (ret == FALSE) + return FALSE; + } + /* If we found a legacy transaction flag, assume we have to scan. * We always do a scan of dirtree objects; see * https://github.com/ostreedev/ostree/issues/543 @@ -3576,6 +3633,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, g_autoptr(GSource) update_timeout = NULL; gboolean opt_gpg_verify_set = FALSE; gboolean opt_gpg_verify_summary_set = FALSE; + gboolean opt_sign_verify_set = FALSE; gboolean opt_collection_refs_set = FALSE; gboolean opt_n_network_retries_set = FALSE; gboolean opt_ref_keyring_map_set = FALSE; @@ -3610,6 +3668,8 @@ ostree_repo_pull_with_options (OstreeRepo *self, g_variant_lookup (options, "gpg-verify", "b", &pull_data->gpg_verify); opt_gpg_verify_summary_set = g_variant_lookup (options, "gpg-verify-summary", "b", &pull_data->gpg_verify_summary); + opt_sign_verify_set = + g_variant_lookup (options, "sign-verify", "b", &pull_data->sign_verify); (void) g_variant_lookup (options, "depth", "i", &pull_data->maxdepth); (void) g_variant_lookup (options, "disable-static-deltas", "b", &pull_data->disable_static_deltas); (void) g_variant_lookup (options, "require-static-deltas", "b", &pull_data->require_static_deltas); @@ -3759,7 +3819,10 @@ ostree_repo_pull_with_options (OstreeRepo *self, /* For compatibility with pull-local, don't gpg verify local * pulls by default. */ - if ((pull_data->gpg_verify || pull_data->gpg_verify_summary) && + if ((pull_data->gpg_verify || + pull_data->gpg_verify_summary || + pull_data->sign_verify + ) && pull_data->remote_name == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, @@ -3788,6 +3851,10 @@ ostree_repo_pull_with_options (OstreeRepo *self, goto out; #endif /* OSTREE_DISABLE_GPGME */ + /* TODO: read option for remote. */ + if (!opt_sign_verify_set) + opt_sign_verify_set = TRUE; + /* NOTE: If changing this, see the matching implementation in * ostree-sysroot-upgrader.c */ @@ -4647,23 +4714,28 @@ ostree_repo_pull_with_options (OstreeRepo *self, g_string_append_printf (msg, "libostree pull from '%s' for %u refs complete", pull_data->remote_name, g_hash_table_size (requested_refs_to_fetch)); - const char *verify_state; + const char *gpg_verify_state; #ifndef OSTREE_DISABLE_GPGME if (pull_data->gpg_verify_summary) { if (pull_data->gpg_verify) - verify_state = "summary+commit"; + gpg_verify_state = "summary+commit"; else - verify_state = "summary-only"; + gpg_verify_state = "summary-only"; } else - verify_state = (pull_data->gpg_verify ? "commit" : "disabled"); - g_string_append_printf (msg, "\nsecurity: GPG: %s ", verify_state); + gpg_verify_state = (pull_data->gpg_verify ? "commit" : "disabled"); + + g_string_append_printf (msg, "\nsecurity: GPG: %s ", gpg_verify_state); #else - verify_state = "disabled"; - g_string_append_printf (msg, "\nsecurity: %s ", verify_state); + gpg_verify_state = "disabled"; + g_string_append_printf (msg, "\nsecurity: %s ", gpg_verify_state); #endif /* OSTREE_DISABLE_GPGME */ + const char *sign_verify_state; + sign_verify_state = (pull_data->sign_verify ? "commit" : "disabled"); + g_string_append_printf (msg, "\nsecurity: SIGN: %s ", sign_verify_state); + OstreeFetcherURI *first_uri = pull_data->meta_mirrorlist->pdata[0]; g_autofree char *first_scheme = _ostree_fetcher_uri_get_scheme (first_uri); if (g_str_has_prefix (first_scheme, "http")) @@ -4698,7 +4770,8 @@ ostree_repo_pull_with_options (OstreeRepo *self, ot_journal_send ("MESSAGE=%s", msg->str, "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_MESSAGE_FETCH_COMPLETE_ID), "OSTREE_REMOTE=%s", pull_data->remote_name, - "OSTREE_GPG=%s", verify_state, + "OSTREE_SIGN=%s", sign_verify_state, + "OSTREE_GPG=%s", gpg_verify_state, "OSTREE_SECONDS=%u", n_seconds, "OSTREE_XFER_SIZE=%s", formatted_xferred, NULL); @@ -6023,6 +6096,7 @@ ostree_repo_pull_from_remotes_async (OstreeRepo *self, g_variant_dict_insert (&local_options_dict, "gpg-verify", "b", FALSE); #endif /* OSTREE_DISABLE_GPGME */ g_variant_dict_insert (&local_options_dict, "gpg-verify-summary", "b", FALSE); + g_variant_dict_insert (&local_options_dict, "sign-verify", "b", FALSE); g_variant_dict_insert (&local_options_dict, "inherit-transaction", "b", TRUE); if (result->remote->refspec_name != NULL) g_variant_dict_insert (&local_options_dict, "override-remote-name", "s", result->remote->refspec_name); diff --git a/src/libostree/ostree-sign-dummy.c b/src/libostree/ostree-sign-dummy.c index e489a988..4baf656c 100644 --- a/src/libostree/ostree-sign-dummy.c +++ b/src/libostree/ostree-sign-dummy.c @@ -64,7 +64,6 @@ static void ostree_sign_dummy_class_init (OstreeSignDummyClass *self) { g_debug ("%s enter", __FUNCTION__); - GObjectClass *object_class = G_OBJECT_CLASS(self); } static void diff --git a/src/libostree/ostree-sign-ed25519.c b/src/libostree/ostree-sign-ed25519.c index e3ab6b57..6a110104 100644 --- a/src/libostree/ostree-sign-ed25519.c +++ b/src/libostree/ostree-sign-ed25519.c @@ -67,7 +67,6 @@ static void ostree_sign_ed25519_class_init (OstreeSignEd25519Class *self) { g_debug ("%s enter", __FUNCTION__); - GObjectClass *object_class = G_OBJECT_CLASS(self); } static void