gpg: Revamp reading and writing of ring trust packets.
[gnupg.git] / g10 / keyring.c
index ca9a698..e7ebbb3 100644 (file)
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <assert.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include "gpg.h"
-#include "util.h"
+#include "../common/util.h"
 #include "keyring.h"
 #include "packet.h"
 #include "keydb.h"
 #include "options.h"
 #include "main.h" /*for check_key_signature()*/
-#include "i18n.h"
+#include "../common/i18n.h"
 #include "../kbx/keybox.h"
 
 
@@ -243,7 +242,7 @@ keyring_new (void *token)
   KEYRING_HANDLE hd;
   KR_RESOURCE resource = token;
 
-  assert (resource);
+  log_assert (resource);
 
   hd = xtrycalloc (1, sizeof *hd);
   if (!hd)
@@ -258,7 +257,7 @@ keyring_release (KEYRING_HANDLE hd)
 {
     if (!hd)
         return;
-    assert (active_handles > 0);
+    log_assert (active_handles > 0);
     active_handles--;
     xfree (hd->word_match.name);
     xfree (hd->word_match.pattern);
@@ -379,6 +378,7 @@ int
 keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
 {
     PACKET *pkt;
+    struct parse_packet_ctx_s parsectx;
     int rc;
     KBNODE keyblock = NULL, node, lastnode;
     IOBUF a;
@@ -408,13 +408,14 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
 
     pkt = xmalloc (sizeof *pkt);
     init_packet (pkt);
+    init_parse_packet (&parsectx, a);
     hd->found.n_packets = 0;;
     lastnode = NULL;
     save_mode = set_packet_list_mode(0);
-    while ((rc=parse_packet (a, pkt)) != -1) {
+    while ((rc=parse_packet (&parsectx, pkt)) != -1) {
         hd->found.n_packets++;
         if (gpg_err_code (rc) == GPG_ERR_UNKNOWN_PACKET) {
-           free_packet (pkt);
+           free_packet (pkt, &parsectx);
            init_packet (pkt);
            continue;
        }
@@ -460,7 +461,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
           default:
            log_error ("skipped packet of type %d in keyring\n",
                        (int)pkt->pkttype);
-           free_packet(pkt);
+           free_packet(pkt, &parsectx);
            init_packet(pkt);
            continue;
           }
@@ -472,29 +473,6 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
         }
 
         in_cert = 1;
-        if (pkt->pkttype == PKT_RING_TRUST)
-          {
-            /*(this code is duplicated after the loop)*/
-            if ( lastnode
-                 && lastnode->pkt->pkttype == PKT_SIGNATURE
-                 && (pkt->pkt.ring_trust->sigcache & 1) ) {
-                /* This is a ring trust packet with a checked signature
-                 * status cache following directly a signature paket.
-                 * Set the cache status into that signature packet.  */
-                PKT_signature *sig = lastnode->pkt->pkt.signature;
-
-                sig->flags.checked = 1;
-                sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
-            }
-            /* Reset LASTNODE, so that we set the cache status only from
-             * the ring trust packet immediately following a signature. */
-            lastnode = NULL;
-           free_packet(pkt);
-           init_packet(pkt);
-           continue;
-          }
-
-
         node = lastnode = new_kbnode (pkt);
         if (!keyblock)
           keyblock = node;
@@ -530,18 +508,10 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
     if (rc || !ret_kb)
        release_kbnode (keyblock);
     else {
-        /*(duplicated from the loop body)*/
-        if ( pkt && pkt->pkttype == PKT_RING_TRUST
-             && lastnode
-             && lastnode->pkt->pkttype == PKT_SIGNATURE
-             && (pkt->pkt.ring_trust->sigcache & 1) ) {
-            PKT_signature *sig = lastnode->pkt->pkt.signature;
-            sig->flags.checked = 1;
-            sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
-        }
-       *ret_kb = keyblock;
+        *ret_kb = keyblock;
     }
-    free_packet (pkt);
+    free_packet (pkt, &parsectx);
+    deinit_parse_packet (&parsectx);
     xfree (pkt);
     iobuf_close(a);
 
@@ -691,7 +661,7 @@ keyring_delete_keyblock (KEYRING_HANDLE hd)
 int
 keyring_search_reset (KEYRING_HANDLE hd)
 {
-    assert (hd);
+    log_assert (hd);
 
     hd->current.kr = NULL;
     iobuf_close (hd->current.iobuf);
@@ -749,10 +719,10 @@ prepare_search (KEYRING_HANDLE hd)
         if (!hd->current.kr) {
           if (DBG_LOOKUP)
             log_debug ("%s: keyring not available!\n", __func__);
-            hd->current.eof = 1;
-            return -1; /* keyring not available */
+          hd->current.eof = 1;
+          return -1; /* keyring not available */
         }
-        assert (!hd->current.iobuf);
+        log_assert (!hd->current.iobuf);
     }
     else { /* EOF */
         if (DBG_LOOKUP)
@@ -778,7 +748,7 @@ prepare_search (KEYRING_HANDLE hd)
 
 \f
 /* A map of the all characters valid used for word_match()
- * Valid characters are in in this table converted to uppercase.
+ * Valid characters are in this table converted to uppercase.
  * because the upper 128 bytes have special meaning, we assume
  * that they are all valid.
  * Note: We must use numerical values here in case that this program
@@ -929,13 +899,27 @@ compare_name (int mode, const char *name, const char *uid, size_t uidlen)
     else if (   mode == KEYDB_SEARCH_MODE_MAIL
              || mode == KEYDB_SEARCH_MODE_MAILSUB
              || mode == KEYDB_SEARCH_MODE_MAILEND) {
+        int have_angles = 1;
        for (i=0, s= uid; i < uidlen && *s != '<'; s++, i++)
            ;
+       if (i == uidlen)
+         {
+           /* The UID is a plain addr-spec (cf. RFC2822 section 4.3).  */
+           have_angles = 0;
+           s = uid;
+           i = 0;
+         }
        if (i < uidlen)  {
-           /* skip opening delim and one char and look for the closing one*/
-           s++; i++;
-           for (se=s+1, i++; i < uidlen && *se != '>'; se++, i++)
-               ;
+           if (have_angles)
+             {
+               /* skip opening delim and one char and look for the closing one*/
+               s++; i++;
+               for (se=s+1, i++; i < uidlen && *se != '>'; se++, i++)
+                 ;
+             }
+           else
+             se = s + uidlen;
+
            if (i < uidlen) {
                i = se - s;
                if (mode == KEYDB_SEARCH_MODE_MAIL) {
@@ -972,6 +956,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
 {
   int rc;
   PACKET pkt;
+  struct parse_packet_ctx_s parsectx;
   int save_mode;
   off_t offset, main_offset;
   size_t n;
@@ -1084,7 +1069,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
           if (desc[n].mode == KEYDB_SEARCH_MODE_WORDS)
             name = desc[n].u.name;
         }
-      assert (name);
+      log_assert (name);
       if ( !hd->word_match.name || strcmp (hd->word_match.name, name) )
         {
           /* name changed */
@@ -1107,15 +1092,16 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
   if (DBG_LOOKUP)
     log_debug ("%s: %ssearching from start of resource.\n",
                __func__, scanned_from_start ? "" : "not ");
+  init_parse_packet (&parsectx, hd->current.iobuf);
   while (1)
     {
       byte afp[MAX_FINGERPRINT_LEN];
       size_t an;
 
-      rc = search_packet (hd->current.iobuf, &pkt, &offset, need_uid);
+      rc = search_packet (&parsectx, &pkt, &offset, need_uid);
       if (ignore_legacy && gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
         {
-          free_packet (&pkt);
+          free_packet (&pkt, &parsectx);
           continue;
         }
       if (rc)
@@ -1129,7 +1115,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
         }
       if (initial_skip)
         {
-          free_packet (&pkt);
+          free_packet (&pkt, &parsectx);
           continue;
         }
 
@@ -1211,7 +1197,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
             goto found;
           }
        }
-      free_packet (&pkt);
+      free_packet (&pkt, &parsectx);
       continue;
     found:
       if (rc)
@@ -1238,7 +1224,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
         }
       if (n == ndesc)
         goto real_found;
-      free_packet (&pkt);
+      free_packet (&pkt, &parsectx);
     }
  real_found:
   if (!rc)
@@ -1292,7 +1278,8 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
       hd->current.error = rc;
     }
 
-  free_packet(&pkt);
+  free_packet (&pkt, &parsectx);
+  deinit_parse_packet (&parsectx);
   set_packet_list_mode(save_mode);
   return rc;
 }
@@ -1339,6 +1326,7 @@ static int
 rename_tmp_file (const char *bakfname, const char *tmpfname, const char *fname)
 {
   int rc = 0;
+  int block = 0;
 
   /* Invalidate close caches.  */
   if (iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)tmpfname ))
