[Pkg-gnupg-commit] [gnupg2] 157/205: gpg: Add experimental AKL method "wkd" and option --with-wkd-hash.

Daniel Kahn Gillmor dkg at fifthhorseman.net
Wed May 11 08:38:33 UTC 2016


This is an automated email from the git hooks/post-receive script.

dkg pushed a commit to branch experimental
in repository gnupg2.

commit 87de9e19edf0311ca0342e15ef44ebe40e32861e
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Apr 27 08:34:29 2016 +0200

    gpg: Add experimental AKL method "wkd" and option --with-wkd-hash.
    
    * g10/getkey.c (parse_auto_key_locate): Add method "wkd".
    (get_pubkey_byname): Implement that method.  Also rename a variable.
    * g10/call-dirmngr.c (gpg_dirmngr_wkd_get): New.
    * g10/keyserver.c (keyserver_import_wkd): New.
    * g10/test-stubs.c (keyserver_import_wkd): Add stub.
    * g10/gpgv.c (keyserver_import_wkd): Ditto.
    * g10/options.h (opt):  Add field 'with_wkd_hash'.
    (AKL_WKD): New.
    
    * g10/gpg.c (oWithWKDHash): New.
    (opts): Add option --with-wkd-hash.
    (main): Set that option.
    * g10/keylist.c (list_keyblock_print): Implement that option.
    --
    
    The Web Key Directory is an experimental feature to retrieve a key via
    https.  It is similar to OpenPGP DANE but also uses an encryption to
    reveal less information about a key lookup.
    
    For example the URI to lookup the key for Joe.Doe at Example.ORG is:
    
        https://example.org/.well-known/openpgpkey/
        hu/example.org/iy9q119eutrkn8s1mk4r39qejnbu3n5q
    
    (line has been wrapped for rendering purposes).  The hash is a
    z-Base-32 encoded SHA-1 hash of the mail address' local-part.  The
    address wk at gnupg.org can be used for testing.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>
---
 doc/gpg.texi             |  9 +++++++
 g10/call-dirmngr.c       | 61 +++++++++++++++++++++++++++++++++++++++++++++++-
 g10/call-dirmngr.h       |  2 ++
 g10/getkey.c             | 34 ++++++++++++++++-----------
 g10/gpg.c                |  6 +++++
 g10/gpgv.c               | 11 +++++++++
 g10/import.c             |  2 +-
 g10/keylist.c            | 36 ++++++++++++++++++++++------
 g10/keyserver-internal.h |  2 ++
 g10/keyserver.c          | 33 ++++++++++++++++++++++++++
 g10/options.h            |  2 ++
 g10/test-stubs.c         | 11 +++++++++
 12 files changed, 187 insertions(+), 22 deletions(-)

diff --git a/doc/gpg.texi b/doc/gpg.texi
index 0c43c55..c10678b 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -1600,6 +1600,10 @@ mechanisms, in the order they are to be tried:
   Locate a key using DANE, as specified
   in draft-ietf-dane-openpgpkey-05.txt.
 
+  @item wkd
+  Locate a key using the Web Key Directory protocol.
+  This is an experimental method and semantics may change.
+
   @item ldap
   Using DNS Service Discovery, check the domain in question for any LDAP
   keyservers to use.  If this fails, attempt to locate the key using the
@@ -2235,6 +2239,11 @@ Print the ICAO spelling of the fingerprint in addition to the hex digits.
 @opindex with-keygrip
 Include the keygrip in the key listings.
 
+ at item --with-wkd-hash
+ at opindex with-wkd-hash
+Print a Web Key Directory indentifier along with each user ID in key
+listings.  This is an experimental feature and semantics may change.
+
 @item --with-secret
 @opindex with-secret
 Include info about the presence of a secret key in public key listings
diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c
index e596533..b0f249e 100644
--- a/g10/call-dirmngr.c
+++ b/g10/call-dirmngr.c
@@ -1064,7 +1064,7 @@ gpg_dirmngr_ks_put (ctrl_t ctrl, void *data, size_t datalen, kbnode_t keyblock)
 
 
 

-/* Data callback for the DNS_CERT command. */
+/* Data callback for the DNS_CERT and WKD_GET commands. */
 static gpg_error_t
 dns_cert_data_cb (void *opaque, const void *data, size_t datalen)
 {
@@ -1287,3 +1287,62 @@ gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
   close_context (ctrl, ctx);
   return err;
 }
+
+
+

