Rocco Rutte:
[apps/madmutt.git] / pgp.c
diff --git a/pgp.c b/pgp.c
index ecb6815..53ff14b 100644 (file)
--- a/pgp.c
+++ b/pgp.c
 #endif
 
 #include "mutt.h"
+#include "enter.h"
+#include "ascii.h"
+#include "handler.h"
 #include "mutt_curses.h"
 #include "pgp.h"
 #include "mime.h"
 #include "copy.h"
+#include "attach.h"
+
+#include "lib/mem.h"
+#include "lib/intl.h"
+#include "lib/str.h"
+#include "lib/debug.h"
 
 #include <sys/wait.h>
 #include <string.h>
@@ -53,7 +62,7 @@
 #include "mutt_menu.h"
 
 
-char PgpPass[STRING];
+char PgpPass[LONG_STRING];
 time_t PgpExptime = 0;          /* when does the cached passphrase expire? */
 
 void pgp_void_passphrase (void)
@@ -77,8 +86,8 @@ int pgp_valid_passphrase (void)
 
   pgp_void_passphrase ();
 
-  if (mutt_get_password
-      (_("Enter PGP passphrase:"), PgpPass, sizeof (PgpPass)) == 0) {
+  if (mutt_get_field_unbuffered (_("Enter PGP passphrase:"), PgpPass,
+                                 sizeof (PgpPass), M_PASS) == 0) {
     PgpExptime = time (NULL) + PgpTimeout;
     return (1);
   }
@@ -135,24 +144,21 @@ static int pgp_copy_checksig (FILE * fpin, FILE * fpout)
 
     while ((line = mutt_read_line (line, &linelen, fpin, &lineno)) != NULL) {
       if (regexec (PgpGoodSign.rx, line, 0, NULL, 0) == 0) {
-        dprint (2, (debugfile, "pgp_copy_checksig: \"%s\" matches regexp.\n",
-                    line));
+        debug_print (2, ("\"%s\" matches regexp.\n", line));
         rv = 0;
       }
       else
-        dprint (2,
-                (debugfile,
-                 "pgp_copy_checksig: \"%s\" doesn't match regexp.\n", line));
+        debug_print (2, ("\"%s\" doesn't match regexp.\n", line));
 
       if (strncmp (line, "[GNUPG:] ", 9) == 0)
         continue;
       fputs (line, fpout);
       fputc ('\n', fpout);
     }
-    FREE (&line);
+    mem_free (&line);
   }
   else {
-    dprint (2, (debugfile, "pgp_copy_checksig: No pattern.\n"));
+    debug_print (2, ("No pattern.\n"));
     mutt_copy_stream (fpin, fpout);
     rv = 1;
   }
@@ -193,11 +199,11 @@ static void pgp_copy_clearsigned (FILE * fpin, STATE * s, char *charset)
       continue;
     }
 
