From 9442f5e5c9b6a929aa3f2ee84204cce0232a32f7 Mon Sep 17 00:00:00 2001 From: Denis Pynkin Date: Tue, 8 Oct 2019 01:55:25 +0300 Subject: [PATCH] sign: use common function for loading public keys during pulling Add function `_load_public_keys()` to pre-load public keys according remote's configuration. If no keys configured for remote, then use system-wide configuration. Signed-off-by: Denis Pynkin --- src/libostree/ostree-repo-pull.c | 173 ++++++++++++++++++------------- 1 file changed, 102 insertions(+), 71 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index a57af470b2..0cf3968f24 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -1469,6 +1469,93 @@ process_verify_result (OtPullData *pull_data, } #endif /* OSTREE_DISABLE_GPGME */ +/* _remote_load_public_keys: + * + * Load public keys according remote's configuration: + * inlined key passed via config option `verification-key` or + * file name with public keys via `verification-file` option. + * + * If both options are set then load all all public keys + * both from file and inlined in config. + * + * Returns: %FALSE if any source is configured but nothing has been loaded. + * Returns: %TRUE if no configuration or any key loaded. + * */ +static gboolean +_load_public_keys (OtPullData *pull_data, + OstreeSign *sign) +{ + + g_autofree gchar *pk_ascii = NULL; + g_autofree gchar *pk_file = NULL; + gboolean loaded_from_file = TRUE; + gboolean loaded_inlined = TRUE; + g_autoptr (GError) error = NULL; + + /* Load keys for remote from file */ + ostree_repo_get_remote_option (pull_data->repo, + pull_data->remote_name, + "verification-file", NULL, + &pk_file, NULL); + + ostree_repo_get_remote_option (pull_data->repo, + pull_data->remote_name, + "verification-key", NULL, + &pk_ascii, NULL); + + /* return TRUE if no configuration for remote */ + if ((pk_file == NULL) &&(pk_ascii == NULL)) + return TRUE; + + if (pk_file != NULL) + { + g_autoptr (GVariantBuilder) builder = NULL; + g_autoptr (GVariant) options = NULL; + + builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_add (builder, "{sv}", "filename", g_variant_new_string (pk_file)); + options = g_variant_builder_end (builder); + + if (ostree_sign_load_pk (sign, options, &error)) + loaded_from_file = TRUE; + else + { + if (error == NULL) + g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, + "unknown reason"); + + g_warning("Unable to load public keys from file '%s': %s", + pk_file, error->message); + g_clear_error (&error); + } + } + + if (pk_ascii != NULL) + { + g_autoptr (GVariant) pk = g_variant_new_string(pk_ascii); + + /* Add inlined public key */ + if (loaded_from_file) + loaded_inlined = ostree_sign_add_pk (sign, pk, &error); + else + loaded_inlined = ostree_sign_set_pk (sign, pk, &error); + + if (!loaded_inlined) + { + if (error == NULL) + g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, + "unknown reason"); + + g_warning("Unable to load public key '%s': %s", + pk_ascii, error->message); + g_clear_error (&error); + } + } + + /* Return true if able to load from any source */ + return (loaded_from_file || loaded_inlined); +} + static gboolean ostree_verify_unwritten_commit (OtPullData *pull_data, const char *checksum, @@ -1518,17 +1605,16 @@ ostree_verify_unwritten_commit (OtPullData *pull_data, 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? */ g_auto (GStrv) names = ostree_sign_list_names(); for (guint i=0; i < g_strv_length (names); i++) { g_autoptr (OstreeSign) sign = NULL; - g_autoptr (GError) local_error = NULL; g_autoptr (GVariant) signatures = NULL; const gchar *signature_key = NULL; GVariantType *signature_format = NULL; - g_autofree gchar *pk_ascii = NULL; - g_autofree gchar *pk_file = NULL; + g_autoptr (GError) local_error = NULL; if ((sign = ostree_sign_get_by_name (names[i], &local_error)) == NULL) continue; @@ -1539,45 +1625,21 @@ ostree_verify_unwritten_commit (OtPullData *pull_data, signatures = g_variant_lookup_value (detached_metadata, signature_key, signature_format); + + /* If not found signatures for requested signature subsystem */ if (!signatures) continue; - /* Load keys for remote from file */ - ostree_repo_get_remote_option (pull_data->repo, - pull_data->remote_name, - "verification-file", NULL, - &pk_file, NULL); - if (pk_file != NULL) - { - g_autoptr (GVariantBuilder) builder = NULL; - g_autoptr (GVariant) options = NULL; - - builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); - g_variant_builder_add (builder, "{sv}", "filename", g_variant_new_string (pk_file)); - options = g_variant_builder_end (builder); - - if (!ostree_sign_load_pk (sign, options, &local_error)) - g_clear_error (&local_error); - } - - /* Override key if it is set explicitly */ - ostree_repo_get_remote_option (pull_data->repo, - pull_data->remote_name, - "verification-key", NULL, - &pk_ascii, NULL); - if (pk_ascii != NULL) - { - g_autoptr (GVariant) pk = g_variant_new_string(pk_ascii); - if (!ostree_sign_set_pk (sign, pk, &local_error)) - continue; - } + /* Try to load public key(s) according remote's configuration */ + if (!_load_public_keys (pull_data, sign)) + continue; - /* Set return to true if any sign fit */ + /* Return true if any signature fit to pre-loaded public keys. + * If no keys configured -- then system configuration will be used */ if (ostree_sign_data_verify (sign, - signed_data, - signatures, - &local_error - )) + signed_data, + signatures, + &local_error)) ret = TRUE; } @@ -1931,44 +1993,13 @@ scan_commit_object (OtPullData *pull_data, { g_autoptr (OstreeSign) sign = NULL; g_autoptr (GError) local_error = NULL; - g_autofree gchar *pk_ascii = NULL; - g_autofree gchar *pk_file = NULL; if ((sign = ostree_sign_get_by_name (names[i], &local_error)) == NULL) continue; - /* Load keys for remote from file */ - ostree_repo_get_remote_option (pull_data->repo, - pull_data->remote_name, - "verification-file", NULL, - &pk_file, NULL); - if (pk_file != NULL) - { - g_autoptr (GVariantBuilder) builder = NULL; - g_autoptr (GVariant) options = NULL; - - builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); - g_variant_builder_add (builder, "{sv}", "filename", g_variant_new_string (pk_file)); - options = g_variant_builder_end (builder); - - if (!ostree_sign_load_pk (sign, options, &local_error)) - g_clear_error (&local_error); - } - - ostree_repo_get_remote_option (pull_data->repo, - pull_data->remote_name, - "verification-key", NULL, - &pk_ascii, NULL); - if (pk_ascii != NULL) - { - g_autoptr (GVariant) pk = NULL; - - // Just use the string as signature - pk = g_variant_new_string(pk_ascii); - if (!ostree_sign_set_pk (sign, pk, &local_error)) - continue; - } - + /* Try to load public key(s) according remote's configuration */ + if (!_load_public_keys (pull_data, sign)) + continue; /* Set return to true if any sign fit */ if (ostree_sign_commit_verify (sign,