2 * Copyright (C) 1997-2001 Thomas Roessler <roessler@does-not-exist.org>
4 * This program is free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later
10 * This program is distributed in the hope that it will be
11 * useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111, USA.
23 * This is a "simple" PGP key ring dumper.
25 * The output format is supposed to be compatible to the one GnuPG
26 * emits and Mutt expects.
28 * Note that the code of this program could be considerably less
29 * complex, but most of it was taken from mutt's second generation
32 * You can actually use this to put together some fairly general
33 * PGP key management applications.
53 short Umask; /* dirty hack because we need Umask in lib.c but don't want globals.h there */
59 #include "pgppacket.h"
61 #define MD5_DIGEST_LENGTH 16
64 #define FGETPOS(fp,pos) fgetpos((fp),&(pos))
65 #define FSETPOS(fp,pos) fsetpos((fp),&(pos))
67 #define FGETPOS(fp,pos) pos=ftell((fp));
68 #define FSETPOS(fp,pos) fseek((fp),(pos),SEEK_SET)
72 static short dump_signatures = 0;
73 static short dump_fingerprints = 0;
76 static void pgpring_find_candidates (char *ringfile, const char *hints[], int nhints);
77 static void pgpring_dump_keyblock (pgp_key_t p);
79 int main (int argc, char * const argv[])
86 const char *_kring = NULL;
87 char *env_pgppath, *env_home;
89 char pgppath[_POSIX_PATH_MAX];
90 char kring[_POSIX_PATH_MAX];
92 while ((c = getopt (argc, argv, "f25sk:S")) != EOF)
104 dump_fingerprints = 1;
128 fprintf (stderr, "usage: %s [-k <key ring> | [-2 | -5] [ -s] [-S] [-f]] [hints]\n",
136 strfcpy (kring, _kring, sizeof (kring));
139 if ((env_pgppath = getenv ("PGPPATH")))
140 strfcpy (pgppath, env_pgppath, sizeof (pgppath));
141 else if ((env_home = getenv ("HOME")))
142 snprintf (pgppath, sizeof (pgppath), "%s/.pgp", env_home);
145 fprintf (stderr, "%s: Can't determine your PGPPATH.\n", argv[0]);
150 snprintf (kring, sizeof (kring), "%s/secring.%s", pgppath, version == 2 ? "pgp" : "skr");
152 snprintf (kring, sizeof (kring), "%s/pubring.%s", pgppath, version == 2 ? "pgp" : "pkr");
155 pgpring_find_candidates (kring, (const char**) argv + optind, argc - optind);
161 /* The actual key ring parser */
163 static void pgp_make_pgp2_fingerprint (unsigned char *buff,
164 unsigned char *digest)
168 unsigned int size = 0;
173 size = (buff[0] << 8) + buff[1];
174 size = ((size + 7) / 8);
177 MD5Update (&context, buff, size);
180 size = (buff[0] << 8) + buff[1];
181 size = ((size + 7) / 8);
184 MD5Update (&context, buff, size);
186 MD5Final (digest, &context);
188 } /* pgp_make_pgp2_fingerprint() */
190 static pgp_key_t pgp_parse_pgp2_key (unsigned char *buff, size_t l)
194 unsigned char digest[MD5_DIGEST_LENGTH];
198 unsigned short exp_days = 0;
201 unsigned char scratch[LONG_STRING];
206 p = pgp_new_keyinfo();
208 for (i = 0, j = 2; i < 4; i++)
209 gen_time = (gen_time << 8) + buff[j++];
211 p->gen_time = gen_time;
213 for (i = 0; i < 2; i++)
214 exp_days = (exp_days << 8) + buff[j++];
216 if (exp_days && time (NULL) > gen_time + exp_days * 24 * 3600)
217 p->flags |= KEYFLAG_EXPIRED;
222 p->algorithm = pgp_pkalgbytype (alg);
223 p->flags |= pgp_get_abilities (alg);
225 if (dump_fingerprints)
227 /* j now points to the key material, which we need for the fingerprint */
228 p->fp_len = MD5_DIGEST_LENGTH;
229 pgp_make_pgp2_fingerprint (&buff[j], digest);
230 memcpy (p->fingerprint, digest, MD5_DIGEST_LENGTH);
232 else /* just to be usre */
233 memset (p->fingerprint, 0, MD5_DIGEST_LENGTH);
236 for (i = 0; i < 2; i++)
237 expl = (expl << 8) + buff[j++];
241 expl = (expl + 7) / 8;
248 for (k = 0; k < 2; k++)
250 for (id = 0, i = 0; i < 4; i++)
251 id = (id << 8) + buff[j++];
253 snprintf ((char *) scratch + k * 8, sizeof (scratch) - k * 8,
257 p->keyid = safe_strdup ((char *) scratch);
267 static void pgp_make_pgp3_fingerprint (unsigned char *buff, size_t l,
268 unsigned char *digest)
273 SHA1_Init (&context);
275 dummy = buff[0] & 0x3f;
277 if (dummy == PT_SUBSECKEY || dummy == PT_SUBKEY || dummy == PT_SECKEY)
280 dummy = (dummy << 2) | 0x81;
281 SHA1_Update (&context, &dummy, 1);
282 dummy = ((l - 1) >> 8) & 0xff;
283 SHA1_Update (&context, &dummy, 1);
284 dummy = (l - 1) & 0xff;
285 SHA1_Update (&context, &dummy, 1);
286 SHA1_Update (&context, buff + 1, l - 1);
287 SHA1_Final (digest, &context);
291 static void skip_bignum (unsigned char *buff, size_t l, size_t j,
292 size_t * toff, size_t n)
298 len = (buff[j] << 8) + buff[j + 1];
299 j += (len + 7) / 8 + 2;
301 while (j <= l && --n > 0);
308 static pgp_key_t pgp_parse_pgp3_key (unsigned char *buff, size_t l)
312 unsigned char digest[SHA_DIGEST_LENGTH];
313 unsigned char scratch[LONG_STRING];
320 p = pgp_new_keyinfo ();
323 for (i = 0; i < 4; i++)
324 gen_time = (gen_time << 8) + buff[j++];
326 p->gen_time = gen_time;
331 p->algorithm = pgp_pkalgbytype (alg);
332 p->flags |= pgp_get_abilities (alg);
335 skip_bignum (buff, l, j, &j, 3);
336 else if (alg == 16 || alg == 20)
337 skip_bignum (buff, l, j, &j, 2);
339 len = (buff[j] << 8) + buff[j + 1];
343 if (alg >= 1 && alg <= 3)
344 skip_bignum (buff, l, j, &j, 2);
345 else if (alg == 17 || alg == 16 || alg == 20)
346 skip_bignum (buff, l, j, &j, 1);
348 pgp_make_pgp3_fingerprint (buff, j, digest);
349 p->fp_len = SHA_DIGEST_LENGTH;
351 for (k = 0; k < 2; k++)
353 for (id = 0, i = SHA_DIGEST_LENGTH - 8 + k * 4;
354 i < SHA_DIGEST_LENGTH + (k - 1) * 4; i++)
355 id = (id << 8) + digest[i];
357 snprintf ((char *) scratch + k * 8, sizeof (scratch) - k * 8, "%08lX", id);
360 p->keyid = safe_strdup ((char *) scratch);
365 static pgp_key_t pgp_parse_keyinfo (unsigned char *buff, size_t l)
374 return pgp_parse_pgp2_key (buff, l);
376 return pgp_parse_pgp3_key (buff, l);
382 static int pgp_parse_pgp2_sig (unsigned char *buff, size_t l,
383 pgp_key_t p, pgp_sig_t *s)
385 unsigned char sigtype;
387 unsigned long signerid1;
388 unsigned long signerid2;
399 for (i = 0; i < 4; i++)
400 sig_gen_time = (sig_gen_time << 8) + buff[j++];
402 signerid1 = signerid2 = 0;
403 for (i = 0; i < 4; i++)
404 signerid1 = (signerid1 << 8) + buff[j++];
406 for (i = 0; i < 4; i++)
407 signerid2 = (signerid2 << 8) + buff[j++];
410 if (sigtype == 0x20 || sigtype == 0x28)
411 p->flags |= KEYFLAG_REVOKED;
415 s->sigtype = sigtype;
423 static int pgp_parse_pgp3_sig (unsigned char *buff, size_t l,
424 pgp_key_t p, pgp_sig_t *s)
426 unsigned char sigtype;
428 unsigned char hashalg;
430 time_t sig_gen_time = -1;
432 long key_validity = -1;
433 unsigned long signerid1 = 0;
434 unsigned long signerid2 = 0;
439 short have_critical_spks = 0;
450 for (ii = 0; ii < 2; ii++)
455 ml = (buff[j] << 8) + buff[j + 1];
471 skl = (skl - 192) * 256 + buff[j++] + 192;
476 if ((int) ml - (int) skl < 0)
485 case 2: /* creation time */
490 for (i = 0; i < 4; i++)
491 sig_gen_time = (sig_gen_time << 8) + buff[j++];
495 case 3: /* expiration time */
500 for (i = 0; i < 4; i++)
501 validity = (validity << 8) + buff[j++];
504 case 9: /* key expiration time */
509 for (i = 0; i < 4; i++)
510 key_validity = (key_validity << 8) + buff[j++];
513 case 16: /* issuer key ID */
517 signerid2 = signerid1 = 0;
518 for (i = 0; i < 4; i++)
519 signerid1 = (signerid1 << 8) + buff[j++];
520 for (i = 0; i < 4; i++)
521 signerid2 = (signerid2 << 8) + buff[j++];
525 case 10: /* CMR key */
527 case 4: /* exportable */
530 case 7: /* revocable */
531 case 11: /* Pref. symm. alg. */
532 case 12: /* revocation key */
533 case 20: /* notation data */
534 case 21: /* pref. hash */
535 case 22: /* pref. comp.alg. */
536 case 23: /* key server prefs. */
537 case 24: /* pref. key server */
541 have_critical_spks = 1;
548 if (sigtype == 0x20 || sigtype == 0x28)
549 p->flags |= KEYFLAG_REVOKED;
550 if (key_validity != -1 && time (NULL) > p->gen_time + key_validity)
551 p->flags |= KEYFLAG_EXPIRED;
552 if (have_critical_spks)
553 p->flags |= KEYFLAG_CRITICAL;
557 s->sigtype = sigtype;
568 static int pgp_parse_sig (unsigned char *buff, size_t l,
569 pgp_key_t p, pgp_sig_t *sig)
571 if (!buff || l < 2 || !p)
578 return pgp_parse_pgp2_sig (buff, l, p, sig);
580 return pgp_parse_pgp3_sig (buff, l, p, sig);
586 /* parse one key block, including all subkeys. */
588 static pgp_key_t pgp_parse_keyblock (FILE * fp)
591 unsigned char pt = 0;
592 unsigned char last_pt;
602 pgp_key_t root = NULL;
603 pgp_key_t *last = &root;
605 pgp_uid_t *uid = NULL;
606 pgp_uid_t **addr = NULL;
607 pgp_sig_t **lsig = NULL;
611 while (!err && (buff = pgp_read_packet (fp, &l)) != NULL)
616 /* check if we have read the complete key block. */
618 if ((pt == PT_SECKEY || pt == PT_PUBKEY) && root)
631 if (!(*last = p = pgp_parse_keyinfo (buff, l)))
641 if (pt == PT_SUBKEY || pt == PT_SUBSECKEY)
643 p->flags |= KEYFLAG_SUBKEY;
647 p->address = pgp_copy_uids (root->address, p);
648 while (*addr) addr = &(*addr)->next;
652 if (pt == PT_SECKEY || pt == PT_SUBSECKEY)
653 p->flags |= KEYFLAG_SECRET;
662 pgp_sig_t *signature = safe_calloc (sizeof (pgp_sig_t), 1);
664 lsig = &signature->next;
666 pgp_parse_sig (buff, l, p, signature);
673 if (p && (last_pt == PT_SECKEY || last_pt == PT_PUBKEY ||
674 last_pt == PT_SUBKEY || last_pt == PT_SUBSECKEY))
678 p->flags |= KEYFLAG_DISABLED;
681 else if (last_pt == PT_NAME && uid)
683 uid->trust = buff[1];
695 chr = safe_malloc (l);
696 memcpy (chr, buff + 1, l - 1);
700 *addr = uid = safe_calloc (1, sizeof (pgp_uid_t)); /* XXX */
707 /* the following tags are generated by
711 if (strstr (chr, "ENCR"))
712 p->flags |= KEYFLAG_PREFER_ENCRYPTION;
713 if (strstr (chr, "SIGN"))
714 p->flags |= KEYFLAG_PREFER_SIGNING;
724 pgp_free_key (&root);
729 static int pgpring_string_matches_hint (const char *s, const char *hints[], int nhints)
733 if (!hints || !nhints)
736 for (i = 0; i < nhints; i++)
738 if (mutt_stristr (s, hints[i]) != NULL)
746 * Go through the key ring file and look for keys with
750 static void pgpring_find_candidates (char *ringfile, const char *hints[], int nhints)
759 unsigned char *buff = NULL;
760 unsigned char pt = 0;
765 if ((rfp = fopen (ringfile, "r")) == NULL)
768 size_t error_buf_len;
770 error_buf_len = sizeof ("fopen: ") - 1 + strlen (ringfile) + 1;
771 error_buf = safe_malloc (error_buf_len);
772 snprintf (error_buf, error_buf_len, "fopen: %s", ringfile);
781 while (!err && (buff = pgp_read_packet (rfp, &l)) != NULL)
788 if ((pt == PT_SECKEY) || (pt == PT_PUBKEY))
792 else if (pt == PT_NAME)
794 char *tmp = safe_malloc (l);
796 memcpy (tmp, buff + 1, l - 1);
799 /* mutt_decode_utf8_string (tmp, chs); */
801 if (pgpring_string_matches_hint (tmp, hints, nhints))
805 FSETPOS(rfp, keypos);
807 /* Not bailing out here would lead us into an endless loop. */
809 if ((p = pgp_parse_keyblock (rfp)) == NULL)
812 pgpring_dump_keyblock (p);
826 static void print_userid (const char *id)
828 for (; id && *id; id++)
830 if (*id >= ' ' && *id <= 'z' && *id != ':')
833 printf ("\\x%02x", (*id) & 0xff);
837 static void print_fingerprint (pgp_key_t p)
841 printf ("fpr:::::::::");
842 for (i = 0; i < p->fp_len; i++)
843 printf ("%02X", p->fingerprint[i]);
846 } /* print_fingerprint() */
849 static void pgpring_dump_signatures (pgp_sig_t *sig)
851 for (; sig; sig = sig->next)
853 if (sig->sigtype == 0x10 || sig->sigtype == 0x11 ||
854 sig->sigtype == 0x12 || sig->sigtype == 0x13)
855 printf ("sig::::%08lX%08lX::::::%X:\n",
856 sig->sid1, sig->sid2, sig->sigtype);
857 else if (sig->sigtype == 0x20)
858 printf ("rev::::%08lX%08lX::::::%X:\n",
859 sig->sid1, sig->sid2, sig->sigtype);
864 static char gnupg_trustletter (int t)
875 static void pgpring_dump_keyblock (pgp_key_t p)
882 for (; p; p = p->next)
886 if (p->flags & KEYFLAG_SECRET)
888 if (p->flags & KEYFLAG_SUBKEY)
895 if (p->flags & KEYFLAG_SUBKEY)
901 if (p->flags & KEYFLAG_REVOKED)
903 if (p->flags & KEYFLAG_EXPIRED)
905 if (p->flags & KEYFLAG_DISABLED)
908 for (uid = p->address; uid; uid = uid->next, first = 0)
912 printf ("uid:%c::::::::", gnupg_trustletter (uid->trust));
913 print_userid (uid->addr);
918 if (p->flags & KEYFLAG_SECRET)
921 putchar (gnupg_trustletter (uid->trust));
926 printf (":%d:%d:%s:%04d-%02d-%02d::::", p->keylen, p->numalg, p->keyid,
927 1900 + tp->tm_year, tp->tm_mon + 1, tp->tm_mday);
929 print_userid (uid->addr);
932 if(pgp_canencrypt(p->numalg))
934 if(pgp_cansign(p->numalg))
936 if (p->flags & KEYFLAG_DISABLED)
940 if (dump_fingerprints)
941 print_fingerprint (p);
946 if (first) pgpring_dump_signatures (p->sigs);
947 pgpring_dump_signatures (uid->sigs);
954 * The mutt_gettext () defined in gettext.c requires iconv,
955 * so we do without charset conversion here.
958 char *mutt_gettext (const char *message)
960 return (char *)message;