aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
authorDavid Shaw <[email protected]>2003-01-06 22:56:08 +0000
committerDavid Shaw <[email protected]>2003-01-06 22:56:08 +0000
commitaf6e3ef0459f47fadb6dce598ca255ca17aa314f (patch)
tree64c73395fc814b2a8f8919c776c5178f00c859c5 /g10
parent* DETAILS: Document disabled flag in capabilities field. (diff)
downloadgnupg-af6e3ef0459f47fadb6dce598ca255ca17aa314f.tar.gz
gnupg-af6e3ef0459f47fadb6dce598ca255ca17aa314f.zip
* packet.h, tdbio.h, tdbio.c (tdbio_read_record, tdbio_write_record),
trustdb.c (update_validity): Store temporary full & marginal counts in the trustdb. (clear_validity, get_validity_counts): Return and clear temp counts. (store_validation_status): Keep track of which keyids have been stored. (validate_one_keyblock, validate_key_list): Use per-uid copies of the full & marginal counts so they can be recalled for multiple levels. (validate_keys): Only use unused keys for each new round. (reset_unconnected_keys): Rename to reset_trust_records, and only skip specifically excluded records.
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog14
-rw-r--r--g10/packet.h4
-rw-r--r--g10/tdbio.c4
-rw-r--r--g10/tdbio.h4
-rw-r--r--g10/trustdb.c245
5 files changed, 178 insertions, 93 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 70297e05e..a57721e2b 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,5 +1,19 @@
2003-01-06 David Shaw <[email protected]>
+ * packet.h, tdbio.h, tdbio.c (tdbio_read_record,
+ tdbio_write_record), trustdb.c (update_validity): Store temporary
+ full & marginal counts in the trustdb.
+ (clear_validity, get_validity_counts): Return and clear temp
+ counts.
+ (store_validation_status): Keep track of which keyids have been
+ stored.
+ (validate_one_keyblock, validate_key_list): Use per-uid copies of
+ the full & marginal counts so they can be recalled for multiple
+ levels.
+ (validate_keys): Only use unused keys for each new round.
+ (reset_unconnected_keys): Rename to reset_trust_records, and only
+ skip specifically excluded records.
+
* keylist.c (print_capabilities): Show 'D' for disabled keys in
capabilities section.
diff --git a/g10/packet.h b/g10/packet.h
index 00b7d2b14..05e7c261a 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -49,7 +49,7 @@ typedef enum {
PKT_OLD_COMMENT =16, /* comment packet from an OpenPGP draft */
PKT_ATTRIBUTE =17, /* PGP's attribute packet */
PKT_ENCRYPTED_MDC =18, /* integrity protected encrypted data */
- PKT_MDC =19, /* manipulaion detection code packet */
+ PKT_MDC =19, /* manipulation detection code packet */
PKT_COMMENT =61, /* new comment packet (private) */
PKT_GPG_CONTROL =63 /* internal control packet */
} pkttype_t;
@@ -169,6 +169,8 @@ typedef struct {
unsigned long attrib_len;
int help_key_usage;
u32 help_key_expire;
+ int help_full_count;
+ int help_marginal_count;
int is_primary;
int is_revoked;
int is_expired;
diff --git a/g10/tdbio.c b/g10/tdbio.c
index 8c49fefb9..c7f04f441 100644
--- a/g10/tdbio.c
+++ b/g10/tdbio.c
@@ -1218,6 +1218,8 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
memcpy( rec->r.valid.namehash, p, 20); p+=20;
rec->r.valid.validity = *p++;
rec->r.valid.next = buftoulong(p); p += 4;
+ rec->r.valid.full_count = *p++;
+ rec->r.valid.marginal_count = *p++;
break;
default:
log_error( "%s: invalid record type %d at recnum %lu\n",
@@ -1299,6 +1301,8 @@ tdbio_write_record( TRUSTREC *rec )
memcpy( p, rec->r.valid.namehash, 20); p += 20;
*p++ = rec->r.valid.validity;
ulongtobuf( p, rec->r.valid.next); p += 4;
+ *p++ = rec->r.valid.full_count;
+ *p++ = rec->r.valid.marginal_count;
break;
default:
diff --git a/g10/tdbio.h b/g10/tdbio.h
index 91a73efe6..26503dc0d 100644
--- a/g10/tdbio.h
+++ b/g10/tdbio.h
@@ -50,7 +50,7 @@ struct trust_record {
ulong recnum;
union {
struct { /* version record: */
- byte version; /* should be 3 */
+ byte version; /* should be 3 */
byte marginals;
byte completes;
byte cert_depth;
@@ -84,6 +84,8 @@ struct trust_record {
byte namehash[20];
ulong next;
byte validity;
+ byte full_count;
+ byte marginal_count;
} valid;
} r;
};
diff --git a/g10/trustdb.c b/g10/trustdb.c
index 312290e0f..10e2df6dc 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -287,9 +287,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) )
@@ -796,13 +795,19 @@ clear_ownertrusts (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)
{
@@ -840,6 +845,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;
@@ -872,14 +879,15 @@ clear_validity (PKT_public_key *pk)
write_record(&trec);
}
- /* 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;
}
@@ -1033,7 +1041,6 @@ get_validity (PKT_public_key *pk, const byte *namehash)
return validity;
}
-
int
get_validity_info (PKT_public_key *pk, const byte *namehash)
{
@@ -1051,17 +1058,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
@@ -1149,7 +1190,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];
@@ -1159,7 +1200,6 @@ mark_keyblock_seen (KeyHashTable tbl, KBNODE node)
}
-
static void
dump_key_array (int depth, struct key_array *keys)
{
@@ -1197,10 +1237,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;
@@ -1209,7 +1248,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)
@@ -1221,13 +1259,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;
}
}
@@ -1449,9 +1485,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)
@@ -1460,22 +1497,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)
{
/* Note that we are only seeing unrevoked sigs here */
PKT_signature *sig = node->pkt->pkt.signature;
@@ -1535,12 +1573,12 @@ validate_one_keyblock (KBNODE kb, struct key_item *klist,
pk->trust_regexp=sig->trust_regexp;
}
- if (kr->ownertrust == TRUST_ULTIMATE)
- fully_count = opt.completes_needed;
+ if (kr->ownertrust == TRUST_ULTIMATE)
+ 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;
}
}
@@ -1548,10 +1586,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;
@@ -1576,7 +1614,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;
@@ -1600,7 +1638,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)
{
@@ -1643,10 +1681,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;
@@ -1656,8 +1696,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;
}
@@ -1676,9 +1725,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;
@@ -1694,8 +1743,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));
@@ -1723,11 +1775,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.
@@ -1767,12 +1817,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)
@@ -1781,7 +1833,12 @@ validate_keys (int interactive)
goto leave;
}
- /* mark all UTKs as visited and set validity to ultimate */
+ kdb = keydb_new (0);
+
+ reset_trust_records (kdb,NULL);
+
+ /* mark all UTKs as used and fully_trusted and set validity to
+ ultimate */
for (k=utk_list; k; k = k->next)
{
KBNODE keyblock;
@@ -1794,21 +1851,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)
@@ -1819,7 +1869,6 @@ validate_keys (int interactive)
}
klist = utk_list;
- kdb = keydb_new (0);
log_info(_("%d marginal(s) needed, %d complete(s) needed, %s trust model\n"),
opt.marginals_needed,opt.completes_needed,
@@ -1886,7 +1935,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");
@@ -1901,14 +1951,14 @@ validate_keys (int interactive)
if (opt.verbose > 1)
dump_key_array (depth, keys);
- log_info (_("checking at depth %d signed=%d"
+ for (kar=keys; kar->keyblock; kar++)
+ store_validation_status (depth, kar->keyblock, stored);
+
+ log_info (_("checking at depth %d valid=%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);
@@ -1919,39 +1969,52 @@ 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->min_ownertrust = get_min_ownertrust (kar->keyblock
- ->pkt->pkt.public_key);
- k->trust_depth=
- kar->keyblock->pkt->pkt.public_key->trust_depth;
- k->trust_value=
- kar->keyblock->pkt->pkt.public_key->trust_value;
- if(kar->keyblock->pkt->pkt.public_key->trust_regexp)
- k->trust_regexp=
- m_strdup(kar->keyblock->pkt->
- pkt.public_key->trust_regexp);
- 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->min_ownertrust =
+ get_min_ownertrust(kar->keyblock->pkt->pkt.public_key);
+ k->trust_depth=
+ kar->keyblock->pkt->pkt.public_key->trust_depth;
+ k->trust_value=
+ kar->keyblock->pkt->pkt.public_key->trust_value;
+ if(kar->keyblock->pkt->pkt.public_key->trust_regexp)
+ k->trust_regexp=
+ m_strdup(kar->keyblock->pkt->
+ pkt.public_key->trust_regexp);
+ 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 )