mirror of
https://github.com/ostreedev/ostree.git
synced 2024-12-22 17:35:55 +03:00
lib/deltas: Check signed delta in execute_offline
Add a new function `ostree_repo_static_delta_execute_offline_with_signature` which takes a signature engine to verify the delta before applying it. The `ostree_repo_static_delta_execute_offline` is just a wrapper to this new function, passing a NULL signature engine. When this function is called without signature engine, but with a sign delta, it will only fails if `sign-verify-deltas` is set to true in repo core options. This commits move signature existence check and delta signature verification to share common parts between existing APIs and the new function. Signed-off-by: Frédéric Danis <frederic.danis@collabora.com>
This commit is contained in:
parent
869dbc037e
commit
fb1faf17d6
@ -412,6 +412,7 @@ ostree_repo_list_commit_objects_starting_with
|
||||
ostree_repo_list_static_delta_names
|
||||
OstreeStaticDeltaGenerateOpt
|
||||
ostree_repo_static_delta_generate
|
||||
ostree_repo_static_delta_execute_offline_with_signature
|
||||
ostree_repo_static_delta_execute_offline
|
||||
ostree_repo_static_delta_verify_signature
|
||||
ostree_repo_traverse_new_reachable
|
||||
|
@ -22,6 +22,7 @@ global:
|
||||
/* Add symbols here, and uncomment the bits in
|
||||
* Makefile-libostree.am to enable this too.
|
||||
*/
|
||||
ostree_repo_static_delta_execute_offline_with_signature;
|
||||
ostree_repo_static_delta_verify_signature;
|
||||
} LIBOSTREE_2020.4;
|
||||
|
||||
|
@ -265,25 +265,68 @@ _ostree_repo_static_delta_is_signed (OstreeRepo *self,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_ostree_repo_static_delta_verify_signature (OstreeRepo *self,
|
||||
int fd,
|
||||
OstreeSign *sign,
|
||||
char **out_success_message,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GVariantBuilder) desc_sign_builder = NULL;
|
||||
g_autoptr(GVariant) delta_meta = NULL;
|
||||
g_autoptr(GVariant) delta = NULL;
|
||||
|
||||
if (!ot_variant_read_fd (fd, 0,
|
||||
(GVariantType*)OSTREE_STATIC_DELTA_SIGNED_FORMAT,
|
||||
TRUE, &delta, error))
|
||||
return FALSE;
|
||||
|
||||
/* Check if there are signatures for signature engine */
|
||||
const gchar *signature_key = ostree_sign_metadata_key(sign);
|
||||
GVariantType *signature_format = (GVariantType *) ostree_sign_metadata_format(sign);
|
||||
delta_meta = g_variant_get_child_value (delta, 2);
|
||||
if (delta_meta == NULL)
|
||||
return glnx_throw (error, "no metadata in static-delta superblock");
|
||||
g_autoptr(GVariant) signatures = g_variant_lookup_value (delta_meta,
|
||||
signature_key,
|
||||
signature_format);
|
||||
if (!signatures)
|
||||
return glnx_throw (error, "no signature for '%s' in static-delta superblock", signature_key);
|
||||
|
||||
/* Get static delta superblock */
|
||||
g_autoptr(GVariant) child = g_variant_get_child_value (delta, 1);
|
||||
if (child == NULL)
|
||||
return glnx_throw (error, "no metadata in static-delta superblock");
|
||||
g_autoptr(GBytes) signed_data = g_variant_get_data_as_bytes(child);
|
||||
|
||||
return ostree_sign_data_verify (sign, signed_data, signatures, out_success_message, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_repo_static_delta_execute_offline:
|
||||
* ostree_repo_static_delta_execute_offline_with_signature:
|
||||
* @self: Repo
|
||||
* @dir_or_file: Path to a directory containing static delta data, or directly to the superblock
|
||||
* @sign: Signature engine used to check superblock
|
||||
* @skip_validation: If %TRUE, assume data integrity
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Given a directory representing an already-downloaded static delta
|
||||
* on disk, apply it, generating a new commit. The directory must be
|
||||
* named with the form "FROM-TO", where both are checksums, and it
|
||||
* must contain a file named "superblock", along with at least one part.
|
||||
* on disk, apply it, generating a new commit.
|
||||
* If sign is passed, the static delta signature is verified.
|
||||
* If sign-verify-deltas configuration option is set and static delta is signed,
|
||||
* signature verification will be mandatory before apply the static delta.
|
||||
* The directory must be named with the form "FROM-TO", where both are
|
||||
* checksums, and it must contain a file named "superblock", along with at least
|
||||
* one part.
|
||||
*/
|
||||
gboolean
|
||||
ostree_repo_static_delta_execute_offline (OstreeRepo *self,
|
||||
GFile *dir_or_file,
|
||||
gboolean skip_validation,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
ostree_repo_static_delta_execute_offline_with_signature (OstreeRepo *self,
|
||||
GFile *dir_or_file,
|
||||
OstreeSign *sign,
|
||||
gboolean skip_validation,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree char *basename = NULL;
|
||||
g_autoptr(GVariant) delta = NULL;
|
||||
@ -316,6 +359,25 @@ ostree_repo_static_delta_execute_offline (OstreeRepo *self,
|
||||
gboolean is_signed = _ostree_repo_static_delta_is_signed (self, meta_fd, NULL, NULL);
|
||||
if (is_signed)
|
||||
{
|
||||
gboolean verify_deltas;
|
||||
gboolean verified;
|
||||
|
||||
if (!ot_keyfile_get_boolean_with_default (self->config, "core", "sign-verify-deltas",
|
||||
FALSE, &verify_deltas, error))
|
||||
return FALSE;
|
||||
|
||||
if (verify_deltas && !sign)
|
||||
return glnx_throw (error, "Key is mandatory to check delta signature");
|
||||
|
||||
if (sign)
|
||||
{
|
||||
verified = _ostree_repo_static_delta_verify_signature (self, meta_fd, sign, NULL, error);
|
||||
if (*error)
|
||||
return FALSE;
|
||||
if (!verified)
|
||||
return glnx_throw (error, "Delta signature verification failed");
|
||||
}
|
||||
|
||||
if (!ot_variant_read_fd (meta_fd, 0, (GVariantType*)OSTREE_STATIC_DELTA_SIGNED_FORMAT,
|
||||
TRUE, &delta, error))
|
||||
return FALSE;
|
||||
@ -479,6 +541,32 @@ ostree_repo_static_delta_execute_offline (OstreeRepo *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_repo_static_delta_execute_offline:
|
||||
* @self: Repo
|
||||
* @dir_or_file: Path to a directory containing static delta data, or directly to the superblock
|
||||
* @skip_validation: If %TRUE, assume data integrity
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Given a directory representing an already-downloaded static delta
|
||||
* on disk, apply it, generating a new commit. The directory must be
|
||||
* named with the form "FROM-TO", where both are checksums, and it
|
||||
* must contain a file named "superblock", along with at least one part.
|
||||
*/
|
||||
gboolean
|
||||
ostree_repo_static_delta_execute_offline (OstreeRepo *self,
|
||||
GFile *dir_or_file,
|
||||
gboolean skip_validation,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
return ostree_repo_static_delta_execute_offline_with_signature(self, dir_or_file, NULL,
|
||||
skip_validation,
|
||||
cancellable,
|
||||
error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_ostree_static_delta_part_open (GInputStream *part_in,
|
||||
GBytes *inline_part_bytes,
|
||||
@ -1030,29 +1118,5 @@ ostree_repo_static_delta_verify_signature (OstreeRepo *self,
|
||||
if (!_ostree_repo_static_delta_is_signed (self, delta_fd, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
g_autoptr(GVariant) delta = NULL;
|
||||
if (!ot_variant_read_fd (delta_fd, 0,
|
||||
(GVariantType*)OSTREE_STATIC_DELTA_SIGNED_FORMAT,
|
||||
TRUE, &delta, error))
|
||||
return FALSE;
|
||||
|
||||
/* Check if there are signatures for signature engine */
|
||||
const gchar *signature_key = ostree_sign_metadata_key(sign);
|
||||
GVariantType *signature_format = (GVariantType *) ostree_sign_metadata_format(sign);
|
||||
delta_meta = g_variant_get_child_value (delta, 2);
|
||||
if (delta_meta == NULL)
|
||||
return glnx_throw (error, "no metadata in static-delta superblock");
|
||||
g_autoptr(GVariant) signatures = g_variant_lookup_value (delta_meta,
|
||||
signature_key,
|
||||
signature_format);
|
||||
if (!signatures)
|
||||
return glnx_throw (error, "no signature for '%s' in static-delta superblock", signature_key);
|
||||
|
||||
/* Get static delta superblock */
|
||||
g_autoptr(GVariant) child = g_variant_get_child_value (delta, 1);
|
||||
if (child == NULL)
|
||||
return glnx_throw (error, "no metadata in static-delta superblock");
|
||||
g_autoptr(GBytes) signed_data = g_variant_get_data_as_bytes(child);
|
||||
|
||||
return ostree_sign_data_verify (sign, signed_data, signatures, out_success_message, error);
|
||||
return _ostree_repo_static_delta_verify_signature (self, delta_fd, sign, out_success_message, error);
|
||||
}
|
||||
|
@ -1068,6 +1068,14 @@ gboolean ostree_repo_static_delta_generate (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
gboolean ostree_repo_static_delta_execute_offline_with_signature (OstreeRepo *self,
|
||||
GFile *dir_or_file,
|
||||
OstreeSign *sign,
|
||||
gboolean skip_validation,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
gboolean ostree_repo_static_delta_execute_offline (OstreeRepo *self,
|
||||
GFile *dir_or_file,
|
||||
|
Loading…
Reference in New Issue
Block a user