2 * Copyright notice from original mutt:
3 * crypt-gpgme.c - GPGME based crypto operations
4 * Copyright (C) 1996,1997 Michael R. Elkins <me@cs.hmc.edu>
5 * Copyright (C) 1998,1999,2000 Thomas Roessler <roessler@guug.de>
6 * Copyright (C) 2001 Thomas Roessler <roessler@guug.de>
7 * Oliver Ehli <elmy@acm.org>
8 * Copyright (C) 2002, 2003, 2004 g10 Code GmbH
10 * This file is part of mutt-ng, see http://www.muttng.org/.
11 * It's licensed under the GNU General Public License,
12 * please see the file GPL in the top level source directory.
19 #ifdef CRYPT_BACKEND_GPGME
32 #ifdef HAVE_LANGINFO_D_T_FMT
33 # include <langinfo.h>
35 #ifdef HAVE_SYS_TIME_H
36 # include <sys/time.h>
38 #ifdef HAVE_SYS_RESOURCE_H
39 # include <sys/resource.h>
44 #include <lib-lib/mem.h>
45 #include <lib-lib/str.h>
46 #include <lib-lib/ascii.h>
47 #include <lib-lib/macros.h>
48 #include <lib-lib/file.h>
50 #include <lib-mime/mime.h>
52 #include <lib-ui/curses.h>
53 #include <lib-ui/enter.h>
54 #include <lib-ui/menu.h>
59 #include <lib-crypt/crypt.h>
63 #include "recvattach.h"
69 #define digitp(p) (*(p) >= '0' && *(p) <= '9')
70 #define hexdigitp(a) (digitp (a) \
71 || (*(a) >= 'A' && *(a) <= 'F') \
72 || (*(a) >= 'a' && *(a) <= 'f'))
73 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
74 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
75 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
77 /* Values used for comparing addresses. */
78 #define CRYPT_KV_VALID 1
79 #define CRYPT_KV_ADDR 2
80 #define CRYPT_KV_STRING 4
81 #define CRYPT_KV_STRONGID 8
82 #define CRYPT_KV_MATCH (CRYPT_KV_ADDR|CRYPT_KV_STRING)
91 struct crypt_cache *next;
99 /* We work based on user IDs, getting from a user ID to the key is
100 check and does not need any memory (gpgme uses reference counting). */
101 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 {
115 static struct crypt_cache *id_defaults = NULL;
116 static gpgme_key_t signature_key = NULL;
119 * General helper functions.
122 /* return true when S points to a didgit or letter. */
123 static int digit_or_letter (const unsigned char *s)
125 return ((*s >= '0' && *s <= '9')
126 || (*s >= 'A' && *s <= 'Z')
127 || (*s >= 'a' && *s <= 'z'));
131 /* Print the utf-8 encoded string BUF of length LEN bytes to stream
132 FP. Convert the character set. */
133 static void print_utf8 (FILE * fp, const char *buf, ssize_t len)
137 tstr = p_dupstr(buf, len);
138 mutt_convert_string (&tstr, "utf-8", Charset, M_ICONV_HOOK_FROM);
148 /* Return the keyID for the key K. Note that this string is valid as
149 long as K is valid */
150 static const char *crypt_keyid (crypt_key_t * k)
152 const char *s = "????????";
154 if (k->kobj && k->kobj->subkeys) {
155 s = k->kobj->subkeys->keyid;
156 if ((!option (OPTPGPLONGIDS)) && (m_strlen(s) == 16))
157 /* Return only the short keyID. */
164 /* Return the hexstring fingerprint from the key K. */
165 static const char *crypt_fpr (crypt_key_t * k)
169 if (k->kobj && k->kobj->subkeys)
170 s = k->kobj->subkeys->fpr;
175 /* Parse FLAGS and return a statically allocated(!) string with them. */
176 static char *crypt_key_abilities (int flags)
180 if (!(flags & KEYFLAG_CANENCRYPT))
182 else if (flags & KEYFLAG_PREFER_SIGNING)
187 if (!(flags & KEYFLAG_CANSIGN))
189 else if (flags & KEYFLAG_PREFER_ENCRYPTION)
199 /* Parse FLAGS and return a character describing the most important flag. */
200 static char crypt_flags (int flags)
202 if (flags & KEYFLAG_REVOKED)
204 else if (flags & KEYFLAG_EXPIRED)
206 else if (flags & KEYFLAG_DISABLED)
208 else if (flags & KEYFLAG_CRITICAL)
214 /* Return a copy of KEY. */
215 static crypt_key_t *crypt_copy_key (crypt_key_t *key)
219 k = p_new(crypt_key_t, 1);
221 gpgme_key_ref (key->kobj);
224 k->flags = key->flags;
229 /* Release all the keys at the address of KEYLIST and set the address
231 static void crypt_free_key (crypt_key_t ** keylist)
234 crypt_key_t *k = (*keylist)->next;
241 /* Return trute when key K is valid. */
242 static int crypt_key_is_valid (crypt_key_t * k)
244 if (k->flags & KEYFLAG_CANTUSE)
249 /* Return true whe validity of KEY is sufficient. */
250 static int crypt_id_is_strong (crypt_key_t * key)
252 gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
253 gpgme_user_id_t uid = NULL;
257 if ((key->flags & KEYFLAG_ISX509))
260 for (i = 0, uid = key->kobj->uids; (i < key->idx) && uid;
261 i++, uid = uid->next);
266 case GPGME_VALIDITY_UNKNOWN:
267 case GPGME_VALIDITY_UNDEFINED:
268 case GPGME_VALIDITY_NEVER:
269 case GPGME_VALIDITY_MARGINAL:
273 case GPGME_VALIDITY_FULL:
274 case GPGME_VALIDITY_ULTIMATE:
282 /* Return true when the KEY is valid, i.e. not marked as unusable. */
283 static int crypt_id_is_valid (crypt_key_t * key)
285 return !(key->flags & KEYFLAG_CANTUSE);
288 /* Return a bit vector describing how well the addresses ADDR and
289 U_ADDR match and whether KEY is valid. */
290 static int crypt_id_matches_addr (address_t * addr, address_t * u_addr,
295 if (crypt_id_is_valid (key))
296 rv |= CRYPT_KV_VALID;
298 if (crypt_id_is_strong (key))
299 rv |= CRYPT_KV_STRONGID;
301 if (addr->mailbox && u_addr->mailbox
302 && m_strcasecmp(addr->mailbox, u_addr->mailbox) == 0)
305 if (addr->personal && u_addr->personal
306 && m_strcasecmp(addr->personal, u_addr->personal) == 0)
307 rv |= CRYPT_KV_STRING;
314 * GPGME convenient functions.
317 /* Create a new gpgme context and return it. With FOR_SMIME set to
318 true, the protocol of the context is set to CMS. */
319 static gpgme_ctx_t create_gpgme_context (int for_smime)
324 err = gpgme_new (&ctx);
326 mutt_error (_("error creating gpgme context: %s\n"), gpgme_strerror (err));
332 err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
334 mutt_error (_("error enabling CMS protocol: %s\n"), gpgme_strerror (err));
343 /* Create a new gpgme data object. This is a wrapper to die on
345 static gpgme_data_t create_gpgme_data (void)
350 err = gpgme_data_new (&data);
352 mutt_error (_("error creating gpgme data object: %s\n"),
353 gpgme_strerror (err));
360 /* Create a new GPGME Data object from the mail body A. With CONVERT
361 passed as true, the lines are converted to CR,LF if required.
362 Return NULL on error or the gpgme_data_t object on success. */
363 static gpgme_data_t body_to_data_object (BODY * a, int convert)
365 char tempfile[_POSIX_PATH_MAX];
370 mutt_mktemp (tempfile);
371 fptmp = safe_fopen (tempfile, "w+");
373 mutt_perror (tempfile);
377 mutt_write_mime_header (a, fptmp);
379 mutt_write_mime_body (a, fptmp);
383 unsigned char buf[1];
385 data = create_gpgme_data ();
387 while ((c = fgetc (fptmp)) != EOF) {
391 if (c == '\n' && !hadcr) {
393 gpgme_data_write (data, buf, 1);
398 /* FIXME: This is quite suboptimal */
400 gpgme_data_write (data, buf, 1);
403 gpgme_data_seek (data, 0, SEEK_SET);
407 err = gpgme_data_new_from_file (&data, tempfile, 1);
411 mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
418 /* Create a GPGME data object from the stream FP but limit the object
419 to LENGTH bytes starting at OFFSET bytes from the beginning of the
421 static gpgme_data_t file_to_data_object (FILE * fp, long offset, long length)
426 err = gpgme_data_new_from_filepart (&data, NULL, fp, offset, length);
428 mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
435 /* Write a GPGME data object to the stream FP. */
436 static int data_object_to_stream (gpgme_data_t data, FILE * fp)
442 err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1)
443 ? gpgme_error_from_errno (errno) : 0);
445 mutt_error (_("error rewinding data object: %s\n"), gpgme_strerror (err));
449 while ((nread = gpgme_data_read (data, buf, sizeof (buf)))) {
450 /* fixme: we are not really converting CRLF to LF but just
451 skipping CR. Doing it correctly needs a more complex logic */
452 for (p = buf; nread; p++, nread--) {
458 mutt_perror ("[tempfile]");
463 mutt_error (_("error reading data object: %s\n"), strerror (errno));
469 /* Copy a data object to a newly created temporay file and return that
470 filename. Caller must free. With RET_FP not NULL, don't close the
471 stream but return it there. */
472 static char *data_object_to_tempfile (gpgme_data_t data, FILE ** ret_fp)
475 char tempfile[_POSIX_PATH_MAX];
479 mutt_mktemp (tempfile);
480 fp = safe_fopen (tempfile, "w+");
482 mutt_perror (tempfile);
486 err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1)
487 ? gpgme_error_from_errno (errno) : 0);
491 while ((nread = gpgme_data_read (data, buf, sizeof (buf)))) {
492 if (fwrite (buf, nread, 1, fp) != 1) {
493 mutt_perror (tempfile);
505 mutt_error (_("error reading data object: %s\n"), gpgme_strerror (err));
512 return m_strdup(tempfile);
516 /* Create a GpgmeRecipientSet from the keys in the string KEYLIST.
517 The keys must be space delimited. */
518 static gpgme_key_t *create_recipient_set (const char *keylist,
519 gpgme_protocol_t protocol)
525 gpgme_key_t *rset = NULL;
526 unsigned int rset_n = 0;
527 gpgme_key_t key = NULL;
528 gpgme_ctx_t context = NULL;
530 err = gpgme_new (&context);
532 err = gpgme_set_protocol (context, protocol);
539 for (i = 0; *s && *s != ' ' && i < ssizeof(buf) - 1;)
543 if (i > 1 && buf[i - 1] == '!') {
544 /* The user selected to override the valididy of that
548 err = gpgme_get_key (context, buf, &key, 0);
550 key->uids->validity = GPGME_VALIDITY_FULL;
554 err = gpgme_get_key (context, buf, &key, 0);
557 p_realloc(&rset, rset_n + 1);
558 rset[rset_n++] = key;
561 mutt_error (_("error adding recipient `%s': %s\n"),
562 buf, gpgme_strerror (err));
570 /* NULL terminate. */
571 p_realloc(&rset, rset_n + 1);
572 rset[rset_n++] = NULL;
575 gpgme_release (context);
581 /* Make sure that the correct signer is set. Returns 0 on success. */
582 static int set_signer (gpgme_ctx_t ctx, int for_smime)
584 char *signid = for_smime ? SmimeDefaultKey : PgpSignAs;
587 gpgme_key_t key, key2;
589 if (!signid || !*signid)
592 listctx = create_gpgme_context (for_smime);
593 err = gpgme_op_keylist_start (listctx, signid, 1);
595 err = gpgme_op_keylist_next (listctx, &key);
597 gpgme_release (listctx);
598 mutt_error (_("secret key `%s' not found: %s\n"),
599 signid, gpgme_strerror (err));
602 err = gpgme_op_keylist_next (listctx, &key2);
604 gpgme_key_release (key);
605 gpgme_key_release (key2);
606 gpgme_release (listctx);
607 mutt_error (_("ambiguous specification of secret key `%s'\n"), signid);
610 gpgme_op_keylist_end (listctx);
611 gpgme_release (listctx);
613 gpgme_signers_clear (ctx);
614 err = gpgme_signers_add (ctx, key);
615 gpgme_key_release (key);
617 mutt_error (_("error setting secret key `%s': %s\n"),
618 signid, gpgme_strerror (err));
625 /* Encrypt the gpgme data object PLAINTEXT to the recipients in RSET
626 and return an allocated filename to a temporary file containing the
627 enciphered text. With USE_SMIME set to true, the smime backend is
628 used. With COMBINED_SIGNED a PGP message is signed and
629 encrypted. Returns NULL in case of error */
630 static char *encrypt_gpgme_object (gpgme_data_t plaintext, gpgme_key_t * rset,
631 int use_smime, int combined_signed)
635 gpgme_data_t ciphertext;
638 ctx = create_gpgme_context (use_smime);
640 gpgme_set_armor (ctx, 1);
642 ciphertext = create_gpgme_data ();
644 if (combined_signed) {
645 if (set_signer (ctx, use_smime)) {
646 gpgme_data_release (ciphertext);
650 err = gpgme_op_encrypt_sign (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST,
651 plaintext, ciphertext);
654 err = gpgme_op_encrypt (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST,
655 plaintext, ciphertext);
656 mutt_need_hard_redraw ();
658 mutt_error (_("error encrypting data: %s\n"), gpgme_strerror (err));
659 gpgme_data_release (ciphertext);
666 outfile = data_object_to_tempfile (ciphertext, NULL);
667 gpgme_data_release (ciphertext);
671 /* Find the "micalg" parameter from the last Gpgme operation on
672 context CTX. It is expected that this operation was a sign
673 operation. Return the algorithm name as a C string in buffer BUF
674 which must have been allocated by the caller with size BUFLEN.
675 Returns 0 on success or -1 in case of an error. The return string
676 is truncted to BUFLEN - 1. */
677 static int get_micalg (gpgme_ctx_t ctx, char *buf, ssize_t buflen)
679 gpgme_sign_result_t result = NULL;
680 const char *algorithm_name = NULL;
686 result = gpgme_op_sign_result (ctx);
688 algorithm_name = gpgme_hash_algo_name (result->signatures->hash_algo);
689 if (algorithm_name) {
690 m_strcpy(buf, buflen, algorithm_name);
694 return *buf ? 0 : -1;
697 static void print_time (time_t t, STATE * s)
701 setlocale (LC_TIME, "");
702 #ifdef HAVE_LANGINFO_D_T_FMT
703 strftime (p, sizeof (p), nl_langinfo (D_T_FMT), localtime (&t));
705 strftime (p, sizeof (p), "%c", localtime (&t));
707 setlocale (LC_TIME, "C");
708 state_attach_puts (p, s);
712 * Implementation of `sign_message'.
715 /* Sign the MESSAGE in body A either using OpenPGP or S/MIME when
716 USE_SMIME is passed as true. Returns the new body or NULL on
718 static BODY *sign_message (BODY * a, int use_smime)
725 gpgme_data_t message, signature;
727 convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */
729 message = body_to_data_object (a, 1);
732 signature = create_gpgme_data ();
734 ctx = create_gpgme_context (use_smime);
736 gpgme_set_armor (ctx, 1);
738 if (set_signer (ctx, use_smime)) {
739 gpgme_data_release (signature);
744 err = gpgme_op_sign (ctx, message, signature, GPGME_SIG_MODE_DETACH);
745 mutt_need_hard_redraw ();
746 gpgme_data_release (message);
748 gpgme_data_release (signature);
750 mutt_error (_("error signing data: %s\n"), gpgme_strerror (err));
754 sigfile = data_object_to_tempfile (signature, NULL);
755 gpgme_data_release (signature);
761 t = mutt_new_body ();
762 t->type = TYPEMULTIPART;
763 t->subtype = m_strdup("signed");
764 t->encoding = ENC7BIT;
766 t->disposition = DISPINLINE;
768 mutt_generate_boundary (&t->parameter);
769 mutt_set_parameter ("protocol",
770 use_smime ? "application/pkcs7-signature"
771 : "application/pgp-signature", &t->parameter);
772 /* Get the micalg from gpgme. Old gpgme versions don't support this
773 for S/MIME so we assume sha-1 in this case. */
774 if (!get_micalg (ctx, buf, sizeof buf))
775 mutt_set_parameter ("micalg", buf, &t->parameter);
777 mutt_set_parameter ("micalg", "sha1", &t->parameter);
783 t->parts->next = mutt_new_body ();
785 t->type = TYPEAPPLICATION;
787 t->subtype = m_strdup("pkcs7-signature");
788 mutt_set_parameter ("name", "smime.p7s", &t->parameter);
789 t->encoding = ENCBASE64;
791 t->disposition = DISPATTACH;
792 t->d_filename = m_strdup("smime.p7s");
795 t->subtype = m_strdup("pgp-signature");
797 t->disposition = DISPINLINE;
798 t->encoding = ENC7BIT;
800 t->filename = sigfile;
801 t->unlink = 1; /* ok to remove this file after sending. */
807 BODY *pgp_gpgme_sign_message (BODY * a)
809 return sign_message (a, 0);
812 BODY *smime_gpgme_sign_message (BODY * a)
814 return sign_message (a, 1);
818 * Implementation of `encrypt_message'.
821 /* Encrypt the mail body A to all keys given as space separated keyids
822 or fingerprints in KEYLIST and return the encrypted body. */
823 BODY *pgp_gpgme_encrypt_message (BODY * a, char *keylist, int sign)
825 char *outfile = NULL;
827 gpgme_key_t *rset = NULL;
828 gpgme_data_t plaintext;
830 rset = create_recipient_set (keylist, GPGME_PROTOCOL_OpenPGP);
836 plaintext = body_to_data_object (a, 0);
842 outfile = encrypt_gpgme_object (plaintext, rset, 0, sign);
843 gpgme_data_release (plaintext);
848 t = mutt_new_body ();
849 t->type = TYPEMULTIPART;
850 t->subtype = m_strdup("encrypted");
851 t->encoding = ENC7BIT;
853 t->disposition = DISPINLINE;
855 mutt_generate_boundary (&t->parameter);
856 mutt_set_parameter ("protocol", "application/pgp-encrypted", &t->parameter);
858 t->parts = mutt_new_body ();
859 t->parts->type = TYPEAPPLICATION;
860 t->parts->subtype = m_strdup("pgp-encrypted");
861 t->parts->encoding = ENC7BIT;
863 t->parts->next = mutt_new_body ();
864 t->parts->next->type = TYPEAPPLICATION;
865 t->parts->next->subtype = m_strdup("octet-stream");
866 t->parts->next->encoding = ENC7BIT;
867 t->parts->next->filename = outfile;
868 t->parts->next->use_disp = 1;
869 t->parts->next->disposition = DISPINLINE;
870 t->parts->next->unlink = 1; /* delete after sending the message */
871 t->parts->next->d_filename = m_strdup("msg.asc"); /* non pgp/mime
878 * Implementation of `smime_build_smime_entity'.
881 /* Encrypt the mail body A to all keys given as space separated
882 fingerprints in KEYLIST and return the S/MIME encrypted body. */
883 BODY *smime_gpgme_build_smime_entity (BODY * a, char *keylist)
885 char *outfile = NULL;
887 gpgme_key_t *rset = NULL;
888 gpgme_data_t plaintext;
890 rset = create_recipient_set (keylist, GPGME_PROTOCOL_CMS);
894 plaintext = body_to_data_object (a, 0);
900 outfile = encrypt_gpgme_object (plaintext, rset, 1, 0);
901 gpgme_data_release (plaintext);
906 t = mutt_new_body ();
907 t->type = TYPEAPPLICATION;
908 t->subtype = m_strdup("pkcs7-mime");
909 mutt_set_parameter ("name", "smime.p7m", &t->parameter);
910 mutt_set_parameter ("smime-type", "enveloped-data", &t->parameter);
911 t->encoding = ENCBASE64; /* The output of OpenSSL SHOULD be binary */
913 t->disposition = DISPATTACH;
914 t->d_filename = m_strdup("smime.p7m");
915 t->filename = outfile;
916 t->unlink = 1; /*delete after sending the message */
925 * Implementation of `verify_one'.
928 /* Display the common attributes of the signature summary SUM.
929 Return 1 if there is is a severe warning.
931 static int show_sig_summary (unsigned long sum,
932 gpgme_ctx_t ctx, gpgme_key_t key, int idx,
937 if ((sum & GPGME_SIGSUM_KEY_REVOKED)) {
938 state_attach_puts (_("Warning: One of the keys has been revoked\n"), s);
942 if ((sum & GPGME_SIGSUM_KEY_EXPIRED)) {
943 time_t at = key->subkeys->expires ? key->subkeys->expires : 0;
946 state_attach_puts (_("Warning: The key used to create the "
947 "signature expired at: "), s);
949 state_attach_puts ("\n", s);
952 state_attach_puts (_("Warning: At least one certification key "
953 "has expired\n"), s);
956 if ((sum & GPGME_SIGSUM_SIG_EXPIRED)) {
957 gpgme_verify_result_t result;
958 gpgme_signature_t sig;
961 result = gpgme_op_verify_result (ctx);
963 for (sig = result->signatures, i = 0; sig && (i < idx);
964 sig = sig->next, i++);
966 state_attach_puts (_("Warning: The signature expired at: "), s);
967 print_time (sig ? sig->exp_timestamp : 0, s);
968 state_attach_puts ("\n", s);
971 if ((sum & GPGME_SIGSUM_KEY_MISSING))
972 state_attach_puts (_("Can't verify due to a missing "
973 "key or certificate\n"), s);
975 if ((sum & GPGME_SIGSUM_CRL_MISSING)) {
976 state_attach_puts (_("The CRL is not available\n"), s);
980 if ((sum & GPGME_SIGSUM_CRL_TOO_OLD)) {
981 state_attach_puts (_("Available CRL is too old\n"), s);
985 if ((sum & GPGME_SIGSUM_BAD_POLICY))
986 state_attach_puts (_("A policy requirement was not met\n"), s);
988 if ((sum & GPGME_SIGSUM_SYS_ERROR)) {
989 const char *t0 = NULL, *t1 = NULL;
990 gpgme_verify_result_t result;
991 gpgme_signature_t sig;
994 state_attach_puts (_("A system error occurred"), s);
996 /* Try to figure out some more detailed system error information. */
997 result = gpgme_op_verify_result (ctx);
998 for (sig = result->signatures, i = 0; sig && (i < idx);
999 sig = sig->next, i++);
1002 t1 = sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
1006 state_attach_puts (": ", s);
1008 state_attach_puts (t0, s);
1009 if (t1 && !(t0 && !m_strcmp(t0, t1))) {
1011 state_attach_puts (",", s);
1012 state_attach_puts (t1, s);
1015 state_attach_puts ("\n", s);
1022 static void show_fingerprint (gpgme_key_t key, STATE * state)
1027 const char *prefix = _("Fingerprint: ");
1031 s = key->subkeys ? key->subkeys->fpr : NULL;
1034 is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
1036 buf = xmalloc(m_strlen(prefix) + m_strlen(s) * 4 + 2);
1037 strcpy (buf, prefix); /* __STRCPY_CHECKED__ */
1038 p = buf + m_strlen(buf);
1039 if (is_pgp && m_strlen(s) == 40) { /* PGP v4 style formatted. */
1040 for (i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) {
1051 for (i = 0; *s && s[1] && s[2]; s += 2, i++) {
1054 *p++ = is_pgp ? ' ' : ':';
1055 if (is_pgp && i == 7)
1060 /* just in case print remaining odd digits */
1065 state_attach_puts (buf, state);
1069 /* Show the valididy of a key used for one signature. */
1070 static void show_one_sig_validity (gpgme_ctx_t ctx, int idx, STATE * s)
1072 gpgme_verify_result_t result = NULL;
1073 gpgme_signature_t sig = NULL;
1074 const char *txt = NULL;
1076 result = gpgme_op_verify_result (ctx);
1078 for (sig = result->signatures; sig && (idx > 0); sig = sig->next, idx--);
1080 switch (sig ? sig->validity : 0) {
1081 case GPGME_VALIDITY_UNKNOWN:
1082 txt = _("WARNING: We have NO indication whether "
1083 "the key belongs to the person named " "as shown above\n");
1085 case GPGME_VALIDITY_UNDEFINED:
1087 case GPGME_VALIDITY_NEVER:
1088 txt = _("WARNING: The key does NOT BELONG to "
1089 "the person named as shown above\n");
1091 case GPGME_VALIDITY_MARGINAL:
1092 txt = _("WARNING: It is NOT certain that the key "
1093 "belongs to the person named as shown above\n");
1095 case GPGME_VALIDITY_FULL:
1096 case GPGME_VALIDITY_ULTIMATE:
1101 state_attach_puts (txt, s);
1104 /* Show information about one signature. This fucntion is called with
1105 the context CTX of a sucessful verification operation and the
1106 enumerator IDX which should start at 0 and incremete for each
1109 Return values are: 0 for normal procession, 1 for a bad signature,
1110 2 for a signature with a warning or -1 for no more signature. */
1111 static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE * s)
1114 const char *fpr, *uid;
1115 gpgme_key_t key = NULL;
1116 int i, anybad = 0, anywarn = 0;
1118 gpgme_user_id_t uids = NULL;
1119 gpgme_verify_result_t result;
1120 gpgme_signature_t sig;
1121 gpgme_error_t err = GPG_ERR_NO_ERROR;
1123 result = gpgme_op_verify_result (ctx);
1125 /* FIXME: this code should use a static variable and remember
1126 the current position in the list of signatures, IMHO.
1129 for (i = 0, sig = result->signatures; sig && (i < idx);
1130 i++, sig = sig->next);
1132 return -1; /* Signature not found. */
1134 if (signature_key) {
1135 gpgme_key_release (signature_key);
1136 signature_key = NULL;
1139 created = sig->timestamp;
1143 if (gpg_err_code (sig->status) != GPG_ERR_NO_ERROR)
1146 err = gpgme_get_key (ctx, fpr, &key, 0); /* secret key? */
1148 uid = (key->uids && key->uids->uid) ? key->uids->uid : "[?]";
1150 signature_key = key;
1153 key = NULL; /* Old gpgme versions did not set KEY to NULL on
1154 error. Do it here to avoid a double free. */
1158 if (!s || !s->fpout || !(s->flags & M_DISPLAY)); /* No state information so no way to print anything. */
1160 state_attach_puts (_("Error getting key information: "), s);
1161 state_attach_puts (gpg_strerror (err), s);
1162 state_attach_puts ("\n", s);
1165 else if ((sum & GPGME_SIGSUM_GREEN)) {
1166 state_attach_puts (_("Good signature from: "), s);
1167 state_attach_puts (uid, s);
1168 state_attach_puts ("\n", s);
1169 for (i = 1, uids = key->uids; uids; i++, uids = uids->next) {
1171 /* Skip primary UID. */
1175 state_attach_puts (_(" aka: "), s);
1176 state_attach_puts (uids->uid, s);
1177 state_attach_puts ("\n", s);
1179 state_attach_puts (_(" created: "), s);
1180 print_time (created, s);
1181 state_attach_puts ("\n", s);
1182 if (show_sig_summary (sum, ctx, key, idx, s))
1184 show_one_sig_validity (ctx, idx, s);
1186 else if ((sum & GPGME_SIGSUM_RED)) {
1187 state_attach_puts (_("*BAD* signature claimed to be from: "), s);
1188 state_attach_puts (uid, s);
1189 state_attach_puts ("\n", s);
1190 show_sig_summary (sum, ctx, key, idx, s);
1192 else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP)) { /* We can't decide (yellow) but this is a PGP key with a good
1193 signature, so we display what a PGP user expects: The name,
1194 fingerprint and the key validity (which is neither fully or
1196 state_attach_puts (_("Good signature from: "), s);
1197 state_attach_puts (uid, s);
1198 state_attach_puts ("\n", s);
1199 state_attach_puts (_(" created: "), s);
1200 print_time (created, s);
1201 state_attach_puts ("\n", s);
1202 show_one_sig_validity (ctx, idx, s);
1203 show_fingerprint (key, s);
1204 if (show_sig_summary (sum, ctx, key, idx, s))
1207 else { /* can't decide (yellow) */
1209 state_attach_puts (_("Error checking signature"), s);
1210 state_attach_puts ("\n", s);
1211 show_sig_summary (sum, ctx, key, idx, s);
1214 if (key != signature_key)
1215 gpgme_key_release (key);
1218 return anybad ? 1 : anywarn ? 2 : 0;
1221 /* Do the actual verification step. With IS_SMIME set to true we
1222 assume S/MIME (surprise!) */
1223 static int verify_one (BODY * sigbdy, STATE * s,
1224 const char *tempfile, int is_smime)
1230 gpgme_data_t signature, message;
1232 signature = file_to_data_object (s->fpin, sigbdy->offset, sigbdy->length);
1236 /* We need to tell gpgme about the encoding because the backend can't
1237 auto-detect plain base-64 encoding which is used by S/MIME. */
1239 gpgme_data_set_encoding (signature, GPGME_DATA_ENCODING_BASE64);
1241 err = gpgme_data_new_from_file (&message, tempfile, 1);
1243 gpgme_data_release (signature);
1244 mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
1247 ctx = create_gpgme_context (is_smime);
1249 /* Note: We don't need a current time output because GPGME avoids
1250 such an attack by separating the meta information from the
1252 state_attach_puts (_("[-- Begin signature information --]\n"), s);
1254 err = gpgme_op_verify (ctx, signature, message, NULL);
1255 mutt_need_hard_redraw ();
1259 snprintf (buf, sizeof (buf) - 1,
1260 _("Error: verification failed: %s\n"), gpgme_strerror (err));
1261 state_attach_puts (buf, s);
1263 else { /* Verification succeeded, see what the result is. */
1267 if (signature_key) {
1268 gpgme_key_release (signature_key);
1269 signature_key = NULL;
1272 for (idx = 0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) {
1283 gpgme_verify_result_t result;
1284 gpgme_sig_notation_t notation;
1285 gpgme_signature_t sig;
1287 result = gpgme_op_verify_result (ctx);
1289 for (sig = result->signatures; sig; sig = sig->next) {
1290 if (sig->notations) {
1291 state_attach_puts ("*** Begin Notation (signature by: ", s);
1292 state_attach_puts (sig->fpr, s);
1293 state_attach_puts (") ***\n", s);
1294 for (notation = sig->notations; notation; notation = notation->next)
1296 if (notation->name) {
1297 state_attach_puts (notation->name, s);
1298 state_attach_puts ("=", s);
1300 if (notation->value) {
1301 state_attach_puts (notation->value, s);
1302 if (!(*notation->value
1303 && (notation->value[m_strlen(notation->value) - 1] ==
1305 state_attach_puts ("\n", s);
1308 state_attach_puts ("*** End Notation ***\n", s);
1314 gpgme_release (ctx);
1316 state_attach_puts (_("[-- End signature information --]\n\n"), s);
1318 return badsig ? 1 : anywarn ? 2 : 0;
1321 int pgp_gpgme_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
1323 return verify_one (sigbdy, s, tempfile, 0);
1326 int smime_gpgme_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
1328 return verify_one (sigbdy, s, tempfile, 1);
1332 * Implementation of `decrypt_part'.
1335 /* Decrypt a PGP or SMIME message (depending on the boolean flag
1336 IS_SMIME) with body A described further by state S. Write
1337 plaintext out to file FPOUT and return a new body. For PGP returns
1338 a flag in R_IS_SIGNED to indicate whether this is a combined
1339 encrypted and signed message, for S/MIME it returns true when it is
1340 not a encrypted but a signed message. */
1341 static BODY *decrypt_part (BODY * a, STATE * s, FILE * fpout, int is_smime,
1348 gpgme_data_t ciphertext, plaintext;
1349 int maybe_signed = 0;
1356 ctx = create_gpgme_context (is_smime);
1359 /* Make a data object from the body, create context etc. */
1360 ciphertext = file_to_data_object (s->fpin, a->offset, a->length);
1363 plaintext = create_gpgme_data ();
1365 /* Do the decryption or the verification in case of the S/MIME hack. */
1366 if ((!is_smime) || maybe_signed) {
1368 err = gpgme_op_decrypt_verify (ctx, ciphertext, plaintext);
1369 else if (maybe_signed)
1370 err = gpgme_op_verify (ctx, ciphertext, NULL, plaintext);
1373 /* Check wether signatures have been verified. */
1374 gpgme_verify_result_t verify_result = gpgme_op_verify_result (ctx);
1376 if (verify_result->signatures)
1381 err = gpgme_op_decrypt (ctx, ciphertext, plaintext);
1382 gpgme_data_release (ciphertext);
1384 if (is_smime && !maybe_signed && gpg_err_code (err) == GPG_ERR_NO_DATA) {
1385 /* Check whether this might be a signed message despite what
1386 the mime header told us. Retry then. gpgsm returns the
1387 error information "unsupported Algorithm '?'" but gpgme
1388 will not store this unknown algorithm, thus we test that
1389 it has not been set. */
1390 gpgme_decrypt_result_t result;
1392 result = gpgme_op_decrypt_result (ctx);
1393 if (!result->unsupported_algorithm) {
1395 gpgme_data_release (plaintext);
1399 mutt_need_hard_redraw ();
1400 if ((s->flags & M_DISPLAY)) {
1403 snprintf (buf, sizeof (buf) - 1,
1404 _("[-- Error: decryption failed: %s --]\n\n"),
1405 gpgme_strerror (err));
1406 state_attach_puts (buf, s);
1408 gpgme_data_release (plaintext);
1409 gpgme_release (ctx);
1412 mutt_need_hard_redraw ();
1414 /* Read the output from GPGME, and make sure to change CRLF to LF,
1415 otherwise read_mime_header has a hard time parsing the message. */
1416 if (data_object_to_stream (plaintext, fpout)) {
1417 gpgme_data_release (plaintext);
1418 gpgme_release (ctx);
1421 gpgme_data_release (plaintext);
1423 a->is_signed_data = 0;
1429 a->is_signed_data = 1;
1431 *r_is_signed = -1; /* A signature exists. */
1433 if ((s->flags & M_DISPLAY))
1434 state_attach_puts (_("[-- Begin signature " "information --]\n"), s);
1435 for (idx = 0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) {
1441 if (!anybad && idx && r_is_signed && *r_is_signed)
1442 *r_is_signed = anywarn ? 2 : 1; /* Good signature. */
1444 if ((s->flags & M_DISPLAY))
1445 state_attach_puts (_("[-- End signature " "information --]\n\n"), s);
1447 gpgme_release (ctx);
1452 tattach = mutt_read_mime_header (fpout, 0);
1455 * Need to set the length of this body part.
1457 fstat (fileno (fpout), &info);
1458 tattach->length = info.st_size - tattach->offset;
1460 tattach->warnsig = anywarn;
1462 /* See if we need to recurse on this MIME part. */
1463 mutt_parse_part (fpout, tattach);
1469 /* Decrypt a PGP/MIME message in FPIN and B and return a new body and
1470 the stream in CUR and FPOUT. Returns 0 on success. */
1471 int pgp_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur)
1473 char tempfile[_POSIX_PATH_MAX];
1475 BODY *first_part = b;
1478 first_part->goodsig = 0;
1479 first_part->warnsig = 0;
1481 if (!mutt_is_multipart_encrypted (b))
1484 if (!b->parts || !b->parts->next)
1491 mutt_mktemp (tempfile);
1492 if (!(*fpout = safe_fopen (tempfile, "w+"))) {
1493 mutt_perror (tempfile);
1498 *cur = decrypt_part (b, &s, *fpout, 0, &is_signed);
1501 first_part->goodsig = 1;
1503 return *cur ? 0 : -1;
1507 /* Decrypt a S/MIME message in FPIN and B and return a new body and
1508 the stream in CUR and FPOUT. Returns 0 on success. */
1509 int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b,
1512 char tempfile[_POSIX_PATH_MAX];
1516 long saved_b_offset;
1517 ssize_t saved_b_length;
1520 if (!mutt_is_application_smime (b))
1526 /* Decode the body - we need to pass binary CMS to the
1527 backend. The backend allows for Base64 encoded data but it does
1528 not allow for QP which I have seen in some messages. So better
1530 saved_b_type = b->type;
1531 saved_b_offset = b->offset;
1532 saved_b_length = b->length;
1535 fseeko (s.fpin, b->offset, 0);
1536 mutt_mktemp (tempfile);
1537 if (!(tmpfp = safe_fopen (tempfile, "w+"))) {
1538 mutt_perror (tempfile);
1541 mutt_unlink (tempfile);
1544 mutt_decode_attachment (b, &s);
1546 b->length = ftello (s.fpout);
1553 mutt_mktemp (tempfile);
1554 if (!(*fpout = safe_fopen (tempfile, "w+"))) {
1555 mutt_perror (tempfile);
1558 mutt_unlink (tempfile);
1560 *cur = decrypt_part (b, &s, *fpout, 1, &is_signed);
1562 (*cur)->goodsig = is_signed > 0;
1563 b->type = saved_b_type;
1564 b->length = saved_b_length;
1565 b->offset = saved_b_offset;
1568 if (*cur && !is_signed && !(*cur)->parts
1569 && mutt_is_application_smime (*cur)) {
1570 /* Assume that this is a opaque signed s/mime message. This is
1571 an ugly way of doing it but we have anyway a problem with
1572 arbitrary encoded S/MIME messages: Only the outer part may be
1573 encrypted. The entire mime parsing should be revamped,
1574 probably by keeping the temportary files so that we don't
1575 need to decrypt them all the time. Inner parts of an
1576 encrypted part can then pint into this file and tehre won't
1577 never be a need to decrypt again. This needs a partial
1578 rewrite of the MIME engine. */
1582 saved_b_type = bb->type;
1583 saved_b_offset = bb->offset;
1584 saved_b_length = bb->length;
1587 fseeko (s.fpin, bb->offset, 0);
1588 mutt_mktemp (tempfile);
1589 if (!(tmpfp = safe_fopen (tempfile, "w+"))) {
1590 mutt_perror (tempfile);
1593 mutt_unlink (tempfile);
1596 mutt_decode_attachment (bb, &s);
1598 bb->length = ftello (s.fpout);
1606 mutt_mktemp (tempfile);
1607 if (!(*fpout = safe_fopen (tempfile, "w+"))) {
1608 mutt_perror (tempfile);
1611 mutt_unlink (tempfile);
1613 tmp_b = decrypt_part (bb, &s, *fpout, 1, &is_signed);
1615 tmp_b->goodsig = is_signed > 0;
1616 bb->type = saved_b_type;
1617 bb->length = saved_b_length;
1618 bb->offset = saved_b_offset;
1621 mutt_free_body (cur);
1624 return *cur ? 0 : -1;
1629 * Implementation of `pgp_check_traditional'.
1632 static int pgp_check_traditional_one_body (FILE * fp, BODY * b,
1635 char tempfile[_POSIX_PATH_MAX];
1636 char buf[HUGE_STRING];
1642 if (b->type != TYPETEXT)
1645 if (tagged_only && !b->tagged)
1648 mutt_mktemp (tempfile);
1649 if (mutt_decode_save_attachment (fp, b, tempfile, 0, 0) != 0) {
1654 if ((tfp = fopen (tempfile, "r")) == NULL) {
1659 while (fgets (buf, sizeof (buf), tfp)) {
1660 if (!m_strncmp("-----BEGIN PGP ", buf, 15)) {
1661 if (!m_strcmp("MESSAGE-----\n", buf + 15))
1663 else if (!m_strcmp("SIGNED MESSAGE-----\n", buf + 15))
1673 /* fix the content type */
1675 mutt_set_parameter ("format", "fixed", &b->parameter);
1676 mutt_set_parameter ("x-action", enc ? "pgp-encrypted" : "pgp-signed",
1682 int pgp_gpgme_check_traditional (FILE * fp, BODY * b, int tagged_only)
1687 for (; b; b = b->next) {
1688 if (is_multipart (b))
1689 rv = (pgp_gpgme_check_traditional (fp, b->parts, tagged_only) || rv);
1690 else if (b->type == TYPETEXT) {
1691 if ((r = mutt_is_application_pgp (b)))
1694 rv = (pgp_check_traditional_one_body (fp, b, tagged_only) || rv);
1702 * Implementation of `application_handler'.
1706 Copy a clearsigned message, and strip the signature and PGP's
1709 XXX - charset handling: We assume that it is safe to do
1710 character set decoding first, dash decoding second here, while
1711 we do it the other way around in the main handler.
1713 (Note that we aren't worse than Outlook & Cie in this, and also
1714 note that we can successfully handle anything produced by any
1715 existing versions of mutt.) */
1717 static void copy_clearsigned (gpgme_data_t data, STATE * s, char *charset)
1719 char buf[HUGE_STRING];
1720 short complete, armor_header;
1725 fname = data_object_to_tempfile (data, &fp);
1731 fc = fgetconv_open (fp, charset, Charset, M_ICONV_HOOK_FROM);
1733 for (complete = 1, armor_header = 1;
1734 fgetconvs (buf, sizeof (buf), fc) != NULL;
1735 complete = strchr (buf, '\n') != NULL) {
1738 state_puts (buf, s);
1742 if (!m_strcmp(buf, "-----BEGIN PGP SIGNATURE-----\n"))
1752 state_puts (s->prefix, s);
1754 if (buf[0] == '-' && buf[1] == ' ')
1755 state_puts (buf + 2, s);
1757 state_puts (buf, s);
1760 fgetconv_close (&fc);
1765 /* Support for classic_application/pgp */
1766 int pgp_gpgme_application_handler (BODY * m, STATE * s)
1768 int needpass = -1, pgp_keyblock = 0;
1772 off_t last_pos, offset;
1773 char buf[HUGE_STRING];
1774 FILE *pgpout = NULL;
1776 gpgme_error_t err = 0;
1777 gpgme_data_t armored_data = NULL;
1779 short maybe_goodsig = 1;
1780 short have_any_sigs = 0;
1782 char body_charset[STRING]; /* Only used for clearsigned messages. */
1784 /* For clearsigned messages we won't be able to get a character set
1785 but we know that this may only be text thus we assume Latin-1
1787 if (!mutt_get_body_charset (body_charset, sizeof (body_charset), m))
1788 m_strcpy(body_charset, sizeof(body_charset), "iso-8859-1");
1790 fseeko (s->fpin, m->offset, 0);
1791 last_pos = m->offset;
1793 for (bytes = m->length; bytes > 0;) {
1794 if (fgets (buf, sizeof (buf), s->fpin) == NULL)
1797 offset = ftello (s->fpin);
1798 bytes -= (offset - last_pos); /* don't rely on m_strlen(buf) */
1801 if (!m_strncmp("-----BEGIN PGP ", buf, 15)) {
1803 start_pos = last_pos;
1805 if (!m_strcmp("MESSAGE-----\n", buf + 15))
1807 else if (!m_strcmp("SIGNED MESSAGE-----\n", buf + 15)) {
1811 else if (!option (OPTDONTHANDLEPGPKEYS) &&
1812 !m_strcmp("PUBLIC KEY BLOCK-----\n", buf + 15)) {
1817 /* XXX - we may wish to recode here */
1819 state_puts (s->prefix, s);
1820 state_puts (buf, s);
1824 have_any_sigs = (have_any_sigs || (clearsign && (s->flags & M_VERIFY)));
1826 /* Copy PGP material to an data container */
1827 armored_data = create_gpgme_data ();
1828 gpgme_data_write (armored_data, buf, m_strlen(buf));
1829 while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL) {
1830 offset = ftello (s->fpin);
1831 bytes -= (offset - last_pos); /* don't rely on m_strlen(buf) */
1834 gpgme_data_write (armored_data, buf, m_strlen(buf));
1836 if ((needpass && !m_strcmp("-----END PGP MESSAGE-----\n", buf))
1838 && (!m_strcmp("-----END PGP SIGNATURE-----\n", buf)
1839 || !m_strcmp("-----END PGP PUBLIC KEY BLOCK-----\n",
1844 /* Invoke PGP if needed */
1845 if (!clearsign || (s->flags & M_VERIFY)) {
1846 unsigned int sig_stat = 0;
1847 gpgme_data_t plaintext;
1850 plaintext = create_gpgme_data ();
1851 ctx = create_gpgme_context (0);
1854 err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
1856 err = gpgme_op_decrypt_verify (ctx, armored_data, plaintext);
1857 if (gpg_err_code (err) == GPG_ERR_NO_DATA) {
1858 /* Decrypt verify can't handle signed only messages. */
1859 err = (gpgme_data_seek (armored_data, 0, SEEK_SET) == -1)
1860 ? gpgme_error_from_errno (errno) : 0;
1861 /* Must release plaintext so that we supply an
1862 uninitialized object. */
1863 gpgme_data_release (plaintext);
1864 plaintext = create_gpgme_data ();
1865 err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
1872 snprintf (errbuf, sizeof (errbuf) - 1,
1873 _("Error: decryption/verification failed: %s\n"),
1874 gpgme_strerror (err));
1875 state_attach_puts (errbuf, s);
1877 else { /* Decryption/Verification succeeded */
1881 /* Check wether signatures have been verified. */
1882 gpgme_verify_result_t verify_result;
1884 verify_result = gpgme_op_verify_result (ctx);
1885 if (verify_result->signatures)
1891 if ((s->flags & M_DISPLAY) && sig_stat) {
1896 state_attach_puts (_("[-- Begin signature "
1897 "information --]\n"), s);
1900 (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) {
1909 state_attach_puts (_("[-- End signature "
1910 "information --]\n\n"), s);
1913 tmpfname = data_object_to_tempfile (plaintext, &pgpout);
1916 state_attach_puts (_("Error: copy data failed\n"), s);
1920 p_delete(&tmpfname);
1923 gpgme_release (ctx);
1927 * Now, copy cleartext to the screen. NOTE - we expect that PGP
1928 * outputs utf-8 cleartext. This may not always be true, but it
1929 * seems to be a reasonable guess.
1932 if (s->flags & M_DISPLAY) {
1934 state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s);
1935 else if (pgp_keyblock)
1936 state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), s);
1938 state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), s);
1942 copy_clearsigned (armored_data, s, body_charset);
1949 fc = fgetconv_open (pgpout, "utf-8", Charset, 0);
1950 while ((c = fgetconv (fc)) != EOF) {
1952 if (c == '\n' && s->prefix)
1953 state_puts (s->prefix, s);
1955 fgetconv_close (&fc);
1958 if (s->flags & M_DISPLAY) {
1959 state_putc ('\n', s);
1961 state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
1962 else if (pgp_keyblock)
1963 state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
1965 state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
1969 safe_fclose (&pgpout);
1973 /* XXX - we may wish to recode here */
1975 state_puts (s->prefix, s);
1976 state_puts (buf, s);
1980 m->goodsig = (maybe_goodsig && have_any_sigs);
1982 if (needpass == -1) {
1983 state_attach_puts (_("[-- Error: could not find beginning"
1984 " of PGP message! --]\n\n"), s);
1991 * Implementation of `encrypted_handler'.
1994 /* MIME handler for pgp/mime encrypted messages. */
1995 int pgp_gpgme_encrypted_handler (BODY * a, STATE * s)
1997 char tempfile[_POSIX_PATH_MAX];
2000 BODY *orig_body = a;
2005 if (!a || a->type != TYPEAPPLICATION || !a->subtype
2006 || ascii_strcasecmp ("pgp-encrypted", a->subtype)
2007 || !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype
2008 || ascii_strcasecmp ("octet-stream", a->next->subtype)) {
2009 if (s->flags & M_DISPLAY)
2010 state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
2015 /* Move forward to the application/pgp-encrypted body. */
2018 mutt_mktemp (tempfile);
2019 if (!(fpout = safe_fopen (tempfile, "w+"))) {
2020 if (s->flags & M_DISPLAY)
2021 state_attach_puts (_("[-- Error: could not create temporary file! "
2026 tattach = decrypt_part (a, s, fpout, 0, &is_signed);
2028 tattach->goodsig = is_signed > 0;
2030 if (s->flags & M_DISPLAY)
2031 state_attach_puts (is_signed ?
2033 ("[-- The following data is PGP/MIME signed and encrypted --]\n\n") :
2034 _("[-- The following data is PGP/MIME encrypted --]\n\n"), s);
2037 FILE *savefp = s->fpin;
2040 rc = mutt_body_handler (tattach, s);
2045 * if a multipart/signed is the _only_ sub-part of a
2046 * multipart/encrypted, cache signature verification
2049 if (mutt_is_multipart_signed (tattach) && !tattach->next)
2050 orig_body->goodsig |= tattach->goodsig;
2052 if (s->flags & M_DISPLAY) {
2053 state_puts ("\n", s);
2054 state_attach_puts (is_signed ?
2056 ("[-- End of PGP/MIME signed and encrypted data --]\n")
2057 : _("[-- End of PGP/MIME encrypted data --]\n"), s);
2060 mutt_free_body (&tattach);
2064 mutt_unlink (tempfile);
2068 /* Support for application/smime */
2069 int smime_gpgme_application_handler (BODY * a, STATE * s)
2071 char tempfile[_POSIX_PATH_MAX];
2078 mutt_mktemp (tempfile);
2079 if (!(fpout = safe_fopen (tempfile, "w+"))) {
2080 if (s->flags & M_DISPLAY)
2081 state_attach_puts (_("[-- Error: could not create temporary file! "
2086 tattach = decrypt_part (a, s, fpout, 1, &is_signed);
2088 tattach->goodsig = is_signed > 0;
2090 if (s->flags & M_DISPLAY)
2091 state_attach_puts (is_signed ?
2092 _("[-- The following data is S/MIME signed --]\n\n") :
2093 _("[-- The following data is S/MIME encrypted --]\n\n"), s);
2096 FILE *savefp = s->fpin;
2099 rc = mutt_body_handler (tattach, s);
2104 * if a multipart/signed is the _only_ sub-part of a
2105 * multipart/encrypted, cache signature verification
2108 if (mutt_is_multipart_signed (tattach) && !tattach->next) {
2109 if (!(a->goodsig = tattach->goodsig))
2110 a->warnsig = tattach->warnsig;
2112 else if (tattach->goodsig) {
2114 a->warnsig = tattach->warnsig;
2117 if (s->flags & M_DISPLAY) {
2118 state_puts ("\n", s);
2119 state_attach_puts (is_signed ?
2120 _("[-- End of S/MIME signed data --]\n") :
2121 _("[-- End of S/MIME encrypted data --]\n"), s);
2124 mutt_free_body (&tattach);
2128 mutt_unlink (tempfile);
2134 * Format an entry on the CRYPT key selection menu.
2137 * %k key id %K key id of the principal key
2139 * %a algorithm %A algorithm of the princ. key
2140 * %l length %L length of the princ. key
2141 * %f flags %F flags of the princ. key
2142 * %c capabilities %C capabilities of the princ. key
2143 * %t trust/validity of the key-uid association
2145 * %[...] date of key using strftime(3)
2149 crypt_entry_fmt (char *dest, ssize_t destlen, char op,
2150 const char *src, const char *prefix,
2151 const char *ifstring, const char *elsestring,
2152 unsigned long data, format_flag flags)
2155 crypt_entry_t *entry;
2158 int optional = (flags & M_FORMAT_OPTIONAL);
2159 const char *s = NULL;
2162 entry = (crypt_entry_t *) data;
2165 /* if (isupper ((unsigned char) op)) */
2168 kflags = (key->flags /*| (pkey->flags & KEYFLAG_RESTRICTIONS)
2171 switch (ascii_tolower (op)) {
2175 char buf2[SHORT_STRING], *p;
2191 while (len > 0 && *cp != ']') {
2200 break; /* not enough space */
2210 if (do_locales && Locale)
2211 setlocale (LC_TIME, Locale);
2216 if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
2217 tt = key->kobj->subkeys->timestamp;
2219 tm = localtime (&tt);
2221 strftime (buf2, sizeof (buf2), dest, tm);
2224 setlocale (LC_TIME, "C");
2226 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2227 snprintf (dest, destlen, fmt, buf2);
2234 snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
2235 snprintf (dest, destlen, fmt, entry->num);
2240 /* fixme: we need a way to distinguish between main and subkeys.
2241 Store the idx in entry? */
2242 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2243 snprintf (dest, destlen, fmt, crypt_keyid (key));
2248 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2249 snprintf (dest, destlen, fmt, key->uid);
2254 snprintf (fmt, sizeof (fmt), "%%%s.3s", prefix);
2255 if (key->kobj->subkeys)
2256 s = gpgme_pubkey_algo_name (key->kobj->subkeys->pubkey_algo);
2259 snprintf (dest, destlen, fmt, s);
2264 snprintf (fmt, sizeof (fmt), "%%%slu", prefix);
2265 if (key->kobj->subkeys)
2266 val = key->kobj->subkeys->length;
2269 snprintf (dest, destlen, fmt, val);
2274 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2275 snprintf (dest, destlen, fmt, crypt_flags (kflags));
2277 else if (!(kflags & (KEYFLAG_RESTRICTIONS)))
2282 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2283 snprintf (dest, destlen, fmt, crypt_key_abilities (kflags));
2285 else if (!(kflags & (KEYFLAG_ABILITIES)))
2289 if ((kflags & KEYFLAG_ISX509))
2292 gpgme_user_id_t uid = NULL;
2295 for (i = 0, uid = key->kobj->uids; uid && (i < key->idx);
2296 i++, uid = uid->next);
2298 switch (uid->validity) {
2299 case GPGME_VALIDITY_UNDEFINED:
2302 case GPGME_VALIDITY_NEVER:
2305 case GPGME_VALIDITY_MARGINAL:
2308 case GPGME_VALIDITY_FULL:
2311 case GPGME_VALIDITY_ULTIMATE:
2314 case GPGME_VALIDITY_UNKNOWN:
2320 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2321 snprintf (dest, destlen, fmt, s ? *s : 'B');
2324 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2325 snprintf (dest, destlen, fmt,
2326 gpgme_get_protocol_name (key->kobj->protocol));
2334 mutt_FormatString (dest, destlen, ifstring, mutt_attach_fmt, data, 0);
2335 else if (flags & M_FORMAT_OPTIONAL)
2336 mutt_FormatString (dest, destlen, elsestring, mutt_attach_fmt, data, 0);
2340 /* Used by the display fucntion to format a line. */
2341 static void crypt_entry (char *s, ssize_t l, MUTTMENU * menu, int num)
2343 crypt_key_t **key_table = (crypt_key_t **) menu->data;
2344 crypt_entry_t entry;
2346 entry.key = key_table[num];
2347 entry.num = num + 1;
2349 mutt_FormatString (s, l, NONULL (PgpEntryFormat), crypt_entry_fmt,
2350 (unsigned long) &entry, M_FORMAT_ARROWCURSOR);
2353 /* Compare two addresses and the keyid to be used for sorting. */
2354 static int _crypt_compare_address (const void *a, const void *b)
2356 crypt_key_t **s = (crypt_key_t **) a;
2357 crypt_key_t **t = (crypt_key_t **) b;
2360 if ((r = m_strcasecmp((*s)->uid, (*t)->uid)))
2363 return m_strcasecmp(crypt_keyid (*s), crypt_keyid (*t)) > 0;
2366 static int crypt_compare_address (const void *a, const void *b)
2368 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_address (a, b)
2369 : _crypt_compare_address (a, b));
2373 /* Compare two key IDs and the addresses to be used for sorting. */
2374 static int _crypt_compare_keyid (const void *a, const void *b)
2376 crypt_key_t **s = (crypt_key_t **) a;
2377 crypt_key_t **t = (crypt_key_t **) b;
2380 if ((r = m_strcasecmp(crypt_keyid (*s), crypt_keyid (*t))))
2383 return m_strcasecmp((*s)->uid, (*t)->uid) > 0;
2386 static int crypt_compare_keyid (const void *a, const void *b)
2388 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_keyid (a, b)
2389 : _crypt_compare_keyid (a, b));
2392 /* Compare 2 creation dates and the addresses. For sorting. */
2393 static int _crypt_compare_date (const void *a, const void *b)
2395 crypt_key_t **s = (crypt_key_t **) a;
2396 crypt_key_t **t = (crypt_key_t **) b;
2397 unsigned long ts = 0, tt = 0;
2399 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2400 ts = (*s)->kobj->subkeys->timestamp;
2401 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2402 tt = (*t)->kobj->subkeys->timestamp;
2409 return m_strcasecmp((*s)->uid, (*t)->uid) > 0;
2412 static int crypt_compare_date (const void *a, const void *b)
2414 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_date (a, b)
2415 : _crypt_compare_date (a, b));
2418 /* Compare two trust values, the key length, the creation dates. the
2419 addresses and the key IDs. For sorting. */
2420 static int _crypt_compare_trust (const void *a, const void *b)
2422 crypt_key_t **s = (crypt_key_t **) a;
2423 crypt_key_t **t = (crypt_key_t **) b;
2424 unsigned long ts = 0, tt = 0;
2427 if ((r = (((*s)->flags & (KEYFLAG_RESTRICTIONS))
2428 - ((*t)->flags & (KEYFLAG_RESTRICTIONS)))))
2431 if ((*s)->kobj->uids)
2432 ts = (*s)->kobj->uids->validity;
2433 if ((*t)->kobj->uids)
2434 tt = (*t)->kobj->uids->validity;
2435 if ((r = (tt - ts)))
2438 if ((*s)->kobj->subkeys)
2439 ts = (*s)->kobj->subkeys->length;
2440 if ((*t)->kobj->subkeys)
2441 tt = (*t)->kobj->subkeys->length;
2445 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2446 ts = (*s)->kobj->subkeys->timestamp;
2447 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2448 tt = (*t)->kobj->subkeys->timestamp;
2454 if ((r = m_strcasecmp((*s)->uid, (*t)->uid)))
2456 return (m_strcasecmp(crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0;
2459 static int crypt_compare_trust (const void *a, const void *b)
2461 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_trust (a, b)
2462 : _crypt_compare_trust (a, b));
2465 /* Print the X.500 Distinguished Name part KEY from the array of parts
2467 static int print_dn_part (FILE * fp, struct dn_array_s *dn, const char *key)
2471 for (; dn->key; dn++) {
2472 if (!m_strcmp(dn->key, key)) {
2475 print_utf8 (fp, dn->value, m_strlen(dn->value));
2482 /* Print all parts of a DN in a standard sequence. */
2483 static void print_dn_parts (FILE * fp, struct dn_array_s *dn)
2485 const char *stdpart[] = {
2486 "CN", "OU", "O", "STREET", "L", "ST", "C", NULL
2488 int any = 0, any2 = 0, i;
2490 for (i = 0; stdpart[i]; i++) {
2493 any = print_dn_part (fp, dn, stdpart[i]);
2495 /* now print the rest without any specific ordering */
2496 for (; dn->key; dn++) {
2497 for (i = 0; stdpart[i]; i++) {
2498 if (!m_strcmp(dn->key, stdpart[i]))
2506 any = print_dn_part (fp, dn, dn->key);
2515 /* Parse an RDN; this is a helper to parse_dn(). */
2516 static const unsigned char *parse_dn_part (struct dn_array_s *array,
2517 const unsigned char *string)
2519 const unsigned char *s, *s1;
2523 /* parse attributeType */
2524 for (s = string + 1; *s && *s != '='; s++);
2526 return NULL; /* error */
2529 return NULL; /* empty key */
2530 array->key = p_dupstr(string, n );
2531 p = (unsigned char *) array->key;
2534 if (*string == '#') { /* hexstring */
2536 for (s = string; hexdigitp (s); s++)
2540 return NULL; /* empty or odd number of digits */
2543 array->value = (char *) p;
2544 for (s1 = string; n; s1 += 2, n--)
2548 else { /* regular v3 quoted string */
2549 for (n = 0, s = string; *s; s++) {
2550 if (*s == '\\') { /* pair */
2552 if (*s == ',' || *s == '=' || *s == '+'
2553 || *s == '<' || *s == '>' || *s == '#' || *s == ';'
2554 || *s == '\\' || *s == '\"' || *s == ' ')
2556 else if (hexdigitp (s) && hexdigitp (s + 1)) {
2561 return NULL; /* invalid escape sequence */
2563 else if (*s == '\"')
2564 return NULL; /* invalid encoding */
2565 else if (*s == ',' || *s == '=' || *s == '+'
2566 || *s == '<' || *s == '>' || *s == '#' || *s == ';')
2573 array->value = (char *) p;
2574 for (s = string; n; s++, n--) {
2577 if (hexdigitp (s)) {
2593 /* Parse a DN and return an array-ized one. This is not a validating
2594 parser and it does not support any old-stylish syntax; gpgme is
2595 expected to return only rfc2253 compatible strings. */
2596 static struct dn_array_s *parse_dn (const unsigned char *string)
2598 struct dn_array_s *array;
2599 ssize_t arrayidx, arraysize;
2602 arraysize = 7; /* C,ST,L,O,OU,CN,email */
2603 array = p_new(struct dn_array_s, arraysize + 1);
2606 while (*string == ' ')
2610 if (arrayidx >= arraysize) { /* mutt lacks a real safe_realoc - so we need to copy */
2611 struct dn_array_s *a2;
2614 a2 = p_new(struct dn_array_s, arraysize + 1);
2615 for (i = 0; i < arrayidx; i++) {
2616 a2[i].key = array[i].key;
2617 a2[i].value = array[i].value;
2622 array[arrayidx].key = NULL;
2623 array[arrayidx].value = NULL;
2624 string = parse_dn_part (array + arrayidx, string);
2628 while (*string == ' ')
2630 if (*string && *string != ',' && *string != ';' && *string != '+')
2631 goto failure; /* invalid delimiter */
2635 array[arrayidx].key = NULL;
2636 array[arrayidx].value = NULL;
2640 for (i = 0; i < arrayidx; i++) {
2641 p_delete(&array[i].key);
2642 p_delete(&array[i].value);
2649 /* Print a nice representation of the USERID and make sure it is
2650 displayed in a proper way, which does mean to reorder some parts
2651 for S/MIME's DNs. USERID is a string as returned by the gpgme key
2652 functions. It is utf-8 encoded. */
2653 static void parse_and_print_user_id (FILE * fp, const char *userid)
2658 if (*userid == '<') {
2659 s = strchr (userid + 1, '>');
2661 print_utf8 (fp, userid + 1, s - userid - 1);
2663 else if (*userid == '(')
2664 fputs (_("[Can't display this user ID (unknown encoding)]"), fp);
2665 else if (!digit_or_letter ((const unsigned char *) userid))
2666 fputs (_("[Can't display this user ID (invalid encoding)]"), fp);
2668 struct dn_array_s *dn = parse_dn ((const unsigned char *) userid);
2671 fputs (_("[Can't display this user ID (invalid DN)]"), fp);
2673 print_dn_parts (fp, dn);
2674 for (i = 0; dn[i].key; i++) {
2675 p_delete(&dn[i].key);
2676 p_delete(&dn[i].value);
2684 KEY_CAP_CAN_ENCRYPT,
2689 static unsigned int key_check_cap (gpgme_key_t key, key_cap_t cap)
2691 gpgme_subkey_t subkey = NULL;
2692 unsigned int ret = 0;
2695 case KEY_CAP_CAN_ENCRYPT:
2696 if (!(ret = key->can_encrypt))
2697 for (subkey = key->subkeys; subkey; subkey = subkey->next)
2698 if ((ret = subkey->can_encrypt))
2701 case KEY_CAP_CAN_SIGN:
2702 if (!(ret = key->can_sign))
2703 for (subkey = key->subkeys; subkey; subkey = subkey->next)
2704 if ((ret = subkey->can_sign))
2707 case KEY_CAP_CAN_CERTIFY:
2708 if (!(ret = key->can_certify))
2709 for (subkey = key->subkeys; subkey; subkey = subkey->next)
2710 if ((ret = subkey->can_certify))
2719 /* Print verbose information about a key or certificate to FP. */
2720 static void print_key_info (gpgme_key_t key, FILE * fp)
2723 const char *s = NULL, *s2 = NULL;
2726 char shortbuf[SHORT_STRING];
2727 unsigned long aval = 0;
2731 gpgme_user_id_t uid = NULL;
2734 setlocale (LC_TIME, Locale);
2736 is_pgp = key->protocol == GPGME_PROTOCOL_OpenPGP;
2738 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
2743 fputs (idx ? _(" aka ......: ") :_("Name ......: "), fp);
2746 fputs (_("[Invalid]"), fp);
2750 print_utf8 (fp, s, m_strlen(s));
2752 parse_and_print_user_id (fp, s);
2756 if (key->subkeys && (key->subkeys->timestamp > 0)) {
2757 tt = key->subkeys->timestamp;
2759 tm = localtime (&tt);
2760 #ifdef HAVE_LANGINFO_D_T_FMT
2761 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2763 strftime (shortbuf, sizeof shortbuf, "%c", tm);
2765 fprintf (fp, _("Valid From : %s\n"), shortbuf);
2768 if (key->subkeys && (key->subkeys->expires > 0)) {
2769 tt = key->subkeys->expires;
2771 tm = localtime (&tt);
2772 #ifdef HAVE_LANGINFO_D_T_FMT
2773 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2775 strftime (shortbuf, sizeof shortbuf, "%c", tm);
2777 fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
2781 s = gpgme_pubkey_algo_name (key->subkeys->pubkey_algo);
2785 s2 = is_pgp ? "PGP" : "X.509";
2788 aval = key->subkeys->length;
2790 fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), s2, aval, s);
2792 fprintf (fp, _("Key Usage .: "));
2795 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) {
2796 fprintf (fp, "%s%s", delim, _("encryption"));
2799 if (key_check_cap (key, KEY_CAP_CAN_SIGN)) {
2800 fprintf (fp, "%s%s", delim, _("signing"));
2803 if (key_check_cap (key, KEY_CAP_CAN_CERTIFY)) {
2804 fprintf (fp, "%s%s", delim, _("certification"));
2810 s = key->subkeys->fpr;
2811 fputs (_("Fingerprint: "), fp);
2812 if (is_pgp && m_strlen(s) == 40) {
2813 for (i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) {
2818 putc (is_pgp ? ' ' : ':', fp);
2819 if (is_pgp && i == 4)
2824 for (i = 0; *s && s[1] && s[2]; s += 2, i++) {
2827 putc (is_pgp ? ' ' : ':', fp);
2828 if (is_pgp && i == 7)
2832 fprintf (fp, "%s\n", s);
2835 if (key->issuer_serial) {
2836 s = key->issuer_serial;
2838 fprintf (fp, _("Serial-No .: 0x%s\n"), s);
2841 if (key->issuer_name) {
2842 s = key->issuer_name;
2844 fprintf (fp, _("Issued By .: "));
2845 parse_and_print_user_id (fp, s);
2850 /* For PGP we list all subkeys. */
2852 gpgme_subkey_t subkey = NULL;
2854 for (idx = 1, subkey = key->subkeys; subkey; idx++, subkey = subkey->next) {
2858 if (m_strlen(s) == 16)
2859 s += 8; /* display only the short keyID */
2860 fprintf (fp, _("Subkey ....: 0x%s"), s);
2861 if (subkey->revoked) {
2863 fputs (_("[Revoked]"), fp);
2865 if (subkey->invalid) {
2867 fputs (_("[Invalid]"), fp);
2869 if (subkey->expired) {
2871 fputs (_("[Expired]"), fp);
2873 if (subkey->disabled) {
2875 fputs (_("[Disabled]"), fp);
2879 if (subkey->timestamp > 0) {
2880 tt = subkey->timestamp;
2882 tm = localtime (&tt);
2883 #ifdef HAVE_LANGINFO_D_T_FMT
2884 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2886 strftime (shortbuf, sizeof shortbuf, "%c", tm);
2888 fprintf (fp, _("Valid From : %s\n"), shortbuf);
2891 if (subkey->expires > 0) {
2892 tt = subkey->expires;
2894 tm = localtime (&tt);
2895 #ifdef HAVE_LANGINFO_D_T_FMT
2896 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2898 strftime (shortbuf, sizeof shortbuf, "%c", tm);
2900 fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
2904 s = gpgme_pubkey_algo_name (subkey->pubkey_algo);
2909 aval = subkey->length;
2913 fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), "PGP", aval, s);
2915 fprintf (fp, _("Key Usage .: "));
2918 if (subkey->can_encrypt) {
2919 fprintf (fp, "%s%s", delim, _("encryption"));
2922 if (subkey->can_sign) {
2923 fprintf (fp, "%s%s", delim, _("signing"));
2926 if (subkey->can_certify) {
2927 fprintf (fp, "%s%s", delim, _("certification"));
2935 setlocale (LC_TIME, "C");
2939 /* Show detailed information about the selected key */
2940 static void verify_key (crypt_key_t * key)
2943 char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
2945 gpgme_ctx_t listctx = NULL;
2947 gpgme_key_t k = NULL;
2950 mutt_mktemp (tempfile);
2951 if (!(fp = safe_fopen (tempfile, "w"))) {
2952 mutt_perror (_("Can't create temporary file"));
2956 mutt_message _("Collecting data...");
2958 print_key_info (key->kobj, fp);
2960 err = gpgme_new (&listctx);
2962 fprintf (fp, "Internal error: can't create gpgme context: %s\n",
2963 gpgme_strerror (err));
2966 if ((key->flags & KEYFLAG_ISX509))
2967 gpgme_set_protocol (listctx, GPGME_PROTOCOL_CMS);
2971 while ((s = k->chain_id) && k->subkeys && m_strcmp(s, k->subkeys->fpr)) {
2973 err = gpgme_op_keylist_start (listctx, s, 0);
2974 gpgme_key_release (k);
2977 err = gpgme_op_keylist_next (listctx, &k);
2979 fprintf (fp, _("Error finding issuer key: %s\n"), gpgme_strerror (err));
2982 gpgme_op_keylist_end (listctx);
2984 print_key_info (k, fp);
2987 fputs (_("Error: certification chain to long - stopping here\n"), fp);
2993 gpgme_key_release (k);
2994 gpgme_release (listctx);
2996 mutt_clear_error ();
2997 snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), crypt_keyid (key));
2998 mutt_do_pager (cmd, tempfile, 0, NULL);
3002 * Implementation of `findkeys'.
3006 /* Convert string_list_t into a pattern string suitable to be passed to GPGME.
3007 We need to convert spaces in an item into a '+' and '%' into
3009 static char *list_to_pattern (string_list_t * list)
3017 for (l = list; l; l = l->next) {
3018 for (s = l->data; *s; s++) {
3023 n++; /* delimiter or end of string */
3025 n++; /* make sure to allocate at least one byte */
3026 pattern = p = p_new(char, n);
3027 for (l = list; l; l = l->next) {
3032 for (s = l->data; *s; s++) {
3038 else if (*s == '+') {
3054 /* Return a list of keys which are candidates for the selection.
3055 Select by looking at the HINTS list. */
3056 static crypt_key_t *get_candidates (string_list_t * hints, unsigned int app,
3059 crypt_key_t *db, *k, **kend;
3065 gpgme_user_id_t uid = NULL;
3067 pattern = list_to_pattern (hints);
3071 err = gpgme_new (&ctx);
3073 mutt_error (_("gpgme_new failed: %s"), gpgme_strerror (err));
3081 if ((app & APPLICATION_PGP)) {
3082 /* Its all a mess. That old GPGME expects different things
3083 depending on the protocol. For gpg we don' t need percent
3084 escaped pappert but simple strings passed in an array to the
3085 keylist_ext_start function. */
3090 for (l = hints, n = 0; l; l = l->next) {
3091 if (l->data && *l->data)
3097 patarr = p_new(char *, n + 1);
3098 for (l = hints, n = 0; l; l = l->next) {
3099 if (l->data && *l->data)
3100 patarr[n++] = m_strdup(l->data);
3103 err = gpgme_op_keylist_ext_start (ctx, (const char **) patarr, secret, 0);
3104 for (n = 0; patarr[n]; n++)
3105 p_delete(&patarr[n]);
3108 mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
3109 gpgme_release (ctx);
3114 while (!(err = gpgme_op_keylist_next (ctx, &key))) {
3115 unsigned int flags = 0;
3117 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3118 flags |= KEYFLAG_CANENCRYPT;
3119 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3120 flags |= KEYFLAG_CANSIGN;
3122 #if 0 /* DISABLED code */
3124 /* Bug in gpg. Capabilities are not listed for secret
3125 keys. Try to deduce them from the algorithm. */
3127 switch (key->subkeys[0].pubkey_algo) {
3129 flags |= KEYFLAG_CANENCRYPT;
3130 flags |= KEYFLAG_CANSIGN;
3132 case GPGME_PK_ELG_E:
3133 flags |= KEYFLAG_CANENCRYPT;
3136 flags |= KEYFLAG_CANSIGN;
3140 #endif /* DISABLED code */
3142 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
3143 k = p_new(crypt_key_t, 1);
3152 if (gpg_err_code (err) != GPG_ERR_EOF)
3153 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3154 gpgme_op_keylist_end (ctx);
3159 if ((app & APPLICATION_SMIME)) {
3160 /* and now look for x509 certificates */
3161 gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
3162 err = gpgme_op_keylist_start (ctx, pattern, 0);
3164 mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
3165 gpgme_release (ctx);
3170 while (!(err = gpgme_op_keylist_next (ctx, &key))) {
3171 unsigned int flags = KEYFLAG_ISX509;
3173 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3174 flags |= KEYFLAG_CANENCRYPT;
3175 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3176 flags |= KEYFLAG_CANSIGN;
3178 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
3179 k = p_new(crypt_key_t, 1);
3188 if (gpg_err_code (err) != GPG_ERR_EOF)
3189 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3190 gpgme_op_keylist_end (ctx);
3193 gpgme_release (ctx);
3198 /* Add the string STR to the list HINTS. This list is later used to
3200 static string_list_t *crypt_add_string_to_hints (string_list_t * hints, const char *str)
3205 if ((scratch = m_strdup(str)) == NULL)
3208 for (t = strtok (scratch, " ,.:\"()<>\n"); t;
3209 t = strtok (NULL, " ,.:\"()<>\n")) {
3210 if (m_strlen(t) > 3)
3211 hints = mutt_add_list(hints, t);
3218 /* Display a menu to select a key from the array KEYS. FORCED_VALID
3219 will be set to true on return if the user did override the the
3221 static crypt_key_t *crypt_select_key (crypt_key_t * keys,
3222 address_t * p, const char *s,
3223 unsigned int app, int *forced_valid)
3226 crypt_key_t **key_table;
3229 char helpstr[SHORT_STRING], buf[LONG_STRING];
3231 int (*f) (const void *, const void *);
3232 int menu_to_use = 0;
3237 /* build the key table */
3240 for (k = keys; k; k = k->next) {
3241 if (!option (OPTPGPSHOWUNUSABLE) && (k->flags & KEYFLAG_CANTUSE)) {
3248 p_realloc(&key_table, keymax);
3254 if (!i && unusable) {
3255 mutt_error _("All matching keys are marked expired/revoked.");
3261 switch (PgpSortKeys & SORT_MASK) {
3263 f = crypt_compare_date;
3266 f = crypt_compare_keyid;
3269 f = crypt_compare_address;
3273 f = crypt_compare_trust;
3276 qsort (key_table, i, sizeof (crypt_key_t *), f);
3278 if (app & APPLICATION_PGP)
3279 menu_to_use = MENU_KEY_SELECT_PGP;
3280 else if (app & APPLICATION_SMIME)
3281 menu_to_use = MENU_KEY_SELECT_SMIME;
3284 mutt_make_help (buf, sizeof (buf), _("Exit "), menu_to_use, OP_EXIT);
3285 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3286 mutt_make_help (buf, sizeof (buf), _("Select "), menu_to_use,
3287 OP_GENERIC_SELECT_ENTRY);
3288 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3289 mutt_make_help (buf, sizeof (buf), _("Check key "),
3290 menu_to_use, OP_VERIFY_KEY);
3291 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3292 mutt_make_help (buf, sizeof (buf), _("Help"), menu_to_use, OP_HELP);
3293 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3295 menu = mutt_new_menu ();
3297 menu->make_entry = crypt_entry;
3298 menu->menu = menu_to_use;
3299 menu->help = helpstr;
3300 menu->data = key_table;
3305 if ((app & APPLICATION_PGP) && (app & APPLICATION_SMIME))
3306 ts = _("PGP and S/MIME keys matching");
3307 else if ((app & APPLICATION_PGP))
3308 ts = _("PGP keys matching");
3309 else if ((app & APPLICATION_SMIME))
3310 ts = _("S/MIME keys matching");
3312 ts = _("keys matching");
3315 snprintf (buf, sizeof (buf), _("%s <%s>."), ts, p->mailbox);
3317 snprintf (buf, sizeof (buf), _("%s \"%s\"."), ts, s);
3321 mutt_clear_error ();
3325 switch (mutt_menuLoop (menu)) {
3327 verify_key (key_table[menu->current]);
3328 menu->redraw = REDRAW_FULL;
3332 mutt_message ("%s", key_table[menu->current]->uid);
3335 case OP_GENERIC_SELECT_ENTRY:
3336 /* FIXME make error reporting more verbose - this should be
3337 easy because gpgme provides more information */
3338 if (option (OPTPGPCHECKTRUST)) {
3339 if (!crypt_key_is_valid (key_table[menu->current])) {
3340 mutt_error _("This key can't be used: "
3341 "expired/disabled/revoked.");
3346 if (option (OPTPGPCHECKTRUST) &&
3347 (!crypt_id_is_valid (key_table[menu->current])
3348 || !crypt_id_is_strong (key_table[menu->current]))) {
3350 char buff[LONG_STRING];
3352 if (key_table[menu->current]->flags & KEYFLAG_CANTUSE)
3353 s = N_("ID is expired/disabled/revoked.");
3355 gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
3356 gpgme_user_id_t uid = NULL;
3361 uid = key_table[menu->current]->kobj->uids;
3362 for (j = 0; (j < key_table[menu->current]->idx) && uid;
3363 j++, uid = uid->next);
3365 val = uid->validity;
3368 case GPGME_VALIDITY_UNKNOWN:
3369 case GPGME_VALIDITY_UNDEFINED:
3370 warn_s = N_("ID has undefined validity.");
3372 case GPGME_VALIDITY_NEVER:
3373 warn_s = N_("ID is not valid.");
3375 case GPGME_VALIDITY_MARGINAL:
3376 warn_s = N_("ID is only marginally valid.");
3378 case GPGME_VALIDITY_FULL:
3379 case GPGME_VALIDITY_ULTIMATE:
3383 snprintf (buff, sizeof (buff),
3384 _("%s Do you really want to use the key?"), _(warn_s));
3386 if (mutt_yesorno (buff, 0) != 1) {
3387 mutt_clear_error ();
3394 k = crypt_copy_key (key_table[menu->current]);
3405 mutt_menuDestroy (&menu);
3406 p_delete(&key_table);
3408 set_option (OPTNEEDREDRAW);
3413 static crypt_key_t *crypt_getkeybyaddr (address_t * a, short abilities,
3414 unsigned int app, int *forced_valid)
3417 string_list_t *hints = NULL;
3422 int this_key_has_strong;
3423 int this_key_has_weak;
3424 int this_key_has_invalid;
3427 crypt_key_t *keys, *k;
3428 crypt_key_t *the_valid_key = NULL;
3429 crypt_key_t *matches = NULL;
3430 crypt_key_t **matches_endp = &matches;
3434 if (a && a->mailbox)
3435 hints = crypt_add_string_to_hints (hints, a->mailbox);
3436 if (a && a->personal)
3437 hints = crypt_add_string_to_hints (hints, a->personal);
3439 mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
3440 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
3442 string_list_wipe(&hints);
3447 for (k = keys; k; k = k->next) {
3448 if (abilities && !(k->flags & abilities)) {
3452 this_key_has_weak = 0; /* weak but valid match */
3453 this_key_has_invalid = 0; /* invalid match */
3454 this_key_has_strong = 0; /* strong and valid match */
3455 match = 0; /* any match */
3457 r = rfc822_parse_adrlist (NULL, k->uid);
3458 for (p = r; p; p = p->next) {
3459 int validity = crypt_id_matches_addr (a, p, k);
3461 if (validity & CRYPT_KV_MATCH) /* something matches */
3464 /* is this key a strong candidate? */
3465 if ((validity & CRYPT_KV_VALID)
3466 && (validity & CRYPT_KV_STRONGID)
3467 && (validity & CRYPT_KV_ADDR)) {
3468 if (the_valid_key && the_valid_key != k)
3471 this_key_has_strong = 1;
3473 else if ((validity & CRYPT_KV_MATCH)
3474 && !(validity & CRYPT_KV_VALID))
3475 this_key_has_invalid = 1;
3476 else if ((validity & CRYPT_KV_MATCH)
3477 && (!(validity & CRYPT_KV_STRONGID)
3478 || !(validity & CRYPT_KV_ADDR)))
3479 this_key_has_weak = 1;
3481 address_list_wipe(&r);
3486 if (!this_key_has_strong && this_key_has_invalid)
3488 if (!this_key_has_strong && this_key_has_weak)
3491 *matches_endp = tmp = crypt_copy_key (k);
3492 matches_endp = &tmp->next;
3493 the_valid_key = tmp;
3497 crypt_free_key (&keys);
3500 if (the_valid_key && !multi && !weak
3501 && !(invalid && option (OPTPGPSHOWUNUSABLE))) {
3503 * There was precisely one strong match on a valid ID, there
3504 * were no valid keys with weak matches, and we aren't
3505 * interested in seeing invalid keys.
3507 * Proceed without asking the user.
3509 k = crypt_copy_key (the_valid_key);
3513 * Else: Ask the user.
3515 k = crypt_select_key (matches, a, NULL, app, forced_valid);
3517 crypt_free_key (&matches);
3526 static crypt_key_t *crypt_getkeybystr (char *p, short abilities,
3527 unsigned int app, int *forced_valid)
3529 string_list_t *hints = NULL;
3531 crypt_key_t *matches = NULL;
3532 crypt_key_t **matches_endp = &matches;
3536 mutt_message (_("Looking for keys matching \"%s\"..."), p);
3540 hints = crypt_add_string_to_hints (hints, p);
3541 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
3542 string_list_wipe(&hints);
3547 for (k = keys; k; k = k->next) {
3548 if (abilities && !(k->flags & abilities))
3553 if (!*p || !m_strcasecmp(p, crypt_keyid (k))
3554 || (!m_strncasecmp(p, "0x", 2)
3555 && !m_strcasecmp(p + 2, crypt_keyid (k)))
3556 || (option (OPTPGPLONGIDS)
3557 && !m_strncasecmp(p, "0x", 2)
3558 && !m_strcasecmp(p + 2, crypt_keyid (k) + 8))
3559 || m_stristr(k->uid, p)) {
3562 *matches_endp = tmp = crypt_copy_key (k);
3563 matches_endp = &tmp->next;
3567 crypt_free_key (&keys);
3570 k = crypt_select_key (matches, NULL, p, app, forced_valid);
3571 crypt_free_key (&matches);
3578 /* Display TAG as a prompt to ask for a key. If WHATFOR is not null
3579 use it as default and store it under that label as the next
3580 default. ABILITIES describe the required key abilities (sign,
3581 encrypt) and APP the type of the requested key; ether S/MIME or
3582 PGP. Return a copy of the key or NULL if not found. */
3583 static crypt_key_t *crypt_ask_for_key (char *tag,
3586 unsigned int app, int *forced_valid)
3589 char resp[SHORT_STRING];
3590 struct crypt_cache *l = NULL;
3594 forced_valid = &dummy;
3596 mutt_clear_error ();
3602 for (l = id_defaults; l; l = l->next)
3603 if (!m_strcasecmp(whatfor, l->what)) {
3604 m_strcpy(resp, sizeof(resp), NONULL(l->dflt));
3612 if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0)
3617 m_strreplace(&l->dflt, resp);
3619 l = p_new(struct crypt_cache, 1);
3620 l->next = id_defaults;
3622 l->what = m_strdup(whatfor);
3623 l->dflt = m_strdup(resp);
3627 if ((key = crypt_getkeybystr (resp, abilities, app, forced_valid)))
3635 /* This routine attempts to find the keyids of the recipients of a
3636 message. It returns NULL if any of the keys can not be found. */
3637 static char *find_keys (address_t * to, address_t * cc, address_t * bcc,
3640 char *keyID, *keylist = NULL, *t;
3641 ssize_t keylist_size = 0;
3642 ssize_t keylist_used = 0;
3643 address_t *tmp = NULL, *addr = NULL;
3644 address_t **last = &tmp;
3647 crypt_key_t *k_info, *key;
3648 const char *fqdn = mutt_fqdn (1);
3651 *r_application = APPLICATION_PGP | APPLICATION_SMIME;
3654 for (i = 0; i < 3; i++) {
3669 *last = address_list_dup (p);
3671 last = &((*last)->next);
3675 rfc822_qualify (tmp, fqdn);
3677 tmp = mutt_remove_duplicates (tmp);
3679 for (p = tmp; p; p = p->next) {
3680 char buf[LONG_STRING];
3681 int forced_valid = 0;
3686 if ((keyID = mutt_crypt_hook (p)) != NULL) {
3689 snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"),
3691 if ((r = mutt_yesorno (buf, M_YES)) == M_YES) {
3692 /* check for e-mail address */
3693 if ((t = strchr (keyID, '@')) &&
3694 (addr = rfc822_parse_adrlist (NULL, keyID))) {
3696 rfc822_qualify (addr, fqdn);
3701 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
3702 *r_application, &forced_valid);
3704 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
3705 app, &forced_valid);
3711 address_list_wipe(&tmp);
3712 address_list_wipe(&addr);
3718 && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT,
3719 app, &forced_valid)) == NULL) {
3720 snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
3722 if ((key = crypt_ask_for_key (buf, q->mailbox, KEYFLAG_CANENCRYPT,
3728 &forced_valid)) == NULL) {
3730 address_list_wipe(&tmp);
3731 address_list_wipe(&addr);
3739 const char *s = crypt_fpr (key);
3742 if (key->flags & KEYFLAG_ISX509)
3743 *r_application &= ~APPLICATION_PGP;
3744 if (!(key->flags & KEYFLAG_ISX509))
3745 *r_application &= ~APPLICATION_SMIME;
3748 keylist_size += m_strlen(s) + 4 + 1;
3749 p_realloc(&keylist, keylist_size);
3750 sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */
3751 keylist_used ? " " : "", s, forced_valid ? "!" : "");
3753 keylist_used = m_strlen(keylist);
3755 crypt_free_key (&key);
3756 address_list_wipe(&addr);
3758 address_list_wipe(&tmp);
3762 char *pgp_gpgme_findkeys (address_t * to, address_t * cc, address_t * bcc)
3764 return find_keys (to, cc, bcc, APPLICATION_PGP);
3767 char *smime_gpgme_findkeys (address_t * to, address_t * cc, address_t * bcc)
3769 return find_keys (to, cc, bcc, APPLICATION_SMIME);
3773 * Implementation of `init'.
3776 /* Initialization. */
3777 static void init_gpgme (void)
3779 /* Make sure that gpg-agent is running. */
3780 if (!getenv ("GPG_AGENT_INFO")) {
3781 mutt_error ("\nUsing GPGME backend, although no gpg-agent is running");
3782 if (mutt_any_key_to_continue (NULL) == -1)
3787 void pgp_gpgme_init (void)
3792 void smime_gpgme_init (void)
3796 static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime)
3799 char input_signas[SHORT_STRING];
3802 if (msg->security & APPLICATION_PGP)
3804 else if (msg->security & APPLICATION_SMIME)
3809 mutt_multi_choice (_
3810 ("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?"),
3814 mutt_multi_choice (_
3815 ("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?"),
3819 case 1: /* (e)ncrypt */
3820 msg->security |= (is_smime ? SMIMEENCRYPT : PGPENCRYPT);
3821 msg->security &= ~(is_smime ? SMIMESIGN : PGPSIGN);
3824 case 2: /* (s)ign */
3825 msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
3826 msg->security &= ~(is_smime ? SMIMEENCRYPT : PGPENCRYPT);
3829 case 3: /* sign (a)s */
3830 /* unset_option(OPTCRYPTCHECKTRUST); */
3831 if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
3832 is_smime ? APPLICATION_SMIME :
3833 APPLICATION_PGP, NULL))) {
3834 snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p));
3835 m_strreplace(is_smime ? &SmimeDefaultKey : &PgpSignAs,
3837 crypt_free_key (&p);
3839 msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
3843 msg->security &= (is_smime ? ~SMIMESIGN : ~PGPSIGN);
3846 *redraw = REDRAW_FULL;
3849 case 4: /* (b)oth */
3851 (is_smime ? (SMIMEENCRYPT | SMIMESIGN) : (PGPENCRYPT | PGPSIGN));
3854 case 5: /* (p)gp or s/(m)ime */
3855 is_smime = !is_smime;
3858 case 6: /* (c)lear */
3863 if (choice == 6 || choice == 7);
3864 else if (is_smime) {
3865 msg->security &= ~APPLICATION_PGP;
3866 msg->security |= APPLICATION_SMIME;
3869 msg->security &= ~APPLICATION_SMIME;
3870 msg->security |= APPLICATION_PGP;
3873 return (msg->security);
3876 int pgp_gpgme_send_menu (HEADER * msg, int *redraw)
3878 return gpgme_send_menu (msg, redraw, 0);
3881 int smime_gpgme_send_menu (HEADER * msg, int *redraw)
3883 return gpgme_send_menu (msg, redraw, 1);
3886 static int verify_sender (HEADER * h, gpgme_protocol_t protocol __attribute__((unused)))
3888 address_t *sender = NULL;
3889 unsigned int ret = 1;
3892 h->env->from = mutt_expand_aliases (h->env->from);
3893 sender = h->env->from;
3895 else if (h->env->sender) {
3896 h->env->sender = mutt_expand_aliases (h->env->sender);
3897 sender = h->env->sender;
3901 if (signature_key) {
3902 gpgme_key_t key = signature_key;
3903 gpgme_user_id_t uid = NULL;
3904 int sender_length = 0;
3907 sender_length = m_strlen(sender->mailbox);
3908 for (uid = key->uids; uid && ret; uid = uid->next) {
3909 uid_length = m_strlen(uid->email);
3910 if (1 && (uid->email[0] == '<')
3911 && (uid->email[uid_length - 1] == '>')
3912 && (uid_length == sender_length + 2)
3913 && (!strncmp (uid->email + 1, sender->mailbox, sender_length)))
3918 mutt_any_key_to_continue ("Failed to verify sender");
3921 mutt_any_key_to_continue ("Failed to figure out sender");
3923 if (signature_key) {
3924 gpgme_key_release (signature_key);
3925 signature_key = NULL;
3931 int smime_gpgme_verify_sender (HEADER * h)
3933 return verify_sender (h, GPGME_PROTOCOL_CMS);