Handle signature revokations better.
[onak.git] / keyindex.c
1 /*
2  * keyindex.c - Routines to list an OpenPGP key.
3  *
4  * Jonathan McDowell <noodles@earth.li>
5  *
6  * Copyright 2002-2005 Project Purple
7  */
8
9 #include <inttypes.h>
10 #include <stdbool.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <time.h>
15
16 #include "decodekey.h"
17 #include "getcgi.h"
18 #include "hash.h"
19 #include "keydb.h"
20 #include "keyid.h"
21 #include "keyindex.h"
22 #include "keystructs.h"
23 #include "log.h"
24
25 int list_sigs(struct openpgp_packet_list *sigs, bool html)
26 {
27         char *uid = NULL;
28         uint64_t sigid = 0;
29         char *sig = NULL;
30
31         while (sigs != NULL) {
32                 sigid = sig_keyid(sigs->packet);
33                 uid = keyid2uid(sigid);
34                 if (sigs->packet->data[0] == 4 &&
35                                 sigs->packet->data[1] == 0x30) {
36                         /* It's a Type 4 sig revocation */
37                         sig = "rev";
38                 } else {
39                         sig = "sig";
40                 }
41                 if (html && uid != NULL) {
42                         printf("%s         <a href=\"lookup?op=get&"
43                                 "search=%08llX\">%08llX</a>             "
44                                 "<a href=\"lookup?op=vindex&search=0x%08llX\">"
45                                 "%s</a>\n",
46                                 sig,
47                                 sigid & 0xFFFFFFFF,
48                                 sigid & 0xFFFFFFFF,
49                                 sigid & 0xFFFFFFFF,
50                                 txt2html(uid));
51                 } else if (html && uid == NULL) {
52                         printf("%s         %08llX             "
53                                 "[User id not found]\n",
54                                 sig,
55                                 sigid & 0xFFFFFFFF);
56                 } else {
57                         printf("%s         %08llX"
58                                 "             %s\n",
59                                 sig,
60                                 sigid & 0xFFFFFFFF,
61                                 (uid != NULL) ? uid :
62                                 "[User id not found]");
63                 }
64                 if (uid != NULL) {
65                         free(uid);
66                         uid = NULL;
67                 }
68                 sigs = sigs->next;
69         }
70
71         return 0;
72 }
73
74 int list_uids(uint64_t keyid, struct openpgp_signedpacket_list *uids,
75                 bool verbose, bool html)
76 {
77         char buf[1024];
78         int  imgindx = 0;
79
80         while (uids != NULL) {
81                 if (uids->packet->tag == 13) {
82                         snprintf(buf, 1023, "%.*s",
83                                 (int) uids->packet->length,
84                                 uids->packet->data);
85                         printf("                                %s\n",
86                                 (html) ? txt2html(buf) : buf);
87                 } else if (uids->packet->tag == 17) {
88                         printf("                                ");
89                         if (html) {
90                                 printf("<img src=\"lookup?op=photo&search=0x%llX&idx=%d\" alt=\"[photo id]\">\n",
91                                                 keyid,
92                                                 imgindx);
93                                 imgindx++;
94                         } else {
95                                 printf("[photo id]\n");
96                         }
97                 }
98                 if (verbose) {
99                         list_sigs(uids->sigs, html);
100                 }
101                 uids = uids->next;
102         }
103
104         return 0;
105 }
106
107 int list_subkeys(struct openpgp_signedpacket_list *subkeys, bool verbose,
108                 bool html)
109 {
110         struct tm       *created = NULL;
111         time_t          created_time = 0;
112         int             type = 0;
113         int             length = 0;
114
115         while (subkeys != NULL) {
116                 if (subkeys->packet->tag == 14) {
117
118                         created_time = (subkeys->packet->data[1] << 24) +
119                                         (subkeys->packet->data[2] << 16) +
120                                         (subkeys->packet->data[3] << 8) +
121                                         subkeys->packet->data[4];
122                         created = gmtime(&created_time);
123
124                         switch (subkeys->packet->data[0]) {
125                         case 2:
126                         case 3:
127                                 type = subkeys->packet->data[7];
128                                 length = (subkeys->packet->data[8] << 8) +
129                                         subkeys->packet->data[9];
130                                 break;
131                         case 4:
132                                 type = subkeys->packet->data[5];
133                                 length = (subkeys->packet->data[6] << 8) +
134                                         subkeys->packet->data[7];
135                                 break;
136                         default:
137                                 logthing(LOGTHING_ERROR,
138                                         "Unknown key type: %d",
139                                         subkeys->packet->data[0]);
140                         }
141                 
142                         printf("sub  %5d%c/%08X %04d/%02d/%02d\n",
143                                 length,
144                                 (type == 1) ? 'R' : ((type == 16) ? 'g' : 
145                                         ((type == 17) ? 'D' : '?')),
146                                 (uint32_t) (get_packetid(subkeys->packet) &
147                                             0xFFFFFFFF),
148                                 created->tm_year + 1900,
149                                 created->tm_mon + 1,
150                                 created->tm_mday);
151
152                 }
153                 if (verbose) {
154                         list_sigs(subkeys->sigs, html);
155                 }
156                 subkeys = subkeys->next;
157         }
158
159         return 0;
160 }
161
162 void display_fingerprint(struct openpgp_publickey *key)
163 {
164         int             i = 0;
165         size_t          length = 0;
166         unsigned char   fp[20];
167
168         get_fingerprint(key->publickey, fp, &length);
169         printf("      Key fingerprint =");
170         for (i = 0; i < length; i++) {
171                 if ((length == 16) ||
172                         (i % 2 == 0)) {
173                         printf(" ");
174                 }
175                 printf("%02X", fp[i]);
176                 if ((i * 2) == length) {
177                         printf(" ");
178                 }
179         }
180         printf("\n");
181
182         return;
183 }
184
185 /**
186  *      key_index - List a set of OpenPGP keys.
187  *      @keys: The keys to display.
188  *      @verbose: Should we list sigs as well?
189  *      @fingerprint: List the fingerprint?
190  *      @html: Should the output be tailored for HTML?
191  *
192  *      This function takes a list of OpenPGP public keys and displays an index
193  *      of them. Useful for debugging or the keyserver Index function.
194  */
195 int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
196                         bool html)
197 {
198         struct openpgp_signedpacket_list        *curuid = NULL;
199         struct tm                               *created = NULL;
200         time_t                                   created_time = 0;
201         int                                      type = 0;
202         int                                      length = 0;
203         char                                     buf[1024];
204         uint64_t                                 keyid;
205
206         if (html) {
207                 puts("<pre>");
208         }
209         puts("Type   bits/keyID    Date       User ID");
210         while (keys != NULL) {
211                 created_time = (keys->publickey->data[1] << 24) +
212                                         (keys->publickey->data[2] << 16) +
213                                         (keys->publickey->data[3] << 8) +
214                                         keys->publickey->data[4];
215                 created = gmtime(&created_time);
216
217                 switch (keys->publickey->data[0]) {
218                 case 2:
219                 case 3:
220                         type = keys->publickey->data[7];
221                         length = (keys->publickey->data[8] << 8) +
222                                         keys->publickey->data[9];
223                         break;
224                 case 4:
225                         type = keys->publickey->data[5];
226                         length = (keys->publickey->data[6] << 8) +
227                                         keys->publickey->data[7];
228                         break;
229                 default:
230                         logthing(LOGTHING_ERROR, "Unknown key type: %d",
231                                 keys->publickey->data[0]);
232                 }
233                 
234                 keyid = (get_keyid(keys) & 0xFFFFFFFF);
235
236                 if (html) {
237                         printf("pub  %5d%c/<a href=\"lookup?op=get&"
238                                 "search=%08X\">%08X</a> %04d/%02d/%02d ",
239                                 length,
240                                 (type == 1) ? 'R' : ((type == 16) ? 'g' : 
241                                         ((type == 17) ? 'D' : '?')),
242                                 (uint32_t) keyid,
243                                 (uint32_t) keyid,
244                                 created->tm_year + 1900,
245                                 created->tm_mon + 1,
246                                 created->tm_mday);
247                 } else {
248                         printf("pub  %5d%c/%08X %04d/%02d/%02d ",
249                                 length,
250                                 (type == 1) ? 'R' : ((type == 16) ? 'g' : 
251                                         ((type == 17) ? 'D' : '?')),
252                                 (uint32_t) keyid,
253                                 created->tm_year + 1900,
254                                 created->tm_mon + 1,
255                                 created->tm_mday);
256                 }
257
258                 curuid = keys->uids;
259                 if (curuid != NULL && curuid->packet->tag == 13) {
260                         snprintf(buf, 1023, "%.*s",
261                                 (int) curuid->packet->length,
262                                 curuid->packet->data);
263                         if (html) {
264                                 printf("<a href=\"lookup?op=vindex&"
265                                         "search=0x%08X\">",
266                                         (uint32_t) keyid);
267                         }
268                         printf("%s%s%s\n", 
269                                 (html) ? txt2html(buf) : buf,
270                                 (html) ? "</a>" : "",
271                                 (keys->revocations == NULL) ? "" :
272                                         " *** REVOKED ***");
273                         if (fingerprint) {
274                                 display_fingerprint(keys);
275                         }
276                         if (verbose) {
277                                 list_sigs(curuid->sigs, html);
278                         }
279                         curuid = curuid->next;
280                 } else {
281                         printf("%s\n", 
282                                 (keys->revocations == NULL) ? "" :
283                                         "*** REVOKED ***");
284                         if (fingerprint) {
285                                 display_fingerprint(keys);
286                         }
287                 }
288
289                 list_uids(keyid, curuid, verbose, html);
290                 if (verbose) {
291                         list_subkeys(keys->subkeys, verbose, html);
292                 }
293
294                 keys = keys->next;
295         }
296
297         if (html) {
298                 puts("</pre>");
299         }
300
301         return 0;
302 }
303
304 /**
305  *      mrkey_index - List a set of OpenPGP keys in the MRHKP format.
306  *      @keys: The keys to display.
307  *
308  *      This function takes a list of OpenPGP public keys and displays a
309  *      machine readable list of them.
310  */
311 int mrkey_index(struct openpgp_publickey *keys)
312 {
313         struct openpgp_signedpacket_list        *curuid = NULL;
314         time_t                                   created_time = 0;
315         int                                      type = 0;
316         int                                      length = 0;
317         int                                      i = 0;
318         size_t                                   fplength = 0;
319         unsigned char                            fp[20];
320
321         while (keys != NULL) {
322                 created_time = (keys->publickey->data[1] << 24) +
323                                         (keys->publickey->data[2] << 16) +
324                                         (keys->publickey->data[3] << 8) +
325                                         keys->publickey->data[4];
326
327                 printf("pub:");
328
329                 switch (keys->publickey->data[0]) {
330                 case 2:
331                 case 3:
332                         printf("%016llX", get_keyid(keys));
333                         type = keys->publickey->data[7];
334                         length = (keys->publickey->data[8] << 8) +
335                                         keys->publickey->data[9];
336                         break;
337                 case 4:
338                         (void) get_fingerprint(keys->publickey, fp, &fplength);
339
340                         for (i = 0; i < fplength; i++) {
341                                 printf("%02X", fp[i]);
342                         }
343
344                         type = keys->publickey->data[5];
345                         length = (keys->publickey->data[6] << 8) +
346                                         keys->publickey->data[7];
347                         break;
348                 default:
349                         logthing(LOGTHING_ERROR, "Unknown key type: %d",
350                                 keys->publickey->data[0]);
351                 }
352
353                 printf(":%d:%d:%ld::%s\n",
354                         type,
355                         length,
356                         created_time,
357                         (keys->revocations == NULL) ? "" : "r");
358         
359                 for (curuid = keys->uids; curuid != NULL;
360                          curuid = curuid->next) {
361                 
362                         if (curuid->packet->tag == 13) {
363                                 printf("uid:%.*s\n",
364                                         (int) curuid->packet->length,
365                                         curuid->packet->data);
366                         }
367                 }
368                 keys = keys->next;
369         }
370         return 0;
371 }