+/* Ask the dirmngr to retrieve a key via the Web Key Directory
+ * protocol.  On success a new estream with the key is stored at
+ * R_KEY.
+ */
+gpg_error_t
+gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, estream_t *r_key)
+{
+  gpg_error_t err;
+  assuan_context_t ctx;
+  struct dns_cert_parm_s parm;
+  char *line = NULL;
+
+  memset (&parm, 0, sizeof parm);
+
+  err = open_context (ctrl, &ctx);
+  if (err)
+    return err;
+
+  line = es_bsprintf ("WKD_GET -- %s", name);
+  if (!line)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+  if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
+    {
+      err = gpg_error (GPG_ERR_TOO_LARGE);
+      goto leave;
+    }
+
+  parm.memfp = es_fopenmem (0, "rwb");
+  if (!parm.memfp)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+  err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
+                         NULL, NULL, NULL, &parm);
+  if (err)
+    goto leave;
+
+  if (r_key)
+    {
+      es_rewind (parm.memfp);
+      *r_key = parm.memfp;
+      parm.memfp = NULL;
+    }
+
+ leave:
+  xfree (parm.fpr);
+  xfree (parm.url);
+  es_fclose (parm.memfp);
+  xfree (line);
+  close_context (ctrl, ctx);
+  return err;
+}
diff --git a/g10/call-dirmngr.h b/g10/call-dirmngr.h
index cdad645..4dc1e30 100644
--- a/g10/call-dirmngr.h
+++ b/g10/call-dirmngr.h
@@ -40,6 +40,8 @@ gpg_error_t gpg_dirmngr_dns_cert (ctrl_t ctrl,
 gpg_error_t gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
                                  unsigned char **r_fpr, size_t *r_fprlen,
                                  char **r_url);
+gpg_error_t gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name,
+                                 estream_t *r_key);
 
 
 #endif /*GNUPG_G10_CALL_DIRMNGR_H*/
