From: Pierre Habouzit Date: Mon, 2 Apr 2007 23:36:25 +0000 (+0200) Subject: take more cruft to the bin X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=commitdiff_plain;h=64a23f5574b096605383ef1886c7d0d6c42aeeee take more cruft to the bin Signed-off-by: Pierre Habouzit --- diff --git a/OPS b/OPS index 10fe828..cacf0c5 100644 --- a/OPS +++ b/OPS @@ -213,7 +213,6 @@ OP_CHECK_TRADITIONAL "check for classic pgp" OP_COMPOSE_SMIME_MENU "show S/MIME options" OP_DECRYPT_SAVE "make decrypted copy and delete" OP_DECRYPT_COPY "make decrypted copy" -OP_FORGET_PASSPHRASE "wipe passphrase(s) from memory" OP_EXTRACT_KEYS "extract supported public keys" OP_MIX_USE "Accept the chain constructed" OP_MIX_APPEND "Append a remailer to the chain" diff --git a/functions.def b/functions.def index e1fd6dd..59ad2f9 100644 --- a/functions.def +++ b/functions.def @@ -182,7 +182,6 @@ LIST(OpMain) ITEM("extract-keys", OP_EXTRACT_KEYS, "\013") - ITEM("forget-passphrase", OP_FORGET_PASSPHRASE, "\006") ITEM("check-traditional-pgp", OP_CHECK_TRADITIONAL, "\033P") ITEM("mail-key", OP_MAIL_KEY, "\033k") ITEM("decrypt-copy", OP_DECRYPT_COPY, NULL) @@ -291,7 +290,6 @@ LIST(OpPager) ITEM("check-traditional-pgp", OP_CHECK_TRADITIONAL, "\033P") ITEM("mail-key", OP_MAIL_KEY, "\033k") ITEM("extract-keys", OP_EXTRACT_KEYS, "\013") - ITEM("forget-passphrase", OP_FORGET_PASSPHRASE, "\006") ITEM("decrypt-copy", OP_DECRYPT_COPY, NULL) ITEM("decrypt-save", OP_DECRYPT_SAVE, NULL) @@ -329,7 +327,6 @@ LIST(OpAttach) ITEM("check-traditional-pgp", OP_CHECK_TRADITIONAL, "\033P") ITEM("extract-keys", OP_EXTRACT_KEYS, "\013") - ITEM("forget-passphrase", OP_FORGET_PASSPHRASE, "\006") ENDLIST LIST(OpCompose) @@ -376,8 +373,6 @@ LIST(OpCompose) ITEM("attach-key", OP_COMPOSE_ATTACH_KEY, "\033k") ITEM("pgp-menu", OP_COMPOSE_PGP_MENU, "p") - ITEM("forget-passphrase", OP_FORGET_PASSPHRASE, "\006") - ITEM("smime-menu", OP_COMPOSE_SMIME_MENU, "S") #ifdef MIXMASTER diff --git a/init.h b/init.h index fbae7da..df18efe 100644 --- a/init.h +++ b/init.h @@ -1725,46 +1725,6 @@ struct option_t MuttVars[] = { ** removed, while the inner multipart/signed part is retained. ** (PGP only) */ - {"pgp_autoinline", DT_BOOL, R_NONE, OPTPGPAUTOINLINE, "no" }, - /* - ** .pp - ** This option controls whether Madmutt generates old-style inline - ** (traditional) PGP encrypted or signed messages under certain - ** circumstances. This can be overridden by use of the \fIpgp-menu\fP, - ** when inline is not required. - ** .pp - ** Note that Madmutt might automatically use PGP/MIME for messages - ** which consist of more than a single MIME part. Madmutt can be - ** configured to ask before sending PGP/MIME messages when inline - ** (traditional) would not work. - ** See also: ``$$pgp_mime_auto''. - ** .pp - ** Also note that using the old-style PGP message format is \fBstrongly\fP - ** \fBdeprecated\fP. - ** (PGP only) - */ - {"pgp_replyinline", DT_BOOL, R_NONE, OPTPGPREPLYINLINE, "no" }, - /* - ** .pp - ** Setting this variable will cause Madmutt to always attempt to - ** create an inline (traditional) message when replying to a - ** message which is PGP encrypted/signed inline. This can be - ** overridden by use of the \fIpgp-menu\fP, when inline is not - ** required. This option does not automatically detect if the - ** (replied-to) message is inline; instead it relies on Madmutt - ** internals for previously checked/flagged messages. - ** .pp - ** Note that Madmutt might automatically use PGP/MIME for messages - ** which consist of more than a single MIME part. Madmutt can be - ** configured to ask before sending PGP/MIME messages when inline - ** (traditional) would not work. - ** See also: ``$$pgp_mime_auto''. - ** .pp - ** Also note that using the old-style PGP message format is \fBstrongly\fP - ** \fBdeprecated\fP. - ** (PGP only) - ** - */ {"pgp_show_unusable", DT_BOOL, R_NONE, OPTPGPSHOWUNUSABLE, "yes" }, /* ** .pp @@ -1805,17 +1765,6 @@ struct option_t MuttVars[] = { ** ``reverse-''. ** (PGP only) */ - {"pgp_mime_auto", DT_QUAD, R_NONE, OPT_PGPMIMEAUTO, "ask-yes" }, - /* - ** .pp - ** This option controls whether Madmutt will prompt you for - ** automatically sending a (signed/encrypted) message using - ** PGP/MIME when inline (traditional) fails (for any reason). - ** .pp - ** Also note that using the old-style PGP message format is \fBstrongly\fP - ** \fBdeprecated\fP. - ** (PGP only) - */ {"pgp_auto_decode", DT_BOOL, R_NONE, OPTPGPAUTODEC, "no" }, /* ** .pp diff --git a/lib-crypt/Makefile.am b/lib-crypt/Makefile.am index a4d7298..e5af18b 100644 --- a/lib-crypt/Makefile.am +++ b/lib-crypt/Makefile.am @@ -1,8 +1,7 @@ noinst_LIBRARIES = libcrypt.a libcrypt_a_SOURCES = crypt.h crypt-gpgme.h \ - crypt.c crypt-gpgme.c \ - cryptglue.c + crypt.c crypt-gpgme.c cryptglue.c noinst_HEADERS = crypt.h crypt-gpgme.h diff --git a/lib-crypt/crypt-gpgme.c b/lib-crypt/crypt-gpgme.c index 70d0713..7b6787e 100644 --- a/lib-crypt/crypt-gpgme.c +++ b/lib-crypt/crypt-gpgme.c @@ -94,6 +94,28 @@ typedef struct crypt_entry { static struct crypt_cache *id_defaults = NULL; static gpgme_key_t signature_key = NULL; +/* Initialization. */ +void crypt_init(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); + } +} + +/* Show a message that a backend will be invoked. */ +void crypt_invoke_message (int type) +{ + if (type & APPLICATION_PGP) { + mutt_message _("Invoking PGP..."); + } + else if (type & APPLICATION_SMIME) { + mutt_message _("Invoking S/MIME..."); + } +} + /* * General helper functions. */ @@ -683,9 +705,7 @@ static void print_time (time_t t, STATE * s) state_attach_puts (p, s); } -/* - * Implementation of `sign_message'. - */ +/* Implementation of `sign_message'. */ /* Sign the MESSAGE in body A either using OpenPGP or S/MIME when USE_SMIME is passed as true. Returns the new body or NULL on @@ -779,12 +799,12 @@ static BODY *sign_message (BODY * a, int use_smime) } -BODY *pgp_gpgme_sign_message (BODY * a) +BODY *crypt_pgp_sign_message (BODY * a) { return sign_message (a, 0); } -BODY *smime_gpgme_sign_message (BODY * a) +BODY *crypt_smime_sign_message (BODY * a) { return sign_message (a, 1); } @@ -795,7 +815,7 @@ BODY *smime_gpgme_sign_message (BODY * a) /* Encrypt the mail body A to all keys given as space separated keyids or fingerprints in KEYLIST and return the encrypted body. */ -BODY *pgp_gpgme_encrypt_message (BODY * a, char *keylist, int sign) +BODY *crypt_pgp_encrypt_message (BODY * a, char *keylist, int sign) { char *outfile = NULL; BODY *t; @@ -896,9 +916,7 @@ BODY *smime_gpgme_build_smime_entity (BODY * a, char *keylist) } -/* - * Implementation of `verify_one'. - */ +/* Implementation of `verify_one'. */ /* Display the common attributes of the signature summary SUM. Return 1 if there is is a severe warning. @@ -1295,12 +1313,12 @@ static int verify_one (BODY * sigbdy, STATE * s, return badsig ? 1 : anywarn ? 2 : 0; } -int pgp_gpgme_verify_one (BODY * sigbdy, STATE * s, const char *tempfile) +int crypt_pgp_verify_one (BODY * sigbdy, STATE * s, const char *tempfile) { return verify_one (sigbdy, s, tempfile, 0); } -int smime_gpgme_verify_one (BODY * sigbdy, STATE * s, const char *tempfile) +int crypt_smime_verify_one (BODY * sigbdy, STATE * s, const char *tempfile) { return verify_one (sigbdy, s, tempfile, 1); } @@ -1445,7 +1463,7 @@ restart: /* Decrypt a PGP/MIME message in FPIN and B and return a new body and the stream in CUR and FPOUT. Returns 0 on success. */ -int pgp_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur) +int crypt_pgp_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur) { char tempfile[_POSIX_PATH_MAX]; STATE s; @@ -1483,7 +1501,7 @@ int pgp_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur) /* Decrypt a S/MIME message in FPIN and B and return a new body and the stream in CUR and FPOUT. Returns 0 on success. */ -int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, +int crypt_smime_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur) { char tempfile[_POSIX_PATH_MAX]; @@ -1656,14 +1674,14 @@ static int pgp_check_traditional_one_body (FILE * fp, BODY * b, return 1; } -int pgp_gpgme_check_traditional (FILE * fp, BODY * b, int tagged_only) +int crypt_pgp_check_traditional (FILE * fp, BODY * b, int tagged_only) { int rv = 0; int r; for (; b; b = b->next) { if (is_multipart (b)) - rv = (pgp_gpgme_check_traditional (fp, b->parts, tagged_only) || rv); + rv = (crypt_pgp_check_traditional (fp, b->parts, tagged_only) || rv); else if (b->type == TYPETEXT) { if ((r = mutt_is_application_pgp (b))) rv = (rv || r); @@ -1675,9 +1693,7 @@ int pgp_gpgme_check_traditional (FILE * fp, BODY * b, int tagged_only) } -/* - * Implementation of `application_handler'. - */ +/* Implementation of `application_handler'. */ /* Copy a clearsigned message, and strip the signature and PGP's @@ -1740,7 +1756,7 @@ static void copy_clearsigned (gpgme_data_t data, STATE * s, char *charset) /* Support for classic_application/pgp */ -int pgp_gpgme_application_handler (BODY * m, STATE * s) +int crypt_pgp_application_pgp_handler (BODY * m, STATE * s) { int needpass = -1, pgp_keyblock = 0; int clearsign = 0; @@ -2043,7 +2059,7 @@ int pgp_gpgme_encrypted_handler (BODY * a, STATE * s) } /* Support for application/smime */ -int smime_gpgme_application_handler (BODY * a, STATE * s) +int crypt_smime_application_smime_handler (BODY * a, STATE * s) { char tempfile[_POSIX_PATH_MAX]; FILE *fpout; @@ -2973,10 +2989,7 @@ leave: mutt_do_pager (cmd, tempfile, 0, NULL); } -/* - * Implementation of `findkeys'. - */ - +/* Implementation of `findkeys'. */ /* Convert string_list_t into a pattern string suitable to be passed to GPGME. We need to convert spaces in an item into a '+' and '%' into @@ -3716,40 +3729,16 @@ static char *find_keys (address_t * to, address_t * cc, address_t * bcc, return (keylist); } -char *pgp_gpgme_findkeys (address_t * to, address_t * cc, address_t * bcc) +char *crypt_pgp_findkeys (address_t * to, address_t * cc, address_t * bcc) { return find_keys (to, cc, bcc, APPLICATION_PGP); } -char *smime_gpgme_findkeys (address_t * to, address_t * cc, address_t * bcc) +char *crypt_smime_findkeys (address_t * to, address_t * cc, address_t * bcc) { return find_keys (to, cc, bcc, APPLICATION_SMIME); } -/* - * Implementation of `init'. - */ - -/* Initialization. */ -static void init_gpgme (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); - } -} - -void pgp_gpgme_init (void) -{ - init_gpgme (); -} - -void smime_gpgme_init (void) -{ -} - static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime) { crypt_key_t *p; @@ -3825,17 +3814,17 @@ static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime) return (msg->security); } -int pgp_gpgme_send_menu (HEADER * msg, int *redraw) +int crypt_pgp_send_menu(HEADER * msg, int *redraw) { - return gpgme_send_menu (msg, redraw, 0); + return gpgme_send_menu(msg, redraw, 0); } -int smime_gpgme_send_menu (HEADER * msg, int *redraw) +int crypt_smime_send_menu(HEADER * msg, int *redraw) { return gpgme_send_menu (msg, redraw, 1); } -static int verify_sender (HEADER * h, gpgme_protocol_t protocol __attribute__((unused))) +int crypt_smime_verify_sender (HEADER * h) { address_t *sender = NULL; unsigned int ret = 1; @@ -3880,14 +3869,9 @@ static int verify_sender (HEADER * h, gpgme_protocol_t protocol __attribute__((u return ret; } -int smime_gpgme_verify_sender (HEADER * h) +static void invoke_import(const char *fname, int smime) { - return verify_sender (h, GPGME_PROTOCOL_CMS); -} - -void pgp_gpgme_invoke_import(const char *fname) -{ - gpgme_ctx_t ctx = create_gpgme_context(0); + gpgme_ctx_t ctx = create_gpgme_context(smime); gpgme_data_t data; gpgme_error_t err; @@ -3911,6 +3895,16 @@ void pgp_gpgme_invoke_import(const char *fname) return; } +void crypt_pgp_invoke_import(const char *fname) +{ + invoke_import(fname, 0); +} + +void crypt_smime_invoke_import(const char *fname) +{ + invoke_import(fname, 1); +} + static void pgp_extract_keys_from_attachment (FILE * fp, BODY * top) { STATE s; @@ -3931,11 +3925,11 @@ static void pgp_extract_keys_from_attachment (FILE * fp, BODY * top) mutt_body_handler (top, &s); m_fclose(&tempfp); - pgp_gpgme_invoke_import(tempfname); + crypt_pgp_invoke_import(tempfname); mutt_unlink (tempfname); } -void pgp_gpgme_from_attachment_list (FILE * fp, int tag, BODY * top) +void crypt_pgp_extract_keys_from_attachment_list(FILE * fp, int tag, BODY * top) { mutt_endwin (NULL); set_option (OPTDONTHANDLEPGPKEYS); diff --git a/lib-crypt/crypt-gpgme.h b/lib-crypt/crypt-gpgme.h index 4fabd3c..4c4e021 100644 --- a/lib-crypt/crypt-gpgme.h +++ b/lib-crypt/crypt-gpgme.h @@ -15,120 +15,40 @@ /* {{{ cruft */ /* Type defintions for crypto module functions. */ -typedef int (*crypt_func_decrypt_mime_t) (FILE * a, FILE ** b, - BODY * c, BODY ** d); - -typedef int (*crypt_func_application_handler_t) (BODY * m, STATE * s); typedef int (*crypt_func_encrypted_handler_t) (BODY * m, STATE * s); typedef void (*crypt_func_pgp_invoke_getkeys_t) (address_t * addr); -typedef int (*crypt_func_pgp_check_traditional_t) (FILE * fp, BODY * b, - int tagged_only); -typedef BODY *(*crypt_func_pgp_traditional_encryptsign_t) (BODY * a, - int flags, - char *keylist); typedef BODY *(*crypt_func_pgp_make_key_attachment_t) (char *tempf); -typedef char *(*crypt_func_findkeys_t) (address_t * to, - address_t * cc, address_t * bcc); -typedef BODY *(*crypt_func_sign_message_t) (BODY * a); -typedef BODY *(*crypt_func_pgp_encrypt_message_t) (BODY * a, char *keylist, - int sign); -typedef void (*crypt_func_pgp_invoke_import_t) (const char *fname); -typedef int (*crypt_func_verify_one_t) (BODY * sigbdy, STATE * s, - const char *tempf); -typedef void (*crypt_func_pgp_extract_keys_from_attachment_list_t) - (FILE * fp, int tag, BODY * top); - typedef int (*crypt_func_send_menu_t) (HEADER * msg, int *redraw); /* (SMIME) */ typedef void (*crypt_func_smime_getkeys_t) (ENVELOPE * env); -typedef int (*crypt_func_smime_verify_sender_t) (HEADER * h); - typedef BODY *(*crypt_func_smime_build_smime_entity_t) (BODY * a, char *certlist); -typedef void (*crypt_func_smime_invoke_import_t) (char *infile, - char *mailbox); - -typedef void (*crypt_func_init_t) (void); - - typedef struct crypt_module_specs { /* Common/General functions. */ - crypt_func_init_t init; - crypt_func_decrypt_mime_t decrypt_mime; - crypt_func_application_handler_t application_handler; crypt_func_encrypted_handler_t encrypted_handler; - crypt_func_findkeys_t findkeys; - crypt_func_sign_message_t sign_message; - crypt_func_verify_one_t verify_one; - crypt_func_send_menu_t send_menu; /* PGP specific functions. */ - crypt_func_pgp_encrypt_message_t pgp_encrypt_message; crypt_func_pgp_make_key_attachment_t pgp_make_key_attachment; - crypt_func_pgp_check_traditional_t pgp_check_traditional; - crypt_func_pgp_traditional_encryptsign_t pgp_traditional_encryptsign; crypt_func_pgp_invoke_getkeys_t pgp_invoke_getkeys; - crypt_func_pgp_invoke_import_t pgp_invoke_import; - - crypt_func_pgp_extract_keys_from_attachment_list_t - pgp_extract_keys_from_attachment_list; /* S/MIME specific functions. */ - crypt_func_smime_getkeys_t smime_getkeys; - crypt_func_smime_verify_sender_t smime_verify_sender; crypt_func_smime_build_smime_entity_t smime_build_smime_entity; - crypt_func_smime_invoke_import_t smime_invoke_import; } crypt_module_specs_t; extern struct crypt_module_specs crypt_mod_SMIME_gpgme; extern struct crypt_module_specs crypt_mod_PGP_gpgme; -#define CRYPT_MOD_CALL_CHECK(identifier, func) \ - ((crypt_mod_##identifier##_gpgme).func) - -#define CRYPT_MOD_CALL(identifier, func) \ - (*((crypt_mod_##identifier##_gpgme).func)) - - /* }}} */ -void pgp_gpgme_init (void); -void smime_gpgme_init (void); - -char *pgp_gpgme_findkeys (address_t * to, address_t * cc, address_t * bcc); -char *smime_gpgme_findkeys (address_t * to, address_t * cc, address_t * bcc); - BODY *pgp_gpgme_encrypt_message (BODY * a, char *keylist, int sign); BODY *smime_gpgme_build_smime_entity (BODY * a, char *keylist); -int pgp_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, - BODY ** cur); -int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, - BODY ** cur); - int pgp_gpgme_check_traditional (FILE * fp, BODY * b, int tagged_only); - -int pgp_gpgme_application_handler (BODY * m, STATE * s); -int smime_gpgme_application_handler (BODY * a, STATE * s); int pgp_gpgme_encrypted_handler (BODY * a, STATE * s); - BODY *pgp_gpgme_make_key_attachment (char *tempf); -BODY *pgp_gpgme_sign_message (BODY * a); -BODY *smime_gpgme_sign_message (BODY * a); - -int pgp_gpgme_verify_one (BODY * sigbdy, STATE * s, const char *tempfile); -int smime_gpgme_verify_one (BODY * sigbdy, STATE * s, const char *tempfile); - -int smime_gpgme_verify_sender (HEADER* h); - -int pgp_gpgme_send_menu (HEADER * msg, int *redraw); -int smime_gpgme_send_menu (HEADER * msg, int *redraw); -void pgp_gpgme_invoke_import(const char *fname); -void pgp_gpgme_from_attachment_list (FILE * fp, int tag, BODY * top); - #endif diff --git a/lib-crypt/crypt.c b/lib-crypt/crypt.c index 8ccac11..730c455 100644 --- a/lib-crypt/crypt.c +++ b/lib-crypt/crypt.c @@ -30,7 +30,6 @@ #include "handler.h" #include "copy.h" #include "crypt.h" -#include "pgp.h" /* print the current time to avoid spoofing of the signature output */ void crypt_current_time (STATE * s, const char *app_name) @@ -52,51 +51,12 @@ void crypt_current_time (STATE * s, const char *app_name) state_attach_puts (tmp, s); } -#if defined(HAVE_SETRLIMIT) - -static void disable_coredumps (void) -{ - struct rlimit rl = { 0, 0 }; - static short done = 0; - - if (!done) { - setrlimit (RLIMIT_CORE, &rl); - done = 1; - } -} - -#endif /* HAVE_SETRLIMIT */ - int mutt_protect (HEADER * msg, char *keylist) { BODY *pbody = NULL, *tmp_pbody = NULL; BODY *tmp_smime_pbody = NULL; BODY *tmp_pgp_pbody = NULL; int flags = msg->security; - int i; - - if ((msg->security & PGPINLINE) == PGPINLINE) { - /* they really want to send it inline... go for it */ - if (!isendwin ()) - mutt_endwin _("Invoking PGP..."); - - pbody = crypt_pgp_traditional_encryptsign (msg->content, flags, keylist); - if (pbody) { - msg->content = pbody; - return 0; - } - - /* otherwise inline won't work...ask for revert */ - if ((i = query_quadoption(OPT_PGPMIMEAUTO, - _("Message can't be sent inline. Revert to using PGP/MIME?"))) - != M_YES) { - mutt_error _("Mail not sent."); - - return -1; - } - - /* go ahead with PGP/MIME */ - } if (!isendwin ()) mutt_endwin (NULL); @@ -290,7 +250,7 @@ void convert_to_7bit (BODY * a) void crypt_extract_keys_from_messages (HEADER * h) { int i; - char tempfname[_POSIX_PATH_MAX], *mbox; + char tempfname[_POSIX_PATH_MAX]; address_t *tmp = NULL; FILE *fpout; @@ -330,12 +290,9 @@ void crypt_extract_keys_from_messages (HEADER * h) else if (Context->hdrs[Context->v2r[i]]->env->sender) tmp = mutt_expand_aliases (Context->hdrs[Context->v2r[i]] ->env->sender); - mbox = tmp ? tmp->mailbox : NULL; - if (mbox) { - mutt_endwin (_("Trying to extract S/MIME certificates...\n")); - crypt_smime_invoke_import (tempfname, mbox); - tmp = NULL; - } + mutt_endwin (_("Trying to extract S/MIME certificates...\n")); + crypt_smime_invoke_import(tempfname); + tmp = NULL; } rewind (fpout); @@ -363,11 +320,8 @@ void crypt_extract_keys_from_messages (HEADER * h) tmp = mutt_expand_aliases (h->env->from); else if (h->env->sender) tmp = mutt_expand_aliases (h->env->sender); - mbox = tmp ? tmp->mailbox : NULL; - if (mbox) { /* else ? */ - mutt_message (_("Trying to extract S/MIME certificates...\n")); - crypt_smime_invoke_import (tempfname, mbox); - } + mutt_message (_("Trying to extract S/MIME certificates...\n")); + crypt_smime_invoke_import(tempfname); } } diff --git a/lib-crypt/crypt.h b/lib-crypt/crypt.h index 45cb952..06bfd1d 100644 --- a/lib-crypt/crypt.h +++ b/lib-crypt/crypt.h @@ -106,6 +106,13 @@ void crypt_extract_keys_from_messages (HEADER * h); Return the list of keys in KEYLIST. */ int crypt_get_keys (HEADER * msg, char **keylist); +/* Forget a passphrase and display a message. */ +void crypt_forget_passphrase (void); + +/* Check that we have a usable passphrase, ask if not. */ +int crypt_valid_passphrase (int); + + /*-- cryptglue.c --*/ /* Show a message that a backend will be invoked. */ @@ -130,9 +137,6 @@ pgp_key_t crypt_pgp_ask_for_key (char *tag, char *whatfor, /* Check for a traditional PGP message in body B. */ int crypt_pgp_check_traditional (FILE * fp, BODY * b, int tagged_only); -/* fixme: needs documentation. */ -BODY *crypt_pgp_traditional_encryptsign (BODY * a, int flags, char *keylist); - /* Release the PGP key KPP (note, that we pass a pointer to it). */ void crypt_pgp_free_key (pgp_key_t * kpp); @@ -192,7 +196,7 @@ BODY *crypt_smime_sign_message (BODY * a); BODY *crypt_smime_build_smime_entity (BODY * a, char *certlist); /* Add a certificate and update index file (externally). */ -void crypt_smime_invoke_import (char *infile, char *mailbox); +void crypt_smime_invoke_import(const char *infile); int crypt_smime_send_menu (HEADER * msg, int *redraw); diff --git a/lib-crypt/cryptglue.c b/lib-crypt/cryptglue.c index 904e4bb..c6b4e94 100644 --- a/lib-crypt/cryptglue.c +++ b/lib-crypt/cryptglue.c @@ -25,290 +25,75 @@ #include "crypt.h" #include "crypt-gpgme.h" +#define CRYPT_MOD_CALL_CHECK(identifier, func) \ + ((crypt_mod_##identifier##_gpgme).func) + +#define CRYPT_MOD_CALL(identifier, func) \ + (*((crypt_mod_##identifier##_gpgme).func)) + + struct crypt_module_specs crypt_mod_SMIME_gpgme = { - smime_gpgme_init, - smime_gpgme_decrypt_mime, - smime_gpgme_application_handler, NULL, /* encrypted_handler */ - smime_gpgme_findkeys, - smime_gpgme_sign_message, - smime_gpgme_verify_one, - smime_gpgme_send_menu, - NULL, /* pgp_encrypt_message */ NULL, /* pgp_make_key_attachment */ - NULL, /* pgp_check_traditional */ - NULL, /* pgp_traditional_encryptsign */ NULL, /* pgp_invoke_getkeys */ - NULL, /* pgp_invoke_import */ - NULL, /* pgp_extract_keys_from_attachment_list */ NULL, /* smime_getkeys */ - smime_gpgme_verify_sender, smime_gpgme_build_smime_entity, - NULL, /* smime_invoke_import */ }; struct crypt_module_specs crypt_mod_PGP_gpgme = { - pgp_gpgme_init, - pgp_gpgme_decrypt_mime, - pgp_gpgme_application_handler, pgp_gpgme_encrypted_handler, - pgp_gpgme_findkeys, - pgp_gpgme_sign_message, - pgp_gpgme_verify_one, - pgp_gpgme_send_menu, /* PGP specific. */ - pgp_gpgme_encrypt_message, NULL, /* pgp_make_key_attachment, */ - pgp_gpgme_check_traditional, - NULL, /* pgp_traditional_encryptsign */ NULL, /* pgp_invoke_getkeys */ - pgp_gpgme_invoke_import, /* pgp_invoke_import */ - pgp_gpgme_from_attachment_list, - /* pgp_extract_keys_from_attachment_list */ NULL, /* smime_getkeys */ - NULL, /* smime_verify_sender */ NULL, /* smime_build_smime_entity */ - NULL, /* smime_invoke_import */ }; -void crypt_init (void) -{ - (CRYPT_MOD_CALL(PGP, init))(); - (CRYPT_MOD_CALL(SMIME, init))(); -} - -/* Show a message that a backend will be invoked. */ -void crypt_invoke_message (int type) -{ - if (type & APPLICATION_PGP) { - mutt_message _("Invoking PGP..."); - } - else if (type & APPLICATION_SMIME) { - mutt_message _("Invoking S/MIME..."); - } -} - /* PGP */ -/* Decrypt a PGP/MIME message. */ -int crypt_pgp_decrypt_mime (FILE * a, FILE ** b, BODY * c, BODY ** d) -{ - if (CRYPT_MOD_CALL_CHECK (PGP, decrypt_mime)) - return (CRYPT_MOD_CALL (PGP, decrypt_mime)) (a, b, c, d); - - return -1; -} - -/* MIME handler for the application/pgp content-type. */ -int crypt_pgp_application_pgp_handler (BODY * m, STATE * s) -{ - if (CRYPT_MOD_CALL_CHECK (PGP, application_handler)) - return (CRYPT_MOD_CALL (PGP, application_handler)) (m, s); - return (-1); -} - /* MIME handler for an PGP/MIME encrypted message. */ int crypt_pgp_encrypted_handler (BODY * a, STATE * s) { - if (CRYPT_MOD_CALL_CHECK (PGP, encrypted_handler)) - return (CRYPT_MOD_CALL (PGP, encrypted_handler)) (a, s); - return (-1); + if (CRYPT_MOD_CALL_CHECK (PGP, encrypted_handler)) + return (CRYPT_MOD_CALL (PGP, encrypted_handler)) (a, s); + return (-1); } /* fixme: needs documentation. */ void crypt_pgp_invoke_getkeys (address_t * addr) { - if (CRYPT_MOD_CALL_CHECK (PGP, pgp_invoke_getkeys)) - (CRYPT_MOD_CALL (PGP, pgp_invoke_getkeys)) (addr); -} - -/* Check for a traditional PGP message in body B. */ -int crypt_pgp_check_traditional (FILE * fp, BODY * b, int tagged_only) -{ - if (CRYPT_MOD_CALL_CHECK (PGP, pgp_check_traditional)) - return (CRYPT_MOD_CALL (PGP, pgp_check_traditional)) (fp, b, tagged_only); - - return 0; -} - -/* fixme: needs documentation. */ -BODY *crypt_pgp_traditional_encryptsign (BODY * a, int flags, char *keylist) -{ - if (CRYPT_MOD_CALL_CHECK (PGP, pgp_traditional_encryptsign)) - return (CRYPT_MOD_CALL (PGP, pgp_traditional_encryptsign)) (a, flags, - keylist); - - return NULL; + if (CRYPT_MOD_CALL_CHECK (PGP, pgp_invoke_getkeys)) + (CRYPT_MOD_CALL (PGP, pgp_invoke_getkeys)) (addr); } /* Generate a PGP public key attachment. */ BODY *crypt_pgp_make_key_attachment (char *tempf) { - if (CRYPT_MOD_CALL_CHECK (PGP, pgp_make_key_attachment)) - return (CRYPT_MOD_CALL (PGP, pgp_make_key_attachment)) (tempf); - - return NULL; -} - -/* This routine attempts to find the keyids of the recipients of a - message. It returns NULL if any of the keys can not be found. */ -char *crypt_pgp_findkeys (address_t * to, address_t * cc, address_t * bcc) -{ - if (CRYPT_MOD_CALL_CHECK (PGP, findkeys)) - return (CRYPT_MOD_CALL (PGP, findkeys)) (to, cc, bcc); - - return NULL; -} - -/* Create a new body with a PGP signed message from A. */ -BODY *crypt_pgp_sign_message (BODY * a) -{ - if (CRYPT_MOD_CALL_CHECK (PGP, sign_message)) - return (CRYPT_MOD_CALL (PGP, sign_message)) (a); - - return NULL; -} - -/* Warning: A is no longer freed in this routine, you need to free it - later. This is necessary for $fcc_attach. */ -BODY *crypt_pgp_encrypt_message (BODY * a, char *keylist, int sign) -{ - if (CRYPT_MOD_CALL_CHECK (PGP, pgp_encrypt_message)) - return (CRYPT_MOD_CALL (PGP, pgp_encrypt_message)) (a, keylist, sign); + if (CRYPT_MOD_CALL_CHECK (PGP, pgp_make_key_attachment)) + return (CRYPT_MOD_CALL (PGP, pgp_make_key_attachment)) (tempf); - return NULL; + return NULL; } -/* Invoke the PGP command to import a key. */ -void crypt_pgp_invoke_import (const char *fname) -{ - if (CRYPT_MOD_CALL_CHECK (PGP, pgp_invoke_import)) - (CRYPT_MOD_CALL (PGP, pgp_invoke_import)) (fname); -} - -/* fixme: needs documentation */ -int crypt_pgp_verify_one (BODY * sigbdy, STATE * s, const char *tempf) -{ - if (CRYPT_MOD_CALL_CHECK (PGP, verify_one)) - return (CRYPT_MOD_CALL (PGP, verify_one)) (sigbdy, s, tempf); - - return -1; -} - - -int crypt_pgp_send_menu (HEADER * msg, int *redraw) -{ - if (CRYPT_MOD_CALL_CHECK (PGP, send_menu)) - return (CRYPT_MOD_CALL (PGP, send_menu)) (msg, redraw); - - return 0; -} - - -/* fixme: needs documentation */ -void crypt_pgp_extract_keys_from_attachment_list (FILE * fp, int tag, - BODY * top) -{ - if (CRYPT_MOD_CALL_CHECK (PGP, pgp_extract_keys_from_attachment_list)) - (CRYPT_MOD_CALL (PGP, pgp_extract_keys_from_attachment_list)) (fp, tag, - top); -} - - - -/* - - S/MIME - -*/ - - -/* Decrypt am S/MIME message. */ -int crypt_smime_decrypt_mime (FILE * a, FILE ** b, BODY * c, BODY ** d) -{ - if (CRYPT_MOD_CALL_CHECK (SMIME, decrypt_mime)) - return (CRYPT_MOD_CALL (SMIME, decrypt_mime)) (a, b, c, d); - - return -1; -} - -/* MIME handler for the application/smime content-type. */ -int crypt_smime_application_smime_handler (BODY * m, STATE * s) -{ - if (CRYPT_MOD_CALL_CHECK (SMIME, application_handler)) - return (CRYPT_MOD_CALL (SMIME, application_handler)) (m, s); - return (-1); -} +/* S/MIME */ /* fixme: Needs documentation. */ void crypt_smime_getkeys (ENVELOPE * env) { - if (CRYPT_MOD_CALL_CHECK (SMIME, smime_getkeys)) - (CRYPT_MOD_CALL (SMIME, smime_getkeys)) (env); -} - -/* Check that the sender matches. */ -int crypt_smime_verify_sender (HEADER * h) -{ - if (CRYPT_MOD_CALL_CHECK (SMIME, smime_verify_sender)) - return (CRYPT_MOD_CALL (SMIME, smime_verify_sender)) (h); - - return 1; -} - -/* This routine attempts to find the keyids of the recipients of a - message. It returns NULL if any of the keys can not be found. */ -char *crypt_smime_findkeys (address_t * to, address_t * cc, address_t * bcc) -{ - if (CRYPT_MOD_CALL_CHECK (SMIME, findkeys)) - return (CRYPT_MOD_CALL (SMIME, findkeys)) (to, cc, bcc); - - return NULL; -} - -/* fixme: Needs documentation. */ -BODY *crypt_smime_sign_message (BODY * a) -{ - if (CRYPT_MOD_CALL_CHECK (SMIME, sign_message)) - return (CRYPT_MOD_CALL (SMIME, sign_message)) (a); - - return NULL; + if (CRYPT_MOD_CALL_CHECK (SMIME, smime_getkeys)) + (CRYPT_MOD_CALL (SMIME, smime_getkeys)) (env); } /* fixme: needs documentation. */ BODY *crypt_smime_build_smime_entity (BODY * a, char *certlist) { - if (CRYPT_MOD_CALL_CHECK (SMIME, smime_build_smime_entity)) - return (CRYPT_MOD_CALL (SMIME, smime_build_smime_entity)) (a, certlist); - - return NULL; -} - -/* Add a certificate and update index file (externally). */ -void crypt_smime_invoke_import (char *infile, char *mailbox) -{ - if (CRYPT_MOD_CALL_CHECK (SMIME, smime_invoke_import)) - (CRYPT_MOD_CALL (SMIME, smime_invoke_import)) (infile, mailbox); -} - -/* fixme: needs documentation */ -int crypt_smime_verify_one (BODY * sigbdy, STATE * s, const char *tempf) -{ - if (CRYPT_MOD_CALL_CHECK (SMIME, verify_one)) - return (CRYPT_MOD_CALL (SMIME, verify_one)) (sigbdy, s, tempf); - - return -1; -} - -int crypt_smime_send_menu (HEADER * msg, int *redraw) -{ - if (CRYPT_MOD_CALL_CHECK (SMIME, send_menu)) - return (CRYPT_MOD_CALL (SMIME, send_menu)) (msg, redraw); + if (CRYPT_MOD_CALL_CHECK (SMIME, smime_build_smime_entity)) + return (CRYPT_MOD_CALL (SMIME, smime_build_smime_entity)) (a, certlist); - return 0; + return NULL; } diff --git a/lib-crypt/pgp.c b/lib-crypt/pgp.c deleted file mode 100644 index abab102..0000000 --- a/lib-crypt/pgp.c +++ /dev/null @@ -1,1457 +0,0 @@ -/* - * Copyright notice from original mutt: - * Copyright (C) 1996,1997 Michael R. Elkins - * Copyright (C) 1998,1999 Thomas Roessler - * Copyright (C) 2004 g10 Code GmbH - * - * This file is part of mutt-ng, see http://www.muttng.org/. - * It's licensed under the GNU General Public License, - * please see the file GPL in the top level source directory. - */ - -/* - * This file contains all of the PGP routines necessary to sign, encrypt, - * verify and decrypt PGP messages in either the new PGP/MIME format, or - * in the older Application/Pgp format. It also contains some code to - * cache the user's passphrase for repeat use when decrypting or signing - * a message. - */ - -#include - -#ifdef HAVE_SYS_RESOURCE_H -# include -#endif - -#include -#include - -#include -#include -#include -#include - -#include "handler.h" -#include "pgp.h" -#include "copy.h" -#include "attach.h" - -#include "crypt.h" - - -char PgpPass[LONG_STRING]; -time_t PgpExptime = 0; /* when does the cached passphrase expire? */ - -void pgp_void_passphrase (void) -{ - p_clear(PgpPass, countof(PgpPass)); - PgpExptime = 0; -} - -int pgp_valid_passphrase (void) -{ - time_t now = time (NULL); - - if (pgp_use_gpg_agent ()) { - *PgpPass = 0; - return 1; /* handled by gpg-agent */ - } - - if (now < PgpExptime) - /* Use cached copy. */ - return 1; - - pgp_void_passphrase (); - - if (mutt_get_field_unbuffered (_("Enter PGP passphrase:"), PgpPass, - sizeof (PgpPass), M_PASS) == 0) { - PgpExptime = time (NULL) + PgpTimeout; - return (1); - } - else - PgpExptime = 0; - - return 0; -} - -void pgp_forget_passphrase (void) -{ - pgp_void_passphrase (); - mutt_message _("PGP passphrase forgotten."); -} - -int pgp_use_gpg_agent (void) { - char *tty; - - if (!option (OPTUSEGPGAGENT) || !getenv ("GPG_AGENT_INFO")) - return 0; - - if ((tty = ttyname(0))) - setenv ("GPG_TTY", tty, 0); - - return 1; -} - -char *pgp_keyid (pgp_key_t k) -{ - if ((k->flags & KEYFLAG_SUBKEY) && k->parent && option (OPTPGPIGNORESUB)) - k = k->parent; - - return _pgp_keyid (k); -} - -char *_pgp_keyid (pgp_key_t k) -{ - if (option (OPTPGPLONGIDS)) - return k->keyid; - else - return (k->keyid + 8); -} - -/* ---------------------------------------------------------------------------- - * Routines for handing PGP input. - */ - - - -/* Copy PGP output messages and look for signs of a good signature */ - -static int pgp_copy_checksig (FILE * fpin, FILE * fpout) -{ - int rv = -1; - - if (PgpGoodSign.pattern) { - char *line = NULL; - int lineno = 0; - ssize_t linelen; - - while ((line = mutt_read_line (line, &linelen, fpin, &lineno)) != NULL) { - if (regexec (PgpGoodSign.rx, line, 0, NULL, 0) == 0) { - rv = 0; - } - - if (m_strncmp (line, "[GNUPG:] ", 9) == 0) - continue; - fputs (line, fpout); - fputc ('\n', fpout); - } - p_delete(&line); - } - else { - mutt_copy_stream (fpin, fpout); - rv = 1; - } - - return rv; -} - -/* - * Copy a clearsigned message, and strip the signature and PGP's - * dash-escaping. - * - * XXX - charset handling: We assume that it is safe to do - * character set decoding first, dash decoding second here, while - * we do it the other way around in the main handler. - * - * (Note that we aren't worse than Outlook &c in this, and also - * note that we can successfully handle anything produced by any - * existing versions of mutt.) - */ - -static void pgp_copy_clearsigned (FILE * fpin, STATE * s, char *charset) -{ - char buf[HUGE_STRING]; - short complete, armor_header; - - fgetconv_t *fc; - - rewind (fpin); - - fc = fgetconv_open (fpin, charset, MCharset.charset, M_ICONV_HOOK_FROM); - - for (complete = 1, armor_header = 1; - fgetconvs (buf, sizeof (buf), fc) != NULL; - complete = strchr (buf, '\n') != NULL) { - if (!complete) { - if (!armor_header) - state_puts (buf, s); - continue; - } - - if (m_strcmp(buf, "-----BEGIN PGP SIGNATURE-----\n") == 0) - break; - - if (armor_header) { - char *p = vskipspaces(buf); - - if (*p == '\0') - armor_header = 0; - continue; - } - - if (s->prefix) - state_puts (s->prefix, s); - - if (buf[0] == '-' && buf[1] == ' ') - state_puts (buf + 2, s); - else - state_puts (buf, s); - } - - fgetconv_close (&fc); -} - - -/* Support for the Application/PGP Content Type. */ - -int pgp_application_pgp_handler (BODY * m, STATE * s) -{ - int could_not_decrypt = 0; - int needpass = -1, pgp_keyblock = 0; - int c = 1; - int clearsign = 0, rv, rc; - long start_pos = 0; - long bytes; - off_t last_pos, offset; - char buf[HUGE_STRING]; - char outfile[_POSIX_PATH_MAX]; - char tmpfname[_POSIX_PATH_MAX]; - FILE *pgpout = NULL, *pgpin = NULL, *pgperr = NULL; - FILE *tmpfp = NULL; - pid_t thepid; - - short maybe_goodsig = 1; - short have_any_sigs = 0; - - char body_charset[STRING]; - - mutt_get_body_charset (body_charset, sizeof (body_charset), m); - - rc = 0; /* silence false compiler warning if (s->flags & M_DISPLAY) */ - - fseeko (s->fpin, m->offset, 0); - last_pos = m->offset; - - for (bytes = m->length; bytes > 0;) { - if (fgets (buf, sizeof (buf), s->fpin) == NULL) - break; - - offset = ftello (s->fpin); - bytes -= (offset - last_pos); /* don't rely on m_strlen(buf) */ - last_pos = offset; - - if (m_strncmp("-----BEGIN PGP ", buf, 15) == 0) { - clearsign = 0; - start_pos = last_pos; - - if (m_strcmp("MESSAGE-----\n", buf + 15) == 0) - needpass = 1; - else if (m_strcmp("SIGNED MESSAGE-----\n", buf + 15) == 0) { - clearsign = 1; - needpass = 0; - } - else if (!option (OPTDONTHANDLEPGPKEYS) && - m_strcmp("PUBLIC KEY BLOCK-----\n", buf + 15) == 0) { - needpass = 0; - pgp_keyblock = 1; - } - else { - /* XXX - we may wish to recode here */ - if (s->prefix) - state_puts (s->prefix, s); - state_puts (buf, s); - continue; - } - - have_any_sigs = have_any_sigs || (clearsign && (s->flags & M_VERIFY)); - - /* Copy PGP material to temporary file */ - tmpfp = m_tempfile(tmpfname, sizeof(tmpfname), NONULL(MCore.tmpdir), NULL); - if (tmpfp == NULL) { - mutt_perror (tmpfname); - return (-1); - } - - fputs (buf, tmpfp); - while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL) { - offset = ftello (s->fpin); - bytes -= (offset - last_pos); /* don't rely on m_strlen(buf) */ - last_pos = offset; - - fputs (buf, tmpfp); - - if ((needpass - && m_strcmp("-----END PGP MESSAGE-----\n", buf) == 0) - || (!needpass - && (m_strcmp("-----END PGP SIGNATURE-----\n", buf) == 0 - || m_strcmp("-----END PGP PUBLIC KEY BLOCK-----\n", - buf) == 0))) - break; - } - - /* leave tmpfp open in case we still need it - but flush it! */ - fflush (tmpfp); - - - /* Invoke PGP if needed */ - if (!clearsign || (s->flags & M_VERIFY)) { - pgpout = m_tempfile(outfile, sizeof(outfile), NONULL(MCore.tmpdir), NULL); - if (pgpout == NULL) { - mutt_perror (outfile); - return (-1); - } - - if ((thepid = pgp_invoke_decode (&pgpin, NULL, &pgperr, -1, - fileno (pgpout), -1, tmpfname, - needpass)) == -1) { - m_fclose(&pgpout); - maybe_goodsig = 0; - pgpin = NULL; - pgperr = NULL; - state_attach_puts (_ - ("[-- Error: unable to create PGP subprocess! --]\n"), - s); - } - else { /* PGP started successfully */ - - if (needpass) { - if (!pgp_valid_passphrase ()) - pgp_void_passphrase (); - if (pgp_use_gpg_agent ()) - *PgpPass = 0; - fprintf (pgpin, "%s\n", PgpPass); - } - - m_fclose(&pgpin); - - if (s->flags & M_DISPLAY) { - crypt_current_time (s, "PGP"); - rc = pgp_copy_checksig (pgperr, s->fpout); - } - - m_fclose(&pgperr); - rv = mutt_wait_filter (thepid); - - if (s->flags & M_DISPLAY) { - if (rc == 0) - have_any_sigs = 1; - - /* - * Sig is bad if - * gpg_good_sign-pattern did not match || pgp_decode_command returned not 0 - * Sig _is_ correct if - * gpg_good_sign="" && pgp_decode_command returned 0 - */ - if (rc == -1 || rv) - maybe_goodsig = 0; - - state_attach_puts (_("[-- End of PGP output --]\n\n"), s); - } - } - - /* treat empty result as sign of failure */ - /* TODO: maybe on failure mutt should include the original undecoded text. */ - if (pgpout) { - rewind (pgpout); - c = fgetc (pgpout); - ungetc (c, pgpout); - } - if (!clearsign && (!pgpout || c == EOF)) { - could_not_decrypt = 1; - pgp_void_passphrase (); - } - - if (could_not_decrypt && !(s->flags & M_DISPLAY)) { - mutt_error _("Could not decrypt PGP message"); - mutt_sleep (1); - rc = -1; - goto out; - } - } - - /* - * Now, copy cleartext to the screen. NOTE - we expect that PGP - * outputs utf-8 cleartext. This may not always be true, but it - * seems to be a reasonable guess. - */ - - if (s->flags & M_DISPLAY) { - if (needpass) - state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s); - else if (pgp_keyblock) - state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), s); - else - state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), s); - } - - if (clearsign) { - rewind (tmpfp); - if (tmpfp) - pgp_copy_clearsigned (tmpfp, s, body_charset); - } - else if (pgpout) { - fgetconv_t *fc; - - rewind (pgpout); - state_set_prefix (s); - fc = fgetconv_open (pgpout, "utf-8", MCharset.charset, 0); - while ((c = fgetconv (fc)) != EOF) - state_prefix_putc (c, s); - fgetconv_close (&fc); - } - - if (s->flags & M_DISPLAY) { - state_putc ('\n', s); - if (needpass) { - state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s); - if (could_not_decrypt) - mutt_error _("Could not decrypt PGP message."); - else - mutt_message _("PGP message successfully decrypted."); - } - else if (pgp_keyblock) - state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s); - else - state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s); - } - - } - else { - /* XXX - we may wish to recode here */ - if (s->prefix) - state_puts (s->prefix, s); - state_puts (buf, s); - } - } - - rc = 0; - -out: - m->goodsig = (maybe_goodsig && have_any_sigs); - - if (tmpfp) { - m_fclose(&tmpfp); - mutt_unlink (tmpfname); - } - if (pgpout) { - m_fclose(&pgpout); - mutt_unlink (outfile); - } - - if (needpass == -1) { - state_attach_puts (_ - ("[-- Error: could not find beginning of PGP message! --]\n\n"), - s); - return (-1); - } - - return (rc); -} - -static int pgp_check_traditional_one_body (FILE * fp, BODY * b, - int tagged_only) -{ - char tempfile[_POSIX_PATH_MAX]; - char buf[HUGE_STRING]; - FILE *tfp; - int tempfd; - - short sgn = 0; - short enc = 0; - short key = 0; - - if (b->type != TYPETEXT) - return 0; - - if (tagged_only && !b->tagged) - return 0; - - tempfd = m_tempfd(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); - if (mutt_decode_save_attachment (fp, b, tempfd, 0) != 0) { - unlink (tempfile); - return 0; - } - - if (!(tfp = fopen(tempfile, "r"))) { - unlink(tempfile); - return 0; - } - - while (fgets (buf, sizeof (buf), tfp)) { - if (m_strncmp("-----BEGIN PGP ", buf, 15) == 0) { - if (m_strcmp("MESSAGE-----\n", buf + 15) == 0) - enc = 1; - else if (m_strcmp("SIGNED MESSAGE-----\n", buf + 15) == 0) - sgn = 1; - else if (m_strcmp("PUBLIC KEY BLOCK-----\n", buf + 15) == 0) - key = 1; - } - } - m_fclose(&tfp); - unlink (tempfile); - - if (!enc && !sgn && !key) - return 0; - - /* fix the content type */ - - parameter_setval(&b->parameter, "format", "fixed"); - if (enc) - parameter_setval(&b->parameter, "x-action", "pgp-encrypted"); - else if (sgn) - parameter_setval(&b->parameter, "x-action", "pgp-signed"); - else if (key) - parameter_setval(&b->parameter, "x-action", "pgp-keys"); - - return 1; -} - -int pgp_check_traditional (FILE * fp, BODY * b, int tagged_only) -{ - int rv = 0; - int r; - - for (; b; b = b->next) { - if (is_multipart (b)) - rv = pgp_check_traditional (fp, b->parts, tagged_only) || rv; - else if (b->type == TYPETEXT) { - if ((r = mutt_is_application_pgp (b))) - rv = rv || r; - else - rv = pgp_check_traditional_one_body (fp, b, tagged_only) || rv; - } - } - - return rv; -} - - - - - -int pgp_verify_one (BODY * sigbdy, STATE * s, const char *tempfile) -{ - char sigfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX]; - FILE *fp, *pgpout, *pgperr; - pid_t thepid; - int badsig = -1; - int rv; - - snprintf (sigfile, sizeof (sigfile), "%s.asc", tempfile); - - if (!(fp = safe_fopen (sigfile, "w"))) { - mutt_perror (sigfile); - return -1; - } - - fseeko (s->fpin, sigbdy->offset, 0); - mutt_copy_bytes (s->fpin, fp, sigbdy->length); - m_fclose(&fp); - - pgperr = m_tempfile(pgperrfile, sizeof(pgperrfile), NONULL(MCore.tmpdir), NULL); - if (pgperr == NULL) { - mutt_perror (pgperrfile); - unlink (sigfile); - return -1; - } - - crypt_current_time (s, "PGP"); - - if ((thepid = pgp_invoke_verify (NULL, &pgpout, NULL, - -1, -1, fileno (pgperr), - tempfile, sigfile)) != -1) { - if (pgp_copy_checksig (pgpout, s->fpout) >= 0) - badsig = 0; - - - m_fclose(&pgpout); - fflush (pgperr); - rewind (pgperr); - - if (pgp_copy_checksig (pgperr, s->fpout) >= 0) - badsig = 0; - - if ((rv = mutt_wait_filter (thepid))) - badsig = -1; - } - - m_fclose(&pgperr); - - state_attach_puts (_("[-- End of PGP output --]\n\n"), s); - - mutt_unlink (sigfile); - mutt_unlink (pgperrfile); - - return badsig; -} - - -/* Extract pgp public keys from messages or attachments */ - -static void pgp_extract_keys_from_attachment (FILE * fp, BODY * top) -{ - STATE s; - FILE *tempfp; - char tempfname[_POSIX_PATH_MAX]; - - tempfp = m_tempfile(tempfname, sizeof(tempfname), NONULL(MCore.tmpdir), NULL); - if (tempfp == NULL) { - mutt_perror (_("Can't create temporary file")); - return; - } - - p_clear(&s, 1); - - s.fpin = fp; - s.fpout = tempfp; - - mutt_body_handler (top, &s); - - m_fclose(&tempfp); - - pgp_invoke_import (tempfname); - mutt_any_key_to_continue (NULL); - - mutt_unlink (tempfname); -} - -void pgp_extract_keys_from_attachment_list (FILE * fp, int tag, BODY * top) -{ - if (!fp) { - mutt_error _("Internal error. Inform ."); - - return; - } - - mutt_endwin (NULL); - set_option (OPTDONTHANDLEPGPKEYS); - - for (; top; top = top->next) { - if (!tag || top->tagged) - pgp_extract_keys_from_attachment (fp, top); - - if (!tag) - break; - } - - unset_option (OPTDONTHANDLEPGPKEYS); -} - -BODY *pgp_decrypt_part (BODY * a, STATE * s, FILE * fpout, BODY * p) -{ - char buf[LONG_STRING]; - FILE *pgpin, *pgpout, *pgperr, *pgptmp; - struct stat info; - BODY *tattach; - int len; - char pgperrfile[_POSIX_PATH_MAX]; - char pgptmpfile[_POSIX_PATH_MAX]; - pid_t thepid; - int rv; - - pgperr = m_tempfile(pgperrfile, sizeof(pgperrfile), NONULL(MCore.tmpdir), NULL); - if (!pgperr) { - mutt_perror (pgperrfile); - return NULL; - } - unlink (pgperrfile); - - pgptmp = m_tempfile(pgptmpfile, sizeof(pgptmpfile), NONULL(MCore.tmpdir), NULL); - if (!pgptmp) { - mutt_perror (pgptmpfile); - m_fclose(&pgperr); - return NULL; - } - - /* Position the stream at the beginning of the body, and send the data to - * the temporary file. - */ - - fseeko (s->fpin, a->offset, 0); - mutt_copy_bytes (s->fpin, pgptmp, a->length); - m_fclose(&pgptmp); - - if ((thepid = pgp_invoke_decrypt (&pgpin, &pgpout, NULL, -1, -1, - fileno (pgperr), pgptmpfile)) == -1) { - m_fclose(&pgperr); - unlink (pgptmpfile); - if (s->flags & M_DISPLAY) - state_attach_puts (_ - ("[-- Error: could not create a PGP subprocess! --]\n\n"), - s); - return (NULL); - } - - /* send the PGP passphrase to the subprocess. Never do this if the - agent is active, because this might lead to a passphrase send as - the message. */ - if (!pgp_use_gpg_agent ()) - fputs (PgpPass, pgpin); - fputc ('\n', pgpin); - m_fclose(&pgpin); - - /* Read the output from PGP, and make sure to change CRLF to LF, otherwise - * read_mime_header has a hard time parsing the message. - */ - while (fgets (buf, sizeof (buf) - 1, pgpout) != NULL) { - len = m_strlen(buf); - if (len > 1 && buf[len - 2] == '\r') - m_strcpy(buf + len - 2, len - 2, "\n"); - fputs (buf, fpout); - } - - m_fclose(&pgpout); - rv = mutt_wait_filter (thepid); - mutt_unlink (pgptmpfile); - - if (s->flags & M_DISPLAY) { - fflush (pgperr); - rewind (pgperr); - if (pgp_copy_checksig (pgperr, s->fpout) == 0 && !rv && p) - p->goodsig = 1; - else - p->goodsig = 0; - state_attach_puts (_("[-- End of PGP output --]\n\n"), s); - } - m_fclose(&pgperr); - - fflush (fpout); - rewind (fpout); - - if (fgetc (fpout) == EOF) { - mutt_error (_("Decryption failed.")); - pgp_void_passphrase (); - return NULL; - } - - rewind (fpout); - - if ((tattach = mutt_read_mime_header (fpout, 0)) != NULL) { - /* - * Need to set the length of this body part. - */ - fstat (fileno (fpout), &info); - tattach->length = info.st_size - tattach->offset; - - /* See if we need to recurse on this MIME part. */ - - mutt_parse_part (fpout, tattach); - } - - return (tattach); -} - -int pgp_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur) -{ - char tempfile[_POSIX_PATH_MAX]; - STATE s; - BODY *p = b; - - if (!mutt_is_multipart_encrypted (b)) - return -1; - - if (!b->parts || !b->parts->next) - return -1; - - b = b->parts->next; - - p_clear(&s, 1); - s.fpin = fpin; - *fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); - if (*fpout == NULL) { - mutt_perror (_("Can't create temporary file")); - return (-1); - } - unlink (tempfile); - - *cur = pgp_decrypt_part (b, &s, *fpout, p); - - rewind (*fpout); - - if (!*cur) - return -1; - - return (0); -} - -int pgp_encrypted_handler (BODY * a, STATE * s) -{ - char tempfile[_POSIX_PATH_MAX]; - FILE *fpout, *fpin; - BODY *tattach; - BODY *p = a; - int rc = 0; - - a = a->parts; - if (!a || a->type != TYPEAPPLICATION || !a->subtype || - ascii_strcasecmp ("pgp-encrypted", a->subtype) != 0 || - !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype || - ascii_strcasecmp ("octet-stream", a->next->subtype) != 0) { - if (s->flags & M_DISPLAY) - state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"), - s); - return (-1); - } - - /* - * Move forward to the application/pgp-encrypted body. - */ - a = a->next; - - fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); - if (fpout == NULL) { - if (s->flags & M_DISPLAY) - state_attach_puts (_ - ("[-- Error: could not create temporary file! --]\n"), - s); - return (-1); - } - - if (s->flags & M_DISPLAY) - crypt_current_time (s, "PGP"); - - if ((tattach = pgp_decrypt_part (a, s, fpout, p)) != NULL) { - if (s->flags & M_DISPLAY) - state_attach_puts (_ - ("[-- The following data is PGP/MIME encrypted --]\n\n"), - s); - - fpin = s->fpin; - s->fpin = fpout; - rc = mutt_body_handler (tattach, s); - s->fpin = fpin; - - /* - * if a multipart/signed is the _only_ sub-part of a - * multipart/encrypted, cache signature verification - * status. - * - */ - - if (mutt_is_multipart_signed (tattach) && !tattach->next) - p->goodsig |= tattach->goodsig; - - if (s->flags & M_DISPLAY) { - state_puts ("\n", s); - state_attach_puts (_("[-- End of PGP/MIME encrypted data --]\n"), s); - } - - body_list_wipe(&tattach); - /* clear 'Invoking...' message, since there's no error */ - mutt_message _("PGP message successfully decrypted."); - } else { - mutt_error _("Could not decrypt PGP message"); - pgp_void_passphrase (); - rc = -1; - } - - m_fclose(&fpout); - mutt_unlink (tempfile); - - return (rc); -} - -/* ---------------------------------------------------------------------------- - * Routines for sending PGP/MIME messages. - */ - - -BODY *pgp_sign_message (BODY * a) -{ - BODY *t; - char buffer[LONG_STRING]; - char sigfile[_POSIX_PATH_MAX], signedfile[_POSIX_PATH_MAX]; - FILE *pgpin, *pgpout, *pgperr, *fp, *sfp; - int err = 0; - int empty = 1; - pid_t thepid; - - convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */ - - fp = m_tempfile(sigfile, sizeof(sigfile), NONULL(MCore.tmpdir), NULL); - if (fp == NULL) { - return (NULL); - } - - sfp = m_tempfile(signedfile, sizeof(signedfile), NONULL(MCore.tmpdir), NULL); - if (sfp == NULL) { - mutt_perror (signedfile); - m_fclose(&fp); - unlink (sigfile); - return NULL; - } - - mutt_write_mime_header (a, sfp); - fputc ('\n', sfp); - mutt_write_mime_body (a, sfp); - m_fclose(&sfp); - - if ((thepid = pgp_invoke_sign (&pgpin, &pgpout, &pgperr, - -1, -1, -1, signedfile)) == -1) { - mutt_perror (_("Can't open PGP subprocess!")); - - m_fclose(&fp); - unlink (sigfile); - unlink (signedfile); - return NULL; - } - - if (!pgp_use_gpg_agent ()) - fputs (PgpPass, pgpin); - fputc ('\n', pgpin); - m_fclose(&pgpin); - - /* - * Read back the PGP signature. Also, change MESSAGE=>SIGNATURE as - * recommended for future releases of PGP. - */ - while (fgets (buffer, sizeof (buffer) - 1, pgpout) != NULL) { - if (m_strcmp("-----BEGIN PGP MESSAGE-----\n", buffer) == 0) - fputs ("-----BEGIN PGP SIGNATURE-----\n", fp); - else if (m_strcmp("-----END PGP MESSAGE-----\n", buffer) == 0) - fputs ("-----END PGP SIGNATURE-----\n", fp); - else - fputs (buffer, fp); - empty = 0; /* got some output, so we're ok */ - } - - /* check for errors from PGP */ - err = 0; - while (fgets (buffer, sizeof (buffer) - 1, pgperr) != NULL) { - err = 1; - fputs (buffer, stdout); - } - - if (mutt_wait_filter (thepid) && option (OPTPGPCHECKEXIT)) - empty = 1; - - m_fclose(&pgperr); - m_fclose(&pgpout); - unlink (signedfile); - - if (m_fclose(&fp) != 0) { - mutt_perror ("fclose"); - unlink (sigfile); - return (NULL); - } - - if (err) { - pgp_void_passphrase (); - mutt_any_key_to_continue (NULL); - } - - if (empty) { - unlink (sigfile); - return (NULL); /* fatal error while signing */ - } - - t = body_new(); - t->type = TYPEMULTIPART; - t->subtype = m_strdup("signed"); - t->encoding = ENC7BIT; - t->use_disp = 0; - t->disposition = DISPINLINE; - - parameter_set_boundary(&t->parameter); - parameter_setval(&t->parameter, "protocol", "application/pgp-signature"); - parameter_setval(&t->parameter, "micalg", pgp_micalg (sigfile)); - - t->parts = a; - a = t; - - t->parts->next = body_new(); - t = t->parts->next; - t->type = TYPEAPPLICATION; - t->subtype = m_strdup("pgp-signature"); - t->filename = m_strdup(sigfile); - t->use_disp = 0; - t->disposition = DISPINLINE; - t->encoding = ENC7BIT; - t->unlink = 1; /* ok to remove this file after sending. */ - - return (a); -} - -static short is_numerical_keyid (const char *s) -{ - /* or should we require the "0x"? */ - if (m_strncmp (s, "0x", 2) == 0) - s += 2; - if (m_strlen(s) % 8) - return 0; - while (*s) - if (strchr ("0123456789ABCDEFabcdef", *s++) == NULL) - return 0; - - return 1; -} - -/* This routine attempts to find the keyids of the recipients of a message. - * It returns NULL if any of the keys can not be found. - */ -char *pgp_findKeys (address_t * to, address_t * cc, address_t * bcc) -{ - char *keylist = NULL, *t; - const char *keyID; - size_t keylist_size = 0; - size_t keylist_used = 0; - address_t *tmp = NULL, *addr = NULL; - address_t **last = &tmp; - address_t *p, *q; - int i; - pgp_key_t k_info = NULL, key = NULL; - - const char *fqdn = mutt_fqdn (1); - - for (i = 0; i < 3; i++) { - switch (i) { - case 0: - p = to; - break; - case 1: - p = cc; - break; - case 2: - p = bcc; - break; - default: - abort (); - } - - *last = address_list_dup (p); - while (*last) - last = &((*last)->next); - } - - rfc822_qualify (tmp, fqdn); - - address_list_uniq(tmp); - - for (p = tmp; p; p = p->next) { - char buf[LONG_STRING]; - - q = p; - k_info = NULL; - - if ((keyID = mutt_crypt_hook (p)) != NULL) { - int r; - - snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, - p->mailbox); - if ((r = mutt_yesorno (buf, M_YES)) == M_YES) { - if (is_numerical_keyid (keyID)) { - if (m_strncmp (keyID, "0x", 2) == 0) - keyID += 2; - goto bypass_selection; /* you don't see this. */ - } - - /* check for e-mail address */ - if ((t = strchr (keyID, '@')) && - (addr = rfc822_parse_adrlist (NULL, keyID))) { - rfc822_qualify (addr, fqdn); - q = addr; - } - else - k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING); - } - else if (r == -1) { - p_delete(&keylist); - address_list_wipe(&tmp); - address_list_wipe(&addr); - return NULL; - } - } - - if (k_info == NULL) - pgp_invoke_getkeys (q); - - if (k_info == NULL - && (k_info = - pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) { - snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox); - - if ((key = pgp_ask_for_key (buf, q->mailbox, - KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) { - p_delete(&keylist); - address_list_wipe(&tmp); - address_list_wipe(&addr); - return NULL; - } - } - else - key = k_info; - - keyID = pgp_keyid (key); - - bypass_selection: - keylist_size += m_strlen(keyID) + 4; - p_realloc(&keylist, keylist_size); - sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "", - keyID); - keylist_used = m_strlen(keylist); - - pgp_free_key (&key); - address_list_wipe(&addr); - - } - address_list_wipe(&tmp); - return (keylist); -} - -/* Warning: "a" is no longer freed in this routine, you need - * to free it later. This is necessary for $fcc_attach. */ - -BODY *pgp_encrypt_message (BODY * a, char *keylist, int sign) -{ - char buf[LONG_STRING]; - char tempfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX]; - char pgpinfile[_POSIX_PATH_MAX]; - FILE *pgpin, *pgperr, *fpout, *fptmp; - BODY *t; - int err = 0; - int empty = 0; - pid_t thepid; - - fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); - if (fpout == NULL) { - mutt_perror (_("Can't create temporary file")); - return (NULL); - } - - pgperr = m_tempfile(pgperrfile, sizeof(pgperrfile), NONULL(MCore.tmpdir), NULL); - if (pgperr == NULL) { - mutt_perror (pgperrfile); - m_fclose(&fpout); - unlink (tempfile); - return NULL; - } - unlink (pgperrfile); - - fptmp = m_tempfile(pgpinfile, sizeof(pgpinfile), NONULL(MCore.tmpdir), NULL); - if (fptmp == NULL) { - mutt_perror (pgpinfile); - m_fclose(&fpout); - unlink (tempfile); - m_fclose(&pgperr); - unlink (pgperrfile); - return NULL; - } - - if (sign) - convert_to_7bit (a); - - mutt_write_mime_header (a, fptmp); - fputc ('\n', fptmp); - mutt_write_mime_body (a, fptmp); - m_fclose(&fptmp); - - if ((thepid = pgp_invoke_encrypt (&pgpin, NULL, NULL, -1, - fileno (fpout), fileno (pgperr), - pgpinfile, keylist, sign)) == -1) { - m_fclose(&pgperr); - unlink (pgpinfile); - return (NULL); - } - - if (sign) { - if (!pgp_use_gpg_agent ()) - fputs (PgpPass, pgpin); - fputc ('\n', pgpin); - } - m_fclose(&pgpin); - - if (mutt_wait_filter (thepid) && option (OPTPGPCHECKEXIT)) - empty = 1; - - unlink (pgpinfile); - - fflush (fpout); - rewind (fpout); - if (!empty) - empty = (fgetc (fpout) == EOF); - m_fclose(&fpout); - - fflush (pgperr); - rewind (pgperr); - while (fgets (buf, sizeof (buf) - 1, pgperr) != NULL) { - err = 1; - fputs (buf, stdout); - } - m_fclose(&pgperr); - - /* pause if there is any error output from PGP */ - if (err) - mutt_any_key_to_continue (NULL); - - if (empty) { - /* fatal error while trying to encrypt message */ - if (sign) - pgp_void_passphrase (); /* just in case */ - unlink (tempfile); - return (NULL); - } - - t = body_new(); - t->type = TYPEMULTIPART; - t->subtype = m_strdup("encrypted"); - t->encoding = ENC7BIT; - t->use_disp = 0; - t->disposition = DISPINLINE; - - parameter_set_boundary(&t->parameter); - parameter_setval(&t->parameter, "protocol", "application/pgp-encrypted"); - - t->parts = body_new(); - t->parts->type = TYPEAPPLICATION; - t->parts->subtype = m_strdup("pgp-encrypted"); - t->parts->encoding = ENC7BIT; - - t->parts->next = body_new(); - t->parts->next->type = TYPEAPPLICATION; - t->parts->next->subtype = m_strdup("octet-stream"); - t->parts->next->encoding = ENC7BIT; - t->parts->next->filename = m_strdup(tempfile); - t->parts->next->use_disp = 1; - t->parts->next->disposition = DISPINLINE; - t->parts->next->unlink = 1; /* delete after sending the message */ - t->parts->next->d_filename = m_strdup("msg.asc"); /* non pgp/mime can save */ - - return (t); -} - -BODY *pgp_traditional_encryptsign (BODY * a, int flags, char *keylist) -{ - BODY *b; - - char pgpoutfile[_POSIX_PATH_MAX]; - char pgperrfile[_POSIX_PATH_MAX]; - char pgpinfile[_POSIX_PATH_MAX]; - - char body_charset[STRING]; - char *from_charset; - const char *send_charset; - - FILE *pgpout = NULL, *pgperr = NULL, *pgpin = NULL; - FILE *fp; - - int empty = 0; - int err; - - char buff[STRING]; - - pid_t thepid; - - if (a->type != TYPETEXT) - return NULL; - if (ascii_strcasecmp (a->subtype, "plain")) - return NULL; - - if ((fp = fopen (a->filename, "r")) == NULL) { - mutt_perror (a->filename); - return NULL; - } - - pgpin = m_tempfile(pgpinfile, sizeof(pgpinfile), NONULL(MCore.tmpdir), NULL); - if (pgpin == NULL) { - mutt_perror (pgpinfile); - m_fclose(&fp); - return NULL; - } - - /* The following code is really correct: If noconv is set, - * a's charset parameter contains the on-disk character set, and - * we have to convert from that to utf-8. If noconv is not set, - * we have to convert from $charset to utf-8. - */ - - mutt_get_body_charset (body_charset, sizeof (body_charset), a); - if (a->noconv) - from_charset = body_charset; - else - from_charset = MCharset.charset; - - if (!charset_is_us_ascii (body_charset)) { - int c; - fgetconv_t *fc; - - if (flags & ENCRYPT) - send_charset = "us-ascii"; - else - send_charset = "utf-8"; - - fc = fgetconv_open (fp, from_charset, "utf-8", M_ICONV_HOOK_FROM); - while ((c = fgetconv (fc)) != EOF) - fputc (c, pgpin); - - fgetconv_close (&fc); - } - else { - send_charset = "us-ascii"; - mutt_copy_stream (fp, pgpin); - } - m_fclose(&fp); - m_fclose(&pgpin); - - pgpout = m_tempfile(pgpoutfile, sizeof(pgpoutfile), NONULL(MCore.tmpdir), NULL); - pgperr = m_tempfile(pgperrfile, sizeof(pgperrfile), NONULL(MCore.tmpdir), NULL); - if (pgpout == NULL || pgperr == NULL) { - mutt_perror (pgpout ? pgperrfile : pgpoutfile); - m_fclose(&pgpin); - unlink (pgpinfile); - m_fclose(&pgpout); - unlink (pgpoutfile); - m_fclose(&pgperr); - unlink(pgperrfile); - return NULL; - } - - unlink (pgperrfile); - - if ((thepid = pgp_invoke_traditional (&pgpin, NULL, NULL, - -1, fileno (pgpout), fileno (pgperr), - pgpinfile, keylist, flags)) == -1) { - mutt_perror (_("Can't invoke PGP")); - - m_fclose(&pgpout); - m_fclose(&pgperr); - mutt_unlink (pgpinfile); - unlink (pgpoutfile); - return NULL; - } - - if (pgp_use_gpg_agent ()) - *PgpPass = 0; - if (flags & SIGN) - fprintf (pgpin, "%s\n", PgpPass); - m_fclose(&pgpin); - - if (mutt_wait_filter (thepid) && option (OPTPGPCHECKEXIT)) - empty = 1; - - mutt_unlink (pgpinfile); - - fflush (pgpout); - fflush (pgperr); - - rewind (pgpout); - rewind (pgperr); - - if (!empty) - empty = (fgetc (pgpout) == EOF); - m_fclose(&pgpout); - - err = 0; - - while (fgets (buff, sizeof (buff), pgperr)) { - err = 1; - fputs (buff, stdout); - } - - m_fclose(&pgperr); - - if (err) - mutt_any_key_to_continue (NULL); - - if (empty) { - if (flags & SIGN) - pgp_void_passphrase (); /* just in case */ - unlink (pgpoutfile); - return NULL; - } - - b = body_new(); - - b->encoding = ENC7BIT; - - b->type = TYPETEXT; - b->subtype = m_strdup("plain"); - - parameter_setval(&b->parameter, "x-action", - flags & ENCRYPT ? "pgp-encrypted" : "pgp-signed"); - parameter_setval(&b->parameter, "charset", send_charset); - - b->filename = m_strdup(pgpoutfile); - - b->disposition = DISPINLINE; - b->unlink = 1; - - b->noconv = 1; - b->use_disp = 0; - - if (!(flags & ENCRYPT)) - b->encoding = a->encoding; - - return b; -} - -int pgp_send_menu (HEADER * msg, int *redraw) -{ - pgp_key_t p; - char input_signas[STRING]; - - char prompt[LONG_STRING]; - - /* If autoinline and no crypto options set, then set inline. */ - if (option (OPTPGPAUTOINLINE) && !((msg->security & APPLICATION_PGP) - && (msg->security & (SIGN | ENCRYPT)))) - msg->security |= INLINE; - - snprintf (prompt, sizeof (prompt), - _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s, or (c)lear? "), - (msg->security & INLINE) ? _("PGP/M(i)ME") : _("(i)nline")); - - switch (mutt_multi_choice (prompt, _("esabifc"))) { - case 1: /* (e)ncrypt */ - msg->security |= ENCRYPT; - msg->security &= ~SIGN; - break; - - case 2: /* (s)ign */ - msg->security |= SIGN; - msg->security &= ~ENCRYPT; - break; - - case 3: /* sign (a)s */ - unset_option (OPTPGPCHECKTRUST); - - if ((p = - pgp_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN, - PGP_PUBRING))) { - snprintf (input_signas, sizeof (input_signas), "0x%s", pgp_keyid (p)); - m_strreplace(&PgpSignAs, input_signas); - pgp_free_key (&p); - - msg->security |= SIGN; - - crypt_pgp_void_passphrase (); /* probably need a different passphrase */ - } - - *redraw = REDRAW_FULL; - break; - - case 4: /* (b)oth */ - msg->security |= (ENCRYPT | SIGN); - break; - - case 5: /* (i)nline */ - if ((msg->security & (ENCRYPT | SIGN))) - msg->security ^= INLINE; - else - msg->security &= ~INLINE; - break; - - case 6: /* (f)orget it */ - case 7: /* (c)lear */ - msg->security = 0; - break; - } - - if (msg->security) { - if (!(msg->security & (ENCRYPT | SIGN))) - msg->security = 0; - else - msg->security |= APPLICATION_PGP; - } - - return (msg->security); -} diff --git a/lib-crypt/pgp.h b/lib-crypt/pgp.h deleted file mode 100644 index 86fba30..0000000 --- a/lib-crypt/pgp.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright notice from original mutt: - * Copyright (C) 1996,1997 Michael R. Elkins - * Copyright (C) 1999-2000 Thomas Roessler - * Copyright (C) 2004 g10 Code GmbH - * - * This file is part of mutt-ng, see http://www.muttng.org/. - * It's licensed under the GNU General Public License, - * please see the file GPL in the top level source directory. - */ - -#include "crypt.h" - -/* prototypes */ - -int pgp_use_gpg_agent (void); - -int pgp_check_traditional (FILE *, BODY *, int); -BODY *pgp_decrypt_part (BODY *, STATE *, FILE *, BODY *); -BODY *pgp_make_key_attachment (char *); -const char *pgp_micalg (const char *fname); - -char *_pgp_keyid (pgp_key_t); -char *pgp_keyid (pgp_key_t); - - -int mutt_check_pgp (HEADER * h); - -int pgp_decrypt_mime (FILE *, FILE **, BODY *, BODY **); - -/* int pgp_string_matches_hint (const char *s, string_list_t * hints); */ - -/* pgp_key_t gpg_get_candidates (struct pgp_vinfo *, pgp_ring_t, string_list_t *); */ -pgp_key_t pgp_ask_for_key (char *, char *, short, pgp_ring_t); -pgp_key_t pgp_get_candidates (pgp_ring_t, string_list_t *); -pgp_key_t pgp_getkeybyaddr (address_t *, short, pgp_ring_t); -pgp_key_t pgp_getkeybystr (const char *, short, pgp_ring_t); - -char *pgp_findKeys (address_t * to, address_t * cc, address_t * bcc); - -int pgp_application_pgp_handler (BODY *, STATE *); -int pgp_encrypted_handler (BODY *, STATE *); -void pgp_extract_keys_from_attachment_list (FILE * fp, int tag, BODY * top); - -/* The PGP invocation interface - not really beautiful. */ - -pid_t pgp_invoke_decode (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname, short need_passphrase); -pid_t pgp_invoke_verify (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname, const char *sig_fname); -pid_t pgp_invoke_decrypt (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname); -pid_t pgp_invoke_sign (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname); -pid_t pgp_invoke_encrypt (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname, const char *uids, int sign); -pid_t pgp_invoke_export (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *uids); -pid_t pgp_invoke_verify_key (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *uids); -pid_t pgp_invoke_list_keys (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - pgp_ring_t keyring, string_list_t * hints); -pid_t pgp_invoke_traditional (FILE ** pgpin, FILE ** pgpout, FILE ** pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname, const char *uids, int flags); - - -void pgp_invoke_import (const char *fname); -void pgp_invoke_getkeys (address_t *); - - -/* private ? */ -int pgp_verify_one (BODY *, STATE *, const char *); -BODY *pgp_traditional_encryptsign (BODY *, int, char *); -BODY *pgp_encrypt_message (BODY *, char *, int); -BODY *pgp_sign_message (BODY *); - -int pgp_send_menu (HEADER * msg, int *redraw); diff --git a/lib-crypt/smime.c b/lib-crypt/smime.c deleted file mode 100644 index 374f9f3..0000000 --- a/lib-crypt/smime.c +++ /dev/null @@ -1,1928 +0,0 @@ -/* - * Copyright notice from original mutt: - * Copyright (C) 2001,2002 Oliver Ehli - * Copyright (C) 2002 Mike Schiraldi - * Copyright (C) 2004 g10 Code GmbH - * - * This file is part of mutt-ng, see http://www.muttng.org/. - * It's licensed under the GNU General Public License, - * please see the file GPL in the top level source directory. - */ - -#include - -#ifdef HAVE_SYS_RESOURCE_H -# include -#endif - -#include -#include - -#include -#include -#include - -#include "alias.h" -#include "handler.h" -#include "copy.h" -#include "alias.h" - -#include "crypt.h" -#include "smime.h" - -struct smime_command_context { - const char *key; /* %k */ - const char *cryptalg; /* %a */ - const char *fname; /* %f */ - const char *sig_fname; /* %s */ - const char *certificates; /* %c */ - const char *intermediates; /* %i */ -}; - - -typedef struct { - unsigned int hash; - char suffix; - char email[256]; - char nick[256]; - char trust; /* i=Invalid r=revoked e=expired u=unverified v=verified t=trusted */ - short public; /* 1=public 0=private */ -} smime_id; - - -char SmimePass[STRING]; -time_t SmimeExptime = 0; /* when does the cached passphrase expire? */ - - -static char SmimeKeyToUse[_POSIX_PATH_MAX] = { 0 }; -static char SmimeCertToUse[_POSIX_PATH_MAX]; -static char SmimeIntermediateToUse[_POSIX_PATH_MAX]; - - -/* - * Create a format string to be used with scanf. - * To use it, write, for instance, MUTT_FORMAT(HUGE_STRING). - * - * See K&R 2nd ed, p. 231 for an explanation. - */ -#define _MUTT_FORMAT_2(a,b) "%" a b -#define _MUTT_FORMAT_1(a, b) _MUTT_FORMAT_2(#a, b) -#define MUTT_FORMAT(a) _MUTT_FORMAT_1(a, "s") - - -/* - * Queries and passphrase handling. - */ - - -/* these are copies from pgp.c */ - - -void smime_void_passphrase (void) -{ - p_clear(SmimePass, countof(SmimePass)); - SmimeExptime = 0; -} - -int smime_valid_passphrase (void) -{ - time_t now = time (NULL); - - if (now < SmimeExptime) - /* Use cached copy. */ - return 1; - - smime_void_passphrase (); - - if (mutt_get_field_unbuffered (_("Enter S/MIME passphrase:"), SmimePass, - sizeof (SmimePass), M_PASS) == 0) { - SmimeExptime = time (NULL) + SmimeTimeout; - return (1); - } - else - SmimeExptime = 0; - - return 0; -} - - -/* - * The OpenSSL interface - */ - -/* This is almost identical to ppgp's invoking interface. */ - -static const char * -_mutt_fmt_smime_command (char *dest, ssize_t destlen, - char op, const char *src, const char *prefix, - const char *ifstr, const char *elstr, - anytype data, format_flag flags) -{ - char fmt[16]; - struct smime_command_context *cctx = data.ptr; - int optional = (flags & M_FORMAT_OPTIONAL); - - switch (op) { - case 'C': - { - if (!optional) { - char path[_POSIX_PATH_MAX]; - char buf1[LONG_STRING], buf2[LONG_STRING]; - struct stat sb; - - m_strcpy(path, sizeof(path), NONULL(SmimeCALocation)); - mutt_expand_path (path, sizeof (path)); - mutt_quote_filename (buf1, sizeof (buf1), path); - - if (stat (path, &sb) != 0 || !S_ISDIR (sb.st_mode)) - snprintf (buf2, sizeof (buf2), "-CAfile %s", buf1); - else - snprintf (buf2, sizeof (buf2), "-CApath %s", buf1); - - snprintf (fmt, sizeof (fmt), "%%%ss", prefix); - snprintf (dest, destlen, fmt, buf2); - } - else if (!SmimeCALocation) - optional = 0; - break; - } - - case 'c': - { /* certificate (list) */ - if (!optional) { - snprintf (fmt, sizeof (fmt), "%%%ss", prefix); - snprintf (dest, destlen, fmt, NONULL (cctx->certificates)); - } - else if (!cctx->certificates) - optional = 0; - break; - } - - case 'i': - { /* intermediate certificates */ - if (!optional) { - snprintf (fmt, sizeof (fmt), "%%%ss", prefix); - snprintf (dest, destlen, fmt, NONULL (cctx->intermediates)); - } - else if (!cctx->intermediates) - optional = 0; - break; - } - - case 's': - { /* detached signature */ - if (!optional) { - snprintf (fmt, sizeof (fmt), "%%%ss", prefix); - snprintf (dest, destlen, fmt, NONULL (cctx->sig_fname)); - } - else if (!cctx->sig_fname) - optional = 0; - break; - } - - case 'k': - { /* private key */ - if (!optional) { - snprintf (fmt, sizeof (fmt), "%%%ss", prefix); - snprintf (dest, destlen, fmt, NONULL (cctx->key)); - } - else if (!cctx->key) - optional = 0; - break; - } - - case 'a': - { /* algorithm for encryption */ - if (!optional) { - snprintf (fmt, sizeof (fmt), "%%%ss", prefix); - snprintf (dest, destlen, fmt, NONULL (cctx->cryptalg)); - } - else if (!cctx->key) - optional = 0; - break; - } - - case 'f': - { /* file to process */ - if (!optional) { - snprintf (fmt, sizeof (fmt), "%%%ss", prefix); - snprintf (dest, destlen, fmt, NONULL (cctx->fname)); - } - else if (!cctx->fname) - optional = 0; - break; - } - - default: - *dest = '\0'; - break; - } - - if (flags & M_FORMAT_OPTIONAL) - m_strformat(dest, destlen, 0, optional ? ifstr : elstr, - _mutt_fmt_smime_command, data, 0); - - return src; -} - - - -static void mutt_smime_command (char *d, ssize_t dlen, - struct smime_command_context *cctx, - const char *fmt) -{ - m_strformat(d, dlen, 0, fmt, _mutt_fmt_smime_command, cctx, 0); -} - -static pid_t smime_invoke (FILE ** smimein, FILE ** smimeout, - FILE ** smimeerr, int smimeinfd, int smimeoutfd, - int smimeerrfd, const char *fname, - const char *sig_fname, const char *cryptalg, - const char *key, const char *certificates, - const char *intermediates, const char *format) -{ - struct smime_command_context cctx; - char cmd[HUGE_STRING]; - - p_clear(&cctx, 1); - - if (!format || !*format) - return (pid_t) - 1; - - cctx.fname = fname; - cctx.sig_fname = sig_fname; - cctx.key = key; - cctx.cryptalg = cryptalg; - cctx.certificates = certificates; - cctx.intermediates = intermediates; - - mutt_smime_command (cmd, sizeof (cmd), &cctx, format); - - return mutt_create_filter_fd (cmd, smimein, smimeout, smimeerr, - smimeinfd, smimeoutfd, smimeerrfd); -} - - - - - - -/* - * Key and certificate handling. - */ - - - -/* - Search the certificate index for given mailbox. - return certificate file name. -*/ - -static void smime_entry (char *s, ssize_t l, MUTTMENU * menu, int num) -{ - smime_id *Table = (smime_id *) menu->data; - smime_id this = Table[num]; - const char *truststate; - - switch (this.trust) { - case 't': - truststate = N_("Trusted "); - break; - case 'v': - truststate = N_("Verified "); - break; - case 'u': - truststate = N_("Unverified"); - break; - case 'e': - truststate = N_("Expired "); - break; - case 'r': - truststate = N_("Revoked "); - break; - case 'i': - truststate = N_("Invalid "); - break; - default: - truststate = N_("Unknown "); - } - if (this.public) - snprintf (s, l, " 0x%.8X.%i %s %-35.35s %s", this.hash, this.suffix, - truststate, this.email, this.nick); - else - snprintf (s, l, " 0x%.8X.%i %-35.35s %s", this.hash, this.suffix, - this.email, this.nick); -} - - - - - -char *smime_ask_for_key (char *prompt, char *mailbox __attribute__((unused)), - short public) -{ - char *fname; - smime_id *Table; - long cert_num; /* Will contain the number of certificates. - * To be able to get it, the .index file will be read twice... */ - char index_file[_POSIX_PATH_MAX]; - FILE *idx; - char buf[LONG_STRING]; - char fields[5][STRING]; - int numFields, hash_suffix, done, cur; /* The current entry */ - MUTTMENU *menu; - unsigned int hash; - char helpstr[HUGE_STRING * 3]; - char qry[256]; - char title[256]; - - if (!prompt) - prompt = _("Enter keyID: "); - snprintf (index_file, sizeof (index_file), "%s/.index", - public ? NONULL (SmimeCertificates) : NONULL (SmimeKeys)); - - idx = fopen (index_file, "r"); - if (idx == NULL) { - mutt_perror (index_file); - return NULL; - } - /* Count Lines */ - cert_num = 0; - while (!feof (idx)) { - if (fgets (buf, sizeof (buf), idx)) - cert_num++; - } - m_fclose(&idx); - - for (;;) { - *qry = 0; - if (mutt_get_field (prompt, qry, sizeof (qry), 0)) - return NULL; - snprintf (title, sizeof (title), - _("S/MIME certificates matching \"%s\"."), qry); - - - idx = fopen (index_file, "r"); - if (idx == NULL) { - mutt_perror (index_file); - return NULL; - } - /* Read Entries */ - cur = 0; - Table = p_new(smime_id, cert_num); - while (!feof (idx)) { - numFields = - fscanf (idx, MUTT_FORMAT (STRING) " %x.%i " MUTT_FORMAT (STRING), - fields[0], &hash, &hash_suffix, fields[2]); - if (public) - fscanf (idx, MUTT_FORMAT (STRING) " " MUTT_FORMAT (STRING) "\n", - fields[3], fields[4]); - - /* 0=email 1=name 2=nick 3=intermediate 4=trust */ - if (numFields < 2) - continue; - - /* Check if query matches this certificate */ - if (!m_stristr(fields[0], qry) && !m_stristr(fields[2], qry)) - continue; - - Table[cur].hash = hash; - Table[cur].suffix = hash_suffix; - m_strcpy(Table[cur].email, sizeof(Table[cur].email), fields[0]); - m_strcpy(Table[cur].nick, sizeof(Table[cur].nick), fields[2]); - Table[cur].trust = *fields[4]; - Table[cur].public = public; - - cur++; - } - m_fclose(&idx); - - /* Make Helpstring */ - helpstr[0] = 0; - mutt_make_help (buf, sizeof (buf), _("Exit "), MENU_SMIME, OP_EXIT); - m_strcat(helpstr, sizeof(helpstr), buf); - mutt_make_help (buf, sizeof (buf), _("Select "), MENU_SMIME, - OP_GENERIC_SELECT_ENTRY); - m_strcat(helpstr, sizeof(helpstr), buf); - mutt_make_help (buf, sizeof (buf), _("Help"), MENU_SMIME, OP_HELP); - m_strcat(helpstr, sizeof(helpstr), buf); - - /* Create the menu */ - menu = mutt_new_menu (); - menu->max = cur; - menu->make_entry = smime_entry; - menu->menu = MENU_SMIME; - menu->help = helpstr; - menu->data = Table; - menu->title = title; - /* sorting keys might be done later - TODO */ - - mutt_clear_error (); - - done = 0; - hash = 0; - while (!done) { - switch (mutt_menuLoop (menu)) { - case OP_GENERIC_SELECT_ENTRY: - cur = menu->current; - hash = 1; - done = 1; - break; - case OP_EXIT: - hash = 0; - done = 1; - break; - } - } - if (hash) { - fname = p_new(char, 13); /* Hash + '.' + Suffix + \0 */ - sprintf (fname, "%.8x.%i", Table[cur].hash, Table[cur].suffix); - } - else - fname = NULL; - - mutt_menuDestroy (&menu); - p_delete(&Table); - set_option (OPTNEEDREDRAW); - - if (fname) - return fname; - } -} - - - -char *smime_get_field_from_db (char *mailbox, char *query, short public, - short may_ask) -{ - int addr_len, query_len, found = 0, ask = 0, choice = 0; - char cert_path[_POSIX_PATH_MAX]; - char buf[LONG_STRING], prompt[STRING]; - char fields[5][STRING]; - char key[STRING]; - int numFields; - struct stat info; - char key_trust_level = 0; - FILE *fp; - - if (!mailbox && !query) - return (NULL); - - addr_len = mailbox ? m_strlen(mailbox) : 0; - query_len = query ? m_strlen(query) : 0; - - *key = '\0'; - - /* index-file format: - mailbox certfile label issuer_certfile trust_flags\n - - certfile is a hash value generated by openssl. - Note that this was done according to the OpenSSL - specs on their CA-directory. - - */ - snprintf (cert_path, sizeof (cert_path), "%s/.index", - (public ? NONULL (SmimeCertificates) : NONULL (SmimeKeys))); - - if (!stat (cert_path, &info)) { - if ((fp = safe_fopen (cert_path, "r")) == NULL) { - mutt_perror (cert_path); - return (NULL); - } - - while (fgets (buf, sizeof (buf) - 1, fp) != NULL) - if (mailbox && !(m_strncasecmp(mailbox, buf, addr_len))) { - numFields = sscanf (buf, - MUTT_FORMAT (STRING) " " MUTT_FORMAT (STRING) " " - MUTT_FORMAT (STRING) " " MUTT_FORMAT (STRING) " " - MUTT_FORMAT (STRING) "\n", - fields[0], fields[1], - fields[2], fields[3], fields[4]); - if (numFields < 2) - continue; - if (mailbox && public && - (!fields[4] || - *fields[4] == 'i' || *fields[4] == 'e' || *fields[4] == 'r')) - continue; - - if (found) { - if (public && *fields[4] == 'u') - snprintf (prompt, sizeof (prompt), - _ - ("ID %s is unverified. Do you want to use it for %s ?"), - fields[1], mailbox); - else if (public && *fields[4] == 'v') - snprintf (prompt, sizeof (prompt), - _("Use (untrusted!) ID %s for %s ?"), - fields[1], mailbox); - else - snprintf (prompt, sizeof (prompt), _("Use ID %s for %s ?"), - fields[1], mailbox); - if (may_ask == 0) - choice = M_YES; - if (may_ask && (choice = mutt_yesorno (prompt, M_NO)) == -1) { - found = 0; - ask = 0; - *key = '\0'; - break; - } - else if (choice == M_NO) { - ask = 1; - continue; - } - else if (choice == M_YES) { - m_strcpy(key, sizeof(key), fields[1]); - ask = 0; - break; - } - } - else { - if (public) - key_trust_level = *fields[4]; - m_strcpy(key, sizeof(key), fields[1]); - } - found = 1; - } - else if (query) { - numFields = sscanf (buf, - MUTT_FORMAT (STRING) " " MUTT_FORMAT (STRING) " " - MUTT_FORMAT (STRING) " " MUTT_FORMAT (STRING) " " - MUTT_FORMAT (STRING) "\n", - fields[0], fields[1], - fields[2], fields[3], fields[4]); - - /* query = label: return certificate. */ - if (numFields >= 3 && - !(m_strncasecmp(query, fields[2], query_len))) { - ask = 0; - m_strcpy(key, sizeof(key), fields[1]); - } - /* query = certificate: return intermediate certificate. */ - else if (numFields >= 4 && - !(m_strncasecmp(query, fields[1], query_len))) { - ask = 0; - m_strcpy(key, sizeof(key), fields[3]); - } - } - - m_fclose(&fp); - - if (ask) { - if (public && *fields[4] == 'u') - snprintf (prompt, sizeof (prompt), - _("ID %s is unverified. Do you want to use it for %s ?"), - fields[1], mailbox); - else if (public && *fields[4] == 'v') - snprintf (prompt, sizeof (prompt), - _("Use (untrusted!) ID %s for %s ?"), fields[1], mailbox); - else - snprintf (prompt, sizeof (prompt), _("Use ID %s for %s ?"), key, - mailbox); - choice = mutt_yesorno (prompt, M_NO); - if (choice == -1 || choice == M_NO) - *key = '\0'; - } - else if (key_trust_level && may_ask) { - if (key_trust_level == 'u') { - snprintf (prompt, sizeof (prompt), - _("ID %s is unverified. Do you want to use it for %s ?"), - key, mailbox); - choice = mutt_yesorno (prompt, M_NO); - if (choice != M_YES) - *key = '\0'; - } - else if (key_trust_level == 'v') { - mutt_error (_ - ("Warning: You have not yet decided to trust ID %s. (any key to continue)"), - key); - mutt_sleep (5); - } - } - - } - - /* Note: m_strdup("") returns NULL. */ - return m_strdup(key); -} - -/* - This sets the '*ToUse' variables for an upcoming decryption, where - the reuquired key is different from SmimeDefaultKey. -*/ -static void _smime_getkeys (char *mailbox) -{ - char *k = NULL; - char buf[STRING]; - - k = smime_get_field_from_db (mailbox, NULL, 0, 1); - - if (!k) { - snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), mailbox); - k = smime_ask_for_key (buf, mailbox, 0); - } - - if (k) { - /* the key used last time. */ - if (*SmimeKeyToUse && - !m_strcasecmp(k, SmimeKeyToUse + m_strlen(SmimeKeys) + 1)) { - p_delete(&k); - return; - } - else - smime_void_passphrase (); - - snprintf (SmimeKeyToUse, sizeof (SmimeKeyToUse), "%s/%s", - NONULL (SmimeKeys), k); - - snprintf (SmimeCertToUse, sizeof (SmimeCertToUse), "%s/%s", - NONULL (SmimeCertificates), k); - - if (m_strcasecmp(k, SmimeDefaultKey)) - smime_void_passphrase (); - - p_delete(&k); - return; - } - - if (*SmimeKeyToUse) { - if (!m_strcasecmp(SmimeDefaultKey, - SmimeKeyToUse + m_strlen(SmimeKeys) + 1)) - return; - - smime_void_passphrase (); - } - - snprintf (SmimeKeyToUse, sizeof (SmimeKeyToUse), "%s/%s", - NONULL (SmimeKeys), NONULL (SmimeDefaultKey)); - - snprintf (SmimeCertToUse, sizeof (SmimeCertToUse), "%s/%s", - NONULL (SmimeCertificates), NONULL (SmimeDefaultKey)); -} - -void smime_getkeys (ENVELOPE * env) -{ - address_t *t; - int found = 0; - - if (option (OPTSDEFAULTDECRYPTKEY) && SmimeDefaultKey && *SmimeDefaultKey) { - snprintf (SmimeKeyToUse, sizeof (SmimeKeyToUse), "%s/%s", - NONULL (SmimeKeys), SmimeDefaultKey); - - snprintf (SmimeCertToUse, sizeof (SmimeCertToUse), "%s/%s", - NONULL (SmimeCertificates), SmimeDefaultKey); - - return; - } - - for (t = env->to; !found && t; t = t->next) - if (mutt_addr_is_user (t)) { - found = 1; - _smime_getkeys (t->mailbox); - } - for (t = env->cc; !found && t; t = t->next) - if (mutt_addr_is_user (t)) { - found = 1; - _smime_getkeys (t->mailbox); - } - if (!found && (t = mutt_default_from ())) { - _smime_getkeys (t->mailbox); - address_list_wipe(&t); - } -} - -/* This routine attempts to find the keyids of the recipients of a message. - * It returns NULL if any of the keys can not be found. - */ - -char *smime_findKeys (address_t * to, address_t * cc, address_t * bcc) -{ - char *keyID, *keylist = NULL; - ssize_t keylist_size = 0; - ssize_t keylist_used = 0; - address_t *tmp = NULL, *addr = NULL; - address_t **last = &tmp; - address_t *p, *q; - int i; - - for (i = 0; i < 3; i++) { - switch (i) { - case 0: - p = to; - break; - case 1: - p = cc; - break; - case 2: - p = bcc; - break; - default: - abort (); - } - - *last = address_list_dup (p); - while (*last) - last = &((*last)->next); - } - - rfc822_qualify(tmp, mutt_fqdn(1)); - - address_list_uniq(tmp); - - for (p = tmp; p; p = p->next) { - char buf[LONG_STRING]; - - q = p; - - if ((keyID = smime_get_field_from_db (q->mailbox, NULL, 1, 1)) == NULL) { - snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox); - keyID = smime_ask_for_key (buf, q->mailbox, 1); - } - if (!keyID) { - mutt_message (_("No (valid) certificate found for %s."), q->mailbox); - p_delete(&keylist); - address_list_wipe(&tmp); - address_list_wipe(&addr); - return NULL; - } - - keylist_size += m_strlen(keyID) + 2; - p_realloc(&keylist, keylist_size); - sprintf (keylist + keylist_used, "%s\n", keyID); - keylist_used = m_strlen(keylist); - - address_list_wipe(&addr); - - } - address_list_wipe(&tmp); - return (keylist); -} - - - - - - -static int smime_handle_cert_email (char *certificate, char *mailbox, - int copy, char ***buffer, int *num) -{ - FILE *fpout = NULL, *fperr = NULL; - char tmpfname[_POSIX_PATH_MAX]; - char email[STRING]; - int ret = -1, count = 0; - pid_t thepid; - - fperr = m_tempfile (tmpfname, sizeof(tmpfname), NONULL(MCore.tmpdir), NULL); - if (!fperr) { - mutt_perror (tmpfname); - return 1; - } - mutt_unlink (tmpfname); - - fpout = m_tempfile (tmpfname, sizeof(tmpfname), NONULL(MCore.tmpdir), NULL); - if (!fpout) { - m_fclose(&fperr); - mutt_perror (tmpfname); - return 1; - } - mutt_unlink (tmpfname); - - if ((thepid = smime_invoke (NULL, NULL, NULL, - -1, fileno (fpout), fileno (fperr), - certificate, NULL, NULL, NULL, NULL, NULL, - SmimeGetCertEmailCommand)) == -1) { - mutt_message (_("Error: unable to create OpenSSL subprocess!")); - m_fclose(&fperr); - m_fclose(&fpout); - return 1; - } - - mutt_wait_filter (thepid); - - fflush (fpout); - rewind (fpout); - rewind (fperr); - fflush (fperr); - - - while ((fgets (email, sizeof (email), fpout))) { - *(email + m_strlen(email) - 1) = '\0'; - if (m_strncasecmp(email, mailbox, m_strlen(mailbox)) == 0) - ret = 1; - - ret = ret < 0 ? 0 : ret; - count++; - } - - if (ret == -1) { - mutt_endwin (NULL); - mutt_copy_stream (fperr, stdout); - mutt_any_key_to_continue (_ - ("Error: unable to create OpenSSL subprocess!")); - ret = 1; - } - else if (!ret) - ret = 1; - else - ret = 0; - - if (copy && buffer && num) { - (*num) = count; - *buffer = p_new(char *, count); - count = 0; - - rewind (fpout); - while ((fgets (email, sizeof (email), fpout))) { - *(email + m_strlen(email) - 1) = '\0'; - (*buffer)[count] = p_dupstr(email, m_strlen(email)); - count++; - } - } - else if (copy) - ret = 2; - - m_fclose(&fpout); - m_fclose(&fperr); - - return ret; -} - - - -static char *smime_extract_certificate (char *infile) -{ - FILE *fpout = NULL, *fperr = NULL; - char pk7out[_POSIX_PATH_MAX], certfile[_POSIX_PATH_MAX]; - char tmpfname[_POSIX_PATH_MAX]; - pid_t thepid; - int empty; - - - fperr = m_tempfile (tmpfname, sizeof(tmpfname), NONULL(MCore.tmpdir), NULL); - if (!fperr) { - mutt_perror (tmpfname); - return NULL; - } - mutt_unlink (tmpfname); - - fpout = m_tempfile (pk7out, sizeof(tmpfname), NONULL(MCore.tmpdir), NULL); - if (!fpout) { - m_fclose(&fperr); - mutt_perror (pk7out); - return NULL; - } - - /* Step 1: Convert the signature to a PKCS#7 structure, as we can't - extract the full set of certificates directly. - */ - if ((thepid = smime_invoke (NULL, NULL, NULL, - -1, fileno (fpout), fileno (fperr), - infile, NULL, NULL, NULL, NULL, NULL, - SmimePk7outCommand)) == -1) { - mutt_any_key_to_continue (_ - ("Error: unable to create OpenSSL subprocess!")); - m_fclose(&fperr); - m_fclose(&fpout); - mutt_unlink (pk7out); - return NULL; - } - - mutt_wait_filter (thepid); - - - fflush (fpout); - rewind (fpout); - rewind (fperr); - fflush (fperr); - - empty = (fgetc (fpout) == EOF); - - m_fclose(&fpout); - - if (empty) { - mutt_perror (pk7out); - mutt_copy_stream (fperr, stdout); - m_fclose(&fperr); - mutt_unlink (pk7out); - return NULL; - } - - fpout = m_tempfile (certfile, sizeof(certfile), NONULL(MCore.tmpdir), NULL); - if (!fpout) { - m_fclose(&fperr); - mutt_unlink (pk7out); - mutt_perror (certfile); - return NULL; - } - - /* Step 2: Extract the certificates from a PKCS#7 structure. - */ - if ((thepid = smime_invoke (NULL, NULL, NULL, - -1, fileno (fpout), fileno (fperr), - pk7out, NULL, NULL, NULL, NULL, NULL, - SmimeGetCertCommand)) == -1) { - mutt_any_key_to_continue (_ - ("Error: unable to create OpenSSL subprocess!")); - m_fclose(&fperr); - m_fclose(&fpout); - mutt_unlink (pk7out); - mutt_unlink (certfile); - return NULL; - } - - mutt_wait_filter (thepid); - - mutt_unlink (pk7out); - - fflush (fpout); - rewind (fpout); - rewind (fperr); - fflush (fperr); - empty = (fgetc (fpout) == EOF); - if (empty) { - mutt_copy_stream (fperr, stdout); - m_fclose(&fpout); - m_fclose(&fperr); - mutt_unlink (certfile); - return NULL; - } - - m_fclose(&fpout); - m_fclose(&fperr); - - return m_strdup(certfile); -} - -static char *smime_extract_signer_certificate (char *infile) -{ - FILE *fpout = NULL, *fperr = NULL; - char pk7out[_POSIX_PATH_MAX], certfile[_POSIX_PATH_MAX]; - char tmpfname[_POSIX_PATH_MAX]; - pid_t thepid; - int empty; - - fperr = m_tempfile (tmpfname, sizeof(tmpfname), NONULL(MCore.tmpdir), NULL); - if (!fperr) { - mutt_perror (tmpfname); - return NULL; - } - mutt_unlink (tmpfname); - - m_tempfile (certfile, sizeof(certfile), NONULL(MCore.tmpdir), NULL); - if (!fpout) { - m_fclose(&fperr); - mutt_perror (certfile); - return NULL; - } - - /* Extract signer's certificate - */ - if ((thepid = smime_invoke (NULL, NULL, NULL, - -1, -1, fileno (fperr), - infile, NULL, NULL, NULL, certfile, NULL, - SmimeGetSignerCertCommand)) == -1) { - mutt_any_key_to_continue (_ - ("Error: unable to create OpenSSL subprocess!")); - m_fclose(&fperr); - m_fclose(&fpout); - mutt_unlink (pk7out); - mutt_unlink (certfile); - return NULL; - } - - mutt_wait_filter (thepid); - - fflush (fpout); - rewind (fpout); - rewind (fperr); - fflush (fperr); - empty = (fgetc (fpout) == EOF); - m_fclose(&fpout); - - if (empty) { - mutt_endwin (NULL); - mutt_copy_stream (fperr, stdout); - mutt_any_key_to_continue (NULL); - m_fclose(&fperr); - mutt_unlink (certfile); - return NULL; - } - - m_fclose(&fperr); - - return m_strdup(certfile); -} - -/* Add a certificate and update index file (externally). */ - -void smime_invoke_import (char *infile, char *mailbox __attribute__ ((unused))) -{ - char tmpfname[_POSIX_PATH_MAX], *certfile = NULL, buf[STRING]; - FILE *smimein = NULL, *fpout = NULL, *fperr = NULL; - pid_t thepid = -1; - - fperr = m_tempfile (tmpfname, sizeof(tmpfname), NONULL(MCore.tmpdir), NULL); - if (!fperr) { - mutt_perror (tmpfname); - return; - } - mutt_unlink (tmpfname); - - fpout = m_tempfile (tmpfname, sizeof(tmpfname), NONULL(MCore.tmpdir), NULL); - if (!fpout) { - m_fclose(&fperr); - mutt_perror (tmpfname); - return; - } - mutt_unlink (tmpfname); - - buf[0] = '\0'; - if (option (OPTASKCERTLABEL)) - mutt_get_field ("Label for certificate:", buf, sizeof (buf), 0); - - mutt_endwin (NULL); - if ((certfile = smime_extract_certificate (infile))) { - mutt_endwin (NULL); - - if ((thepid = smime_invoke (&smimein, NULL, NULL, - -1, fileno (fpout), fileno (fperr), - certfile, NULL, NULL, NULL, NULL, NULL, - SmimeImportCertCommand)) == -1) { - mutt_message (_("Error: unable to create OpenSSL subprocess!")); - return; - } - fputs (buf, smimein); - fputc ('\n', smimein); - m_fclose(&smimein); - - mutt_wait_filter (thepid); - - mutt_unlink (certfile); - p_delete(&certfile); - } - - fflush (fpout); - rewind (fpout); - fflush (fperr); - rewind (fperr); - - mutt_copy_stream (fpout, stdout); - mutt_copy_stream (fperr, stdout); - - m_fclose(&fpout); - m_fclose(&fperr); -} - -int smime_verify_sender (HEADER * h) -{ - char *mbox = NULL, *certfile, tempfname[_POSIX_PATH_MAX]; - FILE *fpout; - int retval = 1; - - fpout = m_tempfile (tempfname, sizeof(tempfname), NONULL(MCore.tmpdir), NULL); - if (!fpout) { - mutt_perror (_("Can't create temporary file")); - return 1; - } - - if (h->security & ENCRYPT) - mutt_copy_message (fpout, Context, h, - M_CM_DECODE_CRYPT & M_CM_DECODE_SMIME, - CH_MIME | CH_WEED | CH_NONEWLINE); - else - mutt_copy_message (fpout, Context, h, 0, 0); - - fflush (fpout); - m_fclose(&fpout); - - if (h->env->from) { - h->env->from = mutt_expand_aliases (h->env->from); - mbox = h->env->from->mailbox; - } - else if (h->env->sender) { - h->env->sender = mutt_expand_aliases (h->env->sender); - mbox = h->env->sender->mailbox; - } - - if (mbox) { - if ((certfile = smime_extract_signer_certificate (tempfname))) { - mutt_unlink (tempfname); - if (smime_handle_cert_email (certfile, mbox, 0, NULL, NULL)) { - if (isendwin ()) - mutt_any_key_to_continue (NULL); - } - else - retval = 0; - mutt_unlink (certfile); - p_delete(&certfile); - } - else - mutt_any_key_to_continue (_("no certfile")); - } - else - mutt_any_key_to_continue (_("no mbox")); - - mutt_unlink (tempfname); - return retval; -} - - - - - - - - - -/* - * Creating S/MIME - bodies. - */ - - - - -static -pid_t smime_invoke_encrypt (FILE ** smimein, FILE ** smimeout, - FILE ** smimeerr, int smimeinfd, int smimeoutfd, - int smimeerrfd, const char *fname, - const char *uids) -{ - return smime_invoke (smimein, smimeout, smimeerr, - smimeinfd, smimeoutfd, smimeerrfd, - fname, NULL, SmimeCryptAlg, NULL, uids, NULL, - SmimeEncryptCommand); -} - - -static -pid_t smime_invoke_sign (FILE ** smimein, FILE ** smimeout, FILE ** smimeerr, - int smimeinfd, int smimeoutfd, int smimeerrfd, - const char *fname) -{ - return smime_invoke (smimein, smimeout, smimeerr, smimeinfd, smimeoutfd, - smimeerrfd, fname, NULL, NULL, SmimeKeyToUse, - SmimeCertToUse, SmimeIntermediateToUse, - SmimeSignCommand); -} - - - - -BODY *smime_build_smime_entity (BODY * a, char *certlist) -{ - char buf[LONG_STRING], certfile[LONG_STRING]; - char tempfile[_POSIX_PATH_MAX], smimeerrfile[_POSIX_PATH_MAX]; - char smimeinfile[_POSIX_PATH_MAX]; - char *cert_start = certlist, *cert_end = certlist; - FILE *smimein = NULL, *smimeerr = NULL, *fpout = NULL, *fptmp = NULL; - BODY *t; - int err = 0, empty; - pid_t thepid; - - fpout = m_tempfile (tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); - if (!fpout) { - mutt_perror (_("Can't create temporary file")); - return NULL; - } - - smimeerr = m_tempfile (smimeerrfile, sizeof(smimeerrfile), NONULL(MCore.tmpdir), NULL); - if (!smimeerr) { - mutt_perror (smimeerrfile); - m_fclose(&fpout); - mutt_unlink (tempfile); - return NULL; - } - mutt_unlink (smimeerrfile); - - fptmp = m_tempfile (smimeinfile, sizeof(smimeinfile), NONULL(MCore.tmpdir), NULL); - if (!fptmp) { - mutt_perror (smimeinfile); - mutt_unlink (tempfile); - m_fclose(&fpout); - m_fclose(&smimeerr); - return NULL; - } - - *certfile = '\0'; - while (1) { - int off = m_strlen(certfile); - - while (*++cert_end && *cert_end != '\n'); - if (!*cert_end) - break; - *cert_end = '\0'; - snprintf (certfile + off, sizeof (certfile) - off, " %s/%s", - NONULL (SmimeCertificates), cert_start); - *cert_end = '\n'; - cert_start = cert_end; - cert_start++; - } - - /* write a MIME entity */ - mutt_write_mime_header (a, fptmp); - fputc ('\n', fptmp); - mutt_write_mime_body (a, fptmp); - m_fclose(&fptmp); - - if ((thepid = - smime_invoke_encrypt (&smimein, NULL, NULL, -1, - fileno (fpout), fileno (smimeerr), - smimeinfile, certfile)) == -1) { - m_fclose(&smimeerr); - mutt_unlink (smimeinfile); - mutt_unlink (certfile); - return (NULL); - } - - m_fclose(&smimein); - - mutt_wait_filter (thepid); - mutt_unlink (smimeinfile); - mutt_unlink (certfile); - - fflush (fpout); - rewind (fpout); - empty = (fgetc (fpout) == EOF); - m_fclose(&fpout); - - fflush (smimeerr); - rewind (smimeerr); - while (fgets (buf, sizeof (buf) - 1, smimeerr) != NULL) { - err = 1; - fputs (buf, stdout); - } - m_fclose(&smimeerr); - - /* pause if there is any error output from SMIME */ - if (err) - mutt_any_key_to_continue (NULL); - - if (empty) { - /* fatal error while trying to encrypt message */ - if (!err) - mutt_any_key_to_continue _("No output from OpenSSL.."); - - mutt_unlink (tempfile); - return (NULL); - } - - t = body_new(); - t->type = TYPEAPPLICATION; - t->subtype = m_strdup("x-pkcs7-mime"); - parameter_setval(&t->parameter, "name", "smime.p7m"); - parameter_setval(&t->parameter, "smime-type", "enveloped-data"); - t->encoding = ENCBASE64; /* The output of OpenSSL SHOULD be binary */ - t->use_disp = 1; - t->disposition = DISPATTACH; - t->d_filename = m_strdup("smime.p7m"); - t->filename = m_strdup(tempfile); - t->unlink = 1; /*delete after sending the message */ - t->parts = 0; - t->next = 0; - - return (t); -} - - - - -BODY *smime_sign_message (BODY * a) -{ - BODY *t; - char buffer[LONG_STRING]; - char signedfile[_POSIX_PATH_MAX], filetosign[_POSIX_PATH_MAX]; - FILE *smimein = NULL, *smimeout = NULL, *smimeerr = NULL, *sfp = NULL; - int err = 0; - int empty = 0; - pid_t thepid; - char *intermediates = smime_get_field_from_db (NULL, SmimeDefaultKey, 1, 1); - - if (!intermediates) { - mutt_message (_("Warning: Intermediate certificate not found.")); - intermediates = SmimeDefaultKey; /* so openssl won't complain in any case */ - } - - convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */ - - sfp = m_tempfile (filetosign, sizeof(filetosign), NONULL(MCore.tmpdir), NULL); - if (!sfp) { - mutt_perror (filetosign); - return NULL; - } - - smimeout = m_tempfile (signedfile, sizeof(signedfile), NONULL(MCore.tmpdir), NULL); - if (!smimeout) { - mutt_perror (signedfile); - m_fclose(&sfp); - mutt_unlink (filetosign); - return NULL; - } - - mutt_write_mime_header (a, sfp); - fputc ('\n', sfp); - mutt_write_mime_body (a, sfp); - m_fclose(&sfp); - - - - snprintf (SmimeKeyToUse, sizeof (SmimeKeyToUse), "%s/%s", - NONULL (SmimeKeys), SmimeDefaultKey); - - snprintf (SmimeCertToUse, sizeof (SmimeCertToUse), "%s/%s", - NONULL (SmimeCertificates), SmimeDefaultKey); - - snprintf (SmimeIntermediateToUse, sizeof (SmimeIntermediateToUse), "%s/%s", - NONULL (SmimeCertificates), intermediates); - - - - if ((thepid = smime_invoke_sign (&smimein, NULL, &smimeerr, - -1, fileno (smimeout), -1, - filetosign)) == -1) { - mutt_perror (_("Can't open OpenSSL subprocess!")); - - m_fclose(&smimeout); - mutt_unlink (signedfile); - mutt_unlink (filetosign); - return NULL; - } - fputs (SmimePass, smimein); - fputc ('\n', smimein); - m_fclose(&smimein); - - - mutt_wait_filter (thepid); - - /* check for errors from OpenSSL */ - err = 0; - fflush (smimeerr); - rewind (smimeerr); - while (fgets (buffer, sizeof (buffer) - 1, smimeerr) != NULL) { - err = 1; - fputs (buffer, stdout); - } - m_fclose(&smimeerr); - - - fflush (smimeout); - rewind (smimeout); - empty = (fgetc (smimeout) == EOF); - m_fclose(&smimeout); - - mutt_unlink (filetosign); - - - if (err) - mutt_any_key_to_continue (NULL); - - if (empty) { - mutt_any_key_to_continue _("No output from OpenSSL..."); - - mutt_unlink (signedfile); - return (NULL); /* fatal error while signing */ - } - - t = body_new(); - t->type = TYPEMULTIPART; - t->subtype = m_strdup("signed"); - t->encoding = ENC7BIT; - t->use_disp = 0; - t->disposition = DISPINLINE; - - parameter_set_boundary(&t->parameter); - /* check if this can be extracted from private key somehow.... */ - parameter_setval(&t->parameter, "micalg", "sha1"); - parameter_setval(&t->parameter, "protocol", - "application/x-pkcs7-signature"); - - t->parts = a; - a = t; - - t->parts->next = body_new(); - t = t->parts->next; - t->type = TYPEAPPLICATION; - t->subtype = m_strdup("x-pkcs7-signature"); - t->filename = m_strdup(signedfile); - t->d_filename = m_strdup("smime.p7s"); - t->use_disp = 1; - t->disposition = DISPATTACH; - t->encoding = ENCBASE64; - t->unlink = 1; /* ok to remove this file after sending. */ - - return (a); - -} - - -/* - * Handling S/MIME - bodies. - */ - - -static -pid_t smime_invoke_verify (FILE ** smimein, FILE ** smimeout, - FILE ** smimeerr, int smimeinfd, int smimeoutfd, - int smimeerrfd, const char *fname, - const char *sig_fname, int opaque) -{ - return smime_invoke (smimein, smimeout, smimeerr, smimeinfd, smimeoutfd, - smimeerrfd, fname, sig_fname, NULL, NULL, NULL, NULL, - (opaque ? SmimeVerifyOpaqueCommand : - SmimeVerifyCommand)); -} - - -static -pid_t smime_invoke_decrypt (FILE ** smimein, FILE ** smimeout, - FILE ** smimeerr, int smimeinfd, int smimeoutfd, - int smimeerrfd, const char *fname) -{ - return smime_invoke (smimein, smimeout, smimeerr, smimeinfd, smimeoutfd, - smimeerrfd, fname, NULL, NULL, SmimeKeyToUse, - SmimeCertToUse, NULL, SmimeDecryptCommand); -} - - - -int smime_verify_one (BODY * sigbdy, STATE * s, const char *tempfile) -{ - char signedfile[_POSIX_PATH_MAX], smimeerrfile[_POSIX_PATH_MAX]; - FILE *fp = NULL, *smimeout = NULL, *smimeerr = NULL; - pid_t thepid; - int badsig = -1; - - long tmpoffset = 0; - ssize_t tmplength = 0; - int origType = sigbdy->type; - char *savePrefix = NULL; - - - snprintf (signedfile, sizeof (signedfile), "%s.sig", tempfile); - - /* decode to a tempfile, saving the original destination */ - fp = s->fpout; - if ((s->fpout = safe_fopen (signedfile, "w")) == NULL) { - mutt_perror (signedfile); - return -1; - } - /* decoding the attachment changes the size and offset, so save a copy - * of the "real" values now, and restore them after processing - */ - tmplength = sigbdy->length; - tmpoffset = sigbdy->offset; - - /* if we are decoding binary bodies, we don't want to prefix each - * line with the prefix or else the data will get corrupted. - */ - savePrefix = s->prefix; - s->prefix = NULL; - - mutt_decode_attachment (sigbdy, s); - - sigbdy->length = ftello (s->fpout); - sigbdy->offset = 0; - m_fclose(&s->fpout); - - /* restore final destination and substitute the tempfile for input */ - s->fpout = fp; - fp = s->fpin; - s->fpin = fopen (signedfile, "r"); - - /* restore the prefix */ - s->prefix = savePrefix; - - sigbdy->type = origType; - - smimeerr = m_tempfile(smimeerrfile, sizeof(smimeerrfile), NONULL(MCore.tmpdir), NULL); - if (!smimeerr) { - mutt_perror (smimeerrfile); - mutt_unlink (signedfile); - return -1; - } - - crypt_current_time (s, "OpenSSL"); - - if ((thepid = smime_invoke_verify (NULL, &smimeout, NULL, - -1, -1, fileno (smimeerr), - tempfile, signedfile, 0)) != -1) { - m_fclose(&smimeout); - - if (mutt_wait_filter (thepid)) - badsig = -1; - else { - char *line = NULL; - int lineno = 0; - ssize_t linelen; - - fflush (smimeerr); - rewind (smimeerr); - - line = mutt_read_line (line, &linelen, smimeerr, &lineno); - if (linelen && !m_strcasecmp(line, "verification successful")) - badsig = 0; - - p_delete(&line); - } - } - - fflush (smimeerr); - rewind (smimeerr); - mutt_copy_stream (smimeerr, s->fpout); - m_fclose(&smimeerr); - - state_attach_puts (_("[-- End of OpenSSL output --]\n\n"), s); - - mutt_unlink (signedfile); - mutt_unlink (smimeerrfile); - - sigbdy->length = tmplength; - sigbdy->offset = tmpoffset; - - /* restore the original source stream */ - m_fclose(&s->fpin); - s->fpin = fp; - - - return badsig; -} - - - - - -/* - This handles application/pkcs7-mime which can either be a signed - or an encrypted message. -*/ - -static BODY *smime_handle_entity (BODY * m, STATE * s, FILE * outFile) -{ - int len = 0; - int c; - long last_pos; - char buf[HUGE_STRING]; - char outfile[_POSIX_PATH_MAX], errfile[_POSIX_PATH_MAX]; - char tmpfname[_POSIX_PATH_MAX]; - char tmptmpfname[_POSIX_PATH_MAX]; - FILE *smimeout = NULL, *smimein = NULL, *smimeerr = NULL; - FILE *tmpfp = NULL, *tmpfp_buffer = NULL, *fpout = NULL; - struct stat info; - BODY *p = NULL; - pid_t thepid = -1; - unsigned int type = mutt_is_application_smime (m); - - if (!(type & APPLICATION_SMIME)) - return NULL; - - smimeout = m_tempfile (outfile, sizeof(outfile), NONULL(MCore.tmpdir), NULL); - if (!smimeout) { - mutt_perror (outfile); - return NULL; - } - - smimeerr = m_tempfile(errfile, sizeof(errfile), NONULL(MCore.tmpdir), NULL); - if (!smimeerr) { - mutt_perror (errfile); - m_fclose(&smimeout); - return NULL; - } - mutt_unlink (errfile); - - tmpfp = m_tempfile (tmpfname, sizeof(tmpfname), NONULL(MCore.tmpdir), NULL); - if (!tmpfp) { - mutt_perror (tmpfname); - m_fclose(&smimeout); - m_fclose(&smimeerr); - return NULL; - } - - fseeko (s->fpin, m->offset, 0); - last_pos = m->offset; - - mutt_copy_bytes (s->fpin, tmpfp, m->length); - m_fclose(&tmpfp); - - if ((type & ENCRYPT) && - (thepid = smime_invoke_decrypt (&smimein, NULL, NULL, -1, - fileno (smimeout), fileno (smimeerr), - tmpfname)) == -1) { - m_fclose(&smimeout); - mutt_unlink (tmpfname); - if (s->flags & M_DISPLAY) - state_attach_puts (_("[-- Error: unable to create OpenSSL subprocess! --]\n"), s); - return NULL; - } - else if ((type & SIGNOPAQUE) && - (thepid = smime_invoke_verify (&smimein, NULL, NULL, -1, - fileno (smimeout), - fileno (smimeerr), NULL, tmpfname, - SIGNOPAQUE)) == -1) { - m_fclose(&smimeout); - mutt_unlink (tmpfname); - if (s->flags & M_DISPLAY) - state_attach_puts (_("[-- Error: unable to create OpenSSL subprocess! --]\n"), s); - return NULL; - } - - - if (type & ENCRYPT) { - if (!smime_valid_passphrase ()) - smime_void_passphrase (); - fputs (SmimePass, smimein); - fputc ('\n', smimein); - } - - m_fclose(&smimein); - - mutt_wait_filter (thepid); - mutt_unlink (tmpfname); - - - if (s->flags & M_DISPLAY) { - rewind (smimeerr); - - if ((c = fgetc (smimeerr)) != EOF) { - ungetc (c, smimeerr); - - crypt_current_time (s, "OpenSSL"); - mutt_copy_stream (smimeerr, s->fpout); - state_attach_puts (_("[-- End of OpenSSL output --]\n\n"), s); - } - - if (type & ENCRYPT) - state_attach_puts (_("[-- The following data is S/MIME" - " encrypted --]\n"), s); - else - state_attach_puts (_("[-- The following data is S/MIME signed --]\n"), - s); - } - - if (smimeout) { - fflush (smimeout); - rewind (smimeout); - - if (outFile) - fpout = outFile; - else { - fpout = m_tempfile (tmptmpfname, sizeof(tmptmpfname), NONULL(MCore.tmpdir), NULL); - if (!fpout) { - mutt_perror (tmptmpfname); - m_fclose(&smimeout); - return NULL; - } - } - while (fgets (buf, sizeof (buf) - 1, smimeout) != NULL) { - len = m_strlen(buf); - if (len > 1 && buf[len - 2] == '\r') { - buf[len - 2] = '\n'; - buf[len - 1] = '\0'; - } - fputs (buf, fpout); - } - fflush (fpout); - rewind (fpout); - - - if ((p = mutt_read_mime_header (fpout, 0)) != NULL) { - fstat (fileno (fpout), &info); - p->length = info.st_size - p->offset; - - mutt_parse_part (fpout, p); - if (s->fpout) { - rewind (fpout); - tmpfp_buffer = s->fpin; - s->fpin = fpout; - mutt_body_handler (p, s); - s->fpin = tmpfp_buffer; - } - - } - m_fclose(&smimeout); - mutt_unlink (outfile); - - if (!outFile) { - m_fclose(&fpout); - mutt_unlink (tmptmpfname); - } - fpout = NULL; - } - - if (s->flags & M_DISPLAY) { - if (type & ENCRYPT) - state_attach_puts (_("\n[-- End of S/MIME encrypted data. --]\n"), s); - else - state_attach_puts (_("\n[-- End of S/MIME signed data. --]\n"), s); - } - - if (type & SIGNOPAQUE) { - char *line = NULL; - int lineno = 0; - ssize_t linelen; - - rewind (smimeerr); - - line = mutt_read_line (line, &linelen, smimeerr, &lineno); - if (linelen && !m_strcasecmp(line, "verification successful")) - m->goodsig = 1; - p_delete(&line); - } - else { - m->goodsig = p->goodsig; - m->badsig = p->badsig; - } - m_fclose(&smimeerr); - - return (p); -} - - - - - -int smime_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur) -{ - - - char tempfile[_POSIX_PATH_MAX]; - STATE s; - long tmpoffset = b->offset; - ssize_t tmplength = b->length; - int origType = b->type; - FILE *tmpfp = NULL; - int rv = 0; - - if (!mutt_is_application_smime (b)) - return -1; - - if (b->parts) - return -1; - - p_clear(&s, 1); - s.fpin = fpin; - fseeko (s.fpin, b->offset, 0); - - tmpfp = m_tempfile (tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); - if (!tmpfp) { - mutt_perror (_("Can't create temporary file")); - return (-1); - } - - mutt_unlink (tempfile); - s.fpout = tmpfp; - mutt_decode_attachment (b, &s); - fflush (tmpfp); - b->length = ftello (s.fpout); - b->offset = 0; - rewind (tmpfp); - s.fpin = tmpfp; - s.fpout = 0; - - *fpout = m_tempfile (tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); - if (!*fpout) { - mutt_perror (_("Can't create temporary file")); - rv = -1; - goto bail; - } - mutt_unlink (tempfile); - - if (!(*cur = smime_handle_entity (b, &s, *fpout))) { - rv = -1; - goto bail; - } - - (*cur)->goodsig = b->goodsig; - (*cur)->badsig = b->badsig; - -bail: - b->type = origType; - b->length = tmplength; - b->offset = tmpoffset; - - m_fclose(&tmpfp); - if (*fpout) - rewind (*fpout); - return (rv); -} - - -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; - - switch (mutt_multi_choice - (_("S/MIME (e)ncrypt, (s)ign, encrypt (w)ith, sign (a)s, (b)oth, or (c)lear? "), - _("eswabfc"))) { - case 1: /* (e)ncrypt */ - msg->security |= ENCRYPT; - msg->security &= ~SIGN; - break; - - case 3: /* encrypt (w)ith */ - { - int choice = 0; - msg->security |= ENCRYPT; - - do { - /* 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: - switch (choice = mutt_multi_choice (_("1: DES, 2: Triple-DES "), - _("dt"))) { - case 1: - m_strreplace(&SmimeCryptAlg, "des"); - break; - case 2: - m_strreplace(&SmimeCryptAlg, "des3"); - break; - } - break; - - case 2: - switch (choice = mutt_multi_choice (_("1: RC2-40, 2: RC2-64, 3: RC2-128 "), - _("468"))) { - case 1: - m_strreplace(&SmimeCryptAlg, "rc2-40"); - break; - case 2: - m_strreplace(&SmimeCryptAlg, "rc2-64"); - break; - case 3: - m_strreplace(&SmimeCryptAlg, "rc2-128"); - break; - } - break; - - case 3: - switch (choice = mutt_multi_choice (_("1: AES128, 2: AES192, 3: AES256 "), - _("895"))) { - case 1: - m_strreplace(&SmimeCryptAlg, "aes128"); - break; - case 2: - m_strreplace(&SmimeCryptAlg, "aes192"); - break; - case 3: - m_strreplace(&SmimeCryptAlg, "aes256"); - break; - } - break; - - case 4: /* (c)lear */ - p_delete(&SmimeCryptAlg); - /* fallback */ - case -1: /* Ctrl-G or Enter */ - choice = 0; - break; - } - } while (choice == -1); - } - break; - - case 2: /* (s)ign */ - - if (!SmimeDefaultKey) - mutt_message (_("Can't sign: No key specified. Use Sign As.")); - - else { - msg->security |= SIGN; - msg->security &= ~ENCRYPT; - } - break; - - case 4: /* sign (a)s */ - - if ((p = smime_ask_for_key (_("Sign as: "), NULL, 0))) { - m_strreplace(&SmimeDefaultKey, p); - - msg->security |= SIGN; - - /* probably need a different passphrase */ - crypt_smime_void_passphrase (); - } - - *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); -} diff --git a/lib-crypt/smime.h b/lib-crypt/smime.h deleted file mode 100644 index f127e06..0000000 --- a/lib-crypt/smime.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright notice from original mutt: - * Copyright (C) 2001,2002 Oliver Ehli - * Copyright (C) 2004 g10 Code GmbH - * - * This file is part of mutt-ng, see http://www.muttng.org/. - * It's licensed under the GNU General Public License, - * please see the file GPL in the top level source directory. - */ - - -#include "crypt.h" - -int smime_decrypt_mime (FILE *, FILE **, BODY *, BODY **); - -int smime_application_smime_handler (BODY *, STATE *); - - -BODY *smime_sign_message (BODY *); - -BODY *smime_build_smime_entity (BODY *, char *); - -int smime_verify_one (BODY *, STATE *, const char *); - - -int smime_verify_sender (HEADER *); - - -char *smime_get_field_from_db (char *, char *, short, short); - -void smime_getkeys (ENVELOPE *); - -char *smime_ask_for_key (char *, char *, short); - -char *smime_findKeys (address_t * to, address_t * cc, address_t * bcc); - -void smime_invoke_import (char *, char *); - -int smime_send_menu (HEADER * msg, int *redraw); diff --git a/mutt.h b/mutt.h index f676a9c..51e4ec2 100644 --- a/mutt.h +++ b/mutt.h @@ -166,7 +166,6 @@ enum { OPT_MIMEFWD, OPT_MIMEFWDREST, OPT_MOVE, - OPT_PGPMIMEAUTO, /* ask to revert to PGP/MIME when inline fails */ OPT_POPDELETE, OPT_POPRECONNECT, OPT_POSTPONE, @@ -354,8 +353,6 @@ enum { OPTPGPRETAINABLESIG, OPTFORWDECRYPT, OPTPGPSHOWUNUSABLE, - OPTPGPAUTOINLINE, - OPTPGPREPLYINLINE, /* news options */ diff --git a/send.c b/send.c index f786e5c..2da13d7 100644 --- a/send.c +++ b/send.c @@ -97,7 +97,7 @@ static void append_signature (FILE * f) fprintf (f, "\n%s", SignOffString); } - if (tmpfp = mutt_open_read(NONULL(MAlias.signature), &thepid)) { + if ((tmpfp = mutt_open_read(NONULL(MAlias.signature), &thepid))) { if (option (OPTSIGDASHES)) fputs ("\n-- \n", f); else if (SignOffString) @@ -1363,12 +1363,6 @@ int ci_send_message (int flags, /* send mode */ if (option (OPTCRYPTREPLYSIGNENCRYPTED) && cur && (cur->security & ENCRYPT)) msg->security |= SIGN; - if (msg->security & (ENCRYPT | SIGN)) { - if (option (OPTPGPAUTOINLINE)) - msg->security |= INLINE; - if (option (OPTPGPREPLYINLINE) && cur && (cur->security & INLINE)) - msg->security |= INLINE; - } if (msg->security) { /*