From: Jonathan McDowell Date: Mon, 6 Jun 2016 20:54:42 +0000 (+0100) Subject: Properly isolate database backend configuration X-Git-Tag: onak-0.5.0~36 X-Git-Url: http://the.earth.li/gitweb/?p=onak.git;a=commitdiff_plain;h=2458360e75aa46091f60c16e041c07bffe2edefb Properly isolate database backend configuration While database backends have had private context for some time they've all been using the same configuration details from the global config structure. Create a new DB specific config structure and initialise a single instance from the config file. Also modify the DB backend initialise functions to take this config structure as a parameter. This will allow in the future for multiple different backends (whether the same type or different) to be included at the same time. --- diff --git a/add.c b/add.c index 4e03719..877af11 100644 --- a/add.c +++ b/add.c @@ -89,7 +89,7 @@ int main(int argc, char *argv[]) fclose(stderr); } catchsignals(); - dbctx = config.dbinit(false); + dbctx = config.dbinit(config.backend, false); count = cleankeys(keys); logthing(LOGTHING_INFO, "%d keys cleaned.", diff --git a/gpgwww.c b/gpgwww.c index 6615887..d126168 100644 --- a/gpgwww.c +++ b/gpgwww.c @@ -183,7 +183,7 @@ int main(int argc, char *argv[]) readconfig(NULL); initlogthing("gpgwww", config.logfile); catchsignals(); - dbctx = config.dbinit(true); + dbctx = config.dbinit(config.backend, true); inithash(); logthing(LOGTHING_NOTICE, "Looking for path from 0x%016" PRIX64 " to 0x%016" diff --git a/hashquery.c b/hashquery.c index 965eaf9..44434c1 100644 --- a/hashquery.c +++ b/hashquery.c @@ -90,7 +90,7 @@ int main(int argc, char *argv[]) } catchsignals(); - dbctx = config.dbinit(false); + dbctx = config.dbinit(config.backend, false); if (dbctx->fetch_key_skshash == NULL) { dbctx->cleanupdb(dbctx); diff --git a/keyd.c b/keyd.c index b73ff28..7fb7eab 100644 --- a/keyd.c +++ b/keyd.c @@ -662,7 +662,7 @@ int main(int argc, char *argv[]) maxfd = fd; memset(clients, -1, sizeof (clients)); - dbctx = config.dbinit(false); + dbctx = config.dbinit(config.backend, false); logthing(LOGTHING_NOTICE, "Accepting connections."); while (!cleanup() && select(maxfd + 1, &rfds, NULL, NULL, NULL) != -1) { diff --git a/keydb.h b/keydb.h index 6c1bcf5..d7515c8 100644 --- a/keydb.h +++ b/keydb.h @@ -207,6 +207,11 @@ struct onak_dbctx { void (*iterfunc)(void *ctx, struct openpgp_publickey *key), void *ctx); +/** + * @brief Configuration file information for this backend instance + */ + struct onak_db_config *config; + /** * @brief Private backend context information. */ diff --git a/keydb_db4.c b/keydb_db4.c index b2d34c5..e09d653 100644 --- a/keydb_db4.c +++ b/keydb_db4.c @@ -161,8 +161,9 @@ static void db4_endtrans(struct onak_dbctx *dbctx) * we're running with a newer version of db4 than the database was * created with. */ -static int db4_upgradedb(struct onak_db4_dbctx *privctx) +static int db4_upgradedb(struct onak_dbctx *dbctx) { + struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv; DB *curdb = NULL; int ret; int i; @@ -171,7 +172,7 @@ static int db4_upgradedb(struct onak_db4_dbctx *privctx) struct stat statbuf; ssize_t written; - snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir, + snprintf(buf, sizeof(buf) - 1, "%s/%s", dbctx->config->location, DB4_UPGRADE_FILE); lockfile_fd = open(buf, O_RDWR | O_CREAT | O_EXCL, 0600); if (lockfile_fd < 0) { @@ -190,7 +191,7 @@ static int db4_upgradedb(struct onak_db4_dbctx *privctx) if (written != strlen(buf)) { logthing(LOGTHING_CRITICAL, "Couldn't write PID to lockfile: " "%s", strerror(errno)); - snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir, + snprintf(buf, sizeof(buf) - 1, "%s/%s", dbctx->config->location, DB4_UPGRADE_FILE); unlink(buf); return -1; @@ -200,14 +201,14 @@ static int db4_upgradedb(struct onak_db4_dbctx *privctx) ret = db_env_create(&privctx->dbenv, 0); if (ret == 0) { privctx->dbenv->set_errcall(privctx->dbenv, &db4_errfunc); - privctx->dbenv->remove(privctx->dbenv, config.db_dir, 0); + privctx->dbenv->remove(privctx->dbenv, dbctx->config->location, 0); privctx->dbenv = NULL; } for (i = 0; i < privctx->numdbs; i++) { ret = db_create(&curdb, NULL, 0); if (ret == 0) { snprintf(buf, sizeof(buf) - 1, "%s/keydb.%d.db", - config.db_dir, i); + dbctx->config->location, i); logthing(LOGTHING_DEBUG, "Upgrading %s", buf); curdb->upgrade(curdb, buf, 0); curdb->close(curdb, 0); @@ -220,7 +221,7 @@ static int db4_upgradedb(struct onak_db4_dbctx *privctx) ret = db_create(&curdb, NULL, 0); if (ret == 0) { - snprintf(buf, sizeof(buf) - 1, "%s/worddb", config.db_dir); + snprintf(buf, sizeof(buf) - 1, "%s/worddb", dbctx->config->location); logthing(LOGTHING_DEBUG, "Upgrading %s", buf); curdb->upgrade(curdb, buf, 0); curdb->close(curdb, 0); @@ -232,7 +233,7 @@ static int db4_upgradedb(struct onak_db4_dbctx *privctx) ret = db_create(&curdb, NULL, 0); if (ret == 0) { - snprintf(buf, sizeof(buf) - 1, "%s/id32db", config.db_dir); + snprintf(buf, sizeof(buf) - 1, "%s/id32db", dbctx->config->location); logthing(LOGTHING_DEBUG, "Upgrading %s", buf); curdb->upgrade(curdb, buf, 0); curdb->close(curdb, 0); @@ -244,7 +245,7 @@ static int db4_upgradedb(struct onak_db4_dbctx *privctx) ret = db_create(&curdb, NULL, 0); if (ret == 0) { - snprintf(buf, sizeof(buf) - 1, "%s/id64db", config.db_dir); + snprintf(buf, sizeof(buf) - 1, "%s/id64db", dbctx->config->location); logthing(LOGTHING_DEBUG, "Upgrading %s", buf); curdb->upgrade(curdb, buf, 0); curdb->close(curdb, 0); @@ -256,7 +257,7 @@ static int db4_upgradedb(struct onak_db4_dbctx *privctx) ret = db_create(&curdb, NULL, 0); if (ret == 0) { - snprintf(buf, sizeof(buf) - 1, "%s/skshashdb", config.db_dir); + snprintf(buf, sizeof(buf) - 1, "%s/skshashdb", dbctx->config->location); logthing(LOGTHING_DEBUG, "Upgrading %s", buf); curdb->upgrade(curdb, buf, 0); curdb->close(curdb, 0); @@ -268,7 +269,7 @@ static int db4_upgradedb(struct onak_db4_dbctx *privctx) ret = db_create(&curdb, NULL, 0); if (ret == 0) { - snprintf(buf, sizeof(buf) - 1, "%s/subkeydb", config.db_dir); + snprintf(buf, sizeof(buf) - 1, "%s/subkeydb", dbctx->config->location); logthing(LOGTHING_DEBUG, "Upgrading %s", buf); curdb->upgrade(curdb, buf, 0); curdb->close(curdb, 0); @@ -278,7 +279,7 @@ static int db4_upgradedb(struct onak_db4_dbctx *privctx) db_strerror(ret)); } - snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir, + snprintf(buf, sizeof(buf) - 1, "%s/%s", dbctx->config->location, DB4_UPGRADE_FILE); unlink(buf); @@ -1626,7 +1627,7 @@ static void db4_cleanupdb(struct onak_dbctx *dbctx) * this file are called in order to allow the DB to be initialized ready * for access. */ -struct onak_dbctx *keydb_db4_init(bool readonly) +struct onak_dbctx *keydb_db4_init(struct onak_db_config *dbcfg, bool readonly) { char buf[1024]; FILE *numdb = NULL; @@ -1642,6 +1643,7 @@ struct onak_dbctx *keydb_db4_init(bool readonly) if (dbctx == NULL) { return NULL; } + dbctx->config = dbcfg; dbctx->priv = privctx = calloc(1, sizeof(*privctx)); if (privctx == NULL) { free(dbctx); @@ -1651,7 +1653,7 @@ struct onak_dbctx *keydb_db4_init(bool readonly) /* Default to 16 key data DBs */ privctx->numdbs = 16; - snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir, + snprintf(buf, sizeof(buf) - 1, "%s/%s", dbcfg->location, DB4_UPGRADE_FILE); ret = stat(buf, &statbuf); while ((ret == 0) || (errno != ENOENT)) { @@ -1666,7 +1668,7 @@ struct onak_dbctx *keydb_db4_init(bool readonly) } ret = 0; - snprintf(buf, sizeof(buf) - 1, "%s/num_keydb", config.db_dir); + snprintf(buf, sizeof(buf) - 1, "%s/num_keydb", dbcfg->location); numdb = fopen(buf, "r"); if (numdb != NULL) { if (fgets(buf, sizeof(buf), numdb) != NULL) { @@ -1730,7 +1732,7 @@ struct onak_dbctx *keydb_db4_init(bool readonly) } if (ret == 0) { - ret = privctx->dbenv->open(privctx->dbenv, config.db_dir, + ret = privctx->dbenv->open(privctx->dbenv, dbcfg->location, DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN | DB_CREATE, @@ -1739,7 +1741,7 @@ struct onak_dbctx *keydb_db4_init(bool readonly) if (ret == DB_VERSION_MISMATCH) { privctx->dbenv->close(privctx->dbenv, 0); privctx->dbenv = NULL; - ret = db4_upgradedb(privctx); + ret = db4_upgradedb(dbctx); if (ret == 0) { ret = db_env_create(&privctx->dbenv, 0); } @@ -1749,7 +1751,7 @@ struct onak_dbctx *keydb_db4_init(bool readonly) privctx->dbenv->set_lk_detect(privctx->dbenv, DB_LOCK_DEFAULT); ret = privctx->dbenv->open(privctx->dbenv, - config.db_dir, + dbcfg->location, DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN | DB_CREATE | DB_RECOVER, @@ -1768,7 +1770,7 @@ struct onak_dbctx *keydb_db4_init(bool readonly) if (ret != 0) { logthing(LOGTHING_CRITICAL, "Error opening db environment: %s (%s)", - config.db_dir, + dbcfg->location, db_strerror(ret)); if (privctx->dbenv != NULL) { privctx->dbenv->close(privctx->dbenv, 0); diff --git a/keydb_dynamic.c b/keydb_dynamic.c index 1e7d6b2..040a045 100644 --- a/keydb_dynamic.c +++ b/keydb_dynamic.c @@ -206,12 +206,13 @@ static void dynamic_cleanupdb(struct onak_dbctx *dbctx) } } -struct onak_dbctx *keydb_dynamic_init(bool readonly) +struct onak_dbctx *keydb_dynamic_init(struct onak_db_config *dbcfg, + bool readonly) { struct onak_dbctx *dbctx; char *soname; char *initname; - struct onak_dbctx *(*backend_init)(bool); + struct onak_dbctx *(*backend_init)(struct onak_db_config *, bool); struct onak_dynamic_dbctx *privctx; dbctx = malloc(sizeof(struct onak_dbctx)); @@ -220,6 +221,7 @@ struct onak_dbctx *keydb_dynamic_init(bool readonly) return NULL; } + dbctx->config = dbcfg; dbctx->priv = privctx = malloc(sizeof(struct onak_dynamic_dbctx)); if (dbctx->priv == NULL) { free(dbctx); @@ -237,21 +239,21 @@ struct onak_dbctx *keydb_dynamic_init(bool readonly) } if (config.backends_dir == NULL) { - soname = malloc(strlen(config.db_backend) + soname = malloc(strlen(dbcfg->type) + strlen("./libkeydb_") + strlen(".so") + 1); - sprintf(soname, "./libkeydb_%s.so", config.db_backend); + sprintf(soname, "./libkeydb_%s.so", dbcfg->type); } else { - soname = malloc(strlen(config.db_backend) + soname = malloc(strlen(dbcfg->type) + strlen("/libkeydb_") + strlen(".so") + strlen(config.backends_dir) + 1); sprintf(soname, "%s/libkeydb_%s.so", config.backends_dir, - config.db_backend); + dbcfg->type); } logthing(LOGTHING_INFO, "Loading dynamic backend: %s", soname); @@ -270,7 +272,7 @@ struct onak_dbctx *keydb_dynamic_init(bool readonly) + strlen("keydb_") + strlen("_init") + 1); - sprintf(initname, "keydb_%s_init", config.db_backend); + sprintf(initname, "keydb_%s_init", dbcfg->type); *(void **) (&backend_init) = dlsym(privctx->backend_handle, initname); free(initname); @@ -286,7 +288,7 @@ struct onak_dbctx *keydb_dynamic_init(bool readonly) free(soname); soname = NULL; - privctx->loadeddbctx = backend_init(readonly); + privctx->loadeddbctx = backend_init(dbcfg, readonly); if (privctx->loadeddbctx != NULL) { dbctx->cleanupdb = dynamic_cleanupdb; diff --git a/keydb_file.c b/keydb_file.c index e0ed610..69c2b99 100644 --- a/keydb_file.c +++ b/keydb_file.c @@ -270,7 +270,7 @@ static void file_cleanupdb(struct onak_dbctx *dbctx) * * This is just a no-op for flat file access. */ -struct onak_dbctx *keydb_file_init(bool readonly) +struct onak_dbctx *keydb_file_init(struct onak_db_config *dbcfg, bool readonly) { struct onak_dbctx *dbctx; @@ -279,7 +279,8 @@ struct onak_dbctx *keydb_file_init(bool readonly) return NULL; } - dbctx->priv = strdup(config.db_dir); + dbctx->config = dbcfg; + dbctx->priv = strdup(dbcfg->location); dbctx->cleanupdb = file_cleanupdb; dbctx->starttrans = file_starttrans; diff --git a/keydb_fs.c b/keydb_fs.c index 2779297..9a7b2ec 100644 --- a/keydb_fs.c +++ b/keydb_fs.c @@ -72,41 +72,43 @@ static uint32_t calchash(uint8_t * ptr) } -static void keypath(char *buffer, size_t length, uint64_t _keyid) +static void keypath(char *buffer, size_t length, uint64_t _keyid, + char *basepath) { uint64_t keyid = _keyid << 32; snprintf(buffer, length, "%s/key/%02X/%02X/%08X/%016" PRIX64, - config.db_dir, (uint8_t) ((keyid >> 56) & 0xFF), + basepath, (uint8_t) ((keyid >> 56) & 0xFF), (uint8_t) ((keyid >> 48) & 0xFF), (uint32_t) (keyid >> 32), _keyid); } -static void keydir(char *buffer, size_t length, uint64_t _keyid) +static void keydir(char *buffer, size_t length, uint64_t _keyid, + char *basepath) { uint64_t keyid = _keyid << 32; - snprintf(buffer, length, "%s/key/%02X/%02X/%08X", config.db_dir, + snprintf(buffer, length, "%s/key/%02X/%02X/%08X", basepath, (uint8_t) ((keyid >> 56) & 0xFF), (uint8_t) ((keyid >> 48) & 0xFF), (uint32_t) (keyid >> 32)); } -static void prove_path_to(uint64_t keyid, char *what) +static void prove_path_to(uint64_t keyid, char *what, char *basepath) { static char buffer[PATH_MAX]; - snprintf(buffer, sizeof(buffer), "%s/%s", config.db_dir, what); + snprintf(buffer, sizeof(buffer), "%s/%s", basepath, what); mkdir(buffer, 0777); - snprintf(buffer, sizeof(buffer), "%s/%s/%02X", config.db_dir, what, + snprintf(buffer, sizeof(buffer), "%s/%s/%02X", basepath, what, (uint8_t) ((keyid >> 24) & 0xFF)); mkdir(buffer, 0777); - snprintf(buffer, sizeof(buffer), "%s/%s/%02X/%02X", config.db_dir, + snprintf(buffer, sizeof(buffer), "%s/%s/%02X/%02X", basepath, what, (uint8_t) ((keyid >> 24) & 0xFF), (uint8_t) ((keyid >> 16) & 0xFF)); mkdir(buffer, 0777); - snprintf(buffer, sizeof(buffer), "%s/%s/%02X/%02X/%08X", config.db_dir, + snprintf(buffer, sizeof(buffer), "%s/%s/%02X/%02X/%08X", basepath, what, (uint8_t) ((keyid >> 24) & 0xFF), (uint8_t) ((keyid >> 16) & 0xFF), (uint32_t) (keyid)); @@ -114,45 +116,48 @@ static void prove_path_to(uint64_t keyid, char *what) } static void wordpath(char *buffer, size_t length, char *word, uint32_t hash, - uint64_t keyid) + uint64_t keyid, char *basepath) { snprintf(buffer, length, "%s/words/%02X/%02X/%08X/%s/%016" PRIX64, - config.db_dir, (uint8_t) ((hash >> 24) & 0xFF), + basepath, (uint8_t) ((hash >> 24) & 0xFF), (uint8_t) ((hash >> 16) & 0xFF), hash, word, keyid); } -static void worddir(char *buffer, size_t length, char *word, uint32_t hash) +static void worddir(char *buffer, size_t length, char *word, uint32_t hash, + char *basepath) { - snprintf(buffer, length, "%s/words/%02X/%02X/%08X/%s", config.db_dir, + snprintf(buffer, length, "%s/words/%02X/%02X/%08X/%s", basepath, (uint8_t) ((hash >> 24) & 0xFF), (uint8_t) ((hash >> 16) & 0xFF), hash, word); } -static void subkeypath(char *buffer, size_t length, uint64_t subkey) +static void subkeypath(char *buffer, size_t length, uint64_t subkey, + char *basepath) { snprintf(buffer, length, "%s/subkeys/%02X/%02X/%08X/%016" PRIX64, - config.db_dir, + basepath, (uint8_t) ((subkey >> 24) & 0xFF), (uint8_t) ((subkey >> 16) & 0xFF), (uint32_t) (subkey & 0xFFFFFFFF), subkey); } -static void subkeydir(char *buffer, size_t length, uint64_t subkey) +static void subkeydir(char *buffer, size_t length, uint64_t subkey, + char *basepath) { snprintf(buffer, length, "%s/subkeys/%02X/%02X/%08X", - config.db_dir, + basepath, (uint8_t) ((subkey >> 24) & 0xFF), (uint8_t) ((subkey >> 16) & 0xFF), (uint32_t) (subkey & 0xFFFFFFFF)); } static void skshashpath(char *buffer, size_t length, - const struct skshash *hash) + const struct skshash *hash, char *basepath) { snprintf(buffer, length, "%s/skshash/%02X/%02X/%02X%02X%02X%02X/" "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", - config.db_dir, + basepath, hash->hash[0], hash->hash[1], hash->hash[0], hash->hash[1], hash->hash[2], hash->hash[3], hash->hash[4], hash->hash[5], hash->hash[6], hash->hash[7], @@ -207,7 +212,7 @@ static uint64_t fs_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid) struct dirent *de = NULL; uint64_t ret = 0; - keydir(buffer, sizeof(buffer), keyid); + keydir(buffer, sizeof(buffer), keyid, dbctx->config->location); d = opendir(buffer); if (d) { @@ -221,7 +226,8 @@ static uint64_t fs_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid) } if (ret == 0) { - subkeydir(buffer, sizeof(buffer), keyid); + subkeydir(buffer, sizeof(buffer), keyid, + dbctx->config->location); d = opendir(buffer); if (d) { @@ -259,10 +265,11 @@ static int fs_fetch_key_id(struct onak_dbctx *dbctx, if ((keyid >> 32) == 0) keyid = fs_getfullkeyid(dbctx, keyid); - keypath(buffer, sizeof(buffer), keyid); + keypath(buffer, sizeof(buffer), keyid, dbctx->config->location); fd = open(buffer, O_RDONLY); if (fd == -1 && errno == ENOENT) { - subkeypath(buffer, sizeof(buffer), keyid); + subkeypath(buffer, sizeof(buffer), keyid, + dbctx->config->location); fd = open(buffer, O_RDONLY); } @@ -312,8 +319,8 @@ static int fs_store_key(struct onak_dbctx *dbctx, if (!intrans) fs_starttrans(dbctx); - prove_path_to(keyid, "key"); - keypath(buffer, sizeof(buffer), keyid); + prove_path_to(keyid, "key", dbctx->config->location); + keypath(buffer, sizeof(buffer), keyid, dbctx->config->location); if ((fd = open(buffer, O_WRONLY | (update ? O_TRUNC : O_CREAT), @@ -334,12 +341,13 @@ static int fs_store_key(struct onak_dbctx *dbctx, wl = wordlist = makewordlistfromkey(wordlist, publickey); while (wl) { uint32_t hash = calchash((uint8_t *) (wl->object)); - prove_path_to(hash, "words"); + prove_path_to(hash, "words", dbctx->config->location); - worddir(wbuffer, sizeof(wbuffer), wl->object, hash); + worddir(wbuffer, sizeof(wbuffer), wl->object, hash, + dbctx->config->location); mkdir(wbuffer, 0777); wordpath(wbuffer, sizeof(wbuffer), wl->object, hash, - keyid); + keyid, dbctx->config->location); link(buffer, wbuffer); wl = wl->next; @@ -351,11 +359,14 @@ static int fs_store_key(struct onak_dbctx *dbctx, while (subkeyids != NULL && subkeyids[i].length != 0) { keyid = fingerprint2keyid(&subkeyids[i]); - prove_path_to(keyid, "subkeys"); + prove_path_to(keyid, "subkeys", + dbctx->config->location); - subkeydir(wbuffer, sizeof(wbuffer), keyid); + subkeydir(wbuffer, sizeof(wbuffer), keyid, + dbctx->config->location); mkdir(wbuffer, 0777); - subkeypath(wbuffer, sizeof(wbuffer), keyid); + subkeypath(wbuffer, sizeof(wbuffer), keyid, + dbctx->config->location); link(buffer, wbuffer); i++; @@ -368,8 +379,9 @@ static int fs_store_key(struct onak_dbctx *dbctx, get_skshash(publickey, &hash); hashid = (hash.hash[0] << 24) + (hash.hash[1] << 16) + (hash.hash[2] << 8) + hash.hash[3]; - prove_path_to(hashid, "skshash"); - skshashpath(wbuffer, sizeof(wbuffer), &hash); + prove_path_to(hashid, "skshash", dbctx->config->location); + skshashpath(wbuffer, sizeof(wbuffer), &hash, + dbctx->config->location); link(buffer, wbuffer); } @@ -410,10 +422,10 @@ static int fs_delete_key(struct onak_dbctx *dbctx, uint64_t keyid, bool intrans) "Wordlist for key %016" PRIX64 " done", keyid); while (wl) { uint32_t hash = calchash((uint8_t *) (wl->object)); - prove_path_to(hash, "words"); + prove_path_to(hash, "words", dbctx->config->location); wordpath(buffer, sizeof(buffer), wl->object, hash, - keyid); + keyid, dbctx->config->location); unlink(buffer); wl = wl->next; @@ -423,9 +435,11 @@ static int fs_delete_key(struct onak_dbctx *dbctx, uint64_t keyid, bool intrans) i = 0; while (subkeyids != NULL && subkeyids[i].length != 0) { subkeyid = fingerprint2keyid(&subkeyids[i]); - prove_path_to(subkeyid, "subkeys"); + prove_path_to(subkeyid, "subkeys", + dbctx->config->location); - subkeypath(buffer, sizeof(buffer), subkeyid); + subkeypath(buffer, sizeof(buffer), subkeyid, + dbctx->config->location); unlink(buffer); i++; @@ -436,11 +450,12 @@ static int fs_delete_key(struct onak_dbctx *dbctx, uint64_t keyid, bool intrans) } get_skshash(pk, &hash); - skshashpath(buffer, sizeof(buffer), &hash); + skshashpath(buffer, sizeof(buffer), &hash, + dbctx->config->location); unlink(buffer); } - keypath(buffer, sizeof(buffer), keyid); + keypath(buffer, sizeof(buffer), keyid, dbctx->config->location); unlink(buffer); if (!intrans) @@ -448,7 +463,8 @@ static int fs_delete_key(struct onak_dbctx *dbctx, uint64_t keyid, bool intrans) return 1; } -static struct ll *internal_get_key_by_word(char *word, struct ll *mct) +static struct ll *internal_get_key_by_word(char *word, struct ll *mct, + char *basepath) { struct ll *keys = NULL; DIR *d = NULL; @@ -456,7 +472,7 @@ static struct ll *internal_get_key_by_word(char *word, struct ll *mct) uint32_t hash = calchash((uint8_t *) (word)); struct dirent *de; - worddir(buffer, sizeof(buffer), word, hash); + worddir(buffer, sizeof(buffer), word, hash, basepath); d = opendir(buffer); logthing(LOGTHING_DEBUG, "Scanning for word %s in dir %s", word, buffer); @@ -503,7 +519,8 @@ static int fs_fetch_key_text(struct onak_dbctx *dbctx, searchtext = strdup(search); wl = wordlist = makewordlist(wordlist, searchtext); - keylist = internal_get_key_by_word(wordlist->object, NULL); + keylist = internal_get_key_by_word(wordlist->object, NULL, + dbctx->config->location); if (!keylist) { llfree(wordlist, NULL); @@ -515,7 +532,8 @@ static int fs_fetch_key_text(struct onak_dbctx *dbctx, wl = wl->next; while (wl) { struct ll *nkl = - internal_get_key_by_word(wl->object, keylist); + internal_get_key_by_word(wl->object, keylist, + dbctx->config->location); if (!nkl) { llfree(wordlist, NULL); llfree(keylist, free); @@ -564,7 +582,7 @@ static int fs_fetch_key_skshash(struct onak_dbctx *dbctx, int ret = 0, fd; struct openpgp_packet_list *packets = NULL; - skshashpath(buffer, sizeof(buffer), hash); + skshashpath(buffer, sizeof(buffer), hash, dbctx->config->location); if ((fd = open(buffer, O_RDONLY)) != -1) { read_openpgp_stream(file_fetchchar, &fd, &packets, 0); parse_keys(packets, publickey); @@ -618,7 +636,7 @@ static void fs_cleanupdb(struct onak_dbctx *dbctx) /** * initdb - Initialize the key database. */ -struct onak_dbctx *keydb_fs_init(bool readonly) +struct onak_dbctx *keydb_fs_init(struct onak_db_config *dbcfg, bool readonly) { char buffer[PATH_MAX]; struct onak_dbctx *dbctx; @@ -628,6 +646,7 @@ struct onak_dbctx *keydb_fs_init(bool readonly) if (dbctx == NULL) { return NULL; } + dbctx->config = dbcfg; dbctx->priv = privctx = malloc(sizeof(*privctx)); if (privctx == NULL) { free(dbctx); @@ -636,19 +655,19 @@ struct onak_dbctx *keydb_fs_init(bool readonly) privctx->lockfile_readonly = readonly; - snprintf(buffer, sizeof(buffer), "%s/.lock", config.db_dir); + snprintf(buffer, sizeof(buffer), "%s/.lock", dbcfg->location); - if (access(config.db_dir, R_OK | W_OK | X_OK) == -1) { + if (access(dbcfg->location, R_OK | W_OK | X_OK) == -1) { if (errno != ENOENT) { logthing(LOGTHING_CRITICAL, "Unable to access keydb_fs root of '%s'. (%s)", - config.db_dir, strerror(errno)); + dbcfg->location, strerror(errno)); exit(1); /* Lacking rwx on the key dir */ } - mkdir(config.db_dir, 0777); + mkdir(dbcfg->location, 0777); privctx->lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600); } - if (chdir(config.db_dir) == -1) { + if (chdir(dbcfg->location) == -1) { /* Shouldn't happen after the above */ logthing(LOGTHING_CRITICAL, "Couldn't change to database directory: %s", diff --git a/keydb_hkp.c b/keydb_hkp.c index 0c6fd5a..6707ae6 100644 --- a/keydb_hkp.c +++ b/keydb_hkp.c @@ -34,6 +34,7 @@ #include "version.h" struct onak_hkp_dbctx { + struct onak_db_config *config; /* Our DB config info */ CURL *curl; char hkpbase[1024]; }; @@ -346,7 +347,7 @@ static void hkp_cleanupdb(struct onak_dbctx *dbctx) * * We initialize CURL here. */ -struct onak_dbctx *keydb_hkp_init(bool readonly) +struct onak_dbctx *keydb_hkp_init(struct onak_db_config *dbcfg, bool readonly) { struct onak_dbctx *dbctx; struct onak_hkp_dbctx *privctx; @@ -357,6 +358,7 @@ struct onak_dbctx *keydb_hkp_init(bool readonly) return NULL; } + dbctx->config = dbcfg; dbctx->priv = privctx = malloc(sizeof(*privctx)); dbctx->cleanupdb = hkp_cleanupdb; dbctx->starttrans = hkp_starttrans; @@ -373,7 +375,7 @@ struct onak_dbctx *keydb_hkp_init(bool readonly) dbctx->getfullkeyid = generic_getfullkeyid; dbctx->iterate_keys = hkp_iterate_keys; - if (!hkp_parse_url(privctx, config.db_dir)) { + if (!hkp_parse_url(privctx, dbcfg->location)) { exit(EXIT_FAILURE); } curl_global_init(CURL_GLOBAL_DEFAULT); diff --git a/keydb_keyd.c b/keydb_keyd.c index 33d2c21..6836e9a 100644 --- a/keydb_keyd.c +++ b/keydb_keyd.c @@ -502,7 +502,7 @@ static void keyd_cleanupdb(struct onak_dbctx *dbctx) * this file are called in order to allow the DB to be initialized ready * for access. */ -struct onak_dbctx *keydb_keyd_init(bool readonly) +struct onak_dbctx *keydb_keyd_init(struct onak_db_config *dbcfg, bool readonly) { struct sockaddr_un sock; uint32_t cmd = KEYD_CMD_UNKNOWN; @@ -515,6 +515,7 @@ struct onak_dbctx *keydb_keyd_init(bool readonly) if (dbctx == NULL) { return NULL; } + dbctx->config = dbcfg; keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0); if (keyd_fd < 0) { diff --git a/keydb_pg.c b/keydb_pg.c index ca7e35b..d599afe 100644 --- a/keydb_pg.c +++ b/keydb_pg.c @@ -666,7 +666,7 @@ static void pg_cleanupdb(struct onak_dbctx *dbctx) * this file are called in order to allow the DB to be initialized ready * for access. */ -struct onak_dbctx *keydb_pg_init(bool readonly) +struct onak_dbctx *keydb_pg_init(struct onak_db_config *dbcfg, bool readonly) { struct onak_dbctx *dbctx; PGconn *dbconn; @@ -675,6 +675,7 @@ struct onak_dbctx *keydb_pg_init(bool readonly) if (dbctx == NULL) { return NULL; } + dbctx->config = dbcfg; dbconn = PQsetdbLogin(config.pg_dbhost, // host NULL, // port diff --git a/lookup.c b/lookup.c index 12eb5a2..23aa96e 100644 --- a/lookup.c +++ b/lookup.c @@ -215,7 +215,7 @@ int main(int argc, char *argv[]) readconfig(NULL); initlogthing("lookup", config.logfile); catchsignals(); - dbctx = config.dbinit(false); + dbctx = config.dbinit(config.backend, false); switch (op) { case OP_GET: case OP_HGET: diff --git a/maxpath.c b/maxpath.c index 0932df3..0e5d632 100644 --- a/maxpath.c +++ b/maxpath.c @@ -102,7 +102,7 @@ int main(int argc, char *argv[]) readconfig(configfile); free(configfile); initlogthing("maxpath", config.logfile); - dbctx = config.dbinit(true); + dbctx = config.dbinit(config.backend, true); if (dbctx != NULL) { inithash(); findmaxpath(dbctx, 30); diff --git a/onak-conf.c b/onak-conf.c index 9a8a471..982d23b 100644 --- a/onak-conf.c +++ b/onak-conf.c @@ -28,7 +28,7 @@ #include "log.h" #include "onak-conf.h" -extern struct onak_dbctx *DBINIT(bool readonly); +extern struct onak_dbctx *DBINIT(struct onak_db_config *dbcfg, bool readonly); /* * config - Runtime configuration for onak. @@ -47,28 +47,15 @@ struct onak_config config = { .use_keyd = false, .sock_dir = ".", - /* - * Options for directory backends. - */ - .db_dir = NULL, - - /* - * Options for the Postgres backend. - */ - .pg_dbhost = NULL, - .pg_dbname = NULL, - .pg_dbuser = NULL, - .pg_dbpass = NULL, - - /* - * Options for dynamic backends. - */ - .db_backend = NULL, + .backends = NULL, .backends_dir = NULL, .dbinit = DBINIT, .check_sighash = true, + + .bin_dir = NULL, + .mail_dir = NULL, }; bool parsebool(char *str, bool fallback) @@ -95,6 +82,7 @@ void readconfig(const char *configfile) { int i; char *dir, *conf; size_t len; + struct onak_db_config *backend; curline[1023] = 0; if (configfile == NULL) { @@ -126,6 +114,11 @@ void readconfig(const char *configfile) { return; } + /* Add a single DB configuration */ + backend = calloc(1, sizeof(*backend)); + config.backend = backend; + config.backends = lladd(NULL, backend); + while (!feof(conffile)) { for (i = strlen(curline) - 1; i >= 0 && isspace(curline[i]); @@ -138,7 +131,7 @@ void readconfig(const char *configfile) { * Comment line, ignore. */ } else if (!strncmp("db_dir ", curline, 7)) { - config.db_dir = strdup(&curline[7]); + backend->location = strdup(&curline[7]); } else if (!strncmp("debug ", curline, 6)) { /* * Not supported yet; ignore for compatibility with @@ -171,13 +164,13 @@ void readconfig(const char *configfile) { } else if (!strncmp("max_reply_keys ", curline, 15)) { config.maxkeys = atoi(&curline[15]); } else if (!strncmp("pg_dbhost ", curline, 10)) { - config.pg_dbhost = strdup(&curline[10]); + backend->hostname = strdup(&curline[10]); } else if (!strncmp("pg_dbname ", curline, 10)) { - config.pg_dbname = strdup(&curline[10]); + backend->location = strdup(&curline[10]); } else if (!strncmp("pg_dbuser ", curline, 10)) { - config.pg_dbuser = strdup(&curline[10]); + backend->username = strdup(&curline[10]); } else if (!strncmp("pg_dbpass ", curline, 10)) { - config.pg_dbpass = strdup(&curline[10]); + backend->password = strdup(&curline[10]); } else if (!strncmp("syncsite ", curline, 9)) { config.syncsites = lladd(config.syncsites, strdup(&curline[9])); @@ -195,6 +188,8 @@ void readconfig(const char *configfile) { * Not applicable; ignored for compatibility with pksd. */ } else if (!strncmp("db_backend ", curline, 11)) { + backend->type = strdup(&curline[11]); + backend->name = strdup(&curline[11]); config.db_backend = strdup(&curline[11]); } else if (!strncmp("backends_dir ", curline, 13)) { config.backends_dir = strdup(&curline[13]); @@ -225,7 +220,41 @@ void readconfig(const char *configfile) { } } +void cleanupdbconfig(void *object) +{ + struct onak_db_config *dbconfig = (struct onak_db_config *) object; + + if (dbconfig->name != NULL) { + free(dbconfig->name); + dbconfig->name = NULL; + } + if (dbconfig->type != NULL) { + free(dbconfig->type); + dbconfig->type = NULL; + } + if (dbconfig->location != NULL) { + free(dbconfig->location); + dbconfig->location = NULL; + } + if (dbconfig->hostname != NULL) { + free(dbconfig->hostname); + dbconfig->hostname = NULL; + } + if (dbconfig->username != NULL) { + free(dbconfig->username); + dbconfig->username = NULL; + } + if (dbconfig->password != NULL) { + free(dbconfig->password); + dbconfig->password = NULL; + } +} + void cleanupconfig(void) { + /* Free any defined DB backend configuration first */ + llfree(config.backends, cleanupdbconfig); + config.backends = NULL; + if (config.thissite != NULL) { free(config.thissite); config.thissite = NULL; @@ -238,26 +267,6 @@ void cleanupconfig(void) { free(config.mta); config.mta = NULL; } - if (config.db_dir != NULL) { - free(config.db_dir); - config.db_dir = NULL; - } - if (config.pg_dbhost != NULL) { - free(config.pg_dbhost); - config.pg_dbhost = NULL; - } - if (config.pg_dbname != NULL) { - free(config.pg_dbname); - config.pg_dbname = NULL; - } - if (config.pg_dbuser != NULL) { - free(config.pg_dbuser); - config.pg_dbuser = NULL; - } - if (config.pg_dbpass != NULL) { - free(config.pg_dbpass); - config.pg_dbpass = NULL; - } if (config.syncsites != NULL) { llfree(config.syncsites, free); config.syncsites = NULL; diff --git a/onak-conf.h b/onak-conf.h index 52439ab..0d937c2 100644 --- a/onak-conf.h +++ b/onak-conf.h @@ -23,6 +23,25 @@ #include "keydb.h" +/** + * @brief Backend database configuration. + * + */ +struct onak_db_config { + /** Name, as used to refer to individual backend instances */ + char *name; + /** Backend type [e.g. db4, pg, fs, file] */ + char *type; + /** Location information; directory for file backed, DB name for DBs */ + char *location; + /** Database backend hostname, if appropriate */ + char *hostname; + /** Database backend username, if appropriate */ + char *username; + /** Database backend password, if appropriate */ + char *password; +}; + /** * @brief Runtime configuration for onak. * @@ -51,24 +70,11 @@ struct onak_config { /** The path to the directory the keyd socket lives in. */ char *sock_dir; - /* - * Options for any database backend that needs a directory, be it the - * file, fs or db4 options. - */ - /** The path to the directory containing the database files. */ - char *db_dir; - - /* - * Options for the Postgres backend. - */ - /** The host that Postgres is running on. */ - char *pg_dbhost; - /** The database name. */ - char *pg_dbname; - /** The user we should connect as. */ - char *pg_dbuser; - /** The password for the user. */ - char *pg_dbpass; + /** List of backend configurations */ + struct ll *backends; + + /* The default backend to use */ + struct onak_db_config *backend; /* * Options for the dynamic backend. @@ -79,7 +85,7 @@ struct onak_config { char *backends_dir; /** Pointer to the initialisation function for our loaded DB backend */ - struct onak_dbctx *(*dbinit)(bool); + struct onak_dbctx *(*dbinit)(struct onak_db_config *, bool); /** Should we verify signature hashes match? */ bool check_sighash; diff --git a/onak.c b/onak.c index 0c4673d..08bdd39 100644 --- a/onak.c +++ b/onak.c @@ -207,7 +207,7 @@ int main(int argc, char *argv[]) if ((argc - optind) < 1) { usage(); } else if (!strcmp("dump", argv[optind])) { - dbctx = config.dbinit(true); + dbctx = config.dbinit(config.backend, true); dumpstate.count = dumpstate.filenum = 0; dumpstate.maxcount = 100000; dumpstate.fd = -1; @@ -238,7 +238,7 @@ int main(int argc, char *argv[]) logthing(LOGTHING_INFO, "%d keys cleaned.", result); - dbctx = config.dbinit(false); + dbctx = config.dbinit(config.backend, false); logthing(LOGTHING_NOTICE, "Got %d new keys.", dbctx->update_keys(dbctx, &keys, false)); @@ -337,7 +337,7 @@ int main(int argc, char *argv[]) ishex = true; } } - dbctx = config.dbinit(false); + dbctx = config.dbinit(config.backend, false); if (!strcmp("index", argv[optind])) { find_keys(dbctx, search, keyid, &fingerprint, ishex, isfp, dispfp, skshash, diff --git a/sixdegrees.c b/sixdegrees.c index b806c3e..3dd13ec 100644 --- a/sixdegrees.c +++ b/sixdegrees.c @@ -158,7 +158,7 @@ int main(int argc, char *argv[]) readconfig(configfile); free(configfile); initlogthing("sixdegrees", config.logfile); - dbctx = config.dbinit(true); + dbctx = config.dbinit(config.backend, true); if (dbctx != NULL) { inithash(); sixdegrees(dbctx, dbctx->getfullkeyid(dbctx, keyid)); diff --git a/wotsap.c b/wotsap.c index 66dc946..ce25b02 100644 --- a/wotsap.c +++ b/wotsap.c @@ -203,7 +203,7 @@ int main(int argc, char *argv[]) readconfig(configfile); initlogthing("wotsap", config.logfile); - dbctx = config.dbinit(true); + dbctx = config.dbinit(config.backend, true); if (dbctx != NULL) { inithash(); wotsap(dbctx, dbctx->getfullkeyid(dbctx, keyid),