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@gnupg.org>
This commit is contained in:
Werner Koch 2016-07-07 17:02:58 +02:00
parent b05878f32a
commit cbe467e794
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
4 changed files with 179 additions and 15 deletions

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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)