aboutsummaryrefslogtreecommitdiffstats
path: root/g10/trustdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/trustdb.c')
-rw-r--r--g10/trustdb.c228
1 files changed, 145 insertions, 83 deletions
diff --git a/g10/trustdb.c b/g10/trustdb.c
index 8ceced1f7..b9527ec71 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -274,9 +274,8 @@ verify_own_keys(void)
(ulong)kid[1]);
}
}
-
- /* the --trusted-key option is again deprecated; however we automagically
- * add those keys to the trustdb */
+
+ /* Put any --trusted-key keys into the trustdb */
for (k = user_utk_list; k; k = k->next)
{
if ( add_utk (k->kid) )
@@ -644,13 +643,19 @@ clear_ownertrust (PKT_public_key *pk)
* Note: Caller has to do a sync
*/
static void
-update_validity (PKT_public_key *pk, const byte *namehash,
+update_validity (PKT_public_key *pk, PKT_user_id *uid,
int depth, int validity)
{
TRUSTREC trec, vrec;
int rc;
ulong recno;
-
+ byte namehash[20];
+
+ if( uid->attrib_data )
+ rmd160_hash_buffer (namehash,uid->attrib_data,uid->attrib_len);
+ else
+ rmd160_hash_buffer (namehash, uid->name, uid->len );
+
rc = read_trust_record (pk, &trec);
if (rc && rc != -1)
{
@@ -688,6 +693,8 @@ update_validity (PKT_public_key *pk, const byte *namehash,
vrec.r.valid.next = trec.r.trust.validlist;
}
vrec.r.valid.validity = validity;
+ vrec.r.valid.full_count = uid->help_full_count;
+ vrec.r.valid.marginal_count = uid->help_marginal_count;
write_record (&vrec);
trec.r.trust.depth = depth;
trec.r.trust.validlist = vrec.recnum;
@@ -710,17 +717,18 @@ clear_validity (PKT_public_key *pk)
tdbio_invalid ();
return 0;
}
- if (rc == -1) /* no record yet - no need to clerar it then ;-) */
+ if (rc == -1) /* no record yet - no need to clear it then ;-) */
return 0;
- /* reset validity for all user IDs */
recno = trec.r.trust.validlist;
while (recno)
{
read_record (recno, &vrec, RECTYPE_VALID);
- if ((vrec.r.valid.validity & TRUST_MASK))
+ if ((vrec.r.valid.validity & TRUST_MASK)
+ || vrec.r.valid.marginal_count || vrec.r.valid.full_count)
{
vrec.r.valid.validity &= ~TRUST_MASK;
+ vrec.r.valid.marginal_count = vrec.r.valid.full_count = 0;
write_record (&vrec);
any = 1;
}
@@ -731,7 +739,6 @@ clear_validity (PKT_public_key *pk)
}
-
/***********************************************
********* Query trustdb values **************
***********************************************/
@@ -876,7 +883,6 @@ get_validity (PKT_public_key *pk, const byte *namehash)
return validity;
}
-
int
get_validity_info (PKT_public_key *pk, const byte *namehash)
{
@@ -894,17 +900,51 @@ get_validity_info (PKT_public_key *pk, const byte *namehash)
return c;
}
+static void
+get_validity_counts (PKT_public_key *pk, PKT_user_id *uid)
+{
+ TRUSTREC trec, vrec;
+ ulong recno;
+ byte namehash[20];
+ if(pk==NULL || uid==NULL)
+ BUG();
+
+ if( uid->attrib_data )
+ rmd160_hash_buffer (namehash,uid->attrib_data,uid->attrib_len);
+ else
+ rmd160_hash_buffer (namehash, uid->name, uid->len );
+ uid->help_marginal_count=uid->help_full_count=0;
+
+ init_trustdb ();
+
+ if(read_trust_record (pk, &trec)!=0)
+ return;
+
+ /* loop over all user IDs */
+ recno = trec.r.trust.validlist;
+ while (recno)
+ {
+ read_record (recno, &vrec, RECTYPE_VALID);
+
+ if(memcmp(vrec.r.valid.namehash,namehash,20)==0)
+ {
+ uid->help_marginal_count=vrec.r.valid.marginal_count;
+ uid->help_full_count=vrec.r.valid.full_count;
+ /* printf("Fetched marginal %d, full %d\n",uid->help_marginal_count,uid->help_full_count); */
+ break;
+ }
+
+ recno = vrec.r.valid.next;
+ }
+}
void
list_trust_path( const char *username )
{
}
-
-
-
/****************
* Enumerate all keys, which are needed to build all trust paths for
* the given key. This function does not return the key itself or
@@ -980,7 +1020,7 @@ mark_keyblock_seen (KeyHashTable tbl, KBNODE node)
{
for ( ;node; node = node->next )
if (node->pkt->pkttype == PKT_PUBLIC_KEY
- || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
+ || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
u32 aki[2];
@@ -990,7 +1030,6 @@ mark_keyblock_seen (KeyHashTable tbl, KBNODE node)
}
-
static void
dump_key_array (int depth, struct key_array *keys)
{
@@ -1028,10 +1067,9 @@ dump_key_array (int depth, struct key_array *keys)
static void
-store_validation_status (int depth, KBNODE keyblock)
+store_validation_status (int depth, KBNODE keyblock, KeyHashTable stored)
{
KBNODE node;
- byte namehash[20];
int status;
int any = 0;
@@ -1040,7 +1078,6 @@ store_validation_status (int depth, KBNODE keyblock)
if (node->pkt->pkttype == PKT_USER_ID)
{
PKT_user_id *uid = node->pkt->pkt.user_id;
-
if (node->flag & 4)
status = TRUST_FULLY;
else if (node->flag & 2)
@@ -1052,13 +1089,11 @@ store_validation_status (int depth, KBNODE keyblock)
if (status)
{
- if( uid->attrib_data )
- rmd160_hash_buffer (namehash,uid->attrib_data,uid->attrib_len);
- else
- rmd160_hash_buffer (namehash, uid->name, uid->len );
-
update_validity (keyblock->pkt->pkt.public_key,
- namehash, depth, status);
+ uid, depth, status);
+
+ mark_keyblock_seen(stored,keyblock);
+
any = 1;
}
}
@@ -1251,9 +1286,10 @@ validate_one_keyblock (KBNODE kb, struct key_item *klist,
{
struct key_item *kr;
KBNODE node, uidnode=NULL;
+ PKT_user_id *uid=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;
+ int issigned=0, any_signed = 0;
keyid_from_pk(pk, main_kid);
for (node=kb; node; node = node->next)
@@ -1262,22 +1298,23 @@ validate_one_keyblock (KBNODE kb, struct key_item *klist,
{
if (uidnode && issigned)
{
- if (fully_count >= opt.completes_needed
- || marginal_count >= opt.marginals_needed )
+ if (uid->help_full_count >= opt.completes_needed
+ || uid->help_marginal_count >= opt.marginals_needed )
uidnode->flag |= 4;
- else if (fully_count || marginal_count)
+ else if (uid->help_full_count || uid->help_marginal_count)
uidnode->flag |= 2;
uidnode->flag |= 1;
any_signed = 1;
}
uidnode = node;
+ uid=uidnode->pkt->pkt.user_id;
issigned = 0;
- fully_count = marginal_count = 0;
+ get_validity_counts(pk,uid);
mark_usable_uid_certs (kb, uidnode, main_kid, klist,
curtime, next_expire);
}
else if (node->pkt->pkttype == PKT_SIGNATURE
- && (node->flag & (1<<8)) )
+ && (node->flag & (1<<8)) && uid)
{
PKT_signature *sig = node->pkt->pkt.signature;
@@ -1285,11 +1322,11 @@ validate_one_keyblock (KBNODE kb, struct key_item *klist,
if (kr)
{
if (kr->ownertrust == TRUST_ULTIMATE)
- fully_count = opt.completes_needed;
+ uid->help_full_count = opt.completes_needed;
else if (kr->ownertrust == TRUST_FULLY)
- fully_count++;
+ uid->help_full_count++;
else if (kr->ownertrust == TRUST_MARGINAL)
- marginal_count++;
+ uid->help_marginal_count++;
issigned = 1;
}
}
@@ -1297,10 +1334,10 @@ validate_one_keyblock (KBNODE kb, struct key_item *klist,
if (uidnode && issigned)
{
- if (fully_count >= opt.completes_needed
- || marginal_count >= opt.marginals_needed )
+ if (uid->help_full_count >= opt.completes_needed
+ || uid->help_marginal_count >= opt.marginals_needed )
uidnode->flag |= 4;
- else if (fully_count || marginal_count)
+ else if (uid->help_full_count || uid->help_marginal_count)
uidnode->flag |= 2;
uidnode->flag |= 1;
any_signed = 1;
@@ -1325,7 +1362,7 @@ search_skipfnc (void *opaque, u32 *kid)
* Caller hast to release the returned array.
*/
static struct key_array *
-validate_key_list (KEYDB_HANDLE hd, KeyHashTable visited,
+validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust,
struct key_item *klist, u32 curtime, u32 *next_expire)
{
KBNODE keyblock = NULL;
@@ -1349,7 +1386,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable visited,
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_FIRST;
desc.skipfnc = search_skipfnc;
- desc.skipfncvalue = visited;
+ desc.skipfncvalue = full_trust;
rc = keydb_search (hd, &desc, 1);
if (rc == -1)
{
@@ -1392,10 +1429,12 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable visited,
if (pk->has_expired || pk->is_revoked)
{
/* it does not make sense to look further at those keys */
- mark_keyblock_seen (visited, keyblock);
+ mark_keyblock_seen (full_trust, keyblock);
}
else if (validate_one_keyblock (keyblock, klist, curtime, next_expire))
{
+ KBNODE node;
+
if (pk->expiredate && pk->expiredate >= curtime
&& pk->expiredate < *next_expire)
*next_expire = pk->expiredate;
@@ -1405,8 +1444,17 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable visited,
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);
+
+ /* Optimization - if all uids are fully trusted, then we
+ never need to consider this key as a candidate again. */
+
+ for (node=keyblock; node; node = node->next)
+ if (node->pkt->pkttype == PKT_USER_ID && !(node->flag & 4))
+ break;
+
+ if(node==NULL)
+ mark_keyblock_seen (full_trust, keyblock);
+
keyblock = NULL;
}
@@ -1425,9 +1473,9 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable visited,
return keys;
}
-
+/* Caller must sync */
static void
-reset_unconnected_keys (KEYDB_HANDLE hd, KeyHashTable visited)
+reset_trust_records (KEYDB_HANDLE hd, KeyHashTable exclude)
{
int rc;
KBNODE keyblock = NULL;
@@ -1443,8 +1491,11 @@ reset_unconnected_keys (KEYDB_HANDLE hd, KeyHashTable visited)
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_FIRST;
- desc.skipfnc = search_skipfnc;
- desc.skipfncvalue = visited;
+ if(exclude)
+ {
+ desc.skipfnc = search_skipfnc;
+ desc.skipfncvalue = exclude;
+ }
rc = keydb_search (hd, &desc, 1);
if (rc && rc != -1 )
log_error ("keydb_search_first failed: %s\n", g10_errstr(rc));
@@ -1472,11 +1523,9 @@ reset_unconnected_keys (KEYDB_HANDLE hd, KeyHashTable visited)
log_error ("keydb_search_next failed: %s\n", g10_errstr(rc));
}
if (opt.verbose)
- log_info ("%d unconnected keys (%d trust records cleared)\n",
+ log_info ("%d keys processed (%d validity counts cleared)\n",
count, nreset);
- do_sync ();
-}
-
+}
/*
* Run the key validation procedure.
@@ -1516,12 +1565,14 @@ validate_keys (int interactive)
int depth;
int key_count;
int ot_unknown, ot_undefined, ot_never, ot_marginal, ot_full, ot_ultimate;
- KeyHashTable visited;
+ KeyHashTable stored,used,full_trust;
u32 start_time, next_expire;
start_time = make_timestamp ();
next_expire = 0xffffffff; /* set next expire to the year 2106 */
- visited = new_key_hash_table ();
+ stored = new_key_hash_table ();
+ used = new_key_hash_table ();
+ full_trust = new_key_hash_table ();
/* Fixme: Instead of always building a UTK list, we could just build it
* here when needed */
if (!utk_list)
@@ -1530,8 +1581,12 @@ validate_keys (int interactive)
goto leave;
}
+ kdb = keydb_new (0);
+
+ reset_trust_records (kdb,NULL);
- /* mark all UTKs as visited and set validity to ultimate */
+ /* mark all UTKs as used and fully_trusted and set validity to
+ ultimate */
for (k=utk_list; k; k = k->next)
{
KBNODE keyblock;
@@ -1544,21 +1599,14 @@ validate_keys (int interactive)
" trusted key %08lX not found\n"), (ulong)k->kid[1]);
continue;
}
- mark_keyblock_seen (visited, keyblock);
+ mark_keyblock_seen (used, keyblock);
+ mark_keyblock_seen (stored, keyblock);
+ mark_keyblock_seen (full_trust, keyblock);
pk = keyblock->pkt->pkt.public_key;
for (node=keyblock; node; node = node->next)
{
if (node->pkt->pkttype == PKT_USER_ID)
- {
- byte namehash[20];
- PKT_user_id *uid = node->pkt->pkt.user_id;
-
- if( uid->attrib_data )
- rmd160_hash_buffer (namehash,uid->attrib_data,uid->attrib_len);
- else
- rmd160_hash_buffer (namehash, uid->name, uid->len );
- update_validity (pk, namehash, 0, TRUST_ULTIMATE);
- }
+ update_validity (pk, node->pkt->pkt.user_id, 0, TRUST_ULTIMATE);
}
if ( pk->expiredate && pk->expiredate >= start_time
&& pk->expiredate < next_expire)
@@ -1568,9 +1616,7 @@ validate_keys (int interactive)
do_sync ();
}
-
klist = utk_list;
- kdb = keydb_new (0);
for (depth=0; depth < opt.max_cert_depth; depth++)
{
@@ -1602,7 +1648,8 @@ validate_keys (int interactive)
}
/* Find all keys which are signed by a key in kdlist */
- keys = validate_key_list (kdb, visited, klist, start_time, &next_expire);
+ keys = validate_key_list (kdb, full_trust, klist,
+ start_time, &next_expire);
if (!keys)
{
log_error ("validate_key_list failed\n");
@@ -1610,7 +1657,6 @@ validate_keys (int interactive)
goto leave;
}
-
for (key_count=0, kar=keys; kar->keyblock; kar++, key_count++)
;
@@ -1618,14 +1664,17 @@ validate_keys (int interactive)
if (opt.verbose > 1)
dump_key_array (depth, keys);
+ for (kar=keys; kar->keyblock; kar++)
+ store_validation_status (depth, kar->keyblock, stored);
+
+ /* This should be valid=%d now, but I'm not changing it so I
+ don't break the translated strings in the stable branch.
+ Change it in devel. -dms */
log_info (_("checking at depth %d signed=%d"
" ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n"),
depth, key_count, ot_unknown, ot_undefined,
ot_never, ot_marginal, ot_full, ot_ultimate );
- for (kar=keys; kar->keyblock; kar++)
- store_validation_status (depth, kar->keyblock);
-
/* Build a new kdlist from all fully valid keys in KEYS */
if (klist != utk_list)
release_key_items (klist);
@@ -1636,29 +1685,42 @@ validate_keys (int interactive)
{
if (node->pkt->pkttype == PKT_USER_ID && (node->flag & 4))
{
- k = new_key_item ();
- keyid_from_pk (kar->keyblock->pkt->pkt.public_key, k->kid);
- k->ownertrust = get_ownertrust (kar->keyblock
- ->pkt->pkt.public_key);
- k->next = klist;
- klist = k;
- break;
- }
- }
- }
+ u32 kid[2];
+
+ /* have we used this key already? */
+ keyid_from_pk (kar->keyblock->pkt->pkt.public_key, kid);
+ if(test_key_hash_table(used,kid)==0)
+ {
+ /* Normally we add both the primary and subkey
+ ids to the hash via mark_keyblock_seen, but
+ since we aren't using this hash as a skipfnc,
+ that doesn't matter here. */
+ add_key_hash_table (used,kid);
+ k = new_key_item ();
+ k->kid[0]=kid[0];
+ k->kid[1]=kid[1];
+ k->ownertrust = get_ownertrust (kar->keyblock
+ ->pkt->pkt.public_key);
+ k->next = klist;
+ klist = k;
+ break;
+ }
+ }
+ }
+ }
release_key_array (keys);
keys = NULL;
if (!klist)
break; /* no need to dive in deeper */
}
- reset_unconnected_keys (kdb, visited);
-
leave:
keydb_release (kdb);
release_key_array (keys);
release_key_items (klist);
- release_key_hash_table (visited);
+ release_key_hash_table (full_trust);
+ release_key_hash_table (used);
+ release_key_hash_table (stored);
if (!rc && !quit) /* mark trustDB as checked */
{
if (next_expire == 0xffffffff || next_expire < start_time )