1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-10 13:04:23 +01:00

gpg: Avoid using cached MD5 signature status.

* 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>
This commit is contained in:
Werner Koch 2014-10-11 19:41:51 +02:00
parent f952fe8c6d
commit 9112fed78b
4 changed files with 145 additions and 125 deletions

View File

@ -31,7 +31,7 @@
#include "util.h" #include "util.h"
#include "keyring.h" #include "keyring.h"
#include "packet.h" #include "packet.h"
#include "keydb.h" #include "keydb.h"
#include "options.h" #include "options.h"
#include "main.h" /*for check_key_signature()*/ #include "main.h" /*for check_key_signature()*/
#include "i18n.h" #include "i18n.h"
@ -46,11 +46,11 @@ struct off_item {
/*off_t off;*/ /*off_t off;*/
}; };
typedef struct off_item **OffsetHashTable; typedef struct off_item **OffsetHashTable;
typedef struct keyring_name *KR_NAME; typedef struct keyring_name *KR_NAME;
struct keyring_name struct keyring_name
{ {
struct keyring_name *next; struct keyring_name *next;
int secret; int secret;
@ -79,7 +79,7 @@ struct keyring_handle {
int error; int error;
} current; } current;
struct { struct {
CONST_KR_NAME kr; CONST_KR_NAME kr;
off_t offset; off_t offset;
size_t pk_no; size_t pk_no;
size_t uid_no; size_t uid_no;
@ -102,7 +102,7 @@ static struct off_item *
new_offset_item (void) new_offset_item (void)
{ {
struct off_item *k; struct off_item *k;
k = xmalloc_clear (sizeof *k); k = xmalloc_clear (sizeof *k);
return k; return k;
} }
@ -121,7 +121,7 @@ release_offset_items (struct off_item *k)
} }
#endif #endif
static OffsetHashTable static OffsetHashTable
new_offset_hash_table (void) new_offset_hash_table (void)
{ {
struct off_item **tbl; 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) 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;*/ /*k->off = off;*/
return; 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 * 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 to be used to create a handles etc, or the already-issued
* pointer if it has already been registered. The function returns 1 * pointer if it has already been registered. The function returns 1
* if a new keyring was registered. * if a new keyring was registered.
*/ */
int int
keyring_register_filename (const char *fname, int secret, int readonly, keyring_register_filename (const char *fname, int secret, int readonly,
void **ptr) void **ptr)
{ {
KR_NAME kr; KR_NAME kr;
@ -217,7 +217,7 @@ keyring_register_filename (const char *fname, int secret, int readonly,
if (readonly) if (readonly)
kr->readonly = 1; kr->readonly = 1;
*ptr=kr; *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; return r? (r->readonly || !access (r->fname, W_OK)) : 0;
} }
/* Create a new handle for the resource associated with TOKEN. SECRET /* Create a new handle for the resource associated with TOKEN. SECRET
is just just as a cross-check. is just just as a cross-check.
The returned handle must be released using keyring_release (). */ The returned handle must be released using keyring_release (). */
KEYRING_HANDLE KEYRING_HANDLE
keyring_new (void *token, int secret) keyring_new (void *token, int secret)
@ -265,7 +265,7 @@ keyring_new (void *token, int secret)
KR_NAME resource = token; KR_NAME resource = token;
assert (resource && !resource->secret == !secret); assert (resource && !resource->secret == !secret);
hd = xmalloc_clear (sizeof *hd); hd = xmalloc_clear (sizeof *hd);
hd->resource = resource; hd->resource = resource;
hd->secret = !!secret; hd->secret = !!secret;
@ -273,7 +273,7 @@ keyring_new (void *token, int secret)
return hd; return hd;
} }
void void
keyring_release (KEYRING_HANDLE hd) keyring_release (KEYRING_HANDLE hd)
{ {
if (!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. * Lock the keyring with the given handle, or unlock if YES is false.
* We ignore the handle and lock all registered files. * We ignore the handle and lock all registered files.
*/ */
int int
keyring_lock (KEYRING_HANDLE hd, int yes) keyring_lock (KEYRING_HANDLE hd, int yes)
{ {
KR_NAME kr; KR_NAME kr;
@ -323,7 +323,7 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
} }
if (rc) if (rc)
return rc; return rc;
/* and now set the locks */ /* and now set the locks */
for (kr=kr_names; kr; kr = kr->next) { for (kr=kr_names; kr; kr = kr->next) {
if (!keyring_is_writable(kr)) 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 ); log_info ("can't lock `%s'\n", kr->fname );
rc = G10ERR_GENERAL; rc = G10ERR_GENERAL;
} }
else else
kr->is_locked = 1; kr->is_locked = 1;
} }
} }
@ -347,10 +347,10 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
; ;
else if (release_dotlock (kr->lockhd)) else if (release_dotlock (kr->lockhd))
log_info ("can't unlock `%s'\n", kr->fname ); log_info ("can't unlock `%s'\n", kr->fname );
else else
kr->is_locked = 0; kr->is_locked = 0;
} }
} }
return rc; return rc;
} }
@ -360,7 +360,7 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
/* /*
* Return the last found keyring. Caller must free it. * Return the last found keyring. Caller must free it.
* The returned keyblock has the kbode flag bit 0 set for the node with * 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. * the user ID node.
*/ */
int int
@ -406,7 +406,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
init_packet (pkt); init_packet (pkt);
continue; continue;
} }
if (rc) { if (rc) {
log_error ("keyring_get_keyblock: read error: %s\n", log_error ("keyring_get_keyblock: read error: %s\n",
g10_errstr(rc) ); g10_errstr(rc) );
rc = G10ERR_INV_KEYRING; rc = G10ERR_INV_KEYRING;
@ -426,19 +426,26 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
} }
in_cert = 1; in_cert = 1;
if (pkt->pkttype == PKT_RING_TRUST) if (pkt->pkttype == PKT_RING_TRUST)
{ {
/*(this code is duplicated after the loop)*/ /*(this code is duplicated after the loop)*/
if ( lastnode if ( lastnode
&& lastnode->pkt->pkttype == PKT_SIGNATURE && lastnode->pkt->pkttype == PKT_SIGNATURE
&& (pkt->pkt.ring_trust->sigcache & 1) ) { && (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. * 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; PKT_signature *sig = lastnode->pkt->pkt.signature;
sig->flags.checked = 1; if (sig->digest_algo != DIGEST_ALGO_MD5)
sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2); {
sig->flags.checked = 1;
sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
}
} }
/* Reset LASTNODE, so that we set the cache status only from /* Reset LASTNODE, so that we set the cache status only from
* the ring trust packet immediately following a signature. */ * 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) if (++uid_no == hd->found.uid_no)
node->flag |= 2; node->flag |= 2;
break; break;
default: default:
break; break;
} }
@ -478,7 +485,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
} }
set_packet_list_mode(save_mode); set_packet_list_mode(save_mode);
if (rc == -1 && keyblock) if (rc == -1 && keyblock)
rc = 0; /* got the entire keyblock */ rc = 0; /* got the entire keyblock */
if (rc || !ret_kb) if (rc || !ret_kb)
@ -486,12 +493,15 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
else { else {
/*(duplicated form the loop body)*/ /*(duplicated form the loop body)*/
if ( pkt && pkt->pkttype == PKT_RING_TRUST if ( pkt && pkt->pkttype == PKT_RING_TRUST
&& lastnode && lastnode
&& lastnode->pkt->pkttype == PKT_SIGNATURE && lastnode->pkt->pkttype == PKT_SIGNATURE
&& (pkt->pkt.ring_trust->sigcache & 1) ) { && (pkt->pkt.ring_trust->sigcache & 1) ) {
PKT_signature *sig = lastnode->pkt->pkt.signature; PKT_signature *sig = lastnode->pkt->pkt.signature;
sig->flags.checked = 1; if (sig->digest_algo != DIGEST_ALGO_MD5)
sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2); {
sig->flags.checked = 1;
sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
}
} }
*ret_kb = keyblock; *ret_kb = keyblock;
} }
@ -500,7 +510,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
iobuf_close(a); iobuf_close(a);
/* Make sure that future search operations fail immediately when /* 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) if (rc == G10ERR_INV_KEYRING)
hd->current.error = rc; hd->current.error = rc;
@ -571,11 +581,11 @@ keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb)
if (hd->current.kr->readonly) if (hd->current.kr->readonly)
return gpg_error (GPG_ERR_EACCES); return gpg_error (GPG_ERR_EACCES);
} }
else else
fname = hd->resource? hd->resource->fname:NULL; fname = hd->resource? hd->resource->fname:NULL;
if (!fname) if (!fname)
return G10ERR_GENERAL; return G10ERR_GENERAL;
/* Close this one otherwise we will lose the position for /* Close this one otherwise we will lose the position for
* a next search. Fixme: it would be better to adjust the position * 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); update_offset_hash_table_from_kb (kr_offtbl, kb, 0);
} }
return rc; return rc;
} }
@ -639,10 +649,10 @@ keyring_delete_keyblock (KEYRING_HANDLE hd)
/* /*
* Start the next search on this handle right at the beginning * Start the next search on this handle right at the beginning
*/ */
int int
keyring_search_reset (KEYRING_HANDLE hd) keyring_search_reset (KEYRING_HANDLE hd)
{ {
assert (hd); assert (hd);
@ -652,17 +662,17 @@ keyring_search_reset (KEYRING_HANDLE hd)
hd->current.iobuf = NULL; hd->current.iobuf = NULL;
hd->current.eof = 0; hd->current.eof = 0;
hd->current.error = 0; hd->current.error = 0;
hd->found.kr = NULL; hd->found.kr = NULL;
hd->found.offset = 0; hd->found.offset = 0;
return 0; return 0;
} }
static int static int
prepare_search (KEYRING_HANDLE hd) prepare_search (KEYRING_HANDLE hd)
{ {
if (hd->current.error) if (hd->current.error)
return hd->current.error; /* still in error state */ return hd->current.error; /* still in error state */
if (hd->current.kr && !hd->current.eof) { if (hd->current.kr && !hd->current.eof) {
@ -671,7 +681,7 @@ prepare_search (KEYRING_HANDLE hd)
return 0; /* okay */ return 0; /* okay */
} }
if (!hd->current.kr && hd->current.eof) if (!hd->current.kr && hd->current.eof)
return -1; /* still EOF */ return -1; /* still EOF */
if (!hd->current.kr) { /* start search with first keyring */ if (!hd->current.kr) { /* start search with first keyring */
@ -683,7 +693,7 @@ prepare_search (KEYRING_HANDLE hd)
assert (!hd->current.iobuf); assert (!hd->current.iobuf);
} }
else { /* EOF */ else { /* EOF */
iobuf_close (hd->current.iobuf); iobuf_close (hd->current.iobuf);
hd->current.iobuf = NULL; hd->current.iobuf = NULL;
hd->current.kr = NULL; hd->current.kr = NULL;
hd->current.eof = 1; hd->current.eof = 1;
@ -841,7 +851,7 @@ compare_name (int mode, const char *name, const char *uid, size_t uidlen)
int i; int i;
const char *s, *se; const char *s, *se;
if (mode == KEYDB_SEARCH_MODE_EXACT) { if (mode == KEYDB_SEARCH_MODE_EXACT) {
for (i=0; name[i] && uidlen; i++, uidlen--) for (i=0; name[i] && uidlen; i++, uidlen--)
if (uid[i] != name[i]) if (uid[i] != name[i])
break; break;
@ -852,7 +862,7 @@ compare_name (int mode, const char *name, const char *uid, size_t uidlen)
if (ascii_memistr( uid, uidlen, name )) if (ascii_memistr( uid, uidlen, name ))
return 0; 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_MAILSUB
|| mode == KEYDB_SEARCH_MODE_MAILEND) { || mode == KEYDB_SEARCH_MODE_MAILEND) {
for (i=0, s= uid; i < uidlen && *s != '<'; s++, i++) 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) { if (i < uidlen) {
i = se - s; i = se - s;
if (mode == KEYDB_SEARCH_MODE_MAIL) { if (mode == KEYDB_SEARCH_MODE_MAIL) {
if( strlen(name)-2 == i if( strlen(name)-2 == i
&& !ascii_memcasecmp( s, name+1, i) ) && !ascii_memcasecmp( s, name+1, i) )
return 0; return 0;
@ -888,11 +898,11 @@ compare_name (int mode, const char *name, const char *uid, size_t uidlen)
} }
/* /*
* Search through the keyring(s), starting at the current position, * Search through the keyring(s), starting at the current position,
* for a keyblock which contains one of the keys described in the DESC array. * 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, keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
size_t ndesc, size_t *descindex) 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 */ /* figure out what information we need */
need_uid = need_words = need_keyid = need_fpr = any_skip = 0; 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_SUBSTR:
case KEYDB_SEARCH_MODE_MAIL: case KEYDB_SEARCH_MODE_MAIL:
case KEYDB_SEARCH_MODE_MAILSUB: case KEYDB_SEARCH_MODE_MAILSUB:
case KEYDB_SEARCH_MODE_MAILEND: case KEYDB_SEARCH_MODE_MAILEND:
need_uid = 1; need_uid = 1;
break; break;
case KEYDB_SEARCH_MODE_WORDS: case KEYDB_SEARCH_MODE_WORDS:
need_uid = 1; need_uid = 1;
need_words = 1; need_words = 1;
break; break;
case KEYDB_SEARCH_MODE_SHORT_KID: case KEYDB_SEARCH_MODE_SHORT_KID:
case KEYDB_SEARCH_MODE_LONG_KID: case KEYDB_SEARCH_MODE_LONG_KID:
need_keyid = 1; need_keyid = 1;
break; break;
case KEYDB_SEARCH_MODE_FPR16: case KEYDB_SEARCH_MODE_FPR16:
case KEYDB_SEARCH_MODE_FPR20: case KEYDB_SEARCH_MODE_FPR20:
case KEYDB_SEARCH_MODE_FPR: case KEYDB_SEARCH_MODE_FPR:
need_fpr = 1; need_fpr = 1;
break; break;
case KEYDB_SEARCH_MODE_FIRST: case KEYDB_SEARCH_MODE_FIRST:
@ -942,7 +952,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
break; break;
default: break; default: break;
} }
if (desc[n].skipfnc) if (desc[n].skipfnc)
{ {
any_skip = 1; any_skip = 1;
need_keyid = 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) else if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID)
{ {
struct off_item *oi; struct off_item *oi;
oi = lookup_offset_hash_table (kr_offtbl, desc[0].u.kid); oi = lookup_offset_hash_table (kr_offtbl, desc[0].u.kid);
if (!oi) if (!oi)
{ /* We know that we don't have this key */ { /* We know that we don't have this key */
@ -970,9 +980,9 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
return -1; return -1;
} }
/* We could now create a positive search status and return. /* 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 * 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"); log_debug ("word search mode does not yet work\n");
/* FIXME: here is a long standing bug in our function and in addition we /* FIXME: here is a long standing bug in our function and in addition we
just use the first search description */ 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; name = desc[n].u.name;
} }
assert (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 */ /* name changed */
xfree (hd->word_match.name); xfree (hd->word_match.name);
@ -1007,23 +1017,23 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
main_offset = 0; main_offset = 0;
pk_no = uid_no = 0; pk_no = uid_no = 0;
initial_skip = 1; /* skip until we see the start of a keyblock */ 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]; byte afp[MAX_FINGERPRINT_LEN];
size_t an; 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; main_offset = offset;
pk_no = uid_no = 0; pk_no = uid_no = 0;
initial_skip = 0; initial_skip = 0;
} }
if (initial_skip) if (initial_skip)
{ {
free_packet (&pkt); free_packet (&pkt);
continue; continue;
} }
pk = NULL; pk = NULL;
sk = NULL; sk = NULL;
uid = NULL; uid = NULL;
@ -1044,13 +1054,13 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
if (use_offtbl && !kr_offtbl_ready) if (use_offtbl && !kr_offtbl_ready)
update_offset_hash_table (kr_offtbl, aki, main_offset); 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 = pkt.pkt.user_id;
++uid_no; ++uid_no;
} }
else if ( pkt.pkttype == PKT_SECRET_KEY else if ( pkt.pkttype == PKT_SECRET_KEY
|| pkt.pkttype == PKT_SECRET_SUBKEY) || pkt.pkttype == PKT_SECRET_SUBKEY)
{ {
sk = pkt.pkt.secret_key; sk = pkt.pkt.secret_key;
++pk_no; ++pk_no;
@ -1062,28 +1072,28 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
} }
if (need_keyid) if (need_keyid)
keyid_from_sk (sk, aki); keyid_from_sk (sk, aki);
} }
for (n=0; n < ndesc; n++) for (n=0; n < ndesc; n++)
{ {
switch (desc[n].mode) { switch (desc[n].mode) {
case KEYDB_SEARCH_MODE_NONE: case KEYDB_SEARCH_MODE_NONE:
BUG (); BUG ();
break; break;
case KEYDB_SEARCH_MODE_EXACT: case KEYDB_SEARCH_MODE_EXACT:
case KEYDB_SEARCH_MODE_SUBSTR: case KEYDB_SEARCH_MODE_SUBSTR:
case KEYDB_SEARCH_MODE_MAIL: case KEYDB_SEARCH_MODE_MAIL:
case KEYDB_SEARCH_MODE_MAILSUB: case KEYDB_SEARCH_MODE_MAILSUB:
case KEYDB_SEARCH_MODE_MAILEND: case KEYDB_SEARCH_MODE_MAILEND:
case KEYDB_SEARCH_MODE_WORDS: case KEYDB_SEARCH_MODE_WORDS:
if ( uid && !compare_name (desc[n].mode, if ( uid && !compare_name (desc[n].mode,
desc[n].u.name, desc[n].u.name,
uid->name, uid->len)) uid->name, uid->len))
goto found; goto found;
break; break;
case KEYDB_SEARCH_MODE_SHORT_KID: case KEYDB_SEARCH_MODE_SHORT_KID:
if ((pk||sk) && desc[n].u.kid[1] == aki[1]) if ((pk||sk) && desc[n].u.kid[1] == aki[1])
goto found; goto found;
break; break;
@ -1097,19 +1107,19 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
goto found; goto found;
break; break;
case KEYDB_SEARCH_MODE_FPR20: 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)) if ((pk||sk) && !memcmp (desc[n].u.fpr, afp, 20))
goto found; goto found;
break; break;
case KEYDB_SEARCH_MODE_FIRST: case KEYDB_SEARCH_MODE_FIRST:
if (pk||sk) if (pk||sk)
goto found; goto found;
break; break;
case KEYDB_SEARCH_MODE_NEXT: case KEYDB_SEARCH_MODE_NEXT:
if (pk||sk) if (pk||sk)
goto found; goto found;
break; break;
default: default:
rc = G10ERR_INV_ARG; rc = G10ERR_INV_ARG;
goto found; goto found;
} }
@ -1121,7 +1131,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
meaningful if this function returns with no errors. */ meaningful if this function returns with no errors. */
if(descindex) if(descindex)
*descindex=n; *descindex=n;
for (n=any_skip?0:ndesc; n < ndesc; n++) for (n=any_skip?0:ndesc; n < ndesc; n++)
{ {
if (desc[n].skipfnc if (desc[n].skipfnc
&& desc[n].skipfnc (desc[n].skipfncvalue, aki, uid)) && 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) if (use_offtbl && !kr_offtbl_ready)
{ {
KR_NAME kr; KR_NAME kr;
/* First set the did_full_scan flag for this keyring (ignore /* First set the did_full_scan flag for this keyring (ignore
secret keyrings) */ secret keyrings) */
for (kr=kr_names; kr; kr = kr->next) 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; kr->did_full_scan = 1;
break; break;
@ -1162,14 +1172,14 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
offtbl ready */ offtbl ready */
for (kr=kr_names; kr; kr = kr->next) for (kr=kr_names; kr; kr = kr->next)
{ {
if (!kr->secret && !kr->did_full_scan) if (!kr->secret && !kr->did_full_scan)
break; break;
} }
if (!kr) if (!kr)
kr_offtbl_ready = 1; kr_offtbl_ready = 1;
} }
} }
else else
hd->current.error = rc; hd->current.error = rc;
free_packet(&pkt); free_packet(&pkt);
@ -1181,7 +1191,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
static int static int
create_tmp_file (const char *template, create_tmp_file (const char *template,
char **r_bakfname, char **r_tmpfname, IOBUF *r_fp) char **r_bakfname, char **r_tmpfname, IOBUF *r_fp)
{ {
char *bakfname, *tmpfname; char *bakfname, *tmpfname;
mode_t oldmask; mode_t oldmask;
@ -1205,7 +1215,7 @@ create_tmp_file (const char *template,
strcpy (tmpfname,template); strcpy (tmpfname,template);
strcpy (tmpfname+strlen(template)-4, EXTSEP_S "tmp"); strcpy (tmpfname+strlen(template)-4, EXTSEP_S "tmp");
} }
else else
{ /* file does not end with gpg; hmmm */ { /* file does not end with gpg; hmmm */
bakfname = xmalloc (strlen( template ) + 5); bakfname = xmalloc (strlen( template ) + 5);
strcpy (stpcpy(bakfname, template), EXTSEP_S "bak"); strcpy (stpcpy(bakfname, template), EXTSEP_S "bak");
@ -1239,7 +1249,7 @@ create_tmp_file (const char *template,
xfree (bakfname); xfree (bakfname);
return rc; return rc;
} }
*r_bakfname = bakfname; *r_bakfname = bakfname;
*r_tmpfname = tmpfname; *r_tmpfname = tmpfname;
return 0; return 0;
@ -1272,7 +1282,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
/* first make a backup file except for secret keyrings */ /* first make a backup file except for secret keyrings */
if (!secret) if (!secret)
{ {
#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
remove (bakfname); remove (bakfname);
#endif #endif
@ -1284,7 +1294,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
return rc; return rc;
} }
} }
/* then rename the file */ /* then rename the file */
#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
remove( fname ); remove( fname );
@ -1309,7 +1319,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
statbuf.st_mode=S_IRUSR | S_IWUSR; statbuf.st_mode=S_IRUSR | S_IWUSR;
if (((secret && !opt.preserve_permissions) if (((secret && !opt.preserve_permissions)
|| !stat (bakfname,&statbuf)) || !stat (bakfname,&statbuf))
&& !chmod (fname,statbuf.st_mode)) && !chmod (fname,statbuf.st_mode))
; ;
else else
@ -1337,10 +1347,10 @@ write_keyblock (IOBUF fp, KBNODE keyblock)
{ {
KBNODE kbctx = NULL, node; KBNODE kbctx = NULL, node;
int rc; 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 */ continue; /* we write it later on our own */
if ( (rc = build_packet (fp, node->pkt) )) if ( (rc = build_packet (fp, node->pkt) ))
@ -1349,12 +1359,12 @@ write_keyblock (IOBUF fp, KBNODE keyblock)
node->pkt->pkttype, g10_errstr(rc) ); node->pkt->pkttype, g10_errstr(rc) );
return rc; return rc;
} }
if (node->pkt->pkttype == PKT_SIGNATURE) if (node->pkt->pkttype == PKT_SIGNATURE)
{ /* always write a signature cache packet */ { /* always write a signature cache packet */
PKT_signature *sig = node->pkt->pkt.signature; PKT_signature *sig = node->pkt->pkt.signature;
unsigned int cacheval = 0; unsigned int cacheval = 0;
if (sig->flags.checked) if (sig->flags.checked && sig->digest_algo != DIGEST_ALGO_MD5)
{ {
cacheval |= 1; cacheval |= 1;
if (sig->flags.valid) 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, 0xb0); /* old style packet 12, 1 byte len*/
iobuf_put (fp, 2); /* 2 bytes */ iobuf_put (fp, 2); /* 2 bytes */
iobuf_put (fp, 0); /* unused */ iobuf_put (fp, 0); /* unused */
if (iobuf_put (fp, cacheval)) if (iobuf_put (fp, cacheval))
{ {
rc = gpg_error_from_syserror (); rc = gpg_error_from_syserror ();
log_error ("writing sigcache packet failed\n"); log_error ("writing sigcache packet failed\n");
@ -1374,7 +1384,7 @@ write_keyblock (IOBUF fp, KBNODE keyblock)
return 0; return 0;
} }
/* /*
* Walk over all public keyrings, check the signatures and replace the * Walk over all public keyrings, check the signatures and replace the
* keyring with a new one where the signature cache is then updated. * keyring with a new one where the signature cache is then updated.
* This is only done for the public keyrings. * This is only done for the public keyrings.
@ -1419,7 +1429,7 @@ keyring_rebuild_cache (void *token,int noisy)
* the original file is closed */ * the original file is closed */
tmpfp = NULL; tmpfp = NULL;
} }
rc = lastresname? rename_tmp_file (bakfilename, tmpfilename, rc = lastresname? rename_tmp_file (bakfilename, tmpfilename,
lastresname, 0) : 0; lastresname, 0) : 0;
xfree (tmpfilename); tmpfilename = NULL; xfree (tmpfilename); tmpfilename = NULL;
xfree (bakfilename); bakfilename = NULL; xfree (bakfilename); bakfilename = NULL;
@ -1432,10 +1442,10 @@ keyring_rebuild_cache (void *token,int noisy)
if (rc) if (rc)
goto leave; goto leave;
} }
release_kbnode (keyblock); release_kbnode (keyblock);
rc = keyring_get_keyblock (hd, &keyblock); rc = keyring_get_keyblock (hd, &keyblock);
if (rc) if (rc)
{ {
log_error ("keyring_get_keyblock failed: %s\n", g10_errstr(rc)); log_error ("keyring_get_keyblock failed: %s\n", g10_errstr(rc));
goto leave; goto leave;
@ -1479,7 +1489,7 @@ keyring_rebuild_cache (void *token,int noisy)
sigcount++; sigcount++;
} }
} }
/* write the keyblock to the temporary file */ /* write the keyblock to the temporary file */
rc = write_keyblock (tmpfp, keyblock); rc = write_keyblock (tmpfp, keyblock);
if (rc) if (rc)
@ -1489,10 +1499,10 @@ keyring_rebuild_cache (void *token,int noisy)
log_info(_("%lu keys cached so far (%lu signatures)\n"), log_info(_("%lu keys cached so far (%lu signatures)\n"),
count, sigcount ); count, sigcount );
} /* end main loop */ } /* end main loop */
if (rc == -1) if (rc == -1)
rc = 0; rc = 0;
if (rc) if (rc)
{ {
log_error ("keyring_search failed: %s\n", g10_errstr(rc)); log_error ("keyring_search failed: %s\n", g10_errstr(rc));
goto leave; goto leave;
@ -1520,8 +1530,8 @@ keyring_rebuild_cache (void *token,int noisy)
leave: leave:
if (tmpfp) if (tmpfp)
iobuf_cancel (tmpfp); iobuf_cancel (tmpfp);
xfree (tmpfilename); xfree (tmpfilename);
xfree (bakfilename); xfree (bakfilename);
release_kbnode (keyblock); release_kbnode (keyblock);
keyring_lock (hd, 0); keyring_lock (hd, 0);
keyring_release (hd); keyring_release (hd);
@ -1544,13 +1554,13 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
char *bakfname = NULL; char *bakfname = NULL;
char *tmpfname = 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 */ permissions of the file */
if (access (fname, W_OK)) if (access (fname, W_OK))
return gpg_error_from_syserror (); return gpg_error_from_syserror ();
fp = iobuf_open (fname); 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 */ /* insert mode but file does not exist: create a new file */
KBNODE kbctx, node; KBNODE kbctx, node;
mode_t oldmask; mode_t oldmask;

View File

@ -63,9 +63,6 @@ extern int g10_errors_seen;
#else #else
void g10_exit(int rc); void g10_exit(int rc);
#endif #endif
void print_pubkey_algo_note( int algo );
void print_cipher_algo_note( int algo );
void print_digest_algo_note( int algo );
/*-- armor.c --*/ /*-- armor.c --*/
char *make_radix64_string( const byte *data, size_t len ); 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 ); u16 checksum_mpi( gcry_mpi_t a );
u32 buffer_to_u32( const byte *buffer ); u32 buffer_to_u32( const byte *buffer );
const byte *get_session_marker( size_t *rlen ); 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); 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_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))) #define openpgp_cipher_get_algo_keylen(_a) gcry_cipher_get_algo_keylen(map_cipher_openpgp_to_gcry((_a)))

View 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 /* Map OpenPGP algo numbers to those used by Libgcrypt. We need to do
this for algorithms we implemented in Libgcrypt after they become this for algorithms we implemented in Libgcrypt after they become
part of OpenPGP. */ part of OpenPGP. */

View 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 if (sig->digest_algo == GCRY_MD_MD5
&& !opt.flags.allow_weak_digest_algos) && !opt.flags.allow_weak_digest_algos)
{ {
static int shown; print_md5_rejected_note ();
if (!shown)
{
log_info
(_("Note: signatures using the %s algorithm are rejected\n"),
"MD5");
shown = 1;
}
return GPG_ERR_DIGEST_ALGO; 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 whether we have cached the result of a previous signature
check. Note that we may no longer have the pubkey or hash 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 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 ( !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 ) { if( is_selfsig ) {
u32 keyid[2]; u32 keyid[2];