kbx: Implement update operation for OpenPGP keyblocks.

* kbx/keybox-update.c (keybox_update_keyblock): Implement.
* kbx/keybox-search.c (get_blob_flags): Move to ...
* kbx/keybox-defs.h (blob_get_type): here.
* kbx/keybox-file.c (_keybox_read_blob2): Fix calling without R_BLOB.
* g10/keydb.c (build_keyblock_image): Allow calling without
R_SIGSTATUS.
(keydb_update_keyblock): Implement for keybox.

* kbx/keybox-dump.c (_keybox_dump_blob): Fix printing of the unhashed
size.  Print "does not expire" also on 64 bit platforms.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2013-11-15 15:54:31 +01:00
parent a0102a548d
commit 5499942571
7 changed files with 108 additions and 48 deletions

View File

@ -1,6 +1,7 @@
/* keydb.c - key database dispatcher
* Copyright (C) 2001, 2002, 2003, 2004, 2005,
* 2008, 2009, 2011, 2013 Free Software Foundation, Inc.
* Coyrright (C) 2013 Werner Koch
*
* This file is part of GnuPG.
*
@ -896,18 +897,24 @@ build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf, u32 **r_sigstatus)
u32 *sigstatus;
*r_iobuf = NULL;
*r_sigstatus = NULL;
if (r_sigstatus)
*r_sigstatus = NULL;
/* Allocate a vector for the signature cache. This is an array of
u32 values with the first value giving the number of elements to
follow and each element descriping the cache status of the
signature. */
for (kbctx = NULL, n_sigs = 0; (node = walk_kbnode (keyblock, &kbctx, 0));)
if (node->pkt->pkttype == PKT_SIGNATURE)
n_sigs++;
sigstatus = xtrycalloc (1+n_sigs, sizeof *sigstatus);
if (!sigstatus)
return gpg_error_from_syserror ();
if (r_sigstatus)
{
for (kbctx=NULL, n_sigs=0; (node = walk_kbnode (keyblock, &kbctx, 0));)
if (node->pkt->pkttype == PKT_SIGNATURE)
n_sigs++;
sigstatus = xtrycalloc (1+n_sigs, sizeof *sigstatus);
if (!sigstatus)
return gpg_error_from_syserror ();
}
else
sigstatus = NULL;
iobuf = iobuf_temp ();
for (kbctx = NULL, n_sigs = 0; (node = walk_kbnode (keyblock, &kbctx, 0));)
@ -940,8 +947,8 @@ build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf, u32 **r_sigstatus)
PKT_signature *sig = node->pkt->pkt.signature;
n_sigs++;
/* Fixme: Detect tye "missing key" status. */
if (sig->flags.checked)
/* Fixme: Detect the "missing key" status. */
if (sig->flags.checked && sigstatus)
{
if (sig->flags.valid)
{
@ -957,10 +964,12 @@ build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf, u32 **r_sigstatus)
}
}
}
sigstatus[0] = n_sigs;
if (sigstatus)
sigstatus[0] = n_sigs;
*r_iobuf = iobuf;
*r_sigstatus = sigstatus;
if (r_sigstatus)
*r_sigstatus = sigstatus;
return 0;
}
@ -971,7 +980,7 @@ build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf, u32 **r_sigstatus)
gpg_error_t
keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
{
gpg_error_t rc;
gpg_error_t err;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
@ -984,28 +993,36 @@ keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
if (opt.dry_run)
return 0;
rc = lock_all (hd);
if (rc)
return rc;
err = lock_all (hd);
if (err)
return err;
switch (hd->active[hd->found].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_update_keyblock (hd->active[hd->found].u.kr, kb);
err = keyring_update_keyblock (hd->active[hd->found].u.kr, kb);
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
{
iobuf_t iobuf;
err = build_keyblock_image (kb, &iobuf, NULL);
if (!err)
{
err = keybox_update_keyblock (hd->active[hd->found].u.kb,
iobuf_get_temp_buffer (iobuf),
iobuf_get_temp_length (iobuf));
iobuf_close (iobuf);
}
}
break;
/* case KEYDB_RESOURCE_TYPE_KEYRING: */
/* rc = build_keyblock (kb, &image, &imagelen); */
/* if (!rc) */
/* rc = keybox_update_keyblock (hd->active[hd->found].u.kb, */
/* image, imagelen); */
/* break; */
}
unlock_all (hd);
return rc;
return err;
}
@ -1197,6 +1214,9 @@ keydb_rebuild_caches (int noisy)
log_error (_("failed to rebuild keyring cache: %s\n"),
g10_errstr (rc));
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
/* N/A. */
break;
}
}
}

