[git] GnuPG - branch, STABLE-BRANCH-2-2, updated. gnupg-2.2.9-9-g0709f35

by Werner Koch cvs at cvs.gnupg.org
Tue Aug 28 15:37:43 CEST 2018


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 "The GNU Privacy Guard".

The branch, STABLE-BRANCH-2-2 has been updated
       via  0709f358cd13abc82e0f97f055fcaa712f0fd44f (commit)
       via  11a9fe1c5820b97d7e0f4b3e91f016df9dc466a9 (commit)
      from  0786ac78423c7c05b2d373f34fcf3316f94198a7 (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 0709f358cd13abc82e0f97f055fcaa712f0fd44f
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Aug 28 15:22:35 2018 +0200

    gpg: Refresh expired keys originating from the WKD.
    
    * g10/getkey.c (getkey_ctx_s): New field found_via_akl.
    (get_pubkey_byname): Set it.
    (only_expired_enc_subkeys): New.
    (get_best_pubkey_byname): Add support to refresh expired keys from the
    WKD.
    --
    
    A little drawback of that code is that if the WKD has no update for an
    expired key each access of the key will trigger a WKD lookup (unless
    cached by the dirmngr).  To avoid this we need to record the last time
    we have checked for an update but that would in turn require that we
    update the keyring for each check.  We defer this until we have a
    better key database which allows for fast updates of meta data.
    
    Testing the code is currently a bit cumbersome because it requires to
    update a key in the WKD several times.  Eventually we we need a
    network emulation layer to provide sample data for the regression
    tests.
    
    GnuPG-bug-id: 2917
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (cherry picked from commit 7f172404bfcf719b9b1af4a182d4803525ebff7c)

diff --git a/g10/getkey.c b/g10/getkey.c
index e8722a3..be81d99 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -88,6 +88,9 @@ struct getkey_ctx_s
      their address used in ITEMS.  */
   strlist_t extra_list;
 
+  /* Hack to return the mechanism (AKL_foo) used to find the key.  */
+  int found_via_akl;
+
   /* Part of the search criteria: The low-level search specification
      as passed to keydb_search.  */
   int nitems;
@@ -1265,6 +1268,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
   int is_mbox;
   int nodefault = 0;
   int anylocalfirst = 0;
+  int mechanism_type = AKL_NODEFAULT;
 
   /* If RETCTX is not NULL, then RET_KDBHD must be NULL.  */
   log_assert (retctx == NULL || ret_kdbhd == NULL);
@@ -1354,18 +1358,19 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
 	  size_t fpr_len;
 	  int did_akl_local = 0;
 	  int no_fingerprint = 0;
-	  const char *mechanism = "?";
+	  const char *mechanism_string = "?";
 
-	  switch (akl->type)
+          mechanism_type = akl->type;
+	  switch (mechanism_type)
 	    {
 	    case AKL_NODEFAULT:
 	      /* This is a dummy mechanism.  */
-	      mechanism = "None";
+	      mechanism_string = "None";
 	      rc = GPG_ERR_NO_PUBKEY;
 	      break;
 
 	    case AKL_LOCAL:
-	      mechanism = "Local";
+	      mechanism_string = "Local";
 	      did_akl_local = 1;
 	      if (retctx)
 		{
@@ -1379,35 +1384,35 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
 	      break;
 
 	    case AKL_CERT:
-	      mechanism = "DNS CERT";
+	      mechanism_string = "DNS CERT";
 	      glo_ctrl.in_auto_key_retrieve++;
 	      rc = keyserver_import_cert (ctrl, name, 0, &fpr, &fpr_len);
 	      glo_ctrl.in_auto_key_retrieve--;
 	      break;
 
 	    case AKL_PKA:
-	      mechanism = "PKA";
+	      mechanism_string = "PKA";
 	      glo_ctrl.in_auto_key_retrieve++;
 	      rc = keyserver_import_pka (ctrl, name, &fpr, &fpr_len);
 	      glo_ctrl.in_auto_key_retrieve--;
 	      break;
 
 	    case AKL_DANE:
-	      mechanism = "DANE";
+	      mechanism_string = "DANE";
 	      glo_ctrl.in_auto_key_retrieve++;
 	      rc = keyserver_import_cert (ctrl, name, 1, &fpr, &fpr_len);
 	      glo_ctrl.in_auto_key_retrieve--;
 	      break;
 
 	    case AKL_WKD:
-	      mechanism = "WKD";
+	      mechanism_string = "WKD";
 	      glo_ctrl.in_auto_key_retrieve++;
 	      rc = keyserver_import_wkd (ctrl, name, 0, &fpr, &fpr_len);
 	      glo_ctrl.in_auto_key_retrieve--;
 	      break;
 
 	    case AKL_LDAP:
-	      mechanism = "LDAP";
+	      mechanism_string = "LDAP";
 	      glo_ctrl.in_auto_key_retrieve++;
 	      rc = keyserver_import_ldap (ctrl, name, &fpr, &fpr_len);
 	      glo_ctrl.in_auto_key_retrieve--;
@@ -1420,7 +1425,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
 	       * and getting a whole lot of keys back. */
 	      if (keyserver_any_configured (ctrl))
 		{
-		  mechanism = "keyserver";
+		  mechanism_string = "keyserver";
 		  glo_ctrl.in_auto_key_retrieve++;
 		  rc = keyserver_import_name (ctrl, name, &fpr, &fpr_len,
                                               opt.keyserver);
@@ -1428,7 +1433,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
 		}
 	      else
 		{
-		  mechanism = "Unconfigured keyserver";
+		  mechanism_string = "Unconfigured keyserver";
 		  rc = GPG_ERR_NO_PUBKEY;
 		}
 	      break;
@@ -1437,7 +1442,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
 	      {
 		struct keyserver_spec *keyserver;
 
-		mechanism = akl->spec->uri;
+		mechanism_string = akl->spec->uri;
 		keyserver = keyserver_match (akl->spec);
 		glo_ctrl.in_auto_key_retrieve++;
 		rc = keyserver_import_name (ctrl,
@@ -1499,13 +1504,13 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
 	      /* Key found.  */
               if (opt.verbose)
                 log_info (_("automatically retrieved '%s' via %s\n"),
-                          name, mechanism);
+                          name, mechanism_string);
 	      break;
 	    }
 	  if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY
               || opt.verbose || no_fingerprint)
 	    log_info (_("error retrieving '%s' via %s: %s\n"),
-		      name, mechanism,
+		      name, mechanism_string,
 		      no_fingerprint ? _("No fingerprint") : gpg_strerror (rc));
 	}
     }
