diff --git a/SOURCES/0001-upgrade-Print-any-GPG-signatures-while-upgrading.patch b/SOURCES/0001-upgrade-Print-any-GPG-signatures-while-upgrading.patch new file mode 100644 index 0000000..ad4eb7a --- /dev/null +++ b/SOURCES/0001-upgrade-Print-any-GPG-signatures-while-upgrading.patch @@ -0,0 +1,115 @@ +From 750a8889f08c4d3ed90f185cf4a0df379271f2bb Mon Sep 17 00:00:00 2001 +From: Matthew Barnes +Date: Mon, 6 Apr 2015 13:09:37 -0400 +Subject: [PATCH 1/2] upgrade: Print any GPG signatures while upgrading + +--- + main.c | 25 +++++++++++++++++++++++++ + rpmostree-builtin-upgrade.c | 22 ++++++++++++++++++++++ + rpmostree-builtins.h | 2 ++ + 3 files changed, 49 insertions(+) + +diff --git a/src/app/main.c b/src/app/main.c +index a093b52..9ee2d6e 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -99,6 +99,31 @@ rpmostree_option_context_parse (GOptionContext *context, + return TRUE; + } + ++void ++rpmostree_print_gpg_verify_result (OstreeGpgVerifyResult *result) ++{ ++ GString *buffer; ++ guint n_sigs, ii; ++ ++ n_sigs = ostree_gpg_verify_result_count_all (result); ++ ++ /* XXX If we ever add internationalization, use ngettext() here. */ ++ g_print ("GPG: Verification enabled, found %u signature%s:\n", ++ n_sigs, n_sigs == 1 ? "" : "s"); ++ ++ buffer = g_string_sized_new (256); ++ ++ for (ii = 0; ii < n_sigs; ii++) ++ { ++ g_string_append_c (buffer, '\n'); ++ ostree_gpg_verify_result_describe (result, ii, buffer, " ", ++ OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT); ++ } ++ ++ g_print ("%s\n", buffer->str); ++ g_string_free (buffer, TRUE); ++} ++ + int + main (int argc, + char **argv) +diff --git a/src/rpmostree-builtin-upgrade.c b/src/rpmostree-builtin-upgrade.c +index e67f9f0..432eac8 100644 +--- a/src/rpmostree-builtin-upgrade.c ++++ b/src/rpmostree-builtin-upgrade.c +@@ -45,6 +45,20 @@ static GOptionEntry option_entries[] = { + { NULL } + }; + ++static void ++gpg_verify_result_cb (OstreeRepo *repo, ++ const char *checksum, ++ OstreeGpgVerifyResult *result, ++ GSConsole *console) ++{ ++ /* Temporarily place the GSConsole stream (which is just stdout) ++ * back in normal mode before printing GPG verification results. */ ++ gs_console_end_status_line (console, NULL, NULL); ++ ++ g_print ("\n"); ++ rpmostree_print_gpg_verify_result (result); ++} ++ + gboolean + rpmostree_builtin_upgrade (int argc, + char **argv, +@@ -63,6 +77,7 @@ rpmostree_builtin_upgrade (int argc, + + gs_free char *origin_description = NULL; + gs_unref_object OstreeRepo *repo = NULL; ++ gulong signal_handler_id = 0; + + if (!rpmostree_option_context_parse (context, option_entries, &argc, &argv, error)) + goto out; +@@ -89,6 +104,10 @@ rpmostree_builtin_upgrade (int argc, + { + gs_console_begin_status_line (console, "", NULL, NULL); + progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, console); ++ signal_handler_id = g_signal_connect (repo, "gpg-verify-result", ++ G_CALLBACK (gpg_verify_result_cb), ++ console); ++ + } + + if (opt_allow_downgrade) +@@ -185,5 +204,8 @@ rpmostree_builtin_upgrade (int argc, + if (console) + (void) gs_console_end_status_line (console, NULL, NULL); + ++ if (signal_handler_id > 0) ++ g_signal_handler_disconnect (repo, signal_handler_id); ++ + return ret; + } +diff --git a/src/rpmostree-builtins.h b/src/rpmostree-builtins.h +index 8e1c5d1..480d06c 100644 +--- a/src/rpmostree-builtins.h ++++ b/src/rpmostree-builtins.h +@@ -46,5 +46,7 @@ gboolean rpmostree_option_context_parse (GOptionContext *context, + char ***argv, + GError **error); + ++void rpmostree_print_gpg_verify_result (OstreeGpgVerifyResult *result); ++ + G_END_DECLS + +-- +1.8.3.1 + diff --git a/SOURCES/0002-status-Print-any-GPG-signatures-for-deployments.patch b/SOURCES/0002-status-Print-any-GPG-signatures-for-deployments.patch new file mode 100644 index 0000000..a815f7a --- /dev/null +++ b/SOURCES/0002-status-Print-any-GPG-signatures-for-deployments.patch @@ -0,0 +1,239 @@ +From 347a5003e0f0fd0e921d20094b871dc39d5f8324 Mon Sep 17 00:00:00 2001 +From: Matthew Barnes +Date: Tue, 7 Apr 2015 13:49:21 -0400 +Subject: [PATCH 2/2] status: Print any GPG signatures for deployments + +In pretty mode (--pretty), print signatures for each listed deployment. + +Otherwise, just print signatures for the booted deployment at the end to +preserve the tabular formatting of the deployment list. +--- + src/app/rpmostree-builtin-status.c | 136 +++++++++++++++++++++++++++++++++++-- + 1 file changed, 129 insertions(+), 7 deletions(-) + +diff --git a/src/rpmostree-builtin-status.c b/src/rpmostree-builtin-status.c +index 5cd8dde..ed492a8 100644 +--- a/src/rpmostree-builtin-status.c ++++ b/src/rpmostree-builtin-status.c +@@ -76,6 +76,37 @@ version_of_commit (OstreeRepo *repo, const char *checksum) + return NULL; + } + ++static gboolean ++deployment_get_gpg_verify (OstreeDeployment *deployment, ++ OstreeRepo *repo) ++{ ++ /* XXX Something like this could be added to the OstreeDeployment ++ * API in libostree if the OstreeRepo parameter is acceptable. */ ++ ++ GKeyFile *origin; ++ gs_free char *refspec = NULL; ++ gs_free char *remote = NULL; ++ gboolean gpg_verify = FALSE; ++ ++ origin = ostree_deployment_get_origin (deployment); ++ ++ if (origin == NULL) ++ goto out; ++ ++ refspec = g_key_file_get_string (origin, "origin", "refspec", NULL); ++ ++ if (refspec == NULL) ++ goto out; ++ ++ if (!ostree_parse_refspec (refspec, &remote, NULL, NULL)) ++ goto out; ++ ++ (void) ostree_repo_remote_get_gpg_verify (repo, remote, &gpg_verify, NULL); ++ ++out: ++ return gpg_verify; ++} ++ + gboolean + rpmostree_builtin_status (int argc, + char **argv, +@@ -85,6 +116,7 @@ rpmostree_builtin_status (int argc, + gboolean ret = FALSE; + gs_unref_object GFile *sysroot_path = NULL; + gs_unref_object OstreeSysroot *sysroot = NULL; ++ gs_unref_object OstreeRepo *repo = NULL; + gs_unref_ptrarray GPtrArray *deployments = NULL; // list of all depoyments + OstreeDeployment *booted_deployment = NULL; // current booted deployment + GOptionContext *context = g_option_context_new ("- Get the version of the booted system"); +@@ -96,6 +128,7 @@ rpmostree_builtin_status (int argc, + guint max_refspec_len = 0; // maximum length of refspec - determined in code + guint max_version_len = 0; // maximum length of version - determined in code + guint buffer = 5; // minimum space between end of one entry and new column ++ gs_free char *booted_csum = NULL; + + if (!rpmostree_option_context_parse (context, option_entries, &argc, &argv, error)) + goto out; +@@ -105,6 +138,9 @@ rpmostree_builtin_status (int argc, + if (!ostree_sysroot_load (sysroot, cancellable, error)) + goto out; + ++ if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error)) ++ goto out; ++ + booted_deployment = ostree_sysroot_get_booted_deployment (sysroot); + deployments = ostree_sysroot_get_deployments (sysroot); + +@@ -114,7 +150,6 @@ rpmostree_builtin_status (int argc, + /* find max lengths of osname and refspec */ + for (j = 0; j < deployments->len; j++) + { +- gs_unref_object OstreeRepo *repo = NULL; + const char *csum = ostree_deployment_get_csum (deployments->pdata[j]); + GKeyFile *origin; + gs_free char *origin_refspec = NULL; +@@ -134,9 +169,6 @@ rpmostree_builtin_status (int argc, + } + max_refspec_len = MAX (max_refspec_len, strlen (origin_refspec)); + +- if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error)) +- goto out; +- + version_string = version_of_commit (repo, csum); + if (version_string) + max_version_len = MAX (max_version_len, strlen (version_string)); +@@ -158,7 +190,6 @@ rpmostree_builtin_status (int argc, + for (i=0; ilen; i++) + { + gs_unref_variant GVariant *commit = NULL; +- gs_unref_object OstreeRepo *repo = NULL; + const char *csum = ostree_deployment_get_csum (deployments->pdata[i]); + OstreeDeployment *deployment = deployments->pdata[i]; + GKeyFile *origin; +@@ -169,8 +200,6 @@ rpmostree_builtin_status (int argc, + gs_free char *version_string = NULL; + + /* get commit for timestamp */ +- if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error)) +- goto out; + if (!ostree_repo_load_variant (repo, + OSTREE_OBJECT_TYPE_COMMIT, + csum, +@@ -202,6 +231,13 @@ rpmostree_builtin_status (int argc, + /* print deployment info column */ + if (!opt_pretty) + { ++ if (deployment == booted_deployment) ++ { ++ /* Stash this for printing signatures later. */ ++ if (deployment_get_gpg_verify (deployment, repo)) ++ booted_csum = g_strdup (csum); ++ } ++ + g_print ("%c %-*s", + deployment == booted_deployment ? '*' : ' ', + max_timestamp_len+buffer, timestamp_string); +@@ -218,8 +254,11 @@ rpmostree_builtin_status (int argc, + /* print "pretty" row info */ + else + { ++ gs_unref_object OstreeGpgVerifyResult *result = NULL; + guint tab = 11; + char *title = NULL; ++ GError *local_error = NULL; ++ + if (i==0) + title = "DEFAULT ON BOOT"; + else if (deployment == booted_deployment || +@@ -239,10 +278,93 @@ rpmostree_builtin_status (int argc, + tab, "id", tab, csum, ostree_deployment_get_deployserial (deployment), + tab, "osname", tab, ostree_deployment_get_osname (deployment), + tab, "refspec", tab, origin_refspec); ++ ++ if (deployment_get_gpg_verify (deployment, repo)) ++ { ++ result = ostree_repo_verify_commit_ext (repo, csum, NULL, NULL, ++ cancellable, &local_error); ++ ++ /* NOT_FOUND just means the commit is not signed. */ ++ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) ++ { ++ g_clear_error (&local_error); ++ } ++ else if (local_error != NULL) ++ { ++ g_propagate_error (error, local_error); ++ goto out; ++ } ++ else ++ { ++ GString *sigs_buffer; ++ guint n_sigs, ii; ++ ++ n_sigs = ostree_gpg_verify_result_count_all (result); ++ ++ sigs_buffer = g_string_sized_new (256); ++ ++ for (ii = 0; ii < n_sigs; ii++) ++ { ++ g_string_append_c (sigs_buffer, '\n'); ++ ostree_gpg_verify_result_describe (result, ii, sigs_buffer, " GPG: ", ++ OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT); ++ } ++ ++ g_print ("%s", sigs_buffer->str); ++ g_string_free (sigs_buffer, TRUE); ++ } ++ } ++ + printchar ("=", 60); + } + } + ++ /* Print any signatures for the booted deployment, but only in NON-pretty ++ * mode. We save this for the end to preserve the tabular formatting for ++ * deployments. */ ++ if (booted_csum != NULL) ++ { ++ gs_unref_object OstreeGpgVerifyResult *result = NULL; ++ GError *local_error = NULL; ++ ++ result = ostree_repo_verify_commit_ext (repo, booted_csum, NULL, NULL, ++ cancellable, &local_error); ++ ++ /* NOT_FOUND just means the commit is not signed. */ ++ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) ++ { ++ g_clear_error (&local_error); ++ } ++ else if (local_error != NULL) ++ { ++ g_propagate_error (error, local_error); ++ goto out; ++ } ++ else ++ { ++ GString *sigs_buffer; ++ guint n_sigs, ii; ++ ++ n_sigs = ostree_gpg_verify_result_count_all (result); ++ ++ /* XXX If we ever add internationalization, use ngettext() here. */ ++ g_print ("\nGPG: Found %u signature%s on the booted deployment (*):\n", ++ n_sigs, n_sigs == 1 ? "" : "s"); ++ ++ sigs_buffer = g_string_sized_new (256); ++ ++ for (ii = 0; ii < n_sigs; ii++) ++ { ++ g_string_append_c (sigs_buffer, '\n'); ++ ostree_gpg_verify_result_describe (result, ii, sigs_buffer, " ", ++ OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT); ++ } ++ ++ g_print ("%s", sigs_buffer->str); ++ g_string_free (sigs_buffer, TRUE); ++ } ++ } ++ + ret = TRUE; + out: + return ret; +-- +1.8.3.1 + diff --git a/SPECS/rpm-ostree-client.spec b/SPECS/rpm-ostree-client.spec index 67af49d..9a5a057 100644 --- a/SPECS/rpm-ostree-client.spec +++ b/SPECS/rpm-ostree-client.spec @@ -1,12 +1,15 @@ Summary: Client side upgrade program Name: rpm-ostree-client Version: 2015.3 -Release: 2.atomic%{?dist} +Release: 3.atomic%{?dist} #VCS: https://github.com/cgwalters/rpm-ostree # This tarball is generated via "make -f Makefile.dist-packaging dist-snapshot-without-compose-tooling" Source0: %{name}-%{version}.tar.xz +Patch0: 0001-upgrade-Print-any-GPG-signatures-while-upgrading.patch +Patch1: 0002-status-Print-any-GPG-signatures-for-deployments.patch License: LGPLv2+ URL: https://github.com/projectatomic/rpm-ostree +BuildRequires: git # We always run autogen.sh BuildRequires: autoconf automake libtool # For docs @@ -29,7 +32,7 @@ the OSTree model of bootable filesystem trees. It provides commands usable on client systems to upgrade and rollback. %prep -%setup -q -n %{name}-%{version} +%autosetup -Sgit -n %{name}-%{version} %build env NOCONFIGURE=1 ./autogen.sh @@ -46,6 +49,9 @@ make install DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p -c" %{_mandir}/man1/*.gz %changelog +* Fri Apr 17 2015 Colin Walters - 2015.3-3.atomic +- Backport client side GPG verification status patches + * Fri Jan 23 2015 Colin Walters - 2015.3-2.atomic - New usptream release