2 * keyindex.c - Routines to list an OpenPGP key.
4 * Jonathan McDowell <noodles@earth.li>
6 * Copyright 2002 Project Purple
22 #include "keystructs.h"
26 int list_sigs(struct openpgp_packet_list *sigs, bool html)
31 while (sigs != NULL) {
32 sigid = sig_keyid(sigs->packet);
33 uid = keyid2uid(sigid);
34 if (html && uid != NULL) {
35 printf("sig <a href=\"lookup?op=get&"
36 "search=%08llX\">%08llX</a> "
37 "<a href=\"lookup?op=vindex&search=0x%08llX\">"
43 } else if (html && uid == NULL) {
45 "[User id not found]\n",
52 "[User id not found]");
64 int list_uids(struct openpgp_signedpacket_list *uids, bool verbose, bool html)
68 while (uids != NULL) {
69 if (uids->packet->tag == 13) {
70 snprintf(buf, 1023, "%.*s",
71 (int) uids->packet->length,
74 (html) ? txt2html(buf) : buf);
75 } else if (uids->packet->tag == 17) {
80 list_sigs(uids->sigs, html);
88 int list_subkeys(struct openpgp_signedpacket_list *subkeys, bool verbose,
91 struct tm *created = NULL;
92 time_t created_time = 0;
96 while (subkeys != NULL) {
97 if (subkeys->packet->tag == 14) {
99 created_time = (subkeys->packet->data[1] << 24) +
100 (subkeys->packet->data[2] << 16) +
101 (subkeys->packet->data[3] << 8) +
102 subkeys->packet->data[4];
103 created = gmtime(&created_time);
105 switch (subkeys->packet->data[0]) {
108 type = subkeys->packet->data[7];
109 length = (subkeys->packet->data[8] << 8) +
110 subkeys->packet->data[9];
113 type = subkeys->packet->data[5];
114 length = (subkeys->packet->data[6] << 8) +
115 subkeys->packet->data[7];
118 fprintf(stderr, "Unknown key type: %d\n",
119 subkeys->packet->data[0]);
122 printf("sub %5d%c/%08X %04d/%02d/%02d\n",
124 (type == 1) ? 'R' : ((type == 16) ? 'g' :
125 ((type == 17) ? 'D' : '?')),
126 (uint32_t) (get_packetid(subkeys->packet) &
128 created->tm_year + 1900,
134 list_sigs(subkeys->sigs, html);
136 subkeys = subkeys->next;
144 * key_index - List a set of OpenPGP keys.
145 * @keys: The keys to display.
146 * @verbose: Should we list sigs as well?
147 * @fingerprint: List the fingerprint?
148 * @html: Should the output be tailored for HTML?
150 * This function takes a list of OpenPGP public keys and displays an index
151 * of them. Useful for debugging or the keyserver Index function.
153 int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
156 struct openpgp_signedpacket_list *curuid = NULL;
157 struct tm *created = NULL;
158 time_t created_time = 0;
166 puts("Type bits/keyID Date User ID");
167 while (keys != NULL) {
168 created_time = (keys->publickey->data[1] << 24) +
169 (keys->publickey->data[2] << 16) +
170 (keys->publickey->data[3] << 8) +
171 keys->publickey->data[4];
172 created = gmtime(&created_time);
174 switch (keys->publickey->data[0]) {
177 type = keys->publickey->data[7];
178 length = (keys->publickey->data[8] << 8) +
179 keys->publickey->data[9];
182 type = keys->publickey->data[5];
183 length = (keys->publickey->data[6] << 8) +
184 keys->publickey->data[7];
187 fprintf(stderr, "Unknown key type: %d\n",
188 keys->publickey->data[0]);
191 printf("pub %5d%c/%08X %04d/%02d/%02d ",
193 (type == 1) ? 'R' : ((type == 16) ? 'g' :
194 ((type == 17) ? 'D' : '?')),
195 (uint32_t) (get_keyid(keys) & 0xFFFFFFFF),
196 created->tm_year + 1900,
201 if (curuid != NULL && curuid->packet->tag == 13) {
202 snprintf(buf, 1023, "%.*s",
203 (int) curuid->packet->length,
204 curuid->packet->data);
205 printf("%s\n", (html) ? txt2html(buf) : buf);
207 list_sigs(curuid->sigs, html);
209 curuid = curuid->next;
214 list_uids(curuid, verbose, html);
215 list_subkeys(keys->subkeys, verbose, html);
228 * parse_subpackets - Parse the subpackets of a Type 4 signature.
229 * @data: The subpacket data.
230 * @keyid: A pointer to where we should return the keyid.
232 * This function parses the subkey data of a Type 4 signature and fills
233 * in the supplied variables. It also returns the length of the data
236 int parse_subpackets(unsigned char *data, uint64_t *keyid)
242 assert(data != NULL);
244 length = (data[0] << 8) + data[1] + 2;
247 while (offset < length) {
248 packetlen = data[offset++];
249 if (packetlen > 191 && packetlen < 255) {
250 packetlen = ((packetlen - 192) << 8) +
251 data[offset++] + 192;
252 } else if (packetlen == 255) {
253 packetlen = data[offset++];
255 packetlen = data[offset++];
257 packetlen = data[offset++];
259 packetlen = data[offset++];
261 switch (data[offset]) {
264 * Signature creation time. Might want to output this?
269 * Signature expiration time. Might want to output this?
273 *keyid = data[offset+packetlen - 8];
275 *keyid += data[offset+packetlen - 7];
277 *keyid += data[offset+packetlen - 6];
279 *keyid += data[offset+packetlen - 5];
281 *keyid += data[offset+packetlen - 4];
283 *keyid += data[offset+packetlen - 3];
285 *keyid += data[offset+packetlen - 2];
287 *keyid += data[offset+packetlen - 1];
291 * Key server preferences. Including no-modify.
301 * We don't care about unrecognized packets unless bit
302 * 7 is set in which case we prefer an error than
305 assert(!(data[offset] & 0x80));
314 * keysigs - Return the sigs on a given OpenPGP signature list.
315 * @curll: The current linked list. Can be NULL to create a new list.
316 * @sigs: The signature list we want the sigs on.
318 * Returns a linked list of stats_key elements containing the sigs on the
319 * supplied OpenPGP packet list.
321 struct ll *keysigs(struct ll *curll,
322 struct openpgp_packet_list *sigs)
326 while (sigs != NULL) {
327 keyid = sig_keyid(sigs->packet);
329 curll = lladd(curll, createandaddtohash(keyid));
336 * sig_keyid - Return the keyid for a given OpenPGP signature packet.
337 * @packet: The signature packet.
339 * Returns the keyid for the supplied signature packet.
341 uint64_t sig_keyid(struct openpgp_packet *packet)
346 if (packet != NULL) {
348 switch (packet->data[0]) {
351 keyid = packet->data[7];
353 keyid += packet->data[8];
355 keyid += packet->data[9];
357 keyid += packet->data[10];
359 keyid += packet->data[11];
361 keyid += packet->data[12];
363 keyid += packet->data[13];
365 keyid += packet->data[14];
368 length = parse_subpackets(&packet->data[4],
370 parse_subpackets(&packet->data[length + 4],
373 * Don't bother to look at the unsigned packets.
385 * TODO: Abstract out; all our linked lists should be generic and then we can
388 int spsize(struct openpgp_signedpacket_list *list)
391 struct openpgp_signedpacket_list *cur;
393 for (cur = list; cur != NULL; cur = cur->next, size++) ;
399 * keyuids - Takes a key and returns an array of its UIDs
400 * @key: The key to get the uids of.
401 * @primary: A pointer to store the primary UID in.
403 * keyuids takes a public key structure and builds an array of the UIDs
404 * on the key. It also attempts to work out the primary UID and returns a
405 * separate pointer to that particular element of the array.
407 char **keyuids(struct openpgp_publickey *key, char **primary)
409 struct openpgp_signedpacket_list *curuid = NULL;
414 if (key != NULL && key->uids != NULL) {
415 uids = malloc((spsize(key->uids) + 1) * sizeof (char *));
418 while (curuid != NULL) {
420 if (curuid->packet->tag == 13) {
421 snprintf(buf, 1023, "%.*s",
422 (int) curuid->packet->length,
423 curuid->packet->data);
424 uids[count++] = strdup(buf);
426 curuid = curuid -> next;
431 * TODO: Parse subpackets for real primary ID (v4 keys)
433 if (primary != NULL) {