diff --git a/g10/getkey.c b/g10/getkey.c
index 481e8dd..a3d29f5 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -1274,7 +1274,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
 	{
 	  unsigned char *fpr = NULL;
 	  size_t fpr_len;
-	  int did_key_byname = 0;
+	  int did_akl_local = 0;
 	  int no_fingerprint = 0;
 	  const char *mechanism = "?";
 
@@ -1288,7 +1288,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
 
 	    case AKL_LOCAL:
 	      mechanism = "Local";
-	      did_key_byname = 1;
+	      did_akl_local = 1;
 	      if (retctx)
 		{
 		  getkey_end (*retctx);
@@ -1321,6 +1321,13 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
 	      glo_ctrl.in_auto_key_retrieve--;
 	      break;
 
+	    case AKL_WKD:
+	      mechanism = "WKD";
+	      glo_ctrl.in_auto_key_retrieve++;
+	      rc = keyserver_import_wkd (ctrl, name, &fpr, &fpr_len);
+	      glo_ctrl.in_auto_key_retrieve--;
+	      break;
+
 	    case AKL_LDAP:
 	      mechanism = "LDAP";
 	      glo_ctrl.in_auto_key_retrieve++;
@@ -1386,22 +1393,20 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
 
 	      add_to_strlist (&namelist, fpr_string);
 	    }
-	  else if (!rc && !fpr && !did_key_byname)
-	    /* The acquisition method said no failure occurred, but it
-	       didn't return a fingerprint.  That's a failure.  */
-	    {
-	      no_fingerprint = 1;
+	  else if (!rc && !fpr && !did_akl_local)
+            { /* The acquisition method said no failure occurred, but
+                 it didn't return a fingerprint.  That's a failure.  */
+              no_fingerprint = 1;
 	      rc = GPG_ERR_NO_PUBKEY;
 	    }
 	  xfree (fpr);
 	  fpr = NULL;
 
-	  if (!rc && !did_key_byname)
-	    /* There was no error and we didn't do a local lookup.
-	       This means that we imported a key into the local
-	       keyring.  Try to read the imported key from the
-	       keyring.  */
-	    {
+	  if (!rc && !did_akl_local)
+            { /* There was no error and we didn't do a local lookup.
+	         This means that we imported a key into the local
+	         keyring.  Try to read the imported key from the
+	         keyring.  */
 	      if (retctx)
 		{
 		  getkey_end (*retctx);
@@ -3195,6 +3200,7 @@ finish_lookup (GETKEY_CTX ctx, KBNODE keyblock)
 	      if (DBG_LOOKUP)
 		log_debug ("\tsubkey has expired\n");
 	      continue;
+
 	    }
 	  if (pk->timestamp > curtime && !opt.ignore_valid_from)
 	    {
@@ -3769,6 +3775,8 @@ parse_auto_key_locate (char *options)
 	akl->type = AKL_PKA;
       else if (ascii_strcasecmp (tok, "dane") == 0)
 	akl->type = AKL_DANE;
+      else if (ascii_strcasecmp (tok, "wkd") == 0)
+	akl->type = AKL_WKD;
       else if ((akl->spec = parse_keyserver_uri (tok, 1)))
 	akl->type = AKL_SPEC;
       else
diff --git a/g10/gpg.c b/g10/gpg.c
index b9d69a7..2f687fc 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -185,6 +185,7 @@ enum cmd_and_opt_values
     oWithICAOSpelling,
     oWithKeygrip,
     oWithSecret,
+    oWithWKDHash,
     oAnswerYes,
     oAnswerNo,
     oKeyring,
@@ -721,6 +722,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oWithICAOSpelling, "with-icao-spelling", "@"),
   ARGPARSE_s_n (oWithKeygrip,     "with-keygrip", "@"),
   ARGPARSE_s_n (oWithSecret,      "with-secret", "@"),
+  ARGPARSE_s_n (oWithWKDHash,     "with-wkd-hash", "@"),
   ARGPARSE_s_s (oDisableCipherAlgo,  "disable-cipher-algo", "@"),
   ARGPARSE_s_s (oDisablePubkeyAlgo,  "disable-pubkey-algo", "@"),
   ARGPARSE_s_n (oAllowNonSelfsignedUID,      "allow-non-selfsigned-uid", "@"),
@@ -2575,6 +2577,10 @@ main (int argc, char **argv)
             opt.with_secret = 1;
             break;
 
+	  case oWithWKDHash:
+            opt.with_wkd_hash = 1;
+            break;
+
 	  case oSecretKeyring:
             /* Ignore this old option.  */
             break;
diff --git a/g10/gpgv.c b/g10/gpgv.c
index 19a2ff6..2a53e69 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -374,6 +374,17 @@ keyserver_import_pka (const char *name,unsigned char *fpr)
   return -1;
 }
 
+gpg_error_t
+keyserver_import_wkd (ctrl_t ctrl, const char *name,
+                      unsigned char **fpr, size_t *fpr_len)
+{
+  (void)ctrl;
+  (void)name;
+  (void)fpr;
+  (void)fpr_len;
+  return GPG_ERR_BUG;
+}
+
 int
 keyserver_import_name (const char *name,struct keyserver_spec *spec)
 {
diff --git a/g10/import.c b/g10/import.c
index 369be35..e9fc014 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -1279,7 +1279,7 @@ import_one (ctrl_t ctrl,
         {
           xfree (*fpr);
           /* Note that we need to compare against 0 here because
-             COUNT gets only incremented after returning form this
+             COUNT gets only incremented after returning from this
              function.  */
           if (!stats->count)
             *fpr = fingerprint_from_pk (pk, NULL, fpr_len);
diff --git a/g10/keylist.c b/g10/keylist.c
index d71bf4f..0812d9c 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -1116,6 +1116,7 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr,
       if (node->pkt->pkttype == PKT_USER_ID)
 	{
 	  PKT_user_id *uid = node->pkt->pkt.user_id;
+          int indent;
 
 	  if ((uid->is_expired || uid->is_revoked)
 	      && !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
@@ -1133,25 +1134,46 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr,
 	      || (opt.list_options & LIST_SHOW_UID_VALIDITY))
 	    {
 	      const char *validity;
-	      int indent;
 
 	      validity = uid_trust_string_fixed (pk, uid);
-	      indent =
-		(keystrlen () + (opt.legacy_list_mode? 9:11)) -
-		atoi (uid_trust_string_fixed (NULL, NULL));
-
+	      indent = ((keystrlen () + (opt.legacy_list_mode? 9:11))
+                        - atoi (uid_trust_string_fixed (NULL, NULL)));
 	      if (indent < 0 || indent > 40)
 		indent = 0;
 
 	      es_fprintf (es_stdout, "uid%*s%s ", indent, "", validity);
 	    }
 	  else
-	    es_fprintf (es_stdout, "uid%*s",
-                        (int) keystrlen () + (opt.legacy_list_mode? 10:12), "");
+            {
+              indent = keystrlen () + (opt.legacy_list_mode? 10:12);
+              es_fprintf (es_stdout, "uid%*s", indent, "");
+            }
 
 	  print_utf8_buffer (es_stdout, uid->name, uid->len);
 	  es_putc ('\n', es_stdout);
 
+          if (opt.with_wkd_hash)
+            {
+              char *mbox, *hash, *p;
+              char hashbuf[32];
+
+              mbox = mailbox_from_userid (uid->name);
+              if (mbox && (p = strchr (mbox, '@')))
+                {
+                  *p++ = 0;
+                  gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf,
+                                       mbox, strlen (mbox));
+                  hash = zb32_encode (hashbuf, 8*20);
+                  if (hash)
+                    {
+                      es_fprintf (es_stdout, "   %*s%s@%s\n",
+                                  indent, "", hash, p);
+                      xfree (hash);
+                    }
+                }
+              xfree (mbox);
+            }
+
 	  if ((opt.list_options & LIST_SHOW_PHOTOS) && uid->attribs != NULL)
 	    show_photos (uid->attribs, uid->numattribs, pk, uid);
 	}
diff --git a/g10/keyserver-internal.h b/g10/keyserver-internal.h
index 6f6f430..f57dcaa 100644
--- a/g10/keyserver-internal.h
+++ b/g10/keyserver-internal.h
@@ -45,6 +45,8 @@ int keyserver_import_cert (ctrl_t ctrl, const char *name, int dane_mode,
                            unsigned char **fpr,size_t *fpr_len);
 gpg_error_t keyserver_import_pka (ctrl_t ctrl, const char *name,
                                   unsigned char **fpr,size_t *fpr_len);
+gpg_error_t keyserver_import_wkd (ctrl_t ctrl, const char *name,
+                                  unsigned char **fpr, size_t *fpr_len);
 int keyserver_import_name (ctrl_t ctrl,
                            const char *name,unsigned char **fpr,size_t *fpr_len,
                            struct keyserver_spec *keyserver);
diff --git a/g10/keyserver.c b/g10/keyserver.c
index e9ccb58..95ef441 100644
--- a/g10/keyserver.c
+++ b/g10/keyserver.c
@@ -2004,6 +2004,39 @@ keyserver_import_pka (ctrl_t ctrl, const char *name,
 }
 
 
+/* Import a key using the Web Key Directory protocol.  */
+gpg_error_t
+keyserver_import_wkd (ctrl_t ctrl, const char *name,
+                      unsigned char **fpr, size_t *fpr_len)
+{
+  gpg_error_t err;
+  estream_t key;
+
+  err = gpg_dirmngr_wkd_get (ctrl, name, &key);
+  if (err)
+    ;
+  else if (key)
+    {
+      int armor_status = opt.no_armor;
+
+      /* Keys returned via WKD are in binary format. */
+      opt.no_armor = 1;
+
+      err = import_keys_es_stream (ctrl, key, NULL, fpr, fpr_len,
+                                   (opt.keyserver_options.import_options
+                                    | IMPORT_NO_SECKEY),
+                                   NULL, NULL);
+
+      opt.no_armor = armor_status;
+
+      es_fclose (key);
+      key = NULL;
+    }
+
+  return err;
+}
+
+
 /* Import a key by name using LDAP */
 int
 keyserver_import_ldap (ctrl_t ctrl,
diff --git a/g10/options.h b/g10/options.h
index 1407b2f..0de0418 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -73,6 +73,7 @@ struct
   int with_fingerprint; /* Option --with-fingerprint active.  */
   int with_keygrip;     /* Option --with-keygrip active.  */
   int with_secret;      /* Option --with-secret active.  */
+  int with_wkd_hash;    /* Option --with-wkd-hash.  */
   int fingerprint; /* list fingerprints */
   int list_sigs;   /* list signatures */
   int print_pka_records;
@@ -245,6 +246,7 @@ struct
       AKL_CERT,
       AKL_PKA,
       AKL_DANE,
+      AKL_WKD,
       AKL_LDAP,
       AKL_KEYSERVER,
       AKL_SPEC
diff --git a/g10/test-stubs.c b/g10/test-stubs.c
index 74b6bf7..2edae18 100644
--- a/g10/test-stubs.c
+++ b/g10/test-stubs.c
@@ -186,6 +186,17 @@ keyserver_import_pka (const char *name,unsigned char *fpr)
   return -1;
 }
 
+gpg_error_t
+keyserver_import_wkd (ctrl_t ctrl, const char *name,
+                      unsigned char **fpr, size_t *fpr_len)
+{
+  (void)ctrl;
+  (void)name;
+  (void)fpr;
+  (void)fpr_len;
+  return GPG_ERR_BUG;
+}
+
 int
 keyserver_import_name (const char *name,struct keyserver_spec *spec)
 {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gnupg/gnupg2.git



More information about the Pkg-gnupg-commit mailing list