]> granicus.if.org Git - mutt/blob - pgpkey.c
Convert smime_invoke_import() and helpers to use buffer pool.
[mutt] / pgpkey.c
1 /*
2  * Copyright (C) 1996-1997,2007 Michael R. Elkins <me@mutt.org>
3  * Copyright (c) 1998-2003 Thomas Roessler <roessler@does-not-exist.org>
4  *
5  *     This program is free software; you can redistribute it
6  *     and/or modify it under the terms of the GNU General Public
7  *     License as published by the Free Software Foundation; either
8  *     version 2 of the License, or (at your option) any later
9  *     version.
10  *
11  *     This program is distributed in the hope that it will be
12  *     useful, but WITHOUT ANY WARRANTY; without even the implied
13  *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  *     PURPOSE.  See the GNU General Public License for more
15  *     details.
16  *
17  *     You should have received a copy of the GNU General Public
18  *     License along with this program; if not, write to the Free
19  *     Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  *     Boston, MA  02110-1301, USA.
21  */
22
23 #if HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #include "mutt.h"
28 #include "mutt_curses.h"
29 #include "mutt_menu.h"
30 #include "mime.h"
31 #include "pgp.h"
32 #include "pager.h"
33 #include "sort.h"
34
35 #include <string.h>
36 #include <ctype.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <sys/stat.h>
40 #include <sys/wait.h>
41
42 #include <locale.h>
43
44 #ifdef CRYPT_BACKEND_CLASSIC_PGP
45
46 struct pgp_cache
47 {
48   char *what;
49   char *dflt;
50   struct pgp_cache *next;
51 };
52
53 static struct pgp_cache *id_defaults = NULL;
54
55 static const char trust_flags[] = "?- +";
56
57 static char *pgp_key_abilities (int flags)
58 {
59   static char buff[3];
60
61   if (!(flags & KEYFLAG_CANENCRYPT))
62     buff[0] = '-';
63   else if (flags & KEYFLAG_PREFER_SIGNING)
64     buff[0] = '.';
65   else
66     buff[0] = 'e';
67
68   if (!(flags & KEYFLAG_CANSIGN))
69     buff[1] = '-';
70   else if (flags & KEYFLAG_PREFER_ENCRYPTION)
71     buff[1] = '.';
72   else
73     buff[1] = 's';
74
75   buff[2] = '\0';
76
77   return buff;
78 }
79
80 static char pgp_flags (int flags)
81 {
82   if (flags & KEYFLAG_REVOKED)
83     return 'R';
84   else if (flags & KEYFLAG_EXPIRED)
85     return 'X';
86   else if (flags & KEYFLAG_DISABLED)
87     return 'd';
88   else if (flags & KEYFLAG_CRITICAL)
89     return 'c';
90   else
91     return ' ';
92 }
93
94 static pgp_key_t pgp_principal_key (pgp_key_t key)
95 {
96   if (key->flags & KEYFLAG_SUBKEY && key->parent)
97     return key->parent;
98   else
99     return key;
100 }
101
102 /*
103  * Format an entry on the PGP key selection menu.
104  *
105  * %n   number
106  * %k   key id          %K      key id of the principal key
107  * %u   user id
108  * %a   algorithm       %A      algorithm of the princ. key
109  * %l   length          %L      length of the princ. key
110  * %f   flags           %F      flags of the princ. key
111  * %c   capabilities    %C      capabilities of the princ. key
112  * %t   trust/validity of the key-uid association
113  * %[...] date of key using strftime(3)
114  */
115
116 typedef struct pgp_entry
117 {
118   size_t num;
119   pgp_uid_t *uid;
120 } pgp_entry_t;
121
122 static const char *pgp_entry_fmt (char *dest,
123                                   size_t destlen,
124                                   size_t col,
125                                   int cols,
126                                   char op,
127                                   const char *src,
128                                   const char *prefix,
129                                   const char *ifstring,
130                                   const char *elsestring,
131                                   unsigned long data,
132                                   format_flag flags)
133 {
134   char fmt[16];
135   pgp_entry_t *entry;
136   pgp_uid_t *uid;
137   pgp_key_t key, pkey;
138   int kflags = 0;
139   int optional = (flags & MUTT_FORMAT_OPTIONAL);
140
141   entry = (pgp_entry_t *) data;
142   uid   = entry->uid;
143   key   = uid->parent;
144   pkey  = pgp_principal_key (key);
145
146   if (isupper ((unsigned char) op))
147     key = pkey;
148
149   kflags = key->flags | (pkey->flags & KEYFLAG_RESTRICTIONS)
150     | uid->flags;
151
152   switch (ascii_tolower (op))
153   {
154     case '[':
155
156     {
157       const char *cp;
158       char buf2[SHORT_STRING], *p;
159       int do_locales;
160       struct tm *tm;
161       size_t len;
162
163       p = dest;
164
165       cp = src;
166       if (*cp == '!')
167       {
168         do_locales = 0;
169         cp++;
170       }
171       else
172         do_locales = 1;
173
174       len = destlen - 1;
175       while (len > 0 && *cp != ']')
176       {
177         if (*cp == '%')
178         {
179           cp++;
180           if (len >= 2)
181           {
182             *p++ = '%';
183             *p++ = *cp;
184             len -= 2;
185           }
186           else
187             break; /* not enough space */
188           cp++;
189         }
190         else
191         {
192           *p++ = *cp++;
193           len--;
194         }
195       }
196       *p = 0;
197
198
199       tm = localtime (&key->gen_time);
200
201       if (!do_locales)
202         setlocale (LC_TIME, "C");
203       strftime (buf2, sizeof (buf2), dest, tm);
204       if (!do_locales)
205         setlocale (LC_TIME, "");
206
207       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
208       snprintf (dest, destlen, fmt, buf2);
209       if (len > 0)
210         src = cp + 1;
211     }
212     break;
213     case 'n':
214       if (!optional)
215       {
216         snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
217         snprintf (dest, destlen, fmt, entry->num);
218       }
219       break;
220     case 'k':
221       if (!optional)
222       {
223         snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
224         snprintf (dest, destlen, fmt, _pgp_keyid (key));
225       }
226       break;
227     case 'u':
228       if (!optional)
229       {
230         snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
231         snprintf (dest, destlen, fmt, NONULL (uid->addr));
232       }
233       break;
234     case 'a':
235       if (!optional)
236       {
237         snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
238         snprintf (dest, destlen, fmt, key->algorithm);
239       }
240       break;
241     case 'l':
242       if (!optional)
243       {
244         snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
245         snprintf (dest, destlen, fmt, key->keylen);
246       }
247       break;
248     case 'f':
249       if (!optional)
250       {
251         snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
252         snprintf (dest, destlen, fmt, pgp_flags (kflags));
253       }
254       else if (!(kflags & (KEYFLAG_RESTRICTIONS)))
255         optional = 0;
256       break;
257     case 'c':
258       if (!optional)
259       {
260         snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
261         snprintf (dest, destlen, fmt, pgp_key_abilities (kflags));
262       }
263       else if (!(kflags & (KEYFLAG_ABILITIES)))
264         optional = 0;
265       break;
266     case 't':
267       if (!optional)
268       {
269         snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
270         snprintf (dest, destlen, fmt, trust_flags[uid->trust & 0x03]);
271       }
272       else if (!(uid->trust & 0x03))
273         /* undefined trust */
274         optional = 0;
275       break;
276     default:
277       *dest = '\0';
278   }
279
280   if (optional)
281     mutt_FormatString (dest, destlen, col, cols, ifstring, mutt_attach_fmt, data, 0);
282   else if (flags & MUTT_FORMAT_OPTIONAL)
283     mutt_FormatString (dest, destlen, col, cols, elsestring, mutt_attach_fmt, data, 0);
284   return (src);
285 }
286
287 static void pgp_entry (char *s, size_t l, MUTTMENU * menu, int num)
288 {
289   pgp_uid_t **KeyTable = (pgp_uid_t **) menu->data;
290   pgp_entry_t entry;
291
292   entry.uid = KeyTable[num];
293   entry.num = num + 1;
294
295   mutt_FormatString (s, l, 0, MuttIndexWindow->cols, NONULL (PgpEntryFormat), pgp_entry_fmt,
296                      (unsigned long) &entry, MUTT_FORMAT_ARROWCURSOR);
297 }
298
299 static int _pgp_compare_address (const void *a, const void *b)
300 {
301   int r;
302
303   pgp_uid_t **s = (pgp_uid_t **) a;
304   pgp_uid_t **t = (pgp_uid_t **) b;
305
306   if ((r = mutt_strcasecmp ((*s)->addr, (*t)->addr)))
307     return r > 0;
308   else
309     return (mutt_strcasecmp (pgp_fpr_or_lkeyid ((*s)->parent),
310                              pgp_fpr_or_lkeyid ((*t)->parent)) > 0);
311 }
312
313 static int pgp_compare_address (const void *a, const void *b)
314 {
315   return ((PgpSortKeys & SORT_REVERSE) ? !_pgp_compare_address (a, b)
316           : _pgp_compare_address (a, b));
317 }
318
319
320
321 static int _pgp_compare_keyid (const void *a, const void *b)
322 {
323   int r;
324
325   pgp_uid_t **s = (pgp_uid_t **) a;
326   pgp_uid_t **t = (pgp_uid_t **) b;
327
328   if ((r = mutt_strcasecmp (pgp_fpr_or_lkeyid ((*s)->parent),
329                             pgp_fpr_or_lkeyid ((*t)->parent))))
330     return r > 0;
331   else
332     return (mutt_strcasecmp ((*s)->addr, (*t)->addr)) > 0;
333 }
334
335 static int pgp_compare_keyid (const void *a, const void *b)
336 {
337   return ((PgpSortKeys & SORT_REVERSE) ? !_pgp_compare_keyid (a, b)
338           : _pgp_compare_keyid (a, b));
339 }
340
341 static int _pgp_compare_date (const void *a, const void *b)
342 {
343   int r;
344   pgp_uid_t **s = (pgp_uid_t **) a;
345   pgp_uid_t **t = (pgp_uid_t **) b;
346
347   if ((r = ((*s)->parent->gen_time - (*t)->parent->gen_time)))
348     return r > 0;
349   return (mutt_strcasecmp ((*s)->addr, (*t)->addr)) > 0;
350 }
351
352 static int pgp_compare_date (const void *a, const void *b)
353 {
354   return ((PgpSortKeys & SORT_REVERSE) ? !_pgp_compare_date (a, b)
355           : _pgp_compare_date (a, b));
356 }
357
358 static int _pgp_compare_trust (const void *a, const void *b)
359 {
360   int r;
361
362   pgp_uid_t **s = (pgp_uid_t **) a;
363   pgp_uid_t **t = (pgp_uid_t **) b;
364
365   if ((r = (((*s)->parent->flags & (KEYFLAG_RESTRICTIONS))
366             - ((*t)->parent->flags & (KEYFLAG_RESTRICTIONS)))))
367     return r > 0;
368   if ((r = ((*s)->trust - (*t)->trust)))
369     return r < 0;
370   if ((r = ((*s)->parent->keylen - (*t)->parent->keylen)))
371     return r < 0;
372   if ((r = ((*s)->parent->gen_time - (*t)->parent->gen_time)))
373     return r < 0;
374   if ((r = mutt_strcasecmp ((*s)->addr, (*t)->addr)))
375     return r > 0;
376   return (mutt_strcasecmp (pgp_fpr_or_lkeyid ((*s)->parent),
377                            pgp_fpr_or_lkeyid ((*t)->parent))) > 0;
378 }
379
380 static int pgp_compare_trust (const void *a, const void *b)
381 {
382   return ((PgpSortKeys & SORT_REVERSE) ? !_pgp_compare_trust (a, b)
383           : _pgp_compare_trust (a, b));
384 }
385
386 static int pgp_key_is_valid (pgp_key_t k)
387 {
388   pgp_key_t pk = pgp_principal_key (k);
389   if (k->flags & KEYFLAG_CANTUSE)
390     return 0;
391   if (pk->flags & KEYFLAG_CANTUSE)
392     return 0;
393
394   return 1;
395 }
396
397 static int pgp_id_is_strong (pgp_uid_t *uid)
398 {
399   if ((uid->trust & 3) < 3)
400     return 0;
401   /* else */
402   return 1;
403 }
404
405 static int pgp_id_is_valid (pgp_uid_t *uid)
406 {
407   if (!pgp_key_is_valid (uid->parent))
408     return 0;
409   if (uid->flags & KEYFLAG_CANTUSE)
410     return 0;
411   /* else */
412   return 1;
413 }
414
415 #define PGP_KV_VALID    1
416 #define PGP_KV_ADDR     2
417 #define PGP_KV_STRING   4
418 #define PGP_KV_STRONGID 8
419
420 #define PGP_KV_MATCH (PGP_KV_ADDR|PGP_KV_STRING)
421
422 static int pgp_id_matches_addr (ADDRESS *addr, ADDRESS *u_addr, pgp_uid_t *uid)
423 {
424   int rv = 0;
425
426   if (pgp_id_is_valid (uid))
427     rv |= PGP_KV_VALID;
428
429   if (pgp_id_is_strong (uid))
430     rv |= PGP_KV_STRONGID;
431
432   if (addr->mailbox && u_addr->mailbox
433       && mutt_strcasecmp (addr->mailbox, u_addr->mailbox) == 0)
434     rv |= PGP_KV_ADDR;
435
436   if (addr->personal && u_addr->personal
437       && mutt_strcasecmp (addr->personal, u_addr->personal) == 0)
438     rv |= PGP_KV_STRING;
439
440   return rv;
441 }
442
443 static pgp_key_t pgp_select_key (pgp_key_t keys,
444                                  ADDRESS * p, const char *s)
445 {
446   int keymax;
447   pgp_uid_t **KeyTable;
448   MUTTMENU *menu;
449   int i, done = 0;
450   char helpstr[LONG_STRING], buf[LONG_STRING], tmpbuf[STRING];
451   char cmd[LONG_STRING];
452   BUFFER *tempfile;
453   FILE *fp, *devnull;
454   pid_t thepid;
455   pgp_key_t kp;
456   pgp_uid_t *a;
457   int (*f) (const void *, const void *);
458
459   int unusable = 0;
460
461   keymax = 0;
462   KeyTable = NULL;
463
464   for (i = 0, kp = keys; kp; kp = kp->next)
465   {
466     if (!option (OPTPGPSHOWUNUSABLE) && (kp->flags & KEYFLAG_CANTUSE))
467     {
468       unusable = 1;
469       continue;
470     }
471
472     for (a = kp->address; a; a = a->next)
473     {
474       if (!option (OPTPGPSHOWUNUSABLE) && (a->flags & KEYFLAG_CANTUSE))
475       {
476         unusable = 1;
477         continue;
478       }
479
480       if (i == keymax)
481       {
482         keymax += 5;
483         safe_realloc (&KeyTable, sizeof (pgp_uid_t *) * keymax);
484       }
485
486       KeyTable[i++] = a;
487     }
488   }
489
490   if (!i && unusable)
491   {
492     mutt_error _("All matching keys are expired, revoked, or disabled.");
493     mutt_sleep (1);
494     return NULL;
495   }
496
497   switch (PgpSortKeys & SORT_MASK)
498   {
499     case SORT_DATE:
500       f = pgp_compare_date;
501       break;
502     case SORT_KEYID:
503       f = pgp_compare_keyid;
504       break;
505     case SORT_ADDRESS:
506       f = pgp_compare_address;
507       break;
508     case SORT_TRUST:
509     default:
510       f = pgp_compare_trust;
511       break;
512   }
513   qsort (KeyTable, i, sizeof (pgp_uid_t *), f);
514
515   helpstr[0] = 0;
516   mutt_make_help (buf, sizeof (buf), _("Exit  "), MENU_PGP, OP_EXIT);
517   strcat (helpstr, buf);        /* __STRCAT_CHECKED__ */
518   mutt_make_help (buf, sizeof (buf), _("Select  "), MENU_PGP,
519                   OP_GENERIC_SELECT_ENTRY);
520   strcat (helpstr, buf);        /* __STRCAT_CHECKED__ */
521   mutt_make_help (buf, sizeof (buf), _("Check key  "), MENU_PGP, OP_VERIFY_KEY);
522   strcat (helpstr, buf);        /* __STRCAT_CHECKED__ */
523   mutt_make_help (buf, sizeof (buf), _("Help"), MENU_PGP, OP_HELP);
524   strcat (helpstr, buf);        /* __STRCAT_CHECKED__ */
525
526   menu = mutt_new_menu (MENU_PGP);
527   menu->max = i;
528   menu->make_entry = pgp_entry;
529   menu->help = helpstr;
530   menu->data = KeyTable;
531   mutt_push_current_menu (menu);
532
533   if (p)
534     snprintf (buf, sizeof (buf), _("PGP keys matching <%s>."), p->mailbox);
535   else
536     snprintf (buf, sizeof (buf), _("PGP keys matching \"%s\"."), s);
537
538
539   menu->title = buf;
540
541   kp = NULL;
542
543   mutt_clear_error ();
544
545   while (!done)
546   {
547     switch (mutt_menuLoop (menu))
548     {
549
550       case OP_VERIFY_KEY:
551         if ((devnull = fopen ("/dev/null", "w")) == NULL)       /* __FOPEN_CHECKED__ */
552         {
553           mutt_perror _("Can't open /dev/null");
554           break;
555         }
556
557         tempfile = mutt_buffer_pool_get ();
558         mutt_buffer_mktemp (tempfile);
559         if ((fp = safe_fopen (mutt_b2s (tempfile), "w")) == NULL)
560         {
561           mutt_perror _("Can't create temporary file");
562           safe_fclose (&devnull);
563           mutt_buffer_pool_release (&tempfile);
564           break;
565         }
566
567         mutt_message _("Invoking PGP...");
568
569         snprintf (tmpbuf, sizeof (tmpbuf), "0x%s",
570                   pgp_fpr_or_lkeyid (pgp_principal_key (KeyTable[menu->current]->parent)));
571
572         if ((thepid = pgp_invoke_verify_key (NULL, NULL, NULL, -1,
573                                              fileno (fp), fileno (devnull), tmpbuf)) == -1)
574         {
575           mutt_perror _("Can't create filter");
576           unlink (mutt_b2s (tempfile));
577           mutt_buffer_pool_release (&tempfile);
578           safe_fclose (&fp);
579           safe_fclose (&devnull);
580           break;
581         }
582
583         mutt_wait_filter (thepid);
584         safe_fclose (&fp);
585         safe_fclose (&devnull);
586         mutt_clear_error ();
587         snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"),
588                   pgp_keyid (pgp_principal_key (KeyTable[menu->current]->parent)));
589         mutt_do_pager (cmd, mutt_b2s (tempfile), 0, NULL);
590         mutt_buffer_pool_release (&tempfile);
591         menu->redraw = REDRAW_FULL;
592
593         break;
594
595       case OP_VIEW_ID:
596
597         mutt_message ("%s", NONULL (KeyTable[menu->current]->addr));
598         break;
599
600       case OP_GENERIC_SELECT_ENTRY:
601
602
603         /* XXX make error reporting more verbose */
604
605         if (option (OPTPGPCHECKTRUST))
606           if (!pgp_key_is_valid (KeyTable[menu->current]->parent))
607           {
608             mutt_error _("This key can't be used: expired/disabled/revoked.");
609             break;
610           }
611
612         if (option (OPTPGPCHECKTRUST) &&
613             (!pgp_id_is_valid (KeyTable[menu->current])
614              || !pgp_id_is_strong (KeyTable[menu->current])))
615         {
616           char *s = "";
617           char buff[LONG_STRING];
618
619           if (KeyTable[menu->current]->flags & KEYFLAG_CANTUSE)
620             s = N_("ID is expired/disabled/revoked.");
621           else switch (KeyTable[menu->current]->trust & 0x03)
622                {
623                  case 0:
624                    s = N_("ID has undefined validity.");
625                    break;
626                  case 1:
627                    s = N_("ID is not valid.");
628                    break;
629                  case 2:
630                    s = N_("ID is only marginally valid.");
631                    break;
632                }
633
634           snprintf (buff, sizeof (buff), _("%s Do you really want to use the key?"),
635                     _(s));
636
637           if (mutt_yesorno (buff, MUTT_NO) != MUTT_YES)
638           {
639             mutt_clear_error ();
640             break;
641           }
642         }
643
644 # if 0
645         kp = pgp_principal_key (KeyTable[menu->current]->parent);
646 # else
647         kp = KeyTable[menu->current]->parent;
648 # endif
649         done = 1;
650         break;
651
652       case OP_EXIT:
653
654         kp = NULL;
655         done = 1;
656         break;
657     }
658   }
659
660   mutt_pop_current_menu (menu);
661   mutt_menuDestroy (&menu);
662   FREE (&KeyTable);
663
664   return (kp);
665 }
666
667 pgp_key_t pgp_ask_for_key (char *tag, char *whatfor,
668                            short abilities, pgp_ring_t keyring)
669 {
670   pgp_key_t key;
671   char resp[SHORT_STRING];
672   struct pgp_cache *l = NULL;
673
674   mutt_clear_error ();
675
676   resp[0] = 0;
677   if (whatfor)
678   {
679
680     for (l = id_defaults; l; l = l->next)
681       if (!mutt_strcasecmp (whatfor, l->what))
682       {
683         strfcpy (resp, NONULL (l->dflt), sizeof (resp));
684         break;
685       }
686   }
687
688
689   FOREVER
690   {
691     resp[0] = 0;
692     if (mutt_get_field (tag, resp, sizeof (resp), MUTT_CLEAR) != 0)
693       return NULL;
694
695     if (whatfor)
696     {
697       if (l)
698         mutt_str_replace (&l->dflt, resp);
699       else
700       {
701         l = safe_malloc (sizeof (struct pgp_cache));
702         l->next = id_defaults;
703         id_defaults = l;
704         l->what = safe_strdup (whatfor);
705         l->dflt = safe_strdup (resp);
706       }
707     }
708
709     if ((key = pgp_getkeybystr (resp, abilities, keyring)))
710       return key;
711
712     BEEP ();
713   }
714   /* not reached */
715 }
716
717 /* generate a public key attachment */
718
719 BODY *pgp_make_key_attachment (void)
720 {
721   BODY *att = NULL;
722   char buff[LONG_STRING], tmp[STRING];
723   BUFFER *tempf = NULL;
724   FILE *tempfp;
725   FILE *devnull;
726   struct stat sb;
727   pid_t thepid;
728   pgp_key_t key;
729   unset_option (OPTPGPCHECKTRUST);
730
731   key = pgp_ask_for_key (_("Please enter the key ID: "), NULL, 0, PGP_PUBRING);
732   if (!key)
733     return NULL;
734
735   snprintf (tmp, sizeof (tmp), "0x%s", pgp_fpr_or_lkeyid (pgp_principal_key (key)));
736   pgp_free_key (&key);
737
738   tempf = mutt_buffer_pool_get ();
739   mutt_buffer_mktemp (tempf);
740   if ((tempfp = safe_fopen (mutt_b2s (tempf), "w")) == NULL)
741   {
742     mutt_perror _("Can't create temporary file");
743     goto cleanup;
744   }
745
746   if ((devnull = fopen ("/dev/null", "w")) == NULL)     /* __FOPEN_CHECKED__ */
747   {
748     mutt_perror _("Can't open /dev/null");
749     safe_fclose (&tempfp);
750     unlink (mutt_b2s (tempf));
751     goto cleanup;
752   }
753
754   mutt_message _("Invoking PGP...");
755
756
757   if ((thepid =
758        pgp_invoke_export (NULL, NULL, NULL, -1,
759                           fileno (tempfp), fileno (devnull), tmp)) == -1)
760   {
761     mutt_perror _("Can't create filter");
762     safe_fclose (&tempfp);
763     unlink (mutt_b2s (tempf));
764     safe_fclose (&devnull);
765     goto cleanup;
766   }
767
768   mutt_wait_filter (thepid);
769
770   safe_fclose (&tempfp);
771   safe_fclose (&devnull);
772
773   att = mutt_new_body ();
774   att->filename = safe_strdup (mutt_b2s (tempf));
775   att->unlink = 1;
776   att->use_disp = 0;
777   att->type = TYPEAPPLICATION;
778   att->subtype = safe_strdup ("pgp-keys");
779   snprintf (buff, sizeof (buff), _("PGP Key %s."), tmp);
780   att->description = safe_strdup (buff);
781   mutt_update_encoding (att);
782
783   stat (mutt_b2s (tempf), &sb);
784   att->length = sb.st_size;
785
786 cleanup:
787   mutt_buffer_pool_release (&tempf);
788   return att;
789 }
790
791 static LIST *pgp_add_string_to_hints (LIST *hints, const char *str)
792 {
793   char *scratch;
794   char *t;
795
796   if ((scratch = safe_strdup (str)) == NULL)
797     return hints;
798
799   for (t = strtok (scratch, " ,.:\"()<>\n"); t;
800        t = strtok (NULL, " ,.:\"()<>\n"))
801   {
802     if (strlen (t) > 3)
803       hints = mutt_add_list (hints, t);
804   }
805
806   FREE (&scratch);
807   return hints;
808 }
809
810 static pgp_key_t *pgp_get_lastp (pgp_key_t p)
811 {
812   for (; p; p = p->next)
813     if (!p->next)
814       return &p->next;
815
816   return NULL;
817 }
818
819 pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring,
820                             int oppenc_mode)
821 {
822   ADDRESS *r, *p;
823   LIST *hints = NULL;
824
825   int multi   = 0;
826   int match;
827
828   pgp_key_t keys, k, kn;
829   pgp_key_t the_strong_valid_key = NULL;
830   pgp_key_t a_valid_addrmatch_key = NULL;
831   pgp_key_t matches = NULL;
832   pgp_key_t *last = &matches;
833   pgp_uid_t *q;
834
835   if (a && a->mailbox)
836     hints = pgp_add_string_to_hints (hints, a->mailbox);
837   if (a && a->personal)
838     hints = pgp_add_string_to_hints (hints, a->personal);
839
840   if (! oppenc_mode )
841     mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
842   keys = pgp_get_candidates (keyring, hints);
843
844   mutt_free_list (&hints);
845
846   if (!keys)
847     return NULL;
848
849   dprint (5, (debugfile, "pgp_getkeybyaddr: looking for %s <%s>.",
850               a->personal, a->mailbox));
851
852
853   for (k = keys; k; k = kn)
854   {
855     kn = k->next;
856
857     dprint (5, (debugfile, "  looking at key: %s\n",
858                 pgp_keyid (k)));
859
860     if (abilities && !(k->flags & abilities))
861     {
862       dprint (5, (debugfile, "  insufficient abilities: Has %x, want %x\n",
863                   k->flags, abilities));
864       continue;
865     }
866
867     match                = 0;   /* any match              */
868
869     for (q = k->address; q; q = q->next)
870     {
871       r = rfc822_parse_adrlist (NULL, NONULL (q->addr));
872
873       for (p = r; p; p = p->next)
874       {
875         int validity = pgp_id_matches_addr (a, p, q);
876
877         if (validity & PGP_KV_MATCH)    /* something matches */
878           match = 1;
879
880         if ((validity & PGP_KV_VALID)
881             && (validity & PGP_KV_ADDR))
882         {
883           if (validity & PGP_KV_STRONGID)
884           {
885             if (the_strong_valid_key && the_strong_valid_key != k)
886               multi = 1;
887             the_strong_valid_key = k;
888           }
889           else
890           {
891             a_valid_addrmatch_key = k;
892           }
893         }
894       }
895
896       rfc822_free_address (&r);
897     }
898
899     if (match)
900     {
901       *last  = pgp_principal_key (k);
902       kn     = pgp_remove_key (&keys, *last);
903       last   = pgp_get_lastp (k);
904     }
905   }
906
907   pgp_free_key (&keys);
908
909   if (matches)
910   {
911     if (oppenc_mode)
912     {
913       if (the_strong_valid_key)
914       {
915         pgp_remove_key (&matches, the_strong_valid_key);
916         k = the_strong_valid_key;
917       }
918       else if (a_valid_addrmatch_key)
919       {
920         pgp_remove_key (&matches, a_valid_addrmatch_key);
921         k = a_valid_addrmatch_key;
922       }
923       else
924         k = NULL;
925     }
926     else if (the_strong_valid_key && !multi)
927     {
928       /*
929        * There was precisely one strong match on a valid ID.
930        *
931        * Proceed without asking the user.
932        */
933       pgp_remove_key (&matches, the_strong_valid_key);
934       k = the_strong_valid_key;
935     }
936     else
937     {
938       /*
939        * Else: Ask the user.
940        */
941       if ((k = pgp_select_key (matches, a, NULL)))
942         pgp_remove_key (&matches, k);
943     }
944
945     pgp_free_key (&matches);
946
947     return k;
948   }
949
950   return NULL;
951 }
952
953 pgp_key_t pgp_getkeybystr (char *p, short abilities, pgp_ring_t keyring)
954 {
955   LIST *hints = NULL;
956   pgp_key_t keys;
957   pgp_key_t matches = NULL;
958   pgp_key_t *last = &matches;
959   pgp_key_t k, kn;
960   pgp_uid_t *a;
961   short match;
962   size_t l;
963   const char *ps, *pl, *pfcopy, *phint;
964
965   if ((l = mutt_strlen (p)) && p[l-1] == '!')
966     p[l-1] = 0;
967
968   mutt_message (_("Looking for keys matching \"%s\"..."), p);
969
970   pfcopy = crypt_get_fingerprint_or_id (p, &phint, &pl, &ps);
971   hints = pgp_add_string_to_hints (hints, phint);
972   keys = pgp_get_candidates (keyring, hints);
973   mutt_free_list (&hints);
974
975   if (!keys)
976     goto out;
977
978   for (k = keys; k; k = kn)
979   {
980     kn = k->next;
981     if (abilities && !(k->flags & abilities))
982       continue;
983
984     /* This shouldn't happen, but keys without any addresses aren't selectable
985      * in pgp_select_key().
986      */
987     if (!k->address)
988       continue;
989
990     match = 0;
991
992     dprint (5, (debugfile, "pgp_getkeybystr: matching \"%s\" against key %s:\n",
993                 p, pgp_long_keyid (k)));
994
995     if (!*p ||
996         (pfcopy && mutt_strcasecmp (pfcopy, k->fingerprint) == 0) ||
997         (pl && mutt_strcasecmp (pl, pgp_long_keyid (k)) == 0) ||
998         (ps && mutt_strcasecmp (ps, pgp_short_keyid (k)) == 0))
999     {
1000       dprint (5, (debugfile, "\t\tmatch.\n"));
1001       match = 1;
1002     }
1003     else
1004     {
1005       for (a = k->address; a; a = a->next)
1006       {
1007         dprint (5, (debugfile, "pgp_getkeybystr: matching \"%s\" against key %s, \"%s\":\n",
1008                     p, pgp_long_keyid (k), NONULL (a->addr)));
1009         if (mutt_stristr (a->addr, p))
1010         {
1011           dprint (5, (debugfile, "\t\tmatch.\n"));
1012           match = 1;
1013           break;
1014         }
1015       }
1016     }
1017
1018     if (match)
1019     {
1020       *last = pgp_principal_key (k);
1021       kn    = pgp_remove_key (&keys, *last);
1022       last  = pgp_get_lastp (k);
1023     }
1024   }
1025
1026   pgp_free_key (&keys);
1027
1028   if (matches)
1029   {
1030     if ((k = pgp_select_key (matches, NULL, p)))
1031       pgp_remove_key (&matches, k);
1032
1033     pgp_free_key (&matches);
1034     FREE (&pfcopy);
1035     if (l && !p[l-1])
1036       p[l-1] = '!';
1037     return k;
1038   }
1039
1040 out:
1041   FREE (&pfcopy);
1042   if (l && !p[l-1])
1043     p[l-1] = '!';
1044   return NULL;
1045 }
1046
1047 #endif /* CRYPT_BACKEND_CLASSIC_PGP */