]> the.earth.li Git - onak.git/commitdiff
Use dynamic context for all backend databases
authorJonathan McDowell <noodles@earth.li>
Sat, 9 Nov 2013 07:02:45 +0000 (23:02 -0800)
committerJonathan McDowell <noodles@earth.li>
Sat, 9 Nov 2013 07:02:45 +0000 (23:02 -0800)
Rather than defining a static set of database functions use a well
known initialisation function for each database backend that then
returns a database context structure. This structure contains function
pointers for all of the functions previously held in dbstructs as well
as a private instance context pointer.

For the moment this doesn't provide any change to behaviour, but it
provides the initial preparation for allowing multiple database instance
(whether of the same or differing types) to be used at the same time.

26 files changed:
Makefile.in
add.c
gpgwww.c
hashquery.c
keyd.c
keydb.c
keydb.h
keydb_db4.c
keydb_dynamic.c
keydb_file.c
keydb_fs.c
keydb_hkp.c
keydb_keyd.c
keydb_pg.c
keydctl.c
keyindex.c
keyindex.h
lookup.c
maxpath.c
onak-conf.c
onak-conf.h
onak.c
sixdegrees.c
stats.c
stats.h
wotsap.c

index da116ac19ca25baad2f39c0dd1689319c397a1b4..76d7fc463b1aa7be6be664ac167c141b38a6ffca 100644 (file)
@@ -142,12 +142,12 @@ onak: onak.o cleankey.o $(CORE_OBJS) $(KEYDB_OBJ)
 
 onak-conf.o: onak-conf.c onak-conf.h
        $(CC) $(CFLAGS) -DCONFIGFILE=\"@sysconfdir@/onak.conf\" \
-               -DDBFUNCS=keydb_@DBTYPE@_funcs -c onak-conf.c
+               -DDBINIT=keydb_@DBTYPE@_init -c onak-conf.c
 
 # HACK: onak-conf.o needs to be able to see keydb_@DBTYPE@_funcs, but
 # keydctl doesn't want to link against the DB stuff. To be fixed more cleanly.
 keydctl.o: keydctl.c keyd.h
-       $(CC) $(CFLAGS) -DDBFUNCS=keydb_@DBTYPE@_funcs -c keydctl.c
+       $(CC) $(CFLAGS) -DDBINIT=keydb_@DBTYPE@_init -c keydctl.c
 
 onak-mail.pl: onak-mail.pl.in
        sed 's:@CONFIG@:@sysconfdir@/onak.conf:g' < onak-mail.pl.in > onak-mail.pl
diff --git a/add.c b/add.c
index 6f919becfe7e30b077cfd11d079851a478fe0091..4e03719a82345819a340c3381a8ec3edb9035ba2 100644 (file)
--- a/add.c
+++ b/add.c
@@ -43,6 +43,7 @@ int main(int argc, char *argv[])
        struct buffer_ctx            ctx;
        int                          count = 0;
        int                          i;
+       struct onak_dbctx           *dbctx;
 
        memset(&ctx, 0, sizeof(ctx));
 
@@ -88,13 +89,13 @@ int main(int argc, char *argv[])
                                fclose(stderr);
                        }
                        catchsignals();
-                       config.dbbackend->initdb(false);
+                       dbctx = config.dbinit(false);
                        
                        count = cleankeys(keys);
                        logthing(LOGTHING_INFO, "%d keys cleaned.",
                                        count);
 
-                       count = config.dbbackend->update_keys(&keys, true);
+                       count = dbctx->update_keys(dbctx, &keys, true);
                        logthing(LOGTHING_NOTICE, "Got %d new keys.",
                                count);
 
@@ -103,7 +104,7 @@ int main(int argc, char *argv[])
                                keys = NULL;
                        }
                        
-                       config.dbbackend->cleanupdb();
+                       dbctx->cleanupdb(dbctx);
                } else {
                        puts("No OpenPGP packets found in input.");
                        end_html();
index 07b448e37eff10cac7d40b211bafd1b576d91c5e..6615887cf753ca29d24f4984b6c9822cbb3f2d05 100644 (file)
--- a/gpgwww.c
+++ b/gpgwww.c
@@ -62,7 +62,8 @@ int parsecgistuff(char **cgiparams, uint64_t *from, uint64_t *to)
        return op;
 }
 
