2 * keyindex.c - Routines to list an OpenPGP key.
4 * Copyright 2002-2008 Jonathan McDowell <noodles@earth.li>
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.
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
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.
27 #include "decodekey.h"
33 #include "keystructs.h"
36 #include "onak-conf.h"
40 * Convert a Public Key algorithm to its single character representation.
42 char pkalgo2char(uint8_t algo)
47 case OPENPGP_PKALGO_DSA:
50 case OPENPGP_PKALGO_ECDSA:
53 case OPENPGP_PKALGO_EC:
56 case OPENPGP_PKALGO_ELGAMAL_SIGN:
59 case OPENPGP_PKALGO_ELGAMAL_ENC:
62 case OPENPGP_PKALGO_RSA:
65 case OPENPGP_PKALGO_RSA_ENC:
68 case OPENPGP_PKALGO_RSA_SIGN:
79 int list_sigs(struct openpgp_packet_list *sigs, bool html)
85 while (sigs != NULL) {
86 sigid = sig_keyid(sigs->packet);
87 uid = config.dbbackend->keyid2uid(sigid);
88 if (sigs->packet->data[0] == 4 &&
89 sigs->packet->data[1] == 0x30) {
90 /* It's a Type 4 sig revocation */
95 if (html && uid != NULL) {
96 printf("%s <a href=\"lookup?op=get&"
97 "search=0x%016" PRIX64 "\">%08" PRIX64
99 "<a href=\"lookup?op=vindex&search=0x%016"
100 PRIX64 "\">%s</a>\n",
106 } else if (html && uid == NULL) {
107 printf("%s %08" PRIX64 " "
108 "[User id not found]\n",
112 printf("%s %08" PRIX64
116 (uid != NULL) ? uid :
117 "[User id not found]");
129 int list_uids(uint64_t keyid, struct openpgp_signedpacket_list *uids,
130 bool verbose, bool html)
135 while (uids != NULL) {
136 if (uids->packet->tag == OPENPGP_PACKET_UID) {
137 snprintf(buf, 1023, "%.*s",
138 (int) uids->packet->length,
141 (html) ? txt2html(buf) : buf);
142 } else if (uids->packet->tag == OPENPGP_PACKET_UAT) {
145 printf("<img src=\"lookup?op=photo&search="
146 "0x%016" PRIX64 "&idx=%d\" alt=\""
152 printf("[photo id]\n");
156 list_sigs(uids->sigs, html);
164 int list_subkeys(struct openpgp_signedpacket_list *subkeys, bool verbose,
167 struct tm *created = NULL;
168 time_t created_time = 0;
173 while (subkeys != NULL) {
174 if (subkeys->packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
176 created_time = (subkeys->packet->data[1] << 24) +
177 (subkeys->packet->data[2] << 16) +
178 (subkeys->packet->data[3] << 8) +
179 subkeys->packet->data[4];
180 created = gmtime(&created_time);
182 switch (subkeys->packet->data[0]) {
185 type = subkeys->packet->data[7];
186 length = (subkeys->packet->data[8] << 8) +
187 subkeys->packet->data[9];
190 type = subkeys->packet->data[5];
191 length = (subkeys->packet->data[6] << 8) +
192 subkeys->packet->data[7];
195 logthing(LOGTHING_ERROR,
196 "Unknown key type: %d",
197 subkeys->packet->data[0]);
200 if (get_packetid(subkeys->packet,
201 &keyid) != ONAK_E_OK) {
202 logthing(LOGTHING_ERROR, "Couldn't get keyid.");
204 printf("sub %5d%c/%08X %04d/%02d/%02d\n",
207 (uint32_t) (keyid & 0xFFFFFFFF),
208 created->tm_year + 1900,
214 list_sigs(subkeys->sigs, html);
216 subkeys = subkeys->next;
222 void display_fingerprint(struct openpgp_publickey *key)
226 unsigned char fp[20];
228 get_fingerprint(key->publickey, fp, &length);
229 printf(" Key fingerprint =");
230 for (i = 0; i < length; i++) {
231 if ((length == 16) ||
235 if (length == 20 && (i * 2) == length) {
236 /* Extra space in the middle of a SHA1 fingerprint */
239 printf("%02X", fp[i]);
246 void display_skshash(struct openpgp_publickey *key, bool html)
251 get_skshash(key, &hash);
252 printf(" Key hash = ");
254 printf("<a href=\"lookup?op=hget&search=");
255 for (i = 0; i < sizeof(hash.hash); i++) {
256 printf("%02X", hash.hash[i]);
260 for (i = 0; i < sizeof(hash.hash); i++) {
261 printf("%02X", hash.hash[i]);
272 * key_index - List a set of OpenPGP keys.
273 * @keys: The keys to display.
274 * @verbose: Should we list sigs as well?
275 * @fingerprint: List the fingerprint?
276 * @html: Should the output be tailored for HTML?
278 * This function takes a list of OpenPGP public keys and displays an index
279 * of them. Useful for debugging or the keyserver Index function.
281 int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
282 bool skshash, bool html)
284 struct openpgp_signedpacket_list *curuid = NULL;
285 struct tm *created = NULL;
286 time_t created_time = 0;
295 puts("Type bits/keyID Date User ID");
296 while (keys != NULL) {
297 created_time = (keys->publickey->data[1] << 24) +
298 (keys->publickey->data[2] << 16) +
299 (keys->publickey->data[3] << 8) +
300 keys->publickey->data[4];
301 created = gmtime(&created_time);
303 switch (keys->publickey->data[0]) {
306 type = keys->publickey->data[7];
307 length = (keys->publickey->data[8] << 8) +
308 keys->publickey->data[9];
311 type = keys->publickey->data[5];
312 length = (keys->publickey->data[6] << 8) +
313 keys->publickey->data[7];
316 logthing(LOGTHING_ERROR, "Unknown key type: %d",
317 keys->publickey->data[0]);
320 if (get_keyid(keys, &keyid) != ONAK_E_OK) {
321 logthing(LOGTHING_ERROR, "Couldn't get keyid.");
325 printf("pub %5d%c/<a href=\"lookup?op=get&"
326 "search=0x%016" PRIX64 "\">%08" PRIX64
327 "</a> %04d/%02d/%02d ",
332 created->tm_year + 1900,
336 printf("pub %5d%c/%08" PRIX64 " %04d/%02d/%02d ",
340 created->tm_year + 1900,
346 if (curuid != NULL &&
347 curuid->packet->tag == OPENPGP_PACKET_UID) {
348 snprintf(buf, 1023, "%.*s",
349 (int) curuid->packet->length,
350 curuid->packet->data);
352 printf("<a href=\"lookup?op=vindex&"
353 "search=0x%016" PRIX64 "\">",
357 (html) ? txt2html(buf) : buf,
358 (html) ? "</a>" : "",
359 (keys->revoked) ? " *** REVOKED ***" : "");
361 display_skshash(keys, html);
364 display_fingerprint(keys);
367 list_sigs(curuid->sigs, html);
369 curuid = curuid->next;
372 (keys->revoked) ? "*** REVOKED ***": "");
374 display_fingerprint(keys);
378 list_uids(keyid, curuid, verbose, html);
380 list_subkeys(keys->subkeys, verbose, html);
394 * mrkey_index - List a set of OpenPGP keys in the MRHKP format.
395 * @keys: The keys to display.
397 * This function takes a list of OpenPGP public keys and displays a
398 * machine readable list of them.
400 int mrkey_index(struct openpgp_publickey *keys)
402 struct openpgp_signedpacket_list *curuid = NULL;
403 time_t created_time = 0;
408 unsigned char fp[20];
412 while (keys != NULL) {
413 created_time = (keys->publickey->data[1] << 24) +
414 (keys->publickey->data[2] << 16) +
415 (keys->publickey->data[3] << 8) +
416 keys->publickey->data[4];
420 switch (keys->publickey->data[0]) {
423 if (get_keyid(keys, &keyid) != ONAK_E_OK) {
424 logthing(LOGTHING_ERROR, "Couldn't get keyid");
426 printf("%016" PRIX64, keyid);
427 type = keys->publickey->data[7];
428 length = (keys->publickey->data[8] << 8) +
429 keys->publickey->data[9];
432 (void) get_fingerprint(keys->publickey, fp, &fplength);
434 for (i = 0; i < fplength; i++) {
435 printf("%02X", fp[i]);
438 type = keys->publickey->data[5];
439 length = (keys->publickey->data[6] << 8) +
440 keys->publickey->data[7];
443 logthing(LOGTHING_ERROR, "Unknown key type: %d",
444 keys->publickey->data[0]);
447 printf(":%d:%d:%ld::%s\n",
451 (keys->revoked) ? "r" : "");
453 for (curuid = keys->uids; curuid != NULL;
454 curuid = curuid->next) {
456 if (curuid->packet->tag == OPENPGP_PACKET_UID) {
458 for (i = 0; i < (int) curuid->packet->length;
460 c = curuid->packet->data[i];
464 } else if (c == ':' || c > 127) {