tests: Make make distcheck work again.
[gnupg.git] / kbx / keybox-update.c
index 1fdf435..ff65904 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "keybox-defs.h"
 #include "../common/sysutils.h"
 
 #include "keybox-defs.h"
 #include "../common/sysutils.h"
+#include "../common/host2net.h"
 
 #define EXTSEP_S "."
 
 
 #define EXTSEP_S "."
 
@@ -67,88 +68,27 @@ fseeko (FILE * stream, off_t newpos, int whence)
 #endif /* !defined(HAVE_FSEEKO) && !defined(fseeko) */
 
 
 #endif /* !defined(HAVE_FSEEKO) && !defined(fseeko) */
 
 
-
 static int
 create_tmp_file (const char *template,
                  char **r_bakfname, char **r_tmpfname, FILE **r_fp)
 {
 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");
-   * but       rename("pubring.kbx.tmp", "pubring.aaa");
-   * works.  So we replace ".kbx" by ".kb_" or ".k__".  Note that we
-   * can't use ".bak" and ".tmp", because these suffixes are used by
-   * gpg and would lead to a sharing violation or data corruption.
-   */
-  if (strlen (template) > 4
-      && !strcmp (template+strlen(template)-4, EXTSEP_S "kbx") )
-    {
-      bakfname = xtrymalloc (strlen (template) + 1);
-      if (!bakfname)
-        return gpg_error_from_syserror ();
-      strcpy (bakfname, template);
-      strcpy (bakfname+strlen(template)-4, EXTSEP_S "kb_");
-
-      tmpfname = xtrymalloc (strlen (template) + 1);
-      if (!tmpfname)
-        {
-          gpg_error_t tmperr = gpg_error_from_syserror ();
-          xfree (bakfname);
-          return tmperr;
-        }
-      strcpy (tmpfname,template);
-      strcpy (tmpfname + strlen (template)-4, EXTSEP_S "k__");
-    }
-  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_");
+  gpg_error_t err;
 
 
-      tmpfname = xtrymalloc ( strlen (template) + 5);
-      if (!tmpfname)
+  err = keybox_tmp_names (template, 0, r_bakfname, r_tmpfname);
+  if (!err)
+    {
+      *r_fp = fopen (*r_tmpfname, "wb");
+      if (!*r_fp)
         {
         {
-          gpg_error_t tmperr = gpg_error_from_syserror ();
-          xfree (bakfname);
-          return tmperr;
+          err = gpg_error_from_syserror ();
+          xfree (*r_tmpfname);
+          *r_tmpfname = NULL;
+          xfree (*r_bakfname);
+          *r_bakfname = NULL;
         }
         }
-      strcpy (stpcpy (tmpfname, template), EXTSEP_S "k__");
-    }
-# else /* Posix file names */
-  bakfname = xtrymalloc (strlen (template) + 2);
-  if (!bakfname)
-    return gpg_error_from_syserror ();
-  strcpy (stpcpy (bakfname,template),"~");
-
-  tmpfname = xtrymalloc ( strlen (template) + 5);
-  if (!tmpfname)
-    {
-      gpg_error_t tmperr = gpg_error_from_syserror ();
-      xfree (bakfname);
-      return tmperr;
     }
     }
-  strcpy (stpcpy (tmpfname,template), EXTSEP_S "tmp");
-# endif /* Posix filename */
 
 
-  *r_fp = fopen (tmpfname, "wb");
-  if (!*r_fp)
-    {
-      gpg_error_t tmperr = gpg_error_from_syserror ();
-      xfree (tmpfname);
-      xfree (bakfname);
-      return tmperr;
-    }
-
-  *r_bakfname = bakfname;
-  *r_tmpfname = tmpfname;
-  return 0;
+  return err;
 }
 
 
 }
 
 
@@ -179,22 +119,15 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
   /* First make a backup file except for secret keyboxes. */
   if (!secret)
     {
   /* First make a backup file except for secret keyboxes. */
   if (!secret)
     {
-#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
-      gnupg_remove (bakfname);
-#endif
-      if (rename (fname, bakfname) )
-        {
-          return gpg_error_from_syserror ();
-       }
+      rc = keybox_file_rename (fname, bakfname);
+      if (rc)
+        return rc;
     }
 
   /* Then rename the file. */
     }
 
   /* Then rename the file. */
