[git] GnuPG - branch, master, updated. gnupg-2.1.13-125-gcbe467e

by Werner Koch cvs at cvs.gnupg.org
Thu Jul 7 17:39:31 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 "The GNU Privacy Guard".

The branch, master has been updated
       via  cbe467e794f3be81b8da2bcb1732b5514b13b71d (commit)
       via  b05878f32aa507aa9087d7c992b630840b5ad71c (commit)
      from  2f61aa0ff11b194d20307751ab686c87cd47dd56 (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 cbe467e794f3be81b8da2bcb1732b5514b13b71d
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Jul 7 17:02:58 2016 +0200

    gpg: Add export options "export-pka" and "export-dane".
    
    * g10/options.h (EXPORT_PKA_FORMAT): New.
    * g10/keylist.c (list_keyblock_pka): Do not use DANE flag.
    * g10/export.c: Include zb32.h.
    (parse_export_options): Add options "export-pka" and "export-dane".
    (do_export): Do not armor if either of these option is set.
    (print_pka_or_dane_records): New.
    (do_export_stream): Implement new options.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/doc/gpg.texi b/doc/gpg.texi
index 11d3a65..ae860d7 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -2320,6 +2320,18 @@ opposite meaning. The options are:
   most recent self-signature on each user ID. This option is the same as
   running the @option{--edit-key} command "minimize" before export except
   that the local copy of the key is not modified. Defaults to no.
+
+  @item export-pka
+  Instead of outputting the key material output PKA records suitable
+  to put into DNS zone files.  An ORIGIN line is printed before each
+  record to allow diverting the records to the corresponding zone file.
+
+  @item export-dane
+  Instead of outputting the key material output OpenPGP DANE records
+  suitable to put into DNS zone files.  An ORIGIN line is printed before
+  each record to allow diverting the records to the corresponding zone
+  file.
+
 @end table
 
 @item --with-colons
diff --git a/g10/export.c b/g10/export.c
index c5b7328..d31b09a 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -35,6 +35,7 @@
 #include "i18n.h"
 #include "membuf.h"
 #include "host2net.h"
+#include "zb32.h"
 #include "recsel.h"
 #include "mbox-util.h"
 #include "init.h"
@@ -103,6 +104,10 @@ parse_export_options(char *str,unsigned int *options,int noisy)
        N_("remove unusable parts from key during export")},
       {"export-minimal",EXPORT_MINIMAL|EXPORT_CLEAN,NULL,
        N_("remove as much as possible from key during export")},
+
+      {"export-pka", EXPORT_PKA_FORMAT, NULL, NULL },
+      {"export-dane", EXPORT_DANE_FORMAT, NULL, NULL },
+
       /* Aliases for backward compatibility */
       {"include-local-sigs",EXPORT_LOCAL_SIGS,NULL,NULL},
       {"include-attributes",EXPORT_ATTRIBUTES,NULL,NULL},
@@ -316,7 +321,7 @@ do_export (ctrl_t ctrl, strlist_t users, int secret, unsigned int options,
   if (rc)
     return rc;
 
-  if ( opt.armor )
+  if ( opt.armor && !(options & (EXPORT_PKA_FORMAT|EXPORT_DANE_FORMAT)) )
     {
       afx = new_armor_context ();
       afx->what = secret? 5 : 1;
@@ -1245,9 +1250,8 @@ apply_keep_uid_filter (kbnode_t keyblock, recsel_expr_t selector)
         {
           if (!recsel_select (selector, filter_getval, node))
             {
-
-              log_debug ("keep-uid: deleting '%s'\n",
-                         node->pkt->pkt.user_id->name);
+              /* log_debug ("keep-uid: deleting '%s'\n", */
+              /*            node->pkt->pkt.user_id->name); */
               /* The UID packet and all following packets up to the
                * next UID or a subkey.  */
               delete_kbnode (node);
@@ -1258,14 +1262,101 @@ apply_keep_uid_filter (kbnode_t keyblock, recsel_expr_t selector)
                    node = node->next)
                 delete_kbnode (node->next);
 	    }
-          else
-            log_debug ("keep-uid: keeping '%s'\n",
-                       node->pkt->pkt.user_id->name);
+          /* else */
+          /*   log_debug ("keep-uid: keeping '%s'\n", */
+          /*              node->pkt->pkt.user_id->name); */
         }
     }
 }
 
 
