repo: Reject duplicate signatures when signing commit
Uses OstreeGpgVerifyResult to catch duplicate signatures. If the commit has already been signed with the given GPG key ID, fail with a G_IO_ERROR_EXISTS error code.
This commit is contained in:
parent
8d127b9dcb
commit
9033cf5da1
|
|
@ -3081,26 +3081,70 @@ ostree_repo_sign_commit (OstreeRepo *self,
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
gs_unref_bytes GBytes *commit_data = NULL;
|
gs_unref_bytes GBytes *commit_data = NULL;
|
||||||
gs_unref_bytes GBytes *signature_data = NULL;
|
gs_unref_bytes GBytes *signature = NULL;
|
||||||
gs_unref_variant GVariant *commit_variant = NULL;
|
gs_unref_variant GVariant *commit_variant = NULL;
|
||||||
|
gs_unref_variant GVariant *old_metadata = NULL;
|
||||||
|
gs_unref_variant GVariant *new_metadata = NULL;
|
||||||
|
gs_unref_object OstreeGpgVerifyResult *result = NULL;
|
||||||
|
GError *local_error = NULL;
|
||||||
|
|
||||||
if (!ostree_repo_load_variant (self, OSTREE_OBJECT_TYPE_COMMIT,
|
if (!ostree_repo_load_variant (self, OSTREE_OBJECT_TYPE_COMMIT,
|
||||||
commit_checksum, &commit_variant, error))
|
commit_checksum, &commit_variant, error))
|
||||||
|
{
|
||||||
|
g_prefix_error (error, "Failed to read commit: ");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ostree_repo_read_commit_detached_metadata (self,
|
||||||
|
commit_checksum,
|
||||||
|
&old_metadata,
|
||||||
|
cancellable,
|
||||||
|
error))
|
||||||
|
{
|
||||||
|
g_prefix_error (error, "Failed to read detached metadata: ");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
commit_data = g_variant_get_data_as_bytes (commit_variant);
|
||||||
|
|
||||||
|
/* The verify operation is merely to parse any existing signatures to
|
||||||
|
* check if the commit has already been signed with the given key ID.
|
||||||
|
* We want to avoid storing duplicate signatures in the metadata. */
|
||||||
|
result = _ostree_repo_gpg_verify_with_metadata (self,
|
||||||
|
commit_data,
|
||||||
|
old_metadata,
|
||||||
|
NULL, NULL,
|
||||||
|
cancellable,
|
||||||
|
&local_error);
|
||||||
|
|
||||||
|
/* "Not found" just means the commit is not yet signed. That's okay. */
|
||||||
|
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 if (ostree_gpg_verify_result_lookup (result, key_id, NULL))
|
||||||
|
{
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS,
|
||||||
|
"Commit is already signed with GPG key %s", key_id);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sign_data (self, commit_data, key_id, homedir,
|
||||||
|
&signature, cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* This has the same lifecycle as the variant, so we can just
|
new_metadata = _ostree_detached_metadata_append_gpg_sig (old_metadata, signature);
|
||||||
* use static.
|
|
||||||
*/
|
|
||||||
signature_data = g_bytes_new_static (g_variant_get_data (commit_variant),
|
|
||||||
g_variant_get_size (commit_variant));
|
|
||||||
|
|
||||||
if (!sign_data (self, signature_data, key_id, homedir,
|
if (!ostree_repo_write_commit_detached_metadata (self,
|
||||||
&signature_data,
|
commit_checksum,
|
||||||
cancellable, error))
|
new_metadata,
|
||||||
goto out;
|
cancellable,
|
||||||
|
error))
|
||||||
if (!ostree_repo_append_gpg_signature (self, commit_checksum, signature_data,
|
|
||||||
cancellable, error))
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue