cscvs to tla changeset 138
authorJonathan McDowell <noodles@earth.li>
Mon, 31 May 2004 23:48:29 +0000 (23:48 +0000)
committerJonathan McDowell <noodles@earth.li>
Mon, 31 May 2004 23:48:29 +0000 (23:48 +0000)
Author: noodles
Date: 2004/05/31 14:16:49
Initial key cleaning routines; de-dupe key uids.

Makefile
add.c
cleankey.c [new file with mode: 0644]
cleankey.h [new file with mode: 0644]
lookup.c
merge.h
onak.c

index fee9fde24f9c2a039a3a6298879b9d47b1cbed20..199155243aeda23ba8ce1729c07c659479433b50 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 #
 # 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
@@ -19,10 +19,11 @@ PROGS = add lookup gpgwww onak splitkeys
 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
 
@@ -41,14 +42,15 @@ sixdegrees: sixdegrees.o $(OBJS)
 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 \
diff --git a/add.c b/add.c
index 32016b5a63d8a2ce782f44e24c0c392ad441c7ff..f15a145bd3c9e0ffb5138eaaaeb956490c4af6c1 100644 (file)
--- a/add.c
+++ b/add.c
@@ -5,7 +5,7 @@
  *
  * 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>
@@ -14,6 +14,7 @@
 #include <string.h>
 
 #include "armor.h"
+#include "cleankey.h"
 #include "charfuncs.h"
 #include "getcgi.h"
 #include "keydb.h"
@@ -70,6 +71,11 @@ int main(int argc, char *argv[])
                        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.",
diff --git a/cleankey.c b/cleankey.c
new file mode 100644 (file)
index 0000000..b236fa3
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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;
+}
diff --git a/cleankey.h b/cleankey.h
new file mode 100644 (file)
index 0000000..2b9d8ec
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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
index 123ec5f1ee936aa91f9750fe5928031b89793407..50426004a4a6074dcd2cb27d5efc775795e2bc2f 100644 (file)
--- a/lookup.c
+++ b/lookup.c
@@ -5,7 +5,7 @@
  *
  * 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>
@@ -17,6 +17,7 @@
 
 #include "armor.h"
 #include "charfuncs.h"
+#include "cleankey.h"
 #include "getcgi.h"
 #include "keydb.h"
 #include "keyindex.h"
@@ -164,6 +165,7 @@ int main(int argc, char *argv[])
                                        keyid);
                        if (fetch_key(keyid, &publickey, false)) {
                                puts("<pre>");
+                               cleankeys(publickey);
                                flatten_publickey(publickey,
                                                        &packets,
                                                        &list_end);
diff --git a/merge.h b/merge.h
index 3ec64f3ed98b824e5263e7b86b4e5eacec81a78b..da8534ff59232ceb31b688e4a72fbf3d80caad05 100644 (file)
--- a/merge.h
+++ b/merge.h
@@ -5,7 +5,7 @@
  *
  * 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__
@@ -39,4 +39,29 @@ int merge_keys(struct openpgp_publickey *a, struct openpgp_publickey *b);
  */
 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
diff --git a/onak.c b/onak.c
index 2a0376e4dbcdfa4a54a6427457912564c77408c1..15154c42c55248e34a56140eee7fad5a691d77b8 100644 (file)
--- a/onak.c
+++ b/onak.c
@@ -7,7 +7,7 @@
  * 
  * 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>
@@ -17,6 +17,7 @@
 
 #include "armor.h"
 #include "charfuncs.h"
+#include "cleankey.h"
 #include "keydb.h"
 #include "keyid.h"
 #include "keyindex.h"
@@ -57,14 +58,19 @@ void usage(void) {
        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[])
@@ -131,6 +137,10 @@ 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));
@@ -138,9 +148,15 @@ int main(int argc, char *argv[])
                                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;
                        }
@@ -157,6 +173,53 @@ int main(int argc, char *argv[])
                        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) {