kbx: Update blob specification
[gnupg.git] / kbx / keybox-update.c
index e524292..6428bb2 100644 (file)
@@ -1,5 +1,5 @@
 /* keybox-update.c - keybox update operations
- *     Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2003, 2004, 2012 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 #include <errno.h>
 #include <time.h>
 #include <unistd.h>
+#include <assert.h>
 
 #include "keybox-defs.h"
+#include "../common/sysutils.h"
 
 #define EXTSEP_S "."
 
@@ -65,12 +67,12 @@ fseeko (FILE * stream, off_t newpos, int whence)
 static int
 create_tmp_file (const char *template,
                  char **r_bakfname, char **r_tmpfname, FILE **r_fp)
-{  
+{
   char *bakfname, *tmpfname;
-  
+
   *r_bakfname = NULL;
   *r_tmpfname = NULL;
-  
+
 # ifdef USE_ONLY_8DOT3
   /* Here is another Windoze bug?:
    * you cant rename("pubring.kbx.tmp", "pubring.kbx");
@@ -87,7 +89,7 @@ create_tmp_file (const char *template,
         return gpg_error_from_syserror ();
       strcpy (bakfname, template);
       strcpy (bakfname+strlen(template)-4, EXTSEP_S "kb_");
-      
+
       tmpfname = xtrymalloc (strlen (template) + 1);
       if (!tmpfname)
         {
@@ -98,14 +100,14 @@ create_tmp_file (const char *template,
       strcpy (tmpfname,template);
       strcpy (tmpfname + strlen (template)-4, EXTSEP_S "k__");
     }
-  else 
+  else
     { /* File does not end with kbx, thus we hope we are working on a
          modern file system and appending a suffix works. */
       bakfname = xtrymalloc ( strlen (template) + 5);
       if (!bakfname)
         return gpg_error_from_syserror ();
       strcpy (stpcpy (bakfname, template), EXTSEP_S "kb_");