View File

@ -120,8 +120,9 @@
- bN Arbitrary space for example used to store data which is not
part of the keyblock or certificate. For example the v3 key
IDs go here.
- bN Space for the keyblock or certifciate.
- bN RFU
- bN Space for the keyblock or certificate.
- bN RFU. This is the remaining space after keyblock and before
the checksum. Is is not covered by the checksum.
- b20 SHA-1 checksum (useful for KS syncronisation?)
Note, that KBX versions before GnuPG 2.1 used an MD5
checksum. However it was only created but never checked.

View File

@ -1,4 +1,4 @@
/* keybox-defs.h - interal Keybox defintions
/* keybox-defs.h - internal Keybox definitions
* Copyright (C) 2001, 2004 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
@ -193,6 +193,20 @@ gpg_err_code_t _keybox_get_flag_location (const unsigned char *buffer,
int what,
size_t *flag_off, size_t *flag_size);
static inline int
blob_get_type (KEYBOXBLOB blob)
{
const unsigned char *buffer;
size_t length;
buffer = _keybox_get_blob_image (blob, &length);
if (length < 32)
return -1; /* blob too short */
return buffer[4];
}
/*-- keybox-dump.c --*/
int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp);
int _keybox_dump_file (const char *filename, int stats_only, FILE *outfp);

View File

@ -245,7 +245,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
|| rawdata_len + 4 > length
|| rawdata_off+rawdata_len + 4 > length)
fprintf (fp, "[Error: raw data larger than blob]\n");
unhashed = get32 (buffer + rawdata_off + rawdata_len);
unhashed = length - rawdata_off - rawdata_len;
fprintf (fp, "Unhashed: %lu\n", unhashed);
nkeys = get16 (buffer + 16);
@ -378,7 +378,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
fputs ("[bad signature]", fp);
else if (sflags < 0x10000000)
fprintf (fp, "[bad flag %0lx]", sflags);
else if (sflags == 0xffffffff)
else if (sflags == (ulong)(-1))
fputs ("[good - does not expire]", fp );
else
fprintf (fp, "[good - expires at %lu]", sflags);

View File

@ -43,7 +43,7 @@ ftello (FILE *stream)
/* Read a block at the current postion and return it in r_blob.
r_blob may be NULL to simply skip the current block */
r_blob may be NULL to simply skip the current block. */
int
_keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted)
{
@ -55,7 +55,8 @@ _keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted)
*skipped_deleted = 0;
again:
*r_blob = NULL;
if (r_blob)
*r_blob = NULL;
off = ftello (fp);
if (off == (off_t)-1)
return gpg_error_from_syserror ();

View File

@ -65,19 +65,6 @@ get16 (const byte *buffer)
static inline int
blob_get_type (KEYBOXBLOB blob)
{
const unsigned char *buffer;
size_t length;
buffer = _keybox_get_blob_image (blob, &length);
if (length < 32)
return -1; /* blob too short */
return buffer[4];
}
static inline unsigned int
blob_get_blob_flags (KEYBOXBLOB blob)
{

View File

@ -425,10 +425,47 @@ keybox_insert_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen,
gpg_error_t
keybox_update_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen)
{
(void)hd;
(void)image;
(void)imagelen;
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
gpg_error_t err;
const char *fname;
off_t off;
KEYBOXBLOB blob;
size_t nparsed;
struct _keybox_openpgp_info info;
if (!hd || !image || !imagelen)
return gpg_error (GPG_ERR_INV_VALUE);
if (!hd->found.blob)
return gpg_error (GPG_ERR_NOTHING_FOUND);
if (blob_get_type (hd->found.blob) != BLOBTYPE_PGP)
return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
fname = hd->kb->fname;
if (!fname)
return gpg_error (GPG_ERR_INV_HANDLE);
off = _keybox_get_blob_fileoffset (hd->found.blob);
if (off == (off_t)-1)
return gpg_error (GPG_ERR_GENERAL);
/* Close this the file so that we do no mess up the position for a
next search. */
_keybox_close_file (hd);
/* Build a new blob. */
err = _keybox_parse_openpgp (image, imagelen, &nparsed, &info);
if (err)
return err;
assert (nparsed <= imagelen);
err = _keybox_create_openpgp_blob (&blob, &info, image, imagelen,
NULL, hd->ephemeral);
_keybox_destroy_openpgp_info (&info);
/* Update the keyblock. */
if (!err)
{
err = blob_filecopy (FILECOPY_UPDATE, fname, blob, hd->secret, off);
_keybox_release_blob (blob);
}
return err;
}