From 6f8669331d8dffa05296135443116268d21bac54 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Tue, 21 Jan 2020 12:43:35 -0700 Subject: repo: Prevent publishing summary without matching signature Use a temporary directory for the summary and signature file in `ostree_repo_regenerate_metadata` so that the summary file isn't published if signing fails. This prevents publishing a summary without a signature file or leaving a mismatched signature file in place. --- src/libostree/ostree-repo.c | 51 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 81d3e612..4dbec47b 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -43,6 +43,7 @@ #include "ostree-repo-static-delta-private.h" #include "ot-fs-utils.h" #include "ostree-autocleanups.h" +#include "ostree-sign-private.h" #include #include @@ -6543,8 +6544,17 @@ regenerate_metadata (OstreeRepo *self, if (!ostree_repo_static_delta_reindex (self, 0, NULL, cancellable, error)) return FALSE; + /* Create the summary and signature in a temporary directory so that + * the summary isn't published without a matching signature. + */ + g_auto(GLnxTmpDir) summary_tmpdir = { 0, }; + if (!glnx_mkdtempat (self->tmp_dir_fd, "summary-XXXXXX", 0777, + &summary_tmpdir, error)) + return FALSE; + g_debug ("Using summary tmpdir %s", summary_tmpdir.path); + if (!_ostree_repo_file_replace_contents (self, - self->repo_dir_fd, + summary_tmpdir.fd, "summary", g_variant_get_data (summary), g_variant_get_size (summary), @@ -6552,18 +6562,45 @@ regenerate_metadata (OstreeRepo *self, error)) return FALSE; - if (!ot_ensure_unlinked_at (self->repo_dir_fd, "summary.sig", error)) - return FALSE; - if (gpg_key_ids != NULL && - !ostree_repo_add_gpg_signature_summary (self, (const char **) gpg_key_ids, gpg_homedir, - cancellable, error)) + !_ostree_repo_add_gpg_signature_summary_at (self, summary_tmpdir.fd, + (const char **) gpg_key_ids, gpg_homedir, + cancellable, error)) return FALSE; if (sign_keys != NULL && - !ostree_sign_summary (sign, self, sign_keys, cancellable, error)) + !_ostree_sign_summary_at (sign, self, summary_tmpdir.fd, sign_keys, + cancellable, error)) return FALSE; + /* Rename them into place */ + if (!glnx_renameat (summary_tmpdir.fd, "summary", + self->repo_dir_fd, "summary", + error)) + return glnx_prefix_error (error, "Unable to rename summary file: "); + + if (gpg_key_ids != NULL || sign_keys != NULL) + { + if (!glnx_renameat (summary_tmpdir.fd, "summary.sig", + self->repo_dir_fd, "summary.sig", + error)) + { + /* Delete an existing signature since it no longer corresponds + * to the published summary. + */ + g_debug ("Deleting existing unmatched summary.sig file"); + (void) ot_ensure_unlinked_at (self->repo_dir_fd, "summary.sig", NULL); + + return glnx_prefix_error (error, "Unable to rename summary signature file: "); + } + } + else + { + g_debug ("Deleting existing unmatched summary.sig file"); + if (!ot_ensure_unlinked_at (self->repo_dir_fd, "summary.sig", error)) + return glnx_prefix_error (error, "Unable to delete summary signature file: "); + } + return TRUE; } -- cgit v1.2.1