gpg: Add ostree_gpg_verify_result_describe()

Internalizes the signature output of "ostree show" so it can be reused
elsewhere.
This commit is contained in:
Matthew Barnes 2015-03-20 12:07:03 -04:00
parent bc5c9fca26
commit 7956b0a5c5
4 changed files with 174 additions and 83 deletions

View File

@ -174,6 +174,8 @@ ostree_gpg_verify_result_count_valid
ostree_gpg_verify_result_lookup
ostree_gpg_verify_result_get
ostree_gpg_verify_result_get_all
OstreeGpgSignatureFormatFlags
ostree_gpg_verify_result_describe
<SUBSECTION Standard>
OSTREE_GPG_VERIFY_RESULT
OSTREE_IS_GPG_VERIFY_RESULT

View File

@ -20,6 +20,9 @@
#include "config.h"
#include <string.h>
#include "libglnx.h"
#include "libgsystem.h"
#include "ostree-gpg-verify-result-private.h"
@ -451,6 +454,147 @@ ostree_gpg_verify_result_get_all (OstreeGpgVerifyResult *result,
G_N_ELEMENTS (all_signature_attrs));
}
/**
* ostree_gpg_verify_result_describe:
* @result: an #OstreeGpgVerifyResult
* @signature_index: which signature to describe
* @output_buffer: a #GString to hold the description
* @line_prefix: (allow-none): optional line prefix string
* @flags: flags to adjust the description format
*
* Appends a brief, human-readable description of the GPG signature at
* @signature_index in @result to the @output_buffer. The description
* spans multiple lines. A @line_prefix string, if given, will precede
* each line of the description.
*
* The @flags argument is reserved for future variations to the description
* format. Currently must be 0.
*
* It is a programmer error to request an invalid @signature_index. Use
* ostree_gpg_verify_result_count_all() to find the number of signatures in
* @result.
*/
void
ostree_gpg_verify_result_describe (OstreeGpgVerifyResult *result,
guint signature_index,
GString *output_buffer,
const gchar *line_prefix,
OstreeGpgSignatureFormatFlags flags)
{
g_autoptr(GVariant) variant = NULL;
g_autoptr(GDateTime) date_time_utc = NULL;
g_autoptr(GDateTime) date_time_local = NULL;
g_autofree char *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;
g_return_if_fail (OSTREE_IS_GPG_VERIFY_RESULT (result));
g_return_if_fail (output_buffer != NULL);
/* The default format 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_return_if_fail (variant != NULL);
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", &timestamp);
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");
if (line_prefix != NULL)
g_string_append (output_buffer, line_prefix);
g_string_append_printf (output_buffer,
"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 (line_prefix != NULL)
g_string_append (output_buffer, line_prefix);
if (key_missing)
{
g_string_append (output_buffer,
"Can't check signature: public key not found\n");
}
else if (valid)
{
g_string_append_printf (output_buffer,
"Good signature from \"%s <%s>\"\n",
user_name, user_email);
}
else if (sig_expired)
{
g_string_append_printf (output_buffer,
"Expired signature from \"%s <%s>\"\n",
user_name, user_email);
}
else
{
g_string_append_printf (output_buffer,
"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 (line_prefix != NULL)
g_string_append (output_buffer, line_prefix);
if (sig_expired)
{
g_string_append_printf (output_buffer,
"Signature expired %s\n",
formatted_date_time);
}
else
{
g_string_append_printf (output_buffer,
"Signature expires %s\n",
formatted_date_time);
}
}
}
void
_ostree_gpg_error_to_gio_error (gpgme_error_t gpg_error,
GError **error)

View File

@ -100,4 +100,23 @@ GVariant * ostree_gpg_verify_result_get (OstreeGpgVerifyResult *result,
GVariant * ostree_gpg_verify_result_get_all (OstreeGpgVerifyResult *result,
guint signature_index);
/**
* OstreeGpgSignatureFormatFlags:
* @OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT:
* Use the default output format
*
* Formatting flags for ostree_gpg_verify_result_describe(). Currently
* there's only one possible output format, but this enumeration allows
* for future variations.
**/
typedef enum {
OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT = 0
} OstreeGpgSignatureFormatFlags;
void ostree_gpg_verify_result_describe (OstreeGpgVerifyResult *result,
guint signature_index,
GString *output_buffer,
const gchar *line_prefix,
OstreeGpgSignatureFormatFlags flags);
G_END_DECLS

View File

@ -148,87 +148,6 @@ 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_autofree char *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", &timestamp);
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,
@ -266,16 +185,23 @@ print_object (OstreeRepo *repo,
}
else
{
GString *buffer;
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");
buffer = g_string_sized_new (256);
for (ii = 0; ii < n_sigs; ii++)
{
g_print ("\n");
print_signature (result, ii);
g_string_append_c (buffer, '\n');
ostree_gpg_verify_result_describe (result, ii, buffer, " ",
OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT);
}
g_print ("%s", buffer->str);
g_string_free (buffer, TRUE);
}
}