diff --git a/0001-Return-dedicated-error-code-for-all-subkeys-expired-.patch b/0001-Return-dedicated-error-code-for-all-subkeys-expired-.patch new file mode 100644 index 0000000..8d183ba --- /dev/null +++ b/0001-Return-dedicated-error-code-for-all-subkeys-expired-.patch @@ -0,0 +1,335 @@ +From e09f681427d700282988885a80dc2bc8d4573718 Mon Sep 17 00:00:00 2001 +From: Werner Koch +Date: Tue, 17 May 2016 20:21:01 +0200 +Subject: [PATCH] Return dedicated error code for all subkeys expired or + revoked. + +* src/gpgme.h.in (GPGME_STATUS_KEY_CONSIDERED): New. +(GPGME_SIGSUM_TOFU_CONFLICT): New. +* src/status-table.c (KEY_CONSIDERED): New. +* src/op-support.c (_gpgme_parse_inv_recp): Add argc KC_FPR and +KC_FLAGS. Use calloc. Detect all expired or revoked subkeys. +(_gpgme_parse_key_considered): New. +* src/sign.c (op_data_t): Add fields KC_FPR and KC_FLAGS. +(release_op_data): Free KC_FPR. +(_gpgme_sign_status_handler): Handle STATUS_KEY_CONSIDERED. +* src/encrypt.c (op_data_t): Add fields KC_FPR and KC_FLAGS. +(release_op_data): Free KC_FPR. +(_gpgme_encrypt_status_handler): Handle STATUS_KEY_CONSIDERED. + +Signed-off-by: Werner Koch +(cherry picked from commit 315fb73d4a774e2c699ac1804f5377559b4d0027) +--- + src/encrypt.c | 26 ++++++++++++++++++++-- + src/gpgme.h.in | 10 +++++++-- + src/op-support.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++------- + src/ops.h | 8 ++++++- + src/sign.c | 25 ++++++++++++++++++++- + src/status-table.c | 1 + + 6 files changed, 121 insertions(+), 14 deletions(-) + +diff --git a/src/encrypt.c b/src/encrypt.c +index 9f5134d..8672cd3 100644 +--- a/src/encrypt.c ++++ b/src/encrypt.c +@@ -39,6 +39,12 @@ typedef struct + /* The error code from a FAILURE status line or 0. */ + gpg_error_t failure_code; + ++ /* The fingerprint from the last KEY_CONSIDERED status line. */ ++ char *kc_fpr; ++ ++ /* The flags from the last KEY_CONSIDERED status line. */ ++ unsigned int kc_flags; ++ + /* A pointer to the next pointer of the last invalid recipient in + the list. This makes appending new invalid recipients painless + while preserving the order. */ +@@ -60,6 +66,8 @@ release_op_data (void *hook) + free (invalid_recipient); + invalid_recipient = next; + } ++ ++ free (opd->kc_fpr); + } + + +@@ -128,12 +136,26 @@ _gpgme_encrypt_status_handler (void *priv, gpgme_status_code_t code, + return opd->failure_code; + break; + ++ case GPGME_STATUS_KEY_CONSIDERED: ++ /* This is emitted during gpg's key lookup to give information ++ * about the lookup results. We store the last one so it can be ++ * used in connection with INV_RECP. */ ++ free (opd->kc_fpr); ++ opd->kc_fpr = NULL; ++ err = _gpgme_parse_key_considered (args, &opd->kc_fpr, &opd->kc_flags); ++ if (err) ++ return err; ++ break; ++ + case GPGME_STATUS_INV_RECP: +- err = _gpgme_parse_inv_recp (args, opd->lastp); ++ err = _gpgme_parse_inv_recp (args, 0, opd->kc_fpr, opd->kc_flags, ++ opd->lastp); + if (err) +- return err; ++ return err; + + opd->lastp = &(*opd->lastp)->next; ++ free (opd->kc_fpr); ++ opd->kc_fpr = NULL; + break; + + case GPGME_STATUS_NO_RECP: +diff --git a/src/gpgme.h.in b/src/gpgme.h.in +index 6cea2c7..cad95f3 100644 +--- a/src/gpgme.h.in ++++ b/src/gpgme.h.in +@@ -531,7 +531,8 @@ typedef enum + GPGME_STATUS_BEGIN_SIGNING = 90, + GPGME_STATUS_KEY_NOT_CREATED = 91, + GPGME_STATUS_INQUIRE_MAXLEN = 92, +- GPGME_STATUS_FAILURE = 93 ++ GPGME_STATUS_FAILURE = 93, ++ GPGME_STATUS_KEY_CONSIDERED = 94 + } + gpgme_status_code_t; + +@@ -860,7 +861,12 @@ typedef struct _gpgme_key *gpgme_key_t; + struct _gpgme_invalid_key + { + struct _gpgme_invalid_key *next; ++ ++ /* The string used to request the key. Despite the name this may ++ * not be a fingerprint. */ + char *fpr; ++ ++ /* The error code. */ + gpgme_error_t reason; + }; + typedef struct _gpgme_invalid_key *gpgme_invalid_key_t; +@@ -1539,7 +1545,7 @@ struct _gpgme_signature + /* Signature creation time. */ + unsigned long timestamp; + +- /* Signature exipration time or 0. */ ++ /* Signature expiration time or 0. */ + unsigned long exp_timestamp; + + /* Key should not have been used for signing. */ +diff --git a/src/op-support.c b/src/op-support.c +index 02940ef..d51d643 100644 +--- a/src/op-support.c ++++ b/src/op-support.c +@@ -33,6 +33,11 @@ + #include "util.h" + #include "debug.h" + ++#if GPG_ERROR_VERSION_NUMBER < 0x011700 /* 1.23 */ ++# define GPG_ERR_SUBKEYS_EXP_REV 217 ++#endif ++ ++ + + gpgme_error_t + _gpgme_op_data_lookup (gpgme_ctx_t ctx, ctx_op_data_id_t type, void **hook, +@@ -190,16 +195,19 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type) + } + + +-/* Parse the INV_RECP or INV-SNDR status line in ARGS and return the +- result in KEY. */ ++/* Parse the INV_RECP or INV_SNDR status line in ARGS and return the ++ result in KEY. If KC_FPR (from the KEY_CONSIDERED status line) is ++ not NULL take the KC_FLAGS in account. */ + gpgme_error_t +-_gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key) ++_gpgme_parse_inv_recp (char *args, int for_signing, ++ const char *kc_fpr, unsigned int kc_flags, ++ gpgme_invalid_key_t *key) + { + gpgme_invalid_key_t inv_key; + char *tail; + long int reason; + +- inv_key = malloc (sizeof (*inv_key)); ++ inv_key = calloc (1, sizeof (*inv_key)); + if (!inv_key) + return gpg_error_from_syserror (); + inv_key->next = NULL; +@@ -214,9 +222,11 @@ _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key) + + switch (reason) + { +- default: + case 0: +- inv_key->reason = gpg_error (GPG_ERR_GENERAL); ++ if (kc_fpr && (kc_flags & 2)) ++ inv_key->reason = gpg_error (GPG_ERR_SUBKEYS_EXP_OR_REV); ++ else ++ inv_key->reason = gpg_error (GPG_ERR_GENERAL); + break; + + case 1: +@@ -274,6 +284,10 @@ _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key) + case 14: + inv_key->reason = gpg_error (GPG_ERR_INV_USER_ID); + break; ++ ++ default: ++ inv_key->reason = gpg_error (GPG_ERR_GENERAL); ++ break; + } + + while (*tail && *tail == ' ') +@@ -287,14 +301,49 @@ _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key) + return gpg_error_from_syserror (); + } + } +- else +- inv_key->fpr = NULL; + + *key = inv_key; + return 0; + } + + ++ ++/* Parse a KEY_CONSIDERED status line in ARGS and store the ++ * fingerprint and the flags at R_FPR and R_FLAGS. The caller must ++ * free the value at R_FPR on success. */ ++gpgme_error_t ++_gpgme_parse_key_considered (const char *args, ++ char **r_fpr, unsigned int *r_flags) ++{ ++ char *pend; ++ size_t n; ++ ++ *r_fpr = NULL; ++ ++ pend = strchr (args, ' '); ++ if (!pend || pend == args) ++ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Bogus status line. */ ++ n = pend - args; ++ *r_fpr = malloc (n + 1); ++ if (!*r_fpr) ++ return gpg_error_from_syserror (); ++ memcpy (*r_fpr, args, n); ++ (*r_fpr)[n] = 0; ++ args = pend + 1; ++ ++ gpg_err_set_errno (0); ++ *r_flags = strtoul (args, &pend, 0); ++ if (errno || args == pend || (*pend && *pend != ' ')) ++ { ++ free (*r_fpr); ++ *r_fpr = NULL; ++ return trace_gpg_error (GPG_ERR_INV_ENGINE); ++ } ++ ++ return 0; ++} ++ ++ + /* Parse the PLAINTEXT status line in ARGS and return the result in + FILENAMEP. */ + gpgme_error_t +diff --git a/src/ops.h b/src/ops.h +index 3662d57..9c27529 100644 +--- a/src/ops.h ++++ b/src/ops.h +@@ -57,9 +57,15 @@ gpgme_error_t _gpgme_op_data_lookup (gpgme_ctx_t ctx, ctx_op_data_id_t type, + /* Prepare a new operation on CTX. */ + gpgme_error_t _gpgme_op_reset (gpgme_ctx_t ctx, int synchronous); + ++/* Parse the KEY_CONSIDERED status line. */ ++gpgme_error_t _gpgme_parse_key_considered (const char *args, ++ char **r_fpr, unsigned int *r_flags); ++ + /* Parse the INV_RECP status line in ARGS and return the result in + KEY. */ +-gpgme_error_t _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key); ++gpgme_error_t _gpgme_parse_inv_recp (char *args, int for_signing, ++ const char *kc_fpr, unsigned int kc_flags, ++ gpgme_invalid_key_t *key); + + /* Parse the PLAINTEXT status line in ARGS and return the result in + FILENAMEP. */ +diff --git a/src/sign.c b/src/sign.c +index 6c9fc03..d8650a9 100644 +--- a/src/sign.c ++++ b/src/sign.c +@@ -42,6 +42,12 @@ typedef struct + /* The error code from a FAILURE status line or 0. */ + gpg_error_t failure_code; + ++ /* The fingerprint from the last KEY_CONSIDERED status line. */ ++ char *kc_fpr; ++ ++ /* The flags from the last KEY_CONSIDERED status line. */ ++ unsigned int kc_flags; ++ + /* A pointer to the next pointer of the last invalid signer in + the list. This makes appending new invalid signers painless + while preserving the order. */ +@@ -86,6 +92,7 @@ release_op_data (void *hook) + } + + release_signatures (opd->result.signatures); ++ free (opd->kc_fpr); + } + + +@@ -316,6 +323,17 @@ _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args) + opd->last_sig_p = &(*opd->last_sig_p)->next; + break; + ++ case GPGME_STATUS_KEY_CONSIDERED: ++ /* This is emitted during gpg's key lookup to give information ++ * about the lookup results. We store the last one so it can be ++ * used in connection with INV_RECP. */ ++ free (opd->kc_fpr); ++ opd->kc_fpr = NULL; ++ err = _gpgme_parse_key_considered (args, &opd->kc_fpr, &opd->kc_flags); ++ if (err) ++ return err; ++ break; ++ + case GPGME_STATUS_INV_RECP: + if (opd->inv_sgnr_seen && opd->ignore_inv_recp) + break; +@@ -323,11 +341,16 @@ _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args) + case GPGME_STATUS_INV_SGNR: + if (code == GPGME_STATUS_INV_SGNR) + opd->inv_sgnr_seen = 1; +- err = _gpgme_parse_inv_recp (args, opd->last_signer_p); ++ free (opd->kc_fpr); ++ opd->kc_fpr = NULL; ++ err = _gpgme_parse_inv_recp (args, 1, opd->kc_fpr, opd->kc_flags, ++ opd->last_signer_p); + if (err) + return err; + + opd->last_signer_p = &(*opd->last_signer_p)->next; ++ free (opd->kc_fpr); ++ opd->kc_fpr = NULL; + break; + + case GPGME_STATUS_FAILURE: +diff --git a/src/status-table.c b/src/status-table.c +index 6d428d7..e70cb8b 100644 +--- a/src/status-table.c ++++ b/src/status-table.c +@@ -84,6 +84,7 @@ static struct status_table_s status_table[] = + { "INQUIRE_MAXLEN", GPGME_STATUS_INQUIRE_MAXLEN }, + { "INV_RECP", GPGME_STATUS_INV_RECP }, + { "INV_SGNR", GPGME_STATUS_INV_SGNR }, ++ { "KEY_CONSIDERED", GPGME_STATUS_KEY_CONSIDERED }, + { "KEY_CREATED", GPGME_STATUS_KEY_CREATED }, + { "KEY_NOT_CREATED", GPGME_STATUS_KEY_NOT_CREATED }, + { "KEYEXPIRED", GPGME_STATUS_KEYEXPIRED }, +-- +2.7.4 + diff --git a/gpgme-1.4.3-no_gpgsm_t-verify.patch b/gpgme-1.4.3-no_gpgsm_t-verify.patch deleted file mode 100644 index 758fe3e..0000000 --- a/gpgme-1.4.3-no_gpgsm_t-verify.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff -up gpgme-1.4.3/tests/gpgsm/Makefile.in.no_t-verify gpgme-1.4.3/tests/gpgsm/Makefile.in ---- gpgme-1.4.3/tests/gpgsm/Makefile.in.no_t-verify 2013-08-12 07:36:10.000000000 -0500 -+++ gpgme-1.4.3/tests/gpgsm/Makefile.in 2013-10-09 10:28:52.991728837 -0500 -@@ -72,8 +72,8 @@ POST_UNINSTALL = : - build_triplet = @build@ - host_triplet = @host@ - TESTS = t-import$(EXEEXT) t-keylist$(EXEEXT) t-encrypt$(EXEEXT) \ -- t-verify$(EXEEXT) t-decrypt$(EXEEXT) t-sign$(EXEEXT) \ -- t-export$(EXEEXT) -+ t-decrypt$(EXEEXT) t-sign$(EXEEXT) \ -+ t-export$(EXEEXT) # t-verify$(EXEEXT) - noinst_PROGRAMS = $(am__EXEEXT_1) t-genkey$(EXEEXT) \ - cms-keylist$(EXEEXT) cms-decrypt$(EXEEXT) - subdir = tests/gpgsm -@@ -94,8 +94,8 @@ CONFIG_HEADER = $(top_builddir)/config.h - CONFIG_CLEAN_FILES = - CONFIG_CLEAN_VPATH_FILES = - am__EXEEXT_1 = t-import$(EXEEXT) t-keylist$(EXEEXT) t-encrypt$(EXEEXT) \ -- t-verify$(EXEEXT) t-decrypt$(EXEEXT) t-sign$(EXEEXT) \ -- t-export$(EXEEXT) -+ t-decrypt$(EXEEXT) t-sign$(EXEEXT) \ -+ t-export$(EXEEXT) # t-verify$(EXEEXT) - PROGRAMS = $(noinst_PROGRAMS) - cms_decrypt_SOURCES = cms-decrypt.c - cms_decrypt_OBJECTS = cms-decrypt.$(OBJEXT) diff --git a/gpgme.spec b/gpgme.spec index 2e6683d..8b38ccc 100644 --- a/gpgme.spec +++ b/gpgme.spec @@ -1,40 +1,41 @@ - # trim changelog included in binary rpms %global _changelog_trimtime %(date +%s -d "1 year ago") -Name: gpgme -Summary: GnuPG Made Easy - high level crypto API -Version: 1.6.0 -Release: 1%{?dist} +# STATUS_KEY_CONSIDERED from Patch101 has been added in 2.1.13 +%global gnupg2_min_ver 2.1.13 -License: LGPLv2+ -URL: http://www.gnupg.org/related_software/gpgme/ -Source0: ftp://ftp.gnupg.org/gcrypt/gpgme/gpgme-%{version}.tar.bz2 -Source1: ftp://ftp.gnupg.org/gcrypt/gpgme/gpgme-%{version}.tar.bz2.sig -Source2: gpgme-multilib.h +Name: gpgme +Summary: GnuPG Made Easy - high level crypto API +Version: 1.6.0 +Release: 2%{?dist} -Patch1: gpgme-1.3.2-config_extras.patch +License: LGPLv2+ +URL: http://www.gnupg.org/related_software/gpgme/ +Source0: ftp://ftp.gnupg.org/gcrypt/gpgme/gpgme-%{version}.tar.bz2 +Source2: gpgme-multilib.h -# gpgsm t-verify check/test hangs if using gnupg2 < 2.0.22 -# see http://bugs.g10code.com/gnupg/issue1493 -Patch2: gpgme-1.4.3-no_gpgsm_t-verify.patch +Patch1: gpgme-1.3.2-config_extras.patch # add -D_FILE_OFFSET_BITS... to gpgme-config, upstreamable -Patch3: gpgme-1.3.2-largefile.patch +Patch3: gpgme-1.3.2-largefile.patch -BuildRequires: gcc -BuildRequires: gawk +# https://bugzilla.redhat.com/show_bug.cgi?id=1359521 +# https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gpgme.git;a=commit;h=315fb73d4a774e2c699ac1804f5377559b4d0027 +Patch101: 0001-Return-dedicated-error-code-for-all-subkeys-expired-.patch + +BuildRequires: gcc +BuildRequires: gawk # see patch2 above, else we only need 2.0.4 -BuildRequires: gnupg2 >= 2.0.22 -BuildRequires: gnupg2-smime -BuildRequires: libgpg-error-devel >= 1.8 -BuildRequires: pth-devel -BuildRequires: libassuan-devel >= 2.0.2 +BuildRequires: gnupg2 >= %{gnupg2_min_ver} +BuildRequires: gnupg2-smime +BuildRequires: libgpg-error-devel >= 1.8 +BuildRequires: pth-devel +BuildRequires: libassuan-devel >= 2.0.2 # to remove RPATH -BuildRequires: chrpath +BuildRequires: chrpath -Requires: gnupg2 +Requires: gnupg2 >= %{gnupg2_min_ver} # On the following architectures workaround multiarch conflict of -devel packages: %define multilib_arches %{ix86} x86_64 ia64 ppc ppc64 s390 s390x %{sparc} @@ -60,11 +61,7 @@ Requires(postun): /sbin/install-info %prep -%setup -q - -%patch1 -p1 -b .config_extras -#patch2 -p1 -b .no_gpgsm_t-verify -%patch3 -p1 -b .largefile +%autosetup -p1 ## HACK ALERT # The config script already suppresses the -L if it's /usr/lib, so cheat and @@ -133,6 +130,9 @@ fi %{_infodir}/gpgme.info* %changelog +* Mon Jul 25 2016 Igor Gnatenko - 1.6.0-2 +- Backport patch for STATUS_KEY_CONSIDERED (RHBZ #1359521) + * Wed Jul 13 2016 Igor Gnatenko - 1.6.0-1 - Update to 1.6.0 (RHBZ #1167656)