* Import keyanalyze into signing-party. Thanks to Matthew Wilcox for the
[pgp-tools.git] / keyanalyze / process_keys.c
1 /*
2 * Does preprocessing of keyrings for an intermediate file to be monged
3 * by keyanalyze.
4 *
5 * Copyright (c)2001 Thomas Roessler <roessler@does-not-exist.org>
6 *
7 * This program can be freely distributed under the GNU General Public
8 * License.
9 */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include <unistd.h>
16 #include <getopt.h>
17
18 static int DontRequireSelfSig = 0;
19
20 #define IDBUF 17
21
22 struct sig
23 {
24 struct sig *next;
25 char id[IDBUF];
26 };
27
28 struct uid
29 {
30 struct uid *next;
31 struct sig *sigs;
32 unsigned self : 1;
33 };
34
35 struct key
36 {
37 char id[IDBUF];
38 struct uid *uids;
39 unsigned rev : 1;
40 };
41
42 static void free_sig (struct sig **sigpp)
43 {
44 struct sig *sigp, *q;
45
46 if (!sigpp || !*sigpp)
47 return;
48
49 for (sigp = *sigpp; sigp; sigp = q)
50 {
51 q = sigp->next;
52 free (sigp);
53 }
54
55 *sigpp = NULL;
56 }
57
58 static void free_uid (struct uid **uidpp)
59 {
60 struct uid *uidp, *q;
61
62 if (!uidpp || !*uidpp)
63 return;
64
65 for (uidp = *uidpp; uidp; uidp = q)
66 {
67 q = uidp->next;
68 free (uidp);
69 }
70
71 *uidpp = NULL;
72 }
73
74 static void free_key (struct key **keypp)
75 {
76 struct key *keyp;
77
78 if (!keypp || !(keyp = *keypp))
79 return;
80
81 free_uid (&keyp->uids);
82
83 free (keyp);
84 *keypp = NULL;
85 }
86
87 #define new_sig() calloc (sizeof (struct sig), 1)
88 #define new_uid() calloc (sizeof (struct uid), 1)
89 #define new_key() calloc (sizeof (struct key), 1)
90
91 /* Is a signature with this ID present? */
92
93 static int check_sig_id (struct sig *signatures, char *id)
94 {
95 struct sig *s;
96
97 for (s = signatures; s; s = s->next)
98 if (!strcmp (s->id, id))
99 return 1;
100
101 return 0;
102 }
103
104 /* Is this user ID self-signed? */
105
106 static int check_selfsig (struct uid *uid, struct key *key)
107 {
108 return (uid->self = check_sig_id (uid->sigs, key->id));
109 }
110
111 /* Append a list of signatures to a different list of signatures */
112
113 static void join_siglists (struct sig **sig_d, struct sig **sig_s)
114 {
115 while (*sig_d)
116 sig_d = &((*sig_d)->next);
117
118 *sig_d = *sig_s;
119 *sig_s = NULL;
120 }
121
122 /* Clean up a list of signatures - inefficient! */
123
124 static void cleanup_siglist (struct sig **sig, char *keyid)
125 {
126 struct sig **last = sig;
127 struct sig *p, *q;
128
129 for (p = *sig; p; p = q)
130 {
131 q = p->next;
132 if (!strcmp (keyid, p->id) || check_sig_id (p->next, p->id))
133 {
134 *last = p->next;
135 p->next = NULL;
136 free_sig (&p);
137 }
138 else
139 last = &p->next;
140 }
141 }
142
143 /* print the information gathered */
144
145 static void do_key (struct key *k)
146 {
147 struct sig *interesting_signatures = NULL, *sigp;
148 struct uid *uidp;
149
150 if (k->rev)
151 return;
152
153 for (uidp = k->uids; uidp; uidp = uidp->next)
154 if (DontRequireSelfSig || check_selfsig (uidp, k))
155 join_siglists (&interesting_signatures, &uidp->sigs);
156
157 cleanup_siglist (&interesting_signatures, k->id);
158 if (interesting_signatures)
159 {
160 printf ("p%s\n", k->id);
161 for (sigp = interesting_signatures; sigp; sigp = sigp->next)
162 printf ("s%s\n", sigp->id);
163 }
164
165 free_sig (&interesting_signatures);
166 free_uid (&k->uids);
167 }
168
169 /* the main routine */
170
171 int main (int argc, char *argv[])
172 {
173 char buff[1024];
174 char *s;
175
176 struct sig **lastsig = NULL;
177 struct uid **lastuid = NULL;
178 struct key *k = new_key();
179
180 lastuid = &k->uids;
181
182 if (argc == 2 && !strcmp (argv[1], "-S"))
183 DontRequireSelfSig = 1;
184
185 while (fgets (buff, sizeof (buff), stdin))
186 {
187 if ((s = strtok (buff, " \t\r\n")))
188 {
189 if (!strcmp (s, "pub"))
190 {
191 do_key (k);
192 k->rev = 0;
193 k->uids = new_uid();
194
195 lastuid = &k->uids->next;
196 lastsig = &k->uids->sigs;
197
198 sprintf (k->id, "%.16s", strtok (NULL, " \t\r\n"));
199 }
200 else if (!strcmp (s, "rev"))
201 k->rev = 1;
202 else if (!strcmp (s, "uid"))
203 {
204 struct uid *uid = *lastuid = new_uid();
205 lastuid = &(*lastuid)->next;
206 lastsig = &uid->sigs;
207 }
208 else if (!strcmp (s, "sig"))
209 {
210 struct sig *sig = *lastsig = new_sig();
211 lastsig = &sig->next;
212 sprintf (sig->id, "%.16s", strtok (NULL, " \t\r\n"));
213 }
214 }
215 }
216
217 do_key (k);
218
219 return 0;
220 }