aboutsummaryrefslogtreecommitdiffstats
path: root/g10/trustdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/trustdb.c')
-rw-r--r--g10/trustdb.c91
1 files changed, 79 insertions, 12 deletions
diff --git a/g10/trustdb.c b/g10/trustdb.c
index 6f3de849d..9714bf938 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -165,7 +165,6 @@ add_key_hash_table (KeyHashTable tbl, u32 *kid)
tbl[(kid[1] & 0x03ff)] = kk;
}
-
/*
* Release a key_array
*/
@@ -671,6 +670,8 @@ get_validity (PKT_public_key *pk, const byte *namehash)
int rc;
ulong recno;
unsigned int validity;
+ u32 kid[2];
+ PKT_public_key *main_pk;
init_trustdb ();
if (!did_nextcheck)
@@ -690,14 +691,33 @@ get_validity (PKT_public_key *pk, const byte *namehash)
}
}
- rc = read_trust_record (pk, &trec);
+ keyid_from_pk (pk, kid);
+ if (pk->main_keyid[0] != kid[0] || pk->main_keyid[1] != kid[1])
+ { /* this is a subkey - get the mainkey */
+ main_pk = m_alloc_clear (sizeof *main_pk);
+ rc = get_pubkey (main_pk, pk->main_keyid);
+ if (rc)
+ {
+ log_error ("error getting main key %08lX of subkey %08lX: %s\n",
+ (ulong)pk->main_keyid[1], (ulong)kid[1], g10_errstr(rc));
+ validity = TRUST_UNKNOWN;
+ goto leave;
+ }
+ }
+ else
+ main_pk = pk;
+
+ rc = read_trust_record (main_pk, &trec);
if (rc && rc != -1)
{
tdbio_invalid ();
return 0;
}
if (rc == -1) /* no record found */
- return TRUST_UNKNOWN;
+ {
+ validity = TRUST_UNKNOWN;
+ goto leave;
+ }
/* loop over all user IDs */
recno = trec.r.trust.validlist;
@@ -719,13 +739,18 @@ get_validity (PKT_public_key *pk, const byte *namehash)
validity |= TRUST_FLAG_DISABLED;
/* set some flags direct from the key */
- if (pk->is_revoked)
+ if (main_pk->is_revoked)
validity |= TRUST_FLAG_REVOKED;
+ if (main_pk != pk && pk->is_revoked)
+ validity |= TRUST_FLAG_SUB_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 (main_pk->has_expired || pk->has_expired)
validity = (validity & ~TRUST_MASK) | TRUST_EXPIRED;
+ leave:
+ if (main_pk != pk)
+ free_public_key (main_pk);
return validity;
}
@@ -825,10 +850,25 @@ ask_ownertrust (u32 *kid)
}
+static void
+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)
+ {
+ u32 aki[2];
+
+ keyid_from_pk (node->pkt->pkt.public_key, aki);
+ add_key_hash_table (tbl, aki);
+ }
+}
+
+
static int
search_skipfnc (void *opaque, u32 *kid)
{
- return test_key_hash_table ((KeyHashTable)opaque, kid);
+ return test_key_hash_table ((KeyHashTable)opaque, kid);
}
/*
@@ -882,7 +922,6 @@ make_key_array (KEYDB_HANDLE hd, KeyHashTable visited,
do
{
PKT_public_key *pk;
- u32 kid[2];
rc = keydb_get_keyblock (hd, &keyblock);
if (rc)
@@ -905,12 +944,10 @@ make_key_array (KEYDB_HANDLE hd, KeyHashTable visited,
merge_keys_and_selfsig (keyblock);
clear_kbnode_flags (keyblock);
pk = keyblock->pkt->pkt.public_key;
- keyid_from_pk (pk, kid); /*(cheap: should already be cached in the pk)*/
-
if (pk->has_expired || pk->is_revoked)
{
/* it does not make sense to look further at those keys */
- add_key_hash_table (visited, kid);
+ mark_keyblock_seen (visited, keyblock);
}
else if (cmpfnc (keyblock, cmpval))
{
@@ -920,7 +957,7 @@ make_key_array (KEYDB_HANDLE hd, KeyHashTable visited,
}
keys[nkeys++].keyblock = keyblock;
/* This key is signed - don't check it again */
- add_key_hash_table (visited, kid);
+ mark_keyblock_seen (visited, keyblock);
}
else
release_kbnode (keyblock);
@@ -1256,8 +1293,38 @@ validate_keys (int interactive)
goto leave;
}
+ /* mark all UTKs as visited and set validity to ultimate */
for (k=utk_list; k; k = k->next)
- add_key_hash_table (visited, k->kid);
+ {
+ KBNODE keyblock;
+
+ keyblock = get_pubkeyblock (k->kid);
+ if (!keyblock)
+ {
+ log_error (_("public key of ultimately"
+ " trusted key %08lX not found\n"), (ulong)k->kid[1]);
+ continue;
+ }
+ mark_keyblock_seen (visited, keyblock);
+ 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->photo )
+ 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);
+ }
+ }
+ release_kbnode (keyblock);
+ do_sync ();
+ }
+
klist = utk_list;
kdb = keydb_new (0);