1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

gpg: First working support for keyboxes.

* g10/getkey.c (get_pubkey_fast): Improve the assertion.
* kbx/keybox.h: Include iobuf.h.
* kbx/keybox-blob.c (keyboxblob_uid): Add field OFF.
(KEYBOX_WITH_OPENPGP): Remove use of this macro.
(pgp_create_key_part_single): New.
(pgp_temp_store_kid): Change to use the keybox-openpgp parser.
(pgp_create_key_part): Ditto.
(pgp_create_uid_part): Ditto.
(pgp_create_sig_part): Ditto.
(pgp_create_blob_keyblock): Ditto.
(_keybox_create_openpgp_blob): Ditto.
* kbx/keybox-search.c (keybox_get_keyblock): New.
* kbx/keybox-update.c (keybox_insert_keyblock): New.
* g10/keydb.c (parse_keyblock_image):
(keydb_get_keyblock): Support keybox.
(build_keyblock_image): New.
(keydb_insert_keyblock): Support keybox.

* kbx/kbxutil.c (import_openpgp, main): Add option --dry-run and print
a kbx file to stdout.

* kbx/keybox-file.c (_keybox_read_blob2): Allow keyblocks up to 10^6
bytes.
--

Import and key listing does now work with the keybox format.  It is
still quite slow and signature caching is completely missing.

Increasing the maximum allowed length for a keyblock was required due
to a 700k keyblock which inhibited kbxutil to list the file.
kbxutil's option name --import-openpgp is not quite appropriate
because it only creates KBX blobs from OpenPGP data.
This commit is contained in:
Werner Koch 2012-12-28 14:03:16 +01:00
parent f7495f1004
commit a986383424
9 changed files with 429 additions and 182 deletions

View file

@ -616,6 +616,97 @@ unlock_all (KEYDB_HANDLE hd)
}
static gpg_error_t
parse_keyblock_image (iobuf_t iobuf, kbnode_t *r_keyblock)
{
gpg_error_t err;
PACKET *pkt;
kbnode_t keyblock = NULL;
kbnode_t node;
int in_cert, save_mode;
*r_keyblock = NULL;
pkt = xtrymalloc (sizeof *pkt);
if (!pkt)
return gpg_error_from_syserror ();
init_packet (pkt);
save_mode = set_packet_list_mode (0);
in_cert = 0;
while ((err = parse_packet (iobuf, pkt)) != -1)
{
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_PACKET)
{
free_packet (pkt);
init_packet (pkt);
continue;
}
if (err)
{
log_error ("parse_keyblock_image: read error: %s\n",
gpg_strerror (err));
err = gpg_error (GPG_ERR_INV_KEYRING);
break;
}
if (pkt->pkttype == PKT_COMPRESSED)
{
log_error ("skipped compressed packet in keybox blob\n");
free_packet(pkt);
init_packet(pkt);
continue;
}
if (pkt->pkttype == PKT_RING_TRUST)
{
log_info ("skipped ring trust packet in keybox blob\n");
free_packet(pkt);
init_packet(pkt);
continue;
}
if (!in_cert && pkt->pkttype != PKT_PUBLIC_KEY)
{
log_error ("error: first packet in a keybox blob is not a "
"public key packet\n");
err = gpg_error (GPG_ERR_INV_KEYRING);
break;
}
if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY
|| pkt->pkttype == PKT_SECRET_KEY))
{
log_error ("error: multiple keyblocks in a keybox blob\n");
err = gpg_error (GPG_ERR_INV_KEYRING);
break;
}
in_cert = 1;
node = new_kbnode (pkt);
if (!keyblock)
keyblock = node;
else
add_kbnode (keyblock, node);
pkt = xtrymalloc (sizeof *pkt);
if (!pkt)
{
err = gpg_error_from_syserror ();
break;
}
init_packet (pkt);
}
set_packet_list_mode (save_mode);
if (err == -1 && keyblock)
err = 0; /* Got the entire keyblock. */
if (err)
release_kbnode (keyblock);
else
*r_keyblock = keyblock;
free_packet (pkt);
xfree (pkt);
return err;
}
/*
* Return the last found keyring. Caller must free it.
* The returned keyblock has the kbode flag bit 0 set for the node with
@ -627,6 +718,8 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
{
gpg_error_t err = 0;
*ret_kb = NULL;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
@ -641,16 +734,66 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
case KEYDB_RESOURCE_TYPE_KEYRING:
err = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
break;
/* case KEYDB_RESOURCE_TYPE_KEYBOX: */
/* err = keybox_get_keyblock (hd->active[hd->found].u.kb, ret_kb); */
/* if (!err) */
/* err = parse_keyblock (image, imagelen) */
/* break; */
case KEYDB_RESOURCE_TYPE_KEYBOX:
{
iobuf_t iobuf;
err = keybox_get_keyblock (hd->active[hd->found].u.kb, &iobuf);
if (!err)
{
err = parse_keyblock_image (iobuf, ret_kb);
iobuf_close (iobuf);
}
}
break;
}
return err;
}
/* Build a keyblock image from KEYBLOCK. Returns 0 on success and
only then stores a new iobuf object at R_IOBUF. */
static gpg_error_t
build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf)
{
gpg_error_t err;
iobuf_t iobuf;
kbnode_t kbctx, node;
*r_iobuf = NULL;
iobuf = iobuf_temp ();
for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
{
/* Make sure to use only packets valid on a keyblock. */
switch (node->pkt->pkttype)
{
case PKT_PUBLIC_KEY:
case PKT_PUBLIC_SUBKEY:
case PKT_SIGNATURE:
case PKT_USER_ID:
case PKT_ATTRIBUTE:
/* Note that we don't want the ring trust packets. They are
not useful. */
break;
default:
continue;
}
err = build_packet (iobuf, node->pkt);
if (err)
{
iobuf_close (iobuf);
return err;
}
}
*r_iobuf = iobuf;
return 0;
}
/*
* Update the current keyblock with the keyblock KB
*/
@ -699,7 +842,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
gpg_error_t
keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
{
int rc;
gpg_error_t err;
int idx;
if (!hd)
@ -715,27 +858,39 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
else
return gpg_error (GPG_ERR_GENERAL);
rc = lock_all (hd);
if (rc)
return rc;
err = lock_all (hd);
if (err)
return err;
switch (hd->active[idx].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
rc = gpg_error (GPG_ERR_GENERAL); /* oops */
err = gpg_error (GPG_ERR_GENERAL); /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
err = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
{ /* We need to turn our kbnode_t list of packets into a proper
keyblock first. This is required by the OpenPGP key parser
included in the keybox code. Eventually we can change this
kludge to have the caller pass the image. */
iobuf_t iobuf;
err = build_keyblock_image (kb, &iobuf);
if (!err)
{
err = keybox_insert_keyblock (hd->active[idx].u.kb,
iobuf_get_temp_buffer (iobuf),
iobuf_get_temp_length (iobuf));
iobuf_close (iobuf);
}
}
break;
/* case KEYDB_RESOURCE_TYPE_KEYBOX: */
/* rc = build_keyblock (kb, &image, &imagelen); */
/* if (!rc) */
/* rc = keybox_insert_keyblock (hd->active[idx].u.kb, image, imagelen); */
/* break; */
}
unlock_all (hd);
return rc;
return err;
}