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
|
ostree_repo_list_static_delta_names
|
||||||
OstreeStaticDeltaGenerateOpt
|
OstreeStaticDeltaGenerateOpt
|
||||||
ostree_repo_static_delta_generate
|
ostree_repo_static_delta_generate
|
||||||
|
ostree_repo_static_delta_execute_offline_with_signature
|
||||||
ostree_repo_static_delta_execute_offline
|
ostree_repo_static_delta_execute_offline
|
||||||
ostree_repo_static_delta_verify_signature
|
ostree_repo_static_delta_verify_signature
|
||||||
ostree_repo_traverse_new_reachable
|
ostree_repo_traverse_new_reachable
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ global:
|
||||||
/* Add symbols here, and uncomment the bits in
|
/* Add symbols here, and uncomment the bits in
|
||||||
* Makefile-libostree.am to enable this too.
|
* Makefile-libostree.am to enable this too.
|
||||||
*/
|
*/
|
||||||
|
ostree_repo_static_delta_execute_offline_with_signature;
|
||||||
ostree_repo_static_delta_verify_signature;
|
ostree_repo_static_delta_verify_signature;
|
||||||
} LIBOSTREE_2020.4;
|
} LIBOSTREE_2020.4;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -265,25 +265,68 @@ _ostree_repo_static_delta_is_signed (OstreeRepo *self,
|
||||||
return ret;
|
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
|
* @self: Repo
|
||||||
* @dir_or_file: Path to a directory containing static delta data, or directly to the superblock
|
* @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
|
* @skip_validation: If %TRUE, assume data integrity
|
||||||
* @cancellable: Cancellable
|
* @cancellable: Cancellable
|
||||||
* @error: Error
|
* @error: Error
|
||||||
*
|
*
|
||||||
* Given a directory representing an already-downloaded static delta
|
* Given a directory representing an already-downloaded static delta
|
||||||
* on disk, apply it, generating a new commit. The directory must be
|
* on disk, apply it, generating a new commit.
|
||||||
* named with the form "FROM-TO", where both are checksums, and it
|
* If sign is passed, the static delta signature is verified.
|
||||||
* must contain a file named "superblock", along with at least one part.
|
* 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
|
gboolean
|
||||||
ostree_repo_static_delta_execute_offline (OstreeRepo *self,
|
ostree_repo_static_delta_execute_offline_with_signature (OstreeRepo *self,
|
||||||
GFile *dir_or_file,
|
GFile *dir_or_file,
|
||||||
gboolean skip_validation,
|
OstreeSign *sign,
|
||||||
GCancellable *cancellable,
|
gboolean skip_validation,
|
||||||
GError **error)
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
g_autofree char *basename = NULL;
|
g_autofree char *basename = NULL;
|
||||||
g_autoptr(GVariant) delta = 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);
|
gboolean is_signed = _ostree_repo_static_delta_is_signed (self, meta_fd, NULL, NULL);
|
||||||
if (is_signed)
|
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,
|
if (!ot_variant_read_fd (meta_fd, 0, (GVariantType*)OSTREE_STATIC_DELTA_SIGNED_FORMAT,
|
||||||
TRUE, &delta, error))
|
TRUE, &delta, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
@ -479,6 +541,32 @@ ostree_repo_static_delta_execute_offline (OstreeRepo *self,
|
||||||
return TRUE;
|
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
|
gboolean
|
||||||
_ostree_static_delta_part_open (GInputStream *part_in,
|
_ostree_static_delta_part_open (GInputStream *part_in,
|
||||||
GBytes *inline_part_bytes,
|
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))
|
if (!_ostree_repo_static_delta_is_signed (self, delta_fd, NULL, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
g_autoptr(GVariant) delta = NULL;
|
return _ostree_repo_static_delta_verify_signature (self, delta_fd, sign, out_success_message, error);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1068,6 +1068,14 @@ gboolean ostree_repo_static_delta_generate (OstreeRepo *self,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error);
|
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
|
_OSTREE_PUBLIC
|
||||||
gboolean ostree_repo_static_delta_execute_offline (OstreeRepo *self,
|
gboolean ostree_repo_static_delta_execute_offline (OstreeRepo *self,
|
||||||
GFile *dir_or_file,
|
GFile *dir_or_file,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue