gpg: Avoid using cached MD5 signature status.
authorWerner Koch <wk@gnupg.org>
Sat, 11 Oct 2014 17:41:51 +0000 (19:41 +0200)
committerWerner Koch <wk@gnupg.org>
Sat, 11 Oct 2014 17:41:51 +0000 (19:41 +0200)
* g10/sig-check.c (check_key_signature2): Avoid using a cached MD5
signature status.
* g10/keyring.c (keyring_get_keyblock): Ditto.
(write_keyblock): Ditto.

* g10/sig-check.c (do_check): Move reject warning to ...
* g10/misc.c (print_md5_rejected_note): new.
--

Signed-off-by: Werner Koch <wk@gnupg.org>
g10/keyring.c
g10/main.h
g10/misc.c
g10/sig-check.c

index 7482724..837df5e 100644 (file)
@@ -31,7 +31,7 @@
 #include "util.h"
 #include "keyring.h"
 #include "packet.h"
-#include "keydb.h" 
+#include "keydb.h"
 #include "options.h"
 #include "main.h" /*for check_key_signature()*/
 #include "i18n.h"
@@ -46,11 +46,11 @@ struct off_item {
   /*off_t off;*/
 };
 
-typedef struct off_item **OffsetHashTable; 
+typedef struct off_item **OffsetHashTable;
 
 
 typedef struct keyring_name *KR_NAME;
-struct keyring_name 
+struct keyring_name
 {
   struct keyring_name *next;
   int secret;
@@ -79,7 +79,7 @@ struct keyring_handle {
     int error;
   } current;
   struct {
-    CONST_KR_NAME kr; 
+    CONST_KR_NAME kr;
     off_t offset;
     size_t pk_no;
     size_t uid_no;
@@ -102,7 +102,7 @@ static struct off_item *
 new_offset_item (void)
 {
   struct off_item *k;
-  
+
   k = xmalloc_clear (sizeof *k);
   return k;
 }
@@ -121,7 +121,7 @@ release_offset_items (struct off_item *k)
 }
 #endif
 
-static OffsetHashTable 
+static OffsetHashTable
 new_offset_hash_table (void)
 {
   struct off_item **tbl;
@@ -164,7 +164,7 @@ update_offset_hash_table (OffsetHashTable tbl, u32 *kid, off_t off)
 
   for (k = tbl[(kid[1] & 0x07ff)]; k; k = k->next)
     {
-      if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) 
+      if (k->kid[0] == kid[0] && k->kid[1] == kid[1])
         {
           /*k->off = off;*/
           return;
@@ -194,14 +194,14 @@ update_offset_hash_table_from_kb (OffsetHashTable tbl, KBNODE node, off_t off)
     }
 }
 
-/* 
+/*
  * Register a filename for plain keyring files.  ptr is set to a
  * pointer to be used to create a handles etc, or the already-issued
  * pointer if it has already been registered.  The function returns 1
  * if a new keyring was registered.
 */
 int
-keyring_register_filename (const char *fname, int secret, int readonly, 
+keyring_register_filename (const char *fname, int secret, int readonly,
                            void **ptr)
 {
     KR_NAME kr;
@@ -217,7 +217,7 @@ keyring_register_filename (const char *fname, int secret, int readonly,
             if (readonly)
               kr->readonly = 1;
             *ptr=kr;
-           return 0; 
+           return 0;
          }
       }
 
@@ -251,12 +251,12 @@ keyring_is_writable (void *token)
 
   return r? (r->readonly || !access (r->fname, W_OK)) : 0;
 }
-    
+
 
 \f
 /* Create a new handle for the resource associated with TOKEN.  SECRET
    is just just as a cross-check.
-   
+
    The returned handle must be released using keyring_release (). */
 KEYRING_HANDLE
 keyring_new (void *token, int secret)
@@ -265,7 +265,7 @@ keyring_new (void *token, int secret)
   KR_NAME resource = token;
 
   assert (resource && !resource->secret == !secret);
-  
+
   hd = xmalloc_clear (sizeof *hd);
   hd->resource = resource;
   hd->secret = !!secret;
@@ -273,7 +273,7 @@ keyring_new (void *token, int secret)
   return hd;
 }
 
-void 
+void
 keyring_release (KEYRING_HANDLE hd)
 {
     if (!hd)
@@ -300,7 +300,7 @@ keyring_get_resource_name (KEYRING_HANDLE hd)
  * Lock the keyring with the given handle, or unlock if YES is false.
  * We ignore the handle and lock all registered files.
  */
-int 
+int
 keyring_lock (KEYRING_HANDLE hd, int yes)
 {
     KR_NAME kr;
@@ -323,7 +323,7 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
         }
         if (rc)
             return rc;
-        
+
         /* and now set the locks */
         for (kr=kr_names; kr; kr = kr->next) {
             if (!keyring_is_writable(kr))
@@ -334,7 +334,7 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
                 log_info ("can't lock `%s'\n", kr->fname );
                 rc = G10ERR_GENERAL;
             }
-            else 
+            else
                 kr->is_locked = 1;
         }
     }
@@ -347,10 +347,10 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
                 ;
             else if (release_dotlock (kr->lockhd))
                 log_info ("can't unlock `%s'\n", kr->fname );
-            else 
+            else
                 kr->is_locked = 0;
         }
-    } 
+    }
 
     return rc;
 }
@@ -360,7 +360,7 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
 /*
  * Return the last found keyring.  Caller must free it.
  * The returned keyblock has the kbode flag bit 0 set for the node with
- * the public key used to locate the keyblock or flag bit 1 set for 
+ * the public key used to locate the keyblock or flag bit 1 set for
  * the user ID node.
  */
 int
@@ -406,7 +406,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
            init_packet (pkt);
            continue;
        }
-       if (rc) {  
+       if (rc) {
             log_error ("keyring_get_keyblock: read error: %s\n",
                        g10_errstr(rc) );
             rc = G10ERR_INV_KEYRING;
@@ -426,19 +426,26 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
         }
 
         in_cert = 1;
-        if (pkt->pkttype == PKT_RING_TRUST) 
+        if (pkt->pkttype == PKT_RING_TRUST)
           {
             /*(this code is duplicated after the loop)*/
-            if ( lastnode 
+            if ( lastnode
                  && lastnode->pkt->pkttype == PKT_SIGNATURE
                  && (pkt->pkt.ring_trust->sigcache & 1) ) {
-                /* This is a ring trust packet with a checked signature 
+                /* 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.  */
+                 * Set the cache status into that signature packet.
+                 *
+                 * We do not use cached signatures made with MD5 to
+                 * avoid using a cached status created with an older
+                 * version of gpg.  */
                 PKT_signature *sig = lastnode->pkt->pkt.signature;
-                
-                sig->flags.checked = 1;
-                sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
+
+                if (sig->digest_algo != DIGEST_ALGO_MD5)
+                  {
+                    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. */
@@ -468,7 +475,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
             if (++uid_no == hd->found.uid_no)
               node->flag |= 2;
             break;
-            
+
           default:
             break;
           }
@@ -478,7 +485,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
     }
     set_packet_list_mode(save_mode);
 
-    if (rc == -1 && keyblock) 
+    if (rc == -1 && keyblock)
        rc = 0; /* got the entire keyblock */
 
     if (rc || !ret_kb)
@@ -486,12 +493,15 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
     else {
         /*(duplicated form the loop body)*/
         if ( pkt && pkt->pkttype == PKT_RING_TRUST
-             && lastnode 
+             && 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);
+            if (sig->digest_algo != DIGEST_ALGO_MD5)
+              {
+                sig->flags.checked = 1;
+                sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
+              }
         }
        *ret_kb = keyblock;
     }
@@ -500,7 +510,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
     iobuf_close(a);
 
     /* Make sure that future search operations fail immediately when
-     * we know that we are working on a invalid keyring 
+     * we know that we are working on a invalid keyring
      */
     if (rc == G10ERR_INV_KEYRING)
         hd->current.error = rc;
@@ -571,11 +581,11 @@ keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb)
         if (hd->current.kr->readonly)
           return gpg_error (GPG_ERR_EACCES);
       }
-    else 
+    else
         fname = hd->resource? hd->resource->fname:NULL;
 
     if (!fname)
