lib/gpg: Show information for expired keys

Introduce a new signature attribute for the key expiration timestamp and
display it when the key has a non-zero expiration time. Without this,
the error shown is `BAD signature`, which isn't correct.

Closes: #1872
Approved by: cgwalters
This commit is contained in:
Dan Nicholson 2019-06-10 12:05:21 -05:00 committed by Atomic Bot
parent 901c2f5e5f
commit d714e622b8
3 changed files with 84 additions and 15 deletions

View File

@ -65,7 +65,9 @@ static OstreeGpgSignatureAttr all_signature_attrs[] = {
OSTREE_GPG_SIGNATURE_ATTR_HASH_ALGO_NAME,
OSTREE_GPG_SIGNATURE_ATTR_USER_NAME,
OSTREE_GPG_SIGNATURE_ATTR_USER_EMAIL,
OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY
OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY,
OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP,
OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY,
};
static void ostree_gpg_verify_result_initable_iface_init (GInitableIface *iface);
@ -331,7 +333,9 @@ ostree_gpg_verify_result_get (OstreeGpgVerifyResult *result,
{
if (attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_USER_NAME ||
attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_USER_EMAIL ||
attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY)
attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY ||
attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP ||
attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY)
{
(void) gpgme_get_key (result->context, signature->fpr, &key, 0);
break;
@ -345,6 +349,7 @@ ostree_gpg_verify_result_get (OstreeGpgVerifyResult *result,
GVariant *child;
gboolean v_boolean;
const char *v_string = NULL;
gint64 v_int64;
switch (attrs[ii])
{
@ -423,6 +428,29 @@ ostree_gpg_verify_result_get (OstreeGpgVerifyResult *result,
child = g_variant_new_string (v_string);
break;
case OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP:
v_int64 = 0;
if (key != NULL)
{
gpgme_subkey_t subkey = key->subkeys;
while (subkey != NULL && (g_strcmp0 (subkey->fpr, signature->fpr) != 0))
subkey = subkey->next;
if (subkey != NULL)
v_int64 = subkey->expires;
}
child = g_variant_new_int64 (v_int64);
break;
case OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY:
if (key != NULL && key->subkeys != NULL)
v_int64 = key->subkeys->expires;
else
v_int64 = 0;
child = g_variant_new_int64 (v_int64);
break;
default:
g_critical ("Invalid signature attribute (%d)", attrs[ii]);
g_variant_builder_clear (&builder);
@ -581,6 +609,8 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant,
g_autofree char *formatted_date_time = NULL;
gint64 timestamp;
gint64 exp_timestamp;
gint64 key_exp_timestamp;
gint64 key_exp_timestamp_primary;
const char *type_string;
const char *fingerprint;
const char *fingerprint_primary;
@ -590,6 +620,7 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant,
const char *key_id;
gboolean valid;
gboolean sig_expired;
gboolean key_expired;
gboolean key_missing;
gsize len;
@ -599,7 +630,7 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant,
/* Verify the variant's type string. This code is
* not prepared to handle just any random GVariant. */
type_string = g_variant_get_type_string (variant);
g_return_if_fail (strcmp (type_string, "(bbbbbsxxsssss)") == 0);
g_return_if_fail (strcmp (type_string, "(bbbbbsxxsssssxx)") == 0);
/* The default format roughly mimics the verify output generated by
* check_sig_and_print() in gnupg/g10/mainproc.c, though obviously
@ -609,6 +640,8 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant,
"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_EXPIRED,
"b", &key_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,
@ -625,6 +658,10 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant,
"&s", &user_name);
g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_USER_EMAIL,
"&s", &user_email);
g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP,
"x", &key_exp_timestamp);
g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY,
"x", &key_exp_timestamp_primary);
len = strlen (fingerprint);
key_id = (len > 16) ? fingerprint + len - 16 : fingerprint;
@ -697,6 +734,12 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant,
if (exp_timestamp > 0)
append_expire_info (output_buffer, line_prefix, "Signature", exp_timestamp,
sig_expired);
if (key_exp_timestamp > 0)
append_expire_info (output_buffer, line_prefix, "Key", key_exp_timestamp,
key_expired);
if (key_exp_timestamp_primary > 0 && (g_strcmp0 (fingerprint, fingerprint_primary) != 0))
append_expire_info (output_buffer, line_prefix, "Primary key",
key_exp_timestamp_primary, key_expired);
}
/**

View File

@ -70,6 +70,14 @@ typedef struct OstreeGpgVerifyResult OstreeGpgVerifyResult;
* (will be the same as OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT if the
* the signature is already from the primary key rather than a subkey,
* and will be the empty string if the key is missing.)
* @OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP:
* [#G_VARIANT_TYPE_INT64] Key expiration Unix timestamp (0 if no
* expiration or if the key is missing)
* @OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY:
* [#G_VARIANT_TYPE_INT64] Key expiration Unix timestamp of the signing key's
* primary key (will be the same as OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP
* if the signing key is the primary key and 0 if no expiration or if the key
* is missing)
*
* Signature attributes available from an #OstreeGpgVerifyResult.
* The attribute's #GVariantType is shown in brackets.
@ -88,6 +96,8 @@ typedef enum {
OSTREE_GPG_SIGNATURE_ATTR_USER_NAME,
OSTREE_GPG_SIGNATURE_ATTR_USER_EMAIL,
OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY,
OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP,
OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY,
} OstreeGpgSignatureAttr;
_OSTREE_PUBLIC

View File

@ -45,7 +45,8 @@ static OstreeGpgSignatureAttr some_attributes[] = {
OSTREE_GPG_SIGNATURE_ATTR_SIG_EXPIRED,
OSTREE_GPG_SIGNATURE_ATTR_KEY_EXPIRED,
OSTREE_GPG_SIGNATURE_ATTR_KEY_REVOKED,
OSTREE_GPG_SIGNATURE_ATTR_KEY_MISSING
OSTREE_GPG_SIGNATURE_ATTR_KEY_MISSING,
OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP,
};
static void
@ -174,7 +175,7 @@ test_attribute_basics (TestFixture *fixture,
tuple = ostree_gpg_verify_result_get_all (fixture->result, ii);
type_string = g_variant_get_type_string (tuple);
g_assert_cmpstr (type_string, ==, "(bbbbbsxxsssss)");
g_assert_cmpstr (type_string, ==, "(bbbbbsxxsssssxx)");
/* Check attributes which should be common to all signatures. */
@ -221,24 +222,27 @@ test_valid_signature (TestFixture *fixture,
gboolean key_expired;
gboolean key_revoked;
gboolean key_missing;
gint64 key_exp_timestamp;
tuple = ostree_gpg_verify_result_get (fixture->result,
signature_index,
some_attributes,
G_N_ELEMENTS (some_attributes));
g_variant_get (tuple, "(bbbbb)",
g_variant_get (tuple, "(bbbbbx)",
&valid,
&sig_expired,
&key_expired,
&key_revoked,
&key_missing);
&key_missing,
&key_exp_timestamp);
g_assert_true (valid);
g_assert_false (sig_expired);
g_assert_false (key_expired);
g_assert_false (key_revoked);
g_assert_false (key_missing);
g_assert_cmpint (key_exp_timestamp, ==, 0);
}
static void
@ -252,24 +256,27 @@ test_expired_key (TestFixture *fixture,
gboolean key_expired;
gboolean key_revoked;
gboolean key_missing;
gint64 key_exp_timestamp;
tuple = ostree_gpg_verify_result_get (fixture->result,
signature_index,
some_attributes,
G_N_ELEMENTS (some_attributes));
g_variant_get (tuple, "(bbbbb)",
g_variant_get (tuple, "(bbbbbx)",
&valid,
&sig_expired,
&key_expired,
&key_revoked,
&key_missing);
&key_missing,
&key_exp_timestamp);
g_assert_false (valid);
g_assert_false (sig_expired);
g_assert_true (key_expired);
g_assert_false (key_revoked);
g_assert_false (key_missing);
g_assert_cmpint (key_exp_timestamp, ==, 1426782201);
}
static void
@ -283,24 +290,27 @@ test_revoked_key (TestFixture *fixture,
gboolean key_expired;
gboolean key_revoked;
gboolean key_missing;
gint64 key_exp_timestamp;
tuple = ostree_gpg_verify_result_get (fixture->result,
signature_index,
some_attributes,
G_N_ELEMENTS (some_attributes));
g_variant_get (tuple, "(bbbbb)",
g_variant_get (tuple, "(bbbbbx)",
&valid,
&sig_expired,
&key_expired,
&key_revoked,
&key_missing);
&key_missing,
&key_exp_timestamp);
g_assert_false (valid);
g_assert_false (sig_expired);
g_assert_false (key_expired);
g_assert_true (key_revoked);
g_assert_false (key_missing);
g_assert_cmpint (key_exp_timestamp, ==, 0);
}
static void
@ -314,24 +324,27 @@ test_missing_key (TestFixture *fixture,
gboolean key_expired;
gboolean key_revoked;
gboolean key_missing;
gint64 key_exp_timestamp;
tuple = ostree_gpg_verify_result_get (fixture->result,
signature_index,
some_attributes,
G_N_ELEMENTS (some_attributes));
g_variant_get (tuple, "(bbbbb)",
g_variant_get (tuple, "(bbbbbx)",
&valid,
&sig_expired,
&key_expired,
&key_revoked,
&key_missing);
&key_missing,
&key_exp_timestamp);
g_assert_false (valid);
g_assert_false (sig_expired);
g_assert_false (key_expired);
g_assert_false (key_revoked);
g_assert_true (key_missing);
g_assert_cmpint (key_exp_timestamp, ==, 0);
}
static void
@ -345,24 +358,27 @@ test_expired_signature (TestFixture *fixture,
gboolean key_expired;
gboolean key_revoked;
gboolean key_missing;
gint64 key_exp_timestamp;
tuple = ostree_gpg_verify_result_get (fixture->result,
signature_index,
some_attributes,
G_N_ELEMENTS (some_attributes));
g_variant_get (tuple, "(bbbbb)",
g_variant_get (tuple, "(bbbbbx)",
&valid,
&sig_expired,
&key_expired,
&key_revoked,
&key_missing);
&key_missing,
&key_exp_timestamp);
g_assert_true (valid);
g_assert_true (sig_expired);
g_assert_false (key_expired);
g_assert_false (key_revoked);
g_assert_false (key_missing);
g_assert_cmpint (key_exp_timestamp, ==, 0);
}
int