2 * keyindex.c - Routines to list an OpenPGP key.
4 * Jonathan McDowell <noodles@earth.li>
6 * Copyright 2002 Project Purple
21 #include "keystructs.h"
25 int parse_subpackets(unsigned char *data, bool html)
34 length = (data[0] << 8) + data[1] + 2;
37 while (offset < length) {
38 packetlen = data[offset++];
39 if (packetlen > 191 && packetlen < 255) {
40 packetlen = ((packetlen - 192) << 8) +
42 } else if (packetlen == 255) {
43 packetlen = data[offset++];
45 packetlen = data[offset++];
47 packetlen = data[offset++];
49 packetlen = data[offset++];
51 switch (data[offset]) {
54 * Signature creation time. Might want to output this?
59 ((uint64_t) data[offset+packetlen - 8] << 56) +
60 ((uint64_t) data[offset+packetlen - 7] << 48) +
61 ((uint64_t) data[offset+packetlen - 6] << 40) +
62 ((uint64_t) data[offset+packetlen - 5] << 32) +
63 ((uint64_t) data[offset+packetlen - 4] << 24) +
64 ((uint64_t) data[offset+packetlen - 3] << 16) +
65 ((uint64_t) data[offset+packetlen - 2] << 8) +
66 data[offset+packetlen - 1]);
67 if (html && uid != NULL) {
68 printf("sig <a href=\"lookup?op=get&"
69 "search=%02X%02X%02X%02X\">"
70 "%02X%02X%02X%02X</a> "
71 "<a href=\"lookup?op=vindex&"
72 "search=0x%02X%02X%02X%02X\">"
74 data[offset+packetlen - 4],
75 data[offset+packetlen - 3],
76 data[offset+packetlen - 2],
77 data[offset+packetlen - 1],
78 data[offset+packetlen - 4],
79 data[offset+packetlen - 3],
80 data[offset+packetlen - 2],
81 data[offset+packetlen - 1],
83 data[offset+packetlen - 4],
84 data[offset+packetlen - 3],
85 data[offset+packetlen - 2],
86 data[offset+packetlen - 1],
88 } else if (html && uid == NULL) {
91 "[User id not found]\n",
92 data[offset+packetlen - 4],
93 data[offset+packetlen - 3],
94 data[offset+packetlen - 2],
95 data[offset+packetlen - 1]);
97 printf("sig %02X%02X%02X%02X"
99 data[offset+packetlen - 4],
100 data[offset+packetlen - 3],
101 data[offset+packetlen - 2],
102 data[offset+packetlen - 1],
103 (uid != NULL) ? uid :
104 "[User id not found]");
109 * We don't care about unrecognized packets unless bit
110 * 7 is set in which case we prefer an error than
113 assert(!(data[offset] & 0x80));
121 int list_sigs(struct openpgp_packet_list *sigs, bool html)
126 while (sigs != NULL) {
127 switch (sigs->packet->data[0]) {
131 ((uint64_t) sigs->packet->data[7] << 56) +
132 ((uint64_t) sigs->packet->data[8] << 48) +
133 ((uint64_t) sigs->packet->data[9] << 40) +
134 ((uint64_t) sigs->packet->data[10] << 32) +
135 ((uint64_t) sigs->packet->data[11] << 24) +
136 ((uint64_t) sigs->packet->data[12] << 16) +
137 ((uint64_t) sigs->packet->data[13] << 8) +
138 sigs->packet->data[14]);
139 if (html && uid != NULL) {
140 printf("sig <a href=\"lookup?op=get&"
141 "search=%02X%02X%02X%02X\">"
142 "%02X%02X%02X%02X</a> "
143 "<a href=\"lookup?op=vindex&"
144 "search=0x%02X%02X%02X%02X\">"
146 sigs->packet->data[11],
147 sigs->packet->data[12],
148 sigs->packet->data[13],
149 sigs->packet->data[14],
150 sigs->packet->data[11],
151 sigs->packet->data[12],
152 sigs->packet->data[13],
153 sigs->packet->data[14],
155 sigs->packet->data[11],
156 sigs->packet->data[12],
157 sigs->packet->data[13],
158 sigs->packet->data[14],
160 } else if (html && uid == NULL) {
161 printf("sig %02X%02X%02X%02X"
163 "[User id not found]\n",
164 sigs->packet->data[11],
165 sigs->packet->data[12],
166 sigs->packet->data[13],
167 sigs->packet->data[14]);
169 printf("sig %02X%02X%02X%02X"
171 sigs->packet->data[11],
172 sigs->packet->data[12],
173 sigs->packet->data[13],
174 sigs->packet->data[14],
175 (uid != NULL) ? uid :
176 "[User id not found]");
180 length = parse_subpackets(&sigs->packet->data[4], html);
181 parse_subpackets(&sigs->packet->data[length + 4], html);
184 printf("sig [Unknown packet version %d]",
185 sigs->packet->data[0]);
193 int list_uids(struct openpgp_signedpacket_list *uids, bool verbose, bool html)
197 while (uids != NULL) {
198 if (uids->packet->tag == 13) {
199 snprintf(buf, 1023, "%.*s",
200 (int) uids->packet->length,
203 (html) ? txt2html(buf) : buf);
204 } else if (uids->packet->tag == 17) {
209 list_sigs(uids->sigs, html);
218 * key_index - List a set of OpenPGP keys.
219 * @keys: The keys to display.
220 * @verbose: Should we list sigs as well?
221 * @fingerprint: List the fingerprint?
222 * @html: Should the output be tailored for HTML?
224 * This function takes a list of OpenPGP public keys and displays an index
225 * of them. Useful for debugging or the keyserver Index function.
227 int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
230 struct openpgp_signedpacket_list *curuid = NULL;
231 struct tm *created = NULL;
232 time_t created_time = 0;
240 puts("Type bits/keyID Date User ID");
241 while (keys != NULL) {
242 created_time = (keys->publickey->data[1] << 24) +
243 (keys->publickey->data[2] << 16) +
244 (keys->publickey->data[3] << 8) +
245 keys->publickey->data[4];
246 created = gmtime(&created_time);
248 switch (keys->publickey->data[0]) {
251 type = keys->publickey->data[7];
252 length = (keys->publickey->data[8] << 8) +
253 keys->publickey->data[9];
256 type = keys->publickey->data[5];
257 length = (keys->publickey->data[6] << 8) +
258 keys->publickey->data[7];
261 fprintf(stderr, "Unknown key type: %d\n",
262 keys->publickey->data[0]);
265 printf("pub %5d%c/%08X %04d/%02d/%02d ",
267 (type == 1) ? 'R' : ((type == 17) ? 'D' : '?'),
268 (uint32_t) (get_keyid(keys) & 0xFFFFFFFF),
269 created->tm_year + 1900,
274 if (curuid != NULL && curuid->packet->tag == 13) {
275 snprintf(buf, 1023, "%.*s",
276 (int) curuid->packet->length,
277 curuid->packet->data);
278 printf("%s\n", (html) ? txt2html(buf) : buf);
280 list_sigs(curuid->sigs, html);
282 curuid = curuid->next;
287 list_uids(curuid, verbose, html);
289 //TODO: List subkeys.
302 int get_subpackets_keyid(unsigned char *data, uint64_t *keyid)
308 assert(data != NULL);
310 length = (data[0] << 8) + data[1] + 2;
313 while (offset < length) {
314 packetlen = data[offset++];
315 if (packetlen > 191 && packetlen < 255) {
316 packetlen = ((packetlen - 192) << 8) +
317 data[offset++] + 192;
318 } else if (packetlen == 255) {
319 packetlen = data[offset++];
321 packetlen = data[offset++];
323 packetlen = data[offset++];
325 packetlen = data[offset++];
327 switch (data[offset]) {
330 * Signature creation time. Might want to output this?
335 * Signature expiration time. Might want to output this?
339 *keyid = data[offset+packetlen - 8];
341 *keyid += data[offset+packetlen - 7];
343 *keyid += data[offset+packetlen - 6];
345 *keyid += data[offset+packetlen - 5];
347 *keyid += data[offset+packetlen - 4];
349 *keyid += data[offset+packetlen - 3];
351 *keyid += data[offset+packetlen - 2];
353 *keyid += data[offset+packetlen - 1];
357 * We don't care about unrecognized packets unless bit
358 * 7 is set in which case we prefer an error than
361 assert(!(data[offset] & 0x80));
371 * keysigs - Return the sigs on a given OpenPGP signature list.
372 * @curll: The current linked list. Can be NULL to create a new list.
373 * @sigs: The signature list we want the sigs on.
375 * Returns a linked list of stats_key elements containing the sigs on the
376 * supplied OpenPGP packet list.
378 struct ll *keysigs(struct ll *curll,
379 struct openpgp_packet_list *sigs)
384 while (sigs != NULL) {
386 switch (sigs->packet->data[0]) {
389 keyid = sigs->packet->data[7];
391 keyid += sigs->packet->data[8];
393 keyid += sigs->packet->data[9];
395 keyid += sigs->packet->data[10];
397 keyid += sigs->packet->data[11];
399 keyid += sigs->packet->data[12];
401 keyid += sigs->packet->data[13];
403 keyid += sigs->packet->data[14];
406 length = get_subpackets_keyid(&sigs->packet->data[4],
408 get_subpackets_keyid(&sigs->packet->data[length + 4],
411 * Don't bother to look at the unsigned packets.
418 curll = lladd(curll, createandaddtohash(keyid));
425 * TODO: Abstract out; all our linked lists should be generic and then we can
428 int spsize(struct openpgp_signedpacket_list *list)
431 struct openpgp_signedpacket_list *cur;
433 for (cur = list; cur != NULL; cur = cur->next, size++) ;
439 * keyuids - Takes a key and returns an array of its UIDs
440 * @key: The key to get the uids of.
441 * @primary: A pointer to store the primary UID in.
443 * keyuids takes a public key structure and builds an array of the UIDs
444 * on the key. It also attempts to work out the primary UID and returns a
445 * separate pointer to that particular element of the array.
447 char **keyuids(struct openpgp_publickey *key, char **primary)
449 struct openpgp_signedpacket_list *curuid = NULL;
454 if (key != NULL && key->uids != NULL) {
455 uids = malloc((spsize(key->uids) + 1) * sizeof (char *));
458 while (curuid != NULL) {
460 if (curuid->packet->tag == 13) {
461 snprintf(buf, 1023, "%.*s",
462 (int) curuid->packet->length,
463 curuid->packet->data);
464 uids[count++] = strdup(buf);
466 curuid = curuid -> next;
471 * TODO: Parse subpackets for real primary ID (v4 keys)
473 if (primary != NULL) {