gpg: Add option --print-dane-records.
authorWerner Koch <wk@gnupg.org>
Thu, 8 Oct 2015 13:04:45 +0000 (15:04 +0200)
committerWerner Koch <wk@gnupg.org>
Thu, 8 Oct 2015 13:40:53 +0000 (15:40 +0200)
* g10/options.h (opt): Add field "print_dane_records".
* g10/gpg.c (oPrintDANERecords): new.
(opts): Add --print-dane-records.
(main): Set that option.
* g10/export.c (do_export): Remove EXPORT_DANE_FORMAT handling.
(do_export_stream): Add EXPORT_DANE_FORMAT handling.
* g10/keylist.c (list_keyblock_pka): Implement DANE record printing.

* g10/gpgv.c (export_pubkey_buffer): New stub.
* g10/test-stubs.c (export_pubkey_buffer): New stub.

Signed-off-by: Werner Koch <wk@gnupg.org>
doc/gpg.texi
g10/export.c
g10/gpg.c
g10/gpgv.c
g10/keylist.c
g10/options.h
g10/test-stubs.c

index 980d326..35291a8 100644 (file)
@@ -2039,6 +2039,13 @@ Modify the output of the list commands to print 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 --print-dane-records
+@opindex print-dane-records
+Modify the output of the list commands to print 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.
+
 @item --fixed-list-mode
 @opindex fixed-list-mode
 Do not merge primary user ID and primary key in @option{--with-colon}
index 94a3256..2e9e61c 100644 (file)
@@ -198,15 +198,11 @@ do_export (ctrl_t ctrl, strlist_t users, int secret, unsigned int options )
   if (rc)
     return rc;
 
-  /* We don't want an Armor for DANE format.  */
-  if (!(options & EXPORT_DANE_FORMAT))
+  if ( opt.armor )
     {
-      if ( opt.armor )
-        {
-          afx = new_armor_context ();
-          afx->what = secret? 5 : 1;
-          push_armor_filter (afx, out);
-        }
+      afx = new_armor_context ();
+      afx->what = secret? 5 : 1;
+      push_armor_filter (afx, out);
     }
 
   rc = do_export_stream (ctrl, out, users, secret, NULL, options, &any );
@@ -776,6 +772,11 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
   init_packet (&pkt);
   kdbhd = keydb_new ();
 
+  /* For the DANE format override the options.  */
+  if ((options & EXPORT_DANE_FORMAT))
+    options = (EXPORT_DANE_FORMAT | EXPORT_MINIMAL | EXPORT_CLEAN);
+
+
   if (!users)
     {
       ndesc = 1;
index 557eeec..39cc2e5 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -384,6 +384,7 @@ enum cmd_and_opt_values
     oFakedSystemTime,
     oNoAutostart,
     oPrintPKARecords,
+    oPrintDANERecords,
 
     oNoop
   };
@@ -716,6 +717,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oLegacyListMode, "legacy-list-mode", "@"),
   ARGPARSE_s_n (oListOnly, "list-only", "@"),
   ARGPARSE_s_n (oPrintPKARecords, "print-pka-records", "@"),
+  ARGPARSE_s_n (oPrintDANERecords, "print-dane-records", "@"),
   ARGPARSE_s_n (oIgnoreTimeConflict, "ignore-time-conflict", "@"),
   ARGPARSE_s_n (oIgnoreValidFrom,    "ignore-valid-from", "@"),
   ARGPARSE_s_n (oIgnoreCrcError, "ignore-crc-error", "@"),
@@ -2998,6 +3000,7 @@ main (int argc, char **argv)
          case oFixedListMode: /* Dummy */ break;
           case oLegacyListMode: opt.legacy_list_mode = 1; break;
          case oPrintPKARecords: opt.print_pka_records = 1; break;
+         case oPrintDANERecords: opt.print_dane_records = 1; break;
          case oListOnly: opt.list_only=1; break;
          case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
          case oIgnoreValidFrom: opt.ignore_valid_from = 1; break;
