# HG changeset patch # User Kevin McCarthy # Date 1423248576 28800 # Fri Feb 06 10:49:36 2015 -0800 # Node ID 22ab841794822e0e1c2595a9851e1f68d332d45d # Parent 44a0805f0053ac7300ec25f23e146d3f1d4b234f Add ui elements for oppenc mode. Add a status message to the Security line when oppenc is enabled. For each send menu, add the ability to toggle it on or off. When enabled, the menus won't show the (e)ncrypt or (b)oth options, and the (c)lear function only clears the SIGN bit when it is active. Change the gpgme_send_menu() to directly use the ENCRYPT and SIGN flags instead of the PGPENCRYPT/SIGN and SMIMEENCRYPT/SMIME flags. Using the latter sometimes resulted in the APPLICATION bit unset, which made oppenc unhappy. The send_menus previously used a switch statement using choice numbers. Since the menus now vary based on the oppenc option and message bit being set, these were all changed to convert the numbers back to a choice letter. diff --git a/compose.c b/compose.c --- a/compose.c +++ b/compose.c @@ -136,16 +136,19 @@ else addstr (_(" (PGP/MIME)")); } else if ((WithCrypto & APPLICATION_SMIME) && (msg->security & APPLICATION_SMIME)) addstr (_(" (S/MIME)")); } + if (option (OPTCRYPTOPPORTUNISTICENCRYPT) && (msg->security & OPPENCRYPT)) + addstr (_(" (OppEnc mode)")); + clrtoeol (); move (HDR_CRYPTINFO, 0); clrtoeol (); if ((WithCrypto & APPLICATION_PGP) && (msg->security & APPLICATION_PGP) && (msg->security & SIGN)) printw ("%s%s", _(" sign as: "), PgpSignAs ? PgpSignAs : _("")); @@ -1232,17 +1235,18 @@ && (msg->security & APPLICATION_SMIME)) { if (mutt_yesorno (_("S/MIME already selected. Clear & continue ? "), M_YES) != M_YES) { mutt_clear_error (); break; } - msg->security = 0; + msg->security &= ~APPLICATION_SMIME; + msg->security |= APPLICATION_PGP; } msg->security = crypt_pgp_send_menu (msg, &menu->redraw); redraw_crypt_lines (msg); mutt_message_hook (NULL, msg, M_SEND2HOOK); break; case OP_FORGET_PASSPHRASE: @@ -1258,17 +1262,18 @@ && (msg->security & APPLICATION_PGP)) { if (mutt_yesorno (_("PGP already selected. Clear & continue ? "), M_YES) != M_YES) { mutt_clear_error (); break; } - msg->security = 0; + msg->security &= ~APPLICATION_PGP; + msg->security |= APPLICATION_SMIME; } msg->security = crypt_smime_send_menu(msg, &menu->redraw); redraw_crypt_lines (msg); mutt_message_hook (NULL, msg, M_SEND2HOOK); break; #ifdef MIXMASTER diff --git a/crypt-gpgme.c b/crypt-gpgme.c --- a/crypt-gpgme.c +++ b/crypt-gpgme.c @@ -4599,92 +4599,156 @@ init_common (); init_smime (); } static int gpgme_send_menu (HEADER *msg, int *redraw, int is_smime) { crypt_key_t *p; char input_signas[SHORT_STRING]; + char *prompt, *letters, *choices; int choice; - if (msg->security & APPLICATION_PGP) - is_smime = 0; - else if (msg->security & APPLICATION_SMIME) - is_smime = 1; - if (is_smime) - choice = mutt_multi_choice ( - _("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?"), - _("esabpfc")); - else - choice = mutt_multi_choice ( - _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?"), - _("esabmfc")); - - switch (choice) + msg->security |= APPLICATION_SMIME; + else + msg->security |= APPLICATION_PGP; + + /* + * Opportunistic encrypt is controlling encryption. + * NOTE: "Signing" and "Clearing" only adjust the sign bit, so we have different + * letter choices for those. + */ + if (option (OPTCRYPTOPPORTUNISTICENCRYPT) && (msg->security & OPPENCRYPT)) { - case 1: /* (e)ncrypt */ - msg->security |= (is_smime ? SMIMEENCRYPT : PGPENCRYPT); - msg->security &= ~(is_smime ? SMIMESIGN : PGPSIGN); - break; - - case 2: /* (s)ign */ - msg->security |= (is_smime? SMIMESIGN :PGPSIGN); - msg->security &= ~(is_smime ? SMIMEENCRYPT : PGPENCRYPT); - break; - - case 3: /* sign (a)s */ -/* unset_option(OPTCRYPTCHECKTRUST); */ - if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN, - is_smime? APPLICATION_SMIME:APPLICATION_PGP, - NULL))) + if (is_smime) { - snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p)); - mutt_str_replace (is_smime? &SmimeDefaultKey : &PgpSignAs, input_signas); - crypt_free_key (&p); - - msg->security |= (is_smime? SMIMESIGN:PGPSIGN); + prompt = _("S/MIME (s)ign, sign (a)s, (p)gp, (c)lear, or (o)ppenc mode off? "); + letters = _("sapfco"); + choices = "SapFCo"; } -#if 0 else { - msg->security &= (is_smime? ~SMIMESIGN : ~PGPSIGN); + prompt = _("PGP (s)ign, sign (a)s, s/(m)ime, (c)lear, or (o)ppenc mode off? "); + letters = _("samfco"); + choices = "SamFCo"; } -#endif - *redraw = REDRAW_FULL; - break; - - case 4: /* (b)oth */ - msg->security = (is_smime? (SMIMEENCRYPT|SMIMESIGN):(PGPENCRYPT|PGPSIGN)); - break; - - case 5: /* (p)gp or s/(m)ime */ - is_smime = !is_smime; - break; - - case 6: /* (f)orget it */ - case 7: /* (c)lear */ - msg->security = 0; - break; } - - if (choice == 6 || choice == 7) - ; - else if (is_smime) + /* + * Opportunistic encryption option is set, but is toggled off + * for this message. + */ + else if (option (OPTCRYPTOPPORTUNISTICENCRYPT)) + { + if (is_smime) { - msg->security &= ~APPLICATION_PGP; - msg->security |= APPLICATION_SMIME; + prompt = _("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp, (c)lear, or (o)ppenc mode? "); + letters = _("esabpfco"); + choices = "esabpfcO"; } + else + { + prompt = _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime, (c)lear, or (o)ppenc mode? "); + letters = _("esabmfco"); + choices = "esabmfcO"; + } + } + /* + * Opportunistic encryption is unset + */ else + { + if (is_smime) { - msg->security &= ~APPLICATION_SMIME; - msg->security |= APPLICATION_PGP; + prompt = _("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear? "); + letters = _("esabpfc"); + choices = "esabpfc"; } - + else + { + prompt = _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear? "); + letters = _("esabmfc"); + choices = "esabmfc"; + } + } + + choice = mutt_multi_choice (prompt, letters); + if (choice > 0) + { + switch (choices[choice - 1]) + { + case 'e': /* (e)ncrypt */ + msg->security |= ENCRYPT; + msg->security &= ~SIGN; + break; + + case 's': /* (s)ign */ + msg->security &= ~ENCRYPT; + msg->security |= SIGN; + break; + + case 'S': /* (s)ign in oppenc mode */ + msg->security |= SIGN; + break; + + case 'a': /* sign (a)s */ + if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN, + is_smime? APPLICATION_SMIME:APPLICATION_PGP, + NULL))) + { + snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p)); + mutt_str_replace (is_smime? &SmimeDefaultKey : &PgpSignAs, input_signas); + crypt_free_key (&p); + + msg->security |= SIGN; + } + *redraw = REDRAW_FULL; + break; + + case 'b': /* (b)oth */ + msg->security |= (ENCRYPT | SIGN); + break; + + case 'p': /* (p)gp or s/(m)ime */ + case 'm': + is_smime = !is_smime; + if (is_smime) + { + msg->security &= ~APPLICATION_PGP; + msg->security |= APPLICATION_SMIME; + } + else + { + msg->security &= ~APPLICATION_SMIME; + msg->security |= APPLICATION_PGP; + } + crypt_opportunistic_encrypt (msg); + break; + + case 'f': /* (f)orget it */ + case 'c': /* (c)lear */ + msg->security &= ~(ENCRYPT | SIGN); + break; + + case 'F': /* (f)orget it or (c)lear in oppenc mode */ + case 'C': + msg->security &= ~SIGN; + break; + + case 'O': /* oppenc mode on */ + msg->security |= OPPENCRYPT; + crypt_opportunistic_encrypt (msg); + break; + + case 'o': /* oppenc mode off */ + msg->security &= ~OPPENCRYPT; + break; + } + } + return (msg->security); } int pgp_gpgme_send_menu (HEADER *msg, int *redraw) { return gpgme_send_menu (msg, redraw, 0); } diff --git a/pgp.c b/pgp.c --- a/pgp.c +++ b/pgp.c @@ -1559,111 +1559,167 @@ if (!(flags & ENCRYPT)) b->encoding = a->encoding; return b; } int pgp_send_menu (HEADER *msg, int *redraw) { + pgp_key_t p; + char input_signas[SHORT_STRING]; + char *prompt, *letters, *choices; + char promptbuf[LONG_STRING]; int choice; - + if (!(WithCrypto & APPLICATION_PGP)) return msg->security; /* If autoinline and no crypto options set, then set inline. */ if (option (OPTPGPAUTOINLINE) && !((msg->security & APPLICATION_PGP) && (msg->security & (SIGN|ENCRYPT)))) msg->security |= INLINE; - - /* When the message is not selected for signing or encryption, the toggle - * between PGP/MIME and Traditional doesn't make sense. + + msg->security |= APPLICATION_PGP; + + /* + * Opportunistic encrypt is controlling encryption. Allow to toggle + * between inline and mime, but not turn encryption on or off. + * NOTE: "Signing" and "Clearing" only adjust the sign bit, so we have different + * letter choices for those. */ - if (msg->security & (ENCRYPT | SIGN)) + if (option (OPTCRYPTOPPORTUNISTICENCRYPT) && (msg->security & OPPENCRYPT)) { - char prompt[LONG_STRING]; + if (msg->security & (ENCRYPT | SIGN)) + { + snprintf (promptbuf, sizeof (promptbuf), + _("PGP (s)ign, sign (a)s, %s format, (c)lear, or (o)ppenc mode off? "), + (msg->security & INLINE) ? _("PGP/M(i)ME") : _("(i)nline")); + prompt = promptbuf; + letters = _("safcoi"); + choices = "SaFCoi"; + } + else + { + prompt = _("PGP (s)ign, sign (a)s, (c)lear, or (o)ppenc mode off? "); + letters = _("safco"); + choices = "SaFCo"; + } + } + /* + * Opportunistic encryption option is set, but is toggled off + * for this message. + */ + else if (option (OPTCRYPTOPPORTUNISTICENCRYPT)) + { + /* When the message is not selected for signing or encryption, the toggle + * between PGP/MIME and Traditional doesn't make sense. + */ + if (msg->security & (ENCRYPT | SIGN)) + { - snprintf (prompt, sizeof (prompt), - _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s format, or (c)lear? "), - (msg->security & INLINE) ? _("PGP/M(i)ME") : _("(i)nline")); - - /* The keys accepted for this prompt *must* match the order in the second - * version in the else clause since the switch statement below depends on - * it. The 'i' key is appended in this version. - */ - choice = mutt_multi_choice (prompt, _("esabfci")); + snprintf (promptbuf, sizeof (promptbuf), + _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s format, (c)lear, or (o)ppenc mode? "), + (msg->security & INLINE) ? _("PGP/M(i)ME") : _("(i)nline")); + prompt = promptbuf; + letters = _("esabfcoi"); + choices = "esabfcOi"; + } + else + { + prompt = _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, (c)lear, or (o)ppenc mode? "); + letters = _("esabfco"); + choices = "esabfcO"; + } } + /* + * Opportunistic encryption is unset + */ else { - /* The keys accepted *must* be a prefix of the accepted keys in the "if" - * clause above since the switch statement below depends on it. - */ - choice = mutt_multi_choice(_("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, or (c)lear? "), - _("esabfc")); + if (msg->security & (ENCRYPT | SIGN)) + { + + snprintf (promptbuf, sizeof (promptbuf), + _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s format, or (c)lear? "), + (msg->security & INLINE) ? _("PGP/M(i)ME") : _("(i)nline")); + prompt = promptbuf; + letters = _("esabfci"); + choices = "esabfci"; + } + else + { + prompt = _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, or (c)lear? "); + letters = _("esabfc"); + choices = "esabfc"; + } } - switch (choice) + choice = mutt_multi_choice (prompt, letters); + if (choice > 0) { - case 1: /* (e)ncrypt */ + switch (choices[choice - 1]) + { + case 'e': /* (e)ncrypt */ msg->security |= ENCRYPT; msg->security &= ~SIGN; break; - case 2: /* (s)ign */ - msg->security |= SIGN; - msg->security &= ~ENCRYPT; - break; + case 's': /* (s)ign */ + msg->security &= ~ENCRYPT; + msg->security |= SIGN; + break; - case 3: /* sign (a)s */ - { - pgp_key_t p; - char input_signas[SHORT_STRING]; + case 'S': /* (s)ign in oppenc mode */ + msg->security |= SIGN; + break; + case 'a': /* sign (a)s */ unset_option(OPTPGPCHECKTRUST); if ((p = pgp_ask_for_key (_("Sign as: "), NULL, 0, PGP_SECRING))) { - snprintf (input_signas, sizeof (input_signas), "0x%s", - pgp_keyid (p)); - mutt_str_replace (&PgpSignAs, input_signas); - pgp_free_key (&p); + snprintf (input_signas, sizeof (input_signas), "0x%s", + pgp_keyid (p)); + mutt_str_replace (&PgpSignAs, input_signas); + pgp_free_key (&p); - msg->security |= SIGN; + msg->security |= SIGN; - crypt_pgp_void_passphrase (); /* probably need a different passphrase */ + crypt_pgp_void_passphrase (); /* probably need a different passphrase */ } -#if 0 - else - { - msg->security &= ~SIGN; - } -#endif + *redraw = REDRAW_FULL; + break; - *redraw = REDRAW_FULL; - } break; + case 'b': /* (b)oth */ + msg->security |= (ENCRYPT | SIGN); + break; - case 4: /* (b)oth */ - msg->security |= (ENCRYPT | SIGN); - break; + case 'f': /* (f)orget it */ + case 'c': /* (c)lear */ + msg->security &= ~(ENCRYPT | SIGN); + break; - case 5: /* (f)orget it */ - case 6: /* (c)lear */ - msg->security = 0; - break; + case 'F': /* (f)orget it or (c)lear in oppenc mode */ + case 'C': + msg->security &= ~SIGN; + break; - case 7: /* toggle (i)nline */ - msg->security ^= INLINE; - break; - } + case 'O': /* oppenc mode on */ + msg->security |= OPPENCRYPT; + crypt_opportunistic_encrypt (msg); + break; - if (msg->security) - { - if (! (msg->security & (ENCRYPT | SIGN))) - msg->security = 0; - else - msg->security |= APPLICATION_PGP; + case 'o': /* oppenc mode off */ + msg->security &= ~OPPENCRYPT; + break; + + case 'i': /* toggle (i)nline */ + msg->security ^= INLINE; + break; + } } return (msg->security); } #endif /* CRYPT_BACKEND_CLASSIC_PGP */ diff --git a/smime.c b/smime.c --- a/smime.c +++ b/smime.c @@ -1903,144 +1903,186 @@ int smime_application_smime_handler (BODY *m, STATE *s) { return smime_handle_entity (m, s, NULL) ? 0 : -1; } int smime_send_menu (HEADER *msg, int *redraw) { char *p; + char *prompt, *letters, *choices; + int choice; if (!(WithCrypto & APPLICATION_SMIME)) return msg->security; - switch (mutt_multi_choice (_("S/MIME (e)ncrypt, (s)ign, encrypt (w)ith, sign (a)s, (b)oth, or (c)lear? "), - _("eswabfc"))) + msg->security |= APPLICATION_SMIME; + + /* + * Opportunistic encrypt is controlling encryption. + * NOTE: "Signing" and "Clearing" only adjust the sign bit, so we have different + * letter choices for those. + */ + if (option (OPTCRYPTOPPORTUNISTICENCRYPT) && (msg->security & OPPENCRYPT)) { - case 1: /* (e)ncrypt */ - msg->security |= ENCRYPT; - msg->security &= ~SIGN; - break; + prompt = _("S/MIME (s)ign, encrypt (w)ith, sign (a)s, (c)lear, or (o)ppenc mode off? "); + letters = _("swafco"); + choices = "SwaFCo"; + } + /* + * Opportunistic encryption option is set, but is toggled off + * for this message. + */ + else if (option (OPTCRYPTOPPORTUNISTICENCRYPT)) + { + prompt = _("S/MIME (e)ncrypt, (s)ign, encrypt (w)ith, sign (a)s, (b)oth, (c)lear, or (o)ppenc mode? "); + letters = _("eswabfco"); + choices = "eswabfcO"; + } + /* + * Opportunistic encryption is unset + */ + else + { + prompt = _("S/MIME (e)ncrypt, (s)ign, encrypt (w)ith, sign (a)s, (b)oth, or (c)lear? "); + letters = _("eswabfc"); + choices = "eswabfc"; + } - case 3: /* encrypt (w)ith */ + + choice = mutt_multi_choice (prompt, letters); + if (choice > 0) + { + switch (choices[choice - 1]) { - int choice = 0; + case 'e': /* (e)ncrypt */ + msg->security |= ENCRYPT; + msg->security &= ~SIGN; + break; - msg->security |= ENCRYPT; - do + case 'w': /* encrypt (w)ith */ { - /* I use "dra" because "123" is recognized anyway */ - switch (mutt_multi_choice (_("Choose algorithm family:" - " 1: DES, 2: RC2, 3: AES," - " or (c)lear? "), - _("drac"))) + msg->security |= ENCRYPT; + do { - case 1: - switch (choice = mutt_multi_choice (_("1: DES, 2: Triple-DES "), - _("dt"))) + /* I use "dra" because "123" is recognized anyway */ + switch (mutt_multi_choice (_("Choose algorithm family:" + " 1: DES, 2: RC2, 3: AES," + " or (c)lear? "), + _("drac"))) { case 1: - mutt_str_replace (&SmimeCryptAlg, "des"); + switch (choice = mutt_multi_choice (_("1: DES, 2: Triple-DES "), + _("dt"))) + { + case 1: + mutt_str_replace (&SmimeCryptAlg, "des"); + break; + case 2: + mutt_str_replace (&SmimeCryptAlg, "des3"); + break; + } break; + case 2: - mutt_str_replace (&SmimeCryptAlg, "des3"); + switch (choice = mutt_multi_choice (_("1: RC2-40, 2: RC2-64, 3: RC2-128 "), + _("468"))) + { + case 1: + mutt_str_replace (&SmimeCryptAlg, "rc2-40"); + break; + case 2: + mutt_str_replace (&SmimeCryptAlg, "rc2-64"); + break; + case 3: + mutt_str_replace (&SmimeCryptAlg, "rc2-128"); + break; + } + break; + + case 3: + switch (choice = mutt_multi_choice (_("1: AES128, 2: AES192, 3: AES256 "), + _("895"))) + { + case 1: + mutt_str_replace (&SmimeCryptAlg, "aes128"); + break; + case 2: + mutt_str_replace (&SmimeCryptAlg, "aes192"); + break; + case 3: + mutt_str_replace (&SmimeCryptAlg, "aes256"); + break; + } + break; + + case 4: /* (c)lear */ + FREE (&SmimeCryptAlg); + /* fallback */ + case -1: /* Ctrl-G or Enter */ + choice = 0; break; } + } while (choice == -1); + } + break; + + case 's': /* (s)ign */ + case 'S': /* (s)ign in oppenc mode */ + if(!SmimeDefaultKey) + { + *redraw = REDRAW_FULL; + + if ((p = smime_ask_for_key (_("Sign as: "), NULL, 0))) + mutt_str_replace (&SmimeDefaultKey, p); + else break; + } + if (choices[choice - 1] == 's') + msg->security &= ~ENCRYPT; + msg->security |= SIGN; + break; - case 2: - switch (choice = mutt_multi_choice (_("1: RC2-40, 2: RC2-64, 3: RC2-128 "), - _("468"))) - { - case 1: - mutt_str_replace (&SmimeCryptAlg, "rc2-40"); - break; - case 2: - mutt_str_replace (&SmimeCryptAlg, "rc2-64"); - break; - case 3: - mutt_str_replace (&SmimeCryptAlg, "rc2-128"); - break; - } - break; + case 'a': /* sign (a)s */ - case 3: - switch (choice = mutt_multi_choice (_("1: AES128, 2: AES192, 3: AES256 "), - _("895"))) - { - case 1: - mutt_str_replace (&SmimeCryptAlg, "aes128"); - break; - case 2: - mutt_str_replace (&SmimeCryptAlg, "aes192"); - break; - case 3: - mutt_str_replace (&SmimeCryptAlg, "aes256"); - break; - } - break; + if ((p = smime_ask_for_key (_("Sign as: "), NULL, 0))) + { + mutt_str_replace (&SmimeDefaultKey, p); + + msg->security |= SIGN; - case 4: /* (c)lear */ - FREE (&SmimeCryptAlg); - /* fallback */ - case -1: /* Ctrl-G or Enter */ - choice = 0; - break; - } - } while (choice == -1); + /* probably need a different passphrase */ + crypt_smime_void_passphrase (); + } + + *redraw = REDRAW_FULL; + break; + + case 'b': /* (b)oth */ + msg->security |= (ENCRYPT | SIGN); + break; + + case 'f': /* (f)orget it */ + case 'c': /* (c)lear */ + msg->security &= ~(ENCRYPT | SIGN); + break; + + case 'F': /* (f)orget it or (c)lear in oppenc mode */ + case 'C': + msg->security &= ~SIGN; + break; + + case 'O': /* oppenc mode on */ + msg->security |= OPPENCRYPT; + crypt_opportunistic_encrypt (msg); + break; + + case 'o': /* oppenc mode off */ + msg->security &= ~OPPENCRYPT; + break; } - break; - - case 2: /* (s)ign */ - - if(!SmimeDefaultKey) - { - *redraw = REDRAW_FULL; - - if ((p = smime_ask_for_key (_("Sign as: "), NULL, 0))) - mutt_str_replace (&SmimeDefaultKey, p); - else - break; - } - - msg->security |= SIGN; - msg->security &= ~ENCRYPT; - break; - - case 4: /* sign (a)s */ - - if ((p = smime_ask_for_key (_("Sign as: "), NULL, 0))) - { - mutt_str_replace (&SmimeDefaultKey, p); - - msg->security |= SIGN; - - /* probably need a different passphrase */ - crypt_smime_void_passphrase (); - } -#if 0 - else - msg->security &= ~SIGN; -#endif - - *redraw = REDRAW_FULL; - break; - - case 5: /* (b)oth */ - msg->security |= (ENCRYPT | SIGN); - break; - - case 6: /* (f)orget it */ - case 7: /* (c)lear */ - msg->security = 0; - break; } - if (msg->security && msg->security != APPLICATION_SMIME) - msg->security |= APPLICATION_SMIME; - else - msg->security = 0; - return (msg->security); } #endif /* CRYPT_BACKEND_CLASSIC_SMIME */