From: Moritz Schulte Date: Thu, 17 Jun 2004 20:36:13 +0000 (+0000) Subject: This is the sequel to the crypto modularization changes I did on X-Git-Tag: mutt-1-5-15-rel~173 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e48dd50afa44e0c6ee30f7ae6ebbe2a3d9179f7b;p=mutt This is the sequel to the crypto modularization changes I did on 2003-01-21. Moritz added another abstraction layer which cleans up the code and allows the crypto modules to use their own option menu. Everything should work as it used to but is now in a really good shape for part III, the Return of the GnuPG Easy Makers. -wk * crypt-mod-pgp-classic.c, crypt-mod-smime-classic.c, crypt-mod.c, crypt-mod.h: New files. * smime.c (smime_valid_passphrase, smime_send_menu): New functions. * smime.h: Removed macro: smime_valid_passphrase. Declared: smime_valid_passphrase, smime_send_menu. * pgp.c: Include "mutt_menu.h". (pgp_valid_passphrase, pgp_send_menu): New functions. * pgp.h: Removed macro: pgp_valid_passphrase. Declared: pgp_valid_passphrase, pgp_send_menu. * mutt_curses.h: Declare: mutt_need_hard_redraw. * mutt_crypt.h: Declare: crypt_pgp_valid_passphrase, crypt_pgp_send_menu, crypt_smime_valid_passphrase, crypt_smime_send_menu, crypt_init. Adjust WithCrypto definition since the GPGME backend does not exclude anymore the other `classic' backends. (KEYFLAG_ISX509): New symbol. * mutt.h (enum): New symbol: OPTCRYPTUSEGPGME. (struct body): New member: is_signed_data, warnsig. * main.c (main): Call crypt_init. * keymap.c (km_get_table): Support for MENU_KEY_SELECT_PGP and MENU_KEY_SELECT_SMIME. (Menus): Added entries fuer MENU_KEY_SELECT_PGP and MENU_KEY_SELECT_SMIME. (km_init): Create bindings for MENU_KEY_SELECT_PGP and MENU_KEY_SELECT_SMIME. * keymap.h (enum): New enum symbols: MENU_KEY_SELECT_PGP, MENU_KEY_SELECT_SMIME. * init.h: New configuration variable: crypt_use_gpgme. * compose.c (pgp_send_menu, smime_send_menu): Removed functions, they are now contained in the crypto backend modules. (mutt_compose_menu): Use crypt_pgp_send_menu and crypt_smime_send_menu instead pgp_send_menu and smime_send_menu. * cryptglue.c: Slightly rewritten in order to make use of the module mechanism used to access crypto backends. * curs_lib.c (mutt_need_hard_redraw): New function. * crypt.c (crypt_forget_passphrase): Adjust for new crypto backend interface. (crypt_valid_passphrase): Stripped, use calls to crypt_pgp_valid_passphrase and crypt_smime_valid_passphrase. --- diff --git a/Makefile.am b/Makefile.am index 66ce4135..38499f7f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,10 +28,10 @@ mutt_SOURCES = $(BUILT_SOURCES) \ score.c send.c sendlib.c signal.c sort.c \ status.c system.c thread.c charset.c history.c lib.c \ muttlib.c editmsg.c utf8.c mbyte.c wcwidth.c \ - url.c ascii.c mutt_idna.c + url.c ascii.c mutt_idna.c crypt-mod.c crypt-mod.h mutt_LDADD = @MUTT_LIB_OBJECTS@ @LIBOBJS@ $(LIBIMAP) $(MUTTLIBS) \ - $(INTLLIBS) $(LIBICONV) + $(INTLLIBS) $(LIBICONV) mutt_DEPENDENCIES = @MUTT_LIB_OBJECTS@ @LIBOBJS@ $(LIBIMAPDEPS) \ $(INTLDEPS) @@ -55,13 +55,14 @@ DEFS=-DPKGDATADIR=\"$(pkgdatadir)\" -DSYSCONFDIR=\"$(sysconfdir)\" \ INCLUDES=-I. -I$(top_srcdir) $(IMAP_INCLUDES) -Iintl -CPPFLAGS=@CPPFLAGS@ -I$(includedir) +CPPFLAGS=@CPPFLAGS@ -I$(includedir) -D_FILE_OFFSET_BITS=64 EXTRA_mutt_SOURCES = account.c md5c.c mutt_sasl.c mutt_socket.c mutt_ssl.c \ mutt_tunnel.c pop.c pop_auth.c pop_lib.c smime.c pgp.c pgpinvoke.c pgpkey.c \ pgplib.c sha1.c pgpmicalg.c gnupgparse.c resize.c dotlock.c remailer.c \ browser.h mbyte.h remailer.h url.h mutt_ssl_nss.c \ + crypt-mod-pgp-classic.c crypt-mod-smime-classic.c \ pgppacket.c mutt_idna.h EXTRA_DIST = COPYRIGHT GPL OPS OPS.PGP OPS.CRYPT OPS.SMIME TODO \ diff --git a/compose.c b/compose.c index bed25df7..8bd93b01 100644 --- a/compose.c +++ b/compose.c @@ -1,5 +1,6 @@ /* * Copyright (C) 1996-2000 Michael R. Elkins + * Copyright (C) 2004 g10 Code GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -162,167 +163,6 @@ static void redraw_crypt_lines (HEADER *msg) } - -static int pgp_send_menu (HEADER *msg, int *redraw) -{ - pgp_key_t p; - char input_signas[SHORT_STRING]; - - if (!(WithCrypto & APPLICATION_PGP)) - return msg->security; - - switch (mutt_multi_choice (_("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, (i)nline, or (f)orget it? "), - _("esabif"))) - { - case 1: /* (e)ncrypt */ - msg->security ^= ENCRYPT; - break; - - case 2: /* (s)ign */ - msg->security ^= SIGN; - break; - - case 3: /* sign (a)s */ - unset_option(OPTPGPCHECKTRUST); - - if ((p = crypt_pgp_ask_for_key (_("Sign as: "), NULL, - KEYFLAG_CANSIGN, PGP_PUBRING))) - { - snprintf (input_signas, sizeof (input_signas), "0x%s", - crypt_pgp_keyid (p)); - mutt_str_replace (&PgpSignAs, input_signas); - crypt_pgp_free_key (&p); - - msg->security |= SIGN; - - crypt_pgp_void_passphrase (); /* probably need a different passphrase */ - } - else - { - msg->security &= ~SIGN; - } - - *redraw = REDRAW_FULL; - break; - - case 4: /* (b)oth */ - if ((msg->security & (ENCRYPT | SIGN)) == (ENCRYPT | SIGN)) - msg->security = 0; - else - 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 */ - msg->security = 0; - break; - } - - if (msg->security) - { - if (! (msg->security & (ENCRYPT | SIGN))) - msg->security = 0; - else - msg->security |= APPLICATION_PGP; - } - - if(*redraw) - redraw_crypt_lines (msg); - return (msg->security); -} - - - -static int smime_send_menu (HEADER *msg, int *redraw) -{ - char *p; - - if (!(WithCrypto & APPLICATION_SMIME)) - return msg->security; - - switch (mutt_multi_choice (_("S/MIME (e)ncrypt, (s)ign, encrypt (w)ith, sign (a)s, (b)oth, or (f)orget it? "), - _("eswabf"))) - { - case 1: /* (e)ncrypt */ - msg->security |= ENCRYPT; - break; - - case 3: /* encrypt (w)ith */ - msg->security |= ENCRYPT; - switch (mutt_multi_choice (_("1: DES, 2: Triple-DES, 3: RC2-40," - " 4: RC2-64, 5: RC2-128, or (f)orget it? "), - _("12345f"))) { - case 1: - mutt_str_replace (&SmimeCryptAlg, "des"); - break; - case 2: - mutt_str_replace (&SmimeCryptAlg, "des3"); - break; - case 3: - mutt_str_replace (&SmimeCryptAlg, "rc2-40"); - break; - case 4: - mutt_str_replace (&SmimeCryptAlg, "rc2-64"); - break; - case 5: - mutt_str_replace (&SmimeCryptAlg, "rc2-128"); - break; - case 6: /* forget it */ - break; - } - break; - - case 2: /* (s)ign */ - - if(!SmimeDefaultKey) - mutt_message("Can\'t sign: No key specified. use sign(as)."); - else - msg->security |= SIGN; - break; - - case 4: /* sign (a)s */ - - if ((p = crypt_smime_ask_for_key (_("Sign as: "), NULL, 0))) { - p[mutt_strlen (p)-1] = '\0'; - mutt_str_replace (&SmimeDefaultKey, p); - - msg->security |= SIGN; - - /* probably need a different passphrase */ - crypt_smime_void_passphrase (); - } - else - msg->security &= ~SIGN; - - *redraw = REDRAW_FULL; - break; - - case 5: /* (b)oth */ - msg->security = ENCRYPT | SIGN; - break; - - case 6: /* (f)orget it */ - msg->security = 0; - break; - } - - if (msg->security && msg->security != APPLICATION_SMIME) - msg->security |= APPLICATION_SMIME; - else - msg->security = 0; - - if(*redraw) - redraw_crypt_lines (msg); - return (msg->security); -} - - #ifdef MIXMASTER static void redraw_mix_line (LIST *chain) @@ -1344,7 +1184,7 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */ } msg->security = 0; } - msg->security = pgp_send_menu (msg, &menu->redraw); + msg->security = crypt_pgp_send_menu (msg, &menu->redraw); redraw_crypt_lines (msg); break; @@ -1369,7 +1209,7 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */ } msg->security = 0; } - msg->security = smime_send_menu(msg, &menu->redraw); + msg->security = crypt_smime_send_menu(msg, &menu->redraw); redraw_crypt_lines (msg); break; diff --git a/configure.in b/configure.in index 892f2f60..5ce55a95 100644 --- a/configure.in +++ b/configure.in @@ -105,7 +105,7 @@ else AC_DEFINE(CRYPT_BACKEND_CLASSIC_PGP,1, [ Define if you want classic PGP support. ]) PGPAUX_TARGET="pgpring pgpewrap" - MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS pgp.o pgpinvoke.o pgpkey.o pgplib.o gnupgparse.o pgpmicalg.o pgppacket.o" + MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS pgp.o pgpinvoke.o pgpkey.o pgplib.o gnupgparse.o pgpmicalg.o pgppacket.o crypt-mod-pgp-classic.o" fi AC_ARG_ENABLE(smime, [ --disable-smime Disable SMIME support], @@ -117,7 +117,7 @@ else if test x$have_smime != xno ; then AC_DEFINE(CRYPT_BACKEND_CLASSIC_SMIME,1, [ Define if you want clasic S/MIME support. ]) - MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS smime.o " + MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS smime.o crypt-mod-smime-classic.o" SMIMEAUX_TARGET="smime_keys" fi diff --git a/crypt-mod-pgp-classic.c b/crypt-mod-pgp-classic.c new file mode 100644 index 00000000..083a82f1 --- /dev/null +++ b/crypt-mod-pgp-classic.c @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2004 g10 Code GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + */ + +/* + This is a crytpo module wrapping the classic pgp code. + */ + +#include "crypt-mod.h" +#include "pgp.h" + +static void crypt_mod_pgp_void_passphrase (void) +{ + pgp_void_passphrase (); +} + +static int crypt_mod_pgp_valid_passphrase (void) +{ + return pgp_valid_passphrase (); +} + +static int crypt_mod_pgp_decrypt_mime (FILE *a, FILE **b, BODY *c, BODY **d) +{ + return pgp_decrypt_mime (a, b, c, d); +} +static void crypt_mod_pgp_application_handler (BODY *m, STATE *s) +{ + pgp_application_pgp_handler (m, s); +} + +static char *crypt_mod_pgp_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) +{ + return pgp_findKeys (to, cc, bcc); +} + +static BODY *crypt_mod_pgp_sign_message (BODY *a) +{ + return pgp_sign_message (a); +} + +static int crypt_mod_pgp_verify_one (BODY *sigbdy, STATE *s, const char *tempf) +{ + return pgp_verify_one (sigbdy, s, tempf); +} + +static int crypt_mod_pgp_send_menu (HEADER *msg, int *redraw) +{ + return pgp_send_menu (msg, redraw); +} + +static BODY *crypt_mod_pgp_encrypt_message (BODY *a, char *keylist, int sign) +{ + return pgp_encrypt_message (a, keylist, sign); +} + +static BODY *crypt_mod_pgp_make_key_attachment (char *tempf) +{ + return pgp_make_key_attachment (tempf); +} + +static int crypt_mod_pgp_check_traditional (FILE *fp, BODY *b, int tagged_only) +{ + return pgp_check_traditional (fp, b, tagged_only); +} + +static BODY *crypt_mod_pgp_traditional_encryptsign (BODY *a, int flags, char *keylist) +{ + return pgp_traditional_encryptsign (a, flags, keylist); +} + +static void crypt_mod_pgp_encrypted_handler (BODY *m, STATE *s) +{ + pgp_encrypted_handler (m, s); +} + +static void crypt_mod_pgp_invoke_getkeys (ADDRESS *addr) +{ + pgp_invoke_getkeys (addr); +} + +static void crypt_mod_pgp_invoke_import (const char *fname) +{ + pgp_invoke_import (fname); +} + +static void crypt_mod_pgp_extract_keys_from_attachment_list (FILE *fp, int tag, BODY *top) +{ + pgp_extract_keys_from_attachment_list (fp, tag, top); +} + +struct crypt_module_specs crypt_mod_pgp_classic = + { APPLICATION_PGP, + { + NULL, /* init */ + crypt_mod_pgp_void_passphrase, + crypt_mod_pgp_valid_passphrase, + crypt_mod_pgp_decrypt_mime, + crypt_mod_pgp_application_handler, + crypt_mod_pgp_encrypted_handler, + crypt_mod_pgp_findkeys, + crypt_mod_pgp_sign_message, + crypt_mod_pgp_verify_one, + crypt_mod_pgp_send_menu, + + crypt_mod_pgp_encrypt_message, + crypt_mod_pgp_make_key_attachment, + crypt_mod_pgp_check_traditional, + crypt_mod_pgp_traditional_encryptsign, + crypt_mod_pgp_invoke_getkeys, + crypt_mod_pgp_invoke_import, + crypt_mod_pgp_extract_keys_from_attachment_list, + + NULL, /* smime_getkeys */ + NULL, /* smime_verify_sender */ + NULL, /* smime_build_smime_entity */ + NULL, /* smime_invoke_import */ + } + }; diff --git a/crypt-mod-smime-classic.c b/crypt-mod-smime-classic.c new file mode 100644 index 00000000..e6ab753b --- /dev/null +++ b/crypt-mod-smime-classic.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2004 g10 Code GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + */ + +/* + This is a crytpo module wrapping the classic smime code. + */ + +#include "crypt-mod.h" +#include "smime.h" + +static void crypt_mod_smime_void_passphrase (void) +{ + smime_void_passphrase (); +} + +static int crypt_mod_smime_valid_passphrase (void) +{ + return smime_valid_passphrase (); +} + +static int crypt_mod_smime_decrypt_mime (FILE *a, FILE **b, BODY *c, BODY **d) +{ + return smime_decrypt_mime (a, b, c, d); +} +static void crypt_mod_smime_application_handler (BODY *m, STATE *s) +{ + smime_application_smime_handler (m, s); +} + +static char *crypt_mod_smime_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) +{ + return smime_findKeys (to, cc, bcc); +} + +static BODY *crypt_mod_smime_sign_message (BODY *a) +{ + return smime_sign_message (a); +} + +static int crypt_mod_smime_verify_one (BODY *sigbdy, STATE *s, const char *tempf) +{ + return smime_verify_one (sigbdy, s, tempf); +} + +static int crypt_mod_smime_send_menu (HEADER *msg, int *redraw) +{ + return smime_send_menu (msg, redraw); +} + +static void crypt_mod_smime_getkeys (ENVELOPE *env) +{ + smime_getkeys (env); +} + +static int crypt_mod_smime_verify_sender (HEADER *h) +{ + return smime_verify_sender (h); +} + +static BODY *crypt_mod_smime_build_smime_entity (BODY *a, char *certlist) +{ + return smime_build_smime_entity (a, certlist); +} + +static void crypt_mod_smime_invoke_import (char *infile, char *mailbox) +{ + smime_invoke_import (infile, mailbox); +} + + +struct crypt_module_specs crypt_mod_smime_classic = + { APPLICATION_SMIME, + { + NULL, /* init */ + crypt_mod_smime_void_passphrase, + crypt_mod_smime_valid_passphrase, + crypt_mod_smime_decrypt_mime, + crypt_mod_smime_application_handler, + NULL, /* encrypted_handler */ + crypt_mod_smime_findkeys, + crypt_mod_smime_sign_message, + crypt_mod_smime_verify_one, + crypt_mod_smime_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 */ + + crypt_mod_smime_getkeys, + crypt_mod_smime_verify_sender, + crypt_mod_smime_build_smime_entity, + crypt_mod_smime_invoke_import, + } + }; diff --git a/crypt-mod.c b/crypt-mod.c new file mode 100644 index 00000000..356e3e9c --- /dev/null +++ b/crypt-mod.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2004 g10 Code GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + */ + +#include "crypt-mod.h" + +/* A type an a variable to keep track of registered crypto modules. */ +typedef struct crypt_module *crypt_module_t; + +struct crypt_module +{ + crypt_module_specs_t specs; + crypt_module_t next, *prevp; +}; + +static crypt_module_t modules; + +/* Register a new crypto module. */ +void crypto_module_register (crypt_module_specs_t specs) +{ + crypt_module_t module_new = safe_malloc (sizeof (*module_new)); + + module_new->specs = specs; + module_new->next = modules; + if (modules) + modules->prevp = &module_new->next; + modules = module_new; +} + +/* Return the crypto module specs for IDENTIFIER. This function is + usually used via the CRYPT_MOD_CALL[_CHECK] macros. */ +crypt_module_specs_t crypto_module_lookup (int identifier) +{ + crypt_module_t module = modules; + + while (module && (module->specs->identifier != identifier)) + module = module->next; + + return module ? module->specs : NULL; +} diff --git a/crypt-mod.h b/crypt-mod.h new file mode 100644 index 00000000..4f69c3e8 --- /dev/null +++ b/crypt-mod.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2004 g10 Code GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + */ + +#ifndef CRYPTOGRAPHY_H +#define CRYPTOGRAPHY_H + +#include "mutt.h" +#include "mutt_crypt.h" + +#define CRYPTO_SUPPORT(identifier) (WithCrypto & APPLICATION_ ## identifier) + + +/* + Type defintions for crypto module functions. + */ +typedef void (*crypt_func_void_passphrase_t) (void); +typedef int (*crypt_func_valid_passphrase_t) (void); + +typedef int (*crypt_func_decrypt_mime_t) (FILE *a, FILE **b, + BODY *c, BODY **d); + +typedef void (*crypt_func_application_handler_t) (BODY *m, STATE *s); +typedef void (*crypt_func_encrypted_handler_t) (BODY *m, STATE *s); + +typedef void (*crypt_func_pgp_invoke_getkeys_t) (ADDRESS *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 *to, + ADDRESS *cc, ADDRESS *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); + + +/* + A structure to keep all crypto module fucntions together. + */ +typedef struct crypt_module_functions +{ + /* Common/General functions. */ + crypt_func_init_t init; + crypt_func_void_passphrase_t void_passphrase; + crypt_func_valid_passphrase_t valid_passphrase; + 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_functions_t; + + +/* + A structure to decribe a crypto module. + */ +typedef struct crypt_module_specs +{ + int identifier; /* Identifying bit. */ + crypt_module_functions_t functions; +} *crypt_module_specs_t; + + + +/* + High Level crypto module interface. + */ + +void crypto_module_register (crypt_module_specs_t specs); +crypt_module_specs_t crypto_module_lookup (int identifier); + +/* If the crypto module identifier by IDENTIFIER has been registered, + call its function FUNC. Do nothing else. This may be used as an + expression. */ +#define CRYPT_MOD_CALL_CHECK(identifier, func) \ + (crypto_module_lookup (APPLICATION_ ## identifier) \ + && (crypto_module_lookup (APPLICATION_ ## identifier))->functions.func) + +/* Call the function FUNC in the crypto module identified by + IDENTIFIER. This may be used as an expression. */ +#define CRYPT_MOD_CALL(identifier, func) \ + *(crypto_module_lookup (APPLICATION_ ## identifier))->functions.func + +#endif diff --git a/crypt.c b/crypt.c index fe5dc2c4..dfb09741 100644 --- a/crypt.c +++ b/crypt.c @@ -4,6 +4,7 @@ * Copyright (C) 2001 Thomas Roessler * Oliver Ehli * Copyright (C) 2003 Werner Koch + * Copyright (C) 2004 g10code GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -107,54 +108,19 @@ static void disable_coredumps (void) int crypt_valid_passphrase(int flags) { time_t now = time (NULL); + int ret = 0; # if defined(HAVE_SETRLIMIT) &&(!defined(DEBUG)) disable_coredumps (); # endif if ((WithCrypto & APPLICATION_PGP) && (flags & APPLICATION_PGP)) - { - extern char PgpPass[STRING]; - extern time_t PgpExptime; - - if (pgp_use_gpg_agent()) - { - *PgpPass = 0; - return 1; /* handled by gpg-agent */ - } - - if (now < PgpExptime) return 1; /* just use the cached copy. */ - crypt_pgp_void_passphrase (); - - if (mutt_get_password (_("Enter PGP passphrase:"), - PgpPass, sizeof (PgpPass)) == 0) - { - PgpExptime = time (NULL) + PgpTimeout; - return (1); - } - else - PgpExptime = 0; - } + ret = crypt_pgp_valid_passphrase (); if ((WithCrypto & APPLICATION_SMIME) && (flags & APPLICATION_SMIME)) - { - extern char SmimePass[STRING]; - extern time_t SmimeExptime; - - if (now < SmimeExptime) return (1); - crypt_smime_void_passphrase (); - - if (mutt_get_password (_("Enter SMIME passphrase:"), SmimePass, - sizeof (SmimePass)) == 0) - { - SmimeExptime = time (NULL) + SmimeTimeout; - return (1); - } - else - SmimeExptime = 0; - } + ret = crypt_smime_valid_passphrase (); - return (0); + return ret; } @@ -275,6 +241,7 @@ int mutt_protect (HEADER *msg, char *keylist) /* destroy temporary signature envelope when doing retainable * signatures. + */ if (flags != msg->security) { diff --git a/cryptglue.c b/cryptglue.c index ce818603..f8ff4793 100644 --- a/cryptglue.c +++ b/cryptglue.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2003 Werner Koch + * Copyright (C) 2004 g10 Code GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,117 +18,92 @@ */ /* - This file dispatches the generic crytpo functions to the implemented - backend or provides dummy stubs. Note, that some generic functions are - handled in crypt.c. + This file dispatches the generic crypto functions to the + implemented backend or provides dummy stubs. Note, that some + generic functions are handled in crypt.c. */ +/* Note: This file has been changed to make use of the new module + system. Consequently there's a 1:1 mapping between the functions + contained in this file and the functions implemented by the crypto + modules. */ + #include "mutt.h" #include "mutt_crypt.h" -/* Make sure those macros are not defined. */ -#undef BFNC_PGP_VOID_PASSPHRASE -#undef BFNC_PGP_DECRYPT_MIME -#undef BFNC_PGP_APPLICATION_PGP_HANDLER -#undef BFNC_PGP_ENCRYPTED_HANDLER -#undef BFNC_PGP_INVOKE_GETKEYS -#undef BFNC_PGP_ASK_FOR_KEY -#undef BNFC_PGP_CHECK_TRADITIONAL -#undef BFNC_PGP_TRADITIONAL_ENCRYPTSIGN -#undef BFNC_PGP_FREE_KEY -#undef BFNC_PGP_MAKE_KEY_ATTACHMENT -#undef BFNC_PGP_FINDKEYS -#undef BFNC_PGP_SIGN_MESSAGE -#undef BFNC_PGP_ENCRYPT_MESSAGE -#undef BFNC_PGP_INVOKE_IMPORT -#undef BFNC_PGP_VERIFY_ONE -#undef BFNC_PGP_KEYID -#undef BFNC_PGP_EXTRACT_KEYS_FROM_ATTACHMENT_LIST - -#undef BFNC_SMIME_VOID_PASSPHRASE -#undef BFNC_SMIME_DECRYPT_MIME -#undef BFNC_SMIME_APPLICATION_SMIME_HANDLER -#undef BFNC_SMIME_GETKEYS -#undef BFNC_SMIME_VERIFY_SENDER -#undef BFNC_SMIME_ASK_FOR_KEY -#undef BFNC_SMIME_FINDKEYS -#undef BFNC_SMIME_SIGN_MESSAGE -#undef BFNC_SMIME_BUILD_SMIME_ENTITY -#undef BFNC_SMIME_INVOKE_IMPORT -#undef BFNC_SMIME_VERIFY_ONE - - -/* The PGP backend */ -#if defined (CRYPT_BACKEND_CLASSIC_PGP) -# include "pgp.h" -# define BFNC_PGP_VOID_PASSPHRASE pgp_void_passphrase -# define BFNC_PGP_DECRYPT_MIME pgp_decrypt_mime -# define BFNC_PGP_APPLICATION_PGP_HANDLER pgp_application_pgp_handler -# define BFNC_PGP_ENCRYPTED_HANDLER pgp_encrypted_handler -# define BFNC_PGP_INVOKE_GETKEYS pgp_invoke_getkeys -# define BFNC_PGP_ASK_FOR_KEY pgp_ask_for_key -# define BNFC_PGP_CHECK_TRADITIONAL pgp_check_traditional -# define BFNC_PGP_TRADITIONAL_ENCRYPTSIGN pgp_traditional_encryptsign -# define BFNC_PGP_FREE_KEY pgp_free_key -# define BFNC_PGP_MAKE_KEY_ATTACHMENT pgp_make_key_attachment -# define BFNC_PGP_FINDKEYS pgp_findKeys -# define BFNC_PGP_SIGN_MESSAGE pgp_sign_message -# define BFNC_PGP_ENCRYPT_MESSAGE pgp_encrypt_message -# define BFNC_PGP_INVOKE_IMPORT pgp_invoke_import -# define BFNC_PGP_VERIFY_ONE pgp_verify_one -# define BFNC_PGP_KEYID pgp_keyid -# define BFNC_PGP_EXTRACT_KEYS_FROM_ATTACHMENT_LIST \ - pgp_extract_keys_from_attachment_list - - -#elif defined (CRYPT_BACKEND_GPGME) -# include "crypt-gpgme.h" -# define BFNC_PGP_VOID_PASSPHRASE NULL /* not required */ -# define BFNC_PGP_DECRYPT_MIME gpg_pgp_decrypt_mime - -#endif /* PGP backend */ - - -/* The SMIME backend */ -#ifdef CRYPT_BACKEND_CLASSIC_SMIME -# include "smime.h" -# define BFNC_SMIME_VOID_PASSPHRASE smime_void_passphrase -# define BFNC_SMIME_DECRYPT_MIME smime_decrypt_mime -# define BFNC_SMIME_APPLICATION_SMIME_HANDLER smime_application_smime_handler -# define BFNC_SMIME_GETKEYS smime_getkeys -# define BFNC_SMIME_VERIFY_SENDER smime_verify_sender -# define BFNC_SMIME_ASK_FOR_KEY smime_ask_for_key -# define BFNC_SMIME_FINDKEYS smime_findKeys -# define BFNC_SMIME_SIGN_MESSAGE smime_sign_message -# define BFNC_SMIME_BUILD_SMIME_ENTITY smime_build_smime_entity -# define BFNC_SMIME_INVOKE_IMPORT smime_invoke_import -# define BFNC_SMIME_VERIFY_ONE smime_verify_one - -#elif defined (CRYPT_BACKEND_GPGME) - /* Already included above (gpgme supports both). */ -# define BFNC_SMIME_VOID_PASSPHRASE NULL /* not required */ - -#endif /* SMIME backend */ +#include "crypt-mod.h" - /* Generic */ +#ifdef CRYPT_BACKEND_CLASSIC_PGP +extern struct crypt_module_specs crypt_mod_pgp_classic; +#endif + +#ifdef CRYPT_BACKEND_CLASSIC_SMIME +extern struct crypt_module_specs crypt_mod_smime_classic; +#endif + +#ifdef CRYPT_BACKEND_GPGME +extern struct crypt_module_specs crypt_mod_pgp_gpgme; +extern struct crypt_module_specs crypt_mod_smime_gpgme; +#endif + +void crypt_init (void) +{ +#ifdef CRYPT_BACKEND_CLASSIC_PGP + if ( +#ifdef CRYPT_BACKEND_GPGME + (! option (OPTCRYPTUSEGPGME)) +#else + 1 +#endif + ) + crypto_module_register (&crypt_mod_pgp_classic); +#endif + +#ifdef CRYPT_BACKEND_CLASSIC_SMIME + if ( +#ifdef CRYPT_BACKEND_GPGME + (! option (OPTCRYPTUSEGPGME)) +#else + 1 +#endif + ) + crypto_module_register (&crypt_mod_smime_classic); +#endif + + if (option (OPTCRYPTUSEGPGME)) + { +#ifdef CRYPT_BACKEND_GPGME + crypto_module_register (&crypt_mod_pgp_gpgme); + crypto_module_register (&crypt_mod_smime_gpgme); +#else + mutt_message (_("\"crypt_use_gpgme\" set" + " but not build with GPGME support.")); +#endif + } + +#if defined CRYPT_BACKEND_CLASSIG_PGP || defined CRYPT_BACKEND_CLASSIG_SMIME || defined CRYPT_BACKEND_GPGME + if (CRYPT_MOD_CALL_CHECK (PGP, init)) + (CRYPT_MOD_CALL (PGP, init)) (); + + if (CRYPT_MOD_CALL_CHECK (SMIME, init)) + (CRYPT_MOD_CALL (SMIME, init)) (); +#endif +} + + /* Show a message that a backend will be invoked. */ void crypt_invoke_message (int type) { -#if defined (CRYPT_BACKEND_CLASSIC_PGP) || defined(CRYPT_BACKEND_CLASSIC_SMIME) - if ((type & APPLICATION_PGP)) + if ((WithCrypto & APPLICATION_PGP) && (type & APPLICATION_PGP)) mutt_message _("Invoking PGP..."); - if ((type & APPLICATION_SMIME)) - mutt_message _("Invoking OpenSSL..."); -#elif defined (CRYPT_BACKEND_GPGME) - if ((type & APPLICATION_PGP) || (type & APPLICATION_SMIME) ) - mutt_message _("Invoking GnuPG..."); -#endif + else if ((WithCrypto & APPLICATION_SMIME) && (type & APPLICATION_SMIME)) + mutt_message _("Invoking SMIME..."); } @@ -142,163 +118,136 @@ void crypt_invoke_message (int type) /* Reset a PGP passphrase */ void crypt_pgp_void_passphrase (void) { -#ifdef BFNC_PGP_VOID_PASSPHRASE - BFNC_PGP_VOID_PASSPHRASE (); -#endif + if (CRYPT_MOD_CALL_CHECK (PGP, void_passphrase)) + (CRYPT_MOD_CALL (PGP, void_passphrase)) (); } +int crypt_pgp_valid_passphrase (void) +{ + if (CRYPT_MOD_CALL_CHECK (PGP, valid_passphrase)) + return (CRYPT_MOD_CALL (PGP, valid_passphrase)) (); + + return 0; +} + + /* Decrypt a PGP/MIME message. */ int crypt_pgp_decrypt_mime (FILE *a, FILE **b, BODY *c, BODY **d) { -#ifdef BFNC_PGP_DECRYPT_MIME - return BFNC_PGP_DECRYPT_MIME (a, b, c, d); -#else - return -1; /* error */ -#endif + 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. */ void crypt_pgp_application_pgp_handler (BODY *m, STATE *s) { -#ifdef BFNC_PGP_APPLICATION_PGP_HANDLER - BFNC_PGP_APPLICATION_PGP_HANDLER (m, s); -#endif + if (CRYPT_MOD_CALL_CHECK (PGP, application_handler)) + (CRYPT_MOD_CALL (PGP, application_handler)) (m, s); } /* MIME handler for an PGP/MIME encrypted message. */ void crypt_pgp_encrypted_handler (BODY *a, STATE *s) { -#ifdef BFNC_PGP_ENCRYPTED_HANDLER - BFNC_PGP_ENCRYPTED_HANDLER (a, s); -#endif + if (CRYPT_MOD_CALL_CHECK (PGP, encrypted_handler)) + (CRYPT_MOD_CALL (PGP, encrypted_handler)) (a, s); } /* fixme: needs documentation. */ void crypt_pgp_invoke_getkeys (ADDRESS *addr) { -#ifdef BFNC_PGP_INVOKE_GETKEYS - BFNC_PGP_INVOKE_GETKEYS (addr); -#endif -} - -/* Ask for a PGP key. */ -pgp_key_t crypt_pgp_ask_for_key (char *tag, char *whatfor, - short abilities, pgp_ring_t keyring) -{ -#ifdef BFNC_PGP_ASK_FOR_KEY - return BFNC_PGP_ASK_FOR_KEY (tag, whatfor, abilities, keyring); -#else - return NULL; -#endif + 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) { -#ifdef BNFC_PGP_CHECK_TRADITIONAL - return BNFC_PGP_CHECK_TRADITIONAL (fp, b, tagged_only); -#else - return 0; /* no */ -#endif + 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) { -#ifdef BFNC_PGP_TRADITIONAL_ENCRYPTSIGN - return BFNC_PGP_TRADITIONAL_ENCRYPTSIGN (a, flags, keylist); -#else - return NULL; -#endif -} + if (CRYPT_MOD_CALL_CHECK (PGP, pgp_traditional_encryptsign)) + return (CRYPT_MOD_CALL (PGP, pgp_traditional_encryptsign)) (a, flags, keylist); -/* Release pgp key KPP. */ -void crypt_pgp_free_key (pgp_key_t *kpp) -{ -#ifdef BFNC_PGP_FREE_KEY - BFNC_PGP_FREE_KEY (kpp); -#endif + return NULL; } - /* Generate a PGP public key attachment. */ BODY *crypt_pgp_make_key_attachment (char *tempf) { -#ifdef BFNC_PGP_MAKE_KEY_ATTACHMENT - return BFNC_PGP_MAKE_KEY_ATTACHMENT (tempf); -#else - return NULL; /* error */ -#endif + 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 *to, ADDRESS *cc, ADDRESS *bcc) { -#ifdef BFNC_PGP_FINDKEYS - return BFNC_PGP_FINDKEYS (to, cc, bcc); -#else + if (CRYPT_MOD_CALL_CHECK (PGP, findkeys)) + return (CRYPT_MOD_CALL (PGP, findkeys)) (to, cc, bcc); + return NULL; -#endif } /* Create a new body with a PGP signed message from A. */ BODY *crypt_pgp_sign_message (BODY *a) { -#ifdef BFNC_PGP_SIGN_MESSAGE - return BFNC_PGP_SIGN_MESSAGE (a); -#else + if (CRYPT_MOD_CALL_CHECK (PGP, sign_message)) + return (CRYPT_MOD_CALL (PGP, sign_message)) (a); + return NULL; -#endif } /* 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) { -#ifdef BFNC_PGP_ENCRYPT_MESSAGE - return BFNC_PGP_ENCRYPT_MESSAGE (a, keylist, sign); -#else + if (CRYPT_MOD_CALL_CHECK (PGP, pgp_encrypt_message)) + return (CRYPT_MOD_CALL (PGP, pgp_encrypt_message)) (a, keylist, sign); + return NULL; -#endif } /* Invoke the PGP command to import a key. */ void crypt_pgp_invoke_import (const char *fname) { -#ifdef BFNC_PGP_INVOKE_IMPORT - BFNC_PGP_INVOKE_IMPORT (fname); -#endif + 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) { -#ifdef BFNC_PGP_VERIFY_ONE - return BFNC_PGP_VERIFY_ONE (sigbdy, s, tempf); -#else + if (CRYPT_MOD_CALL_CHECK (PGP, verify_one)) + return (CRYPT_MOD_CALL (PGP, verify_one)) (sigbdy, s, tempf); + return -1; -#endif } -/* Access the keyID in K. */ -char *crypt_pgp_keyid (pgp_key_t k) +int crypt_pgp_send_menu (HEADER *msg, int *redraw) { -#ifdef BFNC_PGP_KEYID - return pgp_keyid (k); -#else - return "?"; -#endif + 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) { -#ifdef BFNC_PGP_EXTRACT_KEYS_FROM_ATTACHMENT_LIST - BFNC_PGP_EXTRACT_KEYS_FROM_ATTACHMENT_LIST (fp, tag, top); -#endif + 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); } @@ -313,104 +262,105 @@ void crypt_pgp_extract_keys_from_attachment_list (FILE *fp, int tag, BODY *top) /* Reset an SMIME passphrase */ void crypt_smime_void_passphrase (void) { -#ifdef BFNC_SMIME_VOID_PASSPHRASE - BFNC_SMIME_VOID_PASSPHRASE (); -#endif + if (CRYPT_MOD_CALL_CHECK (SMIME, void_passphrase)) + (CRYPT_MOD_CALL (SMIME, void_passphrase)) (); } +int crypt_smime_valid_passphrase (void) +{ + if (CRYPT_MOD_CALL_CHECK (SMIME, valid_passphrase)) + return (CRYPT_MOD_CALL (SMIME, valid_passphrase)) (); + + return 0; +} /* Decrypt am S/MIME message. */ int crypt_smime_decrypt_mime (FILE *a, FILE **b, BODY *c, BODY **d) { -#ifdef BFNC_SMIME_DECRYPT_MIME - return BFNC_SMIME_DECRYPT_MIME (a, b, c, d); -#else - return -1; /* error */ -#endif + 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. */ void crypt_smime_application_smime_handler (BODY *m, STATE *s) { -#ifdef BFNC_SMIME_APPLICATION_SMIME_HANDLER - BFNC_SMIME_APPLICATION_SMIME_HANDLER (m, s); -#endif + if (CRYPT_MOD_CALL_CHECK (SMIME, application_handler)) + (CRYPT_MOD_CALL (SMIME, application_handler)) (m, s); +} + +/* MIME handler for an PGP/MIME encrypted message. */ +void crypt_smime_encrypted_handler (BODY *a, STATE *s) +{ + if (CRYPT_MOD_CALL_CHECK (SMIME, encrypted_handler)) + (CRYPT_MOD_CALL (SMIME, encrypted_handler)) (a, s); } /* fixme: Needs documentation. */ void crypt_smime_getkeys (ENVELOPE *env) { -#ifdef BFNC_SMIME_GETKEYS - BFNC_SMIME_GETKEYS (env); -#endif + 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) { -#ifdef BFNC_SMIME_VERIFY_SENDER - return BFNC_SMIME_VERIFY_SENDER (h); -#else - return 1; /* yes */ -#endif -} + if (CRYPT_MOD_CALL_CHECK (SMIME, smime_verify_sender)) + return (CRYPT_MOD_CALL (SMIME, smime_verify_sender)) (h); -/* Ask for an SMIME key. */ -char *crypt_smime_ask_for_key (char *prompt, char *mailbox, short public) -{ -#ifdef BFNC_SMIME_ASK_FOR_KEY - return BFNC_SMIME_ASK_FOR_KEY (prompt, mailbox, public); -#else - return NULL; /* error */ -#endif + 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 *to, ADDRESS *cc, ADDRESS *bcc) { -#ifdef BFNC_SMIME_FINDKEYS - return BFNC_SMIME_FINDKEYS (to, cc, bcc); -#else + if (CRYPT_MOD_CALL_CHECK (SMIME, findkeys)) + return (CRYPT_MOD_CALL (SMIME, findkeys)) (to, cc, bcc); + return NULL; -#endif } /* fixme: Needs documentation. */ BODY *crypt_smime_sign_message (BODY *a) { -#ifdef BFNC_SMIME_SIGN_MESSAGE - return BFNC_SMIME_SIGN_MESSAGE (a); -#else + if (CRYPT_MOD_CALL_CHECK (SMIME, sign_message)) + return (CRYPT_MOD_CALL (SMIME, sign_message)) (a); + return NULL; -#endif } /* fixme: needs documentation. */ BODY *crypt_smime_build_smime_entity (BODY *a, char *certlist) { -#ifdef BFNC_SMIME_BUILD_SMIME_ENTITY - return BFNC_SMIME_BUILD_SMIME_ENTITY (a, certlist); -#else + if (CRYPT_MOD_CALL_CHECK (SMIME, smime_build_smime_entity)) + return (CRYPT_MOD_CALL (SMIME, smime_build_smime_entity)) (a, certlist); + return NULL; -#endif } /* Add a certificate and update index file (externally). */ void crypt_smime_invoke_import (char *infile, char *mailbox) { -#ifdef BFNC_SMIME_INVOKE_IMPORT - BFNC_SMIME_INVOKE_IMPORT (infile, mailbox); -#endif + 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) { -#ifdef BFNC_SMIME_VERIFY_ONE - return BFNC_SMIME_VERIFY_ONE (sigbdy, s, tempf); -#else + if (CRYPT_MOD_CALL_CHECK (SMIME, verify_one)) + return (CRYPT_MOD_CALL (SMIME, verify_one)) (sigbdy, s, tempf); + return -1; -#endif +} + +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); + + return 0; } diff --git a/curs_lib.c b/curs_lib.c index 28fd0ae7..d546182e 100644 --- a/curs_lib.c +++ b/curs_lib.c @@ -1,5 +1,6 @@ /* * Copyright (C) 1996-2002 Michael R. Elkins + * Copyright (C) 2004 g10 Code GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,6 +58,20 @@ void mutt_refresh (void) refresh (); } +/* Make sure that the next refresh does a full refresh. This could be + optmized by not doing it at all if DISPLAY is set as this might + indicate that a GUI based pinentry was used. Having an option to + customize this is of course the Mutt way. */ +void mutt_need_hard_redraw (void) +{ + if (!getenv ("DISPLAY")) + { + keypad (stdscr, TRUE); + clearok (stdscr, TRUE); + set_option (OPTNEEDREDRAW); + } +} + event_t mutt_getch (void) { int ch; diff --git a/init.h b/init.h index 781dbcd5..8a67a153 100644 --- a/init.h +++ b/init.h @@ -1,5 +1,6 @@ /* * Copyright (C) 1996-2002 Michael R. Elkins + * Copyright (C) 2004 g10 Code GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -359,6 +360,17 @@ struct option_t MuttVars[] = { ** will be saved for later references. Also see ``$$record'', ** ``$$save_name'', ``$$force_name'' and ``$fcc-hook''. */ + + { "crypt_use_gpgme", DT_BOOL, R_NONE, OPTCRYPTUSEGPGME, 0 }, + /* + ** .pp + ** This variable controls the use the GPGME enabled crypto backends. + ** If it is set and Mutt was build with gpgme support, the gpgme code for + ** S/MIME and PGP will be used instead of the classic code. Note, that + ** you need to use this option in .muttrc as it won't have any effect when + ** used interactively. + */ + { "crypt_autopgp", DT_BOOL, R_NONE, OPTCRYPTAUTOPGP, 1 }, /* ** .pp diff --git a/keymap.c b/keymap.c index 828aa5ef..de0169da 100644 --- a/keymap.c +++ b/keymap.c @@ -40,7 +40,11 @@ struct mapping_t Menus[] = { { "postpone", MENU_POST }, { "pgp", MENU_PGP }, { "smime", MENU_SMIME }, - +#ifdef HAVE_GPGME + { "key_select_pgp", MENU_KEY_SELECT_PGP }, + { "key_select_smime", MENU_KEY_SELECT_SMIME }, +#endif + #ifdef MIXMASTER { "mix", MENU_MIX }, #endif @@ -557,6 +561,11 @@ void km_init (void) if ((WithCrypto & APPLICATION_SMIME)) create_bindings (OpSmime, MENU_SMIME); +#ifdef CRYPT_BACKEND_GPGME + create_bindings (OpPgp, MENU_KEY_SELECT_PGP); + create_bindings (OpSmime, MENU_KEY_SELECT_SMIME); +#endif + #ifdef MIXMASTER create_bindings (OpMix, MENU_MIX); @@ -781,6 +790,13 @@ struct binding_t *km_get_table (int menu) case MENU_PGP: return (WithCrypto & APPLICATION_PGP)? OpPgp:NULL; +#ifdef CRYPT_BACKEND_GPGME + case MENU_KEY_SELECT_PGP: + return OpPgp; + case MENU_KEY_SELECT_SMIME: + return OpSmime; +#endif + #ifdef MIXMASTER case MENU_MIX: return OpMix; diff --git a/keymap.h b/keymap.h index a88bbf46..4a75c6a1 100644 --- a/keymap.h +++ b/keymap.h @@ -65,9 +65,13 @@ enum MENU_PGP, - MENU_SMIME, +#ifdef CRYPT_BACKEND_GPGME + MENU_KEY_SELECT_PGP, + MENU_KEY_SELECT_SMIME, +#endif + #ifdef MIXMASTER MENU_MIX, #endif diff --git a/main.c b/main.c index 81062f86..5341f2ac 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,7 @@ /* * Copyright (C) 1996-2002 Michael R. Elkins * Copyright (C) 1999-2002 Thomas Roessler + * Copyright (C) 2004 g10 Code GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -653,6 +654,9 @@ int main (int argc, char **argv) mutt_init (flags & M_NOSYSRC, commands); mutt_free_list (&commands); + /* Initialize crypto backends. */ + crypt_init (); + if (queries) return mutt_query_variables (queries); diff --git a/mutt.h b/mutt.h index 3dfe27d6..45597ece 100644 --- a/mutt.h +++ b/mutt.h @@ -1,6 +1,7 @@ /* * Copyright (C) 1996-2002 Michael R. Elkins + * Copyright (C) 2004 g10 Code GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -429,6 +430,8 @@ enum OPTWRITEBCC, /* write out a bcc header? */ OPTXMAILER, + OPTCRYPTUSEGPGME, + /* PGP options */ OPTCRYPTAUTOSIGN, @@ -633,8 +636,20 @@ typedef struct body /* send mode: don't adjust the character * set when in send-mode. */ + unsigned int is_signed_data : 1; /* A lot of MUAs don't indicate + S/MIME signed-data correctly, + e.g. they use foo.p7m even for + the name of signed data. This + flag is used to keep track of + the actual message type. It + gets set during the verification + (which is done if the encryption + try failed) and check by the + function to figure the type of + the message. */ unsigned int goodsig : 1; /* good cryptographic signature */ + unsigned int warnsig : 1; /* maybe good signature */ unsigned int badsig : 1; /* bad cryptographic signature (needed to check encrypted s/mime-signatures) */ unsigned int collapsed : 1; /* used by recvattach */ diff --git a/mutt_crypt.h b/mutt_crypt.h index f63c8d0d..6b57382e 100644 --- a/mutt_crypt.h +++ b/mutt_crypt.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2003 Werner Koch + * Copyright (C) 2004 g10code GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -63,14 +64,12 @@ effectively as a conditional compile directive. It is set to false if no crypto backend is configures or to a bit vector denoting the configured backends. */ -#if defined(CRYPT_BACKEND_CLASSIC_PGP) && defined(CRYPT_BACKEND_CLASSIC_SMIME) +#if (defined(CRYPT_BACKEND_CLASSIC_PGP) && defined(CRYPT_BACKEND_CLASSIC_SMIME)) || defined (CRYPT_BACKEND_GPGME) # define WithCrypto (APPLICATION_PGP | APPLICATION_SMIME) #elif defined(CRYPT_BACKEND_CLASSIC_PGP) # define WithCrypto APPLICATION_PGP #elif defined(CRYPT_BACKEND_CLASSIC_SMIME) # define WithCrypto APPLICATION_SMIME -#elif defined(CRYPT_BACKEND_GPGME) -# define WithCrypto (APPLICATION_PGP | APPLICATION_SMIME) #else # define WithCrypto 0 #endif @@ -78,6 +77,7 @@ #define KEYFLAG_CANSIGN (1 << 0) #define KEYFLAG_CANENCRYPT (1 << 1) +#define KEYFLAG_ISX509 (1 << 2) #define KEYFLAG_SECRET (1 << 7) #define KEYFLAG_EXPIRED (1 << 8) #define KEYFLAG_REVOKED (1 << 9) @@ -164,6 +164,9 @@ void crypt_invoke_message (int type); /* Silently forget about a passphrase. */ void crypt_pgp_void_passphrase (void); +int crypt_pgp_valid_passphrase (void); + + /* Decrypt a PGP/MIME message. */ int crypt_pgp_decrypt_mime (FILE *a, FILE **b, BODY *c, BODY **d); @@ -206,6 +209,8 @@ BODY *crypt_pgp_encrypt_message (BODY *a, char *keylist, int sign); /* Invoke the PGP command to import a key. */ void crypt_pgp_invoke_import (const char *fname); +int crypt_pgp_send_menu (HEADER *msg, int *redraw); + /* fixme: needs documentation */ int crypt_pgp_verify_one (BODY *sigbdy, STATE *s, const char *tempf); @@ -222,6 +227,8 @@ void crypt_pgp_extract_keys_from_attachment_list (FILE *fp, int tag,BODY *top); /* Silently forget about a passphrase. */ void crypt_smime_void_passphrase (void); +int crypt_smime_valid_passphrase (void); + /* Decrypt an S/MIME message. */ int crypt_smime_decrypt_mime (FILE *a, FILE **b, BODY *c, BODY **d); @@ -250,8 +257,11 @@ 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); +int crypt_smime_send_menu (HEADER *msg, int *redraw); + /* fixme: needs documentation */ int crypt_smime_verify_one (BODY *sigbdy, STATE *s, const char *tempf); +void crypt_init (void); #endif /*MUTT_CRYPT_H*/ diff --git a/mutt_curses.h b/mutt_curses.h index b7b1a828..0b354ca5 100644 --- a/mutt_curses.h +++ b/mutt_curses.h @@ -1,5 +1,6 @@ /* * Copyright (C) 1996-2000 Michael R. Elkins + * Copyright (C) 2004 g10 Code GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -94,6 +95,7 @@ void mutt_flushinp (void); void mutt_refresh (void); void mutt_resize_screen (void); void mutt_ungetch (int, int); +void mutt_need_hard_redraw (void); /* ---------------------------------------------------------------------------- * Support for color diff --git a/pgp.c b/pgp.c index 9fcdd3d3..ccc8e38c 100644 --- a/pgp.c +++ b/pgp.c @@ -1,6 +1,7 @@ /* * Copyright (C) 1996,1997 Michael R. Elkins * Copyright (c) 1998,1999 Thomas Roessler + * Copyright (C) 2004 g10 Code GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -54,7 +55,7 @@ #ifdef CRYPT_BACKEND_CLASSIC_PGP #include "mutt_crypt.h" - +#include "mutt_menu.h" char PgpPass[STRING]; @@ -66,6 +67,24 @@ void pgp_void_passphrase (void) PgpExptime = 0; } +int pgp_valid_passphrase (void) +{ + time_t now = time (NULL); + + if (now < PgpExptime) + /* Use cached copy. */ + return 1; + + if (mutt_get_password (_("Enter PGP passphrase:"), PgpPass, sizeof (PgpPass)) == 0) + { + PgpExptime = time (NULL) + PgpTimeout; + return (1); + } + else + PgpExptime = 0; + + return 0; +} void pgp_forget_passphrase (void) { @@ -1023,7 +1042,7 @@ char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) pgp_key_t k_info = NULL, key = NULL; const char *fqdn = mutt_fqdn (1); - + for (i = 0; i < 3; i++) { switch (i) @@ -1425,4 +1444,76 @@ BODY *pgp_traditional_encryptsign (BODY *a, int flags, char *keylist) return b; } +int pgp_send_menu (HEADER *msg, int *redraw) +{ + pgp_key_t p; + char input_signas[SHORT_STRING]; + + if (!(WithCrypto & APPLICATION_PGP)) + return msg->security; + + switch (mutt_multi_choice (_("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, (i)nline, or (f)orget it? "), + _("esabif"))) + { + case 1: /* (e)ncrypt */ + msg->security ^= ENCRYPT; + break; + + case 2: /* (s)ign */ + msg->security ^= SIGN; + 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)); + mutt_str_replace (&PgpSignAs, input_signas); + pgp_free_key (&p); + + msg->security |= SIGN; + + crypt_pgp_void_passphrase (); /* probably need a different passphrase */ + } + else + { + msg->security &= ~SIGN; + } + + *redraw = REDRAW_FULL; + break; + + case 4: /* (b)oth */ + if ((msg->security & (ENCRYPT | SIGN)) == (ENCRYPT | SIGN)) + msg->security = 0; + else + 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 */ + msg->security = 0; + break; + } + + if (msg->security) + { + if (! (msg->security & (ENCRYPT | SIGN))) + msg->security = 0; + else + msg->security |= APPLICATION_PGP; + } + + return (msg->security); +} + + #endif /* CRYPT_BACKEND_CLASSIC_PGP */ diff --git a/pgp.h b/pgp.h index 5c696651..31718720 100644 --- a/pgp.h +++ b/pgp.h @@ -1,6 +1,7 @@ /* * Copyright (C) 1996,1997 Michael R. Elkins * Copyright (C) 1999-2000 Thomas Roessler + * Copyright (C) 2004 g10 Code GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,8 +43,6 @@ int pgp_decrypt_mime (FILE *, FILE **, BODY *, BODY **); /* int pgp_string_matches_hint (const char *s, LIST * hints); */ -#define pgp_valid_passphrase() crypt_valid_passphrase(APPLICATION_PGP) - /* pgp_key_t gpg_get_candidates (struct pgp_vinfo *, pgp_ring_t, LIST *); */ pgp_key_t pgp_ask_for_key (char *, char *, short, pgp_ring_t); pgp_key_t pgp_get_candidates (pgp_ring_t, LIST *); @@ -57,8 +56,7 @@ void pgp_application_pgp_handler (BODY *, STATE *); void pgp_encrypted_handler (BODY *, STATE *); void pgp_extract_keys_from_attachment_list (FILE * fp, int tag, BODY * top); void pgp_void_passphrase (void); - - +int pgp_valid_passphrase (void); /* The PGP invocation interface - not really beautiful. */ @@ -102,5 +100,6 @@ 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); #endif /* CRYPT_BACKEND_CLASSIC_PGP */ diff --git a/smime.c b/smime.c index fda19e95..a510ed1e 100644 --- a/smime.c +++ b/smime.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2001,2002 Oliver Ehli * Copyright (C) 2002 Mike Schiraldi + * Copyright (C) 2004 g10 Code GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -48,7 +49,6 @@ #include "mutt_crypt.h" - struct smime_command_context { const char *key; /* %k */ const char *cryptalg; /* %a */ @@ -94,9 +94,24 @@ void smime_void_passphrase (void) SmimeExptime = 0; } +int smime_valid_passphrase (void) +{ + time_t now = time (NULL); + if (now < SmimeExptime) + /* Use cached copy. */ + return 1; + if (mutt_get_password (_("Enter SMIME passphrase:"), SmimePass, sizeof (SmimePass)) == 0) + { + SmimeExptime = time (NULL) + SmimeTimeout; + return (1); + } + else + SmimeExptime = 0; + return 0; +} /* @@ -1917,4 +1932,87 @@ void smime_application_smime_handler (BODY *m, STATE *s) smime_handle_entity (m, s, NULL); } + +int smime_send_menu (HEADER *msg, int *redraw) +{ + char *p; + + if (!(WithCrypto & APPLICATION_SMIME)) + return msg->security; + + switch (mutt_multi_choice (_("S/MIME (e)ncrypt, (s)ign, encrypt (w)ith, sign (a)s, (b)oth, or (f)orget it? "), + _("eswabf"))) + { + case 1: /* (e)ncrypt */ + msg->security |= ENCRYPT; + break; + + case 3: /* encrypt (w)ith */ + msg->security |= ENCRYPT; + switch (mutt_multi_choice (_("1: DES, 2: Triple-DES, 3: RC2-40," + " 4: RC2-64, 5: RC2-128, or (f)orget it? "), + _("12345f"))) { + case 1: + mutt_str_replace (&SmimeCryptAlg, "des"); + break; + case 2: + mutt_str_replace (&SmimeCryptAlg, "des3"); + break; + case 3: + mutt_str_replace (&SmimeCryptAlg, "rc2-40"); + break; + case 4: + mutt_str_replace (&SmimeCryptAlg, "rc2-64"); + break; + case 5: + mutt_str_replace (&SmimeCryptAlg, "rc2-128"); + break; + case 6: /* forget it */ + break; + } + break; + + case 2: /* (s)ign */ + + if(!SmimeDefaultKey) + mutt_message("Can\'t sign: No key specified. use sign(as)."); + else + msg->security |= SIGN; + break; + + case 4: /* sign (a)s */ + + if ((p = smime_ask_for_key (_("Sign as: "), NULL, 0))) { + p[mutt_strlen (p)-1] = '\0'; + mutt_str_replace (&SmimeDefaultKey, p); + + msg->security |= SIGN; + + /* probably need a different passphrase */ + crypt_smime_void_passphrase (); + } + else + msg->security &= ~SIGN; + + *redraw = REDRAW_FULL; + break; + + case 5: /* (b)oth */ + msg->security = ENCRYPT | SIGN; + break; + + case 6: /* (f)orget it */ + msg->security = 0; + break; + } + + if (msg->security && msg->security != APPLICATION_SMIME) + msg->security |= APPLICATION_SMIME; + else + msg->security = 0; + + return (msg->security); +} + + #endif /* CRYPT_BACKEND_CLASSIC_SMIME */ diff --git a/smime.h b/smime.h index 360ecd8a..dba0a0fc 100644 --- a/smime.h +++ b/smime.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2001,2002 Oliver Ehli + * Copyright (C) 2004 g10 Code GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,9 +26,8 @@ -#define smime_valid_passphrase() crypt_valid_passphrase(APPLICATION_SMIME) - void smime_void_passphrase (void); +int smime_valid_passphrase (void); int smime_decrypt_mime (FILE *, FILE **, BODY *, BODY **); @@ -54,6 +54,8 @@ char *smime_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc); void smime_invoke_import (char *, char *); +int smime_send_menu (HEADER *msg, int *redraw); + #endif