-int getkeyspath(uint64_t have, uint64_t want, int count)
+int getkeyspath(struct onak_dbctx *dbctx,
+               uint64_t have, uint64_t want, int count)
 {
        struct openpgp_publickey *publickey = NULL;
        struct openpgp_packet_list *packets = NULL;
@@ -71,14 +72,14 @@ int getkeyspath(uint64_t have, uint64_t want, int count)
        uint64_t fullhave, fullwant;
        int pathlen = 0;
 
-       fullhave = config.dbbackend->getfullkeyid(have);
-       fullwant = config.dbbackend->getfullkeyid(want);
+       fullhave = dbctx->getfullkeyid(dbctx, have);
+       fullwant = dbctx->getfullkeyid(dbctx, want);
 
        /*
         * Make sure the keys we have and want are in the cache.
         */
-       config.dbbackend->cached_getkeysigs(fullhave);
-       config.dbbackend->cached_getkeysigs(fullwant);
+       dbctx->cached_getkeysigs(dbctx, fullhave);
+       dbctx->cached_getkeysigs(dbctx, fullwant);
 
        if ((keyinfoa = findinhash(fullhave)) == NULL) {
                return 1;
@@ -92,7 +93,7 @@ int getkeyspath(uint64_t have, uint64_t want, int count)
                 * Fill the tree info up.
                 */
                initcolour(true);
-               findpath(keyinfoa, keyinfob);
+               findpath(dbctx, keyinfoa, keyinfob);
                keyinfob->parent = 0;
                if (keyinfoa->colour == 0) {
                        pathlen = count;
@@ -104,7 +105,7 @@ int getkeyspath(uint64_t have, uint64_t want, int count)
                        curkey = findinhash(keyinfoa->parent);
                        while (curkey != NULL && curkey->keyid != 0) {
                                if (curkey->keyid != fullwant &&
-                                               config.dbbackend->fetch_key_id(
+                                               dbctx->fetch_key_id(dbctx,
                                                curkey->keyid,
                                                &publickey, false)) {
                                        flatten_publickey(publickey,
@@ -125,7 +126,7 @@ int getkeyspath(uint64_t have, uint64_t want, int count)
        /*
         * Add the destination key to the list of returned keys.
         */
-       if (config.dbbackend->fetch_key_id(fullwant, &publickey, false)) {
+       if (dbctx->fetch_key_id(dbctx, fullwant, &publickey, false)) {
                flatten_publickey(publickey,
                                &packets,
                                &list_end);
@@ -145,6 +146,7 @@ int main(int argc, char *argv[])
        char     **cgiparams = NULL;    /* Our CGI parameter block */
        uint64_t   from = 0, to = 0;
        int        op = OP_UNKNOWN;
+       struct onak_dbctx *dbctx;
 
        cgiparams = getcgivars(argc, argv);
 
@@ -181,7 +183,7 @@ int main(int argc, char *argv[])
        readconfig(NULL);
        initlogthing("gpgwww", config.logfile);
        catchsignals();
-       config.dbbackend->initdb(true);
+       dbctx = config.dbinit(true);
        inithash();
        logthing(LOGTHING_NOTICE, "Looking for path from 0x%016" PRIX64
                        " to 0x%016"
@@ -189,12 +191,12 @@ int main(int argc, char *argv[])
                        from,
                        to);
        if (op == OP_GET) {
-               getkeyspath(from, to, 3);
+               getkeyspath(dbctx, from, to, 3);
        } else {
-               dofindpath(from, to, true, 3);
+               dofindpath(dbctx, from, to, true, 3);
        }
        destroyhash();
-       config.dbbackend->cleanupdb();
+       dbctx->cleanupdb(dbctx);
        cleanuplogthing();
        cleanupconfig();
 
index 478c20f9453bc5c327353fdba6a585c4b395947f..965eaf9d19ab233c5b6c7b674d6b7237aff6122e 100644 (file)
@@ -47,6 +47,7 @@ int main(int argc, char *argv[])
        uint8_t **hashes;
        struct buffer_ctx cgipostbuf;
        struct openpgp_publickey **keys;
+       struct onak_dbctx *dbctx;
 
        readconfig(NULL);
        initlogthing("hashquery", config.logfile);
@@ -88,15 +89,16 @@ int main(int argc, char *argv[])
                doerror("Couldn't allocate memory for reply.\n");
        }
 
-       if (config.dbbackend->fetch_key_skshash == NULL) {
+       catchsignals();
+       dbctx = config.dbinit(false);
+
+       if (dbctx->fetch_key_skshash == NULL) {
+               dbctx->cleanupdb(dbctx);
                doerror("Can't fetch by skshash with this backend.");
        }
 
-       catchsignals();
-       config.dbbackend->initdb(false);
-
        for (i = 0; i < count; i++) {
-               config.dbbackend->fetch_key_skshash(
+               dbctx->fetch_key_skshash(dbctx,
                                (struct skshash *) hashes[i], &keys[found]);
                if (keys[found] != NULL) {
                        found++;
@@ -107,7 +109,7 @@ int main(int argc, char *argv[])
        free(hashes);
        hashes = NULL;
 
-       config.dbbackend->cleanupdb();
+       dbctx->cleanupdb(dbctx);
 
        puts("Content-Type: pgp/keys\n");
        marshal_array(stdout_putchar, NULL,
diff --git a/keyd.c b/keyd.c
index a89f0e1f37aade33ecf00d4f171f92d191bf1dee..f3966db96dcdbafde6b92b341566b1199da791a7 100644 (file)
--- a/keyd.c
+++ b/keyd.c
@@ -144,7 +144,7 @@ int sock_init(const char *sockname)
        return fd;
 }
 
-int sock_do(int fd)
+int sock_do(struct onak_dbctx *dbctx, int fd)
 {
        uint32_t cmd = KEYD_CMD_UNKNOWN;
        ssize_t  bytes = 0;
@@ -197,8 +197,8 @@ int sock_do(int fd)
                                                "Fetching 0x%" PRIX64
                                                ", result: %d",
                                                keyid,
-                                               config.dbbackend->
-                                               fetch_key_id(keyid,
+                                               dbctx->fetch_key_id(dbctx,
+                                                       keyid,
                                                        &key, false));
                                if (key != NULL) {
                                        storebuf.size = 8192;
@@ -245,8 +245,8 @@ int sock_do(int fd)
                                logthing(LOGTHING_INFO,
                                                "Fetching by fingerprint"
                                                ", result: %d",
-                                               config.dbbackend->
-                                               fetch_key_fp(fp, bytes,
+                                               dbctx->fetch_key_fp(dbctx,
+                                                       fp, bytes,
                                                        &key, false));
                                if (key != NULL) {
                                        storebuf.size = 8192;
@@ -295,8 +295,8 @@ int sock_do(int fd)
                                logthing(LOGTHING_INFO,
                                                "Fetching %s, result: %d",
                                                search,
-                                               config.dbbackend->
-                                               fetch_key_text(search, &key));
+                                               dbctx->fetch_key_text(dbctx,
+                                                       search, &key));
                                if (key != NULL) {
                                        storebuf.size = 8192;
                                        storebuf.buffer = malloc(8192);
@@ -357,7 +357,7 @@ int sock_do(int fd)
                                                &packets,
                                                0);
                                parse_keys(packets, &key);
-                               config.dbbackend->store_key(key, false, false);
+                               dbctx->store_key(dbctx, key, false, false);
                                free_packet_list(packets);
                                packets = NULL;
                                free_publickey(key);
@@ -379,7 +379,7 @@ int sock_do(int fd)
                                                "Deleting 0x%" PRIX64
                                                ", result: %d",
                                                keyid,
-                                               config.dbbackend->delete_key(
+                                               dbctx->delete_key(dbctx,
                                                        keyid, false));
                        }
                        break;
@@ -391,7 +391,7 @@ int sock_do(int fd)
                                ret = 1;
                        }
                        if (ret == 0) {
-                               keyid = config.dbbackend->getfullkeyid(keyid);
+                               keyid = dbctx->getfullkeyid(dbctx, keyid);
                                cmd = sizeof(keyid);
                                write(fd, &cmd, sizeof(cmd));
                                write(fd, &keyid, sizeof(keyid));
@@ -400,7 +400,7 @@ int sock_do(int fd)
                case KEYD_CMD_KEYITER:
                        cmd = KEYD_REPLY_OK;
                        write(fd, &cmd, sizeof(cmd));
-                       config.dbbackend->iterate_keys(iteratefunc,
+                       dbctx->iterate_keys(dbctx, iteratefunc,
                                        &fd);
                        bytes = 0;
                        write(fd, &bytes, sizeof(bytes));
@@ -438,9 +438,8 @@ int sock_do(int fd)
                                logthing(LOGTHING_INFO,
                                                "Fetching by hash"
                                                ", result: %d",
-                                               config.dbbackend->
-                                               fetch_key_skshash(&hash,
-                                                       &key));
+                                               dbctx->fetch_key_skshash(dbctx,
+                                                       &hash, &key));
                                if (key != NULL) {
                                        storebuf.size = 8192;
                                        storebuf.buffer = malloc(8192);
@@ -531,6 +530,7 @@ int main(int argc, char *argv[])
        char *configfile = NULL;
        bool foreground = false;
        int optchar;
+       struct onak_dbctx *dbctx;
 
        while ((optchar = getopt(argc, argv, "c:fh")) != -1 ) {
                switch (optchar) {
@@ -578,7 +578,7 @@ int main(int argc, char *argv[])
                maxfd = fd;
                memset(clients, -1, sizeof (clients));
 
-               config.dbbackend->initdb(false);
+               dbctx = config.dbinit(false);
 
                logthing(LOGTHING_NOTICE, "Accepting connections.");
                while (!cleanup() && select(maxfd + 1, &rfds, NULL, NULL, NULL) != -1) {
@@ -592,7 +592,7 @@ int main(int argc, char *argv[])
                                                FD_ISSET(clients[i], &rfds)) {
                                        logthing(LOGTHING_DEBUG,
                                                "Handling connection for client %d.", i);
-                                       if (sock_do(clients[i])) {
+                                       if (sock_do(dbctx, clients[i])) {
                                                sock_close(clients[i]);
                                                clients[i] = -1;
                                                logthing(LOGTHING_DEBUG,
@@ -626,7 +626,7 @@ int main(int argc, char *argv[])
                                }
                        }
                }
-               config.dbbackend->cleanupdb();
+               dbctx->cleanupdb(dbctx);
                sock_close(fd);
                unlink(sockname);
        }
diff --git a/keydb.c b/keydb.c
index ac70640e26df6bfedcfd7f506a09e30155a75abf..14418fb7a012e86b2de55f494dd941b3654e609e 100644 (file)
--- a/keydb.c
+++ b/keydb.c
  *     keyid2uid - Takes a keyid and returns the primary UID for it.
  *     @keyid: The keyid to lookup.
  */
-char *generic_keyid2uid(uint64_t keyid)
+char *generic_keyid2uid(struct onak_dbctx *dbctx, uint64_t keyid)
 {
        struct openpgp_publickey *publickey = NULL;
        struct openpgp_signedpacket_list *curuid = NULL;
        char buf[1024];
 
        buf[0]=0;
-       if (config.dbbackend->fetch_key_id(keyid, &publickey, false) &&
+       if (dbctx->fetch_key_id(dbctx, keyid, &publickey, false) &&
                        publickey != NULL) {
                curuid = publickey->uids;
                while (curuid != NULL && buf[0] == 0) {
@@ -82,13 +82,14 @@ char *generic_keyid2uid(uint64_t keyid)
  *     indexing and doing stats bits. If revoked is non-NULL then if the key
  *     is revoked it's set to true.
  */
-struct ll *generic_getkeysigs(uint64_t keyid, bool *revoked)
+struct ll *generic_getkeysigs(struct onak_dbctx *dbctx,
+               uint64_t keyid, bool *revoked)
 {
        struct ll *sigs = NULL;
        struct openpgp_signedpacket_list *uids = NULL;
        struct openpgp_publickey *publickey = NULL;
 
-       config.dbbackend->fetch_key_id(keyid, &publickey, false);
+       dbctx->fetch_key_id(dbctx, keyid, &publickey, false);
        
        if (publickey != NULL) {
                for (uids = publickey->uids; uids != NULL; uids = uids->next) {
@@ -112,7 +113,7 @@ struct ll *generic_getkeysigs(uint64_t keyid, bool *revoked)
  *     getkeysigs function above except we use the hash module to cache the
  *     data so if we need it again it's already loaded.
  */
-struct ll *generic_cached_getkeysigs(uint64_t keyid)
+struct ll *generic_cached_getkeysigs(struct onak_dbctx *dbctx, uint64_t keyid)
 {
        struct stats_key *key = NULL;
        struct stats_key *signedkey = NULL;
@@ -127,7 +128,7 @@ struct ll *generic_cached_getkeysigs(uint64_t keyid)
        key = findinhash(keyid);
 
        if (key == NULL || key->gotsigs == false) {
-               sigs = config.dbbackend->getkeysigs(keyid, &revoked);
+               sigs = dbctx->getkeysigs(dbctx, keyid, &revoked);
                if (sigs == NULL) {
                        return NULL;
                }
@@ -155,12 +156,12 @@ struct ll *generic_cached_getkeysigs(uint64_t 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.
  */
-uint64_t generic_getfullkeyid(uint64_t keyid)
+uint64_t generic_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
 {
        struct openpgp_publickey *publickey = NULL;
 
        if (keyid < 0x100000000LL) {
-               config.dbbackend->fetch_key_id(keyid, &publickey, false);
+               dbctx->fetch_key_id(dbctx, keyid, &publickey, false);
                if (publickey != NULL) {
                        get_keyid(publickey, &keyid);
                        free_publickey(publickey);
@@ -186,7 +187,8 @@ uint64_t generic_getfullkeyid(uint64_t keyid)
  *     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.
  */
-int generic_update_keys(struct openpgp_publickey **keys, bool sendsync)
+int generic_update_keys(struct onak_dbctx *dbctx,
+               struct openpgp_publickey **keys, bool sendsync)
 {
        struct openpgp_publickey *curkey = NULL;
        struct openpgp_publickey *oldkey = NULL;
@@ -196,12 +198,12 @@ int generic_update_keys(struct openpgp_publickey **keys, bool sendsync)
        uint64_t keyid;
 
        for (curkey = *keys; curkey != NULL; curkey = curkey->next) {
-               intrans = config.dbbackend->starttrans();
+               intrans = dbctx->starttrans(dbctx);
                get_keyid(curkey, &keyid);
                logthing(LOGTHING_INFO,
                        "Fetching key 0x%" PRIX64 ", result: %d",
                        keyid,
-                       config.dbbackend->fetch_key_id(keyid, &oldkey,
+                       dbctx->fetch_key_id(dbctx, keyid, &oldkey,
                                        intrans));
 
                /*
@@ -227,7 +229,7 @@ int generic_update_keys(struct openpgp_publickey **keys, bool sendsync)
                                prev = curkey;
                                logthing(LOGTHING_INFO,
                                        "Merged key; storing updated key.");
-                               config.dbbackend->store_key(oldkey, intrans,
+                               dbctx->store_key(dbctx, oldkey, intrans,
                                        true);
                        }
                        free_publickey(oldkey);
@@ -235,10 +237,10 @@ int generic_update_keys(struct openpgp_publickey **keys, bool sendsync)
                } else {
                        logthing(LOGTHING_INFO,
                                "Storing completely new key.");
-                       config.dbbackend->store_key(curkey, intrans, false);
+                       dbctx->store_key(dbctx, curkey, intrans, false);
                        newkeys++;
                }
-               config.dbbackend->endtrans();
+               dbctx->endtrans(dbctx);
                intrans = false;
        }
 
@@ -251,8 +253,9 @@ int generic_update_keys(struct openpgp_publickey **keys, bool sendsync)
 #endif /* NEED_UPDATEKEYS */
 
 #ifdef NEED_GET_FP
-static int generic_fetch_key_fp(uint8_t *fp, size_t fpsize,
-               struct openpgp_publickey **publickey, bool intrans)
+static int generic_fetch_key_fp(struct onak_dbctx *dbctx,
+               uint8_t *fp, size_t fpsize,
+               struct openpgp_publickey **publickey, bool intrans)
 {
        uint64_t keyid;
        int i;
@@ -273,6 +276,6 @@ static int generic_fetch_key_fp(uint8_t *fp, size_t fpsize,
                keyid = (keyid << 8) + fp[i];
        }
 
-       return config.dbbackend->fetch_key_id(keyid, publickey, intrans);
+       return dbctx->fetch_key_id(dbctx, keyid, publickey, intrans);
 }
 #endif
diff --git a/keydb.h b/keydb.h
index 6ad9a59fb46403d6da242bb5559681fa5dca1d34..50f969a303831c5f8cbc27c77d5eb0568f40f29a 100644 (file)
--- a/keydb.h
+++ b/keydb.h
 #include "ll.h"
 
 /**
- * @brief All of the functions a DB backend exports.
+ * @brief Context for a database backend
  */
-struct dbfuncs {
-/**
- * @brief Initialize the key database.
- * @param readonly If we'll only be reading the DB, not writing to it.
- *
- * This function should be called before any of the other functions in
- * this file are called in order to allow the DB to be initialized ready
- * for access.
- */
-       void (*initdb)(bool readonly);
-
+struct onak_dbctx {
 /**
  * @brief De-initialize the key database.
  *
  * This function should be called upon program exit to allow the DB to
  * cleanup after itself.
  */
-       void (*cleanupdb)(void);
+       void (*cleanupdb)(struct onak_dbctx *);
 
 /**
  * @brief Start a transaction.
@@ -55,14 +45,14 @@ struct dbfuncs {
  * operations on the database to help speed it all up, or if we want
  * something to only succeed if all relevant operations are successful.
  */
-       bool (*starttrans)(void);
+       bool (*starttrans)(struct onak_dbctx *);
 
 /**
  * @brief End a transaction.
  *
  * Ends a transaction.
  */
-       void (*endtrans)(void);
+       void (*endtrans)(struct onak_dbctx *);
 
 /**
  * @brief Given a keyid fetch the key from storage.
@@ -75,7 +65,8 @@ struct dbfuncs {
  *
  * TODO: What about keyid collisions? Should we use fingerprint instead?
  */
-       int (*fetch_key_id)(uint64_t keyid,
+       int (*fetch_key_id)(struct onak_dbctx *,
+                       uint64_t keyid,
                        struct openpgp_publickey **publickey,
                        bool intrans);
 
@@ -89,7 +80,8 @@ struct dbfuncs {
  * This function returns a public key from whatever storage mechanism we
  * are using.
  */
-       int (*fetch_key_fp)(uint8_t *fp,
+       int (*fetch_key_fp)(struct onak_dbctx *,
+                       uint8_t *fp,
                        size_t fpsize,
                        struct openpgp_publickey **publickey,
                        bool intrans);
@@ -107,7 +99,8 @@ struct dbfuncs {
  *
  * TODO: Do we store multiple keys of the same id? Or only one and replace it?
  */
-       int (*store_key)(struct openpgp_publickey *publickey, bool intrans,
+       int (*store_key)(struct onak_dbctx *,
+                       struct openpgp_publickey *publickey, bool intrans,
                        bool update);
 
 /**
@@ -118,7 +111,7 @@ struct dbfuncs {
  * This function deletes a public key from whatever storage mechanism we
  * are using. Returns 0 if the key existed.
  */
-       int (*delete_key)(uint64_t keyid, bool intrans);
+       int (*delete_key)(struct onak_dbctx *, uint64_t keyid, bool intrans);
 
 /**
  * @brief Trys to find the keys that contain the supplied text.
@@ -128,7 +121,7 @@ struct dbfuncs {
  * This function searches for the supplied text and returns the keys that
  * contain it.
  */
-       int (*fetch_key_text)(const char *search,
+       int (*fetch_key_text)(struct onak_dbctx *, const char *search,
                        struct openpgp_publickey **publickey);
 
 /**
@@ -139,7 +132,8 @@ struct dbfuncs {
  * This function looks for the key that is referenced by the supplied
  * SKS hash and returns it.
  */
-       int (*fetch_key_skshash)(const struct skshash *hash,
+       int (*fetch_key_skshash)(struct onak_dbctx *,
+                       const struct skshash *hash,
                        struct openpgp_publickey **publickey);
 
 /**
@@ -156,7 +150,8 @@ struct dbfuncs {
  * If sendsync is true then we send out a keysync mail to our sync peers
  * with the update.
  */
-       int (*update_keys)(struct openpgp_publickey **keys, bool sendsync);
+       int (*update_keys)(struct onak_dbctx *,
+                       struct openpgp_publickey **keys, bool sendsync);
 
 /**
  * @brief Takes a keyid and returns the primary UID for it.
@@ -165,7 +160,7 @@ struct dbfuncs {
  * This function returns a UID for the given key. Returns NULL if the key
  * isn't found.
  */
-       char * (*keyid2uid)(uint64_t keyid);
+       char * (*keyid2uid)(struct onak_dbctx *, uint64_t keyid);
 
 /**
  * @brief Gets a linked list of the signatures on a key.
@@ -176,7 +171,8 @@ struct dbfuncs {
  * indexing and doing stats bits. If revoked is non-NULL then if the key
  * is revoked it's set to true.
  */
-       struct ll * (*getkeysigs)(uint64_t keyid, bool *revoked);
+       struct ll * (*getkeysigs)(struct onak_dbctx *,
+                       uint64_t keyid, bool *revoked);
 
 /**
  * @brief Gets the signatures on a key.
@@ -185,7 +181,8 @@ struct dbfuncs {
  * 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
  */
-       struct ll * (*cached_getkeysigs)(uint64_t keyid);
+       struct ll * (*cached_getkeysigs)(struct onak_dbctx *,
+                       uint64_t keyid);
 
 /**
  * @brief Maps a 32 bit key id to a 64 bit one.
@@ -194,7 +191,7 @@ struct dbfuncs {
  * This function maps a 32 bit key id to the full 64 bit one. It returns the
  * full keyid. If the key isn't found a keyid of 0 is returned.
  */
-       uint64_t (*getfullkeyid)(uint64_t keyid);
+       uint64_t (*getfullkeyid)(struct onak_dbctx *, uint64_t keyid);
 
 /**
  * @brief call a function once for each key in the db.
@@ -207,8 +204,14 @@ struct dbfuncs {
  *
  * Returns the number of keys we iterated over.
  */
-       int (*iterate_keys)(void (*iterfunc)(void *ctx,
+       int (*iterate_keys)(struct onak_dbctx *,
+                       void (*iterfunc)(void *ctx,
                        struct openpgp_publickey *key), void *ctx);
+
+/**
+ * @brief Private backend context information.
+ */
+       void *priv;
 };
 
 #endif /* __KEYDB_H__ */
index dae8a2a91f8f9ad830908baa82a405b500d7f559..9d5dd9009fcf85f2e4e27e04983e598260b11b5c 100644 (file)
 
 #define DB4_UPGRADE_FILE "db_upgrade.lck"
 
-/**
- *     dbenv - our database environment.
- */
-static DB_ENV *dbenv = NULL;
-
-/**
- *     numdb - The number of database files we have.
- */
-static int numdbs = 16;
-
-/**
- *     dbconn - our connections to the key database files.
- */
-static DB **dbconns = NULL;
-
-/**
- *     worddb - our connection to the word database.
- */
-static DB *worddb = NULL;
-
-/**
- *     id32db - our connection to the 32bit ID database.
- */
-static DB *id32db = NULL;
-
-/**
- *     skshashdb - our connection to the SKS hash database.
- */
-static DB *skshashdb = NULL;
-
-/**
- *     subkeydb - our connection to the subkey ID lookup database.
- */
-static DB *subkeydb = NULL;
-
-/**
- *     txn - our current transaction id.
- */
-static DB_TXN *txn = NULL;
+struct onak_db4_dbctx {
+       DB_ENV *dbenv;  /* The database environment context */
+       int numdbs;     /* Number of data databases in use */
+       DB **dbconns;   /* Connections to the key data databases */
+       DB *worddb;     /* Connection to the word lookup database */
+       DB *id32db;     /* Connection to the 32 bit ID lookup database */
+       DB *skshashdb;  /* Connection to the SKS hash database */
+       DB *subkeydb;   /* Connection to the subkey ID lookup database */
+       DB_TXN *txn;    /* Our current transaction ID */
+};
 
-DB *keydb(uint64_t keyid)
+DB *keydb(struct onak_db4_dbctx *privctx, uint64_t keyid)
 {
        uint64_t keytrun;
 
        keytrun = keyid >> 8;
 
-       return(dbconns[keytrun % numdbs]);
+       return(privctx->dbconns[keytrun % privctx->numdbs]);
 }
 
 /**
@@ -122,16 +93,17 @@ static void db4_errfunc(const DB_ENV *edbenv, const char *errpfx,
  *     operations on the database to help speed it all up, or if we want
  *     something to only succeed if all relevant operations are successful.
  */
-static bool db4_starttrans(void)
+static bool db4_starttrans(struct onak_dbctx *dbctx)
 {
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        int ret;
 
-       log_assert(dbenv != NULL);
-       log_assert(txn == NULL);
+       log_assert(privctx->dbenv != NULL);
+       log_assert(privctx->txn == NULL);
 
-       ret = dbenv->txn_begin(dbenv,
+       ret = privctx->dbenv->txn_begin(privctx->dbenv,
                NULL, /* No parent transaction */
-               &txn,
+               &privctx->txn,
                0);
        if (ret != 0) {
                logthing(LOGTHING_CRITICAL,
@@ -148,14 +120,15 @@ static bool db4_starttrans(void)
  *
  *     Ends a transaction.
  */
-static void db4_endtrans(void)
+static void db4_endtrans(struct onak_dbctx *dbctx)
 {
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        int ret;
 
-       log_assert(dbenv != NULL);
-       log_assert(txn != NULL);
+       log_assert(privctx->dbenv != NULL);
+       log_assert(privctx->txn != NULL);
 
-       ret = txn->commit(txn,
+       ret = privctx->txn->commit(privctx->txn,
                0);
        if (ret != 0) {
                logthing(LOGTHING_CRITICAL,
@@ -163,52 +136,11 @@ static void db4_endtrans(void)
                                db_strerror(ret));
                exit(1);
        }
-       txn = NULL;
+       privctx->txn = NULL;
 
        return;
 }
 
-/**
- *     cleanupdb - De-initialize the key database.
- *
- *     This function should be called upon program exit to allow the DB to
- *     cleanup after itself.
- */
-static void db4_cleanupdb(void)
-{
-       int i = 0;
-
-       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;
-               }
-               if (id32db != NULL) {
-                       id32db->close(id32db, 0);
-                       id32db = NULL;
-               }
-               if (worddb != NULL) {
-                       worddb->close(worddb, 0);
-                       worddb = NULL;
-               }
-               for (i = 0; i < numdbs; i++) {
-                       if (dbconns[i] != NULL) {
-                               dbconns[i]->close(dbconns[i], 0);
-                               dbconns[i] = NULL;
-                       }
-               }
-               free(dbconns);
-               dbconns = NULL;
-               dbenv->close(dbenv, 0);
-               dbenv = NULL;
-       }
-}
-
 /**
  *     db4_upgradedb - Upgrade a DB4 database
  *
@@ -216,7 +148,7 @@ static void db4_cleanupdb(void)
  *     we're running with a newer version of db4 than the database was
  *     created with.
  */
-static int db4_upgradedb(int numdb)
+static int db4_upgradedb(struct onak_db4_dbctx *privctx)
 {
        DB *curdb = NULL;
        int ret;
@@ -243,11 +175,11 @@ static int db4_upgradedb(int numdb)
        close(lockfile_fd);
 
        logthing(LOGTHING_NOTICE, "Upgrading DB4 database");
-       ret = db_env_create(&dbenv, 0);
-       dbenv->set_errcall(dbenv, &db4_errfunc);
-       dbenv->remove(dbenv, config.db_dir, 0);
-       dbenv = NULL;
-       for (i = 0; i < numdb; i++) {
+       ret = db_env_create(&privctx->dbenv, 0);
+       privctx->dbenv->set_errcall(privctx->dbenv, &db4_errfunc);
+       privctx->dbenv->remove(privctx->dbenv, config.db_dir, 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",
@@ -318,372 +250,100 @@ static int db4_upgradedb(int numdb)
 }
 
 /**
- *     initdb - Initialize the key database.
+ *     getfullkeyid - Maps a 32bit key id to a 64bit one.
+ *     @keyid: The 32bit keyid.
  *
- *     This function should be called before any of the other functions in
- *     this file are called in order to allow the DB to be initialized ready
- *     for access.
+ *     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 void db4_initdb(bool readonly)
+static uint64_t db4_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
 {
-       char       buf[1024];
-       FILE      *numdb = NULL;
-       int        ret = 0;
-       int        i = 0;
-       uint32_t   flags = 0;
-       struct stat statbuf;
-       int        maxlocks;
-
-       snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir,
-                       DB4_UPGRADE_FILE);
-       ret = stat(buf, &statbuf);
-       while ((ret == 0) || (errno != ENOENT)) {
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL, "Couldn't stat upgrade "
-                               "lock file: %s (%d)", strerror(errno), ret);
-                       exit(1);
-               }
-               logthing(LOGTHING_DEBUG, "DB4 upgrade in progress; waiting.");
-               sleep(5);
-               ret = stat(buf, &statbuf);
-       }
-       ret = 0;
-
-       snprintf(buf, sizeof(buf) - 1, "%s/num_keydb", config.db_dir);
-       numdb = fopen(buf, "r");
-       if (numdb != NULL) {
-               if (fgets(buf, sizeof(buf), numdb) != NULL) {
-                       numdbs = atoi(buf);
-               }
-               fclose(numdb);
-       } else if (!readonly) {
-               logthing(LOGTHING_ERROR, "Couldn't open num_keydb: %s",
-                               strerror(errno));
-               numdb = fopen(buf, "w");
-               if (numdb != NULL) {
-                       fprintf(numdb, "%d", numdbs);
-                       fclose(numdb);
-               } else {
-                       logthing(LOGTHING_ERROR,
-                               "Couldn't write num_keydb: %s",
-                               strerror(errno));
-               }
-       }
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
+       DBT       key, data;
+       DBC      *cursor = NULL;
+       uint32_t  shortkeyid = 0;
+       int       ret = 0;
 
-       dbconns = calloc(numdbs, sizeof (DB *));
-       if (dbconns == NULL) {
-               logthing(LOGTHING_CRITICAL,
-                               "Couldn't allocate memory for dbconns");
-               ret = 1;
-       }
+       if (keyid < 0x100000000LL) {
+               ret = privctx->id32db->cursor(privctx->id32db,
+                               privctx->txn,
+                               &cursor,
+                               0);   /* flags */
 
-       if (ret == 0) {
-               ret = db_env_create(&dbenv, 0);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL,
-                               "db_env_create: %s", db_strerror(ret));
-               }
-       }
+               shortkeyid = keyid & 0xFFFFFFFF;
 
-       /*
-        * 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);
+               memset(&key, 0, sizeof(key));
+               memset(&data, 0, sizeof(data));
+               key.data = &shortkeyid;
+               key.size = sizeof(shortkeyid);
+               data.flags = DB_DBT_MALLOC;
 
-       /*
-        * 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
-        * sure how to make the standard DB functions do that yet.
-        */
-       if (ret == 0) {
-               dbenv->set_errcall(dbenv, &db4_errfunc);
-               ret = dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL,
-                               "db_env_create: %s", db_strerror(ret));
-               }
-       }
+               ret = cursor->c_get(cursor,
+                       &key,
+                       &data,
+                       DB_SET);
 
-       if (ret == 0) {
-               ret = dbenv->open(dbenv, config.db_dir,
-                               DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK |
-                               DB_INIT_TXN |
-                               DB_CREATE,
-                               0);
-#ifdef DB_VERSION_MISMATCH
-               if (ret == DB_VERSION_MISMATCH) {
-                       dbenv->close(dbenv, 0);
-                       dbenv = NULL;
-                       ret = db4_upgradedb(numdbs);
-                       if (ret == 0) {
-                               ret = db_env_create(&dbenv, 0);
-                       }
-                       if (ret == 0) {
-                               dbenv->set_errcall(dbenv, &db4_errfunc);
-                               dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT);
-                               ret = dbenv->open(dbenv, config.db_dir,
-                                       DB_INIT_LOG | DB_INIT_MPOOL |
-                                       DB_INIT_LOCK | DB_INIT_TXN |
-                                       DB_CREATE | DB_RECOVER,
-                                       0);
+               if (ret == 0) {
+                       keyid = *(uint64_t *) data.data;
 
-                               if (ret == 0) {
-                                       dbenv->txn_checkpoint(dbenv,
-                                                       0,
-                                                       0,
-                                                       DB_FORCE);
-                               }
+                       if (data.data != NULL) {
+                               free(data.data);
+                               data.data = NULL;
                        }
                }
-#endif
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL,
-                                       "Error opening db environment: %s (%s)",
-                                       config.db_dir,
-                                       db_strerror(ret));
-                       dbenv->close(dbenv, 0);
-                       dbenv = NULL;
-               }
-       }
 
-       if (ret == 0) {
-               db4_starttrans();
+               ret = cursor->c_close(cursor);
+               cursor = NULL;
+       }
 
-               for (i = 0; !ret && i < numdbs; i++) {
-                       ret = db_create(&dbconns[i], dbenv, 0);
-                       if (ret != 0) {
-                               logthing(LOGTHING_CRITICAL,
-                                       "db_create: %s", db_strerror(ret));
-                       }
+       return keyid;
+}
 
-                       if (ret == 0) {
-                               snprintf(buf, 1023, "keydb.%d.db", i);
-                               flags = DB_CREATE;
-                               if (readonly) {
-                                       flags = DB_RDONLY;
-                               }
-                               ret = dbconns[i]->open(dbconns[i],
-                                               txn,
-                                               buf,
-                                               "keydb",
-                                               DB_HASH,
-                                               flags,
-                                               0664);
-                               if (ret != 0) {
-                                       logthing(LOGTHING_CRITICAL,
-                                               "Error opening key database:"
-                                               " %s (%s)",
-                                               buf,
-                                               db_strerror(ret));
-                               }
-                       }
-               }
+/**
+ *     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.
+ *
+ *     We use the hex representation of the keyid as the filename to fetch the
+ *     key from. The key is stored in the file as a binary OpenPGP stream of
+ *     packets, so we can just use read_openpgp_stream() to read the packets
+ *     in and then parse_keys() to parse the packets into a publickey
+ *     structure.
+ */
+static int db4_fetch_key_id(struct onak_dbctx *dbctx, uint64_t keyid,
+               struct openpgp_publickey **publickey,
+               bool intrans)
+{
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
+       struct openpgp_packet_list *packets = NULL;
+       DBT key, data;
+       int ret = 0;
+       int numkeys = 0;
+       struct buffer_ctx fetchbuf;
 
+       if (keyid < 0x100000000LL) {
+               keyid = db4_getfullkeyid(dbctx, keyid);
        }
 
-       if (ret == 0) {
-               ret = db_create(&worddb, dbenv, 0);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL, "db_create: %s",
-                                       db_strerror(ret));
-               }
-       }
+       memset(&key, 0, sizeof(key));
+       memset(&data, 0, sizeof(data));
 
-       if (ret == 0) {
-               ret = worddb->set_flags(worddb, DB_DUP);
-       }
+       data.size = 0;
+       data.data = NULL;
 
-       if (ret == 0) {
-               ret = worddb->open(worddb, txn, "worddb", "worddb", DB_BTREE,
-                               flags,
-                               0664);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL,
-                                       "Error opening word database: %s (%s)",
-                                       "worddb",
-                                       db_strerror(ret));
-               }
-       }
+       key.size = sizeof(keyid);
+       key.data = &keyid;
 
-       if (ret == 0) {
-               ret = db_create(&id32db, dbenv, 0);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL, "db_create: %s",
-                                       db_strerror(ret));
-               }
+       if (!intrans) {
+               db4_starttrans(dbctx);
        }
 
-       if (ret == 0) {
-               ret = id32db->set_flags(id32db, DB_DUP);
-       }
-
-       if (ret == 0) {
-               ret = id32db->open(id32db, txn, "id32db", "id32db", DB_HASH,
-                               flags,
-                               0664);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL,
-                                       "Error opening id32 database: %s (%s)",
-                                       "id32db",
-                                       db_strerror(ret));
-               }
-       }
-
-       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 (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();
-       }
-
-       if (ret != 0) {
-               db4_cleanupdb();
-               logthing(LOGTHING_CRITICAL,
-                               "Error opening database; exiting");
-               exit(EXIT_FAILURE);
-       }
-       
-       return;
-}
-
-/**
- *     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 db4_getfullkeyid(uint64_t keyid)
-{
-       DBT       key, data;
-       DBC      *cursor = NULL;
-       uint32_t  shortkeyid = 0;
-       int       ret = 0;
-
-       if (keyid < 0x100000000LL) {
-               ret = id32db->cursor(id32db,
-                               txn,
-                               &cursor,
-                               0);   /* flags */
-
-               shortkeyid = keyid & 0xFFFFFFFF;
-
-               memset(&key, 0, sizeof(key));
-               memset(&data, 0, sizeof(data));
-               key.data = &shortkeyid;
-               key.size = sizeof(shortkeyid);
-               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 keyid;
-}
-
-/**
- *     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.
- *
- *     We use the hex representation of the keyid as the filename to fetch the
- *     key from. The key is stored in the file as a binary OpenPGP stream of
- *     packets, so we can just use read_openpgp_stream() to read the packets
- *     in and then parse_keys() to parse the packets into a publickey
- *     structure.
- */
-static int db4_fetch_key_id(uint64_t keyid,
-               struct openpgp_publickey **publickey,
-               bool intrans)
-{
-       struct openpgp_packet_list *packets = NULL;
-       DBT key, data;
-       int ret = 0;
-       int numkeys = 0;
-       struct buffer_ctx fetchbuf;
-
-       if (keyid < 0x100000000LL) {
-               keyid = db4_getfullkeyid(keyid);
-       }
-
-       memset(&key, 0, sizeof(key));
-       memset(&data, 0, sizeof(data));
-
-       data.size = 0;
-       data.data = NULL;
-
-       key.size = sizeof(keyid);
-       key.data = &keyid;
-
-       if (!intrans) {
-               db4_starttrans();
-       }
-
-       ret = keydb(keyid)->get(keydb(keyid),
-                       txn,
-                       &key,
-                       &data,
-                       0); /* flags*/
+       ret = keydb(privctx, keyid)->get(keydb(privctx, keyid),
+                       privctx->txn,
+                       &key,
+                       &data,
+                       0); /* flags*/
 
        if (ret == DB_NOTFOUND) {
                /* If we didn't find the key ID see if it's a subkey ID */
@@ -694,8 +354,8 @@ static int db4_fetch_key_id(uint64_t keyid,
                key.size = sizeof(keyid);
                key.data = &keyid;
 
-               ret = subkeydb->get(subkeydb,
-                       txn,
+               ret = privctx->subkeydb->get(privctx->subkeydb,
+                       privctx->txn,
                        &key,
                        &data,
                        0); /* flags*/
@@ -711,8 +371,8 @@ static int db4_fetch_key_id(uint64_t keyid,
                        key.size = sizeof(keyid);
                        key.data = &keyid;
 
-                       ret = keydb(keyid)->get(keydb(keyid),
-                               txn,
+                       ret = keydb(privctx, keyid)->get(keydb(privctx, keyid),
+                               privctx->txn,
                                &key,
                                &data,
                                0); /* flags*/
@@ -736,7 +396,7 @@ static int db4_fetch_key_id(uint64_t keyid,
        }
 
        if (!intrans) {
-               db4_endtrans();
+               db4_endtrans(dbctx);
        }
 
        return (numkeys);
@@ -755,9 +415,10 @@ int worddb_cmp(const void *d1, const void *d2)
  *     This function searches for the supplied text and returns the keys that
  *     contain it.
  */
-static int db4_fetch_key_text(const char *search,
+static int db4_fetch_key_text(struct onak_dbctx *dbctx, const char *search,
                struct openpgp_publickey **publickey)
 {
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        DBC *cursor = NULL;
        DBT key, data;
        int ret;
@@ -776,10 +437,10 @@ static int db4_fetch_key_text(const char *search,
        wordlist = makewordlist(wordlist, searchtext);
 
        for (curword = wordlist; curword != NULL; curword = curword->next) {
-               db4_starttrans();
+               db4_starttrans(dbctx);
 
-               ret = worddb->cursor(worddb,
-                               txn,
+               ret = privctx->worddb->cursor(privctx->worddb,
+                               privctx->txn,
                                &cursor,
                                0);   /* flags */
 
@@ -830,7 +491,7 @@ static int db4_fetch_key_text(const char *search,
                ret = cursor->c_close(cursor);
                cursor = NULL;
                firstpass = 0;
-               db4_endtrans();
+               db4_endtrans(dbctx);
        }
        llfree(wordlist, NULL);
        wordlist = NULL;
@@ -838,10 +499,10 @@ static int db4_fetch_key_text(const char *search,
        if (keylist.count > config.maxkeys) {
                keylist.count = config.maxkeys;
        }
-       
-       db4_starttrans();
+
+       db4_starttrans(dbctx);
        for (i = 0; i < keylist.count; i++) {
-               numkeys += db4_fetch_key_id(keylist.keys[i],
+               numkeys += db4_fetch_key_id(dbctx, keylist.keys[i],
                        publickey,
                        true);
        }
@@ -849,21 +510,23 @@ static int db4_fetch_key_text(const char *search,
        free(searchtext);
        searchtext = NULL;
 
-       db4_endtrans();
-       
+       db4_endtrans(dbctx);
+
        return (numkeys);
 }
 
-static int db4_fetch_key_skshash(const struct skshash *hash,
+static int db4_fetch_key_skshash(struct onak_dbctx *dbctx,
+               const struct skshash *hash,
                struct openpgp_publickey **publickey)
 {
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        DBT       key, data;
        DBC      *cursor = NULL;
        uint64_t  keyid = 0;
        int       ret = 0;
 
-       ret = skshashdb->cursor(skshashdb,
-                       txn,
+       ret = privctx->skshashdb->cursor(privctx->skshashdb,
+                       privctx->txn,
                        &cursor,
                        0);   /* flags */
 
@@ -890,7 +553,7 @@ static int db4_fetch_key_skshash(const struct skshash *hash,
        ret = cursor->c_close(cursor);
        cursor = NULL;
 
-       return db4_fetch_key_id(keyid, publickey, false);
+       return db4_fetch_key_id(dbctx, keyid, publickey, false);
 }
 
 /**
@@ -901,8 +564,10 @@ static int db4_fetch_key_skshash(const struct skshash *hash,
  *     This function deletes a public key from whatever storage mechanism we
  *     are using. Returns 0 if the key existed.
  */
-static int db4_delete_key(uint64_t keyid, bool intrans)
+static int db4_delete_key(struct onak_dbctx *dbctx,
+               uint64_t keyid, bool intrans)
 {
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        struct openpgp_publickey *publickey = NULL;
        DBT key, data;
        DBC *cursor = NULL;
@@ -919,10 +584,10 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
        struct skshash hash;
 
        if (!intrans) {
-               db4_starttrans();
+               db4_starttrans(dbctx);
        }
 
-       db4_fetch_key_id(keyid, &publickey, true);
+       db4_fetch_key_id(dbctx, keyid, &publickey, true);
 
        /*
         * Walk through the uids removing the words from the worddb.
@@ -934,9 +599,9 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
                for (i = 0; ret == 0 && uids[i] != NULL; i++) {
                        wordlist = makewordlist(wordlist, uids[i]);
                }
-                               
-               ret = worddb->cursor(worddb,
-                       txn,
+
+               ret = privctx->worddb->cursor(privctx->worddb,
+                       privctx->txn,
                        &cursor,
                        0);   /* flags */
 
@@ -989,8 +654,8 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
                ret = cursor->c_close(cursor);
                cursor = NULL;
 
-               ret = skshashdb->cursor(skshashdb,
-                       txn,
+               ret = privctx->skshashdb->cursor(privctx->skshashdb,
+                       privctx->txn,
                        &cursor,
                        0);   /* flags */
                get_skshash(publickey, &hash);
@@ -1040,8 +705,8 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
        }
 
        if (!deadlock) {
-               ret = id32db->cursor(id32db,
-                       txn,
+               ret = privctx->id32db->cursor(privctx->id32db,
+                       privctx->txn,
                        &cursor,
                        0);   /* flags */
 
@@ -1080,7 +745,8 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
                        memset(&key, 0, sizeof(key));
                        key.data = &subkeyids[i];
                        key.size = sizeof(subkeyids[i]);
-                       subkeydb->del(subkeydb, txn, &key, 0);
+                       privctx->subkeydb->del(privctx->subkeydb,
+                                       privctx->txn, &key, 0);
                        if (ret != 0) {
                                logthing(LOGTHING_ERROR,
                                        "Problem deleting subkey id: %s "
@@ -1134,14 +800,14 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
                key.data = &keyid;
                key.size = sizeof(keyid);
 
-               keydb(keyid)->del(keydb(keyid),
-                               txn,
+               keydb(privctx, keyid)->del(keydb(privctx, keyid),
+                               privctx->txn,
                                &key,
                                0); /* flags */
        }
 
        if (!intrans) {
-               db4_endtrans();
+               db4_endtrans(dbctx);
        }
 
        return deadlock ? (-1) : (ret == DB_NOTFOUND);
@@ -1159,9 +825,11 @@ static int db4_delete_key(uint64_t keyid, bool intrans)
  *     the file. If update is true then we delete the old key first, otherwise
  *     we trust that it doesn't exist.
  */
-static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
+static int db4_store_key(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *publickey, bool intrans,
                bool update)
 {
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        struct     openpgp_packet_list *packets = NULL;
        struct     openpgp_packet_list *list_end = NULL;
        struct     openpgp_publickey *next = NULL;
@@ -1187,7 +855,7 @@ static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
        }
 
        if (!intrans) {
-               db4_starttrans();
+               db4_starttrans(dbctx);
        }
 
        /*
@@ -1199,7 +867,7 @@ static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
         * it definitely needs updated.
         */
        if (update) {
-               deadlock = (db4_delete_key(keyid, true) == -1);
+               deadlock = (db4_delete_key(dbctx, keyid, true) == -1);
        }
 
        /*
@@ -1211,10 +879,10 @@ static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
                flatten_publickey(publickey, &packets, &list_end);
                publickey->next = next;
 
-               storebuf.offset = 0; 
+               storebuf.offset = 0;
                storebuf.size = 8192;
                storebuf.buffer = malloc(8192);
-       
+
                write_openpgp_stream(buffer_putchar, &storebuf, packets);
 
                /*
@@ -1228,8 +896,8 @@ static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
                data.size = storebuf.offset;
                data.data = storebuf.buffer;
 
-               ret = keydb(keyid)->put(keydb(keyid),
-                               txn,
+               ret = keydb(privctx, keyid)->put(keydb(privctx, keyid),
+                               privctx->txn,
                                &key,
                                &data,
                                0); /* flags*/
@@ -1245,8 +913,8 @@ static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
                free(storebuf.buffer);
                storebuf.buffer = NULL;
                storebuf.size = 0;
-               storebuf.offset = 0; 
-       
+               storebuf.offset = 0;
+
                free_packet_list(packets);
                packets = NULL;
        }
@@ -1286,9 +954,9 @@ static int db4_store_key(struct openpgp_publickey *publickey, 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; 
-                       ret = worddb->put(worddb,
-                               txn,
+                       worddb_data[11] = keyid & 0xFF;
+                       ret = privctx->worddb->put(privctx->worddb,
+                               privctx->txn,
                                &key,
                                &data,
                                0);
@@ -1328,8 +996,8 @@ static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
                data.data = &keyid;
                data.size = sizeof(keyid);
 
-               ret = id32db->put(id32db,
-                       txn,
+               ret = privctx->id32db->put(privctx->id32db,
+                       privctx->txn,
                        &key,
                        &data,
                        0);
@@ -1355,8 +1023,8 @@ static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
                        data.data = &keyid;
                        data.size = sizeof(keyid);
 
-                       ret = subkeydb->put(subkeydb,
-                               txn,
+                       ret = privctx->subkeydb->put(privctx->subkeydb,
+                               privctx->txn,
                                &key,
                                &data,
                                0);
@@ -1379,8 +1047,8 @@ static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
                        data.data = &keyid;
                        data.size = sizeof(keyid);
 
-                       ret = id32db->put(id32db,
-                               txn,
+                       ret = privctx->id32db->put(privctx->id32db,
+                               privctx->txn,
                                &key,
                                &data,
                                0);
@@ -1408,8 +1076,8 @@ static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
                data.data = &keyid;
                data.size = sizeof(keyid);
 
-               ret = skshashdb->put(skshashdb,
-                       txn,
+               ret = privctx->skshashdb->put(privctx->skshashdb,
+                       privctx->txn,
                        &key,
                        &data,
                        0);
@@ -1424,7 +1092,7 @@ static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
        }
 
        if (!intrans) {
-               db4_endtrans();
+               db4_endtrans(dbctx);
        }
 
        return deadlock ? -1 : 0 ;
@@ -1441,9 +1109,11 @@ static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
  *
  *     Returns the number of keys we iterated over.
  */
-static int db4_iterate_keys(void (*iterfunc)(void *ctx,
-               struct openpgp_publickey *key), void *ctx)
+static int db4_iterate_keys(struct onak_dbctx *dbctx,
+               void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
+               void *ctx)
 {
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        DBT                         dbkey, data;
        DBC                        *cursor = NULL;
        int                         ret = 0;
@@ -1453,8 +1123,8 @@ static int db4_iterate_keys(void (*iterfunc)(void *ctx,
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_publickey   *key = NULL;
 
-       for (i = 0; i < numdbs; i++) {
-               ret = dbconns[i]->cursor(dbconns[i],
+       for (i = 0; i < privctx->numdbs; i++) {
+               ret = privctx->dbconns[i]->cursor(privctx->dbconns[i],
                        NULL,
                        &cursor,
                        0);   /* flags */
@@ -1471,12 +1141,12 @@ static int db4_iterate_keys(void (*iterfunc)(void *ctx,
                        parse_keys(packets, &key);
 
                        iterfunc(ctx, key);
-                       
+
                        free_publickey(key);
                        key = NULL;
                        free_packet_list(packets);
                        packets = NULL;
-                       
+
                        memset(&dbkey, 0, sizeof(dbkey));
                        memset(&data, 0, sizeof(data));
                        ret = cursor->c_get(cursor, &dbkey, &data,
@@ -1492,7 +1162,7 @@ static int db4_iterate_keys(void (*iterfunc)(void *ctx,
                ret = cursor->c_close(cursor);
                cursor = NULL;
        }
-       
+
        return numkeys;
 }
 
@@ -1505,21 +1175,363 @@ static int db4_iterate_keys(void (*iterfunc)(void *ctx,
 #define NEED_GET_FP 1
 #include "keydb.c"
 
-struct dbfuncs keydb_db4_funcs = {
-       .initdb                 = db4_initdb,
-       .cleanupdb              = db4_cleanupdb,
-       .starttrans             = db4_starttrans,
-       .endtrans               = db4_endtrans,
-       .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,
-       .update_keys            = generic_update_keys,
-       .delete_key             = db4_delete_key,
-       .getkeysigs             = generic_getkeysigs,
-       .cached_getkeysigs      = generic_cached_getkeysigs,
-       .keyid2uid              = generic_keyid2uid,
-       .getfullkeyid           = db4_getfullkeyid,
-       .iterate_keys           = db4_iterate_keys,
-};
+/**
+ *     cleanupdb - De-initialize the key database.
+ *
+ *     This function should be called upon program exit to allow the DB to
+ *     cleanup after itself.
+ */
+static void db4_cleanupdb(struct onak_dbctx *dbctx)
+{
+       struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
+       int i = 0;
+
+       if (privctx->dbenv != NULL) {
+               privctx->dbenv->txn_checkpoint(privctx->dbenv, 0, 0, 0);
+               if (privctx->subkeydb != NULL) {
+                       privctx->subkeydb->close(privctx->subkeydb, 0);
+                       privctx->subkeydb = NULL;
+               }
+               if (privctx->skshashdb != NULL) {
+                       privctx->skshashdb->close(privctx->skshashdb, 0);
+                       privctx->skshashdb = NULL;
+               }
+               if (privctx->id32db != NULL) {
+                       privctx->id32db->close(privctx->id32db, 0);
+                       privctx->id32db = NULL;
+               }
+               if (privctx->worddb != NULL) {
+                       privctx->worddb->close(privctx->worddb, 0);
+                       privctx->worddb = NULL;
+               }
+               for (i = 0; i < privctx->numdbs; i++) {
+                       if (privctx->dbconns[i] != NULL) {
+                               privctx->dbconns[i]->close(privctx->dbconns[i],
+                                               0);
+                               privctx->dbconns[i] = NULL;
+                       }
+               }
+               free(privctx->dbconns);
+               privctx->dbconns = NULL;
+               privctx->dbenv->close(privctx->dbenv, 0);
+               privctx->dbenv = NULL;
+       }
+
+       free(privctx);
+       dbctx->priv = NULL;
+       free(dbctx);
+}
+
+/**
+ *     initdb - Initialize the key database.
+ *
+ *     This function should be called before any of the other functions in
+ *     this file are called in order to allow the DB to be initialized ready
+ *     for access.
+ */
+struct onak_dbctx *keydb_db4_init(bool readonly)
+{
+       char       buf[1024];
+       FILE      *numdb = NULL;
+       int        ret = 0;
+       int        i = 0;
+       uint32_t   flags = 0;
+       struct stat statbuf;
+       int        maxlocks;
+       struct onak_dbctx *dbctx;
+       struct onak_db4_dbctx *privctx;
+
+       dbctx = malloc(sizeof(*dbctx));
+       if (dbctx == NULL) {
+               return NULL;
+       }
+       dbctx->priv = privctx = calloc(1, sizeof(*privctx));
+       if (privctx == NULL) {
+               free(dbctx);
+               return NULL;
+       }
+
+       /* Default to 16 key data DBs */
+       privctx->numdbs = 16;
+
+       snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir,
+                       DB4_UPGRADE_FILE);
+       ret = stat(buf, &statbuf);
+       while ((ret == 0) || (errno != ENOENT)) {
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL, "Couldn't stat upgrade "
+                               "lock file: %s (%d)", strerror(errno), ret);
+                       exit(1);
+               }
+               logthing(LOGTHING_DEBUG, "DB4 upgrade in progress; waiting.");
+               sleep(5);
+               ret = stat(buf, &statbuf);
+       }
+       ret = 0;
+
+       snprintf(buf, sizeof(buf) - 1, "%s/num_keydb", config.db_dir);
+       numdb = fopen(buf, "r");
+       if (numdb != NULL) {
+               if (fgets(buf, sizeof(buf), numdb) != NULL) {
+                       privctx->numdbs = atoi(buf);
+               }
+               fclose(numdb);
+       } else if (!readonly) {
+               logthing(LOGTHING_ERROR, "Couldn't open num_keydb: %s",
+                               strerror(errno));
+               numdb = fopen(buf, "w");
+               if (numdb != NULL) {
+                       fprintf(numdb, "%d", privctx->numdbs);
+                       fclose(numdb);
+               } else {
+                       logthing(LOGTHING_ERROR,
+                               "Couldn't write num_keydb: %s",
+                               strerror(errno));
+               }
+       }
+
+       privctx->dbconns = calloc(privctx->numdbs, sizeof (DB *));
+       if (privctx->dbconns == NULL) {
+               logthing(LOGTHING_CRITICAL,
+                               "Couldn't allocate memory for dbconns");
+               ret = 1;
+       }
+
+       if (ret == 0) {
+               ret = db_env_create(&privctx->dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                               "db_env_create: %s", db_strerror(ret));
+               }
+       }
+
+       /*
+        * 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;
+       }
+       privctx->dbenv->set_lk_max_locks(privctx->dbenv, maxlocks);
+       privctx->dbenv->set_lk_max_objects(privctx->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
+        * sure how to make the standard DB functions do that yet.
+        */
+       if (ret == 0) {
+               privctx->dbenv->set_errcall(privctx->dbenv, &db4_errfunc);
+               ret = privctx->dbenv->set_lk_detect(privctx->dbenv, DB_LOCK_DEFAULT);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                               "db_env_create: %s", db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = privctx->dbenv->open(privctx->dbenv, config.db_dir,
+                               DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK |
+                               DB_INIT_TXN |
+                               DB_CREATE,
+                               0);
+#ifdef DB_VERSION_MISMATCH
+               if (ret == DB_VERSION_MISMATCH) {
+                       privctx->dbenv->close(privctx->dbenv, 0);
+                       privctx->dbenv = NULL;
+                       ret = db4_upgradedb(privctx);
+                       if (ret == 0) {
+                               ret = db_env_create(&privctx->dbenv, 0);
+                       }
+                       if (ret == 0) {
+                               privctx->dbenv->set_errcall(privctx->dbenv,
+                                       &db4_errfunc);
+                               privctx->dbenv->set_lk_detect(privctx->dbenv,
+                                       DB_LOCK_DEFAULT);
+                               ret = privctx->dbenv->open(privctx->dbenv,
+                                       config.db_dir,
+                                       DB_INIT_LOG | DB_INIT_MPOOL |
+                                       DB_INIT_LOCK | DB_INIT_TXN |
+                                       DB_CREATE | DB_RECOVER,
+                                       0);
+
+                               if (ret == 0) {
+                                       privctx->dbenv->txn_checkpoint(
+                                                       privctx->dbenv,
+                                                       0,
+                                                       0,
+                                                       DB_FORCE);
+                               }
+                       }
+               }
+#endif
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                                       "Error opening db environment: %s (%s)",
+                                       config.db_dir,
+                                       db_strerror(ret));
+                       privctx->dbenv->close(privctx->dbenv, 0);
+                       privctx->dbenv = NULL;
+               }
+       }
+
+       if (ret == 0) {
+               db4_starttrans(dbctx);
+
+               for (i = 0; !ret && i < privctx->numdbs; i++) {
+                       ret = db_create(&privctx->dbconns[i],
+                                       privctx->dbenv, 0);
+                       if (ret != 0) {
+                               logthing(LOGTHING_CRITICAL,
+                                       "db_create: %s", db_strerror(ret));
+                       }
+
+                       if (ret == 0) {
+                               snprintf(buf, 1023, "keydb.%d.db", i);
+                               flags = DB_CREATE;
+                               if (readonly) {
+                                       flags = DB_RDONLY;
+                               }
+                               ret = privctx->dbconns[i]->open(
+                                               privctx->dbconns[i],
+                                               privctx->txn,
+                                               buf,
+                                               "keydb",
+                                               DB_HASH,
+                                               flags,
+                                               0664);
+                               if (ret != 0) {
+                                       logthing(LOGTHING_CRITICAL,
+                                               "Error opening key database:"
+                                               " %s (%s)",
+                                               buf,
+                                               db_strerror(ret));
+                               }
+                       }
+               }
+       }
+
+       if (ret == 0) {
+               ret = db_create(&privctx->worddb, privctx->dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL, "db_create: %s",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = privctx->worddb->set_flags(privctx->worddb, DB_DUP);
+       }
+
+       if (ret == 0) {
+               ret = privctx->worddb->open(privctx->worddb, privctx->txn,
+                               "worddb", "worddb", DB_BTREE,
+                               flags,
+                               0664);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                                       "Error opening word database: %s (%s)",
+                                       "worddb",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = db_create(&privctx->id32db, privctx->dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL, "db_create: %s",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = privctx->id32db->set_flags(privctx->id32db, DB_DUP);
+       }
+
+       if (ret == 0) {
+               ret = privctx->id32db->open(privctx->id32db, privctx->txn,
+                               "id32db", "id32db", DB_HASH,
+                               flags,
+                               0664);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                                       "Error opening id32 database: %s (%s)",
+                                       "id32db",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = db_create(&privctx->skshashdb, privctx->dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL, "db_create: %s",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = privctx->skshashdb->open(privctx->skshashdb, privctx->txn,
+                               "skshashdb",
+                               "skshashdb", DB_HASH,
+                               flags,
+                               0664);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                               "Error opening skshash database: %s (%s)",
+                               "skshashdb",
+                               db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = db_create(&privctx->subkeydb, privctx->dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL, "db_create: %s",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (ret == 0) {
+               ret = privctx->subkeydb->open(privctx->subkeydb, privctx->txn,
+                               "subkeydb", "subkeydb",
+                               DB_HASH,
+                               flags,
+                               0664);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                               "Error opening subkey database: %s (%s)",
+                               "subkeydb",
+                               db_strerror(ret));
+               }
+       }
+
+       if (privctx->txn != NULL) {
+               db4_endtrans(dbctx);
+       }
+
+       if (ret != 0) {
+               db4_cleanupdb(dbctx);
+               logthing(LOGTHING_CRITICAL,
+                               "Error opening database; exiting");
+               exit(EXIT_FAILURE);
+       }
+
+       dbctx->cleanupdb                = db4_cleanupdb;
+       dbctx->starttrans               = db4_starttrans;
+       dbctx->endtrans                 = db4_endtrans;
+       dbctx->fetch_key_id             = db4_fetch_key_id;
+       dbctx->fetch_key_fp             = generic_fetch_key_fp;
+       dbctx->fetch_key_text           = db4_fetch_key_text;
+       dbctx->fetch_key_skshash        = db4_fetch_key_skshash;
+       dbctx->store_key                = db4_store_key;
+       dbctx->update_keys              = generic_update_keys;
+       dbctx->delete_key               = db4_delete_key;
+       dbctx->getkeysigs               = generic_getkeysigs;
+       dbctx->cached_getkeysigs        = generic_cached_getkeysigs;
+       dbctx->keyid2uid                = generic_keyid2uid;
+       dbctx->getfullkeyid             = db4_getfullkeyid;
+       dbctx->iterate_keys             = db4_iterate_keys;
+
+       return dbctx;
+}
index 536909a67c67e1c4219ce913d9ada34665cb1761..32695c389f22de5fe3e07f7afdd443e591800bfa 100644 (file)
 #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");
-       }
-
-       if (!config.db_backend) {
-               logthing(LOGTHING_CRITICAL, "No database backend defined.");
-               exit(EXIT_FAILURE);
-       }
-
-       if (config.backends_dir == NULL) {
-               soname = malloc(strlen(config.db_backend)
-                       + strlen("./libkeydb_")
-                       + strlen(".so")
-                       + 1);
-
-               sprintf(soname, "./libkeydb_%s.so", config.db_backend);
-       } else {
-               soname = malloc(strlen(config.db_backend)
-                       + strlen("/libkeydb_")
-                       + strlen(".so")
-                       + strlen(config.backends_dir)
-                       + 1);
-
-               sprintf(soname, "%s/libkeydb_%s.so", config.backends_dir,
-                       config.db_backend);
-       }
-               
-       logthing(LOGTHING_INFO, "Loading dynamic backend: %s", soname);
+       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);
-       }
+       privctx->loadeddbctx->endtrans(privctx->loadeddbctx);
+}
 
-       funcsname = malloc(strlen(config.db_backend)
-                       + strlen("keydb_")
-                       + strlen("_funcs")
-                       + 1);
-       sprintf(funcsname, "keydb_%s_funcs", config.db_backend);
+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;
 
-       loaded_backend = dlsym(backend_handle, funcsname);
-       free(funcsname);
+       return privctx->loadeddbctx->fetch_key_id(privctx->loadeddbctx, keyid,
+                       publickey, intrans);
+}
 
-       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_fp(struct onak_dbctx *dbctx,
+               uint8_t *fp, size_t fpsize,
+               struct openpgp_publickey **publickey, bool intrans)
+{
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       return true;
+       return privctx->loadeddbctx->fetch_key_fp(privctx->loadeddbctx,
+                       fp, fpsize, publickey, intrans);
 }
 
-static bool dynamic_starttrans()
+static int dynamic_fetch_key_text(struct onak_dbctx *dbctx,
+               const char *search,
+               struct openpgp_publickey **publickey)
 {
-       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->fetch_key_text(privctx->loadeddbctx,
+                       search, publickey);
 }
 
-static void dynamic_endtrans()
+static int dynamic_fetch_key_skshash(struct onak_dbctx *dbctx,
+               const struct skshash *hash,
+               struct openpgp_publickey **publickey)
 {
-       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->fetch_key_skshash(privctx->loadeddbctx,
+                       hash, publickey);
 }
 
-static int dynamic_fetch_key_id(uint64_t keyid,
-               struct openpgp_publickey **publickey, bool intrans)
+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->fetch_key_id != NULL) {
-                       return loaded_backend->fetch_key_id(keyid,
-                               publickey, intrans);
-               }
-       }
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       return -1;
+       return privctx->loadeddbctx->store_key(privctx->loadeddbctx,
+                       publickey, intrans, update);
 }
 
-static int dynamic_fetch_key_fp(uint8_t *fp, size_t fpsize,
-               struct openpgp_publickey **publickey, bool intrans)
+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->fetch_key_id != NULL) {
-                       return loaded_backend->fetch_key_fp(fp, fpsize,
-                               publickey, intrans);
-               }
-       }
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
-       return -1;
+       return privctx->loadeddbctx->delete_key(privctx->loadeddbctx,
+                       keyid, intrans);
 }
 
+static int dynamic_update_keys(struct onak_dbctx *dbctx,
+               struct openpgp_publickey **keys, bool sendsync)
+{
+       struct onak_dynamic_dbctx *privctx =
+                       (struct onak_dynamic_dbctx *) dbctx->priv;
 
+       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);
+       if (privctx->loadeddbctx != NULL) {
+               if (privctx->loadeddbctx->cleanupdb != NULL) {
+                       privctx->loadeddbctx->cleanupdb(privctx->loadeddbctx);
+                       privctx->loadeddbctx = NULL;
                }
        }
-       
-       buf[0]=0;
-       if (dynamic_fetch_key_id(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;
-               }
-               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_id(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(bool readonly)
 {
-       struct stats_key *key = NULL;
-       struct stats_key *signedkey = NULL;
-       struct ll        *cursig = NULL;
-       bool              revoked = false;
+       struct onak_dbctx *dbctx;
+       char *soname;
+       char *initname;
+       struct onak_dbctx *(*backend_init)(bool);
+       struct onak_dynamic_dbctx *privctx;
+
+       dbctx = malloc(sizeof(struct onak_dbctx));
 
-       if (keyid == 0)  {
+       if (dbctx == NULL) {
                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);
 
-       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;
+       dbctx->priv = privctx = malloc(sizeof(struct onak_dynamic_dbctx));
+       if (dbctx->priv == NULL) {
+               free(dbctx);
+               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);
-               }
+       if (config.use_keyd) {
+               free(config.db_backend);
+               config.db_backend = strdup("keyd");
        }
 
-       if (keyid < 0x100000000LL) {
-               dynamic_fetch_key_id(keyid, &publickey, false);
-               if (publickey != NULL) {
-                       get_keyid(publickey, &keyid);
-                       free_publickey(publickey);
-                       publickey = NULL;
-               } else {
-                       keyid = 0;
-               }
+       if (!config.db_backend) {
+               logthing(LOGTHING_CRITICAL, "No database backend defined.");
+               exit(EXIT_FAILURE);
        }
-       
-       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;
-       uint64_t keyid;
-       
-       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.backends_dir == NULL) {
+               soname = malloc(strlen(config.db_backend)
+                       + strlen("./libkeydb_")
+                       + strlen(".so")
+                       + 1);
 
-       for (curkey = *keys; curkey != NULL; curkey = curkey->next) {
-               intrans = dynamic_starttrans();
-               get_keyid(curkey, &keyid);
-               logthing(LOGTHING_INFO,
-                       "Fetching key 0x%" PRIX64 ", result: %d",
-                       keyid,
-                       dynamic_fetch_key_id(keyid, &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;
-       }
+               sprintf(soname, "./libkeydb_%s.so", config.db_backend);
+       } else {
+               soname = malloc(strlen(config.db_backend)
+                       + strlen("/libkeydb_")
+                       + strlen(".so")
+                       + strlen(config.backends_dir)
+                       + 1);
 
-       if (sendsync && keys != NULL) {
-               sendkeysync(*keys);
+               sprintf(soname, "%s/libkeydb_%s.so", config.backends_dir,
+                       config.db_backend);
        }
 
-       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", config.db_backend);
 
-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(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_id           = dynamic_fetch_key_id,
-       .fetch_key_fp           = dynamic_fetch_key_fp,
-       .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,
-};
index eeae01f3013585504ac13b5c520e2374443c3474..e0ed610e33cd7b976df43c01d9e5e8a216816fe9 100644 (file)
 #include "onak-conf.h"
 #include "parsekey.h"
 
-/**
- *     initdb - Initialize the key database.
- *
- *     This is just a no-op for flat file access.
- */
-static void file_initdb(bool readonly)
-{
-}
-
-/**
- *     cleanupdb - De-initialize the key database.
- *
- *     This is just a no-op for flat file access.
- */
-static void file_cleanupdb(void)
-{
-}
-
 /**
  *     starttrans - Start a transaction.
  *
  *     This is just a no-op for flat file access.
  */
-static bool file_starttrans(void)
+static bool file_starttrans(struct onak_dbctx *dbctx)
 {
        return true;
 }
@@ -70,7 +52,7 @@ static bool file_starttrans(void)
  *
  *     This is just a no-op for flat file access.
  */
-static void file_endtrans(void)
+static void file_endtrans(struct onak_dbctx *dbctx)
 {
        return;
 }
@@ -87,15 +69,17 @@ static void file_endtrans(void)
  *     in and then parse_keys() to parse the packets into a publickey
  *     structure.
  */
-static int file_fetch_key_id(uint64_t keyid,
+static int file_fetch_key_id(struct onak_dbctx *dbctx,
+               uint64_t keyid,
                struct openpgp_publickey **publickey,
                bool intrans)
 {
+       char *db_dir = (char *) dbctx->priv;
        struct openpgp_packet_list *packets = NULL;
        char keyfile[1024];
        int fd = -1;
 
-       snprintf(keyfile, 1023, "%s/0x%" PRIX64, config.db_dir,
+       snprintf(keyfile, 1023, "%s/0x%" PRIX64, db_dir,
                        keyid & 0xFFFFFFFF);
        fd = open(keyfile, O_RDONLY); // | O_SHLOCK);
 
@@ -121,9 +105,11 @@ static int file_fetch_key_id(uint64_t keyid,
  *     packets and then use write_openpgp_stream() to write the stream out to
  *     the file.
  */
-static int file_store_key(struct openpgp_publickey *publickey, bool intrans,
+static int file_store_key(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *publickey, bool intrans,
                bool update)
 {
+       char *db_dir = (char *) dbctx->priv;
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_packet_list *list_end = NULL;
        struct openpgp_publickey *next = NULL;
@@ -135,7 +121,7 @@ static int file_store_key(struct openpgp_publickey *publickey, bool intrans,
                logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
                return 0;
        }
-       snprintf(keyfile, 1023, "%s/0x%" PRIX64, config.db_dir,
+       snprintf(keyfile, 1023, "%s/0x%" PRIX64, db_dir,
                        keyid & 0xFFFFFFFF);
        fd = open(keyfile, O_WRONLY | O_CREAT, 0664); // | O_EXLOCK);
 
@@ -162,11 +148,13 @@ static int file_store_key(struct openpgp_publickey *publickey, bool intrans,
  *     This function deletes a public key from whatever storage mechanism we
  *     are using. Returns 0 if the key existed.
  */
-static int file_delete_key(uint64_t keyid, bool intrans)
+static int file_delete_key(struct onak_dbctx *dbctx,
+               uint64_t keyid, bool intrans)
 {
+       char *db_dir = (char *) dbctx->priv;
        char keyfile[1024];
 
-       snprintf(keyfile, 1023, "%s/0x%" PRIX64, config.db_dir,
+       snprintf(keyfile, 1023, "%s/0x%" PRIX64, db_dir,
                        keyid & 0xFFFFFFFF);
 
        return unlink(keyfile);
@@ -182,7 +170,8 @@ static int file_delete_key(uint64_t keyid, bool intrans)
  *
  *     TODO: Write for flat file access. Some sort of grep?
  */
-static int file_fetch_key_text(const char *search,
+static int file_fetch_key_text(struct onak_dbctx *dbctx,
+               const char *search,
                struct openpgp_publickey **publickey)
 {
        return 0;
@@ -199,9 +188,11 @@ static int file_fetch_key_text(const char *search,
  *
  *     Returns the number of keys we iterated over.
  */
-static int file_iterate_keys(void (*iterfunc)(void *ctx,
-               struct openpgp_publickey *key), void *ctx)
+static int file_iterate_keys(struct onak_dbctx *dbctx,
+               void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
+               void *ctx)
 {
+       char *db_dir = (char *) dbctx->priv;
        int                         numkeys = 0;
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_publickey   *key = NULL;
@@ -210,14 +201,14 @@ static int file_iterate_keys(void (*iterfunc)(void *ctx,
        int                         fd = -1;
        struct dirent              *curfile = NULL;
 
-       dir = opendir(config.db_dir);
+       dir = opendir(db_dir);
 
        if (dir != NULL) {
                while ((curfile = readdir(dir)) != NULL) {
                        if (curfile->d_name[0] == '0' &&
                                        curfile->d_name[1] == 'x') {
                                snprintf(keyfile, 1023, "%s/%s",
-                                               config.db_dir,
+                                               db_dir,
                                                curfile->d_name);
                                fd = open(keyfile, O_RDONLY);
 
@@ -257,20 +248,53 @@ static int file_iterate_keys(void (*iterfunc)(void *ctx,
 #define NEED_GET_FP 1
 #include "keydb.c"
 
-struct dbfuncs keydb_file_funcs = {
-       .initdb                 = file_initdb,
-       .cleanupdb              = file_cleanupdb,
-       .starttrans             = file_starttrans,
-       .endtrans               = file_endtrans,
-       .fetch_key_id           = file_fetch_key_id,
-       .fetch_key_fp           = generic_fetch_key_fp,
-       .fetch_key_text         = file_fetch_key_text,
-       .store_key              = file_store_key,
-       .update_keys            = generic_update_keys,
-       .delete_key             = file_delete_key,
-       .getkeysigs             = generic_getkeysigs,
-       .cached_getkeysigs      = generic_cached_getkeysigs,
-       .keyid2uid              = generic_keyid2uid,
-       .getfullkeyid           = generic_getfullkeyid,
-       .iterate_keys           = file_iterate_keys,
-};
+/**
+ *     cleanupdb - De-initialize the key database.
+ *
+ *     This is just a no-op for flat file access.
+ */
+static void file_cleanupdb(struct onak_dbctx *dbctx)
+{
+       if (dbctx->priv != NULL) {
+               free(dbctx->priv);
+               dbctx->priv = NULL;
+       }
+
+       if (dbctx != NULL) {
+               free(dbctx);
+       }
+}
+
+/**
+ *     initdb - Initialize the key database.
+ *
+ *     This is just a no-op for flat file access.
+ */
+struct onak_dbctx *keydb_file_init(bool readonly)
+{
+       struct onak_dbctx *dbctx;
+
+       dbctx = malloc(sizeof(struct onak_dbctx));
+       if (dbctx == NULL) {
+               return NULL;
+       }
+
+       dbctx->priv = strdup(config.db_dir);
+
+       dbctx->cleanupdb                = file_cleanupdb;
+       dbctx->starttrans               = file_starttrans;
+       dbctx->endtrans                 = file_endtrans;
+       dbctx->fetch_key_id             = file_fetch_key_id;
+       dbctx->fetch_key_fp             = generic_fetch_key_fp;
+       dbctx->fetch_key_text           = file_fetch_key_text;
+       dbctx->store_key                = file_store_key;
+       dbctx->update_keys              = generic_update_keys;
+       dbctx->delete_key               = file_delete_key;
+       dbctx->getkeysigs               = generic_getkeysigs;
+       dbctx->cached_getkeysigs        = generic_cached_getkeysigs;
+       dbctx->keyid2uid                = generic_keyid2uid;
+       dbctx->getfullkeyid             = generic_getfullkeyid;
+       dbctx->iterate_keys             = file_iterate_keys;
+
+       return dbctx;
+}
index b9447321153d1f4bd40b4d90a62c9dfb25d45645..9e072bab0f240e9205668c03769032711627e2a6 100644 (file)
 #define PATH_MAX 1024
 #endif
 
-static int keydb_lockfile_fd = -1;
-static bool keydb_lockfile_readonly;
+struct onak_fs_dbctx {
+       int lockfile_fd;
+       bool lockfile_readonly;
+};
 
 /*****************************************************************************/
 
@@ -161,65 +163,21 @@ static void subkeydir(char *buffer, size_t length, uint64_t subkey)
 
 /*****************************************************************************/
 
-/**
- *     initdb - Initialize the key database.
- */
-static void fs_initdb(bool readonly)
-{
-       char buffer[PATH_MAX];
-
-       keydb_lockfile_readonly = readonly;
-
-       snprintf(buffer, sizeof(buffer), "%s/.lock", config.db_dir);
-
-       if (access(config.db_dir, 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));
-                       exit(1);        /* Lacking rwx on the key dir */
-               }
-               mkdir(config.db_dir, 0777);
-               keydb_lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600);
-       }
-       chdir(config.db_dir);
-       if (keydb_lockfile_fd == -1)
-               keydb_lockfile_fd = open(buffer,
-                                        (keydb_lockfile_readonly) ?
-                                        O_RDONLY : O_RDWR);
-       if (keydb_lockfile_fd == -1)
-               keydb_lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600);
-       if (keydb_lockfile_fd == -1) {
-               logthing(LOGTHING_CRITICAL,
-                        "Unable to open lockfile '%s'. (%s)",
-                        buffer, strerror(errno));
-               exit(1);        /* Lacking rwx on the key dir */
-       }
-}
-
-/**
- *     cleanupdb - De-initialize the key database.
- */
-static void fs_cleanupdb(void)
-{
-       /* Mmmm nothing to do here? */
-       close(keydb_lockfile_fd);
-}
-
 /**
  *     starttrans - Start a transaction.
  */
-static bool fs_starttrans(void)
+static bool fs_starttrans(struct onak_dbctx *dbctx)
 {
+       struct onak_fs_dbctx *privctx = (struct onak_fs_dbctx *) dbctx->priv;
        struct flock lockstruct;
        int remaining = 20;
        lockstruct.l_type =
-           F_RDLCK | ((keydb_lockfile_readonly) ? 0 : F_WRLCK);
+           F_RDLCK | ((privctx->lockfile_readonly) ? 0 : F_WRLCK);
        lockstruct.l_whence = SEEK_SET;
        lockstruct.l_start = 0;
        lockstruct.l_len = 1;
 
-       while (fcntl(keydb_lockfile_fd, F_SETLK, &lockstruct) == -1) {
+       while (fcntl(privctx->lockfile_fd, F_SETLK, &lockstruct) == -1) {
                if (remaining-- == 0)
                        return false;   /* Hope to hell that noodles DTRT */
                usleep(100);
@@ -230,18 +188,19 @@ static bool fs_starttrans(void)
 /**
  *     endtrans - End a transaction.
  */
-static void fs_endtrans(void)
+static void fs_endtrans(struct onak_dbctx *dbctx)
 {
+       struct onak_fs_dbctx *privctx = (struct onak_fs_dbctx *) dbctx->priv;
        struct flock lockstruct;
 
        lockstruct.l_type = F_UNLCK;
        lockstruct.l_whence = SEEK_SET;
        lockstruct.l_start = 0;
        lockstruct.l_len = 1;
-       fcntl(keydb_lockfile_fd, F_SETLK, &lockstruct);
+       fcntl(privctx->lockfile_fd, F_SETLK, &lockstruct);
 }
 
-static uint64_t fs_getfullkeyid(uint64_t keyid)
+static uint64_t fs_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
 {
        static char buffer[PATH_MAX];
        DIR *d = NULL;
@@ -285,7 +244,8 @@ static uint64_t fs_getfullkeyid(uint64_t keyid)
  *     @publickey: A pointer to a structure to return the key in.
  *     @intrans: If we're already in a transaction.
  */
-static int fs_fetch_key_id(uint64_t keyid,
+static int fs_fetch_key_id(struct onak_dbctx *dbctx,
+             uint64_t keyid,
              struct openpgp_publickey **publickey,
              bool intrans)
 {
@@ -294,10 +254,10 @@ static int fs_fetch_key_id(uint64_t keyid,
        struct openpgp_packet_list *packets = NULL;
 
        if (!intrans)
-               fs_starttrans();
+               fs_starttrans(dbctx);
 
        if ((keyid >> 32) == 0)
-               keyid = fs_getfullkeyid(keyid);
+               keyid = fs_getfullkeyid(dbctx, keyid);
 
        keypath(buffer, sizeof(buffer), keyid);
        if ((fd = open(buffer, O_RDONLY)) != -1) {
@@ -311,7 +271,7 @@ static int fs_fetch_key_id(uint64_t keyid,
        }
 
        if (!intrans)
-               fs_endtrans();
+               fs_endtrans(dbctx);
        return ret;
 }
 
@@ -321,7 +281,8 @@ static int fs_fetch_key_id(uint64_t keyid,
  *     @intrans: If we're already in a transaction.
  *     @update: If true the key exists and should be updated.
  */
-static int fs_store_key(struct openpgp_publickey *publickey, bool intrans,
+static int fs_store_key(struct onak_dbctx *dbctx,
+             struct openpgp_publickey *publickey, bool intrans,
              bool update)
 {
        static char buffer[PATH_MAX];
@@ -343,7 +304,7 @@ static int fs_store_key(struct openpgp_publickey *publickey, bool intrans,
        }
 
        if (!intrans)
-               fs_starttrans();
+               fs_starttrans(dbctx);
 
        prove_path_to(keyid, "key");
        keypath(buffer, sizeof(buffer), keyid);
@@ -406,7 +367,7 @@ static int fs_store_key(struct openpgp_publickey *publickey, bool intrans,
        }
 
        if (!intrans)
-               fs_endtrans();
+               fs_endtrans(dbctx);
        return ret;
 }
 
@@ -415,7 +376,7 @@ static int fs_store_key(struct openpgp_publickey *publickey, bool intrans,
  *     @keyid: The keyid to delete.
  *     @intrans: If we're already in a transaction.
  */
-static int fs_delete_key(uint64_t keyid, bool intrans)
+static int fs_delete_key(struct onak_dbctx *dbctx, uint64_t keyid, bool intrans)
 {
        static char buffer[PATH_MAX];
        int ret;
@@ -426,12 +387,12 @@ static int fs_delete_key(uint64_t keyid, bool intrans)
        int i = 0;
 
        if ((keyid >> 32) == 0)
-               keyid = fs_getfullkeyid(keyid);
+               keyid = fs_getfullkeyid(dbctx, keyid);
 
        if (!intrans)
-               fs_starttrans();
+               fs_starttrans(dbctx);
 
-       ret = fs_fetch_key_id(keyid, &pk, true);
+       ret = fs_fetch_key_id(dbctx, keyid, &pk, true);
 
        if (ret) {
                logthing(LOGTHING_DEBUG, "Wordlist for key %016" PRIX64,
@@ -475,7 +436,7 @@ static int fs_delete_key(uint64_t keyid, bool intrans)
        unlink(buffer);
 
        if (!intrans)
-               fs_endtrans();
+               fs_endtrans(dbctx);
        return 1;
 }
 
@@ -519,7 +480,8 @@ static struct ll *internal_get_key_by_word(char *word, struct ll *mct)
  *     @search: The text to search for.
  *     @publickey: A pointer to a structure to return the key in.
  */
-static int fs_fetch_key_text(const char *search,
+static int fs_fetch_key_text(struct onak_dbctx *dbctx,
+                  const char *search,
                   struct openpgp_publickey **publickey)
 {
        struct ll *wordlist = NULL, *wl = NULL;
@@ -564,7 +526,8 @@ static int fs_fetch_key_text(const char *search,
        while (wl) {
                logthing(LOGTHING_DEBUG, "Adding key: %s", wl->object);
                addedkeys +=
-                   fs_fetch_key_id(strtoull(wl->object, NULL, 16), publickey,
+                   fs_fetch_key_id(dbctx,
+                             strtoull(wl->object, NULL, 16), publickey,
                              false);
                if (addedkeys >= config.maxkeys)
                        break;
@@ -584,7 +547,8 @@ static int fs_fetch_key_text(const char *search,
  *     @publickey: A pointer to a structure to return the key in.
  *     @intrans: If we're already in a transaction.
  */
-static int fs_fetch_key_skshash(const struct skshash *hash,
+static int fs_fetch_key_skshash(struct onak_dbctx *dbctx,
+             const struct skshash *hash,
              struct openpgp_publickey **publickey)
 {
        static char buffer[PATH_MAX];
@@ -615,7 +579,8 @@ static int fs_fetch_key_skshash(const struct skshash *hash,
  *
  *     Returns the number of keys we iterated over.
  */
-static int fs_iterate_keys(void (*iterfunc)(void *ctx,
+static int fs_iterate_keys(struct onak_dbctx *dbctx,
+               void (*iterfunc)(void *ctx,
                struct openpgp_publickey *key), void *ctx)
 {
        return 0;
@@ -630,21 +595,79 @@ static int fs_iterate_keys(void (*iterfunc)(void *ctx,
 #define NEED_GET_FP 1
 #include "keydb.c"
 
-struct dbfuncs keydb_fs_funcs = {
-       .initdb                 = fs_initdb,
-       .cleanupdb              = fs_cleanupdb,
-       .starttrans             = fs_starttrans,
-       .endtrans               = fs_endtrans,
-       .fetch_key_id           = fs_fetch_key_id,
-       .fetch_key_fp           = generic_fetch_key_fp,
-       .fetch_key_text         = fs_fetch_key_text,
-       .fetch_key_skshash      = fs_fetch_key_skshash,
-       .store_key              = fs_store_key,
-       .update_keys            = generic_update_keys,
-       .delete_key             = fs_delete_key,
-       .getkeysigs             = generic_getkeysigs,
-       .cached_getkeysigs      = generic_cached_getkeysigs,
-       .keyid2uid              = generic_keyid2uid,
-       .getfullkeyid           = fs_getfullkeyid,
-       .iterate_keys           = fs_iterate_keys,
-};
+/**
+ *     cleanupdb - De-initialize the key database.
+ */
+static void fs_cleanupdb(struct onak_dbctx *dbctx)
+{
+       struct onak_fs_dbctx *privctx = (struct onak_fs_dbctx *) dbctx->priv;
+
+       /* Mmmm nothing to do here? */
+       close(privctx->lockfile_fd);
+}
+
+/**
+ *     initdb - Initialize the key database.
+ */
+struct onak_dbctx *keydb_fs_init(bool readonly)
+{
+       char buffer[PATH_MAX];
+       struct onak_dbctx *dbctx;
+       struct onak_fs_dbctx *privctx;
+
+       dbctx = malloc(sizeof(struct onak_dbctx));
+       if (dbctx == NULL) {
+               return NULL;
+       }
+       dbctx->priv = privctx = malloc(sizeof(*privctx));
+       if (privctx == NULL) {
+               free(dbctx);
+               return NULL;
+       }
+
+       privctx->lockfile_readonly = readonly;
+
+       snprintf(buffer, sizeof(buffer), "%s/.lock", config.db_dir);
+
+       if (access(config.db_dir, 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));
+                       exit(1);        /* Lacking rwx on the key dir */
+               }
+               mkdir(config.db_dir, 0777);
+               privctx->lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600);
+       }
+       chdir(config.db_dir);
+       if (privctx->lockfile_fd == -1)
+               privctx->lockfile_fd = open(buffer,
+                                        (privctx->lockfile_readonly) ?
+                                        O_RDONLY : O_RDWR);
+       if (privctx->lockfile_fd == -1)
+               privctx->lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600);
+       if (privctx->lockfile_fd == -1) {
+               logthing(LOGTHING_CRITICAL,
+                        "Unable to open lockfile '%s'. (%s)",
+                        buffer, strerror(errno));
+               exit(1);        /* Lacking rwx on the key dir */
+       }
+
+       dbctx->cleanupdb                = fs_cleanupdb;
+       dbctx->starttrans               = fs_starttrans;
+       dbctx->endtrans                 = fs_endtrans;
+       dbctx->fetch_key_id             = fs_fetch_key_id;
+       dbctx->fetch_key_fp             = generic_fetch_key_fp;
+       dbctx->fetch_key_text           = fs_fetch_key_text;
+       dbctx->fetch_key_skshash        = fs_fetch_key_skshash;
+       dbctx->store_key                = fs_store_key;
+       dbctx->update_keys              = generic_update_keys;
+       dbctx->delete_key               = fs_delete_key;
+       dbctx->getkeysigs               = generic_getkeysigs;
+       dbctx->cached_getkeysigs        = generic_cached_getkeysigs;
+       dbctx->keyid2uid                = generic_keyid2uid;
+       dbctx->getfullkeyid             = fs_getfullkeyid;
+       dbctx->iterate_keys             = fs_iterate_keys;
+
+       return dbctx;
+}
index 3fa15935196b4222d86075d86573942822435acd..7c7b31a4a50e75bc7acc290bb6333e81c8c07cf7 100644 (file)
 #include "parsekey.h"
 #include "version.h"
 
-static CURL *curl = NULL;
-
-static char hkpbase[1024];
+struct onak_hkp_dbctx {
+       CURL *curl;
+       char hkpbase[1024];
+};
 
-static int hkp_parse_url(const char *url)
+static int hkp_parse_url(struct onak_hkp_dbctx *privctx, const char *url)
 {
        char proto[6], host[256];
        unsigned int port;
@@ -65,13 +66,13 @@ static int hkp_parse_url(const char *url)
                if (port == 0) {
                        port = 11371;
                }
-               snprintf(hkpbase, sizeof(hkpbase),
+               snprintf(privctx->hkpbase, sizeof(privctx->hkpbase),
                        "http://%s:%u/pks", host, port);
        } else if (!strcmp(proto, "hkps")) {
                if (port == 0) {
                        port = 11372;
                }
-               snprintf(hkpbase, sizeof(hkpbase),
+               snprintf(privctx->hkpbase, sizeof(privctx->hkpbase),
                        "https://%s:%u/pks", host, port);
        } else if (strcmp(proto, "http") && strcmp(proto, "https")) {
                logthing(LOGTHING_CRITICAL, "Unknown HKP protocol: %s",
@@ -79,10 +80,10 @@ static int hkp_parse_url(const char *url)
                ret = 0;
                goto out;
        } else if (port == 0) {
-               snprintf(hkpbase, sizeof(hkpbase),
+               snprintf(privctx->hkpbase, sizeof(privctx->hkpbase),
                        "%s://%s/pks", proto, host);
        } else {
-               snprintf(hkpbase, sizeof(hkpbase),
+               snprintf(privctx->hkpbase, sizeof(privctx->hkpbase),
                        "%s://%s:%u/pks", proto, host, port);
        }
 
@@ -90,52 +91,6 @@ out:
        return ret;
 }
 
-/**
- *     cleanupdb - De-initialize the key database.
- *
- *     We cleanup CURL here.
- */
-static void hkp_cleanupdb(void)
-{
-       if (curl) {
-               curl_easy_cleanup(curl);
-               curl = NULL;
-       }
-       curl_global_cleanup();
-}
-
-/**
- *     initdb - Initialize the key database.
- *
- *     We initialize CURL here.
- */
-static void hkp_initdb(bool readonly)
-{
-       curl_version_info_data *curl_info;
-
-       if (!hkp_parse_url(config.db_dir)) {
-               exit(EXIT_FAILURE);
-       }
-       curl_global_init(CURL_GLOBAL_DEFAULT);
-       curl = curl_easy_init();
-       if (curl == NULL) {
-               logthing(LOGTHING_CRITICAL, "Could not initialize CURL.");
-               exit(EXIT_FAILURE);
-       }
-       curl_easy_setopt(curl, CURLOPT_USERAGENT, "onak/" ONAK_VERSION);
-
-       if (strncmp(hkpbase, "https://", 8) == 0) {
-               curl_info = curl_version_info(CURLVERSION_NOW);
-               if (! (curl_info->features & CURL_VERSION_SSL)) {
-                       logthing(LOGTHING_CRITICAL,
-                               "CURL lacks SSL support; cannot use HKP url: %s",
-                               hkpbase);
-                       hkp_cleanupdb();
-                       exit(EXIT_FAILURE);
-               }
-       }
-}
-
 /**
  *     Receive data from a CURL request and process it into a buffer context.
  */
@@ -147,10 +102,12 @@ static size_t hkp_curl_recv_data(void *buffer, size_t size, size_t nmemb,
        return (nmemb * size);
 }
 
-static int hkp_fetch_key_url(char *url,
+static int hkp_fetch_key_url(struct onak_dbctx *dbctx,
+               char *url,
                struct openpgp_publickey **publickey,
                bool intrans)
 {
+       struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv;
        struct openpgp_packet_list *packets = NULL;
        CURLcode res;
        struct buffer_ctx buf;
@@ -160,11 +117,11 @@ static int hkp_fetch_key_url(char *url,
        buf.size = 8192;
        buf.buffer = malloc(8192);
 
-       curl_easy_setopt(curl, CURLOPT_URL, url);
-       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
+       curl_easy_setopt(privctx->curl, CURLOPT_URL, url);
+       curl_easy_setopt(privctx->curl, CURLOPT_WRITEFUNCTION,
                        hkp_curl_recv_data);
-       curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);
-       res = curl_easy_perform(curl);
+       curl_easy_setopt(privctx->curl, CURLOPT_WRITEDATA, &buf);
+       res = curl_easy_perform(privctx->curl);
 
        if (res == 0) {
                buf.offset = 0;
@@ -187,26 +144,30 @@ static int hkp_fetch_key_url(char *url,
 /**
  *     hkp_fetch_key_id - Given a keyid fetch the key from HKP server.
  */
-static int hkp_fetch_key_id(uint64_t keyid,
+static int hkp_fetch_key_id(struct onak_dbctx *dbctx,
+               uint64_t keyid,
                struct openpgp_publickey **publickey,
                bool intrans)
 {
+       struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv;
        char keyurl[1024];
 
        snprintf(keyurl, sizeof(keyurl),
                        "%s/lookup?op=get&search=0x%08" PRIX64,
-                       hkpbase, keyid);
+                       privctx->hkpbase, keyid);
 
-       return (hkp_fetch_key_url(keyurl, publickey, intrans));
+       return (hkp_fetch_key_url(dbctx, keyurl, publickey, intrans));
 }
 
 /**
  *     hkp_fetch_key_fp - Given a fingerprint fetch the key from HKP server.
  */
-static int hkp_fetch_key_fp(uint8_t *fp, size_t fpsize,
+static int hkp_fetch_key_fp(struct onak_dbctx *dbctx,
+               uint8_t *fp, size_t fpsize,
                struct openpgp_publickey **publickey,
                bool intrans)
 {
+       struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv;
        char keyurl[1024];
        int i, ofs;
 
@@ -215,7 +176,7 @@ static int hkp_fetch_key_fp(uint8_t *fp, size_t fpsize,
        }
 
        ofs = snprintf(keyurl, sizeof(keyurl),
-                       "%s/lookup?op=get&search=0x", hkpbase);
+                       "%s/lookup?op=get&search=0x", privctx->hkpbase);
 
        if ((ofs + fpsize * 2 + 1)> sizeof(keyurl)) {
                return 0;
@@ -225,7 +186,7 @@ static int hkp_fetch_key_fp(uint8_t *fp, size_t fpsize,
                ofs += sprintf(&keyurl[ofs], "%02X", fp[i]);
        }
 
-       return (hkp_fetch_key_url(keyurl, publickey, intrans));
+       return (hkp_fetch_key_url(dbctx, keyurl, publickey, intrans));
 }
 
 /**
@@ -238,16 +199,18 @@ static int hkp_fetch_key_fp(uint8_t *fp, size_t fpsize,
  *
  *     TODO: Write for flat file access. Some sort of grep?
  */
-static int hkp_fetch_key_text(const char *search,
+static int hkp_fetch_key_text(struct onak_dbctx *dbctx,
+               const char *search,
                struct openpgp_publickey **publickey)
 {
+       struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv;
        char keyurl[1024];
 
        snprintf(keyurl, sizeof(keyurl),
                        "%s/lookup?op=get&search=%s",
-                       hkpbase, search);
+                       privctx->hkpbase, search);
 
-       return (hkp_fetch_key_url(keyurl, publickey, false));
+       return (hkp_fetch_key_url(dbctx, keyurl, publickey, false));
 }
 
 /**
@@ -257,9 +220,11 @@ static int hkp_fetch_key_text(const char *search,
  *     @update: If true the key exists and should be updated.
  *
  */
-static int hkp_store_key(struct openpgp_publickey *publickey, bool intrans,
+static int hkp_store_key(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *publickey, bool intrans,
                bool update)
 {
+       struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv;
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_packet_list *list_end = NULL;
        char keyurl[1024];
@@ -274,18 +239,18 @@ static int hkp_store_key(struct openpgp_publickey *publickey, bool intrans,
 
        flatten_publickey(publickey, &packets, &list_end);
        armor_openpgp_stream(buffer_putchar, &buf, packets);
-       addform = curl_easy_escape(curl, buf.buffer, buf.offset);
+       addform = curl_easy_escape(privctx->curl, buf.buffer, buf.offset);
        addform[7] = '=';
 
-       snprintf(keyurl, sizeof(keyurl), "%s/add", hkpbase);
+       snprintf(keyurl, sizeof(keyurl), "%s/add", privctx->hkpbase);
 
-       curl_easy_setopt(curl, CURLOPT_URL, keyurl);
-       curl_easy_setopt(curl, CURLOPT_POSTFIELDS, addform);
-       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
+       curl_easy_setopt(privctx->curl, CURLOPT_URL, keyurl);
+       curl_easy_setopt(privctx->curl, CURLOPT_POSTFIELDS, addform);
+       curl_easy_setopt(privctx->curl, CURLOPT_WRITEFUNCTION,
                        hkp_curl_recv_data);
        buf.offset = 0;
-       curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);
-       res = curl_easy_perform(curl);
+       curl_easy_setopt(privctx->curl, CURLOPT_WRITEDATA, &buf);
+       res = curl_easy_perform(privctx->curl);
 
        if (res != 0) {
                logthing(LOGTHING_ERROR, "Couldn't send key: %s (%d)",
@@ -309,7 +274,8 @@ static int hkp_store_key(struct openpgp_publickey *publickey, bool intrans,
  *
  *     No op for HKP.
  */
-static int hkp_delete_key(uint64_t keyid, bool intrans)
+static int hkp_delete_key(struct onak_dbctx *dbctx,
+               uint64_t keyid, bool intrans)
 {
        return -1;
 }
@@ -321,8 +287,9 @@ static int hkp_delete_key(uint64_t keyid, bool intrans)
  *
  *     Not applicable for HKP backend.
  */
-static int hkp_iterate_keys(void (*iterfunc)(void *ctx,
-               struct openpgp_publickey *key), void *ctx)
+static int hkp_iterate_keys(struct onak_dbctx *dbctx,
+               void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
+               void *ctx)
 {
        return 0;
 }
@@ -332,7 +299,7 @@ static int hkp_iterate_keys(void (*iterfunc)(void *ctx,
  *
  *     This is just a no-op for HKP access.
  */
-static bool hkp_starttrans(void)
+static bool hkp_starttrans(struct onak_dbctx *dbctx)
 {
        return true;
 }
@@ -342,7 +309,7 @@ static bool hkp_starttrans(void)
  *
  *     This is just a no-op for HKP access.
  */
-static void hkp_endtrans(void)
+static void hkp_endtrans(struct onak_dbctx *dbctx)
 {
        return;
 }
@@ -356,20 +323,81 @@ static void hkp_endtrans(void)
 #define NEED_UPDATEKEYS 1
 #include "keydb.c"
 
-struct dbfuncs keydb_hkp_funcs = {
-       .initdb                 = hkp_initdb,
-       .cleanupdb              = hkp_cleanupdb,
-       .starttrans             = hkp_starttrans,
-       .endtrans               = hkp_endtrans,
-       .fetch_key_id           = hkp_fetch_key_id,
-       .fetch_key_fp           = hkp_fetch_key_fp,
-       .fetch_key_text         = hkp_fetch_key_text,
-       .store_key              = hkp_store_key,
-       .update_keys            = generic_update_keys,
-       .delete_key             = hkp_delete_key,
-       .getkeysigs             = generic_getkeysigs,
-       .cached_getkeysigs      = generic_cached_getkeysigs,
-       .keyid2uid              = generic_keyid2uid,
-       .getfullkeyid           = generic_getfullkeyid,
-       .iterate_keys           = hkp_iterate_keys,
-};
+/**
+ *     cleanupdb - De-initialize the key database.
+ *
+ *     We cleanup CURL here.
+ */
+static void hkp_cleanupdb(struct onak_dbctx *dbctx)
+{
+       struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv;
+
+       if (privctx->curl) {
+               curl_easy_cleanup(privctx->curl);
+               privctx->curl = NULL;
+       }
+       curl_global_cleanup();
+       free(privctx);
+       free(dbctx);
+}
+
+/**
+ *     initdb - Initialize the key database.
+ *
+ *     We initialize CURL here.
+ */
+struct onak_dbctx *keydb_hkp_init(bool readonly)
+{
+       struct onak_dbctx *dbctx;
+       struct onak_hkp_dbctx *privctx;
+       curl_version_info_data *curl_info;
+
+       dbctx = malloc(sizeof(struct onak_dbctx));
+       if (dbctx == NULL) {
+               return NULL;
+       }
+
+       dbctx->priv = privctx = malloc(sizeof(*privctx));
+       dbctx->cleanupdb                = hkp_cleanupdb;
+       dbctx->starttrans               = hkp_starttrans;
+       dbctx->endtrans                 = hkp_endtrans;
+       dbctx->fetch_key_id             = hkp_fetch_key_id;
+       dbctx->fetch_key_fp             = hkp_fetch_key_fp;
+       dbctx->fetch_key_text           = hkp_fetch_key_text;
+       dbctx->store_key                = hkp_store_key;
+       dbctx->update_keys              = generic_update_keys;
+       dbctx->delete_key               = hkp_delete_key;
+       dbctx->getkeysigs               = generic_getkeysigs;
+       dbctx->cached_getkeysigs        = generic_cached_getkeysigs;
+       dbctx->keyid2uid                = generic_keyid2uid;
+       dbctx->getfullkeyid             = generic_getfullkeyid;
+       dbctx->iterate_keys             = hkp_iterate_keys;
+
+       if (!hkp_parse_url(privctx, config.db_dir)) {
+               exit(EXIT_FAILURE);
+       }
+       curl_global_init(CURL_GLOBAL_DEFAULT);
+       privctx->curl = curl_easy_init();
+       if (privctx->curl == NULL) {
+               logthing(LOGTHING_CRITICAL, "Could not initialize CURL.");
+               hkp_cleanupdb(dbctx);
+               dbctx = NULL;
+               exit(EXIT_FAILURE);
+       }
+       curl_easy_setopt(privctx->curl, CURLOPT_USERAGENT,
+               "onak/" ONAK_VERSION);
+
+       if (strncmp(privctx->hkpbase, "https://", 8) == 0) {
+               curl_info = curl_version_info(CURLVERSION_NOW);
+               if (! (curl_info->features & CURL_VERSION_SSL)) {
+                       logthing(LOGTHING_CRITICAL,
+                               "CURL lacks SSL support; cannot use HKP url: %s",
+                               privctx->hkpbase);
+                       hkp_cleanupdb(dbctx);
+                       dbctx = NULL;
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       return dbctx;
+}
index 7995e38a8e757ddb7a1d685432ae54d7b432aa0e..5fd084398d048568df01867785f24453c93304a4 100644 (file)
 #include "onak-conf.h"
 #include "parsekey.h"
 
-/**
- *     keyd_fd - our file descriptor for the socket connection to keyd.
- */
-static int keyd_fd = -1;
-
-/**
- *     initdb - Initialize the key database.
- *     @readonly: If we'll only be reading the DB, not writing to it.
- *
- *     This function should be called before any of the other functions in
- *     this file are called in order to allow the DB to be initialized ready
- *     for access.
- */
-static void keyd_initdb(bool readonly)
-{
-       struct sockaddr_un sock;
-       uint32_t           cmd = KEYD_CMD_UNKNOWN;
-       uint32_t           reply = KEYD_REPLY_UNKNOWN_CMD;
-       ssize_t            count;
-
-       keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
-       if (keyd_fd < 0) {
-               logthing(LOGTHING_CRITICAL,
-                               "Couldn't open socket: %s (%d)",
-                               strerror(errno),
-                               errno);
-               exit(EXIT_FAILURE);
-       }
-
-       sock.sun_family = AF_UNIX;
-       snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
-                       config.db_dir,
-                       KEYD_SOCKET);
-       if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
-               logthing(LOGTHING_CRITICAL,
-                               "Couldn't connect to socket %s: %s (%d)",
-                               sock.sun_path,
-                               strerror(errno),
-                               errno);
-               exit(EXIT_FAILURE);
-       }
-
-       cmd = KEYD_CMD_VERSION;
-       if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
-               logthing(LOGTHING_CRITICAL,
-                               "Couldn't write version cmd: %s (%d)",
-                               strerror(errno),
-                               errno);
-       } else {
-               count = read(keyd_fd, &reply, sizeof(reply));
-               if (count == sizeof(reply) && reply == KEYD_REPLY_OK) {
-                       count = read(keyd_fd, &reply, sizeof(reply));
-                       if (count != sizeof(reply) || reply != sizeof(reply)) {
-                               logthing(LOGTHING_CRITICAL,
-                                       "Error! Unexpected keyd version "
-                                       "length: %d != %d",
-                                       reply, sizeof(reply));
-                               exit(EXIT_FAILURE);
-                       }
-
-                       count = read(keyd_fd, &reply, sizeof(reply));
-                       logthing(LOGTHING_DEBUG,
-                                       "keyd protocol version %d",
-                                       reply);
-                       if (reply != keyd_version) {
-                               logthing(LOGTHING_CRITICAL,
-                                       "Error! keyd protocol version "
-                                       "mismatch. (us = %d, it = %d)",
-                                               keyd_version, reply);
-                       }
-               }
-       }
-
-       return;
-}
-
-/**
- *     cleanupdb - De-initialize the key database.
- *
- *     This function should be called upon program exit to allow the DB to
- *     cleanup after itself.
- */
-static void keyd_cleanupdb(void)
-{
-       uint32_t cmd = KEYD_CMD_CLOSE;
-
-       if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
-               logthing(LOGTHING_CRITICAL,
-                               "Couldn't send close cmd: %s (%d)",
-                               strerror(errno),
-                               errno);
-       }
-       
-       if (read(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
-               logthing(LOGTHING_CRITICAL,
-                       "Couldn't read close cmd reply: %s (%d)",
-                       strerror(errno),
-                       errno);
-       } else if (cmd != KEYD_REPLY_OK) {
-               logthing(LOGTHING_CRITICAL,
-                       "Got bad reply to KEYD_CMD_CLOSE: %d", cmd);
-       }
-
-       if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
-               logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
-                               errno);
-       }
-       if (close(keyd_fd) < 0) {
-               logthing(LOGTHING_NOTICE, "Error closing down socket: %d",
-                               errno);
-       }
-       keyd_fd = -1;
-
-       return;
-}
-
-
 /**
  *     starttrans - Start a transaction.
  *
@@ -161,7 +44,7 @@ static void keyd_cleanupdb(void)
  *     operations on the database to help speed it all up, or if we want
  *     something to only succeed if all relevant operations are successful.
  */
-static bool keyd_starttrans(void)
+static bool keyd_starttrans(struct onak_dbctx *dbctx)
 {
        return true;
 }
@@ -171,7 +54,7 @@ static bool keyd_starttrans(void)
  *
  *     Ends a transaction.
  */
-static void keyd_endtrans(void)
+static void keyd_endtrans(struct onak_dbctx *dbctx)
 {
        return;
 }
@@ -187,10 +70,12 @@ static void keyd_endtrans(void)
  *
  *      TODO: What about keyid collisions? Should we use fingerprint instead?
  */
-static int keyd_fetch_key_id(uint64_t keyid,
+static int keyd_fetch_key_id(struct onak_dbctx *dbctx,
+               uint64_t keyid,
                struct openpgp_publickey **publickey,
                bool intrans)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        struct buffer_ctx           keybuf;
        struct openpgp_packet_list *packets = NULL;
        uint32_t                    cmd = KEYD_CMD_GET_ID;
@@ -230,10 +115,12 @@ static int keyd_fetch_key_id(uint64_t keyid,
        return (count > 0) ? 1 : 0;
 }
 
-static int keyd_fetch_key_fp(uint8_t *fp, size_t fpsize,
+static int keyd_fetch_key_fp(struct onak_dbctx *dbctx,
+               uint8_t *fp, size_t fpsize,
                struct openpgp_publickey **publickey,
                bool intrans)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        struct buffer_ctx           keybuf;
        struct openpgp_packet_list *packets = NULL;
        uint32_t                    cmd = KEYD_CMD_GET_FP;
@@ -288,8 +175,10 @@ static int keyd_fetch_key_fp(uint8_t *fp, size_t fpsize,
 *      This function deletes a public key from whatever storage mechanism we
 *      are using. Returns 0 if the key existed.
 */
-static int keyd_delete_key(uint64_t keyid, bool intrans)
+static int keyd_delete_key(struct onak_dbctx *dbctx,
+               uint64_t keyid, bool intrans)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        uint32_t cmd = KEYD_CMD_DELETE;
 
        write(keyd_fd, &cmd, sizeof(cmd));
@@ -315,9 +204,11 @@ static int keyd_delete_key(uint64_t keyid, bool intrans)
  *     TODO: Do we store multiple keys of the same id? Or only one and replace
  *     it?
  */
-static int keyd_store_key(struct openpgp_publickey *publickey, bool intrans,
+static int keyd_store_key(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *publickey, bool intrans,
                bool update)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        struct buffer_ctx           keybuf;
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_packet_list *list_end = NULL;
@@ -329,9 +220,9 @@ static int keyd_store_key(struct openpgp_publickey *publickey, bool intrans,
                logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
                return 0;
        }
-       
+
        if (update) {
-               keyd_delete_key(keyid, false);
+               keyd_delete_key(dbctx, keyid, false);
        }
 
        write(keyd_fd, &cmd, sizeof(cmd));
@@ -359,7 +250,7 @@ static int keyd_store_key(struct openpgp_publickey *publickey, bool intrans,
                keybuf.buffer = NULL;
                keybuf.size = keybuf.offset = 0;
        }
-       
+
        return 0;
 }
 
@@ -371,9 +262,11 @@ static int keyd_store_key(struct openpgp_publickey *publickey, bool intrans,
  *     This function searches for the supplied text and returns the keys that
  *     contain it.
  */
-static int keyd_fetch_key_text(const char *search,
+static int keyd_fetch_key_text(struct onak_dbctx *dbctx,
+               const char *search,
                struct openpgp_publickey **publickey)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        struct buffer_ctx           keybuf;
        struct openpgp_packet_list *packets = NULL;
        uint32_t                    cmd = KEYD_CMD_GET_TEXT;
@@ -411,15 +304,17 @@ static int keyd_fetch_key_text(const char *search,
                        keybuf.size = 0;
                }
        }
-       
+
        return (count > 0) ? 1 : 0;
 
        return 0;
 }
 
-static int keyd_fetch_key_skshash(const struct skshash *hash,
+static int keyd_fetch_key_skshash(struct onak_dbctx *dbctx,
+               const struct skshash *hash,
                struct openpgp_publickey **publickey)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        struct buffer_ctx           keybuf;
        struct openpgp_packet_list *packets = NULL;
        uint32_t                    cmd = KEYD_CMD_GET_SKSHASH;
@@ -455,7 +350,7 @@ static int keyd_fetch_key_skshash(const struct skshash *hash,
                        keybuf.size = 0;
                }
        }
-       
+
        return (count > 0) ? 1 : 0;
 }
 
@@ -467,8 +362,9 @@ static int keyd_fetch_key_skshash(const struct skshash *hash,
  *     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 keyd_getfullkeyid(uint64_t keyid)
+static uint64_t keyd_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        uint32_t cmd = KEYD_CMD_GETFULLKEYID;
 
        write(keyd_fd, &cmd, sizeof(cmd));
@@ -496,9 +392,11 @@ static uint64_t keyd_getfullkeyid(uint64_t keyid)
  *
  *     Returns the number of keys we iterated over.
  */
-static int keyd_iterate_keys(void (*iterfunc)(void *ctx,
+static int keyd_iterate_keys(struct onak_dbctx *dbctx,
+               void (*iterfunc)(void *ctx,
                struct openpgp_publickey *key), void *ctx)
 {
+       int keyd_fd = (intptr_t) dbctx->priv;
        struct buffer_ctx           keybuf;
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_publickey   *key = NULL;
@@ -546,7 +444,7 @@ static int keyd_iterate_keys(void (*iterfunc)(void *ctx,
                        read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
                }
        }
-       
+
        return numkeys;
 }
 
@@ -555,21 +453,140 @@ static int keyd_iterate_keys(void (*iterfunc)(void *ctx,
 #define NEED_UPDATEKEYS 1
 #include "keydb.c"
 
-struct dbfuncs keydb_keyd_funcs = {
-       .initdb                 = keyd_initdb,
-       .cleanupdb              = keyd_cleanupdb,
-       .starttrans             = keyd_starttrans,
-       .endtrans               = keyd_endtrans,
-       .fetch_key_id           = keyd_fetch_key_id,
-       .fetch_key_fp           = keyd_fetch_key_fp,
-       .fetch_key_text         = keyd_fetch_key_text,
-       .fetch_key_skshash      = keyd_fetch_key_skshash,
-       .store_key              = keyd_store_key,
-       .update_keys            = generic_update_keys,
-       .delete_key             = keyd_delete_key,
-       .getkeysigs             = generic_getkeysigs,
-       .cached_getkeysigs      = generic_cached_getkeysigs,
-       .keyid2uid              = generic_keyid2uid,
-       .getfullkeyid           = keyd_getfullkeyid,
-       .iterate_keys           = keyd_iterate_keys,
-};
+/**
+ *     cleanupdb - De-initialize the key database.
+ *
+ *     This function should be called upon program exit to allow the DB to
+ *     cleanup after itself.
+ */
+static void keyd_cleanupdb(struct onak_dbctx *dbctx)
+{
+       int keyd_fd = (intptr_t) dbctx->priv;
+       uint32_t cmd = KEYD_CMD_CLOSE;
+
+       if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
+               logthing(LOGTHING_CRITICAL,
+                               "Couldn't send close cmd: %s (%d)",
+                               strerror(errno),
+                               errno);
+       }
+
+       if (read(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
+               logthing(LOGTHING_CRITICAL,
+                       "Couldn't read close cmd reply: %s (%d)",
+                       strerror(errno),
+                       errno);
+       } else if (cmd != KEYD_REPLY_OK) {
+               logthing(LOGTHING_CRITICAL,
+                       "Got bad reply to KEYD_CMD_CLOSE: %d", cmd);
+       }
+
+       if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
+               logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
+                               errno);
+       }
+       if (close(keyd_fd) < 0) {
+               logthing(LOGTHING_NOTICE, "Error closing down socket: %d",
+                               errno);
+       }
+       keyd_fd = -1;
+
+       free(dbctx);
+
+       return;
+}
+
+/**
+ *     initdb - Initialize the key database.
+ *     @readonly: If we'll only be reading the DB, not writing to it.
+ *
+ *     This function should be called before any of the other functions in
+ *     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 sockaddr_un sock;
+       uint32_t           cmd = KEYD_CMD_UNKNOWN;
+       uint32_t           reply = KEYD_REPLY_UNKNOWN_CMD;
+       ssize_t            count;
+       int keyd_fd;
+       struct onak_dbctx *dbctx;
+
+       dbctx = malloc(sizeof(*dbctx));
+       if (dbctx == NULL) {
+               return NULL;
+       }
+
+       keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
+       if (keyd_fd < 0) {
+               logthing(LOGTHING_CRITICAL,
+                               "Couldn't open socket: %s (%d)",
+                               strerror(errno),
+                               errno);
+               exit(EXIT_FAILURE);
+       }
+
+       sock.sun_family = AF_UNIX;
+       snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
+                       config.db_dir,
+                       KEYD_SOCKET);
+       if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
+               logthing(LOGTHING_CRITICAL,
+                               "Couldn't connect to socket %s: %s (%d)",
+                               sock.sun_path,
+                               strerror(errno),
+                               errno);
+               exit(EXIT_FAILURE);
+       }
+
+       cmd = KEYD_CMD_VERSION;
+       if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
+               logthing(LOGTHING_CRITICAL,
+                               "Couldn't write version cmd: %s (%d)",
+                               strerror(errno),
+                               errno);
+       } else {
+               count = read(keyd_fd, &reply, sizeof(reply));
+               if (count == sizeof(reply) && reply == KEYD_REPLY_OK) {
+                       count = read(keyd_fd, &reply, sizeof(reply));
+                       if (count != sizeof(reply) || reply != sizeof(reply)) {
+                               logthing(LOGTHING_CRITICAL,
+                                       "Error! Unexpected keyd version "
+                                       "length: %d != %d",
+                                       reply, sizeof(reply));
+                               exit(EXIT_FAILURE);
+                       }
+
+                       count = read(keyd_fd, &reply, sizeof(reply));
+                       logthing(LOGTHING_DEBUG,
+                                       "keyd protocol version %d",
+                                       reply);
+                       if (reply != keyd_version) {
+                               logthing(LOGTHING_CRITICAL,
+                                       "Error! keyd protocol version "
+                                       "mismatch. (us = %d, it = %d)",
+                                               keyd_version, reply);
+                       }
+               }
+       }
+
+       dbctx->priv                     = (void *) (intptr_t) keyd_fd;
+       dbctx->cleanupdb                = keyd_cleanupdb;
+       dbctx->starttrans               = keyd_starttrans;
+       dbctx->endtrans                 = keyd_endtrans;
+       dbctx->fetch_key_id             = keyd_fetch_key_id;
+       dbctx->fetch_key_fp             = keyd_fetch_key_fp;
+       dbctx->fetch_key_text           = keyd_fetch_key_text;
+       dbctx->fetch_key_skshash        = keyd_fetch_key_skshash;
+       dbctx->store_key                = keyd_store_key;
+       dbctx->update_keys              = generic_update_keys;
+       dbctx->delete_key               = keyd_delete_key;
+       dbctx->getkeysigs               = generic_getkeysigs;
+       dbctx->cached_getkeysigs        = generic_cached_getkeysigs;
+       dbctx->keyid2uid                = generic_keyid2uid;
+       dbctx->getfullkeyid             = keyd_getfullkeyid;
+       dbctx->iterate_keys             = keyd_iterate_keys;
+
+       return dbctx;
+}
index 04c760dfbf9759cca2e60241f1fdaeac1f2f8bb3..ca7e35bac0545796f4fe32c768a4b47af2ec78d0 100644 (file)
 #include "onak-conf.h"
 #include "parsekey.h"
 
-/**
- *     dbconn - our connection to the database.
- */
-static PGconn *dbconn = NULL;
+struct pg_fc_ctx {
+       PGconn *dbconn;
+       int fd;
+};
 
 /**
  *     keydb_fetchchar - Fetches a char from a file.
  */
-static int keydb_fetchchar(void *fd, size_t count, void *c)
+static int keydb_fetchchar(void *_ctx, size_t count, void *c)
 {
-       return (!lo_read(dbconn, *(int *) fd, (char *) c, count));
-}
+       struct pg_fc_ctx *ctx = (struct pg_fc_ctx *) _ctx;
 
-/**
- *     keydb_putchar - Puts a char to a file.
- */
-static int keydb_putchar(void *fd, size_t count, void *c)
-{
-       return !(lo_write(dbconn, *(int *) fd, (char *) c, count));
+       return (!lo_read(ctx->dbconn, ctx->fd, (char *) c, count));
 }
 
 /**
- *     initdb - Initialize the key database.
- *
- *     This function should be called before any of the other functions in
- *     this file are called in order to allow the DB to be initialized ready
- *     for access.
+ *     keydb_putchar - Puts a char to a file.
  */
-static void pg_initdb(bool readonly)
+static int keydb_putchar(void *_ctx, size_t count, void *c)
 {
-       dbconn = PQsetdbLogin(config.pg_dbhost, // host
-                       NULL, // port
-                       NULL, // options
-                       NULL, // tty
-                       config.pg_dbname, // database
-                       config.pg_dbuser,  //login
-                       config.pg_dbpass); // password
+       struct pg_fc_ctx *ctx = (struct pg_fc_ctx *) _ctx;
 
-       if (PQstatus(dbconn) == CONNECTION_BAD) {
-               logthing(LOGTHING_CRITICAL, "Connection to database failed.");
-               logthing(LOGTHING_CRITICAL, "%s", PQerrorMessage(dbconn));
-               PQfinish(dbconn);
-               dbconn = NULL;
-               exit(1);
-       }
-}
-
-/**
- *     cleanupdb - De-initialize the key database.
- *
- *     This function should be called upon program exit to allow the DB to
- *     cleanup after itself.
- */
-static void pg_cleanupdb(void)
-{
-       PQfinish(dbconn);
-       dbconn = NULL;
+       return !(lo_write(ctx->dbconn, ctx->fd, (char *) c, count));
 }
 
 /**
@@ -105,8 +71,9 @@ static void pg_cleanupdb(void)
  *     operations on the database to help speed it all up, or if we want
  *     something to only succeed if all relevant operations are successful.
  */
-static bool pg_starttrans(void)
+static bool pg_starttrans(struct onak_dbctx *dbctx)
 {
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        
        result = PQexec(dbconn, "BEGIN");
@@ -120,8 +87,9 @@ static bool pg_starttrans(void)
  *
  *     Ends a transaction.
  */
-static void pg_endtrans(void)
+static void pg_endtrans(struct onak_dbctx *dbctx)
 {
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
 
        result = PQexec(dbconn, "COMMIT");
@@ -142,18 +110,20 @@ static void pg_endtrans(void)
  *     in and then parse_keys() to parse the packets into a publickey
  *     structure.
  */
-static int pg_fetch_key_id(uint64_t keyid,
+static int pg_fetch_key_id(struct onak_dbctx *dbctx,
+               uint64_t keyid,
                struct openpgp_publickey **publickey,
                bool intrans)
 {
        struct openpgp_packet_list *packets = NULL;
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        char *oids = NULL;
        char statement[1024];
-       int fd = -1;
        int i = 0;
        int numkeys = 0;
        Oid key_oid;
+       struct pg_fc_ctx fcctx;
 
        if (!intrans) {
                result = PQexec(dbconn, "BEGIN");
@@ -179,15 +149,16 @@ static int pg_fetch_key_id(uint64_t keyid,
                        oids = PQgetvalue(result, i, 0);
                        key_oid = (Oid) atoi(oids);
 
-                       fd = lo_open(dbconn, key_oid, INV_READ);
-                       if (fd < 0) {
+                       fcctx.fd = lo_open(dbconn, key_oid, INV_READ);
+                       if (fcctx.fd < 0) {
                                logthing(LOGTHING_ERROR,
                                                "Can't open large object.");
                        } else {
-                               read_openpgp_stream(keydb_fetchchar, &fd,
+                               fcctx.dbconn = dbconn;
+                               read_openpgp_stream(keydb_fetchchar, &fcctx,
                                                &packets, 0);
                                parse_keys(packets, publickey);
-                               lo_close(dbconn, fd);
+                               lo_close(dbconn, fcctx.fd);
                                free_packet_list(packets);
                                packets = NULL;
                        }
@@ -213,18 +184,20 @@ static int pg_fetch_key_id(uint64_t keyid,
  *     This function searches for the supplied text and returns the keys that
  *     contain it.
  */
-static int pg_fetch_key_text(const char *search,
+static int pg_fetch_key_text(struct onak_dbctx *dbctx,
+               const char *search,
                struct openpgp_publickey **publickey)
 {
        struct openpgp_packet_list *packets = NULL;
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        char *oids = NULL;
        char statement[1024];
-       int fd = -1;
        int i = 0;
        int numkeys = 0;
        Oid key_oid;
        char *newsearch = NULL;
+       struct pg_fc_ctx fcctx;
 
        result = PQexec(dbconn, "BEGIN");
        PQclear(result);
@@ -247,16 +220,17 @@ static int pg_fetch_key_text(const char *search,
                        oids = PQgetvalue(result, i, 0);
                        key_oid = (Oid) atoi(oids);
 
-                       fd = lo_open(dbconn, key_oid, INV_READ);
-                       if (fd < 0) {
+                       fcctx.fd = lo_open(dbconn, key_oid, INV_READ);
+                       if (fcctx.fd < 0) {
                                logthing(LOGTHING_ERROR,
                                                "Can't open large object.");
                        } else {
-                               read_openpgp_stream(keydb_fetchchar, &fd,
+                               fcctx.dbconn = dbconn;
+                               read_openpgp_stream(keydb_fetchchar, &fcctx,
                                                &packets,
                                                0);
                                parse_keys(packets, publickey);
-                               lo_close(dbconn, fd);
+                               lo_close(dbconn, fcctx.fd);
                                free_packet_list(packets);
                                packets = NULL;
                        }
@@ -280,8 +254,9 @@ static int pg_fetch_key_text(const char *search,
  *     This function deletes a public key from whatever storage mechanism we
  *     are using. Returns 0 if the key existed.
  */
-static int pg_delete_key(uint64_t keyid, bool intrans)
+static int pg_delete_key(struct onak_dbctx *dbctx, uint64_t keyid, bool intrans)
 {
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        char *oids = NULL;
        char statement[1024];
@@ -355,22 +330,24 @@ static int pg_delete_key(uint64_t keyid, bool intrans)
  *     the file. If update is true then we delete the old key first, otherwise
  *     we trust that it doesn't exist.
  */
-static int pg_store_key(struct openpgp_publickey *publickey, bool intrans,
+static int pg_store_key(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *publickey, bool intrans,
                bool update)
 {
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_packet_list *list_end = NULL;
        struct openpgp_publickey *next = NULL;
        struct openpgp_signedpacket_list *curuid = NULL;
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        char statement[1024];
        Oid key_oid;
-       int fd;
        char **uids = NULL;
        char *primary = NULL;
        char *safeuid = NULL;
        int i;
        uint64_t keyid;
+       struct pg_fc_ctx fcctx;
 
        if (!intrans) {
                result = PQexec(dbconn, "BEGIN");
@@ -391,7 +368,7 @@ static int pg_store_key(struct openpgp_publickey *publickey, bool intrans,
         * it definitely needs updated.
         */
        if (update) {
-               pg_delete_key(keyid, true);
+               pg_delete_key(dbctx, keyid, true);
        }
 
        next = publickey->next;
@@ -403,9 +380,10 @@ static int pg_store_key(struct openpgp_publickey *publickey, bool intrans,
        if (key_oid == 0) {
                logthing(LOGTHING_ERROR, "Can't create key OID");
        } else {
-               fd = lo_open(dbconn, key_oid, INV_WRITE);
-               write_openpgp_stream(keydb_putchar, &fd, packets);
-               lo_close(dbconn, fd);
+               fcctx.fd = lo_open(dbconn, key_oid, INV_WRITE);
+               fcctx.dbconn = dbconn;
+               write_openpgp_stream(keydb_putchar, &fcctx, packets);
+               lo_close(dbconn, fcctx.fd);
        }
        free_packet_list(packets);
        packets = NULL;
@@ -489,8 +467,9 @@ static int pg_store_key(struct openpgp_publickey *publickey, bool intrans,
  *     keyid2uid - Takes a keyid and returns the primary UID for it.
  *     @keyid: The keyid to lookup.
  */
-static char *pg_keyid2uid(uint64_t keyid)
+static char *pg_keyid2uid(struct onak_dbctx *dbctx, uint64_t keyid)
 {
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        char statement[1024];
        char *uid = NULL;
@@ -531,9 +510,11 @@ static char *pg_keyid2uid(uint64_t keyid)
  *     This function gets the list of signatures on a key. Used for key 
  *     indexing and doing stats bits.
  */
-static struct ll *pg_getkeysigs(uint64_t keyid, bool *revoked)
+static struct ll *pg_getkeysigs(struct onak_dbctx *dbctx,
+                       uint64_t keyid, bool *revoked)
 {
        struct ll *sigs = NULL;
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        uint64_t signer;
        char statement[1024];
@@ -604,17 +585,19 @@ static struct ll *pg_getkeysigs(uint64_t keyid, bool *revoked)
  *
  *     Returns the number of keys we iterated over.
  */
-static int pg_iterate_keys(void (*iterfunc)(void *ctx,
+static int pg_iterate_keys(struct onak_dbctx *dbctx,
+               void (*iterfunc)(void *ctx,
                struct openpgp_publickey *key), void *ctx)
 {
        struct openpgp_packet_list *packets = NULL;
        struct openpgp_publickey *key = NULL;
+       PGconn *dbconn = (PGconn *) dbctx->priv;
        PGresult *result = NULL;
        char *oids = NULL;
-       int fd = -1;
        int i = 0;
        int numkeys = 0;
        Oid key_oid;
+       struct pg_fc_ctx fcctx;
 
        result = PQexec(dbconn, "SELECT keydata FROM onak_keys;");
 
@@ -624,15 +607,16 @@ static int pg_iterate_keys(void (*iterfunc)(void *ctx,
                        oids = PQgetvalue(result, i, 0);
                        key_oid = (Oid) atoi(oids);
 
-                       fd = lo_open(dbconn, key_oid, INV_READ);
-                       if (fd < 0) {
+                       fcctx.fd = lo_open(dbconn, key_oid, INV_READ);
+                       if (fcctx.fd < 0) {
                                logthing(LOGTHING_ERROR,
                                                "Can't open large object.");
                        } else {
-                               read_openpgp_stream(keydb_fetchchar, &fd,
+                               fcctx.dbconn = dbconn;
+                               read_openpgp_stream(keydb_fetchchar, &fcctx,
                                                &packets, 0);
                                parse_keys(packets, &key);
-                               lo_close(dbconn, fd);
+                               lo_close(dbconn, fcctx.fd);
 
                                iterfunc(ctx, key);
                                        
@@ -659,20 +643,71 @@ static int pg_iterate_keys(void (*iterfunc)(void *ctx,
 #define NEED_GET_FP 1
 #include "keydb.c"
 
-struct dbfuncs keydb_pg_funcs = {
-       .initdb                 = pg_initdb,
-       .cleanupdb              = pg_cleanupdb,
-       .starttrans             = pg_starttrans,
-       .endtrans               = pg_endtrans,
-       .fetch_key_id           = pg_fetch_key_id,
-       .fetch_key_fp           = generic_fetch_key_fp,
-       .fetch_key_text         = pg_fetch_key_text,
-       .store_key              = pg_store_key,
-       .update_keys            = generic_update_keys,
-       .delete_key             = pg_delete_key,
-       .getkeysigs             = pg_getkeysigs,
-       .cached_getkeysigs      = generic_cached_getkeysigs,
-       .keyid2uid              = pg_keyid2uid,
-       .getfullkeyid           = generic_getfullkeyid,
-       .iterate_keys           = pg_iterate_keys,
-};
+/**
+ *     cleanupdb - De-initialize the key database.
+ *
+ *     This function should be called upon program exit to allow the DB to
+ *     cleanup after itself.
+ */
+static void pg_cleanupdb(struct onak_dbctx *dbctx)
+{
+       PGconn *dbconn = (PGconn *) dbctx->priv;
+
+       PQfinish(dbconn);
+       dbconn = NULL;
+
+       free(dbctx);
+}
+
+/**
+ *     initdb - Initialize the key database.
+ *
+ *     This function should be called before any of the other functions in
+ *     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 *dbctx;
+       PGconn *dbconn;
+
+       dbctx = malloc(sizeof(struct onak_dbctx));
+       if (dbctx == NULL) {
+               return NULL;
+       }
+
+       dbconn = PQsetdbLogin(config.pg_dbhost, // host
+                       NULL, // port
+                       NULL, // options
+                       NULL, // tty
+                       config.pg_dbname, // database
+                       config.pg_dbuser,  //login
+                       config.pg_dbpass); // password
+
+       if (PQstatus(dbconn) == CONNECTION_BAD) {
+               logthing(LOGTHING_CRITICAL, "Connection to database failed.");
+               logthing(LOGTHING_CRITICAL, "%s", PQerrorMessage(dbconn));
+               PQfinish(dbconn);
+               dbconn = NULL;
+               exit(1);
+       }
+
+       dbctx->priv = dbconn;
+
+       dbctx->cleanupdb                = pg_cleanupdb;
+       dbctx->starttrans               = pg_starttrans;
+       dbctx->endtrans                 = pg_endtrans;
+       dbctx->fetch_key_id             = pg_fetch_key_id;
+       dbctx->fetch_key_fp             = generic_fetch_key_fp;
+       dbctx->fetch_key_text           = pg_fetch_key_text;
+       dbctx->store_key                = pg_store_key;
+       dbctx->update_keys              = generic_update_keys;
+       dbctx->delete_key               = pg_delete_key;
+       dbctx->getkeysigs               = pg_getkeysigs;
+       dbctx->cached_getkeysigs        = generic_cached_getkeysigs;
+       dbctx->keyid2uid                = pg_keyid2uid;
+       dbctx->getfullkeyid             = generic_getfullkeyid;
+       dbctx->iterate_keys             = pg_iterate_keys;
+
+       return dbctx;
+}
index 4ffecae2943a3fa2bcb51ba08a4889aa0c8208dc..47492c59e26c887474cf125b6024cea1a3de2bf5 100644 (file)
--- a/keydctl.c
+++ b/keydctl.c
@@ -32,7 +32,7 @@
 #include "version.h"
 
 /* HACK: We need to stop onak-conf.o requiring this. */
-void *DBFUNCS = NULL;
+void *DBINIT = NULL;
 
 static int keyd_fd = -1;
 static int verbose = 0;
index f3c36aafbf3527408894357ce80c1c7f6ecc2bd0..4ca6a413f02642bd1501af78abc7039f91ba74a3 100644 (file)
@@ -138,7 +138,8 @@ unsigned int keylength(struct openpgp_packet *keydata)
        return length;
 }
 
-int list_sigs(struct openpgp_packet_list *sigs, bool html)
+int list_sigs(struct onak_dbctx *dbctx,
+               struct openpgp_packet_list *sigs, bool html)
 {
        char *uid = NULL;
        uint64_t sigid = 0;
@@ -146,7 +147,7 @@ int list_sigs(struct openpgp_packet_list *sigs, bool html)
 
        while (sigs != NULL) {
                sigid = sig_keyid(sigs->packet);
-               uid = config.dbbackend->keyid2uid(sigid);
+               uid = dbctx->keyid2uid(dbctx, sigid);
                if (sigs->packet->data[0] == 4 &&
                                sigs->packet->data[1] == 0x30) {
                        /* It's a Type 4 sig revocation */
@@ -188,7 +189,8 @@ int list_sigs(struct openpgp_packet_list *sigs, bool html)
        return 0;
 }
 
-int list_uids(uint64_t keyid, struct openpgp_signedpacket_list *uids,
+int list_uids(struct onak_dbctx *dbctx,
+               uint64_t keyid, struct openpgp_signedpacket_list *uids,
                bool verbose, bool html)
 {
        char buf[1024];
@@ -215,7 +217,7 @@ int list_uids(uint64_t keyid, struct openpgp_signedpacket_list *uids,
                        }
                }
                if (verbose) {
-                       list_sigs(uids->sigs, html);
+                       list_sigs(dbctx, uids->sigs, html);
                }
                uids = uids->next;
        }
@@ -223,7 +225,8 @@ int list_uids(uint64_t keyid, struct openpgp_signedpacket_list *uids,
        return 0;
 }
 
-int list_subkeys(struct openpgp_signedpacket_list *subkeys, bool verbose,
+int list_subkeys(struct onak_dbctx *dbctx,
+               struct openpgp_signedpacket_list *subkeys, bool verbose,
                bool html)
 {
        struct tm       *created = NULL;
@@ -270,7 +273,7 @@ int list_subkeys(struct openpgp_signedpacket_list *subkeys, bool verbose,
 
                }
                if (verbose) {
-                       list_sigs(subkeys->sigs, html);
+                       list_sigs(dbctx, subkeys->sigs, html);
                }
                subkeys = subkeys->next;
        }
@@ -337,7 +340,8 @@ void display_skshash(struct openpgp_publickey *key, bool html)
  *     This function takes a list of OpenPGP public keys and displays an index
  *     of them. Useful for debugging or the keyserver Index function.
  */
-int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
+int key_index(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *keys, bool verbose, bool fingerprint,
                        bool skshash, bool html)
 {
        struct openpgp_signedpacket_list        *curuid = NULL;
@@ -420,7 +424,7 @@ int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
                                display_fingerprint(keys);
                        }
                        if (verbose) {
-                               list_sigs(curuid->sigs, html);
+                               list_sigs(dbctx, curuid->sigs, html);
                        }
                        curuid = curuid->next;
                } else {
@@ -431,9 +435,9 @@ int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
                        }
                }
 
-               list_uids(keyid, curuid, verbose, html);
+               list_uids(dbctx, keyid, curuid, verbose, html);
                if (verbose) {
-                       list_subkeys(keys->subkeys, verbose, html);
+                       list_subkeys(dbctx, keys->subkeys, verbose, html);
                }
 
                keys = keys->next;
index c9a584328cb0b43ea24a79a80bc687947832890b..8a4e529e9545ee0c2be500a569cfa9cf45bdeb7d 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <stdbool.h>
 
+#include "keydb.h"
 #include "keystructs.h"
 
 /**
@@ -35,7 +36,8 @@
  *     This function takes a list of OpenPGP public keys and displays an index
  *     of them. Useful for debugging or the keyserver Index function.
  */
-int key_index(struct openpgp_publickey *keys, bool verbose,
+int key_index(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *keys, bool verbose,
                bool fingerprint, bool skshash, bool html);
 
 /**
index 13ffbcc9e11848557f454c96de6009673411d058..533433a3c1d66d9fee2e6221e095e5f1b61944ab 100644 (file)
--- a/lookup.c
+++ b/lookup.c
@@ -46,7 +46,8 @@
 #define OP_PHOTO   4
 #define OP_HGET    5
 
-void find_keys(char *search, uint64_t keyid, uint8_t *fp, size_t fpsize,
+void find_keys(struct onak_dbctx *dbctx,
+               char *search, uint64_t keyid, uint8_t *fp, size_t fpsize,
                bool ishex, bool isfp, bool fingerprint, bool skshash,
                bool exact, bool verbose, bool mrhkp)
 {
@@ -54,21 +55,21 @@ void find_keys(char *search, uint64_t keyid, uint8_t *fp, size_t fpsize,
        int count = 0;
 
        if (ishex) {
-               count = config.dbbackend->fetch_key_id(keyid, &publickey,
+               count = dbctx->fetch_key_id(dbctx, keyid, &publickey,
                                false);
        } else if (isfp) {
-               count = config.dbbackend->fetch_key_fp(fp, fpsize, &publickey,
+               count = dbctx->fetch_key_fp(dbctx, fp, fpsize, &publickey,
                                false);
        } else {
-               count = config.dbbackend->fetch_key_text(search, &publickey);
+               count = dbctx->fetch_key_text(dbctx, search, &publickey);
        }
        if (publickey != NULL) {
                if (mrhkp) {
                        printf("info:1:%d\n", count);
                        mrkey_index(publickey);
                } else {
-                       key_index(publickey, verbose, fingerprint, skshash,
-                               true);
+                       key_index(dbctx, publickey, verbose, fingerprint,
+                               skshash, true);
                }
                free_publickey(publickey);
        } else if (count == 0) {
@@ -124,6 +125,7 @@ int main(int argc, char *argv[])
        struct openpgp_packet_list *list_end = NULL;
        int result;
        struct skshash hash;
+       struct onak_dbctx *dbctx;
 
        params = getcgivars(argc, argv);
        for (i = 0; params != NULL && params[i] != NULL; i += 2) {
@@ -210,22 +212,22 @@ int main(int argc, char *argv[])
                readconfig(NULL);
                initlogthing("lookup", config.logfile);
                catchsignals();
-               config.dbbackend->initdb(false);
+               dbctx = config.dbinit(false);
                switch (op) {
                case OP_GET:
                case OP_HGET:
                        if (op == OP_HGET) {
                                parse_skshash(search, &hash);
-                               result = config.dbbackend->fetch_key_skshash(
+                               result = dbctx->fetch_key_skshash(dbctx,
                                        &hash, &publickey);
                        } else if (ishex) {
-                               result = config.dbbackend->fetch_key_id(keyid,
+                               result = dbctx->fetch_key_id(dbctx, keyid,
                                        &publickey, false);
                        } else if (isfp) {
-                               result = config.dbbackend->fetch_key_fp(fp,
+                               result = dbctx->fetch_key_fp(dbctx, fp,
                                        MAX_FINGERPRINT_LEN, &publickey, false);
                        } else {
-                               result = config.dbbackend->fetch_key_text(
+                               result = dbctx->fetch_key_text(dbctx,
                                        search,
                                        &publickey);
                        }
@@ -251,22 +253,22 @@ int main(int argc, char *argv[])
                        }
                        break;
                case OP_INDEX:
-                       find_keys(search, keyid, fp, MAX_FINGERPRINT_LEN,
+                       find_keys(dbctx, search, keyid, fp, MAX_FINGERPRINT_LEN,
                                        ishex, isfp, fingerprint, skshash,
                                        exact, false, mrhkp);
                        break;
                case OP_VINDEX:
-                       find_keys(search, keyid, fp, MAX_FINGERPRINT_LEN,
+                       find_keys(dbctx, search, keyid, fp, MAX_FINGERPRINT_LEN,
                                        ishex, isfp, fingerprint, skshash,
                                        exact, true, mrhkp);
                        break;
                case OP_PHOTO:
                        if (isfp) {
-                               config.dbbackend->fetch_key_fp(fp,
+                               dbctx->fetch_key_fp(dbctx, fp,
                                        MAX_FINGERPRINT_LEN,
                                        &publickey, false);
                        } else {
-                               config.dbbackend->fetch_key_id(keyid,
+                               dbctx->fetch_key_id(dbctx, keyid,
                                        &publickey, false);
                        }
                        if (publickey != NULL) {
@@ -287,7 +289,7 @@ int main(int argc, char *argv[])
                default:
                        puts("Unknown operation!");
                }
-               config.dbbackend->cleanupdb();
+               dbctx->cleanupdb(dbctx);
                cleanuplogthing();
                cleanupconfig();
        }
index 25264ced5855c0a21dcf45c6eae7782144d5dab4..fbd5a177deed76eb30139ebd8a5d85cd8abd7adf 100644 (file)
--- a/maxpath.c
+++ b/maxpath.c
@@ -30,7 +30,7 @@
 #include "onak-conf.h"
 #include "stats.h"
 
-void findmaxpath(unsigned long max)
+void findmaxpath(struct onak_dbctx *dbctx, unsigned long max)
 {
        struct stats_key *from, *to, *tmp;
        struct ll *curkey;
@@ -43,7 +43,7 @@ void findmaxpath(unsigned long max)
         * My (noodles@earth.li, RSA) key is in the strongly connected set of
         * keys, so we use it as a suitable starting seed.
         */
-       config.dbbackend->cached_getkeysigs(0x94FA372B2DA8B985);
+       dbctx->cached_getkeysigs(dbctx, 0x94FA372B2DA8B985);
 
        /*
         * Loop through the hash examining each key present and finding the
@@ -54,11 +54,11 @@ void findmaxpath(unsigned long max)
        for (loop = 0; (loop < HASHSIZE) && (distance < max); loop++) {
                curkey = gethashtableentry(loop);
                while (curkey != NULL && distance < max) {
-                       config.dbbackend->cached_getkeysigs(
+                       dbctx->cached_getkeysigs(dbctx,
                                        ((struct stats_key *)
                                        curkey->object)->keyid);
                        initcolour(false);
-                       tmp = furthestkey((struct stats_key *)
+                       tmp = furthestkey(dbctx, (struct stats_key *)
                                                curkey->object);
                        if (tmp->colour > distance) {
                                from = (struct stats_key *)curkey->object;
@@ -79,13 +79,14 @@ void findmaxpath(unsigned long max)
                        from->keyid,
                        to->keyid,
                        distance);
-       dofindpath(to->keyid, from->keyid, false, 1);
+       dofindpath(dbctx, to->keyid, from->keyid, false, 1);
 }
 
 int main(int argc, char *argv[])
 {
        int optchar;
        char *configfile = NULL;
+       struct onak_dbctx *dbctx;
 
        while ((optchar = getopt(argc, argv, "c:")) != -1 ) {
                switch (optchar) {
@@ -97,13 +98,17 @@ int main(int argc, char *argv[])
 
        readconfig(configfile);
        initlogthing("maxpath", config.logfile);
-       config.dbbackend->initdb(true);
-       inithash();
-       findmaxpath(30);
-       printf("--------\n");
-       findmaxpath(30);
-       destroyhash();
-       config.dbbackend->cleanupdb();
+       dbctx = config.dbinit(true);
+       if (dbctx != NULL) {
+               inithash();
+               findmaxpath(dbctx, 30);
+               printf("--------\n");
+               findmaxpath(dbctx, 30);
+               destroyhash();
+               dbctx->cleanupdb(dbctx);
+       } else {
+               fprintf(stderr, "Couldn't initialize key database.\n");
+       }
        cleanuplogthing();
        cleanupconfig();
        
index a29a58bfc7979df54957028a24cbc5b8734c72e9..e3085e1996be9e1fa6ec7690ea8f70fdf7e10951 100644 (file)
@@ -28,7 +28,7 @@
 #include "log.h"
 #include "onak-conf.h"
 
-extern struct dbfuncs DBFUNCS;
+extern struct onak_dbctx *DBINIT(bool readonly);
 
 /*
  *     config - Runtime configuration for onak.
@@ -65,7 +65,7 @@ struct onak_config config = {
        NULL,                   /* db_backend */
        NULL,                   /* backends_dir */
 
-       &DBFUNCS,               /* Default dbfuncs struct */
+       DBINIT,                 /* Default db initialisation function */
 
        true,                   /* Check packet sig hashes */
 };
index 2a9e335c91dc54d64b11b7ff2e910c9155c26430..34dcff2edd89c45aa3c63a4bb01bf23b2e3599a1 100644 (file)
@@ -76,8 +76,8 @@ struct onak_config {
        /** Directory where backend .so files can be found */
        char *backends_dir;
 
-       /** Pointer to the function table for our loaded DB backend */
-       struct dbfuncs *dbbackend;
+       /** Pointer to the initialisation function for our loaded DB backend */
+       struct onak_dbctx *(*dbinit)(bool);
 
        /** Should we verify signature hashes match? */
        bool check_sighash;
diff --git a/onak.c b/onak.c
index f67c969e513e47382cff59e1e5be867de36ed0bc..dd39bb3757fb2992e288923b5bb40f570160b48c 100644 (file)
--- a/onak.c
+++ b/onak.c
@@ -44,7 +44,8 @@
 #include "photoid.h"
 #include "version.h"
 
-void find_keys(char *search, uint64_t keyid, uint8_t *fp, bool ishex,
+void find_keys(struct onak_dbctx *dbctx,
+               char *search, uint64_t keyid, uint8_t *fp, bool ishex,
                bool isfp, bool fingerprint, bool skshash, bool exact,
                bool verbose)
 {
@@ -52,16 +53,17 @@ void find_keys(char *search, uint64_t keyid, uint8_t *fp, bool ishex,
        int count = 0;
 
        if (ishex) {
-               count = config.dbbackend->fetch_key_id(keyid, &publickey,
+               count = dbctx->fetch_key_id(dbctx, keyid, &publickey,
                                false);
        } else if (isfp) {
-               count = config.dbbackend->fetch_key_fp(fp, MAX_FINGERPRINT_LEN,
+               count = dbctx->fetch_key_fp(dbctx, fp, MAX_FINGERPRINT_LEN,
                                &publickey, false);
        } else {
-               count = config.dbbackend->fetch_key_text(search, &publickey);
+               count = dbctx->fetch_key_text(dbctx, search, &publickey);
        }
        if (publickey != NULL) {
-               key_index(publickey, verbose, fingerprint, skshash, false);
+               key_index(dbctx, publickey, verbose, fingerprint, skshash,
+                       false);
                free_publickey(publickey);
        } else if (count == 0) {
                puts("Key not found.");
@@ -172,6 +174,7 @@ int main(int argc, char *argv[])
        int                              optchar;
        struct dump_ctx                  dumpstate;
        struct skshash                   hash;
+       struct onak_dbctx               *dbctx;
 
        while ((optchar = getopt(argc, argv, "bc:fsuv")) != -1 ) {
                switch (optchar) {
@@ -204,17 +207,17 @@ int main(int argc, char *argv[])
        if ((argc - optind) < 1) {
                usage();
        } else if (!strcmp("dump", argv[optind])) {
-               config.dbbackend->initdb(true);
+               dbctx = config.dbinit(true);
                dumpstate.count = dumpstate.filenum = 0;
                dumpstate.maxcount = 100000;
                dumpstate.fd = -1;
                dumpstate.filebase = "keydump.%d.pgp";
-               config.dbbackend->iterate_keys(dump_func, &dumpstate);
+               dbctx->iterate_keys(dbctx, dump_func, &dumpstate);
                if (dumpstate.fd != -1) {
                        close(dumpstate.fd);
                        dumpstate.fd = -1;
                }
-               config.dbbackend->cleanupdb();
+               dbctx->cleanupdb(dbctx);
        } else if (!strcmp("add", argv[optind])) {
                if (binary) {
                        result = read_openpgp_stream(stdin_getchar, NULL,
@@ -235,9 +238,9 @@ int main(int argc, char *argv[])
                        logthing(LOGTHING_INFO, "%d keys cleaned.",
                                        result);
 
-                       config.dbbackend->initdb(false);
+                       dbctx = config.dbinit(false);
                        logthing(LOGTHING_NOTICE, "Got %d new keys.",
-                                       config.dbbackend->update_keys(&keys,
+                                       dbctx->update_keys(dbctx, &keys,
                                        false));
                        if (keys != NULL && update) {
                                flatten_publickey(keys,
@@ -255,7 +258,7 @@ int main(int argc, char *argv[])
                                free_packet_list(packets);
                                packets = NULL;
                        }
-                       config.dbbackend->cleanupdb();
+                       dbctx->cleanupdb(dbctx);
                } else {
                        rc = 1;
                        logthing(LOGTHING_NOTICE, "No keys read.");
@@ -332,20 +335,20 @@ int main(int argc, char *argv[])
                                ishex = true;
                        }
                }
-               config.dbbackend->initdb(false);
+               dbctx = config.dbinit(false);
                if (!strcmp("index", argv[optind])) {
-                       find_keys(search, keyid, fp, ishex, isfp,
+                       find_keys(dbctx, search, keyid, fp, ishex, isfp,
                                        fingerprint, skshash,
                                        false, false);
                } else if (!strcmp("vindex", argv[optind])) {
-                       find_keys(search, keyid, fp, ishex, isfp,
+                       find_keys(dbctx, search, keyid, fp, ishex, isfp,
                                        fingerprint, skshash,
                                        false, true);
                } else if (!strcmp("getphoto", argv[optind])) {
                        if (!ishex) {
                                puts("Can't get a key on uid text."
                                        " You must supply a keyid.");
-                       } else if (config.dbbackend->fetch_key_id(keyid, &keys,
+                       } else if (dbctx->fetch_key_id(dbctx, keyid, &keys,
                                        false)) {
                                unsigned char *photo = NULL;
                                size_t         length = 0;
@@ -363,8 +366,8 @@ int main(int argc, char *argv[])
                                puts("Key not found");
                        }
                } else if (!strcmp("delete", argv[optind])) {
-                       config.dbbackend->delete_key(
-                                       config.dbbackend->getfullkeyid(keyid),
+                       dbctx->delete_key(dbctx,
+                                       dbctx->getfullkeyid(dbctx, keyid),
                                        false);
                } else if (!strcmp("get", argv[optind])) {
                        if (!(ishex || isfp)) {
@@ -372,11 +375,11 @@ int main(int argc, char *argv[])
                                        " You must supply a keyid / "
                                        "fingerprint.");
                        } else if ((isfp &&
-                                       config.dbbackend->fetch_key_fp(fp,
+                                       dbctx->fetch_key_fp(dbctx, fp,
                                                MAX_FINGERPRINT_LEN,
                                                &keys, false)) ||
                                        (ishex &&
-                                       config.dbbackend->fetch_key_id(keyid,
+                                       dbctx->fetch_key_id(dbctx, keyid,
                                                &keys, false))) {
                                logthing(LOGTHING_INFO, "Got key.");
                                flatten_publickey(keys,
@@ -400,7 +403,7 @@ int main(int argc, char *argv[])
                } else if (!strcmp("hget", argv[optind])) {
                        if (!parse_skshash(search, &hash)) {
                                puts("Couldn't parse sks hash.");
-                       } else if (config.dbbackend->fetch_key_skshash(&hash,
+                       } else if (dbctx->fetch_key_skshash(dbctx, &hash,
                                        &keys)) {
                                logthing(LOGTHING_INFO, "Got key.");
                                flatten_publickey(keys,
@@ -422,7 +425,7 @@ int main(int argc, char *argv[])
                                puts("Key not found");
                        }
                }
-               config.dbbackend->cleanupdb();
+               dbctx->cleanupdb(dbctx);
        } else {
                usage();
        }
index 738f6264b6c1c17c8f1e959ceb27f4a805147181..a842230c4c9bbc808754410e3908d19a57c23169 100644 (file)
@@ -30,7 +30,8 @@
 #include "onak-conf.h"
 #include "stats.h"
 
-unsigned long countdegree(struct stats_key *have, bool sigs, int maxdegree)
+unsigned long countdegree(struct onak_dbctx *dbctx,
+               struct stats_key *have, bool sigs, int maxdegree)
 {
        unsigned long     count = 0, curdegree = 0;
        struct ll        *curll, *nextll, *sigll, *tmp;
@@ -43,7 +44,7 @@ unsigned long countdegree(struct stats_key *have, bool sigs, int maxdegree)
 
        while (curll != NULL && curdegree <= maxdegree) {
                if (sigs) {
-                       sigll = config.dbbackend->cached_getkeysigs(
+                       sigll = dbctx->cached_getkeysigs(dbctx,
                                ((struct stats_key *)
                                curll->object)->keyid);
                } else {
@@ -89,21 +90,21 @@ unsigned long countdegree(struct stats_key *have, bool sigs, int maxdegree)
        return count;
 }
 
-void sixdegrees(uint64_t keyid)
+void sixdegrees(struct onak_dbctx *dbctx, uint64_t keyid)
 {
        struct stats_key *keyinfo;
        int loop;
        long degree;
        char *uid;
 
-       config.dbbackend->cached_getkeysigs(keyid);
+       dbctx->cached_getkeysigs(dbctx, keyid);
 
        if ((keyinfo = findinhash(keyid)) == NULL) {
                printf("Couldn't find key 0x%016" PRIX64 ".\n", keyid);
                return;
        }
 
-       uid = config.dbbackend->keyid2uid(keyinfo->keyid);
+       uid = dbctx->keyid2uid(dbctx, keyinfo->keyid);
        printf("Six degrees for 0x%016" PRIX64 " (%s):\n", keyinfo->keyid,
                        uid);
        free(uid);
@@ -118,16 +119,16 @@ void sixdegrees(uint64_t keyid)
         * if it's signed by the key we're looking at.
         */
        initcolour(false);
-       degree = countdegree(keyinfo, true, 7);
+       degree = countdegree(dbctx, keyinfo, true, 7);
 
        puts("\t\tSigned by\t\tSigns");
        for (loop = 1; loop < 7; loop++) {
                initcolour(false);
-               degree = countdegree(keyinfo, true, loop);
+               degree = countdegree(dbctx, keyinfo, true, loop);
                printf("Degree %d:\t%8ld", loop, degree);
 
                initcolour(false);
-               degree = countdegree(keyinfo, false, loop);
+               degree = countdegree(dbctx, keyinfo, false, loop);
                printf("\t\t%8ld\n", degree);
        }
 }
@@ -137,6 +138,7 @@ int main(int argc, char *argv[])
        int optchar;
        char *configfile = NULL;
        uint64_t keyid = 0x2DA8B985;
+       struct onak_dbctx *dbctx;
 
        while ((optchar = getopt(argc, argv, "c:")) != -1 ) {
                switch (optchar) {
@@ -152,11 +154,15 @@ int main(int argc, char *argv[])
 
        readconfig(configfile);
        initlogthing("sixdegrees", config.logfile);
-       config.dbbackend->initdb(true);
-       inithash();
-       sixdegrees(config.dbbackend->getfullkeyid(keyid));
-       destroyhash();
-       config.dbbackend->cleanupdb();
+       dbctx = config.dbinit(true);
+       if (dbctx != NULL) {
+               inithash();
+               sixdegrees(dbctx, dbctx->getfullkeyid(dbctx, keyid));
+               destroyhash();
+               dbctx->cleanupdb(dbctx);
+       } else {
+               fprintf(stderr, "Couldn't initialize key database.\n");
+       }
        cleanuplogthing();
        cleanupconfig();
 
diff --git a/stats.c b/stats.c
index bcc4f9128d9a93825ae6e12e7c76378890e9dab2..a65650854b45f13365b08da95e0c6e4d5b1c8d69 100644 (file)
--- a/stats.c
+++ b/stats.c
@@ -66,7 +66,8 @@ void initcolour(bool parent)
  *     key we have. It returns as soon as a path is found or when we run out
  *     of keys; whichever comes sooner.
  */
-unsigned long findpath(struct stats_key *have, struct stats_key *want)
+unsigned long findpath(struct onak_dbctx *dbctx,
+               struct stats_key *have, struct stats_key *want)
 {
        struct ll *keys = NULL;
        struct ll *oldkeys = NULL;
@@ -80,7 +81,7 @@ unsigned long findpath(struct stats_key *have, struct stats_key *want)
        oldkeys = keys;
 
        while ((!cleanup()) && keys != NULL && have->colour == 0) {
-               sigs = config.dbbackend->cached_getkeysigs(((struct stats_key *)
+               sigs = dbctx->cached_getkeysigs(dbctx, ((struct stats_key *)
                                        keys->object)->keyid);
                while ((!cleanup()) && sigs != NULL && have->colour == 0) {
                        /*
@@ -132,7 +133,8 @@ unsigned long findpath(struct stats_key *have, struct stats_key *want)
  *     key we have. It returns as soon as a path is found or when we run out
  *     of keys; whichever comes sooner.
  */
-void dofindpath(uint64_t have, uint64_t want, bool html, int count)
+void dofindpath(struct onak_dbctx *dbctx,
+               uint64_t have, uint64_t want, bool html, int count)
 {
        struct stats_key *keyinfoa, *keyinfob, *curkey;
        uint64_t fullhave, fullwant;
@@ -140,14 +142,14 @@ void dofindpath(uint64_t have, uint64_t want, bool html, int count)
        int pathnum;
        char *uid;
 
-       fullhave = config.dbbackend->getfullkeyid(have);
-       fullwant = config.dbbackend->getfullkeyid(want);
+       fullhave = dbctx->getfullkeyid(dbctx, have);
+       fullwant = dbctx->getfullkeyid(dbctx, want);
 
        /*
         * Make sure the keys we have and want are in the cache.
         */
-       (void) config.dbbackend->cached_getkeysigs(fullhave);
-       (void) config.dbbackend->cached_getkeysigs(fullwant);
+       (void) dbctx->cached_getkeysigs(dbctx, fullhave);
+       (void) dbctx->cached_getkeysigs(dbctx, fullwant);
 
        if ((keyinfoa = findinhash(fullhave)) == NULL) {
                printf("Couldn't find key 0x%016" PRIX64 ".\n", have);
@@ -165,7 +167,7 @@ void dofindpath(uint64_t have, uint64_t want, bool html, int count)
                 * Fill the tree info up.
                 */
                initcolour(true);
-               rec = findpath(keyinfoa, keyinfob);
+               rec = findpath(dbctx, keyinfoa, keyinfob);
                keyinfob->parent = 0;
 
                printf("%s%d nodes examined. %ld elements in the hash%s\n",
@@ -193,7 +195,7 @@ void dofindpath(uint64_t have, uint64_t want, bool html, int count)
                                html ? "<BR>" : "");
                        curkey = keyinfoa;
                        while (curkey != NULL && curkey->keyid != 0) {
-                               uid = config.dbbackend->keyid2uid(
+                               uid = dbctx->keyid2uid(dbctx,
                                                curkey->keyid);
                                if (html && uid == NULL) {
                                        printf("<a href=\"lookup?op=get&search="
@@ -255,7 +257,7 @@ void dofindpath(uint64_t have, uint64_t want, bool html, int count)
 
 
 
-struct stats_key *furthestkey(struct stats_key *have)
+struct stats_key *furthestkey(struct onak_dbctx *dbctx, struct stats_key *have)
 {
        unsigned long count = 0;
        unsigned long curdegree = 0;
@@ -274,7 +276,7 @@ struct stats_key *furthestkey(struct stats_key *have)
        curll = lladd(NULL, have);
 
        while (curll != NULL) {
-               sigs = config.dbbackend->cached_getkeysigs(((struct stats_key *)
+               sigs = dbctx->cached_getkeysigs(dbctx, ((struct stats_key *)
                                curll->object)->keyid);
                while (sigs != NULL) {
                        if (((struct stats_key *) sigs->object)->colour == 0) {
diff --git a/stats.h b/stats.h
index 08e2abea0152c22384d73e5072ec6f844c68b96b..991bb1c6c20ae29f2956eabfe07046df4a0e7607 100644 (file)
--- a/stats.h
+++ b/stats.h
@@ -33,6 +33,7 @@ key_getsigns - get the keys a key signs. */
 #include <inttypes.h>
 #include <stdbool.h>
 
+#include "keydb.h"
 #include "ll.h"
 
 /**
@@ -75,7 +76,8 @@ void initcolour(bool parent);
  *     key we have. It returns as soon as a path is found or when we run out
  *     of keys; whichever comes sooner.
  */
-unsigned long findpath(struct stats_key *have, struct stats_key *want);
+unsigned long findpath(struct onak_dbctx *dbctx,
+               struct stats_key *have, struct stats_key *want);
 
 /**
  *     dofindpath - Given 2 keys displays a path between them.
@@ -88,8 +90,9 @@ unsigned long findpath(struct stats_key *have, struct stats_key *want);
  *     key we have. It returns as soon as a path is found or when we run out
  *     of keys; whichever comes sooner.
  */
-void dofindpath(uint64_t have, uint64_t want, bool html, int count);
+void dofindpath(struct onak_dbctx *dbctx,
+               uint64_t have, uint64_t want, bool html, int count);
 
-struct stats_key *furthestkey(struct stats_key *have);
+struct stats_key *furthestkey(struct onak_dbctx *dbctx, struct stats_key *have);
 
 #endif /* __STATS_H__ */
index 8990787a135b9df43eabb13964d44bc3d5555ed0..66dc94699d2dc12150e541b543b0e6e12c3d47c3 100644 (file)
--- a/wotsap.c
+++ b/wotsap.c
@@ -62,16 +62,17 @@ static struct ll *sortkeyll(struct ll *keys)
        return newll;
 }
 
-static void output_key(FILE *names, FILE *keys, uint64_t keyid)
+static void output_key(struct onak_dbctx *dbctx,
+               FILE *names, FILE *keys, uint64_t keyid)
 {
-       fprintf(names, "%s\n", config.dbbackend->keyid2uid(keyid));
+       fprintf(names, "%s\n", dbctx->keyid2uid(dbctx, keyid));
        fprintf(keys, "%c%c%c%c", (int) (keyid >> 24) & 0xFF,
                        (int) (keyid >> 16) & 0xFF,
                        (int) (keyid >>  8) & 0xFF,
                        (int) (keyid      ) & 0xFF);
 }
 
-static void wotsap(uint64_t keyid, char *dir)
+static void wotsap(struct onak_dbctx *dbctx, uint64_t keyid, char *dir)
 {
        struct ll *pending, *sigll, *sigsave;
        uint32_t curidx = 0;
@@ -125,29 +126,31 @@ static void wotsap(uint64_t keyid, char *dir)
        }
        free(tmppath);
 
-       config.dbbackend->cached_getkeysigs(keyid);
+       dbctx->cached_getkeysigs(dbctx, keyid);
        curkey = findinhash(keyid);
        curkey->colour = ++curidx;
        pending = lladd(NULL, curkey);
 
-       output_key(names, keys, curkey->keyid);
+       output_key(dbctx, names, keys, curkey->keyid);
 
        while (pending != NULL) {
                curkey = (struct stats_key *) pending->object;
-               sigll = config.dbbackend->cached_getkeysigs(curkey->keyid);
+               sigll = dbctx->cached_getkeysigs(dbctx, curkey->keyid);
                sigsave = sigll = sortkeyll(sigll);
                sigcount = 0;
                while (sigll != NULL) {
                        addkey = (struct stats_key *) sigll->object;
                        if (addkey->colour == 0 && !addkey->revoked) {
-                               uid = config.dbbackend->keyid2uid(addkey->keyid);
+                               uid = dbctx->keyid2uid(dbctx, addkey->keyid);
                                if (uid != NULL) {
                                        /* Force it to be loaded so we know if it's revoked */
-                                       config.dbbackend->cached_getkeysigs(addkey->keyid);
+                                       dbctx->cached_getkeysigs(dbctx,
+                                                       addkey->keyid);
                                        if (!addkey->revoked) {
                                                addkey->colour = ++curidx;
                                                pending = lladdend(pending, addkey);
-                                               output_key(names, keys, addkey->keyid);
+                                               output_key(dbctx, names, keys,
+                                                       addkey->keyid);
                                        }
                                }
                        }
@@ -184,6 +187,7 @@ int main(int argc, char *argv[])
        int optchar;
        char *configfile = NULL, *dir = NULL;
        uint64_t keyid = 0x2DA8B985;
+       struct onak_dbctx *dbctx;
 
        while ((optchar = getopt(argc, argv, "c:")) != -1 ) {
                switch (optchar) {
@@ -199,11 +203,16 @@ int main(int argc, char *argv[])
 
        readconfig(configfile);
        initlogthing("wotsap", config.logfile);
-       config.dbbackend->initdb(true);
-       inithash();
-       wotsap(config.dbbackend->getfullkeyid(keyid), dir ? dir : ".");
-       destroyhash();
-       config.dbbackend->cleanupdb();
+       dbctx = config.dbinit(true);
+       if (dbctx != NULL) {
+               inithash();
+               wotsap(dbctx, dbctx->getfullkeyid(dbctx, keyid),
+                       dir ? dir : ".");
+               destroyhash();
+               dbctx->cleanupdb(dbctx);
+       } else {
+               fprintf(stderr, "Couldn't initialize key database.\n");
+       }
        cleanuplogthing();
        cleanupconfig();
 }