From: Jonathan McDowell Date: Mon, 30 Sep 2013 14:18:31 +0000 (+0100) Subject: Add initial wotsap file generation tool X-Git-Url: https://git.sommitrealweird.co.uk/onak.git/commitdiff_plain/e517c4f6effa3187dc46397e19aeada9574f7286 Add initial wotsap file generation tool Wotsap (http://www.lysator.liu.se/~jc/wotsap/) is a web of trust statistics and pathfinding tool. It takes a set of preformatted key data covering the primary UID and signatures on each key. This commit adds a tool which will generate the file data required for wotsap. These files still need ar/bzip2 run against them in order to be fed into wotsap, but are generated from the live keyring data. --- diff --git a/.gitignore b/.gitignore index d7e1c66..6a7382c 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ sixdegrees splitkeys stripkey testparse +wotsap tags .depend autom4te.cache diff --git a/Makefile.in b/Makefile.in index b5b8a55..ead45eb 100644 --- a/Makefile.in +++ b/Makefile.in @@ -16,7 +16,8 @@ MAKEDEPEND = $(CC) -MM prefix ?= @prefix@ exec_prefix ?= @exec_prefix@ -PROGS = add lookup hashquery gpgwww onak splitkeys onak-mail.pl stripkey +PROGS = add lookup hashquery gpgwww onak splitkeys onak-mail.pl stripkey \ + wotsap CORE_OBJS = armor.o charfuncs.o decodekey.o getcgi.o hash.o marshal.o \ keyid.o keyindex.o ll.o mem.o onak-conf.o parsekey.o sigcheck.o \ log.o photoid.o wordlist.o cleanup.o merge.o sendsync.o keyarray.o @@ -49,7 +50,7 @@ endif OBJS = stats.o cleankey.o $(CORE_OBJS) $(KEYDB_OBJ) all: .depend $(PROGS) testparse maxpath sixdegrees splitkeys onak.conf \ - $(BACKENDS) + wotsap $(BACKENDS) test: onak $(BACKENDS) @./runtests @@ -105,6 +106,10 @@ sixdegrees: sixdegrees.o $(OBJS) $(CC) $(LDFLAGS) -o sixdegrees sixdegrees.o $(OBJS) $(LIBS) \ $(PROGS_LDFLAGS_EXTRA) +wotsap: wotsap.o $(OBJS) + $(CC) $(LDFLAGS) -o wotsap wotsap.o $(OBJS) $(LIBS) \ + $(PROGS_LDFLAGS_EXTRA) + stripkey: stripkey.o $(OBJS) $(CC) $(LDFLAGS) -o stripkey stripkey.o $(OBJS) $(LIBS) \ $(PROGS_LDFLAGS_EXTRA) @@ -152,7 +157,7 @@ clean: $(RM) $(PROGS) $(OBJS) Makefile.bak testparse maxpath *.core core \ gpgwww.o add.o lookup.o main.o maxpath.o onak.o sixdegrees \ sixdegrees.o splitkeys.o stripkey.o onak.conf keyd.o \ - keydctl.o hashquery.o version.h \ + keydctl.o hashquery.o wotsap.o version.h \ TAGS cscope.out cscope.files \ $(foreach be,@BACKENDS@,keydb_$(be).o) *.so ifeq (x@KEYD@, xyes) diff --git a/wotsap.c b/wotsap.c new file mode 100644 index 0000000..339b949 --- /dev/null +++ b/wotsap.c @@ -0,0 +1,205 @@ +/* + * wotsap.c - Output a set of wotsap files from an onak keyring + * + * See: + * + * http://www.lysator.liu.se/~jc/wotsap/wotfileformat.txt + * + * for more details of the format. + * + * Copyright 2013 Jonathan McDowell + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include + +#include "hash.h" +#include "log.h" +#include "onak-conf.h" +#include "stats.h" +#include "version.h" + +static struct ll *sortkeyll(struct ll *keys) +{ + struct ll *newll, *tmp, **curobj; + struct stats_key *curkey, *toadd; + + newll = NULL; + while (keys) { + toadd = (struct stats_key *) keys->object; + curobj = &newll; + while (*curobj) { + curkey = (struct stats_key *) (*curobj)->object; + if (curkey->keyid >= toadd->keyid) { + break; + } + curobj = &((*curobj)->next); + } + + tmp = keys->next; + if (*curobj == NULL || curkey->keyid != toadd->keyid) { + keys->next = *curobj; + *curobj = keys; + } + keys = tmp; + } + return newll; +} + +static void output_key(FILE *names, FILE *keys, uint64_t keyid) +{ + fprintf(names, "%s\n", config.dbbackend->keyid2uid(keyid)); + fprintf(keys, "%c%c%c%c", (int) (keyid >> 24) & 0xFF, + (int) (keyid >> 16) & 0xFF, + (int) (keyid >> 8) & 0xFF, + (int) (keyid ) & 0xFF); +} + +static void wotsap(uint64_t keyid, char *dir) +{ + struct ll *pending, *sigll, *sigsave; + uint32_t curidx = 0; + struct stats_key *curkey, *addkey; + char *uid; + FILE *names, *keys, *sigs, *file; + char *tmppath; + uint32_t sigcount, sigentry; + + /* Length of dir + "/" + "signatures" + NUL */ + tmppath = malloc(strlen(dir) + 12); + + sprintf(tmppath, "%s/WOTVERSION", dir); + file = fopen(tmppath, "w"); + if (file == NULL) { + fprintf(stderr, "Couldn't open %s\n", tmppath); + return; + } + fprintf(file, "0.2\n"); + fclose(file); + + sprintf(tmppath, "%s/README", dir); + file = fopen(tmppath, "w"); + if (file == NULL) { + fprintf(stderr, "Couldn't open %s\n", tmppath); + return; + } + fprintf(file, "This is a Web of Trust archive.\n"); + fprintf(file, "The file format is documented at:\n"); + fprintf(file, " http://www.lysator.liu.se/~jc/wotsap/wotfileformat.txt\n\n"); + fprintf(file, "This file was generated by onak " ONAK_VERSION " \n"); + fclose(file); + + sprintf(tmppath, "%s/names", dir); + names = fopen(tmppath, "w"); + if (names == NULL) { + fprintf(stderr, "Couldn't open %s\n", tmppath); + return; + } + sprintf(tmppath, "%s/keys", dir); + keys = fopen(tmppath, "wb"); + if (keys == NULL) { + fprintf(stderr, "Couldn't open %s\n", tmppath); + return; + } + sprintf(tmppath, "%s/signatures", dir); + sigs = fopen(tmppath, "wb"); + if (sigs == NULL) { + fprintf(stderr, "Couldn't open %s\n", tmppath); + return; + } + free(tmppath); + + config.dbbackend->cached_getkeysigs(keyid); + curkey = findinhash(keyid); + curkey->colour = ++curidx; + pending = lladd(NULL, curkey); + + output_key(names, keys, curkey->keyid); + + while (pending != NULL) { + curkey = (struct stats_key *) pending->object; + sigll = config.dbbackend->cached_getkeysigs(curkey->keyid); + sigsave = sigll = sortkeyll(sigll); + sigcount = 0; + while (sigll != NULL) { + addkey = (struct stats_key *) sigll->object; + if (addkey->colour == 0) { + uid = config.dbbackend->keyid2uid(addkey->keyid); + if (uid != NULL) { + addkey->colour = ++curidx; + pending = lladdend(pending, addkey); + output_key(names, keys, addkey->keyid); + } + } + if (addkey->colour != 0) { + sigcount++; + } + sigll = sigll->next; + } + /* Now output the signatures */ + sigcount = htonl(sigcount); + fwrite(&sigcount, sizeof (sigcount), 1, sigs); + sigll = sigsave; + while (sigll != NULL) { + addkey = (struct stats_key *) sigll->object; + if (addkey->colour != 0) { + sigentry = addkey->colour - 1; + /* Pretend it's on the primary UID for now */ + sigentry |= 0x40000000; + sigentry = htonl(sigentry); + fwrite(&sigentry, sizeof (sigentry), 1, sigs); + } + sigll = sigll->next; + } + pending = pending->next; + } + + fclose(sigs); + fclose(keys); + fclose(names); +} + +int main(int argc, char *argv[]) +{ + int optchar; + char *configfile = NULL, *dir = NULL; + uint64_t keyid = 0x2DA8B985; + + while ((optchar = getopt(argc, argv, "c:")) != -1 ) { + switch (optchar) { + case 'c': + configfile = strdup(optarg); + break; + } + } + + if (optind < argc) { + dir = argv[optind]; + } + + readconfig(configfile); + initlogthing("wotsap", config.logfile); + config.dbbackend->initdb(true); + inithash(); + wotsap(config.dbbackend->getfullkeyid(keyid), dir ? dir : "."); + destroyhash(); + config.dbbackend->cleanupdb(); + cleanuplogthing(); + cleanupconfig(); +}