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);
762 t->type = TYPEMULTIPART;
763 t->subtype = m_strdup("signed");
764 t->encoding = ENC7BIT;
766 t->disposition = DISPINLINE;
768 parameter_set_boundary(&t->parameter);
769 parameter_setval(&t->parameter, "protocol",
770 use_smime ? "application/pkcs7-signature"
771 : "application/pgp-signature");
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 parameter_setval(&t->parameter, "micalg", buf);
777 parameter_setval(&t->parameter, "micalg", "sha1");
783 t->parts->next = body_new();
785 t->type = TYPEAPPLICATION;
787 t->subtype = m_strdup("pkcs7-signature");
788 parameter_setval(&t->parameter, "name", "smime.p7s");
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);
849 t->type = TYPEMULTIPART;
850 t->subtype = m_strdup("encrypted");
851 t->encoding = ENC7BIT;
853 t->disposition = DISPINLINE;
855 parameter_set_boundary(&t->parameter);
856 parameter_setval(&t->parameter, "protocol", "application/pgp-encrypted");
858 t->parts = body_new();
859 t->parts->type = TYPEAPPLICATION;
860 t->parts->subtype = m_strdup("pgp-encrypted");
861 t->parts->encoding = ENC7BIT;
863 t->parts->next = body_new();
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);
907 t->type = TYPEAPPLICATION;
908 t->subtype = m_strdup("pkcs7-mime");
909 parameter_setval(&t->parameter, "name", "smime.p7m");
910 parameter_setval(&t->parameter, "smime-type", "enveloped-data");
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 body_list_wipe(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 parameter_setval(&b->parameter, "format", "fixed");
1676 parameter_setval(&b->parameter, "x-action",
1677 enc ? "pgp-encrypted" : "pgp-signed");
1681 int pgp_gpgme_check_traditional (FILE * fp, BODY * b, int tagged_only)
1686 for (; b; b = b->next) {
1687 if (is_multipart (b))
1688 rv = (pgp_gpgme_check_traditional (fp, b->parts, tagged_only) || rv);
1689 else if (b->type == TYPETEXT) {
1690 if ((r = mutt_is_application_pgp (b)))
1693 rv = (pgp_check_traditional_one_body (fp, b, tagged_only) || rv);
1701 * Implementation of `application_handler'.
1705 Copy a clearsigned message, and strip the signature and PGP's
1708 XXX - charset handling: We assume that it is safe to do
1709 character set decoding first, dash decoding second here, while
1710 we do it the other way around in the main handler.
1712 (Note that we aren't worse than Outlook & Cie in this, and also
1713 note that we can successfully handle anything produced by any
1714 existing versions of mutt.) */
1716 static void copy_clearsigned (gpgme_data_t data, STATE * s, char *charset)
1718 char buf[HUGE_STRING];
1719 short complete, armor_header;
1724 fname = data_object_to_tempfile (data, &fp);
1730 fc = fgetconv_open (fp, charset, Charset, M_ICONV_HOOK_FROM);
1732 for (complete = 1, armor_header = 1;
1733 fgetconvs (buf, sizeof (buf), fc) != NULL;
1734 complete = strchr (buf, '\n') != NULL) {
1737 state_puts (buf, s);
1741 if (!m_strcmp(buf, "-----BEGIN PGP SIGNATURE-----\n"))
1751 state_puts (s->prefix, s);
1753 if (buf[0] == '-' && buf[1] == ' ')
1754 state_puts (buf + 2, s);
1756 state_puts (buf, s);
1759 fgetconv_close (&fc);
1764 /* Support for classic_application/pgp */
1765 int pgp_gpgme_application_handler (BODY * m, STATE * s)
1767 int needpass = -1, pgp_keyblock = 0;
1771 off_t last_pos, offset;
1772 char buf[HUGE_STRING];
1773 FILE *pgpout = NULL;
1775 gpgme_error_t err = 0;
1776 gpgme_data_t armored_data = NULL;
1778 short maybe_goodsig = 1;
1779 short have_any_sigs = 0;
1781 char body_charset[STRING]; /* Only used for clearsigned messages. */
1783 /* For clearsigned messages we won't be able to get a character set
1784 but we know that this may only be text thus we assume Latin-1
1786 if (!mutt_get_body_charset (body_charset, sizeof (body_charset), m))
1787 m_strcpy(body_charset, sizeof(body_charset), "iso-8859-1");
1789 fseeko (s->fpin, m->offset, 0);
1790 last_pos = m->offset;
1792 for (bytes = m->length; bytes > 0;) {
1793 if (fgets (buf, sizeof (buf), s->fpin) == NULL)
1796 offset = ftello (s->fpin);
1797 bytes -= (offset - last_pos); /* don't rely on m_strlen(buf) */
1800 if (!m_strncmp("-----BEGIN PGP ", buf, 15)) {
1802 start_pos = last_pos;
1804 if (!m_strcmp("MESSAGE-----\n", buf + 15))
1806 else if (!m_strcmp("SIGNED MESSAGE-----\n", buf + 15)) {
1810 else if (!option (OPTDONTHANDLEPGPKEYS) &&
1811 !m_strcmp("PUBLIC KEY BLOCK-----\n", buf + 15)) {
1816 /* XXX - we may wish to recode here */
1818 state_puts (s->prefix, s);
1819 state_puts (buf, s);
1823 have_any_sigs = (have_any_sigs || (clearsign && (s->flags & M_VERIFY)));
1825 /* Copy PGP material to an data container */
1826 armored_data = create_gpgme_data ();
1827 gpgme_data_write (armored_data, buf, m_strlen(buf));
1828 while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL) {
1829 offset = ftello (s->fpin);
1830 bytes -= (offset - last_pos); /* don't rely on m_strlen(buf) */
1833 gpgme_data_write (armored_data, buf, m_strlen(buf));
1835 if ((needpass && !m_strcmp("-----END PGP MESSAGE-----\n", buf))
1837 && (!m_strcmp("-----END PGP SIGNATURE-----\n", buf)
1838 || !m_strcmp("-----END PGP PUBLIC KEY BLOCK-----\n",
1843 /* Invoke PGP if needed */
1844 if (!clearsign || (s->flags & M_VERIFY)) {
1845 unsigned int sig_stat = 0;
1846 gpgme_data_t plaintext;
1849 plaintext = create_gpgme_data ();
1850 ctx = create_gpgme_context (0);
1853 err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
1855 err = gpgme_op_decrypt_verify (ctx, armored_data, plaintext);
1856 if (gpg_err_code (err) == GPG_ERR_NO_DATA) {
1857 /* Decrypt verify can't handle signed only messages. */
1858 err = (gpgme_data_seek (armored_data, 0, SEEK_SET) == -1)
1859 ? gpgme_error_from_errno (errno) : 0;
1860 /* Must release plaintext so that we supply an
1861 uninitialized object. */
1862 gpgme_data_release (plaintext);
1863 plaintext = create_gpgme_data ();
1864 err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
1871 snprintf (errbuf, sizeof (errbuf) - 1,
1872 _("Error: decryption/verification failed: %s\n"),
1873 gpgme_strerror (err));
1874 state_attach_puts (errbuf, s);
1876 else { /* Decryption/Verification succeeded */
1880 /* Check wether signatures have been verified. */
1881 gpgme_verify_result_t verify_result;
1883 verify_result = gpgme_op_verify_result (ctx);
1884 if (verify_result->signatures)
1890 if ((s->flags & M_DISPLAY) && sig_stat) {
1895 state_attach_puts (_("[-- Begin signature "
1896 "information --]\n"), s);
1899 (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) {
1908 state_attach_puts (_("[-- End signature "
1909 "information --]\n\n"), s);
1912 tmpfname = data_object_to_tempfile (plaintext, &pgpout);
1915 state_attach_puts (_("Error: copy data failed\n"), s);
1919 p_delete(&tmpfname);
1922 gpgme_release (ctx);
1926 * Now, copy cleartext to the screen. NOTE - we expect that PGP
1927 * outputs utf-8 cleartext. This may not always be true, but it
1928 * seems to be a reasonable guess.
1931 if (s->flags & M_DISPLAY) {
1933 state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s);
1934 else if (pgp_keyblock)
1935 state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), s);
1937 state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), s);
1941 copy_clearsigned (armored_data, s, body_charset);
1948 fc = fgetconv_open (pgpout, "utf-8", Charset, 0);
1949 while ((c = fgetconv (fc)) != EOF) {
1951 if (c == '\n' && s->prefix)
1952 state_puts (s->prefix, s);
1954 fgetconv_close (&fc);
1957 if (s->flags & M_DISPLAY) {
1958 state_putc ('\n', s);
1960 state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
1961 else if (pgp_keyblock)
1962 state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
1964 state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
1968 safe_fclose (&pgpout);
1972 /* XXX - we may wish to recode here */
1974 state_puts (s->prefix, s);
1975 state_puts (buf, s);
1979 m->goodsig = (maybe_goodsig && have_any_sigs);
1981 if (needpass == -1) {
1982 state_attach_puts (_("[-- Error: could not find beginning"
1983 " of PGP message! --]\n\n"), s);
1990 * Implementation of `encrypted_handler'.
1993 /* MIME handler for pgp/mime encrypted messages. */
1994 int pgp_gpgme_encrypted_handler (BODY * a, STATE * s)
1996 char tempfile[_POSIX_PATH_MAX];
1999 BODY *orig_body = a;
2004 if (!a || a->type != TYPEAPPLICATION || !a->subtype
2005 || ascii_strcasecmp ("pgp-encrypted", a->subtype)
2006 || !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype
2007 || ascii_strcasecmp ("octet-stream", a->next->subtype)) {
2008 if (s->flags & M_DISPLAY)
2009 state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
2014 /* Move forward to the application/pgp-encrypted body. */
2017 mutt_mktemp (tempfile);
2018 if (!(fpout = safe_fopen (tempfile, "w+"))) {
2019 if (s->flags & M_DISPLAY)
2020 state_attach_puts (_("[-- Error: could not create temporary file! "
2025 tattach = decrypt_part (a, s, fpout, 0, &is_signed);
2027 tattach->goodsig = is_signed > 0;
2029 if (s->flags & M_DISPLAY)
2030 state_attach_puts (is_signed ?
2032 ("[-- The following data is PGP/MIME signed and encrypted --]\n\n") :
2033 _("[-- The following data is PGP/MIME encrypted --]\n\n"), s);
2036 FILE *savefp = s->fpin;
2039 rc = mutt_body_handler (tattach, s);
2044 * if a multipart/signed is the _only_ sub-part of a
2045 * multipart/encrypted, cache signature verification
2048 if (mutt_is_multipart_signed (tattach) && !tattach->next)
2049 orig_body->goodsig |= tattach->goodsig;
2051 if (s->flags & M_DISPLAY) {
2052 state_puts ("\n", s);
2053 state_attach_puts (is_signed ?
2055 ("[-- End of PGP/MIME signed and encrypted data --]\n")
2056 : _("[-- End of PGP/MIME encrypted data --]\n"), s);
2059 body_list_wipe(&tattach);
2063 mutt_unlink (tempfile);
2067 /* Support for application/smime */
2068 int smime_gpgme_application_handler (BODY * a, STATE * s)
2070 char tempfile[_POSIX_PATH_MAX];
2077 mutt_mktemp (tempfile);
2078 if (!(fpout = safe_fopen (tempfile, "w+"))) {
2079 if (s->flags & M_DISPLAY)
2080 state_attach_puts (_("[-- Error: could not create temporary file! "
2085 tattach = decrypt_part (a, s, fpout, 1, &is_signed);
2087 tattach->goodsig = is_signed > 0;
2089 if (s->flags & M_DISPLAY)
2090 state_attach_puts (is_signed ?
2091 _("[-- The following data is S/MIME signed --]\n\n") :
2092 _("[-- The following data is S/MIME encrypted --]\n\n"), s);
2095 FILE *savefp = s->fpin;
2098 rc = mutt_body_handler (tattach, s);
2103 * if a multipart/signed is the _only_ sub-part of a
2104 * multipart/encrypted, cache signature verification
2107 if (mutt_is_multipart_signed (tattach) && !tattach->next) {
2108 if (!(a->goodsig = tattach->goodsig))
2109 a->warnsig = tattach->warnsig;
2111 else if (tattach->goodsig) {
2113 a->warnsig = tattach->warnsig;
2116 if (s->flags & M_DISPLAY) {
2117 state_puts ("\n", s);
2118 state_attach_puts (is_signed ?
2119 _("[-- End of S/MIME signed data --]\n") :
2120 _("[-- End of S/MIME encrypted data --]\n"), s);
2123 body_list_wipe(&tattach);
2127 mutt_unlink (tempfile);
2133 * Format an entry on the CRYPT key selection menu.
2136 * %k key id %K key id of the principal key
2138 * %a algorithm %A algorithm of the princ. key
2139 * %l length %L length of the princ. key
2140 * %f flags %F flags of the princ. key
2141 * %c capabilities %C capabilities of the princ. key
2142 * %t trust/validity of the key-uid association
2144 * %[...] date of key using strftime(3)
2148 crypt_entry_fmt (char *dest, ssize_t destlen, char op,
2149 const char *src, const char *prefix,
2150 const char *ifstring, const char *elsestring,
2151 unsigned long data, format_flag flags)
2154 crypt_entry_t *entry;
2157 int optional = (flags & M_FORMAT_OPTIONAL);
2158 const char *s = NULL;
2161 entry = (crypt_entry_t *) data;
2164 /* if (isupper ((unsigned char) op)) */
2167 kflags = (key->flags /*| (pkey->flags & KEYFLAG_RESTRICTIONS)
2170 switch (ascii_tolower (op)) {
2174 char buf2[SHORT_STRING], *p;
2190 while (len > 0 && *cp != ']') {
2199 break; /* not enough space */
2209 if (do_locales && Locale)
2210 setlocale (LC_TIME, Locale);
2215 if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
2216 tt = key->kobj->subkeys->timestamp;
2218 tm = localtime (&tt);
2220 strftime (buf2, sizeof (buf2), dest, tm);
2223 setlocale (LC_TIME, "C");
2225 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2226 snprintf (dest, destlen, fmt, buf2);
2233 snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
2234 snprintf (dest, destlen, fmt, entry->num);
2239 /* fixme: we need a way to distinguish between main and subkeys.
2240 Store the idx in entry? */
2241 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2242 snprintf (dest, destlen, fmt, crypt_keyid (key));
2247 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2248 snprintf (dest, destlen, fmt, key->uid);
2253 snprintf (fmt, sizeof (fmt), "%%%s.3s", prefix);
2254 if (key->kobj->subkeys)
2255 s = gpgme_pubkey_algo_name (key->kobj->subkeys->pubkey_algo);
2258 snprintf (dest, destlen, fmt, s);
2263 snprintf (fmt, sizeof (fmt), "%%%slu", prefix);
2264 if (key->kobj->subkeys)
2265 val = key->kobj->subkeys->length;
2268 snprintf (dest, destlen, fmt, val);
2273 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2274 snprintf (dest, destlen, fmt, crypt_flags (kflags));
2276 else if (!(kflags & (KEYFLAG_RESTRICTIONS)))
2281 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2282 snprintf (dest, destlen, fmt, crypt_key_abilities (kflags));
2284 else if (!(kflags & (KEYFLAG_ABILITIES)))
2288 if ((kflags & KEYFLAG_ISX509))
2291 gpgme_user_id_t uid = NULL;
2294 for (i = 0, uid = key->kobj->uids; uid && (i < key->idx);
2295 i++, uid = uid->next);
2297 switch (uid->validity) {
2298 case GPGME_VALIDITY_UNDEFINED:
2301 case GPGME_VALIDITY_NEVER:
2304 case GPGME_VALIDITY_MARGINAL:
2307 case GPGME_VALIDITY_FULL:
2310 case GPGME_VALIDITY_ULTIMATE:
2313 case GPGME_VALIDITY_UNKNOWN:
2319 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2320 snprintf (dest, destlen, fmt, s ? *s : 'B');
2323 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2324 snprintf (dest, destlen, fmt,
2325 gpgme_get_protocol_name (key->kobj->protocol));
2333 mutt_FormatString (dest, destlen, ifstring, mutt_attach_fmt, data, 0);
2334 else if (flags & M_FORMAT_OPTIONAL)
2335 mutt_FormatString (dest, destlen, elsestring, mutt_attach_fmt, data, 0);
2339 /* Used by the display fucntion to format a line. */
2340 static void crypt_entry (char *s, ssize_t l, MUTTMENU * menu, int num)
2342 crypt_key_t **key_table = (crypt_key_t **) menu->data;
2343 crypt_entry_t entry;
2345 entry.key = key_table[num];
2346 entry.num = num + 1;
2348 mutt_FormatString (s, l, NONULL (PgpEntryFormat), crypt_entry_fmt,
2349 (unsigned long) &entry, M_FORMAT_ARROWCURSOR);
2352 /* Compare two addresses and the keyid to be used for sorting. */
2353 static int _crypt_compare_address (const void *a, const void *b)
2355 crypt_key_t **s = (crypt_key_t **) a;
2356 crypt_key_t **t = (crypt_key_t **) b;
2359 if ((r = m_strcasecmp((*s)->uid, (*t)->uid)))
2362 return m_strcasecmp(crypt_keyid (*s), crypt_keyid (*t)) > 0;
2365 static int crypt_compare_address (const void *a, const void *b)
2367 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_address (a, b)
2368 : _crypt_compare_address (a, b));
2372 /* Compare two key IDs and the addresses to be used for sorting. */
2373 static int _crypt_compare_keyid (const void *a, const void *b)
2375 crypt_key_t **s = (crypt_key_t **) a;
2376 crypt_key_t **t = (crypt_key_t **) b;
2379 if ((r = m_strcasecmp(crypt_keyid (*s), crypt_keyid (*t))))
2382 return m_strcasecmp((*s)->uid, (*t)->uid) > 0;
2385 static int crypt_compare_keyid (const void *a, const void *b)
2387 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_keyid (a, b)
2388 : _crypt_compare_keyid (a, b));
2391 /* Compare 2 creation dates and the addresses. For sorting. */
2392 static int _crypt_compare_date (const void *a, const void *b)
2394 crypt_key_t **s = (crypt_key_t **) a;
2395 crypt_key_t **t = (crypt_key_t **) b;
2396 unsigned long ts = 0, tt = 0;
2398 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2399 ts = (*s)->kobj->subkeys->timestamp;
2400 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2401 tt = (*t)->kobj->subkeys->timestamp;
2408 return m_strcasecmp((*s)->uid, (*t)->uid) > 0;
2411 static int crypt_compare_date (const void *a, const void *b)
2413 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_date (a, b)
2414 : _crypt_compare_date (a, b));
2417 /* Compare two trust values, the key length, the creation dates. the
2418 addresses and the key IDs. For sorting. */
2419 static int _crypt_compare_trust (const void *a, const void *b)
2421 crypt_key_t **s = (crypt_key_t **) a;
2422 crypt_key_t **t = (crypt_key_t **) b;
2423 unsigned long ts = 0, tt = 0;
2426 if ((r = (((*s)->flags & (KEYFLAG_RESTRICTIONS))
2427 - ((*t)->flags & (KEYFLAG_RESTRICTIONS)))))
2430 if ((*s)->kobj->uids)
2431 ts = (*s)->kobj->uids->validity;
2432 if ((*t)->kobj->uids)
2433 tt = (*t)->kobj->uids->validity;
2434 if ((r = (tt - ts)))
2437 if ((*s)->kobj->subkeys)
2438 ts = (*s)->kobj->subkeys->length;
2439 if ((*t)->kobj->subkeys)
2440 tt = (*t)->kobj->subkeys->length;
2444 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2445 ts = (*s)->kobj->subkeys->timestamp;
2446 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2447 tt = (*t)->kobj->subkeys->timestamp;
2453 if ((r = m_strcasecmp((*s)->uid, (*t)->uid)))
2455 return (m_strcasecmp(crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0;
2458 static int crypt_compare_trust (const void *a, const void *b)
2460 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_trust (a, b)
2461 : _crypt_compare_trust (a, b));
2464 /* Print the X.500 Distinguished Name part KEY from the array of parts
2466 static int print_dn_part (FILE * fp, struct dn_array_s *dn, const char *key)
2470 for (; dn->key; dn++) {
2471 if (!m_strcmp(dn->key, key)) {
2474 print_utf8 (fp, dn->value, m_strlen(dn->value));
2481 /* Print all parts of a DN in a standard sequence. */
2482 static void print_dn_parts (FILE * fp, struct dn_array_s *dn)
2484 const char *stdpart[] = {
2485 "CN", "OU", "O", "STREET", "L", "ST", "C", NULL
2487 int any = 0, any2 = 0, i;
2489 for (i = 0; stdpart[i]; i++) {
2492 any = print_dn_part (fp, dn, stdpart[i]);
2494 /* now print the rest without any specific ordering */
2495 for (; dn->key; dn++) {
2496 for (i = 0; stdpart[i]; i++) {
2497 if (!m_strcmp(dn->key, stdpart[i]))
2505 any = print_dn_part (fp, dn, dn->key);
2514 /* Parse an RDN; this is a helper to parse_dn(). */
2515 static const unsigned char *parse_dn_part (struct dn_array_s *array,
2516 const unsigned char *string)
2518 const unsigned char *s, *s1;
2522 /* parse attributeType */
2523 for (s = string + 1; *s && *s != '='; s++);
2525 return NULL; /* error */
2528 return NULL; /* empty key */
2529 array->key = p_dupstr(string, n );
2530 p = (unsigned char *) array->key;
2533 if (*string == '#') { /* hexstring */
2535 for (s = string; hexdigitp (s); s++)
2539 return NULL; /* empty or odd number of digits */
2542 array->value = (char *) p;
2543 for (s1 = string; n; s1 += 2, n--)
2547 else { /* regular v3 quoted string */
2548 for (n = 0, s = string; *s; s++) {
2549 if (*s == '\\') { /* pair */
2551 if (*s == ',' || *s == '=' || *s == '+'
2552 || *s == '<' || *s == '>' || *s == '#' || *s == ';'
2553 || *s == '\\' || *s == '\"' || *s == ' ')
2555 else if (hexdigitp (s) && hexdigitp (s + 1)) {
2560 return NULL; /* invalid escape sequence */
2562 else if (*s == '\"')
2563 return NULL; /* invalid encoding */
2564 else if (*s == ',' || *s == '=' || *s == '+'
2565 || *s == '<' || *s == '>' || *s == '#' || *s == ';')
2572 array->value = (char *) p;
2573 for (s = string; n; s++, n--) {
2576 if (hexdigitp (s)) {
2592 /* Parse a DN and return an array-ized one. This is not a validating
2593 parser and it does not support any old-stylish syntax; gpgme is
2594 expected to return only rfc2253 compatible strings. */
2595 static struct dn_array_s *parse_dn (const unsigned char *string)
2597 struct dn_array_s *array;
2598 ssize_t arrayidx, arraysize;
2601 arraysize = 7; /* C,ST,L,O,OU,CN,email */
2602 array = p_new(struct dn_array_s, arraysize + 1);
2605 while (*string == ' ')
2609 if (arrayidx >= arraysize) { /* mutt lacks a real safe_realoc - so we need to copy */
2610 struct dn_array_s *a2;
2613 a2 = p_new(struct dn_array_s, arraysize + 1);
2614 for (i = 0; i < arrayidx; i++) {
2615 a2[i].key = array[i].key;
2616 a2[i].value = array[i].value;
2621 array[arrayidx].key = NULL;
2622 array[arrayidx].value = NULL;
2623 string = parse_dn_part (array + arrayidx, string);
2627 while (*string == ' ')
2629 if (*string && *string != ',' && *string != ';' && *string != '+')
2630 goto failure; /* invalid delimiter */
2634 array[arrayidx].key = NULL;
2635 array[arrayidx].value = NULL;
2639 for (i = 0; i < arrayidx; i++) {
2640 p_delete(&array[i].key);
2641 p_delete(&array[i].value);
2648 /* Print a nice representation of the USERID and make sure it is
2649 displayed in a proper way, which does mean to reorder some parts
2650 for S/MIME's DNs. USERID is a string as returned by the gpgme key
2651 functions. It is utf-8 encoded. */
2652 static void parse_and_print_user_id (FILE * fp, const char *userid)
2657 if (*userid == '<') {
2658 s = strchr (userid + 1, '>');
2660 print_utf8 (fp, userid + 1, s - userid - 1);
2662 else if (*userid == '(')
2663 fputs (_("[Can't display this user ID (unknown encoding)]"), fp);
2664 else if (!digit_or_letter ((const unsigned char *) userid))
2665 fputs (_("[Can't display this user ID (invalid encoding)]"), fp);
2667 struct dn_array_s *dn = parse_dn ((const unsigned char *) userid);
2670 fputs (_("[Can't display this user ID (invalid DN)]"), fp);
2672 print_dn_parts (fp, dn);
2673 for (i = 0; dn[i].key; i++) {
2674 p_delete(&dn[i].key);
2675 p_delete(&dn[i].value);
2683 KEY_CAP_CAN_ENCRYPT,
2688 static unsigned int key_check_cap (gpgme_key_t key, key_cap_t cap)
2690 gpgme_subkey_t subkey = NULL;
2691 unsigned int ret = 0;
2694 case KEY_CAP_CAN_ENCRYPT:
2695 if (!(ret = key->can_encrypt))
2696 for (subkey = key->subkeys; subkey; subkey = subkey->next)
2697 if ((ret = subkey->can_encrypt))
2700 case KEY_CAP_CAN_SIGN:
2701 if (!(ret = key->can_sign))
2702 for (subkey = key->subkeys; subkey; subkey = subkey->next)
2703 if ((ret = subkey->can_sign))
2706 case KEY_CAP_CAN_CERTIFY:
2707 if (!(ret = key->can_certify))
2708 for (subkey = key->subkeys; subkey; subkey = subkey->next)
2709 if ((ret = subkey->can_certify))
2718 /* Print verbose information about a key or certificate to FP. */
2719 static void print_key_info (gpgme_key_t key, FILE * fp)
2722 const char *s = NULL, *s2 = NULL;
2725 char shortbuf[SHORT_STRING];
2726 unsigned long aval = 0;
2730 gpgme_user_id_t uid = NULL;
2733 setlocale (LC_TIME, Locale);
2735 is_pgp = key->protocol == GPGME_PROTOCOL_OpenPGP;
2737 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
2742 fputs (idx ? _(" aka ......: ") :_("Name ......: "), fp);
2745 fputs (_("[Invalid]"), fp);
2749 print_utf8 (fp, s, m_strlen(s));
2751 parse_and_print_user_id (fp, s);
2755 if (key->subkeys && (key->subkeys->timestamp > 0)) {
2756 tt = key->subkeys->timestamp;
2758 tm = localtime (&tt);
2759 #ifdef HAVE_LANGINFO_D_T_FMT
2760 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2762 strftime (shortbuf, sizeof shortbuf, "%c", tm);
2764 fprintf (fp, _("Valid From : %s\n"), shortbuf);
2767 if (key->subkeys && (key->subkeys->expires > 0)) {
2768 tt = key->subkeys->expires;
2770 tm = localtime (&tt);
2771 #ifdef HAVE_LANGINFO_D_T_FMT
2772 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2774 strftime (shortbuf, sizeof shortbuf, "%c", tm);
2776 fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
2780 s = gpgme_pubkey_algo_name (key->subkeys->pubkey_algo);
2784 s2 = is_pgp ? "PGP" : "X.509";
2787 aval = key->subkeys->length;
2789 fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), s2, aval, s);
2791 fprintf (fp, _("Key Usage .: "));
2794 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) {
2795 fprintf (fp, "%s%s", delim, _("encryption"));
2798 if (key_check_cap (key, KEY_CAP_CAN_SIGN)) {
2799 fprintf (fp, "%s%s", delim, _("signing"));
2802 if (key_check_cap (key, KEY_CAP_CAN_CERTIFY)) {
2803 fprintf (fp, "%s%s", delim, _("certification"));
2809 s = key->subkeys->fpr;
2810 fputs (_("Fingerprint: "), fp);
2811 if (is_pgp && m_strlen(s) == 40) {
2812 for (i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) {
2817 putc (is_pgp ? ' ' : ':', fp);
2818 if (is_pgp && i == 4)
2823 for (i = 0; *s && s[1] && s[2]; s += 2, i++) {
2826 putc (is_pgp ? ' ' : ':', fp);
2827 if (is_pgp && i == 7)
2831 fprintf (fp, "%s\n", s);
2834 if (key->issuer_serial) {
2835 s = key->issuer_serial;
2837 fprintf (fp, _("Serial-No .: 0x%s\n"), s);
2840 if (key->issuer_name) {
2841 s = key->issuer_name;
2843 fprintf (fp, _("Issued By .: "));
2844 parse_and_print_user_id (fp, s);
2849 /* For PGP we list all subkeys. */
2851 gpgme_subkey_t subkey = NULL;
2853 for (idx = 1, subkey = key->subkeys; subkey; idx++, subkey = subkey->next) {
2857 if (m_strlen(s) == 16)
2858 s += 8; /* display only the short keyID */
2859 fprintf (fp, _("Subkey ....: 0x%s"), s);
2860 if (subkey->revoked) {
2862 fputs (_("[Revoked]"), fp);
2864 if (subkey->invalid) {
2866 fputs (_("[Invalid]"), fp);
2868 if (subkey->expired) {
2870 fputs (_("[Expired]"), fp);
2872 if (subkey->disabled) {
2874 fputs (_("[Disabled]"), fp);
2878 if (subkey->timestamp > 0) {
2879 tt = subkey->timestamp;
2881 tm = localtime (&tt);
2882 #ifdef HAVE_LANGINFO_D_T_FMT
2883 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2885 strftime (shortbuf, sizeof shortbuf, "%c", tm);
2887 fprintf (fp, _("Valid From : %s\n"), shortbuf);
2890 if (subkey->expires > 0) {
2891 tt = subkey->expires;
2893 tm = localtime (&tt);
2894 #ifdef HAVE_LANGINFO_D_T_FMT
2895 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2897 strftime (shortbuf, sizeof shortbuf, "%c", tm);
2899 fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
2903 s = gpgme_pubkey_algo_name (subkey->pubkey_algo);
2908 aval = subkey->length;
2912 fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), "PGP", aval, s);
2914 fprintf (fp, _("Key Usage .: "));
2917 if (subkey->can_encrypt) {
2918 fprintf (fp, "%s%s", delim, _("encryption"));
2921 if (subkey->can_sign) {
2922 fprintf (fp, "%s%s", delim, _("signing"));
2925 if (subkey->can_certify) {
2926 fprintf (fp, "%s%s", delim, _("certification"));
2934 setlocale (LC_TIME, "C");
2938 /* Show detailed information about the selected key */
2939 static void verify_key (crypt_key_t * key)
2942 char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
2944 gpgme_ctx_t listctx = NULL;
2946 gpgme_key_t k = NULL;
2949 mutt_mktemp (tempfile);
2950 if (!(fp = safe_fopen (tempfile, "w"))) {
2951 mutt_perror (_("Can't create temporary file"));
2955 mutt_message _("Collecting data...");
2957 print_key_info (key->kobj, fp);
2959 err = gpgme_new (&listctx);
2961 fprintf (fp, "Internal error: can't create gpgme context: %s\n",
2962 gpgme_strerror (err));
2965 if ((key->flags & KEYFLAG_ISX509))
2966 gpgme_set_protocol (listctx, GPGME_PROTOCOL_CMS);
2970 while ((s = k->chain_id) && k->subkeys && m_strcmp(s, k->subkeys->fpr)) {
2972 err = gpgme_op_keylist_start (listctx, s, 0);
2973 gpgme_key_release (k);
2976 err = gpgme_op_keylist_next (listctx, &k);
2978 fprintf (fp, _("Error finding issuer key: %s\n"), gpgme_strerror (err));
2981 gpgme_op_keylist_end (listctx);
2983 print_key_info (k, fp);
2986 fputs (_("Error: certification chain to long - stopping here\n"), fp);
2992 gpgme_key_release (k);
2993 gpgme_release (listctx);
2995 mutt_clear_error ();
2996 snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), crypt_keyid (key));
2997 mutt_do_pager (cmd, tempfile, 0, NULL);
3001 * Implementation of `findkeys'.
3005 /* Convert string_list_t into a pattern string suitable to be passed to GPGME.
3006 We need to convert spaces in an item into a '+' and '%' into
3008 static char *list_to_pattern (string_list_t * list)
3016 for (l = list; l; l = l->next) {
3017 for (s = l->data; *s; s++) {
3022 n++; /* delimiter or end of string */
3024 n++; /* make sure to allocate at least one byte */
3025 pattern = p = p_new(char, n);
3026 for (l = list; l; l = l->next) {
3031 for (s = l->data; *s; s++) {
3037 else if (*s == '+') {
3053 /* Return a list of keys which are candidates for the selection.
3054 Select by looking at the HINTS list. */
3055 static crypt_key_t *get_candidates (string_list_t * hints, unsigned int app,
3058 crypt_key_t *db, *k, **kend;
3064 gpgme_user_id_t uid = NULL;
3066 pattern = list_to_pattern (hints);
3070 err = gpgme_new (&ctx);
3072 mutt_error (_("gpgme_new failed: %s"), gpgme_strerror (err));
3080 if ((app & APPLICATION_PGP)) {
3081 /* Its all a mess. That old GPGME expects different things
3082 depending on the protocol. For gpg we don' t need percent
3083 escaped pappert but simple strings passed in an array to the
3084 keylist_ext_start function. */
3089 for (l = hints, n = 0; l; l = l->next) {
3090 if (l->data && *l->data)
3096 patarr = p_new(char *, n + 1);
3097 for (l = hints, n = 0; l; l = l->next) {
3098 if (l->data && *l->data)
3099 patarr[n++] = m_strdup(l->data);
3102 err = gpgme_op_keylist_ext_start (ctx, (const char **) patarr, secret, 0);
3103 for (n = 0; patarr[n]; n++)
3104 p_delete(&patarr[n]);
3107 mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
3108 gpgme_release (ctx);
3113 while (!(err = gpgme_op_keylist_next (ctx, &key))) {
3114 unsigned int flags = 0;
3116 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3117 flags |= KEYFLAG_CANENCRYPT;
3118 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3119 flags |= KEYFLAG_CANSIGN;
3121 #if 0 /* DISABLED code */
3123 /* Bug in gpg. Capabilities are not listed for secret
3124 keys. Try to deduce them from the algorithm. */
3126 switch (key->subkeys[0].pubkey_algo) {
3128 flags |= KEYFLAG_CANENCRYPT;
3129 flags |= KEYFLAG_CANSIGN;
3131 case GPGME_PK_ELG_E:
3132 flags |= KEYFLAG_CANENCRYPT;
3135 flags |= KEYFLAG_CANSIGN;
3139 #endif /* DISABLED code */
3141 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
3142 k = p_new(crypt_key_t, 1);
3151 if (gpg_err_code (err) != GPG_ERR_EOF)
3152 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3153 gpgme_op_keylist_end (ctx);
3158 if ((app & APPLICATION_SMIME)) {
3159 /* and now look for x509 certificates */
3160 gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
3161 err = gpgme_op_keylist_start (ctx, pattern, 0);
3163 mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
3164 gpgme_release (ctx);
3169 while (!(err = gpgme_op_keylist_next (ctx, &key))) {
3170 unsigned int flags = KEYFLAG_ISX509;
3172 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3173 flags |= KEYFLAG_CANENCRYPT;
3174 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3175 flags |= KEYFLAG_CANSIGN;
3177 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
3178 k = p_new(crypt_key_t, 1);
3187 if (gpg_err_code (err) != GPG_ERR_EOF)
3188 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3189 gpgme_op_keylist_end (ctx);
3192 gpgme_release (ctx);
3197 /* Add the string STR to the list HINTS. This list is later used to
3199 static string_list_t *crypt_add_string_to_hints (string_list_t * hints, const char *str)
3204 if ((scratch = m_strdup(str)) == NULL)
3207 for (t = strtok (scratch, " ,.:\"()<>\n"); t;
3208 t = strtok (NULL, " ,.:\"()<>\n")) {
3209 if (m_strlen(t) > 3)
3210 hints = mutt_add_list(hints, t);
3217 /* Display a menu to select a key from the array KEYS. FORCED_VALID
3218 will be set to true on return if the user did override the the
3220 static crypt_key_t *crypt_select_key (crypt_key_t * keys,
3221 address_t * p, const char *s,
3222 unsigned int app, int *forced_valid)
3225 crypt_key_t **key_table;
3228 char helpstr[SHORT_STRING], buf[LONG_STRING];
3230 int (*f) (const void *, const void *);
3231 int menu_to_use = 0;
3236 /* build the key table */
3239 for (k = keys; k; k = k->next) {
3240 if (!option (OPTPGPSHOWUNUSABLE) && (k->flags & KEYFLAG_CANTUSE)) {
3247 p_realloc(&key_table, keymax);
3253 if (!i && unusable) {
3254 mutt_error _("All matching keys are marked expired/revoked.");
3260 switch (PgpSortKeys & SORT_MASK) {
3262 f = crypt_compare_date;
3265 f = crypt_compare_keyid;
3268 f = crypt_compare_address;
3272 f = crypt_compare_trust;
3275 qsort (key_table, i, sizeof (crypt_key_t *), f);
3277 if (app & APPLICATION_PGP)
3278 menu_to_use = MENU_KEY_SELECT_PGP;
3279 else if (app & APPLICATION_SMIME)
3280 menu_to_use = MENU_KEY_SELECT_SMIME;
3283 mutt_make_help (buf, sizeof (buf), _("Exit "), menu_to_use, OP_EXIT);
3284 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3285 mutt_make_help (buf, sizeof (buf), _("Select "), menu_to_use,
3286 OP_GENERIC_SELECT_ENTRY);
3287 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3288 mutt_make_help (buf, sizeof (buf), _("Check key "),
3289 menu_to_use, OP_VERIFY_KEY);
3290 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3291 mutt_make_help (buf, sizeof (buf), _("Help"), menu_to_use, OP_HELP);
3292 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3294 menu = mutt_new_menu ();
3296 menu->make_entry = crypt_entry;
3297 menu->menu = menu_to_use;
3298 menu->help = helpstr;
3299 menu->data = key_table;
3304 if ((app & APPLICATION_PGP) && (app & APPLICATION_SMIME))
3305 ts = _("PGP and S/MIME keys matching");
3306 else if ((app & APPLICATION_PGP))
3307 ts = _("PGP keys matching");
3308 else if ((app & APPLICATION_SMIME))
3309 ts = _("S/MIME keys matching");
3311 ts = _("keys matching");
3314 snprintf (buf, sizeof (buf), _("%s <%s>."), ts, p->mailbox);
3316 snprintf (buf, sizeof (buf), _("%s \"%s\"."), ts, s);
3320 mutt_clear_error ();
3324 switch (mutt_menuLoop (menu)) {
3326 verify_key (key_table[menu->current]);
3327 menu->redraw = REDRAW_FULL;
3331 mutt_message ("%s", key_table[menu->current]->uid);
3334 case OP_GENERIC_SELECT_ENTRY:
3335 /* FIXME make error reporting more verbose - this should be
3336 easy because gpgme provides more information */
3337 if (option (OPTPGPCHECKTRUST)) {
3338 if (!crypt_key_is_valid (key_table[menu->current])) {
3339 mutt_error _("This key can't be used: "
3340 "expired/disabled/revoked.");
3345 if (option (OPTPGPCHECKTRUST) &&
3346 (!crypt_id_is_valid (key_table[menu->current])
3347 || !crypt_id_is_strong (key_table[menu->current]))) {
3349 char buff[LONG_STRING];
3351 if (key_table[menu->current]->flags & KEYFLAG_CANTUSE)
3352 s = N_("ID is expired/disabled/revoked.");
3354 gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
3355 gpgme_user_id_t uid = NULL;
3360 uid = key_table[menu->current]->kobj->uids;
3361 for (j = 0; (j < key_table[menu->current]->idx) && uid;
3362 j++, uid = uid->next);
3364 val = uid->validity;
3367 case GPGME_VALIDITY_UNKNOWN:
3368 case GPGME_VALIDITY_UNDEFINED:
3369 warn_s = N_("ID has undefined validity.");
3371 case GPGME_VALIDITY_NEVER:
3372 warn_s = N_("ID is not valid.");
3374 case GPGME_VALIDITY_MARGINAL:
3375 warn_s = N_("ID is only marginally valid.");
3377 case GPGME_VALIDITY_FULL:
3378 case GPGME_VALIDITY_ULTIMATE:
3382 snprintf (buff, sizeof (buff),
3383 _("%s Do you really want to use the key?"), _(warn_s));
3385 if (mutt_yesorno (buff, 0) != 1) {
3386 mutt_clear_error ();
3393 k = crypt_copy_key (key_table[menu->current]);
3404 mutt_menuDestroy (&menu);
3405 p_delete(&key_table);
3407 set_option (OPTNEEDREDRAW);
3412 static crypt_key_t *crypt_getkeybyaddr (address_t * a, short abilities,
3413 unsigned int app, int *forced_valid)
3416 string_list_t *hints = NULL;
3421 int this_key_has_strong;
3422 int this_key_has_weak;
3423 int this_key_has_invalid;
3426 crypt_key_t *keys, *k;
3427 crypt_key_t *the_valid_key = NULL;
3428 crypt_key_t *matches = NULL;
3429 crypt_key_t **matches_endp = &matches;
3433 if (a && a->mailbox)
3434 hints = crypt_add_string_to_hints (hints, a->mailbox);
3435 if (a && a->personal)
3436 hints = crypt_add_string_to_hints (hints, a->personal);
3438 mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
3439 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
3441 string_list_wipe(&hints);
3446 for (k = keys; k; k = k->next) {
3447 if (abilities && !(k->flags & abilities)) {
3451 this_key_has_weak = 0; /* weak but valid match */
3452 this_key_has_invalid = 0; /* invalid match */
3453 this_key_has_strong = 0; /* strong and valid match */
3454 match = 0; /* any match */
3456 r = rfc822_parse_adrlist (NULL, k->uid);
3457 for (p = r; p; p = p->next) {
3458 int validity = crypt_id_matches_addr (a, p, k);
3460 if (validity & CRYPT_KV_MATCH) /* something matches */
3463 /* is this key a strong candidate? */
3464 if ((validity & CRYPT_KV_VALID)
3465 && (validity & CRYPT_KV_STRONGID)
3466 && (validity & CRYPT_KV_ADDR)) {
3467 if (the_valid_key && the_valid_key != k)
3470 this_key_has_strong = 1;
3472 else if ((validity & CRYPT_KV_MATCH)
3473 && !(validity & CRYPT_KV_VALID))
3474 this_key_has_invalid = 1;
3475 else if ((validity & CRYPT_KV_MATCH)
3476 && (!(validity & CRYPT_KV_STRONGID)
3477 || !(validity & CRYPT_KV_ADDR)))
3478 this_key_has_weak = 1;
3480 address_list_wipe(&r);
3485 if (!this_key_has_strong && this_key_has_invalid)
3487 if (!this_key_has_strong && this_key_has_weak)
3490 *matches_endp = tmp = crypt_copy_key (k);
3491 matches_endp = &tmp->next;
3492 the_valid_key = tmp;
3496 crypt_free_key (&keys);
3499 if (the_valid_key && !multi && !weak
3500 && !(invalid && option (OPTPGPSHOWUNUSABLE))) {
3502 * There was precisely one strong match on a valid ID, there
3503 * were no valid keys with weak matches, and we aren't
3504 * interested in seeing invalid keys.
3506 * Proceed without asking the user.
3508 k = crypt_copy_key (the_valid_key);
3512 * Else: Ask the user.
3514 k = crypt_select_key (matches, a, NULL, app, forced_valid);
3516 crypt_free_key (&matches);
3525 static crypt_key_t *crypt_getkeybystr (char *p, short abilities,
3526 unsigned int app, int *forced_valid)
3528 string_list_t *hints = NULL;
3530 crypt_key_t *matches = NULL;
3531 crypt_key_t **matches_endp = &matches;
3535 mutt_message (_("Looking for keys matching \"%s\"..."), p);
3539 hints = crypt_add_string_to_hints (hints, p);
3540 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
3541 string_list_wipe(&hints);
3546 for (k = keys; k; k = k->next) {
3547 if (abilities && !(k->flags & abilities))
3552 if (!*p || !m_strcasecmp(p, crypt_keyid (k))
3553 || (!m_strncasecmp(p, "0x", 2)
3554 && !m_strcasecmp(p + 2, crypt_keyid (k)))
3555 || (option (OPTPGPLONGIDS)
3556 && !m_strncasecmp(p, "0x", 2)
3557 && !m_strcasecmp(p + 2, crypt_keyid (k) + 8))
3558 || m_stristr(k->uid, p)) {
3561 *matches_endp = tmp = crypt_copy_key (k);
3562 matches_endp = &tmp->next;
3566 crypt_free_key (&keys);
3569 k = crypt_select_key (matches, NULL, p, app, forced_valid);
3570 crypt_free_key (&matches);
3577 /* Display TAG as a prompt to ask for a key. If WHATFOR is not null
3578 use it as default and store it under that label as the next
3579 default. ABILITIES describe the required key abilities (sign,
3580 encrypt) and APP the type of the requested key; ether S/MIME or
3581 PGP. Return a copy of the key or NULL if not found. */
3582 static crypt_key_t *crypt_ask_for_key (char *tag,
3585 unsigned int app, int *forced_valid)
3588 char resp[SHORT_STRING];
3589 struct crypt_cache *l = NULL;
3593 forced_valid = &dummy;
3595 mutt_clear_error ();
3601 for (l = id_defaults; l; l = l->next)
3602 if (!m_strcasecmp(whatfor, l->what)) {
3603 m_strcpy(resp, sizeof(resp), NONULL(l->dflt));
3611 if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0)
3616 m_strreplace(&l->dflt, resp);
3618 l = p_new(struct crypt_cache, 1);
3619 l->next = id_defaults;
3621 l->what = m_strdup(whatfor);
3622 l->dflt = m_strdup(resp);
3626 if ((key = crypt_getkeybystr (resp, abilities, app, forced_valid)))
3634 /* This routine attempts to find the keyids of the recipients of a
3635 message. It returns NULL if any of the keys can not be found. */
3636 static char *find_keys (address_t * to, address_t * cc, address_t * bcc,
3639 char *keyID, *keylist = NULL, *t;
3640 ssize_t keylist_size = 0;
3641 ssize_t keylist_used = 0;
3642 address_t *tmp = NULL, *addr = NULL;
3643 address_t **last = &tmp;
3646 crypt_key_t *k_info, *key;
3647 const char *fqdn = mutt_fqdn (1);
3650 *r_application = APPLICATION_PGP | APPLICATION_SMIME;
3653 for (i = 0; i < 3; i++) {
3668 *last = address_list_dup (p);
3670 last = &((*last)->next);
3674 rfc822_qualify (tmp, fqdn);
3676 tmp = mutt_remove_duplicates (tmp);
3678 for (p = tmp; p; p = p->next) {
3679 char buf[LONG_STRING];
3680 int forced_valid = 0;
3685 if ((keyID = mutt_crypt_hook (p)) != NULL) {
3688 snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"),
3690 if ((r = mutt_yesorno (buf, M_YES)) == M_YES) {
3691 /* check for e-mail address */
3692 if ((t = strchr (keyID, '@')) &&
3693 (addr = rfc822_parse_adrlist (NULL, keyID))) {
3695 rfc822_qualify (addr, fqdn);
3700 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
3701 *r_application, &forced_valid);
3703 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
3704 app, &forced_valid);
3710 address_list_wipe(&tmp);
3711 address_list_wipe(&addr);
3717 && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT,
3718 app, &forced_valid)) == NULL) {
3719 snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
3721 if ((key = crypt_ask_for_key (buf, q->mailbox, KEYFLAG_CANENCRYPT,
3727 &forced_valid)) == NULL) {
3729 address_list_wipe(&tmp);
3730 address_list_wipe(&addr);
3738 const char *s = crypt_fpr (key);
3741 if (key->flags & KEYFLAG_ISX509)
3742 *r_application &= ~APPLICATION_PGP;
3743 if (!(key->flags & KEYFLAG_ISX509))
3744 *r_application &= ~APPLICATION_SMIME;
3747 keylist_size += m_strlen(s) + 4 + 1;
3748 p_realloc(&keylist, keylist_size);
3749 sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */
3750 keylist_used ? " " : "", s, forced_valid ? "!" : "");
3752 keylist_used = m_strlen(keylist);
3754 crypt_free_key (&key);
3755 address_list_wipe(&addr);
3757 address_list_wipe(&tmp);
3761 char *pgp_gpgme_findkeys (address_t * to, address_t * cc, address_t * bcc)
3763 return find_keys (to, cc, bcc, APPLICATION_PGP);
3766 char *smime_gpgme_findkeys (address_t * to, address_t * cc, address_t * bcc)
3768 return find_keys (to, cc, bcc, APPLICATION_SMIME);
3772 * Implementation of `init'.
3775 /* Initialization. */
3776 static void init_gpgme (void)
3778 /* Make sure that gpg-agent is running. */
3779 if (!getenv ("GPG_AGENT_INFO")) {
3780 mutt_error ("\nUsing GPGME backend, although no gpg-agent is running");
3781 if (mutt_any_key_to_continue (NULL) == -1)
3786 void pgp_gpgme_init (void)
3791 void smime_gpgme_init (void)
3795 static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime)
3798 char input_signas[SHORT_STRING];
3801 if (msg->security & APPLICATION_PGP)
3803 else if (msg->security & APPLICATION_SMIME)
3808 mutt_multi_choice (_
3809 ("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?"),
3813 mutt_multi_choice (_
3814 ("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?"),
3818 case 1: /* (e)ncrypt */
3819 msg->security |= (is_smime ? SMIMEENCRYPT : PGPENCRYPT);
3820 msg->security &= ~(is_smime ? SMIMESIGN : PGPSIGN);
3823 case 2: /* (s)ign */
3824 msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
3825 msg->security &= ~(is_smime ? SMIMEENCRYPT : PGPENCRYPT);
3828 case 3: /* sign (a)s */
3829 /* unset_option(OPTCRYPTCHECKTRUST); */
3830 if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
3831 is_smime ? APPLICATION_SMIME :
3832 APPLICATION_PGP, NULL))) {
3833 snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p));
3834 m_strreplace(is_smime ? &SmimeDefaultKey : &PgpSignAs,
3836 crypt_free_key (&p);
3838 msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
3842 msg->security &= (is_smime ? ~SMIMESIGN : ~PGPSIGN);
3845 *redraw = REDRAW_FULL;
3848 case 4: /* (b)oth */
3850 (is_smime ? (SMIMEENCRYPT | SMIMESIGN) : (PGPENCRYPT | PGPSIGN));
3853 case 5: /* (p)gp or s/(m)ime */
3854 is_smime = !is_smime;
3857 case 6: /* (c)lear */
3862 if (choice == 6 || choice == 7);
3863 else if (is_smime) {
3864 msg->security &= ~APPLICATION_PGP;
3865 msg->security |= APPLICATION_SMIME;
3868 msg->security &= ~APPLICATION_SMIME;
3869 msg->security |= APPLICATION_PGP;
3872 return (msg->security);
3875 int pgp_gpgme_send_menu (HEADER * msg, int *redraw)
3877 return gpgme_send_menu (msg, redraw, 0);
3880 int smime_gpgme_send_menu (HEADER * msg, int *redraw)
3882 return gpgme_send_menu (msg, redraw, 1);
3885 static int verify_sender (HEADER * h, gpgme_protocol_t protocol __attribute__((unused)))
3887 address_t *sender = NULL;
3888 unsigned int ret = 1;
3891 h->env->from = mutt_expand_aliases (h->env->from);
3892 sender = h->env->from;
3894 else if (h->env->sender) {
3895 h->env->sender = mutt_expand_aliases (h->env->sender);
3896 sender = h->env->sender;
3900 if (signature_key) {
3901 gpgme_key_t key = signature_key;
3902 gpgme_user_id_t uid = NULL;
3903 int sender_length = 0;
3906 sender_length = m_strlen(sender->mailbox);
3907 for (uid = key->uids; uid && ret; uid = uid->next) {
3908 uid_length = m_strlen(uid->email);
3909 if (1 && (uid->email[0] == '<')
3910 && (uid->email[uid_length - 1] == '>')
3911 && (uid_length == sender_length + 2)
3912 && (!strncmp (uid->email + 1, sender->mailbox, sender_length)))
3917 mutt_any_key_to_continue ("Failed to verify sender");
3920 mutt_any_key_to_continue ("Failed to figure out sender");
3922 if (signature_key) {
3923 gpgme_key_release (signature_key);
3924 signature_key = NULL;
3930 int smime_gpgme_verify_sender (HEADER * h)
3932 return verify_sender (h, GPGME_PROTOCOL_CMS);