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, sizeof (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, sizeof (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 = DISPNONE;
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 = DISPATTACH;
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, sizeof (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, sizeof (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, sizeof (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, sizeof (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, sizeof (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, sizeof (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, sizeof (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);
2376 /* A traditional PGP part may mix signed and unsigned content */
2377 /* XXX - we may wish to recode here */
2379 state_puts (s->prefix, s);
2380 state_puts (buf, s);
2384 m->goodsig = (maybe_goodsig && have_any_sigs);
2388 state_attach_puts (_("[-- Error: could not find beginning"
2389 " of PGP message! --]\n\n"), s);
2392 dprint (2, (debugfile, "Leaving pgp_application_pgp handler\n"));
2398 * Implementation of `encrypted_handler'.
2401 /* MIME handler for pgp/mime encrypted messages. */
2402 int pgp_gpgme_encrypted_handler (BODY *a, STATE *s)
2404 char tempfile[_POSIX_PATH_MAX];
2407 BODY *orig_body = a;
2411 dprint (2, (debugfile, "Entering pgp_encrypted handler\n"));
2413 if (!a || a->type != TYPEAPPLICATION || !a->subtype
2414 || ascii_strcasecmp ("pgp-encrypted", a->subtype)
2415 || !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype
2416 || ascii_strcasecmp ("octet-stream", a->next->subtype) )
2418 if (s->flags & M_DISPLAY)
2419 state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
2424 /* Move forward to the application/pgp-encrypted body. */
2427 mutt_mktemp (tempfile, sizeof (tempfile));
2428 if (!(fpout = safe_fopen (tempfile, "w+")))
2430 if (s->flags & M_DISPLAY)
2431 state_attach_puts (_("[-- Error: could not create temporary file! "
2436 tattach = decrypt_part (a, s, fpout, 0, &is_signed);
2439 tattach->goodsig = is_signed > 0;
2441 if (s->flags & M_DISPLAY)
2442 state_attach_puts (is_signed?
2443 _("[-- The following data is PGP/MIME signed and encrypted --]\n\n"):
2444 _("[-- The following data is PGP/MIME encrypted --]\n\n"),
2448 FILE *savefp = s->fpin;
2450 rc = mutt_body_handler (tattach, s);
2455 * if a multipart/signed is the _only_ sub-part of a
2456 * multipart/encrypted, cache signature verification
2459 if (mutt_is_multipart_signed (tattach) && !tattach->next)
2460 orig_body->goodsig |= tattach->goodsig;
2462 if (s->flags & M_DISPLAY)
2464 state_puts ("\n", s);
2465 state_attach_puts (is_signed?
2466 _("[-- End of PGP/MIME signed and encrypted data --]\n"):
2467 _("[-- End of PGP/MIME encrypted data --]\n"),
2471 mutt_free_body (&tattach);
2474 safe_fclose (&fpout);
2475 mutt_unlink(tempfile);
2476 dprint (2, (debugfile, "Leaving pgp_encrypted handler\n"));
2481 /* Support for application/smime */
2482 int smime_gpgme_application_handler (BODY *a, STATE *s)
2484 char tempfile[_POSIX_PATH_MAX];
2490 dprint (2, (debugfile, "Entering smime_encrypted handler\n"));
2493 mutt_mktemp (tempfile, sizeof (tempfile));
2494 if (!(fpout = safe_fopen (tempfile, "w+")))
2496 if (s->flags & M_DISPLAY)
2497 state_attach_puts (_("[-- Error: could not create temporary file! "
2502 tattach = decrypt_part (a, s, fpout, 1, &is_signed);
2505 tattach->goodsig = is_signed > 0;
2507 if (s->flags & M_DISPLAY)
2508 state_attach_puts (is_signed?
2509 _("[-- The following data is S/MIME signed --]\n\n"):
2510 _("[-- The following data is S/MIME encrypted --]\n\n"),
2514 FILE *savefp = s->fpin;
2516 rc = mutt_body_handler (tattach, s);
2521 * if a multipart/signed is the _only_ sub-part of a
2522 * multipart/encrypted, cache signature verification
2525 if (mutt_is_multipart_signed (tattach) && !tattach->next)
2527 if (!(a->goodsig = tattach->goodsig))
2528 a->warnsig = tattach->warnsig;
2530 else if (tattach->goodsig)
2533 a->warnsig = tattach->warnsig;
2536 if (s->flags & M_DISPLAY)
2538 state_puts ("\n", s);
2539 state_attach_puts (is_signed?
2540 _("[-- End of S/MIME signed data --]\n"):
2541 _("[-- End of S/MIME encrypted data --]\n"),
2545 mutt_free_body (&tattach);
2548 safe_fclose (&fpout);
2549 mutt_unlink(tempfile);
2550 dprint (2, (debugfile, "Leaving smime_encrypted handler\n"));
2557 * Format an entry on the CRYPT key selection menu.
2560 * %k key id %K key id of the principal key
2562 * %a algorithm %A algorithm of the princ. key
2563 * %l length %L length of the princ. key
2564 * %f flags %F flags of the princ. key
2565 * %c capabilities %C capabilities of the princ. key
2566 * %t trust/validity of the key-uid association
2568 * %[...] date of key using strftime(3)
2571 static const char *crypt_entry_fmt (char *dest,
2577 const char *ifstring,
2578 const char *elsestring,
2583 crypt_entry_t *entry;
2586 int optional = (flags & M_FORMAT_OPTIONAL);
2587 const char *s = NULL;
2590 entry = (crypt_entry_t *) data;
2593 /* if (isupper ((unsigned char) op)) */
2596 kflags = (key->flags /*| (pkey->flags & KEYFLAG_RESTRICTIONS)
2599 switch (ascii_tolower (op))
2604 char buf2[SHORT_STRING], *p;
2621 while (len > 0 && *cp != ']')
2633 break; /* not enough space */
2644 if (do_locales && Locale)
2645 setlocale (LC_TIME, Locale);
2650 if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
2651 tt = key->kobj->subkeys->timestamp;
2653 tm = localtime (&tt);
2655 strftime (buf2, sizeof (buf2), dest, tm);
2658 setlocale (LC_TIME, "C");
2660 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2661 snprintf (dest, destlen, fmt, buf2);
2669 snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
2670 snprintf (dest, destlen, fmt, entry->num);
2676 /* fixme: we need a way to distinguish between main and subkeys.
2677 Store the idx in entry? */
2678 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2679 snprintf (dest, destlen, fmt, crypt_keyid (key));
2685 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2686 snprintf (dest, destlen, fmt, key->uid);
2692 snprintf (fmt, sizeof (fmt), "%%%s.3s", prefix);
2693 if (key->kobj->subkeys)
2694 s = gpgme_pubkey_algo_name (key->kobj->subkeys->pubkey_algo);
2697 snprintf (dest, destlen, fmt, s);
2703 snprintf (fmt, sizeof (fmt), "%%%slu", prefix);
2704 if (key->kobj->subkeys)
2705 val = key->kobj->subkeys->length;
2708 snprintf (dest, destlen, fmt, val);
2714 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2715 snprintf (dest, destlen, fmt, crypt_flags (kflags));
2717 else if (!(kflags & (KEYFLAG_RESTRICTIONS)))
2723 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2724 snprintf (dest, destlen, fmt, crypt_key_abilities (kflags));
2726 else if (!(kflags & (KEYFLAG_ABILITIES)))
2730 if ((kflags & KEYFLAG_ISX509))
2734 gpgme_user_id_t uid = NULL;
2737 for (i = 0, uid = key->kobj->uids; uid && (i < key->idx);
2738 i++, uid = uid->next)
2741 switch (uid->validity)
2743 case GPGME_VALIDITY_UNDEFINED:
2746 case GPGME_VALIDITY_NEVER:
2749 case GPGME_VALIDITY_MARGINAL:
2752 case GPGME_VALIDITY_FULL:
2755 case GPGME_VALIDITY_ULTIMATE:
2758 case GPGME_VALIDITY_UNKNOWN:
2764 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2765 snprintf (dest, destlen, fmt, s? *s: 'B');
2768 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2769 snprintf (dest, destlen, fmt,
2770 gpgme_get_protocol_name (key->kobj->protocol));
2778 mutt_FormatString (dest, destlen, col, ifstring, mutt_attach_fmt, data, 0);
2779 else if (flags & M_FORMAT_OPTIONAL)
2780 mutt_FormatString (dest, destlen, col, elsestring, mutt_attach_fmt, data, 0);
2784 /* Used by the display fucntion to format a line. */
2785 static void crypt_entry (char *s, size_t l, MUTTMENU * menu, int num)
2787 crypt_key_t **key_table = (crypt_key_t **) menu->data;
2788 crypt_entry_t entry;
2790 entry.key = key_table[num];
2791 entry.num = num + 1;
2793 mutt_FormatString (s, l, 0, NONULL (PgpEntryFormat), crypt_entry_fmt,
2794 (unsigned long) &entry, M_FORMAT_ARROWCURSOR);
2797 /* Compare two addresses and the keyid to be used for sorting. */
2798 static int _crypt_compare_address (const void *a, const void *b)
2800 crypt_key_t **s = (crypt_key_t **) a;
2801 crypt_key_t **t = (crypt_key_t **) b;
2804 if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid)))
2807 return mutt_strcasecmp (crypt_keyid (*s), crypt_keyid (*t)) > 0;
2810 static int crypt_compare_address (const void *a, const void *b)
2812 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_address (a, b)
2813 : _crypt_compare_address (a, b));
2817 /* Compare two key IDs and the addresses to be used for sorting. */
2818 static int _crypt_compare_keyid (const void *a, const void *b)
2820 crypt_key_t **s = (crypt_key_t **) a;
2821 crypt_key_t **t = (crypt_key_t **) b;
2824 if ((r = mutt_strcasecmp (crypt_keyid (*s), crypt_keyid (*t))))
2827 return mutt_strcasecmp ((*s)->uid, (*t)->uid) > 0;
2830 static int crypt_compare_keyid (const void *a, const void *b)
2832 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_keyid (a, b)
2833 : _crypt_compare_keyid (a, b));
2836 /* Compare 2 creation dates and the addresses. For sorting. */
2837 static int _crypt_compare_date (const void *a, const void *b)
2839 crypt_key_t **s = (crypt_key_t **) a;
2840 crypt_key_t **t = (crypt_key_t **) b;
2841 unsigned long ts = 0, tt = 0;
2843 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2844 ts = (*s)->kobj->subkeys->timestamp;
2845 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2846 tt = (*t)->kobj->subkeys->timestamp;
2853 return mutt_strcasecmp ((*s)->uid, (*t)->uid) > 0;
2856 static int crypt_compare_date (const void *a, const void *b)
2858 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_date (a, b)
2859 : _crypt_compare_date (a, b));
2862 /* Compare two trust values, the key length, the creation dates. the
2863 addresses and the key IDs. For sorting. */
2864 static int _crypt_compare_trust (const void *a, const void *b)
2866 crypt_key_t **s = (crypt_key_t **) a;
2867 crypt_key_t **t = (crypt_key_t **) b;
2868 unsigned long ts = 0, tt = 0;
2871 if ((r = (((*s)->flags & (KEYFLAG_RESTRICTIONS))
2872 - ((*t)->flags & (KEYFLAG_RESTRICTIONS)))))
2875 if ((*s)->kobj->uids)
2876 ts = (*s)->kobj->uids->validity;
2877 if ((*t)->kobj->uids)
2878 tt = (*t)->kobj->uids->validity;
2879 if ((r = (tt - ts)))
2882 if ((*s)->kobj->subkeys)
2883 ts = (*s)->kobj->subkeys->length;
2884 if ((*t)->kobj->subkeys)
2885 tt = (*t)->kobj->subkeys->length;
2889 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2890 ts = (*s)->kobj->subkeys->timestamp;
2891 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2892 tt = (*t)->kobj->subkeys->timestamp;
2898 if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid)))
2900 return (mutt_strcasecmp (crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0;
2903 static int crypt_compare_trust (const void *a, const void *b)
2905 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_trust (a, b)
2906 : _crypt_compare_trust (a, b));
2909 /* Print the X.500 Distinguished Name part KEY from the array of parts
2912 print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key)
2916 for (; dn->key; dn++)
2918 if (!strcmp (dn->key, key))
2922 print_utf8 (fp, dn->value, strlen (dn->value));
2929 /* Print all parts of a DN in a standard sequence. */
2931 print_dn_parts (FILE *fp, struct dn_array_s *dn)
2933 const char *stdpart[] = {
2934 "CN", "OU", "O", "STREET", "L", "ST", "C", NULL
2936 int any=0, any2=0, i;
2938 for (i=0; stdpart[i]; i++)
2942 any = print_dn_part (fp, dn, stdpart[i]);
2944 /* now print the rest without any specific ordering */
2945 for (; dn->key; dn++)
2947 for (i=0; stdpart[i]; i++)
2949 if (!strcmp (dn->key, stdpart[i]))
2958 any = print_dn_part (fp, dn, dn->key);
2967 /* Parse an RDN; this is a helper to parse_dn(). */
2968 static const unsigned char *
2969 parse_dn_part (struct dn_array_s *array, const unsigned char *string)
2971 const unsigned char *s, *s1;
2975 /* parse attributeType */
2976 for (s = string+1; *s && *s != '='; s++)
2979 return NULL; /* error */
2982 return NULL; /* empty key */
2983 array->key = safe_malloc (n+1);
2984 p = (unsigned char *)array->key;
2985 memcpy (p, string, n); /* fixme: trim trailing spaces */
2992 for (s=string; hexdigitp (s); s++)
2996 return NULL; /* empty or odd number of digits */
2998 p = safe_malloc (n+1);
2999 array->value = (char*)p;
3000 for (s1=string; n; s1 += 2, n--)
3005 { /* regular v3 quoted string */
3006 for (n=0, s=string; *s; s++)
3011 if (*s == ',' || *s == '=' || *s == '+'
3012 || *s == '<' || *s == '>' || *s == '#' || *s == ';'
3013 || *s == '\\' || *s == '\"' || *s == ' ')
3015 else if (hexdigitp (s) && hexdigitp (s+1))
3021 return NULL; /* invalid escape sequence */
3023 else if (*s == '\"')
3024 return NULL; /* invalid encoding */
3025 else if (*s == ',' || *s == '=' || *s == '+'
3026 || *s == '<' || *s == '>' || *s == '#' || *s == ';' )
3032 p = safe_malloc (n+1);
3033 array->value = (char*)p;
3034 for (s=string; n; s++, n--)
3056 /* Parse a DN and return an array-ized one. This is not a validating
3057 parser and it does not support any old-stylish syntax; gpgme is
3058 expected to return only rfc2253 compatible strings. */
3059 static struct dn_array_s *
3060 parse_dn (const unsigned char *string)
3062 struct dn_array_s *array;
3063 size_t arrayidx, arraysize;
3066 arraysize = 7; /* C,ST,L,O,OU,CN,email */
3067 array = safe_malloc ((arraysize+1) * sizeof *array);
3071 while (*string == ' ')
3075 if (arrayidx >= arraysize)
3076 { /* mutt lacks a real safe_realoc - so we need to copy */
3077 struct dn_array_s *a2;
3080 a2 = safe_malloc ((arraysize+1) * sizeof *array);
3081 for (i=0; i < arrayidx; i++)
3083 a2[i].key = array[i].key;
3084 a2[i].value = array[i].value;
3089 array[arrayidx].key = NULL;
3090 array[arrayidx].value = NULL;
3091 string = parse_dn_part (array+arrayidx, string);
3095 while (*string == ' ')
3097 if (*string && *string != ',' && *string != ';' && *string != '+')
3098 goto failure; /* invalid delimiter */
3102 array[arrayidx].key = NULL;
3103 array[arrayidx].value = NULL;
3107 for (i=0; i < arrayidx; i++)
3109 FREE (&array[i].key);
3110 FREE (&array[i].value);
3117 /* Print a nice representation of the USERID and make sure it is
3118 displayed in a proper way, which does mean to reorder some parts
3119 for S/MIME's DNs. USERID is a string as returned by the gpgme key
3120 functions. It is utf-8 encoded. */
3122 parse_and_print_user_id (FILE *fp, const char *userid)
3129 s = strchr (userid+1, '>');
3131 print_utf8 (fp, userid+1, s-userid-1);
3133 else if (*userid == '(')
3134 fputs (_("[Can't display this user ID (unknown encoding)]"), fp);
3135 else if (!digit_or_letter ((const unsigned char *)userid))
3136 fputs (_("[Can't display this user ID (invalid encoding)]"), fp);
3139 struct dn_array_s *dn = parse_dn ((const unsigned char *)userid);
3141 fputs (_("[Can't display this user ID (invalid DN)]"), fp);
3144 print_dn_parts (fp, dn);
3145 for (i=0; dn[i].key; i++)
3148 FREE (&dn[i].value);
3157 KEY_CAP_CAN_ENCRYPT,
3164 key_check_cap (gpgme_key_t key, key_cap_t cap)
3166 gpgme_subkey_t subkey = NULL;
3167 unsigned int ret = 0;
3171 case KEY_CAP_CAN_ENCRYPT:
3172 if (! (ret = key->can_encrypt))
3173 for (subkey = key->subkeys; subkey; subkey = subkey->next)
3174 if ((ret = subkey->can_encrypt))
3177 case KEY_CAP_CAN_SIGN:
3178 if (! (ret = key->can_sign))
3179 for (subkey = key->subkeys; subkey; subkey = subkey->next)
3180 if ((ret = subkey->can_sign))
3183 case KEY_CAP_CAN_CERTIFY:
3184 if (! (ret = key->can_certify))
3185 for (subkey = key->subkeys; subkey; subkey = subkey->next)
3186 if ((ret = subkey->can_certify))
3195 /* Print verbose information about a key or certificate to FP. */
3196 static void print_key_info (gpgme_key_t key, FILE *fp)
3199 const char *s = NULL, *s2 = NULL;
3202 char shortbuf[SHORT_STRING];
3203 unsigned long aval = 0;
3207 gpgme_user_id_t uid = NULL;
3210 setlocale (LC_TIME, Locale);
3212 is_pgp = key->protocol == GPGME_PROTOCOL_OpenPGP;
3214 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3220 fputs (idx ? _(" aka ......: ") :_("Name ......: "), fp);
3223 fputs (_("[Invalid]"), fp);
3227 print_utf8 (fp, s, strlen(s));
3229 parse_and_print_user_id (fp, s);
3233 if (key->subkeys && (key->subkeys->timestamp > 0))
3235 tt = key->subkeys->timestamp;
3237 tm = localtime (&tt);
3238 #ifdef HAVE_LANGINFO_D_T_FMT
3239 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
3241 strftime (shortbuf, sizeof shortbuf, "%c", tm);
3243 fprintf (fp, _("Valid From : %s\n"), shortbuf);
3246 if (key->subkeys && (key->subkeys->expires > 0))
3248 tt = key->subkeys->expires;
3250 tm = localtime (&tt);
3251 #ifdef HAVE_LANGINFO_D_T_FMT
3252 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
3254 strftime (shortbuf, sizeof shortbuf, "%c", tm);
3256 fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
3260 s = gpgme_pubkey_algo_name (key->subkeys->pubkey_algo);
3264 s2 = is_pgp ? "PGP" : "X.509";
3267 aval = key->subkeys->length;
3269 fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), s2, aval, s);
3271 fprintf (fp, _("Key Usage .: "));
3274 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3276 fprintf (fp, "%s%s", delim, _("encryption"));
3279 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3281 fprintf (fp, "%s%s", delim, _("signing"));
3284 if (key_check_cap (key, KEY_CAP_CAN_CERTIFY))
3286 fprintf (fp, "%s%s", delim, _("certification"));
3293 s = key->subkeys->fpr;
3294 fputs (_("Fingerprint: "), fp);
3295 if (is_pgp && strlen (s) == 40)
3297 for (i=0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++)
3303 putc (is_pgp? ' ':':', fp);
3304 if (is_pgp && i == 4)
3310 for (i=0; *s && s[1] && s[2]; s += 2, i++)
3314 putc (is_pgp? ' ':':', fp);
3315 if (is_pgp && i == 7)
3319 fprintf (fp, "%s\n", s);
3322 if (key->issuer_serial)
3324 s = key->issuer_serial;
3326 fprintf (fp, _("Serial-No .: 0x%s\n"), s);
3329 if (key->issuer_name)
3331 s = key->issuer_name;
3334 fprintf (fp, _("Issued By .: "));
3335 parse_and_print_user_id (fp, s);
3340 /* For PGP we list all subkeys. */
3343 gpgme_subkey_t subkey = NULL;
3345 for (idx = 1, subkey = key->subkeys; subkey;
3346 idx++, subkey = subkey->next)
3351 if ( strlen (s) == 16)
3352 s += 8; /* display only the short keyID */
3353 fprintf (fp, _("Subkey ....: 0x%s"), s);
3354 if (subkey->revoked)
3357 fputs (_("[Revoked]"), fp);
3359 if (subkey->invalid)
3362 fputs (_("[Invalid]"), fp);
3364 if (subkey->expired)
3367 fputs (_("[Expired]"), fp);
3369 if (subkey->disabled)
3372 fputs (_("[Disabled]"), fp);
3376 if (subkey->timestamp > 0)
3378 tt = subkey->timestamp;
3380 tm = localtime (&tt);
3381 #ifdef HAVE_LANGINFO_D_T_FMT
3382 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
3384 strftime (shortbuf, sizeof shortbuf, "%c", tm);
3386 fprintf (fp, _("Valid From : %s\n"), shortbuf);
3389 if (subkey->expires > 0)
3391 tt = subkey->expires;
3393 tm = localtime (&tt);
3394 #ifdef HAVE_LANGINFO_D_T_FMT
3395 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
3397 strftime (shortbuf, sizeof shortbuf, "%c", tm);
3399 fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
3403 s = gpgme_pubkey_algo_name (subkey->pubkey_algo);
3408 aval = subkey->length;
3412 fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), "PGP", aval, s);
3414 fprintf (fp, _("Key Usage .: "));
3417 if (subkey->can_encrypt)
3419 fprintf (fp, "%s%s", delim, _("encryption"));
3422 if (subkey->can_sign)
3424 fprintf (fp, "%s%s", delim, _("signing"));
3427 if (subkey->can_certify)
3429 fprintf (fp, "%s%s", delim, _("certification"));
3437 setlocale (LC_TIME, "C");
3441 /* Show detailed information about the selected key */
3443 verify_key (crypt_key_t *key)
3446 char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
3448 gpgme_ctx_t listctx = NULL;
3450 gpgme_key_t k = NULL;
3453 mutt_mktemp (tempfile, sizeof (tempfile));
3454 if (!(fp = safe_fopen (tempfile, "w")))
3456 mutt_perror _("Can't create temporary file");
3459 mutt_message _("Collecting data...");
3461 print_key_info (key->kobj, fp);
3463 err = gpgme_new (&listctx);
3466 fprintf (fp, "Internal error: can't create gpgme context: %s\n",
3467 gpgme_strerror (err));
3470 if ((key->flags & KEYFLAG_ISX509))
3471 gpgme_set_protocol (listctx, GPGME_PROTOCOL_CMS);
3475 while ((s = k->chain_id) && k->subkeys && strcmp (s, k->subkeys->fpr) )
3478 err = gpgme_op_keylist_start (listctx, s, 0);
3479 gpgme_key_release (k);
3482 err = gpgme_op_keylist_next (listctx, &k);
3485 fprintf (fp, _("Error finding issuer key: %s\n"),
3486 gpgme_strerror (err));
3489 gpgme_op_keylist_end (listctx);
3491 print_key_info (k, fp);
3495 fputs (_("Error: certification chain to long - stopping here\n"),
3502 gpgme_key_release (k);
3503 gpgme_release (listctx);
3505 mutt_clear_error ();
3506 snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), crypt_keyid (key));
3507 mutt_do_pager (cmd, tempfile, 0, NULL);
3511 * Implementation of `findkeys'.
3515 /* Convert LIST into a pattern string suitable to be passed to GPGME.
3516 We need to convert spaces in an item into a '+' and '%' into
3518 static char *list_to_pattern (LIST *list)
3526 for(l=list; l; l = l->next)
3528 for(s = l->data; *s; s++)
3534 n++; /* delimiter or end of string */
3536 n++; /* make sure to allocate at least one byte */
3537 pattern = p = safe_calloc (1,n);
3538 for(l=list; l; l = l->next)
3545 for(s = l->data; *s; s++)
3570 /* Return a list of keys which are candidates for the selection.
3571 Select by looking at the HINTS list. */
3572 static crypt_key_t *get_candidates (LIST * hints, unsigned int app, int secret)
3574 crypt_key_t *db, *k, **kend;
3580 gpgme_user_id_t uid = NULL;
3582 pattern = list_to_pattern (hints);
3586 err = gpgme_new (&ctx);
3589 mutt_error (_("gpgme_new failed: %s"), gpgme_strerror (err));
3597 if ((app & APPLICATION_PGP))
3599 /* Its all a mess. That old GPGME expects different things
3600 depending on the protocol. For gpg we don' t need percent
3601 escaped pappert but simple strings passed in an array to the
3602 keylist_ext_start function. */
3607 for(l=hints, n=0; l; l = l->next)
3609 if (l->data && *l->data)
3615 patarr = safe_calloc (n+1, sizeof *patarr);
3616 for(l=hints, n=0; l; l = l->next)
3618 if (l->data && *l->data)
3619 patarr[n++] = safe_strdup (l->data);
3622 err = gpgme_op_keylist_ext_start (ctx, (const char**)patarr, secret, 0);
3623 for (n=0; patarr[n]; n++)
3628 mutt_error (_("gpgme_op_keylist_start failed: %s"),
3629 gpgme_strerror (err));
3630 gpgme_release (ctx);
3635 while (!(err = gpgme_op_keylist_next (ctx, &key)) )
3637 unsigned int flags = 0;
3639 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3640 flags |= KEYFLAG_CANENCRYPT;
3641 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3642 flags |= KEYFLAG_CANSIGN;
3644 #if 0 /* DISABLED code */
3647 /* Bug in gpg. Capabilities are not listed for secret
3648 keys. Try to deduce them from the algorithm. */
3650 switch (key->subkeys[0].pubkey_algo)
3653 flags |= KEYFLAG_CANENCRYPT;
3654 flags |= KEYFLAG_CANSIGN;
3656 case GPGME_PK_ELG_E:
3657 flags |= KEYFLAG_CANENCRYPT;
3660 flags |= KEYFLAG_CANSIGN;
3664 #endif /* DISABLED code */
3666 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3668 k = safe_calloc (1, sizeof *k);
3677 if (gpg_err_code (err) != GPG_ERR_EOF)
3678 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3679 gpgme_op_keylist_end (ctx);
3684 if ((app & APPLICATION_SMIME))
3686 /* and now look for x509 certificates */
3687 gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
3688 err = gpgme_op_keylist_start (ctx, pattern, 0);
3691 mutt_error (_("gpgme_op_keylist_start failed: %s"),
3692 gpgme_strerror (err));
3693 gpgme_release (ctx);
3698 while (!(err = gpgme_op_keylist_next (ctx, &key)) )
3700 unsigned int flags = KEYFLAG_ISX509;
3702 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3703 flags |= KEYFLAG_CANENCRYPT;
3704 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3705 flags |= KEYFLAG_CANSIGN;
3707 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3709 k = safe_calloc (1, sizeof *k);
3718 if (gpg_err_code (err) != GPG_ERR_EOF)
3719 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3720 gpgme_op_keylist_end (ctx);
3723 gpgme_release (ctx);
3728 /* Add the string STR to the list HINTS. This list is later used to
3730 static LIST *crypt_add_string_to_hints (LIST *hints, const char *str)
3735 if ((scratch = safe_strdup (str)) == NULL)
3738 for (t = strtok (scratch, " ,.:\"()<>\n"); t;
3739 t = strtok (NULL, " ,.:\"()<>\n"))
3742 hints = mutt_add_list (hints, t);
3749 /* Display a menu to select a key from the array KEYS. FORCED_VALID
3750 will be set to true on return if the user did override the the
3752 static crypt_key_t *crypt_select_key (crypt_key_t *keys,
3753 ADDRESS * p, const char *s,
3754 unsigned int app, int *forced_valid)
3757 crypt_key_t **key_table;
3760 char helpstr[LONG_STRING], buf[LONG_STRING];
3762 int (*f) (const void *, const void *);
3763 int menu_to_use = 0;
3768 /* build the key table */
3771 for (k = keys; k; k = k->next)
3773 if (!option (OPTPGPSHOWUNUSABLE) && (k->flags & KEYFLAG_CANTUSE))
3782 safe_realloc (&key_table, sizeof (crypt_key_t*)*keymax);
3790 mutt_error _("All matching keys are marked expired/revoked.");
3795 switch (PgpSortKeys & SORT_MASK)
3798 f = crypt_compare_date;
3801 f = crypt_compare_keyid;
3804 f = crypt_compare_address;
3808 f = crypt_compare_trust;
3811 qsort (key_table, i, sizeof (crypt_key_t*), f);
3813 if (app & APPLICATION_PGP)
3814 menu_to_use = MENU_KEY_SELECT_PGP;
3815 else if (app & APPLICATION_SMIME)
3816 menu_to_use = MENU_KEY_SELECT_SMIME;
3819 mutt_make_help (buf, sizeof (buf), _("Exit "), menu_to_use, OP_EXIT);
3820 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3821 mutt_make_help (buf, sizeof (buf), _("Select "), menu_to_use,
3822 OP_GENERIC_SELECT_ENTRY);
3823 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3824 mutt_make_help (buf, sizeof (buf), _("Check key "),
3825 menu_to_use, OP_VERIFY_KEY);
3826 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3827 mutt_make_help (buf, sizeof (buf), _("Help"), menu_to_use, OP_HELP);
3828 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3830 menu = mutt_new_menu (menu_to_use);
3832 menu->make_entry = crypt_entry;
3833 menu->help = helpstr;
3834 menu->data = key_table;
3839 if ((app & APPLICATION_PGP) && (app & APPLICATION_SMIME))
3840 ts = _("PGP and S/MIME keys matching");
3841 else if ((app & APPLICATION_PGP))
3842 ts = _("PGP keys matching");
3843 else if ((app & APPLICATION_SMIME))
3844 ts = _("S/MIME keys matching");
3846 ts = _("keys matching");
3849 snprintf (buf, sizeof (buf), _("%s <%s>."), ts, p->mailbox);
3851 snprintf (buf, sizeof (buf), _("%s \"%s\"."), ts, s);
3855 mutt_clear_error ();
3860 switch (mutt_menuLoop (menu))
3863 verify_key (key_table[menu->current]);
3864 menu->redraw = REDRAW_FULL;
3868 mutt_message ("%s", key_table[menu->current]->uid);
3871 case OP_GENERIC_SELECT_ENTRY:
3872 /* FIXME make error reporting more verbose - this should be
3873 easy because gpgme provides more information */
3874 if (option (OPTPGPCHECKTRUST))
3876 if (!crypt_key_is_valid (key_table[menu->current]))
3878 mutt_error _("This key can't be used: "
3879 "expired/disabled/revoked.");
3884 if (option (OPTPGPCHECKTRUST) &&
3885 (!crypt_id_is_valid (key_table[menu->current])
3886 || !crypt_id_is_strong (key_table[menu->current])))
3889 char buff[LONG_STRING];
3891 if (key_table[menu->current]->flags & KEYFLAG_CANTUSE)
3892 s = N_("ID is expired/disabled/revoked.");
3895 gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
3896 gpgme_user_id_t uid = NULL;
3901 uid = key_table[menu->current]->kobj->uids;
3902 for (j = 0; (j < key_table[menu->current]->idx) && uid;
3903 j++, uid = uid->next)
3906 val = uid->validity;
3910 case GPGME_VALIDITY_UNKNOWN:
3911 case GPGME_VALIDITY_UNDEFINED:
3912 warn_s = N_("ID has undefined validity.");
3914 case GPGME_VALIDITY_NEVER:
3915 warn_s = N_("ID is not valid.");
3917 case GPGME_VALIDITY_MARGINAL:
3918 warn_s = N_("ID is only marginally valid.");
3920 case GPGME_VALIDITY_FULL:
3921 case GPGME_VALIDITY_ULTIMATE:
3925 snprintf (buff, sizeof (buff),
3926 _("%s Do you really want to use the key?"),
3929 if (mutt_yesorno (buff, 0) != 1)
3931 mutt_clear_error ();
3938 k = crypt_copy_key (key_table[menu->current]);
3949 mutt_menuDestroy (&menu);
3952 set_option (OPTNEEDREDRAW);
3957 static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
3958 unsigned int app, int *forced_valid)
3966 int this_key_has_strong;
3967 int this_key_has_weak;
3968 int this_key_has_invalid;
3971 crypt_key_t *keys, *k;
3972 crypt_key_t *the_valid_key = NULL;
3973 crypt_key_t *matches = NULL;
3974 crypt_key_t **matches_endp = &matches;
3978 if (a && a->mailbox)
3979 hints = crypt_add_string_to_hints (hints, a->mailbox);
3980 if (a && a->personal)
3981 hints = crypt_add_string_to_hints (hints, a->personal);
3983 mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
3984 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN) );
3986 mutt_free_list (&hints);
3991 dprint (5, (debugfile, "crypt_getkeybyaddr: looking for %s <%s>.",
3992 a->personal, a->mailbox));
3994 for (k = keys; k; k = k->next)
3996 dprint (5, (debugfile, " looking at key: %s `%.15s'\n",
3997 crypt_keyid (k), k->uid));
3999 if (abilities && !(k->flags & abilities))
4001 dprint (5, (debugfile, " insufficient abilities: Has %x, want %x\n",
4002 k->flags, abilities));
4006 this_key_has_weak = 0; /* weak but valid match */
4007 this_key_has_invalid = 0; /* invalid match */
4008 this_key_has_strong = 0; /* strong and valid match */
4009 match = 0; /* any match */
4011 r = rfc822_parse_adrlist (NULL, k->uid);
4012 for (p = r; p; p = p->next)
4014 int validity = crypt_id_matches_addr (a, p, k);
4016 if (validity & CRYPT_KV_MATCH) /* something matches */
4019 /* is this key a strong candidate? */
4020 if ((validity & CRYPT_KV_VALID)
4021 && (validity & CRYPT_KV_STRONGID)
4022 && (validity & CRYPT_KV_ADDR))
4024 if (the_valid_key && the_valid_key != k)
4027 this_key_has_strong = 1;
4029 else if ((validity & CRYPT_KV_MATCH)
4030 && !(validity & CRYPT_KV_VALID))
4031 this_key_has_invalid = 1;
4032 else if ((validity & CRYPT_KV_MATCH)
4033 && (!(validity & CRYPT_KV_STRONGID)
4034 || !(validity & CRYPT_KV_ADDR)))
4035 this_key_has_weak = 1;
4037 rfc822_free_address (&r);
4043 if (!this_key_has_strong && this_key_has_invalid)
4045 if (!this_key_has_strong && this_key_has_weak)
4048 *matches_endp = tmp = crypt_copy_key (k);
4049 matches_endp = &tmp->next;
4050 the_valid_key = tmp;
4054 crypt_free_key (&keys);
4058 if (the_valid_key && !multi && !weak
4059 && !(invalid && option (OPTPGPSHOWUNUSABLE)))
4062 * There was precisely one strong match on a valid ID, there
4063 * were no valid keys with weak matches, and we aren't
4064 * interested in seeing invalid keys.
4066 * Proceed without asking the user.
4068 k = crypt_copy_key (the_valid_key);
4073 * Else: Ask the user.
4075 k = crypt_select_key (matches, a, NULL, app, forced_valid);
4077 crypt_free_key (&matches);
4086 static crypt_key_t *crypt_getkeybystr (char *p, short abilities,
4087 unsigned int app, int *forced_valid)
4091 crypt_key_t *matches = NULL;
4092 crypt_key_t **matches_endp = &matches;
4096 mutt_message (_("Looking for keys matching \"%s\"..."), p);
4100 hints = crypt_add_string_to_hints (hints, p);
4101 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
4102 mutt_free_list (&hints);
4107 for (k = keys; k; k = k->next)
4109 if (abilities && !(k->flags & abilities))
4113 dprint (5, (debugfile, "crypt_getkeybystr: matching \"%s\" against "
4114 "key %s, \"%s\": ", p, crypt_keyid (k), k->uid));
4117 || !mutt_strcasecmp (p, crypt_keyid (k))
4118 || (!mutt_strncasecmp (p, "0x", 2)
4119 && !mutt_strcasecmp (p + 2, crypt_keyid (k)))
4120 || (option (OPTPGPLONGIDS)
4121 && !mutt_strncasecmp (p, "0x", 2)
4122 && !mutt_strcasecmp (p + 2, crypt_keyid (k) + 8))
4123 || mutt_stristr (k->uid, p))
4127 dprint (5, (debugfile, "match.\n"));
4129 *matches_endp = tmp = crypt_copy_key (k);
4130 matches_endp = &tmp->next;
4134 crypt_free_key (&keys);
4138 k = crypt_select_key (matches, NULL, p, app, forced_valid);
4139 crypt_free_key (&matches);
4146 /* Display TAG as a prompt to ask for a key. If WHATFOR is not null
4147 use it as default and store it under that label as the next
4148 default. ABILITIES describe the required key abilities (sign,
4149 encrypt) and APP the type of the requested key; ether S/MIME or
4150 PGP. Return a copy of the key or NULL if not found. */
4151 static crypt_key_t *crypt_ask_for_key (char *tag,
4158 char resp[SHORT_STRING];
4159 struct crypt_cache *l = NULL;
4163 forced_valid = &dummy;
4165 mutt_clear_error ();
4172 for (l = id_defaults; l; l = l->next)
4173 if (!mutt_strcasecmp (whatfor, l->what))
4175 strfcpy (resp, NONULL (l->dflt), sizeof (resp));
4184 if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0)
4190 mutt_str_replace (&l->dflt, resp);
4193 l = safe_malloc (sizeof (struct crypt_cache));
4194 l->next = id_defaults;
4196 l->what = safe_strdup (whatfor);
4197 l->dflt = safe_strdup (resp);
4201 if ((key = crypt_getkeybystr (resp, abilities, app, forced_valid)))
4209 /* This routine attempts to find the keyids of the recipients of a
4210 message. It returns NULL if any of the keys can not be found. */
4211 static char *find_keys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc,
4214 char *keyID, *keylist = NULL, *t;
4215 size_t keylist_size = 0;
4216 size_t keylist_used = 0;
4217 ADDRESS *tmp = NULL, *addr = NULL;
4218 ADDRESS **last = &tmp;
4221 crypt_key_t *k_info, *key;
4222 const char *fqdn = mutt_fqdn (1);
4225 *r_application = APPLICATION_PGP|APPLICATION_SMIME;
4228 for (i = 0; i < 3; i++)
4232 case 0: p = to; break;
4233 case 1: p = cc; break;
4234 case 2: p = bcc; break;
4238 *last = rfc822_cpy_adr (p, 0);
4240 last = &((*last)->next);
4244 rfc822_qualify (tmp, fqdn);
4246 tmp = mutt_remove_duplicates (tmp);
4248 for (p = tmp; p ; p = p->next)
4250 char buf[LONG_STRING];
4251 int forced_valid = 0;
4256 if ((keyID = mutt_crypt_hook (p)) != NULL)
4259 snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"),
4261 if ((r = mutt_yesorno (buf, M_YES)) == M_YES)
4263 /* check for e-mail address */
4264 if ((t = strchr (keyID, '@')) &&
4265 (addr = rfc822_parse_adrlist (NULL, keyID)))
4268 rfc822_qualify (addr, fqdn);
4274 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
4275 *r_application, &forced_valid);
4277 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
4278 app, &forced_valid);
4285 rfc822_free_address (&tmp);
4286 rfc822_free_address (&addr);
4292 && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT,
4293 app, &forced_valid)) == NULL)
4295 snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
4297 if ((key = crypt_ask_for_key (buf, q->mailbox,
4304 &forced_valid)) == NULL)
4307 rfc822_free_address (&tmp);
4308 rfc822_free_address (&addr);
4316 const char *s = crypt_fpr (key);
4319 if (key->flags & KEYFLAG_ISX509)
4320 *r_application &= ~APPLICATION_PGP;
4321 if (!(key->flags & KEYFLAG_ISX509))
4322 *r_application &= ~APPLICATION_SMIME;
4325 keylist_size += mutt_strlen (s) + 4 + 1;
4326 safe_realloc (&keylist, keylist_size);
4327 sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */
4328 keylist_used ? " " : "", s,
4329 forced_valid? "!":"");
4331 keylist_used = mutt_strlen (keylist);
4333 crypt_free_key (&key);
4334 rfc822_free_address (&addr);
4336 rfc822_free_address (&tmp);
4340 char *pgp_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc)
4342 return find_keys (to, cc, bcc, APPLICATION_PGP);
4345 char *smime_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc)
4347 return find_keys (to, cc, bcc, APPLICATION_SMIME);
4351 * Implementation of `init'.
4354 /* Initialization. */
4355 static void init_gpgme (void)
4357 /* Make sure that gpg-agent is running. */
4358 if (! getenv ("GPG_AGENT_INFO"))
4360 mutt_error (_("\nUsing GPGME backend, although no gpg-agent is running"));
4361 if (mutt_any_key_to_continue (NULL) == -1)
4366 void pgp_gpgme_init (void)
4371 void smime_gpgme_init (void)
4375 static int gpgme_send_menu (HEADER *msg, int *redraw, int is_smime)
4378 char input_signas[SHORT_STRING];
4381 if (msg->security & APPLICATION_PGP)
4383 else if (msg->security & APPLICATION_SMIME)
4387 choice = mutt_multi_choice (
4388 _("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?"),
4391 choice = mutt_multi_choice (
4392 _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?"),
4397 case 1: /* (e)ncrypt */
4398 msg->security |= (is_smime ? SMIMEENCRYPT : PGPENCRYPT);
4399 msg->security &= ~(is_smime ? SMIMESIGN : PGPSIGN);
4402 case 2: /* (s)ign */
4403 msg->security |= (is_smime? SMIMESIGN :PGPSIGN);
4404 msg->security &= ~(is_smime ? SMIMEENCRYPT : PGPENCRYPT);
4407 case 3: /* sign (a)s */
4408 /* unset_option(OPTCRYPTCHECKTRUST); */
4409 if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
4410 is_smime? APPLICATION_SMIME:APPLICATION_PGP,
4413 snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p));
4414 mutt_str_replace (is_smime? &SmimeDefaultKey : &PgpSignAs, input_signas);
4415 crypt_free_key (&p);
4417 msg->security |= (is_smime? SMIMESIGN:PGPSIGN);
4422 msg->security &= (is_smime? ~SMIMESIGN : ~PGPSIGN);
4425 *redraw = REDRAW_FULL;
4428 case 4: /* (b)oth */
4429 msg->security = (is_smime? (SMIMEENCRYPT|SMIMESIGN):(PGPENCRYPT|PGPSIGN));
4432 case 5: /* (p)gp or s/(m)ime */
4433 is_smime = !is_smime;
4436 case 6: /* (f)orget it */
4437 case 7: /* (c)lear */
4442 if (choice == 6 || choice == 7)
4446 msg->security &= ~APPLICATION_PGP;
4447 msg->security |= APPLICATION_SMIME;
4451 msg->security &= ~APPLICATION_SMIME;
4452 msg->security |= APPLICATION_PGP;
4455 return (msg->security);
4458 int pgp_gpgme_send_menu (HEADER *msg, int *redraw)
4460 return gpgme_send_menu (msg, redraw, 0);
4463 int smime_gpgme_send_menu (HEADER *msg, int *redraw)
4465 return gpgme_send_menu (msg, redraw, 1);
4468 static int verify_sender (HEADER *h, gpgme_protocol_t protocol)
4470 ADDRESS *sender = NULL;
4471 unsigned int ret = 1;
4475 h->env->from = mutt_expand_aliases (h->env->from);
4476 sender = h->env->from;
4478 else if (h->env->sender)
4480 h->env->sender = mutt_expand_aliases (h->env->sender);
4481 sender = h->env->sender;
4488 gpgme_key_t key = signature_key;
4489 gpgme_user_id_t uid = NULL;
4490 int sender_length = 0;
4493 sender_length = strlen (sender->mailbox);
4494 for (uid = key->uids; uid && ret; uid = uid->next)
4496 uid_length = strlen (uid->email);
4498 && (uid->email[0] == '<')
4499 && (uid->email[uid_length - 1] == '>')
4500 && (uid_length == sender_length + 2))
4502 const char* at_sign = strchr(uid->email + 1, '@');
4503 if (at_sign == NULL)
4505 if (! strncmp (uid->email + 1, sender->mailbox, sender_length))
4511 * Assume address is 'mailbox@domainname'.
4512 * The mailbox part is case-sensitive,
4513 * the domainname is not. (RFC 2821)
4515 const char* tmp_email = uid->email + 1;
4516 const char* tmp_sender = sender->mailbox;
4517 /* length of mailbox part including '@' */
4518 int mailbox_length = at_sign - tmp_email + 1;
4519 int domainname_length = sender_length - mailbox_length;
4520 int mailbox_match, domainname_match;
4522 mailbox_match = (! strncmp (tmp_email, tmp_sender,
4524 tmp_email += mailbox_length;
4525 tmp_sender += mailbox_length;
4526 domainname_match = (! strncasecmp (tmp_email, tmp_sender,
4527 domainname_length));
4528 if (mailbox_match && domainname_match)
4535 mutt_any_key_to_continue (_("Failed to verify sender"));
4538 mutt_any_key_to_continue (_("Failed to figure out sender"));
4542 gpgme_key_release (signature_key);
4543 signature_key = NULL;
4549 int smime_gpgme_verify_sender (HEADER *h)
4551 return verify_sender (h, GPGME_PROTOCOL_CMS);
4554 void gpgme_set_sender (const char *sender)
4556 mutt_error ("[setting sender] mailbox: %s\n", sender);
4557 FREE (¤t_sender);
4558 current_sender = safe_strdup (sender);