kbx: Implement update operation for OpenPGP keyblocks.
authorWerner Koch <wk@gnupg.org>
Fri, 15 Nov 2013 14:54:31 +0000 (15:54 +0100)
committerWerner Koch <wk@gnupg.org>
Fri, 15 Nov 2013 14:54:31 +0000 (15:54 +0100)
* 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>
g10/keydb.c
kbx/keybox-blob.c
kbx/keybox-defs.h
kbx/keybox-dump.c
kbx/keybox-file.c
kbx/keybox-search.c
kbx/keybox-update.c

index 79ab5af..9085012 100644 (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.
 /* 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.
  *
  *
  * 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;
   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.  */
 
   /* 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));)
 
   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++;
           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)
                 {
             {
               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_iobuf = iobuf;
-  *r_sigstatus = sigstatus;
+  if (r_sigstatus)
+    *r_sigstatus = sigstatus;
   return 0;
 }
 
   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
 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);
 
   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;
 
   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:
 
   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:
       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;
       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);
     }
 
   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;
             log_error (_("failed to rebuild keyring cache: %s\n"),
                        g10_errstr (rc));
           break;
+        case KEYDB_RESOURCE_TYPE_KEYBOX:
+          /* N/A.  */
+          break;
         }
     }
 }
         }
     }
 }
index 6493527..a38f991 100644 (file)
    - 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   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.
    - 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.
index ad8e49d..f79c093 100644 (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.
  *     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);
 
                                           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);
 /*-- keybox-dump.c --*/
 int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp);
 int _keybox_dump_file (const char *filename, int stats_only, FILE *outfp);
index 1af6a9c..af9052d 100644 (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");
       || 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);
   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);
           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);
           fputs ("[good - does not expire]", fp );
         else
           fprintf (fp, "[good - expires at %lu]", sflags);
index 027bcf8..f720993 100644 (file)
@@ -43,7 +43,7 @@ ftello (FILE *stream)
 
 
 /* Read a block at the current postion and return it in r_blob.
 
 
 /* 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)
 {
 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:
 
   *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 ();
   off = ftello (fp);
   if (off == (off_t)-1)
     return gpg_error_from_syserror ();
index 5e6432f..7980794 100644 (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)
 {
 static inline unsigned int
 blob_get_blob_flags (KEYBOXBLOB blob)
 {
index 1fdf435..6ade9e7 100644 (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)
 {
 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;
 }
 
 
 }