index 412f4be..8bb3fc4 100644 (file)
@@ -592,3 +592,17 @@ gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
     *r_url = NULL;
   return gpg_error (GPG_ERR_NOT_FOUND);
 }
+
+gpg_error_t
+export_pubkey_buffer (ctrl_t ctrl, const char *keyspec, unsigned int options,
+                      kbnode_t *r_keyblock, void **r_data, size_t *r_datalen)
+{
+  (void)ctrl;
+  (void)keyspec;
+  (void)options;
+
+  *r_keyblock = NULL;
+  *r_data = NULL;
+  *r_datalen = 0;
+  return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+}
index 192ced7..3814f1c 100644 (file)
@@ -847,6 +847,9 @@ list_keyblock_pka (ctrl_t ctrl, kbnode_t keyblock)
   PKT_public_key *pk;
   char pkstrbuf[PUBKEY_STRING_SIZE];
   char *hexfpr;
+  char *hexkeyblock = NULL;
+  unsigned int hexkeyblocklen;
+  const char *s;
 
   /* Get the keyid from the keyblock.  */
   node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
@@ -859,11 +862,55 @@ list_keyblock_pka (ctrl_t ctrl, kbnode_t keyblock)
 
   pk = node->pkt->pkt.public_key;
 
-  es_fprintf (es_stdout, ";; pub  %s/%s %s\n;; ",
+  /* First print an overview of the key with all userids.  */
+  es_fprintf (es_stdout, ";; pub  %s/%s %s\n;;",
               pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
               keystr_from_pk (pk), datestr_from_pk (pk));
   print_fingerprint (NULL, pk, 10);
+  for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
+    {
+      if (node->pkt->pkttype == PKT_USER_ID)
+       {
+         PKT_user_id *uid = node->pkt->pkt.user_id;
+
+         if (pk && (uid->is_expired || uid->is_revoked)
+             && !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
+            continue;
+
+          es_fputs (";; uid  ", es_stdout);
+          print_utf8_buffer (es_stdout, uid->name, uid->len);
+          es_putc ('\n', es_stdout);
+        }
+    }
+
+
   hexfpr = hexfingerprint (pk);
+  if (opt.print_dane_records)
+    {
+      kbnode_t dummy_keyblock;
+      void *data;
+      size_t datalen;
+      gpg_error_t err;
+
+      /* We do not have an export fucntion which allows to pass a
+         keyblock, thus we need to search the key again.  */
+      err = export_pubkey_buffer (ctrl, hexfpr,
+                                  EXPORT_DANE_FORMAT,
+                                  &dummy_keyblock, &data, &datalen);
+      release_kbnode (dummy_keyblock);
+      if (!err)
+        {
+          hexkeyblocklen = datalen;
+          hexkeyblock = bin2hex (data, datalen, NULL);
+          if (!hexkeyblock)
+            err = gpg_error_from_syserror ();
+          xfree (data);
+          ascii_strlwr (hexkeyblock);
+        }
+      if (err)
+        log_error (_("skipped \"%s\": %s\n"), hexfpr, gpg_strerror (err));
+
+    }
 
   for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
     {
@@ -877,27 +924,57 @@ list_keyblock_pka (ctrl_t ctrl, kbnode_t keyblock)
              && !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
             continue;
 
-          es_fputs (";; uid  ", es_stdout);
-          print_utf8_buffer (es_stdout, uid->name, uid->len);
-         es_putc ('\n', es_stdout);
           mbox = mailbox_from_userid (uid->name);
           if (mbox && (p = strchr (mbox, '@')))
             {
-              char hashbuf[20];
+              char hashbuf[32];
               char *hash;
               unsigned int len;
 
               *p++ = 0;
-              es_fprintf (es_stdout, "$ORIGIN _pka.%s.\n", p);
-              gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf, mbox, strlen (mbox));
-              hash = zb32_encode (hashbuf, 8*20);
-              if (hash)
+              if (opt.print_pka_records)
                 {
-                  len = strlen (hexfpr)/2;
-                  es_fprintf (es_stdout,
-                              "%s TYPE37 \\# %u 0006 0000 00 %02X %s\n",
-                              hash, 6 + len, len, hexfpr);
-                  xfree (hash);
+                  es_fprintf (es_stdout, "$ORIGIN _pka.%s.\n; %s\n; ",
+                              p, hexfpr);
+                  print_utf8_buffer (es_stdout, uid->name, uid->len);
+                  es_putc ('\n', es_stdout);
+                  gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf,
+                                       mbox, strlen (mbox));
+                  hash = zb32_encode (hashbuf, 8*20);
+                  if (hash)
+                    {
+                      len = strlen (hexfpr)/2;
+                      es_fprintf (es_stdout,
+                                  "%s TYPE37 \\# %u 0006 0000 00 %02X %s\n",
+                                  hash, 6 + len, len, hexfpr);
+                      xfree (hash);
+                    }
+                }
+              if (opt.print_dane_records && hexkeyblock)
+                {
+                  es_fprintf (es_stdout, "$ORIGIN _openpgpkey.%s.\n; %s\n; ",
+                              p, hexfpr);
+                  print_utf8_buffer (es_stdout, uid->name, uid->len);
+                  es_putc ('\n', es_stdout);
+                  gcry_md_hash_buffer (GCRY_MD_SHA256, hashbuf,
+                                       mbox, strlen (mbox));
+                  hash = bin2hex (hashbuf, 28, NULL);
+                  if (hash)
+                    {
+                      ascii_strlwr (hash);
+                      es_fprintf (es_stdout, "%s TYPE61 \\# %u (\n",
+                                  hash, hexkeyblocklen);
+                      xfree (hash);
+                      s = hexkeyblock;
+                      for (;;)
+                        {
+                          es_fprintf (es_stdout, "\t%.64s\n", s);
+                          if (strlen (s) < 64)
+                            break;
+                          s += 64;
+                        }
+                      es_fputs ("\t)\n", es_stdout);
+                    }
                 }
             }
           xfree (mbox);
@@ -906,6 +983,7 @@ list_keyblock_pka (ctrl_t ctrl, kbnode_t keyblock)
     }
   es_putc ('\n', es_stdout);
 
