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);
443 safe_fclose (&fptmp);
444 gpgme_data_seek (data, 0, SEEK_SET);
448 safe_fclose (&fptmp);
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;
1791 safe_fclose (&tmpfp);
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);
1827 safe_fclose (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;
1846 safe_fclose (&tmpfp);
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"));
1962 mutt_rmtree (tmpdir);
1964 gpgme_release (tmpctx);
1970 * Implementation of `pgp_check_traditional'.
1973 static int pgp_check_traditional_one_body (FILE *fp, BODY *b, int tagged_only)
1975 char tempfile[_POSIX_PATH_MAX];
1976 char buf[HUGE_STRING];
1982 if (b->type != TYPETEXT)
1985 if (tagged_only && !b->tagged)
1988 mutt_mktemp (tempfile);
1989 if (mutt_decode_save_attachment (fp, b, tempfile, 0, 0) != 0)
1995 if ((tfp = fopen (tempfile, "r")) == NULL)
2001 while (fgets (buf, sizeof (buf), tfp))
2003 if (!mutt_strncmp ("-----BEGIN PGP ", buf, 15))
2005 if (!mutt_strcmp ("MESSAGE-----\n", buf + 15))
2010 else if (!mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15))
2023 /* fix the content type */
2025 mutt_set_parameter ("format", "fixed", &b->parameter);
2026 mutt_set_parameter ("x-action", enc ? "pgp-encrypted" : "pgp-signed",
2032 int pgp_gpgme_check_traditional (FILE *fp, BODY *b, int tagged_only)
2036 for (; b; b = b->next)
2038 if (is_multipart (b))
2039 rv = (pgp_gpgme_check_traditional (fp, b->parts, tagged_only) || rv);
2040 else if (b->type == TYPETEXT)
2042 if ((r = mutt_is_application_pgp (b)))
2045 rv = (pgp_check_traditional_one_body (fp, b, tagged_only) || rv);
2051 /* TODO: looks like this won't work and we'll have to fully parse the
2052 * message file. GPGME makes life hard yet again. */
2053 void pgp_gpgme_invoke_import (const char *fname)
2055 gpgme_data_t keydata;
2061 if (!(in = safe_fopen (fname, "r")))
2063 if ((err = gpgme_data_new_from_stream (&keydata, in)) != GPG_ERR_NO_ERROR)
2065 dprint (1, (debugfile, "error converting key file into data object\n"));
2070 if (!pgp_gpgme_extract_keys (keydata, &out, 0))
2072 /* display import results */
2073 outlen = ftell (out);
2074 fseek (out, 0, SEEK_SET);
2075 mutt_copy_bytes (out, stdout, outlen);
2079 printf (_("Error extracting key data!\n"));
2084 * Implementation of `application_handler'.
2088 Copy a clearsigned message, and strip the signature and PGP's
2091 XXX - charset handling: We assume that it is safe to do
2092 character set decoding first, dash decoding second here, while
2093 we do it the other way around in the main handler.
2095 (Note that we aren't worse than Outlook & Cie in this, and also
2096 note that we can successfully handle anything produced by any
2097 existing versions of mutt.) */
2099 static void copy_clearsigned (gpgme_data_t data, STATE *s, char *charset)
2101 char buf[HUGE_STRING];
2102 short complete, armor_header;
2107 fname = data_object_to_tempfile (data, &fp);
2113 /* fromcode comes from the MIME Content-Type charset label. It might
2114 * be a wrong label, so we want the ability to do corrections via
2115 * charset-hooks. Therefore we set flags to M_ICONV_HOOK_FROM.
2117 fc = fgetconv_open (fp, charset, Charset, M_ICONV_HOOK_FROM);
2119 for (complete = 1, armor_header = 1;
2120 fgetconvs (buf, sizeof (buf), fc) != NULL;
2121 complete = strchr (buf, '\n') != NULL)
2126 state_puts (buf, s);
2130 if (!mutt_strcmp (buf, "-----BEGIN PGP SIGNATURE-----\n"))
2141 state_puts (s->prefix, s);
2143 if (buf[0] == '-' && buf[1] == ' ')
2144 state_puts (buf + 2, s);
2146 state_puts (buf, s);
2149 fgetconv_close (&fc);
2154 /* Support for classic_application/pgp */
2155 int pgp_gpgme_application_handler (BODY *m, STATE *s)
2157 int needpass = -1, pgp_keyblock = 0;
2161 LOFF_T last_pos, offset;
2162 char buf[HUGE_STRING];
2163 FILE *pgpout = NULL;
2165 gpgme_error_t err = 0;
2166 gpgme_data_t armored_data = NULL;
2168 short maybe_goodsig = 1;
2169 short have_any_sigs = 0;
2171 char body_charset[STRING]; /* Only used for clearsigned messages. */
2173 dprint (2, (debugfile, "Entering pgp_application_pgp handler\n"));
2175 /* For clearsigned messages we won't be able to get a character set
2176 but we know that this may only be text thus we assume Latin-1
2178 if (!mutt_get_body_charset (body_charset, sizeof (body_charset), m))
2179 strfcpy (body_charset, "iso-8859-1", sizeof body_charset);
2181 fseeko (s->fpin, m->offset, 0);
2182 last_pos = m->offset;
2184 for (bytes = m->length; bytes > 0;)
2186 if (fgets (buf, sizeof (buf), s->fpin) == NULL)
2189 offset = ftello (s->fpin);
2190 bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */
2193 if (!mutt_strncmp ("-----BEGIN PGP ", buf, 15))
2196 start_pos = last_pos;
2198 if (!mutt_strcmp ("MESSAGE-----\n", buf + 15))
2200 else if (!mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15))
2205 else if (!mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15))
2212 /* XXX - we may wish to recode here */
2214 state_puts (s->prefix, s);
2215 state_puts (buf, s);
2219 have_any_sigs = (have_any_sigs
2220 || (clearsign && (s->flags & M_VERIFY)));
2222 /* Copy PGP material to an data container */
2223 armored_data = file_to_data_object (s->fpin, m->offset, m->length);
2224 /* Invoke PGP if needed */
2227 pgp_gpgme_extract_keys (armored_data, &pgpout, 1);
2229 else if (!clearsign || (s->flags & M_VERIFY))
2231 unsigned int sig_stat = 0;
2232 gpgme_data_t plaintext;
2235 plaintext = create_gpgme_data ();
2236 ctx = create_gpgme_context (0);
2239 err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
2242 err = gpgme_op_decrypt_verify (ctx, armored_data, plaintext);
2243 if (gpg_err_code (err) == GPG_ERR_NO_DATA)
2245 /* Decrypt verify can't handle signed only messages. */
2246 err = (gpgme_data_seek (armored_data, 0, SEEK_SET) == -1)
2247 ? gpgme_error_from_errno (errno) : 0;
2248 /* Must release plaintext so that we supply an
2249 uninitialized object. */
2250 gpgme_data_release (plaintext);
2251 plaintext = create_gpgme_data ();
2252 err = gpgme_op_verify (ctx, armored_data,
2261 snprintf (errbuf, sizeof(errbuf)-1,
2262 _("Error: decryption/verification failed: %s\n"),
2263 gpgme_strerror (err));
2264 state_attach_puts (errbuf, s);
2267 { /* Decryption/Verification succeeded */
2271 /* Check whether signatures have been verified. */
2272 gpgme_verify_result_t verify_result;
2274 verify_result = gpgme_op_verify_result (ctx);
2275 if (verify_result->signatures)
2281 if ((s->flags & M_DISPLAY) && sig_stat)
2287 state_attach_puts (_("[-- Begin signature "
2288 "information --]\n"), s);
2291 (res = show_one_sig_status (ctx, idx, s)) != -1;
2302 state_attach_puts (_("[-- End signature "
2303 "information --]\n\n"), s);
2306 tmpfname = data_object_to_tempfile (plaintext, &pgpout);
2310 state_attach_puts (_("Error: copy data failed\n"), s);
2318 gpgme_release (ctx);
2322 * Now, copy cleartext to the screen. NOTE - we expect that PGP
2323 * outputs utf-8 cleartext. This may not always be true, but it
2324 * seems to be a reasonable guess.
2327 if(s->flags & M_DISPLAY)
2330 state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s);
2331 else if (pgp_keyblock)
2332 state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"),
2335 state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"),
2341 copy_clearsigned (armored_data, s, body_charset);
2348 fc = fgetconv_open (pgpout, "utf-8", Charset, 0);
2349 while ((c = fgetconv (fc)) != EOF)
2352 if (c == '\n' && s->prefix)
2353 state_puts (s->prefix, s);
2355 fgetconv_close (&fc);
2358 if (s->flags & M_DISPLAY)
2360 state_putc ('\n', s);
2362 state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
2363 else if (pgp_keyblock)
2364 state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
2366 state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
2371 safe_fclose (&pgpout);
2377 /* why would we want to display this at all? */
2378 /* XXX - we may wish to recode here */
2380 state_puts (s->prefix, s);
2381 state_puts (buf, s);
2386 m->goodsig = (maybe_goodsig && have_any_sigs);
2390 state_attach_puts (_("[-- Error: could not find beginning"
2391 " of PGP message! --]\n\n"), s);
2394 dprint (2, (debugfile, "Leaving pgp_application_pgp handler\n"));
2400 * Implementation of `encrypted_handler'.
2403 /* MIME handler for pgp/mime encrypted messages. */
2404 int pgp_gpgme_encrypted_handler (BODY *a, STATE *s)
2406 char tempfile[_POSIX_PATH_MAX];
2409 BODY *orig_body = a;
2413 dprint (2, (debugfile, "Entering pgp_encrypted handler\n"));
2415 if (!a || a->type != TYPEAPPLICATION || !a->subtype
2416 || ascii_strcasecmp ("pgp-encrypted", a->subtype)
2417 || !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype
2418 || ascii_strcasecmp ("octet-stream", a->next->subtype) )
2420 if (s->flags & M_DISPLAY)
2421 state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
2426 /* Move forward to the application/pgp-encrypted body. */
2429 mutt_mktemp (tempfile);
2430 if (!(fpout = safe_fopen (tempfile, "w+")))
2432 if (s->flags & M_DISPLAY)
2433 state_attach_puts (_("[-- Error: could not create temporary file! "
2438 tattach = decrypt_part (a, s, fpout, 0, &is_signed);
2441 tattach->goodsig = is_signed > 0;
2443 if (s->flags & M_DISPLAY)
2444 state_attach_puts (is_signed?
2445 _("[-- The following data is PGP/MIME signed and encrypted --]\n\n"):
2446 _("[-- The following data is PGP/MIME encrypted --]\n\n"),
2450 FILE *savefp = s->fpin;
2452 rc = mutt_body_handler (tattach, s);
2457 * if a multipart/signed is the _only_ sub-part of a
2458 * multipart/encrypted, cache signature verification
2461 if (mutt_is_multipart_signed (tattach) && !tattach->next)
2462 orig_body->goodsig |= tattach->goodsig;
2464 if (s->flags & M_DISPLAY)
2466 state_puts ("\n", s);
2467 state_attach_puts (is_signed?
2468 _("[-- End of PGP/MIME signed and encrypted data --]\n"):
2469 _("[-- End of PGP/MIME encrypted data --]\n"),
2473 mutt_free_body (&tattach);
2476 safe_fclose (&fpout);
2477 mutt_unlink(tempfile);
2478 dprint (2, (debugfile, "Leaving pgp_encrypted handler\n"));
2483 /* Support for application/smime */
2484 int smime_gpgme_application_handler (BODY *a, STATE *s)
2486 char tempfile[_POSIX_PATH_MAX];
2492 dprint (2, (debugfile, "Entering smime_encrypted handler\n"));
2495 mutt_mktemp (tempfile);
2496 if (!(fpout = safe_fopen (tempfile, "w+")))
2498 if (s->flags & M_DISPLAY)
2499 state_attach_puts (_("[-- Error: could not create temporary file! "
2504 tattach = decrypt_part (a, s, fpout, 1, &is_signed);
2507 tattach->goodsig = is_signed > 0;
2509 if (s->flags & M_DISPLAY)
2510 state_attach_puts (is_signed?
2511 _("[-- The following data is S/MIME signed --]\n\n"):
2512 _("[-- The following data is S/MIME encrypted --]\n\n"),
2516 FILE *savefp = s->fpin;
2518 rc = mutt_body_handler (tattach, s);
2523 * if a multipart/signed is the _only_ sub-part of a
2524 * multipart/encrypted, cache signature verification
2527 if (mutt_is_multipart_signed (tattach) && !tattach->next)
2529 if (!(a->goodsig = tattach->goodsig))
2530 a->warnsig = tattach->warnsig;
2532 else if (tattach->goodsig)
2535 a->warnsig = tattach->warnsig;
2538 if (s->flags & M_DISPLAY)
2540 state_puts ("\n", s);
2541 state_attach_puts (is_signed?
2542 _("[-- End of S/MIME signed data --]\n"):
2543 _("[-- End of S/MIME encrypted data --]\n"),
2547 mutt_free_body (&tattach);
2550 safe_fclose (&fpout);
2551 mutt_unlink(tempfile);
2552 dprint (2, (debugfile, "Leaving smime_encrypted handler\n"));
2559 * Format an entry on the CRYPT key selection menu.
2562 * %k key id %K key id of the principal key
2564 * %a algorithm %A algorithm of the princ. key
2565 * %l length %L length of the princ. key
2566 * %f flags %F flags of the princ. key
2567 * %c capabilities %C capabilities of the princ. key
2568 * %t trust/validity of the key-uid association
2570 * %[...] date of key using strftime(3)
2573 static const char *crypt_entry_fmt (char *dest,
2579 const char *ifstring,
2580 const char *elsestring,
2585 crypt_entry_t *entry;
2588 int optional = (flags & M_FORMAT_OPTIONAL);
2589 const char *s = NULL;
2592 entry = (crypt_entry_t *) data;
2595 /* if (isupper ((unsigned char) op)) */
2598 kflags = (key->flags /*| (pkey->flags & KEYFLAG_RESTRICTIONS)
2601 switch (ascii_tolower (op))
2606 char buf2[SHORT_STRING], *p;
2623 while (len > 0 && *cp != ']')
2635 break; /* not enough space */
2646 if (do_locales && Locale)
2647 setlocale (LC_TIME, Locale);
2652 if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
2653 tt = key->kobj->subkeys->timestamp;
2655 tm = localtime (&tt);
2657 strftime (buf2, sizeof (buf2), dest, tm);
2660 setlocale (LC_TIME, "C");
2662 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2663 snprintf (dest, destlen, fmt, buf2);
2671 snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
2672 snprintf (dest, destlen, fmt, entry->num);
2678 /* fixme: we need a way to distinguish between main and subkeys.
2679 Store the idx in entry? */
2680 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2681 snprintf (dest, destlen, fmt, crypt_keyid (key));
2687 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2688 snprintf (dest, destlen, fmt, key->uid);
2694 snprintf (fmt, sizeof (fmt), "%%%s.3s", prefix);
2695 if (key->kobj->subkeys)
2696 s = gpgme_pubkey_algo_name (key->kobj->subkeys->pubkey_algo);
2699 snprintf (dest, destlen, fmt, s);
2705 snprintf (fmt, sizeof (fmt), "%%%slu", prefix);
2706 if (key->kobj->subkeys)
2707 val = key->kobj->subkeys->length;
2710 snprintf (dest, destlen, fmt, val);
2716 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2717 snprintf (dest, destlen, fmt, crypt_flags (kflags));
2719 else if (!(kflags & (KEYFLAG_RESTRICTIONS)))
2725 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2726 snprintf (dest, destlen, fmt, crypt_key_abilities (kflags));
2728 else if (!(kflags & (KEYFLAG_ABILITIES)))
2732 if ((kflags & KEYFLAG_ISX509))
2736 gpgme_user_id_t uid = NULL;
2739 for (i = 0, uid = key->kobj->uids; uid && (i < key->idx);
2740 i++, uid = uid->next)
2743 switch (uid->validity)
2745 case GPGME_VALIDITY_UNDEFINED:
2748 case GPGME_VALIDITY_NEVER:
2751 case GPGME_VALIDITY_MARGINAL:
2754 case GPGME_VALIDITY_FULL:
2757 case GPGME_VALIDITY_ULTIMATE:
2760 case GPGME_VALIDITY_UNKNOWN:
2766 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2767 snprintf (dest, destlen, fmt, s? *s: 'B');
2770 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2771 snprintf (dest, destlen, fmt,
2772 gpgme_get_protocol_name (key->kobj->protocol));
2780 mutt_FormatString (dest, destlen, col, ifstring, mutt_attach_fmt, data, 0);
2781 else if (flags & M_FORMAT_OPTIONAL)
2782 mutt_FormatString (dest, destlen, col, elsestring, mutt_attach_fmt, data, 0);
2786 /* Used by the display fucntion to format a line. */
2787 static void crypt_entry (char *s, size_t l, MUTTMENU * menu, int num)
2789 crypt_key_t **key_table = (crypt_key_t **) menu->data;
2790 crypt_entry_t entry;
2792 entry.key = key_table[num];
2793 entry.num = num + 1;
2795 mutt_FormatString (s, l, 0, NONULL (PgpEntryFormat), crypt_entry_fmt,
2796 (unsigned long) &entry, M_FORMAT_ARROWCURSOR);
2799 /* Compare two addresses and the keyid to be used for sorting. */
2800 static int _crypt_compare_address (const void *a, const void *b)
2802 crypt_key_t **s = (crypt_key_t **) a;
2803 crypt_key_t **t = (crypt_key_t **) b;
2806 if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid)))
2809 return mutt_strcasecmp (crypt_keyid (*s), crypt_keyid (*t)) > 0;
2812 static int crypt_compare_address (const void *a, const void *b)
2814 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_address (a, b)
2815 : _crypt_compare_address (a, b));
2819 /* Compare two key IDs and the addresses to be used for sorting. */
2820 static int _crypt_compare_keyid (const void *a, const void *b)
2822 crypt_key_t **s = (crypt_key_t **) a;
2823 crypt_key_t **t = (crypt_key_t **) b;
2826 if ((r = mutt_strcasecmp (crypt_keyid (*s), crypt_keyid (*t))))
2829 return mutt_strcasecmp ((*s)->uid, (*t)->uid) > 0;
2832 static int crypt_compare_keyid (const void *a, const void *b)
2834 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_keyid (a, b)
2835 : _crypt_compare_keyid (a, b));
2838 /* Compare 2 creation dates and the addresses. For sorting. */
2839 static int _crypt_compare_date (const void *a, const void *b)
2841 crypt_key_t **s = (crypt_key_t **) a;
2842 crypt_key_t **t = (crypt_key_t **) b;
2843 unsigned long ts = 0, tt = 0;
2845 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2846 ts = (*s)->kobj->subkeys->timestamp;
2847 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2848 tt = (*t)->kobj->subkeys->timestamp;
2855 return mutt_strcasecmp ((*s)->uid, (*t)->uid) > 0;
2858 static int crypt_compare_date (const void *a, const void *b)
2860 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_date (a, b)
2861 : _crypt_compare_date (a, b));
2864 /* Compare two trust values, the key length, the creation dates. the
2865 addresses and the key IDs. For sorting. */
2866 static int _crypt_compare_trust (const void *a, const void *b)
2868 crypt_key_t **s = (crypt_key_t **) a;
2869 crypt_key_t **t = (crypt_key_t **) b;
2870 unsigned long ts = 0, tt = 0;
2873 if ((r = (((*s)->flags & (KEYFLAG_RESTRICTIONS))
2874 - ((*t)->flags & (KEYFLAG_RESTRICTIONS)))))
2877 if ((*s)->kobj->uids)
2878 ts = (*s)->kobj->uids->validity;
2879 if ((*t)->kobj->uids)
2880 tt = (*t)->kobj->uids->validity;
2881 if ((r = (tt - ts)))
2884 if ((*s)->kobj->subkeys)
2885 ts = (*s)->kobj->subkeys->length;
2886 if ((*t)->kobj->subkeys)
2887 tt = (*t)->kobj->subkeys->length;
2891 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2892 ts = (*s)->kobj->subkeys->timestamp;
2893 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2894 tt = (*t)->kobj->subkeys->timestamp;
2900 if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid)))
2902 return (mutt_strcasecmp (crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0;
2905 static int crypt_compare_trust (const void *a, const void *b)
2907 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_trust (a, b)
2908 : _crypt_compare_trust (a, b));
2911 /* Print the X.500 Distinguished Name part KEY from the array of parts
2914 print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key)
2918 for (; dn->key; dn++)
2920 if (!strcmp (dn->key, key))
2924 print_utf8 (fp, dn->value, strlen (dn->value));
2931 /* Print all parts of a DN in a standard sequence. */
2933 print_dn_parts (FILE *fp, struct dn_array_s *dn)
2935 const char *stdpart[] = {
2936 "CN", "OU", "O", "STREET", "L", "ST", "C", NULL
2938 int any=0, any2=0, i;
2940 for (i=0; stdpart[i]; i++)
2944 any = print_dn_part (fp, dn, stdpart[i]);
2946 /* now print the rest without any specific ordering */
2947 for (; dn->key; dn++)
2949 for (i=0; stdpart[i]; i++)
2951 if (!strcmp (dn->key, stdpart[i]))
2960 any = print_dn_part (fp, dn, dn->key);
2969 /* Parse an RDN; this is a helper to parse_dn(). */
2970 static const unsigned char *
2971 parse_dn_part (struct dn_array_s *array, const unsigned char *string)
2973 const unsigned char *s, *s1;
2977 /* parse attributeType */
2978 for (s = string+1; *s && *s != '='; s++)
2981 return NULL; /* error */
2984 return NULL; /* empty key */
2985 array->key = safe_malloc (n+1);
2986 p = (unsigned char *)array->key;
2987 memcpy (p, string, n); /* fixme: trim trailing spaces */
2994 for (s=string; hexdigitp (s); s++)
2998 return NULL; /* empty or odd number of digits */
3000 p = safe_malloc (n+1);
3001 array->value = (char*)p;
3002 for (s1=string; n; s1 += 2, n--)
3007 { /* regular v3 quoted string */
3008 for (n=0, s=string; *s; s++)
3013 if (*s == ',' || *s == '=' || *s == '+'
3014 || *s == '<' || *s == '>' || *s == '#' || *s == ';'
3015 || *s == '\\' || *s == '\"' || *s == ' ')
3017 else if (hexdigitp (s) && hexdigitp (s+1))
3023 return NULL; /* invalid escape sequence */
3025 else if (*s == '\"')
3026 return NULL; /* invalid encoding */
3027 else if (*s == ',' || *s == '=' || *s == '+'
3028 || *s == '<' || *s == '>' || *s == '#' || *s == ';' )
3034 p = safe_malloc (n+1);
3035 array->value = (char*)p;
3036 for (s=string; n; s++, n--)
3058 /* Parse a DN and return an array-ized one. This is not a validating
3059 parser and it does not support any old-stylish syntax; gpgme is
3060 expected to return only rfc2253 compatible strings. */
3061 static struct dn_array_s *
3062 parse_dn (const unsigned char *string)
3064 struct dn_array_s *array;
3065 size_t arrayidx, arraysize;
3068 arraysize = 7; /* C,ST,L,O,OU,CN,email */
3069 array = safe_malloc ((arraysize+1) * sizeof *array);
3073 while (*string == ' ')
3077 if (arrayidx >= arraysize)
3078 { /* mutt lacks a real safe_realoc - so we need to copy */
3079 struct dn_array_s *a2;
3082 a2 = safe_malloc ((arraysize+1) * sizeof *array);
3083 for (i=0; i < arrayidx; i++)
3085 a2[i].key = array[i].key;
3086 a2[i].value = array[i].value;
3091 array[arrayidx].key = NULL;
3092 array[arrayidx].value = NULL;
3093 string = parse_dn_part (array+arrayidx, string);
3097 while (*string == ' ')
3099 if (*string && *string != ',' && *string != ';' && *string != '+')
3100 goto failure; /* invalid delimiter */
3104 array[arrayidx].key = NULL;
3105 array[arrayidx].value = NULL;
3109 for (i=0; i < arrayidx; i++)
3111 FREE (&array[i].key);
3112 FREE (&array[i].value);
3119 /* Print a nice representation of the USERID and make sure it is
3120 displayed in a proper way, which does mean to reorder some parts
3121 for S/MIME's DNs. USERID is a string as returned by the gpgme key
3122 functions. It is utf-8 encoded. */
3124 parse_and_print_user_id (FILE *fp, const char *userid)
3131 s = strchr (userid+1, '>');
3133 print_utf8 (fp, userid+1, s-userid-1);
3135 else if (*userid == '(')
3136 fputs (_("[Can't display this user ID (unknown encoding)]"), fp);
3137 else if (!digit_or_letter ((const unsigned char *)userid))
3138 fputs (_("[Can't display this user ID (invalid encoding)]"), fp);
3141 struct dn_array_s *dn = parse_dn ((const unsigned char *)userid);
3143 fputs (_("[Can't display this user ID (invalid DN)]"), fp);
3146 print_dn_parts (fp, dn);
3147 for (i=0; dn[i].key; i++)
3150 FREE (&dn[i].value);
3159 KEY_CAP_CAN_ENCRYPT,
3166 key_check_cap (gpgme_key_t key, key_cap_t cap)
3168 gpgme_subkey_t subkey = NULL;
3169 unsigned int ret = 0;
3173 case KEY_CAP_CAN_ENCRYPT:
3174 if (! (ret = key->can_encrypt))
3175 for (subkey = key->subkeys; subkey; subkey = subkey->next)
3176 if ((ret = subkey->can_encrypt))
3179 case KEY_CAP_CAN_SIGN:
3180 if (! (ret = key->can_sign))
3181 for (subkey = key->subkeys; subkey; subkey = subkey->next)
3182 if ((ret = subkey->can_sign))
3185 case KEY_CAP_CAN_CERTIFY:
3186 if (! (ret = key->can_certify))
3187 for (subkey = key->subkeys; subkey; subkey = subkey->next)
3188 if ((ret = subkey->can_certify))
3197 /* Print verbose information about a key or certificate to FP. */
3198 static void print_key_info (gpgme_key_t key, FILE *fp)
3201 const char *s = NULL, *s2 = NULL;
3204 char shortbuf[SHORT_STRING];
3205 unsigned long aval = 0;
3209 gpgme_user_id_t uid = NULL;
3212 setlocale (LC_TIME, Locale);
3214 is_pgp = key->protocol == GPGME_PROTOCOL_OpenPGP;
3216 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3222 fputs (idx ? _(" aka ......: ") :_("Name ......: "), fp);
3225 fputs (_("[Invalid]"), fp);
3229 print_utf8 (fp, s, strlen(s));
3231 parse_and_print_user_id (fp, s);
3235 if (key->subkeys && (key->subkeys->timestamp > 0))
3237 tt = key->subkeys->timestamp;
3239 tm = localtime (&tt);
3240 #ifdef HAVE_LANGINFO_D_T_FMT
3241 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
3243 strftime (shortbuf, sizeof shortbuf, "%c", tm);
3245 fprintf (fp, _("Valid From : %s\n"), shortbuf);
3248 if (key->subkeys && (key->subkeys->expires > 0))
3250 tt = key->subkeys->expires;
3252 tm = localtime (&tt);
3253 #ifdef HAVE_LANGINFO_D_T_FMT
3254 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
3256 strftime (shortbuf, sizeof shortbuf, "%c", tm);
3258 fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
3262 s = gpgme_pubkey_algo_name (key->subkeys->pubkey_algo);
3266 s2 = is_pgp ? "PGP" : "X.509";
3269 aval = key->subkeys->length;
3271 fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), s2, aval, s);
3273 fprintf (fp, _("Key Usage .: "));
3276 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3278 fprintf (fp, "%s%s", delim, _("encryption"));
3281 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3283 fprintf (fp, "%s%s", delim, _("signing"));
3286 if (key_check_cap (key, KEY_CAP_CAN_CERTIFY))
3288 fprintf (fp, "%s%s", delim, _("certification"));
3295 s = key->subkeys->fpr;
3296 fputs (_("Fingerprint: "), fp);
3297 if (is_pgp && strlen (s) == 40)
3299 for (i=0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++)
3305 putc (is_pgp? ' ':':', fp);
3306 if (is_pgp && i == 4)
3312 for (i=0; *s && s[1] && s[2]; s += 2, i++)
3316 putc (is_pgp? ' ':':', fp);
3317 if (is_pgp && i == 7)
3321 fprintf (fp, "%s\n", s);
3324 if (key->issuer_serial)
3326 s = key->issuer_serial;
3328 fprintf (fp, _("Serial-No .: 0x%s\n"), s);
3331 if (key->issuer_name)
3333 s = key->issuer_name;
3336 fprintf (fp, _("Issued By .: "));
3337 parse_and_print_user_id (fp, s);
3342 /* For PGP we list all subkeys. */
3345 gpgme_subkey_t subkey = NULL;
3347 for (idx = 1, subkey = key->subkeys; subkey;
3348 idx++, subkey = subkey->next)
3353 if ( strlen (s) == 16)
3354 s += 8; /* display only the short keyID */
3355 fprintf (fp, _("Subkey ....: 0x%s"), s);
3356 if (subkey->revoked)
3359 fputs (_("[Revoked]"), fp);
3361 if (subkey->invalid)
3364 fputs (_("[Invalid]"), fp);
3366 if (subkey->expired)
3369 fputs (_("[Expired]"), fp);
3371 if (subkey->disabled)
3374 fputs (_("[Disabled]"), fp);
3378 if (subkey->timestamp > 0)
3380 tt = subkey->timestamp;
3382 tm = localtime (&tt);
3383 #ifdef HAVE_LANGINFO_D_T_FMT
3384 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
3386 strftime (shortbuf, sizeof shortbuf, "%c", tm);
3388 fprintf (fp, _("Valid From : %s\n"), shortbuf);
3391 if (subkey->expires > 0)
3393 tt = subkey->expires;
3395 tm = localtime (&tt);
3396 #ifdef HAVE_LANGINFO_D_T_FMT
3397 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
3399 strftime (shortbuf, sizeof shortbuf, "%c", tm);
3401 fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
3405 s = gpgme_pubkey_algo_name (subkey->pubkey_algo);
3410 aval = subkey->length;
3414 fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), "PGP", aval, s);
3416 fprintf (fp, _("Key Usage .: "));
3419 if (subkey->can_encrypt)
3421 fprintf (fp, "%s%s", delim, _("encryption"));
3424 if (subkey->can_sign)
3426 fprintf (fp, "%s%s", delim, _("signing"));
3429 if (subkey->can_certify)
3431 fprintf (fp, "%s%s", delim, _("certification"));
3439 setlocale (LC_TIME, "C");
3443 /* Show detailed information about the selected key */
3445 verify_key (crypt_key_t *key)
3448 char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
3450 gpgme_ctx_t listctx = NULL;
3452 gpgme_key_t k = NULL;
3455 mutt_mktemp (tempfile);
3456 if (!(fp = safe_fopen (tempfile, "w")))
3458 mutt_perror _("Can't create temporary file");
3461 mutt_message _("Collecting data...");
3463 print_key_info (key->kobj, fp);
3465 err = gpgme_new (&listctx);
3468 fprintf (fp, "Internal error: can't create gpgme context: %s\n",
3469 gpgme_strerror (err));
3472 if ((key->flags & KEYFLAG_ISX509))
3473 gpgme_set_protocol (listctx, GPGME_PROTOCOL_CMS);
3477 while ((s = k->chain_id) && k->subkeys && strcmp (s, k->subkeys->fpr) )
3480 err = gpgme_op_keylist_start (listctx, s, 0);
3481 gpgme_key_release (k);
3484 err = gpgme_op_keylist_next (listctx, &k);
3487 fprintf (fp, _("Error finding issuer key: %s\n"),
3488 gpgme_strerror (err));
3491 gpgme_op_keylist_end (listctx);
3493 print_key_info (k, fp);
3497 fputs (_("Error: certification chain to long - stopping here\n"),
3504 gpgme_key_release (k);
3505 gpgme_release (listctx);
3507 mutt_clear_error ();
3508 snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), crypt_keyid (key));
3509 mutt_do_pager (cmd, tempfile, 0, NULL);
3513 * Implementation of `findkeys'.
3517 /* Convert LIST into a pattern string suitable to be passed to GPGME.
3518 We need to convert spaces in an item into a '+' and '%' into
3520 static char *list_to_pattern (LIST *list)
3528 for(l=list; l; l = l->next)
3530 for(s = l->data; *s; s++)
3536 n++; /* delimiter or end of string */
3538 n++; /* make sure to allocate at least one byte */
3539 pattern = p = safe_calloc (1,n);
3540 for(l=list; l; l = l->next)
3547 for(s = l->data; *s; s++)
3572 /* Return a list of keys which are candidates for the selection.
3573 Select by looking at the HINTS list. */
3574 static crypt_key_t *get_candidates (LIST * hints, unsigned int app, int secret)
3576 crypt_key_t *db, *k, **kend;
3582 gpgme_user_id_t uid = NULL;
3584 pattern = list_to_pattern (hints);
3588 err = gpgme_new (&ctx);
3591 mutt_error (_("gpgme_new failed: %s"), gpgme_strerror (err));
3599 if ((app & APPLICATION_PGP))
3601 /* Its all a mess. That old GPGME expects different things
3602 depending on the protocol. For gpg we don' t need percent
3603 escaped pappert but simple strings passed in an array to the
3604 keylist_ext_start function. */
3609 for(l=hints, n=0; l; l = l->next)
3611 if (l->data && *l->data)
3617 patarr = safe_calloc (n+1, sizeof *patarr);
3618 for(l=hints, n=0; l; l = l->next)
3620 if (l->data && *l->data)
3621 patarr[n++] = safe_strdup (l->data);
3624 err = gpgme_op_keylist_ext_start (ctx, (const char**)patarr, secret, 0);
3625 for (n=0; patarr[n]; n++)
3630 mutt_error (_("gpgme_op_keylist_start failed: %s"),
3631 gpgme_strerror (err));
3632 gpgme_release (ctx);
3637 while (!(err = gpgme_op_keylist_next (ctx, &key)) )
3639 unsigned int flags = 0;
3641 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3642 flags |= KEYFLAG_CANENCRYPT;
3643 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3644 flags |= KEYFLAG_CANSIGN;
3646 #if 0 /* DISABLED code */
3649 /* Bug in gpg. Capabilities are not listed for secret
3650 keys. Try to deduce them from the algorithm. */
3652 switch (key->subkeys[0].pubkey_algo)
3655 flags |= KEYFLAG_CANENCRYPT;
3656 flags |= KEYFLAG_CANSIGN;
3658 case GPGME_PK_ELG_E:
3659 flags |= KEYFLAG_CANENCRYPT;
3662 flags |= KEYFLAG_CANSIGN;
3666 #endif /* DISABLED code */
3668 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3670 k = safe_calloc (1, sizeof *k);
3679 if (gpg_err_code (err) != GPG_ERR_EOF)
3680 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3681 gpgme_op_keylist_end (ctx);
3686 if ((app & APPLICATION_SMIME))
3688 /* and now look for x509 certificates */
3689 gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
3690 err = gpgme_op_keylist_start (ctx, pattern, 0);
3693 mutt_error (_("gpgme_op_keylist_start failed: %s"),
3694 gpgme_strerror (err));
3695 gpgme_release (ctx);
3700 while (!(err = gpgme_op_keylist_next (ctx, &key)) )
3702 unsigned int flags = KEYFLAG_ISX509;
3704 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3705 flags |= KEYFLAG_CANENCRYPT;
3706 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3707 flags |= KEYFLAG_CANSIGN;
3709 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3711 k = safe_calloc (1, sizeof *k);
3720 if (gpg_err_code (err) != GPG_ERR_EOF)
3721 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3722 gpgme_op_keylist_end (ctx);
3725 gpgme_release (ctx);
3730 /* Add the string STR to the list HINTS. This list is later used to
3732 static LIST *crypt_add_string_to_hints (LIST *hints, const char *str)
3737 if ((scratch = safe_strdup (str)) == NULL)
3740 for (t = strtok (scratch, " ,.:\"()<>\n"); t;
3741 t = strtok (NULL, " ,.:\"()<>\n"))
3744 hints = mutt_add_list (hints, t);
3751 /* Display a menu to select a key from the array KEYS. FORCED_VALID
3752 will be set to true on return if the user did override the the
3754 static crypt_key_t *crypt_select_key (crypt_key_t *keys,
3755 ADDRESS * p, const char *s,
3756 unsigned int app, int *forced_valid)
3759 crypt_key_t **key_table;
3762 char helpstr[LONG_STRING], buf[LONG_STRING];
3764 int (*f) (const void *, const void *);
3765 int menu_to_use = 0;
3770 /* build the key table */
3773 for (k = keys; k; k = k->next)
3775 if (!option (OPTPGPSHOWUNUSABLE) && (k->flags & KEYFLAG_CANTUSE))
3784 safe_realloc (&key_table, sizeof (crypt_key_t*)*keymax);
3792 mutt_error _("All matching keys are marked expired/revoked.");
3797 switch (PgpSortKeys & SORT_MASK)
3800 f = crypt_compare_date;
3803 f = crypt_compare_keyid;
3806 f = crypt_compare_address;
3810 f = crypt_compare_trust;
3813 qsort (key_table, i, sizeof (crypt_key_t*), f);
3815 if (app & APPLICATION_PGP)
3816 menu_to_use = MENU_KEY_SELECT_PGP;
3817 else if (app & APPLICATION_SMIME)
3818 menu_to_use = MENU_KEY_SELECT_SMIME;
3821 mutt_make_help (buf, sizeof (buf), _("Exit "), menu_to_use, OP_EXIT);
3822 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3823 mutt_make_help (buf, sizeof (buf), _("Select "), menu_to_use,
3824 OP_GENERIC_SELECT_ENTRY);
3825 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3826 mutt_make_help (buf, sizeof (buf), _("Check key "),
3827 menu_to_use, OP_VERIFY_KEY);
3828 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3829 mutt_make_help (buf, sizeof (buf), _("Help"), menu_to_use, OP_HELP);
3830 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3832 menu = mutt_new_menu (menu_to_use);
3834 menu->make_entry = crypt_entry;
3835 menu->help = helpstr;
3836 menu->data = key_table;
3841 if ((app & APPLICATION_PGP) && (app & APPLICATION_SMIME))
3842 ts = _("PGP and S/MIME keys matching");
3843 else if ((app & APPLICATION_PGP))
3844 ts = _("PGP keys matching");
3845 else if ((app & APPLICATION_SMIME))
3846 ts = _("S/MIME keys matching");
3848 ts = _("keys matching");
3851 snprintf (buf, sizeof (buf), _("%s <%s>."), ts, p->mailbox);
3853 snprintf (buf, sizeof (buf), _("%s \"%s\"."), ts, s);
3857 mutt_clear_error ();
3862 switch (mutt_menuLoop (menu))
3865 verify_key (key_table[menu->current]);
3866 menu->redraw = REDRAW_FULL;
3870 mutt_message ("%s", key_table[menu->current]->uid);
3873 case OP_GENERIC_SELECT_ENTRY:
3874 /* FIXME make error reporting more verbose - this should be
3875 easy because gpgme provides more information */
3876 if (option (OPTPGPCHECKTRUST))
3878 if (!crypt_key_is_valid (key_table[menu->current]))
3880 mutt_error _("This key can't be used: "
3881 "expired/disabled/revoked.");
3886 if (option (OPTPGPCHECKTRUST) &&
3887 (!crypt_id_is_valid (key_table[menu->current])
3888 || !crypt_id_is_strong (key_table[menu->current])))
3891 char buff[LONG_STRING];
3893 if (key_table[menu->current]->flags & KEYFLAG_CANTUSE)
3894 s = N_("ID is expired/disabled/revoked.");
3897 gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
3898 gpgme_user_id_t uid = NULL;
3903 uid = key_table[menu->current]->kobj->uids;
3904 for (j = 0; (j < key_table[menu->current]->idx) && uid;
3905 j++, uid = uid->next)
3908 val = uid->validity;
3912 case GPGME_VALIDITY_UNKNOWN:
3913 case GPGME_VALIDITY_UNDEFINED:
3914 warn_s = N_("ID has undefined validity.");
3916 case GPGME_VALIDITY_NEVER:
3917 warn_s = N_("ID is not valid.");
3919 case GPGME_VALIDITY_MARGINAL:
3920 warn_s = N_("ID is only marginally valid.");
3922 case GPGME_VALIDITY_FULL:
3923 case GPGME_VALIDITY_ULTIMATE:
3927 snprintf (buff, sizeof (buff),
3928 _("%s Do you really want to use the key?"),
3931 if (mutt_yesorno (buff, 0) != 1)
3933 mutt_clear_error ();
3940 k = crypt_copy_key (key_table[menu->current]);
3951 mutt_menuDestroy (&menu);
3954 set_option (OPTNEEDREDRAW);
3959 static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
3960 unsigned int app, int *forced_valid)
3968 int this_key_has_strong;
3969 int this_key_has_weak;
3970 int this_key_has_invalid;
3973 crypt_key_t *keys, *k;
3974 crypt_key_t *the_valid_key = NULL;
3975 crypt_key_t *matches = NULL;
3976 crypt_key_t **matches_endp = &matches;
3980 if (a && a->mailbox)
3981 hints = crypt_add_string_to_hints (hints, a->mailbox);
3982 if (a && a->personal)
3983 hints = crypt_add_string_to_hints (hints, a->personal);
3985 mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
3986 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN) );
3988 mutt_free_list (&hints);
3993 dprint (5, (debugfile, "crypt_getkeybyaddr: looking for %s <%s>.",
3994 a->personal, a->mailbox));
3996 for (k = keys; k; k = k->next)
3998 dprint (5, (debugfile, " looking at key: %s `%.15s'\n",
3999 crypt_keyid (k), k->uid));
4001 if (abilities && !(k->flags & abilities))
4003 dprint (5, (debugfile, " insufficient abilities: Has %x, want %x\n",
4004 k->flags, abilities));
4008 this_key_has_weak = 0; /* weak but valid match */
4009 this_key_has_invalid = 0; /* invalid match */
4010 this_key_has_strong = 0; /* strong and valid match */
4011 match = 0; /* any match */
4013 r = rfc822_parse_adrlist (NULL, k->uid);
4014 for (p = r; p; p = p->next)
4016 int validity = crypt_id_matches_addr (a, p, k);
4018 if (validity & CRYPT_KV_MATCH) /* something matches */
4021 /* is this key a strong candidate? */
4022 if ((validity & CRYPT_KV_VALID)
4023 && (validity & CRYPT_KV_STRONGID)
4024 && (validity & CRYPT_KV_ADDR))
4026 if (the_valid_key && the_valid_key != k)
4029 this_key_has_strong = 1;
4031 else if ((validity & CRYPT_KV_MATCH)
4032 && !(validity & CRYPT_KV_VALID))
4033 this_key_has_invalid = 1;
4034 else if ((validity & CRYPT_KV_MATCH)
4035 && (!(validity & CRYPT_KV_STRONGID)
4036 || !(validity & CRYPT_KV_ADDR)))
4037 this_key_has_weak = 1;
4039 rfc822_free_address (&r);
4045 if (!this_key_has_strong && this_key_has_invalid)
4047 if (!this_key_has_strong && this_key_has_weak)
4050 *matches_endp = tmp = crypt_copy_key (k);
4051 matches_endp = &tmp->next;
4052 the_valid_key = tmp;
4056 crypt_free_key (&keys);
4060 if (the_valid_key && !multi && !weak
4061 && !(invalid && option (OPTPGPSHOWUNUSABLE)))
4064 * There was precisely one strong match on a valid ID, there
4065 * were no valid keys with weak matches, and we aren't
4066 * interested in seeing invalid keys.
4068 * Proceed without asking the user.
4070 k = crypt_copy_key (the_valid_key);
4075 * Else: Ask the user.
4077 k = crypt_select_key (matches, a, NULL, app, forced_valid);
4079 crypt_free_key (&matches);
4088 static crypt_key_t *crypt_getkeybystr (char *p, short abilities,
4089 unsigned int app, int *forced_valid)
4093 crypt_key_t *matches = NULL;
4094 crypt_key_t **matches_endp = &matches;
4098 mutt_message (_("Looking for keys matching \"%s\"..."), p);
4102 hints = crypt_add_string_to_hints (hints, p);
4103 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
4104 mutt_free_list (&hints);
4109 for (k = keys; k; k = k->next)
4111 if (abilities && !(k->flags & abilities))
4115 dprint (5, (debugfile, "crypt_getkeybystr: matching \"%s\" against "
4116 "key %s, \"%s\": ", p, crypt_keyid (k), k->uid));
4119 || !mutt_strcasecmp (p, crypt_keyid (k))
4120 || (!mutt_strncasecmp (p, "0x", 2)
4121 && !mutt_strcasecmp (p + 2, crypt_keyid (k)))
4122 || (option (OPTPGPLONGIDS)
4123 && !mutt_strncasecmp (p, "0x", 2)
4124 && !mutt_strcasecmp (p + 2, crypt_keyid (k) + 8))
4125 || mutt_stristr (k->uid, p))
4129 dprint (5, (debugfile, "match.\n"));
4131 *matches_endp = tmp = crypt_copy_key (k);
4132 matches_endp = &tmp->next;
4136 crypt_free_key (&keys);
4140 k = crypt_select_key (matches, NULL, p, app, forced_valid);
4141 crypt_free_key (&matches);
4148 /* Display TAG as a prompt to ask for a key. If WHATFOR is not null
4149 use it as default and store it under that label as the next
4150 default. ABILITIES describe the required key abilities (sign,
4151 encrypt) and APP the type of the requested key; ether S/MIME or
4152 PGP. Return a copy of the key or NULL if not found. */
4153 static crypt_key_t *crypt_ask_for_key (char *tag,
4160 char resp[SHORT_STRING];
4161 struct crypt_cache *l = NULL;
4165 forced_valid = &dummy;
4167 mutt_clear_error ();
4174 for (l = id_defaults; l; l = l->next)
4175 if (!mutt_strcasecmp (whatfor, l->what))
4177 strfcpy (resp, NONULL (l->dflt), sizeof (resp));
4186 if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0)
4192 mutt_str_replace (&l->dflt, resp);
4195 l = safe_malloc (sizeof (struct crypt_cache));
4196 l->next = id_defaults;
4198 l->what = safe_strdup (whatfor);
4199 l->dflt = safe_strdup (resp);
4203 if ((key = crypt_getkeybystr (resp, abilities, app, forced_valid)))
4211 /* This routine attempts to find the keyids of the recipients of a
4212 message. It returns NULL if any of the keys can not be found. */
4213 static char *find_keys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc,
4216 char *keyID, *keylist = NULL, *t;
4217 size_t keylist_size = 0;
4218 size_t keylist_used = 0;
4219 ADDRESS *tmp = NULL, *addr = NULL;
4220 ADDRESS **last = &tmp;
4223 crypt_key_t *k_info, *key;
4224 const char *fqdn = mutt_fqdn (1);
4227 *r_application = APPLICATION_PGP|APPLICATION_SMIME;
4230 for (i = 0; i < 3; i++)
4234 case 0: p = to; break;
4235 case 1: p = cc; break;
4236 case 2: p = bcc; break;
4240 *last = rfc822_cpy_adr (p, 0);
4242 last = &((*last)->next);
4246 rfc822_qualify (tmp, fqdn);
4248 tmp = mutt_remove_duplicates (tmp);
4250 for (p = tmp; p ; p = p->next)
4252 char buf[LONG_STRING];
4253 int forced_valid = 0;
4258 if ((keyID = mutt_crypt_hook (p)) != NULL)
4261 snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"),
4263 if ((r = mutt_yesorno (buf, M_YES)) == M_YES)
4265 /* check for e-mail address */
4266 if ((t = strchr (keyID, '@')) &&
4267 (addr = rfc822_parse_adrlist (NULL, keyID)))
4270 rfc822_qualify (addr, fqdn);
4276 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
4277 *r_application, &forced_valid);
4279 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
4280 app, &forced_valid);
4287 rfc822_free_address (&tmp);
4288 rfc822_free_address (&addr);
4294 && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT,
4295 app, &forced_valid)) == NULL)
4297 snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
4299 if ((key = crypt_ask_for_key (buf, q->mailbox,
4306 &forced_valid)) == NULL)
4309 rfc822_free_address (&tmp);
4310 rfc822_free_address (&addr);
4318 const char *s = crypt_fpr (key);
4321 if (key->flags & KEYFLAG_ISX509)
4322 *r_application &= ~APPLICATION_PGP;
4323 if (!(key->flags & KEYFLAG_ISX509))
4324 *r_application &= ~APPLICATION_SMIME;
4327 keylist_size += mutt_strlen (s) + 4 + 1;
4328 safe_realloc (&keylist, keylist_size);
4329 sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */
4330 keylist_used ? " " : "", s,
4331 forced_valid? "!":"");
4333 keylist_used = mutt_strlen (keylist);
4335 crypt_free_key (&key);
4336 rfc822_free_address (&addr);
4338 rfc822_free_address (&tmp);
4342 char *pgp_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc)
4344 return find_keys (to, cc, bcc, APPLICATION_PGP);
4347 char *smime_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc)
4349 return find_keys (to, cc, bcc, APPLICATION_SMIME);
4353 * Implementation of `init'.
4356 /* Initialization. */
4357 static void init_gpgme (void)
4359 /* Make sure that gpg-agent is running. */
4360 if (! getenv ("GPG_AGENT_INFO"))
4362 mutt_error (_("\nUsing GPGME backend, although no gpg-agent is running"));
4363 if (mutt_any_key_to_continue (NULL) == -1)
4368 void pgp_gpgme_init (void)
4373 void smime_gpgme_init (void)
4377 static int gpgme_send_menu (HEADER *msg, int *redraw, int is_smime)
4380 char input_signas[SHORT_STRING];
4383 if (msg->security & APPLICATION_PGP)
4385 else if (msg->security & APPLICATION_SMIME)
4389 choice = mutt_multi_choice (
4390 _("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?"),
4393 choice = mutt_multi_choice (
4394 _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?"),
4399 case 1: /* (e)ncrypt */
4400 msg->security |= (is_smime ? SMIMEENCRYPT : PGPENCRYPT);
4401 msg->security &= ~(is_smime ? SMIMESIGN : PGPSIGN);
4404 case 2: /* (s)ign */
4405 msg->security |= (is_smime? SMIMESIGN :PGPSIGN);
4406 msg->security &= ~(is_smime ? SMIMEENCRYPT : PGPENCRYPT);
4409 case 3: /* sign (a)s */
4410 /* unset_option(OPTCRYPTCHECKTRUST); */
4411 if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
4412 is_smime? APPLICATION_SMIME:APPLICATION_PGP,
4415 snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p));
4416 mutt_str_replace (is_smime? &SmimeDefaultKey : &PgpSignAs, input_signas);
4417 crypt_free_key (&p);
4419 msg->security |= (is_smime? SMIMESIGN:PGPSIGN);
4424 msg->security &= (is_smime? ~SMIMESIGN : ~PGPSIGN);
4427 *redraw = REDRAW_FULL;
4430 case 4: /* (b)oth */
4431 msg->security = (is_smime? (SMIMEENCRYPT|SMIMESIGN):(PGPENCRYPT|PGPSIGN));
4434 case 5: /* (p)gp or s/(m)ime */
4435 is_smime = !is_smime;
4438 case 6: /* (f)orget it */
4439 case 7: /* (c)lear */
4444 if (choice == 6 || choice == 7)
4448 msg->security &= ~APPLICATION_PGP;
4449 msg->security |= APPLICATION_SMIME;
4453 msg->security &= ~APPLICATION_SMIME;
4454 msg->security |= APPLICATION_PGP;
4457 return (msg->security);
4460 int pgp_gpgme_send_menu (HEADER *msg, int *redraw)
4462 return gpgme_send_menu (msg, redraw, 0);
4465 int smime_gpgme_send_menu (HEADER *msg, int *redraw)
4467 return gpgme_send_menu (msg, redraw, 1);
4470 static int verify_sender (HEADER *h, gpgme_protocol_t protocol)
4472 ADDRESS *sender = NULL;
4473 unsigned int ret = 1;
4477 h->env->from = mutt_expand_aliases (h->env->from);
4478 sender = h->env->from;
4480 else if (h->env->sender)
4482 h->env->sender = mutt_expand_aliases (h->env->sender);
4483 sender = h->env->sender;
4490 gpgme_key_t key = signature_key;
4491 gpgme_user_id_t uid = NULL;
4492 int sender_length = 0;
4495 sender_length = strlen (sender->mailbox);
4496 for (uid = key->uids; uid && ret; uid = uid->next)
4498 uid_length = strlen (uid->email);
4500 && (uid->email[0] == '<')
4501 && (uid->email[uid_length - 1] == '>')
4502 && (uid_length == sender_length + 2)
4503 && (! strncmp (uid->email + 1, sender->mailbox, sender_length)))
4508 mutt_any_key_to_continue (_("Failed to verify sender"));
4511 mutt_any_key_to_continue (_("Failed to figure out sender"));
4515 gpgme_key_release (signature_key);
4516 signature_key = NULL;
4522 int smime_gpgme_verify_sender (HEADER *h)
4524 return verify_sender (h, GPGME_PROTOCOL_CMS);
4527 void gpgme_set_sender (const char *sender)
4529 mutt_error ("[setting sender] mailbox: %s\n", sender);
4530 FREE (¤t_sender);
4531 current_sender = safe_strdup (sender);