gpg: Extend import-option import-export to print PKA or DANE.
authorWerner Koch <wk@gnupg.org>
Tue, 12 Jul 2016 13:09:18 +0000 (15:09 +0200)
committerWerner Koch <wk@gnupg.org>
Tue, 12 Jul 2016 13:13:34 +0000 (15:13 +0200)
* g10/export.c (do_export_stream): Move PKA and DANE printing helper
code to ...
(print_pka_or_dane_records): this fucntion.
(write_keyblock_to_output): Add arg OPTIOSN and call
print_pka_or_dane_records if requested.
--

It is now possible to print a DANE record given a a file with a key
without importing the key first:

  gpg --export-options export-dane \
      --import-options import-export \
      --import-filter keep-uid='mbox =~ alpha' \
      --import FILE_WITH_KEY

Using the filter we only print a user id with the substring "alpha" in
the addr-spec.

Signed-off-by: Werner Koch <wk@gnupg.org>
g10/export.c
g10/import.c
g10/main.h

index 3ce8185..92235fb 100644 (file)
@@ -77,6 +77,10 @@ static int do_export_stream (ctrl_t ctrl, iobuf_t out,
                              strlist_t users, int secret,
                              kbnode_t *keyblock_out, unsigned int options,
                             export_stats_t stats, int *any);
+static gpg_error_t print_pka_or_dane_records
+/**/                 (iobuf_t out, kbnode_t keyblock, PKT_public_key *pk,
+                      const void *data, size_t datalen,
+                      int print_pka, int print_dane);
 
 \f
 static void
@@ -1204,15 +1208,19 @@ receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
 
 
 /* Write KEYBLOCK either to stdout or to the file set with the
- * --output option.  */
+ * --output option.  This is a simplified version of do_export_stream
+ * which supports only a few export options.  */
 gpg_error_t
-write_keyblock_to_output (kbnode_t keyblock, int with_armor)
+write_keyblock_to_output (kbnode_t keyblock, int with_armor,
+                          unsigned int options)
 {
   gpg_error_t err;
   const char *fname;
   iobuf_t out;
   kbnode_t node;
   armor_filter_context_t *afx = NULL;
+  iobuf_t out_help = NULL;
+  PKT_public_key *pk = NULL;
 
   fname = opt.outfile? opt.outfile : "-";
   if (is_secured_filename (fname) )
@@ -1228,6 +1236,12 @@ write_keyblock_to_output (kbnode_t keyblock, int with_armor)
   if (opt.verbose)
     log_info (_("writing to '%s'\n"), iobuf_get_fname_nonnull (out));
 
+  if ((options & (EXPORT_PKA_FORMAT|EXPORT_DANE_FORMAT)))
+    {
+      with_armor = 0;
+      out_help = iobuf_temp ();
+    }
+
   if (with_armor)
     {
       afx = new_armor_context ();
@@ -1237,24 +1251,43 @@ write_keyblock_to_output (kbnode_t keyblock, int with_armor)
 
   for (node = keyblock; node; node = node->next)
     {
-      if (!is_deleted_kbnode (node) && node->pkt->pkttype != PKT_RING_TRUST)
-       {
-         err = build_packet (out, node->pkt);
-         if (err)
-           {
-             log_error ("build_packet(%d) failed: %s\n",
-                        node->pkt->pkttype, gpg_strerror (err) );
-             goto leave;
-           }
-       }
+      if (is_deleted_kbnode (node) || node->pkt->pkttype == PKT_RING_TRUST)
+        continue;
+      if (!pk && (node->pkt->pkttype == PKT_PUBLIC_KEY
+                  || node->pkt->pkttype == PKT_SECRET_KEY))
+        pk = node->pkt->pkt.public_key;
+
+      err = build_packet (out_help? out_help : out, node->pkt);
+      if (err)
+        {
+          log_error ("build_packet(%d) failed: %s\n",
+                     node->pkt->pkttype, gpg_strerror (err) );
+          goto leave;
+        }
     }
   err = 0;
 
+  if (out_help && pk)
+    {
+      const void *data;
+      size_t datalen;
+
+      iobuf_flush_temp (out_help);
+      data = iobuf_get_temp_buffer (out_help);
+      datalen = iobuf_get_temp_length (out_help);
+
+      err = print_pka_or_dane_records (out,
+                                       keyblock, pk, data, datalen,
+                                       (options & EXPORT_PKA_FORMAT),
+                                       (options & EXPORT_DANE_FORMAT));
+    }
+
  leave:
   if (err)
     iobuf_cancel (out);
   else
     iobuf_close (out);
+  iobuf_cancel (out_help);
   release_armor_context (afx);
   return err;
 }
@@ -1327,12 +1360,12 @@ apply_keep_uid_filter (kbnode_t keyblock, recsel_expr_t selector)
 }
 
 