-    if (mutt_strcmp (buf, "-----BEGIN PGP SIGNATURE-----\n") == 0)
+    if (str_cmp (buf, "-----BEGIN PGP SIGNATURE-----\n") == 0)
       break;
 
     if (armor_header) {
-      char *p = mutt_skip_whitespace (buf);
+      char *p = str_skip_initws (buf);
 
       if (*p == '\0')
         armor_header = 0;
@@ -219,9 +225,10 @@ static void pgp_copy_clearsigned (FILE * fpin, STATE * s, char *charset)
 
 /* Support for the Application/PGP Content Type. */
 
-void pgp_application_pgp_handler (BODY * m, STATE * s)
+int pgp_application_pgp_handler (BODY * m, STATE * s)
 {
   int needpass = -1, pgp_keyblock = 0;
+  int c;
   int clearsign = 0, rv, rc;
   long start_pos = 0;
   long bytes, last_pos, offset;
@@ -229,7 +236,7 @@ void pgp_application_pgp_handler (BODY * m, STATE * s)
   char outfile[_POSIX_PATH_MAX];
   char tmpfname[_POSIX_PATH_MAX];
   FILE *pgpout = NULL, *pgpin = NULL, *pgperr = NULL;
-  FILE *tmpfp;
+  FILE *tmpfp = NULL;
   pid_t thepid;
 
   short maybe_goodsig = 1;
@@ -249,21 +256,21 @@ void pgp_application_pgp_handler (BODY * m, STATE * s)
       break;
 
     offset = ftell (s->fpin);
-    bytes -= (offset - last_pos);       /* don't rely on mutt_strlen(buf) */
+    bytes -= (offset - last_pos);       /* don't rely on str_len(buf) */
     last_pos = offset;
 
-    if (mutt_strncmp ("-----BEGIN PGP ", buf, 15) == 0) {
+    if (str_ncmp ("-----BEGIN PGP ", buf, 15) == 0) {
       clearsign = 0;
       start_pos = last_pos;
 
-      if (mutt_strcmp ("MESSAGE-----\n", buf + 15) == 0)
+      if (str_cmp ("MESSAGE-----\n", buf + 15) == 0)
         needpass = 1;
-      else if (mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15) == 0) {
+      else if (str_cmp ("SIGNED MESSAGE-----\n", buf + 15) == 0) {
         clearsign = 1;
         needpass = 0;
       }
       else if (!option (OPTDONTHANDLEPGPKEYS) &&
-               mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15) == 0) {
+               str_cmp ("PUBLIC KEY BLOCK-----\n", buf + 15) == 0) {
         needpass = 0;
         pgp_keyblock = 1;
       }
@@ -281,22 +288,22 @@ void pgp_application_pgp_handler (BODY * m, STATE * s)
       mutt_mktemp (tmpfname);
       if ((tmpfp = safe_fopen (tmpfname, "w+")) == NULL) {
         mutt_perror (tmpfname);
-        return;
+        return (-1);
       }
 
       fputs (buf, tmpfp);
       while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL) {
         offset = ftell (s->fpin);
-        bytes -= (offset - last_pos);   /* don't rely on mutt_strlen(buf) */
+        bytes -= (offset - last_pos);   /* don't rely on str_len(buf) */
         last_pos = offset;
 
         fputs (buf, tmpfp);
 
         if ((needpass
-             && mutt_strcmp ("-----END PGP MESSAGE-----\n", buf) == 0)
+             && str_cmp ("-----END PGP MESSAGE-----\n", buf) == 0)
             || (!needpass
-                && (mutt_strcmp ("-----END PGP SIGNATURE-----\n", buf) == 0
-                    || mutt_strcmp ("-----END PGP PUBLIC KEY BLOCK-----\n",
+                && (str_cmp ("-----END PGP SIGNATURE-----\n", buf) == 0
+                    || str_cmp ("-----END PGP PUBLIC KEY BLOCK-----\n",
                                     buf) == 0)))
           break;
       }
@@ -310,7 +317,7 @@ void pgp_application_pgp_handler (BODY * m, STATE * s)
         mutt_mktemp (outfile);
         if ((pgpout = safe_fopen (outfile, "w+")) == NULL) {
           mutt_perror (tmpfname);
-          return;
+          return (-1);
         }
 
         if ((thepid = pgp_invoke_decode (&pgpin, NULL, &pgperr, -1,
@@ -347,21 +354,30 @@ void pgp_application_pgp_handler (BODY * m, STATE * s)
           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
- */
+
+            /*
+             * 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_putc ('\n', s);
             state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
           }
         }
-      }
 
+        /* treat empty result as sign of failure */
+        rewind (pgpout);
+        if ((c = fgetc (pgpout)) == EOF) {
+            mutt_error _("Could not decrypt PGP message");
+            pgp_void_passphrase ();
+            rc = -1;
+            goto out;
+        }
+        ungetc (c, pgpout);
+      }
 
       /*
        * Now, copy cleartext to the screen.  NOTE - we expect that PGP
@@ -397,22 +413,16 @@ void pgp_application_pgp_handler (BODY * m, STATE * s)
 
       if (s->flags & M_DISPLAY) {
         state_putc ('\n', s);
-        if (needpass)
+        if (needpass) {
           state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
+          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);
       }
 
-      if (tmpfp) {
-        safe_fclose (&tmpfp);
-        mutt_unlink (tmpfname);
-      }
-      if (pgpout) {
-        safe_fclose (&pgpout);
-        mutt_unlink (outfile);
-      }
     }
     else {
       /* XXX - we may wish to recode here */
@@ -422,14 +432,28 @@ void pgp_application_pgp_handler (BODY * m, STATE * s)
     }
   }
 
+  rc = 0;
+
+out:
   m->goodsig = (maybe_goodsig && have_any_sigs);
 
+  if (tmpfp) {
+    safe_fclose (&tmpfp);
+    mutt_unlink (tmpfname);
+  }
+  if (pgpout) {
+    safe_fclose (&pgpout);
+    mutt_unlink (outfile);
+  }
+
   if (needpass == -1) {
     state_attach_puts (_
                        ("[-- Error: could not find beginning of PGP message! --]\n\n"),
                        s);
-    return;
+    return (-1);
   }
+
+  return (rc);
 }
 
 static int pgp_check_traditional_one_body (FILE * fp, BODY * b,
@@ -461,12 +485,12 @@ static int pgp_check_traditional_one_body (FILE * fp, BODY * b,
   }
 
   while (fgets (buf, sizeof (buf), tfp)) {
-    if (mutt_strncmp ("-----BEGIN PGP ", buf, 15) == 0) {
-      if (mutt_strcmp ("MESSAGE-----\n", buf + 15) == 0)
+    if (str_ncmp ("-----BEGIN PGP ", buf, 15) == 0) {
+      if (str_cmp ("MESSAGE-----\n", buf + 15) == 0)
         enc = 1;
-      else if (mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15) == 0)
+      else if (str_cmp ("SIGNED MESSAGE-----\n", buf + 15) == 0)
         sgn = 1;
-      else if (mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15) == 0)
+      else if (str_cmp ("PUBLIC KEY BLOCK-----\n", buf + 15) == 0)
         key = 1;
     }
   }
@@ -557,9 +581,7 @@ int pgp_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
     if ((rv = mutt_wait_filter (thepid)))
       badsig = -1;
 
-    dprint (1,
-            (debugfile, "pgp_verify_one: mutt_wait_filter returned %d.\n",
-             rv));
+    debug_print (1, ("mutt_wait_filter returned %d.\n", rv));
   }
 
   safe_fclose (&pgperr);
@@ -569,7 +591,7 @@ int pgp_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
   mutt_unlink (sigfile);
   mutt_unlink (pgperrfile);
 
-  dprint (1, (debugfile, "pgp_verify_one: returning %d.\n", badsig));
+  debug_print (1, ("returning %d.\n", badsig));
 
   return badsig;
 }
