Rocco Rutte:
[apps/madmutt.git] / smime.c
diff --git a/smime.c b/smime.c
index a7498e5..2361830 100644 (file)
--- a/smime.c
+++ b/smime.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2001,2002 Oliver Ehli <elmy@acm.org>
  * Copyright (C) 2002 Mike Schiraldi <raldi@research.netsol.com>
+ * 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
  *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  */
 
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
 #include "mutt.h"
 #include "mutt_curses.h"
 #include "mutt_menu.h"
@@ -48,7 +53,6 @@
 
 #include "mutt_crypt.h"
 
-
 struct smime_command_context {
   const char *key;                 /* %k */
   const char *cryptalg;                    /* %a */
@@ -94,9 +98,26 @@ 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;
 
+  smime_void_passphrase();
+  
+  if (mutt_get_password (_("Enter SMIME passphrase:"), SmimePass, sizeof (SmimePass)) == 0)
+    {
+      SmimeExptime = time (NULL) + SmimeTimeout;
+      return (1);
+    }
+  else
+    SmimeExptime = 0;
 
+  return 0;
+}
 
 
 /*
@@ -443,8 +464,8 @@ char* smime_ask_for_key (char *prompt, char *mailbox, short public)
       }
     }
     if (hash) {
-      fname = safe_malloc(14); /* Hash + '.' + Suffix + \n + \0 */
-      sprintf(fname, "%.8x.%i\n", Table[cur].hash, Table[cur].suffix);
+      fname = safe_malloc(13); /* Hash + '.' + Suffix + \0 */
+      sprintf(fname, "%.8x.%i", Table[cur].hash, Table[cur].suffix);
     }
     else fname = NULL;
   
@@ -464,21 +485,22 @@ char *smime_get_field_from_db (char *mailbox, char *query, short public, short m
   char cert_path[_POSIX_PATH_MAX];
   char buf[LONG_STRING], prompt[STRING];
   char fields[5][STRING];
+  char key[STRING];  
   int numFields;
   struct stat info;
-  char *key=NULL, key_trust_level = 0;
+  char key_trust_level = 0;
   FILE *fp;
 
   if(!mailbox && !query) return(NULL);
 
   addr_len = mailbox ? mutt_strlen (mailbox) : 0;
   query_len = query ? mutt_strlen (query) : 0;
+  
+  *key = '\0';
 
   /* index-file format:
      mailbox certfile label issuer_certfile trust_flags\n
 
-     \n is also copied here, serving as delimitation.
-     
      certfile is a hash value generated by openssl.
      Note that this was done according to the OpenSSL
      specs on their CA-directory.
@@ -531,8 +553,7 @@ char *smime_get_field_from_db (char *mailbox, char *query, short public, short m
          {
            found = 0;
            ask = 0;
-           FREE (&key);
-           key = NULL;
+           *key = '\0';
            break;
          }
          else if (choice == M_NO) 
@@ -542,44 +563,46 @@ char *smime_get_field_from_db (char *mailbox, char *query, short public, short m
          }
          else if (choice == M_YES)
          {
-           snprintf (key,mutt_strlen(key)+1, "%s", fields[1]);
+           strfcpy (key, fields[1], sizeof (key));
            ask = 0;
            break;
          }
        }
        else
        {
-         key = safe_calloc(1, mutt_strlen(fields[1])+2);
-         if (public) key_trust_level = *fields[4];
-         snprintf(key, mutt_strlen(fields[1])+1, "%s", fields[1]);
-
+         if (public) 
+           key_trust_level = *fields[4];
+         strfcpy (key, fields[1], sizeof (key));
        }
        found = 1;
       }
       else if(query)
       {
-       numFields = sscanf (buf, "%s %s %s %s %s\n", fields[0], fields[1],
-                           fields[2], fields[3], fields[4]);
+       numFields = sscanf (buf, 
+                           MUTT_FORMAT(STRING) " " MUTT_FORMAT(STRING) " " 
+                           MUTT_FORMAT(STRING) " " MUTT_FORMAT(STRING) " " 
+                           MUTT_FORMAT(STRING) "\n", 
+                           fields[0], fields[1],
+                           fields[2], fields[3], 
+                           fields[4]);
 
        /* query = label: return certificate. */
        if (numFields >= 3 && 
            !(mutt_strncasecmp (query, fields[2], query_len)))
        {
          ask = 0;
-         key = safe_calloc(1, mutt_strlen(fields[1])+2);
-         snprintf(key, mutt_strlen(fields[1])+1, "%s", fields[1]);
+         strfcpy (key, fields[1], sizeof (key));
        }
        /* query = certificate: return intermediate certificate. */
        else if (numFields >= 4 && 
                 !(mutt_strncasecmp (query, fields[1], query_len)))
        {
          ask = 0;
-         key = safe_calloc(1, mutt_strlen(fields[3])+2);
-         snprintf(key, mutt_strlen(fields[3])+1, "%s", fields[3]);
+         strfcpy (key, fields[3], sizeof (key));
        }
       }
 
