summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Nicholson <nicholson@endlessm.com>2020-01-21 12:43:35 -0700
committerDan Nicholson <dbn@endlessos.org>2023-02-07 14:50:47 -0700
commit6f8669331d8dffa05296135443116268d21bac54 (patch)
tree69f98778460ff8d8f6e344936d568d310e440ca3 /src
parent6cc75a6c1e2e72d536568e17a6a45ca6cd629630 (diff)
downloadostree-6f8669331d8dffa05296135443116268d21bac54.tar.gz
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.
Diffstat (limited to 'src')
-rw-r--r--src/libostree/ostree-repo.c51
1 files changed, 44 insertions, 7 deletions
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 <locale.h>
#include <glib/gstdio.h>
@@ -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;
}