[git] GPGME - branch, master, updated. gpgme-1.6.0-108-g30b447f

by Werner Koch cvs at cvs.gnupg.org
Tue May 17 20:24:54 CEST 2016


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GnuPG Made Easy".

The branch, master has been updated
       via  30b447fcfe0e4f362c2575e1b9388e8144b5b2fd (commit)
       via  315fb73d4a774e2c699ac1804f5377559b4d0027 (commit)
      from  9b36ebf37a3b889c955ba68038bd5b3d9c5cde4e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 30b447fcfe0e4f362c2575e1b9388e8144b5b2fd
Author: Werner Koch <wk at gnupg.org>
Date:   Tue May 17 19:59:51 2016 +0200

    tests: New maintenance helper run-encrypt.
    
    * tests/run-encrypt.c: New.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/NEWS b/NEWS
index 85c084f..cfff559 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-Noteworthy changes in version 1.6.1 (unreleased) [C25/A14/R_]
+Noteworthy changes in version 1.7.0 (unreleased) [C25/A14/R_]
 ------------------------------------------------
 
  * New function to format a GnuPG style public key algorithm string.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 89e52e8..22c07d2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -32,7 +32,7 @@ LDADD = ../src/libgpgme.la @GPG_ERROR_LIBS@
 noinst_HEADERS = run-support.h
 
 noinst_PROGRAMS = $(TESTS) run-keylist run-export run-import run-sign \
-		  run-verify
+		  run-verify run-encrypt
 
 
 if RUN_GPG_TESTS
diff --git a/tests/run-encrypt.c b/tests/run-encrypt.c
new file mode 100644
index 0000000..a00f028
--- /dev/null
+++ b/tests/run-encrypt.c
@@ -0,0 +1,218 @@
+/* run-encrypt.c  - Helper to perform an encrypt operation
+ * Copyright (C) 2016 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* We need to include config.h so that we know whether we are building
+   with large file system (LFS) support. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <gpgme.h>
+
+#define PGM "run-encrypt"
+
+#include "run-support.h"
+
+
+static int verbose;
+
+static gpg_error_t
+status_cb (void *opaque, const char *keyword, const char *value)
+{
+  (void)opaque;
+  printf ("status_cb: %s %s\n", keyword, value);
+  return 0;
+}
+
+
+static void
+print_result (gpgme_encrypt_result_t result)
+{
+  gpgme_invalid_key_t invkey;
+
+  for (invkey = result->invalid_recipients; invkey; invkey = invkey->next)
+    printf ("Encryption key `%s' not used: %s <%s>\n",
+            nonnull (invkey->fpr),
+            gpg_strerror (invkey->reason), gpg_strsource (invkey->reason));
+}
+
+
+
+static int
+show_usage (int ex)
+{
+  fputs ("usage: " PGM " [options] FILE\n\n"
+         "Options:\n"
+         "  --verbose        run in verbose mode\n"
+         "  --status         print status lines from the backend\n"
+         "  --openpgp        use the OpenPGP protocol (default)\n"
+         "  --cms            use the CMS protocol\n"
+         "  --uiserver       use the UI server\n"
+         "  --loopback       use a loopback pinentry\n"
+         "  --key NAME       encrypt to key NAME\n"
+         , stderr);
+  exit (ex);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  int last_argc = -1;
+  gpgme_error_t err;
+  gpgme_ctx_t ctx;
+  const char *key_string = NULL;
+  gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
+  gpgme_data_t in, out;
+  gpgme_encrypt_result_t result;
+  int print_status = 0;
+  int use_loopback = 0;
+  char *keyargs[10];
+  gpgme_key_t keys[10+1];
+  int keycount = 0;
+  int i;
+
+  if (argc)
+    { argc--; argv++; }
+
+  if (DIM(keys) != DIM(keyargs)+1)
+    abort ();
+
+  while (argc && last_argc != argc )
+    {
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--help"))
+        show_usage (0);
+      else if (!strcmp (*argv, "--verbose"))
+        {
+          verbose = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--status"))
+        {
+          print_status = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--openpgp"))
+        {
+          protocol = GPGME_PROTOCOL_OpenPGP;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--cms"))
+        {
+          protocol = GPGME_PROTOCOL_CMS;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--uiserver"))
+        {
+          protocol = GPGME_PROTOCOL_UISERVER;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--key"))
+        {
+          argc--; argv++;
+          if (!argc)
+            show_usage (1);
+          if (keycount == DIM (keyargs))
+            show_usage (1);
+          keyargs[keycount++] = *argv;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--loopback"))
+        {
+          use_loopback = 1;
+          argc--; argv++;
+        }
+      else if (!strncmp (*argv, "--", 2))
+        show_usage (1);
+
+    }
+
+  if (argc != 1)
+    show_usage (1);
+
+  if (key_string && protocol == GPGME_PROTOCOL_UISERVER)
+    {
+      fprintf (stderr, PGM ": ignoring --key in UI-server mode\n");
+      key_string = NULL;
+    }
+
+  if (!key_string)
+    key_string = "test";
+
+  init_gpgme (protocol);
+
+  err = gpgme_new (&ctx);
+  fail_if_err (err);
+  gpgme_set_protocol (ctx, protocol);
+  gpgme_set_armor (ctx, 1);
+  if (print_status)
+    gpgme_set_status_cb (ctx, status_cb, NULL);
+  if (use_loopback)
+    gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
+
+  for (i=0; i < keycount; i++)
+    {
+      err = gpgme_get_key (ctx, keyargs[i], &keys[i], 0);
+      fail_if_err (err);
+    }
+  keys[i] = NULL;
+
+  err = gpgme_data_new_from_file (&in, *argv, 1);
+  if (err)
+    {
+      fprintf (stderr, PGM ": error reading `%s': %s\n",
+               *argv, gpg_strerror (err));
+      exit (1);
+    }
+
+  err = gpgme_data_new (&out);
+  fail_if_err (err);
+
+  err = gpgme_op_encrypt (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
+  result = gpgme_op_encrypt_result (ctx);
+  if (result)
+    print_result (result);
+  if (err)
+    {
+      fprintf (stderr, PGM ": encrypting failed: %s\n", gpg_strerror (err));
+      exit (1);
+    }
+
+  fputs ("Begin Output:\n", stdout);
+  print_data (out);
+  fputs ("End Output.\n", stdout);
+  gpgme_data_release (out);
+
+  gpgme_data_release (in);
+
+  for (i=0; i < keycount; i++)
+    gpgme_key_unref (keys[i]);
+  gpgme_release (ctx);
+  return 0;
+}

commit 315fb73d4a774e2c699ac1804f5377559b4d0027
Author: Werner Koch <wk at gnupg.org>
Date:   Tue May 17 20:21:01 2016 +0200

    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 <wk at gnupg.org>

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 8264bab..7a58ded 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 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 },

-----------------------------------------------------------------------

Summary of changes:
 NEWS                                |  2 +-
 src/encrypt.c                       | 26 +++++++++-
 src/gpgme.h.in                      | 13 +++--
 src/op-support.c                    | 65 ++++++++++++++++++++++---
 src/ops.h                           |  8 ++-
 src/sign.c                          | 25 +++++++++-
 src/status-table.c                  |  1 +
 tests/Makefile.am                   |  2 +-
 tests/{run-sign.c => run-encrypt.c} | 97 ++++++++++++++++++-------------------
 9 files changed, 171 insertions(+), 68 deletions(-)
 copy tests/{run-sign.c => run-encrypt.c} (64%)


hooks/post-receive
-- 
GnuPG Made Easy
http://git.gnupg.org




More information about the Gnupg-commits mailing list