-#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
-  gnupg_remove (fname);
-#endif
-  if (rename (tmpfname, fname) )
+  rc = keybox_file_rename (tmpfname, fname);
+  if (rc)
     {
     {
-      rc = gpg_error_from_syserror ();
       if (secret)
         {
 /*            log_info ("WARNING: 2 files with confidential" */
       if (secret)
         {
 /*            log_info ("WARNING: 2 files with confidential" */
@@ -211,18 +144,18 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
 
 
 
 
 
 
-/* Perform insert/delete/update operation.
-   MODE is one of FILECOPY_INSERT, FILECOPY_DELETE, FILECOPY_UPDATE.
-*/
+/* Perform insert/delete/update operation.  MODE is one of
+   FILECOPY_INSERT, FILECOPY_DELETE, FILECOPY_UPDATE.  FOR_OPENPGP
+   indicates that this is called due to an OpenPGP keyblock change.  */
 static int
 blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
 static int
 blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
-               int secret, off_t start_offset)
+               int secret, int for_openpgp, off_t start_offset)
 {
   FILE *fp, *newfp;
   int rc=0;
   char *bakfname = NULL;
   char *tmpfname = NULL;
 {
   FILE *fp, *newfp;
   int rc=0;
   char *bakfname = NULL;
   char *tmpfname = NULL;
-  char buffer[4096];
+  char buffer[4096];  /* (Must be at least 32 bytes) */
   int nread, nbytes;
 
   /* Open the source file. Because we do a rename, we have to check the
   int nread, nbytes;
 
   /* Open the source file. Because we do a rename, we have to check the
@@ -239,13 +172,19 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
       if (!newfp )
         return gpg_error_from_syserror ();
 
       if (!newfp )
         return gpg_error_from_syserror ();
 
-      rc = _keybox_write_header_blob (newfp);
+      rc = _keybox_write_header_blob (newfp, for_openpgp);
       if (rc)
       if (rc)
-        return rc;
+        {
+          fclose (newfp);
+          return rc;
+        }
 
       rc = _keybox_write_blob (blob, newfp);
       if (rc)
 
       rc = _keybox_write_blob (blob, newfp);
       if (rc)
-        return rc;
+        {
+          fclose (newfp);
+          return rc;
+        }
 
       if ( fclose (newfp) )
         return gpg_error_from_syserror ();
 
       if ( fclose (newfp) )
         return gpg_error_from_syserror ();
@@ -264,29 +203,44 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
       goto leave;
     }
 
       goto leave;
     }
 
-  /* Create the new file. */
+  /* Create the new file.  On success NEWFP is initialized.  */
   rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
   if (rc)
     {
   rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
   if (rc)
     {
-      fclose(fp);
+      fclose (fp);
       goto leave;
     }
 
   /* prepare for insert */
   if (mode == FILECOPY_INSERT)
     {
       goto leave;
     }
 
   /* prepare for insert */
   if (mode == FILECOPY_INSERT)
     {
-      /* Copy everything to the new file. */
+      int first_record = 1;
+
+      /* Copy everything to the new file.  If this is for OpenPGP, we
+         make sure that the openpgp flag is set in the header.  (We
+         failsafe the blob type.) */
       while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
         {
       while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
         {
+          if (first_record && for_openpgp
+              && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
+            {
+              first_record = 0;
+              buffer[7] |= 0x02; /* OpenPGP data may be available.  */
+            }
+
           if (fwrite (buffer, nread, 1, newfp) != 1)
             {
               rc = gpg_error_from_syserror ();
           if (fwrite (buffer, nread, 1, newfp) != 1)
             {
               rc = gpg_error_from_syserror ();
+              fclose (fp);
+              fclose (newfp);
               goto leave;
             }
         }
       if (ferror (fp))
         {
           rc = gpg_error_from_syserror ();
               goto leave;
             }
         }
       if (ferror (fp))
         {
           rc = gpg_error_from_syserror ();
+          fclose (fp);
+          fclose (newfp);
           goto leave;
         }
     }
           goto leave;
         }
     }
@@ -310,19 +264,27 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
           if (fwrite (buffer, nread, 1, newfp) != 1)
             {
               rc = gpg_error_from_syserror ();
           if (fwrite (buffer, nread, 1, newfp) != 1)
             {
               rc = gpg_error_from_syserror ();
+              fclose (fp);
+              fclose (newfp);
               goto leave;
             }
         }
       if (ferror (fp))
         {
           rc = gpg_error_from_syserror ();
               goto leave;
             }
         }
       if (ferror (fp))
         {
           rc = gpg_error_from_syserror ();
+          fclose (fp);
+          fclose (newfp);
           goto leave;
         }
 
       /* Skip this blob. */
       rc = _keybox_read_blob (NULL, fp);
       if (rc)
           goto leave;
         }
 
       /* Skip this blob. */
       rc = _keybox_read_blob (NULL, fp);
       if (rc)
-        return rc;
+        {
+          fclose (fp);
+          fclose (newfp);
+          return rc;
+        }
     }
 
   /* Do an insert or update. */
     }
 
   /* Do an insert or update. */
@@ -330,7 +292,11 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
     {
       rc = _keybox_write_blob (blob, newfp);
       if (rc)
     {
       rc = _keybox_write_blob (blob, newfp);
       if (rc)
+        {
+          fclose (fp);
+          fclose (newfp);
           return rc;
           return rc;
+        }
     }
 
   /* Copy the rest of the packet for an delete or update. */
     }
 
   /* Copy the rest of the packet for an delete or update. */
@@ -341,12 +307,16 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
           if (fwrite (buffer, nread, 1, newfp) != 1)
             {
               rc = gpg_error_from_syserror ();
           if (fwrite (buffer, nread, 1, newfp) != 1)
             {
               rc = gpg_error_from_syserror ();
+              fclose (fp);
+              fclose (newfp);
               goto leave;
             }
         }
       if (ferror (fp))
         {
           rc = gpg_error_from_syserror ();
               goto leave;
             }
         }
       if (ferror (fp))
         {
           rc = gpg_error_from_syserror ();
+          fclose (fp);
+          fclose (newfp);
           goto leave;
         }
     }
           goto leave;
         }
     }
