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