+/* Print DANE or PKA records for all user IDs in KEYBLOCK to the
+ * stream FP.  The data for the record is taken from HEXDATA.  HEXFPR
+ * is the fingerprint of the primary key.  */
+static gpg_error_t
+print_pka_or_dane_records (kbnode_t keyblock, const char *hexdata,
+                           const char *hexfpr, estream_t fp,
+                           int print_pka, int print_dane)
+{
+  gpg_error_t err = 0;
+  kbnode_t kbctx, node;
+  PKT_user_id *uid;
+  char *mbox = NULL;
+  char hashbuf[32];
+  char *hash = NULL;
+  char *domain;
+  const char *s;
+  unsigned int len;
+
+  for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
+    {
+      if (node->pkt->pkttype != PKT_USER_ID)
+        continue;
+      uid = node->pkt->pkt.user_id;
+
+      if (uid->is_expired || uid->is_revoked)
+        continue;
+
+      xfree (mbox);
+      mbox = mailbox_from_userid (uid->name);
+      if (!mbox)
+        continue;
+
+      domain = strchr (mbox, '@');
+      *domain++ = 0;
+
+      if (print_pka)
+        {
+          es_fprintf (fp, "$ORIGIN _pka.%s.\n; %s\n; ", domain, hexfpr);
+          print_utf8_buffer (fp, uid->name, uid->len);
+          es_putc ('\n', fp);
+          gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf, mbox, strlen (mbox));
+          xfree (hash);
+          hash = zb32_encode (hashbuf, 8*20);
+          if (!hash)
+            {
+              err = gpg_error_from_syserror ();
+              goto leave;
+            }
+          len = strlen (hexfpr)/2;
+          es_fprintf (fp, "%s TYPE37 \\# %u 0006 0000 00 %02X %s\n\n",
+                      hash, 6 + len, len, hexfpr);
+        }
+
+      if (print_dane && hexdata)
+        {
+          es_fprintf (fp, "$ORIGIN _openpgpkey.%s.\n; %s\n; ", domain, hexfpr);
+          print_utf8_buffer (fp, uid->name, uid->len);
+          es_putc ('\n', fp);
+          gcry_md_hash_buffer (GCRY_MD_SHA256, hashbuf, mbox, strlen (mbox));
+          xfree (hash);
+          hash = bin2hex (hashbuf, 28, NULL);
+          if (!hash)
+            {
+              err = gpg_error_from_syserror ();
+              goto leave;
+            }
+          ascii_strlwr (hash);
+          len = strlen (hexdata)/2;
+          es_fprintf (fp, "%s TYPE61 \\# %u (\n", hash, len);
+          for (s = hexdata; ;)
+            {
+              es_fprintf (fp, "\t%.64s\n", s);
+              if (strlen (s) < 64)
+                break;
+              s += 64;
+            }
+          es_fputs ("\t)\n\n", fp);
+        }
+    }
+
+ leave:
+  xfree (hash);
+  xfree (mbox);
+  return err;
+}
+
+
 /* Helper for do_export_stream which writes one keyblock to OUT.  */
 static gpg_error_t
 do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
@@ -1572,6 +1663,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
   strlist_t sl;
   gcry_cipher_hd_t cipherhd = NULL;
   struct export_stats_s dummystats;
+  iobuf_t out_help = NULL;
 
   if (!stats)
     stats = &dummystats;
@@ -1581,10 +1673,14 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
   if (!kdbhd)
     return gpg_error_from_syserror ();
 