@@ -1350,12 +1338,18 @@ rename_tmp_file (const char *bakfname, const char *tmpfname, const char *fname)
   iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname );
 
   /* First make a backup file. */
-  rc = keybox_file_rename (fname, bakfname);
+  block = 1;
+  rc = gnupg_rename_file (fname, bakfname, &block);
   if (rc)
     goto fail;
 
   /* then rename the file */
-  rc = keybox_file_rename (tmpfname, fname);
+  rc = gnupg_rename_file (tmpfname, fname, NULL);
+  if (block)
+    {
+      gnupg_unblock_all_signals ();
+      block = 0;
+    }
   if (rc)
     {
       register_secured_file (fname);
@@ -1380,6 +1374,8 @@ rename_tmp_file (const char *bakfname, const char *tmpfname, const char *fname)
   return 0;
 
  fail:
+  if (block)
+    gnupg_unblock_all_signals ();
   return rc;
 }
 
@@ -1392,36 +1388,12 @@ write_keyblock (IOBUF fp, KBNODE keyblock)
 
   while ( (node = walk_kbnode (keyblock, &kbctx, 0)) )
     {
-      if (node->pkt->pkttype == PKT_RING_TRUST)
-        continue; /* we write it later on our own */
-
-      if ( (rc = build_packet (fp, node->pkt) ))
+      if ( (rc = build_packet_and_meta (fp, node->pkt) ))
         {
           log_error ("build_packet(%d) failed: %s\n",
                      node->pkt->pkttype, gpg_strerror (rc) );
           return rc;
         }
-      if (node->pkt->pkttype == PKT_SIGNATURE)
-        { /* always write a signature cache packet */
-          PKT_signature *sig = node->pkt->pkt.signature;
-          unsigned int cacheval = 0;
-
-          if (sig->flags.checked)
-            {
-              cacheval |= 1;
-              if (sig->flags.valid)
-                cacheval |= 2;
-            }
-          iobuf_put (fp, 0xb0); /* old style packet 12, 1 byte len*/
-          iobuf_put (fp, 2);    /* 2 bytes */
-          iobuf_put (fp, 0);    /* unused */
-          if (iobuf_put (fp, cacheval))
-            {
-              rc = gpg_error_from_syserror ();
-              log_error ("writing sigcache packet failed\n");
-              return rc;
-            }
-        }
     }
   return 0;
 }
