From: Jonathan McDowell Date: Fri, 31 Oct 2025 15:22:49 +0000 (+0000) Subject: Add a dummy skeleton keydb backend X-Git-Url: https://the.earth.li/gitweb/?a=commitdiff_plain;h=aa301e6537ef6ba67efd76b493779e9798f8ec42;p=onak.git Add a dummy skeleton keydb backend We want to add Lightning Memory-Mapped DB + SQLite3 backends, so let's start by added a skeleton we can work from. --- diff --git a/keydb.h b/keydb.h index 9a9371b..4213940 100644 --- a/keydb.h +++ b/keydb.h @@ -45,6 +45,8 @@ struct onak_dbctx { * Start a transaction. Intended to be used if we're about to perform many * operations on the database to help speed it all up, or if we want * something to only succeed if all relevant operations are successful. + * + * @return Boolean indicating if we started the transaction successfully. */ bool (*starttrans)(struct onak_dbctx *); @@ -61,6 +63,7 @@ struct onak_dbctx { * @param fpsize Number of bytes in the fingerprint (16 for v3, 20 for v4) * @param publickey A pointer to a structure to return the key in. * @param intrans If we're already in a transaction. + * @return Number of keys returned. * * This function returns a public key from whatever storage mechanism we * are using. This only searches for the fingerprint of the primary key @@ -76,6 +79,7 @@ struct onak_dbctx { * @param keyid The keyid to fetch. * @param publickey A pointer to a structure to return the key in. * @param intrans If we're already in a transaction. + * @return Number of keys returned. * * This function returns a public key from whatever storage mechanism we * are using. It may return multiple keys in the case where there are @@ -92,6 +96,7 @@ struct onak_dbctx { * @param fpsize Number of bytes in the fingerprint (16 for v3, 20 for v4) * @param publickey A pointer to a structure to return the key in. * @param intrans If we're already in a transaction. + * @return Number of keys returned. * * This function returns a public key from whatever storage mechanism we * are using. Although the fingerprint should be unique this function may @@ -107,6 +112,7 @@ struct onak_dbctx { * @brief Tries to find the keys that contain the supplied text. * @param search The text to search for. * @param publickey A pointer to a structure to return the key in. + * @return Number of keys returned. * * This function searches for the supplied text and returns the keys that * contain it. It is likely it will return multiple keys. @@ -118,6 +124,7 @@ struct onak_dbctx { * @brief Tries to find the keys from an SKS hash * @param hash The hash to search for. * @param publickey A pointer to a structure to return the key in. + * @return Number of keys returned. * * This function looks for the key that is referenced by the supplied * SKS hash and returns it. @@ -190,7 +197,7 @@ struct onak_dbctx { * @param keyid The keyid to get the sigs for. * @param revoked Is the key revoked? * - * This function gets the list of signatures on a key. Used for key + * 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. */ @@ -202,7 +209,7 @@ struct onak_dbctx { * @param 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 + * getkeysigs function above except we use the hash module to cache them. */ struct ll * (*cached_getkeysigs)(struct onak_dbctx *, uint64_t keyid); diff --git a/keydb/CMakeLists.txt b/keydb/CMakeLists.txt index 64c4215..a8a1888 100644 --- a/keydb/CMakeLists.txt +++ b/keydb/CMakeLists.txt @@ -1,7 +1,7 @@ # Key database backends # These have no dependencies and can always be compiled -set(BACKENDS "file" "fs" "keyring" "stacked") +set(BACKENDS "dummy" "file" "fs" "keyring" "stacked") # DB4 backend (add check for existence) find_package(BDB) diff --git a/keydb/keydb_dummy.c b/keydb/keydb_dummy.c new file mode 100644 index 0000000..7f71491 --- /dev/null +++ b/keydb/keydb_dummy.c @@ -0,0 +1,389 @@ +/* + * keydb_dummy.c - skeleton backend that does nothing + * + * Copyright 2025 Jonathan McDowell + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#include "keydb.h" +#include "keystructs.h" +#include "ll.h" +#include "log.h" +#include "onak-conf.h" + +/** + * @brief Private per-instance context for dummy database backend + */ +struct onak_dummy_dbctx { +}; + +/** + * @brief Start a transaction. + * + * Start a transaction. Intended to be used if we're about to perform many + * operations on the database to help speed it all up, or if we want + * something to only succeed if all relevant operations are successful. + * + * @return Boolean indicating if we started the transaction successfully. + */ +static bool dummy_starttrans(struct onak_dbctx *dbctx) +{ + return true; +} + +/** + * @brief End a transaction. + * + * Ends a transaction. + */ +static void dummy_endtrans(struct onak_dbctx *dbctx) +{ + return; +} + +/** + * @brief Takes a key and stores it. + * @param publickey A pointer to the public key to store. + * @param intrans If we're already in a transaction. + * @param update If true the key exists and should be updated. + * + * This function stores a public key in whatever storage mechanism we are + * using. intrans indicates if we're already in a transaction so don't + * need to start one. update indicates if the key already exists and is + * just being updated. + */ +static int dummy_store_key(struct onak_dbctx *dbctx, + struct openpgp_publickey *publickey, bool intrans, + bool update) +{ + struct onak_dummy_dbctx *privctx = (struct onak_dummy_dbctx *) dbctx->priv; + + if (!intrans) { + dummy_starttrans(dbctx); + } + + if (!intrans) { + dummy_endtrans(dbctx); + } + + return 0; +} + +/** + * @brief Given a keyid delete the key from storage. + * @param fp The fingerprint of the key to delete. + * @param intrans If we're already in a transaction. + * + * This function deletes a public key from whatever storage mechanism we + * are using. Returns 0 if the key existed. + */ +static int dummy_delete_key(struct onak_dbctx *dbctx, + struct openpgp_fingerprint *fp, + bool intrans) +{ + struct onak_dummy_dbctx *privctx = (struct onak_dummy_dbctx *) dbctx->priv; + + if (!intrans) { + dummy_starttrans(dbctx); + } + + if (!intrans) { + dummy_endtrans(dbctx); + } + + return 0; +} + +/** + * @brief Takes a list of public keys and updates them in the DB. + * @param keys The keys to update in the DB. + * @param blacklist A keyarray of fingerprints that shouldn't be added. + * @updateonly: Only update existing keys, don't add new ones. + * @param sendsync If we should send a keysync mail. + * + * 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. + * + * If sendsync is true then we send out a keysync mail to our sync peers + * with the update. + */ +static int dummy_update_keys(struct onak_dbctx *dbctx, + struct openpgp_publickey **keys, + struct keyarray *blacklist, + bool updateonly, + bool sendsync) +{ + struct onak_dummy_dbctx *privctx = (struct onak_dummy_dbctx *) dbctx->priv; + + return 0; +} + +/** + * @brief call a function once for each key in the db. + * @param iterfunc The function to call. + * @param ctx A context pointer + * + * Calls iterfunc once for each key in the database. ctx is passed + * unaltered to iterfunc. This function is intended to aid database dumps + * and statistic calculations. + * + * Returns the number of keys we iterated over. + */ +static int dummy_iterate_keys(struct onak_dbctx *dbctx, + void (*iterfunc)(void *ctx, struct openpgp_publickey *key), + void *ctx) +{ + struct onak_dummy_dbctx *privctx = (struct onak_dummy_dbctx *) dbctx->priv; + + return 0; +} + +/** + * @brief Given a fingerprint fetch the key from storage. + * @param fp The fingerprint to fetch. + * @param fpsize Number of bytes in the fingerprint (16 for v3, 20 for v4) + * @param publickey A pointer to a structure to return the key in. + * @param intrans If we're already in a transaction. + * @return Number of keys returned. + * + * This function returns a public key from whatever storage mechanism we + * are using. This only searches for the fingerprint of the primary key + * and will thus only ever return at most a single key. + */ +static int dummy_fetch_key(struct onak_dbctx *dbctx, + struct openpgp_fingerprint *fingerprint, + struct openpgp_publickey **publickey, bool intrans) +{ + struct onak_dummy_dbctx *privctx = (struct onak_dummy_dbctx *) dbctx->priv; + + if (!intrans) { + dummy_starttrans(dbctx); + } + + if (!intrans) { + dummy_endtrans(dbctx); + } + + return 0; +} + +/** + * @brief Given a fingerprint fetch the key from storage. + * @param fp The fingerprint to fetch. + * @param fpsize Number of bytes in the fingerprint (16 for v3, 20 for v4) + * @param publickey A pointer to a structure to return the key in. + * @param intrans If we're already in a transaction. + * @return Number of keys returned. + * + * This function returns a public key from whatever storage mechanism we + * are using. Although the fingerprint should be unique this function may + * also search subkeys, which could be bound to multiple primary keys. As + * a result multiple keys may be returned. + */ +static int dummy_fetch_key_fp(struct onak_dbctx *dbctx, + struct openpgp_fingerprint *fingerprint, + struct openpgp_publickey **publickey, bool intrans) +{ + struct onak_dummy_dbctx *privctx = (struct onak_dummy_dbctx *) dbctx->priv; + + if (!intrans) { + dummy_starttrans(dbctx); + } + + if (!intrans) { + dummy_endtrans(dbctx); + } + + return 0; +} + +/** + * @brief Given a keyid fetch the key from storage. + * @param keyid The keyid to fetch. + * @param publickey A pointer to a structure to return the key in. + * @param intrans If we're already in a transaction. + * @return Number of keys returned. + * + * This function returns a public key from whatever storage mechanism we + * are using. It may return multiple keys in the case where there are + * colliding keyids. + */ +static int dummy_fetch_key_id(struct onak_dbctx *dbctx, uint64_t keyid, + struct openpgp_publickey **publickey, bool intrans) +{ + struct onak_dummy_dbctx *privctx = (struct onak_dummy_dbctx *) dbctx->priv; + + if (!intrans) { + dummy_starttrans(dbctx); + } + + if (!intrans) { + dummy_endtrans(dbctx); + } + + return 0; +} + +/** + * @brief Tries to find the keys that contain the supplied text. + * @param search The text to search for. + * @param publickey A pointer to a structure to return the key in. + * @return Number of keys returned. + * + * This function searches for the supplied text and returns the keys that + * contain it. It is likely it will return multiple keys. + */ +static int dummy_fetch_key_text(struct onak_dbctx *dbctx, + const char *search, + struct openpgp_publickey **publickey) +{ + struct onak_dummy_dbctx *privctx = (struct onak_dummy_dbctx *) dbctx->priv; + + return 0; +} + +/** + * @brief Tries to find the keys from an SKS hash + * @param hash The hash to search for. + * @param publickey A pointer to a structure to return the key in. + * @return Number of keys returned. + * + * This function looks for the key that is referenced by the supplied + * SKS hash and returns it. + */ +static int dummy_fetch_key_skshash(struct onak_dbctx *dbctx, + const struct skshash *hash, + struct openpgp_publickey **publickey) +{ + struct onak_dummy_dbctx *privctx = (struct onak_dummy_dbctx *) dbctx->priv; + + return 0; +} + +/** + * @brief Gets a linked list of the signatures on a key. + * @param keyid The keyid to get the sigs for. + * @param 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 *dummy_getkeysigs(struct onak_dbctx *dbctx, + uint64_t keyid, bool *revoked) +{ + struct onak_dummy_dbctx *privctx = (struct onak_dummy_dbctx *) dbctx->priv; + + return NULL; +} + +/** + * @brief Gets the signatures on a key. + * @param 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 them. + */ +static struct ll *dummy_cached_getkeysigs(struct onak_dbctx *dbctx, + uint64_t keyid) +{ + struct onak_dummy_dbctx *privctx = (struct onak_dummy_dbctx *) dbctx->priv; + + return NULL; +} + +/** + * @brief Takes a keyid and returns the primary UID for it. + * @param keyid The keyid to lookup. + * + * This function returns a UID for the given key. Returns NULL if the key + * isn't found. + */ +static char *dummy_keyid2uid(struct onak_dbctx *dbctx, + uint64_t keyid) +{ + struct onak_dummy_dbctx *privctx = (struct onak_dummy_dbctx *) dbctx->priv; + + return NULL; +} + +/** + * @brief De-initialize the key database. + * + * This function should be called upon program exit to allow the DB to + * cleanup after itself. + */ +static void dummy_cleanupdb(struct onak_dbctx *dbctx) +{ + struct onak_dummy_dbctx *privctx = (struct onak_dummy_dbctx *) dbctx->priv; + + free(privctx); + dbctx->priv = NULL; + free(dbctx); + + return; +} + +struct onak_dbctx *keydb_dummy_init(struct onak_db_config *dbcfg, + bool readonly) +{ + struct onak_dummy_dbctx *privctx; + struct onak_dbctx *dbctx; + + if (dbcfg == NULL) { + logthing(LOGTHING_CRITICAL, + "No backend database configuration supplied."); + return NULL; + } + + dbctx = calloc(1, sizeof(struct onak_dbctx)); + if (dbctx == NULL) { + return NULL; + } + + dbctx->priv = privctx = calloc(1, sizeof(*privctx)); + if (privctx == NULL) { + free(dbctx); + return NULL; + } + + dbctx->config = dbcfg; + + dbctx->cleanupdb = dummy_cleanupdb; + dbctx->starttrans = dummy_starttrans; + dbctx->endtrans = dummy_endtrans; + dbctx->fetch_key = dummy_fetch_key; + dbctx->fetch_key_fp = dummy_fetch_key_fp; + dbctx->fetch_key_id = dummy_fetch_key_id; + dbctx->fetch_key_text = dummy_fetch_key_text; + dbctx->fetch_key_skshash = dummy_fetch_key_skshash; + dbctx->store_key = dummy_store_key; + dbctx->update_keys = dummy_update_keys; + dbctx->delete_key = dummy_delete_key; + dbctx->getkeysigs = dummy_getkeysigs; + dbctx->cached_getkeysigs = dummy_cached_getkeysigs; + dbctx->keyid2uid = dummy_keyid2uid; + dbctx->iterate_keys = dummy_iterate_keys; + + return dbctx; +} diff --git a/runtests b/runtests index 3a74d24..5217309 100755 --- a/runtests +++ b/runtests @@ -38,7 +38,12 @@ for t in keydb/libkeydb_*.so; do -e "s;DB;${backend};" \ ${TESTSDIR}/test-in.ini > ${WORKDIR}/test.ini touch ${WORKDIR}/blacklist - for t in ${TESTSDIR}/$backend-*.t ${TESTSDIR}/all-*.t; do + if [ "${backend}" = "dummy" ]; then + TESTS="${TESTSDIR}/$backend-*.t" + else + TESTS="${TESTSDIR}/$backend-*.t ${TESTSDIR}/all-*.t" + fi + for t in ${TESTS}; do total=`expr $total + 1` mkdir ${WORKDIR}/db/ if ! $t ${WORKDIR}/test.ini $backend; then diff --git a/t/dummy-000-add.t b/t/dummy-000-add.t new file mode 100755 index 0000000..b2aa3a7 --- /dev/null +++ b/t/dummy-000-add.t @@ -0,0 +1,9 @@ +#!/bin/sh +# Check we can add a key "successfully" with the dummy backend. + +set -e + +cd ${WORKDIR} +${BUILDDIR}/onak -b -c $1 add < ${TESTSDIR}/../keys/noodles.key + +exit 0