@@ -1521,6 +1526,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
     {
       log_assert (!(*retctx)->extra_list);
       (*retctx)->extra_list = namelist;
+      (*retctx)->found_via_akl = mechanism_type;
     }
   else
     free_strlist (namelist);
@@ -1568,6 +1574,34 @@ subkey_is_ok (const PKT_public_key *sub)
   return ! sub->flags.revoked && sub->flags.valid && ! sub->flags.disabled;
 }
 
+/* Return true if KEYBLOCK has only expired encryption subkyes.  Note
+ * that the function returns false if the key has no encryption
+ * subkeys at all or the subkecys are revoked.  */
+static int
+only_expired_enc_subkeys (kbnode_t keyblock)
+{
+  kbnode_t node;
+  PKT_public_key *sub;
+  int any = 0;
+
+  for (node = find_next_kbnode (keyblock, PKT_PUBLIC_SUBKEY);
+       node; node = find_next_kbnode (node, PKT_PUBLIC_SUBKEY))
+    {
+      sub = node->pkt->pkt.public_key;
+
+      if (!(sub->pubkey_usage & PUBKEY_USAGE_ENC))
+        continue;
+
+      if (!subkey_is_ok (sub))
+        continue;
+
+      any = 1;
+      if (!sub->has_expired)
+        return 0;
+    }
+
+  return any? 1 : 0;
+}
 
 /* Finally this function compares a NEW key to the former candidate
  * OLD.  Returns < 0 if the old key is worse, > 0 if the old key is
@@ -1640,10 +1674,23 @@ get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk,
 {
   gpg_error_t err;
   struct getkey_ctx_s *ctx = NULL;
+  int is_mbox = is_valid_mailbox (name);
+  int wkd_tried = 0;
 
   if (retctx)
     *retctx = NULL;
 
+ start_over:
+  if (ctx)  /* Clear  in case of a start over.  */
+    {
+      if (ret_keyblock)
+        {
+          release_kbnode (*ret_keyblock);
+          *ret_keyblock = NULL;
+        }
+      getkey_end (ctrl, ctx);
+      ctx = NULL;
+    }
   err = get_pubkey_byname (ctrl, &ctx, pk, name, ret_keyblock,
                            NULL, include_unusable, 0);
   if (err)
@@ -1652,7 +1699,39 @@ get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk,
       return err;
     }
 
