1 /* crypt-gpgme.c - GPGME based crypto operations
2 * Copyright (C) 1996,1997 Michael R. Elkins <me@cs.hmc.edu>
3 * Copyright (C) 1998,1999,2000 Thomas Roessler <roessler@guug.de>
4 * Copyright (C) 2001 Thomas Roessler <roessler@guug.de>
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., 59 Temple Place - Suite 330, Boston, MA 02111, 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 /* Values used for comparing addresses. */
75 #define CRYPT_KV_VALID 1
76 #define CRYPT_KV_ADDR 2
77 #define CRYPT_KV_STRING 4
78 #define CRYPT_KV_STRONGID 8
79 #define CRYPT_KV_MATCH (CRYPT_KV_ADDR|CRYPT_KV_STRING)
89 struct crypt_cache *next;
98 /* We work based on user IDs, getting from a user ID to the key is
99 check and does not need any memory (gpgme uses reference counting). */
100 typedef struct crypt_keyinfo
102 struct crypt_keyinfo *next;
104 int idx; /* and the user ID at this index */
105 const char *uid; /* and for convenience point to this user ID */
106 unsigned int flags; /* global and per uid flags (for convenience)*/
109 typedef struct crypt_entry
116 static struct crypt_cache *id_defaults = NULL;
117 static gpgme_key_t signature_key = NULL;
120 * General helper functions.
123 /* return true when S pints to a didgit or letter. */
125 digit_or_letter (const unsigned char *s)
127 return ( (*s >= '0' && *s < '9')
128 || (*s >= 'A' && *s <= 'Z')
129 || (*s >= 'a' && *s <= 'z'));
133 /* Print the utf-8 encoded string BUF of length LEN bytes to stream
134 FP. Convert the character set. */
136 print_utf8 (FILE *fp, const char *buf, size_t len)
140 tstr = safe_malloc (len+1);
141 memcpy (tstr, buf, len);
143 mutt_convert_string (&tstr, "utf-8", Charset, M_ICONV_HOOK_FROM);
153 /* Return the keyID for the key K. Note that this string is valid as
154 long as K is valid */
155 static const char *crypt_keyid (crypt_key_t *k)
157 const char *s = "????????";
159 if (k->kobj && k->kobj->subkeys)
161 s = k->kobj->subkeys->keyid;
162 if ((! option (OPTPGPLONGIDS)) && (strlen (s) == 16))
163 /* Return only the short keyID. */
170 /* Return the hexstring fingerprint from the key K. */
171 static const char *crypt_fpr (crypt_key_t *k)
175 if (k->kobj && k->kobj->subkeys)
176 s = k->kobj->subkeys->fpr;
181 /* Parse FLAGS and return a statically allocated(!) string with them. */
182 static char *crypt_key_abilities (int flags)
186 if (!(flags & KEYFLAG_CANENCRYPT))
188 else if (flags & KEYFLAG_PREFER_SIGNING)
193 if (!(flags & KEYFLAG_CANSIGN))
195 else if (flags & KEYFLAG_PREFER_ENCRYPTION)
205 /* Parse FLAGS and return a character describing the most important flag. */
206 static char crypt_flags (int flags)
208 if (flags & KEYFLAG_REVOKED)
210 else if (flags & KEYFLAG_EXPIRED)
212 else if (flags & KEYFLAG_DISABLED)
214 else if (flags & KEYFLAG_CRITICAL)
220 /* Return a copy of KEY. */
221 static crypt_key_t *crypt_copy_key (crypt_key_t *key)
225 k = safe_calloc (1, sizeof *k);
227 gpgme_key_ref (key->kobj);
230 k->flags = key->flags;
235 /* Release all the keys at the address of KEYLIST and set the address
237 static void crypt_free_key (crypt_key_t **keylist)
241 crypt_key_t *k = (*keylist)->next;
247 /* Return trute when key K is valid. */
248 static int crypt_key_is_valid (crypt_key_t *k)
250 if (k->flags & KEYFLAG_CANTUSE)
255 /* Return true whe validity of KEY is sufficient. */
256 static int crypt_id_is_strong (crypt_key_t *key)
258 gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
259 gpgme_user_id_t uid = NULL;
260 unsigned int is_strong = 0;
263 if ((key->flags & KEYFLAG_ISX509))
266 for (i = 0, uid = key->kobj->uids; (i < key->idx) && uid;
267 i++, uid = uid->next)
274 case GPGME_VALIDITY_UNKNOWN:
275 case GPGME_VALIDITY_UNDEFINED:
276 case GPGME_VALIDITY_NEVER:
277 case GPGME_VALIDITY_MARGINAL:
281 case GPGME_VALIDITY_FULL:
282 case GPGME_VALIDITY_ULTIMATE:
290 /* Return true when the KEY is valid, i.e. not marked as unusable. */
291 static int crypt_id_is_valid (crypt_key_t *key)
293 return ! (key->flags & KEYFLAG_CANTUSE);
296 /* Return a bit vector describing how well the addresses ADDR and
297 U_ADDR match and whether KEY is valid. */
298 static int crypt_id_matches_addr (ADDRESS *addr, ADDRESS *u_addr,
303 if (crypt_id_is_valid (key))
304 rv |= CRYPT_KV_VALID;
306 if (crypt_id_is_strong (key))
307 rv |= CRYPT_KV_STRONGID;
309 if (addr->mailbox && u_addr->mailbox
310 && mutt_strcasecmp (addr->mailbox, u_addr->mailbox) == 0)
313 if (addr->personal && u_addr->personal
314 && mutt_strcasecmp (addr->personal, u_addr->personal) == 0)
315 rv |= CRYPT_KV_STRING;
322 * GPGME convenient functions.
325 /* Create a new gpgme context and return it. With FOR_SMIME set to
326 true, the protocol of the context is set to CMS. */
327 static gpgme_ctx_t create_gpgme_context (int for_smime)
332 err = gpgme_new (&ctx);
335 mutt_error ("error creating gpgme context: %s\n", gpgme_strerror (err));
342 err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
345 mutt_error ("error enabling CMS protocol: %s\n",
346 gpgme_strerror (err));
355 /* Create a new gpgme data object. This is a wrapper to die on
357 static gpgme_data_t create_gpgme_data (void)
362 err = gpgme_data_new (&data);
365 mutt_error ("error creating gpgme data object: %s\n",
366 gpgme_strerror (err));
373 /* Create a new GPGME Data object from the mail body A. With CONVERT
374 passed as true, the lines are converted to CR,LF if required.
375 Return NULL on error or the gpgme_data_t object on success. */
376 static gpgme_data_t body_to_data_object (BODY *a, int convert)
378 char tempfile[_POSIX_PATH_MAX];
383 mutt_mktemp (tempfile);
384 fptmp = safe_fopen (tempfile, "w+");
387 mutt_perror (tempfile);
391 mutt_write_mime_header (a, fptmp);
393 mutt_write_mime_body (a, fptmp);
398 unsigned char buf[1];
400 data = create_gpgme_data ();
402 while ((c = fgetc (fptmp)) != EOF)
408 if (c == '\n' && !hadcr)
411 gpgme_data_write (data, buf, 1);
416 /* FIXME: This is quite suboptimal */
418 gpgme_data_write (data, buf, 1);
421 gpgme_data_seek (data, 0, SEEK_SET);
426 err = gpgme_data_new_from_file (&data, tempfile, 1);
431 mutt_error ("error allocating data object: %s\n", gpgme_strerror (err));
438 /* Create a GPGME data object from the stream FP but limit the object
439 to LENGTH bytes starting at OFFSET bytes from the beginning of the
441 static gpgme_data_t file_to_data_object (FILE *fp, long offset, long length)
446 err = gpgme_data_new_from_filepart (&data, NULL, fp, offset, length);
449 mutt_error ("error allocating data object: %s\n", gpgme_strerror (err));
456 /* Write a GPGME data object to the stream FP. */
457 static int data_object_to_stream (gpgme_data_t data, FILE *fp)
463 err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1)
464 ? gpgme_error_from_errno (errno) : 0);
467 mutt_error ("error rewinding data object: %s\n", gpgme_strerror (err));
471 while ((nread = gpgme_data_read (data, buf, sizeof (buf))))
473 /* fixme: we are not really converting CRLF to LF but just
474 skipping CR. Doing it correctly needs a more complex logic */
475 for (p=buf; nread; p++, nread--)
483 mutt_perror ("[tempfile]");
489 mutt_error ("error reading data object: %s\n", strerror (errno));
495 /* Copy a data object to a newly created temporay file and return that
496 filename. Caller must free. With RET_FP not NULL, don't close the
497 stream but return it there. */
498 static char *data_object_to_tempfile (gpgme_data_t data, FILE **ret_fp)
501 char tempfile[_POSIX_PATH_MAX];
505 mutt_mktemp (tempfile);
506 fp = safe_fopen (tempfile, "w+");
509 mutt_perror (tempfile);
513 err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1)
514 ? gpgme_error_from_errno (errno) : 0);
519 while ((nread = gpgme_data_read (data, buf, sizeof (buf))))
521 if (fwrite (buf, nread, 1, fp) != 1)
523 mutt_perror (tempfile);
536 mutt_error ("error reading data object: %s\n", gpgme_strerror (err));
543 return safe_strdup (tempfile);
547 /* Create a GpgmeRecipientSet from the keys in the string KEYLIST.
548 The keys must be space delimited. */
549 static gpgme_key_t *create_recipient_set (const char *keylist,
550 gpgme_protocol_t protocol)
556 gpgme_key_t *rset = NULL;
557 unsigned int rset_n = 0;
558 gpgme_key_t key = NULL;
559 gpgme_ctx_t context = NULL;
561 err = gpgme_new (&context);
563 err = gpgme_set_protocol (context, protocol);
571 for (i=0; *s && *s != ' ' && i < sizeof(buf)-1;)
576 if (i>1 && buf[i-1] == '!')
578 /* The user selected to override the valididy of that
582 err = gpgme_get_key (context, buf, &key, 0);
584 key->uids->validity = GPGME_VALIDITY_FULL;
588 err = gpgme_get_key (context, buf, &key, 0);
592 safe_realloc (&rset, sizeof (*rset) * (rset_n + 1));
593 rset[rset_n++] = key;
597 mutt_error ("error adding recipient `%s': %s\n",
598 buf, gpgme_strerror (err));
606 /* NULL terminate. */
607 safe_realloc (&rset, sizeof (*rset) * (rset_n + 1));
608 rset[rset_n++] = NULL;
611 gpgme_release (context);
617 /* Make sure that the correct signer is set. Returns 0 on success. */
618 static int set_signer (gpgme_ctx_t ctx, int for_smime)
620 char *signid = for_smime ? SmimeDefaultKey: PgpSignAs;
623 gpgme_key_t key, key2;
625 if (!signid || !*signid)
628 listctx = create_gpgme_context (for_smime);
629 err = gpgme_op_keylist_start (listctx, signid, 1);
631 err = gpgme_op_keylist_next (listctx, &key);
634 gpgme_release (listctx);
635 mutt_error (_("secret key `%s' not found: %s\n"),
636 signid, gpgme_strerror (err));
639 err = gpgme_op_keylist_next (listctx, &key2);
642 gpgme_key_release (key);
643 gpgme_key_release (key2);
644 gpgme_release (listctx);
645 mutt_error (_("ambiguous specfication of secret key `%s'\n"),
649 gpgme_op_keylist_end (listctx);
650 gpgme_release (listctx);
652 gpgme_signers_clear (ctx);
653 err = gpgme_signers_add (ctx, key);
654 gpgme_key_release (key);
657 mutt_error (_("error setting secret key `%s': %s\n"),
658 signid, gpgme_strerror (err));
665 /* Encrypt the gpgme data object PLAINTEXT to the recipients in RSET
666 and return an allocated filename to a temporary file containing the
667 enciphered text. With USE_SMIME set to true, the smime backend is
668 used. With COMBINED_SIGNED a PGP message is signed and
669 encrypted. Returns NULL in case of error */
670 static char *encrypt_gpgme_object (gpgme_data_t plaintext, gpgme_key_t *rset,
671 int use_smime, int combined_signed)
675 gpgme_data_t ciphertext;
678 ctx = create_gpgme_context (use_smime);
680 gpgme_set_armor (ctx, 1);
682 ciphertext = create_gpgme_data ();
686 if (set_signer (ctx, use_smime))
688 gpgme_data_release (ciphertext);
692 err = gpgme_op_encrypt_sign (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST,
693 plaintext, ciphertext);
696 err = gpgme_op_encrypt (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST,
697 plaintext, ciphertext);
698 mutt_need_hard_redraw ();
701 mutt_error ("error encrypting data: %s\n", gpgme_strerror (err));
702 gpgme_data_release (ciphertext);
709 outfile = data_object_to_tempfile (ciphertext, NULL);
710 gpgme_data_release (ciphertext);
714 /* Find the "micalg" parameter from the last Gpgme operation on
715 context CTX. It is expected that this operation was a sign
716 operation. Return the algorithm name as a C string in buffer BUF
717 which must have been allocated by the caller with size BUFLEN.
718 Returns 0 on success or -1 in case of an error. The return string
719 is truncted to BUFLEN - 1. */
720 static int get_micalg (gpgme_ctx_t ctx, char *buf, size_t buflen)
722 gpgme_sign_result_t result = NULL;
723 const char *algorithm_name = NULL;
729 result = gpgme_op_sign_result (ctx);
732 algorithm_name = gpgme_hash_algo_name (result->signatures->hash_algo);
735 strncpy (buf, algorithm_name, buflen - 1);
743 static void print_time(time_t t, STATE *s)
747 setlocale (LC_TIME, "");
748 #ifdef HAVE_LANGINFO_D_T_FMT
749 strftime (p, sizeof (p), nl_langinfo (D_T_FMT), localtime (&t));
751 strftime (p, sizeof (p), "%c", localtime (&t));
753 setlocale (LC_TIME, "C");
754 state_attach_puts (p, s);
758 * Implementation of `sign_message'.
761 /* Sign the MESSAGE in body A either using OpenPGP or S/MIME when
762 USE_SMIME is passed as true. Returns the new body or NULL on
764 static BODY *sign_message (BODY *a, int use_smime)
771 gpgme_data_t message, signature;
773 convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */
775 message = body_to_data_object (a, 1);
778 signature = create_gpgme_data ();
780 ctx = create_gpgme_context (use_smime);
782 gpgme_set_armor (ctx, 1);
784 if (set_signer (ctx, use_smime))
786 gpgme_data_release (signature);
791 err = gpgme_op_sign (ctx, message, signature, GPGME_SIG_MODE_DETACH );
792 mutt_need_hard_redraw ();
793 gpgme_data_release (message);
796 gpgme_data_release (signature);
798 mutt_error ("error signing data: %s\n", gpgme_strerror (err));
802 sigfile = data_object_to_tempfile (signature, NULL);
803 gpgme_data_release (signature);
810 t = mutt_new_body ();
811 t->type = TYPEMULTIPART;
812 t->subtype = safe_strdup ("signed");
813 t->encoding = ENC7BIT;
815 t->disposition = DISPINLINE;
817 mutt_generate_boundary (&t->parameter);
818 mutt_set_parameter ("protocol",
819 use_smime? "application/pkcs7-signature"
820 : "application/pgp-signature",
822 /* Get the micalg from gpgme. Old gpgme versions don't support this
823 for S/MIME so we assume sha-1 in this case. */
824 if (!get_micalg (ctx, buf, sizeof buf))
825 mutt_set_parameter ("micalg", buf, &t->parameter);
827 mutt_set_parameter ("micalg", "sha1", &t->parameter);
833 t->parts->next = mutt_new_body ();
835 t->type = TYPEAPPLICATION;
838 t->subtype = safe_strdup ("pkcs7-signature");
839 mutt_set_parameter ("name", "smime.p7s", &t->parameter);
840 t->encoding = ENCBASE64;
842 t->disposition = DISPATTACH;
843 t->d_filename = safe_strdup ("smime.p7s");
847 t->subtype = safe_strdup ("pgp-signature");
849 t->disposition = DISPINLINE;
850 t->encoding = ENC7BIT;
852 t->filename = sigfile;
853 t->unlink = 1; /* ok to remove this file after sending. */
859 BODY *pgp_gpgme_sign_message (BODY *a)
861 return sign_message (a, 0);
864 BODY *smime_gpgme_sign_message (BODY *a)
866 return sign_message (a, 1);
870 * Implementation of `encrypt_message'.
873 /* Encrypt the mail body A to all keys given as space separated keyids
874 or fingerprints in KEYLIST and return the encrypted body. */
875 BODY *pgp_gpgme_encrypt_message (BODY *a, char *keylist, int sign)
877 char *outfile = NULL;
879 gpgme_key_t *rset = NULL;
880 gpgme_data_t plaintext;
882 rset = create_recipient_set (keylist, GPGME_PROTOCOL_OpenPGP);
888 plaintext = body_to_data_object (a, 0);
895 outfile = encrypt_gpgme_object (plaintext, rset, 0, sign);
896 gpgme_data_release (plaintext);
901 t = mutt_new_body ();
902 t->type = TYPEMULTIPART;
903 t->subtype = safe_strdup ("encrypted");
904 t->encoding = ENC7BIT;
906 t->disposition = DISPINLINE;
908 mutt_generate_boundary(&t->parameter);
909 mutt_set_parameter("protocol", "application/pgp-encrypted", &t->parameter);
911 t->parts = mutt_new_body ();
912 t->parts->type = TYPEAPPLICATION;
913 t->parts->subtype = safe_strdup ("pgp-encrypted");
914 t->parts->encoding = ENC7BIT;
916 t->parts->next = mutt_new_body ();
917 t->parts->next->type = TYPEAPPLICATION;
918 t->parts->next->subtype = safe_strdup ("octet-stream");
919 t->parts->next->encoding = ENC7BIT;
920 t->parts->next->filename = outfile;
921 t->parts->next->use_disp = 1;
922 t->parts->next->disposition = DISPINLINE;
923 t->parts->next->unlink = 1; /* delete after sending the message */
924 t->parts->next->d_filename = safe_strdup ("msg.asc"); /* non pgp/mime
931 * Implementation of `smime_build_smime_entity'.
934 /* Encrypt the mail body A to all keys given as space separated
935 fingerprints in KEYLIST and return the S/MIME encrypted body. */
936 BODY *smime_gpgme_build_smime_entity (BODY *a, char *keylist)
938 char *outfile = NULL;
940 gpgme_key_t *rset = NULL;
941 gpgme_data_t plaintext;
943 rset = create_recipient_set (keylist, GPGME_PROTOCOL_CMS);
947 plaintext = body_to_data_object (a, 0);
954 outfile = encrypt_gpgme_object (plaintext, rset, 1, 0);
955 gpgme_data_release (plaintext);
960 t = mutt_new_body ();
961 t->type = TYPEAPPLICATION;
962 t->subtype = safe_strdup ("pkcs7-mime");
963 mutt_set_parameter ("name", "smime.p7m", &t->parameter);
964 mutt_set_parameter ("smime-type", "enveloped-data", &t->parameter);
965 t->encoding = ENCBASE64; /* The output of OpenSSL SHOULD be binary */
967 t->disposition = DISPATTACH;
968 t->d_filename = safe_strdup ("smime.p7m");
969 t->filename = outfile;
970 t->unlink = 1; /*delete after sending the message */
979 * Implementation of `verify_one'.
982 /* Display the common attributes of the signature summary SUM.
983 Return 1 if there is is a severe warning.
985 static int show_sig_summary (unsigned long sum,
986 gpgme_ctx_t ctx, gpgme_key_t key, int idx,
991 if ((sum & GPGME_SIGSUM_KEY_REVOKED))
993 state_attach_puts (_("Warning: One of the keys has been revoked\n"),s);
997 if ((sum & GPGME_SIGSUM_KEY_EXPIRED))
999 time_t at = key->subkeys->expires ? key->subkeys->expires : 0;
1002 state_attach_puts (_("Warning: The key used to create the "
1003 "signature expired at: "), s);
1004 print_time (at , s);
1005 state_attach_puts ("\n", s);
1008 state_attach_puts (_("Warning: At least one certification key "
1009 "has expired\n"), s);
1012 if ((sum & GPGME_SIGSUM_SIG_EXPIRED))
1014 gpgme_verify_result_t result;
1015 gpgme_signature_t sig;
1018 result = gpgme_op_verify_result (ctx);
1020 for (sig = result->signatures, i = 0; sig && (i < idx);
1021 sig = sig->next, i++)
1024 state_attach_puts (_("Warning: The signature expired at: "), s);
1025 print_time (sig ? sig->exp_timestamp : 0, s);
1026 state_attach_puts ("\n", s);
1029 if ((sum & GPGME_SIGSUM_KEY_MISSING))
1030 state_attach_puts (_("Can't verify due to a missing "
1031 "key or certificate\n"), s);
1033 if ((sum & GPGME_SIGSUM_CRL_MISSING))
1035 state_attach_puts (_("The CRL is not available\n"), s);
1039 if ((sum & GPGME_SIGSUM_CRL_TOO_OLD))
1041 state_attach_puts (_("Available CRL is too old\n"), s);
1045 if ((sum & GPGME_SIGSUM_BAD_POLICY))
1046 state_attach_puts (_("A policy requirement was not met\n"), s);
1048 if ((sum & GPGME_SIGSUM_SYS_ERROR))
1050 const char *t0 = NULL, *t1 = NULL;
1051 gpgme_verify_result_t result;
1052 gpgme_signature_t sig;
1055 state_attach_puts (_("A system error occured"), s );
1057 /* Try to figure out some more detailed system error information. */
1058 result = gpgme_op_verify_result (ctx);
1059 for (sig = result->signatures, i = 0; sig && (i < idx);
1060 sig = sig->next, i++)
1065 t1 = sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
1070 state_attach_puts (": ", s);
1072 state_attach_puts (t0, s);
1073 if (t1 && !(t0 && !strcmp (t0, t1)))
1076 state_attach_puts (",", s);
1077 state_attach_puts (t1, s);
1080 state_attach_puts ("\n", s);
1087 static void show_fingerprint (gpgme_key_t key, STATE *state)
1092 const char *prefix = _("Fingerprint: ");
1096 s = key->subkeys ? key->subkeys->fpr : NULL;
1099 is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
1101 buf = safe_malloc ( strlen (prefix) + strlen(s) * 4 + 2 );
1102 strcpy (buf, prefix); /* __STRCPY_CHECKED__ */
1103 p = buf + strlen (buf);
1104 if (is_pgp && strlen (s) == 40)
1105 { /* PGP v4 style formatted. */
1106 for (i=0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++)
1119 for (i=0; *s && s[1] && s[2]; s += 2, i++)
1123 *p++ = is_pgp? ' ':':';
1124 if (is_pgp && i == 7)
1129 /* just in case print remaining odd digits */
1134 state_attach_puts (buf, state);
1138 /* Show the valididy of a key used for one signature. */
1139 static void show_one_sig_validity (gpgme_ctx_t ctx, int idx, STATE *s)
1141 gpgme_verify_result_t result = NULL;
1142 gpgme_signature_t sig = NULL;
1143 const char *txt = NULL;
1145 result = gpgme_op_verify_result (ctx);
1147 for (sig = result->signatures; sig && (idx > 0); sig = sig->next, idx--);
1149 switch (sig ? sig->validity : 0)
1151 case GPGME_VALIDITY_UNKNOWN:
1152 txt = _("WARNING: We have NO indication whether "
1153 "the key belongs to the person named "
1154 "as shown above\n");
1156 case GPGME_VALIDITY_UNDEFINED:
1158 case GPGME_VALIDITY_NEVER:
1159 txt = _("WARNING: The key does NOT BELONG to "
1160 "the person named as shown above\n");
1162 case GPGME_VALIDITY_MARGINAL:
1163 txt = _("WARNING: It is NOT certain that the key "
1164 "belongs to the person named as shown above\n");
1166 case GPGME_VALIDITY_FULL:
1167 case GPGME_VALIDITY_ULTIMATE:
1172 state_attach_puts (txt, s);
1175 /* Show information about one signature. This fucntion is called with
1176 the context CTX of a sucessful verification operation and the
1177 enumerator IDX which should start at 0 and incremete for each
1180 Return values are: 0 for normal procession, 1 for a bad signature,
1181 2 for a signature with a warning or -1 for no more signature. */
1182 static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE *s)
1185 const char *fpr, *uid;
1186 gpgme_key_t key = NULL;
1187 int i, anybad = 0, anywarn = 0;
1189 gpgme_user_id_t uids = NULL;
1190 gpgme_verify_result_t result;
1191 gpgme_signature_t sig;
1192 gpgme_error_t err = GPG_ERR_NO_ERROR;
1194 result = gpgme_op_verify_result (ctx);
1197 /* FIXME: this code should use a static variable and remember
1198 the current position in the list of signatures, IMHO.
1201 for (i = 0, sig = result->signatures; sig && (i < idx);
1202 i++, sig = sig->next)
1205 return -1; /* Signature not found. */
1209 gpgme_key_release (signature_key);
1210 signature_key = NULL;
1213 created = sig->timestamp;
1217 if (gpg_err_code (sig->status) != GPG_ERR_NO_ERROR)
1220 err = gpgme_get_key (ctx, fpr, &key, 0); /* secret key? */
1223 uid = (key->uids && key->uids->uid) ? key->uids->uid : "[?]";
1224 if (! signature_key)
1225 signature_key = key;
1229 key = NULL; /* Old gpgme versions did not set KEY to NULL on
1230 error. Do it here to avoid a double free. */
1234 if (!s || !s->fpout || !(s->flags & M_DISPLAY))
1235 ; /* No state information so no way to print anything. */
1238 state_attach_puts (_("Error getting key information: "), s);
1239 state_attach_puts ( gpg_strerror (err), s );
1240 state_attach_puts ("\n", s);
1243 else if ((sum & GPGME_SIGSUM_GREEN))
1245 state_attach_puts (_("Good signature from: "), s);
1246 state_attach_puts (uid, s);
1247 state_attach_puts ("\n", s);
1248 for (i = 1, uids = key->uids; uids; i++, uids = uids->next)
1251 /* Skip primary UID. */
1255 state_attach_puts (_(" aka: "), s);
1256 state_attach_puts (uids->uid, s);
1257 state_attach_puts ("\n", s);
1259 state_attach_puts (_(" created: "), s);
1260 print_time (created, s);
1261 state_attach_puts ("\n", s);
1262 if (show_sig_summary (sum, ctx, key, idx, s))
1264 show_one_sig_validity (ctx, idx, s);
1266 else if ((sum & GPGME_SIGSUM_RED))
1268 state_attach_puts (_("*BAD* signature claimed to be from: "), s);
1269 state_attach_puts (uid, s);
1270 state_attach_puts ("\n", s);
1271 show_sig_summary (sum, ctx, key, idx, s);
1273 else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP))
1274 { /* We can't decide (yellow) but this is a PGP key with a good
1275 signature, so we display what a PGP user expects: The name,
1276 fingerprint and the key validity (which is neither fully or
1278 state_attach_puts (_("Good signature from: "), s);
1279 state_attach_puts (uid, s);
1280 state_attach_puts ("\n", s);
1281 state_attach_puts (_(" created: "), s);
1282 print_time (created, s);
1283 state_attach_puts ("\n", s);
1284 show_one_sig_validity (ctx, idx, s);
1285 show_fingerprint (key,s);
1286 if (show_sig_summary (sum, ctx, key, idx, s))
1289 else /* can't decide (yellow) */
1291 state_attach_puts (_("Error checking signature"), s);
1292 state_attach_puts ("\n", s);
1293 show_sig_summary (sum, ctx, key, idx, s);
1296 if (key != signature_key)
1297 gpgme_key_release (key);
1300 return anybad ? 1 : anywarn ? 2 : 0;
1303 /* Do the actual verification step. With IS_SMIME set to true we
1304 assume S/MIME (surprise!) */
1305 static int verify_one (BODY *sigbdy, STATE *s,
1306 const char *tempfile, int is_smime)
1312 gpgme_data_t signature, message;
1314 signature = file_to_data_object (s->fpin, sigbdy->offset, sigbdy->length);
1318 /* We need to tell gpgme about the encoding because the backend can't
1319 auto-detect plain base-64 encoding which is used by S/MIME. */
1321 gpgme_data_set_encoding (signature, GPGME_DATA_ENCODING_BASE64);
1323 err = gpgme_data_new_from_file (&message, tempfile, 1);
1326 gpgme_data_release (signature);
1327 mutt_error ("error allocating data object: %s\n", gpgme_strerror (err));
1330 ctx = create_gpgme_context (is_smime);
1332 /* Note: We don't need a current time output because GPGME avoids
1333 such an attack by separating the meta information from the
1335 state_attach_puts (_("[-- Begin signature information --]\n"), s);
1337 err = gpgme_op_verify (ctx, signature, message, NULL);
1338 mutt_need_hard_redraw ();
1343 snprintf (buf, sizeof(buf)-1,
1344 _("Error: verification failed: %s\n"),
1345 gpgme_strerror (err));
1346 state_attach_puts (buf, s);
1349 { /* Verification succeeded, see what the result is. */
1355 gpgme_key_release (signature_key);
1356 signature_key = NULL;
1359 for(idx=0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++)
1372 gpgme_verify_result_t result;
1373 gpgme_sig_notation_t notation;
1374 gpgme_signature_t signature;
1376 result = gpgme_op_verify_result (ctx);
1379 for (signature = result->signatures; signature;
1380 signature = signature->next)
1382 if (signature->notations)
1384 state_attach_puts ("*** Begin Notation (signature by: ", s);
1385 state_attach_puts (signature->fpr, s);
1386 state_attach_puts (") ***\n", s);
1387 for (notation = signature->notations; notation;
1388 notation = notation->next)
1392 state_attach_puts (notation->name, s);
1393 state_attach_puts ("=", s);
1395 if (notation->value)
1397 state_attach_puts (notation->value, s);
1398 if (!(*notation->value
1399 && (notation->value[strlen (notation->value)-1]=='\n')))
1400 state_attach_puts ("\n", s);
1403 state_attach_puts ("*** End Notation ***\n", s);
1409 gpgme_release (ctx);
1411 state_attach_puts (_("[-- End signature information --]\n\n"), s);
1412 dprint (1, (debugfile, "verify_one: returning %d.\n", badsig));
1414 return badsig? 1: anywarn? 2 : 0;
1417 int pgp_gpgme_verify_one (BODY *sigbdy, STATE *s, const char *tempfile)
1419 return verify_one (sigbdy, s, tempfile, 0);
1422 int smime_gpgme_verify_one (BODY *sigbdy, STATE *s, const char *tempfile)
1424 return verify_one (sigbdy, s, tempfile, 1);
1428 * Implementation of `decrypt_part'.
1431 /* Decrypt a PGP or SMIME message (depending on the boolean flag
1432 IS_SMIME) with body A described further by state S. Write
1433 plaintext out to file FPOUT and return a new body. For PGP returns
1434 a flag in R_IS_SIGNED to indicate whether this is a combined
1435 encrypted and signed message, for S/MIME it returns true when it is
1436 not a encrypted but a signed message. */
1437 static BODY *decrypt_part (BODY *a, STATE *s, FILE *fpout, int is_smime,
1444 gpgme_data_t ciphertext, plaintext;
1445 int maybe_signed = 0;
1452 ctx = create_gpgme_context (is_smime);
1455 /* Make a data object from the body, create context etc. */
1456 ciphertext = file_to_data_object (s->fpin, a->offset, a->length);
1459 plaintext = create_gpgme_data ();
1461 /* Do the decryption or the verification in case of the S/MIME hack. */
1462 if ((! is_smime) || maybe_signed)
1465 err = gpgme_op_decrypt_verify (ctx, ciphertext, plaintext);
1466 else if (maybe_signed)
1467 err = gpgme_op_verify (ctx, ciphertext, NULL, plaintext);
1470 /* Check wether signatures have been verified. */
1471 gpgme_verify_result_t verify_result = gpgme_op_verify_result (ctx);
1472 if (verify_result->signatures)
1477 err = gpgme_op_decrypt (ctx, ciphertext, plaintext);
1478 gpgme_data_release (ciphertext);
1481 if (is_smime && !maybe_signed
1482 && gpg_err_code (err) == GPG_ERR_NO_DATA)
1484 /* Check whether this might be a signed message despite what
1485 the mime header told us. Retry then. gpgsm returns the
1486 error information "unsupported Algorithm '?'" but gpgme
1487 will not store this unknown algorithm, thus we test that
1488 it has not been set. */
1489 gpgme_decrypt_result_t result;
1491 result = gpgme_op_decrypt_result (ctx);
1492 if (!result->unsupported_algorithm)
1495 gpgme_data_release (plaintext);
1499 mutt_need_hard_redraw ();
1500 if ((s->flags & M_DISPLAY))
1504 snprintf (buf, sizeof(buf)-1,
1505 _("[-- Error: decryption failed: %s --]\n\n"),
1506 gpgme_strerror (err));
1507 state_attach_puts (buf, s);
1509 gpgme_data_release (plaintext);
1510 gpgme_release (ctx);
1513 mutt_need_hard_redraw ();
1515 /* Read the output from GPGME, and make sure to change CRLF to LF,
1516 otherwise read_mime_header has a hard time parsing the message. */
1517 if (data_object_to_stream (plaintext, fpout))
1519 gpgme_data_release (plaintext);
1520 gpgme_release (ctx);
1523 gpgme_data_release (plaintext);
1525 a->is_signed_data = 0;
1532 a->is_signed_data = 1;
1534 *r_is_signed = -1; /* A signature exists. */
1536 if ((s->flags & M_DISPLAY))
1537 state_attach_puts (_("[-- Begin signature "
1538 "information --]\n"), s);
1539 for(idx = 0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++)
1546 if (!anybad && idx && r_is_signed && *r_is_signed)
1547 *r_is_signed = anywarn? 2:1; /* Good signature. */
1549 if ((s->flags & M_DISPLAY))
1550 state_attach_puts (_("[-- End signature "
1551 "information --]\n\n"), s);
1553 gpgme_release (ctx); ctx = NULL;
1557 tattach = mutt_read_mime_header (fpout, 0);
1561 * Need to set the length of this body part.
1563 fstat (fileno (fpout), &info);
1564 tattach->length = info.st_size - tattach->offset;
1566 tattach->warnsig = anywarn;
1568 /* See if we need to recurse on this MIME part. */
1569 mutt_parse_part (fpout, tattach);
1575 /* Decrypt a PGP/MIME message in FPIN and B and return a new body and
1576 the stream in CUR and FPOUT. Returns 0 on success. */
1577 int pgp_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur)
1579 char tempfile[_POSIX_PATH_MAX];
1581 BODY *first_part = b;
1584 first_part->goodsig = 0;
1585 first_part->warnsig = 0;
1587 if(!mutt_is_multipart_encrypted(b))
1590 if(!b->parts || !b->parts->next)
1595 memset (&s, 0, sizeof (s));
1597 mutt_mktemp (tempfile);
1598 if (!(*fpout = safe_fopen (tempfile, "w+")))
1600 mutt_perror (tempfile);
1605 *cur = decrypt_part (b, &s, *fpout, 0, &is_signed);
1608 first_part->goodsig = 1;
1614 /* Decrypt a S/MIME message in FPIN and B and return a new body and
1615 the stream in CUR and FPOUT. Returns 0 on success. */
1616 int smime_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur)
1618 char tempfile[_POSIX_PATH_MAX];
1622 long saved_b_offset;
1623 size_t saved_b_length;
1626 if (!mutt_is_application_smime (b))
1632 /* Decode the body - we need to pass binary CMS to the
1633 backend. The backend allows for Base64 encoded data but it does
1634 not allow for QP which I have seen in some messages. So better
1636 saved_b_type = b->type;
1637 saved_b_offset = b->offset;
1638 saved_b_length = b->length;
1639 memset (&s, 0, sizeof (s));
1641 fseek (s.fpin, b->offset, 0);
1642 mutt_mktemp (tempfile);
1643 if (!(tmpfp = safe_fopen (tempfile, "w+")))
1645 mutt_perror (tempfile);
1648 mutt_unlink (tempfile);
1651 mutt_decode_attachment (b, &s);
1653 b->length = ftell (s.fpout);
1657 memset (&s, 0, sizeof (s));
1660 mutt_mktemp (tempfile);
1661 if (!(*fpout = safe_fopen (tempfile, "w+")))
1663 mutt_perror (tempfile);
1666 mutt_unlink (tempfile);
1668 *cur = decrypt_part (b, &s, *fpout, 1, &is_signed);
1670 (*cur)->goodsig = is_signed > 0;
1671 b->type = saved_b_type;
1672 b->length = saved_b_length;
1673 b->offset = saved_b_offset;
1676 if (*cur && !is_signed && !(*cur)->parts && mutt_is_application_smime (*cur))
1678 /* Assume that this is a opaque signed s/mime message. This is
1679 an ugly way of doing it but we have anyway a problem with
1680 arbitrary encoded S/MIME messages: Only the outer part may be
1681 encrypted. The entire mime parsing should be revamped,
1682 probably by keeping the temportary files so that we don't
1683 need to decrypt them all the time. Inner parts of an
1684 encrypted part can then pint into this file and tehre won't
1685 never be a need to decrypt again. This needs a partial
1686 rewrite of the MIME engine. */
1690 saved_b_type = bb->type;
1691 saved_b_offset = bb->offset;
1692 saved_b_length = bb->length;
1693 memset (&s, 0, sizeof (s));
1695 fseek (s.fpin, bb->offset, 0);
1696 mutt_mktemp (tempfile);
1697 if (!(tmpfp = safe_fopen (tempfile, "w+")))
1699 mutt_perror (tempfile);
1702 mutt_unlink (tempfile);
1705 mutt_decode_attachment (bb, &s);
1707 bb->length = ftell (s.fpout);
1712 memset (&s, 0, sizeof (s));
1715 mutt_mktemp (tempfile);
1716 if (!(*fpout = safe_fopen (tempfile, "w+")))
1718 mutt_perror (tempfile);
1721 mutt_unlink (tempfile);
1723 tmp_b = decrypt_part (bb, &s, *fpout, 1, &is_signed);
1725 tmp_b->goodsig = is_signed > 0;
1726 bb->type = saved_b_type;
1727 bb->length = saved_b_length;
1728 bb->offset = saved_b_offset;
1731 mutt_free_body (cur);
1739 * Implementation of `pgp_check_traditional'.
1742 static int pgp_check_traditional_one_body (FILE *fp, BODY *b, int tagged_only)
1744 char tempfile[_POSIX_PATH_MAX];
1745 char buf[HUGE_STRING];
1751 if (b->type != TYPETEXT)
1754 if (tagged_only && !b->tagged)
1757 mutt_mktemp (tempfile);
1758 if (mutt_decode_save_attachment (fp, b, tempfile, 0, 0) != 0)
1764 if ((tfp = fopen (tempfile, "r")) == NULL)
1770 while (fgets (buf, sizeof (buf), tfp))
1772 if (!mutt_strncmp ("-----BEGIN PGP ", buf, 15))
1774 if (!mutt_strcmp ("MESSAGE-----\n", buf + 15))
1776 else if (!mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15))
1786 /* fix the content type */
1788 mutt_set_parameter ("format", "fixed", &b->parameter);
1789 mutt_set_parameter ("x-action", enc ? "pgp-encrypted" : "pgp-signed",
1795 int pgp_gpgme_check_traditional (FILE *fp, BODY *b, int tagged_only)
1799 for (; b; b = b->next)
1801 if (is_multipart (b))
1802 rv = (pgp_gpgme_check_traditional (fp, b->parts, tagged_only) || rv);
1803 else if (b->type == TYPETEXT)
1805 if ((r = mutt_is_application_pgp (b)))
1808 rv = (pgp_check_traditional_one_body (fp, b, tagged_only) || rv);
1816 * Implementation of `application_handler'.
1820 Copy a clearsigned message, and strip the signature and PGP's
1823 XXX - charset handling: We assume that it is safe to do
1824 character set decoding first, dash decoding second here, while
1825 we do it the other way around in the main handler.
1827 (Note that we aren't worse than Outlook & Cie in this, and also
1828 note that we can successfully handle anything produced by any
1829 existing versions of mutt.) */
1831 static void copy_clearsigned (gpgme_data_t data, STATE *s, char *charset)
1833 char buf[HUGE_STRING];
1834 short complete, armor_header;
1839 fname = data_object_to_tempfile (data, &fp);
1845 fc = fgetconv_open (fp, charset, Charset, M_ICONV_HOOK_FROM);
1847 for (complete = 1, armor_header = 1;
1848 fgetconvs (buf, sizeof (buf), fc) != NULL;
1849 complete = strchr (buf, '\n') != NULL)
1854 state_puts (buf, s);
1858 if (!mutt_strcmp (buf, "-----BEGIN PGP SIGNATURE-----\n"))
1869 state_puts (s->prefix, s);
1871 if (buf[0] == '-' && buf[1] == ' ')
1872 state_puts (buf + 2, s);
1874 state_puts (buf, s);
1877 fgetconv_close (&fc);
1882 /* Support for classic_application/pgp */
1883 void pgp_gpgme_application_handler (BODY *m, STATE *s)
1885 int needpass = -1, pgp_keyblock = 0;
1888 long bytes, last_pos, offset;
1889 char buf[HUGE_STRING];
1890 FILE *pgpout = NULL;
1893 gpgme_data_t armored_data = NULL;
1895 short maybe_goodsig = 1;
1896 short have_any_sigs = 0;
1898 char body_charset[STRING]; /* Only used for clearsigned messages. */
1900 dprint (2, (debugfile, "Entering pgp_application_pgp handler\n"));
1902 /* For clearsigned messages we won't be able to get a character set
1903 but we know that this may only be text thus we assume Latin-1
1905 if (!mutt_get_body_charset (body_charset, sizeof (body_charset), m))
1906 strfcpy (body_charset, "iso-8859-1", sizeof body_charset);
1908 fseek (s->fpin, m->offset, 0);
1909 last_pos = m->offset;
1911 for (bytes = m->length; bytes > 0;)
1913 if (fgets (buf, sizeof (buf), s->fpin) == NULL)
1916 offset = ftell (s->fpin);
1917 bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */
1920 if (!mutt_strncmp ("-----BEGIN PGP ", buf, 15))
1923 start_pos = last_pos;
1925 if (!mutt_strcmp ("MESSAGE-----\n", buf + 15))
1927 else if (!mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15))
1932 else if (!option (OPTDONTHANDLEPGPKEYS) &&
1933 !mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15))
1940 /* XXX - we may wish to recode here */
1942 state_puts (s->prefix, s);
1943 state_puts (buf, s);
1947 have_any_sigs = (have_any_sigs
1948 || (clearsign && (s->flags & M_VERIFY)));
1950 /* Copy PGP material to an data container */
1951 armored_data = create_gpgme_data ();
1952 gpgme_data_write (armored_data, buf, strlen (buf));
1953 while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL)
1955 offset = ftell (s->fpin);
1956 bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf)*/
1959 gpgme_data_write (armored_data, buf, strlen (buf));
1962 && !mutt_strcmp ("-----END PGP MESSAGE-----\n", buf))
1964 && (!mutt_strcmp ("-----END PGP SIGNATURE-----\n", buf)
1966 "-----END PGP PUBLIC KEY BLOCK-----\n",buf))))
1970 /* Invoke PGP if needed */
1971 if (!clearsign || (s->flags & M_VERIFY))
1973 unsigned int sig_stat = 0;
1974 gpgme_data_t plaintext;
1977 plaintext = create_gpgme_data ();
1978 ctx = create_gpgme_context (0);
1981 err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
1984 err = gpgme_op_decrypt_verify (ctx, armored_data, plaintext);
1985 if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1987 /* Decrypt verify can't handle signed only messages. */
1988 err = (gpgme_data_seek (armored_data, 0, SEEK_SET) == -1)
1989 ? gpgme_error_from_errno (errno) : 0;
1990 /* Must release plaintext so that we supply an
1991 uninitialized object. */
1992 gpgme_data_release (plaintext);
1993 plaintext = create_gpgme_data ();
1994 err = gpgme_op_verify (ctx, armored_data,
2003 snprintf (errbuf, sizeof(errbuf)-1,
2004 _("Error: decryption/verification failed: %s\n"),
2005 gpgme_strerror (err));
2006 state_attach_puts (errbuf, s);
2009 { /* Decryption/Verification succeeded */
2013 /* Check wether signatures have been verified. */
2014 gpgme_verify_result_t verify_result;
2016 verify_result = gpgme_op_verify_result (ctx);
2017 if (verify_result->signatures)
2023 if ((s->flags & M_DISPLAY) && sig_stat)
2029 state_attach_puts (_("[-- Begin signature "
2030 "information --]\n"), s);
2033 (res = show_one_sig_status (ctx, idx, s)) != -1;
2044 state_attach_puts (_("[-- End signature "
2045 "information --]\n\n"), s);
2048 tmpfname = data_object_to_tempfile (plaintext, &pgpout);
2052 state_attach_puts (_("Error: copy data failed\n"), s);
2060 gpgme_release (ctx);
2064 * Now, copy cleartext to the screen. NOTE - we expect that PGP
2065 * outputs utf-8 cleartext. This may not always be true, but it
2066 * seems to be a reasonable guess.
2069 if(s->flags & M_DISPLAY)
2072 state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s);
2073 else if (pgp_keyblock)
2074 state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"),
2077 state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"),
2083 copy_clearsigned (armored_data, s, body_charset);
2090 fc = fgetconv_open (pgpout, "utf-8", Charset, 0);
2091 while ((c = fgetconv (fc)) != EOF)
2094 if (c == '\n' && s->prefix)
2095 state_puts (s->prefix, s);
2097 fgetconv_close (&fc);
2100 if (s->flags & M_DISPLAY)
2102 state_putc ('\n', s);
2104 state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
2105 else if (pgp_keyblock)
2106 state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
2108 state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
2113 safe_fclose (&pgpout);
2118 /* XXX - we may wish to recode here */
2120 state_puts (s->prefix, s);
2121 state_puts (buf, s);
2125 m->goodsig = (maybe_goodsig && have_any_sigs);
2129 state_attach_puts (_("[-- Error: could not find beginning"
2130 " of PGP message! --]\n\n"), s);
2133 dprint (2, (debugfile, "Leaving pgp_application_pgp handler\n"));
2137 * Implementation of `encrypted_handler'.
2140 /* MIME handler for pgp/mime encrypted messages. */
2141 void pgp_gpgme_encrypted_handler (BODY *a, STATE *s)
2143 char tempfile[_POSIX_PATH_MAX];
2146 BODY *orig_body = a;
2149 dprint (2, (debugfile, "Entering pgp_encrypted handler\n"));
2151 if (!a || a->type != TYPEAPPLICATION || !a->subtype
2152 || ascii_strcasecmp ("pgp-encrypted", a->subtype)
2153 || !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype
2154 || ascii_strcasecmp ("octet-stream", a->next->subtype) )
2156 if (s->flags & M_DISPLAY)
2157 state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
2162 /* Move forward to the application/pgp-encrypted body. */
2165 mutt_mktemp (tempfile);
2166 if (!(fpout = safe_fopen (tempfile, "w+")))
2168 if (s->flags & M_DISPLAY)
2169 state_attach_puts (_("[-- Error: could not create temporary file! "
2174 tattach = decrypt_part (a, s, fpout, 0, &is_signed);
2177 tattach->goodsig = is_signed > 0;
2179 if (s->flags & M_DISPLAY)
2180 state_attach_puts (is_signed?
2181 _("[-- The following data is PGP/MIME signed and encrypted --]\n\n"):
2182 _("[-- The following data is PGP/MIME encrypted --]\n\n"),
2186 FILE *savefp = s->fpin;
2188 mutt_body_handler (tattach, s);
2193 * if a multipart/signed is the _only_ sub-part of a
2194 * multipart/encrypted, cache signature verification
2197 if (mutt_is_multipart_signed (tattach) && !tattach->next)
2198 orig_body->goodsig |= tattach->goodsig;
2200 if (s->flags & M_DISPLAY)
2202 state_puts ("\n", s);
2203 state_attach_puts (is_signed?
2204 _("[-- End of PGP/MIME signed and encrypted data --]\n"):
2205 _("[-- End of PGP/MIME encrypted data --]\n"),
2209 mutt_free_body (&tattach);
2213 mutt_unlink(tempfile);
2214 dprint (2, (debugfile, "Leaving pgp_encrypted handler\n"));
2217 /* Support for application/smime */
2218 void smime_gpgme_application_handler (BODY *a, STATE *s)
2220 char tempfile[_POSIX_PATH_MAX];
2226 dprint (2, (debugfile, "Entering smime_encrypted handler\n"));
2229 mutt_mktemp (tempfile);
2230 if (!(fpout = safe_fopen (tempfile, "w+")))
2232 if (s->flags & M_DISPLAY)
2233 state_attach_puts (_("[-- Error: could not create temporary file! "
2238 tattach = decrypt_part (a, s, fpout, 1, &is_signed);
2241 tattach->goodsig = is_signed > 0;
2243 if (s->flags & M_DISPLAY)
2244 state_attach_puts (is_signed?
2245 _("[-- The following data is S/MIME signed --]\n\n"):
2246 _("[-- The following data is S/MIME encrypted --]\n\n"),
2250 FILE *savefp = s->fpin;
2252 mutt_body_handler (tattach, s);
2257 * if a multipart/signed is the _only_ sub-part of a
2258 * multipart/encrypted, cache signature verification
2261 if (mutt_is_multipart_signed (tattach) && !tattach->next)
2263 if (!(a->goodsig = tattach->goodsig))
2264 a->warnsig = tattach->warnsig;
2266 else if (tattach->goodsig)
2269 a->warnsig = tattach->warnsig;
2272 if (s->flags & M_DISPLAY)
2274 state_puts ("\n", s);
2275 state_attach_puts (is_signed?
2276 _("[-- End of S/MIME signed data --]\n"):
2277 _("[-- End of S/MIME encrypted data --]\n"),
2281 mutt_free_body (&tattach);
2285 mutt_unlink(tempfile);
2286 dprint (2, (debugfile, "Leaving smime_encrypted handler\n"));
2291 * Format an entry on the CRYPT key selection menu.
2294 * %k key id %K key id of the principal key
2296 * %a algorithm %A algorithm of the princ. key
2297 * %l length %L length of the princ. key
2298 * %f flags %F flags of the princ. key
2299 * %c capabilities %C capabilities of the princ. key
2300 * %t trust/validity of the key-uid association
2302 * %[...] date of key using strftime(3)
2305 static const char *crypt_entry_fmt (char *dest,
2310 const char *ifstring,
2311 const char *elsestring,
2316 crypt_entry_t *entry;
2319 int optional = (flags & M_FORMAT_OPTIONAL);
2320 const char *s = NULL;
2323 entry = (crypt_entry_t *) data;
2326 /* if (isupper ((unsigned char) op)) */
2329 kflags = (key->flags /*| (pkey->flags & KEYFLAG_RESTRICTIONS)
2332 switch (ascii_tolower (op))
2337 char buf2[SHORT_STRING], *p;
2354 while (len > 0 && *cp != ']')
2366 break; /* not enough space */
2377 if (do_locales && Locale)
2378 setlocale (LC_TIME, Locale);
2383 if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
2384 tt = key->kobj->subkeys->timestamp;
2386 tm = localtime (&tt);
2388 strftime (buf2, sizeof (buf2), dest, tm);
2391 setlocale (LC_TIME, "C");
2393 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2394 snprintf (dest, destlen, fmt, buf2);
2402 snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
2403 snprintf (dest, destlen, fmt, entry->num);
2409 /* fixme: we need a way to distinguish between main and subkeys.
2410 Store the idx in entry? */
2411 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2412 snprintf (dest, destlen, fmt, crypt_keyid (key));
2418 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2419 snprintf (dest, destlen, fmt, key->uid);
2425 snprintf (fmt, sizeof (fmt), "%%%s.3s", prefix);
2426 if (key->kobj->subkeys)
2427 s = gpgme_pubkey_algo_name (key->kobj->subkeys->pubkey_algo);
2430 snprintf (dest, destlen, fmt, s);
2436 snprintf (fmt, sizeof (fmt), "%%%slu", prefix);
2437 if (key->kobj->subkeys)
2438 val = key->kobj->subkeys->length;
2441 snprintf (dest, destlen, fmt, val);
2447 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2448 snprintf (dest, destlen, fmt, crypt_flags (kflags));
2450 else if (!(kflags & (KEYFLAG_RESTRICTIONS)))
2456 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2457 snprintf (dest, destlen, fmt, crypt_key_abilities (kflags));
2459 else if (!(kflags & (KEYFLAG_ABILITIES)))
2463 if ((kflags & KEYFLAG_ISX509))
2467 gpgme_user_id_t uid = NULL;
2470 for (i = 0, uid = key->kobj->uids; uid && (i < key->idx);
2471 i++, uid = uid->next)
2474 switch (uid->validity)
2476 case GPGME_VALIDITY_UNDEFINED:
2479 case GPGME_VALIDITY_NEVER:
2482 case GPGME_VALIDITY_MARGINAL:
2485 case GPGME_VALIDITY_FULL:
2488 case GPGME_VALIDITY_ULTIMATE:
2491 case GPGME_VALIDITY_UNKNOWN:
2497 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2498 snprintf (dest, destlen, fmt, s? *s: 'B');
2501 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2502 snprintf (dest, destlen, fmt,
2503 gpgme_get_protocol_name (key->kobj->protocol));
2511 mutt_FormatString (dest, destlen, ifstring, mutt_attach_fmt, data, 0);
2512 else if (flags & M_FORMAT_OPTIONAL)
2513 mutt_FormatString (dest, destlen, elsestring, mutt_attach_fmt, data, 0);
2517 /* Used by the display fucntion to format a line. */
2518 static void crypt_entry (char *s, size_t l, MUTTMENU * menu, int num)
2520 crypt_key_t **key_table = (crypt_key_t **) menu->data;
2521 crypt_entry_t entry;
2523 entry.key = key_table[num];
2524 entry.num = num + 1;
2526 mutt_FormatString (s, l, NONULL (PgpEntryFormat), crypt_entry_fmt,
2527 (unsigned long) &entry, M_FORMAT_ARROWCURSOR);
2530 /* Compare two addresses and the keyid to be used for sorting. */
2531 static int _crypt_compare_address (const void *a, const void *b)
2533 crypt_key_t **s = (crypt_key_t **) a;
2534 crypt_key_t **t = (crypt_key_t **) b;
2537 if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid)))
2540 return mutt_strcasecmp (crypt_keyid (*s), crypt_keyid (*t)) > 0;
2543 static int crypt_compare_address (const void *a, const void *b)
2545 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_address (a, b)
2546 : _crypt_compare_address (a, b));
2550 /* Compare two key IDs and the addresses to be used for sorting. */
2551 static int _crypt_compare_keyid (const void *a, const void *b)
2553 crypt_key_t **s = (crypt_key_t **) a;
2554 crypt_key_t **t = (crypt_key_t **) b;
2557 if ((r = mutt_strcasecmp (crypt_keyid (*s), crypt_keyid (*t))))
2560 return mutt_strcasecmp ((*s)->uid, (*t)->uid) > 0;
2563 static int crypt_compare_keyid (const void *a, const void *b)
2565 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_keyid (a, b)
2566 : _crypt_compare_keyid (a, b));
2569 /* Compare 2 creation dates and the addresses. For sorting. */
2570 static int _crypt_compare_date (const void *a, const void *b)
2572 crypt_key_t **s = (crypt_key_t **) a;
2573 crypt_key_t **t = (crypt_key_t **) b;
2574 unsigned long ts = 0, tt = 0;
2576 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2577 ts = (*s)->kobj->subkeys->timestamp;
2578 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2579 tt = (*t)->kobj->subkeys->timestamp;
2586 return mutt_strcasecmp ((*s)->uid, (*t)->uid) > 0;
2589 static int crypt_compare_date (const void *a, const void *b)
2591 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_date (a, b)
2592 : _crypt_compare_date (a, b));
2595 /* Compare two trust values, the key length, the creation dates. the
2596 addresses and the key IDs. For sorting. */
2597 static int _crypt_compare_trust (const void *a, const void *b)
2599 crypt_key_t **s = (crypt_key_t **) a;
2600 crypt_key_t **t = (crypt_key_t **) b;
2601 unsigned long ts = 0, tt = 0;
2604 if ((r = (((*s)->flags & (KEYFLAG_RESTRICTIONS))
2605 - ((*t)->flags & (KEYFLAG_RESTRICTIONS)))))
2608 if ((*s)->kobj->uids)
2609 ts = (*s)->kobj->uids->validity;
2610 if ((*t)->kobj->uids)
2611 tt = (*t)->kobj->uids->validity;
2612 if ((r = (tt - ts)))
2615 if ((*s)->kobj->subkeys)
2616 ts = (*s)->kobj->subkeys->length;
2617 if ((*t)->kobj->subkeys)
2618 tt = (*t)->kobj->subkeys->length;
2622 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2623 ts = (*s)->kobj->subkeys->timestamp;
2624 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2625 tt = (*t)->kobj->subkeys->timestamp;
2631 if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid)))
2633 return (mutt_strcasecmp (crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0;
2636 static int crypt_compare_trust (const void *a, const void *b)
2638 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_trust (a, b)
2639 : _crypt_compare_trust (a, b));
2642 /* Print the X.500 Distinguished Name part KEY from the array of parts
2645 print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key)
2649 for (; dn->key; dn++)
2651 if (!strcmp (dn->key, key))
2655 print_utf8 (fp, dn->value, strlen (dn->value));
2662 /* Print all parts of a DN in a standard sequence. */
2664 print_dn_parts (FILE *fp, struct dn_array_s *dn)
2666 const char *stdpart[] = {
2667 "CN", "OU", "O", "STREET", "L", "ST", "C", NULL
2669 int any=0, any2=0, i;
2671 for (i=0; stdpart[i]; i++)
2675 any = print_dn_part (fp, dn, stdpart[i]);
2677 /* now print the rest without any specific ordering */
2678 for (; dn->key; dn++)
2680 for (i=0; stdpart[i]; i++)
2682 if (!strcmp (dn->key, stdpart[i]))
2691 any = print_dn_part (fp, dn, dn->key);
2700 /* Parse an RDN; this is a helper to parse_dn(). */
2701 static const unsigned char *
2702 parse_dn_part (struct dn_array_s *array, const unsigned char *string)
2704 const unsigned char *s, *s1;
2708 /* parse attributeType */
2709 for (s = string+1; *s && *s != '='; s++)
2712 return NULL; /* error */
2715 return NULL; /* empty key */
2716 array->key = safe_malloc (n+1);
2717 p = (unsigned char *)array->key;
2718 memcpy (p, string, n); /* fixme: trim trailing spaces */
2725 for (s=string; hexdigitp (s); s++)
2729 return NULL; /* empty or odd number of digits */
2731 p = safe_malloc (n+1);
2732 array->value = (char*)p;
2733 for (s1=string; n; s1 += 2, n--)
2738 { /* regular v3 quoted string */
2739 for (n=0, s=string; *s; s++)
2744 if (*s == ',' || *s == '=' || *s == '+'
2745 || *s == '<' || *s == '>' || *s == '#' || *s == ';'
2746 || *s == '\\' || *s == '\"' || *s == ' ')
2748 else if (hexdigitp (s) && hexdigitp (s+1))
2754 return NULL; /* invalid escape sequence */
2756 else if (*s == '\"')
2757 return NULL; /* invalid encoding */
2758 else if (*s == ',' || *s == '=' || *s == '+'
2759 || *s == '<' || *s == '>' || *s == '#' || *s == ';' )
2765 p = safe_malloc (n+1);
2766 array->value = (char*)p;
2767 for (s=string; n; s++, n--)
2789 /* Parse a DN and return an array-ized one. This is not a validating
2790 parser and it does not support any old-stylish syntax; gpgme is
2791 expected to return only rfc2253 compatible strings. */
2792 static struct dn_array_s *
2793 parse_dn (const unsigned char *string)
2795 struct dn_array_s *array;
2796 size_t arrayidx, arraysize;
2799 arraysize = 7; /* C,ST,L,O,OU,CN,email */
2800 array = safe_malloc ((arraysize+1) * sizeof *array);
2804 while (*string == ' ')
2808 if (arrayidx >= arraysize)
2809 { /* mutt lacks a real safe_realoc - so we need to copy */
2810 struct dn_array_s *a2;
2813 a2 = safe_malloc ((arraysize+1) * sizeof *array);
2814 for (i=0; i < arrayidx; i++)
2816 a2[i].key = array[i].key;
2817 a2[i].value = array[i].value;
2822 array[arrayidx].key = NULL;
2823 array[arrayidx].value = NULL;
2824 string = parse_dn_part (array+arrayidx, string);
2828 while (*string == ' ')
2830 if (*string && *string != ',' && *string != ';' && *string != '+')
2831 goto failure; /* invalid delimiter */
2835 array[arrayidx].key = NULL;
2836 array[arrayidx].value = NULL;
2840 for (i=0; i < arrayidx; i++)
2842 FREE (&array[i].key);
2843 FREE (&array[i].value);
2850 /* Print a nice representation of the USERID and make sure it is
2851 displayed in a proper way, which does mean to reorder some parts
2852 for S/MIME's DNs. USERID is a string as returned by the gpgme key
2853 functions. It is utf-8 encoded. */
2855 parse_and_print_user_id (FILE *fp, const char *userid)
2862 s = strchr (userid+1, '>');
2864 print_utf8 (fp, userid+1, s-userid-1);
2866 else if (*userid == '(')
2867 fputs (_("[Can't display this user ID (unknown encoding)]"), fp);
2868 else if (!digit_or_letter ((const unsigned char *)userid))
2869 fputs (_("[Can't display this user ID (invalid encoding)]"), fp);
2872 struct dn_array_s *dn = parse_dn ((const unsigned char *)userid);
2874 fputs (_("[Can't display this user ID (invalid DN)]"), fp);
2877 print_dn_parts (fp, dn);
2878 for (i=0; dn[i].key; i++)
2881 FREE (&dn[i].value);
2890 KEY_CAP_CAN_ENCRYPT,
2897 key_check_cap (gpgme_key_t key, key_cap_t cap)
2899 gpgme_subkey_t subkey = NULL;
2900 unsigned int ret = 0;
2904 case KEY_CAP_CAN_ENCRYPT:
2905 if (! (ret = key->can_encrypt))
2906 for (subkey = key->subkeys; subkey; subkey = subkey->next)
2907 if ((ret = subkey->can_encrypt))
2910 case KEY_CAP_CAN_SIGN:
2911 if (! (ret = key->can_sign))
2912 for (subkey = key->subkeys; subkey; subkey = subkey->next)
2913 if ((ret = subkey->can_sign))
2916 case KEY_CAP_CAN_CERTIFY:
2917 if (! (ret = key->can_certify))
2918 for (subkey = key->subkeys; subkey; subkey = subkey->next)
2919 if ((ret = subkey->can_certify))
2928 /* Print verbose information about a key or certificate to FP. */
2929 static void print_key_info (gpgme_key_t key, FILE *fp)
2932 const char *s = NULL, *s2 = NULL;
2935 char shortbuf[SHORT_STRING];
2936 unsigned long aval = 0;
2940 gpgme_user_id_t uid = NULL;
2943 setlocale (LC_TIME, Locale);
2945 is_pgp = key->protocol == GPGME_PROTOCOL_OpenPGP;
2947 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
2953 fprintf (fp, "%s ......: ", idx ? _(" aka") :_("Name"));
2956 fputs (_("[Invalid]"), fp);
2960 print_utf8 (fp, s, strlen(s));
2962 parse_and_print_user_id (fp, s);
2966 if (key->subkeys && (key->subkeys->timestamp > 0))
2968 tt = key->subkeys->timestamp;
2970 tm = localtime (&tt);
2971 #ifdef HAVE_LANGINFO_D_T_FMT
2972 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2974 strftime (shortbuf, sizeof shortbuf, "%c", tm);
2976 fprintf (fp, "Valid From : %s\n", shortbuf);
2979 if (key->subkeys && (key->subkeys->expires > 0))
2981 tt = key->subkeys->expires;
2983 tm = localtime (&tt);
2984 #ifdef HAVE_LANGINFO_D_T_FMT
2985 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2987 strftime (shortbuf, sizeof shortbuf, "%c", tm);
2989 fprintf (fp, "Valid To ..: %s\n", shortbuf);
2993 s = gpgme_pubkey_algo_name (key->subkeys->pubkey_algo);
2997 s2 = is_pgp ? "PGP" : "X.509";
3000 aval = key->subkeys->length;
3002 fprintf (fp, "Key Type ..: %s, %lu bit %s\n", s2, aval, s);
3004 fprintf (fp, "Key Usage .: ");
3007 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3009 fprintf (fp, "%s%s", delim, _("encryption"));
3012 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3014 fprintf (fp, "%s%s", delim, _("signing"));
3017 if (key_check_cap (key, KEY_CAP_CAN_CERTIFY))
3019 fprintf (fp, "%s%s", delim, _("certification"));
3026 s = key->subkeys->fpr;
3027 fputs (_("Fingerprint: "), fp);
3028 if (is_pgp && strlen (s) == 40)
3030 for (i=0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++)
3036 putc (is_pgp? ' ':':', fp);
3037 if (is_pgp && i == 4)
3043 for (i=0; *s && s[1] && s[2]; s += 2, i++)
3047 putc (is_pgp? ' ':':', fp);
3048 if (is_pgp && i == 7)
3052 fprintf (fp, "%s\n", s);
3055 if (key->issuer_serial)
3057 s = key->issuer_serial;
3059 fprintf (fp, "Serial-No .: 0x%s\n", s);
3062 if (key->issuer_name)
3064 s = key->issuer_name;
3067 fprintf (fp, "Issued By .: ");
3068 parse_and_print_user_id (fp, s);
3073 /* For PGP we list all subkeys. */
3076 gpgme_subkey_t subkey = NULL;
3078 for (idx = 1, subkey = key->subkeys; subkey;
3079 idx++, subkey = subkey->next)
3084 if ( strlen (s) == 16)
3085 s += 8; /* display only the short keyID */
3086 fprintf (fp, "Subkey ....: 0x%s", s);
3087 if (subkey->revoked)
3090 fputs (_("[Revoked]"), fp);
3092 if (subkey->invalid)
3095 fputs (_("[Invalid]"), fp);
3097 if (subkey->expired)
3100 fputs (_("[Expired]"), fp);
3102 if (subkey->disabled)
3105 fputs (_("[Disabled]"), fp);
3109 if (subkey->timestamp > 0)
3111 tt = subkey->timestamp;
3113 tm = localtime (&tt);
3114 #ifdef HAVE_LANGINFO_D_T_FMT
3115 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
3117 strftime (shortbuf, sizeof shortbuf, "%c", tm);
3119 fprintf (fp, "Valid From : %s\n", shortbuf);
3122 if (subkey->expires > 0)
3124 tt = subkey->expires;
3126 tm = localtime (&tt);
3127 #ifdef HAVE_LANGINFO_D_T_FMT
3128 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
3130 strftime (shortbuf, sizeof shortbuf, "%c", tm);
3132 fprintf (fp, "Valid To ..: %s\n", shortbuf);
3136 s = gpgme_pubkey_algo_name (subkey->pubkey_algo);
3141 aval = subkey->length;
3145 fprintf (fp, "Key Type ..: %s, %lu bit %s\n", "PGP", aval, s);
3147 fprintf (fp, "Key Usage .: ");
3150 if (subkey->can_encrypt)
3152 fprintf (fp, "%s%s", delim, _("encryption"));
3155 if (subkey->can_sign)
3157 fprintf (fp, "%s%s", delim, _("signing"));
3160 if (subkey->can_certify)
3162 fprintf (fp, "%s%s", delim, _("certification"));
3170 setlocale (LC_TIME, "C");
3174 /* Show detailed information about the selected key */
3176 verify_key (crypt_key_t *key)
3179 char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
3181 gpgme_ctx_t listctx = NULL;
3183 gpgme_key_t k = NULL;
3186 mutt_mktemp (tempfile);
3187 if (!(fp = safe_fopen (tempfile, "w")))
3189 mutt_perror _("Can't create temporary file");
3192 mutt_message _("Collecting data...");
3194 print_key_info (key->kobj, fp);
3196 err = gpgme_new (&listctx);
3199 fprintf (fp, "Internal error: can't create gpgme context: %s\n",
3200 gpgme_strerror (err));
3203 if ((key->flags & KEYFLAG_ISX509))
3204 gpgme_set_protocol (listctx, GPGME_PROTOCOL_CMS);
3208 while ((s = k->chain_id) && k->subkeys && strcmp (s, k->subkeys->fpr) )
3211 err = gpgme_op_keylist_start (listctx, s, 0);
3212 gpgme_key_release (k);
3215 err = gpgme_op_keylist_next (listctx, &k);
3218 fprintf (fp, _("Error finding issuer key: %s\n"),
3219 gpgme_strerror (err));
3222 gpgme_op_keylist_end (listctx);
3224 print_key_info (k, fp);
3228 fputs (_("Error: certification chain to long - stopping here\n"),
3235 gpgme_key_release (k);
3236 gpgme_release (listctx);
3238 mutt_clear_error ();
3239 snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), crypt_keyid (key));
3240 mutt_do_pager (cmd, tempfile, 0, NULL);
3244 * Implementation of `findkeys'.
3248 /* Convert LIST into a pattern string suitable to be passed to GPGME.
3249 We need to convert spaces in an item into a '+' and '%' into
3251 static char *list_to_pattern (LIST *list)
3259 for(l=list; l; l = l->next)
3261 for(s = l->data; *s; s++)
3267 n++; /* delimiter or end of string */
3269 n++; /* make sure to allocate at least one byte */
3270 pattern = p = safe_calloc (1,n);
3271 for(l=list; l; l = l->next)
3278 for(s = l->data; *s; s++)
3303 /* Return a list of keys which are candidates for the selection.
3304 Select by looking at the HINTS list. */
3305 static crypt_key_t *get_candidates (LIST * hints, unsigned int app, int secret)
3307 crypt_key_t *db, *k, **kend;
3313 gpgme_user_id_t uid = NULL;
3315 pattern = list_to_pattern (hints);
3319 err = gpgme_new (&ctx);
3322 mutt_error ("gpgme_new failed: %s", gpgme_strerror (err));
3330 if ((app & APPLICATION_PGP))
3332 /* Its all a mess. That old GPGME expects different things
3333 depending on the protocol. For gpg we don' t need percent
3334 escaped pappert but simple strings passed in an array to the
3335 keylist_ext_start function. */
3340 for(l=hints, n=0; l; l = l->next)
3342 if (l->data && *l->data)
3348 patarr = safe_calloc (n+1, sizeof *patarr);
3349 for(l=hints, n=0; l; l = l->next)
3351 if (l->data && *l->data)
3352 patarr[n++] = safe_strdup (l->data);
3355 err = gpgme_op_keylist_ext_start (ctx, (const char**)patarr, secret, 0);
3356 for (n=0; patarr[n]; n++)
3361 mutt_error ("gpgme_op_keylist_start failed: %s",
3362 gpgme_strerror (err));
3363 gpgme_release (ctx);
3368 while (!(err = gpgme_op_keylist_next (ctx, &key)) )
3370 unsigned int flags = 0;
3372 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3373 flags |= KEYFLAG_CANENCRYPT;
3374 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3375 flags |= KEYFLAG_CANSIGN;
3377 #if 0 /* DISABLED code */
3380 /* Bug in gpg. Capabilities are not listed for secret
3381 keys. Try to deduce them from the algorithm. */
3383 switch (key->subkeys[0].pubkey_algo)
3386 flags |= KEYFLAG_CANENCRYPT;
3387 flags |= KEYFLAG_CANSIGN;
3389 case GPGME_PK_ELG_E:
3390 flags |= KEYFLAG_CANENCRYPT;
3393 flags |= KEYFLAG_CANSIGN;
3397 #endif /* DISABLED code */
3399 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3401 k = safe_calloc (1, sizeof *k);
3410 if (gpg_err_code (err) != GPG_ERR_EOF)
3411 mutt_error ("gpgme_op_keylist_next failed: %s", gpgme_strerror (err));
3412 gpgme_op_keylist_end (ctx);
3417 if ((app & APPLICATION_SMIME))
3419 /* and now look for x509 certificates */
3420 gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
3421 err = gpgme_op_keylist_start (ctx, pattern, 0);
3424 mutt_error ("gpgme_op_keylist_start failed: %s",
3425 gpgme_strerror (err));
3426 gpgme_release (ctx);
3431 while (!(err = gpgme_op_keylist_next (ctx, &key)) )
3433 unsigned int flags = KEYFLAG_ISX509;
3435 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3436 flags |= KEYFLAG_CANENCRYPT;
3437 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3438 flags |= KEYFLAG_CANSIGN;
3440 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3442 k = safe_calloc (1, sizeof *k);
3451 if (gpg_err_code (err) != GPG_ERR_EOF)
3452 mutt_error ("gpgme_op_keylist_next failed: %s", gpgme_strerror (err));
3453 gpgme_op_keylist_end (ctx);
3456 gpgme_release (ctx);
3461 /* Add the string STR to the list HINTS. This list is later used to
3463 static LIST *crypt_add_string_to_hints (LIST *hints, const char *str)
3468 if ((scratch = safe_strdup (str)) == NULL)
3471 for (t = strtok (scratch, " ,.:\"()<>\n"); t;
3472 t = strtok (NULL, " ,.:\"()<>\n"))
3475 hints = mutt_add_list (hints, t);
3482 /* Display a menu to select a key from the array KEYS. FORCED_VALID
3483 will be set to true on return if the user did override the the
3485 static crypt_key_t *crypt_select_key (crypt_key_t *keys,
3486 ADDRESS * p, const char *s,
3487 unsigned int app, int *forced_valid)
3490 crypt_key_t **key_table;
3493 char helpstr[SHORT_STRING], buf[LONG_STRING];
3495 int (*f) (const void *, const void *);
3496 int menu_to_use = 0;
3501 /* build the key table */
3504 for (k = keys; k; k = k->next)
3506 if (!option (OPTPGPSHOWUNUSABLE) && (k->flags & KEYFLAG_CANTUSE))
3515 safe_realloc (&key_table, sizeof (crypt_key_t*)*keymax);
3523 mutt_error _("All matching keys are marked expired/revoked.");
3528 switch (PgpSortKeys & SORT_MASK)
3531 f = crypt_compare_date;
3534 f = crypt_compare_keyid;
3537 f = crypt_compare_address;
3541 f = crypt_compare_trust;
3544 qsort (key_table, i, sizeof (crypt_key_t*), f);
3546 if (app & APPLICATION_PGP)
3547 menu_to_use = MENU_KEY_SELECT_PGP;
3548 else if (app & APPLICATION_SMIME)
3549 menu_to_use = MENU_KEY_SELECT_SMIME;
3552 mutt_make_help (buf, sizeof (buf), _("Exit "), menu_to_use, OP_EXIT);
3553 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3554 mutt_make_help (buf, sizeof (buf), _("Select "), menu_to_use,
3555 OP_GENERIC_SELECT_ENTRY);
3556 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3557 mutt_make_help (buf, sizeof (buf), _("Check key "),
3558 menu_to_use, OP_VERIFY_KEY);
3559 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3560 mutt_make_help (buf, sizeof (buf), _("Help"), menu_to_use, OP_HELP);
3561 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3563 menu = mutt_new_menu ();
3565 menu->make_entry = crypt_entry;
3566 menu->menu = menu_to_use;
3567 menu->help = helpstr;
3568 menu->data = key_table;
3573 if ((app & APPLICATION_PGP) && (app & APPLICATION_SMIME))
3574 ts = _("PGP and S/MIME keys matching");
3575 else if ((app & APPLICATION_PGP))
3576 ts = _("PGP keys matching");
3577 else if ((app & APPLICATION_SMIME))
3578 ts = _("S/MIME keys matching");
3580 ts = _("keys matching");
3583 snprintf (buf, sizeof (buf), _("%s <%s>."), ts, p->mailbox);
3585 snprintf (buf, sizeof (buf), _("%s \"%s\"."), ts, s);
3589 mutt_clear_error ();
3594 switch (mutt_menuLoop (menu))
3597 verify_key (key_table[menu->current]);
3598 menu->redraw = REDRAW_FULL;
3602 mutt_message ("%s", key_table[menu->current]->uid);
3605 case OP_GENERIC_SELECT_ENTRY:
3606 /* FIXME make error reporting more verbose - this should be
3607 easy because gpgme provides more information */
3608 if (option (OPTPGPCHECKTRUST))
3610 if (!crypt_key_is_valid (key_table[menu->current]))
3612 mutt_error _("This key can't be used: "
3613 "expired/disabled/revoked.");
3618 if (option (OPTPGPCHECKTRUST) &&
3619 (!crypt_id_is_valid (key_table[menu->current])
3620 || !crypt_id_is_strong (key_table[menu->current])))
3623 char buff[LONG_STRING];
3625 if (key_table[menu->current]->flags & KEYFLAG_CANTUSE)
3626 s = N_("ID is expired/disabled/revoked.");
3629 gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
3630 gpgme_user_id_t uid = NULL;
3635 uid = key_table[menu->current]->kobj->uids;
3636 for (j = 0; (j < key_table[menu->current]->idx) && uid;
3637 j++, uid = uid->next)
3640 val = uid->validity;
3644 case GPGME_VALIDITY_UNKNOWN:
3645 case GPGME_VALIDITY_UNDEFINED:
3646 warn_s = N_("ID has undefined validity.");
3648 case GPGME_VALIDITY_NEVER:
3649 warn_s = N_("ID is not valid.");
3651 case GPGME_VALIDITY_MARGINAL:
3652 warn_s = N_("ID is only marginally valid.");
3654 case GPGME_VALIDITY_FULL:
3655 case GPGME_VALIDITY_ULTIMATE:
3659 snprintf (buff, sizeof (buff),
3660 _("%s Do you really want to use the key?"),
3663 if (mutt_yesorno (buff, 0) != 1)
3665 mutt_clear_error ();
3672 k = crypt_copy_key (key_table[menu->current]);
3683 mutt_menuDestroy (&menu);
3686 set_option (OPTNEEDREDRAW);
3691 static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
3692 unsigned int app, int *forced_valid)
3700 int this_key_has_strong;
3701 int this_key_has_weak;
3702 int this_key_has_invalid;
3705 crypt_key_t *keys, *k;
3706 crypt_key_t *the_valid_key = NULL;
3707 crypt_key_t *matches = NULL;
3708 crypt_key_t **matches_endp = &matches;
3712 if (a && a->mailbox)
3713 hints = crypt_add_string_to_hints (hints, a->mailbox);
3714 if (a && a->personal)
3715 hints = crypt_add_string_to_hints (hints, a->personal);
3717 mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
3718 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN) );
3720 mutt_free_list (&hints);
3725 dprint (5, (debugfile, "crypt_getkeybyaddr: looking for %s <%s>.",
3726 a->personal, a->mailbox));
3728 for (k = keys; k; k = k->next)
3730 dprint (5, (debugfile, " looking at key: %s `%.15s'\n",
3731 crypt_keyid (k), k->uid));
3733 if (abilities && !(k->flags & abilities))
3735 dprint (5, (debugfile, " insufficient abilities: Has %x, want %x\n",
3736 k->flags, abilities));
3740 this_key_has_weak = 0; /* weak but valid match */
3741 this_key_has_invalid = 0; /* invalid match */
3742 this_key_has_strong = 0; /* strong and valid match */
3743 match = 0; /* any match */
3745 r = rfc822_parse_adrlist (NULL, k->uid);
3746 for (p = r; p; p = p->next)
3748 int validity = crypt_id_matches_addr (a, p, k);
3750 if (validity & CRYPT_KV_MATCH) /* something matches */
3753 /* is this key a strong candidate? */
3754 if ((validity & CRYPT_KV_VALID)
3755 && (validity & CRYPT_KV_STRONGID)
3756 && (validity & CRYPT_KV_ADDR))
3758 if (the_valid_key && the_valid_key != k)
3761 this_key_has_strong = 1;
3763 else if ((validity & CRYPT_KV_MATCH)
3764 && !(validity & CRYPT_KV_VALID))
3765 this_key_has_invalid = 1;
3766 else if ((validity & CRYPT_KV_MATCH)
3767 && (!(validity & CRYPT_KV_STRONGID)
3768 || !(validity & CRYPT_KV_ADDR)))
3769 this_key_has_weak = 1;
3771 rfc822_free_address (&r);
3777 if (!this_key_has_strong && this_key_has_invalid)
3779 if (!this_key_has_strong && this_key_has_weak)
3782 *matches_endp = tmp = crypt_copy_key (k);
3783 matches_endp = &tmp->next;
3784 the_valid_key = tmp;
3788 crypt_free_key (&keys);
3792 if (the_valid_key && !multi && !weak
3793 && !(invalid && option (OPTPGPSHOWUNUSABLE)))
3796 * There was precisely one strong match on a valid ID, there
3797 * were no valid keys with weak matches, and we aren't
3798 * interested in seeing invalid keys.
3800 * Proceed without asking the user.
3802 k = crypt_copy_key (the_valid_key);
3807 * Else: Ask the user.
3809 k = crypt_select_key (matches, a, NULL, app, forced_valid);
3811 crypt_free_key (&matches);
3820 static crypt_key_t *crypt_getkeybystr (char *p, short abilities,
3821 unsigned int app, int *forced_valid)
3825 crypt_key_t *matches = NULL;
3826 crypt_key_t **matches_endp = &matches;
3830 mutt_message (_("Looking for keys matching \"%s\"..."), p);
3834 hints = crypt_add_string_to_hints (hints, p);
3835 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
3836 mutt_free_list (&hints);
3841 for (k = keys; k; k = k->next)
3843 if (abilities && !(k->flags & abilities))
3847 dprint (5, (debugfile, "crypt_getkeybystr: matching \"%s\" against "
3848 "key %s, \"%s\": ", p, crypt_keyid (k), k->uid));
3851 || !mutt_strcasecmp (p, crypt_keyid (k))
3852 || (!mutt_strncasecmp (p, "0x", 2)
3853 && !mutt_strcasecmp (p + 2, crypt_keyid (k)))
3854 || (option (OPTPGPLONGIDS)
3855 && !mutt_strncasecmp (p, "0x", 2)
3856 && !mutt_strcasecmp (p + 2, crypt_keyid (k) + 8))
3857 || mutt_stristr (k->uid, p))
3861 dprint (5, (debugfile, "match.\n"));
3863 *matches_endp = tmp = crypt_copy_key (k);
3864 matches_endp = &tmp->next;
3868 crypt_free_key (&keys);
3872 k = crypt_select_key (matches, NULL, p, app, forced_valid);
3873 crypt_free_key (&matches);
3880 /* Display TAG as a prompt to ask for a key. If WHATFOR is not null
3881 use it as default and store it under that label as the next
3882 default. ABILITIES describe the required key abilities (sign,
3883 encrypt) and APP the type of the requested key; ether S/MIME or
3884 PGP. Return a copy of the key or NULL if not found. */
3885 static crypt_key_t *crypt_ask_for_key (char *tag,
3892 char resp[SHORT_STRING];
3893 struct crypt_cache *l = NULL;
3897 forced_valid = &dummy;
3899 mutt_clear_error ();
3906 for (l = id_defaults; l; l = l->next)
3907 if (!mutt_strcasecmp (whatfor, l->what))
3909 strfcpy (resp, NONULL (l->dflt), sizeof (resp));
3918 if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0)
3924 mutt_str_replace (&l->dflt, resp);
3927 l = safe_malloc (sizeof (struct crypt_cache));
3928 l->next = id_defaults;
3930 l->what = safe_strdup (whatfor);
3931 l->dflt = safe_strdup (resp);
3935 if ((key = crypt_getkeybystr (resp, abilities, app, forced_valid)))
3943 /* This routine attempts to find the keyids of the recipients of a
3944 message. It returns NULL if any of the keys can not be found. */
3945 static char *find_keys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc,
3948 char *keyID, *keylist = NULL, *t;
3949 size_t keylist_size = 0;
3950 size_t keylist_used = 0;
3951 ADDRESS *tmp = NULL, *addr = NULL;
3952 ADDRESS **last = &tmp;
3955 crypt_key_t *k_info, *key;
3956 const char *fqdn = mutt_fqdn (1);
3959 *r_application = APPLICATION_PGP|APPLICATION_SMIME;
3962 for (i = 0; i < 3; i++)
3966 case 0: p = to; break;
3967 case 1: p = cc; break;
3968 case 2: p = bcc; break;
3972 *last = rfc822_cpy_adr (p);
3974 last = &((*last)->next);
3978 rfc822_qualify (tmp, fqdn);
3980 tmp = mutt_remove_duplicates (tmp);
3982 for (p = tmp; p ; p = p->next)
3984 char buf[LONG_STRING];
3985 int forced_valid = 0;
3990 if ((keyID = mutt_crypt_hook (p)) != NULL)
3993 snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"),
3995 if ((r = mutt_yesorno (buf, M_YES)) == M_YES)
3997 /* check for e-mail address */
3998 if ((t = strchr (keyID, '@')) &&
3999 (addr = rfc822_parse_adrlist (NULL, keyID)))
4002 rfc822_qualify (addr, fqdn);
4008 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
4009 *r_application, &forced_valid);
4011 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
4012 app, &forced_valid);
4019 rfc822_free_address (&tmp);
4020 rfc822_free_address (&addr);
4026 && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT,
4027 app, &forced_valid)) == NULL)
4029 snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
4031 if ((key = crypt_ask_for_key (buf, q->mailbox,
4038 &forced_valid)) == NULL)
4041 rfc822_free_address (&tmp);
4042 rfc822_free_address (&addr);
4050 const char *s = crypt_fpr (key);
4053 if (key->flags & KEYFLAG_ISX509)
4054 *r_application &= ~APPLICATION_PGP;
4055 if (!(key->flags & KEYFLAG_ISX509))
4056 *r_application &= ~APPLICATION_SMIME;
4059 keylist_size += mutt_strlen (s) + 4 + 1;
4060 safe_realloc (&keylist, keylist_size);
4061 sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */
4062 keylist_used ? " " : "", s,
4063 forced_valid? "!":"");
4065 keylist_used = mutt_strlen (keylist);
4067 crypt_free_key (&key);
4068 rfc822_free_address (&addr);
4070 rfc822_free_address (&tmp);
4074 char *pgp_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc)
4076 return find_keys (to, cc, bcc, APPLICATION_PGP);
4079 char *smime_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc)
4081 return find_keys (to, cc, bcc, APPLICATION_SMIME);
4085 * Implementation of `init'.
4088 /* Initialization. */
4089 static void init_gpgme (void)
4091 /* Make sure that gpg-agent is running. */
4092 if (! getenv ("GPG_AGENT_INFO"))
4094 mutt_error ("\nUsing GPGME backend, although no gpg-agent is running");
4095 if (mutt_any_key_to_continue (NULL) == -1)
4100 void pgp_gpgme_init (void)
4105 void smime_gpgme_init (void)
4109 static int gpgme_send_menu (HEADER *msg, int *redraw, int is_smime)
4112 char input_signas[SHORT_STRING];
4115 if (msg->security & APPLICATION_PGP)
4117 else if (msg->security & APPLICATION_SMIME)
4121 choice = mutt_multi_choice (
4122 _("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (t)oggle or (f)orget it?"),
4125 choice = mutt_multi_choice (
4126 _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, (t)oggle or (f)orget it?"),
4131 case 1: /* (e)ncrypt */
4132 msg->security |= (is_smime ? SMIMEENCRYPT : PGPENCRYPT);
4135 case 2: /* (s)ign */
4136 msg->security |= (is_smime? SMIMESIGN :PGPSIGN);
4139 case 3: /* sign (a)s */
4140 /* unset_option(OPTCRYPTCHECKTRUST); */
4141 if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
4142 is_smime? APPLICATION_SMIME:APPLICATION_PGP,
4145 snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p));
4146 mutt_str_replace (is_smime? &SmimeDefaultKey : &PgpSignAs, input_signas);
4147 crypt_free_key (&p);
4149 msg->security |= (is_smime? SMIMESIGN:PGPSIGN);
4153 msg->security &= (is_smime? ~SMIMESIGN : ~PGPSIGN);
4155 *redraw = REDRAW_FULL;
4158 case 4: /* (b)oth */
4159 msg->security = (is_smime? (SMIMEENCRYPT|SMIMESIGN):(PGPENCRYPT|PGPSIGN));
4162 case 5: /* (t)oggle */
4163 is_smime = !is_smime;
4166 case 6: /* (f)orget it */
4175 msg->security &= ~APPLICATION_PGP;
4176 msg->security |= APPLICATION_SMIME;
4180 msg->security &= ~APPLICATION_SMIME;
4181 msg->security |= APPLICATION_PGP;
4184 return (msg->security);
4187 int pgp_gpgme_send_menu (HEADER *msg, int *redraw)
4189 return gpgme_send_menu (msg, redraw, 0);
4192 int smime_gpgme_send_menu (HEADER *msg, int *redraw)
4194 return gpgme_send_menu (msg, redraw, 1);
4197 static int verify_sender (HEADER *h, gpgme_protocol_t protocol)
4199 ADDRESS *sender = NULL;
4200 unsigned int ret = 1;
4204 h->env->from = mutt_expand_aliases (h->env->from);
4205 sender = h->env->from;
4207 else if (h->env->sender)
4209 h->env->sender = mutt_expand_aliases (h->env->sender);
4210 sender = h->env->sender;
4217 gpgme_key_t key = signature_key;
4218 gpgme_user_id_t uid = NULL;
4219 int sender_length = 0;
4222 sender_length = strlen (sender->mailbox);
4223 for (uid = key->uids; uid && ret; uid = uid->next)
4225 uid_length = strlen (uid->email);
4227 && (uid->email[0] == '<')
4228 && (uid->email[uid_length - 1] == '>')
4229 && (uid_length == sender_length + 2)
4230 && (! strncmp (uid->email + 1, sender->mailbox, sender_length)))
4235 mutt_any_key_to_continue ("Failed to verify sender");
4238 mutt_any_key_to_continue ("Failed to figure out sender");
4242 gpgme_key_release (signature_key);
4243 signature_key = NULL;
4249 int smime_gpgme_verify_sender (HEADER *h)
4251 return verify_sender (h, GPGME_PROTOCOL_CMS);