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