-  if (is_valid_mailbox (name) && ctx)
+  /* If the keyblock was retrieved from the local database and the key
+   * has expired, do further checks.  However, we can do this only if
+   * the caller requested a keyblock.  */
+  if (is_mbox && ctx && ctx->found_via_akl == AKL_LOCAL && ret_keyblock)
+    {
+      u32 now = make_timestamp ();
+      PKT_public_key *pk2 = (*ret_keyblock)->pkt->pkt.public_key;
+      int found;
+
+      /* If the key has expired and its origin was the WKD then try to
+       * get a fresh key from the WKD.  We also try this if the key
+       * has any only expired encryption subkeys.  In case we checked
+       * for a fresh copy in the last 3 hours we won't do that again.
+       * Unfortunately that does not yet work because KEYUPDATE is
+       * only updated during import iff the key has actually changed
+       * (see import.c:import_one).  */
+      if (!wkd_tried && pk2->keyorg == KEYORG_WKD
+          && (pk2->keyupdate + 3*3600) < now
+          && (pk2->has_expired || only_expired_enc_subkeys (*ret_keyblock)))
+        {
+          if (opt.verbose)
+            log_info (_("checking for a fresh copy of an expired key via %s\n"),
+                      "WKD");
+          wkd_tried = 1;
+          glo_ctrl.in_auto_key_retrieve++;
+          found = !keyserver_import_wkd (ctrl, name, 0, NULL, NULL);
+          glo_ctrl.in_auto_key_retrieve--;
+          if (found)
+            goto start_over;
+        }
+    }
+
+  if (is_mbox && ctx)
     {
       /* Rank results and return only the most relevant key.  */
       struct pubkey_cmp_cookie best = { 0 };
diff --git a/g10/import.c b/g10/import.c
index 6dad8ee..11de592 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -2070,9 +2070,12 @@ import_one (ctrl_t ctrl,
           keydb_release (hd);
           hd = NULL;
 
-          /* Fixme: we do not track the time we last checked a key for
+          /* FIXME: We do not track the time we last checked a key for
            * updates.  To do this we would need to rewrite even the
-           * keys which have no changes.  */
+           * keys which have no changes.  Adding this would be useful
+           * for the automatic update of expired keys via the WKD in
+           * case the WKD still carries the expired key.  See
+           * get_best_pubkey_byname.  */
           same_key = 1;
           if (is_status_enabled ())
             print_import_ok (pk, 0);

commit 11a9fe1c5820b97d7e0f4b3e91f016df9dc466a9
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Aug 28 15:11:10 2018 +0200

    gpg: Remove unused arg from a function.
    
    * g10/getkey.c (get_best_pubkey_byname): Remove unused arg 'no_akl'.
    Change both callers.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (cherry picked from commit db67ccb759426c1173761574b14bdfe6a76394c2)

diff --git a/g10/getkey.c b/g10/getkey.c
index d76e7cc..e8722a3 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -1636,7 +1636,7 @@ pubkey_cmp (ctrl_t ctrl, const char *name, struct pubkey_cmp_cookie *old,
 gpg_error_t
 get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk,
                         const char *name, KBNODE *ret_keyblock,
-                        int include_unusable, int no_akl)
+                        int include_unusable)
 {
   gpg_error_t err;
   struct getkey_ctx_s *ctx = NULL;
@@ -1645,7 +1645,7 @@ get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk,
     *retctx = NULL;
 
   err = get_pubkey_byname (ctrl, &ctx, pk, name, ret_keyblock,
-                           NULL, include_unusable, no_akl);
+                           NULL, include_unusable, 0);
   if (err)
     {
       getkey_end (ctrl, ctx);
diff --git a/g10/keydb.h b/g10/keydb.h
index 8e1a724..7cd628d 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -367,7 +367,7 @@ int get_pubkey_byname (ctrl_t ctrl,
 gpg_error_t get_best_pubkey_byname (ctrl_t ctrl,
                                     GETKEY_CTX *retctx, PKT_public_key *pk,
                                     const char *name, KBNODE *ret_keyblock,
-                                    int include_unusable, int no_akl);
+                                    int include_unusable);
 
 /* Get a public key directly from file FNAME.  */
 gpg_error_t get_pubkey_fromfile (ctrl_t ctrl,
diff --git a/g10/keylist.c b/g10/keylist.c
index c9121a1..7942558 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -652,7 +652,7 @@ locate_one (ctrl_t ctrl, strlist_t names)
 
   for (sl = names; sl; sl = sl->next)
     {
-      rc = get_best_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, 1, 0);
+      rc = get_best_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, 1);
       if (rc)
 	{
 	  if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
diff --git a/g10/pkclist.c b/g10/pkclist.c
index 6f04249..56c9385 100644
--- a/g10/pkclist.c
+++ b/g10/pkclist.c
@@ -834,7 +834,7 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
   if (from_file)
     rc = get_pubkey_fromfile (ctrl, pk, name);
   else
-    rc = get_best_pubkey_byname (ctrl, NULL, pk, name, &keyblock, 0, 0);
+    rc = get_best_pubkey_byname (ctrl, NULL, pk, name, &keyblock, 0);
   if (rc)
     {
       int code;

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

Summary of changes:
 g10/getkey.c  | 113 +++++++++++++++++++++++++++++++++++++++++++++++++---------
 g10/import.c  |   7 ++--
 g10/keydb.h   |   2 +-
 g10/keylist.c |   2 +-
 g10/pkclist.c |   2 +-
 5 files changed, 104 insertions(+), 22 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list