exec_prefix ?= @exec_prefix@
PROGS = add lookup gpgwww onak splitkeys onak-mail.pl stripkey
-CORE_OBJS = armor.o charfuncs.o decodekey.o getcgi.o hash.o keydb_$(DBTYPE).o \
+CORE_OBJS = armor.o charfuncs.o decodekey.o getcgi.o hash.o \
keyid.o keyindex.o ll.o mem.o onak-conf.o parsekey.o sha1.o md5.o \
log.o photoid.o wordlist.o cleanup.o
-OBJS = merge.o stats.o sendsync.o cleankey.o $(CORE_OBJS)
SRCS = armor.c parsekey.c merge.c keyid.c md5.c sha1.c main.c getcgi.c mem.c \
keyindex.c stats.c lookup.c add.c keydb_$(DBTYPE).c ll.c hash.c \
gpgwww.c onak-conf.c charfuncs.c sendsync.c log.c photoid.c \
wordlist.c cleankey.c cleanup.c
+ifeq (x@KEYD@, xyes)
+PROGS += keyd
+KEYDB_OBJ = keydb_keyd.o
+SRCS += keyd.c keydb_keyd.c
+else
+KEYDB_OBJ = keydb_$(DBTYPE).o
+endif
+
+OBJS = merge.o stats.o sendsync.o cleankey.o $(CORE_OBJS) $(KEYDB_OBJ)
+
all: .depend $(PROGS) testparse maxpath sixdegrees splitkeys onak.conf
-splitkeys: splitkeys.o $(CORE_OBJS)
- $(CC) $(LDFLAGS) -o splitkeys splitkeys.o $(CORE_OBJS) $(LIBS)
+keyd: keyd.o $(CORE_OBJS) keydb_$(DBTYPE).o
+ $(CC) $(LDFLAGS) -o keyd keyd.o $(CORE_OBJS) keydb_$(DBTYPE).o $(LIBS)
+
+splitkeys: splitkeys.o $(CORE_OBJS) $(KEYDB_OBJ)
+ $(CC) $(LDFLAGS) -o splitkeys splitkeys.o $(CORE_OBJS) $(KEYDB_OBJ) \
+ $(LIBS)
testparse: main.o $(OBJS)
$(CC) $(LDFLAGS) -o testparse main.o $(OBJS) $(LIBS)
gpgwww: gpgwww.o $(OBJS)
$(CC) $(LDFLAGS) -o gpgwww gpgwww.o $(OBJS) $(LIBS)
-lookup: lookup.o cleankey.o merge.o $(CORE_OBJS)
+lookup: lookup.o cleankey.o merge.o $(CORE_OBJS) $(KEYDB_OBJ)
$(CC) $(LDFLAGS) -o lookup lookup.o cleankey.o merge.o $(CORE_OBJS) \
- $(LIBS)
+ $(KEYDB_OBJ) $(LIBS)
-add: add.o cleankey.o merge.o sendsync.o $(CORE_OBJS)
+add: add.o cleankey.o merge.o sendsync.o $(CORE_OBJS) $(KEYDB_OBJ)
$(CC) $(LDFLAGS) -o add add.o cleankey.o merge.o sendsync.o \
- $(CORE_OBJS) $(LIBS)
+ $(CORE_OBJS) $(KEYDB_OBJ) $(LIBS)
-onak: onak.o merge.o cleankey.o $(CORE_OBJS)
+onak: onak.o merge.o cleankey.o $(CORE_OBJS) $(KEYDB_OBJ)
$(CC) $(LDFLAGS) -o onak onak.o merge.o cleankey.o \
- $(CORE_OBJS) $(LIBS)
+ $(CORE_OBJS) $(KEYDB_OBJ) $(LIBS)
onak-conf.o: onak-conf.c onak-conf.h
$(CC) $(CFLAGS) -DCONFIGFILE=\"@sysconfdir@/onak.conf\" -c onak-conf.c
--- /dev/null
+/*
+ * keyd.c - key retrieval daemon
+ *
+ * Jonathan McDowell <noodles@earth.li>
+ *
+ * Copyright 2004 Project Purple
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "charfuncs.h"
+#include "cleanup.h"
+#include "keyd.h"
+#include "keydb.h"
+#include "keystructs.h"
+#include "log.h"
+#include "mem.h"
+#include "onak-conf.h"
+#include "parsekey.h"
+
+int sock_init(const char *sockname)
+{
+ struct sockaddr_un sock;
+ int fd = -1;
+ int ret = -1;
+
+ fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (fd != -1) {
+ ret = fcntl(fd, F_SETFD, 1);
+ }
+
+ if (ret != -1) {
+ sock.sun_family = AF_UNIX;
+ strncpy(sock.sun_path, sockname, sizeof(sock.sun_path) - 1);
+ unlink(sockname);
+ ret = bind(fd, (struct sockaddr *) &sock, sizeof(sock));
+ }
+
+ if (ret != -1) {
+ ret = listen(fd, 5);
+ }
+
+ return fd;
+}
+
+int sock_do(int fd)
+{
+ int cmd = KEYD_CMD_UNKNOWN;
+ ssize_t bytes = 0;
+ ssize_t count = 0;
+ int ret = 0;
+ uint64_t keyid = 0;
+ char *search = NULL;
+ struct openpgp_publickey *key = NULL;
+ struct openpgp_packet_list *packets = NULL;
+ struct openpgp_packet_list *list_end = NULL;
+ struct buffer_ctx storebuf;
+
+ /*
+ * Get the command from the client.
+ */
+ bytes = read(fd, &cmd, sizeof(cmd));
+
+ logthing(LOGTHING_DEBUG, "Read %d bytes, command: %d", bytes, cmd);
+
+ if (bytes != sizeof(cmd)) {
+ ret = 1;
+ }
+
+ if (ret == 0) {
+ switch (cmd) {
+ case KEYD_CMD_VERSION:
+ cmd = KEYD_REPLY_OK;
+ write(fd, &cmd, sizeof(cmd));
+ write(fd, &keyd_version, sizeof(keyd_version));
+ break;
+ case KEYD_CMD_GET:
+ cmd = KEYD_REPLY_OK;
+ write(fd, &cmd, sizeof(cmd));
+ bytes = read(fd, &keyid, sizeof(keyid));
+ if (bytes != sizeof(keyid)) {
+ ret = 1;
+ }
+ storebuf.offset = 0;
+ if (ret == 0) {
+ logthing(LOGTHING_INFO,
+ "Fetching 0x%llX, result: %d",
+ keyid,
+ fetch_key(keyid, &key, false));
+ if (key != NULL) {
+ storebuf.size = 8192;
+ storebuf.buffer = malloc(8192);
+
+ flatten_publickey(key,
+ &packets,
+ &list_end);
+ write_openpgp_stream(buffer_putchar,
+ &storebuf,
+ packets);
+ logthing(LOGTHING_TRACE,
+ "Sending %d bytes.",
+ storebuf.offset);
+ write(fd, &storebuf.offset,
+ sizeof(storebuf.offset));
+ write(fd, storebuf.buffer,
+ storebuf.offset);
+
+ free(storebuf.buffer);
+ storebuf.buffer = NULL;
+ storebuf.size = storebuf.offset = 0;
+ free_packet_list(packets);
+ packets = list_end = NULL;
+ free_publickey(key);
+ key = NULL;
+ } else {
+ write(fd, &storebuf.offset,
+ sizeof(storebuf.offset));
+ }
+ }
+ break;
+ case KEYD_CMD_GETTEXT:
+ cmd = KEYD_REPLY_OK;
+ write(fd, &cmd, sizeof(cmd));
+ bytes = read(fd, &count, sizeof(count));
+ if (bytes != sizeof(count)) {
+ ret = 1;
+ }
+ storebuf.offset = 0;
+ if (ret == 0) {
+ search = malloc(count+1);
+ read(fd, search, count);
+ search[count] = 0;
+ logthing(LOGTHING_INFO,
+ "Fetching %s, result: %d",
+ search,
+ fetch_key_text(search, &key));
+ if (key != NULL) {
+ storebuf.size = 8192;
+ storebuf.buffer = malloc(8192);
+
+ flatten_publickey(key,
+ &packets,
+ &list_end);
+ write_openpgp_stream(buffer_putchar,
+ &storebuf,
+ packets);
+ logthing(LOGTHING_TRACE,
+ "Sending %d bytes.",
+ storebuf.offset);
+ write(fd, &storebuf.offset,
+ sizeof(storebuf.offset));
+ write(fd, storebuf.buffer,
+ storebuf.offset);
+
+ free(storebuf.buffer);
+ storebuf.buffer = NULL;
+ storebuf.size = storebuf.offset = 0;
+ free_packet_list(packets);
+ packets = list_end = NULL;
+ free_publickey(key);
+ key = NULL;
+ } else {
+ write(fd, &storebuf.offset,
+ sizeof(storebuf.offset));
+ }
+ }
+ break;
+ case KEYD_CMD_STORE:
+ cmd = KEYD_REPLY_OK;
+ write(fd, &cmd, sizeof(cmd));
+ storebuf.offset = 0;
+ bytes = read(fd, &storebuf.size,
+ sizeof(storebuf.size));
+ logthing(LOGTHING_TRACE, "Reading %d bytes.",
+ storebuf.size);
+ if (bytes != sizeof(storebuf.size)) {
+ ret = 1;
+ }
+ if (ret == 0 && storebuf.size > 0) {
+ storebuf.buffer = malloc(storebuf.size);
+ bytes = count = 0;
+ while (bytes >= 0 && count < storebuf.size) {
+ bytes = read(fd,
+ &storebuf.buffer[count],
+ storebuf.size - count);
+ logthing(LOGTHING_TRACE,
+ "Read %d bytes.",
+ bytes);
+ count += bytes;
+ }
+ read_openpgp_stream(buffer_fetchchar,
+ &storebuf,
+ &packets,
+ 0);
+ parse_keys(packets, &key);
+ store_key(key, false, false);
+ free_packet_list(packets);
+ packets = NULL;
+ free_publickey(key);
+ key = NULL;
+ free(storebuf.buffer);
+ storebuf.buffer = NULL;
+ storebuf.size = storebuf.offset = 0;
+ }
+ break;
+ case KEYD_CMD_DELETE:
+ cmd = KEYD_REPLY_OK;
+ write(fd, &cmd, sizeof(cmd));
+ bytes = read(fd, &keyid, sizeof(keyid));
+ if (bytes != sizeof(keyid)) {
+ ret = 1;
+ }
+ if (ret == 0) {
+ logthing(LOGTHING_INFO,
+ "Deleting 0x%llX, result: %d",
+ keyid,
+ delete_key(keyid, false));
+ }
+ break;
+ case KEYD_CMD_GETFULLKEYID:
+ cmd = KEYD_REPLY_OK;
+ write(fd, &cmd, sizeof(cmd));
+ bytes = read(fd, &keyid, sizeof(keyid));
+ if (bytes != sizeof(keyid)) {
+ ret = 1;
+ }
+ if (ret == 0) {
+ keyid = getfullkeyid(keyid);
+ write(fd, &keyid, sizeof(keyid));
+ }
+ break;
+ case KEYD_CMD_CLOSE:
+ ret = 1;
+ break;
+ case KEYD_CMD_QUIT:
+ trytocleanup();
+ break;
+ default:
+ logthing(LOGTHING_ERROR, "Got unknown command: %d",
+ cmd);
+ cmd = KEYD_REPLY_UNKNOWN_CMD;
+ write(fd, &cmd, sizeof(cmd));
+ }
+ }
+
+ return(ret);
+}
+
+int sock_close(int fd)
+{
+ return shutdown(fd, SHUT_RDWR);
+}
+
+int sock_accept(int fd)
+{
+ struct sockaddr_un sock;
+ socklen_t socklen;
+ int srv = -1;
+ int ret = -1;
+
+ socklen = sizeof(sock);
+ srv = accept(fd, (struct sockaddr *) &sock, &socklen);
+ if (srv != -1) {
+ ret = fcntl(srv, F_SETFD, 1);
+ }
+
+ if (ret != -1) {
+ while (!sock_do(srv)) ;
+ sock_close(srv);
+ }
+
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ int fd = -1;
+ fd_set rfds;
+ char sockname[1024];
+
+ readconfig(NULL);
+ initlogthing("keyd", config.logfile);
+
+ catchsignals();
+
+ snprintf(sockname, 1023, "%s/%s", config.db_dir, KEYD_SOCKET);
+ fd = sock_init(sockname);
+
+ if (fd != -1) {
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ initdb(false);
+
+ logthing(LOGTHING_NOTICE, "Accepting connections.");
+ while (!cleanup() && select(fd + 1, &rfds, NULL, NULL, NULL) != -1) {
+ logthing(LOGTHING_INFO, "Accepted connection.");
+ sock_accept(fd);
+ FD_SET(fd, &rfds);
+ }
+ cleanupdb();
+ sock_close(fd);
+ unlink(sockname);
+ }
+
+ cleanuplogthing();
+ cleanupconfig();
+
+ return(EXIT_SUCCESS);
+}
--- /dev/null
+/*
+ * keydb_keyd.c - Routines to talk to keyd backend.
+ *
+ * Jonathan McDowell <noodles@earth.li>
+ *
+ * Copyright 2004 Project Purple
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "charfuncs.h"
+#include "keyd.h"
+#include "keydb.h"
+#include "keyid.h"
+#include "keystructs.h"
+#include "log.h"
+#include "mem.h"
+#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.
+ */
+void initdb(bool readonly)
+{
+ struct sockaddr_un sock;
+ int cmd = KEYD_CMD_UNKNOWN;
+ int 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)) {
+ if (reply == KEYD_REPLY_OK) {
+ 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.
+ */
+void cleanupdb(void)
+{
+ if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
+ logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
+ errno);
+ }
+ keyd_fd = -1;
+
+ return;
+}
+
+
+/**
+ * starttrans - 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.
+ */
+bool starttrans(void)
+{
+ return true;
+}
+
+/**
+ * endtrans - End a transaction.
+ *
+ * Ends a transaction.
+ */
+void endtrans(void)
+{
+ return;
+}
+
+/**
+ * fetch_key - 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.
+ *
+ * This function returns a public key from whatever storage mechanism we
+ * are using.
+ *
+ * TODO: What about keyid collisions? Should we use fingerprint instead?
+ */
+int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
+ bool intrans)
+{
+ struct buffer_ctx keybuf;
+ struct openpgp_packet_list *packets = NULL;
+ int cmd = KEYD_CMD_GET;
+ ssize_t bytes = 0;
+ ssize_t count = 0;
+
+ write(keyd_fd, &cmd, sizeof(cmd));
+ read(keyd_fd, &cmd, sizeof(cmd));
+ if (cmd == KEYD_REPLY_OK) {
+ write(keyd_fd, &keyid, sizeof(keyid));
+ keybuf.offset = 0;
+ read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
+ if (keybuf.size > 0) {
+ keybuf.buffer = malloc(keybuf.size);
+ bytes = count = 0;
+ logthing(LOGTHING_TRACE,
+ "Getting %d bytes of key data.",
+ keybuf.size);
+ while (bytes >= 0 && count < keybuf.size) {
+ bytes = read(keyd_fd, &keybuf.buffer[count],
+ keybuf.size - count);
+ logthing(LOGTHING_TRACE,
+ "Read %d bytes.", bytes);
+ count += bytes;
+ }
+ read_openpgp_stream(buffer_fetchchar, &keybuf,
+ &packets, 0);
+ parse_keys(packets, publickey);
+ free_packet_list(packets);
+ packets = NULL;
+ free(keybuf.buffer);
+ keybuf.buffer = NULL;
+ keybuf.size = 0;
+ }
+ }
+
+ return (count > 0) ? 1 : 0;
+}
+
+/**
+ * store_key - Takes a key and stores it.
+ * @publickey: A pointer to the public key to store.
+ * @intrans: If we're already in a transaction.
+ * @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.
+ *
+ * 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, bool update)
+{
+ struct buffer_ctx keybuf;
+ struct openpgp_packet_list *packets = NULL;
+ struct openpgp_packet_list *list_end = NULL;
+ struct openpgp_publickey *next = NULL;
+ int cmd = KEYD_CMD_STORE;
+ uint64_t keyid;
+
+ keyid = get_keyid(publickey);
+
+ if (update) {
+ delete_key(keyid, false);
+ }
+
+ write(keyd_fd, &cmd, sizeof(cmd));
+ read(keyd_fd, &cmd, sizeof(cmd));
+ if (cmd == KEYD_REPLY_OK) {
+ keybuf.offset = 0;
+ keybuf.size = 8192;
+ keybuf.buffer = malloc(keybuf.size);
+
+ next = publickey->next;
+ publickey->next = NULL;
+ flatten_publickey(publickey,
+ &packets,
+ &list_end);
+ publickey->next = next;
+
+ write_openpgp_stream(buffer_putchar, &keybuf, packets);
+ logthing(LOGTHING_TRACE, "Sending %d bytes.", keybuf.offset);
+ write(keyd_fd, &keybuf.offset, sizeof(keybuf.offset));
+ write(keyd_fd, keybuf.buffer, keybuf.offset);
+
+ free_packet_list(packets);
+ packets = list_end = NULL;
+ free(keybuf.buffer);
+ keybuf.buffer = NULL;
+ keybuf.size = keybuf.offset = 0;
+ }
+
+ return 0;
+}
+
+/**
+ * delete_key - Given a keyid delete the key from storage.
+ * @keyid: The keyid to delete.
+ * @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.
+ */
+int delete_key(uint64_t keyid, bool intrans)
+{
+ int cmd = KEYD_CMD_DELETE;
+
+ write(keyd_fd, &cmd, sizeof(cmd));
+ read(keyd_fd, &cmd, sizeof(cmd));
+ if (cmd == KEYD_REPLY_OK) {
+ write(keyd_fd, &keyid, sizeof(keyid));
+ }
+
+ return 0;
+}
+
+/**
+ * fetch_key_text - Trys to find the keys that contain the supplied text.
+ * @search: The text to search for.
+ * @publickey: A pointer to a structure to return the key in.
+ *
+ * This function searches for the supplied text and returns the keys that
+ * contain it.
+ */
+int fetch_key_text(const char *search, struct openpgp_publickey **publickey)
+{
+ struct buffer_ctx keybuf;
+ struct openpgp_packet_list *packets = NULL;
+ int cmd = KEYD_CMD_GETTEXT;
+ ssize_t bytes = 0;
+ ssize_t count = 0;
+
+ write(keyd_fd, &cmd, sizeof(cmd));
+ read(keyd_fd, &cmd, sizeof(cmd));
+ if (cmd == KEYD_REPLY_OK) {
+ bytes = strlen(search);
+ write(keyd_fd, &bytes, sizeof(bytes));
+ write(keyd_fd, search, bytes);
+ keybuf.offset = 0;
+ read(keyd_fd, &keybuf.size, sizeof(keybuf.size));
+ if (keybuf.size > 0) {
+ keybuf.buffer = malloc(keybuf.size);
+ bytes = count = 0;
+ logthing(LOGTHING_TRACE,
+ "Getting %d bytes of key data.",
+ keybuf.size);
+ while (bytes >= 0 && count < keybuf.size) {
+ bytes = read(keyd_fd, &keybuf.buffer[count],
+ keybuf.size - count);
+ logthing(LOGTHING_TRACE,
+ "Read %d bytes.", bytes);
+ count += bytes;
+ }
+ read_openpgp_stream(buffer_fetchchar, &keybuf,
+ &packets, 0);
+ parse_keys(packets, publickey);
+ free_packet_list(packets);
+ packets = NULL;
+ free(keybuf.buffer);
+ keybuf.buffer = NULL;
+ keybuf.size = 0;
+ }
+ }
+
+ return (count > 0) ? 1 : 0;
+
+ return 0;
+}
+
+/**
+ * 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.
+ */
+uint64_t getfullkeyid(uint64_t keyid)
+{
+ int cmd = KEYD_CMD_GETFULLKEYID;
+
+ write(keyd_fd, &cmd, sizeof(cmd));
+ read(keyd_fd, &cmd, sizeof(cmd));
+ if (cmd == KEYD_REPLY_OK) {
+ write(keyd_fd, &keyid, sizeof(keyid));
+ read(keyd_fd, &keyid, sizeof(keyid));
+ }
+
+ return keyid;
+}
+
+/**
+ * dumpdb - dump the key database
+ * @filenamebase: The base filename to use for the dump.
+ *
+ * Dumps the database into one or more files, which contain pure OpenPGP
+ * that can be reimported into onak or gpg. filenamebase provides a base
+ * file name for the dump; several files may be created, all of which will
+ * begin with this string and then have a unique number and a .pgp
+ * extension.
+ */
+int dumpdb(char *filenamebase)
+{
+ return 0;
+}
+
+#define NEED_KEYID2UID 1
+#define NEED_GETKEYSIGS 1
+#include "keydb.c"