-  /* For the DANE format override the options.  */
-  if ((options & EXPORT_DANE_FORMAT))
-    options = (EXPORT_DANE_FORMAT | EXPORT_MINIMAL | EXPORT_CLEAN);
-
+  /* For the PKA and DANE format open a helper iobuf and for DANE
+   * enforce some options.  */
+  if ((options & (EXPORT_PKA_FORMAT | EXPORT_DANE_FORMAT)))
+    {
+      out_help = iobuf_temp ();
+      if ((options & EXPORT_DANE_FORMAT))
+        options |= EXPORT_MINIMAL | EXPORT_CLEAN;
+    }
 
   if (!users)
     {
@@ -1731,8 +1827,9 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
         }
 
       /* And write it. */
-      err = do_export_one_keyblock (ctrl, keyblock, keyid, out, secret,
-                                    options, stats, any,
+      err = do_export_one_keyblock (ctrl, keyblock, keyid,
+                                    out_help? out_help : out,
+                                    secret, options, stats, any,
                                     desc, ndesc, descindex, cipherhd);
       if (err)
         break;
@@ -1742,11 +1839,65 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
           *keyblock_out = keyblock;
           break;
         }
+
+      if (out_help)
+        {
+          /* We want to write PKA or DANE records.  OUT_HELP has the
+           * keyblock and we print a record for each uid to OUT. */
+          char *hexdata;
+          const void *data;
+          void *vp;
+          size_t datalen;
+          estream_t fp;
+
+          iobuf_flush_temp (out_help);
+          data = iobuf_get_temp_buffer (out_help);
+          datalen = iobuf_get_temp_length (out_help);
+          hexdata = bin2hex (data, datalen, NULL);
+          if (!hexdata)
+            {
+              err = gpg_error_from_syserror ();
+              goto leave;
+            }
+          iobuf_close (out_help);
+          out_help = iobuf_temp ();
+          ascii_strlwr (hexdata);
+          fp = es_fopenmem (0, "rw,samethread");
+          if (!fp)
+            {
+              err = gpg_error_from_syserror ();
+              xfree (hexdata);
+              goto leave;
+            }
+
+          {
+            char *hexfpr = hexfingerprint (pk, NULL, 0);
+            err = print_pka_or_dane_records (keyblock, hexdata, hexfpr, fp,
+                                             (options & EXPORT_PKA_FORMAT),
+                                             (options & EXPORT_DANE_FORMAT));
+            xfree (hexfpr);
+          }
+          xfree (hexdata);
+          if (err)
+            {
+              es_fclose (fp);
+              goto leave;
+            }
+          es_fputc (0, fp);
+          if (es_fclose_snatch (fp, &vp, NULL))
+            {
+              err = gpg_error_from_syserror ();
+              goto leave;
+            }
+          iobuf_writestr (out, vp);
+        }
+
     }
   if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
     err = 0;
 
  leave:
+  iobuf_cancel (out_help);
   gcry_cipher_close (cipherhd);
   xfree(desc);
   keydb_release (kdbhd);
diff --git a/g10/keylist.c b/g10/keylist.c
index e595fe3..b8f97f5 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -921,7 +921,7 @@ list_keyblock_pka (ctrl_t ctrl, kbnode_t keyblock)
       /* We do not have an export function which allows to pass a
          keyblock, thus we need to search the key again.  */
       err = export_pubkey_buffer (ctrl, hexfpr,
-                                  EXPORT_DANE_FORMAT, NULL,
+                                  (EXPORT_MINIMAL | EXPORT_CLEAN), NULL,
                                   &dummy_keyblock, &data, &datalen);
       release_kbnode (dummy_keyblock);
       if (!err)
diff --git a/g10/options.h b/g10/options.h
index fc333cd..2b3cabd 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -348,7 +348,8 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
 #define EXPORT_RESET_SUBKEY_PASSWD       (1<<3)
 #define EXPORT_MINIMAL                   (1<<4)
 #define EXPORT_CLEAN                     (1<<5)
-#define EXPORT_DANE_FORMAT               (1<<6)
+#define EXPORT_PKA_FORMAT                (1<<6)
+#define EXPORT_DANE_FORMAT               (1<<7)
 
 #define LIST_SHOW_PHOTOS                 (1<<0)
 #define LIST_SHOW_POLICY_URLS            (1<<1)

