]> granicus.if.org Git - mutt/commitdiff
PKA signature verification via GPGME, controlled by $crypt_use_pka.
authorMoritz Schulte <Moritz.Schulte@ruhr-uni-bochum.de>
Sat, 24 Feb 2007 06:12:19 +0000 (06:12 +0000)
committerMoritz Schulte <Moritz.Schulte@ruhr-uni-bochum.de>
Sat, 24 Feb 2007 06:12:19 +0000 (06:12 +0000)
15 files changed:
Makefile.am
UPDATING
configure.in
crypt-gpgme.c
crypt-gpgme.h
crypt-mod-pgp-classic.c
crypt-mod-pgp-gpgme.c
crypt-mod-smime-classic.c
crypt-mod-smime-gpgme.c
crypt-mod.h
crypt.c
cryptglue.c
init.h
mutt.h
mutt_crypt.h

index e194705ea70b53dcee89e80dcaef22adc785c784..46ada466b3a23c890341d0b0c4626cbf18f9aa3d 100644 (file)
@@ -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)
 
index 2eff364197cd397e9ae590f2041cb84aae2f2c7b..c53fc44a2fd0e6d803b50d559ddcf6e19d6efa55 100644 (file)
--- a/UPDATING
+++ b/UPDATING
@@ -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):
 
index 60e72da91b409b4ff41568bffd5a1b52cfad3950..8fa03858c6d973650b02d53c8e81345c5cb8d731 100644 (file)
@@ -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
index 07d0039a97ebe25cefd6e45324e1142927e2471f..bf1bd3821a0da3fd7cf3904c5099e9cf5150a9b4 100644 (file)
                      *(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
index c8aa08ed75fe75651150175245f1d9eb42fd9c80..d0da2bb562ee6c1093764c8f4a795bf890474dd3 100644 (file)
@@ -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
index b471e4c90f74796ae10db3438c5bfae281dfec4f..e414a147e1274f23d58152c1b666f130cdc203bc 100644 (file)
@@ -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,
index 55257cb06c7403a6e02250d913a42a9e0af798ea..290adf710d56b3f84401b41fb80a137aa3c6ed04 100644 (file)
@@ -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,
index a5e7d92a9c37121834da9861c5e1c09d598760ce..bc0bb75eff20abfdc37927d069c1b9d73d7bad6c 100644 (file)
@@ -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 */
index 57730963431200994e00405f7691b51ecfff9b3b..6e85b98036d5d92f6dbf425fff73952c1f0fd4e4 100644 (file)
@@ -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 */
index 3bd74260ba371f4729b62b20c39f40d5fe9788e8..08dfa43c41408123d5545772410b1551def6b947 100644 (file)
@@ -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;
diff --git a/crypt.c b/crypt.c
index 473e099aef75495ff82d587e2fd2c4daf694ce49..67d7276bfdc687c529dc9de1d8996f022e210bda 100644 (file)
--- a/crypt.c
+++ b/crypt.c
@@ -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)
index 8f840c57b65f4c8a29c24a488901409ea41b67f3..e6f0aab61a3eec7ffbd84accb2e1d51b7ab2dbef 100644 (file)
@@ -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);
+}
+
 
 \f
+
 /* 
 
    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);
+}
diff --git a/init.h b/init.h
index fd9c78c501274783c7813cc5753a8e9740ad2e3e..0bba9d226c10d347f6eccb30f8a63b1108ea0e19 100644 (file)
--- a/init.h
+++ b/init.h
@@ -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
diff --git a/mutt.h b/mutt.h
index 8cb74f8b249d2b13cf03855f00b074d006ca6a4f..e23771cba5dcfbcf0cbafb12f2d57b45fff8fa6e 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -453,6 +453,7 @@ enum
   OPTXMAILER,
 
   OPTCRYPTUSEGPGME,
+  OPTCRYPTUSEPKA,
 
   /* PGP options */
   
index b432cd6eb803609dea834a80edafd8c95281cc53..db152b0276c807d05cff6715f8e9200deade313a 100644 (file)
@@ -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);