1 /* crypt-gpgme.c - GPGME based crypto operations
2 * Copyright (C) 1996-7,2007 Michael R. Elkins <me@cs.hmc.edu>
3 * Copyright (C) 1998,1999,2000 Thomas Roessler <roessler@does-not-exist.org>
4 * Copyright (C) 2001 Thomas Roessler <roessler@does-not-exist.org>
5 * Oliver Ehli <elmy@acm.org>
6 * Copyright (C) 2002, 2003, 2004 g10 Code GmbH
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 #ifdef CRYPT_BACKEND_GPGME
30 #include "mutt_crypt.h"
31 #include "mutt_menu.h"
32 #include "mutt_curses.h"
51 #ifdef HAVE_LANGINFO_D_T_FMT
55 #ifdef HAVE_SYS_TIME_H
56 # include <sys/time.h>
59 #ifdef HAVE_SYS_RESOURCE_H
60 # include <sys/resource.h>
66 #define digitp(p) (*(p) >= '0' && *(p) <= '9')
67 #define hexdigitp(a) (digitp (a) \
68 || (*(a) >= 'A' && *(a) <= 'F') \
69 || (*(a) >= 'a' && *(a) <= 'f'))
70 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
71 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
72 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
74 #define PKA_NOTATION_NAME "pka-address@gnupg.org"
75 #define is_pka_notation(notation) (! strcmp ((notation)->name, \
78 /* Values used for comparing addresses. */
79 #define CRYPT_KV_VALID 1
80 #define CRYPT_KV_ADDR 2
81 #define CRYPT_KV_STRING 4
82 #define CRYPT_KV_STRONGID 8
83 #define CRYPT_KV_MATCH (CRYPT_KV_ADDR|CRYPT_KV_STRING)
85 /* static local variables */
86 static int GpgmeLocaleSet = 0;
96 struct crypt_cache *next;
105 /* We work based on user IDs, getting from a user ID to the key is
106 check and does not need any memory (gpgme uses reference counting). */
107 typedef struct crypt_keyinfo
109 struct crypt_keyinfo *next;
111 int idx; /* and the user ID at this index */
112 const char *uid; /* and for convenience point to this user ID */
113 unsigned int flags; /* global and per uid flags (for convenience)*/
116 typedef struct crypt_entry
123 static struct crypt_cache *id_defaults = NULL;
124 static gpgme_key_t signature_key = NULL;
125 static char *current_sender = NULL;
129 * General helper functions.
132 /* return true when S pints to a didgit or letter. */
134 digit_or_letter (const unsigned char *s)
136 return ( (*s >= '0' && *s < '9')
137 || (*s >= 'A' && *s <= 'Z')
138 || (*s >= 'a' && *s <= 'z'));
142 /* Print the utf-8 encoded string BUF of length LEN bytes to stream
143 FP. Convert the character set. */
145 print_utf8 (FILE *fp, const char *buf, size_t len)
149 tstr = safe_malloc (len+1);
150 memcpy (tstr, buf, len);
153 /* fromcode "utf-8" is sure, so we don't want
154 * charset-hook corrections: flags must be 0.
156 mutt_convert_string (&tstr, "utf-8", Charset, 0);
166 /* Return the keyID for the key K. Note that this string is valid as
167 long as K is valid */
168 static const char *crypt_keyid (crypt_key_t *k)
170 const char *s = "????????";
172 if (k->kobj && k->kobj->subkeys)
174 s = k->kobj->subkeys->keyid;
175 if ((! option (OPTPGPLONGIDS)) && (strlen (s) == 16))
176 /* Return only the short keyID. */
183 /* Return the hexstring fingerprint from the key K. */
184 static const char *crypt_fpr (crypt_key_t *k)
188 if (k->kobj && k->kobj->subkeys)
189 s = k->kobj->subkeys->fpr;
194 /* Parse FLAGS and return a statically allocated(!) string with them. */
195 static char *crypt_key_abilities (int flags)
199 if (!(flags & KEYFLAG_CANENCRYPT))
201 else if (flags & KEYFLAG_PREFER_SIGNING)
206 if (!(flags & KEYFLAG_CANSIGN))
208 else if (flags & KEYFLAG_PREFER_ENCRYPTION)
218 /* Parse FLAGS and return a character describing the most important flag. */
219 static char crypt_flags (int flags)
221 if (flags & KEYFLAG_REVOKED)
223 else if (flags & KEYFLAG_EXPIRED)
225 else if (flags & KEYFLAG_DISABLED)
227 else if (flags & KEYFLAG_CRITICAL)
233 /* Return a copy of KEY. */
234 static crypt_key_t *crypt_copy_key (crypt_key_t *key)
238 k = safe_calloc (1, sizeof *k);
240 gpgme_key_ref (key->kobj);
243 k->flags = key->flags;
248 /* Release all the keys at the address of KEYLIST and set the address
250 static void crypt_free_key (crypt_key_t **keylist)
254 crypt_key_t *k = (*keylist)->next;
260 /* Return trute when key K is valid. */
261 static int crypt_key_is_valid (crypt_key_t *k)
263 if (k->flags & KEYFLAG_CANTUSE)
268 /* Return true whe validity of KEY is sufficient. */
269 static int crypt_id_is_strong (crypt_key_t *key)
271 gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
272 gpgme_user_id_t uid = NULL;
273 unsigned int is_strong = 0;
276 if ((key->flags & KEYFLAG_ISX509))
279 for (i = 0, uid = key->kobj->uids; (i < key->idx) && uid;
280 i++, uid = uid->next)
287 case GPGME_VALIDITY_UNKNOWN:
288 case GPGME_VALIDITY_UNDEFINED:
289 case GPGME_VALIDITY_NEVER:
290 case GPGME_VALIDITY_MARGINAL:
294 case GPGME_VALIDITY_FULL:
295 case GPGME_VALIDITY_ULTIMATE:
303 /* Return true when the KEY is valid, i.e. not marked as unusable. */
304 static int crypt_id_is_valid (crypt_key_t *key)
306 return ! (key->flags & KEYFLAG_CANTUSE);
309 /* Return a bit vector describing how well the addresses ADDR and
310 U_ADDR match and whether KEY is valid. */
311 static int crypt_id_matches_addr (ADDRESS *addr, ADDRESS *u_addr,
316 if (crypt_id_is_valid (key))
317 rv |= CRYPT_KV_VALID;
319 if (crypt_id_is_strong (key))
320 rv |= CRYPT_KV_STRONGID;
322 if (addr->mailbox && u_addr->mailbox
323 && mutt_strcasecmp (addr->mailbox, u_addr->mailbox) == 0)
326 if (addr->personal && u_addr->personal
327 && mutt_strcasecmp (addr->personal, u_addr->personal) == 0)
328 rv |= CRYPT_KV_STRING;
335 * GPGME convenient functions.
338 /* Create a new gpgme context and return it. With FOR_SMIME set to
339 true, the protocol of the context is set to CMS. */
340 static gpgme_ctx_t create_gpgme_context (int for_smime)
347 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
349 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
355 err = gpgme_new (&ctx);
358 mutt_error (_("error creating gpgme context: %s\n"), gpgme_strerror (err));
365 err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
368 mutt_error (_("error enabling CMS protocol: %s\n"),
369 gpgme_strerror (err));
378 /* Create a new gpgme data object. This is a wrapper to die on
380 static gpgme_data_t create_gpgme_data (void)
385 err = gpgme_data_new (&data);
388 mutt_error (_("error creating gpgme data object: %s\n"),
389 gpgme_strerror (err));
396 /* Create a new GPGME Data object from the mail body A. With CONVERT
397 passed as true, the lines are converted to CR,LF if required.
398 Return NULL on error or the gpgme_data_t object on success. */
399 static gpgme_data_t body_to_data_object (BODY *a, int convert)
401 char tempfile[_POSIX_PATH_MAX];
406 mutt_mktemp (tempfile);
407 fptmp = safe_fopen (tempfile, "w+");
410 mutt_perror (tempfile);
414 mutt_write_mime_header (a, fptmp);
416 mutt_write_mime_body (a, fptmp);
421 unsigned char buf[1];
423 data = create_gpgme_data ();
425 while ((c = fgetc (fptmp)) != EOF)
431 if (c == '\n' && !hadcr)
434 gpgme_data_write (data, buf, 1);
439 /* FIXME: This is quite suboptimal */
441 gpgme_data_write (data, buf, 1);
444 gpgme_data_seek (data, 0, SEEK_SET);
449 err = gpgme_data_new_from_file (&data, tempfile, 1);
454 mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
461 /* Create a GPGME data object from the stream FP but limit the object
462 to LENGTH bytes starting at OFFSET bytes from the beginning of the
464 static gpgme_data_t file_to_data_object (FILE *fp, long offset, long length)
469 err = gpgme_data_new_from_filepart (&data, NULL, fp, offset, length);
472 mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
479 /* Write a GPGME data object to the stream FP. */
480 static int data_object_to_stream (gpgme_data_t data, FILE *fp)
486 err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1)
487 ? gpgme_error_from_errno (errno) : 0);
490 mutt_error (_("error rewinding data object: %s\n"), gpgme_strerror (err));
494 while ((nread = gpgme_data_read (data, buf, sizeof (buf))))
496 /* fixme: we are not really converting CRLF to LF but just
497 skipping CR. Doing it correctly needs a more complex logic */
498 for (p=buf; nread; p++, nread--)
506 mutt_perror ("[tempfile]");
512 mutt_error (_("error reading data object: %s\n"), strerror (errno));
518 /* Copy a data object to a newly created temporay file and return that
519 filename. Caller must free. With RET_FP not NULL, don't close the
520 stream but return it there. */
521 static char *data_object_to_tempfile (gpgme_data_t data, FILE **ret_fp)
524 char tempfile[_POSIX_PATH_MAX];
528 mutt_mktemp (tempfile);
529 fp = safe_fopen (tempfile, "w+");
532 mutt_perror (tempfile);
536 err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1)
537 ? gpgme_error_from_errno (errno) : 0);
542 while ((nread = gpgme_data_read (data, buf, sizeof (buf))))
544 if (fwrite (buf, nread, 1, fp) != 1)
546 mutt_perror (tempfile);
559 mutt_error (_("error reading data object: %s\n"), gpgme_strerror (err));
566 return safe_strdup (tempfile);
570 /* Create a GpgmeRecipientSet from the keys in the string KEYLIST.
571 The keys must be space delimited. */
572 static gpgme_key_t *create_recipient_set (const char *keylist,
573 gpgme_protocol_t protocol)
579 gpgme_key_t *rset = NULL;
580 unsigned int rset_n = 0;
581 gpgme_key_t key = NULL;
582 gpgme_ctx_t context = NULL;
584 err = gpgme_new (&context);
586 err = gpgme_set_protocol (context, protocol);
594 for (i=0; *s && *s != ' ' && i < sizeof(buf)-1;)
599 if (i>1 && buf[i-1] == '!')
601 /* The user selected to override the valididy of that
605 err = gpgme_get_key (context, buf, &key, 0);
607 key->uids->validity = GPGME_VALIDITY_FULL;
611 err = gpgme_get_key (context, buf, &key, 0);
615 safe_realloc (&rset, sizeof (*rset) * (rset_n + 1));
616 rset[rset_n++] = key;
620 mutt_error (_("error adding recipient `%s': %s\n"),
621 buf, gpgme_strerror (err));
629 /* NULL terminate. */
630 safe_realloc (&rset, sizeof (*rset) * (rset_n + 1));
631 rset[rset_n++] = NULL;
634 gpgme_release (context);
640 /* Make sure that the correct signer is set. Returns 0 on success. */
641 static int set_signer (gpgme_ctx_t ctx, int for_smime)
643 char *signid = for_smime ? SmimeDefaultKey: PgpSignAs;
646 gpgme_key_t key, key2;
648 if (!signid || !*signid)
651 listctx = create_gpgme_context (for_smime);
652 err = gpgme_op_keylist_start (listctx, signid, 1);
654 err = gpgme_op_keylist_next (listctx, &key);
657 gpgme_release (listctx);
658 mutt_error (_("secret key `%s' not found: %s\n"),
659 signid, gpgme_strerror (err));
662 err = gpgme_op_keylist_next (listctx, &key2);
665 gpgme_key_release (key);
666 gpgme_key_release (key2);
667 gpgme_release (listctx);
668 mutt_error (_("ambiguous specification of secret key `%s'\n"),
672 gpgme_op_keylist_end (listctx);
673 gpgme_release (listctx);
675 gpgme_signers_clear (ctx);
676 err = gpgme_signers_add (ctx, key);
677 gpgme_key_release (key);
680 mutt_error (_("error setting secret key `%s': %s\n"),
681 signid, gpgme_strerror (err));
688 set_pka_sig_notation (gpgme_ctx_t ctx)
692 err = gpgme_sig_notation_add (ctx,
693 PKA_NOTATION_NAME, current_sender, 0);
697 mutt_error (_("error setting PKA signature notation: %s\n"),
698 gpgme_strerror (err));
705 /* Encrypt the gpgme data object PLAINTEXT to the recipients in RSET
706 and return an allocated filename to a temporary file containing the
707 enciphered text. With USE_SMIME set to true, the smime backend is
708 used. With COMBINED_SIGNED a PGP message is signed and
709 encrypted. Returns NULL in case of error */
710 static char *encrypt_gpgme_object (gpgme_data_t plaintext, gpgme_key_t *rset,
711 int use_smime, int combined_signed)
715 gpgme_data_t ciphertext;
718 ctx = create_gpgme_context (use_smime);
720 gpgme_set_armor (ctx, 1);
722 ciphertext = create_gpgme_data ();
726 if (set_signer (ctx, use_smime))
728 gpgme_data_release (ciphertext);
733 if (option (OPTCRYPTUSEPKA))
735 err = set_pka_sig_notation (ctx);
738 gpgme_data_release (ciphertext);
744 err = gpgme_op_encrypt_sign (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST,
745 plaintext, ciphertext);
748 err = gpgme_op_encrypt (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST,
749 plaintext, ciphertext);
750 mutt_need_hard_redraw ();
753 mutt_error (_("error encrypting data: %s\n"), gpgme_strerror (err));
754 gpgme_data_release (ciphertext);
761 outfile = data_object_to_tempfile (ciphertext, NULL);
762 gpgme_data_release (ciphertext);
766 /* Find the "micalg" parameter from the last Gpgme operation on
767 context CTX. It is expected that this operation was a sign
768 operation. Return the algorithm name as a C string in buffer BUF
769 which must have been allocated by the caller with size BUFLEN.
770 Returns 0 on success or -1 in case of an error. The return string
771 is truncted to BUFLEN - 1. */
772 static int get_micalg (gpgme_ctx_t ctx, int use_smime, char *buf, size_t buflen)
774 gpgme_sign_result_t result = NULL;
775 const char *algorithm_name = NULL;
781 result = gpgme_op_sign_result (ctx);
782 if (result && result->signatures)
784 algorithm_name = gpgme_hash_algo_name (result->signatures->hash_algo);
789 /* convert GPGME raw hash name to RFC 2633 format */
790 snprintf (buf, buflen, "%s", algorithm_name);
791 ascii_strlower (buf);
793 /* convert GPGME raw hash name to RFC 3156 format */
794 snprintf (buf, buflen, "pgp-%s", algorithm_name);
795 ascii_strlower (buf + 4);
803 static void print_time(time_t t, STATE *s)
807 setlocale (LC_TIME, "");
808 #ifdef HAVE_LANGINFO_D_T_FMT
809 strftime (p, sizeof (p), nl_langinfo (D_T_FMT), localtime (&t));
811 strftime (p, sizeof (p), "%c", localtime (&t));
813 setlocale (LC_TIME, "C");
814 state_attach_puts (p, s);
818 * Implementation of `sign_message'.
821 /* Sign the MESSAGE in body A either using OpenPGP or S/MIME when
822 USE_SMIME is passed as true. Returns the new body or NULL on
824 static BODY *sign_message (BODY *a, int use_smime)
831 gpgme_data_t message, signature;
833 convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */
835 message = body_to_data_object (a, 1);
838 signature = create_gpgme_data ();
840 ctx = create_gpgme_context (use_smime);
842 gpgme_set_armor (ctx, 1);
844 if (set_signer (ctx, use_smime))
846 gpgme_data_release (signature);
851 if (option (OPTCRYPTUSEPKA))
853 err = set_pka_sig_notation (ctx);
856 gpgme_data_release (signature);
857 gpgme_data_release (message);
863 err = gpgme_op_sign (ctx, message, signature, GPGME_SIG_MODE_DETACH );
864 mutt_need_hard_redraw ();
865 gpgme_data_release (message);
868 gpgme_data_release (signature);
870 mutt_error (_("error signing data: %s\n"), gpgme_strerror (err));
874 sigfile = data_object_to_tempfile (signature, NULL);
875 gpgme_data_release (signature);
882 t = mutt_new_body ();
883 t->type = TYPEMULTIPART;
884 t->subtype = safe_strdup ("signed");
885 t->encoding = ENC7BIT;
887 t->disposition = DISPINLINE;
889 mutt_generate_boundary (&t->parameter);
890 mutt_set_parameter ("protocol",
891 use_smime? "application/pkcs7-signature"
892 : "application/pgp-signature",
894 /* Get the micalg from gpgme. Old gpgme versions don't support this
895 for S/MIME so we assume sha-1 in this case. */
896 if (!get_micalg (ctx, use_smime, buf, sizeof buf))
897 mutt_set_parameter ("micalg", buf, &t->parameter);
899 mutt_set_parameter ("micalg", "sha1", &t->parameter);
905 t->parts->next = mutt_new_body ();
907 t->type = TYPEAPPLICATION;
910 t->subtype = safe_strdup ("pkcs7-signature");
911 mutt_set_parameter ("name", "smime.p7s", &t->parameter);
912 t->encoding = ENCBASE64;
914 t->disposition = DISPATTACH;
915 t->d_filename = safe_strdup ("smime.p7s");
919 t->subtype = safe_strdup ("pgp-signature");
921 t->disposition = DISPINLINE;
922 t->encoding = ENC7BIT;
924 t->filename = sigfile;
925 t->unlink = 1; /* ok to remove this file after sending. */
931 BODY *pgp_gpgme_sign_message (BODY *a)
933 return sign_message (a, 0);
936 BODY *smime_gpgme_sign_message (BODY *a)
938 return sign_message (a, 1);
942 * Implementation of `encrypt_message'.
945 /* Encrypt the mail body A to all keys given as space separated keyids
946 or fingerprints in KEYLIST and return the encrypted body. */
947 BODY *pgp_gpgme_encrypt_message (BODY *a, char *keylist, int sign)
949 char *outfile = NULL;
951 gpgme_key_t *rset = NULL;
952 gpgme_data_t plaintext;
954 rset = create_recipient_set (keylist, GPGME_PROTOCOL_OpenPGP);
960 plaintext = body_to_data_object (a, 0);
967 outfile = encrypt_gpgme_object (plaintext, rset, 0, sign);
968 gpgme_data_release (plaintext);
973 t = mutt_new_body ();
974 t->type = TYPEMULTIPART;
975 t->subtype = safe_strdup ("encrypted");
976 t->encoding = ENC7BIT;
978 t->disposition = DISPINLINE;
980 mutt_generate_boundary(&t->parameter);
981 mutt_set_parameter("protocol", "application/pgp-encrypted", &t->parameter);
983 t->parts = mutt_new_body ();
984 t->parts->type = TYPEAPPLICATION;
985 t->parts->subtype = safe_strdup ("pgp-encrypted");
986 t->parts->encoding = ENC7BIT;
988 t->parts->next = mutt_new_body ();
989 t->parts->next->type = TYPEAPPLICATION;
990 t->parts->next->subtype = safe_strdup ("octet-stream");
991 t->parts->next->encoding = ENC7BIT;
992 t->parts->next->filename = outfile;
993 t->parts->next->use_disp = 1;
994 t->parts->next->disposition = DISPINLINE;
995 t->parts->next->unlink = 1; /* delete after sending the message */
996 t->parts->next->d_filename = safe_strdup ("msg.asc"); /* non pgp/mime
1003 * Implementation of `smime_build_smime_entity'.
1006 /* Encrypt the mail body A to all keys given as space separated
1007 fingerprints in KEYLIST and return the S/MIME encrypted body. */
1008 BODY *smime_gpgme_build_smime_entity (BODY *a, char *keylist)
1010 char *outfile = NULL;
1012 gpgme_key_t *rset = NULL;
1013 gpgme_data_t plaintext;
1015 rset = create_recipient_set (keylist, GPGME_PROTOCOL_CMS);
1019 plaintext = body_to_data_object (a, 0);
1026 outfile = encrypt_gpgme_object (plaintext, rset, 1, 0);
1027 gpgme_data_release (plaintext);
1032 t = mutt_new_body ();
1033 t->type = TYPEAPPLICATION;
1034 t->subtype = safe_strdup ("pkcs7-mime");
1035 mutt_set_parameter ("name", "smime.p7m", &t->parameter);
1036 mutt_set_parameter ("smime-type", "enveloped-data", &t->parameter);
1037 t->encoding = ENCBASE64; /* The output of OpenSSL SHOULD be binary */
1039 t->disposition = DISPATTACH;
1040 t->d_filename = safe_strdup ("smime.p7m");
1041 t->filename = outfile;
1042 t->unlink = 1; /*delete after sending the message */
1051 * Implementation of `verify_one'.
1054 /* Display the common attributes of the signature summary SUM.
1055 Return 1 if there is is a severe warning.
1057 static int show_sig_summary (unsigned long sum,
1058 gpgme_ctx_t ctx, gpgme_key_t key, int idx,
1059 STATE *s, gpgme_signature_t sig)
1063 if ((sum & GPGME_SIGSUM_KEY_REVOKED))
1065 state_attach_puts (_("Warning: One of the keys has been revoked\n"),s);
1069 if ((sum & GPGME_SIGSUM_KEY_EXPIRED))
1071 time_t at = key->subkeys->expires ? key->subkeys->expires : 0;
1074 state_attach_puts (_("Warning: The key used to create the "
1075 "signature expired at: "), s);
1076 print_time (at , s);
1077 state_attach_puts ("\n", s);
1080 state_attach_puts (_("Warning: At least one certification key "
1081 "has expired\n"), s);
1084 if ((sum & GPGME_SIGSUM_SIG_EXPIRED))
1086 gpgme_verify_result_t result;
1087 gpgme_signature_t sig;
1090 result = gpgme_op_verify_result (ctx);
1092 for (sig = result->signatures, i = 0; sig && (i < idx);
1093 sig = sig->next, i++)
1096 state_attach_puts (_("Warning: The signature expired at: "), s);
1097 print_time (sig ? sig->exp_timestamp : 0, s);
1098 state_attach_puts ("\n", s);
1101 if ((sum & GPGME_SIGSUM_KEY_MISSING))
1102 state_attach_puts (_("Can't verify due to a missing "
1103 "key or certificate\n"), s);
1105 if ((sum & GPGME_SIGSUM_CRL_MISSING))
1107 state_attach_puts (_("The CRL is not available\n"), s);
1111 if ((sum & GPGME_SIGSUM_CRL_TOO_OLD))
1113 state_attach_puts (_("Available CRL is too old\n"), s);
1117 if ((sum & GPGME_SIGSUM_BAD_POLICY))
1118 state_attach_puts (_("A policy requirement was not met\n"), s);
1120 if ((sum & GPGME_SIGSUM_SYS_ERROR))
1122 const char *t0 = NULL, *t1 = NULL;
1123 gpgme_verify_result_t result;
1124 gpgme_signature_t sig;
1127 state_attach_puts (_("A system error occurred"), s );
1129 /* Try to figure out some more detailed system error information. */
1130 result = gpgme_op_verify_result (ctx);
1131 for (sig = result->signatures, i = 0; sig && (i < idx);
1132 sig = sig->next, i++)
1137 t1 = sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
1142 state_attach_puts (": ", s);
1144 state_attach_puts (t0, s);
1145 if (t1 && !(t0 && !strcmp (t0, t1)))
1148 state_attach_puts (",", s);
1149 state_attach_puts (t1, s);
1152 state_attach_puts ("\n", s);
1155 #ifdef HAVE_GPGME_PKA_TRUST
1157 if (option (OPTCRYPTUSEPKA))
1159 if (sig->pka_trust == 1 && sig->pka_address)
1161 state_attach_puts (_("WARNING: PKA entry does not match "
1162 "signer's address: "), s);
1163 state_attach_puts (sig->pka_address, s);
1164 state_attach_puts ("\n", s);
1166 else if (sig->pka_trust == 2 && sig->pka_address)
1168 state_attach_puts (_("PKA verified signer's address is: "), s);
1169 state_attach_puts (sig->pka_address, s);
1170 state_attach_puts ("\n", s);
1180 static void show_fingerprint (gpgme_key_t key, STATE *state)
1185 const char *prefix = _("Fingerprint: ");
1189 s = key->subkeys ? key->subkeys->fpr : NULL;
1192 is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
1194 buf = safe_malloc ( strlen (prefix) + strlen(s) * 4 + 2 );
1195 strcpy (buf, prefix); /* __STRCPY_CHECKED__ */
1196 p = buf + strlen (buf);
1197 if (is_pgp && strlen (s) == 40)
1198 { /* PGP v4 style formatted. */
1199 for (i=0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++)
1212 for (i=0; *s && s[1] && s[2]; s += 2, i++)
1216 *p++ = is_pgp? ' ':':';
1217 if (is_pgp && i == 7)
1222 /* just in case print remaining odd digits */
1227 state_attach_puts (buf, state);
1231 /* Show the valididy of a key used for one signature. */
1232 static void show_one_sig_validity (gpgme_ctx_t ctx, int idx, STATE *s)
1234 gpgme_verify_result_t result = NULL;
1235 gpgme_signature_t sig = NULL;
1236 const char *txt = NULL;
1238 result = gpgme_op_verify_result (ctx);
1240 for (sig = result->signatures; sig && (idx > 0); sig = sig->next, idx--);
1242 switch (sig ? sig->validity : 0)
1244 case GPGME_VALIDITY_UNKNOWN:
1245 txt = _("WARNING: We have NO indication whether "
1246 "the key belongs to the person named "
1247 "as shown above\n");
1249 case GPGME_VALIDITY_UNDEFINED:
1251 case GPGME_VALIDITY_NEVER:
1252 txt = _("WARNING: The key does NOT BELONG to "
1253 "the person named as shown above\n");
1255 case GPGME_VALIDITY_MARGINAL:
1256 txt = _("WARNING: It is NOT certain that the key "
1257 "belongs to the person named as shown above\n");
1259 case GPGME_VALIDITY_FULL:
1260 case GPGME_VALIDITY_ULTIMATE:
1265 state_attach_puts (txt, s);
1268 static void print_smime_keyinfo (const char* msg, gpgme_signature_t sig,
1269 gpgme_key_t key, STATE *s)
1272 gpgme_user_id_t uids = NULL;
1275 state_attach_puts (msg, s);
1276 state_attach_puts (" ", s);
1277 for (uids = key->uids; uids; uids = uids->next)
1283 msglen = mutt_strlen (msg) - 4;
1284 for (i = 0; i < msglen; i++)
1285 state_attach_puts(" ", s);
1286 state_attach_puts(_("aka: "), s);
1288 state_attach_puts (uids->uid, s);
1289 state_attach_puts ("\n", s);
1294 msglen = mutt_strlen (msg) - 8;
1295 for (i = 0; i < msglen; i++)
1296 state_attach_puts(" ", s);
1297 state_attach_puts (_("created: "), s);
1298 print_time (sig->timestamp, s);
1299 state_attach_puts ("\n", s);
1302 /* Show information about one signature. This fucntion is called with
1303 the context CTX of a sucessful verification operation and the
1304 enumerator IDX which should start at 0 and incremete for each
1307 Return values are: 0 for normal procession, 1 for a bad signature,
1308 2 for a signature with a warning or -1 for no more signature. */
1309 static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE *s)
1311 const char *fpr, *uid;
1312 gpgme_key_t key = NULL;
1313 int i, anybad = 0, anywarn = 0;
1315 gpgme_verify_result_t result;
1316 gpgme_signature_t sig;
1317 gpgme_error_t err = GPG_ERR_NO_ERROR;
1319 result = gpgme_op_verify_result (ctx);
1322 /* FIXME: this code should use a static variable and remember
1323 the current position in the list of signatures, IMHO.
1326 for (i = 0, sig = result->signatures; sig && (i < idx);
1327 i++, sig = sig->next)
1330 return -1; /* Signature not found. */
1334 gpgme_key_release (signature_key);
1335 signature_key = NULL;
1341 if (gpg_err_code (sig->status) != GPG_ERR_NO_ERROR)
1344 err = gpgme_get_key (ctx, fpr, &key, 0); /* secret key? */
1347 uid = (key->uids && key->uids->uid) ? key->uids->uid : "[?]";
1348 if (! signature_key)
1349 signature_key = key;
1353 key = NULL; /* Old gpgme versions did not set KEY to NULL on
1354 error. Do it here to avoid a double free. */
1358 if (!s || !s->fpout || !(s->flags & M_DISPLAY))
1359 ; /* No state information so no way to print anything. */
1362 state_attach_puts (_("Error getting key information: "), s);
1363 state_attach_puts ( gpg_strerror (err), s );
1364 state_attach_puts ("\n", s);
1367 else if ((sum & GPGME_SIGSUM_GREEN))
1369 print_smime_keyinfo (_("Good signature from:"), sig, key, s);
1370 if (show_sig_summary (sum, ctx, key, idx, s, sig))
1372 show_one_sig_validity (ctx, idx, s);
1374 else if ((sum & GPGME_SIGSUM_RED))
1376 print_smime_keyinfo (_("*BAD* signature from:"), sig, key, s);
1377 show_sig_summary (sum, ctx, key, idx, s, sig);
1379 else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP))
1380 { /* We can't decide (yellow) but this is a PGP key with a good
1381 signature, so we display what a PGP user expects: The name,
1382 fingerprint and the key validity (which is neither fully or
1384 print_smime_keyinfo (_("Good signature from:"), sig, key, s);
1385 show_one_sig_validity (ctx, idx, s);
1386 show_fingerprint (key,s);
1387 if (show_sig_summary (sum, ctx, key, idx, s, sig))
1390 else /* can't decide (yellow) */
1392 print_smime_keyinfo (_("Problem signature from:"), sig, key, s);
1393 state_attach_puts (_(" expires: "), s);
1394 print_time (sig->exp_timestamp, s);
1395 state_attach_puts ("\n", s);
1396 show_sig_summary (sum, ctx, key, idx, s, sig);
1400 if (key != signature_key)
1401 gpgme_key_release (key);
1404 return anybad ? 1 : anywarn ? 2 : 0;
1407 /* Do the actual verification step. With IS_SMIME set to true we
1408 assume S/MIME (surprise!) */
1409 static int verify_one (BODY *sigbdy, STATE *s,
1410 const char *tempfile, int is_smime)
1416 gpgme_data_t signature, message;
1418 signature = file_to_data_object (s->fpin, sigbdy->offset, sigbdy->length);
1422 /* We need to tell gpgme about the encoding because the backend can't
1423 auto-detect plain base-64 encoding which is used by S/MIME. */
1425 gpgme_data_set_encoding (signature, GPGME_DATA_ENCODING_BASE64);
1427 err = gpgme_data_new_from_file (&message, tempfile, 1);
1430 gpgme_data_release (signature);
1431 mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
1434 ctx = create_gpgme_context (is_smime);
1436 /* Note: We don't need a current time output because GPGME avoids
1437 such an attack by separating the meta information from the
1439 state_attach_puts (_("[-- Begin signature information --]\n"), s);
1441 err = gpgme_op_verify (ctx, signature, message, NULL);
1442 mutt_need_hard_redraw ();
1447 snprintf (buf, sizeof(buf)-1,
1448 _("Error: verification failed: %s\n"),
1449 gpgme_strerror (err));
1450 state_attach_puts (buf, s);
1453 { /* Verification succeeded, see what the result is. */
1459 gpgme_key_release (signature_key);
1460 signature_key = NULL;
1463 for(idx=0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++)
1476 gpgme_verify_result_t result;
1477 gpgme_sig_notation_t notation;
1478 gpgme_signature_t signature;
1479 int non_pka_notations;
1481 result = gpgme_op_verify_result (ctx);
1484 for (signature = result->signatures; signature;
1485 signature = signature->next)
1487 non_pka_notations = 0;
1488 for (notation = signature->notations; notation;
1489 notation = notation->next)
1490 if (! is_pka_notation (notation))
1491 non_pka_notations++;
1493 if (non_pka_notations)
1495 char buf[SHORT_STRING];
1496 snprintf (buf, sizeof (buf),
1497 _("*** Begin Notation (signature by: %s) ***\n"),
1499 state_attach_puts (buf, s);
1500 for (notation = signature->notations; notation;
1501 notation = notation->next)
1503 if (is_pka_notation (notation))
1508 state_attach_puts (notation->name, s);
1509 state_attach_puts ("=", s);
1511 if (notation->value)
1513 state_attach_puts (notation->value, s);
1514 if (!(*notation->value
1515 && (notation->value[strlen (notation->value)-1]=='\n')))
1516 state_attach_puts ("\n", s);
1519 state_attach_puts (_("*** End Notation ***\n"), s);
1525 gpgme_release (ctx);
1527 state_attach_puts (_("[-- End signature information --]\n\n"), s);
1528 dprint (1, (debugfile, "verify_one: returning %d.\n", badsig));
1530 return badsig? 1: anywarn? 2 : 0;
1533 int pgp_gpgme_verify_one (BODY *sigbdy, STATE *s, const char *tempfile)
1535 return verify_one (sigbdy, s, tempfile, 0);
1538 int smime_gpgme_verify_one (BODY *sigbdy, STATE *s, const char *tempfile)
1540 return verify_one (sigbdy, s, tempfile, 1);
1544 * Implementation of `decrypt_part'.
1547 /* Decrypt a PGP or SMIME message (depending on the boolean flag
1548 IS_SMIME) with body A described further by state S. Write
1549 plaintext out to file FPOUT and return a new body. For PGP returns
1550 a flag in R_IS_SIGNED to indicate whether this is a combined
1551 encrypted and signed message, for S/MIME it returns true when it is
1552 not a encrypted but a signed message. */
1553 static BODY *decrypt_part (BODY *a, STATE *s, FILE *fpout, int is_smime,
1560 gpgme_data_t ciphertext, plaintext;
1561 int maybe_signed = 0;
1568 ctx = create_gpgme_context (is_smime);
1571 /* Make a data object from the body, create context etc. */
1572 ciphertext = file_to_data_object (s->fpin, a->offset, a->length);
1575 plaintext = create_gpgme_data ();
1577 /* Do the decryption or the verification in case of the S/MIME hack. */
1578 if ((! is_smime) || maybe_signed)
1581 err = gpgme_op_decrypt_verify (ctx, ciphertext, plaintext);
1582 else if (maybe_signed)
1583 err = gpgme_op_verify (ctx, ciphertext, NULL, plaintext);
1585 if (err == GPG_ERR_NO_ERROR)
1587 /* Check whether signatures have been verified. */
1588 gpgme_verify_result_t verify_result = gpgme_op_verify_result (ctx);
1589 if (verify_result->signatures)
1594 err = gpgme_op_decrypt (ctx, ciphertext, plaintext);
1595 gpgme_data_release (ciphertext);
1598 if (is_smime && !maybe_signed
1599 && gpg_err_code (err) == GPG_ERR_NO_DATA)
1601 /* Check whether this might be a signed message despite what
1602 the mime header told us. Retry then. gpgsm returns the
1603 error information "unsupported Algorithm '?'" but gpgme
1604 will not store this unknown algorithm, thus we test that
1605 it has not been set. */
1606 gpgme_decrypt_result_t result;
1608 result = gpgme_op_decrypt_result (ctx);
1609 if (!result->unsupported_algorithm)
1612 gpgme_data_release (plaintext);
1616 mutt_need_hard_redraw ();
1617 if ((s->flags & M_DISPLAY))
1621 snprintf (buf, sizeof(buf)-1,
1622 _("[-- Error: decryption failed: %s --]\n\n"),
1623 gpgme_strerror (err));
1624 state_attach_puts (buf, s);
1626 gpgme_data_release (plaintext);
1627 gpgme_release (ctx);
1630 mutt_need_hard_redraw ();
1632 /* Read the output from GPGME, and make sure to change CRLF to LF,
1633 otherwise read_mime_header has a hard time parsing the message. */
1634 if (data_object_to_stream (plaintext, fpout))
1636 gpgme_data_release (plaintext);
1637 gpgme_release (ctx);
1640 gpgme_data_release (plaintext);
1642 a->is_signed_data = 0;
1649 a->is_signed_data = 1;
1651 *r_is_signed = -1; /* A signature exists. */
1653 if ((s->flags & M_DISPLAY))
1654 state_attach_puts (_("[-- Begin signature "
1655 "information --]\n"), s);
1656 for(idx = 0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++)
1663 if (!anybad && idx && r_is_signed && *r_is_signed)
1664 *r_is_signed = anywarn? 2:1; /* Good signature. */
1666 if ((s->flags & M_DISPLAY))
1667 state_attach_puts (_("[-- End signature "
1668 "information --]\n\n"), s);
1670 gpgme_release (ctx); ctx = NULL;
1674 tattach = mutt_read_mime_header (fpout, 0);
1678 * Need to set the length of this body part.
1680 fstat (fileno (fpout), &info);
1681 tattach->length = info.st_size - tattach->offset;
1683 tattach->warnsig = anywarn;
1685 /* See if we need to recurse on this MIME part. */
1686 mutt_parse_part (fpout, tattach);
1692 /* Decrypt a PGP/MIME message in FPIN and B and return a new body and
1693 the stream in CUR and FPOUT. Returns 0 on success. */
1694 int pgp_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur)
1696 char tempfile[_POSIX_PATH_MAX];
1698 BODY *first_part = b;
1701 first_part->goodsig = 0;
1702 first_part->warnsig = 0;
1704 if(!mutt_is_multipart_encrypted(b))
1707 if(!b->parts || !b->parts->next)
1712 memset (&s, 0, sizeof (s));
1714 mutt_mktemp (tempfile);
1715 if (!(*fpout = safe_fopen (tempfile, "w+")))
1717 mutt_perror (tempfile);
1722 *cur = decrypt_part (b, &s, *fpout, 0, &is_signed);
1725 first_part->goodsig = 1;
1731 /* Decrypt a S/MIME message in FPIN and B and return a new body and
1732 the stream in CUR and FPOUT. Returns 0 on success. */
1733 int smime_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur)
1735 char tempfile[_POSIX_PATH_MAX];
1739 LOFF_T saved_b_offset;
1740 size_t saved_b_length;
1743 if (!mutt_is_application_smime (b))
1749 /* Decode the body - we need to pass binary CMS to the
1750 backend. The backend allows for Base64 encoded data but it does
1751 not allow for QP which I have seen in some messages. So better
1753 saved_b_type = b->type;
1754 saved_b_offset = b->offset;
1755 saved_b_length = b->length;
1756 memset (&s, 0, sizeof (s));
1758 fseeko (s.fpin, b->offset, 0);
1759 mutt_mktemp (tempfile);
1760 if (!(tmpfp = safe_fopen (tempfile, "w+")))
1762 mutt_perror (tempfile);
1765 mutt_unlink (tempfile);
1768 mutt_decode_attachment (b, &s);
1770 b->length = ftello (s.fpout);
1774 memset (&s, 0, sizeof (s));
1777 mutt_mktemp (tempfile);
1778 if (!(*fpout = safe_fopen (tempfile, "w+")))
1780 mutt_perror (tempfile);
1783 mutt_unlink (tempfile);
1785 *cur = decrypt_part (b, &s, *fpout, 1, &is_signed);
1787 (*cur)->goodsig = is_signed > 0;
1788 b->type = saved_b_type;
1789 b->length = saved_b_length;
1790 b->offset = saved_b_offset;
1793 if (*cur && !is_signed && !(*cur)->parts && mutt_is_application_smime (*cur))
1795 /* Assume that this is a opaque signed s/mime message. This is
1796 an ugly way of doing it but we have anyway a problem with
1797 arbitrary encoded S/MIME messages: Only the outer part may be
1798 encrypted. The entire mime parsing should be revamped,
1799 probably by keeping the temportary files so that we don't
1800 need to decrypt them all the time. Inner parts of an
1801 encrypted part can then pint into this file and tehre won't
1802 never be a need to decrypt again. This needs a partial
1803 rewrite of the MIME engine. */
1807 saved_b_type = bb->type;
1808 saved_b_offset = bb->offset;
1809 saved_b_length = bb->length;
1810 memset (&s, 0, sizeof (s));
1812 fseeko (s.fpin, bb->offset, 0);
1813 mutt_mktemp (tempfile);
1814 if (!(tmpfp = safe_fopen (tempfile, "w+")))
1816 mutt_perror (tempfile);
1819 mutt_unlink (tempfile);
1822 mutt_decode_attachment (bb, &s);
1824 bb->length = ftello (s.fpout);
1829 memset (&s, 0, sizeof (s));
1832 mutt_mktemp (tempfile);
1833 if (!(*fpout = safe_fopen (tempfile, "w+")))
1835 mutt_perror (tempfile);
1838 mutt_unlink (tempfile);
1840 tmp_b = decrypt_part (bb, &s, *fpout, 1, &is_signed);
1842 tmp_b->goodsig = is_signed > 0;
1843 bb->type = saved_b_type;
1844 bb->length = saved_b_length;
1845 bb->offset = saved_b_offset;
1848 mutt_free_body (cur);
1854 static int pgp_gpgme_extract_keys (gpgme_data_t keydata, FILE** fp, int dryrun)
1856 /* there's no side-effect free way to view key data in GPGME,
1857 * so we import the key into a temporary keyring */
1858 char tmpdir[_POSIX_PATH_MAX];
1859 char tmpfile[_POSIX_PATH_MAX];
1862 gpgme_engine_info_t engineinfo;
1864 gpgme_user_id_t uid;
1865 gpgme_subkey_t subkey;
1866 const char* shortid;
1872 if ((err = gpgme_new (&tmpctx)) != GPG_ERR_NO_ERROR)
1874 dprint (1, (debugfile, "Error creating GPGME context\n"));
1880 snprintf (tmpdir, sizeof(tmpdir), "%s/mutt-gpgme-XXXXXX", Tempdir);
1881 if (!mkdtemp (tmpdir))
1883 dprint (1, (debugfile, "Error creating temporary GPGME home\n"));
1887 engineinfo = gpgme_ctx_get_engine_info (tmpctx);
1888 while (engineinfo && engineinfo->protocol != GPGME_PROTOCOL_OpenPGP)
1889 engineinfo = engineinfo->next;
1892 dprint (1, (debugfile, "Error finding GPGME PGP engine\n"));
1896 err = gpgme_ctx_set_engine_info (tmpctx, GPGME_PROTOCOL_OpenPGP,
1897 engineinfo->file_name, tmpdir);
1898 if (err != GPG_ERR_NO_ERROR)
1900 dprint (1, (debugfile, "Error setting GPGME context home\n"));
1905 if ((err = gpgme_op_import (tmpctx, keydata)) != GPG_ERR_NO_ERROR)
1907 dprint (1, (debugfile, "Error importing key\n"));
1911 mutt_mktemp (tmpfile);
1912 *fp = safe_fopen (tmpfile, "w+");
1915 mutt_perror (tmpfile);
1920 err = gpgme_op_keylist_start (tmpctx, NULL, 0);
1923 if ((err = gpgme_op_keylist_next (tmpctx, &key)))
1926 subkey = key->subkeys;
1930 shortid = subkey->keyid;
1931 len = mutt_strlen (subkey->keyid);
1934 strftime (date, sizeof (date), "%Y-%m-%d", localtime (&subkey->timestamp));
1937 fprintf (*fp, "%s %5.5s %d/%8s %s %s\n", more ? "sub" : "pub",
1938 gpgme_pubkey_algo_name (subkey->pubkey_algo), subkey->length,
1939 shortid, date, uid->uid);
1941 fprintf (*fp, "%s %5.5s %d/%8s %s\n", more ? "sub" : "pub",
1942 gpgme_pubkey_algo_name (subkey->pubkey_algo), subkey->length,
1944 subkey = subkey->next;
1947 gpgme_key_release (key);
1949 if (gpg_err_code (err) != GPG_ERR_EOF)
1951 dprint (1, (debugfile, "Error listing keys\n"));
1965 mutt_rmtree (tmpdir);
1967 gpgme_release (tmpctx);
1973 * Implementation of `pgp_check_traditional'.
1976 static int pgp_check_traditional_one_body (FILE *fp, BODY *b, int tagged_only)
1978 char tempfile[_POSIX_PATH_MAX];
1979 char buf[HUGE_STRING];
1985 if (b->type != TYPETEXT)
1988 if (tagged_only && !b->tagged)
1991 mutt_mktemp (tempfile);
1992 if (mutt_decode_save_attachment (fp, b, tempfile, 0, 0) != 0)
1998 if ((tfp = fopen (tempfile, "r")) == NULL)
2004 while (fgets (buf, sizeof (buf), tfp))
2006 if (!mutt_strncmp ("-----BEGIN PGP ", buf, 15))
2008 if (!mutt_strcmp ("MESSAGE-----\n", buf + 15))
2013 else if (!mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15))
2026 /* fix the content type */
2028 mutt_set_parameter ("format", "fixed", &b->parameter);
2029 mutt_set_parameter ("x-action", enc ? "pgp-encrypted" : "pgp-signed",
2035 int pgp_gpgme_check_traditional (FILE *fp, BODY *b, int tagged_only)
2039 for (; b; b = b->next)
2041 if (is_multipart (b))
2042 rv = (pgp_gpgme_check_traditional (fp, b->parts, tagged_only) || rv);
2043 else if (b->type == TYPETEXT)
2045 if ((r = mutt_is_application_pgp (b)))
2048 rv = (pgp_check_traditional_one_body (fp, b, tagged_only) || rv);
2054 /* TODO: looks like this won't work and we'll have to fully parse the
2055 * message file. GPGME makes life hard yet again. */
2056 void pgp_gpgme_invoke_import (const char *fname)
2058 gpgme_data_t keydata;
2064 if (!(in = safe_fopen (fname, "r")))
2066 if ((err = gpgme_data_new_from_stream (&keydata, in)) != GPG_ERR_NO_ERROR)
2068 dprint (1, (debugfile, "error converting key file into data object\n"));
2073 if (!pgp_gpgme_extract_keys (keydata, &out, 0))
2075 /* display import results */
2076 outlen = ftell (out);
2077 fseek (out, 0, SEEK_SET);
2078 mutt_copy_bytes (out, stdout, outlen);
2082 printf (_("Error extracting key data!\n"));
2087 * Implementation of `application_handler'.
2091 Copy a clearsigned message, and strip the signature and PGP's
2094 XXX - charset handling: We assume that it is safe to do
2095 character set decoding first, dash decoding second here, while
2096 we do it the other way around in the main handler.
2098 (Note that we aren't worse than Outlook & Cie in this, and also
2099 note that we can successfully handle anything produced by any
2100 existing versions of mutt.) */
2102 static void copy_clearsigned (gpgme_data_t data, STATE *s, char *charset)
2104 char buf[HUGE_STRING];
2105 short complete, armor_header;
2110 fname = data_object_to_tempfile (data, &fp);
2116 /* fromcode comes from the MIME Content-Type charset label. It might
2117 * be a wrong label, so we want the ability to do corrections via
2118 * charset-hooks. Therefore we set flags to M_ICONV_HOOK_FROM.
2120 fc = fgetconv_open (fp, charset, Charset, M_ICONV_HOOK_FROM);
2122 for (complete = 1, armor_header = 1;
2123 fgetconvs (buf, sizeof (buf), fc) != NULL;
2124 complete = strchr (buf, '\n') != NULL)
2129 state_puts (buf, s);
2133 if (!mutt_strcmp (buf, "-----BEGIN PGP SIGNATURE-----\n"))
2144 state_puts (s->prefix, s);
2146 if (buf[0] == '-' && buf[1] == ' ')
2147 state_puts (buf + 2, s);
2149 state_puts (buf, s);
2152 fgetconv_close (&fc);
2157 /* Support for classic_application/pgp */
2158 int pgp_gpgme_application_handler (BODY *m, STATE *s)
2160 int needpass = -1, pgp_keyblock = 0;
2164 LOFF_T last_pos, offset;
2165 char buf[HUGE_STRING];
2166 FILE *pgpout = NULL;
2168 gpgme_error_t err = 0;
2169 gpgme_data_t armored_data = NULL;
2171 short maybe_goodsig = 1;
2172 short have_any_sigs = 0;
2174 char body_charset[STRING]; /* Only used for clearsigned messages. */
2176 dprint (2, (debugfile, "Entering pgp_application_pgp handler\n"));
2178 /* For clearsigned messages we won't be able to get a character set
2179 but we know that this may only be text thus we assume Latin-1
2181 if (!mutt_get_body_charset (body_charset, sizeof (body_charset), m))
2182 strfcpy (body_charset, "iso-8859-1", sizeof body_charset);
2184 fseeko (s->fpin, m->offset, 0);
2185 last_pos = m->offset;
2187 for (bytes = m->length; bytes > 0;)
2189 if (fgets (buf, sizeof (buf), s->fpin) == NULL)
2192 offset = ftello (s->fpin);
2193 bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */
2196 if (!mutt_strncmp ("-----BEGIN PGP ", buf, 15))
2199 start_pos = last_pos;
2201 if (!mutt_strcmp ("MESSAGE-----\n", buf + 15))
2203 else if (!mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15))
2208 else if (!mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15))
2215 /* XXX - we may wish to recode here */
2217 state_puts (s->prefix, s);
2218 state_puts (buf, s);
2222 have_any_sigs = (have_any_sigs
2223 || (clearsign && (s->flags & M_VERIFY)));
2225 /* Copy PGP material to an data container */
2226 armored_data = file_to_data_object (s->fpin, m->offset, m->length);
2227 /* Invoke PGP if needed */
2230 pgp_gpgme_extract_keys (armored_data, &pgpout, 1);
2232 else if (!clearsign || (s->flags & M_VERIFY))
2234 unsigned int sig_stat = 0;
2235 gpgme_data_t plaintext;
2238 plaintext = create_gpgme_data ();
2239 ctx = create_gpgme_context (0);
2242 err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
2245 err = gpgme_op_decrypt_verify (ctx, armored_data, plaintext);
2246 if (gpg_err_code (err) == GPG_ERR_NO_DATA)
2248 /* Decrypt verify can't handle signed only messages. */
2249 err = (gpgme_data_seek (armored_data, 0, SEEK_SET) == -1)
2250 ? gpgme_error_from_errno (errno) : 0;
2251 /* Must release plaintext so that we supply an
2252 uninitialized object. */
2253 gpgme_data_release (plaintext);
2254 plaintext = create_gpgme_data ();
2255 err = gpgme_op_verify (ctx, armored_data,
2264 snprintf (errbuf, sizeof(errbuf)-1,
2265 _("Error: decryption/verification failed: %s\n"),
2266 gpgme_strerror (err));
2267 state_attach_puts (errbuf, s);
2270 { /* Decryption/Verification succeeded */
2274 /* Check whether signatures have been verified. */
2275 gpgme_verify_result_t verify_result;
2277 verify_result = gpgme_op_verify_result (ctx);
2278 if (verify_result->signatures)
2284 if ((s->flags & M_DISPLAY) && sig_stat)
2290 state_attach_puts (_("[-- Begin signature "
2291 "information --]\n"), s);
2294 (res = show_one_sig_status (ctx, idx, s)) != -1;
2305 state_attach_puts (_("[-- End signature "
2306 "information --]\n\n"), s);
2309 tmpfname = data_object_to_tempfile (plaintext, &pgpout);
2313 state_attach_puts (_("Error: copy data failed\n"), s);
2321 gpgme_release (ctx);
2325 * Now, copy cleartext to the screen. NOTE - we expect that PGP
2326 * outputs utf-8 cleartext. This may not always be true, but it
2327 * seems to be a reasonable guess.
2330 if(s->flags & M_DISPLAY)
2333 state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s);
2334 else if (pgp_keyblock)
2335 state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"),
2338 state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"),
2344 copy_clearsigned (armored_data, s, body_charset);
2351 fc = fgetconv_open (pgpout, "utf-8", Charset, 0);
2352 while ((c = fgetconv (fc)) != EOF)
2355 if (c == '\n' && s->prefix)
2356 state_puts (s->prefix, s);
2358 fgetconv_close (&fc);
2361 if (s->flags & M_DISPLAY)
2363 state_putc ('\n', s);
2365 state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
2366 else if (pgp_keyblock)
2367 state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
2369 state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
2374 safe_fclose (&pgpout);
2380 /* why would we want to display this at all? */
2381 /* XXX - we may wish to recode here */
2383 state_puts (s->prefix, s);
2384 state_puts (buf, s);
2389 m->goodsig = (maybe_goodsig && have_any_sigs);
2393 state_attach_puts (_("[-- Error: could not find beginning"
2394 " of PGP message! --]\n\n"), s);
2397 dprint (2, (debugfile, "Leaving pgp_application_pgp handler\n"));
2403 * Implementation of `encrypted_handler'.
2406 /* MIME handler for pgp/mime encrypted messages. */
2407 int pgp_gpgme_encrypted_handler (BODY *a, STATE *s)
2409 char tempfile[_POSIX_PATH_MAX];
2412 BODY *orig_body = a;
2416 dprint (2, (debugfile, "Entering pgp_encrypted handler\n"));
2418 if (!a || a->type != TYPEAPPLICATION || !a->subtype
2419 || ascii_strcasecmp ("pgp-encrypted", a->subtype)
2420 || !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype
2421 || ascii_strcasecmp ("octet-stream", a->next->subtype) )
2423 if (s->flags & M_DISPLAY)
2424 state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
2429 /* Move forward to the application/pgp-encrypted body. */
2432 mutt_mktemp (tempfile);
2433 if (!(fpout = safe_fopen (tempfile, "w+")))
2435 if (s->flags & M_DISPLAY)
2436 state_attach_puts (_("[-- Error: could not create temporary file! "
2441 tattach = decrypt_part (a, s, fpout, 0, &is_signed);
2444 tattach->goodsig = is_signed > 0;
2446 if (s->flags & M_DISPLAY)
2447 state_attach_puts (is_signed?
2448 _("[-- The following data is PGP/MIME signed and encrypted --]\n\n"):
2449 _("[-- The following data is PGP/MIME encrypted --]\n\n"),
2453 FILE *savefp = s->fpin;
2455 rc = mutt_body_handler (tattach, s);
2460 * if a multipart/signed is the _only_ sub-part of a
2461 * multipart/encrypted, cache signature verification
2464 if (mutt_is_multipart_signed (tattach) && !tattach->next)
2465 orig_body->goodsig |= tattach->goodsig;
2467 if (s->flags & M_DISPLAY)
2469 state_puts ("\n", s);
2470 state_attach_puts (is_signed?
2471 _("[-- End of PGP/MIME signed and encrypted data --]\n"):
2472 _("[-- End of PGP/MIME encrypted data --]\n"),
2476 mutt_free_body (&tattach);
2480 mutt_unlink(tempfile);
2481 dprint (2, (debugfile, "Leaving pgp_encrypted handler\n"));
2486 /* Support for application/smime */
2487 int smime_gpgme_application_handler (BODY *a, STATE *s)
2489 char tempfile[_POSIX_PATH_MAX];
2495 dprint (2, (debugfile, "Entering smime_encrypted handler\n"));
2498 mutt_mktemp (tempfile);
2499 if (!(fpout = safe_fopen (tempfile, "w+")))
2501 if (s->flags & M_DISPLAY)
2502 state_attach_puts (_("[-- Error: could not create temporary file! "
2507 tattach = decrypt_part (a, s, fpout, 1, &is_signed);
2510 tattach->goodsig = is_signed > 0;
2512 if (s->flags & M_DISPLAY)
2513 state_attach_puts (is_signed?
2514 _("[-- The following data is S/MIME signed --]\n\n"):
2515 _("[-- The following data is S/MIME encrypted --]\n\n"),
2519 FILE *savefp = s->fpin;
2521 rc = mutt_body_handler (tattach, s);
2526 * if a multipart/signed is the _only_ sub-part of a
2527 * multipart/encrypted, cache signature verification
2530 if (mutt_is_multipart_signed (tattach) && !tattach->next)
2532 if (!(a->goodsig = tattach->goodsig))
2533 a->warnsig = tattach->warnsig;
2535 else if (tattach->goodsig)
2538 a->warnsig = tattach->warnsig;
2541 if (s->flags & M_DISPLAY)
2543 state_puts ("\n", s);
2544 state_attach_puts (is_signed?
2545 _("[-- End of S/MIME signed data --]\n"):
2546 _("[-- End of S/MIME encrypted data --]\n"),
2550 mutt_free_body (&tattach);
2554 mutt_unlink(tempfile);
2555 dprint (2, (debugfile, "Leaving smime_encrypted handler\n"));
2562 * Format an entry on the CRYPT key selection menu.
2565 * %k key id %K key id of the principal key
2567 * %a algorithm %A algorithm of the princ. key
2568 * %l length %L length of the princ. key
2569 * %f flags %F flags of the princ. key
2570 * %c capabilities %C capabilities of the princ. key
2571 * %t trust/validity of the key-uid association
2573 * %[...] date of key using strftime(3)
2576 static const char *crypt_entry_fmt (char *dest,
2582 const char *ifstring,
2583 const char *elsestring,
2588 crypt_entry_t *entry;
2591 int optional = (flags & M_FORMAT_OPTIONAL);
2592 const char *s = NULL;
2595 entry = (crypt_entry_t *) data;
2598 /* if (isupper ((unsigned char) op)) */
2601 kflags = (key->flags /*| (pkey->flags & KEYFLAG_RESTRICTIONS)
2604 switch (ascii_tolower (op))
2609 char buf2[SHORT_STRING], *p;
2626 while (len > 0 && *cp != ']')
2638 break; /* not enough space */
2649 if (do_locales && Locale)
2650 setlocale (LC_TIME, Locale);
2655 if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
2656 tt = key->kobj->subkeys->timestamp;
2658 tm = localtime (&tt);
2660 strftime (buf2, sizeof (buf2), dest, tm);
2663 setlocale (LC_TIME, "C");
2665 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2666 snprintf (dest, destlen, fmt, buf2);
2674 snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
2675 snprintf (dest, destlen, fmt, entry->num);
2681 /* fixme: we need a way to distinguish between main and subkeys.
2682 Store the idx in entry? */
2683 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2684 snprintf (dest, destlen, fmt, crypt_keyid (key));
2690 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2691 snprintf (dest, destlen, fmt, key->uid);
2697 snprintf (fmt, sizeof (fmt), "%%%s.3s", prefix);
2698 if (key->kobj->subkeys)
2699 s = gpgme_pubkey_algo_name (key->kobj->subkeys->pubkey_algo);
2702 snprintf (dest, destlen, fmt, s);
2708 snprintf (fmt, sizeof (fmt), "%%%slu", prefix);
2709 if (key->kobj->subkeys)
2710 val = key->kobj->subkeys->length;
2713 snprintf (dest, destlen, fmt, val);
2719 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2720 snprintf (dest, destlen, fmt, crypt_flags (kflags));
2722 else if (!(kflags & (KEYFLAG_RESTRICTIONS)))
2728 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2729 snprintf (dest, destlen, fmt, crypt_key_abilities (kflags));
2731 else if (!(kflags & (KEYFLAG_ABILITIES)))
2735 if ((kflags & KEYFLAG_ISX509))
2739 gpgme_user_id_t uid = NULL;
2742 for (i = 0, uid = key->kobj->uids; uid && (i < key->idx);
2743 i++, uid = uid->next)
2746 switch (uid->validity)
2748 case GPGME_VALIDITY_UNDEFINED:
2751 case GPGME_VALIDITY_NEVER:
2754 case GPGME_VALIDITY_MARGINAL:
2757 case GPGME_VALIDITY_FULL:
2760 case GPGME_VALIDITY_ULTIMATE:
2763 case GPGME_VALIDITY_UNKNOWN:
2769 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2770 snprintf (dest, destlen, fmt, s? *s: 'B');
2773 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2774 snprintf (dest, destlen, fmt,
2775 gpgme_get_protocol_name (key->kobj->protocol));
2783 mutt_FormatString (dest, destlen, col, ifstring, mutt_attach_fmt, data, 0);
2784 else if (flags & M_FORMAT_OPTIONAL)
2785 mutt_FormatString (dest, destlen, col, elsestring, mutt_attach_fmt, data, 0);
2789 /* Used by the display fucntion to format a line. */
2790 static void crypt_entry (char *s, size_t l, MUTTMENU * menu, int num)
2792 crypt_key_t **key_table = (crypt_key_t **) menu->data;
2793 crypt_entry_t entry;
2795 entry.key = key_table[num];
2796 entry.num = num + 1;
2798 mutt_FormatString (s, l, 0, NONULL (PgpEntryFormat), crypt_entry_fmt,
2799 (unsigned long) &entry, M_FORMAT_ARROWCURSOR);
2802 /* Compare two addresses and the keyid to be used for sorting. */
2803 static int _crypt_compare_address (const void *a, const void *b)
2805 crypt_key_t **s = (crypt_key_t **) a;
2806 crypt_key_t **t = (crypt_key_t **) b;
2809 if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid)))
2812 return mutt_strcasecmp (crypt_keyid (*s), crypt_keyid (*t)) > 0;
2815 static int crypt_compare_address (const void *a, const void *b)
2817 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_address (a, b)
2818 : _crypt_compare_address (a, b));
2822 /* Compare two key IDs and the addresses to be used for sorting. */
2823 static int _crypt_compare_keyid (const void *a, const void *b)
2825 crypt_key_t **s = (crypt_key_t **) a;
2826 crypt_key_t **t = (crypt_key_t **) b;
2829 if ((r = mutt_strcasecmp (crypt_keyid (*s), crypt_keyid (*t))))
2832 return mutt_strcasecmp ((*s)->uid, (*t)->uid) > 0;
2835 static int crypt_compare_keyid (const void *a, const void *b)
2837 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_keyid (a, b)
2838 : _crypt_compare_keyid (a, b));
2841 /* Compare 2 creation dates and the addresses. For sorting. */
2842 static int _crypt_compare_date (const void *a, const void *b)
2844 crypt_key_t **s = (crypt_key_t **) a;
2845 crypt_key_t **t = (crypt_key_t **) b;
2846 unsigned long ts = 0, tt = 0;
2848 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2849 ts = (*s)->kobj->subkeys->timestamp;
2850 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2851 tt = (*t)->kobj->subkeys->timestamp;
2858 return mutt_strcasecmp ((*s)->uid, (*t)->uid) > 0;
2861 static int crypt_compare_date (const void *a, const void *b)
2863 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_date (a, b)
2864 : _crypt_compare_date (a, b));
2867 /* Compare two trust values, the key length, the creation dates. the
2868 addresses and the key IDs. For sorting. */
2869 static int _crypt_compare_trust (const void *a, const void *b)
2871 crypt_key_t **s = (crypt_key_t **) a;
2872 crypt_key_t **t = (crypt_key_t **) b;
2873 unsigned long ts = 0, tt = 0;
2876 if ((r = (((*s)->flags & (KEYFLAG_RESTRICTIONS))
2877 - ((*t)->flags & (KEYFLAG_RESTRICTIONS)))))
2880 if ((*s)->kobj->uids)
2881 ts = (*s)->kobj->uids->validity;
2882 if ((*t)->kobj->uids)
2883 tt = (*t)->kobj->uids->validity;
2884 if ((r = (tt - ts)))
2887 if ((*s)->kobj->subkeys)
2888 ts = (*s)->kobj->subkeys->length;
2889 if ((*t)->kobj->subkeys)
2890 tt = (*t)->kobj->subkeys->length;
2894 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2895 ts = (*s)->kobj->subkeys->timestamp;
2896 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2897 tt = (*t)->kobj->subkeys->timestamp;
2903 if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid)))
2905 return (mutt_strcasecmp (crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0;
2908 static int crypt_compare_trust (const void *a, const void *b)
2910 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_trust (a, b)
2911 : _crypt_compare_trust (a, b));
2914 /* Print the X.500 Distinguished Name part KEY from the array of parts
2917 print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key)
2921 for (; dn->key; dn++)
2923 if (!strcmp (dn->key, key))
2927 print_utf8 (fp, dn->value, strlen (dn->value));
2934 /* Print all parts of a DN in a standard sequence. */
2936 print_dn_parts (FILE *fp, struct dn_array_s *dn)
2938 const char *stdpart[] = {
2939 "CN", "OU", "O", "STREET", "L", "ST", "C", NULL
2941 int any=0, any2=0, i;
2943 for (i=0; stdpart[i]; i++)
2947 any = print_dn_part (fp, dn, stdpart[i]);
2949 /* now print the rest without any specific ordering */
2950 for (; dn->key; dn++)
2952 for (i=0; stdpart[i]; i++)
2954 if (!strcmp (dn->key, stdpart[i]))
2963 any = print_dn_part (fp, dn, dn->key);
2972 /* Parse an RDN; this is a helper to parse_dn(). */
2973 static const unsigned char *
2974 parse_dn_part (struct dn_array_s *array, const unsigned char *string)
2976 const unsigned char *s, *s1;
2980 /* parse attributeType */
2981 for (s = string+1; *s && *s != '='; s++)
2984 return NULL; /* error */
2987 return NULL; /* empty key */
2988 array->key = safe_malloc (n+1);
2989 p = (unsigned char *)array->key;
2990 memcpy (p, string, n); /* fixme: trim trailing spaces */
2997 for (s=string; hexdigitp (s); s++)
3001 return NULL; /* empty or odd number of digits */
3003 p = safe_malloc (n+1);
3004 array->value = (char*)p;
3005 for (s1=string; n; s1 += 2, n--)
3010 { /* regular v3 quoted string */
3011 for (n=0, s=string; *s; s++)
3016 if (*s == ',' || *s == '=' || *s == '+'
3017 || *s == '<' || *s == '>' || *s == '#' || *s == ';'
3018 || *s == '\\' || *s == '\"' || *s == ' ')
3020 else if (hexdigitp (s) && hexdigitp (s+1))
3026 return NULL; /* invalid escape sequence */
3028 else if (*s == '\"')
3029 return NULL; /* invalid encoding */
3030 else if (*s == ',' || *s == '=' || *s == '+'
3031 || *s == '<' || *s == '>' || *s == '#' || *s == ';' )
3037 p = safe_malloc (n+1);
3038 array->value = (char*)p;
3039 for (s=string; n; s++, n--)
3061 /* Parse a DN and return an array-ized one. This is not a validating
3062 parser and it does not support any old-stylish syntax; gpgme is
3063 expected to return only rfc2253 compatible strings. */
3064 static struct dn_array_s *
3065 parse_dn (const unsigned char *string)
3067 struct dn_array_s *array;
3068 size_t arrayidx, arraysize;
3071 arraysize = 7; /* C,ST,L,O,OU,CN,email */
3072 array = safe_malloc ((arraysize+1) * sizeof *array);
3076 while (*string == ' ')
3080 if (arrayidx >= arraysize)
3081 { /* mutt lacks a real safe_realoc - so we need to copy */
3082 struct dn_array_s *a2;
3085 a2 = safe_malloc ((arraysize+1) * sizeof *array);
3086 for (i=0; i < arrayidx; i++)
3088 a2[i].key = array[i].key;
3089 a2[i].value = array[i].value;
3094 array[arrayidx].key = NULL;
3095 array[arrayidx].value = NULL;
3096 string = parse_dn_part (array+arrayidx, string);
3100 while (*string == ' ')
3102 if (*string && *string != ',' && *string != ';' && *string != '+')
3103 goto failure; /* invalid delimiter */
3107 array[arrayidx].key = NULL;
3108 array[arrayidx].value = NULL;
3112 for (i=0; i < arrayidx; i++)
3114 FREE (&array[i].key);
3115 FREE (&array[i].value);
3122 /* Print a nice representation of the USERID and make sure it is
3123 displayed in a proper way, which does mean to reorder some parts
3124 for S/MIME's DNs. USERID is a string as returned by the gpgme key
3125 functions. It is utf-8 encoded. */
3127 parse_and_print_user_id (FILE *fp, const char *userid)
3134 s = strchr (userid+1, '>');
3136 print_utf8 (fp, userid+1, s-userid-1);
3138 else if (*userid == '(')
3139 fputs (_("[Can't display this user ID (unknown encoding)]"), fp);
3140 else if (!digit_or_letter ((const unsigned char *)userid))
3141 fputs (_("[Can't display this user ID (invalid encoding)]"), fp);
3144 struct dn_array_s *dn = parse_dn ((const unsigned char *)userid);
3146 fputs (_("[Can't display this user ID (invalid DN)]"), fp);
3149 print_dn_parts (fp, dn);
3150 for (i=0; dn[i].key; i++)
3153 FREE (&dn[i].value);
3162 KEY_CAP_CAN_ENCRYPT,
3169 key_check_cap (gpgme_key_t key, key_cap_t cap)
3171 gpgme_subkey_t subkey = NULL;
3172 unsigned int ret = 0;
3176 case KEY_CAP_CAN_ENCRYPT:
3177 if (! (ret = key->can_encrypt))
3178 for (subkey = key->subkeys; subkey; subkey = subkey->next)
3179 if ((ret = subkey->can_encrypt))
3182 case KEY_CAP_CAN_SIGN:
3183 if (! (ret = key->can_sign))
3184 for (subkey = key->subkeys; subkey; subkey = subkey->next)
3185 if ((ret = subkey->can_sign))
3188 case KEY_CAP_CAN_CERTIFY:
3189 if (! (ret = key->can_certify))
3190 for (subkey = key->subkeys; subkey; subkey = subkey->next)
3191 if ((ret = subkey->can_certify))
3200 /* Print verbose information about a key or certificate to FP. */
3201 static void print_key_info (gpgme_key_t key, FILE *fp)
3204 const char *s = NULL, *s2 = NULL;
3207 char shortbuf[SHORT_STRING];
3208 unsigned long aval = 0;
3212 gpgme_user_id_t uid = NULL;
3215 setlocale (LC_TIME, Locale);
3217 is_pgp = key->protocol == GPGME_PROTOCOL_OpenPGP;
3219 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3225 fputs (idx ? _(" aka ......: ") :_("Name ......: "), fp);
3228 fputs (_("[Invalid]"), fp);
3232 print_utf8 (fp, s, strlen(s));
3234 parse_and_print_user_id (fp, s);
3238 if (key->subkeys && (key->subkeys->timestamp > 0))
3240 tt = key->subkeys->timestamp;
3242 tm = localtime (&tt);
3243 #ifdef HAVE_LANGINFO_D_T_FMT
3244 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
3246 strftime (shortbuf, sizeof shortbuf, "%c", tm);
3248 fprintf (fp, _("Valid From : %s\n"), shortbuf);
3251 if (key->subkeys && (key->subkeys->expires > 0))
3253 tt = key->subkeys->expires;
3255 tm = localtime (&tt);
3256 #ifdef HAVE_LANGINFO_D_T_FMT
3257 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
3259 strftime (shortbuf, sizeof shortbuf, "%c", tm);
3261 fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
3265 s = gpgme_pubkey_algo_name (key->subkeys->pubkey_algo);
3269 s2 = is_pgp ? "PGP" : "X.509";
3272 aval = key->subkeys->length;
3274 fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), s2, aval, s);
3276 fprintf (fp, _("Key Usage .: "));
3279 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3281 fprintf (fp, "%s%s", delim, _("encryption"));
3284 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3286 fprintf (fp, "%s%s", delim, _("signing"));
3289 if (key_check_cap (key, KEY_CAP_CAN_CERTIFY))
3291 fprintf (fp, "%s%s", delim, _("certification"));
3298 s = key->subkeys->fpr;
3299 fputs (_("Fingerprint: "), fp);
3300 if (is_pgp && strlen (s) == 40)
3302 for (i=0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++)
3308 putc (is_pgp? ' ':':', fp);
3309 if (is_pgp && i == 4)
3315 for (i=0; *s && s[1] && s[2]; s += 2, i++)
3319 putc (is_pgp? ' ':':', fp);
3320 if (is_pgp && i == 7)
3324 fprintf (fp, "%s\n", s);
3327 if (key->issuer_serial)
3329 s = key->issuer_serial;
3331 fprintf (fp, _("Serial-No .: 0x%s\n"), s);
3334 if (key->issuer_name)
3336 s = key->issuer_name;
3339 fprintf (fp, _("Issued By .: "));
3340 parse_and_print_user_id (fp, s);
3345 /* For PGP we list all subkeys. */
3348 gpgme_subkey_t subkey = NULL;
3350 for (idx = 1, subkey = key->subkeys; subkey;
3351 idx++, subkey = subkey->next)
3356 if ( strlen (s) == 16)
3357 s += 8; /* display only the short keyID */
3358 fprintf (fp, _("Subkey ....: 0x%s"), s);
3359 if (subkey->revoked)
3362 fputs (_("[Revoked]"), fp);
3364 if (subkey->invalid)
3367 fputs (_("[Invalid]"), fp);
3369 if (subkey->expired)
3372 fputs (_("[Expired]"), fp);
3374 if (subkey->disabled)
3377 fputs (_("[Disabled]"), fp);
3381 if (subkey->timestamp > 0)
3383 tt = subkey->timestamp;
3385 tm = localtime (&tt);
3386 #ifdef HAVE_LANGINFO_D_T_FMT
3387 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
3389 strftime (shortbuf, sizeof shortbuf, "%c", tm);
3391 fprintf (fp, _("Valid From : %s\n"), shortbuf);
3394 if (subkey->expires > 0)
3396 tt = subkey->expires;
3398 tm = localtime (&tt);
3399 #ifdef HAVE_LANGINFO_D_T_FMT
3400 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
3402 strftime (shortbuf, sizeof shortbuf, "%c", tm);
3404 fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
3408 s = gpgme_pubkey_algo_name (subkey->pubkey_algo);
3413 aval = subkey->length;
3417 fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), "PGP", aval, s);
3419 fprintf (fp, _("Key Usage .: "));
3422 if (subkey->can_encrypt)
3424 fprintf (fp, "%s%s", delim, _("encryption"));
3427 if (subkey->can_sign)
3429 fprintf (fp, "%s%s", delim, _("signing"));
3432 if (subkey->can_certify)
3434 fprintf (fp, "%s%s", delim, _("certification"));
3442 setlocale (LC_TIME, "C");
3446 /* Show detailed information about the selected key */
3448 verify_key (crypt_key_t *key)
3451 char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
3453 gpgme_ctx_t listctx = NULL;
3455 gpgme_key_t k = NULL;
3458 mutt_mktemp (tempfile);
3459 if (!(fp = safe_fopen (tempfile, "w")))
3461 mutt_perror _("Can't create temporary file");
3464 mutt_message _("Collecting data...");
3466 print_key_info (key->kobj, fp);
3468 err = gpgme_new (&listctx);
3471 fprintf (fp, "Internal error: can't create gpgme context: %s\n",
3472 gpgme_strerror (err));
3475 if ((key->flags & KEYFLAG_ISX509))
3476 gpgme_set_protocol (listctx, GPGME_PROTOCOL_CMS);
3480 while ((s = k->chain_id) && k->subkeys && strcmp (s, k->subkeys->fpr) )
3483 err = gpgme_op_keylist_start (listctx, s, 0);
3484 gpgme_key_release (k);
3487 err = gpgme_op_keylist_next (listctx, &k);
3490 fprintf (fp, _("Error finding issuer key: %s\n"),
3491 gpgme_strerror (err));
3494 gpgme_op_keylist_end (listctx);
3496 print_key_info (k, fp);
3500 fputs (_("Error: certification chain to long - stopping here\n"),
3507 gpgme_key_release (k);
3508 gpgme_release (listctx);
3510 mutt_clear_error ();
3511 snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), crypt_keyid (key));
3512 mutt_do_pager (cmd, tempfile, 0, NULL);
3516 * Implementation of `findkeys'.
3520 /* Convert LIST into a pattern string suitable to be passed to GPGME.
3521 We need to convert spaces in an item into a '+' and '%' into
3523 static char *list_to_pattern (LIST *list)
3531 for(l=list; l; l = l->next)
3533 for(s = l->data; *s; s++)
3539 n++; /* delimiter or end of string */
3541 n++; /* make sure to allocate at least one byte */
3542 pattern = p = safe_calloc (1,n);
3543 for(l=list; l; l = l->next)
3550 for(s = l->data; *s; s++)
3575 /* Return a list of keys which are candidates for the selection.
3576 Select by looking at the HINTS list. */
3577 static crypt_key_t *get_candidates (LIST * hints, unsigned int app, int secret)
3579 crypt_key_t *db, *k, **kend;
3585 gpgme_user_id_t uid = NULL;
3587 pattern = list_to_pattern (hints);
3591 err = gpgme_new (&ctx);
3594 mutt_error (_("gpgme_new failed: %s"), gpgme_strerror (err));
3602 if ((app & APPLICATION_PGP))
3604 /* Its all a mess. That old GPGME expects different things
3605 depending on the protocol. For gpg we don' t need percent
3606 escaped pappert but simple strings passed in an array to the
3607 keylist_ext_start function. */
3612 for(l=hints, n=0; l; l = l->next)
3614 if (l->data && *l->data)
3620 patarr = safe_calloc (n+1, sizeof *patarr);
3621 for(l=hints, n=0; l; l = l->next)
3623 if (l->data && *l->data)
3624 patarr[n++] = safe_strdup (l->data);
3627 err = gpgme_op_keylist_ext_start (ctx, (const char**)patarr, secret, 0);
3628 for (n=0; patarr[n]; n++)
3633 mutt_error (_("gpgme_op_keylist_start failed: %s"),
3634 gpgme_strerror (err));
3635 gpgme_release (ctx);
3640 while (!(err = gpgme_op_keylist_next (ctx, &key)) )
3642 unsigned int flags = 0;
3644 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3645 flags |= KEYFLAG_CANENCRYPT;
3646 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3647 flags |= KEYFLAG_CANSIGN;
3649 #if 0 /* DISABLED code */
3652 /* Bug in gpg. Capabilities are not listed for secret
3653 keys. Try to deduce them from the algorithm. */
3655 switch (key->subkeys[0].pubkey_algo)
3658 flags |= KEYFLAG_CANENCRYPT;
3659 flags |= KEYFLAG_CANSIGN;
3661 case GPGME_PK_ELG_E:
3662 flags |= KEYFLAG_CANENCRYPT;
3665 flags |= KEYFLAG_CANSIGN;
3669 #endif /* DISABLED code */
3671 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3673 k = safe_calloc (1, sizeof *k);
3682 if (gpg_err_code (err) != GPG_ERR_EOF)
3683 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3684 gpgme_op_keylist_end (ctx);
3689 if ((app & APPLICATION_SMIME))
3691 /* and now look for x509 certificates */
3692 gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
3693 err = gpgme_op_keylist_start (ctx, pattern, 0);
3696 mutt_error (_("gpgme_op_keylist_start failed: %s"),
3697 gpgme_strerror (err));
3698 gpgme_release (ctx);
3703 while (!(err = gpgme_op_keylist_next (ctx, &key)) )
3705 unsigned int flags = KEYFLAG_ISX509;
3707 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3708 flags |= KEYFLAG_CANENCRYPT;
3709 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3710 flags |= KEYFLAG_CANSIGN;
3712 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3714 k = safe_calloc (1, sizeof *k);
3723 if (gpg_err_code (err) != GPG_ERR_EOF)
3724 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3725 gpgme_op_keylist_end (ctx);
3728 gpgme_release (ctx);
3733 /* Add the string STR to the list HINTS. This list is later used to
3735 static LIST *crypt_add_string_to_hints (LIST *hints, const char *str)
3740 if ((scratch = safe_strdup (str)) == NULL)
3743 for (t = strtok (scratch, " ,.:\"()<>\n"); t;
3744 t = strtok (NULL, " ,.:\"()<>\n"))
3747 hints = mutt_add_list (hints, t);
3754 /* Display a menu to select a key from the array KEYS. FORCED_VALID
3755 will be set to true on return if the user did override the the
3757 static crypt_key_t *crypt_select_key (crypt_key_t *keys,
3758 ADDRESS * p, const char *s,
3759 unsigned int app, int *forced_valid)
3762 crypt_key_t **key_table;
3765 char helpstr[LONG_STRING], buf[LONG_STRING];
3767 int (*f) (const void *, const void *);
3768 int menu_to_use = 0;
3773 /* build the key table */
3776 for (k = keys; k; k = k->next)
3778 if (!option (OPTPGPSHOWUNUSABLE) && (k->flags & KEYFLAG_CANTUSE))
3787 safe_realloc (&key_table, sizeof (crypt_key_t*)*keymax);
3795 mutt_error _("All matching keys are marked expired/revoked.");
3800 switch (PgpSortKeys & SORT_MASK)
3803 f = crypt_compare_date;
3806 f = crypt_compare_keyid;
3809 f = crypt_compare_address;
3813 f = crypt_compare_trust;
3816 qsort (key_table, i, sizeof (crypt_key_t*), f);
3818 if (app & APPLICATION_PGP)
3819 menu_to_use = MENU_KEY_SELECT_PGP;
3820 else if (app & APPLICATION_SMIME)
3821 menu_to_use = MENU_KEY_SELECT_SMIME;
3824 mutt_make_help (buf, sizeof (buf), _("Exit "), menu_to_use, OP_EXIT);
3825 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3826 mutt_make_help (buf, sizeof (buf), _("Select "), menu_to_use,
3827 OP_GENERIC_SELECT_ENTRY);
3828 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3829 mutt_make_help (buf, sizeof (buf), _("Check key "),
3830 menu_to_use, OP_VERIFY_KEY);
3831 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3832 mutt_make_help (buf, sizeof (buf), _("Help"), menu_to_use, OP_HELP);
3833 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3835 menu = mutt_new_menu (menu_to_use);
3837 menu->make_entry = crypt_entry;
3838 menu->help = helpstr;
3839 menu->data = key_table;
3844 if ((app & APPLICATION_PGP) && (app & APPLICATION_SMIME))
3845 ts = _("PGP and S/MIME keys matching");
3846 else if ((app & APPLICATION_PGP))
3847 ts = _("PGP keys matching");
3848 else if ((app & APPLICATION_SMIME))
3849 ts = _("S/MIME keys matching");
3851 ts = _("keys matching");
3854 snprintf (buf, sizeof (buf), _("%s <%s>."), ts, p->mailbox);
3856 snprintf (buf, sizeof (buf), _("%s \"%s\"."), ts, s);
3860 mutt_clear_error ();
3865 switch (mutt_menuLoop (menu))
3868 verify_key (key_table[menu->current]);
3869 menu->redraw = REDRAW_FULL;
3873 mutt_message ("%s", key_table[menu->current]->uid);
3876 case OP_GENERIC_SELECT_ENTRY:
3877 /* FIXME make error reporting more verbose - this should be
3878 easy because gpgme provides more information */
3879 if (option (OPTPGPCHECKTRUST))
3881 if (!crypt_key_is_valid (key_table[menu->current]))
3883 mutt_error _("This key can't be used: "
3884 "expired/disabled/revoked.");
3889 if (option (OPTPGPCHECKTRUST) &&
3890 (!crypt_id_is_valid (key_table[menu->current])
3891 || !crypt_id_is_strong (key_table[menu->current])))
3894 char buff[LONG_STRING];
3896 if (key_table[menu->current]->flags & KEYFLAG_CANTUSE)
3897 s = N_("ID is expired/disabled/revoked.");
3900 gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
3901 gpgme_user_id_t uid = NULL;
3906 uid = key_table[menu->current]->kobj->uids;
3907 for (j = 0; (j < key_table[menu->current]->idx) && uid;
3908 j++, uid = uid->next)
3911 val = uid->validity;
3915 case GPGME_VALIDITY_UNKNOWN:
3916 case GPGME_VALIDITY_UNDEFINED:
3917 warn_s = N_("ID has undefined validity.");
3919 case GPGME_VALIDITY_NEVER:
3920 warn_s = N_("ID is not valid.");
3922 case GPGME_VALIDITY_MARGINAL:
3923 warn_s = N_("ID is only marginally valid.");
3925 case GPGME_VALIDITY_FULL:
3926 case GPGME_VALIDITY_ULTIMATE:
3930 snprintf (buff, sizeof (buff),
3931 _("%s Do you really want to use the key?"),
3934 if (mutt_yesorno (buff, 0) != 1)
3936 mutt_clear_error ();
3943 k = crypt_copy_key (key_table[menu->current]);
3954 mutt_menuDestroy (&menu);
3957 set_option (OPTNEEDREDRAW);
3962 static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
3963 unsigned int app, int *forced_valid)
3971 int this_key_has_strong;
3972 int this_key_has_weak;
3973 int this_key_has_invalid;
3976 crypt_key_t *keys, *k;
3977 crypt_key_t *the_valid_key = NULL;
3978 crypt_key_t *matches = NULL;
3979 crypt_key_t **matches_endp = &matches;
3983 if (a && a->mailbox)
3984 hints = crypt_add_string_to_hints (hints, a->mailbox);
3985 if (a && a->personal)
3986 hints = crypt_add_string_to_hints (hints, a->personal);
3988 mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
3989 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN) );
3991 mutt_free_list (&hints);
3996 dprint (5, (debugfile, "crypt_getkeybyaddr: looking for %s <%s>.",
3997 a->personal, a->mailbox));
3999 for (k = keys; k; k = k->next)
4001 dprint (5, (debugfile, " looking at key: %s `%.15s'\n",
4002 crypt_keyid (k), k->uid));
4004 if (abilities && !(k->flags & abilities))
4006 dprint (5, (debugfile, " insufficient abilities: Has %x, want %x\n",
4007 k->flags, abilities));
4011 this_key_has_weak = 0; /* weak but valid match */
4012 this_key_has_invalid = 0; /* invalid match */
4013 this_key_has_strong = 0; /* strong and valid match */
4014 match = 0; /* any match */
4016 r = rfc822_parse_adrlist (NULL, k->uid);
4017 for (p = r; p; p = p->next)
4019 int validity = crypt_id_matches_addr (a, p, k);
4021 if (validity & CRYPT_KV_MATCH) /* something matches */
4024 /* is this key a strong candidate? */
4025 if ((validity & CRYPT_KV_VALID)
4026 && (validity & CRYPT_KV_STRONGID)
4027 && (validity & CRYPT_KV_ADDR))
4029 if (the_valid_key && the_valid_key != k)
4032 this_key_has_strong = 1;
4034 else if ((validity & CRYPT_KV_MATCH)
4035 && !(validity & CRYPT_KV_VALID))
4036 this_key_has_invalid = 1;
4037 else if ((validity & CRYPT_KV_MATCH)
4038 && (!(validity & CRYPT_KV_STRONGID)
4039 || !(validity & CRYPT_KV_ADDR)))
4040 this_key_has_weak = 1;
4042 rfc822_free_address (&r);
4048 if (!this_key_has_strong && this_key_has_invalid)
4050 if (!this_key_has_strong && this_key_has_weak)
4053 *matches_endp = tmp = crypt_copy_key (k);
4054 matches_endp = &tmp->next;
4055 the_valid_key = tmp;
4059 crypt_free_key (&keys);
4063 if (the_valid_key && !multi && !weak
4064 && !(invalid && option (OPTPGPSHOWUNUSABLE)))
4067 * There was precisely one strong match on a valid ID, there
4068 * were no valid keys with weak matches, and we aren't
4069 * interested in seeing invalid keys.
4071 * Proceed without asking the user.
4073 k = crypt_copy_key (the_valid_key);
4078 * Else: Ask the user.
4080 k = crypt_select_key (matches, a, NULL, app, forced_valid);
4082 crypt_free_key (&matches);
4091 static crypt_key_t *crypt_getkeybystr (char *p, short abilities,
4092 unsigned int app, int *forced_valid)
4096 crypt_key_t *matches = NULL;
4097 crypt_key_t **matches_endp = &matches;
4101 mutt_message (_("Looking for keys matching \"%s\"..."), p);
4105 hints = crypt_add_string_to_hints (hints, p);
4106 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
4107 mutt_free_list (&hints);
4112 for (k = keys; k; k = k->next)
4114 if (abilities && !(k->flags & abilities))
4118 dprint (5, (debugfile, "crypt_getkeybystr: matching \"%s\" against "
4119 "key %s, \"%s\": ", p, crypt_keyid (k), k->uid));
4122 || !mutt_strcasecmp (p, crypt_keyid (k))
4123 || (!mutt_strncasecmp (p, "0x", 2)
4124 && !mutt_strcasecmp (p + 2, crypt_keyid (k)))
4125 || (option (OPTPGPLONGIDS)
4126 && !mutt_strncasecmp (p, "0x", 2)
4127 && !mutt_strcasecmp (p + 2, crypt_keyid (k) + 8))
4128 || mutt_stristr (k->uid, p))
4132 dprint (5, (debugfile, "match.\n"));
4134 *matches_endp = tmp = crypt_copy_key (k);
4135 matches_endp = &tmp->next;
4139 crypt_free_key (&keys);
4143 k = crypt_select_key (matches, NULL, p, app, forced_valid);
4144 crypt_free_key (&matches);
4151 /* Display TAG as a prompt to ask for a key. If WHATFOR is not null
4152 use it as default and store it under that label as the next
4153 default. ABILITIES describe the required key abilities (sign,
4154 encrypt) and APP the type of the requested key; ether S/MIME or
4155 PGP. Return a copy of the key or NULL if not found. */
4156 static crypt_key_t *crypt_ask_for_key (char *tag,
4163 char resp[SHORT_STRING];
4164 struct crypt_cache *l = NULL;
4168 forced_valid = &dummy;
4170 mutt_clear_error ();
4177 for (l = id_defaults; l; l = l->next)
4178 if (!mutt_strcasecmp (whatfor, l->what))
4180 strfcpy (resp, NONULL (l->dflt), sizeof (resp));
4189 if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0)
4195 mutt_str_replace (&l->dflt, resp);
4198 l = safe_malloc (sizeof (struct crypt_cache));
4199 l->next = id_defaults;
4201 l->what = safe_strdup (whatfor);
4202 l->dflt = safe_strdup (resp);
4206 if ((key = crypt_getkeybystr (resp, abilities, app, forced_valid)))
4214 /* This routine attempts to find the keyids of the recipients of a
4215 message. It returns NULL if any of the keys can not be found. */
4216 static char *find_keys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc,
4219 char *keyID, *keylist = NULL, *t;
4220 size_t keylist_size = 0;
4221 size_t keylist_used = 0;
4222 ADDRESS *tmp = NULL, *addr = NULL;
4223 ADDRESS **last = &tmp;
4226 crypt_key_t *k_info, *key;
4227 const char *fqdn = mutt_fqdn (1);
4230 *r_application = APPLICATION_PGP|APPLICATION_SMIME;
4233 for (i = 0; i < 3; i++)
4237 case 0: p = to; break;
4238 case 1: p = cc; break;
4239 case 2: p = bcc; break;
4243 *last = rfc822_cpy_adr (p);
4245 last = &((*last)->next);
4249 rfc822_qualify (tmp, fqdn);
4251 tmp = mutt_remove_duplicates (tmp);
4253 for (p = tmp; p ; p = p->next)
4255 char buf[LONG_STRING];
4256 int forced_valid = 0;
4261 if ((keyID = mutt_crypt_hook (p)) != NULL)
4264 snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"),
4266 if ((r = mutt_yesorno (buf, M_YES)) == M_YES)
4268 /* check for e-mail address */
4269 if ((t = strchr (keyID, '@')) &&
4270 (addr = rfc822_parse_adrlist (NULL, keyID)))
4273 rfc822_qualify (addr, fqdn);
4279 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
4280 *r_application, &forced_valid);
4282 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
4283 app, &forced_valid);
4290 rfc822_free_address (&tmp);
4291 rfc822_free_address (&addr);
4297 && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT,
4298 app, &forced_valid)) == NULL)
4300 snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
4302 if ((key = crypt_ask_for_key (buf, q->mailbox,
4309 &forced_valid)) == NULL)
4312 rfc822_free_address (&tmp);
4313 rfc822_free_address (&addr);
4321 const char *s = crypt_fpr (key);
4324 if (key->flags & KEYFLAG_ISX509)
4325 *r_application &= ~APPLICATION_PGP;
4326 if (!(key->flags & KEYFLAG_ISX509))
4327 *r_application &= ~APPLICATION_SMIME;
4330 keylist_size += mutt_strlen (s) + 4 + 1;
4331 safe_realloc (&keylist, keylist_size);
4332 sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */
4333 keylist_used ? " " : "", s,
4334 forced_valid? "!":"");
4336 keylist_used = mutt_strlen (keylist);
4338 crypt_free_key (&key);
4339 rfc822_free_address (&addr);
4341 rfc822_free_address (&tmp);
4345 char *pgp_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc)
4347 return find_keys (to, cc, bcc, APPLICATION_PGP);
4350 char *smime_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc)
4352 return find_keys (to, cc, bcc, APPLICATION_SMIME);
4356 * Implementation of `init'.
4359 /* Initialization. */
4360 static void init_gpgme (void)
4362 /* Make sure that gpg-agent is running. */
4363 if (! getenv ("GPG_AGENT_INFO"))
4365 mutt_error (_("\nUsing GPGME backend, although no gpg-agent is running"));
4366 if (mutt_any_key_to_continue (NULL) == -1)
4371 void pgp_gpgme_init (void)
4376 void smime_gpgme_init (void)
4380 static int gpgme_send_menu (HEADER *msg, int *redraw, int is_smime)
4383 char input_signas[SHORT_STRING];
4386 if (msg->security & APPLICATION_PGP)
4388 else if (msg->security & APPLICATION_SMIME)
4392 choice = mutt_multi_choice (
4393 _("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?"),
4396 choice = mutt_multi_choice (
4397 _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?"),
4402 case 1: /* (e)ncrypt */
4403 msg->security |= (is_smime ? SMIMEENCRYPT : PGPENCRYPT);
4404 msg->security &= ~(is_smime ? SMIMESIGN : PGPSIGN);
4407 case 2: /* (s)ign */
4408 msg->security |= (is_smime? SMIMESIGN :PGPSIGN);
4409 msg->security &= ~(is_smime ? SMIMEENCRYPT : PGPENCRYPT);
4412 case 3: /* sign (a)s */
4413 /* unset_option(OPTCRYPTCHECKTRUST); */
4414 if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
4415 is_smime? APPLICATION_SMIME:APPLICATION_PGP,
4418 snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p));
4419 mutt_str_replace (is_smime? &SmimeDefaultKey : &PgpSignAs, input_signas);
4420 crypt_free_key (&p);
4422 msg->security |= (is_smime? SMIMESIGN:PGPSIGN);
4427 msg->security &= (is_smime? ~SMIMESIGN : ~PGPSIGN);
4430 *redraw = REDRAW_FULL;
4433 case 4: /* (b)oth */
4434 msg->security = (is_smime? (SMIMEENCRYPT|SMIMESIGN):(PGPENCRYPT|PGPSIGN));
4437 case 5: /* (p)gp or s/(m)ime */
4438 is_smime = !is_smime;
4441 case 6: /* (f)orget it */
4442 case 7: /* (c)lear */
4447 if (choice == 6 || choice == 7)
4451 msg->security &= ~APPLICATION_PGP;
4452 msg->security |= APPLICATION_SMIME;
4456 msg->security &= ~APPLICATION_SMIME;
4457 msg->security |= APPLICATION_PGP;
4460 return (msg->security);
4463 int pgp_gpgme_send_menu (HEADER *msg, int *redraw)
4465 return gpgme_send_menu (msg, redraw, 0);
4468 int smime_gpgme_send_menu (HEADER *msg, int *redraw)
4470 return gpgme_send_menu (msg, redraw, 1);
4473 static int verify_sender (HEADER *h, gpgme_protocol_t protocol)
4475 ADDRESS *sender = NULL;
4476 unsigned int ret = 1;
4480 h->env->from = mutt_expand_aliases (h->env->from);
4481 sender = h->env->from;
4483 else if (h->env->sender)
4485 h->env->sender = mutt_expand_aliases (h->env->sender);
4486 sender = h->env->sender;
4493 gpgme_key_t key = signature_key;
4494 gpgme_user_id_t uid = NULL;
4495 int sender_length = 0;
4498 sender_length = strlen (sender->mailbox);
4499 for (uid = key->uids; uid && ret; uid = uid->next)
4501 uid_length = strlen (uid->email);
4503 && (uid->email[0] == '<')
4504 && (uid->email[uid_length - 1] == '>')
4505 && (uid_length == sender_length + 2)
4506 && (! strncmp (uid->email + 1, sender->mailbox, sender_length)))
4511 mutt_any_key_to_continue (_("Failed to verify sender"));
4514 mutt_any_key_to_continue (_("Failed to figure out sender"));
4518 gpgme_key_release (signature_key);
4519 signature_key = NULL;
4525 int smime_gpgme_verify_sender (HEADER *h)
4527 return verify_sender (h, GPGME_PROTOCOL_CMS);
4530 void gpgme_set_sender (const char *sender)
4532 mutt_error ("[setting sender] mailbox: %s\n", sender);
4533 FREE (¤t_sender);
4534 current_sender = safe_strdup (sender);