X-Git-Url: https://the.earth.li/gitweb/?a=blobdiff_plain;f=keydb_dynamic.c;h=9e4e3bcb7585e27decf07aa2a8ca22905d0a0573;hb=adc800dbc424a1e246dd4a82a0c2e88eeda25531;hp=10bec165e6decd21c6820095fd6f21abfd0057fa;hpb=5e1b22d763640c4d7a09d07920403d8d491b4410;p=onak.git diff --git a/keydb_dynamic.c b/keydb_dynamic.c index 10bec16..9e4e3bc 100644 --- a/keydb_dynamic.c +++ b/keydb_dynamic.c @@ -13,8 +13,7 @@ * 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. + * this program. If not, see . */ #include @@ -34,495 +33,286 @@ #include "parsekey.h" #include "sendsync.h" -static struct dbfuncs *loaded_backend = NULL; -static void *backend_handle; +struct onak_dynamic_dbctx { + struct onak_dbctx *loadeddbctx; + void *backend_handle; +}; -static bool close_backend(void) +static bool dynamic_starttrans(struct onak_dbctx *dbctx) { - loaded_backend = NULL; - dlclose(backend_handle); - backend_handle = NULL; + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; - return true; + return privctx->loadeddbctx->starttrans(privctx->loadeddbctx); } -static bool load_backend(void) +static void dynamic_endtrans(struct onak_dbctx *dbctx) { - char *soname = NULL; - char *funcsname = NULL; - - if (loaded_backend != NULL) { - close_backend(); - loaded_backend = NULL; - } - - if (config.use_keyd) { - free(config.db_backend); - config.db_backend = strdup("keyd"); - } + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; - if (!config.db_backend) { - logthing(LOGTHING_CRITICAL, "No database backend defined."); - exit(EXIT_FAILURE); - } + privctx->loadeddbctx->endtrans(privctx->loadeddbctx); +} - if (config.backends_dir == NULL) { - soname = malloc(strlen(config.db_backend) - + strlen("./libkeydb_") - + strlen(".so") - + 1); +static int dynamic_fetch_key_id(struct onak_dbctx *dbctx, uint64_t keyid, + struct openpgp_publickey **publickey, bool intrans) +{ + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; - sprintf(soname, "./libkeydb_%s.so", config.db_backend); - } else { - soname = malloc(strlen(config.db_backend) - + strlen("/libkeydb_") - + strlen(".so") - + strlen(config.backends_dir) - + 1); + return privctx->loadeddbctx->fetch_key_id(privctx->loadeddbctx, keyid, + publickey, intrans); +} - sprintf(soname, "%s/libkeydb_%s.so", config.backends_dir, - config.db_backend); - } - - logthing(LOGTHING_INFO, "Loading dynamic backend: %s", soname); +static int dynamic_fetch_key_fp(struct onak_dbctx *dbctx, + struct openpgp_fingerprint *fingerprint, + struct openpgp_publickey **publickey, bool intrans) +{ + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; - backend_handle = dlopen(soname, RTLD_LAZY); - if (backend_handle == NULL) { - logthing(LOGTHING_CRITICAL, - "Failed to open handle to library '%s': %s", - soname, dlerror()); - free(soname); - soname = NULL; - exit(EXIT_FAILURE); - } + return privctx->loadeddbctx->fetch_key_fp(privctx->loadeddbctx, + fingerprint, publickey, intrans); +} - funcsname = malloc(strlen(config.db_backend) - + strlen("keydb_") - + strlen("_funcs") - + 1); - sprintf(funcsname, "keydb_%s_funcs", config.db_backend); +static int dynamic_fetch_key_text(struct onak_dbctx *dbctx, + const char *search, + struct openpgp_publickey **publickey) +{ + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; - loaded_backend = dlsym(backend_handle, funcsname); - free(funcsname); + return privctx->loadeddbctx->fetch_key_text(privctx->loadeddbctx, + search, publickey); +} - if (loaded_backend == NULL) { - logthing(LOGTHING_CRITICAL, - "Failed to find dbfuncs structure in library " - "'%s' : %s", soname, dlerror()); - free(soname); - soname = NULL; - exit(EXIT_FAILURE); - } - free(soname); - soname = NULL; +static int dynamic_fetch_key_skshash(struct onak_dbctx *dbctx, + const struct skshash *hash, + struct openpgp_publickey **publickey) +{ + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; - return true; + return privctx->loadeddbctx->fetch_key_skshash(privctx->loadeddbctx, + hash, publickey); } -static bool dynamic_starttrans() +static int dynamic_store_key(struct onak_dbctx *dbctx, + struct openpgp_publickey *publickey, bool intrans, + bool update) { - if (loaded_backend == NULL) { - load_backend(); - } - - if (loaded_backend != NULL) { - if (loaded_backend->starttrans != NULL) { - return loaded_backend->starttrans(); - } - } + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; - return false; + return privctx->loadeddbctx->store_key(privctx->loadeddbctx, + publickey, intrans, update); } -static void dynamic_endtrans() +static int dynamic_delete_key(struct onak_dbctx *dbctx, uint64_t keyid, + bool intrans) { - if (loaded_backend == NULL) { - load_backend(); - } - - if (loaded_backend != NULL) { - if (loaded_backend->endtrans != NULL) { - loaded_backend->endtrans(); - } - } + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; + + return privctx->loadeddbctx->delete_key(privctx->loadeddbctx, + keyid, intrans); } -static int dynamic_fetch_key(uint64_t keyid, - struct openpgp_publickey **publickey, bool intrans) +static int dynamic_update_keys(struct onak_dbctx *dbctx, + struct openpgp_publickey **keys, bool sendsync) { - if (loaded_backend == NULL) { - load_backend(); - } - - if (loaded_backend != NULL) { - if (loaded_backend->fetch_key != NULL) { - return loaded_backend->fetch_key(keyid,publickey,intrans); - } - } + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; - return -1; + return privctx->loadeddbctx->update_keys(privctx->loadeddbctx, + keys, sendsync); } -static int dynamic_store_key(struct openpgp_publickey *publickey, bool intrans, - bool update) +static struct ll *dynamic_getkeysigs(struct onak_dbctx *dbctx, + uint64_t keyid, bool *revoked) { - if (loaded_backend == NULL) { - load_backend(); - } - - if (loaded_backend != NULL) { - if (loaded_backend->store_key != NULL) { - return loaded_backend->store_key(publickey,intrans,update); - } - } + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; - return -1; + return privctx->loadeddbctx->getkeysigs(privctx->loadeddbctx, + keyid, revoked); } -static int dynamic_delete_key(uint64_t keyid, bool intrans) +static struct ll *dynamic_cached_getkeysigs(struct onak_dbctx *dbctx, + uint64_t keyid) { - if (loaded_backend == NULL) { - load_backend(); - } - - if (loaded_backend != NULL) { - if (loaded_backend->delete_key != NULL) { - return loaded_backend->delete_key(keyid, intrans); - } - } + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; - return -1; + return privctx->loadeddbctx->cached_getkeysigs(privctx->loadeddbctx, + keyid); } -static int dynamic_fetch_key_text(const char *search, - struct openpgp_publickey **publickey) +static char *dynamic_keyid2uid(struct onak_dbctx *dbctx, + uint64_t keyid) { - if (loaded_backend == NULL) { - load_backend(); - } - - if (loaded_backend != NULL) { - if (loaded_backend->fetch_key_text != NULL) { - return loaded_backend->fetch_key_text(search, publickey); - } - } + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; - return -1; + return privctx->loadeddbctx->keyid2uid(privctx->loadeddbctx, + keyid); } -static int dynamic_fetch_key_skshash(const struct skshash *hash, - struct openpgp_publickey **publickey) +static uint64_t dynamic_getfullkeyid(struct onak_dbctx *dbctx, + uint64_t keyid) { - if (loaded_backend == NULL) { - load_backend(); - } - - if (loaded_backend != NULL) { - if (loaded_backend->fetch_key_skshash != NULL) { - return loaded_backend->fetch_key_skshash(hash, - publickey); - } - } + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; - return -1; + return privctx->loadeddbctx->getfullkeyid(privctx->loadeddbctx, keyid); } -static int dynamic_iterate_keys(void (*iterfunc)(void *ctx, - struct openpgp_publickey *key), void *ctx) +static int dynamic_iterate_keys(struct onak_dbctx *dbctx, + void (*iterfunc)(void *ctx, struct openpgp_publickey *key), + void *ctx) { - if (loaded_backend == NULL) { - load_backend(); - } - - if (loaded_backend != NULL) { - if (loaded_backend->iterate_keys != NULL) { - return loaded_backend->iterate_keys(iterfunc, ctx); - } - } + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; - return -1; + return privctx->loadeddbctx->iterate_keys(privctx->loadeddbctx, + iterfunc, ctx); } -/** - * keyid2uid - Takes a keyid and returns the primary UID for it. - * @keyid: The keyid to lookup. - */ -static char *dynamic_keyid2uid(uint64_t keyid) +static void dynamic_cleanupdb(struct onak_dbctx *dbctx) { - struct openpgp_publickey *publickey = NULL; - struct openpgp_signedpacket_list *curuid = NULL; - char buf[1024]; + struct onak_dynamic_dbctx *privctx = + (struct onak_dynamic_dbctx *) dbctx->priv; - if (loaded_backend == NULL) { - load_backend(); - } - - if (loaded_backend != NULL) { - if (loaded_backend->keyid2uid != NULL) { - return loaded_backend->keyid2uid(keyid); - } - } - - buf[0]=0; - if (dynamic_fetch_key(keyid, &publickey, false) && publickey != NULL) { - curuid = publickey->uids; - while (curuid != NULL && buf[0] == 0) { - if (curuid->packet->tag == OPENPGP_PACKET_UID) { - snprintf(buf, 1023, "%.*s", - (int) curuid->packet->length, - curuid->packet->data); - } - curuid = curuid -> next; + if (privctx->loadeddbctx != NULL) { + if (privctx->loadeddbctx->cleanupdb != NULL) { + privctx->loadeddbctx->cleanupdb(privctx->loadeddbctx); + privctx->loadeddbctx = NULL; } - free_publickey(publickey); } - if (buf[0] == 0) { - return NULL; - } else { - return strdup(buf); + if (privctx->backend_handle != NULL) { + dlclose(privctx->backend_handle); + privctx->backend_handle = NULL; } -} -/** - * getkeysigs - Gets a linked list of the signatures on a key. - * @keyid: The keyid to get the sigs for. - * @revoked: Is the key revoked? - * - * This function gets the list of signatures on a key. Used for key - * indexing and doing stats bits. If revoked is non-NULL then if the key - * is revoked it's set to true. - */ -static struct ll *dynamic_getkeysigs(uint64_t keyid, bool *revoked) -{ - struct ll *sigs = NULL; - struct openpgp_signedpacket_list *uids = NULL; - struct openpgp_publickey *publickey = NULL; - - if ( loaded_backend == NULL ) { - load_backend(); - } - - if (loaded_backend != NULL) { - if (loaded_backend->getkeysigs != NULL) { - return loaded_backend->getkeysigs(keyid,revoked); - } + if (dbctx->priv != NULL) { + free(dbctx->priv); + dbctx->priv = NULL; } - dynamic_fetch_key(keyid, &publickey, false); - - if (publickey != NULL) { - for (uids = publickey->uids; uids != NULL; uids = uids->next) { - sigs = keysigs(sigs, uids->sigs); - } - if (revoked != NULL) { - *revoked = publickey->revoked; - } - free_publickey(publickey); + if (dbctx != NULL) { + free(dbctx); } - - return sigs; } -/** - * cached_getkeysigs - Gets the signatures on a key. - * @keyid: The key we want the signatures for. - * - * This function gets the signatures on a key. It's the same as the - * getkeysigs function above except we use the hash module to cache the - * data so if we need it again it's already loaded. - */ -static struct ll *dynamic_cached_getkeysigs(uint64_t keyid) +struct onak_dbctx *keydb_dynamic_init(struct onak_db_config *dbcfg, + bool readonly) { - struct stats_key *key = NULL; - struct stats_key *signedkey = NULL; - struct ll *cursig = NULL; - bool revoked = false; - - if (keyid == 0) { + struct onak_dbctx *dbctx; + char *soname; + char *initname; + struct onak_dbctx *(*backend_init)(struct onak_db_config *, bool); + struct onak_dynamic_dbctx *privctx; + char *type; + + if (dbcfg == NULL) { + logthing(LOGTHING_CRITICAL, + "No backend database configuration supplied."); return NULL; } - - if (loaded_backend == NULL) { - load_backend(); - } - - if (loaded_backend != NULL) { - if (loaded_backend->cached_getkeysigs != NULL) { - return loaded_backend->cached_getkeysigs(keyid); - } - } - key = createandaddtohash(keyid); + dbctx = malloc(sizeof(struct onak_dbctx)); - if (key->gotsigs == false) { - key->sigs = dynamic_getkeysigs(key->keyid, &revoked); - key->revoked = revoked; - for (cursig = key->sigs; cursig != NULL; - cursig = cursig->next) { - signedkey = (struct stats_key *) cursig->object; - signedkey->signs = lladd(signedkey->signs, key); - } - key->gotsigs = true; + if (dbctx == NULL) { + return NULL; } - return key->sigs; -} - -/** - * getfullkeyid - Maps a 32bit key id to a 64bit one. - * @keyid: The 32bit keyid. - * - * This function maps a 32bit key id to the full 64bit one. It returns the - * full keyid. If the key isn't found a keyid of 0 is returned. - */ -static uint64_t dynamic_getfullkeyid(uint64_t keyid) -{ - struct openpgp_publickey *publickey = NULL; - - if (loaded_backend == NULL) { - load_backend(); - } - - if (loaded_backend != NULL) { - if (loaded_backend->getfullkeyid != NULL) { - return loaded_backend->getfullkeyid(keyid); - } + dbctx->config = dbcfg; + dbctx->priv = privctx = malloc(sizeof(struct onak_dynamic_dbctx)); + if (dbctx->priv == NULL) { + free(dbctx); + return (NULL); } - if (keyid < 0x100000000LL) { - dynamic_fetch_key(keyid, &publickey, false); - if (publickey != NULL) { - keyid = get_keyid(publickey); - free_publickey(publickey); - publickey = NULL; - } else { - keyid = 0; - } + type = dbcfg->type; + if (config.use_keyd) { + type = "keyd"; } - - return keyid; -} -/** - * update_keys - Takes a list of public keys and updates them in the DB. - * @keys: The keys to update in the DB. - * @sendsync: Should we send a sync mail to our peers. - * - * Takes a list of keys and adds them to the database, merging them with - * the key in the database if it's already present there. The key list is - * update to contain the minimum set of updates required to get from what - * we had before to what we have now (ie the set of data that was added to - * the DB). Returns the number of entirely new keys added. - */ -static int dynamic_update_keys(struct openpgp_publickey **keys, bool sendsync) -{ - struct openpgp_publickey *curkey = NULL; - struct openpgp_publickey *oldkey = NULL; - struct openpgp_publickey *prev = NULL; - int newkeys = 0; - bool intrans; - - if (loaded_backend == NULL) { - load_backend(); - } - - if (loaded_backend != NULL) { - if (loaded_backend->update_keys != NULL) { - return loaded_backend->update_keys(keys, sendsync); - } + if (!config.db_backend) { + logthing(LOGTHING_CRITICAL, "No database backend defined."); + exit(EXIT_FAILURE); } - for (curkey = *keys; curkey != NULL; curkey = curkey->next) { - intrans = dynamic_starttrans(); - logthing(LOGTHING_INFO, - "Fetching key 0x%" PRIX64 ", result: %d", - get_keyid(curkey), - dynamic_fetch_key(get_keyid(curkey), &oldkey, intrans)); - - /* - * If we already have the key stored in the DB then merge it - * with the new one that's been supplied. Otherwise the key - * we've just got is the one that goes in the DB and also the - * one that we send out. - */ - if (oldkey != NULL) { - merge_keys(oldkey, curkey); - if (curkey->sigs == NULL && - curkey->uids == NULL && - curkey->subkeys == NULL) { - if (prev == NULL) { - *keys = curkey->next; - } else { - prev->next = curkey->next; - curkey->next = NULL; - free_publickey(curkey); - curkey = prev; - } - } else { - prev = curkey; - logthing(LOGTHING_INFO, - "Merged key; storing updated key."); - dynamic_store_key(oldkey, intrans, true); - } - free_publickey(oldkey); - oldkey = NULL; - - } else { - logthing(LOGTHING_INFO, - "Storing completely new key."); - dynamic_store_key(curkey, intrans, false); - newkeys++; - } - dynamic_endtrans(); - intrans = false; - } + if (config.backends_dir == NULL) { + soname = malloc(strlen(type) + + strlen("./libkeydb_") + + strlen(".so") + + 1); - if (sendsync && keys != NULL) { - sendkeysync(*keys); + sprintf(soname, "./libkeydb_%s.so", type); + } else { + soname = malloc(strlen(type) + + strlen("/libkeydb_") + + strlen(".so") + + strlen(config.backends_dir) + + 1); + + sprintf(soname, "%s/libkeydb_%s.so", config.backends_dir, + type); } - return newkeys; -} + logthing(LOGTHING_INFO, "Loading dynamic backend: %s", soname); -static void dynamic_initdb(bool readonly) -{ - if (loaded_backend == NULL) { - load_backend(); + privctx->backend_handle = dlopen(soname, RTLD_LAZY); + if (privctx->backend_handle == NULL) { + logthing(LOGTHING_CRITICAL, + "Failed to open handle to library '%s': %s", + soname, dlerror()); + free(soname); + soname = NULL; + exit(EXIT_FAILURE); } - if (loaded_backend != NULL) { - if (loaded_backend->initdb != NULL) { - loaded_backend->initdb(readonly); - } - } -} + initname = malloc(strlen(config.db_backend) + + strlen("keydb_") + + strlen("_init") + + 1); + sprintf(initname, "keydb_%s_init", type); -static void dynamic_cleanupdb(void) -{ - if (loaded_backend != NULL) { - if (loaded_backend->cleanupdb != NULL) { - loaded_backend->cleanupdb(); - } + *(void **) (&backend_init) = dlsym(privctx->backend_handle, initname); + free(initname); + + if (backend_init == NULL) { + logthing(LOGTHING_CRITICAL, + "Failed to find dbfuncs structure in library " + "'%s' : %s", soname, dlerror()); + free(soname); + soname = NULL; + exit(EXIT_FAILURE); } + free(soname); + soname = NULL; - close_backend(); + privctx->loadeddbctx = backend_init(dbcfg, readonly); + + if (privctx->loadeddbctx != NULL) { + dbctx->cleanupdb = dynamic_cleanupdb; + dbctx->starttrans = dynamic_starttrans; + dbctx->endtrans = dynamic_endtrans; + dbctx->fetch_key_id = dynamic_fetch_key_id; + dbctx->fetch_key_fp = dynamic_fetch_key_fp; + dbctx->fetch_key_text = dynamic_fetch_key_text; + dbctx->fetch_key_skshash = dynamic_fetch_key_skshash; + dbctx->store_key = dynamic_store_key; + dbctx->update_keys = dynamic_update_keys; + dbctx->delete_key = dynamic_delete_key; + dbctx->getkeysigs = dynamic_getkeysigs; + dbctx->cached_getkeysigs = dynamic_cached_getkeysigs; + dbctx->keyid2uid = dynamic_keyid2uid; + dbctx->getfullkeyid = dynamic_getfullkeyid; + dbctx->iterate_keys = dynamic_iterate_keys; + } + + return dbctx; } - -struct dbfuncs keydb_dynamic_funcs = { - .initdb = dynamic_initdb, - .cleanupdb = dynamic_cleanupdb, - .starttrans = dynamic_starttrans, - .endtrans = dynamic_endtrans, - .fetch_key = dynamic_fetch_key, - .fetch_key_text = dynamic_fetch_key_text, - .fetch_key_skshash = dynamic_fetch_key_skshash, - .store_key = dynamic_store_key, - .update_keys = dynamic_update_keys, - .delete_key = dynamic_delete_key, - .getkeysigs = dynamic_getkeysigs, - .cached_getkeysigs = dynamic_cached_getkeysigs, - .keyid2uid = dynamic_keyid2uid, - .getfullkeyid = dynamic_getfullkeyid, - .iterate_keys = dynamic_iterate_keys, -};