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
struct buffer_ctx ctx;
int count = 0;
int i;
+ struct onak_dbctx *dbctx;
memset(&ctx, 0, sizeof(ctx));
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);
keys = NULL;
}
- config.dbbackend->cleanupdb();
+ dbctx->cleanupdb(dbctx);
} else {
puts("No OpenPGP packets found in input.");
end_html();
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;
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;
* Fill the tree info up.
*/
initcolour(true);
- findpath(keyinfoa, keyinfob);
+ findpath(dbctx, keyinfoa, keyinfob);
keyinfob->parent = 0;
if (keyinfoa->colour == 0) {
pathlen = 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,
/*
* 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);
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);
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"
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();
uint8_t **hashes;
struct buffer_ctx cgipostbuf;
struct openpgp_publickey **keys;
+ struct onak_dbctx *dbctx;
readconfig(NULL);
initlogthing("hashquery", config.logfile);
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++;
free(hashes);
hashes = NULL;
- config.dbbackend->cleanupdb();
+ dbctx->cleanupdb(dbctx);
puts("Content-Type: pgp/keys\n");
marshal_array(stdout_putchar, NULL,
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;
"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;
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;
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);
&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);
"Deleting 0x%" PRIX64
", result: %d",
keyid,
- config.dbbackend->delete_key(
+ dbctx->delete_key(dbctx,
keyid, false));
}
break;
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));
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));
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);
char *configfile = NULL;
bool foreground = false;
int optchar;
+ struct onak_dbctx *dbctx;
while ((optchar = getopt(argc, argv, "c:fh")) != -1 ) {
switch (optchar) {
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) {
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,
}
}
}
- config.dbbackend->cleanupdb();
+ dbctx->cleanupdb(dbctx);
sock_close(fd);
unlink(sockname);
}
* 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) {
* 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) {
* 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;
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;
}
* 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);
* 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;
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));
/*
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);
} 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;
}
#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;
keyid = (keyid << 8) + fp[i];
}
- return config.dbbackend->fetch_key_id(keyid, publickey, intrans);
+ return dbctx->fetch_key_id(dbctx, keyid, publickey, intrans);
}
#endif
#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.
* 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.
*
* 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);
* 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);
*
* 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);
/**
* 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.
* 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);
/**
* 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);
/**
* 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.
* 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.
* 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.
* 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.
* 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.
*
* 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__ */
#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]);
}
/**
* 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,
*
* 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,
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
*
* 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;
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",
}
/**
- * 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 */
key.size = sizeof(keyid);
key.data = &keyid;
- ret = subkeydb->get(subkeydb,
- txn,
+ ret = privctx->subkeydb->get(privctx->subkeydb,
+ privctx->txn,
&key,
&data,
0); /* flags*/
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*/
}
if (!intrans) {
- db4_endtrans();
+ db4_endtrans(dbctx);
}
return (numkeys);
* 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;
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 */
ret = cursor->c_close(cursor);
cursor = NULL;
firstpass = 0;
- db4_endtrans();
+ db4_endtrans(dbctx);
}
llfree(wordlist, NULL);
wordlist = NULL;
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);
}
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 */
ret = cursor->c_close(cursor);
cursor = NULL;
- return db4_fetch_key_id(keyid, publickey, false);
+ return db4_fetch_key_id(dbctx, keyid, publickey, false);
}
/**
* 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;
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.
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 */
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);
}
if (!deadlock) {
- ret = id32db->cursor(id32db,
- txn,
+ ret = privctx->id32db->cursor(privctx->id32db,
+ privctx->txn,
&cursor,
0); /* flags */
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 "
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);
* 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;
}
if (!intrans) {
- db4_starttrans();
+ db4_starttrans(dbctx);
}
/*
* it definitely needs updated.
*/
if (update) {
- deadlock = (db4_delete_key(keyid, true) == -1);
+ deadlock = (db4_delete_key(dbctx, keyid, true) == -1);
}
/*
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);
/*
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*/
free(storebuf.buffer);
storebuf.buffer = NULL;
storebuf.size = 0;
- storebuf.offset = 0;
-
+ storebuf.offset = 0;
+
free_packet_list(packets);
packets = NULL;
}
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);
data.data = &keyid;
data.size = sizeof(keyid);
- ret = id32db->put(id32db,
- txn,
+ ret = privctx->id32db->put(privctx->id32db,
+ privctx->txn,
&key,
&data,
0);
data.data = &keyid;
data.size = sizeof(keyid);
- ret = subkeydb->put(subkeydb,
- txn,
+ ret = privctx->subkeydb->put(privctx->subkeydb,
+ privctx->txn,
&key,
&data,
0);
data.data = &keyid;
data.size = sizeof(keyid);
- ret = id32db->put(id32db,
- txn,
+ ret = privctx->id32db->put(privctx->id32db,
+ privctx->txn,
&key,
&data,
0);
data.data = &keyid;
data.size = sizeof(keyid);
- ret = skshashdb->put(skshashdb,
- txn,
+ ret = privctx->skshashdb->put(privctx->skshashdb,
+ privctx->txn,
&key,
&data,
0);
}
if (!intrans) {
- db4_endtrans();
+ db4_endtrans(dbctx);
}
return deadlock ? -1 : 0 ;
*
* 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;
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 */
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,
ret = cursor->c_close(cursor);
cursor = NULL;
}
-
+
return numkeys;
}
#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;
+}
#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,
-};
#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;
}
*
* This is just a no-op for flat file access.
*/
-static void file_endtrans(void)
+static void file_endtrans(struct onak_dbctx *dbctx)
{
return;
}
* 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);
* 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;
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);
* 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);
*
* 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;
*
* 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;
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);
#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;
+}
#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;
+};
/*****************************************************************************/
/*****************************************************************************/
-/**
- * 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);
/**
* 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;
* @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)
{
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) {
}
if (!intrans)
- fs_endtrans();
+ fs_endtrans(dbctx);
return ret;
}
* @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];
}
if (!intrans)
- fs_starttrans();
+ fs_starttrans(dbctx);
prove_path_to(keyid, "key");
keypath(buffer, sizeof(buffer), keyid);
}
if (!intrans)
- fs_endtrans();
+ fs_endtrans(dbctx);
return ret;
}
* @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;
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,
unlink(buffer);
if (!intrans)
- fs_endtrans();
+ fs_endtrans(dbctx);
return 1;
}
* @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;
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;
* @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];
*
* 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;
#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;
+}
#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;
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",
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);
}
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.
*/
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;
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;
/**
* 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;
}
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;
ofs += sprintf(&keyurl[ofs], "%02X", fp[i]);
}
- return (hkp_fetch_key_url(keyurl, publickey, intrans));
+ return (hkp_fetch_key_url(dbctx, keyurl, publickey, intrans));
}
/**
*
* 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));
}
/**
* @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];
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)",
*
* 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;
}
*
* 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;
}
*
* This is just a no-op for HKP access.
*/
-static bool hkp_starttrans(void)
+static bool hkp_starttrans(struct onak_dbctx *dbctx)
{
return true;
}
*
* This is just a no-op for HKP access.
*/
-static void hkp_endtrans(void)
+static void hkp_endtrans(struct onak_dbctx *dbctx)
{
return;
}
#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;
+}
#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.
*
* 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;
}
*
* Ends a transaction.
*/
-static void keyd_endtrans(void)
+static void keyd_endtrans(struct onak_dbctx *dbctx)
{
return;
}
*
* 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;
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;
* 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));
* 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;
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));
keybuf.buffer = NULL;
keybuf.size = keybuf.offset = 0;
}
-
+
return 0;
}
* 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;
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;
keybuf.size = 0;
}
}
-
+
return (count > 0) ? 1 : 0;
}
* 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));
*
* 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;
read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
}
}
-
+
return numkeys;
}
#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;
+}
#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));
}
/**
* 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");
*
* 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");
* 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");
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;
}
* 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);
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;
}
* 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];
* 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");
* it definitely needs updated.
*/
if (update) {
- pg_delete_key(keyid, true);
+ pg_delete_key(dbctx, keyid, true);
}
next = publickey->next;
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;
* 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;
* 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];
*
* 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;");
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);
#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;
+}
#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;
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;
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 */
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];
}
}
if (verbose) {
- list_sigs(uids->sigs, html);
+ list_sigs(dbctx, uids->sigs, html);
}
uids = uids->next;
}
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;
}
if (verbose) {
- list_sigs(subkeys->sigs, html);
+ list_sigs(dbctx, subkeys->sigs, html);
}
subkeys = subkeys->next;
}
* 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;
display_fingerprint(keys);
}
if (verbose) {
- list_sigs(curuid->sigs, html);
+ list_sigs(dbctx, curuid->sigs, html);
}
curuid = curuid->next;
} else {
}
}
- 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;
#include <stdbool.h>
+#include "keydb.h"
#include "keystructs.h"
/**
* 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);
/**
#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)
{
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) {
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) {
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);
}
}
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) {
default:
puts("Unknown operation!");
}
- config.dbbackend->cleanupdb();
+ dbctx->cleanupdb(dbctx);
cleanuplogthing();
cleanupconfig();
}
#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;
* 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
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;
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) {
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();
#include "log.h"
#include "onak-conf.h"
-extern struct dbfuncs DBFUNCS;
+extern struct onak_dbctx *DBINIT(bool readonly);
/*
* config - Runtime configuration for onak.
NULL, /* db_backend */
NULL, /* backends_dir */
- &DBFUNCS, /* Default dbfuncs struct */
+ DBINIT, /* Default db initialisation function */
true, /* Check packet sig hashes */
};
/** 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;
#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)
{
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.");
int optchar;
struct dump_ctx dumpstate;
struct skshash hash;
+ struct onak_dbctx *dbctx;
while ((optchar = getopt(argc, argv, "bc:fsuv")) != -1 ) {
switch (optchar) {
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,
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,
free_packet_list(packets);
packets = NULL;
}
- config.dbbackend->cleanupdb();
+ dbctx->cleanupdb(dbctx);
} else {
rc = 1;
logthing(LOGTHING_NOTICE, "No keys read.");
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;
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)) {
" 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,
} 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,
puts("Key not found");
}
}
- config.dbbackend->cleanupdb();
+ dbctx->cleanupdb(dbctx);
} else {
usage();
}
#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;
while (curll != NULL && curdegree <= maxdegree) {
if (sigs) {
- sigll = config.dbbackend->cached_getkeysigs(
+ sigll = dbctx->cached_getkeysigs(dbctx,
((struct stats_key *)
curll->object)->keyid);
} else {
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);
* 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);
}
}
int optchar;
char *configfile = NULL;
uint64_t keyid = 0x2DA8B985;
+ struct onak_dbctx *dbctx;
while ((optchar = getopt(argc, argv, "c:")) != -1 ) {
switch (optchar) {
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();
* 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;
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) {
/*
* 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;
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);
* 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",
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="
-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;
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) {
#include <inttypes.h>
#include <stdbool.h>
+#include "keydb.h"
#include "ll.h"
/**
* 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.
* 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__ */
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;
}
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);
}
}
}
int optchar;
char *configfile = NULL, *dir = NULL;
uint64_t keyid = 0x2DA8B985;
+ struct onak_dbctx *dbctx;
while ((optchar = getopt(argc, argv, "c:")) != -1 ) {
switch (optchar) {
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();
}