-/* 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.  */
+/* Print DANE or PKA records for all user IDs in KEYBLOCK to OUT.  The
+ * data for the record is taken from (DATA,DATELEN).  PK is the public
+ * key packet with the primary key. */
 static gpg_error_t
-print_pka_or_dane_records (kbnode_t keyblock, const char *hexdata,
-                           const char *hexfpr, estream_t fp,
+print_pka_or_dane_records (iobuf_t out, kbnode_t keyblock, PKT_public_key *pk,
+                           const void *data, size_t datalen,
                            int print_pka, int print_dane)
 {
   gpg_error_t err = 0;
@@ -1344,6 +1377,24 @@ print_pka_or_dane_records (kbnode_t keyblock, const char *hexdata,
   char *domain;
   const char *s;
   unsigned int len;
+  estream_t fp = NULL;
+  char *hexdata = NULL;
+  char *hexfpr;
+
+  hexfpr = hexfingerprint (pk, NULL, 0);
+  hexdata = bin2hex (data, datalen, NULL);
+  if (!hexdata)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+  ascii_strlwr (hexdata);
+  fp = es_fopenmem (0, "rw,samethread");
+  if (!fp)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
 
   for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
     {
@@ -1407,9 +1458,28 @@ print_pka_or_dane_records (kbnode_t keyblock, const char *hexdata,
         }
     }
 
+  /* Make sure it is a string and write it.  */
+  es_fputc (0, fp);
+  {
+    void *vp;
+
+    if (es_fclose_snatch (fp, &vp, NULL))
+      {
+        err = gpg_error_from_syserror ();
+        goto leave;
+      }
+    fp = NULL;
+    iobuf_writestr (out, vp);
+    es_free (vp);
+  }
+  err = 0;
+
  leave:
   xfree (hash);
   xfree (mbox);
+  es_fclose (fp);
+  xfree (hexdata);
+  xfree (hexfpr);
   return err;
 }
 
@@ -1901,52 +1971,22 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
         {
           /* 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);
+          err = print_pka_or_dane_records (out,
+                                           keyblock, pk, data, datalen,
+                                           (options & EXPORT_PKA_FORMAT),
+                                           (options & EXPORT_DANE_FORMAT));
           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);
+            goto leave;
+
+          iobuf_close (out_help);
+          out_help = iobuf_temp ();
         }
 
     }
index 371f095..375bd03 100644 (file)
@@ -1330,7 +1330,7 @@ import_one (ctrl_t ctrl,
           merge_keys_and_selfsig (keyblock);
           merge_keys_done = 1;
         }
-      rc = write_keyblock_to_output (keyblock, opt.armor);
+      rc = write_keyblock_to_output (keyblock, opt.armor, opt.export_options);
       goto leave;
     }
 
index 92a26a7..0956f66 100644 (file)
@@ -400,7 +400,8 @@ gpg_error_t receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
                                        const char *hexgrip,
                                        PKT_public_key *pk);
 
-gpg_error_t write_keyblock_to_output (kbnode_t keyblock, int with_armor);
+gpg_error_t write_keyblock_to_output (kbnode_t keyblock,
+                                      int with_armor, unsigned int options);
 
 gpg_error_t export_ssh_key (ctrl_t ctrl, const char *userid);