]> the.earth.li Git - onak.git/blobdiff - keydb_db4.c
Skip signature hash verification for X509 signatures
[onak.git] / keydb_db4.c
index 638be28dc2583afe5932cdceeb5df0c785882f5a..dae8a2a91f8f9ad830908baa82a405b500d7f559 100644 (file)
@@ -74,6 +74,11 @@ static DB *id32db = NULL;
  */
 static DB *skshashdb = NULL;
 
+/**
+ *     subkeydb - our connection to the subkey ID lookup database.
+ */
+static DB *subkeydb = NULL;
+
 /**
  *     txn - our current transaction id.
  */
@@ -175,6 +180,10 @@ static void db4_cleanupdb(void)
 
        if (dbenv != NULL) {
                dbenv->txn_checkpoint(dbenv, 0, 0, 0);
+               if (subkeydb != NULL) {
+                       subkeydb->close(subkeydb, 0);
+                       subkeydb = NULL;
+               }
                if (skshashdb != NULL) {
                        skshashdb->close(skshashdb, 0);
                        skshashdb = NULL;
@@ -289,6 +298,18 @@ static int db4_upgradedb(int numdb)
                        db_strerror(ret));
        }
 
+       ret = db_create(&curdb, NULL, 0);
+       if (ret == 0) {
+               snprintf(buf, sizeof(buf) - 1, "%s/subkeydb", config.db_dir);
+               logthing(LOGTHING_DEBUG, "Upgrading %s", buf);
+               ret = curdb->upgrade(curdb, buf, 0);
+               curdb->close(curdb, 0);
+       } else {
+               logthing(LOGTHING_ERROR, "Error upgrading DB %s : %s",
+                       buf,
+                       db_strerror(ret));
+       }
+
        snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir,
                        DB4_UPGRADE_FILE);
        unlink(buf);
@@ -535,6 +556,27 @@ static void db4_initdb(bool readonly)
                }
        }
 
+       if (ret == 0) {
+               ret = db_create(&subkeydb, dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL, "db_create: %s",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = subkeydb->open(subkeydb, txn, "subkeydb", "subkeydb",
+                               DB_HASH,
+                               flags,
+                               0664);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                               "Error opening subkey database: %s (%s)",
+                               "subkeydb",
+                               db_strerror(ret));
+               }
+       }
+
        if (txn != NULL) {
                db4_endtrans();
        }
@@ -599,7 +641,7 @@ static uint64_t db4_getfullkeyid(uint64_t keyid)
 }
 
 /**
- *     fetch_key - Given a keyid fetch the key from storage.
+ *     fetch_key_id - Given a keyid fetch the key from storage.
  *     @keyid: The keyid to fetch.
  *     @publickey: A pointer to a structure to return the key in.
  *     @intrans: If we're already in a transaction.
@@ -610,7 +652,8 @@ static uint64_t db4_getfullkeyid(uint64_t keyid)
  *     in and then parse_keys() to parse the packets into a publickey
  *     structure.
  */
-static int db4_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
+static int db4_fetch_key_id(uint64_t keyid,
+               struct openpgp_publickey **publickey,
                bool intrans)
 {
        struct openpgp_packet_list *packets = NULL;
@@ -641,7 +684,41 @@ static int db4_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
                        &key,
                        &data,
                        0); /* flags*/
