Use C99 uint32_t rather than u_int32_t
[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  * This program is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * this program; if not, write to the Free Software Foundation, Inc., 51
17  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #include <inttypes.h>
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26
27 #include "decodekey.h"
28 #include "getcgi.h"
29 #include "hash.h"
30 #include "keydb.h"
31 #include "keyid.h"
32 #include "keyindex.h"
33 #include "keystructs.h"
34 #include "log.h"
35 #include "onak-conf.h"
36 #include "openpgp.h"
37
38 int list_sigs(struct openpgp_packet_list *sigs, bool html)
39 {
40         char *uid = NULL;
41         uint64_t sigid = 0;
42         char *sig = NULL;
43
44         while (sigs != NULL) {
45                 sigid = sig_keyid(sigs->packet);
46                 uid = config.dbbackend->keyid2uid(sigid);
47                 if (sigs->packet->data[0] == 4 &&
48                                 sigs->packet->data[1] == 0x30) {
49                         /* It's a Type 4 sig revocation */
50                         sig = "rev";
51                 } else {
52                         sig = "sig";
53                 }
54                 if (html && uid != NULL) {
55                         printf("%s         <a href=\"lookup?op=get&"
56                                 "search=%016" PRIX64 "\">%08" PRIX64
57                                 "</a>             "
58                                 "<a href=\"lookup?op=vindex&search=0x%016"
59                                 PRIX64 "\">%s</a>\n",
60                                 sig,
61                                 sigid,
62                                 sigid & 0xFFFFFFFF,
63                                 sigid,
64                                 txt2html(uid));
65                 } else if (html && uid == NULL) {
66                         printf("%s         %08" PRIX64 "             "
67                                 "[User id not found]\n",
68                                 sig,
69                                 sigid & 0xFFFFFFFF);
70                 } else {
71                         printf("%s         %08" PRIX64
72                                 "             %s\n",
73                                 sig,
74                                 sigid & 0xFFFFFFFF,
75                                 (uid != NULL) ? uid :
76                                 "[User id not found]");
77                 }
78                 if (uid != NULL) {
79                         free(uid);
80                         uid = NULL;
81                 }
82                 sigs = sigs->next;
83         }
84
85         return 0;
86 }
87
88 int list_uids(uint64_t keyid, struct openpgp_signedpacket_list *uids,
89                 bool verbose, bool html)
90 {
91         char buf[1024];
92         int  imgindx = 0;
93
94         while (uids != NULL) {
95                 if (uids->packet->tag == OPENPGP_PACKET_UID) {
96                         snprintf(buf, 1023, "%.*s",
97                                 (int) uids->packet->length,
98                                 uids->packet->data);
99                         printf("                                %s\n",
100                                 (html) ? txt2html(buf) : buf);
101                 } else if (uids->packet->tag == OPENPGP_PACKET_UAT) {
102                         printf("                                ");
103                         if (html) {
104                                 printf("<img src=\"lookup?op=photo&search="
105                                         "0x%016" PRIX64 "&idx=%d\" alt=\""
106                                         "[photo id]\">\n",
107                                         keyid,
108                                         imgindx);
109                                 imgindx++;
110                         } else {
111                                 printf("[photo id]\n");
112                         }
113                 }
114                 if (verbose) {
115                         list_sigs(uids->sigs, html);
116                 }
117                 uids = uids->next;
118         }
119
120         return 0;
121 }
122
123 int list_subkeys(struct openpgp_signedpacket_list *subkeys, bool verbose,
124                 bool html)
125 {
126         struct tm       *created = NULL;
127         time_t          created_time = 0;
128         int             type = 0;
129         int             length = 0;
130
131         while (subkeys != NULL) {
132                 if (subkeys->packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
133
134                         created_time = (subkeys->packet->data[1] << 24) +
135                                         (subkeys->packet->data[2] << 16) +
136                                         (subkeys->packet->data[3] << 8) +
137                                         subkeys->packet->data[4];
138                         created = gmtime(&created_time);
139
140                         switch (subkeys->packet->data[0]) {
141                         case 2:
142                         case 3:
143                                 type = subkeys->packet->data[7];
144                                 length = (subkeys->packet->data[8] << 8) +
145                                         subkeys->packet->data[9];
146                                 break;
147                         case 4:
148                                 type = subkeys->packet->data[5];
149                                 length = (subkeys->packet->data[6] << 8) +
150                                         subkeys->packet->data[7];
151                                 break;
152                         default:
153                                 logthing(LOGTHING_ERROR,
154                                         "Unknown key type: %d",
155                                         subkeys->packet->data[0]);
156                         }
157                 
158                         printf("sub  %5d%c/%08X %04d/%02d/%02d\n",
159                                 length,
160                                 (type == OPENPGP_PKALGO_RSA) ? 'R' :
161                                 ((type == OPENPGP_PKALGO_ELGAMAL) ? 'g' :
162                                 ((type == OPENPGP_PKALGO_DSA) ? 'D' : '?')),
163                                 (uint32_t) (get_packetid(subkeys->packet) &
164                                             0xFFFFFFFF),
165                                 created->tm_year + 1900,
166                                 created->tm_mon + 1,
167                                 created->tm_mday);
168
169                 }
170                 if (verbose) {
171                         list_sigs(subkeys->sigs, html);
172                 }
173                 subkeys = subkeys->next;
174         }
175
176         return 0;
177 }
178
179 void display_fingerprint(struct openpgp_publickey *key)
180 {
181         int             i = 0;
182         size_t          length = 0;
183         unsigned char   fp[20];
184
185         get_fingerprint(key->publickey, fp, &length);
186         printf("      Key fingerprint =");
187         for (i = 0; i < length; i++) {
188                 if ((length == 16) ||
189                         (i % 2 == 0)) {
190                         printf(" ");
191                 }
192                 printf("%02X", fp[i]);
193                 if ((i * 2) == length) {
194                         printf(" ");
195                 }
196         }
197         printf("\n");
198
199         return;
200 }
201
202 void display_skshash(struct openpgp_publickey *key, bool html)
203 {
204         int             i = 0;
205         struct skshash  hash;
206
207         get_skshash(key, &hash);
208         printf("      Key hash = ");
209         if (html) {
210                 printf("<a href=\"lookup?op=hget&search=");
211                 for (i = 0; i < sizeof(hash.hash); i++) {
212                         printf("%02X", hash.hash[i]);
213                 }
214                 printf("\">");
215         }
216         for (i = 0; i < sizeof(hash.hash); i++) {
217                 printf("%02X", hash.hash[i]);
218         }
219         if (html) {
220                 printf("</a>");
221         }
222         printf("\n");
223
224         return;
225 }
226
227 /**
228  *      key_index - List a set of OpenPGP keys.
229  *      @keys: The keys to display.
230  *      @verbose: Should we list sigs as well?
231  *      @fingerprint: List the fingerprint?
232  *      @html: Should the output be tailored for HTML?
233  *
234  *      This function takes a list of OpenPGP public keys and displays an index
235  *      of them. Useful for debugging or the keyserver Index function.
236  */
237 int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
238                         bool skshash, bool html)
239 {
240         struct openpgp_signedpacket_list        *curuid = NULL;
241         struct tm                               *created = NULL;
242         time_t                                   created_time = 0;
243         int                                      type = 0;
244         char                                     typech;
245         int                                      length = 0;
246         char                                     buf[1024];
247         uint64_t                                 keyid;
248
249         if (html) {
250                 puts("<pre>");
251         }
252         puts("Type   bits/keyID    Date       User ID");
253         while (keys != NULL) {
254                 created_time = (keys->publickey->data[1] << 24) +
255                                         (keys->publickey->data[2] << 16) +
256                                         (keys->publickey->data[3] << 8) +
257                                         keys->publickey->data[4];
258                 created = gmtime(&created_time);
259
260                 switch (keys->publickey->data[0]) {
261                 case 2:
262                 case 3:
263                         type = keys->publickey->data[7];
264                         length = (keys->publickey->data[8] << 8) +
265                                         keys->publickey->data[9];
266                         break;
267                 case 4:
268                         type = keys->publickey->data[5];
269                         length = (keys->publickey->data[6] << 8) +
270                                         keys->publickey->data[7];
271                         break;
272                 default:
273                         logthing(LOGTHING_ERROR, "Unknown key type: %d",
274                                 keys->publickey->data[0]);
275                 }
276                 
277                 keyid = get_keyid(keys);
278
279                 switch (type) {
280                 case OPENPGP_PKALGO_RSA:
281                         typech = 'R';
282                         break;
283                 case OPENPGP_PKALGO_ELGAMAL:
284                         typech = 'g';
285                         break;
286                 case OPENPGP_PKALGO_DSA:
287                         typech = 'D';
288                         break;
289                 case OPENPGP_PKALGO_ELGAMAL_SIGN:
290                         typech = 'G';
291                         break;
292                 default:
293                         typech = '?';
294                         break;
295                 }
296
297                 if (html) {
298                         printf("pub  %5d%c/<a href=\"lookup?op=get&"
299                                 "search=%016" PRIX64 "\">%08" PRIX64
300                                 "</a> %04d/%02d/%02d ",
301                                 length,
302                                 typech,
303                                 keyid,
304                                 keyid & 0xFFFFFFFF,
305                                 created->tm_year + 1900,
306                                 created->tm_mon + 1,
307                                 created->tm_mday);
308                 } else {
309                         printf("pub  %5d%c/%08" PRIX64 " %04d/%02d/%02d ",
310                                 length,
311                                 typech,
312                                 keyid & 0xFFFFFFFF,
313                                 created->tm_year + 1900,
314                                 created->tm_mon + 1,
315                                 created->tm_mday);
316                 }
317
318                 curuid = keys->uids;
319                 if (curuid != NULL &&
320                                 curuid->packet->tag == OPENPGP_PACKET_UID) {
321                         snprintf(buf, 1023, "%.*s",
322                                 (int) curuid->packet->length,
323                                 curuid->packet->data);
324                         if (html) {
325                                 printf("<a href=\"lookup?op=vindex&"
326                                         "search=0x%016" PRIX64 "\">",
327                                         keyid);
328                         }
329                         printf("%s%s%s\n", 
330                                 (html) ? txt2html(buf) : buf,
331                                 (html) ? "</a>" : "",
332                                 (keys->revoked) ? " *** REVOKED ***" : "");
333                         if (skshash) {
334                                 display_skshash(keys, html);
335                         }
336                         if (fingerprint) {
337                                 display_fingerprint(keys);
338                         }
339                         if (verbose) {
340                                 list_sigs(curuid->sigs, html);
341                         }
342                         curuid = curuid->next;
343                 } else {
344                         printf("%s\n", 
345                                 (keys->revoked) ? "*** REVOKED ***": "");
346                         if (fingerprint) {
347                                 display_fingerprint(keys);
348                         }
349                 }
350
351                 list_uids(keyid, curuid, verbose, html);
352                 if (verbose) {
353                         list_subkeys(keys->subkeys, verbose, html);
354                 }
355
356                 keys = keys->next;
357         }
358
359         if (html) {
360                 puts("</pre>");
361         }
362
363         return 0;
364 }
365
366 /**
367  *      mrkey_index - List a set of OpenPGP keys in the MRHKP format.
368  *      @keys: The keys to display.
369  *
370  *      This function takes a list of OpenPGP public keys and displays a
371  *      machine readable list of them.
372  */
373 int mrkey_index(struct openpgp_publickey *keys)
374 {
375         struct openpgp_signedpacket_list        *curuid = NULL;
376         time_t                                   created_time = 0;
377         int                                      type = 0;
378         int                                      length = 0;
379         int                                      i = 0;
380         size_t                                   fplength = 0;
381         unsigned char                            fp[20];
382         int                                      c;
383
384         while (keys != NULL) {
385                 created_time = (keys->publickey->data[1] << 24) +
386                                         (keys->publickey->data[2] << 16) +
387                                         (keys->publickey->data[3] << 8) +
388                                         keys->publickey->data[4];
389
390                 printf("pub:");
391
392                 switch (keys->publickey->data[0]) {
393                 case 2:
394                 case 3:
395                         printf("%016" PRIX64, get_keyid(keys));
396                         type = keys->publickey->data[7];
397                         length = (keys->publickey->data[8] << 8) +
398                                         keys->publickey->data[9];
399                         break;
400                 case 4:
401                         (void) get_fingerprint(keys->publickey, fp, &fplength);
402
403                         for (i = 0; i < fplength; i++) {
404                                 printf("%02X", fp[i]);
405                         }
406
407                         type = keys->publickey->data[5];
408                         length = (keys->publickey->data[6] << 8) +
409                                         keys->publickey->data[7];
410                         break;
411                 default:
412                         logthing(LOGTHING_ERROR, "Unknown key type: %d",
413                                 keys->publickey->data[0]);
414                 }
415
416                 printf(":%d:%d:%ld::%s\n",
417                         type,
418                         length,
419                         created_time,
420                         (keys->revoked) ? "r" : "");
421         
422                 for (curuid = keys->uids; curuid != NULL;
423                          curuid = curuid->next) {
424                 
425                         if (curuid->packet->tag == OPENPGP_PACKET_UID) {
426                                 printf("uid:");
427                                 for (i = 0; i < (int) curuid->packet->length;
428                                                 i++) {
429                                         c = curuid->packet->data[i];
430                                         if (c == '%') {
431                                                 putchar('%');
432                                                 putchar(c);
433                                         } else if (c == ':' || c > 127) {
434                                                 printf("%%%X", c);
435                                         } else {
436                                                 putchar(c);
437                                         }
438                                 }
439                                 printf("\n");
440                         }
441                 }
442                 keys = keys->next;
443         }
444         return 0;
445 }