-        return G10ERR_GENERAL; 
+        return G10ERR_GENERAL;
 
     /* Close this one otherwise we will lose the position for
      * a next search.  Fixme: it would be better to adjust the position
@@ -590,7 +600,7 @@ keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb)
       {
         update_offset_hash_table_from_kb (kr_offtbl, kb, 0);
       }
-      
+
     return rc;
 }
 
@@ -639,10 +649,10 @@ keyring_delete_keyblock (KEYRING_HANDLE hd)
 
 
 \f
-/* 
+/*
  * Start the next search on this handle right at the beginning
  */
-int 
+int
 keyring_search_reset (KEYRING_HANDLE hd)
 {
     assert (hd);
@@ -652,17 +662,17 @@ keyring_search_reset (KEYRING_HANDLE hd)
     hd->current.iobuf = NULL;
     hd->current.eof = 0;
     hd->current.error = 0;
-    
+
     hd->found.kr = NULL;
     hd->found.offset = 0;
-    return 0; 
+    return 0;
 }
 
 
 static int
 prepare_search (KEYRING_HANDLE hd)
 {
-    if (hd->current.error)  
+    if (hd->current.error)
         return hd->current.error; /* still in error state */
 
     if (hd->current.kr && !hd->current.eof) {
@@ -671,7 +681,7 @@ prepare_search (KEYRING_HANDLE hd)
         return 0; /* okay */
     }
 
-    if (!hd->current.kr && hd->current.eof)  
+    if (!hd->current.kr && hd->current.eof)
         return -1; /* still EOF */
 
     if (!hd->current.kr) { /* start search with first keyring */
@@ -683,7 +693,7 @@ prepare_search (KEYRING_HANDLE hd)
         assert (!hd->current.iobuf);
     }
     else { /* EOF */
-        iobuf_close (hd->current.iobuf); 
+        iobuf_close (hd->current.iobuf);
         hd->current.iobuf = NULL;
         hd->current.kr = NULL;
         hd->current.eof = 1;
@@ -841,7 +851,7 @@ compare_name (int mode, const char *name, const char *uid, size_t uidlen)
     int i;
     const char *s, *se;
 
-    if (mode == KEYDB_SEARCH_MODE_EXACT) { 
+    if (mode == KEYDB_SEARCH_MODE_EXACT) {
        for (i=0; name[i] && uidlen; i++, uidlen--)
            if (uid[i] != name[i])
                break;
@@ -852,7 +862,7 @@ compare_name (int mode, const char *name, const char *uid, size_t uidlen)
        if (ascii_memistr( uid, uidlen, name ))
            return 0;
     }
-    else if (   mode == KEYDB_SEARCH_MODE_MAIL 
+    else if (   mode == KEYDB_SEARCH_MODE_MAIL
              || mode == KEYDB_SEARCH_MODE_MAILSUB
              || mode == KEYDB_SEARCH_MODE_MAILEND) {
        for (i=0, s= uid; i < uidlen && *s != '<'; s++, i++)
@@ -864,7 +874,7 @@ compare_name (int mode, const char *name, const char *uid, size_t uidlen)
                ;
            if (i < uidlen) {
                i = se - s;
-               if (mode == KEYDB_SEARCH_MODE_MAIL) { 
+               if (mode == KEYDB_SEARCH_MODE_MAIL) {
                    if( strlen(name)-2 == i
                         && !ascii_memcasecmp( s, name+1, i) )
                        return 0;
@@ -888,11 +898,11 @@ compare_name (int mode, const char *name, const char *uid, size_t uidlen)
 }
 
 \f
-/* 
+/*
  * Search through the keyring(s), starting at the current position,
  * for a keyblock which contains one of the keys described in the DESC array.
  */
-int 
+int
 keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
                size_t ndesc, size_t *descindex)
 {
@@ -912,28 +922,28 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
 
   /* figure out what information we need */
   need_uid = need_words = need_keyid = need_fpr = any_skip = 0;
-  for (n=0; n < ndesc; n++) 
+  for (n=0; n < ndesc; n++)
     {
-      switch (desc[n].mode) 
+      switch (desc[n].mode)
         {
-        case KEYDB_SEARCH_MODE_EXACT: 
+        case KEYDB_SEARCH_MODE_EXACT:
         case KEYDB_SEARCH_MODE_SUBSTR:
         case KEYDB_SEARCH_MODE_MAIL:
         case KEYDB_SEARCH_MODE_MAILSUB:
         case KEYDB_SEARCH_MODE_MAILEND:
           need_uid = 1;
           break;
-        case KEYDB_SEARCH_MODE_WORDS: 
+        case KEYDB_SEARCH_MODE_WORDS:
           need_uid = 1;
           need_words = 1;
           break;
-        case KEYDB_SEARCH_MODE_SHORT_KID: 
+        case KEYDB_SEARCH_MODE_SHORT_KID:
         case KEYDB_SEARCH_MODE_LONG_KID:
           need_keyid = 1;
           break;
-        case KEYDB_SEARCH_MODE_FPR16: 
+        case KEYDB_SEARCH_MODE_FPR16:
         case KEYDB_SEARCH_MODE_FPR20:
-        case KEYDB_SEARCH_MODE_FPR: 
+        case KEYDB_SEARCH_MODE_FPR:
           need_fpr = 1;
           break;
         case KEYDB_SEARCH_MODE_FIRST:
@@ -942,7 +952,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
           break;
         default: break;
        }
-      if (desc[n].skipfnc) 
+      if (desc[n].skipfnc)
         {
           any_skip = 1;
           need_keyid = 1;
@@ -961,7 +971,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
   else if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID)
     {
       struct off_item *oi;
-            
+
       oi = lookup_offset_hash_table (kr_offtbl, desc[0].u.kid);
       if (!oi)
         { /* We know that we don't have this key */
@@ -970,9 +980,9 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
           return -1;
         }
       /* We could now create a positive search status and return.
-       * However the problem is that another instance of gpg may 
+       * However the problem is that another instance of gpg may
        * have changed the keyring so that the offsets are not valid
-       * anymore - therefore we don't do it 
+       * anymore - therefore we don't do it
        */
     }
 
@@ -983,13 +993,13 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
       log_debug ("word search mode does not yet work\n");
       /* FIXME: here is a long standing bug in our function and in addition we
          just use the first search description */
-      for (n=0; n < ndesc && !name; n++) 
+      for (n=0; n < ndesc && !name; n++)
         {
-          if (desc[n].mode == KEYDB_SEARCH_MODE_WORDS) 
+          if (desc[n].mode == KEYDB_SEARCH_MODE_WORDS)
             name = desc[n].u.name;
         }
       assert (name);
-      if ( !hd->word_match.name || strcmp (hd->word_match.name, name) ) 
+      if ( !hd->word_match.name || strcmp (hd->word_match.name, name) )
         {
           /* name changed */
           xfree (hd->word_match.name);
@@ -1007,23 +1017,23 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
   main_offset = 0;
   pk_no = uid_no = 0;
   initial_skip = 1; /* skip until we see the start of a keyblock */
-  while (!(rc=search_packet (hd->current.iobuf, &pkt, &offset, need_uid))) 
+  while (!(rc=search_packet (hd->current.iobuf, &pkt, &offset, need_uid)))
     {
       byte afp[MAX_FINGERPRINT_LEN];
       size_t an;
 
-      if (pkt.pkttype == PKT_PUBLIC_KEY  || pkt.pkttype == PKT_SECRET_KEY) 
+      if (pkt.pkttype == PKT_PUBLIC_KEY  || pkt.pkttype == PKT_SECRET_KEY)
         {
           main_offset = offset;
           pk_no = uid_no = 0;
           initial_skip = 0;
         }
-      if (initial_skip) 
+      if (initial_skip)
         {
           free_packet (&pkt);
           continue;
         }
-       
+
       pk = NULL;
       sk = NULL;
       uid = NULL;
@@ -1044,13 +1054,13 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
           if (use_offtbl && !kr_offtbl_ready)
             update_offset_hash_table (kr_offtbl, aki, main_offset);
         }
-      else if (pkt.pkttype == PKT_USER_ID) 
+      else if (pkt.pkttype == PKT_USER_ID)
         {
           uid = pkt.pkt.user_id;
           ++uid_no;
         }
       else if (    pkt.pkttype == PKT_SECRET_KEY
-                   || pkt.pkttype == PKT_SECRET_SUBKEY) 
+                   || pkt.pkttype == PKT_SECRET_SUBKEY)
         {
           sk = pkt.pkt.secret_key;
           ++pk_no;
@@ -1062,28 +1072,28 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
           }
           if (need_keyid)
             keyid_from_sk (sk, aki);
-            
+
         }
 
-      for (n=0; n < ndesc; n++) 
+      for (n=0; n < ndesc; n++)
         {
           switch (desc[n].mode) {
-          case KEYDB_SEARCH_MODE_NONE: 
+          case KEYDB_SEARCH_MODE_NONE:
             BUG ();
             break;
-          case KEYDB_SEARCH_MODE_EXACT: 
+          case KEYDB_SEARCH_MODE_EXACT:
           case KEYDB_SEARCH_MODE_SUBSTR:
           case KEYDB_SEARCH_MODE_MAIL:
           case KEYDB_SEARCH_MODE_MAILSUB:
           case KEYDB_SEARCH_MODE_MAILEND:
-          case KEYDB_SEARCH_MODE_WORDS: 
+          case KEYDB_SEARCH_MODE_WORDS:
             if ( uid && !compare_name (desc[n].mode,
                                        desc[n].u.name,
-                                       uid->name, uid->len)) 
+                                       uid->name, uid->len))
               goto found;
             break;
-                
-          case KEYDB_SEARCH_MODE_SHORT_KID: 
+
+          case KEYDB_SEARCH_MODE_SHORT_KID:
             if ((pk||sk) && desc[n].u.kid[1] == aki[1])
               goto found;
             break;
@@ -1097,19 +1107,19 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
               goto found;
             break;
           case KEYDB_SEARCH_MODE_FPR20:
-          case KEYDB_SEARCH_MODE_FPR: 
+          case KEYDB_SEARCH_MODE_FPR:
             if ((pk||sk) && !memcmp (desc[n].u.fpr, afp, 20))
               goto found;
             break;
-          case KEYDB_SEARCH_MODE_FIRST: 
+          case KEYDB_SEARCH_MODE_FIRST:
             if (pk||sk)
               goto found;
             break;
-          case KEYDB_SEARCH_MODE_NEXT: 
+          case KEYDB_SEARCH_MODE_NEXT:
             if (pk||sk)
               goto found;
             break;
-          default: 
+          default:
             rc = G10ERR_INV_ARG;
             goto found;
           }
@@ -1121,7 +1131,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
         meaningful if this function returns with no errors. */
       if(descindex)
        *descindex=n;
-      for (n=any_skip?0:ndesc; n < ndesc; n++) 
+      for (n=any_skip?0:ndesc; n < ndesc; n++)
         {
           if (desc[n].skipfnc
               && desc[n].skipfnc (desc[n].skipfncvalue, aki, uid))
@@ -1147,12 +1157,12 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
       if (use_offtbl && !kr_offtbl_ready)
         {
           KR_NAME kr;
-          
+
           /* First set the did_full_scan flag for this keyring (ignore
              secret keyrings) */
           for (kr=kr_names; kr; kr = kr->next)
             {
-              if (!kr->secret && hd->resource == kr) 
+              if (!kr->secret && hd->resource == kr)
                 {
                   kr->did_full_scan = 1;
                   break;
@@ -1162,14 +1172,14 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
              offtbl ready */
           for (kr=kr_names; kr; kr = kr->next)
             {
-              if (!kr->secret && !kr->did_full_scan) 
+              if (!kr->secret && !kr->did_full_scan)
                 break;
             }
           if (!kr)
             kr_offtbl_ready = 1;
         }
     }
-  else 
+  else
     hd->current.error = rc;
 
   free_packet(&pkt);
@@ -1181,7 +1191,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
 static int
 create_tmp_file (const char *template,
                  char **r_bakfname, char **r_tmpfname, IOBUF *r_fp)
-{  
+{
   char *bakfname, *tmpfname;
   mode_t oldmask;
 
@@ -1205,7 +1215,7 @@ create_tmp_file (const char *template,
       strcpy (tmpfname,template);
       strcpy (tmpfname+strlen(template)-4, EXTSEP_S "tmp");
     }
-    else 
+    else
       { /* file does not end with gpg; hmmm */
        bakfname = xmalloc (strlen( template ) + 5);
        strcpy (stpcpy(bakfname, template), EXTSEP_S "bak");
@@ -1239,7 +1249,7 @@ create_tmp_file (const char *template,
         xfree (bakfname);
        return rc;
       }
-    
+
     *r_bakfname = bakfname;
     *r_tmpfname = tmpfname;
     return 0;
@@ -1272,7 +1282,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
 
   /* first make a backup file except for secret keyrings */
   if (!secret)
-    { 
+    {
 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
       remove (bakfname);
 #endif
@@ -1284,7 +1294,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
           return rc;
        }
     }
-  
+
   /* then rename the file */
 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
   remove( fname );
@@ -1309,7 +1319,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
     statbuf.st_mode=S_IRUSR | S_IWUSR;
 
     if (((secret && !opt.preserve_permissions)
-         || !stat (bakfname,&statbuf)) 
+         || !stat (bakfname,&statbuf))
         && !chmod (fname,statbuf.st_mode))
       ;
     else
@@ -1337,10 +1347,10 @@ write_keyblock (IOBUF fp, KBNODE keyblock)
 {
   KBNODE kbctx = NULL, node;
   int rc;
-  
-  while ( (node = walk_kbnode (keyblock, &kbctx, 0)) ) 
+
+  while ( (node = walk_kbnode (keyblock, &kbctx, 0)) )
     {
-      if (node->pkt->pkttype == PKT_RING_TRUST) 
+      if (node->pkt->pkttype == PKT_RING_TRUST)
         continue; /* we write it later on our own */
 
       if ( (rc = build_packet (fp, node->pkt) ))
@@ -1349,12 +1359,12 @@ write_keyblock (IOBUF fp, KBNODE keyblock)
                      node->pkt->pkttype, g10_errstr(rc) );
           return rc;
         }
-      if (node->pkt->pkttype == PKT_SIGNATURE) 
+      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
+
+          if (sig->flags.checked && sig->digest_algo != DIGEST_ALGO_MD5)
             {
               cacheval |= 1;
               if (sig->flags.valid)
@@ -1363,7 +1373,7 @@ write_keyblock (IOBUF fp, KBNODE keyblock)
           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)) 
+          if (iobuf_put (fp, cacheval))
             {
               rc = gpg_error_from_syserror ();
               log_error ("writing sigcache packet failed\n");
@@ -1374,7 +1384,7 @@ write_keyblock (IOBUF fp, KBNODE keyblock)
   return 0;
 }
 
-/* 
+/*
  * Walk over all public keyrings, check the signatures and replace the
  * keyring with a new one where the signature cache is then updated.
  * This is only done for the public keyrings.
@@ -1419,7 +1429,7 @@ keyring_rebuild_cache (void *token,int noisy)
                * the original file is closed */
               tmpfp = NULL;
             }
-          rc = lastresname? rename_tmp_file (bakfilename, tmpfilename, 
+          rc = lastresname? rename_tmp_file (bakfilename, tmpfilename,
                                              lastresname, 0) : 0;
           xfree (tmpfilename);  tmpfilename = NULL;
           xfree (bakfilename);  bakfilename = NULL;
@@ -1432,10 +1442,10 @@ keyring_rebuild_cache (void *token,int noisy)
           if (rc)
             goto leave;
         }
-      
+
       release_kbnode (keyblock);
       rc = keyring_get_keyblock (hd, &keyblock);
-      if (rc) 
+      if (rc)
         {
           log_error ("keyring_get_keyblock failed: %s\n", g10_errstr(rc));
           goto leave;
@@ -1479,7 +1489,7 @@ keyring_rebuild_cache (void *token,int noisy)
               sigcount++;
             }
         }
-      
+
       /* write the keyblock to the temporary file */
       rc = write_keyblock (tmpfp, keyblock);
       if (rc)
@@ -1489,10 +1499,10 @@ keyring_rebuild_cache (void *token,int noisy)
         log_info(_("%lu keys cached so far (%lu signatures)\n"),
                  count, sigcount );
 
-    } /* end main loop */ 
+    } /* end main loop */
   if (rc == -1)
     rc = 0;
-  if (rc) 
+  if (rc)
     {
       log_error ("keyring_search failed: %s\n", g10_errstr(rc));
       goto leave;
@@ -1520,8 +1530,8 @@ keyring_rebuild_cache (void *token,int noisy)
  leave:
   if (tmpfp)
     iobuf_cancel (tmpfp);
-  xfree (tmpfilename);  
-  xfree (bakfilename);  
+  xfree (tmpfilename);
+  xfree (bakfilename);
   release_kbnode (keyblock);
   keyring_lock (hd, 0);
   keyring_release (hd);
@@ -1544,13 +1554,13 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
     char *bakfname = NULL;
     char *tmpfname = NULL;
 
-    /* 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 = iobuf_open (fname);
-    if (mode == 1 && !fp && errno == ENOENT) { 
+    if (mode == 1 && !fp && errno == ENOENT) {
        /* insert mode but file does not exist: create a new file */
        KBNODE kbctx, node;
        mode_t oldmask;
index 4cf2cc7..e97b936 100644 (file)
@@ -63,9 +63,6 @@ extern int g10_errors_seen;
 #else
   void g10_exit(int rc);
 #endif
-void print_pubkey_algo_note( int algo );
-void print_cipher_algo_note( int algo );
-void print_digest_algo_note( int algo );
 
 /*-- armor.c --*/
 char *make_radix64_string( const byte *data, size_t len );
@@ -82,6 +79,10 @@ u16 checksum( byte *p, unsigned n );
 u16 checksum_mpi( gcry_mpi_t a );
 u32 buffer_to_u32( const byte *buffer );
 const byte *get_session_marker( size_t *rlen );
+void print_pubkey_algo_note( int algo );
+void print_cipher_algo_note( int algo );
+void print_digest_algo_note( int algo );
+void print_md5_rejected_note (void);
 int map_cipher_openpgp_to_gcry (int algo);
 #define openpgp_cipher_open(_a,_b,_c,_d) gcry_cipher_open((_a),map_cipher_openpgp_to_gcry((_b)),(_c),(_d))
 #define openpgp_cipher_get_algo_keylen(_a) gcry_cipher_get_algo_keylen(map_cipher_openpgp_to_gcry((_a)))
index ef03776..17494ac 100644 (file)
@@ -340,6 +340,22 @@ print_digest_algo_note( int algo )
 }
 
 
+void
+print_md5_rejected_note (void)
+{
+  static int shown;
+
+  if (!shown)
+    {
+      fflush (stdout);
+      log_info
+        (_("Note: signatures using the %s algorithm are rejected\n"),
+         "MD5");
+      shown = 1;
+    }
+}
+
+
 /* Map OpenPGP algo numbers to those used by Libgcrypt.  We need to do
    this for algorithms we implemented in Libgcrypt after they become
    part of OpenPGP.  */
index ed4fa89..2999693 100644 (file)
@@ -272,16 +272,7 @@ do_check( PKT_public_key *pk, PKT_signature *sig, gcry_md_hd_t digest,
     if (sig->digest_algo == GCRY_MD_MD5
         && !opt.flags.allow_weak_digest_algos)
       {
-        static int shown;
-
-        if (!shown)
-          {
-            log_info
-              (_("Note: signatures using the %s algorithm are rejected\n"),
-               "MD5");
-            shown = 1;
-          }
-
+        print_md5_rejected_note ();
         return GPG_ERR_DIGEST_ALGO;
       }
 
@@ -549,9 +540,11 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
     /* Check whether we have cached the result of a previous signature
        check.  Note that we may no longer have the pubkey or hash
        needed to verify a sig, but can still use the cached value.  A
-       cache refresh detects and clears these cases. */
+       cache refresh detects and clears these cases.
+       For safety reasons we ignore cache entries from MD5 signatures.  */
     if ( !opt.no_sig_cache ) {
-        if (sig->flags.checked) { /*cached status available*/
+        if (sig->flags.checked && sig->digest_algo != DIGEST_ALGO_MD5) {
+            /*cached status available*/
            if( is_selfsig ) {
                u32 keyid[2];