@@ -1456,7 +1428,7 @@ keyring_rebuild_cache (void *token,int noisy)
 
   for (;;)
     {
-      rc = keyring_search (hd, &desc, 1, NULL, 0);
+      rc = keyring_search (hd, &desc, 1, NULL, 1 /* ignore_legacy */);
       if (rc)
         break;  /* ready.  */
 
@@ -1493,9 +1465,6 @@ keyring_rebuild_cache (void *token,int noisy)
             goto leave;
         }
 
-      if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
-        continue;
-
       release_kbnode (keyblock);
       rc = keyring_get_keyblock (hd, &keyblock);
       if (rc)
@@ -1564,8 +1533,10 @@ keyring_rebuild_cache (void *token,int noisy)
             goto leave;
 
           if ( !(++count % 50) && noisy && !opt.quiet)
-            log_info(_("%lu keys cached so far (%lu signatures)\n"),
-                     count, sigcount );
+            log_info (ngettext("%lu keys cached so far (%lu signature)\n",
+                               "%lu keys cached so far (%lu signatures)\n",
+                               sigcount),
+                      count, sigcount);
         }
     } /* end main loop */
   if (rc == -1)
@@ -1575,8 +1546,15 @@ keyring_rebuild_cache (void *token,int noisy)
       log_error ("keyring_search failed: %s\n", gpg_strerror (rc));
       goto leave;
     }
-  if(noisy || opt.verbose)
-    log_info(_("%lu keys cached (%lu signatures)\n"), count, sigcount );
+
+  if (noisy || opt.verbose)
+    {
+      log_info (ngettext("%lu key cached",
+                         "%lu keys cached", count), count);
+      log_printf (ngettext(" (%lu signature)\n",
+                           " (%lu signatures)\n", sigcount), sigcount);
+    }
+
   if (tmpfp)
     {
       if (iobuf_close (tmpfp))
@@ -1606,6 +1584,7 @@ keyring_rebuild_cache (void *token,int noisy)
   return rc;
 }
 
+
 \f
 /****************
  * Perform insert/delete/update operation.
@@ -1704,7 +1683,7 @@ do_copy (int mode, const char *fname, KBNODE root,
            goto leave;
        }
        /* skip this keyblock */
-       assert( n_packets );
+       log_assert( n_packets );
        rc = skip_some_packets( fp, n_packets );
        if( rc ) {
            log_error("%s: skipping %u packets failed: %s\n",