1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

calculate time of next trustdb check

This commit is contained in:
Werner Koch 2001-09-28 17:00:00 +00:00
parent aa971d5c89
commit ebf6b8a515
29 changed files with 14188 additions and 13912 deletions

View file

@ -1,5 +1,18 @@
2001-09-28 Werner Koch <wk@gnupg.org>
* keyedit.c (sign_uids): Always use the primary key to sign keys.
* getkey.c (finish_lookup): Hack to return only the primary key if
a certification key has been requested.
* trustdb.c (cmp_kid_for_make_key_array): Renamed to
(validate_one_keyblock): this and changed arg for direct calling.
(make_key_array): Renamed to
(validate_one_keyblock): this and changed args for direct calling.
(mark_usable_uid_certs, validate_one_keyblock)
(validate_key_list): Add next_expire arg to keep track of
expiration times.
(validate_keys): Ditto for UTKs and write the stamp.
* tdbio.c (migrate_from_v2): Check return code of tbdio_sync.
* tdbdump.c (import_ownertrust): Do a tdbio_sync().

View file

@ -1110,6 +1110,8 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated )
uid->help_key_usage |= PUBKEY_USAGE_SIG;
if ( (*p & 12) )
uid->help_key_usage |= PUBKEY_USAGE_ENC;
/* Note: we do not set the CERT flag here because it can be assumed
* that thre is no real policy to set it. */
}
/* ditto or the key expiration */
@ -1656,7 +1658,7 @@ merge_public_with_secret ( KBNODE pubblock, KBNODE secblock )
* secret subkey is avalable and deletes the public subkey otherwise.
* We need this function because we can't delete it later when we
* actually merge the secret parts into the pubring.
& The function also plays some games with the node flags.
* The function also plays some games with the node flags.
*/
static void
premerge_public_with_secret ( KBNODE pubblock, KBNODE secblock )
@ -1754,6 +1756,7 @@ finish_lookup (GETKEY_CTX ctx)
PKT_user_id *foundu = NULL;
#define USAGE_MASK (PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC)
unsigned int req_usage = ( ctx->req_usage & USAGE_MASK );
int req_cert = (ctx->req_usage & PUBKEY_USAGE_CERT);
u32 latest_date;
KBNODE latest_key;
u32 curtime = make_timestamp ();
@ -1803,7 +1806,8 @@ finish_lookup (GETKEY_CTX ctx)
latest_date = 0;
latest_key = NULL;
if ( !foundk || foundk->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
/* do not look at subkeys if a certification key is requested */
if ((!foundk || foundk->pkt->pkttype == PKT_PUBLIC_SUBKEY) && !req_cert) {
KBNODE nextk;
/* either start a loop or check just this one subkey */
for (k=foundk?foundk:keyblock; k; k = nextk ) {
@ -1854,11 +1858,11 @@ finish_lookup (GETKEY_CTX ctx)
}
}
/* Okay now try the primary key unless we have want an exact
/* Okay now try the primary key unless we want an exact
* key ID match on a subkey */
if ( !latest_key && !(ctx->exact && foundk != keyblock) ) {
if ((!latest_key && !(ctx->exact && foundk != keyblock)) || req_cert) {
PKT_public_key *pk;
if (DBG_CACHE && !foundk )
if (DBG_CACHE && !foundk && !req_cert )
log_debug( "\tno suitable subkeys found - trying primary\n");
pk = keyblock->pkt->pkt.public_key;
if ( !pk->is_valid ) {

View file

@ -253,8 +253,14 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int local )
int select_all = !count_selected_uids(keyblock);
int upd_trust = 0;
/* build a list of all signators */
rc=build_sk_list( locusr, &sk_list, 0, 1 );
/* build a list of all signators.
*
* We use the CERT flag to request the primary which must always
* be one which is capable of signing keys. I can't see a reason
* why to sign keys using a subkey. Implementation of SUAGE_CERT
* is just a hack in getkey.c and does not mean that a subkey
* marked as certification capable will be used */
rc=build_sk_list( locusr, &sk_list, 0, PUBKEY_USAGE_SIG|PUBKEY_USAGE_CERT);
if( rc )
goto leave;

View file

@ -121,6 +121,15 @@ list_one( STRLIST names, int secret )
KBNODE keyblock = NULL;
GETKEY_CTX ctx;
/* fixme: using the bynames function has the disadvantage that we
* don't knowether one of the names given was not found. OTOH,
* this function has the advantage to list the names in the
* sequence as defined by the keyDB and does not duplicate
* outputs. A solution could be do test whether all given have
* been listed (this needs a way to use the keyDB search
* functions) or to have the search function return indicators for
* found names. Yet another way is to use the keydb search
* facilities directly. */
if( secret ) {
rc = get_seckey_bynames( &ctx, NULL, names, &keyblock );
if( rc ) {

View file

@ -102,6 +102,7 @@ new_offset_item (void)
return k;
}
#if 0
static void
release_offset_items (struct off_item *k)
{
@ -113,7 +114,7 @@ release_offset_items (struct off_item *k)
m_free (k);
}
}
#endif
static OffsetHashTable
new_offset_hash_table (void)

View file

@ -82,8 +82,8 @@ is_duplicated_entry (STRLIST list, STRLIST item)
int
build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
unsigned use )
build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list,
int unlock, unsigned int use )
{
SK_LIST sk_list = NULL;
int rc;

View file

@ -452,12 +452,33 @@ trust_letter (unsigned int value)
/****************
* Recreate the WoT but do not ask for new ownertrusts
* Recreate the WoT but do not ask for new ownertrusts. Special
* feature: In batch mode and without a forced yes, this is only done
* when a check is due. This can be used to run the check from a crontab
*/
void
check_trustdb()
check_trustdb ()
{
init_trustdb();
if (opt.batch && !opt.answer_yes)
{
ulong scheduled;
scheduled = tdbio_read_nextcheck ();
if (!scheduled)
{
log_info (_("no need for a trustdb check\n"));
return;
}
if (scheduled > make_timestamp ())
{
log_info (_("next trustdb check due at %s\n"),
strtimestamp (scheduled));
return;
}
}
validate_keys (0);
}
@ -865,116 +886,6 @@ mark_keyblock_seen (KeyHashTable tbl, KBNODE node)
}
static int
search_skipfnc (void *opaque, u32 *kid)
{
return test_key_hash_table ((KeyHashTable)opaque, kid);
}
/*
* Scan all keys and return a key_array of all keys which are
* indicated as found by the supplied CMPFNC. The caller has to pass
* a keydb handle so that we don't use to create our own. Returns
* either a key_array or NULL in case of an error. No results found
* are indicated by an empty array. Caller hast to release the
* returned array.
*/
static struct key_array *
make_key_array (KEYDB_HANDLE hd, KeyHashTable visited,
int (*cmpfnc)(KBNODE kb, void *opaque), void *cmpval)
{
KBNODE keyblock = NULL;
struct key_array *keys = NULL;
size_t nkeys, maxkeys;
int rc;
KEYDB_SEARCH_DESC desc;
maxkeys = 1000;
keys = m_alloc ((maxkeys+1) * sizeof *keys);
nkeys = 0;
rc = keydb_search_reset (hd);
if (rc)
{
log_error ("keydb_search_reset failed: %s\n", g10_errstr(rc));
m_free (keys);
return NULL;
}
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_FIRST;
desc.skipfnc = search_skipfnc;
desc.skipfncvalue = visited;
rc = keydb_search (hd, &desc, 1);
if (rc == -1)
{
keys[nkeys].keyblock = NULL;
return keys;
}
if (rc)
{
log_error ("keydb_search_first failed: %s\n", g10_errstr(rc));
m_free (keys);
return NULL;
}
desc.mode = KEYDB_SEARCH_MODE_NEXT; /* change mode */
do
{
PKT_public_key *pk;
rc = keydb_get_keyblock (hd, &keyblock);
if (rc)
{
log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc));
m_free (keys);
return NULL;
}
if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY)
{
log_debug ("ooops: invalid pkttype %d encountered\n",
keyblock->pkt->pkttype);
dump_kbnode (keyblock);
release_kbnode(keyblock);
continue;
}
/* prepare the keyblock for further processing */
merge_keys_and_selfsig (keyblock);
clear_kbnode_flags (keyblock);
pk = keyblock->pkt->pkt.public_key;
if (pk->has_expired || pk->is_revoked)
{
/* it does not make sense to look further at those keys */
mark_keyblock_seen (visited, keyblock);
}
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 */
mark_keyblock_seen (visited, keyblock);
}
else
release_kbnode (keyblock);
keyblock = NULL;
}
while ( !(rc = keydb_search (hd, &desc, 1)) );
if (rc && rc != -1)
{
log_error ("keydb_search_next failed: %s\n", g10_errstr(rc));
m_free (keys);
return NULL;
}
keys[nkeys].keyblock = NULL;
return keys;
}
static void
dump_key_array (int depth, struct key_array *keys)
@ -1077,7 +988,8 @@ is_in_klist (struct key_item *k, PKT_signature *sig)
*/
static void
mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
u32 *main_kid, struct key_item *klist, u32 curtime)
u32 *main_kid, struct key_item *klist,
u32 curtime, u32 *next_expire)
{
KBNODE node;
PKT_signature *sig = node->pkt->pkt.signature;
@ -1157,12 +1069,16 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
* system falls back to an older certification which has a
* different expiration time */
const byte *p;
u32 expire;
p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_EXPIRE, NULL );
if ( p && (sig->timestamp + buffer_to_u32(p)) >= curtime )
; /* signature expired */
else
signode->flag |= (1<<8); /* yeah eventually we found a good cert */
expire = p? sig->timestamp + buffer_to_u32(p) : 0;
if ( expire < curtime )
{
signode->flag |= (1<<8); /* yeah, found a good cert */
if (expire && expire < *next_expire)
*next_expire = expire;
}
}
}
}
@ -1181,9 +1097,8 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
* This function assumes that all kbnode flags are cleared on entry.
*/
static int
cmp_kid_for_make_key_array (KBNODE kb, void *opaque)
validate_one_keyblock (KBNODE kb, struct key_item *klist, u32 *next_expire)
{
struct key_item *klist = opaque;
struct key_item *kr;
KBNODE node, uidnode=NULL;
PKT_public_key *pk = kb->pkt->pkt.public_key;
@ -1209,7 +1124,8 @@ cmp_kid_for_make_key_array (KBNODE kb, void *opaque)
uidnode = node;
issigned = 0;
fully_count = marginal_count = 0;
mark_usable_uid_certs (kb, uidnode, main_kid, klist, curtime);
mark_usable_uid_certs (kb, uidnode, main_kid, klist,
curtime, next_expire);
}
else if (node->pkt->pkttype == PKT_SIGNATURE
&& (node->flag & (1<<8)) )
@ -1245,6 +1161,120 @@ cmp_kid_for_make_key_array (KBNODE kb, void *opaque)
}
static int
search_skipfnc (void *opaque, u32 *kid)
{
return test_key_hash_table ((KeyHashTable)opaque, kid);
}
/*
* Scan all keys and return a key_array of all suitable keys from
* kllist. The caller has to pass keydb handle so that we don't use
* to create our own. Returns either a key_array or NULL in case of
* an error. No results found are indicated by an empty array.
* Caller hast to release the returned array.
*/
static struct key_array *
validate_key_list (KEYDB_HANDLE hd, KeyHashTable visited,
struct key_item *klist, u32 *next_expire)
{
KBNODE keyblock = NULL;
struct key_array *keys = NULL;
size_t nkeys, maxkeys;
int rc;
KEYDB_SEARCH_DESC desc;
maxkeys = 1000;
keys = m_alloc ((maxkeys+1) * sizeof *keys);
nkeys = 0;
rc = keydb_search_reset (hd);
if (rc)
{
log_error ("keydb_search_reset failed: %s\n", g10_errstr(rc));
m_free (keys);
return NULL;
}
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_FIRST;
desc.skipfnc = search_skipfnc;
desc.skipfncvalue = visited;
rc = keydb_search (hd, &desc, 1);
if (rc == -1)
{
keys[nkeys].keyblock = NULL;
return keys;
}
if (rc)
{
log_error ("keydb_search_first failed: %s\n", g10_errstr(rc));
m_free (keys);
return NULL;
}
desc.mode = KEYDB_SEARCH_MODE_NEXT; /* change mode */
do
{
PKT_public_key *pk;
rc = keydb_get_keyblock (hd, &keyblock);
if (rc)
{
log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc));
m_free (keys);
return NULL;
}
if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY)
{
log_debug ("ooops: invalid pkttype %d encountered\n",
keyblock->pkt->pkttype);
dump_kbnode (keyblock);
release_kbnode(keyblock);
continue;
}
/* prepare the keyblock for further processing */
merge_keys_and_selfsig (keyblock);
clear_kbnode_flags (keyblock);
pk = keyblock->pkt->pkt.public_key;
if (pk->has_expired || pk->is_revoked)
{
/* it does not make sense to look further at those keys */
mark_keyblock_seen (visited, keyblock);
}
else if (validate_one_keyblock (keyblock, klist, next_expire))
{
if (pk->expiredate && pk->expiredate < *next_expire)
*next_expire = pk->expiredate;
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 */
mark_keyblock_seen (visited, keyblock);
keyblock = NULL;
}
release_kbnode (keyblock);
keyblock = NULL;
}
while ( !(rc = keydb_search (hd, &desc, 1)) );
if (rc && rc != -1)
{
log_error ("keydb_search_next failed: %s\n", g10_errstr(rc));
m_free (keys);
return NULL;
}
keys[nkeys].keyblock = NULL;
return keys;
}
/*
* Run the key validation procedure.
*
@ -1283,6 +1313,7 @@ validate_keys (int interactive)
int key_count;
int ot_unknown, ot_undefined, ot_never, ot_marginal, ot_full, ot_ultimate;
KeyHashTable visited;
u32 next_expire;
visited = new_key_hash_table ();
/* Fixme: Instead of always building a UTK list, we could just build it
@ -1293,10 +1324,13 @@ validate_keys (int interactive)
goto leave;
}
next_expire = 0xffffffff; /* set next expire to the year 2106 */
/* mark all UTKs as visited and set validity to ultimate */
for (k=utk_list; k; k = k->next)
{
KBNODE keyblock;
PKT_public_key *pk;
keyblock = get_pubkeyblock (k->kid);
if (!keyblock)
@ -1306,6 +1340,7 @@ validate_keys (int interactive)
continue;
}
mark_keyblock_seen (visited, keyblock);
pk = keyblock->pkt->pkt.public_key;
for (node=keyblock; node; node = node->next)
{
if (node->pkt->pkttype == PKT_USER_ID)
@ -1317,10 +1352,12 @@ validate_keys (int interactive)
rmd160_hash_buffer (namehash, uid->photo, uid->photolen);
else
rmd160_hash_buffer (namehash, uid->name, uid->len );
update_validity (keyblock->pkt->pkt.public_key,
namehash, 0, TRUST_ULTIMATE);
update_validity (pk, namehash, 0, TRUST_ULTIMATE);
}
}
if ( pk->expiredate && pk->expiredate < next_expire)
next_expire = pk->expiredate;
release_kbnode (keyblock);
do_sync ();
}
@ -1355,10 +1392,10 @@ validate_keys (int interactive)
}
/* Find all keys which are signed by a key in kdlist */
keys = make_key_array (kdb, visited, cmp_kid_for_make_key_array, klist);
keys = validate_key_list (kdb, visited, klist, &next_expire);
if (!keys)
{
log_error ("make_key_array failed\n");
log_error ("validate_key_list failed\n");
rc = G10ERR_GENERAL;
goto leave;
}
@ -1413,7 +1450,14 @@ validate_keys (int interactive)
release_key_hash_table (visited);
if (!rc) /* mark trustDB as checked */
{
tdbio_write_nextcheck (0);
if (next_expire == 0xffffffff)
tdbio_write_nextcheck (0);
else
{
tdbio_write_nextcheck (next_expire);
log_info (_("next trustdb check due at %s\n"),
strtimestamp (next_expire));
}
do_sync ();
}
return rc;