+  xfree (hexkeyblock);
   xfree (hexfpr);
 }
 
@@ -1679,7 +1757,7 @@ list_keyblock (ctrl_t ctrl,
                struct keylist_context *listctx)
 {
   reorder_keyblock (keyblock);
-  if (opt.print_pka_records)
+  if (opt.print_pka_records || opt.print_dane_records)
     list_keyblock_pka (ctrl, keyblock);
   else if (opt.with_colons)
     list_keyblock_colon (keyblock, secret, has_secret, fpr);
index 694c29f..d57ab5d 100644 (file)
@@ -74,6 +74,7 @@ struct
   int fingerprint; /* list fingerprints */
   int list_sigs;   /* list signatures */
   int print_pka_records;
+  int print_dane_records;
   int no_armor;
   int list_packets; /* list-packets mode: 1=normal, 2=invoked by command*/
   int def_cipher_algo;
index c6f6d68..f3155fd 100644 (file)
@@ -411,3 +411,17 @@ gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
     *r_url = NULL;
   return gpg_error (GPG_ERR_NOT_FOUND);
 }
+
+gpg_error_t
+export_pubkey_buffer (ctrl_t ctrl, const char *keyspec, unsigned int options,
+                      kbnode_t *r_keyblock, void **r_data, size_t *r_datalen)
+{
+  (void)ctrl;
+  (void)keyspec;
+  (void)options;
+
+  *r_keyblock = NULL;
+  *r_data = NULL;
+  *r_datalen = 0;
+  return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+}