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)
32 while (sigs != NULL) {
33 sigid = sig_keyid(sigs->packet);
34 uid = keyid2uid(sigid);
35 if (html && uid != NULL) {
36 printf("sig <a href=\"lookup?op=get&"
37 "search=%08llX\">%08llX</a> "
38 "<a href=\"lookup?op=vindex&search=0x%08llX\">"
44 } else if (html && uid == NULL) {
46 "[User id not found]\n",
53 "[User id not found]");
65 int list_uids(struct openpgp_signedpacket_list *uids, bool verbose, bool html)
69 while (uids != NULL) {
70 if (uids->packet->tag == 13) {
71 snprintf(buf, 1023, "%.*s",
72 (int) uids->packet->length,
75 (html) ? txt2html(buf) : buf);
76 } else if (uids->packet->tag == 17) {
81 list_sigs(uids->sigs, html);
90 * key_index - List a set of OpenPGP keys.
91 * @keys: The keys to display.
92 * @verbose: Should we list sigs as well?
93 * @fingerprint: List the fingerprint?
94 * @html: Should the output be tailored for HTML?
96 * This function takes a list of OpenPGP public keys and displays an index
97 * of them. Useful for debugging or the keyserver Index function.
99 int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
102 struct openpgp_signedpacket_list *curuid = NULL;
103 struct tm *created = NULL;
104 time_t created_time = 0;
112 puts("Type bits/keyID Date User ID");
113 while (keys != NULL) {
114 created_time = (keys->publickey->data[1] << 24) +
115 (keys->publickey->data[2] << 16) +
116 (keys->publickey->data[3] << 8) +
117 keys->publickey->data[4];
118 created = gmtime(&created_time);
120 switch (keys->publickey->data[0]) {
123 type = keys->publickey->data[7];
124 length = (keys->publickey->data[8] << 8) +
125 keys->publickey->data[9];
128 type = keys->publickey->data[5];
129 length = (keys->publickey->data[6] << 8) +
130 keys->publickey->data[7];
133 fprintf(stderr, "Unknown key type: %d\n",
134 keys->publickey->data[0]);
137 printf("pub %5d%c/%08X %04d/%02d/%02d ",
139 (type == 1) ? 'R' : ((type == 17) ? 'D' : '?'),
140 (uint32_t) (get_keyid(keys) & 0xFFFFFFFF),
141 created->tm_year + 1900,
146 if (curuid != NULL && curuid->packet->tag == 13) {
147 snprintf(buf, 1023, "%.*s",
148 (int) curuid->packet->length,
149 curuid->packet->data);
150 printf("%s\n", (html) ? txt2html(buf) : buf);
152 list_sigs(curuid->sigs, html);
154 curuid = curuid->next;
159 list_uids(curuid, verbose, html);
161 //TODO: List subkeys.
174 * parse_subpackets - Parse the subpackets of a Type 4 signature.
175 * @data: The subpacket data.
176 * @keyid: A pointer to where we should return the keyid.
178 * This function parses the subkey data of a Type 4 signature and fills
179 * in the supplied variables. It also returns the length of the data
182 int parse_subpackets(unsigned char *data, uint64_t *keyid)
188 assert(data != NULL);
190 length = (data[0] << 8) + data[1] + 2;
193 while (offset < length) {
194 packetlen = data[offset++];
195 if (packetlen > 191 && packetlen < 255) {
196 packetlen = ((packetlen - 192) << 8) +
197 data[offset++] + 192;
198 } else if (packetlen == 255) {
199 packetlen = data[offset++];
201 packetlen = data[offset++];
203 packetlen = data[offset++];
205 packetlen = data[offset++];
207 switch (data[offset]) {
210 * Signature creation time. Might want to output this?
215 * Signature expiration time. Might want to output this?
219 *keyid = data[offset+packetlen - 8];
221 *keyid += data[offset+packetlen - 7];
223 *keyid += data[offset+packetlen - 6];
225 *keyid += data[offset+packetlen - 5];
227 *keyid += data[offset+packetlen - 4];
229 *keyid += data[offset+packetlen - 3];
231 *keyid += data[offset+packetlen - 2];
233 *keyid += data[offset+packetlen - 1];
237 * Key server preferences. Including no-modify.
247 * We don't care about unrecognized packets unless bit
248 * 7 is set in which case we prefer an error than
251 assert(!(data[offset] & 0x80));
260 * keysigs - Return the sigs on a given OpenPGP signature list.
261 * @curll: The current linked list. Can be NULL to create a new list.
262 * @sigs: The signature list we want the sigs on.
264 * Returns a linked list of stats_key elements containing the sigs on the
265 * supplied OpenPGP packet list.
267 struct ll *keysigs(struct ll *curll,
268 struct openpgp_packet_list *sigs)
272 while (sigs != NULL) {
273 keyid = sig_keyid(sigs->packet);
275 curll = lladd(curll, createandaddtohash(keyid));
282 * sig_keyid - Return the keyid for a given OpenPGP signature packet.
283 * @packet: The signature packet.
285 * Returns the keyid for the supplied signature packet.
287 uint64_t sig_keyid(struct openpgp_packet *packet)
292 if (packet != NULL) {
294 switch (packet->data[0]) {
297 keyid = packet->data[7];
299 keyid += packet->data[8];
301 keyid += packet->data[9];
303 keyid += packet->data[10];
305 keyid += packet->data[11];
307 keyid += packet->data[12];
309 keyid += packet->data[13];
311 keyid += packet->data[14];
314 length = parse_subpackets(&packet->data[4],
316 parse_subpackets(&packet->data[length + 4],
319 * Don't bother to look at the unsigned packets.
331 * TODO: Abstract out; all our linked lists should be generic and then we can
334 int spsize(struct openpgp_signedpacket_list *list)
337 struct openpgp_signedpacket_list *cur;
339 for (cur = list; cur != NULL; cur = cur->next, size++) ;
345 * keyuids - Takes a key and returns an array of its UIDs
346 * @key: The key to get the uids of.
347 * @primary: A pointer to store the primary UID in.
349 * keyuids takes a public key structure and builds an array of the UIDs
350 * on the key. It also attempts to work out the primary UID and returns a
351 * separate pointer to that particular element of the array.
353 char **keyuids(struct openpgp_publickey *key, char **primary)
355 struct openpgp_signedpacket_list *curuid = NULL;
360 if (key != NULL && key->uids != NULL) {
361 uids = malloc((spsize(key->uids) + 1) * sizeof (char *));
364 while (curuid != NULL) {
366 if (curuid->packet->tag == 13) {
367 snprintf(buf, 1023, "%.*s",
368 (int) curuid->packet->length,
369 curuid->packet->data);
370 uids[count++] = strdup(buf);
372 curuid = curuid -> next;
377 * TODO: Parse subpackets for real primary ID (v4 keys)
379 if (primary != NULL) {