@@ -691,6 +713,7 @@ BODY *pgp_decrypt_part (BODY * a, STATE * s, FILE * fpout, BODY * p)
   char pgperrfile[_POSIX_PATH_MAX];
   char pgptmpfile[_POSIX_PATH_MAX];
   pid_t thepid;
+  int rv;
 
   mutt_mktemp (pgperrfile);
   if ((pgperr = safe_fopen (pgperrfile, "w+")) == NULL) {
@@ -737,21 +760,23 @@ BODY *pgp_decrypt_part (BODY * a, STATE * s, FILE * fpout, BODY * p)
    * read_mime_header has a hard time parsing the message.
    */
   while (fgets (buf, sizeof (buf) - 1, pgpout) != NULL) {
-    len = mutt_strlen (buf);
+    len = str_len (buf);
     if (len > 1 && buf[len - 2] == '\r')
       strcpy (buf + len - 2, "\n");     /* __STRCPY_CHECKED__ */
     fputs (buf, fpout);
   }
 
   fclose (pgpout);
-  mutt_wait_filter (thepid);
+  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 && p)
+    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);
   }
   fclose (pgperr);
@@ -759,8 +784,11 @@ BODY *pgp_decrypt_part (BODY * a, STATE * s, FILE * fpout, BODY * p)
   fflush (fpout);
   rewind (fpout);
 
-  if (fgetc (fpout) == EOF)
+  if (fgetc (fpout) == EOF) {
+    mutt_error (_("Decryption failed."));
+    pgp_void_passphrase ();
     return NULL;
+  }
 
   rewind (fpout);
 
@@ -812,12 +840,13 @@ int pgp_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur)
   return (0);
 }
 
-void pgp_encrypted_handler (BODY * a, STATE * s)
+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 ||
@@ -827,7 +856,7 @@ void pgp_encrypted_handler (BODY * a, STATE * s)
     if (s->flags & M_DISPLAY)
       state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
                          s);
