mirror of
git://git.gnupg.org/gnupg.git
synced 2025-02-08 17:43:04 +01:00
Changed signature status cache
This commit is contained in:
parent
a3af543617
commit
1f4bdf4d26
12
NEWS
12
NEWS
@ -37,6 +37,18 @@
|
|||||||
|
|
||||||
* The entire keyring management has been revamped.
|
* 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)
|
Noteworthy changes in version 1.0.6 (2001-05-29)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
@ -513,7 +513,6 @@ command --update-trustdb.
|
|||||||
There are a few other options which control how this command works.
|
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
|
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.
|
but does only the merging of new signatures, user-IDs and subkeys.
|
||||||
See also the option --allow-secret-key-import.
|
|
||||||
</para></listitem></varlistentry>
|
</para></listitem></varlistentry>
|
||||||
|
|
||||||
|
|
||||||
@ -1530,9 +1529,7 @@ Don't insert new keys into the keyrings while doing an import.
|
|||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>--allow-secret-key-import</term>
|
<term>--allow-secret-key-import</term>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
Allow import of secret keys. The import command normally skips secret
|
This is an obsolete option and is not used anywhere.
|
||||||
keys because a secret key can otherwise be used to attack the trust
|
|
||||||
calculation.
|
|
||||||
</para></listitem></varlistentry>
|
</para></listitem></varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
@ -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>
|
2001-09-24 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
* g10.c, options.h: New option --no-auto-check-trustdb.
|
* g10.c, options.h: New option --no-auto-check-trustdb.
|
||||||
|
@ -135,7 +135,7 @@ build_packet( IOBUF out, PACKET *pkt )
|
|||||||
rc = do_onepass_sig( out, ctb, pkt->pkt.onepass_sig );
|
rc = do_onepass_sig( out, ctb, pkt->pkt.onepass_sig );
|
||||||
break;
|
break;
|
||||||
case PKT_RING_TRUST:
|
case PKT_RING_TRUST:
|
||||||
break; /* ignore it */
|
break; /* ignore it (keyring.c does write it directly)*/
|
||||||
default:
|
default:
|
||||||
log_bug("invalid packet type in build_packet()\n");
|
log_bug("invalid packet type in build_packet()\n");
|
||||||
break;
|
break;
|
||||||
|
@ -186,6 +186,9 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
|
|||||||
* secret keyring */
|
* secret keyring */
|
||||||
if( !secret && node->pkt->pkttype == PKT_COMMENT )
|
if( !secret && node->pkt->pkttype == PKT_COMMENT )
|
||||||
continue;
|
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 */
|
/* do not export packets which are marked as not exportable */
|
||||||
if( node->pkt->pkttype == PKT_SIGNATURE ) {
|
if( node->pkt->pkttype == PKT_SIGNATURE ) {
|
||||||
const char *p;
|
const char *p;
|
||||||
|
12
g10/g10.c
12
g10/g10.c
@ -112,7 +112,7 @@ enum cmd_and_opt_values { aNull = 0,
|
|||||||
aEnArmor,
|
aEnArmor,
|
||||||
aGenRandom,
|
aGenRandom,
|
||||||
aPipeMode,
|
aPipeMode,
|
||||||
aRefreshCaches,
|
aRebuildKeydbCaches,
|
||||||
aRefreshKeys,
|
aRefreshKeys,
|
||||||
|
|
||||||
oTextmode,
|
oTextmode,
|
||||||
@ -441,6 +441,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
{ oEnableSpecialFilenames, "enable-special-filenames", 0, "@" },
|
{ oEnableSpecialFilenames, "enable-special-filenames", 0, "@" },
|
||||||
{ oNoExpensiveTrustChecks, "no-expensive-trust-checks", 0, "@" },
|
{ oNoExpensiveTrustChecks, "no-expensive-trust-checks", 0, "@" },
|
||||||
{ aDeleteSecretAndPublicKey, "delete-secret-and-public-key",256, "@" },
|
{ aDeleteSecretAndPublicKey, "delete-secret-and-public-key",256, "@" },
|
||||||
|
{ aRebuildKeydbCaches, "rebuild-keydb-caches", 256, "@"},
|
||||||
{ oPreservePermissions, "preserve-permissions", 0, "@"},
|
{ oPreservePermissions, "preserve-permissions", 0, "@"},
|
||||||
{ oPreferenceList, "preference-list", 2, "@"},
|
{ oPreferenceList, "preference-list", 2, "@"},
|
||||||
{ oEmu3DESS2KBug, "emulate-3des-s2k-bug", 0, "@"},
|
{ oEmu3DESS2KBug, "emulate-3des-s2k-bug", 0, "@"},
|
||||||
@ -848,6 +849,7 @@ main( int argc, char **argv )
|
|||||||
case aExportOwnerTrust: set_cmd( &cmd, aExportOwnerTrust); break;
|
case aExportOwnerTrust: set_cmd( &cmd, aExportOwnerTrust); break;
|
||||||
case aImportOwnerTrust: set_cmd( &cmd, aImportOwnerTrust); break;
|
case aImportOwnerTrust: set_cmd( &cmd, aImportOwnerTrust); break;
|
||||||
case aPipeMode: set_cmd( &cmd, aPipeMode); 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 oArmor: opt.armor = 1; opt.no_armor=0; break;
|
||||||
case oOutput: opt.outfile = pargs.r.ret_str; 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;
|
opt.override_session_key = pargs.r.ret_str;
|
||||||
break;
|
break;
|
||||||
case oMergeOnly: opt.merge_only = 1; 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 oTryAllSecrets: opt.try_all_secrets = 1; break;
|
||||||
case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break;
|
case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break;
|
||||||
case oEnableSpecialFilenames:
|
case oEnableSpecialFilenames:
|
||||||
@ -1689,6 +1691,12 @@ main( int argc, char **argv )
|
|||||||
run_in_pipemode ();
|
run_in_pipemode ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case aRebuildKeydbCaches:
|
||||||
|
if (argc)
|
||||||
|
wrong_args ("--rebuild-keydb-caches");
|
||||||
|
keydb_rebuild_caches ();
|
||||||
|
break;
|
||||||
|
|
||||||
case aListPackets:
|
case aListPackets:
|
||||||
opt.list_packets=2;
|
opt.list_packets=2;
|
||||||
default:
|
default:
|
||||||
|
32
g10/import.c
32
g10/import.c
@ -55,13 +55,13 @@ struct stats_s {
|
|||||||
|
|
||||||
|
|
||||||
static int import( IOBUF inp, int fast, const char* fname,
|
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 int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root );
|
||||||
static void remove_bad_stuff (KBNODE keyblock);
|
static void remove_bad_stuff (KBNODE keyblock);
|
||||||
static int import_one( const char *fname, KBNODE keyblock, int fast,
|
static int import_one( const char *fname, KBNODE keyblock, int fast,
|
||||||
struct stats_s *stats);
|
struct stats_s *stats);
|
||||||
static int import_secret_one( const char *fname, KBNODE keyblock,
|
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,
|
static int import_revoke_cert( const char *fname, KBNODE node,
|
||||||
struct stats_s *stats);
|
struct stats_s *stats);
|
||||||
static int chk_self_sigs( const char *fname, KBNODE keyblock,
|
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 )
|
if( !inp )
|
||||||
log_error(_("can't open `%s': %s\n"), fname, strerror(errno) );
|
log_error(_("can't open `%s': %s\n"), fname, strerror(errno) );
|
||||||
else {
|
else {
|
||||||
int rc = import( inp, fast, fname,
|
int rc = import( inp, fast, fname, stats );
|
||||||
opt.allow_secret_key_import, stats );
|
|
||||||
iobuf_close(inp);
|
iobuf_close(inp);
|
||||||
if( rc )
|
if( rc )
|
||||||
log_error("import from `%s' failed: %s\n", fname,
|
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)
|
if (!stats)
|
||||||
stats = import_new_stats_handle ();
|
stats = import_new_stats_handle ();
|
||||||
|
|
||||||
rc = import( inp, fast, "[stream]",
|
rc = import( inp, fast, "[stream]", stats);
|
||||||
opt.allow_secret_key_import, stats );
|
|
||||||
if (!stats_handle) {
|
if (!stats_handle) {
|
||||||
import_print_stats (stats);
|
import_print_stats (stats);
|
||||||
import_release_stats_handle (stats);
|
import_release_stats_handle (stats);
|
||||||
@ -181,8 +179,7 @@ import_keys_stream( IOBUF inp, int fast, void *stats_handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
import( IOBUF inp, int fast, const char* fname, int allow_secret,
|
import( IOBUF inp, int fast, const char* fname, struct stats_s *stats )
|
||||||
struct stats_s *stats )
|
|
||||||
{
|
{
|
||||||
PACKET *pending_pkt = NULL;
|
PACKET *pending_pkt = NULL;
|
||||||
KBNODE keyblock;
|
KBNODE keyblock;
|
||||||
@ -201,8 +198,7 @@ import( IOBUF inp, int fast, const char* fname, int allow_secret,
|
|||||||
if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY )
|
if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY )
|
||||||
rc = import_one( fname, keyblock, fast, stats );
|
rc = import_one( fname, keyblock, fast, stats );
|
||||||
else if( keyblock->pkt->pkttype == PKT_SECRET_KEY )
|
else if( keyblock->pkt->pkttype == PKT_SECRET_KEY )
|
||||||
rc = import_secret_one( fname, keyblock,
|
rc = import_secret_one( fname, keyblock, stats );
|
||||||
allow_secret, stats );
|
|
||||||
else if( keyblock->pkt->pkttype == PKT_SIGNATURE
|
else if( keyblock->pkt->pkttype == PKT_SIGNATURE
|
||||||
&& keyblock->pkt->pkt.signature->sig_class == 0x20 )
|
&& keyblock->pkt->pkt.signature->sig_class == 0x20 )
|
||||||
rc = import_revoke_cert( fname, keyblock, stats );
|
rc = import_revoke_cert( fname, keyblock, stats );
|
||||||
@ -344,6 +340,11 @@ read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root )
|
|||||||
init_packet(pkt);
|
init_packet(pkt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PKT_RING_TRUST:
|
||||||
|
/* skip those packets */
|
||||||
|
free_packet( pkt );
|
||||||
|
init_packet(pkt);
|
||||||
|
break;
|
||||||
|
|
||||||
case PKT_PUBLIC_KEY:
|
case PKT_PUBLIC_KEY:
|
||||||
case PKT_SECRET_KEY:
|
case PKT_SECRET_KEY:
|
||||||
@ -386,7 +387,8 @@ remove_bad_stuff (KBNODE keyblock)
|
|||||||
|
|
||||||
for (node=keyblock; node; node = node->next ) {
|
for (node=keyblock; node; node = node->next ) {
|
||||||
if( node->pkt->pkttype == PKT_SIGNATURE ) {
|
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,
|
delete_sig_subpkt (node->pkt->pkt.signature->unhashed,
|
||||||
SIGSUBPKT_PRIV_VERIFY_CACHE);
|
SIGSUBPKT_PRIV_VERIFY_CACHE);
|
||||||
}
|
}
|
||||||
@ -606,7 +608,7 @@ import_one( const char *fname, KBNODE keyblock, int fast,
|
|||||||
* with the trust calculation.
|
* with the trust calculation.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
import_secret_one( const char *fname, KBNODE keyblock, int allow,
|
import_secret_one( const char *fname, KBNODE keyblock,
|
||||||
struct stats_s *stats)
|
struct stats_s *stats)
|
||||||
{
|
{
|
||||||
PKT_secret_key *sk;
|
PKT_secret_key *sk;
|
||||||
@ -634,12 +636,6 @@ import_secret_one( const char *fname, KBNODE keyblock, int allow,
|
|||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
}
|
}
|
||||||
stats->secret_read++;
|
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 ) {
|
if( !uidnode ) {
|
||||||
log_error( _("key %08lX: no user ID\n"), (ulong)keyid[1]);
|
log_error( _("key %08lX: no user ID\n"), (ulong)keyid[1]);
|
||||||
|
18
g10/keydb.c
18
g10/keydb.c
@ -320,7 +320,7 @@ lock_all (KEYDB_HANDLE hd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
/* revert the alreadt set locks */
|
/* revert the already set locks */
|
||||||
for (i--; i >= 0; i--) {
|
for (i--; i >= 0; i--) {
|
||||||
switch (hd->active[i].type) {
|
switch (hd->active[i].type) {
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
case KEYDB_RESOURCE_TYPE_NONE:
|
||||||
@ -517,6 +517,22 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
|
|||||||
return rc;
|
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
|
* Start the next search on this handle right at the beginning
|
||||||
|
@ -148,6 +148,7 @@ int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb);
|
|||||||
int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb);
|
int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb);
|
||||||
int keydb_delete_keyblock (KEYDB_HANDLE hd);
|
int keydb_delete_keyblock (KEYDB_HANDLE hd);
|
||||||
int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved);
|
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_reset (KEYDB_HANDLE hd);
|
||||||
int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
|
int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
|
||||||
int keydb_search_first (KEYDB_HANDLE hd);
|
int keydb_search_first (KEYDB_HANDLE hd);
|
||||||
|
411
g10/keyring.c
411
g10/keyring.c
@ -32,6 +32,7 @@
|
|||||||
#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 "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
typedef struct keyring_name *KR_NAME;
|
typedef struct keyring_name *KR_NAME;
|
||||||
@ -219,7 +220,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
|
|||||||
{
|
{
|
||||||
PACKET *pkt;
|
PACKET *pkt;
|
||||||
int rc;
|
int rc;
|
||||||
KBNODE keyblock = NULL, node;
|
KBNODE keyblock = NULL, node, lastnode;
|
||||||
IOBUF a;
|
IOBUF a;
|
||||||
int in_cert = 0;
|
int in_cert = 0;
|
||||||
int pk_no = 0;
|
int pk_no = 0;
|
||||||
@ -246,6 +247,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
|
|||||||
pkt = m_alloc (sizeof *pkt);
|
pkt = m_alloc (sizeof *pkt);
|
||||||
init_packet (pkt);
|
init_packet (pkt);
|
||||||
hd->found.n_packets = 0;;
|
hd->found.n_packets = 0;;
|
||||||
|
lastnode = NULL;
|
||||||
while ((rc=parse_packet (a, pkt)) != -1) {
|
while ((rc=parse_packet (a, pkt)) != -1) {
|
||||||
hd->found.n_packets++;
|
hd->found.n_packets++;
|
||||||
if (rc == G10ERR_UNKNOWN_PACKET) {
|
if (rc == G10ERR_UNKNOWN_PACKET) {
|
||||||
@ -273,7 +275,25 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
in_cert = 1;
|
in_cert = 1;
|
||||||
node = new_kbnode (pkt);
|
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 {
|
||||||
|
node = lastnode = new_kbnode (pkt);
|
||||||
if (!keyblock)
|
if (!keyblock)
|
||||||
keyblock = node;
|
keyblock = node;
|
||||||
else
|
else
|
||||||
@ -290,6 +310,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;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pkt = m_alloc (sizeof *pkt);
|
pkt = m_alloc (sizeof *pkt);
|
||||||
init_packet(pkt);
|
init_packet(pkt);
|
||||||
@ -300,9 +321,18 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
|
|||||||
|
|
||||||
if (rc || !ret_kb)
|
if (rc || !ret_kb)
|
||||||
release_kbnode (keyblock);
|
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;
|
*ret_kb = keyblock;
|
||||||
|
}
|
||||||
free_packet (pkt);
|
free_packet (pkt);
|
||||||
m_free (pkt);
|
m_free (pkt);
|
||||||
iobuf_close(a);
|
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.
|
* Perform insert/delete/update operation.
|
||||||
@ -932,38 +1241,9 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* create the new file */
|
/* create the new file */
|
||||||
#ifdef USE_ONLY_8DOT3
|
rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
|
||||||
/* Here is another Windoze bug?:
|
if (rc) {
|
||||||
* 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) );
|
|
||||||
iobuf_close(fp);
|
iobuf_close(fp);
|
||||||
rc = G10ERR_OPEN_FILE;
|
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1003,21 +1283,13 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( mode == 1 || mode == 3 ) { /* insert or update */
|
if( mode == 1 || mode == 3 ) { /* insert or update */
|
||||||
KBNODE kbctx, node;
|
rc = write_keyblock (newfp, root);
|
||||||
|
if (rc) {
|
||||||
/* 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_close(fp);
|
||||||
iobuf_cancel(newfp);
|
iobuf_cancel(newfp);
|
||||||
rc = G10ERR_WRITE_FILE;
|
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if( mode == 2 || mode == 3 ) { /* delete or update */
|
if( mode == 2 || mode == 3 ) { /* delete or update */
|
||||||
/* copy the rest */
|
/* copy the rest */
|
||||||
@ -1043,58 +1315,11 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
|
|||||||
rc = G10ERR_CLOSE_FILE;
|
rc = G10ERR_CLOSE_FILE;
|
||||||
goto leave;
|
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 */
|
rc = rename_tmp_file (bakfname, tmpfname, fname, secret);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
m_free(bakfname);
|
m_free(bakfname);
|
||||||
m_free(tmpfname);
|
m_free(tmpfname);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,6 +39,6 @@ int keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb);
|
|||||||
int keyring_delete_keyblock (KEYRING_HANDLE hd);
|
int keyring_delete_keyblock (KEYRING_HANDLE hd);
|
||||||
int keyring_search_reset (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_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
|
||||||
|
int keyring_rebuild_cache (void);
|
||||||
|
|
||||||
#endif /*GPG_KEYRING_H*/
|
#endif /*GPG_KEYRING_H*/
|
||||||
|
BIN
g10/keyring.o
BIN
g10/keyring.o
Binary file not shown.
@ -109,7 +109,6 @@ struct {
|
|||||||
int show_session_key;
|
int show_session_key;
|
||||||
int use_agent;
|
int use_agent;
|
||||||
int merge_only;
|
int merge_only;
|
||||||
int allow_secret_key_import;
|
|
||||||
int try_all_secrets;
|
int try_all_secrets;
|
||||||
int no_expensive_trust_checks;
|
int no_expensive_trust_checks;
|
||||||
int no_sig_cache;
|
int no_sig_cache;
|
||||||
|
@ -235,6 +235,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int trustval;
|
unsigned int trustval;
|
||||||
|
unsigned int sigcache;
|
||||||
} PKT_ring_trust;
|
} PKT_ring_trust;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -306,7 +307,7 @@ typedef enum {
|
|||||||
SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */
|
SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */
|
||||||
SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */
|
SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */
|
||||||
SIGSUBPKT_FEATURES =30, /* feature flags */
|
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
|
SIGSUBPKT_FLAG_CRITICAL=128
|
||||||
} sigsubpkttype_t;
|
} sigsubpkttype_t;
|
||||||
|
@ -883,7 +883,7 @@ dump_sig_subpkt( int hashed, int type, int critical,
|
|||||||
printf(" %02x", buffer[i] );
|
printf(" %02x", buffer[i] );
|
||||||
break;
|
break;
|
||||||
case SIGSUBPKT_PRIV_VERIFY_CACHE:
|
case SIGSUBPKT_PRIV_VERIFY_CACHE:
|
||||||
p = "verification cache";
|
p = "obsolete verification cache";
|
||||||
break;
|
break;
|
||||||
default: p = "?"; break;
|
default: p = "?"; break;
|
||||||
}
|
}
|
||||||
@ -936,7 +936,9 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
|
|||||||
break;
|
break;
|
||||||
return 0;
|
return 0;
|
||||||
case SIGSUBPKT_PRIV_VERIFY_CACHE:
|
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
|
* where mode == 1: valid data, stat == 0: invalid signature
|
||||||
* stat == 1: valid signature
|
* stat == 1: valid signature
|
||||||
* (because we use private data, we check our marker) */
|
* (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);
|
c = iobuf_get_noeof(inp);
|
||||||
pkt->pkt.ring_trust = m_alloc( sizeof *pkt->pkt.ring_trust );
|
pkt->pkt.ring_trust = m_alloc( sizeof *pkt->pkt.ring_trust );
|
||||||
pkt->pkt.ring_trust->trustval = c;
|
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 )
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
144
g10/sig-check.c
144
g10/sig-check.c
@ -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.
|
* 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"));
|
log_info(_("assuming bad signature due to an unknown critical bit\n"));
|
||||||
rc = G10ERR_BAD_SIGN;
|
rc = G10ERR_BAD_SIGN;
|
||||||
}
|
}
|
||||||
sig->flags.checked = 1;
|
|
||||||
sig->flags.valid = !rc;
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -442,31 +350,20 @@ hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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 ) {
|
if ( !result ) {
|
||||||
buf[4] = 1; /* mark cache valid */
|
sig->flags.checked = 1;
|
||||||
buf[5] = 1; /* mark signature valid */
|
sig->flags.valid = 1;
|
||||||
}
|
}
|
||||||
else if ( result == G10ERR_BAD_SIGN ) {
|
else if ( result == G10ERR_BAD_SIGN ) {
|
||||||
buf[4] = 1; /* mark cache valid */
|
sig->flags.checked = 1;
|
||||||
buf[5] = 0; /* mark signature invalid */
|
sig->flags.valid = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buf[4] = 0; /* mark cache invalid */
|
sig->flags.checked = 0;
|
||||||
buf[5] = 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;
|
sig = node->pkt->pkt.signature;
|
||||||
algo = sig->digest_algo;
|
algo = sig->digest_algo;
|
||||||
|
|
||||||
#if 0 /* I am not sure whether this is a good thing to do */
|
/* check whether we have cached the result of a previous signature check.*/
|
||||||
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.*/
|
|
||||||
if ( !opt.no_sig_cache ) {
|
if ( !opt.no_sig_cache ) {
|
||||||
const byte *p;
|
if (sig->flags.checked) { /*cached status available*/
|
||||||
size_t len;
|
|
||||||
|
|
||||||
p = parse_sig_subpkt( sig->unhashed,
|
|
||||||
SIGSUBPKT_PRIV_VERIFY_CACHE, &len );
|
|
||||||
if ( p && len >= 2 && p[0] == 1 ) { /* cache hit */
|
|
||||||
if( is_selfsig ) {
|
if( is_selfsig ) {
|
||||||
u32 keyid[2];
|
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] )
|
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
|
||||||
*is_selfsig = 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 );
|
md = md_open( algo, 0 );
|
||||||
hash_public_key( md, pk );
|
hash_public_key( md, pk );
|
||||||
rc = do_check( pk, sig, md, r_expired );
|
rc = do_check( pk, sig, md, r_expired );
|
||||||
cache_selfsig_result ( sig, rc );
|
cache_sig_result ( sig, rc );
|
||||||
md_close(md);
|
md_close(md);
|
||||||
}
|
}
|
||||||
else if( sig->sig_class == 0x28 ) { /* subkey revocation */
|
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, pk );
|
||||||
hash_public_key( md, snode->pkt->pkt.public_key );
|
hash_public_key( md, snode->pkt->pkt.public_key );
|
||||||
rc = do_check( pk, sig, md, r_expired );
|
rc = do_check( pk, sig, md, r_expired );
|
||||||
cache_selfsig_result ( sig, rc );
|
cache_sig_result ( sig, rc );
|
||||||
md_close(md);
|
md_close(md);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -571,7 +457,7 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
|
|||||||
hash_public_key( md, pk );
|
hash_public_key( md, pk );
|
||||||
hash_public_key( md, snode->pkt->pkt.public_key );
|
hash_public_key( md, snode->pkt->pkt.public_key );
|
||||||
rc = do_check( pk, sig, md, r_expired );
|
rc = do_check( pk, sig, md, r_expired );
|
||||||
cache_selfsig_result ( sig, rc );
|
cache_sig_result ( sig, rc );
|
||||||
md_close(md);
|
md_close(md);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -585,7 +471,7 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
|
|||||||
md = md_open( algo, 0 );
|
md = md_open( algo, 0 );
|
||||||
hash_public_key( md, pk );
|
hash_public_key( md, pk );
|
||||||
rc = do_check( pk, sig, md, r_expired );
|
rc = do_check( pk, sig, md, r_expired );
|
||||||
cache_selfsig_result ( sig, rc );
|
cache_sig_result ( sig, rc );
|
||||||
md_close(md);
|
md_close(md);
|
||||||
}
|
}
|
||||||
else { /* all other classes */
|
else { /* all other classes */
|
||||||
@ -602,11 +488,11 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
|
|||||||
if( is_selfsig )
|
if( is_selfsig )
|
||||||
*is_selfsig = 1;
|
*is_selfsig = 1;
|
||||||
rc = do_check( pk, sig, md, r_expired );
|
rc = do_check( pk, sig, md, r_expired );
|
||||||
cache_selfsig_result ( sig, rc );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rc = do_signature_check( sig, md, r_expiredate, r_expired );
|
rc = do_signature_check( sig, md, r_expiredate, r_expired );
|
||||||
}
|
}
|
||||||
|
cache_sig_result ( sig, rc );
|
||||||
md_close(md);
|
md_close(md);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -768,7 +768,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
|
|||||||
rc = tdbio_read_record( rec.r.hlst.next,
|
rc = tdbio_read_record( rec.r.hlst.next,
|
||||||
&rec, RECTYPE_HLST);
|
&rec, RECTYPE_HLST);
|
||||||
if( rc ) {
|
if( rc ) {
|
||||||
log_error( "scan keyhashtbl read hlst failed: %s\n",
|
log_error( "upd_hashtable: read hlst failed: %s\n",
|
||||||
g10_errstr(rc) );
|
g10_errstr(rc) );
|
||||||
return 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,
|
rc = tdbio_read_record( rec.r.hlst.next,
|
||||||
&rec, RECTYPE_HLST);
|
&rec, RECTYPE_HLST);
|
||||||
if( rc ) {
|
if( rc ) {
|
||||||
log_error( "scan keyhashtbl read hlst failed: %s\n",
|
log_error( "drop_from_hashtable: read hlst failed: %s\n",
|
||||||
g10_errstr(rc) );
|
g10_errstr(rc) );
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -718,9 +718,11 @@ get_validity (PKT_public_key *pk, const byte *namehash)
|
|||||||
if ( (trec.r.trust.ownertrust & TRUST_FLAG_DISABLED) )
|
if ( (trec.r.trust.ownertrust & TRUST_FLAG_DISABLED) )
|
||||||
validity |= 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)
|
if (pk->is_revoked)
|
||||||
validity |= TRUST_FLAG_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)
|
if (pk->has_expired)
|
||||||
validity = (validity & ~TRUST_MASK) | TRUST_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 */
|
desc.mode = KEYDB_SEARCH_MODE_NEXT; /* change mode */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
PKT_public_key *pk;
|
||||||
|
u32 kid[2];
|
||||||
|
|
||||||
rc = keydb_get_keyblock (hd, &keyblock);
|
rc = keydb_get_keyblock (hd, &keyblock);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
@ -896,18 +901,25 @@ make_key_array (KEYDB_HANDLE hd, KeyHashTable visited,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* prepare the keyblock for further processing */
|
||||||
|
merge_keys_and_selfsig (keyblock);
|
||||||
clear_kbnode_flags (keyblock);
|
clear_kbnode_flags (keyblock);
|
||||||
if (cmpfnc (keyblock, cmpval))
|
pk = keyblock->pkt->pkt.public_key;
|
||||||
{
|
keyid_from_pk (pk, kid); /*(cheap: should already be cached in the pk)*/
|
||||||
u32 kid[2];
|
|
||||||
|
|
||||||
|
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) {
|
if (nkeys == maxkeys) {
|
||||||
maxkeys += 1000;
|
maxkeys += 1000;
|
||||||
keys = m_realloc (keys, (maxkeys+1) * sizeof *keys);
|
keys = m_realloc (keys, (maxkeys+1) * sizeof *keys);
|
||||||
}
|
}
|
||||||
keys[nkeys++].keyblock = keyblock;
|
keys[nkeys++].keyblock = keyblock;
|
||||||
/* This key is signed - don't check it again */
|
/* This key is signed - don't check it again */
|
||||||
keyid_from_pk (keyblock->pkt->pkt.public_key, kid);
|
|
||||||
add_key_hash_table (visited, kid);
|
add_key_hash_table (visited, kid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1018,10 +1030,11 @@ cmp_kid_for_make_key_array (KBNODE kb, void *opaque)
|
|||||||
struct key_item *klist = opaque;
|
struct key_item *klist = opaque;
|
||||||
struct key_item *kr;
|
struct key_item *kr;
|
||||||
KBNODE node, uidnode=NULL;
|
KBNODE node, uidnode=NULL;
|
||||||
|
PKT_public_key *pk = kb->pkt->pkt.public_key;
|
||||||
u32 main_kid[2];
|
u32 main_kid[2];
|
||||||
int issigned=0, any_signed = 0, fully_count =0, marginal_count = 0;
|
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)
|
for (node=kb; node; node = node->next)
|
||||||
{
|
{
|
||||||
if (node->pkt->pkttype == PKT_USER_ID)
|
if (node->pkt->pkttype == PKT_USER_ID)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user