-      
+
       tmpfname = xtrymalloc ( strlen (template) + 5);
       if (!tmpfname)
         {
@@ -120,7 +122,7 @@ create_tmp_file (const char *template,
   if (!bakfname)
     return gpg_error_from_syserror ();
   strcpy (stpcpy (bakfname,template),"~");
-  
+
   tmpfname = xtrymalloc ( strlen (template) + 5);
   if (!tmpfname)
     {
@@ -158,7 +160,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
 /*      { */
 /*        if (chmod (tmpfname, S_IRUSR | S_IWUSR) )  */
 /*          { */
-/*            log_debug ("chmod of `%s' failed: %s\n", */
+/*            log_debug ("chmod of '%s' failed: %s\n", */
 /*                       tmpfname, strerror(errno) ); */
 /*            return KEYBOX_Write_File; */
 /*     } */
@@ -172,19 +174,19 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
 
   /* First make a backup file except for secret keyboxes. */
   if (!secret)
-    { 
+    {
 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
-      remove (bakfname);
+      gnupg_remove (bakfname);
 #endif
       if (rename (fname, bakfname) )
         {
           return gpg_error_from_syserror ();
        }
     }
-  
+
   /* Then rename the file. */
 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
-  remove (fname);
+  gnupg_remove (fname);
 #endif
   if (rename (tmpfname, fname) )
     {
@@ -199,7 +201,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
        }
       return rc;
     }
-  
+
   return 0;
 }
 
@@ -211,7 +213,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
         3 = update
 */
 static int
-blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob, 
+blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
                int secret, off_t start_offset)
 {
   FILE *fp, *newfp;
@@ -221,14 +223,14 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
   char buffer[4096];
   int nread, nbytes;
 
-  /* Open the source file. Because we do a rename, we have to check the 
+  /* Open the source file. Because we do a rename, we have to check the
      permissions of the file */
   if (access (fname, W_OK))
     return gpg_error_from_syserror ();
 
   fp = fopen (fname, "rb");
   if (mode == 1 && !fp && errno == ENOENT)
-    { 
+    {
       /* Insert mode but file does not exist:
          Create a new keybox file. */
       newfp = fopen (fname, "wb");
@@ -267,10 +269,10 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
       fclose(fp);
       goto leave;
     }
-  
+
   /* prepare for insert */
   if (mode == 1)
-    { 
+    {
       /* Copy everything to the new file. */
       while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
         {
@@ -286,12 +288,12 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
           goto leave;
         }
     }
-  
+
   /* Prepare for delete or update. */
-  if ( mode == 2 || mode == 3 ) 
-    { 
+  if ( mode == 2 || mode == 3 )
+    {
       off_t current = 0;
-      
+
       /* Copy first part to the new file. */
       while ( current < start_offset )
         {
@@ -302,7 +304,7 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
           if (!nread)
             break;
           current += nread;
-          
+
           if (fwrite (buffer, nread, 1, newfp) != 1)
             {
               rc = gpg_error_from_syserror ();
@@ -314,24 +316,24 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
           rc = gpg_error_from_syserror ();
           goto leave;
         }
-      
+
       /* Skip this blob. */
       rc = _keybox_read_blob (NULL, fp);
       if (rc)
         return rc;
     }
-  
+
   /* Do an insert or update. */
   if ( mode == 1 || mode == 3 )
-    { 
+    {
       rc = _keybox_write_blob (blob, newfp);
       if (rc)
           return rc;
     }
-  
+
   /* Copy the rest of the packet for an delete or update. */
   if (mode == 2 || mode == 3)
-    { 
+    {
       while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
         {
           if (fwrite (buffer, nread, 1, newfp) != 1)
@@ -346,7 +348,7 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
           goto leave;
         }
     }
-    
+
   /* Close both files. */
   if (fclose(fp))
     {
@@ -369,8 +371,67 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
 }
 
 
+/* Insert the OpenPGP keyblock {IMAGE,IMAGELEN} into HD.  SIGSTATUS is
+   a vector describing the status of the signatures; its first element
+   gives the number of following elements.  */
+gpg_error_t
+keybox_insert_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen,
+                        u32 *sigstatus)
+{
+  gpg_error_t err;
+  const char *fname;
+  KEYBOXBLOB blob;
+  size_t nparsed;
+  struct _keybox_openpgp_info info;
 
-#ifdef KEYBOX_WITH_X509 
+  if (!hd)
+    return gpg_error (GPG_ERR_INV_HANDLE);
+  if (!hd->kb)
+    return gpg_error (GPG_ERR_INV_HANDLE);
+  fname = hd->kb->fname;
+  if (!fname)
+    return gpg_error (GPG_ERR_INV_HANDLE);
+
+
+  /* Close this one otherwise we will mess up the position for a next
+     search.  Fixme: it would be better to adjust the position after
+     the write operation.  */
+  _keybox_close_file (hd);
+
+  err = _keybox_parse_openpgp (image, imagelen, &nparsed, &info);
+  if (err)
+    return err;
+  assert (nparsed <= imagelen);
+  err = _keybox_create_openpgp_blob (&blob, &info, image, imagelen,
+                                     sigstatus, hd->ephemeral);
+  _keybox_destroy_openpgp_info (&info);
+  if (!err)
+    {
+      err = blob_filecopy (1, fname, blob, hd->secret, 0);
+      _keybox_release_blob (blob);
+      /*    if (!rc && !hd->secret && kb_offtbl) */
+      /*      { */
+      /*        update_offset_hash_table_from_kb (kb_offtbl, kb, 0); */
+      /*      } */
+    }
+  return err;
+}
+
+
+/* Update the current key at HD with the given OpenPGP keyblock in
+   {IMAGE,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);
+}
+
+
+
+#ifdef KEYBOX_WITH_X509
 int
 keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
                     unsigned char *sha1_digest)
@@ -380,12 +441,12 @@ keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
   KEYBOXBLOB blob;
 
   if (!hd)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
   if (!hd->kb)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
   fname = hd->kb->fname;
   if (!fname)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
 
   /* Close this one otherwise we will mess up the position for a next
      search.  Fixme: it would be better to adjust the position after
@@ -439,12 +500,12 @@ keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value)
   if (!hd->found.blob)
     return gpg_error (GPG_ERR_NOTHING_FOUND);
   if (!hd->kb)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
   if (!hd->found.blob)
     return gpg_error (GPG_ERR_NOTHING_FOUND);
   fname = hd->kb->fname;
   if (!fname)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
 
   off = _keybox_get_blob_fileoffset (hd->found.blob);
   if (off == (off_t)-1)
@@ -454,7 +515,7 @@ keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value)
   ec = _keybox_get_flag_location (buffer, length, what, &flag_pos, &flag_size);
   if (ec)
     return gpg_error (ec);
-  
+
   off += flag_pos;
 
   _keybox_close_file (hd);
@@ -476,7 +537,7 @@ keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value)
 
       switch (flag_size)
         {
-        case 1: 
+        case 1:
         case 2:
         case 4:
           if (fwrite (tmp+4-flag_size, flag_size, 1, fp) != 1)
@@ -512,10 +573,10 @@ keybox_delete (KEYBOX_HANDLE hd)
   if (!hd->found.blob)
     return gpg_error (GPG_ERR_NOTHING_FOUND);
   if (!hd->kb)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
   fname = hd->kb->fname;
   if (!fname)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
 
   off = _keybox_get_blob_fileoffset (hd->found.blob);
   if (off == (off_t)-1)
@@ -561,18 +622,18 @@ keybox_compress (KEYBOX_HANDLE hd)
   int skipped_deleted;
 
   if (!hd)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
   if (!hd->kb)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
   if (hd->secret)
     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
   fname = hd->kb->fname;
   if (!fname)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
 
   _keybox_close_file (hd);
 
-  /* Open the source file. Because we do a rename, we have to check the 
+  /* Open the source file. Because we do a rename, we have to check the
      permissions of the file */
   if (access (fname, W_OK))
     return gpg_error_from_syserror ();
@@ -598,7 +659,7 @@ keybox_compress (KEYBOX_HANDLE hd)
         {
           u32 last_maint = ((buffer[20] << 24) | (buffer[20+1] << 16)
                             | (buffer[20+2] << 8) | (buffer[20+3]));
-          
+
           if ( (last_maint + 3*3600) > time (NULL) )
             {
               fclose (fp);
@@ -607,7 +668,8 @@ keybox_compress (KEYBOX_HANDLE hd)
             }
         }
       _keybox_release_blob (blob);
-      rewind (fp);
+      fseek (fp, 0, SEEK_SET);
+      clearerr (fp);
     }
 
   /* Create the new file. */
@@ -618,7 +680,7 @@ keybox_compress (KEYBOX_HANDLE hd)
       return rc;;
     }
 
-  
+
   /* Processing loop.  By reading using _keybox_read_blob we
      automagically skip any blobs flagged as deleted.  Thus what we
      only have to do is to check all ephemeral flagged blocks whether
@@ -663,7 +725,7 @@ keybox_compress (KEYBOX_HANDLE hd)
           continue;
         }
 
-      if (_keybox_get_flag_location (buffer, length, 
+      if (_keybox_get_flag_location (buffer, length,
                                      KEYBOX_FLAG_BLOB, &pos, &size)
           || size != 2)
         {
@@ -674,7 +736,7 @@ keybox_compress (KEYBOX_HANDLE hd)
       if ((blobflags & KEYBOX_FLAG_BLOB_EPHEMERAL))
         {
           /* This is an ephemeral blob. */
-          if (_keybox_get_flag_location (buffer, length, 
+          if (_keybox_get_flag_location (buffer, length,
                                          KEYBOX_FLAG_CREATED_AT, &pos, &size)
               || size != 4)
             created_at = 0; /* oops. */
@@ -709,7 +771,7 @@ keybox_compress (KEYBOX_HANDLE hd)
 
   /* Rename or remove the temporary file. */
   if (rc || !any_changes)
-    remove (tmpfname);
+    gnupg_remove (tmpfname);
   else
     rc = rename_tmp_file (bakfname, tmpfname, fname, hd->secret);
 
@@ -717,4 +779,3 @@ keybox_compress (KEYBOX_HANDLE hd)
   xfree(tmpfname);
   return rc;
 }
-