-       
+
+       if (ret == DB_NOTFOUND) {
+               /* If we didn't find the key ID see if it's a subkey ID */
+               memset(&key, 0, sizeof(key));
+               memset(&data, 0, sizeof(data));
+               data.size = 0;
+               data.data = NULL;
+               key.size = sizeof(keyid);
+               key.data = &keyid;
+
+               ret = subkeydb->get(subkeydb,
+                       txn,
+                       &key,
+                       &data,
+                       0); /* flags*/
+
+               if (ret == 0) {
+                       /* We got a subkey match; retrieve the actual key */
+                       keyid = *(uint64_t *) data.data;
+
+                       memset(&key, 0, sizeof(key));
+                       memset(&data, 0, sizeof(data));
+                       data.size = 0;
+                       data.data = NULL;
+                       key.size = sizeof(keyid);
+                       key.data = &keyid;
+
+                       ret = keydb(keyid)->get(keydb(keyid),
+                               txn,
+                               &key,
+                               &data,
+                               0); /* flags*/
+               }
+       }
+
        if (ret == 0) {
                fetchbuf.buffer = data.data;
                fetchbuf.offset = 0;
@@ -764,7 +841,7 @@ static int db4_fetch_key_text(const char *search,
        
        db4_starttrans();
        for (i = 0; i < keylist.count; i++) {
-               numkeys += db4_fetch_key(keylist.keys[i],
+               numkeys += db4_fetch_key_id(keylist.keys[i],
                        publickey,
                        true);
        }
@@ -813,7 +890,7 @@ static int db4_fetch_key_skshash(const struct skshash *hash,
        ret = cursor->c_close(cursor);
        cursor = NULL;
 
-       return db4_fetch_key(keyid, publickey, false);
+       return db4_fetch_key_id(keyid, publickey, false);
 }
 
 /**
@@ -845,7 +922,7 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
                db4_starttrans();
        }
 
-       db4_fetch_key(keyid, &publickey, true);
+       db4_fetch_key_id(keyid, &publickey, true);
 
        /*
         * Walk through the uids removing the words from the worddb.
@@ -887,7 +964,7 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
                        worddb_data[ 8] = (keyid >> 24) & 0xFF;
                        worddb_data[ 9] = (keyid >> 16) & 0xFF;
                        worddb_data[10] = (keyid >>  8) & 0xFF;
-                       worddb_data[11] = keyid & 0xFF; 
+                       worddb_data[11] = keyid & 0xFF;
 
                        ret = cursor->c_get(cursor,
                                &key,
@@ -896,17 +973,14 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
 
                        if (ret == 0) {
                                ret = cursor->c_del(cursor, 0);
-                               if (ret != 0) {
-                                       logthing(LOGTHING_ERROR,
-                                               "Problem deleting word: %s",
-                                               db_strerror(ret));
-                               }
                        }
 
                        if (ret != 0) {
                                logthing(LOGTHING_ERROR,
-                                       "Problem deleting word: %s",
-                                       db_strerror(ret));
+                                       "Problem deleting word: %s "
+                                       "(0x%016" PRIX64 ")",
+                                       db_strerror(ret),
+                                       keyid);
                                if (ret == DB_LOCK_DEADLOCK) {
                                        deadlock = true;
                                }
@@ -915,6 +989,42 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
                ret = cursor->c_close(cursor);
                cursor = NULL;
 
+               ret = skshashdb->cursor(skshashdb,
+                       txn,
+                       &cursor,
+                       0);   /* flags */
+               get_skshash(publickey, &hash);
+
+               memset(&key, 0, sizeof(key));
+               memset(&data, 0, sizeof(data));
+               key.data = hash.hash;
+               key.size = sizeof(hash.hash);
+               data.data = &keyid;
+               data.size = sizeof(keyid);
+
+               ret = cursor->c_get(cursor,
+                       &key,
+                       &data,
+                       DB_GET_BOTH);
+
+               if (ret == 0) {
+                       ret = cursor->c_del(cursor, 0);
+               }
+
+               if (ret != 0) {
+                       logthing(LOGTHING_ERROR,
+                               "Problem deleting skshash: %s "
+                               "(0x%016" PRIX64 ")",
+                               db_strerror(ret),
+                               keyid);
+                       if (ret == DB_LOCK_DEADLOCK) {
+                               deadlock = true;
+                       }
+               }
+
+               ret = cursor->c_close(cursor);
+               cursor = NULL;
+
                /*
                 * Free our UID and word lists.
                 */
@@ -951,17 +1061,14 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
 
                if (ret == 0) {
                        ret = cursor->c_del(cursor, 0);
-                       if (ret != 0) {
-                               logthing(LOGTHING_ERROR,
-                                       "Problem deleting short keyid: %s",
-                                       db_strerror(ret));
-                       }
                }
 
                if (ret != 0) {
                        logthing(LOGTHING_ERROR,
-                               "Problem deleting short keyid: %s",
-                               db_strerror(ret));
+                               "Problem deleting short keyid: %s "
+                               "(0x%016" PRIX64 ")",
+                               db_strerror(ret),
+                               keyid);
                        if (ret == DB_LOCK_DEADLOCK) {
                                deadlock = true;
                        }
@@ -970,6 +1077,21 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
                subkeyids = keysubkeys(publickey);
                i = 0;
                while (subkeyids != NULL && subkeyids[i] != 0) {
+                       memset(&key, 0, sizeof(key));
+                       key.data = &subkeyids[i];
+                       key.size = sizeof(subkeyids[i]);
+                       subkeydb->del(subkeydb, txn, &key, 0);
+                       if (ret != 0) {
+                               logthing(LOGTHING_ERROR,
+                                       "Problem deleting subkey id: %s "
+                                       "(0x%016" PRIX64 ")",
+                                       db_strerror(ret),
+                                       keyid);
+                               if (ret == DB_LOCK_DEADLOCK) {
+                                       deadlock = true;
+                               }
+                       }
+
                        shortkeyid = subkeyids[i++] & 0xFFFFFFFF;
 
                        memset(&key, 0, sizeof(key));
@@ -986,18 +1108,14 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
 
                        if (ret == 0) {
                                ret = cursor->c_del(cursor, 0);
-                               if (ret != 0) {
-                                       logthing(LOGTHING_ERROR,
-                                               "Problem deleting short"
-                                               " keyid: %s",
-                                               db_strerror(ret));
-                               }
                        }
 
                        if (ret != 0) {
                                logthing(LOGTHING_ERROR,
-                                       "Problem deleting short keyid: %s",
-                                       db_strerror(ret));
+                                       "Problem deleting short keyid: %s "
+                                       "(0x%016" PRIX64 ")",
+                                       db_strerror(ret),
+                                       keyid);
                                if (ret == DB_LOCK_DEADLOCK) {
                                        deadlock = true;
                                }
@@ -1012,38 +1130,6 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
 
        }
 
-       if (!deadlock) {
-               get_skshash(publickey, &hash);
-
-               memset(&key, 0, sizeof(key));
-               memset(&data, 0, sizeof(data));
-               key.data = hash.hash;
-               key.size = sizeof(hash.hash);
-               data.data = &keyid;
-               data.size = sizeof(keyid);
-
-               ret = cursor->c_get(cursor,
-                       &key,
-                       &data,
-                       DB_GET_BOTH);
-
-               if (ret == 0) {
-                       ret = cursor->c_del(cursor, 0);
-               }
-
-               if (ret != 0) {
-                       logthing(LOGTHING_ERROR,
-                               "Problem deleting skshash: %s",
-                               db_strerror(ret));
-                       if (ret == DB_LOCK_DEADLOCK) {
-                               deadlock = true;
-                       }
-               }
-
-               ret = cursor->c_close(cursor);
-               cursor = NULL;
-       }
-
        if (!deadlock) {
                key.data = &keyid;
                key.size = sizeof(keyid);
@@ -1095,7 +1181,10 @@ static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
        bool       deadlock = false;
        struct skshash hash;
 
-       keyid = get_keyid(publickey);
+       if (get_keyid(publickey, &keyid) != ONAK_E_OK) {
+               logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
+               return 0;
+       }
 
        if (!intrans) {
                db4_starttrans();
@@ -1258,6 +1347,29 @@ static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
                subkeyids = keysubkeys(publickey);
                i = 0;
                while (subkeyids != NULL && subkeyids[i] != 0) {
+                       /* Store the subkey ID -> main key ID mapping */
+                       memset(&key, 0, sizeof(key));
+                       memset(&data, 0, sizeof(data));
+                       key.data = &subkeyids[i];
+                       key.size = sizeof(subkeyids[i]);
+                       data.data = &keyid;
+                       data.size = sizeof(keyid);
+
+                       ret = subkeydb->put(subkeydb,
+                               txn,
+                               &key,
+                               &data,
+                               0);
+                       if (ret != 0) {
+                               logthing(LOGTHING_ERROR,
+                                       "Problem storing subkey keyid: %s",
+                                       db_strerror(ret));
+                               if (ret == DB_LOCK_DEADLOCK) {
+                                       deadlock = true;
+                               }
+                       }
+
+                       /* Store the short subkey ID -> main key ID mapping */
                        shortkeyid = subkeyids[i++] & 0xFFFFFFFF;
 
                        memset(&key, 0, sizeof(key));
@@ -1390,6 +1502,7 @@ static int db4_iterate_keys(void (*iterfunc)(void *ctx,
 #define NEED_GETKEYSIGS 1
 #define NEED_KEYID2UID 1
 #define NEED_UPDATEKEYS 1
+#define NEED_GET_FP 1
 #include "keydb.c"
 
 struct dbfuncs keydb_db4_funcs = {
@@ -1397,7 +1510,8 @@ struct dbfuncs keydb_db4_funcs = {
        .cleanupdb              = db4_cleanupdb,
        .starttrans             = db4_starttrans,
        .endtrans               = db4_endtrans,
-       .fetch_key              = db4_fetch_key,
+       .fetch_key_id           = db4_fetch_key_id,
+       .fetch_key_fp           = generic_fetch_key_fp,
        .fetch_key_text         = db4_fetch_key_text,
        .fetch_key_skshash      = db4_fetch_key_skshash,
        .store_key              = db4_store_key,