commit b05878f32aa507aa9087d7c992b630840b5ad71c
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Jul 7 14:16:21 2016 +0200

    gpg: Split a too large export function.
    
    * g10/export.c (do_export_stream): Factor some code out to ...
    (do_export_one_keyblock): new.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/g10/export.c b/g10/export.c
index 2a50b32..c5b7328 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -1266,8 +1266,290 @@ apply_keep_uid_filter (kbnode_t keyblock, recsel_expr_t selector)
 }
 
 
+/* Helper for do_export_stream which writes one keyblock to OUT.  */
+static gpg_error_t
+do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
+                        iobuf_t out, int secret, unsigned int options,
+                        export_stats_t stats, int *any,
+                        KEYDB_SEARCH_DESC *desc, size_t ndesc,
+                        size_t descindex, gcry_cipher_hd_t cipherhd)
+{
+  gpg_error_t err;
+  char *cache_nonce = NULL;
+  subkey_list_t subkey_list = NULL;  /* Track already processed subkeys. */
+  int skip_until_subkey = 0;
+  int cleartext = 0;
+  char *hexgrip = NULL;
+  char *serialno = NULL;
+  PKT_public_key *pk;
+  u32 subkidbuf[2], *subkid;
+  kbnode_t kbctx, node;
+
+  for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
+    {
+      if (skip_until_subkey)
+        {
+          if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
+            skip_until_subkey = 0;
+          else
+            continue;
+        }
+
+      /* We used to use comment packets, but not any longer.  In
+       * case we still have comments on a key, strip them here
+       * before we call build_packet(). */
+      if (node->pkt->pkttype == PKT_COMMENT)
+        continue;
+
+      /* Make sure that ring_trust packets never get exported. */
+      if (node->pkt->pkttype == PKT_RING_TRUST)
+        continue;
+
+      /* If exact is set, then we only export what was requested
+       * (plus the primary key, if the user didn't specifically
+       * request it). */
+      if (desc[descindex].exact && node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
+        {
+          if (!exact_subkey_match_p (desc+descindex, node))
+            {
+              /* Before skipping this subkey, check whether any
+               * other description wants an exact match on a
+               * subkey and include that subkey into the output
+               * too.  Need to add this subkey to a list so that
+               * it won't get processed a second time.
+               *
+               * So the first step here is to check that list and
+               * skip in any case if the key is in that list.
+               *
+               * We need this whole mess because the import
+               * function of GnuPG < 2.1 is not able to merge
+               * secret keys and thus it is useless to output them
+               * as two separate keys and have import merge them.
+               */
+              if (subkey_in_list_p (subkey_list, node))
+                skip_until_subkey = 1; /* Already processed this one. */
+              else
+                {
+                  size_t j;
+
+                  for (j=0; j < ndesc; j++)
+                    if (j != descindex && desc[j].exact
+                        && exact_subkey_match_p (desc+j, node))
+                      break;
+                  if (!(j < ndesc))
+                    skip_until_subkey = 1; /* No other one matching. */
+                }
+            }
+
+          if (skip_until_subkey)
+            continue;
+
+          /* Mark this one as processed. */
+          {
+            subkey_list_t tmp = new_subkey_list_item (node);
+            tmp->next = subkey_list;
+            subkey_list = tmp;
+          }
+        }
+
+      if (node->pkt->pkttype == PKT_SIGNATURE)
+        {
+          /* Do not export packets which are marked as not
+           * exportable.  */
+          if (!(options & EXPORT_LOCAL_SIGS)
+              && !node->pkt->pkt.signature->flags.exportable)
+            continue; /* not exportable */
+
+          /* Do not export packets with a "sensitive" revocation key
+           * unless the user wants us to.  Note that we do export
+           * these when issuing the actual revocation (see revoke.c). */
+          if (!(options & EXPORT_SENSITIVE_REVKEYS)
+              && node->pkt->pkt.signature->revkey)
+            {
+              int i;
+
+              for (i = 0; i < node->pkt->pkt.signature->numrevkeys; i++)
+                if ((node->pkt->pkt.signature->revkey[i].class & 0x40))
+                  break;
+              if (i < node->pkt->pkt.signature->numrevkeys)
+                continue;
+            }
+        }
+
+      /* Don't export attribs? */
+      if (!(options & EXPORT_ATTRIBUTES)
+          && node->pkt->pkttype == PKT_USER_ID
+          && node->pkt->pkt.user_id->attrib_data)
+        {
+          /* Skip until we get to something that is not an attrib or a
+           * signature on an attrib.  */
+          while (kbctx->next && kbctx->next->pkt->pkttype == PKT_SIGNATURE)
+            kbctx = kbctx->next;
+
+          continue;
+        }
+
+      if (secret && (node->pkt->pkttype == PKT_PUBLIC_KEY
+                     || node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
+        {
+          pk = node->pkt->pkt.public_key;
+          if (node->pkt->pkttype == PKT_PUBLIC_KEY)
+            subkid = NULL;
+          else
+            {
+              keyid_from_pk (pk, subkidbuf);
+              subkid = subkidbuf;
+            }
+
+          if (pk->seckey_info)
+            {
+              log_error ("key %s: oops: seckey_info already set"
+                         " - skipped\n", keystr_with_sub (keyid, subkid));
+              skip_until_subkey = 1;
+              continue;
+            }
+
+          xfree (hexgrip);
+          err = hexkeygrip_from_pk (pk, &hexgrip);
+          if (err)
+            {
+              log_error ("key %s: error computing keygrip: %s"
+                         " - skipped\n", keystr_with_sub (keyid, subkid),
+                         gpg_strerror (err));
+              skip_until_subkey = 1;
+              err = 0;
+              continue;
+            }
+
+          xfree (serialno);
+          serialno = NULL;
+          if (secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
+            {
+              /* We are asked not to export the secret parts of the
+               * primary key.  Make up an error code to create the
+               * stub.  */
+              err = GPG_ERR_NOT_FOUND;
+            }
+          else
+            err = agent_get_keyinfo (ctrl, hexgrip, &serialno, &cleartext);
+
+          if ((!err && serialno)
+              && secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
+            {
+              /* It does not make sense to export a key with its
+               * primary key on card using a non-key stub.  Thus we
+               * skip those keys when used with --export-secret-subkeys. */
+              log_info (_("key %s: key material on-card - skipped\n"),
+                        keystr_with_sub (keyid, subkid));
+              skip_until_subkey = 1;
+            }
+          else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND
+                   || (!err && serialno))
+            {
+              /* Create a key stub.  */
+              struct seckey_info *ski;
+              const char *s;
+
+              pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
+              if (!ski)
+                {
+                  err = gpg_error_from_syserror ();
+                  goto leave;
+                }
+
+              ski->is_protected = 1;
+              if (err)
+                ski->s2k.mode = 1001; /* GNU dummy (no secret key).  */
+              else
+                {
+                  ski->s2k.mode = 1002; /* GNU-divert-to-card.  */
+                  for (s=serialno; sizeof (ski->ivlen) && *s && s[1];
+                       ski->ivlen++, s += 2)
+                    ski->iv[ski->ivlen] = xtoi_2 (s);
+                }
+
+              err = build_packet (out, node->pkt);
+              if (!err && node->pkt->pkttype == PKT_PUBLIC_KEY)
+                {
+                  stats->exported++;
+                  print_status_exported (node->pkt->pkt.public_key);
+                }
+            }
+          else if (!err)
+            {
+              err = receive_seckey_from_agent (ctrl, cipherhd,
+                                               cleartext, &cache_nonce,
+                                               hexgrip, pk);
+              if (err)
+                {
+                  if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
+                    goto leave;
+                  skip_until_subkey = 1;
+                  err = 0;
+                }
+              else
+                {
+                  err = build_packet (out, node->pkt);
+                  if (node->pkt->pkttype == PKT_PUBLIC_KEY)
+                    {
+                      stats->exported++;
+                      print_status_exported (node->pkt->pkt.public_key);
+                    }
+                }
+            }
+          else
+            {
+              log_error ("key %s: error getting keyinfo from agent: %s"
+                         " - skipped\n", keystr_with_sub (keyid, subkid),
+                             gpg_strerror (err));
+              skip_until_subkey = 1;
+              err = 0;
+            }
+
+          xfree (pk->seckey_info);
+          pk->seckey_info = NULL;
+          {
+            int i;
+            for (i = pubkey_get_npkey (pk->pubkey_algo);
+                 i < pubkey_get_nskey (pk->pubkey_algo); i++)
+              {
+                gcry_mpi_release (pk->pkey[i]);
+                pk->pkey[i] = NULL;
+              }
+          }
+        }
+      else /* Not secret or common packets.  */
+        {
+          err = build_packet (out, node->pkt);
+          if (!err && node->pkt->pkttype == PKT_PUBLIC_KEY)
+            {
+              stats->exported++;
+              print_status_exported (node->pkt->pkt.public_key);
+            }
+        }
+
+      if (err)
+        {
+          log_error ("build_packet(%d) failed: %s\n",
+                     node->pkt->pkttype, gpg_strerror (err));
+          goto leave;
+        }
+
+      if (!skip_until_subkey)
+        *any = 1;
+    }
+
+ leave:
+  release_subkey_list (subkey_list);
+  xfree (serialno);
+  xfree (hexgrip);
+  xfree (cache_nonce);
+  return err;
+}
+
+
 /* Export the keys identified by the list of strings in USERS to the
-   stream OUT.  If Secret is false public keys will be exported.  With
+   stream OUT.  If SECRET is false public keys will be exported.  With
    secret true secret keys will be exported; in this case 1 means the
    entire secret keyblock and 2 only the subkeys.  OPTIONS are the
    export options to apply.  If KEYBLOCK_OUT is not NULL, AND the exit
@@ -1282,17 +1564,14 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
 {
   gpg_error_t err = 0;
   PACKET pkt;
-  KBNODE keyblock = NULL;
-  KBNODE kbctx, node;
+  kbnode_t keyblock = NULL;
+  kbnode_t node;
   size_t ndesc, descindex;
   KEYDB_SEARCH_DESC *desc = NULL;
-  subkey_list_t subkey_list = NULL;  /* Track already processed subkeys. */
   KEYDB_HANDLE kdbhd;
   strlist_t sl;
   gcry_cipher_hd_t cipherhd = NULL;
-  char *cache_nonce = NULL;
   struct export_stats_s dummystats;
-  int cleartext = 0;
 
   if (!stats)
     stats = &dummystats;
@@ -1377,7 +1656,6 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
 
   for (;;)
     {
-      int skip_until_subkey = 0;
       u32 keyid[2];
       PKT_public_key *pk;
 
@@ -1453,268 +1731,11 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
         }
 
       /* And write it. */
-      xfree (cache_nonce);
-      cache_nonce = NULL;
-      for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
-        {
-          if (skip_until_subkey)
-            {
-              if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
-                skip_until_subkey = 0;
-              else
-                continue;
-            }
-
-          /* We used to use comment packets, but not any longer.  In
-             case we still have comments on a key, strip them here
-             before we call build_packet(). */
-          if (node->pkt->pkttype == PKT_COMMENT)
-            continue;
-
-          /* Make sure that ring_trust packets never get exported. */
-          if (node->pkt->pkttype == PKT_RING_TRUST)
-            continue;
-
-          /* If exact is set, then we only export what was requested
-             (plus the primary key, if the user didn't specifically
-             request it). */
-          if (desc[descindex].exact
-              && node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
-            {
-              if (!exact_subkey_match_p (desc+descindex, node))
-                {
-                  /* Before skipping this subkey, check whether any
-                     other description wants an exact match on a
-                     subkey and include that subkey into the output
-                     too.  Need to add this subkey to a list so that
-                     it won't get processed a second time.
-
-                     So the first step here is to check that list and
-                     skip in any case if the key is in that list.
-
-                     We need this whole mess because the import
-                     function of GnuPG < 2.1 is not able to merge
-                     secret keys and thus it is useless to output them
-                     as two separate keys and have import merge them.  */
-                  if (subkey_in_list_p (subkey_list, node))
-                    skip_until_subkey = 1; /* Already processed this one. */
-                  else
-                    {
-                      size_t j;
-
-                      for (j=0; j < ndesc; j++)
-                        if (j != descindex && desc[j].exact
-                            && exact_subkey_match_p (desc+j, node))
-                          break;
-                      if (!(j < ndesc))
-                        skip_until_subkey = 1; /* No other one matching. */
-                    }
-                }
-
-              if(skip_until_subkey)
-                continue;
-
-              /* Mark this one as processed. */
-              {
-                subkey_list_t tmp = new_subkey_list_item (node);
-                tmp->next = subkey_list;
-                subkey_list = tmp;
-              }
-            }
-
-          if (node->pkt->pkttype == PKT_SIGNATURE)
-            {
-              /* Do not export packets which are marked as not
-                 exportable.  */
-              if (!(options&EXPORT_LOCAL_SIGS)
-                  && !node->pkt->pkt.signature->flags.exportable)
-                continue; /* not exportable */
-
-              /* Do not export packets with a "sensitive" revocation
-                 key unless the user wants us to.  Note that we do
-                 export these when issuing the actual revocation
-                 (see revoke.c). */
-              if (!(options&EXPORT_SENSITIVE_REVKEYS)
-                  && node->pkt->pkt.signature->revkey)
-                {
-                  int i;
-
-                  for (i=0;i<node->pkt->pkt.signature->numrevkeys;i++)
-                    if ( (node->pkt->pkt.signature->revkey[i].class & 0x40))
-                      break;
-
-                  if (i < node->pkt->pkt.signature->numrevkeys)
-                    continue;
-                }
-            }
-
-          /* Don't export attribs? */
-          if (!(options&EXPORT_ATTRIBUTES)
-              && node->pkt->pkttype == PKT_USER_ID
-              && node->pkt->pkt.user_id->attrib_data )
-            {
-	      /* Skip until we get to something that is not an attrib
-		 or a signature on an attrib */
-	      while (kbctx->next && kbctx->next->pkt->pkttype==PKT_SIGNATURE)
-                kbctx = kbctx->next;
-
-	      continue;
-	    }
-
-          if (secret && (node->pkt->pkttype == PKT_PUBLIC_KEY
-                         || node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
-            {
-              u32 subkidbuf[2], *subkid;
-              char *hexgrip, *serialno;
-
-              pk = node->pkt->pkt.public_key;
-              if (node->pkt->pkttype == PKT_PUBLIC_KEY)
-                subkid = NULL;
-              else
-                {
-                  keyid_from_pk (pk, subkidbuf);
-                  subkid = subkidbuf;
-                }
-
-              if (pk->seckey_info)
-                {
-                  log_error ("key %s: oops: seckey_info already set"
-                             " - skipped\n", keystr_with_sub (keyid, subkid));
-                  skip_until_subkey = 1;
-                  continue;
-                }
-
-              err = hexkeygrip_from_pk (pk, &hexgrip);
-              if (err)
-                {
-                  log_error ("key %s: error computing keygrip: %s"
-                             " - skipped\n", keystr_with_sub (keyid, subkid),
-                             gpg_strerror (err));
-                  skip_until_subkey = 1;
-                  err = 0;
-                  continue;
-                }
-
-              if (secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
-                {
-                  /* We are asked not to export the secret parts of
-                     the primary key.  Make up an error code to create
-                     the stub.  */
-                  err = GPG_ERR_NOT_FOUND;
-                  serialno = NULL;
-                }
-              else
-                err = agent_get_keyinfo (ctrl, hexgrip, &serialno, &cleartext);
-
-              if ((!err && serialno)
-                  && secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
-                {
-                  /* It does not make sense to export a key with its
-                     primary key on card using a non-key stub.  Thus
-                     we skip those keys when used with
-                     --export-secret-subkeys. */
-                  log_info (_("key %s: key material on-card - skipped\n"),
-                            keystr_with_sub (keyid, subkid));
-                  skip_until_subkey = 1;
-                }
-              else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND
-                       || (!err && serialno))
-                {
-                  /* Create a key stub.  */
-                  struct seckey_info *ski;
-                  const char *s;
-
-                  pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
-                  if (!ski)
-                    {
-                      err = gpg_error_from_syserror ();
-                      xfree (hexgrip);
-                      goto leave;
-                    }
-
-                  ski->is_protected = 1;
-                  if (err)
-                    ski->s2k.mode = 1001; /* GNU dummy (no secret key).  */
-                  else
-                    {
-                      ski->s2k.mode = 1002; /* GNU-divert-to-card.  */
-                      for (s=serialno; sizeof (ski->ivlen) && *s && s[1];
-                           ski->ivlen++, s += 2)
-                        ski->iv[ski->ivlen] = xtoi_2 (s);
-                    }
-
-                  err = build_packet (out, node->pkt);
-                  if (!err && node->pkt->pkttype == PKT_PUBLIC_KEY)
-                    {
-                      stats->exported++;
-                      print_status_exported (node->pkt->pkt.public_key);
-                    }
-                }
-              else if (!err)
-                {
-                  err = receive_seckey_from_agent (ctrl, cipherhd,
-                                                   cleartext, &cache_nonce,
-                                                   hexgrip, pk);
-                  if (err)
-                    {
-                      if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
-                        goto leave;
-                      skip_until_subkey = 1;
-                      err = 0;
-                    }
-                  else
-                    {
-                      err = build_packet (out, node->pkt);
-                      if (node->pkt->pkttype == PKT_PUBLIC_KEY)
-                        {
-                          stats->exported++;
-                          print_status_exported (node->pkt->pkt.public_key);
-                        }
-                    }
-                }
-              else
-                {
-                  log_error ("key %s: error getting keyinfo from agent: %s"
-                             " - skipped\n", keystr_with_sub (keyid, subkid),
-                             gpg_strerror (err));
-                  skip_until_subkey = 1;
-                  err = 0;
-                }
-
-              xfree (pk->seckey_info);
-              pk->seckey_info = NULL;
-              {
-                int i;
-                for (i = pubkey_get_npkey (pk->pubkey_algo);
-                     i < pubkey_get_nskey (pk->pubkey_algo); i++)
-                  {
-                    gcry_mpi_release (pk->pkey[i]);
-                    pk->pkey[i] = NULL;
-                  }
-              }
-              xfree (hexgrip);
-            }
-          else
-            {
-              err = build_packet (out, node->pkt);
-              if (!err && node->pkt->pkttype == PKT_PUBLIC_KEY)
-                {
-                  stats->exported++;
-                  print_status_exported (node->pkt->pkt.public_key);
-                }
-            }
-
-
-          if (err)
-            {
-              log_error ("build_packet(%d) failed: %s\n",
-                         node->pkt->pkttype, gpg_strerror (err));
-              goto leave;
-	    }
-
-          if (!skip_until_subkey)
-            *any = 1;
-	}
+      err = do_export_one_keyblock (ctrl, keyblock, keyid, out, secret,
+                                    options, stats, any,
+                                    desc, ndesc, descindex, cipherhd);
+      if (err)
+        break;
 
       if (keyblock_out)
         {
@@ -1727,12 +1748,10 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
 
  leave:
   gcry_cipher_close (cipherhd);
-  release_subkey_list (subkey_list);
   xfree(desc);
   keydb_release (kdbhd);
   if (err || !keyblock_out)
     release_kbnode( keyblock );
-  xfree (cache_nonce);
   if( !*any )
     log_info(_("WARNING: nothing exported\n"));
   return err;

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

Summary of changes:
 doc/gpg.texi  |  12 +
 g10/export.c  | 720 ++++++++++++++++++++++++++++++++++++----------------------
 g10/keylist.c |   2 +-
 g10/options.h |   3 +-
 4 files changed, 460 insertions(+), 277 deletions(-)


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




More information about the Gnupg-commits mailing list