1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-02-01 16:33:02 +01:00

Changed signature status cache

This commit is contained in:
Werner Koch 2001-09-25 15:20:59 +00:00
parent a3af543617
commit 1f4bdf4d26
18 changed files with 478 additions and 281 deletions

12
NEWS
View File

@ -37,6 +37,18 @@
* The entire keyring management has been revamped.
* The way signature stati are store has changed, so that v3
signatures can be supported. To increase the speed of many
operations for existing keys you can use the new
--rebuild-keydb-caches command.
* The entire key validation process (trustdb) has been revamped.
See the man page entries for --update-trustdb, --check-trustdb
and --no-auto-check-trustdb.
* --trusted-keys is again obsolete, --edit can be used to set the
ownertrust of any key to ultimately trusted.
Noteworthy changes in version 1.0.6 (2001-05-29)
------------------------------------------------

View File

@ -513,7 +513,6 @@ command --update-trustdb.
There are a few other options which control how this command works.
Most notable here is the --merge-only option which does not insert new keys
but does only the merging of new signatures, user-IDs and subkeys.
See also the option --allow-secret-key-import.
</para></listitem></varlistentry>
@ -1530,9 +1529,7 @@ Don't insert new keys into the keyrings while doing an import.
<varlistentry>
<term>--allow-secret-key-import</term>
<listitem><para>
Allow import of secret keys. The import command normally skips secret
keys because a secret key can otherwise be used to attack the trust
calculation.
This is an obsolete option and is not used anywhere.
</para></listitem></varlistentry>
<varlistentry>

View File

@ -1,3 +1,31 @@
2001-09-25 Werner Koch <wk@gnupg.org>
* g10.c, options.h, import.c: Removed the entire
allow-secret-key-import stuff because the validity is now
controlled by other means.
* g10.c: New command --rebuild-keydb-caches.
* keydb.c (keydb_rebuild_caches): New.
* keyring.c (do_copy): Moved some code to
(create_tmp_file, rename_tmp_file, write_keyblock): new functions.
(keyring_rebuild_cache): New.
* packet.h (PKT_ring_trust): Add sigcache field.
* parse-packet.c (parse_trust): Parse sigcache.
* keyring.c (do_copy): Always insert a sigcache packet.
(keyring_get_keyblock): Copy the sigcache packet to the signature.
* sig-check.c (cache_sig_result): Renamed from
cache_selfsig_result. Changed implementation to use the flag bits
and changed all callers.
(mdc_kludge_check): Removed this unused code.
(do_check): Do not set the sig flags here.
* import.c (read_block): Make sure that ring_trust packets are
never imported.
* export.c (do_export_stream): and never export them.
* trustdb.c (make_key_array): Skip revoked and expired keys.
2001-09-24 Werner Koch <wk@gnupg.org>
* g10.c, options.h: New option --no-auto-check-trustdb.

View File

@ -135,7 +135,7 @@ build_packet( IOBUF out, PACKET *pkt )
rc = do_onepass_sig( out, ctb, pkt->pkt.onepass_sig );
break;
case PKT_RING_TRUST:
break; /* ignore it */
break; /* ignore it (keyring.c does write it directly)*/
default:
log_bug("invalid packet type in build_packet()\n");
break;

View File

