]> the.earth.li Git - onak.git/blobdiff - cleankey.c
Fix handling of other signature requirement
[onak.git] / cleankey.c
index 51274fe874b25898a1405e006ddd20296deebc9d..10fb661bca71b9dd3918e5ffdc83d69bb50aa6dc 100644 (file)
@@ -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++;