Commit fce975f5 authored by Moritz Schulte's avatar Moritz Schulte

PKA signature verification via GPGME, controlled by $crypt_use_pka.

parent 6c4a2264
......@@ -32,7 +32,7 @@ mutt_SOURCES = $(BUILT_SOURCES) \
url.c ascii.c mutt_idna.c crypt-mod.c crypt-mod.h
mutt_LDADD = @MUTT_LIB_OBJECTS@ @LIBOBJS@ $(LIBIMAP) $(MUTTLIBS) \
$(INTLLIBS) $(LIBICONV) $(LIBGPGME_LIBS)
$(INTLLIBS) $(LIBICONV) $(GPGME_LIBS)
mutt_DEPENDENCIES = @MUTT_LIB_OBJECTS@ @LIBOBJS@ $(LIBIMAPDEPS) \
$(INTLDEPS)
......@@ -52,7 +52,7 @@ DEFS=-DPKGDATADIR=\"$(pkgdatadir)\" -DSYSCONFDIR=\"$(sysconfdir)\" \
-DBINDIR=\"$(bindir)\" -DMUTTLOCALEDIR=\"$(datadir)/locale\" \
-DHAVE_CONFIG_H=1
AM_CPPFLAGS=-I. -I$(top_srcdir) $(IMAP_INCLUDES) $(LIBGPGME_CFLAGS) -Iintl
AM_CPPFLAGS=-I. -I$(top_srcdir) $(IMAP_INCLUDES) $(GPGME_CFLAGS) -Iintl
CPPFLAGS=@CPPFLAGS@ -I$(includedir)
......
......@@ -4,10 +4,12 @@ mutt. Please read this file carefully when upgrading your installation.
The keys used are:
!: modified feature, -: deleted feature, +: new feature
+ $crypt_use_pka (use GPGME PKA signature verification)
1.5.13 (2006-08-14):
+ thread patterns. Use ~(...) to match all threads that
contain a message that matches ...
+ thread patterns. Use ~(...) to match all threads that
contain a message that matches ...
1.5.12 (2006-07-14):
......
......@@ -107,31 +107,31 @@ AC_DEFINE_UNQUOTED(SENDMAIL,"$ac_cv_path_SENDMAIL", [Where to find sendmail on y
OPS='$(srcdir)/OPS'
AC_MSG_CHECKING([whether to build with GPGME support])
AC_ARG_ENABLE(gpgme, AC_HELP_STRING([--enable-gpgme], [Enable GPGME support]),
[ if test x$enableval = xyes; then
have_gpgme=yes
enable_gpgme=yes
fi
])
AC_ARG_WITH(gpgme-prefix, AC_HELP_STRING([--with-gpgme-prefix=PFX], [prefix where GPGME is installed (optional)]),
gpgme_config_prefix="$withval", gpgme_config_prefix="")
if test x$have_gpgme = xyes; then
if test x$gpgme_config_prefix != x; then
GPGME_CONFIG="$gpgme_config_prefix/bin/gpgme-config"
else
AC_PATH_PROG(GPGME_CONFIG, gpgme-config, no)
fi
if test "x$GPGME_CONFIG" = "xno"; then
AC_MSG_ERROR([GPGME not found])
else
LIBGPGME_CFLAGS=`$GPGME_CONFIG --cflags`
LIBGPGME_LIBS=`$GPGME_CONFIG --libs`
MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS crypt-gpgme.o crypt-mod-pgp-gpgme.o crypt-mod-smime-gpgme.o"
AC_DEFINE(CRYPT_BACKEND_GPGME, 1, [Defined, if GPGME support is enabled])
fi
if test x"$enable_gpgme" = xyes; then
AC_MSG_RESULT(yes)
AM_PATH_GPGME(1.0.0, AC_DEFINE(CRYPT_BACKEND_GPGME, 1,
[Defined, if GPGME support is enabled]),
[gpgme_found=no])
if test x"$gpgme_found" = xno; then
AC_MSG_ERROR([*** GPGME not found ***])
else
AM_PATH_GPGME(1.1.1, AC_DEFINE(HAVE_GPGME_PKA_TRUST, 1,
[Define if GPGME supports PKA]))
#needed to get GPGME_LIBS and al correctly
AM_PATH_GPGME(1.0.0, AC_DEFINE(CRYPT_BACKEND_GPGME, 1,
[Define if you use GPGME to support OpenPGP]))
MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS crypt-gpgme.o crypt-mod-pgp-gpgme.o crypt-mod-smime-gpgme.o"
fi
else
AC_MSG_RESULT([no])
fi
AC_SUBST(LIBGPGME_CFLAGS)
AC_SUBST(LIBGPGME_LIBS)
AC_ARG_ENABLE(pgp, AC_HELP_STRING([--disable-pgp], [Disable PGP support]),
[ if test x$enableval = xno ; then
......
......@@ -71,6 +71,10 @@
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
#define PKA_NOTATION_NAME "pka-address@gnupg.org"
#define is_pka_notation(notation) (! strcmp ((notation)->name, \
PKA_NOTATION_NAME))
/* Values used for comparing addresses. */
#define CRYPT_KV_VALID 1
#define CRYPT_KV_ADDR 2
......@@ -115,6 +119,8 @@ typedef struct crypt_entry
static struct crypt_cache *id_defaults = NULL;
static gpgme_key_t signature_key = NULL;
static char *current_sender = NULL;
/*
* General helper functions.
......@@ -661,6 +667,23 @@ static int set_signer (gpgme_ctx_t ctx, int for_smime)
return 0;
}
static gpgme_error_t
set_pka_sig_notation (gpgme_ctx_t ctx)
{
gpgme_error_t err;
err = gpgme_sig_notation_add (ctx,
PKA_NOTATION_NAME, current_sender, 0);
if (err)
{
mutt_error (_("error setting PKA signature notation: %s\n"),
gpgme_strerror (err));
mutt_sleep (2);
}
return err;
}
/* Encrypt the gpgme data object PLAINTEXT to the recipients in RSET
and return an allocated filename to a temporary file containing the
......@@ -670,7 +693,7 @@ static int set_signer (gpgme_ctx_t ctx, int for_smime)
static char *encrypt_gpgme_object (gpgme_data_t plaintext, gpgme_key_t *rset,
int use_smime, int combined_signed)
{
int err;
gpgme_error_t err;
gpgme_ctx_t ctx;
gpgme_data_t ciphertext;
char *outfile;
......@@ -689,6 +712,18 @@ static char *encrypt_gpgme_object (gpgme_data_t plaintext, gpgme_key_t *rset,
gpgme_release (ctx);
return NULL;
}
if (option (OPTCRYPTUSEPKA))
{
err = set_pka_sig_notation (ctx);
if (err)
{
gpgme_data_release (ciphertext);
gpgme_release (ctx);
return NULL;
}
}
err = gpgme_op_encrypt_sign (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST,
plaintext, ciphertext);
}
......@@ -788,6 +823,18 @@ static BODY *sign_message (BODY *a, int use_smime)
return NULL;
}
if (option (OPTCRYPTUSEPKA))
{
err = set_pka_sig_notation (ctx);
if (err)
{
gpgme_data_release (signature);
gpgme_data_release (message);
gpgme_release (ctx);
return NULL;
}
}
err = gpgme_op_sign (ctx, message, signature, GPGME_SIG_MODE_DETACH );
mutt_need_hard_redraw ();
gpgme_data_release (message);
......@@ -984,7 +1031,7 @@ BODY *smime_gpgme_build_smime_entity (BODY *a, char *keylist)
*/
static int show_sig_summary (unsigned long sum,
gpgme_ctx_t ctx, gpgme_key_t key, int idx,
STATE *s)
STATE *s, gpgme_signature_t sig)
{
int severe = 0;
......@@ -1080,6 +1127,27 @@ static int show_sig_summary (unsigned long sum,
state_attach_puts ("\n", s);
}
#ifdef HAVE_GPGME_PKA_TRUST
if (option (OPTCRYPTUSEPKA))
{
if (sig->pka_trust == 1 && sig->pka_address)
{
state_attach_puts (_("WARNING: PKA entry does not match "
"signer's address: "), s);
state_attach_puts (sig->pka_address, s);
state_attach_puts ("\n", s);
}
else if (sig->pka_trust == 2 && sig->pka_address)
{
state_attach_puts (_("PKA verified signer's address is: "), s);
state_attach_puts (sig->pka_address, s);
state_attach_puts ("\n", s);
}
}
#endif
return severe;
}
......@@ -1259,7 +1327,7 @@ static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE *s)
state_attach_puts (_(" created: "), s);
print_time (created, s);
state_attach_puts ("\n", s);
if (show_sig_summary (sum, ctx, key, idx, s))
if (show_sig_summary (sum, ctx, key, idx, s, sig))
anywarn = 1;
show_one_sig_validity (ctx, idx, s);
}
......@@ -1268,7 +1336,7 @@ static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE *s)
state_attach_puts (_("*BAD* signature claimed to be from: "), s);
state_attach_puts (uid, s);
state_attach_puts ("\n", s);
show_sig_summary (sum, ctx, key, idx, s);
show_sig_summary (sum, ctx, key, idx, s, sig);
}
else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP))
{ /* We can't decide (yellow) but this is a PGP key with a good
......@@ -1283,14 +1351,14 @@ static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE *s)
state_attach_puts ("\n", s);
show_one_sig_validity (ctx, idx, s);
show_fingerprint (key,s);
if (show_sig_summary (sum, ctx, key, idx, s))
if (show_sig_summary (sum, ctx, key, idx, s, sig))
anywarn = 1;
}
else /* can't decide (yellow) */
{
state_attach_puts (_("Error checking signature"), s);
state_attach_puts ("\n", s);
show_sig_summary (sum, ctx, key, idx, s);
show_sig_summary (sum, ctx, key, idx, s, sig);
}
if (key != signature_key)
......@@ -1372,6 +1440,7 @@ static int verify_one (BODY *sigbdy, STATE *s,
gpgme_verify_result_t result;
gpgme_sig_notation_t notation;
gpgme_signature_t signature;
int non_pka_notations;
result = gpgme_op_verify_result (ctx);
if (result)
......@@ -1379,7 +1448,13 @@ static int verify_one (BODY *sigbdy, STATE *s,
for (signature = result->signatures; signature;
signature = signature->next)
{
if (signature->notations)
non_pka_notations = 0;
for (notation = signature->notations; notation;
notation = notation->next)
if (! is_pka_notation (notation))
non_pka_notations++;
if (non_pka_notations)
{
char buf[SHORT_STRING];
snprintf (buf, sizeof (buf),
......@@ -1389,6 +1464,9 @@ static int verify_one (BODY *sigbdy, STATE *s,
for (notation = signature->notations; notation;
notation = notation->next)
{
if (is_pka_notation (notation))
continue;
if (notation->name)
{
state_attach_puts (notation->name, s);
......@@ -4266,4 +4344,12 @@ int smime_gpgme_verify_sender (HEADER *h)
return verify_sender (h, GPGME_PROTOCOL_CMS);
}
void gpgme_set_sender (const char *sender)
{
mutt_error ("[setting sender] mailbox: %s\n", sender);
FREE (&current_sender);
current_sender = safe_strdup (sender);
}
#endif
......@@ -51,4 +51,7 @@ int pgp_gpgme_send_menu (HEADER *msg, int *redraw);
int smime_gpgme_send_menu (HEADER *msg, int *redraw);
int smime_gpgme_verify_sender (HEADER *h);
void gpgme_set_sender (const char *sender);
#endif
......@@ -119,6 +119,7 @@ struct crypt_module_specs crypt_mod_pgp_classic =
crypt_mod_pgp_sign_message,
crypt_mod_pgp_verify_one,
crypt_mod_pgp_send_menu,
NULL,
crypt_mod_pgp_encrypt_message,
crypt_mod_pgp_make_key_attachment,
......
......@@ -90,6 +90,11 @@ static BODY *crypt_mod_pgp_encrypt_message (BODY *a, char *keylist, int sign)
return pgp_gpgme_encrypt_message (a, keylist, sign);
}
static void crypt_mod_pgp_set_sender (const char *sender)
{
gpgme_set_sender (sender);
}
struct crypt_module_specs crypt_mod_pgp_gpgme =
{ APPLICATION_PGP,
{
......@@ -104,6 +109,7 @@ struct crypt_module_specs crypt_mod_pgp_gpgme =
crypt_mod_pgp_sign_message,
crypt_mod_pgp_verify_one,
crypt_mod_pgp_send_menu,
crypt_mod_pgp_set_sender,
/* PGP specific. */
crypt_mod_pgp_encrypt_message,
......
......@@ -100,6 +100,7 @@ struct crypt_module_specs crypt_mod_smime_classic =
crypt_mod_smime_sign_message,
crypt_mod_smime_verify_one,
crypt_mod_smime_send_menu,
NULL,
NULL, /* pgp_encrypt_message */
NULL, /* pgp_make_key_attachment */
......
......@@ -98,6 +98,7 @@ struct crypt_module_specs crypt_mod_smime_gpgme =
crypt_mod_smime_sign_message,
crypt_mod_smime_verify_one,
crypt_mod_smime_send_menu,
NULL,
NULL, /* pgp_encrypt_message */
NULL, /* pgp_make_key_attachment */
......
......@@ -67,6 +67,7 @@ typedef void (*crypt_func_smime_invoke_import_t) (char *infile, char *mailbox);
typedef void (*crypt_func_init_t) (void);
typedef void (*crypt_func_set_sender_t) (const char *sender);
/*
A structure to keep all crypto module fucntions together.
......@@ -84,6 +85,7 @@ typedef struct crypt_module_functions
crypt_func_sign_message_t sign_message;
crypt_func_verify_one_t verify_one;
crypt_func_send_menu_t send_menu;
crypt_func_set_sender_t set_sender;
/* PGP specific functions. */
crypt_func_pgp_encrypt_message_t pgp_encrypt_message;
......
......@@ -169,6 +169,18 @@ int mutt_protect (HEADER *msg, char *keylist)
if ((WithCrypto & APPLICATION_PGP))
tmp_pgp_pbody = msg->content;
if (option (OPTCRYPTUSEPKA) && (msg->security & SIGN))
{
/* Set sender (necessary for e.g. PKA). */
if ((WithCrypto & APPLICATION_SMIME)
&& (msg->security & APPLICATION_SMIME))
crypt_smime_set_sender (msg->env->from->mailbox);
else if ((WithCrypto & APPLICATION_PGP)
&& (msg->security & APPLICATION_PGP))
crypt_pgp_set_sender (msg->env->from->mailbox);
}
if (msg->security & SIGN)
{
if ((WithCrypto & APPLICATION_SMIME)
......
......@@ -260,8 +260,15 @@ void crypt_pgp_extract_keys_from_attachment_list (FILE *fp, int tag, BODY *top)
(CRYPT_MOD_CALL (PGP, pgp_extract_keys_from_attachment_list)) (fp, tag, top);
}
void crypt_pgp_set_sender (const char *sender)
{
if (CRYPT_MOD_CALL_CHECK (PGP, set_sender))
(CRYPT_MOD_CALL (PGP, set_sender)) (sender);
}
/*
S/MIME
......@@ -376,3 +383,9 @@ int crypt_smime_send_menu (HEADER *msg, int *redraw)
return 0;
}
void crypt_smime_set_sender (const char *sender)
{
if (CRYPT_MOD_CALL_CHECK (SMIME, set_sender))
(CRYPT_MOD_CALL (SMIME, set_sender)) (sender);
}
......@@ -406,13 +406,19 @@ struct option_t MuttVars[] = {
{ "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
** This variable controls the use of the GPGME-enabled crypto backends.
** If it is set and Mutt was built with gpgme support, the gpgme code for
** S/MIME and PGP will be used instead of the classic code. Note that
** you need to set this option in .muttrc; it won't have any effect when
** used interactively.
*/
{ "crypt_use_pka", DT_BOOL, R_NONE, OPTCRYPTUSEPKA, 0 },
/*
** .pp Controls whether mutt uses PKA
** (http://www.g10code.de/docs/pka-intro.de.pdf) during signature
** verification (only supported by the GPGME backend).
*/
{ "crypt_autopgp", DT_BOOL, R_NONE, OPTCRYPTAUTOPGP, 1 },
/*
** .pp
......
......@@ -453,6 +453,7 @@ enum
OPTXMAILER,
OPTCRYPTUSEGPGME,
OPTCRYPTUSEPKA,
/* PGP options */
......
......@@ -220,7 +220,7 @@ char *crypt_pgp_keyid (pgp_key_t k);
/* fixme: needs documentation */
void crypt_pgp_extract_keys_from_attachment_list (FILE *fp, int tag,BODY *top);
void crypt_pgp_set_sender (const char *sender);
......@@ -259,6 +259,8 @@ void crypt_smime_invoke_import (char *infile, char *mailbox);
int crypt_smime_send_menu (HEADER *msg, int *redraw);
void crypt_smime_set_sender (const char *sender);
/* fixme: needs documentation */
int crypt_smime_verify_one (BODY *sigbdy, STATE *s, const char *tempf);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment