Add support for displaying/retrieving by SKS hash to lookup and onak CLI
[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="
91                                         "0x%016" PRIX64 "&idx=%d\" alt=\""
92                                         "[photo id]\">\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 void display_skshash(struct openpgp_publickey *key, bool html)
188 {
189         int             i = 0;
190         struct skshash  hash;
191
192         get_skshash(key, &hash);
193         printf("      Key hash = ");
194         if (html) {
195                 printf("<a href=\"lookup?op=hget&search=");
196                 for (i = 0; i < sizeof(hash.hash); i++) {
197                         printf("%02X", hash.hash[i]);
198                 }
199                 printf("\">");
200         }
201         for (i = 0; i < sizeof(hash.hash); i++) {
202                 printf("%02X", hash.hash[i]);
203         }
204         if (html) {
205                 printf("</a>");
206         }
207         printf("\n");
208
209         return;
210 }
211
212 /**
213  *      key_index - List a set of OpenPGP keys.
214  *      @keys: The keys to display.
215  *      @verbose: Should we list sigs as well?
216  *      @fingerprint: List the fingerprint?
217  *      @html: Should the output be tailored for HTML?
218  *
219  *      This function takes a list of OpenPGP public keys and displays an index
220  *      of them. Useful for debugging or the keyserver Index function.
221  */
222 int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
223                         bool skshash, bool html)
224 {
225         struct openpgp_signedpacket_list        *curuid = NULL;
226         struct tm                               *created = NULL;
227         time_t                                   created_time = 0;
228         int                                      type = 0;
229         char                                     typech;
230         int                                      length = 0;
231         char                                     buf[1024];
232         uint64_t                                 keyid;
233
234         if (html) {
235                 puts("<pre>");
236         }
237         puts("Type   bits/keyID    Date       User ID");
238         while (keys != NULL) {
239                 created_time = (keys->publickey->data[1] << 24) +
240                                         (keys->publickey->data[2] << 16) +
241                                         (keys->publickey->data[3] << 8) +
242                                         keys->publickey->data[4];
243                 created = gmtime(&created_time);
244
245                 switch (keys->publickey->data[0]) {
246                 case 2:
247                 case 3:
248                         type = keys->publickey->data[7];
249                         length = (keys->publickey->data[8] << 8) +
250                                         keys->publickey->data[9];
251                         break;
252                 case 4:
253                         type = keys->publickey->data[5];
254                         length = (keys->publickey->data[6] << 8) +
255                                         keys->publickey->data[7];
256                         break;
257                 default:
258                         logthing(LOGTHING_ERROR, "Unknown key type: %d",
259                                 keys->publickey->data[0]);
260                 }
261                 
262                 keyid = get_keyid(keys);
263
264                 switch (type) {
265                 case 1:
266                         typech = 'R';
267                         break;
268                 case 16:
269                         typech = 'g';
270                         break;
271                 case 17:
272                         typech = 'D';
273                         break;
274                 case 20:
275                         typech = 'G';
276                         break;
277                 default:
278                         typech = '?';
279                         break;
280                 }
281
282                 if (html) {
283                         printf("pub  %5d%c/<a href=\"lookup?op=get&"
284                                 "search=%016" PRIX64 "\">%08" PRIX64
285                                 "</a> %04d/%02d/%02d ",
286                                 length,
287                                 typech,
288                                 keyid,
289                                 keyid & 0xFFFFFFFF,
290                                 created->tm_year + 1900,
291                                 created->tm_mon + 1,
292                                 created->tm_mday);
293                 } else {
294                         printf("pub  %5d%c/%08" PRIX64 " %04d/%02d/%02d ",
295                                 length,
296                                 typech,
297                                 keyid & 0xFFFFFFFF,
298                                 created->tm_year + 1900,
299                                 created->tm_mon + 1,
300                                 created->tm_mday);
301                 }
302
303                 curuid = keys->uids;
304                 if (curuid != NULL && curuid->packet->tag == 13) {
305                         snprintf(buf, 1023, "%.*s",
306                                 (int) curuid->packet->length,
307                                 curuid->packet->data);
308                         if (html) {
309                                 printf("<a href=\"lookup?op=vindex&"
310                                         "search=0x%016" PRIX64 "\">",
311                                         keyid);
312                         }
313                         printf("%s%s%s\n", 
314                                 (html) ? txt2html(buf) : buf,
315                                 (html) ? "</a>" : "",
316                                 (keys->revoked) ? " *** REVOKED ***" : "");
317                         if (skshash) {
318                                 display_skshash(keys, html);
319                         }
320                         if (fingerprint) {
321                                 display_fingerprint(keys);
322                         }
323                         if (verbose) {
324                                 list_sigs(curuid->sigs, html);
325                         }
326                         curuid = curuid->next;
327                 } else {
328                         printf("%s\n", 
329                                 (keys->revoked) ? "*** REVOKED ***": "");
330                         if (fingerprint) {
331                                 display_fingerprint(keys);
332                         }
333                 }
334
335                 list_uids(keyid, curuid, verbose, html);
336                 if (verbose) {
337                         list_subkeys(keys->subkeys, verbose, html);
338                 }
339
340                 keys = keys->next;
341         }
342
343         if (html) {
344                 puts("</pre>");
345         }
346
347         return 0;
348 }
349
350 /**
351  *      mrkey_index - List a set of OpenPGP keys in the MRHKP format.
352  *      @keys: The keys to display.
353  *
354  *      This function takes a list of OpenPGP public keys and displays a
355  *      machine readable list of them.
356  */
357 int mrkey_index(struct openpgp_publickey *keys)
358 {
359         struct openpgp_signedpacket_list        *curuid = NULL;
360         time_t                                   created_time = 0;
361         int                                      type = 0;
362         int                                      length = 0;
363         int                                      i = 0;
364         size_t                                   fplength = 0;
365         unsigned char                            fp[20];
366         int                                      c;
367
368         while (keys != NULL) {
369                 created_time = (keys->publickey->data[1] << 24) +
370                                         (keys->publickey->data[2] << 16) +
371                                         (keys->publickey->data[3] << 8) +
372                                         keys->publickey->data[4];
373
374                 printf("pub:");
375
376                 switch (keys->publickey->data[0]) {
377                 case 2:
378                 case 3:
379                         printf("%016" PRIX64, get_keyid(keys));
380                         type = keys->publickey->data[7];
381                         length = (keys->publickey->data[8] << 8) +
382                                         keys->publickey->data[9];
383                         break;
384                 case 4:
385                         (void) get_fingerprint(keys->publickey, fp, &fplength);
386
387                         for (i = 0; i < fplength; i++) {
388                                 printf("%02X", fp[i]);
389                         }
390
391                         type = keys->publickey->data[5];
392                         length = (keys->publickey->data[6] << 8) +
393                                         keys->publickey->data[7];
394                         break;
395                 default:
396                         logthing(LOGTHING_ERROR, "Unknown key type: %d",
397                                 keys->publickey->data[0]);
398                 }
399
400                 printf(":%d:%d:%ld::%s\n",
401                         type,
402                         length,
403                         created_time,
404                         (keys->revoked) ? "r" : "");
405         
406                 for (curuid = keys->uids; curuid != NULL;
407                          curuid = curuid->next) {
408                 
409                         if (curuid->packet->tag == 13) {
410                                 printf("uid:");
411                                 for (i = 0; i < (int) curuid->packet->length;
412                                                 i++) {
413                                         c = curuid->packet->data[i];
414                                         if (c == '%') {
415                                                 putchar('%');
416                                                 putchar(c);
417                                         } else if (c == ':' || c > 127) {
418                                                 printf("%%%X", c);
419                                         } else {
420                                                 putchar(c);
421                                         }
422                                 }
423                                 printf("\n");
424                         }
425                 }
426                 keys = keys->next;
427         }
428         return 0;
429 }