Update Debian Vcs-* fields to point to git repository
[onak.git] / keydb_db4.c
index 6fbf9da5392798159cac6e13682ea087f154ed16..d582eaaf8334c4618c8962d0c5bcd40271468cde 100644 (file)
@@ -2,6 +2,19 @@
  * keydb_db4.c - Routines to store and fetch keys in a DB4 database.
  *
  * Copyright 2002-2008 Jonathan McDowell <noodles@earth.li>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
 #include <sys/types.h>
@@ -56,6 +69,11 @@ static DB *worddb = NULL;
  */
 static DB *id32db = NULL;
 
+/**
+ *     skshashdb - our connection to the SKS hash database.
+ */
+static DB *skshashdb = NULL;
+
 /**
  *     txn - our current transaction id.
  */
@@ -157,6 +175,10 @@ static void db4_cleanupdb(void)
 
        if (dbenv != NULL) {
                dbenv->txn_checkpoint(dbenv, 0, 0, 0);
+               if (skshashdb != NULL) {
+                       skshashdb->close(skshashdb, 0);
+                       skshashdb = NULL;
+               }
                if (id32db != NULL) {
                        id32db->close(id32db, 0);
                        id32db = NULL;
@@ -255,6 +277,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/skshashdb", 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);
@@ -275,7 +309,7 @@ static void db4_initdb(bool readonly)
        FILE      *numdb = NULL;
        int        ret = 0;
        int        i = 0;
-       u_int32_t  flags = 0;
+       uint32_t   flags = 0;
        struct stat statbuf;
        int        maxlocks;
 
@@ -480,6 +514,27 @@ static void db4_initdb(bool readonly)
                }
        }
 
+       if (ret == 0) {
+               ret = db_create(&skshashdb, dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL, "db_create: %s",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = skshashdb->open(skshashdb, txn, "skshashdb",
+                               "skshashdb", DB_HASH,
+                               flags,
+                               0664);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                               "Error opening skshash database: %s (%s)",
+                               "skshashdb",
+                               db_strerror(ret));
+               }
+       }
+
        if (txn != NULL) {
                db4_endtrans();
        }
@@ -722,6 +777,45 @@ static int db4_fetch_key_text(const char *search,
        return (numkeys);
 }
 
+static int db4_fetch_key_skshash(const struct skshash *hash,
+               struct openpgp_publickey **publickey)
+{
+       DBT       key, data;
+       DBC      *cursor = NULL;
+       uint64_t  keyid = 0;
+       int       ret = 0;
+
+       ret = skshashdb->cursor(skshashdb,
+                       txn,
+                       &cursor,
+                       0);   /* flags */
+
+       memset(&key, 0, sizeof(key));
+       memset(&data, 0, sizeof(data));
+       key.data = (void *) hash->hash;
+       key.size = sizeof(hash->hash);
+       data.flags = DB_DBT_MALLOC;
+
+       ret = cursor->c_get(cursor,
+               &key,
+               &data,
+               DB_SET);
+
+       if (ret == 0) {
+               keyid = *(uint64_t *) data.data;
+
+               if (data.data != NULL) {
+                       free(data.data);
+                       data.data = NULL;
+               }
+       }
+
+       ret = cursor->c_close(cursor);
+       cursor = NULL;
+
+       return db4_fetch_key(keyid, publickey, false);
+}
+
 /**
  *     delete_key - Given a keyid delete the key from storage.
  *     @keyid: The keyid to delete.
@@ -745,6 +839,7 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
        struct ll *wordlist = NULL;
        struct ll *curword  = NULL;
        bool deadlock = false;
+       struct skshash hash;
 
        if (!intrans) {
                db4_starttrans();
@@ -792,7 +887,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,
@@ -801,17 +896,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;
                                }
@@ -820,6 +912,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.
                 */
@@ -856,17 +984,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;
                        }
@@ -891,18 +1016,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;
                                }
@@ -912,9 +1033,9 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
                        free(subkeyids);
                        subkeyids = NULL;
                }
-
                ret = cursor->c_close(cursor);
                cursor = NULL;
+
        }
 
        if (!deadlock) {
@@ -966,8 +1087,9 @@ static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
        struct ll *wordlist = NULL;
        struct ll *curword  = NULL;
        bool       deadlock = false;
+       struct skshash hash;
 
-       keyid = get_keyid(publickey);
+       get_keyid(publickey, &keyid);
 
        if (!intrans) {
                db4_starttrans();
@@ -1159,6 +1281,30 @@ static int db4_store_key(struct openpgp_publickey *publickey, 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 = skshashdb->put(skshashdb,
+                       txn,
+                       &key,
+                       &data,
+                       0);
+               if (ret != 0) {
+                       logthing(LOGTHING_ERROR,
+                               "Problem storing SKS hash: %s",
+                               db_strerror(ret));
+                       if (ret == DB_LOCK_DEADLOCK) {
+                               deadlock = true;
+                       }
+               }
+       }
+
        if (!intrans) {
                db4_endtrans();
        }
@@ -1247,6 +1393,7 @@ struct dbfuncs keydb_db4_funcs = {
        .endtrans               = db4_endtrans,
        .fetch_key              = db4_fetch_key,
        .fetch_key_text         = db4_fetch_key_text,
+       .fetch_key_skshash      = db4_fetch_key_skshash,
        .store_key              = db4_store_key,
        .update_keys            = generic_update_keys,
        .delete_key             = db4_delete_key,