From 902898f29c99927b9a88df1542872adfcd343947 Mon Sep 17 00:00:00 2001 From: wangxp006 Date: Mon, 7 Jun 2021 22:12:46 +0800 Subject: [PATCH] CVE-2021-3445 --- libdnf/dnf-keyring.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/libdnf/dnf-keyring.cpp b/libdnf/dnf-keyring.cpp index 6797b11..c81df12 100644 --- a/libdnf/dnf-keyring.cpp +++ b/libdnf/dnf-keyring.cpp @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include "catch-error.hpp" #include "dnf-types.h" @@ -211,6 +213,26 @@ dnf_keyring_add_public_keys(rpmKeyring keyring, GError **error) try return TRUE; } CATCH_TO_GERROR(FALSE) +static int +rpmcliverifysignatures_log_handler_cb(rpmlogRec rec, rpmlogCallbackData data) +{ + GString **string =(GString **) data; + + /* create string if required */ + if (*string == NULL) + *string = g_string_new(""); + + /* if text already exists, join them */ + if ((*string)->len > 0) + g_string_append(*string, ": "); + g_string_append(*string, rpmlogRecMessage(rec)); + + /* remove the trailing /n which rpm does */ + if ((*string)->len > 0) + g_string_truncate(*string,(*string)->len - 1); + return 0; +} + /** * dnf_keyring_check_untrusted_file: */ @@ -227,6 +249,10 @@ dnf_keyring_check_untrusted_file(rpmKeyring keyring, rpmtd td = NULL; rpmts ts = NULL; + char *path = g_strdup(filename); + char *path_array[2] = {path, NULL}; + g_autoptr(GString) rpm_error = NULL; + /* open the file for reading */ fd = Fopen(filename, "r.fdio"); if (fd == NULL) { @@ -247,9 +273,27 @@ dnf_keyring_check_untrusted_file(rpmKeyring keyring, goto out; } - /* we don't want to abort on missing keys */ ts = rpmtsCreate(); - rpmtsSetVSFlags(ts, _RPMVSF_NOSIGNATURES); + + if (rpmtsSetKeyring(ts, keyring) < 0) { + g_set_error_literal(error, DNF_ERROR, DNF_ERROR_INTERNAL_ERROR, "failed to set keyring"); + goto out; + } + rpmtsSetVfyLevel(ts, RPMSIG_SIGNATURE_TYPE); + rpmlogSetCallback(rpmcliverifysignatures_log_handler_cb, &rpm_error); + + // rpm doesn't provide any better API call than rpmcliVerifySignatures (which is for CLI): + // - use path_array as input argument + // - gather logs via callback because we don't want to print anything if check is successful + if (rpmcliVerifySignatures(ts, (char * const*) path_array)) { + g_set_error(error, + DNF_ERROR, + DNF_ERROR_GPG_SIGNATURE_INVALID, + "%s could not be verified.\n%s", + filename, + (rpm_error ? rpm_error->str : "UNKNOWN ERROR")); + goto out; + } /* read in the file */ rc = rpmReadPackageFile(ts, fd, filename, &hdr); @@ -313,6 +357,10 @@ dnf_keyring_check_untrusted_file(rpmKeyring keyring, g_debug("%s has been verified as trusted", filename); ret = TRUE; out: + rpmlogSetCallback(NULL, NULL); + + if (path != NULL) + g_free(path); if (dig != NULL) pgpFreeDig(dig); if (td != NULL) { -- 1.8.3.1