* Added searching on uids to lookup & keydb_pg.
* Changed Postgres backend to use 64 bit keyids instead of 32 bit.
* Made dearmor ignore CRs when looking for 2 blank lines.
+
+0.0.3 - 2nd July 2002
+
+* Added index on keyid for key table in Postgres backend.
+* Twiddled transaction support in an attempt to speed up mass key adding.
+* Changed putchar_func to take a character count rather than doing one char at
+ a time (massive speed up in Postgres case).
+* Introduced onak binary for general keyserver operations.
+* Changed all version number references to use VERSION macro.
+* Made lldel free the unused list structure. (pointed out by Simon Huggins)
+* Made llfind assert that the cmp function is non NULL. (Simon Huggins again)
+* Fixed gpgwww; after the move to 64bit keyids internally it was trying to
+ compare the 32bit user supplied keyid to the retrieved 64bit one and never
+ finding paths.
+* Various tidying up I've forgotten.
+* Fixed bug with removing signed packets while merging.
+* Fixed bug with potentially adding an already existing uid to a key when
+ merging.
+* Fixed stupid typo bug in merging keys.
CC = gcc
CFLAGS += -Wall -pedantic -g -I/usr/local/include
+#LDFLAGS += -pg
# Can be "pg" for Postgresql, "file" for flat files or "db2" for pksd db2 style.
DBTYPE = pg
# If using DBTYPE of "file" then comment the following line out.
LIBS = -L/usr/local/lib -lpq
#LIBS = -L/usr/local/lib -ldb2
-PROGS = keymerge add lookup gpgwww
+PROGS = add lookup gpgwww onak
OBJS = armor.o parsekey.o keydb_$(DBTYPE).o merge.o keyid.o md5.o sha.o \
- getcgi.o keyindex.o mem.o stats.o ll.o hash.o onak_conf.o
+ getcgi.o keyindex.o mem.o stats.o ll.o hash.o onak-conf.o
SRCS = armor.c parsekey.c merge.c keyid.c md5.c sha.c main.c getcgi.c stats.c \
keyindex.c mem.c lookup.c add.c keydb_$(DBTYPE).c ll.c hash.c \
- pathtest.c gpgwww.c onak_conf.c
+ gpgwww.c onak-conf.c
-all: $(PROGS) testparse pathtest maxpath
+all: $(PROGS) testparse maxpath
testparse: main.o $(OBJS)
$(CC) -o testparse main.o $(OBJS) $(LIBS)
-pathtest: pathtest.o $(OBJS)
- $(CC) -o pathtest pathtest.o $(OBJS) $(LIBS)
-
maxpath: maxpath.o $(OBJS)
$(CC) -o maxpath maxpath.o $(OBJS) $(LIBS)
$(CC) -o gpgwww gpgwww.o $(OBJS) $(LIBS)
lookup: lookup.o getcgi.o keyindex.o keydb_$(DBTYPE).o keyid.o sha.o \
- parsekey.o mem.o armor.o ll.o hash.o onak_conf.o
+ parsekey.o mem.o armor.o ll.o hash.o onak-conf.o
$(CC) -o lookup lookup.o getcgi.o keyindex.o keydb_$(DBTYPE).o keyid.o \
- sha.o parsekey.o mem.o armor.o ll.o hash.o onak_conf.o $(LIBS)
+ sha.o parsekey.o mem.o armor.o ll.o hash.o onak-conf.o $(LIBS)
add: add.o getcgi.o armor.o parsekey.o keydb_$(DBTYPE).o keyid.o sha.o mem.o \
- keyindex.o ll.o hash.o merge.o onak_conf.o
+ keyindex.o ll.o hash.o merge.o onak-conf.o
$(CC) -o add add.o getcgi.o armor.o parsekey.o keydb_$(DBTYPE).o \
- keyid.o sha.o mem.o keyindex.o ll.o hash.o merge.o onak_conf.o \
+ keyid.o sha.o mem.o keyindex.o ll.o hash.o merge.o onak-conf.o \
$(LIBS)
-keymerge: keymerge.o merge.o keyid.o sha.o armor.o parsekey.o ll.o \
- keydb_$(DBTYPE).o mem.o keyindex.o hash.o getcgi.o onak_conf.o
- $(CC) -o keymerge keymerge.o merge.o keyid.o sha.o armor.o parsekey.o \
- keydb_$(DBTYPE).o mem.o keyindex.o ll.o hash.o getcgi.o \
- onak_conf.o $(LIBS)
-
onak: onak.o merge.o keyid.o sha.o armor.o parsekey.o ll.o \
- keydb_$(DBTYPE).o mem.o keyindex.o hash.o getcgi.o onak_conf.o
- $(CC) -o onak onak.o merge.o keyid.o sha.o armor.o parsekey.o \
+ keydb_$(DBTYPE).o mem.o keyindex.o hash.o getcgi.o onak-conf.o
+ $(CC) $(LDFLAGS) -o onak onak.o merge.o keyid.o sha.o armor.o parsekey.o \
keydb_$(DBTYPE).o mem.o keyindex.o ll.o hash.o getcgi.o \
- onak_conf.o $(LIBS)
+ onak-conf.o $(LIBS)
clean:
- rm -f $(PROGS) $(OBJS) Makefile.bak testparse pathtest maxpath \
- *.core core \
- keymerge.o pathtest.o gpgwww.o add.o lookup.o main.o maxpath.o
+ rm -f $(PROGS) $(OBJS) Makefile.bak testparse maxpath *.core core \
+ gpgwww.o add.o lookup.o main.o maxpath.o onak.o
depend:
makedepend $(SRCS)
+keydb_pg.o: keydb.o
+
# DO NOT DELETE
--- /dev/null
+Performance of adding 2M key chunks (~ 1700 keys).
+
+Originally ~ 30 mins with 0.0.2.
+
+After adding an index on keyid for onak_keys:
+ Command being timed: "/u2/noodles/onak-0.0.3/onak"
+ User time (seconds): 75.12
+ System time (seconds): 76.08
+ Percent of CPU this job got: 3%
+ Elapsed (wall clock) time (h:mm:ss or m:ss): 1:18:17
+ Major (requiring I/O) page faults: 630
+ Minor (reclaiming a frame) page faults: 1238
+
+Making deletion in the same transaction as readding:
+ Command being timed: "/u2/noodles/onak-0.0.3/onak"
+ User time (seconds): 67.28
+ System time (seconds): 75.74
+ Percent of CPU this job got: 2%
+ Elapsed (wall clock) time (h:mm:ss or m:ss): 1:22:08
+ Major (requiring I/O) page faults: 617
+ Minor (reclaiming a frame) page faults: 1241
+
+Making merge_keys all one transaction:
+ Command being timed: "/u2/noodles/onak-0.0.3/onak"
+ User time (seconds): 74.45
+ System time (seconds): 69.82
+ Percent of CPU this job got: 2%
+ Elapsed (wall clock) time (h:mm:ss or m:ss): 1:29:28
+ Major (requiring I/O) page faults: 610
+ Minor (reclaiming a frame) page faults: 1237
+
+Only delete old key if we know it exists:
+ Command being timed: "/u2/noodles/onak-0.0.3/onak"
+ User time (seconds): 77.47
+ System time (seconds): 75.06
+ Percent of CPU this job got: 3%
+ Elapsed (wall clock) time (h:mm:ss or m:ss): 1:16:41
+ Major (requiring I/O) page faults: 610
+ Minor (reclaiming a frame) page faults: 1239
* Check keys on import?
* Test library?
* Better signature subpacket parsing (primary UID for example).
+* Better merging of signatures; need to decode subpackets so we can make sure
+ we don't add a signature that's already on a key but has different
+ subpackets.
* Better txt2html routine.
* Remove bithelp.h (i386 only at present & inlined).
- Build and test on non-i386.
-* BSD license? (Needs md5 & sha routines rewritten/replaced then)
* Pathfinder - graphical as well? Multiple paths?
* Do pathlengths for similar email addresses to help aide keysigning.
(ie "Find me the keys furthest from mine that end ox.ac.uk'")
* Change over to PQescapeString in PostgreSQL backend once Woody releases.
* Check freeing.
* More comments.
-* Sort out merging (use keymerge + some Perl to answer incoming email. Not
- sure about keys via hkp yet though).
+* Sort out merging (use onak + some Perl to answer incoming email. Not
+ sure about keys via hkp yet though - need to send updates out).
* Look at db2 backend - is it db2's fault? (Well, deadlock in that the library
probably is...). Is there an alternative library that would provide us with
similar features but be more reliable? gdbm?
+* Honor no-modify keyserver flag ("Brian M. Carlson" <karlsson@hal-pc.org>)
--- /dev/null
+#!/usr/bin/perl
+
+while (<>) {
+ /(........)$/;
+ print "Attempting to get $1\n";
+ $key = `./onak-db2 get $1`;
+ open (ONAK, "| ./onak -v add");
+ print ONAK $key;
+ close ONAK;
+
+ sleep 60;
+}
parse_keys(packets, &keys);
initdb();
printf("Got %d new keys.\n",
- update_keys(&keys));
+ update_keys(&keys, false));
cleanupdb();
} else {
puts("No OpenPGP packets found in input.");
#include "armor.h"
#include "keystructs.h"
+#include "onak-conf.h"
#include "parsekey.h"
#define ARMOR_WIDTH 64
return c;
}
-
-void putstring(int (*putchar_func)(void *ctx, unsigned char c),
- void *ctx,
- const char *string)
-{
- int i;
-
- assert(putchar_func != NULL);
- assert(string != NULL);
-
- for (i = 0; string[i] != 0; i++) {
- putchar_func(ctx, string[i]);
- }
-}
-
/**
* @lastoctet: The last octet we got.
* @curoctet: The current octet we're expecting (0, 1 or 2).
int curoctet;
int count;
long crc24;
- int (*putchar_func)(void *ctx, unsigned char c);
+ int (*putchar_func)(void *ctx, size_t count, unsigned char *c);
void *ctx;
};
static void armor_finish(struct armor_context *state)
{
+ unsigned char c;
+
switch (state->curoctet++) {
case 0:
break;
case 1:
- state->putchar_func(state->ctx,
- encode64((state->lastoctet & 3) << 4));
- state->putchar_func(state->ctx, '=');
- state->putchar_func(state->ctx, '=');
+ c = encode64((state->lastoctet & 3) << 4);
+ state->putchar_func(state->ctx, 1, &c);
+ state->putchar_func(state->ctx, 1, (unsigned char *) "=");
+ state->putchar_func(state->ctx, 1, (unsigned char *) "=");
break;
case 2:
- state->putchar_func(state->ctx,
- encode64((state->lastoctet & 0xF) << 2));
- state->putchar_func(state->ctx, '=');
+ c = encode64((state->lastoctet & 0xF) << 2);
+ state->putchar_func(state->ctx, 1, &c);
+ state->putchar_func(state->ctx, 1, (unsigned char *) "=");
break;
}
state->crc24 &= 0xffffffL;
- state->putchar_func(state->ctx, '\n');
- state->putchar_func(state->ctx, '=');
- state->putchar_func(state->ctx, encode64(state->crc24 >> 18));
- state->putchar_func(state->ctx, encode64((state->crc24 >> 12) & 0x3F));
- state->putchar_func(state->ctx, encode64((state->crc24 >> 6) & 0x3F));
- state->putchar_func(state->ctx, encode64(state->crc24 & 0x3F));
- state->putchar_func(state->ctx, '\n');
+ state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
+ state->putchar_func(state->ctx, 1, (unsigned char *) "=");
+ c = encode64(state->crc24 >> 18);
+ state->putchar_func(state->ctx, 1, &c);
+ c = encode64((state->crc24 >> 12) & 0x3F);
+ state->putchar_func(state->ctx, 1, &c);
+ c = encode64((state->crc24 >> 6) & 0x3F);
+ state->putchar_func(state->ctx, 1, &c);
+ c = encode64(state->crc24 & 0x3F);
+ state->putchar_func(state->ctx, 1, &c);
+ state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
}
-static int armor_putchar(void *ctx, unsigned char c)
+
+static int armor_putchar_int(void *ctx, unsigned char c)
{
struct armor_context *state;
+ unsigned char t;
int i;
assert(ctx != NULL);
switch (state->curoctet++) {
case 0:
- state->putchar_func(state->ctx, encode64(c >> 2));
+ t = encode64(c >> 2);
+ state->putchar_func(state->ctx, 1, &t);
state->count++;
break;
case 1:
- state->putchar_func(state->ctx,
- encode64(((state->lastoctet & 3) << 4) + (c >> 4)));
+ t = encode64(((state->lastoctet & 3) << 4) + (c >> 4));
+ state->putchar_func(state->ctx, 1, &t);
state->count++;
break;
case 2:
- state->putchar_func(state->ctx,
- encode64(((state->lastoctet & 0xF) << 2) + (c >> 6)));
- state->putchar_func(state->ctx, encode64(c & 0x3F));
+ t = encode64(((state->lastoctet & 0xF) << 2) + (c >> 6));
+ state->putchar_func(state->ctx, 1, &t);
+ t = encode64(c & 0x3F);
+ state->putchar_func(state->ctx, 1, &t);
state->count += 2;
break;
}
}
if ((state->count % ARMOR_WIDTH) == 0) {
- state->putchar_func(state->ctx, '\n');
+ state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
}
return 0;
}
+
+static int armor_putchar(void *ctx, size_t count, unsigned char *c)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ armor_putchar_int(ctx, c[i]);
+ }
+
+ return 0;
+}
+
/**
* @lastoctet: The last octet we got.
* @curoctet: The current octet we're expecting (0, 1 or 2).
* This function ASCII armors a list of OpenPGP packets and outputs it
* using putchar_func.
*/
-int armor_openpgp_stream(int (*putchar_func)(void *ctx, unsigned char c),
+int armor_openpgp_stream(int (*putchar_func)(void *ctx, size_t count,
+ unsigned char *c),
void *ctx,
struct openpgp_packet_list *packets)
{
struct armor_context armor_ctx;
-
/*
* Print armor header
*/
- putstring(putchar_func, ctx, "-----BEGIN PGP PUBLIC KEY BLOCK-----\n");
- putstring(putchar_func, ctx, "Version: onak 0.0.1\n\n");
+ putchar_func(ctx, sizeof("-----BEGIN PGP PUBLIC KEY BLOCK-----\n"),
+ (unsigned char *) "-----BEGIN PGP PUBLIC KEY BLOCK-----\n");
+ putchar_func(ctx, sizeof("Version: onak " VERSION "\n\n"),
+ (unsigned char *) "Version: onak " VERSION "\n\n");
armor_init(&armor_ctx);
armor_ctx.putchar_func = putchar_func;
/*
* Print armor footer
*/
- putstring(putchar_func, ctx, "-----END PGP PUBLIC KEY BLOCK-----\n");
+ putchar_func(ctx, sizeof("-----END PGP PUBLIC KEY BLOCK-----\n"),
+ (unsigned char *) "-----END PGP PUBLIC KEY BLOCK-----\n");
return 0;
}
* This function ASCII armors a list of OpenPGP packets and outputs it
* using putchar_func.
*/
-int armor_openpgp_stream(int (*putchar_func)(void *ctx, unsigned char c),
+int armor_openpgp_stream(int (*putchar_func)(void *ctx, size_t count,
+ unsigned char *c),
void *ctx,
struct openpgp_packet_list *packets);
#include "getcgi.h"
#include "hash.h"
#include "keydb.h"
-#include "onak_conf.h"
+#include "onak-conf.h"
#include "stats.h"
void dofindpath(uint64_t have, uint64_t want, bool html)
int rec;
char *uid;
+ have = getfullkeyid(have);
+ want = getfullkeyid(want);
+
/*
* Make sure the keys we have and want are in the cache.
*/
want);
} else {
printf("%d steps from 0x%llX to 0x%llX\n",
- keyinfoa->colour, have, want);
+ keyinfoa->colour, have & 0xFFFFFFFF,
+ want & 0xFFFFFFFF);
curkey = keyinfoa;
while (curkey != NULL && curkey->keyid != 0) {
uid = keyid2uid(curkey->keyid);
if (html && uid == NULL) {
printf("<a href=\"lookup?op=get&search=%llX\">"
"0x%llX</a> ([User id not found])%s)%s\n",
- curkey->keyid,
- curkey->keyid,
+ curkey->keyid & 0xFFFFFFFF,
+ curkey->keyid & 0xFFFFFFFF,
(curkey->keyid == want) ? "" :
" signs");
} else if (html && uid != NULL) {
printf("<a href=\"lookup?op=get&search=%llX\">"
"0x%llX</a> (<a href=\"lookup?op=vindex"
"&search=0x%llX\">%s</a>)%s\n",
- curkey->keyid,
- curkey->keyid,
- curkey->keyid,
+ curkey->keyid & 0xFFFFFFFF,
+ curkey->keyid & 0xFFFFFFFF,
+ curkey->keyid & 0xFFFFFFFF,
txt2html(keyid2uid(curkey->keyid)),
(curkey->keyid == want) ? "" :
" signs");
} else {
printf("0x%llX (%s)%s\n",
- curkey->keyid,
+ curkey->keyid & 0xFFFFFFFF,
(uid == NULL) ? "[User id not found]" :
uid,
(curkey->keyid == want) ? "" :
#include "hash.h"
#include "keydb.h"
+#include "keyid.h"
#include "ll.h"
#include "stats.h"
static char buf[1024];
buf[0]=0;
- if (fetch_key(keyid, &publickey) && publickey != NULL) {
+ if (fetch_key(keyid, &publickey, false) && publickey != NULL) {
curuid = publickey->uids;
while (curuid != NULL && buf[0] == 0) {
if (curuid->packet->tag == 13) {
struct openpgp_signedpacket_list *uids = NULL;
struct openpgp_publickey *publickey = NULL;
- fetch_key(keyid, &publickey);
+ fetch_key(keyid, &publickey, false);
if (publickey != NULL) {
for (uids = publickey->uids; uids != NULL; uids = uids->next) {
return sigs;
}
#endif
+
+#ifdef NEED_GETFULLKEYID
+/**
+ * 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.
+ */
+uint64_t getfullkeyid(uint64_t keyid)
+{
+ struct openpgp_publickey *publickey = NULL;
+
+ if (keyid < 0x100000000) {
+ fetch_key(keyid, &publickey, false);
+ keyid = get_keyid(publickey);
+ free_publickey(publickey);
+ }
+
+ return keyid;
+}
+#endif
*/
void cleanupdb(void);
+/**
+ * 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);
+
+/**
+ * endtrans - End a transaction.
+ *
+ * Ends a transaction.
+ */
+void endtrans(void);
+
/**
* 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);
+int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey, bool intrans);
/**
* 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.
+ * 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);
+int store_key(struct openpgp_publickey *publickey, bool intrans, bool update);
/**
* 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);
+int delete_key(uint64_t keyid, bool intrans);
/**
* fetch_key_text - Trys to find the keys that contain the supplied text.
*/
struct ll *getkeysigs(uint64_t keyid);
+/**
+ * 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.
+ */
+uint64_t getfullkeyid(uint64_t keyid);
+
#endif /* __KEYDB_H__ */
#include "keyindex.h"
#include "keystructs.h"
#include "mem.h"
-#include "onak_conf.h"
+#include "onak-conf.h"
#include "parsekey.h"
#define KEYDB_KEYID_BYTES 4
db_appexit(&db2_env);
}
+/**
+ * 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.
*
* 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
* in and then parse_keys() to parse the packets into a publickey
* structure.
*/
-int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey)
+int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
+ bool intrans)
{
struct openpgp_packet_list *packets = NULL;
int ret;
ret = (*(keydb(&key)->get))(keydb(&key), NULL, &key, &data, 0);
if (ret == 0) {
- //do stuff with data.
fetchbuf.buffer = data.data;
fetchbuf.offset = 0;
fetchbuf.size = data.size;
return (!ret);
}
+/**
+ * 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)
+{
+ return 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.
*
* Again we just use the hex representation of the keyid as the filename
* to store the key to. We flatten the public key to a list of OpenPGP
* packets and then use write_openpgp_stream() to write the stream out to
* the file.
*/
-int store_key(struct openpgp_publickey *publickey)
+int store_key(struct openpgp_publickey *publickey, bool intrans, bool update)
{
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)
+int delete_key(uint64_t keyid, bool intrans)
{
return (1);
}
*/
#define NEED_KEYID2UID 1
#define NEED_GETKEYSIGS 1
+#define NEED_GETFULLKEYID 1
#include "keydb.c"
#include "keystructs.h"
#include "ll.h"
#include "mem.h"
-#include "onak_conf.h"
+#include "onak-conf.h"
#include "parsekey.h"
/**
/**
* keydb_putchar - Puts a char to a file.
*/
-static int keydb_putchar(void *fd, unsigned char c)
+static int keydb_putchar(void *fd, size_t count, unsigned char *c)
{
- return !(write( *(int *) fd, &c, sizeof(c)));
+ return !(write( *(int *) fd, c, count));
}
/**
*/
#define NEED_KEYID2UID 1
#define NEED_GETKEYSIGS 1
+#define NEED_GETFULLKEYID 1
#include "keydb.c"
#include "keyindex.h"
#include "keystructs.h"
#include "mem.h"
-#include "onak_conf.h"
+#include "onak-conf.h"
#include "parsekey.h"
/**
/**
* keydb_putchar - Puts a char to a file.
*/
-static int keydb_putchar(void *fd, unsigned char c)
+static int keydb_putchar(void *fd, size_t count, unsigned char *c)
{
- return !(lo_write(dbconn, *(int *) fd, &c, sizeof(c)));
+ return !(lo_write(dbconn, *(int *) fd, c, count));
}
/**
dbconn = NULL;
}
+/**
+ * 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)
+{
+ PGresult *result = NULL;
+
+ result = PQexec(dbconn, "BEGIN");
+ PQclear(result);
+
+ return true;
+}
+
+/**
+ * endtrans - End a transaction.
+ *
+ * Ends a transaction.
+ */
+void endtrans(void)
+{
+ PGresult *result = NULL;
+
+ result = PQexec(dbconn, "COMMIT");
+ PQclear(result);
+
+ 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.
*
* 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
* in and then parse_keys() to parse the packets into a publickey
* structure.
*/
-int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey)
+int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey, bool intrans)
{
struct openpgp_packet_list *packets = NULL;
PGresult *result = NULL;
int numkeys = 0;
Oid key_oid;
- result = PQexec(dbconn, "BEGIN");
- PQclear(result);
+ if (!intrans) {
+ result = PQexec(dbconn, "BEGIN");
+ PQclear(result);
+ }
if (keyid > 0xFFFFFFFF) {
snprintf(statement, 1023,
PQclear(result);
- result = PQexec(dbconn, "COMMIT");
- PQclear(result);
+ if (!intrans) {
+ result = PQexec(dbconn, "COMMIT");
+ PQclear(result);
+ }
return (numkeys);
}
/**
* 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.
*
* Again we just use the hex representation of the keyid as the filename
* to store the key to. We flatten the public key to a list of OpenPGP
* packets and then use write_openpgp_stream() to write the stream out to
- * the file.
+ * the file. If update is true then we delete the old key first, otherwise we
+ * trust that it doesn't exist.
*/
-int store_key(struct openpgp_publickey *publickey)
+int store_key(struct openpgp_publickey *publickey, bool intrans, bool update)
{
struct openpgp_packet_list *packets = NULL;
struct openpgp_packet_list *list_end = NULL;
char *dodgychar = NULL;
int i;
+ if (!intrans) {
+ result = PQexec(dbconn, "BEGIN");
+ PQclear(result);
+ }
/*
* Delete the key if we already have it.
* of difference though - the largest chunk of data is the keydata and
* it definitely needs updated.
*/
- delete_key(get_keyid(publickey));
-
- result = PQexec(dbconn, "BEGIN");
- PQclear(result);
+ if (update) {
+ delete_key(get_keyid(publickey), true);
+ }
next = publickey->next;
publickey->next = NULL;
}
}
- result = PQexec(dbconn, "COMMIT");
- PQclear(result);
+ if (!intrans) {
+ result = PQexec(dbconn, "COMMIT");
+ PQclear(result);
+ }
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)
+int delete_key(uint64_t keyid, bool intrans)
{
PGresult *result = NULL;
char *oids = NULL;
int i;
Oid key_oid;
- result = PQexec(dbconn, "BEGIN");
- PQclear(result);
+ if (!intrans) {
+ result = PQexec(dbconn, "BEGIN");
+ PQclear(result);
+ }
snprintf(statement, 1023,
"SELECT keydata FROM onak_keys WHERE keyid = '%llX'",
PQclear(result);
- result = PQexec(dbconn, "COMMIT");
- PQclear(result);
+ if (!intrans) {
+ result = PQexec(dbconn, "COMMIT");
+ PQclear(result);
+ }
return (found);
}
* Include the basic keydb routines.
*/
#define NEED_GETKEYSIGS 1
+#define NEED_GETFULLKEYID 1
#include "keydb.c"
unsigned char c;
unsigned char *buff = NULL;
+ assert(publickey != NULL);
+
switch (publickey->publickey->data[0]) {
case 2:
case 3:
if (html) {
puts("<pre>");
}
- puts("Type bits/keyID Date User ID");
+ puts("Type bits/keyID Date User ID");
while (keys != NULL) {
created_time = (keys->publickey->data[1] << 24) +
(keys->publickey->data[2] << 16) +
+++ /dev/null
-/*
- * keymerge.c - Takes a key on stdin, merges it and outputs the difference.
- *
- * Jonathan McDowell <noodles@earth.li>
- *
- * Copyright 2002 Project Purple
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "armor.h"
-#include "keydb.h"
-#include "keyid.h"
-#include "keystructs.h"
-#include "mem.h"
-#include "merge.h"
-#include "parsekey.h"
-
-int stdin_getchar(void *ctx, size_t count, unsigned char *c)
-{
- int ic;
-
- do {
- ic = getchar();
- *c = ic;
- c++;
- } while ((ic != EOF) && (--count > 0));
- return (ic == EOF);
-}
-
-int stdout_putchar(void *ctx, unsigned char c)
-{
- return (putchar(c));
-}
-
-
-int main(int argc, char *argv[])
-{
- struct openpgp_packet_list *packets = NULL;
- struct openpgp_packet_list *list_end = NULL;
- struct openpgp_publickey *keys = NULL;
- int rc = EXIT_SUCCESS;
-
- dearmor_openpgp_stream(stdin_getchar, NULL, &packets);
- if (packets != NULL) {
- parse_keys(packets, &keys);
- free_packet_list(packets);
- packets = NULL;
-
- initdb();
- fprintf(stderr, "Got %d new keys.\n",
- update_keys(&keys));
- cleanupdb();
- } else {
- rc = 1;
- fprintf(stderr, "No keys read.\n");
- }
-
- if (keys != NULL) {
- flatten_publickey(keys, &packets, &list_end);
- free_publickey(keys);
- keys = NULL;
-
- armor_openpgp_stream(stdout_putchar, NULL, packets);
- free_packet_list(packets);
- packets = NULL;
- } else {
- rc = 1;
- fprintf(stderr, "No changes.\n");
- }
-
- return rc;
-}
struct ll *lldel(struct ll *curll, void *object,
int (*objectcmp) (const void *object1, const void *object2))
{
- struct ll *cur;
+ struct ll *cur = NULL;
+ struct ll *old = NULL;
assert(objectcmp != NULL);
if (cur == NULL) {
return NULL;
} else if (!(*objectcmp)(cur->object, object)) {
- return cur->next;
+ old = cur;
+ cur = cur->next;
+ free(old);
+ return cur;
}
while (cur->next != NULL) {
if (!(*objectcmp)(cur->next->object, object)) {
+ old = cur->next;
cur->next = cur->next->next;
+ free(old);
break;
}
}
{
struct ll *cur;
+ assert(objectcmp != NULL);
+
cur = curll;
while (cur != NULL && (*objectcmp)(cur->object, object)) {
cur = cur->next;
#include "keydb.h"
#include "keyindex.h"
#include "mem.h"
-#include "onak_conf.h"
+#include "onak-conf.h"
#include "parsekey.h"
#define OP_UNKNOWN 0
#define OP_INDEX 2
#define OP_VINDEX 3
-int putnextchar(void *ctx, unsigned char c)
+int putnextchar(void *ctx, size_t count, unsigned char *c)
{
- return putchar(c);
+ return printf("%.*s", count, c);
}
void find_keys(char *search, uint64_t keyid, bool ishex,
int count = 0;
if (ishex) {
- count = fetch_key(keyid, &publickey);
+ count = fetch_key(keyid, &publickey, false);
} else {
count = fetch_key_text(search, &publickey);
}
initdb();
switch (op) {
case OP_GET:
- if (fetch_key(keyid, &publickey)) {
+ if (fetch_key(keyid, &publickey, false)) {
puts("<pre>");
flatten_publickey(publickey,
&packets,
printf("In findmaxpath\n");
distance = 0;
from = to = tmp = NULL;
- hash_getkeysigs(0x5B430367);
+ hash_getkeysigs(0xF1BD4BE45B430367);
for (loop = 0; (loop < HASHSIZE) && (distance < max); loop++) {
curkey = gethashtableentry(loop);
if (cur->next == NULL) {
*list_end = prev;
}
+ // TODO: Free the removed signed packet...
}
+ prev = cur;
}
return found;
if (newelem->sigs == NULL) {
remove_signed_packet(new,
new_end,
- curelem->packet);
+ newelem->packet);
}
}
}
/*
- * If *new != NULL now then there are UIDs on the new key that weren't
- * on the old key. Add them.
+ * If *new != NULL now then there might be UIDs on the new key that
+ * weren't on the old key. Walk through them, checking if the UID is
+ * on the old key and if not adding them to it.
*/
for (curelem = *new; curelem != NULL;
curelem = curelem->next) {
- ADD_PACKET_TO_LIST((*old_end),
+
+ if (find_signed_packet(*old, curelem->packet) == NULL) {
+ ADD_PACKET_TO_LIST((*old_end),
packet_dup(curelem->packet));
- if (*old == NULL) {
- *old = *old_end;
- }
- packet_list_add(&(*old_end)->sigs,
+ if (*old == NULL) {
+ *old = *old_end;
+ }
+ packet_list_add(&(*old_end)->sigs,
&(*old_end)->last_sig,
curelem->sigs);
+ }
}
return 0;
*/
merge_signed_packets(&a->uids, &a->last_uid,
&b->uids, &b->last_uid);
- merge_signed_packets(&a->subkeys, &a->last_uid,
+ merge_signed_packets(&a->subkeys, &a->last_subkey,
&b->subkeys, &b->last_subkey);
}
/**
* update_keys - Takes a list of public keys and updates them in the DB.
* @keys: The keys to update in the DB.
+ * @verbose: Should we output more information as we add keys?
*
* 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
* 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 update_keys(struct openpgp_publickey **keys)
+int update_keys(struct openpgp_publickey **keys, bool verbose)
{
struct openpgp_publickey *curkey = NULL;
struct openpgp_publickey *oldkey = NULL;
- struct openpgp_publickey *prev = NULL;
+ struct openpgp_publickey *prev = NULL;
int newkeys = 0;
+ bool intrans;
for (curkey = *keys; curkey != NULL; curkey = curkey->next) {
- fetch_key(get_keyid(curkey), &oldkey);
+ intrans = starttrans();
+ if (verbose) {
+ fprintf(stderr, "Fetching key 0x%llX, result: %d\n",
+ get_keyid(curkey),
+ fetch_key(get_keyid(curkey), &oldkey, intrans));
+ } else {
+ fetch_key(get_keyid(curkey), &oldkey, intrans);
+ }
/*
* If we already have the key stored in the DB then merge it
}
} else {
prev = curkey;
- store_key(oldkey);
+ if (verbose) {
+ fprintf(stderr, "Merged key; storing updated key.\n");
+ }
+ store_key(oldkey, intrans, true);
}
free_publickey(oldkey);
oldkey = NULL;
} else {
- store_key(curkey);
+ if (verbose) {
+ fprintf(stderr, "Storing completely new key.\n");
+ }
+ store_key(curkey, intrans, false);
newkeys++;
}
+ endtrans();
+ intrans = false;
}
return newkeys;
/**
* update_keys - Takes a list of public keys and updates them in the DB.
* @keys: The keys to update in the DB.
+ * @verbose: Should we output more information as we add keys?
*
* 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
* 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 update_keys(struct openpgp_publickey **keys);
+int update_keys(struct openpgp_publickey **keys, bool verbose);
#endif
--- /dev/null
+/*
+ * onak-conf.c - Routines related to runtime config.
+ *
+ * Jonathan McDowell <noodles@earth.li>
+ *
+ * Copyright 2002 Project Purple
+ */
+
+#include <stdlib.h>
+
+#include "onak-conf.h"
+
+/*
+ * config - Runtime configuration for onak.
+ *
+ * Currently this is all hardcoded, but only needs changed here. In future
+ * it'll be read from a config file.
+ */
+struct onak_config config = {
+ 128, /* maxkeys */
+
+ /*
+ * Options for the db2 file backend.
+ */
+ "/community/pgp-keyserver/db-copy", /* db2_dbpath */
+
+ /*
+ * Options for the file backend.
+ */
+ NULL, /* file_dbpath */
+
+ /*
+ * Options for the Postgres backend.
+ */
+ NULL, /* pg_dbhost */
+ "noodles", /* pg_dbname */
+ NULL, /* pg_dbuser */
+ NULL, /* pg_dbpass */
+};
--- /dev/null
+/*
+ * onak-conf.h - Routines related to runtime config.
+ *
+ * Jonathan McDowell <noodles@earth.li>
+ *
+ * Copyright 2002 Project Purple
+ */
+
+#ifndef __ONAK_CONF_H_
+#define __ONAK_CONF_H_
+
+#define VERSION "0.0.3"
+
+/*
+ * struct onak_config - Runtime configuration for onak.
+ * @maxkeys: The maximum number of keys a query should return.
+ *
+ * @db2_dbpath: The path to the directory containing the db2 files.
+ *
+ * @file_dbpath: The path to the flat file DB directory.
+ *
+ * @pg_dbhost: The host that Postgres is running on.
+ * @pg_dbname: The database name.
+ * @pg_dbuser: The user we should connect as.
+ * @pg_dbpass: The password for the user.
+ *
+ * This structure holds various runtime configuration options for onak. It
+ * will eventually be populated from the config file.
+ */
+struct onak_config {
+ int maxkeys;
+
+ /*
+ * Options for the db2 file backend.
+ */
+ char *db2_dbpath;
+
+ /*
+ * Options for the file backend.
+ */
+ char *file_dbpath;
+
+ /*
+ * Options for the Postgres backend.
+ */
+ char *pg_dbhost;
+ char *pg_dbname;
+ char *pg_dbuser;
+ char *pg_dbpass;
+};
+
+/*
+ * config - The variable containing our runtime config.
+ */
+extern struct onak_config config;
+
+#endif /* __ONAK_CONF_H_ */
my @data = @_;
my (@errors, @mergedata);
- open3(\*MERGEIN, \*MERGEOUT, \*MERGEERR, "/home/noodles/onak-0.0.2/keymerge");
+ open3(\*MERGEIN, \*MERGEOUT, \*MERGEERR, "/home/noodles/onak-0.0.3/onak", "add");
print MERGEIN @data;
close MERGEIN;
@errors = <MERGEERR>;
@mergedata = <MERGEOUT>;
- #print @errors;
+ open (LOG, ">>/home/noodles/onak-0.0.3/keyadd.log");
+ print LOG @errors;
+ close LOG;
return @mergedata;
}
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include "armor.h"
#include "keydb.h"
#include "keyid.h"
+#include "keyindex.h"
#include "keystructs.h"
#include "mem.h"
#include "merge.h"
+#include "onak-conf.h"
#include "parsekey.h"
int stdin_getchar(void *ctx, size_t count, unsigned char *c)
return (ic == EOF);
}
-int stdout_putchar(void *ctx, unsigned char c)
+int stdout_putchar(void *ctx, size_t count, unsigned char *c)
{
- return (putchar(c));
+ int i;
+
+ for (i = 0; i < count; i++) {
+ putchar(c[i]);
+ }
+ return 0;
}
+void find_keys(char *search, uint64_t keyid, bool ishex,
+ bool fingerprint, bool exact, bool verbose)
+{
+ struct openpgp_publickey *publickey = NULL;
+ int count = 0;
+
+ if (ishex) {
+ count = fetch_key(keyid, &publickey, false);
+ } else {
+ count = fetch_key_text(search, &publickey);
+ }
+ if (publickey != NULL) {
+ key_index(publickey, verbose, fingerprint, false);
+ free_publickey(publickey);
+ } else if (count == 0) {
+ puts("Key not found.");
+ } else {
+ printf("Found %d keys, but maximum number to return is %d.\n",
+ count,
+ config.maxkeys);
+ puts("Try again with a more specific search.");
+ }
+}
+
+void usage(void) {
+ puts("onak " VERSION " - an OpenPGP keyserver.\n");
+ puts("Usage:\n");
+ puts("\tonak [options] <command> <parameters>\n");
+ puts("\tCommands:\n");
+ puts("\tadd - read armored OpenPGP keys from stdin and add to the keyserver");
+ puts("\tdelete - delete a given key from the keyserver");
+ puts("\tindex - search for a key and list it");
+ puts("\tvindex - search for a key and list it and its signatures");
+}
int main(int argc, char *argv[])
{
struct openpgp_packet_list *list_end = NULL;
struct openpgp_publickey *keys = NULL;
int rc = EXIT_SUCCESS;
+ char *search = NULL;
+ char *end = NULL;
+ uint64_t keyid = 0;
+ bool ishex = false;
+ bool verbose = false;
+ bool binary = false;
+ int optchar;
- read_openpgp_stream(stdin_getchar, NULL, &packets);
- if (packets != NULL) {
- parse_keys(packets, &keys);
- free_packet_list(packets);
- packets = NULL;
- initdb();
- fprintf(stderr, "Got %d new keys.\n",
- update_keys(&keys));
- cleanupdb();
- } else {
- rc = 1;
- fprintf(stderr, "No keys read.\n");
+ while ((optchar = getopt(argc, argv, "bv")) != -1 ) {
+ switch (optchar) {
+ case 'b':
+ binary = true;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ }
}
- if (keys != NULL) {
- free_publickey(keys);
- keys = NULL;
+ if ((argc - optind) < 1) {
+ usage();
+ } else if (!strcmp("add", argv[optind])) {
+ if (binary) {
+ read_openpgp_stream(stdin_getchar, NULL, &packets);
+ } else {
+ dearmor_openpgp_stream(stdin_getchar, NULL, &packets);
+ }
+ if (packets != NULL) {
+ parse_keys(packets, &keys);
+ free_packet_list(packets);
+ packets = NULL;
+ if (verbose) {
+ fprintf(stderr, "Finished reading keys.\n");
+ }
+
+ initdb();
+ fprintf(stderr, "Got %d new keys.\n",
+ update_keys(&keys, verbose));
+ cleanupdb();
+ } else {
+ rc = 1;
+ fprintf(stderr, "No keys read.\n");
+ }
+
+ if (keys != NULL) {
+ free_publickey(keys);
+ keys = NULL;
+ } else {
+ rc = 1;
+ fprintf(stderr, "No changes.\n");
+ }
+ } else if ((argc - optind) == 2) {
+ search = argv[optind+1];
+ if (search != NULL) {
+ keyid = strtoul(search, &end, 16);
+ if (*search != 0 &&
+ end != NULL &&
+ *end == 0) {
+ ishex = true;
+ }
+ }
+ initdb();
+ if (!strcmp("index", argv[optind])) {
+ find_keys(search, keyid, ishex, false, false, false);
+ } else if (!strcmp("vindex", argv[optind])) {
+ find_keys(search, keyid, ishex, false, false, true);
+ } else if (!strcmp("delete", argv[optind])) {
+ delete_key(getfullkeyid(keyid), false);
+ } else if (!strcmp("get", argv[optind])) {
+ if (fetch_key(keyid, &keys, false)) {
+ if (verbose) {
+ fprintf(stderr, "Got key.\n");
+ }
+ flatten_publickey(keys,
+ &packets,
+ &list_end);
+ armor_openpgp_stream(stdout_putchar,
+ NULL,
+ packets);
+ } else {
+ puts("Key not found");
+ }
+ }
+ cleanupdb();
} else {
- rc = 1;
- fprintf(stderr, "No changes.\n");
+ usage();
}
return rc;
--- /dev/null
+Flat profile:
+
+Each sample counts as 0.01 seconds.
+ % cumulative self self total
+ time seconds seconds calls us/call us/call name
+ 44.57 0.41 0.41 44208 9.27 14.02 transform
+ 22.83 0.62 0.21 9902592 0.02 0.02 rol
+ 9.78 0.71 0.09 31610 2.85 19.66 sha1_write
+ 7.61 0.78 0.07 33623 2.08 2.08 stdin_getchar
+ 2.17 0.80 0.02 6937 2.88 106.67 get_keyid
+ 2.17 0.82 0.02 1690 11.83 17.75 write_openpgp_stream
+ 2.17 0.84 0.02 Letext
+ 1.09 0.85 0.01 30179 0.33 0.33 keydb_putchar
+ 1.09 0.86 0.01 17848 0.56 0.56 packet_dup
+ 1.09 0.87 0.01 6322 1.58 35.26 sha1_final
+ 1.09 0.88 0.01 1690 5.92 8.88 flatten_publickey
+ 1.09 0.89 0.01 1690 5.92 5.92 keyuids
+ 1.09 0.90 0.01 1690 5.92 262.98 store_key
+ 1.09 0.91 0.01 1 10000.00 10000.00 free_publickey
+ 1.09 0.92 0.01 1 10000.00 815000.00 update_keys
+ 0.00 0.92 0.00 17848 0.00 0.00 free_packet
+ 0.00 0.92 0.00 6322 0.00 0.00 sha1_init
+ 0.00 0.92 0.00 6322 0.00 0.00 sha1_read
+ 0.00 0.92 0.00 3438 0.00 0.00 free_packet_list
+ 0.00 0.92 0.00 3227 0.00 0.00 free_signedpacket_list
+ 0.00 0.92 0.00 1690 0.00 0.00 endtrans
+ 0.00 0.92 0.00 1690 0.00 0.00 fetch_key
+ 0.00 0.92 0.00 1690 0.00 0.00 spsize
+ 0.00 0.92 0.00 1690 0.00 0.00 starttrans
+ 0.00 0.92 0.00 1 0.00 0.00 cleanupdb
+ 0.00 0.92 0.00 1 0.00 0.00 initdb
+ 0.00 0.92 0.00 1 0.00 5000.00 parse_keys
+ 0.00 0.92 0.00 1 0.00 70000.00 read_openpgp_stream
+
+ % the percentage of the total running time of the
+time program used by this function.
+
+cumulative a running sum of the number of seconds accounted
+ seconds for by this function and those listed above it.
+
+ self the number of seconds accounted for by this
+seconds function alone. This is the major sort for this
+ listing.
+
+calls the number of times this function was invoked, if
+ this function is profiled, else blank.
+
+ self the average number of milliseconds spent in this
+ms/call function per call, if this function is profiled,
+ else blank.
+
+ total the average number of milliseconds spent in this
+ms/call function and its descendents per call, if this
+ function is profiled, else blank.
+
+name the name of the function. This is the minor sort
+ for this listing. The index shows the location of
+ the function in the gprof listing. If the index is
+ in parenthesis it shows where it would appear in
+ the gprof listing if it were to be printed.
+\f
+ Call graph (explanation follows)
+
+
+granularity: each sample hit covers 4 byte(s) for 1.09% of 0.92 seconds
+
+index % time self children called name
+ <spontaneous>
+[1] 97.8 0.00 0.90 main [1]
+ 0.01 0.81 1/1 update_keys [2]
+ 0.00 0.07 1/1 read_openpgp_stream [10]
+ 0.01 0.00 1/1 free_publickey [17]
+ 0.00 0.01 1/1 parse_keys [18]
+ 0.00 0.00 1/3438 free_packet_list [22]
+ 0.00 0.00 1/1 initdb [29]
+ 0.00 0.00 1/1 cleanupdb [28]
+-----------------------------------------------
+ 0.01 0.81 1/1 main [1]
+[2] 88.6 0.01 0.81 1 update_keys [2]
+ 0.01 0.43 1690/1690 store_key [6]
+ 0.01 0.35 3380/6937 get_keyid [3]
+ 0.00 0.00 1690/1690 starttrans [27]
+ 0.00 0.00 1690/1690 fetch_key [25]
+ 0.00 0.00 1690/1690 endtrans [24]
+-----------------------------------------------
+ 0.01 0.35 3380/6937 update_keys [2]
+ 0.01 0.37 3557/6937 store_key [6]
+[3] 80.4 0.02 0.72 6937 get_keyid [3]
+ 0.07 0.43 25288/31610 sha1_write [4]
+ 0.01 0.21 6322/6322 sha1_final [7]
+ 0.00 0.00 6322/6322 sha1_init [20]
+ 0.00 0.00 6322/6322 sha1_read [21]
+-----------------------------------------------
+ 18966 sha1_write [4]
+ 0.02 0.11 6322/31610 sha1_final [7]
+ 0.07 0.43 25288/31610 get_keyid [3]
+[4] 67.5 0.09 0.53 31610+18966 sha1_write [4]
+ 0.35 0.18 37886/44208 transform [5]
+ 18966 sha1_write [4]
+-----------------------------------------------
+ 0.06 0.03 6322/44208 sha1_final [7]
+ 0.35 0.18 37886/44208 sha1_write [4]
+[5] 67.4 0.41 0.21 44208 transform [5]
+ 0.21 0.00 9902592/9902592 rol [8]
+-----------------------------------------------
+ 0.01 0.43 1690/1690 update_keys [2]
+[6] 48.3 0.01 0.43 1690 store_key [6]
+ 0.01 0.37 3557/6937 get_keyid [3]
+ 0.02 0.01 1690/1690 write_openpgp_stream [11]
+ 0.01 0.01 1690/1690 flatten_publickey [13]
+ 0.01 0.00 1690/1690 keyuids [16]
+-----------------------------------------------
+ 0.01 0.21 6322/6322 get_keyid [3]
+[7] 24.2 0.01 0.21 6322 sha1_final [7]
+ 0.02 0.11 6322/31610 sha1_write [4]
+ 0.06 0.03 6322/44208 transform [5]
+-----------------------------------------------
+ 0.21 0.00 9902592/9902592 transform [5]
+[8] 22.8 0.21 0.00 9902592 rol [8]
+-----------------------------------------------
+ 0.07 0.00 33623/33623 read_openpgp_stream [10]
+[9] 7.6 0.07 0.00 33623 stdin_getchar [9]
+-----------------------------------------------
+ 0.00 0.07 1/1 main [1]
+[10] 7.6 0.00 0.07 1 read_openpgp_stream [10]
+ 0.07 0.00 33623/33623 stdin_getchar [9]
+-----------------------------------------------
+ 0.02 0.01 1690/1690 store_key [6]
+[11] 3.3 0.02 0.01 1690 write_openpgp_stream [11]
+ 0.01 0.00 30179/30179 keydb_putchar [14]
+-----------------------------------------------
+ <spontaneous>
+[12] 2.2 0.02 0.00 Letext [12]
+-----------------------------------------------
+ 0.01 0.01 1690/1690 store_key [6]
+[13] 1.6 0.01 0.01 1690 flatten_publickey [13]
+ 0.01 0.00 8924/17848 packet_dup [15]
+-----------------------------------------------
+ 0.01 0.00 30179/30179 write_openpgp_stream [11]
+[14] 1.1 0.01 0.00 30179 keydb_putchar [14]
+-----------------------------------------------
+ 0.01 0.00 8924/17848 parse_keys [18]
+ 0.01 0.00 8924/17848 flatten_publickey [13]
+[15] 1.1 0.01 0.00 17848 packet_dup [15]
+-----------------------------------------------
+ 0.01 0.00 1690/1690 store_key [6]
+[16] 1.1 0.01 0.00 1690 keyuids [16]
+ 0.00 0.00 1690/1690 spsize [26]
+-----------------------------------------------
+ 0.01 0.00 1/1 main [1]
+[17] 1.1 0.01 0.00 1 free_publickey [17]
+ 0.00 0.00 3227/3227 free_signedpacket_list [23]
+ 0.00 0.00 1690/17848 free_packet [19]
+ 0.00 0.00 41/3438 free_packet_list [22]
+-----------------------------------------------
+ 0.00 0.01 1/1 main [1]
+[18] 0.5 0.00 0.01 1 parse_keys [18]
+ 0.01 0.00 8924/17848 packet_dup [15]
+-----------------------------------------------
+ 0.00 0.00 1690/17848 free_publickey [17]
+ 0.00 0.00 3410/17848 free_signedpacket_list [23]
+ 0.00 0.00 12748/17848 free_packet_list [22]
+[19] 0.0 0.00 0.00 17848 free_packet [19]
+-----------------------------------------------
+ 0.00 0.00 6322/6322 get_keyid [3]
+[20] 0.0 0.00 0.00 6322 sha1_init [20]
+-----------------------------------------------
+ 0.00 0.00 6322/6322 get_keyid [3]
+[21] 0.0 0.00 0.00 6322 sha1_read [21]
+-----------------------------------------------
+ 0.00 0.00 1/3438 main [1]
+ 0.00 0.00 41/3438 free_publickey [17]
+ 0.00 0.00 3396/3438 free_signedpacket_list [23]
+[22] 0.0 0.00 0.00 3438 free_packet_list [22]
+ 0.00 0.00 12748/17848 free_packet [19]
+-----------------------------------------------
+ 0.00 0.00 3227/3227 free_publickey [17]
+[23] 0.0 0.00 0.00 3227 free_signedpacket_list [23]
+ 0.00 0.00 3410/17848 free_packet [19]
+ 0.00 0.00 3396/3438 free_packet_list [22]
+-----------------------------------------------
+ 0.00 0.00 1690/1690 update_keys [2]
+[24] 0.0 0.00 0.00 1690 endtrans [24]
+-----------------------------------------------
+ 0.00 0.00 1690/1690 update_keys [2]
+[25] 0.0 0.00 0.00 1690 fetch_key [25]
+-----------------------------------------------
+ 0.00 0.00 1690/1690 keyuids [16]
+[26] 0.0 0.00 0.00 1690 spsize [26]
+-----------------------------------------------
+ 0.00 0.00 1690/1690 update_keys [2]
+[27] 0.0 0.00 0.00 1690 starttrans [27]
+-----------------------------------------------
+ 0.00 0.00 1/1 main [1]
+[28] 0.0 0.00 0.00 1 cleanupdb [28]
+-----------------------------------------------
+ 0.00 0.00 1/1 main [1]
+[29] 0.0 0.00 0.00 1 initdb [29]
+-----------------------------------------------
+
+ This table describes the call tree of the program, and was sorted by
+ the total amount of time spent in each function and its children.
+
+ Each entry in this table consists of several lines. The line with the
+ index number at the left hand margin lists the current function.
+ The lines above it list the functions that called this function,
+ and the lines below it list the functions this one called.
+ This line lists:
+ index A unique number given to each element of the table.
+ Index numbers are sorted numerically.
+ The index number is printed next to every function name so
+ it is easier to look up where the function in the table.
+
+ % time This is the percentage of the `total' time that was spent
+ in this function and its children. Note that due to
+ different viewpoints, functions excluded by options, etc,
+ these numbers will NOT add up to 100%.
+
+ self This is the total amount of time spent in this function.
+
+ children This is the total amount of time propagated into this
+ function by its children.
+
+ called This is the number of times the function was called.
+ If the function called itself recursively, the number
+ only includes non-recursive calls, and is followed by
+ a `+' and the number of recursive calls.
+
+ name The name of the current function. The index number is
+ printed after it. If the function is a member of a
+ cycle, the cycle number is printed between the
+ function's name and the index number.
+
+
+ For the function's parents, the fields have the following meanings:
+
+ self This is the amount of time that was propagated directly
+ from the function into this parent.
+
+ children This is the amount of time that was propagated from
+ the function's children into this parent.
+
+ called This is the number of times this parent called the
+ function `/' the total number of times the function
+ was called. Recursive calls to the function are not
+ included in the number after the `/'.
+
+ name This is the name of the parent. The parent's index
+ number is printed after it. If the parent is a
+ member of a cycle, the cycle number is printed between
+ the name and the index number.
+
+ If the parents of the function cannot be determined, the word
+ `<spontaneous>' is printed in the `name' field, and all the other
+ fields are blank.
+
+ For the function's children, the fields have the following meanings:
+
+ self This is the amount of time that was propagated directly
+ from the child into the function.
+
+ children This is the amount of time that was propagated from the
+ child's children to the function.
+
+ called This is the number of times the function called
+ this child `/' the total number of times the child
+ was called. Recursive calls by the child are not
+ listed in the number after the `/'.
+
+ name This is the name of the child. The child's index
+ number is printed after it. If the child is a
+ member of a cycle, the cycle number is printed
+ between the name and the index number.
+
+ If there are any cycles (circles) in the call graph, there is an
+ entry for the cycle-as-a-whole. This entry shows who called the
+ cycle (as parents) and the members of the cycle (as children.)
+ The `+' recursive calls entry shows the number of function calls that
+ were internal to the cycle, and the calls entry for each member shows,
+ for that member, how many times it was called from other members of
+ the cycle.
+
+\f
+Index by function name
+
+ [12] Letext (bithelp.h) [29] initdb [4] sha1_write
+ [28] cleanupdb [14] keydb_putchar (keydb_pg.c) [26] spsize
+ [24] endtrans [16] keyuids [27] starttrans
+ [25] fetch_key [15] packet_dup [9] stdin_getchar
+ [13] flatten_publickey [18] parse_keys [6] store_key
+ [19] free_packet [10] read_openpgp_stream [5] transform (sha.c)
+ [22] free_packet_list [8] rol (bithelp.h) [2] update_keys
+ [17] free_publickey [7] sha1_final [11] write_openpgp_stream
+ [23] free_signedpacket_list [20] sha1_init
+ [3] get_keyid [21] sha1_read
keyid char(16) NOT NULL,
keydata oid NOT NULL
);
+CREATE INDEX onak_keys_keyid_index ON onak_keys(keyid);
CREATE TABLE onak_uids (
keyid char(16) NOT NULL,
+++ /dev/null
-/*
- * onak_conf.c - Routines related to runtime config.
- *
- * Jonathan McDowell <noodles@earth.li>
- *
- * Copyright 2002 Project Purple
- */
-
-#include <stdlib.h>
-
-#include "onak_conf.h"
-
-/*
- * config - Runtime configuration for onak.
- *
- * Currently this is all hardcoded, but only needs changed here. In future
- * it'll be read from a config file.
- */
-struct onak_config config = {
- 128, /* maxkeys */
-
- /*
- * Options for the db2 file backend.
- */
- NULL, /* db2_dbpath */
-
- /*
- * Options for the file backend.
- */
- NULL, /* file_dbpath */
-
- /*
- * Options for the Postgres backend.
- */
- NULL, /* pg_dbhost */
- NULL, /* pg_dbname */
- "noodles", /* pg_dbuser */
- NULL, /* pg_dbpass */
-};
+++ /dev/null
-/*
- * onak_conf.h - Routines related to runtime config.
- *
- * Jonathan McDowell <noodles@earth.li>
- *
- * Copyright 2002 Project Purple
- */
-
-#ifndef __ONAK_CONF_H_
-#define __ONAK_CONF_H_
-
-#define VERSION "0.0.2"
-
-/*
- * struct onak_config - Runtime configuration for onak.
- * @maxkeys: The maximum number of keys a query should return.
- *
- * @db2_dbpath: The path to the directory containing the db2 files.
- *
- * @file_dbpath: The path to the flat file DB directory.
- *
- * @pg_dbhost: The host that Postgres is running on.
- * @pg_dbname: The database name.
- * @pg_dbuser: The user we should connect as.
- * @pg_dbpass: The password for the user.
- *
- * This structure holds various runtime configuration options for onak. It
- * will eventually be populated from the config file.
- */
-struct onak_config {
- int maxkeys;
-
- /*
- * Options for the db2 file backend.
- */
- char *db2_dbpath;
-
- /*
- * Options for the file backend.
- */
- char *file_dbpath;
-
- /*
- * Options for the Postgres backend.
- */
- char *pg_dbhost;
- char *pg_dbname;
- char *pg_dbuser;
- char *pg_dbpass;
-};
-
-/*
- * config - The variable containing our runtime config.
- */
-extern struct onak_config config;
-
-#endif /* __ONAK_CONF_H_ */
* This function uses putchar_func to write characters to an OpenPGP
* packet stream from a linked list of packets.
*/
-int write_openpgp_stream(int (*putchar_func)(void *ctx, unsigned char c),
+int write_openpgp_stream(int (*putchar_func)(void *ctx, size_t count,
+ unsigned char *c),
void *ctx,
struct openpgp_packet_list *packets)
{
unsigned char curchar = 0;
- int i;
while (packets != NULL) {
curchar = 0x80;
if (packets->packet->newformat) {
curchar |= 0x40;
curchar |= packets->packet->tag;
- putchar_func(ctx, curchar);
+ putchar_func(ctx, 1, &curchar);
if (packets->packet->length < 192) {
- putchar_func(ctx, packets->packet->length);
+ curchar = packets->packet->length;
+ putchar_func(ctx, 1, &curchar);
} else if (packets->packet->length > 191 &&
packets->packet->length < 8383) {
-// fputs("Potentially dodgy code here.\n", stderr);
- putchar_func(ctx,
- (((packets->packet->length - 192) &
- 0xFF00) >> 8) + 192);
-
- putchar_func(ctx,
- (packets->packet->length - 192) &
- 0xFF);
+ curchar = (((packets->packet->length - 192) &
+ 0xFF00) >> 8) + 192;
+ putchar_func(ctx, 1, &curchar);
+ curchar = (packets->packet->length - 192) &
+ 0xFF;
+ putchar_func(ctx, 1, &curchar);
} else {
fputs("Unsupported new format length.\n", stderr);
}
} else {
curchar |= (packets->packet->tag << 2);
if (packets->packet->length < 256) {
- putchar_func(ctx, curchar);
- putchar_func(ctx, packets->packet->length);
+ putchar_func(ctx, 1, &curchar);
+ curchar = packets->packet->length;
+ putchar_func(ctx, 1, &curchar);
} else if (packets->packet->length < 0x10000) {
curchar |= 1;
- putchar_func(ctx, curchar);
- putchar_func(ctx, packets->packet->length >> 8);
- putchar_func(ctx,
- packets->packet->length & 0xFF);
+ putchar_func(ctx, 1, &curchar);
+ curchar = packets->packet->length >> 8;
+ putchar_func(ctx, 1, &curchar);
+ curchar = packets->packet->length & 0xFF;
+ putchar_func(ctx, 1, &curchar);
} else {
curchar |= 2;
- putchar_func(ctx, curchar);
- putchar_func(ctx,
- packets->packet->length >> 24);
- putchar_func(ctx,
- (packets->packet->length >> 16) & 0xFF);
- putchar_func(ctx,
- (packets->packet->length >> 8) & 0xFF);
- putchar_func(ctx,
- packets->packet->length & 0xFF);
+ putchar_func(ctx, 1, &curchar);
+ curchar = packets->packet->length >> 24;
+ putchar_func(ctx, 1, &curchar);
+ curchar = (packets->packet->length >> 16) & 0xFF;
+ putchar_func(ctx, 1, &curchar);
+ curchar = (packets->packet->length >> 8) & 0xFF;
+ putchar_func(ctx, 1, &curchar);
+ curchar = packets->packet->length & 0xFF;
+ putchar_func(ctx, 1, &curchar);
}
}
- for (i = 0; i < packets->packet->length; i++) {
- putchar_func(ctx, packets->packet->data[i]);
- }
+ putchar_func(ctx, packets->packet->length, packets->packet->data);
+// for (i = 0; i < packets->packet->length; i++) {
+// putchar_func(ctx, packets->packet->data[i]);
+// }
packets = packets->next;
}
return 0;
* This function uses putchar_func to write characters to an OpenPGP
* packet stream from a linked list of packets.
*/
-int write_openpgp_stream(int (*putchar_func)(void *ctx, unsigned char c),
+int write_openpgp_stream(int (*putchar_func)(void *ctx, size_t count,
+ unsigned char *c),
void *ctx,
struct openpgp_packet_list *packets);
+++ /dev/null
-//#include <stdint.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "hash.h"
-#include "keydb.h"
-#include "stats.h"
-
-void dofindpath(uint64_t have, uint64_t want, bool html)
-{
- struct stats_key *keyinfoa, *keyinfob, *curkey;
- int rec;
-
- /*
- * Make sure the key we have and want are in the cache.
- */
- hash_getkeysigs(have);
- hash_getkeysigs(want);
-
- if ((keyinfoa = findinhash(have)) == NULL) {
- printf("550 Couldn't find key 0x%llX.\n", have);
- return;
- }
- if ((keyinfob = findinhash(want)) == NULL) {
- printf("550 Couldn't find key 0x%llX.\n", want);
- return;
- }
-
- /*
- * Fill the tree info up.
- */
- initcolour(true);
- rec = findpath(keyinfoa, keyinfob);
- keyinfob->parent = 0;
-
- printf("%d nodes examined. %ld elements in the hash\n", rec,
- hashelements());
- if (keyinfoa->colour == 0) {
- printf("550 Can't find a link from 0x%llX to 0x%llX\n",
- have,
- want);
- } else {
- printf("250-%d steps from 0x%llX to 0x%llX\n",
- keyinfoa->colour, have, want);
- curkey = keyinfoa;
- while (curkey != NULL) {
- printf("250-0x%llX (%s)\n",
- curkey->keyid,
- keyid2uid(curkey->keyid));
- curkey = findinhash(curkey->parent);
- }
- }
-}
-
-int main(int argc, char *argv[])
-{
- initdb();
- inithash();
- dofindpath(0x5B430367, 0x3E1D0C1C, false);
- dofindpath(0x3E1D0C1C, 0x5B430367, false);
- cleanupdb();
-
- return EXIT_SUCCESS;
-}
* Copyright 2000-2002 Project Purple
*/
+#include <stdio.h>
#include <stdlib.h>
#include "hash.h"
nextkeys = NULL;
curdegree++;
}
+ fprintf(stderr, "Hash contains %ld keys.\n", hashelements());
}
return count;