X-Git-Url: https://the.earth.li/gitweb/?a=blobdiff_plain;f=cleankey.c;h=10fb661bca71b9dd3918e5ffdc83d69bb50aa6dc;hb=6d60149434eed130c201d4d670ce7b3be5c2866b;hp=51274fe874b25898a1405e006ddd20296deebc9d;hpb=c981a80699901eb3d513a4cc9355574a69016037;p=onak.git diff --git a/cleankey.c b/cleankey.c index 51274fe..10fb661 100644 --- a/cleankey.c +++ b/cleankey.c @@ -141,7 +141,7 @@ int clean_sighashes(struct onak_dbctx *dbctx, bool *selfsig, bool *othersig) { struct openpgp_packet_list *tmpsig; - struct openpgp_publickey *sigkey = NULL; + struct openpgp_publickey *sigkeys = NULL, *curkey; onak_status_t ret; uint8_t hashtype; uint8_t hash[64]; @@ -151,9 +151,6 @@ int clean_sighashes(struct onak_dbctx *dbctx, bool remove; get_keyid(key, &keyid); - if (othersig != NULL) { - *othersig = false; - } if (selfsig != NULL) { *selfsig = false; } @@ -198,10 +195,20 @@ int clean_sighashes(struct onak_dbctx *dbctx, } } - if (remove && dbctx->fetch_key_id(dbctx, sigid, - &sigkey, false)) { + if (remove) { + dbctx->fetch_key_id(dbctx, sigid, + &sigkeys, false); + } + + /* + * A 64 bit collision is probably a sign of something + * sneaky happening, but if the signature verifies we + * should keep it. + */ + for (curkey = sigkeys; curkey != NULL; + curkey = curkey->next) { - ret = onak_check_hash_sig(sigkey, + ret = onak_check_hash_sig(curkey, (*sigs)->packet, hash, hashtype); @@ -211,11 +218,12 @@ int clean_sighashes(struct onak_dbctx *dbctx, if (othersig != NULL) { *othersig = true; } + break; } - - free_publickey(sigkey); - sigkey = NULL; } + + free_publickey(sigkeys); + sigkeys = NULL; } #endif @@ -238,17 +246,19 @@ int clean_list_sighashes(struct onak_dbctx *dbctx, struct openpgp_signedpacket_list **siglist, bool fullverify, bool needother) { - struct openpgp_signedpacket_list *tmp = NULL; + struct openpgp_signedpacket_list **orig, *tmp = NULL; bool selfsig, othersig; int removed = 0; + othersig = false; + orig = siglist; while (siglist != NULL && *siglist != NULL) { - selfsig = othersig = false; + selfsig = false; removed += clean_sighashes(dbctx, key, (*siglist)->packet, &(*siglist)->sigs, fullverify, &selfsig, &othersig); - if (fullverify && (!selfsig || (needother && !othersig))) { + if (fullverify && !selfsig) { /* Remove the UID/subkey if there's no selfsig */ tmp = *siglist; *siglist = (*siglist)->next; @@ -259,6 +269,20 @@ int clean_list_sighashes(struct onak_dbctx *dbctx, } } + /* + * We need at least one UID to have a signature from another key, + * otherwise we remove all of them if needother is set. + */ + if (needother && fullverify && !othersig) { + siglist = orig; + while (siglist != NULL && *siglist != NULL) { + tmp = *siglist; + *siglist = (*siglist)->next; + tmp->next = NULL; + free_signedpacket_list(tmp); + } + } + return removed; } @@ -339,7 +363,9 @@ int cleankeys(struct onak_dbctx *dbctx, struct openpgp_publickey **keys, uint64_t policies) { struct openpgp_publickey **curkey, *tmp; + struct openpgp_fingerprint fp; int changed = 0, count = 0; + bool needother; if (keys == NULL) return 0; @@ -364,9 +390,24 @@ int cleankeys(struct onak_dbctx *dbctx, struct openpgp_publickey **keys, count += dedupsubkeys(*curkey); if (policies & (ONAK_CLEAN_CHECK_SIGHASH | ONAK_CLEAN_VERIFY_SIGNATURES)) { + + needother = policies & ONAK_CLEAN_NEED_OTHER_SIG; + if (needother) { + /* + * Check if we already have the key; if we do + * then we can skip the check to make sure we + * have signatures from other keys. + */ + get_fingerprint((*curkey)->publickey, &fp); + tmp = NULL; + needother = dbctx->fetch_key(dbctx, &fp, + &tmp, false) == 0; + free_publickey(tmp); + } + count += clean_key_signatures(dbctx, *curkey, policies & ONAK_CLEAN_VERIFY_SIGNATURES, - policies & ONAK_CLEAN_NEED_OTHER_SIG); + needother); } if (count > 0) { changed++;