From: Jonathan McDowell <noodles@earth.li> Date: Mon, 31 May 2004 23:46:54 +0000 (+0000) Subject: cscvs to tla changeset 3 X-Git-Url: https://git.sommitrealweird.co.uk/onak.git/commitdiff_plain/e02c731dfbb288c736f2cd09a9b6df0507c59ddd?ds=inline cscvs to tla changeset 3 Author: noodles Date: 2002/09/08 09:16:22 Committing onak 0.0.3. --- diff --git a/HISTORY b/HISTORY index e72f3df..8cc8eb2 100644 --- a/HISTORY +++ b/HISTORY @@ -21,3 +21,22 @@ * 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. diff --git a/Makefile b/Makefile index 115ebe0..9f432b8 100644 --- a/Makefile +++ b/Makefile @@ -2,27 +2,25 @@ 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) @@ -30,35 +28,30 @@ gpgwww: gpgwww.o $(OBJS) $(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 diff --git a/PERFORMANCE b/PERFORMANCE new file mode 100644 index 0000000..3221831 --- /dev/null +++ b/PERFORMANCE @@ -0,0 +1,39 @@ +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 diff --git a/TODO b/TODO index 72dc698..d06b23b 100644 --- a/TODO +++ b/TODO @@ -2,10 +2,12 @@ * 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'") @@ -22,8 +24,9 @@ * 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>) diff --git a/add-imp.pl b/add-imp.pl new file mode 100755 index 0000000..09470c3 --- /dev/null +++ b/add-imp.pl @@ -0,0 +1,12 @@ +#!/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; +} diff --git a/add.c b/add.c index d820b52..3af9309 100644 --- a/add.c +++ b/add.c @@ -66,7 +66,7 @@ int main(int argc, char *argv[]) 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."); diff --git a/armor.c b/armor.c index d811e50..9f5c19a 100644 --- a/armor.c +++ b/armor.c @@ -11,6 +11,7 @@ #include "armor.h" #include "keystructs.h" +#include "onak-conf.h" #include "parsekey.h" #define ARMOR_WIDTH 64 @@ -62,21 +63,6 @@ static unsigned char decode64(unsigned char c) { 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). @@ -90,7 +76,7 @@ struct armor_context { 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; }; @@ -104,36 +90,44 @@ static void armor_init(struct armor_context *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); @@ -141,18 +135,20 @@ static int armor_putchar(void *ctx, unsigned char c) 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; } @@ -168,12 +164,24 @@ static int armor_putchar(void *ctx, unsigned char c) } 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). @@ -285,18 +293,20 @@ static int dearmor_getchar_c(void *ctx, size_t count, unsigned char *c) * 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; @@ -307,7 +317,8 @@ int armor_openpgp_stream(int (*putchar_func)(void *ctx, unsigned char c), /* * 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; } diff --git a/armor.h b/armor.h index 6b58a34..85ac6a6 100644 --- a/armor.h +++ b/armor.h @@ -20,7 +20,8 @@ * 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); diff --git a/gpgwww.c b/gpgwww.c index 5f7da46..dc79135 100644 --- a/gpgwww.c +++ b/gpgwww.c @@ -14,7 +14,7 @@ #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) @@ -23,6 +23,9 @@ 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. */ @@ -53,30 +56,31 @@ void dofindpath(uint64_t have, uint64_t want, bool html) 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) ? "" : diff --git a/hash.c b/hash.c index 82dfcc7..47ec2d8 100644 --- a/hash.c +++ b/hash.c @@ -11,6 +11,7 @@ #include "hash.h" #include "keydb.h" +#include "keyid.h" #include "ll.h" #include "stats.h" diff --git a/keydb.c b/keydb.c index a9e4cef..3ebb056 100644 --- a/keydb.c +++ b/keydb.c @@ -35,7 +35,7 @@ char *keyid2uid(uint64_t keyid) 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) { @@ -70,7 +70,7 @@ struct ll *getkeysigs(uint64_t keyid) 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) { @@ -82,3 +82,25 @@ struct ll *getkeysigs(uint64_t keyid) 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 diff --git a/keydb.h b/keydb.h index 9a248e3..e9bcb67 100644 --- a/keydb.h +++ b/keydb.h @@ -32,38 +32,60 @@ void initdb(void); */ 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. @@ -93,4 +115,13 @@ char *keyid2uid(uint64_t keyid); */ 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__ */ diff --git a/keydb_db2.c b/keydb_db2.c index 771b2a5..3d66c5a 100644 --- a/keydb_db2.c +++ b/keydb_db2.c @@ -21,7 +21,7 @@ #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 @@ -155,10 +155,33 @@ void cleanupdb(void) 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 @@ -166,7 +189,8 @@ void cleanupdb(void) * 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; @@ -187,7 +211,6 @@ int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey) 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; @@ -198,16 +221,31 @@ int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey) 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; } @@ -215,11 +253,12 @@ int store_key(struct openpgp_publickey *publickey) /** * 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); } @@ -229,4 +268,5 @@ int delete_key(uint64_t keyid) */ #define NEED_KEYID2UID 1 #define NEED_GETKEYSIGS 1 +#define NEED_GETFULLKEYID 1 #include "keydb.c" diff --git a/keydb_file.c b/keydb_file.c index 9784ecf..1d9b081 100644 --- a/keydb_file.c +++ b/keydb_file.c @@ -20,7 +20,7 @@ #include "keystructs.h" #include "ll.h" #include "mem.h" -#include "onak_conf.h" +#include "onak-conf.h" #include "parsekey.h" /** @@ -34,9 +34,9 @@ static int keydb_fetchchar(void *fd, size_t count, unsigned char *c) /** * 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)); } /** @@ -143,4 +143,5 @@ int delete_key(uint64_t keyid) */ #define NEED_KEYID2UID 1 #define NEED_GETKEYSIGS 1 +#define NEED_GETFULLKEYID 1 #include "keydb.c" diff --git a/keydb_pg.c b/keydb_pg.c index d2a2a55..3f519bc 100644 --- a/keydb_pg.c +++ b/keydb_pg.c @@ -25,7 +25,7 @@ #include "keyindex.h" #include "keystructs.h" #include "mem.h" -#include "onak_conf.h" +#include "onak-conf.h" #include "parsekey.h" /** @@ -44,9 +44,9 @@ static int keydb_fetchchar(void *fd, size_t count, unsigned char *c) /** * 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)); } /** @@ -87,10 +87,43 @@ void cleanupdb(void) 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 @@ -98,7 +131,7 @@ void cleanupdb(void) * 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; @@ -109,8 +142,10 @@ int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey) 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, @@ -146,8 +181,10 @@ int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey) PQclear(result); - result = PQexec(dbconn, "COMMIT"); - PQclear(result); + if (!intrans) { + result = PQexec(dbconn, "COMMIT"); + PQclear(result); + } return (numkeys); } @@ -228,13 +265,16 @@ int fetch_key_text(const char *search, struct openpgp_publickey **publickey) /** * 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; @@ -248,6 +288,10 @@ int store_key(struct openpgp_publickey *publickey) char *dodgychar = NULL; int i; + if (!intrans) { + result = PQexec(dbconn, "BEGIN"); + PQclear(result); + } /* * Delete the key if we already have it. @@ -257,10 +301,9 @@ int store_key(struct openpgp_publickey *publickey) * 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; @@ -328,8 +371,10 @@ int store_key(struct openpgp_publickey *publickey) } } - result = PQexec(dbconn, "COMMIT"); - PQclear(result); + if (!intrans) { + result = PQexec(dbconn, "COMMIT"); + PQclear(result); + } return 0; } @@ -337,11 +382,12 @@ int store_key(struct openpgp_publickey *publickey) /** * 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; @@ -350,8 +396,10 @@ int delete_key(uint64_t keyid) 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'", @@ -386,8 +434,10 @@ int delete_key(uint64_t keyid) PQclear(result); - result = PQexec(dbconn, "COMMIT"); - PQclear(result); + if (!intrans) { + result = PQexec(dbconn, "COMMIT"); + PQclear(result); + } return (found); } @@ -430,4 +480,5 @@ char *keyid2uid(uint64_t keyid) * Include the basic keydb routines. */ #define NEED_GETKEYSIGS 1 +#define NEED_GETFULLKEYID 1 #include "keydb.c" diff --git a/keyid.c b/keyid.c index 8131e16..65a0363 100644 --- a/keyid.c +++ b/keyid.c @@ -26,6 +26,8 @@ uint64_t get_keyid(struct openpgp_publickey *publickey) unsigned char c; unsigned char *buff = NULL; + assert(publickey != NULL); + switch (publickey->publickey->data[0]) { case 2: case 3: diff --git a/keyindex.c b/keyindex.c index dfa0d44..a1bbe2e 100644 --- a/keyindex.c +++ b/keyindex.c @@ -237,7 +237,7 @@ int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint, 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) + diff --git a/keymerge.c b/keymerge.c deleted file mode 100644 index fb95c2d..0000000 --- a/keymerge.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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; -} diff --git a/ll.c b/ll.c index acad0bc..7110378 100644 --- a/ll.c +++ b/ll.c @@ -31,7 +31,8 @@ struct ll *lladd(struct ll *curll, void *object) 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); @@ -39,11 +40,16 @@ struct ll *lldel(struct ll *curll, void *object, 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; } } @@ -55,6 +61,8 @@ struct ll *llfind(struct ll *curll, void *object, { struct ll *cur; + assert(objectcmp != NULL); + cur = curll; while (cur != NULL && (*objectcmp)(cur->object, object)) { cur = cur->next; diff --git a/lookup.c b/lookup.c index 3c55a61..94f38c8 100644 --- a/lookup.c +++ b/lookup.c @@ -18,7 +18,7 @@ #include "keydb.h" #include "keyindex.h" #include "mem.h" -#include "onak_conf.h" +#include "onak-conf.h" #include "parsekey.h" #define OP_UNKNOWN 0 @@ -26,9 +26,9 @@ #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, @@ -38,7 +38,7 @@ 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); } @@ -115,7 +115,7 @@ int main(int argc, char *argv[]) initdb(); switch (op) { case OP_GET: - if (fetch_key(keyid, &publickey)) { + if (fetch_key(keyid, &publickey, false)) { puts("<pre>"); flatten_publickey(publickey, &packets, diff --git a/maxpath.c b/maxpath.c index 3714281..f46ea4c 100644 --- a/maxpath.c +++ b/maxpath.c @@ -24,7 +24,7 @@ void findmaxpath(unsigned long max) 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); diff --git a/merge.c b/merge.c index 96e628b..8bfbd09 100644 --- a/merge.c +++ b/merge.c @@ -105,7 +105,9 @@ bool remove_signed_packet(struct openpgp_signedpacket_list **packet_list, if (cur->next == NULL) { *list_end = prev; } + // TODO: Free the removed signed packet... } + prev = cur; } return found; @@ -192,25 +194,29 @@ int merge_signed_packets(struct openpgp_signedpacket_list **old, 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; @@ -290,7 +296,7 @@ int merge_keys(struct openpgp_publickey *a, struct openpgp_publickey *b) */ 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); } @@ -301,6 +307,7 @@ int merge_keys(struct openpgp_publickey *a, struct openpgp_publickey *b) /** * 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 @@ -308,15 +315,23 @@ int merge_keys(struct openpgp_publickey *a, struct openpgp_publickey *b) * 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 @@ -337,14 +352,22 @@ int update_keys(struct openpgp_publickey **keys) } } 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; diff --git a/merge.h b/merge.h index 208c39b..f298172 100644 --- a/merge.h +++ b/merge.h @@ -28,6 +28,7 @@ int merge_keys(struct openpgp_publickey *a, struct openpgp_publickey *b); /** * 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 @@ -35,6 +36,6 @@ int merge_keys(struct openpgp_publickey *a, struct openpgp_publickey *b); * 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 diff --git a/onak_conf.c b/onak-conf.c similarity index 74% rename from onak_conf.c rename to onak-conf.c index a72d31d..a3ee64b 100644 --- a/onak_conf.c +++ b/onak-conf.c @@ -1,5 +1,5 @@ /* - * onak_conf.c - Routines related to runtime config. + * onak-conf.c - Routines related to runtime config. * * Jonathan McDowell <noodles@earth.li> * @@ -8,7 +8,7 @@ #include <stdlib.h> -#include "onak_conf.h" +#include "onak-conf.h" /* * config - Runtime configuration for onak. @@ -22,7 +22,7 @@ struct onak_config config = { /* * Options for the db2 file backend. */ - NULL, /* db2_dbpath */ + "/community/pgp-keyserver/db-copy", /* db2_dbpath */ /* * Options for the file backend. @@ -33,7 +33,7 @@ struct onak_config config = { * Options for the Postgres backend. */ NULL, /* pg_dbhost */ - NULL, /* pg_dbname */ - "noodles", /* pg_dbuser */ + "noodles", /* pg_dbname */ + NULL, /* pg_dbuser */ NULL, /* pg_dbpass */ }; diff --git a/onak_conf.h b/onak-conf.h similarity index 93% rename from onak_conf.h rename to onak-conf.h index 9e11167..dde7320 100644 --- a/onak_conf.h +++ b/onak-conf.h @@ -1,5 +1,5 @@ /* - * onak_conf.h - Routines related to runtime config. + * onak-conf.h - Routines related to runtime config. * * Jonathan McDowell <noodles@earth.li> * @@ -9,7 +9,7 @@ #ifndef __ONAK_CONF_H_ #define __ONAK_CONF_H_ -#define VERSION "0.0.2" +#define VERSION "0.0.3" /* * struct onak_config - Runtime configuration for onak. diff --git a/onak-mail.pl b/onak-mail.pl index 30e5b93..0f108f4 100755 --- a/onak-mail.pl +++ b/onak-mail.pl @@ -22,14 +22,16 @@ sub submitupdate { 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; } diff --git a/onak.c b/onak.c index 7b0f2f3..e7c7486 100644 --- a/onak.c +++ b/onak.c @@ -10,13 +10,17 @@ #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) @@ -31,11 +35,50 @@ 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[]) { @@ -43,28 +86,93 @@ 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; diff --git a/onak.gprof b/onak.gprof new file mode 100644 index 0000000..0e8b40b --- /dev/null +++ b/onak.gprof @@ -0,0 +1,295 @@ +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. + + 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. + + +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 diff --git a/onak.sql b/onak.sql index 6afa737..9fc033c 100644 --- a/onak.sql +++ b/onak.sql @@ -6,6 +6,7 @@ CREATE TABLE onak_keys ( 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, diff --git a/parsekey.c b/parsekey.c index f83e805..fbdde15 100644 --- a/parsekey.c +++ b/parsekey.c @@ -281,64 +281,66 @@ int read_openpgp_stream(int (*getchar_func)(void *ctx, size_t count, * 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; diff --git a/parsekey.h b/parsekey.h index 113f14a..2bfaf72 100644 --- a/parsekey.h +++ b/parsekey.h @@ -68,7 +68,8 @@ int read_openpgp_stream(int (*getchar_func)(void *ctx, size_t count, * 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); diff --git a/pathtest.c b/pathtest.c deleted file mode 100644 index 50dcdcf..0000000 --- a/pathtest.c +++ /dev/null @@ -1,65 +0,0 @@ -//#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; -} diff --git a/stats.c b/stats.c index 0e2662b..b302f09 100644 --- a/stats.c +++ b/stats.c @@ -6,6 +6,7 @@ * Copyright 2000-2002 Project Purple */ +#include <stdio.h> #include <stdlib.h> #include "hash.h" @@ -87,6 +88,7 @@ unsigned long findpath(struct stats_key *have, struct stats_key *want) nextkeys = NULL; curdegree++; } + fprintf(stderr, "Hash contains %ld keys.\n", hashelements()); } return count;