changeset: 6423:70b85d8b232b user: Peter Wu <[email protected]> date: Tue Feb 10 18:29:24 2015 +0100 link: http://dev.mutt.org/hg/mutt/rev/70b85d8b232b
Fix buffer underread for empty header values. (closes #3736) When a header has no value (*p == '\0' so l == 0), do not read outside the buffer but print the newline anyway when a tag is already printed (col != 0). Caught by ASAN while opening a draft with no Subject. changeset: 6424:71f12fef8c6f user: Kevin McCarthy <[email protected]> date: Thu Feb 19 11:00:32 2015 -0800 link: http://dev.mutt.org/hg/mutt/rev/71f12fef8c6f merge stable diffs (truncated from 4764 to 950 lines): diff -r 31ce789af3df -r 71f12fef8c6f .hgignore --- a/.hgignore Wed Dec 31 20:35:38 2014 -0800 +++ b/.hgignore Thu Feb 19 11:00:32 2015 -0800 @@ -37,6 +37,8 @@ ^doc/manual\.(txt|xml|aux|log|out|tex|pdf)$ ^doc/mutt\.1$ ^doc/muttrc\.man$ +^doc/pgpewrap\.1$ +^doc/pgpring\.1$ ^doc/.*\.html$ ^doc/stamp- ^doc/smime_keys\.1$ @@ -53,6 +55,9 @@ syntax: glob .deps Makefile +GPATH +GRTAGS +GTAGS TAGS cscope.* *.swp diff -r 31ce789af3df -r 71f12fef8c6f INSTALL --- a/INSTALL Wed Dec 31 20:35:38 2014 -0800 +++ b/INSTALL Thu Feb 19 11:00:32 2015 -0800 @@ -280,7 +280,7 @@ For the real fix, applying Sun patches # 105490-05 (linker patch) and # 105210-17 (libc and malloc patch) from sunsolve.sun.com has been reported to stop these problems - from occuring. + from occurring. Linux diff -r 31ce789af3df -r 71f12fef8c6f Makefile.am --- a/Makefile.am Wed Dec 31 20:35:38 2014 -0800 +++ b/Makefile.am Thu Feb 19 11:00:32 2015 -0800 @@ -1,5 +1,6 @@ ## Process this file with automake to produce Makefile.in ## Use aclocal -I m4; automake --foreign +include $(top_srcdir)/flymake.am AUTOMAKE_OPTIONS = 1.6 foreign EXTRA_PROGRAMS = mutt_dotlock pgpring pgpewrap mutt_md5 diff -r 31ce789af3df -r 71f12fef8c6f README.SECURITY --- a/README.SECURITY Wed Dec 31 20:35:38 2014 -0800 +++ b/README.SECURITY Thu Feb 19 11:00:32 2015 -0800 @@ -19,7 +19,7 @@ - Backticks are handled specially when preparing % expandos for mailcap entries. This fix will keep the current problem from - occuring, but we are sure there are other possible mailcap entries + occurring, but we are sure there are other possible mailcap entries where this doesn't help. - We have added a configuration variable named $mailcap_sanitize, diff -r 31ce789af3df -r 71f12fef8c6f README.SSL --- a/README.SSL Wed Dec 31 20:35:38 2014 -0800 +++ b/README.SSL Thu Feb 19 11:00:32 2015 -0800 @@ -97,7 +97,7 @@ openssl s_client -host <imap server> -port <port> -verify -debug -no_ssl2 openssl s_client -host <imap server> -port <port> -verify -debug -no_ssl3 -You can also combine the options until you get a successfull connect. Once +You can also combine the options until you get a successful connect. Once you know which options do not work, you can set the variables for non-working protocols to know. The variables for the protocols are ssl_use_tlsv1, ssl_use_sslv2, and ssl_use_sslv3. diff -r 31ce789af3df -r 71f12fef8c6f TODO --- a/TODO Wed Dec 31 20:35:38 2014 -0800 +++ b/TODO Thu Feb 19 11:00:32 2015 -0800 @@ -50,7 +50,7 @@ Note: This still requires some thought, since we'd have to store per-entry data in the menu structure. As an alternative, we could extend the tag method to do something to more general flags. The - latter approach would make the implementation of propper + latter approach would make the implementation of proper tag-prefix behaviour more simple: Functions should only be applied when a message is tagged and visible. Additionally, we must not access a menu's max field directly any more: Adding an entry to a diff -r 31ce789af3df -r 71f12fef8c6f UPDATING --- a/UPDATING Wed Dec 31 20:35:38 2014 -0800 +++ b/UPDATING Thu Feb 19 11:00:32 2015 -0800 @@ -9,6 +9,8 @@ ! FCC is now preserved when postponing a message. ! Mail-Followup-To is now preserved when recalling a postponed message. ! Allow filename prompt when saving multiple attachments to a directory. + + terminal status-line (TS) support, a.k.a. xterm title. see the + following variables: $ts_enabled, $ts_icon_format, $ts_status_format 1.5.22 (2013-10-18): diff -r 31ce789af3df -r 71f12fef8c6f color.c --- a/color.c Wed Dec 31 20:35:38 2014 -0800 +++ b/color.c Thu Feb 19 11:00:32 2015 -0800 @@ -93,6 +93,7 @@ { "bold", MT_COLOR_BOLD }, { "underline", MT_COLOR_UNDERLINE }, { "index", MT_COLOR_INDEX }, + { "prompt", MT_COLOR_PROMPT }, { NULL, 0 } }; diff -r 31ce789af3df -r 71f12fef8c6f commands.c --- a/commands.c Wed Dec 31 20:35:38 2014 -0800 +++ b/commands.c Thu Feb 19 11:00:32 2015 -0800 @@ -286,7 +286,7 @@ if (rc || !buf[0]) return; - if (!(adr = rfc822_parse_adrlist (adr, buf))) + if (!(adr = mutt_parse_adrlist (adr, buf))) { mutt_error _("Error parsing address!"); return; diff -r 31ce789af3df -r 71f12fef8c6f configure.ac --- a/configure.ac Wed Dec 31 20:35:38 2014 -0800 +++ b/configure.ac Thu Feb 19 11:00:32 2015 -0800 @@ -138,6 +138,11 @@ #needed to get GPGME_LIBS and al correctly AM_PATH_GPGME(1.0.0, AC_DEFINE(CRYPT_BACKEND_GPGME, 1, [Define if you use GPGME to support OpenPGP])) + dnl AC_CHECK_FUNCS([gpgme_op_export_keys]) + saved_LIBS="$LIBS" + LIBS="$LIBS $GPGME_LIBS" + AC_CHECK_FUNCS([gpgme_op_export_keys]) + LIBS="$saved_LIBS" MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS crypt-gpgme.o crypt-mod-pgp-gpgme.o crypt-mod-smime-gpgme.o" fi else @@ -163,7 +168,7 @@ ]) if test x$have_smime != xno ; then - AC_DEFINE(CRYPT_BACKEND_CLASSIC_SMIME, 1, [Define if you want clasic S/MIME support.]) + AC_DEFINE(CRYPT_BACKEND_CLASSIC_SMIME, 1, [Define if you want classic S/MIME support.]) MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS smime.o crypt-mod-smime-classic.o" SMIMEAUX_TARGET="smime_keys" fi @@ -295,6 +300,7 @@ if test "$ac_cv_func_decl_resizeterm" = yes; then MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS resize.o" fi + AC_CHECK_FUNCS([use_extended_names]) LIBS="$old_LIBS" ]) @@ -706,6 +712,16 @@ AC_CHECK_DECLS([GNUTLS_VERIFY_DISABLE_TIME_CHECKS], [], [], [[#include <gnutls/x509.h>]]) + LIBS="$LIBS -lgnutls" + AC_CHECK_FUNCS(gnutls_priority_set_direct) + AC_CHECK_TYPES([gnutls_certificate_credentials_t, + gnutls_certificate_status_t, + gnutls_datum_t, + gnutls_digest_algorithm_t, + gnutls_session_t, + gnutls_transport_ptr_t, + gnutls_x509_crt_t], [], [], [[#include <gnutls/gnutls.h>]]) + LIBS="$saved_LIBS" MUTTLIBS="$MUTTLIBS -lgnutls" diff -r 31ce789af3df -r 71f12fef8c6f contrib/colors.default --- a/contrib/colors.default Wed Dec 31 20:35:38 2014 -0800 +++ b/contrib/colors.default Thu Feb 19 11:00:32 2015 -0800 @@ -6,6 +6,7 @@ color quoted blue white color signature red white color attachment red white +color prompt brightmagenta white color message brightred white color error brightred white color indicator brightyellow red diff -r 31ce789af3df -r 71f12fef8c6f contrib/colors.linux --- a/contrib/colors.linux Wed Dec 31 20:35:38 2014 -0800 +++ b/contrib/colors.linux Thu Feb 19 11:00:32 2015 -0800 @@ -6,6 +6,7 @@ color quoted blue black color signature blue black color attachment red black +color prompt brightmagenta black color message brightred black color error brightred black color indicator black red diff -r 31ce789af3df -r 71f12fef8c6f contrib/gpg.rc --- a/contrib/gpg.rc Wed Dec 31 20:35:38 2014 -0800 +++ b/contrib/gpg.rc Thu Feb 19 11:00:32 2015 -0800 @@ -65,10 +65,10 @@ set pgp_verify_key_command="gpg --verbose --batch --fingerprint --check-sigs %r" # read in the public key ring -set pgp_list_pubring_command="gpg --no-verbose --batch --quiet --with-colons --list-keys %r" +set pgp_list_pubring_command="gpg --no-verbose --batch --quiet --with-colons --with-fingerprint --with-fingerprint --list-keys %r" # read in the secret key ring -set pgp_list_secring_command="gpg --no-verbose --batch --quiet --with-colons --list-secret-keys %r" +set pgp_list_secring_command="gpg --no-verbose --batch --quiet --with-colons --with-fingerprint --with-fingerprint --list-secret-keys %r" # fetch keys # set pgp_getkeys_command="pkspxycwrap %r" diff -r 31ce789af3df -r 71f12fef8c6f contrib/smime.rc --- a/contrib/smime.rc Wed Dec 31 20:35:38 2014 -0800 +++ b/contrib/smime.rc Thu Feb 19 11:00:32 2015 -0800 @@ -59,8 +59,8 @@ # Sction B: Outgoing messages # Algorithm to use for encryption. -# valid choices are rc2-40, rc2-64, rc2-128, des, des3 -set smime_encrypt_with="des3" +# valid choices are aes128, aes192, aes256, rc2-40, rc2-64, rc2-128, des, des3 +set smime_encrypt_with="aes256" # Encrypt a message. Input file is a MIME entity. set smime_encrypt_command="openssl smime -encrypt -%a -outform DER -in %f %c" diff -r 31ce789af3df -r 71f12fef8c6f crypt-gpgme.c --- a/crypt-gpgme.c Wed Dec 31 20:35:38 2014 -0800 +++ b/crypt-gpgme.c Thu Feb 19 11:00:32 2015 -0800 @@ -110,6 +110,7 @@ int idx; /* and the user ID at this index */ const char *uid; /* and for convenience point to this user ID */ unsigned int flags; /* global and per uid flags (for convenience)*/ + gpgme_validity_t validity; /* uid validity (cached for convenience) */ } crypt_key_t; typedef struct crypt_entry @@ -179,6 +180,34 @@ return s; } +/* Return the long keyID for the key K. */ +static const char *crypt_long_keyid (crypt_key_t *k) +{ + const char *s = "????????????????"; + + if (k->kobj && k->kobj->subkeys) + { + s = k->kobj->subkeys->keyid; + } + + return s; +} + +/* Return the short keyID for the key K. */ +static const char *crypt_short_keyid (crypt_key_t *k) +{ + const char *s = "????????"; + + if (k->kobj && k->kobj->subkeys) + { + s = k->kobj->subkeys->keyid; + if (strlen (s) == 16) + s += 8; + } + + return s; +} + /* Return the hexstring fingerprint from the key K. */ static const char *crypt_fpr (crypt_key_t *k) { @@ -240,6 +269,7 @@ k->idx = key->idx; k->uid = key->uid; k->flags = key->flags; + k->validity = key->validity; return k; } @@ -248,12 +278,19 @@ to NULL. */ static void crypt_free_key (crypt_key_t **keylist) { + crypt_key_t *k; + + if (!keylist) + return; + while (*keylist) - { - crypt_key_t *k = (*keylist)->next; - FREE (&k); - *keylist = k; - } + { + k = *keylist; + *keylist = (*keylist)->next; + + gpgme_key_unref (k->kobj); + FREE (&k); + } } /* Return trute when key K is valid. */ @@ -267,21 +304,12 @@ /* Return true whe validity of KEY is sufficient. */ static int crypt_id_is_strong (crypt_key_t *key) { - gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN; - gpgme_user_id_t uid = NULL; unsigned int is_strong = 0; - unsigned int i = 0; if ((key->flags & KEYFLAG_ISX509)) return 1; - for (i = 0, uid = key->kobj->uids; (i < key->idx) && uid; - i++, uid = uid->next) - ; - if (uid) - val = uid->validity; - - switch (val) + switch (key->validity) { case GPGME_VALIDITY_UNKNOWN: case GPGME_VALIDITY_UNDEFINED: @@ -504,21 +532,27 @@ return 0; } -/* Copy a data object to a newly created temporay file and return that - filename. Caller must free. With RET_FP not NULL, don't close the - stream but return it there. */ -static char *data_object_to_tempfile (gpgme_data_t data, FILE **ret_fp) +/* Copy a data object to a temporary file. + * The tempfile name may be optionally passed in. + * If ret_fp is passed in, the file will be rewound, left open, and returned + * via that parameter. + * The tempfile name is returned, and must be freed. + */ +static char *data_object_to_tempfile (gpgme_data_t data, char *tempf, FILE **ret_fp) { int err; - char tempfile[_POSIX_PATH_MAX]; + char tempfb[_POSIX_PATH_MAX]; FILE *fp; size_t nread = 0; - mutt_mktemp (tempfile, sizeof (tempfile)); - fp = safe_fopen (tempfile, "w+"); - if (!fp) + if (!tempf) { - mutt_perror (tempfile); + mutt_mktemp (tempfb, sizeof (tempfb)); + tempf = tempfb; + } + if ((fp = safe_fopen (tempf, tempf == tempfb ? "w+" : "a+")) == NULL) + { + mutt_perror _("Can't create temporary file"); return NULL; } @@ -532,9 +566,9 @@ { if (fwrite (buf, nread, 1, fp) != 1) { - mutt_perror (tempfile); + mutt_perror (tempf); safe_fclose (&fp); - unlink (tempfile); + unlink (tempf); return NULL; } } @@ -546,13 +580,35 @@ if (nread == -1) { mutt_error (_("error reading data object: %s\n"), gpgme_strerror (err)); - unlink (tempfile); + unlink (tempf); safe_fclose (&fp); return NULL; } if (ret_fp) *ret_fp = fp; - return safe_strdup (tempfile); + return safe_strdup (tempf); +} + + +static void free_recipient_set (gpgme_key_t **p_rset) +{ + gpgme_key_t *rset, k; + + if (!p_rset) + return; + + rset = *p_rset; + if (!rset) + return; + + while (*rset) + { + k = *rset; + gpgme_key_unref (k); + rset++; + } + + FREE (p_rset); /* __FREE_CHECKED__ */ } @@ -608,7 +664,9 @@ { mutt_error (_("error adding recipient `%s': %s\n"), buf, gpgme_strerror (err)); - FREE (&rset); + rset[rset_n] = NULL; + free_recipient_set (&rset); + gpgme_release (context); return NULL; } } @@ -651,8 +709,8 @@ err = gpgme_op_keylist_next (listctx, &key2); if (!err) { - gpgme_key_release (key); - gpgme_key_release (key2); + gpgme_key_unref (key); + gpgme_key_unref (key2); gpgme_release (listctx); mutt_error (_("ambiguous specification of secret key `%s'\n"), signid); @@ -663,7 +721,7 @@ gpgme_signers_clear (ctx); err = gpgme_signers_add (ctx, key); - gpgme_key_release (key); + gpgme_key_unref (key); if (err) { mutt_error (_("error setting secret key `%s': %s\n"), @@ -747,7 +805,7 @@ gpgme_release (ctx); - outfile = data_object_to_tempfile (ciphertext, NULL); + outfile = data_object_to_tempfile (ciphertext, NULL, NULL); gpgme_data_release (ciphertext); return outfile; } @@ -834,6 +892,7 @@ if (set_signer (ctx, use_smime)) { gpgme_data_release (signature); + gpgme_data_release (message); gpgme_release (ctx); return NULL; } @@ -872,7 +931,7 @@ return NULL; } - sigfile = data_object_to_tempfile (signature, NULL); + sigfile = data_object_to_tempfile (signature, NULL, NULL); gpgme_data_release (signature); if (!sigfile) { @@ -918,6 +977,7 @@ else { t->subtype = safe_strdup ("pgp-signature"); + mutt_set_parameter ("name", "signature.asc", &t->parameter); t->use_disp = 0; t->disposition = DISPNONE; t->encoding = ENC7BIT; @@ -961,13 +1021,13 @@ plaintext = body_to_data_object (a, 0); if (!plaintext) { - FREE (&rset); + free_recipient_set (&rset); return NULL; } outfile = encrypt_gpgme_object (plaintext, rset, 0, sign); gpgme_data_release (plaintext); - FREE (&rset); + free_recipient_set (&rset); if (!outfile) return NULL; @@ -1020,13 +1080,13 @@ plaintext = body_to_data_object (a, 0); if (!plaintext) { - FREE (&rset); + free_recipient_set (&rset); return NULL; } outfile = encrypt_gpgme_object (plaintext, rset, 1, 0); gpgme_data_release (plaintext); - FREE (&rset); + free_recipient_set (&rset); if (!outfile) return NULL; @@ -1342,7 +1402,7 @@ if (signature_key) { - gpgme_key_release (signature_key); + gpgme_key_unref (signature_key); signature_key = NULL; } @@ -1420,7 +1480,7 @@ } if (key != signature_key) - gpgme_key_release (key); + gpgme_key_unref (key); } return anybad ? 1 : anywarn ? 2 : 0; @@ -1461,6 +1521,9 @@ state_attach_puts (_("[-- Begin signature information --]\n"), s); err = gpgme_op_verify (ctx, signature, message, NULL); + gpgme_data_release (message); + gpgme_data_release (signature); + mutt_need_hard_redraw (); if (err) { @@ -1478,7 +1541,7 @@ if (signature_key) { - gpgme_key_release (signature_key); + gpgme_key_unref (signature_key); signature_key = NULL; } @@ -1966,7 +2029,7 @@ subkey = subkey->next; more = 1; } - gpgme_key_release (key); + gpgme_key_unref (key); } if (gpg_err_code (err) != GPG_ERR_EOF) { @@ -2148,7 +2211,7 @@ char *fname; FILE *fp; - fname = data_object_to_tempfile (data, &fp); + fname = data_object_to_tempfile (data, NULL, &fp); if (!fname) return; unlink (fname); @@ -2341,7 +2404,7 @@ "information --]\n\n"), s); } - tmpfname = data_object_to_tempfile (plaintext, &pgpout); + tmpfname = data_object_to_tempfile (plaintext, NULL, &pgpout); if (!tmpfname) { pgpout = NULL; @@ -2353,6 +2416,7 @@ FREE (&tmpfname); } } + gpgme_data_release (plaintext); gpgme_release (ctx); } @@ -2404,6 +2468,7 @@ state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s); } + gpgme_data_release (armored_data); if (pgpout) { safe_fclose (&pgpout); @@ -2769,35 +2834,28 @@ s = "x"; else { - gpgme_user_id_t uid = NULL; - unsigned int i = 0; - - for (i = 0, uid = key->kobj->uids; uid && (i < key->idx); - i++, uid = uid->next) - ; - if (uid) - switch (uid->validity) - { - case GPGME_VALIDITY_UNDEFINED: - s = "q"; - break; - case GPGME_VALIDITY_NEVER: - s = "n"; - break; - case GPGME_VALIDITY_MARGINAL: - s = "m"; - break; - case GPGME_VALIDITY_FULL: - s = "f"; - break; - case GPGME_VALIDITY_ULTIMATE: - s = "u"; - break; - case GPGME_VALIDITY_UNKNOWN: - default: - s = "?"; - break; - } + switch (key->validity) + { + case GPGME_VALIDITY_UNDEFINED: + s = "q"; + break; + case GPGME_VALIDITY_NEVER: + s = "n"; + break; + case GPGME_VALIDITY_MARGINAL: + s = "m"; + break; + case GPGME_VALIDITY_FULL: + s = "f"; + break; + case GPGME_VALIDITY_ULTIMATE: + s = "u"; + break; + case GPGME_VALIDITY_UNKNOWN: + default: + s = "?"; + break; + } } snprintf (fmt, sizeof (fmt), "%%%sc", prefix); snprintf (dest, destlen, fmt, s? *s: 'B'); @@ -2910,10 +2968,8 @@ - ((*t)->flags & (KEYFLAG_RESTRICTIONS))))) return r > 0; - if ((*s)->kobj->uids) - ts = (*s)->kobj->uids->validity; - if ((*t)->kobj->uids) - tt = (*t)->kobj->uids->validity; + ts = (*s)->validity; + tt = (*t)->validity; if ((r = (tt - ts))) return r < 0; @@ -3514,7 +3570,7 @@ { putc ('\n', fp); err = gpgme_op_keylist_start (listctx, s, 0); - gpgme_key_release (k); + gpgme_key_unref (k); k = NULL; if (!err) err = gpgme_op_keylist_next (listctx, &k); @@ -3537,7 +3593,7 @@ } leave: - gpgme_key_release (k); + gpgme_key_unref (k); gpgme_release (listctx); safe_fclose (&fp); mutt_clear_error (); @@ -3679,6 +3735,13 @@ if (key_check_cap (key, KEY_CAP_CAN_SIGN)) flags |= KEYFLAG_CANSIGN; + if (key->revoked) + flags |= KEYFLAG_REVOKED; + if (key->expired) + flags |= KEYFLAG_EXPIRED; + if (key->disabled) + flags |= KEYFLAG_DISABLED; + #if 0 /* DISABLED code */ if (!flags) { @@ -3705,12 +3768,17 @@ { k = safe_calloc (1, sizeof *k); k->kobj = key; + gpgme_key_ref (k->kobj); k->idx = idx; k->uid = uid->uid; k->flags = flags; + if (uid->revoked) + k->flags |= KEYFLAG_REVOKED; + k->validity = uid->validity; *kend = k; kend = &k->next; } + gpgme_key_unref (key); } if (gpg_err_code (err) != GPG_ERR_EOF) mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err)); @@ -3746,12 +3814,15 @@ { k = safe_calloc (1, sizeof *k); k->kobj = key; + gpgme_key_ref (k->kobj); k->idx = idx; k->uid = uid->uid; k->flags = flags; + k->validity = uid->validity; *kend = k; kend = &k->next; } + gpgme_key_unref (key); } if (gpg_err_code (err) != GPG_ERR_EOF) mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err)); @@ -3927,23 +3998,11 @@ char buff[LONG_STRING]; if (key_table[menu->current]->flags & KEYFLAG_CANTUSE) - s = N_("ID is expired/disabled/revoked."); + warn_s = N_("ID is expired/disabled/revoked."); else { - gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN; - gpgme_user_id_t uid = NULL; - unsigned int j = 0; - warn_s = "??"; - - uid = key_table[menu->current]->kobj->uids; - for (j = 0; (j < key_table[menu->current]->idx) && uid; - j++, uid = uid->next) - ; - if (uid) - val = uid->validity; - - switch (val) + switch (key_table[menu->current]->validity) { case GPGME_VALIDITY_UNKNOWN: case GPGME_VALIDITY_UNDEFINED: @@ -3959,18 +4018,18 @@ case GPGME_VALIDITY_ULTIMATE: break; } - - snprintf (buff, sizeof (buff), - _("%s Do you really want to use the key?"), - _(warn_s)); - - if (mutt_yesorno (buff, 0) != 1) - { - mutt_clear_error (); - break; - } - *forced_valid = 1; } + + snprintf (buff, sizeof (buff), + _("%s Do you really want to use the key?"), + _(warn_s)); + + if (mutt_yesorno (buff, 0) != 1) + { + mutt_clear_error (); + break; + } + *forced_valid = 1; } k = crypt_copy_key (key_table[menu->current]); @@ -4129,33 +4188,35 @@ crypt_key_t *matches = NULL; crypt_key_t **matches_endp = &matches; crypt_key_t *k; + const char *ps, *pl, *pfcopy, *phint; mutt_message (_("Looking for keys matching \"%s\"..."), p); *forced_valid = 0; - hints = crypt_add_string_to_hints (hints, p); + pfcopy = crypt_get_fingerprint_or_id (p, &phint, &pl, &ps); + hints = crypt_add_string_to_hints (hints, phint); keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN)); mutt_free_list (&hints); if (!keys) + { + FREE (&pfcopy); return NULL; - + } + for (k = keys; k; k = k->next) { if (abilities && !(k->flags & abilities)) continue; dprint (5, (debugfile, "crypt_getkeybystr: matching \"%s\" against " - "key %s, \"%s\": ", p, crypt_keyid (k), k->uid)); + "key %s, \"%s\": ", p, crypt_long_keyid (k), k->uid)); if (!*p - || !mutt_strcasecmp (p, crypt_keyid (k)) - || (!mutt_strncasecmp (p, "0x", 2) - && !mutt_strcasecmp (p + 2, crypt_keyid (k))) - || (option (OPTPGPLONGIDS) - && !mutt_strncasecmp (p, "0x", 2) - && !mutt_strcasecmp (p + 2, crypt_keyid (k) + 8)) + || (pfcopy && mutt_strcasecmp (pfcopy, crypt_fpr (k)) == 0) + || (pl && mutt_strcasecmp (pl, crypt_long_keyid (k)) == 0) + || (ps && mutt_strcasecmp (ps, crypt_short_keyid (k)) == 0) || mutt_stristr (k->uid, p)) { crypt_key_t *tmp; @@ -4167,6 +4228,7 @@ } } + FREE (&pfcopy); crypt_free_key (&keys); if (matches) @@ -4383,6 +4445,65 @@ return find_keys (to, cc, bcc, APPLICATION_SMIME); } +#ifdef HAVE_GPGME_OP_EXPORT_KEYS +BODY *pgp_gpgme_make_key_attachment (char *tempf) +{ + crypt_key_t *key = NULL; + gpgme_ctx_t context = NULL; + gpgme_key_t export_keys[2]; + gpgme_data_t keydata = NULL; + gpgme_error_t err; + BODY *att = NULL; + char buff[LONG_STRING]; + struct stat sb; + + unset_option (OPTPGPCHECKTRUST); + + key = crypt_ask_for_key (_("Please enter the key ID: "), NULL, 0, + APPLICATION_PGP, NULL); + if (!key) + goto bail; + export_keys[0] = key->kobj; + export_keys[1] = NULL; + + context = create_gpgme_context (0); + gpgme_set_armor (context, 1); + keydata = create_gpgme_data (); + err = gpgme_op_export_keys (context, export_keys, 0, keydata); + if (err != GPG_ERR_NO_ERROR) + { + mutt_error (_("Error exporting key: %s\n"), gpgme_strerror (err)); + mutt_sleep (1); + goto bail; + } + + tempf = data_object_to_tempfile (keydata, tempf, NULL); + if (!tempf) + goto bail; + + att = mutt_new_body (); + /* tempf is a newly allocated string, so this is correct: */ + att->filename = tempf; + att->unlink = 1; + att->use_disp = 0; + att->type = TYPEAPPLICATION; + att->subtype = safe_strdup ("pgp-keys"); + snprintf (buff, sizeof (buff), _("PGP Key 0x%s."), crypt_keyid (key)); + att->description = safe_strdup (buff); + mutt_update_encoding (att); + + stat (tempf, &sb); + att->length = sb.st_size; + +bail: + crypt_free_key (&key); + gpgme_data_release (keydata); + gpgme_release (context); + + return att; +} +#endif + /* * Implementation of `init'. */ @@ -4405,27 +4526,36 @@ } } -/* Initialization. */ -static void init_gpgme (void) +static void init_pgp (void) { - /* Make sure that gpg-agent is running. */ - if (! getenv ("GPG_AGENT_INFO")) - { - mutt_error (_("\nUsing GPGME backend, although no gpg-agent is running")); - if (mutt_any_key_to_continue (NULL) == -1) - mutt_exit(1); - } + if (gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP) != GPG_ERR_NO_ERROR) + { + mutt_error (_("GPGME: OpenPGP protocol not available")); + if (mutt_any_key_to_continue (NULL) == -1) + mutt_exit(1); + } +} + +static void init_smime (void) +{ + if (gpgme_engine_check_version (GPGME_PROTOCOL_CMS) != GPG_ERR_NO_ERROR) + { + mutt_error (_("GPGME: CMS protocol not available")); + if (mutt_any_key_to_continue (NULL) == -1) + mutt_exit(1); + } } void pgp_gpgme_init (void) { - init_common(); - init_gpgme (); + init_common (); + init_pgp (); } void smime_gpgme_init (void) { - init_common(); + init_common (); + init_smime (); } static int gpgme_send_menu (HEADER *msg, int *redraw, int is_smime) @@ -4595,7 +4725,7 @@ if (signature_key) { - gpgme_key_release (signature_key); + gpgme_key_unref (signature_key); signature_key = NULL;
