X-Git-Url: https://git.sommitrealweird.co.uk/onak.git/blobdiff_plain/61b6fcfd1226b6540c151c902f8b688545494736..33cfd5887ea8d05241b5b4749abbf7fdfadb51fe:/keydb_db4.c diff --git a/keydb_db4.c b/keydb_db4.c index 8990758..04d727c 100644 --- a/keydb_db4.c +++ b/keydb_db4.c @@ -2,6 +2,19 @@ * keydb_db4.c - Routines to store and fetch keys in a DB4 database. * * Copyright 2002-2008 Jonathan McDowell + * + * 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 @@ -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); @@ -277,6 +311,7 @@ static void db4_initdb(bool readonly) int i = 0; u_int32_t flags = 0; struct stat statbuf; + int maxlocks; snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir, DB4_UPGRADE_FILE); @@ -329,6 +364,17 @@ static void db4_initdb(bool readonly) } } + /* + * Up the number of locks we're allowed at once. We base this on + * the maximum number of keys we're going to return. + */ + maxlocks = config.maxkeys * 16; + if (maxlocks < 1000) { + maxlocks = 1000; + } + dbenv->set_lk_max_locks(dbenv, maxlocks); + dbenv->set_lk_max_objects(dbenv, maxlocks); + /* * Enable deadlock detection so that we don't block indefinitely on * anything. What we really want is simple 2 state locks, but I'm not @@ -468,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(); } @@ -690,6 +757,10 @@ static int db4_fetch_key_text(const char *search, } llfree(wordlist, NULL); wordlist = NULL; + + if (keylist.count > config.maxkeys) { + keylist.count = config.maxkeys; + } db4_starttrans(); for (i = 0; i < keylist.count; i++) { @@ -706,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. @@ -729,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(); @@ -896,6 +1007,38 @@ static int db4_delete_key(uint64_t keyid, bool intrans) free(subkeyids); subkeyids = NULL; } + ret = cursor->c_close(cursor); + cursor = NULL; + + } + + 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; @@ -950,6 +1093,7 @@ 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); @@ -1143,6 +1287,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(); } @@ -1231,6 +1399,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,