]> git.sthu.org Git - pgp-tools.git/blob - keyanalyze/pgpring/pgppubring.c
* debian.control: added ${misc:Depends} as Depends for the keyanalyze
[pgp-tools.git] / keyanalyze / pgpring / pgppubring.c
1 /*
2 * Copyright (C) 1997-2001 Thomas Roessler <roessler@does-not-exist.org>
3 *
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
8 * version.
9 *
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
14 * details.
15 *
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.
20 */
21
22 /*
23 * This is a "simple" PGP key ring dumper.
24 *
25 * The output format is supposed to be compatible to the one GnuPG
26 * emits and Mutt expects.
27 *
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
30 * key ring parser.
31 *
32 * You can actually use this to put together some fairly general
33 * PGP key management applications.
34 *
35 */
36
37
38 #include "config.h"
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <time.h>
45 #ifdef HAVE_GETOPT_H
46 # include <getopt.h>
47 #endif
48
49 extern char *optarg;
50 extern int optind;
51
52 #include "sha1.h"
53 #include "lib.h"
54 #include "pgplib.h"
55 #include "pgppacket.h"
56
57
58 #ifdef HAVE_FGETPOS
59 #define FGETPOS(fp,pos) fgetpos((fp),&(pos))
60 #define FSETPOS(fp,pos) fsetpos((fp),&(pos))
61 #else
62 #define FGETPOS(fp,pos) pos=ftell((fp));
63 #define FSETPOS(fp,pos) fseek((fp),(pos),SEEK_SET)
64 #endif
65
66
67 static short dump_signatures = 0;
68
69
70 static void pgpring_find_candidates (char *ringfile, const char *hints[], int nhints);
71 static void pgpring_dump_keyblock (pgp_key_t *p);
72
73 int main (int argc, char * const argv[])
74 {
75 int c;
76
77 short version = 2;
78 short secring = 0;
79
80 const char *_kring = NULL;
81 char *env_pgppath, *env_home;
82
83 char pgppath[_POSIX_PATH_MAX];
84 char kring[_POSIX_PATH_MAX];
85
86 while ((c = getopt (argc, argv, "25sk:S")) != EOF)
87 {
88 switch (c)
89 {
90 case 'S':
91 {
92 dump_signatures = 1;
93 break;
94 }
95
96 case 'k':
97 {
98 _kring = optarg;
99 break;
100 }
101
102 case '2': case '5':
103 {
104 version = c - '0';
105 break;
106 }
107
108 case 's':
109 {
110 secring = 1;
111 break;
112 }
113
114 default:
115 {
116 fprintf (stderr, "usage: %s [-k <key ring> | [-2 | -5] [ -s]] [hints]\n",
117 argv[0]);
118 exit (1);
119 }
120 }
121 }
122
123 if (_kring)
124 strfcpy (kring, _kring, sizeof (kring));
125 else
126 {
127 if ((env_pgppath = getenv ("PGPPATH")))
128 strfcpy (pgppath, env_pgppath, sizeof (pgppath));
129 else if ((env_home = getenv ("HOME")))
130 snprintf (pgppath, sizeof (pgppath), "%s/.pgp", env_home);
131 else
132 {
133 fprintf (stderr, "%s: Can't determine your PGPPATH.\n", argv[0]);
134 exit (1);
135 }
136
137 if (secring)
138 snprintf (kring, sizeof (kring), "%s/secring.%s", pgppath, version == 2 ? "pgp" : "skr");
139 else
140 snprintf (kring, sizeof (kring), "%s/pubring.%s", pgppath, version == 2 ? "pgp" : "pkr");
141 }
142
143 pgpring_find_candidates (kring, (const char**) argv + optind, argc - optind);
144
145 return 0;
146 }
147
148
149 /* The actual key ring parser */
150
151 static pgp_key_t *pgp_parse_pgp2_key (unsigned char *buff, size_t l)
152 {
153 pgp_key_t *p;
154 unsigned char alg;
155 size_t expl;
156 unsigned long id;
157 time_t gen_time = 0;
158 unsigned short exp_days = 0;
159 size_t j;
160 int i, k;
161 unsigned char scratch[LONG_STRING];
162
163 if (l < 12)
164 return NULL;
165
166 p = pgp_new_keyinfo();
167
168 for (i = 0, j = 2; i < 4; i++)
169 gen_time = (gen_time << 8) + buff[j++];
170
171 p->gen_time = gen_time;
172
173 for (i = 0; i < 2; i++)
174 exp_days = (exp_days << 8) + buff[j++];
175
176 if (exp_days && time (NULL) > gen_time + exp_days * 24 * 3600)
177 p->flags |= KEYFLAG_EXPIRED;
178
179 alg = buff[j++];
180
181 p->numalg = alg;
182 p->algorithm = pgp_pkalgbytype (alg);
183 p->flags |= pgp_get_abilities (alg);
184
185 expl = 0;
186 for (i = 0; i < 2; i++)
187 expl = (expl << 8) + buff[j++];
188
189 p->keylen = expl;
190
191 expl = (expl + 7) / 8;
192 if (expl < 4)
193 goto bailout;
194
195
196 j += expl - 8;
197
198 for (k = 0; k < 2; k++)
199 {
200 for (id = 0, i = 0; i < 4; i++)
201 id = (id << 8) + buff[j++];
202
203 snprintf ((char *) scratch + k * 8, sizeof (scratch) - k * 8,
204 "%08lX", id);
205 }
206
207 p->keyid = safe_strdup ((char *) scratch);
208
209 return p;
210
211 bailout:
212
213 safe_free ((void *)&p);
214 return NULL;
215 }
216
217 static void pgp_make_pgp3_fingerprint (unsigned char *buff, size_t l,
218 unsigned char *digest)
219 {
220 unsigned char dummy;
221 SHA1_CTX context;
222
223 SHA1_Init (&context);
224
225 dummy = buff[0] & 0x3f;
226
227 if (dummy == PT_SUBSECKEY || dummy == PT_SUBKEY || dummy == PT_SECKEY)
228 dummy = PT_PUBKEY;
229
230 dummy = (dummy << 2) | 0x81;
231 SHA1_Update (&context, &dummy, 1);
232 dummy = ((l - 1) >> 8) & 0xff;
233 SHA1_Update (&context, &dummy, 1);
234 dummy = (l - 1) & 0xff;
235 SHA1_Update (&context, &dummy, 1);
236 SHA1_Update (&context, buff + 1, l - 1);
237 SHA1_Final (digest, &context);
238
239 }
240
241 static void skip_bignum (unsigned char *buff, size_t l, size_t j,
242 size_t * toff, size_t n)
243 {
244 size_t len;
245
246 do
247 {
248 len = (buff[j] << 8) + buff[j + 1];
249 j += (len + 7) / 8 + 2;
250 }
251 while (j <= l && --n > 0);
252
253 if (toff)
254 *toff = j;
255 }
256
257
258 static pgp_key_t *pgp_parse_pgp3_key (unsigned char *buff, size_t l)
259 {
260 pgp_key_t *p;
261 unsigned char alg;
262 unsigned char digest[SHA_DIGEST_LENGTH];
263 unsigned char scratch[LONG_STRING];
264 time_t gen_time = 0;
265 unsigned long id;
266 int i, k;
267 short len;
268 size_t j;
269
270 p = pgp_new_keyinfo ();
271 j = 2;
272
273 for (i = 0; i < 4; i++)
274 gen_time = (gen_time << 8) + buff[j++];
275
276 p->gen_time = gen_time;
277
278 alg = buff[j++];
279
280 p->numalg = alg;
281 p->algorithm = pgp_pkalgbytype (alg);
282 p->flags |= pgp_get_abilities (alg);
283
284 if (alg == 17)
285 skip_bignum (buff, l, j, &j, 3);
286 else if (alg == 16 || alg == 20)
287 skip_bignum (buff, l, j, &j, 2);
288
289 len = (buff[j] << 8) + buff[j + 1];
290 p->keylen = len;
291
292 if (alg >= 1 && alg <= 3)
293 skip_bignum (buff, l, j, &j, 2);
294 else if (alg == 17 || alg == 16 || alg == 20)
295 skip_bignum (buff, l, j, &j, 1);
296
297 pgp_make_pgp3_fingerprint (buff, j, digest);
298
299 for (k = 0; k < 2; k++)
300 {
301 for (id = 0, i = SHA_DIGEST_LENGTH - 8 + k * 4;
302 i < SHA_DIGEST_LENGTH + (k - 1) * 4; i++)
303 id = (id << 8) + digest[i];
304
305 snprintf ((char *) scratch + k * 8, sizeof (scratch) - k * 8, "%08lX", id);
306 }
307
308 p->keyid = safe_strdup ((char *) scratch);
309
310 return p;
311 }
312
313 static pgp_key_t *pgp_parse_keyinfo (unsigned char *buff, size_t l)
314 {
315 if (!buff || l < 2)
316 return NULL;
317
318 switch (buff[1])
319 {
320 case 2:
321 case 3:
322 return pgp_parse_pgp2_key (buff, l);
323 case 4:
324 return pgp_parse_pgp3_key (buff, l);
325 default:
326 return NULL;
327 }
328 }
329
330 static int pgp_parse_pgp2_sig (unsigned char *buff, size_t l, pgp_key_t * p, pgp_sig_t *s)
331 {
332 unsigned char sigtype;
333 time_t sig_gen_time;
334 unsigned long signerid1;
335 unsigned long signerid2;
336 size_t j;
337 int i;
338
339 if (l < 22)
340 return -1;
341
342 j = 3;
343 sigtype = buff[j++];
344
345 sig_gen_time = 0;
346 for (i = 0; i < 4; i++)
347 sig_gen_time = (sig_gen_time << 8) + buff[j++];
348
349 signerid1 = signerid2 = 0;
350 for (i = 0; i < 4; i++)
351 signerid1 = (signerid1 << 8) + buff[j++];
352
353 for (i = 0; i < 4; i++)
354 signerid2 = (signerid2 << 8) + buff[j++];
355
356
357 if (sigtype == 0x20 || sigtype == 0x28)
358 p->flags |= KEYFLAG_REVOKED;
359
360 if (s)
361 {
362 s->sigtype = sigtype;
363 s->sid1 = signerid1;
364 s->sid2 = signerid2;
365 }
366
367 return 0;
368 }
369
370 static int pgp_parse_pgp3_sig (unsigned char *buff, size_t l, pgp_key_t * p, pgp_sig_t *s)
371 {
372 unsigned char sigtype;
373 unsigned char pkalg;
374 unsigned char hashalg;
375 unsigned char skt;
376 time_t sig_gen_time = -1;
377 long validity = -1;
378 long key_validity = -1;
379 unsigned long signerid1 = 0;
380 unsigned long signerid2 = 0;
381 size_t ml;
382 size_t j;
383 int i;
384 short ii;
385 short have_critical_spks = 0;
386
387 if (l < 7)
388 return -1;
389
390 j = 2;
391
392 sigtype = buff[j++];
393 pkalg = buff[j++];
394 hashalg = buff[j++];
395
396 for (ii = 0; ii < 2; ii++)
397 {
398 size_t skl;
399 size_t nextone;
400
401 ml = (buff[j] << 8) + buff[j + 1];
402 j += 2;
403
404 if (j + ml > l)
405 break;
406
407 nextone = j;
408 while (ml)
409 {
410 j = nextone;
411 skl = buff[j++];
412 if (!--ml)
413 break;
414
415 if (skl >= 192)
416 {
417 skl = (skl - 192) * 256 + buff[j++] + 192;
418 if (!--ml)
419 break;
420 }
421
422 if ((int) ml - (int) skl < 0)
423 break;
424 ml -= skl;
425
426 nextone = j + skl;
427 skt = buff[j++];
428
429 switch (skt & 0x7f)
430 {
431 case 2: /* creation time */
432 {
433 if (skl < 4)
434 break;
435 sig_gen_time = 0;
436 for (i = 0; i < 4; i++)
437 sig_gen_time = (sig_gen_time << 8) + buff[j++];
438
439 break;
440 }
441 case 3: /* expiration time */
442 {
443 if (skl < 4)
444 break;
445 validity = 0;
446 for (i = 0; i < 4; i++)
447 validity = (validity << 8) + buff[j++];
448 break;
449 }
450 case 9: /* key expiration time */
451 {
452 if (skl < 4)
453 break;
454 key_validity = 0;
455 for (i = 0; i < 4; i++)
456 key_validity = (key_validity << 8) + buff[j++];
457 break;
458 }
459 case 16: /* issuer key ID */
460 {
461 if (skl < 8)
462 break;
463 signerid2 = signerid1 = 0;
464 for (i = 0; i < 4; i++)
465 signerid1 = (signerid1 << 8) + buff[j++];
466 for (i = 0; i < 4; i++)
467 signerid2 = (signerid2 << 8) + buff[j++];
468
469 break;
470 }
471 case 10: /* CMR key */
472 break;
473 case 4: /* exportable */
474 case 5: /* trust */
475 case 6: /* regexp */
476 case 7: /* revocable */
477 case 11: /* Pref. symm. alg. */
478 case 12: /* revocation key */
479 case 20: /* notation data */
480 case 21: /* pref. hash */
481 case 22: /* pref. comp.alg. */
482 case 23: /* key server prefs. */
483 case 24: /* pref. key server */
484 default:
485 {
486 if (skt & 0x80)
487 have_critical_spks = 1;
488 }
489 }
490 }
491 j = nextone;
492 }
493
494 if (sigtype == 0x20 || sigtype == 0x28)
495 p->flags |= KEYFLAG_REVOKED;
496 if (key_validity != -1 && time (NULL) > p->gen_time + key_validity)
497 p->flags |= KEYFLAG_EXPIRED;
498 if (have_critical_spks)
499 p->flags |= KEYFLAG_CRITICAL;
500
501 if (s)
502 {
503 s->sigtype = sigtype;
504 s->sid1 = signerid1;
505 s->sid2 = signerid2;
506 }
507
508
509 return 0;
510
511 }
512
513
514 static int pgp_parse_sig (unsigned char *buff, size_t l, pgp_key_t * p, pgp_sig_t *sig)
515 {
516 if (!buff || l < 2 || !p)
517 return -1;
518
519 switch (buff[1])
520 {
521 case 2:
522 case 3:
523 return pgp_parse_pgp2_sig (buff, l, p, sig);
524 case 4:
525 return pgp_parse_pgp3_sig (buff, l, p, sig);
526 default:
527 return -1;
528 }
529 }
530
531 /* parse one key block, including all subkeys. */
532
533 static pgp_key_t *pgp_parse_keyblock (FILE * fp)
534 {
535 unsigned char *buff;
536 unsigned char pt = 0;
537 unsigned char last_pt;
538 size_t l;
539 short err = 0;
540
541 #ifdef HAVE_FGETPOS
542 fpos_t pos;
543 #else
544 long pos;
545 #endif
546
547 pgp_key_t *root = NULL;
548 pgp_key_t **last = &root;
549 pgp_key_t *p = NULL;
550 pgp_uid_t *uid = NULL;
551 pgp_uid_t **addr = NULL;
552 pgp_sig_t **lsig = NULL;
553
554 FGETPOS(fp,pos);
555
556 while (!err && (buff = pgp_read_packet (fp, &l)) != NULL)
557 {
558 last_pt = pt;
559 pt = buff[0] & 0x3f;
560
561 /* check if we have read the complete key block. */
562
563 if ((pt == PT_SECKEY || pt == PT_PUBKEY) && root)
564 {
565 FSETPOS(fp, pos);
566 return root;
567 }
568
569 switch (pt)
570 {
571 case PT_SECKEY:
572 case PT_PUBKEY:
573 case PT_SUBKEY:
574 case PT_SUBSECKEY:
575 {
576 if (!(*last = p = pgp_parse_keyinfo (buff, l)))
577 {
578 err = 1;
579 break;
580 }
581
582 last = &p->next;
583 addr = &p->address;
584 lsig = &p->sigs;
585
586 if (pt == PT_SUBKEY || pt == PT_SUBSECKEY)
587 {
588 p->flags |= KEYFLAG_SUBKEY;
589 if (p != root)
590 {
591 p->parent = root;
592 p->address = pgp_copy_uids (root->address, p);
593 while (*addr) addr = &(*addr)->next;
594 }
595 }
596
597 if (pt == PT_SECKEY || pt == PT_SUBSECKEY)
598 p->flags |= KEYFLAG_SECRET;
599
600 break;
601 }
602
603 case PT_SIG:
604 {
605 if (lsig)
606 {
607 pgp_sig_t *signature = safe_calloc (sizeof (pgp_sig_t), 1);
608 *lsig = signature;
609 lsig = &signature->next;
610
611 pgp_parse_sig (buff, l, p, signature);
612 }
613 break;
614 }
615
616 case PT_TRUST:
617 {
618 if (p && (last_pt == PT_SECKEY || last_pt == PT_PUBKEY ||
619 last_pt == PT_SUBKEY || last_pt == PT_SUBSECKEY))
620 {
621 if (buff[1] & 0x20)
622 {
623 p->flags |= KEYFLAG_DISABLED;
624 }
625 }
626 else if (last_pt == PT_NAME && uid)
627 {
628 uid->trust = buff[1];
629 }
630 break;
631 }
632 case PT_NAME:
633 {
634 char *chr;
635
636
637 if (!addr)
638 break;
639
640 chr = safe_malloc (l);
641 memcpy (chr, buff + 1, l - 1);
642 chr[l - 1] = '\0';
643
644
645 *addr = uid = safe_calloc (1, sizeof (pgp_uid_t)); /* XXX */
646 uid->addr = chr;
647 uid->parent = p;
648 uid->trust = 0;
649 addr = &uid->next;
650 lsig = &uid->sigs;
651
652 /* the following tags are generated by
653 * pgp 2.6.3in.
654 */
655
656 if (strstr (chr, "ENCR"))
657 p->flags |= KEYFLAG_PREFER_ENCRYPTION;
658 if (strstr (chr, "SIGN"))
659 p->flags |= KEYFLAG_PREFER_SIGNING;
660
661 break;
662 }
663 }
664
665 FGETPOS(fp,pos);
666 }
667
668 if (err)
669 pgp_free_key (&root);
670
671 return root;
672 }
673
674 static int pgpring_string_matches_hint (const char *s, const char *hints[], int nhints)
675 {
676 int i;
677
678 if (!hints || !nhints)
679 return 1;
680
681 for (i = 0; i < nhints; i++)
682 {
683 if (mutt_stristr (s, hints[i]) != NULL)
684 return 1;
685 }
686
687 return 0;
688 }
689
690 /*
691 * Go through the key ring file and look for keys with
692 * matching IDs.
693 */
694
695 static void pgpring_find_candidates (char *ringfile, const char *hints[], int nhints)
696 {
697 FILE *rfp;
698 #ifdef HAVE_FGETPOS
699 fpos_t pos, keypos;
700 #else
701 long pos, keypos;
702 #endif
703
704 unsigned char *buff = NULL;
705 unsigned char pt = 0;
706 size_t l = 0;
707
708 short err = 0;
709
710 if ((rfp = fopen (ringfile, "r")) == NULL)
711 {
712 perror ("fopen");
713 return;
714 }
715
716 FGETPOS(rfp,pos);
717 FGETPOS(rfp,keypos);
718
719 while (!err && (buff = pgp_read_packet (rfp, &l)) != NULL)
720 {
721 pt = buff[0] & 0x3f;
722
723 if (l < 1)
724 continue;
725
726 if ((pt == PT_SECKEY) || (pt == PT_PUBKEY))
727 {
728 keypos = pos;
729 }
730 else if (pt == PT_NAME)
731 {
732 char *tmp = safe_malloc (l);
733
734 memcpy (tmp, buff + 1, l - 1);
735 tmp[l - 1] = '\0';
736
737 /* mutt_decode_utf8_string (tmp, chs); */
738
739 if (pgpring_string_matches_hint (tmp, hints, nhints))
740 {
741 pgp_key_t *p;
742
743 FSETPOS(rfp, keypos);
744
745 /* Not bailing out here would lead us into an endless loop. */
746
747 if ((p = pgp_parse_keyblock (rfp)) == NULL)
748 err = 1;
749
750 pgpring_dump_keyblock (p);
751 pgp_free_key (&p);
752 }
753
754 safe_free (&tmp);
755 }
756
757 FGETPOS(rfp,pos);
758 }
759
760 fclose (rfp);
761
762 }
763
764 static void print_userid (const char *id)
765 {
766 for (; id && *id; id++)
767 {
768 if (*id >= ' ' && *id <= 'z' && *id != ':')
769 putchar (*id);
770 else
771 printf ("\\x%02x", *id);
772 }
773 }
774
775 static void pgpring_dump_signatures (pgp_sig_t *sig)
776 {
777 for (; sig; sig = sig->next)
778 {
779 if (sig->sigtype == 0x10 || sig->sigtype == 0x11 ||
780 sig->sigtype == 0x12 || sig->sigtype == 0x13)
781 printf ("sig::::%08lX%08lX::::::%X:\n",
782 sig->sid1, sig->sid2, sig->sigtype);
783 else if (sig->sigtype == 0x20)
784 printf ("rev::::%08lX%08lX::::::%X:\n",
785 sig->sid1, sig->sid2, sig->sigtype);
786 }
787 }
788
789
790 static char gnupg_trustletter (int t)
791 {
792 switch (t)
793 {
794 case 1: return 'n';
795 case 2: return 'm';
796 case 3: return 'f';
797 }
798 return 'q';
799 }
800
801 static void pgpring_dump_keyblock (pgp_key_t *p)
802 {
803 pgp_uid_t *uid;
804 short first;
805 struct tm *tp;
806 time_t t;
807
808 for (; p; p = p->next)
809 {
810 first = 1;
811
812 if (p->flags & KEYFLAG_SECRET)
813 {
814 if (p->flags & KEYFLAG_SUBKEY)
815 printf ("ssb:");
816 else
817 printf ("sec:");
818 }
819 else
820 {
821 if (p->flags & KEYFLAG_SUBKEY)
822 printf ("sub:");
823 else
824 printf ("pub:");
825 }
826
827 if (p->flags & KEYFLAG_REVOKED)
828 putchar ('r');
829 if (p->flags & KEYFLAG_EXPIRED)
830 putchar ('e');
831 if (p->flags & KEYFLAG_DISABLED)
832 putchar ('d');
833
834 for (uid = p->address; uid; uid = uid->next, first = 0)
835 {
836 if (!first)
837 {
838 printf ("uid:%c::::::::", gnupg_trustletter (uid->trust));
839 print_userid (uid->addr);
840 printf (":\n");
841 }
842 else
843 {
844 if (p->flags & KEYFLAG_SECRET)
845 putchar ('u');
846 else
847 putchar (gnupg_trustletter (uid->trust));
848
849 t = p->gen_time;
850 tp = gmtime (&t);
851
852 printf (":%d:%d:%s:%04d-%02d-%02d::::", p->keylen, p->numalg, p->keyid,
853 1900 + tp->tm_year, tp->tm_mon + 1, tp->tm_mday);
854
855 print_userid (uid->addr);
856 printf (":\n");
857 }
858
859 if (dump_signatures)
860 {
861 if (first) pgpring_dump_signatures (p->sigs);
862 pgpring_dump_signatures (uid->sigs);
863 }
864 }
865 }
866 }
867
868 /*
869 * The mutt_gettext () defined in gettext.c requires iconv,
870 * so we do without charset conversion here.
871 */
872
873 char *mutt_gettext (const char *message)
874 {
875 return (char *)message;
876 }