-    return;
+    return (-1);
   }
 
   /*
@@ -841,7 +870,7 @@ void pgp_encrypted_handler (BODY * a, STATE * s)
       state_attach_puts (_
                          ("[-- Error: could not create temporary file! --]\n"),
                          s);
-    return;
+    return (-1);
   }
 
   if (s->flags & M_DISPLAY)
@@ -855,7 +884,7 @@ void pgp_encrypted_handler (BODY * a, STATE * s)
 
     fpin = s->fpin;
     s->fpin = fpout;
-    mutt_body_handler (tattach, s);
+    rc = mutt_body_handler (tattach, s);
     s->fpin = fpin;
 
     /* 
@@ -874,10 +903,18 @@ void pgp_encrypted_handler (BODY * a, STATE * s)
     }
 
     mutt_free_body (&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;
   }
 
   fclose (fpout);
   mutt_unlink (tempfile);
+
+  return (rc);
 }
 
 /* ----------------------------------------------------------------------------
@@ -917,7 +954,7 @@ BODY *pgp_sign_message (BODY * a)
 
   if ((thepid = pgp_invoke_sign (&pgpin, &pgpout, &pgperr,
                                  -1, -1, -1, signedfile)) == -1) {
-    mutt_perror _("Can't open PGP subprocess!");
+    mutt_perror (_("Can't open PGP subprocess!"));
 
     fclose (fp);
     unlink (sigfile);
@@ -935,9 +972,9 @@ BODY *pgp_sign_message (BODY * a)
    * recommended for future releases of PGP.
    */
   while (fgets (buffer, sizeof (buffer) - 1, pgpout) != NULL) {
-    if (mutt_strcmp ("-----BEGIN PGP MESSAGE-----\n", buffer) == 0)
+    if (str_cmp ("-----BEGIN PGP MESSAGE-----\n", buffer) == 0)
       fputs ("-----BEGIN PGP SIGNATURE-----\n", fp);
-    else if (mutt_strcmp ("-----END PGP MESSAGE-----\n", buffer) == 0)
+    else if (str_cmp ("-----END PGP MESSAGE-----\n", buffer) == 0)
       fputs ("-----END PGP SIGNATURE-----\n", fp);
     else
       fputs (buffer, fp);
@@ -976,7 +1013,7 @@ BODY *pgp_sign_message (BODY * a)
 
   t = mutt_new_body ();
   t->type = TYPEMULTIPART;
-  t->subtype = safe_strdup ("signed");
+  t->subtype = str_dup ("signed");
   t->encoding = ENC7BIT;
   t->use_disp = 0;
   t->disposition = DISPINLINE;
@@ -991,8 +1028,8 @@ BODY *pgp_sign_message (BODY * a)
   t->parts->next = mutt_new_body ();
   t = t->parts->next;
   t->type = TYPEAPPLICATION;
-  t->subtype = safe_strdup ("pgp-signature");
-  t->filename = safe_strdup (sigfile);
+  t->subtype = str_dup ("pgp-signature");
+  t->filename = str_dup (sigfile);
   t->use_disp = 0;
   t->disposition = DISPINLINE;
   t->encoding = ENC7BIT;
@@ -1006,7 +1043,7 @@ static short is_numerical_keyid (const char *s)
   /* or should we require the "0x"? */
   if (strncmp (s, "0x", 2) == 0)
     s += 2;
-  if (strlen (s) % 8)
+  if (str_len (s) % 8)
     return 0;
   while (*s)
     if (strchr ("0123456789ABCDEFabcdef", *s++) == NULL)
@@ -1085,7 +1122,7 @@ char *pgp_findKeys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc)
           k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING);
       }
       else if (r == -1) {
-        FREE (&keylist);
+        mem_free (&keylist);
         rfc822_free_address (&tmp);
         rfc822_free_address (&addr);
         return NULL;
@@ -1102,7 +1139,7 @@ char *pgp_findKeys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc)
 
       if ((key = pgp_ask_for_key (buf, q->mailbox,
                                   KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) {
-        FREE (&keylist);
+        mem_free (&keylist);
         rfc822_free_address (&tmp);
         rfc822_free_address (&addr);
         return NULL;
@@ -1114,11 +1151,11 @@ char *pgp_findKeys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc)
     keyID = pgp_keyid (key);
 
   bypass_selection:
-    keylist_size += mutt_strlen (keyID) + 4;
-    safe_realloc (&keylist, keylist_size);
+    keylist_size += str_len (keyID) + 4;
+    mem_realloc (&keylist, keylist_size);
     sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "", /* __SPRINTF_CHECKED__ */
              keyID);
-    keylist_used = mutt_strlen (keylist);
+    keylist_used = str_len (keylist);
 
     pgp_free_key (&key);
     rfc822_free_address (&addr);
@@ -1214,13 +1251,15 @@ BODY *pgp_encrypt_message (BODY * a, char *keylist, int sign)
 
   if (empty) {
     /* fatal error while trying to encrypt message */
+    if (sign)
+      pgp_void_passphrase (); /* just in case */
     unlink (tempfile);
     return (NULL);
   }
 
   t = mutt_new_body ();
   t->type = TYPEMULTIPART;
-  t->subtype = safe_strdup ("encrypted");
+  t->subtype = str_dup ("encrypted");
   t->encoding = ENC7BIT;
   t->use_disp = 0;
   t->disposition = DISPINLINE;
@@ -1230,18 +1269,18 @@ BODY *pgp_encrypt_message (BODY * a, char *keylist, int sign)
 
   t->parts = mutt_new_body ();
   t->parts->type = TYPEAPPLICATION;
-  t->parts->subtype = safe_strdup ("pgp-encrypted");
+  t->parts->subtype = str_dup ("pgp-encrypted");
   t->parts->encoding = ENC7BIT;
 
   t->parts->next = mutt_new_body ();
   t->parts->next->type = TYPEAPPLICATION;
-  t->parts->next->subtype = safe_strdup ("octet-stream");
+  t->parts->next->subtype = str_dup ("octet-stream");
   t->parts->next->encoding = ENC7BIT;
-  t->parts->next->filename = safe_strdup (tempfile);
+  t->parts->next->filename = str_dup (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 = safe_strdup ("msg.asc"); /* non pgp/mime can save */
+  t->parts->next->d_filename = str_dup ("msg.asc"); /* non pgp/mime can save */
 
   return (t);
 }
@@ -1337,7 +1376,7 @@ BODY *pgp_traditional_encryptsign (BODY * a, int flags, char *keylist)
   if ((thepid = pgp_invoke_traditional (&pgpin, NULL, NULL,
                                         -1, fileno (pgpout), fileno (pgperr),
                                         pgpinfile, keylist, flags)) == -1) {
-    mutt_perror _("Can't invoke PGP");
+    mutt_perror (_("Can't invoke PGP"));
 
     fclose (pgpout);
     fclose (pgperr);
@@ -1380,6 +1419,8 @@ BODY *pgp_traditional_encryptsign (BODY * a, int flags, char *keylist)
     mutt_any_key_to_continue (NULL);
 
   if (empty) {
+    if (flags & SIGN)
+      pgp_void_passphrase (); /* just in case */
     unlink (pgpoutfile);
     return NULL;
   }
@@ -1389,21 +1430,21 @@ BODY *pgp_traditional_encryptsign (BODY * a, int flags, char *keylist)
   b->encoding = ENC7BIT;
 
   b->type = TYPETEXT;
-  b->subtype = safe_strdup ("plain");
+  b->subtype = str_dup ("plain");
 
   mutt_set_parameter ("x-action",
                       flags & ENCRYPT ? "pgp-encrypted" : "pgp-signed",
                       &b->parameter);
   mutt_set_parameter ("charset", send_charset, &b->parameter);
 
-  b->filename = safe_strdup (pgpoutfile);
+  b->filename = str_dup (pgpoutfile);
 
 #if 0
   /* The following is intended to give a clue to some completely brain-dead 
    * "mail environments" which are typically used by large corporations.
    */
 
-  b->d_filename = safe_strdup ("msg.pgp");
+  b->d_filename = str_dup ("msg.pgp");
   b->use_disp = 1;
 
 #endif
@@ -1457,7 +1498,7 @@ int pgp_send_menu (HEADER * msg, int *redraw)
          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);
+      str_replace (&PgpSignAs, input_signas);
       pgp_free_key (&p);
 
       msg->security |= SIGN;