-    fclose (fp);
+    safe_fclose (&fp);
 
     if (ask)
     {
@@ -596,10 +619,7 @@ char *smime_get_field_from_db (char *mailbox, char *query, short public, short m
                  mailbox);
       choice = mutt_yesorno (prompt, M_NO);
       if (choice == -1 || choice == M_NO)
-      {
-       FREE (&key);
-       key = NULL;
-      }
+       *key = '\0';
     }
     else if (key_trust_level && may_ask)
     {
@@ -610,11 +630,7 @@ char *smime_get_field_from_db (char *mailbox, char *query, short public, short m
                  key, mailbox);
        choice = mutt_yesorno (prompt, M_NO);
        if (choice != M_YES)
-       {
-         FREE (&key);
-         key = NULL;
-       }
-
+         *key = '\0';
       }
       else if (key_trust_level == 'v' )
       {
@@ -625,13 +641,8 @@ char *smime_get_field_from_db (char *mailbox, char *query, short public, short m
 
   }
 
-  if (key)
-  {
-    key[mutt_strlen(key)+1] = '\0';
-    key[mutt_strlen(key)] = '\n';
-  }
-
-  return key;
+  /* Note: safe_strdup ("") returns NULL. */
+  return safe_strdup (key);
 }
 
 
@@ -658,8 +669,6 @@ void _smime_getkeys (char *mailbox)
 
   if (k)
   {
-    k[mutt_strlen (k)-1] = '\0';
-    
     /* the key used last time. */
     if (*SmimeKeyToUse && 
         !mutt_strcasecmp (k, SmimeKeyToUse + mutt_strlen (SmimeKeys)+1))
@@ -791,9 +800,9 @@ char *smime_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc)
       return NULL;
     }
     
-    keylist_size += mutt_strlen (keyID) + 1;
+    keylist_size += mutt_strlen (keyID) + 2;
     safe_realloc (&keylist, keylist_size);
-    sprintf (keylist + keylist_used, "%s", keyID);     /* __SPRINTF_CHECKED__ */
+    sprintf (keylist + keylist_used, "%s\n", keyID);   /* __SPRINTF_CHECKED__ */
     keylist_used = mutt_strlen (keylist);
 
     rfc822_free_address (&addr);
@@ -1381,8 +1390,6 @@ BODY *smime_sign_message (BODY *a )
     mutt_message(_("Warning: Intermediate certificate not found."));
     intermediates = SmimeDefaultKey; /* so openssl won't complain in any case */
   }
-  else
-      intermediates[mutt_strlen (intermediates)-1] = '\0';
 
   convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */
 
@@ -1917,4 +1924,95 @@ 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 (c)lear? "),
+                            _("eswabfc")))
+  {
+  case 1: /* (e)ncrypt */
+    msg->security |= ENCRYPT;
+    msg->security &= ~SIGN;
+    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;
+      msg->security &= ~ENCRYPT;
+    }
+    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 ();
+    }
+#if 0
+    else
+      msg->security &= ~SIGN;
+#endif
+
+    *redraw = REDRAW_FULL;
+    break;
+
+  case 5: /* (b)oth */
+    msg->security |= (ENCRYPT | SIGN);
+    break;
+
+  case 6: /* (f)orget it */
+  case 7: /* (c)lear */
+    msg->security = 0;
+    break;
+  }
+
+  if (msg->security && msg->security != APPLICATION_SMIME)
+    msg->security |= APPLICATION_SMIME;
+  else
+    msg->security = 0;
+
+  return (msg->security);
+}
+
+
 #endif /* CRYPT_BACKEND_CLASSIC_SMIME */