]> the.earth.li Git - onak.git/commitdiff
Add a dummy skeleton keydb backend
authorJonathan McDowell <noodles@earth.li>
Fri, 31 Oct 2025 15:22:49 +0000 (15:22 +0000)
committerJonathan McDowell <noodles@earth.li>
Fri, 31 Oct 2025 15:22:49 +0000 (15:22 +0000)
We want to add Lightning Memory-Mapped DB + SQLite3 backends, so let's
start by added a skeleton we can work from.

keydb.h
keydb/CMakeLists.txt
keydb/keydb_dummy.c [new file with mode: 0644]
runtests
t/dummy-000-add.t [new file with mode: 0755]

diff --git a/keydb.h b/keydb.h
index 9a9371b4ac9614759c3501c9d756d019488cfa51..42139408db6ab85255eae5af432d72fe94a03ed7 100644 (file)
--- 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);
index 64c4215e3fcba255409f77bb4dfa9ea71216fb39..a8a18887efc1f22f6ebaffe1830a4a2b2938bea4 100644 (file)
@@ -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 (file)
index 0000000..7f71491
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * keydb_dummy.c - skeleton backend that does nothing
+ *
+ * Copyright 2025 Jonathan McDowell <noodles@earth.li>
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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;
+}
index 3a74d2456e28d1d40b69a93a595a47d6c0c823a9..52173099b47ddcaed957bcc8d640393f72c2614f 100755 (executable)
--- 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 (executable)
index 0000000..b2aa3a7
--- /dev/null
@@ -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