#
# Makefile for onak.
#
-# $Id: Makefile,v 1.21 2004/05/27 22:02:05 noodles Exp $
+# $Id: Makefile,v 1.22 2004/05/31 14:16:49 noodles Exp $
#
CC = gcc
CORE_OBJS = armor.o charfuncs.o decodekey.o getcgi.o hash.o keydb_$(DBTYPE).o \
keyid.o keyindex.o ll.o mem.o onak-conf.o parsekey.o sha.o md5.o \
log.o photoid.o wordlist.o
-OBJS = merge.o stats.o sendsync.o $(CORE_OBJS)
+OBJS = merge.o stats.o sendsync.o cleankey.o $(CORE_OBJS)
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 \
- gpgwww.c onak-conf.c charfuncs.c sendsync.c log.c photoid.c wordlist.c
+ gpgwww.c onak-conf.c charfuncs.c sendsync.c log.c photoid.c \
+ wordlist.c cleankey.c
all: .depend $(PROGS) testparse maxpath sixdegrees splitkeys
gpgwww: gpgwww.o $(OBJS)
$(LINK) -o gpgwww gpgwww.o $(OBJS) $(LIBS)
-lookup: lookup.o $(CORE_OBJS)
- $(LINK) -o lookup lookup.o $(CORE_OBJS) $(LIBS)
+lookup: lookup.o cleankey.o merge.o $(CORE_OBJS)
+ $(LINK) -o lookup lookup.o cleankey.o merge.o $(CORE_OBJS) $(LIBS)
-add: add.o merge.o sendsync.o $(CORE_OBJS)
- $(LINK) -o add add.o merge.o sendsync.o $(CORE_OBJS) $(LIBS)
+add: add.o cleankey.o merge.o sendsync.o $(CORE_OBJS)
+ $(LINK) -o add add.o cleankey.o merge.o sendsync.o $(CORE_OBJS) $(LIBS)
-onak: onak.o merge.o $(CORE_OBJS)
- $(LINK) $(LDFLAGS) -o onak onak.o merge.o $(CORE_OBJS) $(LIBS)
+onak: onak.o merge.o cleankey.o $(CORE_OBJS)
+ $(LINK) $(LDFLAGS) -o onak onak.o merge.o cleankey.o $(CORE_OBJS) \
+ $(LIBS)
clean:
rm -f $(PROGS) $(OBJS) Makefile.bak testparse maxpath *.core core \
*
* Copyright 2002 Project Purple
*
- * $Id: add.c,v 1.14 2004/05/26 21:20:05 noodles Exp $
+ * $Id: add.c,v 1.15 2004/05/31 14:16:49 noodles Exp $
*/
#include <errno.h>
#include <string.h>
#include "armor.h"
+#include "cleankey.h"
#include "charfuncs.h"
#include "getcgi.h"
#include "keydb.h"
fclose(stdout);
fclose(stderr);
initdb(false);
+
+ count = cleankeys(keys);
+ logthing(LOGTHING_INFO, "%d keys cleaned.",
+ count);
+
count = update_keys(&keys);
printf("Got %d new keys.\n", count);
logthing(LOGTHING_NOTICE, "Got %d new keys.",
--- /dev/null
+/*
+ * cleankey.c - Routines to look for common key problems and clean them up.
+ *
+ * Jonathan McDowell <noodles@earth.li>
+ *
+ * Copyright 2004 Project Purple
+ *
+ * $Id: cleankey.c,v 1.1 2004/05/31 14:16:49 noodles Exp $
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cleankey.h"
+#include "keystructs.h"
+#include "mem.h"
+#include "merge.h"
+#include "log.h"
+
+/**
+ * dedupuids - Merge duplicate uids on a key.
+ * @key: The key to de-dup uids on.
+ *
+ * This function attempts to merge duplicate IDs on a key. It returns 0
+ * if the key is unchanged, otherwise the number of dups merged.
+ */
+int dedupuids(struct openpgp_publickey *key)
+{
+ struct openpgp_signedpacket_list *curuid = NULL;
+ struct openpgp_signedpacket_list *dup = NULL;
+ struct openpgp_signedpacket_list *tmp = NULL;
+ int merged = 0;
+
+ assert(key != NULL);
+ curuid = key->uids;
+ while (curuid != NULL) {
+ dup = find_signed_packet(curuid->next, curuid->packet);
+ while (dup != NULL) {
+ logthing(LOGTHING_INFO, "Found duplicate uid: %.*s",
+ curuid->packet->length,
+ curuid->packet->data);
+ merged++;
+ merge_packet_sigs(curuid, dup);
+ /*
+ * Remove the duplicate uid.
+ */
+ tmp = curuid;
+ while (tmp != NULL && tmp->next != dup) {
+ tmp = tmp->next;
+ }
+ assert(tmp != NULL);
+ tmp->next = dup->next;
+ dup->next = NULL;
+ free_signedpacket_list(dup);
+
+ dup = find_signed_packet(curuid->next, curuid->packet);
+ }
+ curuid = curuid->next;
+ }
+
+ return merged;
+}
+
+/**
+ * cleankeys - Apply all available cleaning options on a list of keys.
+ * @keys: The list of keys to clean.
+ *
+ * Applies all the cleaning options we can (eg duplicate key ids) to a
+ * list of keys. Returns 0 if no changes were made, otherwise the number
+ * of keys cleaned.
+ */
+int cleankeys(struct openpgp_publickey *keys)
+{
+ int changed = 0;
+
+ while (keys != NULL) {
+ if (dedupuids(keys) > 0) {
+ changed++;
+ }
+ keys = keys->next;
+ }
+
+ return changed;
+}
--- /dev/null
+/*
+ * cleankey.h - Routines to look for common key problems and clean them up.
+ *
+ * Jonathan McDowell <noodles@earth.li>
+ *
+ * Copyright 2004 Project Purple
+ *
+ * $Id: cleankey.h,v 1.1 2004/05/31 14:16:49 noodles Exp $
+ */
+
+#ifndef __CLEANKEY_H__
+#define __CLEANKEY_H__
+
+#include "keystructs.h"
+
+/**
+ * cleankeys - Apply all available cleaning options on a list of keys.
+ * @publickey: The list of keys to clean.
+ *
+ * Applies all the cleaning options we can (eg duplicate key ids) to a
+ * list of keys. Returns 0 if no changes were made, otherwise the number
+ * of keys cleaned.
+ */
+int cleankeys(struct openpgp_publickey *keys);
+
+#endif
*
* Copyright 2002 Project Purple
*
- * $Id: lookup.c,v 1.16 2004/05/27 21:58:18 noodles Exp $
+ * $Id: lookup.c,v 1.17 2004/05/31 14:16:49 noodles Exp $
*/
#include <inttypes.h>
#include "armor.h"
#include "charfuncs.h"
+#include "cleankey.h"
#include "getcgi.h"
#include "keydb.h"
#include "keyindex.h"
keyid);
if (fetch_key(keyid, &publickey, false)) {
puts("<pre>");
+ cleankeys(publickey);
flatten_publickey(publickey,
&packets,
&list_end);
*
* Copyright 2002 Project Purple
*
- * $Id: merge.h,v 1.5 2003/06/04 20:57:11 noodles Exp $
+ * $Id: merge.h,v 1.6 2004/05/31 14:16:49 noodles Exp $
*/
#ifndef __MERGE_H__
*/
int update_keys(struct openpgp_publickey **keys);
+/**
+ * get_signed_packet - Gets a signed packet from a list.
+ * @packet_list: The list of packets to look in.
+ * @packet: The packet to look for.
+ *
+ * Walks through the signedpacket_list looking for the supplied packet and
+ * returns it if found. Otherwise returns NULL.
+ */
+struct openpgp_signedpacket_list *find_signed_packet(
+ struct openpgp_signedpacket_list *packet_list,
+ struct openpgp_packet *packet);
+
+/**
+ * merge_packet_sigs - Takes 2 signed packets and merges their sigs.
+ * @old: The old signed packet.
+ * @new: The new signed packet.
+ *
+ * Takes 2 signed packet list structures and the sigs of the packets on
+ * the head of these structures. These packets must both be the same and
+ * the fully merged structure is returned in old and the minimal
+ * difference to get from old to new in new.
+ */
+int merge_packet_sigs(struct openpgp_signedpacket_list *old,
+ struct openpgp_signedpacket_list *new);
+
#endif
*
* Copyright 2002 Project Purple
*
- * $Id: onak.c,v 1.21 2004/05/27 21:58:18 noodles Exp $
+ * $Id: onak.c,v 1.22 2004/05/31 14:16:49 noodles Exp $
*/
#include <stdio.h>
#include "armor.h"
#include "charfuncs.h"
+#include "cleankey.h"
#include "keydb.h"
#include "keyid.h"
#include "keyindex.h"
puts("Usage:\n");
puts("\tonak [options] <command> <parameters>\n");
puts("\tCommands:\n");
- puts("\tadd - read armored OpenPGP keys from stdin and add to the"
+ puts("\tadd - read armored OpenPGP keys from stdin and add to the"
" keyserver");
- puts("\tdelete - delete a given key from the keyserver");
- puts("\tdump - dump all the keys from the keyserver to a file or"
- " files\n\t starting keydump*");
- puts("\tget - retrieves the key requested from the keyserver");
- puts("\tindex - search for a key and list it");
- puts("\tvindex - search for a key and list it and its signatures");
+ puts("\tclean - read armored OpenPGP keys from stdin, run the "
+ " cleaning\n\t routines against them and dump to"
+ " stdout");
+ puts("\tdelete - delete a given key from the keyserver");
+ puts("\tdump - dump all the keys from the keyserver to a file or"
+ " files\n\t starting keydump*");
+ puts("\tget - retrieves the key requested from the keyserver");
+ puts("\tgetphoto - retrieves the first photoid on the given key and"
+ " dumps to\n\t stdout");
+ 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[])
logthing(LOGTHING_INFO, "Finished reading %d keys.",
result);
+ result = cleankeys(keys);
+ logthing(LOGTHING_INFO, "%d keys cleaned.",
+ result);
+
initdb(false);
logthing(LOGTHING_NOTICE, "Got %d new keys.",
update_keys(&keys));
flatten_publickey(keys,
&packets,
&list_end);
- armor_openpgp_stream(stdout_putchar,
- NULL,
- packets);
+ if (binary) {
+ write_openpgp_stream(stdout_putchar,
+ NULL,
+ packets);
+ } else {
+ armor_openpgp_stream(stdout_putchar,
+ NULL,
+ packets);
+ }
free_packet_list(packets);
packets = NULL;
}
rc = 1;
logthing(LOGTHING_NOTICE, "No changes.");
}
+ } else if (!strcmp("clean", argv[optind])) {
+ if (binary) {
+ result = read_openpgp_stream(stdin_getchar, NULL,
+ &packets, 0);
+ logthing(LOGTHING_INFO,
+ "read_openpgp_stream: %d", result);
+ } else {
+ dearmor_openpgp_stream(stdin_getchar, NULL, &packets);
+ }
+
+ if (packets != NULL) {
+ result = parse_keys(packets, &keys);
+ free_packet_list(packets);
+ packets = NULL;
+ logthing(LOGTHING_INFO, "Finished reading %d keys.",
+ result);
+
+ if (keys != NULL) {
+ result = cleankeys(keys);
+ logthing(LOGTHING_INFO, "%d keys cleaned.",
+ result);
+
+ flatten_publickey(keys,
+ &packets,
+ &list_end);
+
+ if (binary) {
+ write_openpgp_stream(stdout_putchar,
+ NULL,
+ packets);
+ } else {
+ armor_openpgp_stream(stdout_putchar,
+ NULL,
+ packets);
+ }
+ free_packet_list(packets);
+ packets = NULL;
+ }
+ } else {
+ rc = 1;
+ logthing(LOGTHING_NOTICE, "No keys read.");
+ }
+
+ if (keys != NULL) {
+ free_publickey(keys);
+ keys = NULL;
+ }
} else if ((argc - optind) == 2) {
search = argv[optind+1];
if (search != NULL) {