diff --git a/src/ostree/ot-builtin-show.c b/src/ostree/ot-builtin-show.c index d0949745..4eb52f36 100644 --- a/src/ostree/ot-builtin-show.c +++ b/src/ostree/ot-builtin-show.c @@ -148,6 +148,87 @@ do_print_metadata_key (OstreeRepo *repo, return ret; } +static void +print_signature (OstreeGpgVerifyResult *result, + guint signature_index) +{ + g_autoptr(GVariant) variant = NULL; + g_autoptr(GDateTime) date_time_utc = NULL; + g_autoptr(GDateTime) date_time_local = NULL; + g_autoptr(gchar) formatted_date_time = NULL; + gint64 timestamp; + gint64 exp_timestamp; + const char *fingerprint; + const char *pubkey_algo; + const char *user_name; + const char *user_email; + const char *key_id; + gboolean valid; + gboolean sig_expired; + gboolean key_missing; + gsize len; + + /* This function roughly mimics the verify output generated by + * check_sig_and_print() in gnupg/g10/mainproc.c, though obviously + * greatly simplified. */ + + variant = ostree_gpg_verify_result_get_all (result, signature_index); + + g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_VALID, + "b", &valid); + g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_SIG_EXPIRED, + "b", &sig_expired); + g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_KEY_MISSING, + "b", &key_missing); + g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT, + "&s", &fingerprint); + g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_TIMESTAMP, + "x", ×tamp); + g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_EXP_TIMESTAMP, + "x", &exp_timestamp); + g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_PUBKEY_ALGO_NAME, + "&s", &pubkey_algo); + g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_USER_NAME, + "&s", &user_name); + g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_USER_EMAIL, + "&s", &user_email); + + len = strlen (fingerprint); + key_id = (len > 16) ? fingerprint + len - 16 : fingerprint; + + date_time_utc = g_date_time_new_from_unix_utc (timestamp); + date_time_local = g_date_time_to_local (date_time_utc); + formatted_date_time = g_date_time_format (date_time_local, "%c"); + + g_print (" Signature made %s using %s key ID %s\n", + formatted_date_time, pubkey_algo, key_id); + + g_clear_pointer (&date_time_utc, g_date_time_unref); + g_clear_pointer (&date_time_local, g_date_time_unref); + g_clear_pointer (&formatted_date_time, g_free); + + if (key_missing) + g_print (" Can't check signature: public key not found\n"); + else if (valid) + g_print (" Good signature from \"%s <%s>\"\n", user_name, user_email); + else if (sig_expired) + g_print (" Expired signature from \"%s <%s>\"\n", user_name, user_email); + else + g_print (" BAD signature from \"%s <%s>\"\n", user_name, user_email); + + if (exp_timestamp > 0) + { + date_time_utc = g_date_time_new_from_unix_utc (exp_timestamp); + date_time_local = g_date_time_to_local (date_time_utc); + formatted_date_time = g_date_time_format (date_time_local, "%c"); + + if (sig_expired) + g_print (" Signature expired %s\n", formatted_date_time); + else + g_print (" Signature expires %s\n", formatted_date_time); + } +} + static gboolean print_object (OstreeRepo *repo, OstreeObjectType objtype, @@ -165,6 +246,39 @@ print_object (OstreeRepo *repo, flags |= OSTREE_DUMP_RAW; ot_dump_object (objtype, checksum, variant, flags); + if (objtype == OSTREE_OBJECT_TYPE_COMMIT) + { + gs_unref_object OstreeGpgVerifyResult *result = NULL; + GError *local_error = NULL; + + result = ostree_repo_verify_commit_ext (repo, checksum, + NULL, NULL, NULL, + &local_error); + + 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 + { + guint n_sigs, ii; + + n_sigs = ostree_gpg_verify_result_count_all (result); + g_print ("Found %u signature%s:\n", n_sigs, n_sigs == 1 ? "" : "s"); + + for (ii = 0; ii < n_sigs; ii++) + { + g_print ("\n"); + print_signature (result, ii); + } + } + } + ret = TRUE; out: return ret;