diff options
| -rw-r--r-- | src/encrypt.c | 26 | ||||
| -rw-r--r-- | src/gpgme.h.in | 13 | ||||
| -rw-r--r-- | src/op-support.c | 65 | ||||
| -rw-r--r-- | src/ops.h | 8 | ||||
| -rw-r--r-- | src/sign.c | 25 | ||||
| -rw-r--r-- | src/status-table.c | 1 | 
6 files changed, 123 insertions, 15 deletions
| diff --git a/src/encrypt.c b/src/encrypt.c index 9f5134de..8672cd36 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 8264bab9..7a58dedd 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -532,7 +532,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; @@ -861,7 +862,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; @@ -1518,7 +1524,8 @@ typedef enum      GPGME_SIGSUM_CRL_MISSING = 0x0100,  /* CRL not available.  */      GPGME_SIGSUM_CRL_TOO_OLD = 0x0200,  /* Available CRL is too old.  */      GPGME_SIGSUM_BAD_POLICY  = 0x0400,  /* A policy was not met.  */ -    GPGME_SIGSUM_SYS_ERROR   = 0x0800   /* A system error occurred.  */ +    GPGME_SIGSUM_SYS_ERROR   = 0x0800,  /* A system error occurred.  */ +    GPGME_SIGSUM_TOFU_CONFLICT=0x1000   /* Tofu conflict detected.  */    }  gpgme_sigsum_t; @@ -1541,7 +1548,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 02940efd..d51d643b 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 @@ -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.  */ @@ -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 6d428d71..e70cb8bd 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 }, | 
