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/lib-lib.h>
46 #include <lib-mime/mime.h>
48 #include <lib-ui/curses.h>
49 #include <lib-ui/enter.h>
50 #include <lib-ui/menu.h>
55 #include <lib-crypt/crypt.h>
59 #include "recvattach.h"
65 #define digitp(p) (*(p) >= '0' && *(p) <= '9')
66 #define hexdigitp(a) (digitp (a) \
67 || (*(a) >= 'A' && *(a) <= 'F') \
68 || (*(a) >= 'a' && *(a) <= 'f'))
69 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
70 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
71 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
73 /* Values used for comparing addresses. */
74 #define CRYPT_KV_VALID 1
75 #define CRYPT_KV_ADDR 2
76 #define CRYPT_KV_STRING 4
77 #define CRYPT_KV_STRONGID 8
78 #define CRYPT_KV_MATCH (CRYPT_KV_ADDR|CRYPT_KV_STRING)
87 struct crypt_cache *next;
95 /* We work based on user IDs, getting from a user ID to the key is
96 check and does not need any memory (gpgme uses reference counting). */
97 typedef struct crypt_keyinfo {
98 struct crypt_keyinfo *next;
100 int idx; /* and the user ID at this index */
101 const char *uid; /* and for convenience point to this user ID */
102 unsigned int flags; /* global and per uid flags (for convenience) */
105 typedef struct crypt_entry {
111 static struct crypt_cache *id_defaults = NULL;
112 static gpgme_key_t signature_key = NULL;
115 * General helper functions.
118 /* return true when S points to a didgit or letter. */
119 static int digit_or_letter (const unsigned char *s)
121 return ((*s >= '0' && *s <= '9')
122 || (*s >= 'A' && *s <= 'Z')
123 || (*s >= 'a' && *s <= 'z'));
127 /* Print the utf-8 encoded string BUF of length LEN bytes to stream
128 FP. Convert the character set. */
129 static void print_utf8 (FILE * fp, const char *buf, ssize_t len)
133 tstr = p_dupstr(buf, len);
134 mutt_convert_string (&tstr, "utf-8", Charset, M_ICONV_HOOK_FROM);
144 /* Return the keyID for the key K. Note that this string is valid as
145 long as K is valid */
146 static const char *crypt_keyid (crypt_key_t * k)
148 const char *s = "????????";
150 if (k->kobj && k->kobj->subkeys) {
151 s = k->kobj->subkeys->keyid;
152 if ((!option (OPTPGPLONGIDS)) && (m_strlen(s) == 16))
153 /* Return only the short keyID. */
160 /* Return the hexstring fingerprint from the key K. */
161 static const char *crypt_fpr (crypt_key_t * k)
165 if (k->kobj && k->kobj->subkeys)
166 s = k->kobj->subkeys->fpr;
171 /* Parse FLAGS and return a statically allocated(!) string with them. */
172 static char *crypt_key_abilities (int flags)
176 if (!(flags & KEYFLAG_CANENCRYPT))
178 else if (flags & KEYFLAG_PREFER_SIGNING)
183 if (!(flags & KEYFLAG_CANSIGN))
185 else if (flags & KEYFLAG_PREFER_ENCRYPTION)
195 /* Parse FLAGS and return a character describing the most important flag. */
196 static char crypt_flags (int flags)
198 if (flags & KEYFLAG_REVOKED)
200 else if (flags & KEYFLAG_EXPIRED)
202 else if (flags & KEYFLAG_DISABLED)
204 else if (flags & KEYFLAG_CRITICAL)
210 /* Return a copy of KEY. */
211 static crypt_key_t *crypt_copy_key (crypt_key_t *key)
215 k = p_new(crypt_key_t, 1);
217 gpgme_key_ref (key->kobj);
220 k->flags = key->flags;
225 /* Release all the keys at the address of KEYLIST and set the address
227 static void crypt_free_key (crypt_key_t ** keylist)
230 crypt_key_t *k = (*keylist)->next;
237 /* Return trute when key K is valid. */
238 static int crypt_key_is_valid (crypt_key_t * k)
240 if (k->flags & KEYFLAG_CANTUSE)
245 /* Return true whe validity of KEY is sufficient. */
246 static int crypt_id_is_strong (crypt_key_t * key)
248 gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
249 gpgme_user_id_t uid = NULL;
253 if ((key->flags & KEYFLAG_ISX509))
256 for (i = 0, uid = key->kobj->uids; (i < key->idx) && uid;
257 i++, uid = uid->next);
262 case GPGME_VALIDITY_UNKNOWN:
263 case GPGME_VALIDITY_UNDEFINED:
264 case GPGME_VALIDITY_NEVER:
265 case GPGME_VALIDITY_MARGINAL:
269 case GPGME_VALIDITY_FULL:
270 case GPGME_VALIDITY_ULTIMATE:
278 /* Return true when the KEY is valid, i.e. not marked as unusable. */
279 static int crypt_id_is_valid (crypt_key_t * key)
281 return !(key->flags & KEYFLAG_CANTUSE);
284 /* Return a bit vector describing how well the addresses ADDR and
285 U_ADDR match and whether KEY is valid. */
286 static int crypt_id_matches_addr (address_t * addr, address_t * u_addr,
291 if (crypt_id_is_valid (key))
292 rv |= CRYPT_KV_VALID;
294 if (crypt_id_is_strong (key))
295 rv |= CRYPT_KV_STRONGID;
297 if (addr->mailbox && u_addr->mailbox
298 && m_strcasecmp(addr->mailbox, u_addr->mailbox) == 0)
301 if (addr->personal && u_addr->personal
302 && m_strcasecmp(addr->personal, u_addr->personal) == 0)
303 rv |= CRYPT_KV_STRING;
310 * GPGME convenient functions.
313 /* Create a new gpgme context and return it. With FOR_SMIME set to
314 true, the protocol of the context is set to CMS. */
315 static gpgme_ctx_t create_gpgme_context (int for_smime)
320 err = gpgme_new (&ctx);
322 mutt_error (_("error creating gpgme context: %s\n"), gpgme_strerror (err));
328 err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
330 mutt_error (_("error enabling CMS protocol: %s\n"), gpgme_strerror (err));
339 /* Create a new gpgme data object. This is a wrapper to die on
341 static gpgme_data_t create_gpgme_data (void)
346 err = gpgme_data_new (&data);
348 mutt_error (_("error creating gpgme data object: %s\n"),
349 gpgme_strerror (err));
356 /* Create a new GPGME Data object from the mail body A. With CONVERT
357 passed as true, the lines are converted to CR,LF if required.
358 Return NULL on error or the gpgme_data_t object on success. */
359 static gpgme_data_t body_to_data_object (BODY * a, int convert)
361 char tempfile[_POSIX_PATH_MAX];
366 mutt_mktemp (tempfile);
367 fptmp = safe_fopen (tempfile, "w+");
369 mutt_perror (tempfile);
373 mutt_write_mime_header (a, fptmp);
375 mutt_write_mime_body (a, fptmp);
379 unsigned char buf[1];
381 data = create_gpgme_data ();
383 while ((c = fgetc (fptmp)) != EOF) {
387 if (c == '\n' && !hadcr) {
389 gpgme_data_write (data, buf, 1);
394 /* FIXME: This is quite suboptimal */
396 gpgme_data_write (data, buf, 1);
399 gpgme_data_seek (data, 0, SEEK_SET);
403 err = gpgme_data_new_from_file (&data, tempfile, 1);
407 mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
414 /* Create a GPGME data object from the stream FP but limit the object
415 to LENGTH bytes starting at OFFSET bytes from the beginning of the
417 static gpgme_data_t file_to_data_object (FILE * fp, long offset, long length)
422 err = gpgme_data_new_from_filepart (&data, NULL, fp, offset, length);
424 mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
431 /* Write a GPGME data object to the stream FP. */
432 static int data_object_to_stream (gpgme_data_t data, FILE * fp)
438 err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1)
439 ? gpgme_error_from_errno (errno) : 0);
441 mutt_error (_("error rewinding data object: %s\n"), gpgme_strerror (err));
445 while ((nread = gpgme_data_read (data, buf, sizeof (buf)))) {
446 /* fixme: we are not really converting CRLF to LF but just
447 skipping CR. Doing it correctly needs a more complex logic */
448 for (p = buf; nread; p++, nread--) {
454 mutt_perror ("[tempfile]");
459 mutt_error (_("error reading data object: %s\n"), strerror (errno));
465 /* Copy a data object to a newly created temporay file and return that
466 filename. Caller must free. With RET_FP not NULL, don't close the
467 stream but return it there. */
468 static char *data_object_to_tempfile (gpgme_data_t data, FILE ** ret_fp)
471 char tempfile[_POSIX_PATH_MAX];
475 mutt_mktemp (tempfile);
476 fp = safe_fopen (tempfile, "w+");
478 mutt_perror (tempfile);
482 err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1)
483 ? gpgme_error_from_errno (errno) : 0);
487 while ((nread = gpgme_data_read (data, buf, sizeof (buf)))) {
488 if (fwrite (buf, nread, 1, fp) != 1) {
489 mutt_perror (tempfile);
501 mutt_error (_("error reading data object: %s\n"), gpgme_strerror (err));
508 return m_strdup(tempfile);
512 /* Create a GpgmeRecipientSet from the keys in the string KEYLIST.
513 The keys must be space delimited. */
514 static gpgme_key_t *create_recipient_set (const char *keylist,
515 gpgme_protocol_t protocol)
521 gpgme_key_t *rset = NULL;
522 unsigned int rset_n = 0;
523 gpgme_key_t key = NULL;
524 gpgme_ctx_t context = NULL;
526 err = gpgme_new (&context);
528 err = gpgme_set_protocol (context, protocol);
535 for (i = 0; *s && *s != ' ' && i < ssizeof(buf) - 1;)
539 if (i > 1 && buf[i - 1] == '!') {
540 /* The user selected to override the valididy of that
544 err = gpgme_get_key (context, buf, &key, 0);
546 key->uids->validity = GPGME_VALIDITY_FULL;
550 err = gpgme_get_key (context, buf, &key, 0);
553 p_realloc(&rset, rset_n + 1);
554 rset[rset_n++] = key;
557 mutt_error (_("error adding recipient `%s': %s\n"),
558 buf, gpgme_strerror (err));
566 /* NULL terminate. */
567 p_realloc(&rset, rset_n + 1);
568 rset[rset_n++] = NULL;
571 gpgme_release (context);
577 /* Make sure that the correct signer is set. Returns 0 on success. */
578 static int set_signer (gpgme_ctx_t ctx, int for_smime)
580 char *signid = for_smime ? SmimeDefaultKey : PgpSignAs;
583 gpgme_key_t key, key2;
585 if (!signid || !*signid)
588 listctx = create_gpgme_context (for_smime);
589 err = gpgme_op_keylist_start (listctx, signid, 1);
591 err = gpgme_op_keylist_next (listctx, &key);
593 gpgme_release (listctx);
594 mutt_error (_("secret key `%s' not found: %s\n"),
595 signid, gpgme_strerror (err));
598 err = gpgme_op_keylist_next (listctx, &key2);
600 gpgme_key_release (key);
601 gpgme_key_release (key2);
602 gpgme_release (listctx);
603 mutt_error (_("ambiguous specification of secret key `%s'\n"), signid);
606 gpgme_op_keylist_end (listctx);
607 gpgme_release (listctx);
609 gpgme_signers_clear (ctx);
610 err = gpgme_signers_add (ctx, key);
611 gpgme_key_release (key);
613 mutt_error (_("error setting secret key `%s': %s\n"),
614 signid, gpgme_strerror (err));
621 /* Encrypt the gpgme data object PLAINTEXT to the recipients in RSET
622 and return an allocated filename to a temporary file containing the
623 enciphered text. With USE_SMIME set to true, the smime backend is
624 used. With COMBINED_SIGNED a PGP message is signed and
625 encrypted. Returns NULL in case of error */
626 static char *encrypt_gpgme_object (gpgme_data_t plaintext, gpgme_key_t * rset,
627 int use_smime, int combined_signed)
631 gpgme_data_t ciphertext;
634 ctx = create_gpgme_context (use_smime);
636 gpgme_set_armor (ctx, 1);
638 ciphertext = create_gpgme_data ();
640 if (combined_signed) {
641 if (set_signer (ctx, use_smime)) {
642 gpgme_data_release (ciphertext);
646 err = gpgme_op_encrypt_sign (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST,
647 plaintext, ciphertext);
650 err = gpgme_op_encrypt (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST,
651 plaintext, ciphertext);
652 mutt_need_hard_redraw ();
654 mutt_error (_("error encrypting data: %s\n"), gpgme_strerror (err));
655 gpgme_data_release (ciphertext);
662 outfile = data_object_to_tempfile (ciphertext, NULL);
663 gpgme_data_release (ciphertext);
667 /* Find the "micalg" parameter from the last Gpgme operation on
668 context CTX. It is expected that this operation was a sign
669 operation. Return the algorithm name as a C string in buffer BUF
670 which must have been allocated by the caller with size BUFLEN.
671 Returns 0 on success or -1 in case of an error. The return string
672 is truncted to BUFLEN - 1. */
673 static int get_micalg (gpgme_ctx_t ctx, char *buf, ssize_t buflen)
675 gpgme_sign_result_t result = NULL;
676 const char *algorithm_name = NULL;
682 result = gpgme_op_sign_result (ctx);
684 algorithm_name = gpgme_hash_algo_name (result->signatures->hash_algo);
685 if (algorithm_name) {
686 m_strcpy(buf, buflen, algorithm_name);
690 return *buf ? 0 : -1;
693 static void print_time (time_t t, STATE * s)
697 setlocale (LC_TIME, "");
698 #ifdef HAVE_LANGINFO_D_T_FMT
699 strftime (p, sizeof (p), nl_langinfo (D_T_FMT), localtime (&t));
701 strftime (p, sizeof (p), "%c", localtime (&t));
703 setlocale (LC_TIME, "C");
704 state_attach_puts (p, s);
708 * Implementation of `sign_message'.
711 /* Sign the MESSAGE in body A either using OpenPGP or S/MIME when
712 USE_SMIME is passed as true. Returns the new body or NULL on
714 static BODY *sign_message (BODY * a, int use_smime)
721 gpgme_data_t message, signature;
723 convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */
725 message = body_to_data_object (a, 1);
728 signature = create_gpgme_data ();
730 ctx = create_gpgme_context (use_smime);
732 gpgme_set_armor (ctx, 1);
734 if (set_signer (ctx, use_smime)) {
735 gpgme_data_release (signature);
740 err = gpgme_op_sign (ctx, message, signature, GPGME_SIG_MODE_DETACH);
741 mutt_need_hard_redraw ();
742 gpgme_data_release (message);
744 gpgme_data_release (signature);
746 mutt_error (_("error signing data: %s\n"), gpgme_strerror (err));
750 sigfile = data_object_to_tempfile (signature, NULL);
751 gpgme_data_release (signature);
758 t->type = TYPEMULTIPART;
759 t->subtype = m_strdup("signed");
760 t->encoding = ENC7BIT;
762 t->disposition = DISPINLINE;
764 parameter_set_boundary(&t->parameter);
765 parameter_setval(&t->parameter, "protocol",
766 use_smime ? "application/pkcs7-signature"
767 : "application/pgp-signature");
768 /* Get the micalg from gpgme. Old gpgme versions don't support this
769 for S/MIME so we assume sha-1 in this case. */
770 if (!get_micalg (ctx, buf, sizeof buf))
771 parameter_setval(&t->parameter, "micalg", buf);
773 parameter_setval(&t->parameter, "micalg", "sha1");
779 t->parts->next = body_new();
781 t->type = TYPEAPPLICATION;
783 t->subtype = m_strdup("pkcs7-signature");
784 parameter_setval(&t->parameter, "name", "smime.p7s");
785 t->encoding = ENCBASE64;
787 t->disposition = DISPATTACH;
788 t->d_filename = m_strdup("smime.p7s");
791 t->subtype = m_strdup("pgp-signature");
793 t->disposition = DISPINLINE;
794 t->encoding = ENC7BIT;
796 t->filename = sigfile;
797 t->unlink = 1; /* ok to remove this file after sending. */
803 BODY *pgp_gpgme_sign_message (BODY * a)
805 return sign_message (a, 0);
808 BODY *smime_gpgme_sign_message (BODY * a)
810 return sign_message (a, 1);
814 * Implementation of `encrypt_message'.
817 /* Encrypt the mail body A to all keys given as space separated keyids
818 or fingerprints in KEYLIST and return the encrypted body. */
819 BODY *pgp_gpgme_encrypt_message (BODY * a, char *keylist, int sign)
821 char *outfile = NULL;
823 gpgme_key_t *rset = NULL;
824 gpgme_data_t plaintext;
826 rset = create_recipient_set (keylist, GPGME_PROTOCOL_OpenPGP);
832 plaintext = body_to_data_object (a, 0);
838 outfile = encrypt_gpgme_object (plaintext, rset, 0, sign);
839 gpgme_data_release (plaintext);
845 t->type = TYPEMULTIPART;
846 t->subtype = m_strdup("encrypted");
847 t->encoding = ENC7BIT;
849 t->disposition = DISPINLINE;
851 parameter_set_boundary(&t->parameter);
852 parameter_setval(&t->parameter, "protocol", "application/pgp-encrypted");
854 t->parts = body_new();
855 t->parts->type = TYPEAPPLICATION;
856 t->parts->subtype = m_strdup("pgp-encrypted");
857 t->parts->encoding = ENC7BIT;
859 t->parts->next = body_new();
860 t->parts->next->type = TYPEAPPLICATION;
861 t->parts->next->subtype = m_strdup("octet-stream");
862 t->parts->next->encoding = ENC7BIT;
863 t->parts->next->filename = outfile;
864 t->parts->next->use_disp = 1;
865 t->parts->next->disposition = DISPINLINE;
866 t->parts->next->unlink = 1; /* delete after sending the message */
867 t->parts->next->d_filename = m_strdup("msg.asc"); /* non pgp/mime
874 * Implementation of `smime_build_smime_entity'.
877 /* Encrypt the mail body A to all keys given as space separated
878 fingerprints in KEYLIST and return the S/MIME encrypted body. */
879 BODY *smime_gpgme_build_smime_entity (BODY * a, char *keylist)
881 char *outfile = NULL;
883 gpgme_key_t *rset = NULL;
884 gpgme_data_t plaintext;
886 rset = create_recipient_set (keylist, GPGME_PROTOCOL_CMS);
890 plaintext = body_to_data_object (a, 0);
896 outfile = encrypt_gpgme_object (plaintext, rset, 1, 0);
897 gpgme_data_release (plaintext);
903 t->type = TYPEAPPLICATION;
904 t->subtype = m_strdup("pkcs7-mime");
905 parameter_setval(&t->parameter, "name", "smime.p7m");
906 parameter_setval(&t->parameter, "smime-type", "enveloped-data");
907 t->encoding = ENCBASE64; /* The output of OpenSSL SHOULD be binary */
909 t->disposition = DISPATTACH;
910 t->d_filename = m_strdup("smime.p7m");
911 t->filename = outfile;
912 t->unlink = 1; /*delete after sending the message */
921 * Implementation of `verify_one'.
924 /* Display the common attributes of the signature summary SUM.
925 Return 1 if there is is a severe warning.
927 static int show_sig_summary (unsigned long sum,
928 gpgme_ctx_t ctx, gpgme_key_t key, int idx,
933 if ((sum & GPGME_SIGSUM_KEY_REVOKED)) {
934 state_attach_puts (_("Warning: One of the keys has been revoked\n"), s);
938 if ((sum & GPGME_SIGSUM_KEY_EXPIRED)) {
939 time_t at = key->subkeys->expires ? key->subkeys->expires : 0;
942 state_attach_puts (_("Warning: The key used to create the "
943 "signature expired at: "), s);
945 state_attach_puts ("\n", s);
948 state_attach_puts (_("Warning: At least one certification key "
949 "has expired\n"), s);
952 if ((sum & GPGME_SIGSUM_SIG_EXPIRED)) {
953 gpgme_verify_result_t result;
954 gpgme_signature_t sig;
957 result = gpgme_op_verify_result (ctx);
959 for (sig = result->signatures, i = 0; sig && (i < idx);
960 sig = sig->next, i++);
962 state_attach_puts (_("Warning: The signature expired at: "), s);
963 print_time (sig ? sig->exp_timestamp : 0, s);
964 state_attach_puts ("\n", s);
967 if ((sum & GPGME_SIGSUM_KEY_MISSING))
968 state_attach_puts (_("Can't verify due to a missing "
969 "key or certificate\n"), s);
971 if ((sum & GPGME_SIGSUM_CRL_MISSING)) {
972 state_attach_puts (_("The CRL is not available\n"), s);
976 if ((sum & GPGME_SIGSUM_CRL_TOO_OLD)) {
977 state_attach_puts (_("Available CRL is too old\n"), s);
981 if ((sum & GPGME_SIGSUM_BAD_POLICY))
982 state_attach_puts (_("A policy requirement was not met\n"), s);
984 if ((sum & GPGME_SIGSUM_SYS_ERROR)) {
985 const char *t0 = NULL, *t1 = NULL;
986 gpgme_verify_result_t result;
987 gpgme_signature_t sig;
990 state_attach_puts (_("A system error occurred"), s);
992 /* Try to figure out some more detailed system error information. */
993 result = gpgme_op_verify_result (ctx);
994 for (sig = result->signatures, i = 0; sig && (i < idx);
995 sig = sig->next, i++);
998 t1 = sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
1002 state_attach_puts (": ", s);
1004 state_attach_puts (t0, s);
1005 if (t1 && !(t0 && !m_strcmp(t0, t1))) {
1007 state_attach_puts (",", s);
1008 state_attach_puts (t1, s);
1011 state_attach_puts ("\n", s);
1018 static void show_fingerprint (gpgme_key_t key, STATE * state)
1023 const char *prefix = _("Fingerprint: ");
1027 s = key->subkeys ? key->subkeys->fpr : NULL;
1030 is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
1032 buf = xmalloc(m_strlen(prefix) + m_strlen(s) * 4 + 2);
1033 strcpy (buf, prefix); /* __STRCPY_CHECKED__ */
1034 p = buf + m_strlen(buf);
1035 if (is_pgp && m_strlen(s) == 40) { /* PGP v4 style formatted. */
1036 for (i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) {
1047 for (i = 0; *s && s[1] && s[2]; s += 2, i++) {
1050 *p++ = is_pgp ? ' ' : ':';
1051 if (is_pgp && i == 7)
1056 /* just in case print remaining odd digits */
1061 state_attach_puts (buf, state);
1065 /* Show the valididy of a key used for one signature. */
1066 static void show_one_sig_validity (gpgme_ctx_t ctx, int idx, STATE * s)
1068 gpgme_verify_result_t result = NULL;
1069 gpgme_signature_t sig = NULL;
1070 const char *txt = NULL;
1072 result = gpgme_op_verify_result (ctx);
1074 for (sig = result->signatures; sig && (idx > 0); sig = sig->next, idx--);
1076 switch (sig ? sig->validity : 0) {
1077 case GPGME_VALIDITY_UNKNOWN:
1078 txt = _("WARNING: We have NO indication whether "
1079 "the key belongs to the person named " "as shown above\n");
1081 case GPGME_VALIDITY_UNDEFINED:
1083 case GPGME_VALIDITY_NEVER:
1084 txt = _("WARNING: The key does NOT BELONG to "
1085 "the person named as shown above\n");
1087 case GPGME_VALIDITY_MARGINAL:
1088 txt = _("WARNING: It is NOT certain that the key "
1089 "belongs to the person named as shown above\n");
1091 case GPGME_VALIDITY_FULL:
1092 case GPGME_VALIDITY_ULTIMATE:
1097 state_attach_puts (txt, s);
1100 /* Show information about one signature. This fucntion is called with
1101 the context CTX of a sucessful verification operation and the
1102 enumerator IDX which should start at 0 and incremete for each
1105 Return values are: 0 for normal procession, 1 for a bad signature,
1106 2 for a signature with a warning or -1 for no more signature. */
1107 static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE * s)
1110 const char *fpr, *uid;
1111 gpgme_key_t key = NULL;
1112 int i, anybad = 0, anywarn = 0;
1114 gpgme_user_id_t uids = NULL;
1115 gpgme_verify_result_t result;
1116 gpgme_signature_t sig;
1117 gpgme_error_t err = GPG_ERR_NO_ERROR;
1119 result = gpgme_op_verify_result (ctx);
1121 /* FIXME: this code should use a static variable and remember
1122 the current position in the list of signatures, IMHO.
1125 for (i = 0, sig = result->signatures; sig && (i < idx);
1126 i++, sig = sig->next);
1128 return -1; /* Signature not found. */
1130 if (signature_key) {
1131 gpgme_key_release (signature_key);
1132 signature_key = NULL;
1135 created = sig->timestamp;
1139 if (gpg_err_code (sig->status) != GPG_ERR_NO_ERROR)
1142 err = gpgme_get_key (ctx, fpr, &key, 0); /* secret key? */
1144 uid = (key->uids && key->uids->uid) ? key->uids->uid : "[?]";
1146 signature_key = key;
1149 key = NULL; /* Old gpgme versions did not set KEY to NULL on
1150 error. Do it here to avoid a double free. */
1154 if (!s || !s->fpout || !(s->flags & M_DISPLAY)); /* No state information so no way to print anything. */
1156 state_attach_puts (_("Error getting key information: "), s);
1157 state_attach_puts (gpg_strerror (err), s);
1158 state_attach_puts ("\n", s);
1161 else if ((sum & GPGME_SIGSUM_GREEN)) {
1162 state_attach_puts (_("Good signature from: "), s);
1163 state_attach_puts (uid, s);
1164 state_attach_puts ("\n", s);
1165 for (i = 1, uids = key->uids; uids; i++, uids = uids->next) {
1167 /* Skip primary UID. */
1171 state_attach_puts (_(" aka: "), s);
1172 state_attach_puts (uids->uid, s);
1173 state_attach_puts ("\n", s);
1175 state_attach_puts (_(" created: "), s);
1176 print_time (created, s);
1177 state_attach_puts ("\n", s);
1178 if (show_sig_summary (sum, ctx, key, idx, s))
1180 show_one_sig_validity (ctx, idx, s);
1182 else if ((sum & GPGME_SIGSUM_RED)) {
1183 state_attach_puts (_("*BAD* signature claimed to be from: "), s);
1184 state_attach_puts (uid, s);
1185 state_attach_puts ("\n", s);
1186 show_sig_summary (sum, ctx, key, idx, s);
1188 else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP)) { /* We can't decide (yellow) but this is a PGP key with a good
1189 signature, so we display what a PGP user expects: The name,
1190 fingerprint and the key validity (which is neither fully or
1192 state_attach_puts (_("Good signature from: "), s);
1193 state_attach_puts (uid, s);
1194 state_attach_puts ("\n", s);
1195 state_attach_puts (_(" created: "), s);
1196 print_time (created, s);
1197 state_attach_puts ("\n", s);
1198 show_one_sig_validity (ctx, idx, s);
1199 show_fingerprint (key, s);
1200 if (show_sig_summary (sum, ctx, key, idx, s))
1203 else { /* can't decide (yellow) */
1205 state_attach_puts (_("Error checking signature"), s);
1206 state_attach_puts ("\n", s);
1207 show_sig_summary (sum, ctx, key, idx, s);
1210 if (key != signature_key)
1211 gpgme_key_release (key);
1214 return anybad ? 1 : anywarn ? 2 : 0;
1217 /* Do the actual verification step. With IS_SMIME set to true we
1218 assume S/MIME (surprise!) */
1219 static int verify_one (BODY * sigbdy, STATE * s,
1220 const char *tempfile, int is_smime)
1226 gpgme_data_t signature, message;
1228 signature = file_to_data_object (s->fpin, sigbdy->offset, sigbdy->length);
1232 /* We need to tell gpgme about the encoding because the backend can't
1233 auto-detect plain base-64 encoding which is used by S/MIME. */
1235 gpgme_data_set_encoding (signature, GPGME_DATA_ENCODING_BASE64);
1237 err = gpgme_data_new_from_file (&message, tempfile, 1);
1239 gpgme_data_release (signature);
1240 mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
1243 ctx = create_gpgme_context (is_smime);
1245 /* Note: We don't need a current time output because GPGME avoids
1246 such an attack by separating the meta information from the
1248 state_attach_puts (_("[-- Begin signature information --]\n"), s);
1250 err = gpgme_op_verify (ctx, signature, message, NULL);
1251 mutt_need_hard_redraw ();
1255 snprintf (buf, sizeof (buf) - 1,
1256 _("Error: verification failed: %s\n"), gpgme_strerror (err));
1257 state_attach_puts (buf, s);
1259 else { /* Verification succeeded, see what the result is. */
1263 if (signature_key) {
1264 gpgme_key_release (signature_key);
1265 signature_key = NULL;
1268 for (idx = 0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) {
1279 gpgme_verify_result_t result;
1280 gpgme_sig_notation_t notation;
1281 gpgme_signature_t sig;
1283 result = gpgme_op_verify_result (ctx);
1285 for (sig = result->signatures; sig; sig = sig->next) {
1286 if (sig->notations) {
1287 state_attach_puts ("*** Begin Notation (signature by: ", s);
1288 state_attach_puts (sig->fpr, s);
1289 state_attach_puts (") ***\n", s);
1290 for (notation = sig->notations; notation; notation = notation->next)
1292 if (notation->name) {
1293 state_attach_puts (notation->name, s);
1294 state_attach_puts ("=", s);
1296 if (notation->value) {
1297 state_attach_puts (notation->value, s);
1298 if (!(*notation->value
1299 && (notation->value[m_strlen(notation->value) - 1] ==
1301 state_attach_puts ("\n", s);
1304 state_attach_puts ("*** End Notation ***\n", s);
1310 gpgme_release (ctx);
1312 state_attach_puts (_("[-- End signature information --]\n\n"), s);
1314 return badsig ? 1 : anywarn ? 2 : 0;
1317 int pgp_gpgme_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
1319 return verify_one (sigbdy, s, tempfile, 0);
1322 int smime_gpgme_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
1324 return verify_one (sigbdy, s, tempfile, 1);
1328 * Implementation of `decrypt_part'.
1331 /* Decrypt a PGP or SMIME message (depending on the boolean flag
1332 IS_SMIME) with body A described further by state S. Write
1333 plaintext out to file FPOUT and return a new body. For PGP returns
1334 a flag in R_IS_SIGNED to indicate whether this is a combined
1335 encrypted and signed message, for S/MIME it returns true when it is
1336 not a encrypted but a signed message. */
1337 static BODY *decrypt_part (BODY * a, STATE * s, FILE * fpout, int is_smime,
1344 gpgme_data_t ciphertext, plaintext;
1345 int maybe_signed = 0;
1352 ctx = create_gpgme_context (is_smime);
1355 /* Make a data object from the body, create context etc. */
1356 ciphertext = file_to_data_object (s->fpin, a->offset, a->length);
1359 plaintext = create_gpgme_data ();
1361 /* Do the decryption or the verification in case of the S/MIME hack. */
1362 if ((!is_smime) || maybe_signed) {
1364 err = gpgme_op_decrypt_verify (ctx, ciphertext, plaintext);
1365 else if (maybe_signed)
1366 err = gpgme_op_verify (ctx, ciphertext, NULL, plaintext);
1369 /* Check wether signatures have been verified. */
1370 gpgme_verify_result_t verify_result = gpgme_op_verify_result (ctx);
1372 if (verify_result->signatures)
1377 err = gpgme_op_decrypt (ctx, ciphertext, plaintext);
1378 gpgme_data_release (ciphertext);
1380 if (is_smime && !maybe_signed && gpg_err_code (err) == GPG_ERR_NO_DATA) {
1381 /* Check whether this might be a signed message despite what
1382 the mime header told us. Retry then. gpgsm returns the
1383 error information "unsupported Algorithm '?'" but gpgme
1384 will not store this unknown algorithm, thus we test that
1385 it has not been set. */
1386 gpgme_decrypt_result_t result;
1388 result = gpgme_op_decrypt_result (ctx);
1389 if (!result->unsupported_algorithm) {
1391 gpgme_data_release (plaintext);
1395 mutt_need_hard_redraw ();
1396 if ((s->flags & M_DISPLAY)) {
1399 snprintf (buf, sizeof (buf) - 1,
1400 _("[-- Error: decryption failed: %s --]\n\n"),
1401 gpgme_strerror (err));
1402 state_attach_puts (buf, s);
1404 gpgme_data_release (plaintext);
1405 gpgme_release (ctx);
1408 mutt_need_hard_redraw ();
1410 /* Read the output from GPGME, and make sure to change CRLF to LF,
1411 otherwise read_mime_header has a hard time parsing the message. */
1412 if (data_object_to_stream (plaintext, fpout)) {
1413 gpgme_data_release (plaintext);
1414 gpgme_release (ctx);
1417 gpgme_data_release (plaintext);
1419 a->is_signed_data = 0;
1425 a->is_signed_data = 1;
1427 *r_is_signed = -1; /* A signature exists. */
1429 if ((s->flags & M_DISPLAY))
1430 state_attach_puts (_("[-- Begin signature " "information --]\n"), s);
1431 for (idx = 0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) {
1437 if (!anybad && idx && r_is_signed && *r_is_signed)
1438 *r_is_signed = anywarn ? 2 : 1; /* Good signature. */
1440 if ((s->flags & M_DISPLAY))
1441 state_attach_puts (_("[-- End signature " "information --]\n\n"), s);
1443 gpgme_release (ctx);
1448 tattach = mutt_read_mime_header (fpout, 0);
1451 * Need to set the length of this body part.
1453 fstat (fileno (fpout), &info);
1454 tattach->length = info.st_size - tattach->offset;
1456 tattach->warnsig = anywarn;
1458 /* See if we need to recurse on this MIME part. */
1459 mutt_parse_part (fpout, tattach);
1465 /* Decrypt a PGP/MIME message in FPIN and B and return a new body and
1466 the stream in CUR and FPOUT. Returns 0 on success. */
1467 int pgp_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur)
1469 char tempfile[_POSIX_PATH_MAX];
1471 BODY *first_part = b;
1474 first_part->goodsig = 0;
1475 first_part->warnsig = 0;
1477 if (!mutt_is_multipart_encrypted (b))
1480 if (!b->parts || !b->parts->next)
1487 mutt_mktemp (tempfile);
1488 if (!(*fpout = safe_fopen (tempfile, "w+"))) {
1489 mutt_perror (tempfile);
1494 *cur = decrypt_part (b, &s, *fpout, 0, &is_signed);
1497 first_part->goodsig = 1;
1499 return *cur ? 0 : -1;
1503 /* Decrypt a S/MIME message in FPIN and B and return a new body and
1504 the stream in CUR and FPOUT. Returns 0 on success. */
1505 int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b,
1508 char tempfile[_POSIX_PATH_MAX];
1512 long saved_b_offset;
1513 ssize_t saved_b_length;
1516 if (!mutt_is_application_smime (b))
1522 /* Decode the body - we need to pass binary CMS to the
1523 backend. The backend allows for Base64 encoded data but it does
1524 not allow for QP which I have seen in some messages. So better
1526 saved_b_type = b->type;
1527 saved_b_offset = b->offset;
1528 saved_b_length = b->length;
1531 fseeko (s.fpin, b->offset, 0);
1532 mutt_mktemp (tempfile);
1533 if (!(tmpfp = safe_fopen (tempfile, "w+"))) {
1534 mutt_perror (tempfile);
1537 mutt_unlink (tempfile);
1540 mutt_decode_attachment (b, &s);
1542 b->length = ftello (s.fpout);
1549 mutt_mktemp (tempfile);
1550 if (!(*fpout = safe_fopen (tempfile, "w+"))) {
1551 mutt_perror (tempfile);
1554 mutt_unlink (tempfile);
1556 *cur = decrypt_part (b, &s, *fpout, 1, &is_signed);
1558 (*cur)->goodsig = is_signed > 0;
1559 b->type = saved_b_type;
1560 b->length = saved_b_length;
1561 b->offset = saved_b_offset;
1564 if (*cur && !is_signed && !(*cur)->parts
1565 && mutt_is_application_smime (*cur)) {
1566 /* Assume that this is a opaque signed s/mime message. This is
1567 an ugly way of doing it but we have anyway a problem with
1568 arbitrary encoded S/MIME messages: Only the outer part may be
1569 encrypted. The entire mime parsing should be revamped,
1570 probably by keeping the temportary files so that we don't
1571 need to decrypt them all the time. Inner parts of an
1572 encrypted part can then pint into this file and tehre won't
1573 never be a need to decrypt again. This needs a partial
1574 rewrite of the MIME engine. */
1578 saved_b_type = bb->type;
1579 saved_b_offset = bb->offset;
1580 saved_b_length = bb->length;
1583 fseeko (s.fpin, bb->offset, 0);
1584 mutt_mktemp (tempfile);
1585 if (!(tmpfp = safe_fopen (tempfile, "w+"))) {
1586 mutt_perror (tempfile);
1589 mutt_unlink (tempfile);
1592 mutt_decode_attachment (bb, &s);
1594 bb->length = ftello (s.fpout);
1602 mutt_mktemp (tempfile);
1603 if (!(*fpout = safe_fopen (tempfile, "w+"))) {
1604 mutt_perror (tempfile);
1607 mutt_unlink (tempfile);
1609 tmp_b = decrypt_part (bb, &s, *fpout, 1, &is_signed);
1611 tmp_b->goodsig = is_signed > 0;
1612 bb->type = saved_b_type;
1613 bb->length = saved_b_length;
1614 bb->offset = saved_b_offset;
1617 body_list_wipe(cur);
1620 return *cur ? 0 : -1;
1625 * Implementation of `pgp_check_traditional'.
1628 static int pgp_check_traditional_one_body (FILE * fp, BODY * b,
1631 char tempfile[_POSIX_PATH_MAX];
1632 char buf[HUGE_STRING];
1638 if (b->type != TYPETEXT)
1641 if (tagged_only && !b->tagged)
1644 mutt_mktemp (tempfile);
1645 if (mutt_decode_save_attachment (fp, b, tempfile, 0, 0) != 0) {
1650 if ((tfp = fopen (tempfile, "r")) == NULL) {
1655 while (fgets (buf, sizeof (buf), tfp)) {
1656 if (!m_strncmp("-----BEGIN PGP ", buf, 15)) {
1657 if (!m_strcmp("MESSAGE-----\n", buf + 15))
1659 else if (!m_strcmp("SIGNED MESSAGE-----\n", buf + 15))
1669 /* fix the content type */
1671 parameter_setval(&b->parameter, "format", "fixed");
1672 parameter_setval(&b->parameter, "x-action",
1673 enc ? "pgp-encrypted" : "pgp-signed");
1677 int pgp_gpgme_check_traditional (FILE * fp, BODY * b, int tagged_only)
1682 for (; b; b = b->next) {
1683 if (is_multipart (b))
1684 rv = (pgp_gpgme_check_traditional (fp, b->parts, tagged_only) || rv);
1685 else if (b->type == TYPETEXT) {
1686 if ((r = mutt_is_application_pgp (b)))
1689 rv = (pgp_check_traditional_one_body (fp, b, tagged_only) || rv);
1697 * Implementation of `application_handler'.
1701 Copy a clearsigned message, and strip the signature and PGP's
1704 XXX - charset handling: We assume that it is safe to do
1705 character set decoding first, dash decoding second here, while
1706 we do it the other way around in the main handler.
1708 (Note that we aren't worse than Outlook & Cie in this, and also
1709 note that we can successfully handle anything produced by any
1710 existing versions of mutt.) */
1712 static void copy_clearsigned (gpgme_data_t data, STATE * s, char *charset)
1714 char buf[HUGE_STRING];
1715 short complete, armor_header;
1720 fname = data_object_to_tempfile (data, &fp);
1726 fc = fgetconv_open (fp, charset, Charset, M_ICONV_HOOK_FROM);
1728 for (complete = 1, armor_header = 1;
1729 fgetconvs (buf, sizeof (buf), fc) != NULL;
1730 complete = strchr (buf, '\n') != NULL) {
1733 state_puts (buf, s);
1737 if (!m_strcmp(buf, "-----BEGIN PGP SIGNATURE-----\n"))
1747 state_puts (s->prefix, s);
1749 if (buf[0] == '-' && buf[1] == ' ')
1750 state_puts (buf + 2, s);
1752 state_puts (buf, s);
1755 fgetconv_close (&fc);
1760 /* Support for classic_application/pgp */
1761 int pgp_gpgme_application_handler (BODY * m, STATE * s)
1763 int needpass = -1, pgp_keyblock = 0;
1767 off_t last_pos, offset;
1768 char buf[HUGE_STRING];
1769 FILE *pgpout = NULL;
1771 gpgme_error_t err = 0;
1772 gpgme_data_t armored_data = NULL;
1774 short maybe_goodsig = 1;
1775 short have_any_sigs = 0;
1777 char body_charset[STRING]; /* Only used for clearsigned messages. */
1779 /* For clearsigned messages we won't be able to get a character set
1780 but we know that this may only be text thus we assume Latin-1
1782 if (!mutt_get_body_charset (body_charset, sizeof (body_charset), m))
1783 m_strcpy(body_charset, sizeof(body_charset), "iso-8859-1");
1785 fseeko (s->fpin, m->offset, 0);
1786 last_pos = m->offset;
1788 for (bytes = m->length; bytes > 0;) {
1789 if (fgets (buf, sizeof (buf), s->fpin) == NULL)
1792 offset = ftello (s->fpin);
1793 bytes -= (offset - last_pos); /* don't rely on m_strlen(buf) */
1796 if (!m_strncmp("-----BEGIN PGP ", buf, 15)) {
1798 start_pos = last_pos;
1800 if (!m_strcmp("MESSAGE-----\n", buf + 15))
1802 else if (!m_strcmp("SIGNED MESSAGE-----\n", buf + 15)) {
1806 else if (!option (OPTDONTHANDLEPGPKEYS) &&
1807 !m_strcmp("PUBLIC KEY BLOCK-----\n", buf + 15)) {
1812 /* XXX - we may wish to recode here */
1814 state_puts (s->prefix, s);
1815 state_puts (buf, s);
1819 have_any_sigs = (have_any_sigs || (clearsign && (s->flags & M_VERIFY)));
1821 /* Copy PGP material to an data container */
1822 armored_data = create_gpgme_data ();
1823 gpgme_data_write (armored_data, buf, m_strlen(buf));
1824 while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL) {
1825 offset = ftello (s->fpin);
1826 bytes -= (offset - last_pos); /* don't rely on m_strlen(buf) */
1829 gpgme_data_write (armored_data, buf, m_strlen(buf));
1831 if ((needpass && !m_strcmp("-----END PGP MESSAGE-----\n", buf))
1833 && (!m_strcmp("-----END PGP SIGNATURE-----\n", buf)
1834 || !m_strcmp("-----END PGP PUBLIC KEY BLOCK-----\n",
1839 /* Invoke PGP if needed */
1840 if (!clearsign || (s->flags & M_VERIFY)) {
1841 unsigned int sig_stat = 0;
1842 gpgme_data_t plaintext;
1845 plaintext = create_gpgme_data ();
1846 ctx = create_gpgme_context (0);
1849 err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
1851 err = gpgme_op_decrypt_verify (ctx, armored_data, plaintext);
1852 if (gpg_err_code (err) == GPG_ERR_NO_DATA) {
1853 /* Decrypt verify can't handle signed only messages. */
1854 err = (gpgme_data_seek (armored_data, 0, SEEK_SET) == -1)
1855 ? gpgme_error_from_errno (errno) : 0;
1856 /* Must release plaintext so that we supply an
1857 uninitialized object. */
1858 gpgme_data_release (plaintext);
1859 plaintext = create_gpgme_data ();
1860 err = gpgme_op_verify (ctx, armored_data, NULL, plaintext);
1867 snprintf (errbuf, sizeof (errbuf) - 1,
1868 _("Error: decryption/verification failed: %s\n"),
1869 gpgme_strerror (err));
1870 state_attach_puts (errbuf, s);
1872 else { /* Decryption/Verification succeeded */
1876 /* Check wether signatures have been verified. */
1877 gpgme_verify_result_t verify_result;
1879 verify_result = gpgme_op_verify_result (ctx);
1880 if (verify_result->signatures)
1886 if ((s->flags & M_DISPLAY) && sig_stat) {
1891 state_attach_puts (_("[-- Begin signature "
1892 "information --]\n"), s);
1895 (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) {
1904 state_attach_puts (_("[-- End signature "
1905 "information --]\n\n"), s);
1908 tmpfname = data_object_to_tempfile (plaintext, &pgpout);
1911 state_attach_puts (_("Error: copy data failed\n"), s);
1915 p_delete(&tmpfname);
1918 gpgme_release (ctx);
1922 * Now, copy cleartext to the screen. NOTE - we expect that PGP
1923 * outputs utf-8 cleartext. This may not always be true, but it
1924 * seems to be a reasonable guess.
1927 if (s->flags & M_DISPLAY) {
1929 state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s);
1930 else if (pgp_keyblock)
1931 state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), s);
1933 state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), s);
1937 copy_clearsigned (armored_data, s, body_charset);
1944 fc = fgetconv_open (pgpout, "utf-8", Charset, 0);
1945 while ((c = fgetconv (fc)) != EOF) {
1947 if (c == '\n' && s->prefix)
1948 state_puts (s->prefix, s);
1950 fgetconv_close (&fc);
1953 if (s->flags & M_DISPLAY) {
1954 state_putc ('\n', s);
1956 state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
1957 else if (pgp_keyblock)
1958 state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
1960 state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
1964 safe_fclose (&pgpout);
1968 /* XXX - we may wish to recode here */
1970 state_puts (s->prefix, s);
1971 state_puts (buf, s);
1975 m->goodsig = (maybe_goodsig && have_any_sigs);
1977 if (needpass == -1) {
1978 state_attach_puts (_("[-- Error: could not find beginning"
1979 " of PGP message! --]\n\n"), s);
1986 * Implementation of `encrypted_handler'.
1989 /* MIME handler for pgp/mime encrypted messages. */
1990 int pgp_gpgme_encrypted_handler (BODY * a, STATE * s)
1992 char tempfile[_POSIX_PATH_MAX];
1995 BODY *orig_body = a;
2000 if (!a || a->type != TYPEAPPLICATION || !a->subtype
2001 || ascii_strcasecmp ("pgp-encrypted", a->subtype)
2002 || !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype
2003 || ascii_strcasecmp ("octet-stream", a->next->subtype)) {
2004 if (s->flags & M_DISPLAY)
2005 state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
2010 /* Move forward to the application/pgp-encrypted body. */
2013 mutt_mktemp (tempfile);
2014 if (!(fpout = safe_fopen (tempfile, "w+"))) {
2015 if (s->flags & M_DISPLAY)
2016 state_attach_puts (_("[-- Error: could not create temporary file! "
2021 tattach = decrypt_part (a, s, fpout, 0, &is_signed);
2023 tattach->goodsig = is_signed > 0;
2025 if (s->flags & M_DISPLAY)
2026 state_attach_puts (is_signed ?
2028 ("[-- The following data is PGP/MIME signed and encrypted --]\n\n") :
2029 _("[-- The following data is PGP/MIME encrypted --]\n\n"), s);
2032 FILE *savefp = s->fpin;
2035 rc = mutt_body_handler (tattach, s);
2040 * if a multipart/signed is the _only_ sub-part of a
2041 * multipart/encrypted, cache signature verification
2044 if (mutt_is_multipart_signed (tattach) && !tattach->next)
2045 orig_body->goodsig |= tattach->goodsig;
2047 if (s->flags & M_DISPLAY) {
2048 state_puts ("\n", s);
2049 state_attach_puts (is_signed ?
2051 ("[-- End of PGP/MIME signed and encrypted data --]\n")
2052 : _("[-- End of PGP/MIME encrypted data --]\n"), s);
2055 body_list_wipe(&tattach);
2059 mutt_unlink (tempfile);
2063 /* Support for application/smime */
2064 int smime_gpgme_application_handler (BODY * a, STATE * s)
2066 char tempfile[_POSIX_PATH_MAX];
2073 mutt_mktemp (tempfile);
2074 if (!(fpout = safe_fopen (tempfile, "w+"))) {
2075 if (s->flags & M_DISPLAY)
2076 state_attach_puts (_("[-- Error: could not create temporary file! "
2081 tattach = decrypt_part (a, s, fpout, 1, &is_signed);
2083 tattach->goodsig = is_signed > 0;
2085 if (s->flags & M_DISPLAY)
2086 state_attach_puts (is_signed ?
2087 _("[-- The following data is S/MIME signed --]\n\n") :
2088 _("[-- The following data is S/MIME encrypted --]\n\n"), s);
2091 FILE *savefp = s->fpin;
2094 rc = mutt_body_handler (tattach, s);
2099 * if a multipart/signed is the _only_ sub-part of a
2100 * multipart/encrypted, cache signature verification
2103 if (mutt_is_multipart_signed (tattach) && !tattach->next) {
2104 if (!(a->goodsig = tattach->goodsig))
2105 a->warnsig = tattach->warnsig;
2107 else if (tattach->goodsig) {
2109 a->warnsig = tattach->warnsig;
2112 if (s->flags & M_DISPLAY) {
2113 state_puts ("\n", s);
2114 state_attach_puts (is_signed ?
2115 _("[-- End of S/MIME signed data --]\n") :
2116 _("[-- End of S/MIME encrypted data --]\n"), s);
2119 body_list_wipe(&tattach);
2123 mutt_unlink (tempfile);
2129 * Format an entry on the CRYPT key selection menu.
2132 * %k key id %K key id of the principal key
2134 * %a algorithm %A algorithm of the princ. key
2135 * %l length %L length of the princ. key
2136 * %f flags %F flags of the princ. key
2137 * %c capabilities %C capabilities of the princ. key
2138 * %t trust/validity of the key-uid association
2140 * %[...] date of key using strftime(3)
2144 crypt_entry_fmt (char *dest, ssize_t destlen, char op,
2145 const char *src, const char *prefix,
2146 const char *ifstring, const char *elsestring,
2147 unsigned long data, format_flag flags)
2150 crypt_entry_t *entry;
2153 int optional = (flags & M_FORMAT_OPTIONAL);
2154 const char *s = NULL;
2157 entry = (crypt_entry_t *) data;
2160 /* if (isupper ((unsigned char) op)) */
2163 kflags = (key->flags /*| (pkey->flags & KEYFLAG_RESTRICTIONS)
2166 switch (ascii_tolower (op)) {
2170 char buf2[SHORT_STRING], *p;
2186 while (len > 0 && *cp != ']') {
2195 break; /* not enough space */
2205 if (do_locales && Locale)
2206 setlocale (LC_TIME, Locale);
2211 if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
2212 tt = key->kobj->subkeys->timestamp;
2214 tm = localtime (&tt);
2216 strftime (buf2, sizeof (buf2), dest, tm);
2219 setlocale (LC_TIME, "C");
2221 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2222 snprintf (dest, destlen, fmt, buf2);
2229 snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
2230 snprintf (dest, destlen, fmt, entry->num);
2235 /* fixme: we need a way to distinguish between main and subkeys.
2236 Store the idx in entry? */
2237 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2238 snprintf (dest, destlen, fmt, crypt_keyid (key));
2243 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2244 snprintf (dest, destlen, fmt, key->uid);
2249 snprintf (fmt, sizeof (fmt), "%%%s.3s", prefix);
2250 if (key->kobj->subkeys)
2251 s = gpgme_pubkey_algo_name (key->kobj->subkeys->pubkey_algo);
2254 snprintf (dest, destlen, fmt, s);
2259 snprintf (fmt, sizeof (fmt), "%%%slu", prefix);
2260 if (key->kobj->subkeys)
2261 val = key->kobj->subkeys->length;
2264 snprintf (dest, destlen, fmt, val);
2269 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2270 snprintf (dest, destlen, fmt, crypt_flags (kflags));
2272 else if (!(kflags & (KEYFLAG_RESTRICTIONS)))
2277 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2278 snprintf (dest, destlen, fmt, crypt_key_abilities (kflags));
2280 else if (!(kflags & (KEYFLAG_ABILITIES)))
2284 if ((kflags & KEYFLAG_ISX509))
2287 gpgme_user_id_t uid = NULL;
2290 for (i = 0, uid = key->kobj->uids; uid && (i < key->idx);
2291 i++, uid = uid->next);
2293 switch (uid->validity) {
2294 case GPGME_VALIDITY_UNDEFINED:
2297 case GPGME_VALIDITY_NEVER:
2300 case GPGME_VALIDITY_MARGINAL:
2303 case GPGME_VALIDITY_FULL:
2306 case GPGME_VALIDITY_ULTIMATE:
2309 case GPGME_VALIDITY_UNKNOWN:
2315 snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
2316 snprintf (dest, destlen, fmt, s ? *s : 'B');
2319 snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
2320 snprintf (dest, destlen, fmt,
2321 gpgme_get_protocol_name (key->kobj->protocol));
2329 mutt_FormatString (dest, destlen, ifstring, mutt_attach_fmt, data, 0);
2330 else if (flags & M_FORMAT_OPTIONAL)
2331 mutt_FormatString (dest, destlen, elsestring, mutt_attach_fmt, data, 0);
2335 /* Used by the display fucntion to format a line. */
2336 static void crypt_entry (char *s, ssize_t l, MUTTMENU * menu, int num)
2338 crypt_key_t **key_table = (crypt_key_t **) menu->data;
2339 crypt_entry_t entry;
2341 entry.key = key_table[num];
2342 entry.num = num + 1;
2344 mutt_FormatString (s, l, NONULL (PgpEntryFormat), crypt_entry_fmt,
2345 (unsigned long) &entry, M_FORMAT_ARROWCURSOR);
2348 /* Compare two addresses and the keyid to be used for sorting. */
2349 static int _crypt_compare_address (const void *a, const void *b)
2351 crypt_key_t **s = (crypt_key_t **) a;
2352 crypt_key_t **t = (crypt_key_t **) b;
2355 if ((r = m_strcasecmp((*s)->uid, (*t)->uid)))
2358 return m_strcasecmp(crypt_keyid (*s), crypt_keyid (*t)) > 0;
2361 static int crypt_compare_address (const void *a, const void *b)
2363 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_address (a, b)
2364 : _crypt_compare_address (a, b));
2368 /* Compare two key IDs and the addresses to be used for sorting. */
2369 static int _crypt_compare_keyid (const void *a, const void *b)
2371 crypt_key_t **s = (crypt_key_t **) a;
2372 crypt_key_t **t = (crypt_key_t **) b;
2375 if ((r = m_strcasecmp(crypt_keyid (*s), crypt_keyid (*t))))
2378 return m_strcasecmp((*s)->uid, (*t)->uid) > 0;
2381 static int crypt_compare_keyid (const void *a, const void *b)
2383 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_keyid (a, b)
2384 : _crypt_compare_keyid (a, b));
2387 /* Compare 2 creation dates and the addresses. For sorting. */
2388 static int _crypt_compare_date (const void *a, const void *b)
2390 crypt_key_t **s = (crypt_key_t **) a;
2391 crypt_key_t **t = (crypt_key_t **) b;
2392 unsigned long ts = 0, tt = 0;
2394 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2395 ts = (*s)->kobj->subkeys->timestamp;
2396 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2397 tt = (*t)->kobj->subkeys->timestamp;
2404 return m_strcasecmp((*s)->uid, (*t)->uid) > 0;
2407 static int crypt_compare_date (const void *a, const void *b)
2409 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_date (a, b)
2410 : _crypt_compare_date (a, b));
2413 /* Compare two trust values, the key length, the creation dates. the
2414 addresses and the key IDs. For sorting. */
2415 static int _crypt_compare_trust (const void *a, const void *b)
2417 crypt_key_t **s = (crypt_key_t **) a;
2418 crypt_key_t **t = (crypt_key_t **) b;
2419 unsigned long ts = 0, tt = 0;
2422 if ((r = (((*s)->flags & (KEYFLAG_RESTRICTIONS))
2423 - ((*t)->flags & (KEYFLAG_RESTRICTIONS)))))
2426 if ((*s)->kobj->uids)
2427 ts = (*s)->kobj->uids->validity;
2428 if ((*t)->kobj->uids)
2429 tt = (*t)->kobj->uids->validity;
2430 if ((r = (tt - ts)))
2433 if ((*s)->kobj->subkeys)
2434 ts = (*s)->kobj->subkeys->length;
2435 if ((*t)->kobj->subkeys)
2436 tt = (*t)->kobj->subkeys->length;
2440 if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
2441 ts = (*s)->kobj->subkeys->timestamp;
2442 if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
2443 tt = (*t)->kobj->subkeys->timestamp;
2449 if ((r = m_strcasecmp((*s)->uid, (*t)->uid)))
2451 return (m_strcasecmp(crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0;
2454 static int crypt_compare_trust (const void *a, const void *b)
2456 return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_trust (a, b)
2457 : _crypt_compare_trust (a, b));
2460 /* Print the X.500 Distinguished Name part KEY from the array of parts
2462 static int print_dn_part (FILE * fp, struct dn_array_s *dn, const char *key)
2466 for (; dn->key; dn++) {
2467 if (!m_strcmp(dn->key, key)) {
2470 print_utf8 (fp, dn->value, m_strlen(dn->value));
2477 /* Print all parts of a DN in a standard sequence. */
2478 static void print_dn_parts (FILE * fp, struct dn_array_s *dn)
2480 const char *stdpart[] = {
2481 "CN", "OU", "O", "STREET", "L", "ST", "C", NULL
2483 int any = 0, any2 = 0, i;
2485 for (i = 0; stdpart[i]; i++) {
2488 any = print_dn_part (fp, dn, stdpart[i]);
2490 /* now print the rest without any specific ordering */
2491 for (; dn->key; dn++) {
2492 for (i = 0; stdpart[i]; i++) {
2493 if (!m_strcmp(dn->key, stdpart[i]))
2501 any = print_dn_part (fp, dn, dn->key);
2510 /* Parse an RDN; this is a helper to parse_dn(). */
2511 static const unsigned char *parse_dn_part (struct dn_array_s *array,
2512 const unsigned char *string)
2514 const unsigned char *s, *s1;
2518 /* parse attributeType */
2519 for (s = string + 1; *s && *s != '='; s++);
2521 return NULL; /* error */
2524 return NULL; /* empty key */
2525 array->key = p_dupstr(string, n );
2526 p = (unsigned char *) array->key;
2529 if (*string == '#') { /* hexstring */
2531 for (s = string; hexdigitp (s); s++)
2535 return NULL; /* empty or odd number of digits */
2538 array->value = (char *) p;
2539 for (s1 = string; n; s1 += 2, n--)
2543 else { /* regular v3 quoted string */
2544 for (n = 0, s = string; *s; s++) {
2545 if (*s == '\\') { /* pair */
2547 if (*s == ',' || *s == '=' || *s == '+'
2548 || *s == '<' || *s == '>' || *s == '#' || *s == ';'
2549 || *s == '\\' || *s == '\"' || *s == ' ')
2551 else if (hexdigitp (s) && hexdigitp (s + 1)) {
2556 return NULL; /* invalid escape sequence */
2558 else if (*s == '\"')
2559 return NULL; /* invalid encoding */
2560 else if (*s == ',' || *s == '=' || *s == '+'
2561 || *s == '<' || *s == '>' || *s == '#' || *s == ';')
2568 array->value = (char *) p;
2569 for (s = string; n; s++, n--) {
2572 if (hexdigitp (s)) {
2588 /* Parse a DN and return an array-ized one. This is not a validating
2589 parser and it does not support any old-stylish syntax; gpgme is
2590 expected to return only rfc2253 compatible strings. */
2591 static struct dn_array_s *parse_dn (const unsigned char *string)
2593 struct dn_array_s *array;
2594 ssize_t arrayidx, arraysize;
2597 arraysize = 7; /* C,ST,L,O,OU,CN,email */
2598 array = p_new(struct dn_array_s, arraysize + 1);
2601 while (*string == ' ')
2605 if (arrayidx >= arraysize) { /* mutt lacks a real safe_realoc - so we need to copy */
2606 struct dn_array_s *a2;
2609 a2 = p_new(struct dn_array_s, arraysize + 1);
2610 for (i = 0; i < arrayidx; i++) {
2611 a2[i].key = array[i].key;
2612 a2[i].value = array[i].value;
2617 array[arrayidx].key = NULL;
2618 array[arrayidx].value = NULL;
2619 string = parse_dn_part (array + arrayidx, string);
2623 while (*string == ' ')
2625 if (*string && *string != ',' && *string != ';' && *string != '+')
2626 goto failure; /* invalid delimiter */
2630 array[arrayidx].key = NULL;
2631 array[arrayidx].value = NULL;
2635 for (i = 0; i < arrayidx; i++) {
2636 p_delete(&array[i].key);
2637 p_delete(&array[i].value);
2644 /* Print a nice representation of the USERID and make sure it is
2645 displayed in a proper way, which does mean to reorder some parts
2646 for S/MIME's DNs. USERID is a string as returned by the gpgme key
2647 functions. It is utf-8 encoded. */
2648 static void parse_and_print_user_id (FILE * fp, const char *userid)
2653 if (*userid == '<') {
2654 s = strchr (userid + 1, '>');
2656 print_utf8 (fp, userid + 1, s - userid - 1);
2658 else if (*userid == '(')
2659 fputs (_("[Can't display this user ID (unknown encoding)]"), fp);
2660 else if (!digit_or_letter ((const unsigned char *) userid))
2661 fputs (_("[Can't display this user ID (invalid encoding)]"), fp);
2663 struct dn_array_s *dn = parse_dn ((const unsigned char *) userid);
2666 fputs (_("[Can't display this user ID (invalid DN)]"), fp);
2668 print_dn_parts (fp, dn);
2669 for (i = 0; dn[i].key; i++) {
2670 p_delete(&dn[i].key);
2671 p_delete(&dn[i].value);
2679 KEY_CAP_CAN_ENCRYPT,
2684 static unsigned int key_check_cap (gpgme_key_t key, key_cap_t cap)
2686 gpgme_subkey_t subkey = NULL;
2687 unsigned int ret = 0;
2690 case KEY_CAP_CAN_ENCRYPT:
2691 if (!(ret = key->can_encrypt))
2692 for (subkey = key->subkeys; subkey; subkey = subkey->next)
2693 if ((ret = subkey->can_encrypt))
2696 case KEY_CAP_CAN_SIGN:
2697 if (!(ret = key->can_sign))
2698 for (subkey = key->subkeys; subkey; subkey = subkey->next)
2699 if ((ret = subkey->can_sign))
2702 case KEY_CAP_CAN_CERTIFY:
2703 if (!(ret = key->can_certify))
2704 for (subkey = key->subkeys; subkey; subkey = subkey->next)
2705 if ((ret = subkey->can_certify))
2714 /* Print verbose information about a key or certificate to FP. */
2715 static void print_key_info (gpgme_key_t key, FILE * fp)
2718 const char *s = NULL, *s2 = NULL;
2721 char shortbuf[SHORT_STRING];
2722 unsigned long aval = 0;
2726 gpgme_user_id_t uid = NULL;
2729 setlocale (LC_TIME, Locale);
2731 is_pgp = key->protocol == GPGME_PROTOCOL_OpenPGP;
2733 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
2738 fputs (idx ? _(" aka ......: ") :_("Name ......: "), fp);
2741 fputs (_("[Invalid]"), fp);
2745 print_utf8 (fp, s, m_strlen(s));
2747 parse_and_print_user_id (fp, s);
2751 if (key->subkeys && (key->subkeys->timestamp > 0)) {
2752 tt = key->subkeys->timestamp;
2754 tm = localtime (&tt);
2755 #ifdef HAVE_LANGINFO_D_T_FMT
2756 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2758 strftime (shortbuf, sizeof shortbuf, "%c", tm);
2760 fprintf (fp, _("Valid From : %s\n"), shortbuf);
2763 if (key->subkeys && (key->subkeys->expires > 0)) {
2764 tt = key->subkeys->expires;
2766 tm = localtime (&tt);
2767 #ifdef HAVE_LANGINFO_D_T_FMT
2768 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2770 strftime (shortbuf, sizeof shortbuf, "%c", tm);
2772 fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
2776 s = gpgme_pubkey_algo_name (key->subkeys->pubkey_algo);
2780 s2 = is_pgp ? "PGP" : "X.509";
2783 aval = key->subkeys->length;
2785 fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), s2, aval, s);
2787 fprintf (fp, _("Key Usage .: "));
2790 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) {
2791 fprintf (fp, "%s%s", delim, _("encryption"));
2794 if (key_check_cap (key, KEY_CAP_CAN_SIGN)) {
2795 fprintf (fp, "%s%s", delim, _("signing"));
2798 if (key_check_cap (key, KEY_CAP_CAN_CERTIFY)) {
2799 fprintf (fp, "%s%s", delim, _("certification"));
2805 s = key->subkeys->fpr;
2806 fputs (_("Fingerprint: "), fp);
2807 if (is_pgp && m_strlen(s) == 40) {
2808 for (i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) {
2813 putc (is_pgp ? ' ' : ':', fp);
2814 if (is_pgp && i == 4)
2819 for (i = 0; *s && s[1] && s[2]; s += 2, i++) {
2822 putc (is_pgp ? ' ' : ':', fp);
2823 if (is_pgp && i == 7)
2827 fprintf (fp, "%s\n", s);
2830 if (key->issuer_serial) {
2831 s = key->issuer_serial;
2833 fprintf (fp, _("Serial-No .: 0x%s\n"), s);
2836 if (key->issuer_name) {
2837 s = key->issuer_name;
2839 fprintf (fp, _("Issued By .: "));
2840 parse_and_print_user_id (fp, s);
2845 /* For PGP we list all subkeys. */
2847 gpgme_subkey_t subkey = NULL;
2849 for (idx = 1, subkey = key->subkeys; subkey; idx++, subkey = subkey->next) {
2853 if (m_strlen(s) == 16)
2854 s += 8; /* display only the short keyID */
2855 fprintf (fp, _("Subkey ....: 0x%s"), s);
2856 if (subkey->revoked) {
2858 fputs (_("[Revoked]"), fp);
2860 if (subkey->invalid) {
2862 fputs (_("[Invalid]"), fp);
2864 if (subkey->expired) {
2866 fputs (_("[Expired]"), fp);
2868 if (subkey->disabled) {
2870 fputs (_("[Disabled]"), fp);
2874 if (subkey->timestamp > 0) {
2875 tt = subkey->timestamp;
2877 tm = localtime (&tt);
2878 #ifdef HAVE_LANGINFO_D_T_FMT
2879 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2881 strftime (shortbuf, sizeof shortbuf, "%c", tm);
2883 fprintf (fp, _("Valid From : %s\n"), shortbuf);
2886 if (subkey->expires > 0) {
2887 tt = subkey->expires;
2889 tm = localtime (&tt);
2890 #ifdef HAVE_LANGINFO_D_T_FMT
2891 strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm);
2893 strftime (shortbuf, sizeof shortbuf, "%c", tm);
2895 fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
2899 s = gpgme_pubkey_algo_name (subkey->pubkey_algo);
2904 aval = subkey->length;
2908 fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), "PGP", aval, s);
2910 fprintf (fp, _("Key Usage .: "));
2913 if (subkey->can_encrypt) {
2914 fprintf (fp, "%s%s", delim, _("encryption"));
2917 if (subkey->can_sign) {
2918 fprintf (fp, "%s%s", delim, _("signing"));
2921 if (subkey->can_certify) {
2922 fprintf (fp, "%s%s", delim, _("certification"));
2930 setlocale (LC_TIME, "C");
2934 /* Show detailed information about the selected key */
2935 static void verify_key (crypt_key_t * key)
2938 char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
2940 gpgme_ctx_t listctx = NULL;
2942 gpgme_key_t k = NULL;
2945 mutt_mktemp (tempfile);
2946 if (!(fp = safe_fopen (tempfile, "w"))) {
2947 mutt_perror (_("Can't create temporary file"));
2951 mutt_message _("Collecting data...");
2953 print_key_info (key->kobj, fp);
2955 err = gpgme_new (&listctx);
2957 fprintf (fp, "Internal error: can't create gpgme context: %s\n",
2958 gpgme_strerror (err));
2961 if ((key->flags & KEYFLAG_ISX509))
2962 gpgme_set_protocol (listctx, GPGME_PROTOCOL_CMS);
2966 while ((s = k->chain_id) && k->subkeys && m_strcmp(s, k->subkeys->fpr)) {
2968 err = gpgme_op_keylist_start (listctx, s, 0);
2969 gpgme_key_release (k);
2972 err = gpgme_op_keylist_next (listctx, &k);
2974 fprintf (fp, _("Error finding issuer key: %s\n"), gpgme_strerror (err));
2977 gpgme_op_keylist_end (listctx);
2979 print_key_info (k, fp);
2982 fputs (_("Error: certification chain to long - stopping here\n"), fp);
2988 gpgme_key_release (k);
2989 gpgme_release (listctx);
2991 mutt_clear_error ();
2992 snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), crypt_keyid (key));
2993 mutt_do_pager (cmd, tempfile, 0, NULL);
2997 * Implementation of `findkeys'.
3001 /* Convert string_list_t into a pattern string suitable to be passed to GPGME.
3002 We need to convert spaces in an item into a '+' and '%' into
3004 static char *list_to_pattern (string_list_t * list)
3012 for (l = list; l; l = l->next) {
3013 for (s = l->data; *s; s++) {
3018 n++; /* delimiter or end of string */
3020 n++; /* make sure to allocate at least one byte */
3021 pattern = p = p_new(char, n);
3022 for (l = list; l; l = l->next) {
3027 for (s = l->data; *s; s++) {
3033 else if (*s == '+') {
3049 /* Return a list of keys which are candidates for the selection.
3050 Select by looking at the HINTS list. */
3051 static crypt_key_t *get_candidates (string_list_t * hints, unsigned int app,
3054 crypt_key_t *db, *k, **kend;
3060 gpgme_user_id_t uid = NULL;
3062 pattern = list_to_pattern (hints);
3066 err = gpgme_new (&ctx);
3068 mutt_error (_("gpgme_new failed: %s"), gpgme_strerror (err));
3076 if ((app & APPLICATION_PGP)) {
3077 /* Its all a mess. That old GPGME expects different things
3078 depending on the protocol. For gpg we don' t need percent
3079 escaped pappert but simple strings passed in an array to the
3080 keylist_ext_start function. */
3085 for (l = hints, n = 0; l; l = l->next) {
3086 if (l->data && *l->data)
3092 patarr = p_new(char *, n + 1);
3093 for (l = hints, n = 0; l; l = l->next) {
3094 if (l->data && *l->data)
3095 patarr[n++] = m_strdup(l->data);
3098 err = gpgme_op_keylist_ext_start (ctx, (const char **) patarr, secret, 0);
3099 for (n = 0; patarr[n]; n++)
3100 p_delete(&patarr[n]);
3103 mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
3104 gpgme_release (ctx);
3109 while (!(err = gpgme_op_keylist_next (ctx, &key))) {
3110 unsigned int flags = 0;
3112 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3113 flags |= KEYFLAG_CANENCRYPT;
3114 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3115 flags |= KEYFLAG_CANSIGN;
3117 #if 0 /* DISABLED code */
3119 /* Bug in gpg. Capabilities are not listed for secret
3120 keys. Try to deduce them from the algorithm. */
3122 switch (key->subkeys[0].pubkey_algo) {
3124 flags |= KEYFLAG_CANENCRYPT;
3125 flags |= KEYFLAG_CANSIGN;
3127 case GPGME_PK_ELG_E:
3128 flags |= KEYFLAG_CANENCRYPT;
3131 flags |= KEYFLAG_CANSIGN;
3135 #endif /* DISABLED code */
3137 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
3138 k = p_new(crypt_key_t, 1);
3147 if (gpg_err_code (err) != GPG_ERR_EOF)
3148 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3149 gpgme_op_keylist_end (ctx);
3154 if ((app & APPLICATION_SMIME)) {
3155 /* and now look for x509 certificates */
3156 gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
3157 err = gpgme_op_keylist_start (ctx, pattern, 0);
3159 mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
3160 gpgme_release (ctx);
3165 while (!(err = gpgme_op_keylist_next (ctx, &key))) {
3166 unsigned int flags = KEYFLAG_ISX509;
3168 if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
3169 flags |= KEYFLAG_CANENCRYPT;
3170 if (key_check_cap (key, KEY_CAP_CAN_SIGN))
3171 flags |= KEYFLAG_CANSIGN;
3173 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
3174 k = p_new(crypt_key_t, 1);
3183 if (gpg_err_code (err) != GPG_ERR_EOF)
3184 mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
3185 gpgme_op_keylist_end (ctx);
3188 gpgme_release (ctx);
3193 /* Add the string STR to the list HINTS. This list is later used to
3195 static string_list_t *crypt_add_string_to_hints (string_list_t * hints, const char *str)
3200 if ((scratch = m_strdup(str)) == NULL)
3203 for (t = strtok (scratch, " ,.:\"()<>\n"); t;
3204 t = strtok (NULL, " ,.:\"()<>\n")) {
3205 if (m_strlen(t) > 3)
3206 hints = mutt_add_list(hints, t);
3213 /* Display a menu to select a key from the array KEYS. FORCED_VALID
3214 will be set to true on return if the user did override the the
3216 static crypt_key_t *crypt_select_key (crypt_key_t * keys,
3217 address_t * p, const char *s,
3218 unsigned int app, int *forced_valid)
3221 crypt_key_t **key_table;
3224 char helpstr[SHORT_STRING], buf[LONG_STRING];
3226 int (*f) (const void *, const void *);
3227 int menu_to_use = 0;
3232 /* build the key table */
3235 for (k = keys; k; k = k->next) {
3236 if (!option (OPTPGPSHOWUNUSABLE) && (k->flags & KEYFLAG_CANTUSE)) {
3243 p_realloc(&key_table, keymax);
3249 if (!i && unusable) {
3250 mutt_error _("All matching keys are marked expired/revoked.");
3256 switch (PgpSortKeys & SORT_MASK) {
3258 f = crypt_compare_date;
3261 f = crypt_compare_keyid;
3264 f = crypt_compare_address;
3268 f = crypt_compare_trust;
3271 qsort (key_table, i, sizeof (crypt_key_t *), f);
3273 if (app & APPLICATION_PGP)
3274 menu_to_use = MENU_KEY_SELECT_PGP;
3275 else if (app & APPLICATION_SMIME)
3276 menu_to_use = MENU_KEY_SELECT_SMIME;
3279 mutt_make_help (buf, sizeof (buf), _("Exit "), menu_to_use, OP_EXIT);
3280 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3281 mutt_make_help (buf, sizeof (buf), _("Select "), menu_to_use,
3282 OP_GENERIC_SELECT_ENTRY);
3283 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3284 mutt_make_help (buf, sizeof (buf), _("Check key "),
3285 menu_to_use, OP_VERIFY_KEY);
3286 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3287 mutt_make_help (buf, sizeof (buf), _("Help"), menu_to_use, OP_HELP);
3288 strcat (helpstr, buf); /* __STRCAT_CHECKED__ */
3290 menu = mutt_new_menu ();
3292 menu->make_entry = crypt_entry;
3293 menu->menu = menu_to_use;
3294 menu->help = helpstr;
3295 menu->data = key_table;
3300 if ((app & APPLICATION_PGP) && (app & APPLICATION_SMIME))
3301 ts = _("PGP and S/MIME keys matching");
3302 else if ((app & APPLICATION_PGP))
3303 ts = _("PGP keys matching");
3304 else if ((app & APPLICATION_SMIME))
3305 ts = _("S/MIME keys matching");
3307 ts = _("keys matching");
3310 snprintf (buf, sizeof (buf), _("%s <%s>."), ts, p->mailbox);
3312 snprintf (buf, sizeof (buf), _("%s \"%s\"."), ts, s);
3316 mutt_clear_error ();
3320 switch (mutt_menuLoop (menu)) {
3322 verify_key (key_table[menu->current]);
3323 menu->redraw = REDRAW_FULL;
3327 mutt_message ("%s", key_table[menu->current]->uid);
3330 case OP_GENERIC_SELECT_ENTRY:
3331 /* FIXME make error reporting more verbose - this should be
3332 easy because gpgme provides more information */
3333 if (option (OPTPGPCHECKTRUST)) {
3334 if (!crypt_key_is_valid (key_table[menu->current])) {
3335 mutt_error _("This key can't be used: "
3336 "expired/disabled/revoked.");
3341 if (option (OPTPGPCHECKTRUST) &&
3342 (!crypt_id_is_valid (key_table[menu->current])
3343 || !crypt_id_is_strong (key_table[menu->current]))) {
3345 char buff[LONG_STRING];
3347 if (key_table[menu->current]->flags & KEYFLAG_CANTUSE)
3348 s = N_("ID is expired/disabled/revoked.");
3350 gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
3351 gpgme_user_id_t uid = NULL;
3356 uid = key_table[menu->current]->kobj->uids;
3357 for (j = 0; (j < key_table[menu->current]->idx) && uid;
3358 j++, uid = uid->next);
3360 val = uid->validity;
3363 case GPGME_VALIDITY_UNKNOWN:
3364 case GPGME_VALIDITY_UNDEFINED:
3365 warn_s = N_("ID has undefined validity.");
3367 case GPGME_VALIDITY_NEVER:
3368 warn_s = N_("ID is not valid.");
3370 case GPGME_VALIDITY_MARGINAL:
3371 warn_s = N_("ID is only marginally valid.");
3373 case GPGME_VALIDITY_FULL:
3374 case GPGME_VALIDITY_ULTIMATE:
3378 snprintf (buff, sizeof (buff),
3379 _("%s Do you really want to use the key?"), _(warn_s));
3381 if (mutt_yesorno (buff, 0) != 1) {
3382 mutt_clear_error ();
3389 k = crypt_copy_key (key_table[menu->current]);
3400 mutt_menuDestroy (&menu);
3401 p_delete(&key_table);
3403 set_option (OPTNEEDREDRAW);
3408 static crypt_key_t *crypt_getkeybyaddr (address_t * a, short abilities,
3409 unsigned int app, int *forced_valid)
3412 string_list_t *hints = NULL;
3417 int this_key_has_strong;
3418 int this_key_has_weak;
3419 int this_key_has_invalid;
3422 crypt_key_t *keys, *k;
3423 crypt_key_t *the_valid_key = NULL;
3424 crypt_key_t *matches = NULL;
3425 crypt_key_t **matches_endp = &matches;
3429 if (a && a->mailbox)
3430 hints = crypt_add_string_to_hints (hints, a->mailbox);
3431 if (a && a->personal)
3432 hints = crypt_add_string_to_hints (hints, a->personal);
3434 mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
3435 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
3437 string_list_wipe(&hints);
3442 for (k = keys; k; k = k->next) {
3443 if (abilities && !(k->flags & abilities)) {
3447 this_key_has_weak = 0; /* weak but valid match */
3448 this_key_has_invalid = 0; /* invalid match */
3449 this_key_has_strong = 0; /* strong and valid match */
3450 match = 0; /* any match */
3452 r = rfc822_parse_adrlist (NULL, k->uid);
3453 for (p = r; p; p = p->next) {
3454 int validity = crypt_id_matches_addr (a, p, k);
3456 if (validity & CRYPT_KV_MATCH) /* something matches */
3459 /* is this key a strong candidate? */
3460 if ((validity & CRYPT_KV_VALID)
3461 && (validity & CRYPT_KV_STRONGID)
3462 && (validity & CRYPT_KV_ADDR)) {
3463 if (the_valid_key && the_valid_key != k)
3466 this_key_has_strong = 1;
3468 else if ((validity & CRYPT_KV_MATCH)
3469 && !(validity & CRYPT_KV_VALID))
3470 this_key_has_invalid = 1;
3471 else if ((validity & CRYPT_KV_MATCH)
3472 && (!(validity & CRYPT_KV_STRONGID)
3473 || !(validity & CRYPT_KV_ADDR)))
3474 this_key_has_weak = 1;
3476 address_list_wipe(&r);
3481 if (!this_key_has_strong && this_key_has_invalid)
3483 if (!this_key_has_strong && this_key_has_weak)
3486 *matches_endp = tmp = crypt_copy_key (k);
3487 matches_endp = &tmp->next;
3488 the_valid_key = tmp;
3492 crypt_free_key (&keys);
3495 if (the_valid_key && !multi && !weak
3496 && !(invalid && option (OPTPGPSHOWUNUSABLE))) {
3498 * There was precisely one strong match on a valid ID, there
3499 * were no valid keys with weak matches, and we aren't
3500 * interested in seeing invalid keys.
3502 * Proceed without asking the user.
3504 k = crypt_copy_key (the_valid_key);
3508 * Else: Ask the user.
3510 k = crypt_select_key (matches, a, NULL, app, forced_valid);
3512 crypt_free_key (&matches);
3521 static crypt_key_t *crypt_getkeybystr (char *p, short abilities,
3522 unsigned int app, int *forced_valid)
3524 string_list_t *hints = NULL;
3526 crypt_key_t *matches = NULL;
3527 crypt_key_t **matches_endp = &matches;
3531 mutt_message (_("Looking for keys matching \"%s\"..."), p);
3535 hints = crypt_add_string_to_hints (hints, p);
3536 keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
3537 string_list_wipe(&hints);
3542 for (k = keys; k; k = k->next) {
3543 if (abilities && !(k->flags & abilities))
3548 if (!*p || !m_strcasecmp(p, crypt_keyid (k))
3549 || (!m_strncasecmp(p, "0x", 2)
3550 && !m_strcasecmp(p + 2, crypt_keyid (k)))
3551 || (option (OPTPGPLONGIDS)
3552 && !m_strncasecmp(p, "0x", 2)
3553 && !m_strcasecmp(p + 2, crypt_keyid (k) + 8))
3554 || m_stristr(k->uid, p)) {
3557 *matches_endp = tmp = crypt_copy_key (k);
3558 matches_endp = &tmp->next;
3562 crypt_free_key (&keys);
3565 k = crypt_select_key (matches, NULL, p, app, forced_valid);
3566 crypt_free_key (&matches);
3573 /* Display TAG as a prompt to ask for a key. If WHATFOR is not null
3574 use it as default and store it under that label as the next
3575 default. ABILITIES describe the required key abilities (sign,
3576 encrypt) and APP the type of the requested key; ether S/MIME or
3577 PGP. Return a copy of the key or NULL if not found. */
3578 static crypt_key_t *crypt_ask_for_key (char *tag,
3581 unsigned int app, int *forced_valid)
3584 char resp[SHORT_STRING];
3585 struct crypt_cache *l = NULL;
3589 forced_valid = &dummy;
3591 mutt_clear_error ();
3597 for (l = id_defaults; l; l = l->next)
3598 if (!m_strcasecmp(whatfor, l->what)) {
3599 m_strcpy(resp, sizeof(resp), NONULL(l->dflt));
3607 if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0)
3612 m_strreplace(&l->dflt, resp);
3614 l = p_new(struct crypt_cache, 1);
3615 l->next = id_defaults;
3617 l->what = m_strdup(whatfor);
3618 l->dflt = m_strdup(resp);
3622 if ((key = crypt_getkeybystr (resp, abilities, app, forced_valid)))
3630 /* This routine attempts to find the keyids of the recipients of a
3631 message. It returns NULL if any of the keys can not be found. */
3632 static char *find_keys (address_t * to, address_t * cc, address_t * bcc,
3635 char *keyID, *keylist = NULL, *t;
3636 ssize_t keylist_size = 0;
3637 ssize_t keylist_used = 0;
3638 address_t *tmp = NULL, *addr = NULL;
3639 address_t **last = &tmp;
3642 crypt_key_t *k_info, *key;
3643 const char *fqdn = mutt_fqdn (1);
3646 *r_application = APPLICATION_PGP | APPLICATION_SMIME;
3649 for (i = 0; i < 3; i++) {
3664 *last = address_list_dup (p);
3666 last = &((*last)->next);
3670 rfc822_qualify (tmp, fqdn);
3672 address_list_uniq(tmp);
3674 for (p = tmp; p; p = p->next) {
3675 char buf[LONG_STRING];
3676 int forced_valid = 0;
3681 if ((keyID = mutt_crypt_hook (p)) != NULL) {
3684 snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"),
3686 if ((r = mutt_yesorno (buf, M_YES)) == M_YES) {
3687 /* check for e-mail address */
3688 if ((t = strchr (keyID, '@')) &&
3689 (addr = rfc822_parse_adrlist (NULL, keyID))) {
3691 rfc822_qualify (addr, fqdn);
3696 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
3697 *r_application, &forced_valid);
3699 k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
3700 app, &forced_valid);
3706 address_list_wipe(&tmp);
3707 address_list_wipe(&addr);
3713 && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT,
3714 app, &forced_valid)) == NULL) {
3715 snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
3717 if ((key = crypt_ask_for_key (buf, q->mailbox, KEYFLAG_CANENCRYPT,
3723 &forced_valid)) == NULL) {
3725 address_list_wipe(&tmp);
3726 address_list_wipe(&addr);
3734 const char *s = crypt_fpr (key);
3737 if (key->flags & KEYFLAG_ISX509)
3738 *r_application &= ~APPLICATION_PGP;
3739 if (!(key->flags & KEYFLAG_ISX509))
3740 *r_application &= ~APPLICATION_SMIME;
3743 keylist_size += m_strlen(s) + 4 + 1;
3744 p_realloc(&keylist, keylist_size);
3745 sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */
3746 keylist_used ? " " : "", s, forced_valid ? "!" : "");
3748 keylist_used = m_strlen(keylist);
3750 crypt_free_key (&key);
3751 address_list_wipe(&addr);
3753 address_list_wipe(&tmp);
3757 char *pgp_gpgme_findkeys (address_t * to, address_t * cc, address_t * bcc)
3759 return find_keys (to, cc, bcc, APPLICATION_PGP);
3762 char *smime_gpgme_findkeys (address_t * to, address_t * cc, address_t * bcc)
3764 return find_keys (to, cc, bcc, APPLICATION_SMIME);
3768 * Implementation of `init'.
3771 /* Initialization. */
3772 static void init_gpgme (void)
3774 /* Make sure that gpg-agent is running. */
3775 if (!getenv ("GPG_AGENT_INFO")) {
3776 mutt_error ("\nUsing GPGME backend, although no gpg-agent is running");
3777 if (mutt_any_key_to_continue (NULL) == -1)
3782 void pgp_gpgme_init (void)
3787 void smime_gpgme_init (void)
3791 static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime)
3794 char input_signas[SHORT_STRING];
3797 if (msg->security & APPLICATION_PGP)
3799 else if (msg->security & APPLICATION_SMIME)
3804 mutt_multi_choice (_
3805 ("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?"),
3809 mutt_multi_choice (_
3810 ("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?"),
3814 case 1: /* (e)ncrypt */
3815 msg->security |= (is_smime ? SMIMEENCRYPT : PGPENCRYPT);
3816 msg->security &= ~(is_smime ? SMIMESIGN : PGPSIGN);
3819 case 2: /* (s)ign */
3820 msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
3821 msg->security &= ~(is_smime ? SMIMEENCRYPT : PGPENCRYPT);
3824 case 3: /* sign (a)s */
3825 /* unset_option(OPTCRYPTCHECKTRUST); */
3826 if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
3827 is_smime ? APPLICATION_SMIME :
3828 APPLICATION_PGP, NULL))) {
3829 snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p));
3830 m_strreplace(is_smime ? &SmimeDefaultKey : &PgpSignAs,
3832 crypt_free_key (&p);
3834 msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
3838 msg->security &= (is_smime ? ~SMIMESIGN : ~PGPSIGN);
3841 *redraw = REDRAW_FULL;
3844 case 4: /* (b)oth */
3846 (is_smime ? (SMIMEENCRYPT | SMIMESIGN) : (PGPENCRYPT | PGPSIGN));
3849 case 5: /* (p)gp or s/(m)ime */
3850 is_smime = !is_smime;
3853 case 6: /* (c)lear */
3858 if (choice == 6 || choice == 7);
3859 else if (is_smime) {
3860 msg->security &= ~APPLICATION_PGP;
3861 msg->security |= APPLICATION_SMIME;
3864 msg->security &= ~APPLICATION_SMIME;
3865 msg->security |= APPLICATION_PGP;
3868 return (msg->security);
3871 int pgp_gpgme_send_menu (HEADER * msg, int *redraw)
3873 return gpgme_send_menu (msg, redraw, 0);
3876 int smime_gpgme_send_menu (HEADER * msg, int *redraw)
3878 return gpgme_send_menu (msg, redraw, 1);
3881 static int verify_sender (HEADER * h, gpgme_protocol_t protocol __attribute__((unused)))
3883 address_t *sender = NULL;
3884 unsigned int ret = 1;
3887 h->env->from = mutt_expand_aliases (h->env->from);
3888 sender = h->env->from;
3890 else if (h->env->sender) {
3891 h->env->sender = mutt_expand_aliases (h->env->sender);
3892 sender = h->env->sender;
3896 if (signature_key) {
3897 gpgme_key_t key = signature_key;
3898 gpgme_user_id_t uid = NULL;
3899 int sender_length = 0;
3902 sender_length = m_strlen(sender->mailbox);
3903 for (uid = key->uids; uid && ret; uid = uid->next) {
3904 uid_length = m_strlen(uid->email);
3905 if (1 && (uid->email[0] == '<')
3906 && (uid->email[uid_length - 1] == '>')
3907 && (uid_length == sender_length + 2)
3908 && (!strncmp (uid->email + 1, sender->mailbox, sender_length)))
3913 mutt_any_key_to_continue ("Failed to verify sender");
3916 mutt_any_key_to_continue ("Failed to figure out sender");
3918 if (signature_key) {
3919 gpgme_key_release (signature_key);
3920 signature_key = NULL;
3926 int smime_gpgme_verify_sender (HEADER * h)
3928 return verify_sender (h, GPGME_PROTOCOL_CMS);