From 604321c5d40a9b3d26cee167e79fc6408e09e482 Mon Sep 17 00:00:00 2001 From: Hubert Tarasiuk Date: Thu, 2 Jul 2015 00:16:12 +0200 Subject: [PATCH 10/12] Support at most one file signature. Adapt comments to libmetalink 0.13. * src/metalink.c (retrieve_from_metalink): Add comment about new libmetalink version. Do not iterate over signatures - support just one. --- src/metalink.c | 209 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 105 insertions(+), 104 deletions(-) diff --git a/src/metalink.c b/src/metalink.c index f2c4175..b751864 100644 --- a/src/metalink.c +++ b/src/metalink.c @@ -224,15 +224,21 @@ retrieve_from_metalink (const metalink_t* metalink) sig_status = 0; /* Not verified. */ #ifdef HAVE_GPGME - /* Check the crypto signature. */ + /* Check the crypto signature. + + Note that the signtures from Metalink in XML will not be + parsed when using libmetalink version older than 0.1.3. + Metalink-over-HTTP is not affected by this problem. */ if (mfile->signature) { - metalink_signature_t *msig; + metalink_signature_t *msig = mfile->signature; gpgme_error_t gpgerr; gpgme_ctx_t gpgctx; gpgme_data_t gpgsigdata, gpgdata; gpgme_verify_result_t gpgres; - int fd; + gpgme_signature_t gpgsig; + gpgme_protocol_t gpgprot = GPGME_PROTOCOL_UNKNOWN; + int fd = -1; /* Initialize the library - as name suggests. */ gpgme_check_version (NULL); @@ -254,7 +260,7 @@ retrieve_from_metalink (const metalink_t* metalink) logprintf (LOG_NOTQUIET, "GPGME data_new_from_fd: %s\n", gpgme_strerror (gpgerr)); - goto gpg_cleanup_fd; + goto gpg_skip_verification; } /* Prepare new GPGME context. */ @@ -264,127 +270,122 @@ retrieve_from_metalink (const metalink_t* metalink) logprintf (LOG_NOTQUIET, "GPGME new: %s\n", gpgme_strerror (gpgerr)); - goto gpg_cleanup_data; + gpgme_data_release (gpgdata); + goto gpg_skip_verification; } - /* Note that this will only work for Metalink-over-HTTP - requests (that we parse manually) due to a bug in - Libmetalink. Another problem with Libmetalink is that - it supports at most one signature per file. The below - line should be modified after Libmetalink resolves these - issues. */ - for (msig = mfile->signature; msig == mfile->signature; msig++) + DEBUGP (("Veryfying signature %s:\n%s\n", + quote (msig->mediatype), + msig->signature)); + + /* Check signature type. */ + if (!strcmp (msig->mediatype, "application/pgp-signature")) + gpgprot = GPGME_PROTOCOL_OpenPGP; + else /* Unsupported signature type. */ { - gpgme_signature_t gpgsig; - gpgme_protocol_t gpgprot = GPGME_PROTOCOL_UNKNOWN; + gpgme_release (gpgctx); + gpgme_data_release (gpgdata); + goto gpg_skip_verification; + } - DEBUGP (("Veryfying signature %s:\n%s\n", - quote (msig->mediatype), - msig->signature)); + gpgerr = gpgme_set_protocol (gpgctx, gpgprot); + if (gpgerr != GPG_ERR_NO_ERROR) + { + logprintf (LOG_NOTQUIET, + "GPGME set_protocol: %s\n", + gpgme_strerror (gpgerr)); + gpgme_release (gpgctx); + gpgme_data_release (gpgdata); + goto gpg_skip_verification; + } - /* Check signature type. */ - if (!strcmp (msig->mediatype, "application/pgp-signature")) - gpgprot = GPGME_PROTOCOL_OpenPGP; - else /* Unsupported signature type. */ - continue; + /* Load the signature. */ + gpgerr = gpgme_data_new_from_mem (&gpgsigdata, + msig->signature, + strlen (msig->signature), + 0); + if (gpgerr != GPG_ERR_NO_ERROR) + { + logprintf (LOG_NOTQUIET, + _("GPGME data_new_from_mem: %s\n"), + gpgme_strerror (gpgerr)); + gpgme_release (gpgctx); + gpgme_data_release (gpgdata); + goto gpg_skip_verification; + } - gpgerr = gpgme_set_protocol (gpgctx, gpgprot); - if (gpgerr != GPG_ERR_NO_ERROR) - { - logprintf (LOG_NOTQUIET, - "GPGME set_protocol: %s\n", - gpgme_strerror (gpgerr)); - continue; - } + /* Verify the signature. */ + gpgerr = gpgme_op_verify (gpgctx, gpgsigdata, gpgdata, NULL); + if (gpgerr != GPG_ERR_NO_ERROR) + { + logprintf (LOG_NOTQUIET, + _("GPGME op_verify: %s\n"), + gpgme_strerror (gpgerr)); + gpgme_data_release (gpgsigdata); + gpgme_release (gpgctx); + gpgme_data_release (gpgdata); + goto gpg_skip_verification; + } - /* Load the signature. */ - gpgerr = gpgme_data_new_from_mem (&gpgsigdata, - msig->signature, - strlen (msig->signature), - 0); - if (gpgerr != GPG_ERR_NO_ERROR) - { - logprintf (LOG_NOTQUIET, - _("GPGME data_new_from_mem: %s\n"), - gpgme_strerror (gpgerr)); - continue; - } + /* Check the results. */ + gpgres = gpgme_op_verify_result (gpgctx); + if (!gpgres) + { + logputs (LOG_NOTQUIET, + _("GPGME op_verify_result: NULL\n")); + gpgme_data_release (gpgsigdata); + gpgme_release (gpgctx); + gpgme_data_release (gpgdata); + goto gpg_skip_verification; + } - /* Verify the signature. */ - gpgerr = gpgme_op_verify (gpgctx, gpgsigdata, gpgdata, NULL); - if (gpgerr != GPG_ERR_NO_ERROR) + /* The list is null-terminated. */ + for (gpgsig = gpgres->signatures; gpgsig; gpgsig = gpgsig->next) + { + DEBUGP (("Checking signature 0x%p\n", + (void *) gpgsig)); + DEBUGP (("Summary=0x%x Status=0x%x\n", + gpgsig->summary, gpgsig->status & 0xFFFF)); + + if (gpgsig->summary + & (GPGME_SIGSUM_VALID | GPGME_SIGSUM_GREEN)) { - logprintf (LOG_NOTQUIET, - _("GPGME op_verify: %s\n"), - gpgme_strerror (gpgerr)); - gpgme_data_release (gpgsigdata); - continue; + logputs (LOG_VERBOSE, + _("Signature validation suceeded.\n")); + sig_status = 1; + break; } - /* Check the results. */ - gpgres = gpgme_op_verify_result (gpgctx); - if (!gpgres) + if (gpgsig->summary & GPGME_SIGSUM_RED) { logputs (LOG_NOTQUIET, - _("GPGME op_verify_result: NULL\n")); - gpgme_data_release (gpgsigdata); - continue; + _("Invalid signature. Rejecting resource.\n")); + sig_status = -1; + break; } - /* The list is null-terminated. */ - for (gpgsig = gpgres->signatures; gpgsig; gpgsig = gpgsig->next) + if (gpgsig->summary == 0 + && (gpgsig->status & 0xFFFF) == GPG_ERR_NO_ERROR) { - DEBUGP (("Checking signature 0x%p\n", - (void *) gpgsig)); - DEBUGP (("Summary=0x%x Status=0x%x\n", - gpgsig->summary, gpgsig->status & 0xFFFF)); - - if (gpgsig->summary - & (GPGME_SIGSUM_VALID | GPGME_SIGSUM_GREEN)) - { - logputs (LOG_VERBOSE, - _("Signature validation suceeded.\n")); - sig_status = 1; - break; - } - - if (gpgsig->summary & GPGME_SIGSUM_RED) - { - logputs (LOG_NOTQUIET, - _("Invalid signature. Rejecting resource.\n")); - sig_status = -1; - break; - } - - if (gpgsig->summary == 0 - && (gpgsig->status & 0xFFFF) == GPG_ERR_NO_ERROR) - { - logputs (LOG_VERBOSE, - _("Data matches signature, but signature " - "is not trusted.\n")); - } - - if ((gpgsig->status & 0xFFFF) != GPG_ERR_NO_ERROR) - { - logprintf (LOG_NOTQUIET, - "GPGME: %s\n", - gpgme_strerror (gpgsig->status & 0xFFFF)); - } + logputs (LOG_VERBOSE, + _("Data matches signature, but signature " + "is not trusted.\n")); } - gpgme_data_release (gpgsigdata); - - if (sig_status != 0) - break; - } /* Iterate over signatures. */ - + if ((gpgsig->status & 0xFFFF) != GPG_ERR_NO_ERROR) + { + logprintf (LOG_NOTQUIET, + "GPGME: %s\n", + gpgme_strerror (gpgsig->status & 0xFFFF)); + } + } + gpgme_data_release (gpgsigdata); gpgme_release (gpgctx); -gpg_cleanup_data: gpgme_data_release (gpgdata); -gpg_cleanup_fd: - close (fd); - } /* endif (mfile->signature) */ gpg_skip_verification: + if (fd != -1) + close (fd); + } /* endif (mfile->signature) */ #endif /* Stop if file was downloaded with success. */ if (sig_status >= 0) -- 2.4.3