diff --git a/src/libostree/ostree-gpg-verify-result.c b/src/libostree/ostree-gpg-verify-result.c index 63c3394a..67270c82 100644 --- a/src/libostree/ostree-gpg-verify-result.c +++ b/src/libostree/ostree-gpg-verify-result.c @@ -769,8 +769,58 @@ ostree_gpg_verify_result_require_valid_signature (OstreeGpgVerifyResult *result, if (ostree_gpg_verify_result_count_valid (result) == 0) { - g_set_error (error, OSTREE_GPG_ERROR, OSTREE_GPG_ERROR_MISSING_KEY, - "GPG signatures found, but none are in trusted keyring"); + /* + * Join the description of each failed signature for the error message. + * Only one error code can be returned, so if there was more than one + * signature, use the error of the last one under the assumption that + * it's the most recent and hopefully most likely to be made with a + * valid key. + */ + gint code = OSTREE_GPG_ERROR_NO_SIGNATURE; + g_autoptr(GString) buffer = g_string_sized_new (256); + guint nsigs = ostree_gpg_verify_result_count_all (result); + + if (nsigs == 0) + /* In case an empty result was passed in */ + g_string_append (buffer, "No GPG signatures found"); + else + { + for (int i = nsigs - 1; i >= 0; i--) + { + g_autoptr(GVariant) info = ostree_gpg_verify_result_get_all (result, i); + ostree_gpg_verify_result_describe_variant (info, buffer, "", + OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT); + + if (i == nsigs - 1) + { + gboolean key_missing, key_revoked, key_expired, sig_expired; + g_variant_get_child (info, OSTREE_GPG_SIGNATURE_ATTR_KEY_MISSING, + "b", &key_missing); + g_variant_get_child (info, OSTREE_GPG_SIGNATURE_ATTR_KEY_REVOKED, + "b", &key_revoked); + g_variant_get_child (info, OSTREE_GPG_SIGNATURE_ATTR_KEY_EXPIRED, + "b", &key_expired); + g_variant_get_child (info, OSTREE_GPG_SIGNATURE_ATTR_SIG_EXPIRED, + "b", &sig_expired); + + if (key_missing) + code = OSTREE_GPG_ERROR_MISSING_KEY; + else if (key_revoked) + code = OSTREE_GPG_ERROR_REVOKED_KEY; + else if (key_expired) + code = OSTREE_GPG_ERROR_EXPIRED_KEY; + else if (sig_expired) + code = OSTREE_GPG_ERROR_EXPIRED_SIGNATURE; + else + /* Assume any other issue is a bad signature */ + code = OSTREE_GPG_ERROR_INVALID_SIGNATURE; + } + } + } + + /* Strip any trailing newlines */ + g_strchomp (buffer->str); + g_set_error_literal (error, OSTREE_GPG_ERROR, code, buffer->str); return FALSE; } diff --git a/src/libostree/ostree-gpg-verify-result.h b/src/libostree/ostree-gpg-verify-result.h index 7c71ecdc..f71ab981 100644 --- a/src/libostree/ostree-gpg-verify-result.h +++ b/src/libostree/ostree-gpg-verify-result.h @@ -159,6 +159,11 @@ gboolean ostree_gpg_verify_result_require_valid_signature (OstreeGpgVerifyResult * @OSTREE_GPG_ERROR_NO_SIGNATURE: A signature was expected, but not found. * @OSTREE_GPG_ERROR_INVALID_SIGNATURE: A signature was malformed. * @OSTREE_GPG_ERROR_MISSING_KEY: A signature was found, but was created with a key not in the configured keyrings. + * @OSTREE_GPG_ERROR_EXPIRED_SIGNATURE: A signature was expired. Since: 2019.7. + * @OSTREE_GPG_ERROR_EXPIRED_KEY: A signature was found, but the key used to + * sign it has expired. Since: 2019.7. + * @OSTREE_GPG_ERROR_REVOKED_KEY: A signature was found, but the key used to + * sign it has been revoked. Since: 2019.7. * * Errors returned by signature creation and verification operations in OSTree. * These may be returned by any API which creates or verifies signatures. @@ -169,6 +174,9 @@ typedef enum { OSTREE_GPG_ERROR_NO_SIGNATURE = 0, OSTREE_GPG_ERROR_INVALID_SIGNATURE, OSTREE_GPG_ERROR_MISSING_KEY, + OSTREE_GPG_ERROR_EXPIRED_SIGNATURE, + OSTREE_GPG_ERROR_EXPIRED_KEY, + OSTREE_GPG_ERROR_REVOKED_KEY, } OstreeGpgError; /** diff --git a/tests/test-pull-summary-sigs.sh b/tests/test-pull-summary-sigs.sh index 821ae953..401e88c9 100755 --- a/tests/test-pull-summary-sigs.sh +++ b/tests/test-pull-summary-sigs.sh @@ -189,7 +189,7 @@ cp ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig{.2,} if ${OSTREE} --repo=repo pull origin main 2>err.txt; then assert_not_reached "Successful pull with old summary" fi -assert_file_has_content err.txt "none are in trusted keyring" +assert_file_has_content err.txt "BAD signature" assert_has_file repo/tmp/cache/summaries/origin assert_has_file repo/tmp/cache/summaries/origin.sig cmp repo/tmp/cache/summaries/origin ${test_tmpdir}/ostree-srv/gnomerepo/summary.1 >&2 diff --git a/tests/test-remote-gpg-import.sh b/tests/test-remote-gpg-import.sh index 4d73fa11..b8673852 100755 --- a/tests/test-remote-gpg-import.sh +++ b/tests/test-remote-gpg-import.sh @@ -163,7 +163,7 @@ ${OSTREE} remote add --set=gpgkeypath=${test_tmpdir}/gpghome/key1.asc,${test_tmp if ${OSTREE} pull R8:main 2>err.txt; then assert_not_reached "Unexpectedly succeeded at pulling with different key" fi -assert_file_has_content err.txt "GPG signatures found, but none are in trusted keyring" +assert_file_has_content err.txt "public key not found" # Test gpgkeypath success with directory containing a valid key ${OSTREE} remote add --set=gpgkeypath=${test_tmpdir}/gpghome/ R9 $(cat httpd-address)/ostree/gnomerepo @@ -243,7 +243,7 @@ ${OSTREE} remote add --set=gpgkeypath=${test_tmpdir}/gpghome/key2.asc R6 $(cat h if ${OSTREE} pull R6:main 2>err.txt; then assert_not_reached "Unexpectedly succeeded at pulling with different key" fi -assert_file_has_content err.txt "GPG signatures found, but none are in trusted keyring" +assert_file_has_content err.txt "public key not found" echo "ok" @@ -269,7 +269,7 @@ newrev=$(${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo rev-par if ${OSTREE} pull --require-static-deltas R1:main 2>err.txt; then assert_not_reached "Unexpectedly succeeded at pulling commit signed with untrusted key" fi -assert_file_has_content err.txt "GPG signatures found, but none are in trusted keyring" +assert_file_has_content err.txt "public key not found" echo "ok gpg untrusted signed commit for delta upgrades"