@ -186,6 +186,9 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
* secret keyring */
if( !secret && node->pkt->pkttype == PKT_COMMENT )
continue;
/* make sure that ring_trust packets never get exported */
if (node->pkt->pkttype == PKT_RING_TRUST)
continue;
/* do not export packets which are marked as not exportable */
if( node->pkt->pkttype == PKT_SIGNATURE ) {
const char *p;

View File

@ -112,7 +112,7 @@ enum cmd_and_opt_values { aNull = 0,
aEnArmor,
aGenRandom,
aPipeMode,
aRefreshCaches,
aRebuildKeydbCaches,
aRefreshKeys,
oTextmode,
@ -441,6 +441,7 @@ static ARGPARSE_OPTS opts[] = {
{ oEnableSpecialFilenames, "enable-special-filenames", 0, "@" },
{ oNoExpensiveTrustChecks, "no-expensive-trust-checks", 0, "@" },
{ aDeleteSecretAndPublicKey, "delete-secret-and-public-key",256, "@" },
{ aRebuildKeydbCaches, "rebuild-keydb-caches", 256, "@"},
{ oPreservePermissions, "preserve-permissions", 0, "@"},
{ oPreferenceList, "preference-list", 2, "@"},
{ oEmu3DESS2KBug, "emulate-3des-s2k-bug", 0, "@"},
@ -848,6 +849,7 @@ main( int argc, char **argv )
case aExportOwnerTrust: set_cmd( &cmd, aExportOwnerTrust); break;
case aImportOwnerTrust: set_cmd( &cmd, aImportOwnerTrust); break;
case aPipeMode: set_cmd( &cmd, aPipeMode); break;
case aRebuildKeydbCaches: set_cmd( &cmd, aRebuildKeydbCaches); break;
case oArmor: opt.armor = 1; opt.no_armor=0; break;
case oOutput: opt.outfile = pargs.r.ret_str; break;
@ -1078,7 +1080,7 @@ main( int argc, char **argv )
opt.override_session_key = pargs.r.ret_str;
break;
case oMergeOnly: opt.merge_only = 1; break;
case oAllowSecretKeyImport: opt.allow_secret_key_import = 1; break;
case oAllowSecretKeyImport: /* obsolete */ break;
case oTryAllSecrets: opt.try_all_secrets = 1; break;
case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break;
case oEnableSpecialFilenames:
@ -1689,6 +1691,12 @@ main( int argc, char **argv )
run_in_pipemode ();
break;
case aRebuildKeydbCaches:
if (argc)
wrong_args ("--rebuild-keydb-caches");
keydb_rebuild_caches ();
break;
case aListPackets:
opt.list_packets=2;
default:

View File

@ -55,13 +55,13 @@ struct stats_s {
static int import( IOBUF inp, int fast, const char* fname,
int allow_secret, struct stats_s *stats );
struct stats_s *stats );
static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root );
static void remove_bad_stuff (KBNODE keyblock);
static int import_one( const char *fname, KBNODE keyblock, int fast,
struct stats_s *stats);
static int import_secret_one( const char *fname, KBNODE keyblock,
int allow, struct stats_s *stats );
struct stats_s *stats );
static int import_revoke_cert( const char *fname, KBNODE node,
struct stats_s *stats);
static int chk_self_sigs( const char *fname, KBNODE keyblock,
@ -144,8 +144,7 @@ import_keys( char **fnames, int nnames, int fast, void *stats_handle )
if( !inp )
log_error(_("can't open `%s': %s\n"), fname, strerror(errno) );
else {
int rc = import( inp, fast, fname,
opt.allow_secret_key_import, stats );
int rc = import( inp, fast, fname, stats );
iobuf_close(inp);
if( rc )
log_error("import from `%s' failed: %s\n", fname,
@ -170,8 +169,7 @@ import_keys_stream( IOBUF inp, int fast, void *stats_handle )
if (!stats)
stats = import_new_stats_handle ();
rc = import( inp, fast, "[stream]",
opt.allow_secret_key_import, stats );
rc = import( inp, fast, "[stream]", stats);
if (!stats_handle) {
import_print_stats (stats);
import_release_stats_handle (stats);
@ -181,8 +179,7 @@ import_keys_stream( IOBUF inp, int fast, void *stats_handle )
}
static int
import( IOBUF inp, int fast, const char* fname, int allow_secret,
struct stats_s *stats )
import( IOBUF inp, int fast, const char* fname, struct stats_s *stats )
{
PACKET *pending_pkt = NULL;
KBNODE keyblock;
@ -201,8 +198,7 @@ import( IOBUF inp, int fast, const char* fname, int allow_secret,
if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY )
rc = import_one( fname, keyblock, fast, stats );
else if( keyblock->pkt->pkttype == PKT_SECRET_KEY )
rc = import_secret_one( fname, keyblock,
allow_secret, stats );
rc = import_secret_one( fname, keyblock, stats );
else if( keyblock->pkt->pkttype == PKT_SIGNATURE
&& keyblock->pkt->pkt.signature->sig_class == 0x20 )
rc = import_revoke_cert( fname, keyblock, stats );
@ -344,6 +340,11 @@ read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root )
init_packet(pkt);
break;
case PKT_RING_TRUST:
/* skip those packets */
free_packet( pkt );
init_packet(pkt);
break;
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
@ -386,7 +387,8 @@ remove_bad_stuff (KBNODE keyblock)
for (node=keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_SIGNATURE ) {
/* delete the subpackets we use for the verification cache */
/* delete the subpackets we used to use for the
verification cache */
delete_sig_subpkt (node->pkt->pkt.signature->unhashed,
SIGSUBPKT_PRIV_VERIFY_CACHE);
}
@ -606,7 +608,7 @@ import_one( const char *fname, KBNODE keyblock, int fast,
* with the trust calculation.
*/
static int
import_secret_one( const char *fname, KBNODE keyblock, int allow,
import_secret_one( const char *fname, KBNODE keyblock,
struct stats_s *stats)
{
PKT_secret_key *sk;
@ -634,12 +636,6 @@ import_secret_one( const char *fname, KBNODE keyblock, int allow,
putc('\n', stderr);
}
stats->secret_read++;
if (!allow) {
log_info ( _("secret key %08lX not imported "
"(use %s to allow for it)\n"),
(ulong)keyid[1], "--allow-secret-key-import");
return 0;
}
if( !uidnode ) {
log_error( _("key %08lX: no user ID\n"), (ulong)keyid[1]);

View File

@ -320,7 +320,7 @@ lock_all (KEYDB_HANDLE hd)
}
if (rc) {
/* revert the alreadt set locks */
/* revert the already set locks */
for (i--; i >= 0; i--) {
switch (hd->active[i].type) {
case KEYDB_RESOURCE_TYPE_NONE:
@ -517,6 +517,22 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
return rc;
}
/*
* Rebuild the caches of all key resources.
*/
void
keydb_rebuild_caches (void)
{
int rc;
rc = keyring_rebuild_cache ();
if (rc)
log_error (_("failed to rebuild all keyring caches: %s\n"),
g10_errstr (rc));
/* add other types here */
}
/*
* Start the next search on this handle right at the beginning

View File

@ -148,6 +148,7 @@ int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb);
int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb);
int keydb_delete_keyblock (KEYDB_HANDLE hd);
int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved);
void keydb_rebuild_caches (void);
int keydb_search_reset (KEYDB_HANDLE hd);
int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
int keydb_search_first (KEYDB_HANDLE hd);

View File

@ -32,6 +32,7 @@
#include "packet.h"
#include "keydb.h"
#include "options.h"
#include "main.h" /*for check_key_signature()*/
#include "i18n.h"
typedef struct keyring_name *KR_NAME;
@ -219,7 +220,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
{
PACKET *pkt;
int rc;
KBNODE keyblock = NULL, node;
KBNODE keyblock = NULL, node, lastnode;
IOBUF a;
int in_cert = 0;
int pk_no = 0;
@ -246,6 +247,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
pkt = m_alloc (sizeof *pkt);
init_packet (pkt);
hd->found.n_packets = 0;;
lastnode = NULL;
while ((rc=parse_packet (a, pkt)) != -1) {
hd->found.n_packets++;
if (rc == G10ERR_UNKNOWN_PACKET) {
@ -273,36 +275,64 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
}
in_cert = 1;
node = new_kbnode (pkt);
if (!keyblock)
keyblock = node;
else
add_kbnode (keyblock, node);
if ( pkt->pkttype == PKT_PUBLIC_KEY
|| pkt->pkttype == PKT_PUBLIC_SUBKEY
|| pkt->pkttype == PKT_SECRET_KEY
|| pkt->pkttype == PKT_SECRET_SUBKEY) {
if (++pk_no == hd->found.pk_no)
node->flag |= 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 folling a signature */
lastnode = NULL;
}
else if ( pkt->pkttype == PKT_USER_ID) {
if (++uid_no == hd->found.uid_no)
node->flag |= 2;
else {
node = lastnode = new_kbnode (pkt);
if (!keyblock)
keyblock = node;
else
add_kbnode (keyblock, node);
if ( pkt->pkttype == PKT_PUBLIC_KEY
|| pkt->pkttype == PKT_PUBLIC_SUBKEY
|| pkt->pkttype == PKT_SECRET_KEY
|| pkt->pkttype == PKT_SECRET_SUBKEY) {
if (++pk_no == hd->found.pk_no)
node->flag |= 1;
}
else if ( pkt->pkttype == PKT_USER_ID) {
if (++uid_no == hd->found.uid_no)
node->flag |= 2;
}
}
pkt = m_alloc (sizeof *pkt);
init_packet(pkt);
}
if (rc == -1 && keyblock)
if (rc == -1 && keyblock)
rc = 0; /* got the entire keyblock */
if (rc || !ret_kb)
release_kbnode (keyblock);
else
else {
/*(duplicated form 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;
}
free_packet (pkt);
m_free (pkt);
iobuf_close(a);
@ -874,6 +904,285 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
}
static int
create_tmp_file (const char *template,
char **r_bakfname, char **r_tmpfname, IOBUF *r_fp)
{
char *bakfname, *tmpfname;
*r_bakfname = NULL;
*r_tmpfname = NULL;
# ifdef USE_ONLY_8DOT3
/* Here is another Windoze bug?:
* you cant rename("pubring.gpg.tmp", "pubring.gpg");
* but rename("pubring.gpg.tmp", "pubring.aaa");
* works. So we replace .gpg by .bak or .tmp
*/
if (strlen (template) > 4
&& !strcmp (template+strlen(template)-4, EXTSEP_S "gpg") )
{
bakfname = m_alloc (strlen (template) + 1);
strcpy (bakfname, template);
strcpy (bakfname+strlen(template)-4, EXTSEP_S "bak");
tmpfname = m_alloc (strlen( template ) + 1 );
strcpy (tmpfname,template);
strcpy (tmpfname+strlen(template)-4, EXTSEP_S "tmp");
}
else
{ /* file does not end with gpg; hmmm */
bakfname = m_alloc (strlen( template ) + 5);
strcpy (stpcpy(bakfname, template), EXTSEP_S "bak");
tmpfname = m_alloc (strlen( template ) + 5);
strcpy (stpcpy(tmpfname, template), EXTSEP_S "tmp");
}
# else /* Posix file names */
bakfname = m_alloc (strlen( template ) + 2);
strcpy (stpcpy (bakfname,template),"~");
tmpfname = m_alloc (strlen( template ) + 5);
strcpy (stpcpy(tmpfname,template), EXTSEP_S "tmp");
# endif /* Posix filename */
*r_fp = iobuf_create (tmpfname);
if (!*r_fp) {
log_error ("can't create `%s': %s\n", tmpfname, strerror(errno) );
m_free (tmpfname);
m_free (bakfname);
return G10ERR_OPEN_FILE;
}
*r_bakfname = bakfname;
*r_tmpfname = tmpfname;
return 0;
}
static int
rename_tmp_file (const char *bakfname, const char *tmpfname,
const char *fname, int secret )
{
int rc=0;
/* restrict the permissions for secret keyrings */
#ifndef HAVE_DOSISH_SYSTEM
if (secret && !opt.preserve_permissions)
{
if (chmod (tmpfname, S_IRUSR | S_IWUSR) )
{
log_error ("chmod of `%s' failed: %s\n",
tmpfname, strerror(errno) );
return G10ERR_WRITE_FILE;
}
}
#endif
/* invalidate close caches*/
iobuf_ioctl (NULL, 2, 0, (char*)tmpfname );
iobuf_ioctl (NULL, 2, 0, (char*)bakfname );
iobuf_ioctl (NULL, 2, 0, (char*)fname );
/* first make a backup file except for secret keyrings */
if (!secret)
{
#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
remove (bakfname);
#endif
if (rename (fname, bakfname) )
{
log_error ("renaming `%s' to `%s' failed: %s\n",
fname, bakfname, strerror(errno) );
return G10ERR_RENAME_FILE;
}
}
/* then rename the file */
#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
remove( fname );
#endif
if (rename (tmpfname, fname) )
{
log_error ("renaming `%s' to `%s' failed: %s\n",
tmpfname, fname, strerror(errno) );
rc = G10ERR_RENAME_FILE;
if (secret)
{
log_info(_("WARNING: 2 files with confidential"
" information exists.\n"));
log_info(_("%s is the unchanged one\n"), fname );
log_info(_("%s is the new one\n"), tmpfname );
log_info(_("Please fix this possible security flaw\n"));
}
return rc;
}
return 0;
}
static int
write_keyblock (IOBUF fp, KBNODE keyblock)
{
KBNODE kbctx = NULL, node;
int rc;
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) ))
{
log_error ("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(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)) {
log_error ("writing sigcache packet failed\n");
return G10ERR_WRITE_FILE;
}
}
}
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.
*/
int
keyring_rebuild_cache ()
{
KEYRING_HANDLE hd;
KEYDB_SEARCH_DESC desc;
KBNODE keyblock = NULL, node;
const char *lastresname = NULL, *resname;
IOBUF tmpfp = NULL;
char *tmpfilename = NULL;
char *bakfilename = NULL;
int rc;
ulong count = 0, sigcount = 0;
hd = keyring_new (0);
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_FIRST;
while ( !(rc = keyring_search (hd, &desc, 1)) )
{
desc.mode = KEYDB_SEARCH_MODE_NEXT;
resname = keyring_get_resource_name (hd);
if (lastresname != resname )
{ /* we have switched to a new keyring - commit changes */
if (tmpfp)
{
if (iobuf_close (tmpfp))
{
log_error ("error closing `%s': %s\n",
tmpfilename, strerror (errno));
rc = G10ERR_CLOSE_FILE;
goto leave;
}
/* because we have switched resources, we can be sure that
* the original file is closed */
tmpfp = NULL;
}
rc = lastresname? rename_tmp_file (bakfilename, tmpfilename,
lastresname, 0) : 0;
m_free (tmpfilename); tmpfilename = NULL;
m_free (bakfilename); bakfilename = NULL;
if (rc)
goto leave;
lastresname = resname;
if (!opt.quiet)
log_info (_("checking keyring `%s'\n"), resname);
rc = create_tmp_file (resname, &bakfilename, &tmpfilename, &tmpfp);
if (rc)
goto leave;
}
release_kbnode (keyblock);
rc = keyring_get_keyblock (hd, &keyblock);
if (rc)
{
log_error ("keyring_get_keyblock failed: %s\n", g10_errstr(rc));
goto leave;
}
assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
/* check all signature to set the signature's cache flags */
for (node=keyblock; node; node=node->next)
{
if (node->pkt->pkttype == PKT_SIGNATURE)
{
check_key_signature (keyblock, node, NULL);
sigcount++;
}
}
/* write the keyblock to the temporary file */
rc = write_keyblock (tmpfp, keyblock);
if (rc)
goto leave;
if ( !(++count % 50) && !opt.quiet)
log_info(_("%lu keys so far checked (%lu signatures)\n"),
count, sigcount );
} /* end main loop */
if (rc == -1)
rc = 0;
if (rc)
{
log_error ("keyring_search failed: %s\n", g10_errstr(rc));
goto leave;
}
log_info(_("%lu keys checked (%lu signatures)\n"), count, sigcount );
if (tmpfp)
{
if (iobuf_close (tmpfp))
{
log_error ("error closing `%s': %s\n",
tmpfilename, strerror (errno));
rc = G10ERR_CLOSE_FILE;
goto leave;
}
/* because we have switched resources, we can be sure that
* the original file is closed */
tmpfp = NULL;
}
rc = lastresname? rename_tmp_file (bakfilename, tmpfilename,
lastresname, 0) : 0;
m_free (tmpfilename); tmpfilename = NULL;
m_free (bakfilename); bakfilename = NULL;
leave:
if (tmpfp)
iobuf_cancel (tmpfp);
m_free (tmpfilename);
m_free (bakfilename);
release_kbnode (keyblock);
keyring_release (hd);
return rc;
}
/****************
* Perform insert/delete/update operation.
@ -932,38 +1241,9 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
}
/* create the new file */
#ifdef USE_ONLY_8DOT3
/* Here is another Windoze bug?:
* you cant rename("pubring.gpg.tmp", "pubring.gpg");
* but rename("pubring.gpg.tmp", "pubring.aaa");
* works. So we replace .gpg by .bak or .tmp
*/
if( strlen (fname) > 4
&& !strcmp (fname+strlen(fname)-4, EXTSEP_S "gpg") ) {
bakfname = m_alloc( strlen (fname) + 1 );
strcpy(bakfname, fname);
strcpy(bakfname+strlen(fname)-4, EXTSEP_S "bak");
tmpfname = m_alloc( strlen( fname ) + 1 );
strcpy(tmpfname,fname);
strcpy(tmpfname+strlen(fname)-4, EXTSEP_S "tmp");
}
else { /* file does not end with gpg; hmmm */
bakfname = m_alloc( strlen( fname ) + 5 );
strcpy(stpcpy(bakfname, fname), EXTSEP_S "bak");
tmpfname = m_alloc( strlen( fname ) + 5 );
strcpy(stpcpy(tmpfname, fname), EXTSEP_S "tmp");
}
#else
bakfname = m_alloc( strlen( fname ) + 2 );
strcpy(stpcpy(bakfname,fname),"~");
tmpfname = m_alloc( strlen( fname ) + 5 );
strcpy(stpcpy(tmpfname,fname), EXTSEP_S "tmp");
#endif
newfp = iobuf_create (tmpfname);
if (!newfp) {
log_error ("%s: can't create: %s\n", tmpfname, strerror(errno) );
rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
if (rc) {
iobuf_close(fp);
rc = G10ERR_OPEN_FILE;
goto leave;
}
@ -1003,20 +1283,12 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
}
if( mode == 1 || mode == 3 ) { /* insert or update */
KBNODE kbctx, node;
/* append the new data */
kbctx=NULL;
while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
if( (rc = build_packet( newfp, node->pkt )) ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(rc) );
iobuf_close(fp);
iobuf_cancel(newfp);
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
rc = write_keyblock (newfp, root);
if (rc) {
iobuf_close(fp);
iobuf_cancel(newfp);
goto leave;
}
}
if( mode == 2 || mode == 3 ) { /* delete or update */
@ -1043,58 +1315,11 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
rc = G10ERR_CLOSE_FILE;
goto leave;
}
/* if the new file is a secring, restrict the permissions */
#ifndef HAVE_DOSISH_SYSTEM
if( secret && !opt.preserve_permissions ) {
if( chmod( tmpfname, S_IRUSR | S_IWUSR ) ) {
log_error("%s: chmod failed: %s\n",
tmpfname, strerror(errno) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
#endif
/* rename and make backup file */
if( !secret ) { /* but not for secret keyrings */
iobuf_ioctl (NULL, 2, 0, (char *)bakfname );
iobuf_ioctl (NULL, 2, 0, (char *)fname );
#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
remove( bakfname );
#endif
if( rename( fname, bakfname ) ) {
log_error("%s: rename to `%s' failed: %s\n",
fname, bakfname, strerror(errno) );
rc = G10ERR_RENAME_FILE;
goto leave;
}
}
iobuf_ioctl (NULL, 2, 0, (char*)tmpfname );
iobuf_ioctl (NULL, 2, 0, (char*)fname );
#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
remove( fname );
#endif
if( rename( tmpfname, fname ) ) {
log_error("%s: rename to `%s' failed: %s\n",
tmpfname, fname,strerror(errno) );
rc = G10ERR_RENAME_FILE;
if( secret ) {
log_info(_(
"WARNING: 2 files with confidential information exists.\n"));
log_info(_("%s is the unchanged one\n"), fname );
log_info(_("%s is the new one\n"), tmpfname );
log_info(_("Please fix this possible security flaw\n"));
}
goto leave;
}
rc = rename_tmp_file (bakfname, tmpfname, fname, secret);
leave:
m_free(bakfname);
m_free(tmpfname);
return rc;
}

View File

@ -39,6 +39,6 @@ int keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb);
int keyring_delete_keyblock (KEYRING_HANDLE hd);
int keyring_search_reset (KEYRING_HANDLE hd);
int keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
int keyring_rebuild_cache (void);
#endif /*GPG_KEYRING_H*/

Binary file not shown.

View File

@ -109,7 +109,6 @@ struct {
int show_session_key;
int use_agent;
int merge_only;
int allow_secret_key_import;
int try_all_secrets;
int no_expensive_trust_checks;
int no_sig_cache;

View File

@ -235,6 +235,7 @@ typedef struct {
typedef struct {
unsigned int trustval;
unsigned int sigcache;
} PKT_ring_trust;
typedef struct {
@ -306,7 +307,7 @@ typedef enum {
SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */
SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */
SIGSUBPKT_FEATURES =30, /* feature flags */
SIGSUBPKT_PRIV_VERIFY_CACHE =101, /* cache verification result */
SIGSUBPKT_PRIV_VERIFY_CACHE =101, /* cache verification result (obsolete)*/
SIGSUBPKT_FLAG_CRITICAL=128
} sigsubpkttype_t;

View File

@ -883,7 +883,7 @@ dump_sig_subpkt( int hashed, int type, int critical,
printf(" %02x", buffer[i] );
break;
case SIGSUBPKT_PRIV_VERIFY_CACHE:
p = "verification cache";
p = "obsolete verification cache";
break;
default: p = "?"; break;
}
@ -936,7 +936,9 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
break;
return 0;
case SIGSUBPKT_PRIV_VERIFY_CACHE:
/* "GPG" 0x00 <mode> <stat>
/* We used this in gpg 1.0.5 and 1.0.6 to cache signature
* verification results - it is no longer used.
* "GPG" 0x00 <mode> <stat>
* where mode == 1: valid data, stat == 0: invalid signature
* stat == 1: valid signature
* (because we use private data, we check our marker) */
@ -1732,8 +1734,18 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
c = iobuf_get_noeof(inp);
pkt->pkt.ring_trust = m_alloc( sizeof *pkt->pkt.ring_trust );
pkt->pkt.ring_trust->trustval = c;
pkt->pkt.ring_trust->sigcache = 0;
if (!c && pktlen==2) {
c = iobuf_get_noeof (inp);
/* we require that bit 7 of the sigcache is 0 (easier eof handling)*/
if ( !(c & 0x80) )
pkt->pkt.ring_trust->sigcache = c;
}
if( list_mode )
printf(":trust packet: flag=%02x\n", c );
printf(":trust packet: flag=%02x sigcache=%02x\n",
pkt->pkt.ring_trust->trustval,
pkt->pkt.ring_trust->sigcache);
}

View File

@ -120,96 +120,6 @@ do_signature_check( PKT_signature *sig, MD_HANDLE digest,
}
#if 0 /* not anymore used */
/****************
* Check the MDC which is contained in SIG.
* The MD_HANDLE should be currently open, so that this function
* is able to append some data, before finalizing the digest.
*/
int
mdc_kludge_check( PKT_signature *sig, MD_HANDLE digest )
{
int rc=0;
if( (rc=check_digest_algo(sig->digest_algo)) )
return rc;
/* make sure the digest algo is enabled (in case of a detached mdc??) */
md_enable( digest, sig->digest_algo );
/* complete the digest */
if( sig->version >= 4 )
md_putc( digest, sig->version );
md_putc( digest, sig->sig_class );
if( sig->version < 4 ) {
u32 a = sig->timestamp;
md_putc( digest, (a >> 24) & 0xff );
md_putc( digest, (a >> 16) & 0xff );
md_putc( digest, (a >> 8) & 0xff );
md_putc( digest, a & 0xff );
}
else {
byte buf[6];
size_t n;
md_putc( digest, sig->pubkey_algo );
md_putc( digest, sig->digest_algo );
if( sig->hashed ) {
n = sig->hashed->len;
md_putc (digest, (n >> 8) );
md_putc (digest, n );
md_write (digest, sig->hashed->data, n);
n += 6;
}
else
n = 6;
/* add some magic */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24;
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
md_write( digest, buf, 6 );
}
md_final( digest );
rc = G10ERR_BAD_SIGN;
{ const byte *s1 = md_read( digest, sig->digest_algo );
int s1len = md_digest_length( sig->digest_algo );
log_hexdump( "MDC calculated", s1, s1len );
if( !sig->data[0] )
log_debug("sig_data[0] is NULL\n");
else {
unsigned s2len;
byte *s2;
s2 = mpi_get_buffer( sig->data[0], &s2len, NULL );
log_hexdump( "MDC stored ", s2, s2len );
if( s2len != s1len )
log_debug("MDC check: len differ: %d/%d\n", s1len, s2len);
else if( memcmp( s1, s2, s1len ) )
log_debug("MDC check: hashs differ\n");
else
rc = 0;
m_free(s2);
}
}
if( !rc && sig->flags.unknown_critical ) {
log_info(_("assuming bad MDC due to an unknown critical bit\n"));
rc = G10ERR_BAD_SIGN;
}
sig->flags.checked = 1;
sig->flags.valid = !rc;
/* FIXME: check that we are actually in an encrypted packet */
return rc;
}
#endif
/****************
* This function gets called by pubkey_verify() if the algorithm needs it.
*/
@ -402,8 +312,6 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest,
log_info(_("assuming bad signature due to an unknown critical bit\n"));
rc = G10ERR_BAD_SIGN;
}
sig->flags.checked = 1;
sig->flags.valid = !rc;
return rc;
}
@ -442,31 +350,20 @@ hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig )
}
static void
cache_selfsig_result ( PKT_signature *sig, int result )
cache_sig_result ( PKT_signature *sig, int result )
{
byte buf[6];
if ( opt.no_sig_cache )
return;
buf[0] = 'G';
buf[1] = 'P';
buf[2] = 'G';
buf[3] = 0;
if ( !result ) {
buf[4] = 1; /* mark cache valid */
buf[5] = 1; /* mark signature valid */
sig->flags.checked = 1;
sig->flags.valid = 1;
}
else if ( result == G10ERR_BAD_SIGN ) {
buf[4] = 1; /* mark cache valid */
buf[5] = 0; /* mark signature invalid */
sig->flags.checked = 1;
sig->flags.valid = 0;
}
else {
buf[4] = 0; /* mark cache invalid */
buf[5] = 0;
sig->flags.checked = 0;
sig->flags.valid = 0;
}
build_sig_subpkt (sig, SIGSUBPKT_PRIV_VERIFY_CACHE, buf, 6 );
}
/****************
@ -503,20 +400,9 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
sig = node->pkt->pkt.signature;
algo = sig->digest_algo;
#if 0 /* I am not sure whether this is a good thing to do */
if( sig->flags.checked )
log_debug("check_key_signature: already checked: %s\n",
sig->flags.valid? "good":"bad" );
#endif
/* Check whether we have cached the result of a previous signature check.*/
/* check whether we have cached the result of a previous signature check.*/
if ( !opt.no_sig_cache ) {
const byte *p;
size_t len;
p = parse_sig_subpkt( sig->unhashed,
SIGSUBPKT_PRIV_VERIFY_CACHE, &len );
if ( p && len >= 2 && p[0] == 1 ) { /* cache hit */
if (sig->flags.checked) { /*cached status available*/
if( is_selfsig ) {
u32 keyid[2];
@ -524,7 +410,7 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
*is_selfsig = 1;
}
return p[1] == 1? 0 : G10ERR_BAD_SIGN;
return sig->flags.valid? 0 : G10ERR_BAD_SIGN;
}
}
@ -535,7 +421,7 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
md = md_open( algo, 0 );
hash_public_key( md, pk );
rc = do_check( pk, sig, md, r_expired );
cache_selfsig_result ( sig, rc );
cache_sig_result ( sig, rc );
md_close(md);
}
else if( sig->sig_class == 0x28 ) { /* subkey revocation */
@ -546,7 +432,7 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
hash_public_key( md, pk );
hash_public_key( md, snode->pkt->pkt.public_key );
rc = do_check( pk, sig, md, r_expired );
cache_selfsig_result ( sig, rc );
cache_sig_result ( sig, rc );
md_close(md);
}
else {
@ -571,7 +457,7 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
hash_public_key( md, pk );
hash_public_key( md, snode->pkt->pkt.public_key );
rc = do_check( pk, sig, md, r_expired );
cache_selfsig_result ( sig, rc );
cache_sig_result ( sig, rc );
md_close(md);
}
else {
@ -585,7 +471,7 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
md = md_open( algo, 0 );
hash_public_key( md, pk );
rc = do_check( pk, sig, md, r_expired );
cache_selfsig_result ( sig, rc );
cache_sig_result ( sig, rc );
md_close(md);
}
else { /* all other classes */
@ -602,11 +488,11 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
if( is_selfsig )
*is_selfsig = 1;
rc = do_check( pk, sig, md, r_expired );
cache_selfsig_result ( sig, rc );
}
else {
rc = do_signature_check( sig, md, r_expiredate, r_expired );
}
cache_sig_result ( sig, rc );
md_close(md);
}
else {

View File

@ -768,7 +768,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
rc = tdbio_read_record( rec.r.hlst.next,
&rec, RECTYPE_HLST);
if( rc ) {
log_error( "scan keyhashtbl read hlst failed: %s\n",
log_error( "upd_hashtable: read hlst failed: %s\n",
g10_errstr(rc) );
return rc;
}
@ -923,7 +923,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum )
rc = tdbio_read_record( rec.r.hlst.next,
&rec, RECTYPE_HLST);
if( rc ) {
log_error( "scan keyhashtbl read hlst failed: %s\n",
log_error( "drop_from_hashtable: read hlst failed: %s\n",
g10_errstr(rc) );
return rc;
}

View File

@ -718,9 +718,11 @@ get_validity (PKT_public_key *pk, const byte *namehash)
if ( (trec.r.trust.ownertrust & TRUST_FLAG_DISABLED) )
validity |= TRUST_FLAG_DISABLED;
/* for convenience set some flags from the key */
/* set some flags direct from the key */
if (pk->is_revoked)
validity |= TRUST_FLAG_REVOKED;
/* Note: expiration is a trust value and not a flag - don't know why
* I initially designed it that way */
if (pk->has_expired)
validity = (validity & ~TRUST_MASK) | TRUST_EXPIRED;
@ -879,6 +881,9 @@ make_key_array (KEYDB_HANDLE hd, KeyHashTable visited,
desc.mode = KEYDB_SEARCH_MODE_NEXT; /* change mode */
do
{
PKT_public_key *pk;
u32 kid[2];
rc = keydb_get_keyblock (hd, &keyblock);
if (rc)
{
@ -896,18 +901,25 @@ make_key_array (KEYDB_HANDLE hd, KeyHashTable visited,
continue;
}
/* prepare the keyblock for further processing */
merge_keys_and_selfsig (keyblock);
clear_kbnode_flags (keyblock);
if (cmpfnc (keyblock, cmpval))
{
u32 kid[2];
pk = keyblock->pkt->pkt.public_key;
keyid_from_pk (pk, kid); /*(cheap: should already be cached in the pk)*/
if (pk->has_expired || pk->is_revoked)
{
/* it does not make sense to look further at those keys */
add_key_hash_table (visited, kid);
}
else if (cmpfnc (keyblock, cmpval))
{
if (nkeys == maxkeys) {
maxkeys += 1000;
keys = m_realloc (keys, (maxkeys+1) * sizeof *keys);
}
keys[nkeys++].keyblock = keyblock;
/* This key is signed - don't check it again */
keyid_from_pk (keyblock->pkt->pkt.public_key, kid);
add_key_hash_table (visited, kid);
}
else
@ -1018,10 +1030,11 @@ cmp_kid_for_make_key_array (KBNODE kb, void *opaque)
struct key_item *klist = opaque;
struct key_item *kr;
KBNODE node, uidnode=NULL;
PKT_public_key *pk = kb->pkt->pkt.public_key;
u32 main_kid[2];
int issigned=0, any_signed = 0, fully_count =0, marginal_count = 0;
keyid_from_pk(kb->pkt->pkt.public_key, main_kid);
keyid_from_pk(pk, main_kid);
for (node=kb; node; node = node->next)
{
if (node->pkt->pkttype == PKT_USER_ID)