@@ -409,7 +379,7 @@ keybox_insert_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen,
   _keybox_destroy_openpgp_info (&info);
   if (!err)
     {
   _keybox_destroy_openpgp_info (&info);
   if (!err)
     {
-      err = blob_filecopy (FILECOPY_INSERT, fname, blob, hd->secret, 0);
+      err = blob_filecopy (FILECOPY_INSERT, fname, blob, hd->secret, 1, 0);
       _keybox_release_blob (blob);
       /*    if (!rc && !hd->secret && kb_offtbl) */
       /*      { */
       _keybox_release_blob (blob);
       /*    if (!rc && !hd->secret && kb_offtbl) */
       /*      { */
@@ -425,10 +395,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) != KEYBOX_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, 1, off);
+      _keybox_release_blob (blob);
+    }
+  return err;
 }
 
 
 }
 
 
@@ -458,7 +465,7 @@ keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
   rc = _keybox_create_x509_blob (&blob, cert, sha1_digest, hd->ephemeral);
   if (!rc)
     {
   rc = _keybox_create_x509_blob (&blob, cert, sha1_digest, hd->ephemeral);
   if (!rc)
     {
-      rc = blob_filecopy (FILECOPY_INSERT, fname, blob, hd->secret, 0);
+      rc = blob_filecopy (FILECOPY_INSERT, fname, blob, hd->secret, 0, 0);
       _keybox_release_blob (blob);
       /*    if (!rc && !hd->secret && kb_offtbl) */
       /*      { */
       _keybox_release_blob (blob);
       /*    if (!rc && !hd->secret && kb_offtbl) */
       /*      { */
@@ -527,7 +534,7 @@ keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value)
 
   ec = 0;
   if (fseeko (fp, off, SEEK_SET))
 
   ec = 0;
   if (fseeko (fp, off, SEEK_SET))
-    ec = gpg_error_from_syserror ();
+    ec = gpg_err_code_from_syserror ();
   else
     {
       unsigned char tmp[4];
   else
     {
       unsigned char tmp[4];
@@ -657,10 +664,9 @@ keybox_compress (KEYBOX_HANDLE hd)
       size_t length;
 
       buffer = _keybox_get_blob_image (blob, &length);
       size_t length;
 
       buffer = _keybox_get_blob_image (blob, &length);
-      if (length > 4 && buffer[4] == BLOBTYPE_HEADER)
+      if (length > 4 && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
         {
         {
-          u32 last_maint = ((buffer[20] << 24) | (buffer[20+1] << 16)
-                            | (buffer[20+2] << 8) | (buffer[20+3]));
+          u32 last_maint = buf32_to_u32 (buffer+20);
 
           if ( (last_maint + 3*3600) > time (NULL) )
             {
 
           if ( (last_maint + 3*3600) > time (NULL) )
             {
@@ -678,7 +684,7 @@ keybox_compress (KEYBOX_HANDLE hd)
   rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
   if (rc)
     {
   rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
   if (rc)
     {
-      fclose(fp);
+      fclose (fp);
       return rc;;
     }
 
       return rc;;
     }
 
@@ -704,10 +710,12 @@ keybox_compress (KEYBOX_HANDLE hd)
       if (first_blob)
         {
           first_blob = 0;
       if (first_blob)
         {
           first_blob = 0;
-          if (length > 4 && buffer[4] == BLOBTYPE_HEADER)
+          if (length > 4 && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
             {
             {
-              /* Write out the blob with an updated maintenance time stamp. */
-              _keybox_update_header_blob (blob);
+              /* Write out the blob with an updated maintenance time
+                 stamp and if needed (ie. used by gpg) set the openpgp
+                 flag.  */
+              _keybox_update_header_blob (blob, hd->for_openpgp);
               rc = _keybox_write_blob (blob, newfp);
               if (rc)
                 break;
               rc = _keybox_write_blob (blob, newfp);
               if (rc)
                 break;
@@ -715,12 +723,12 @@ keybox_compress (KEYBOX_HANDLE hd)
             }
 
           /* The header blob is missing.  Insert it.  */
             }
 
           /* The header blob is missing.  Insert it.  */
-          rc = _keybox_write_header_blob (newfp);
+          rc = _keybox_write_header_blob (newfp, hd->for_openpgp);
           if (rc)
             break;
           any_changes = 1;
         }
           if (rc)
             break;
           any_changes = 1;
         }
-      else if (length > 4 && buffer[4] == BLOBTYPE_HEADER)
+      else if (length > 4 && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
         {
           /* Oops: There is another header record - remove it. */
           any_changes = 1;
         {
           /* Oops: There is another header record - remove it. */
           any_changes = 1;
@@ -734,7 +742,7 @@ keybox_compress (KEYBOX_HANDLE hd)
           rc = gpg_error (GPG_ERR_BUG);
           break;
         }
           rc = gpg_error (GPG_ERR_BUG);
           break;
         }
-      blobflags = ((buffer[pos] << 8) | (buffer[pos+1]));
+      blobflags = buf16_to_uint (buffer+pos);
       if ((blobflags & KEYBOX_FLAG_BLOB_EPHEMERAL))
         {
           /* This is an ephemeral blob. */
       if ((blobflags & KEYBOX_FLAG_BLOB_EPHEMERAL))
         {
           /* This is an ephemeral blob. */
@@ -743,8 +751,7 @@ keybox_compress (KEYBOX_HANDLE hd)
               || size != 4)
             created_at = 0; /* oops. */
           else
               || size != 4)
             created_at = 0; /* oops. */
           else
-            created_at = ((buffer[pos] << 24) | (buffer[pos+1] << 16)
-                          | (buffer[pos+2] << 8) | (buffer[pos+3]));
+            created_at = buf32_to_u32 (buffer+pos);
 
           if (created_at && created_at < cut_time)
             {
 
           if (created_at && created_at < cut_time)
             {