* keygen.c (proc_parameter_file): Default key and subkey usage flags to
[gnupg.git] / g10 / passphrase.c
index a68d564..d0a19d2 100644 (file)
@@ -1,6 +1,6 @@
 /* passphrase.c -  Get a passphrase
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
- *               2004, 2005 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ *               2005 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -16,7 +16,8 @@
  *
  * 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-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
  */
 
 #include <config.h>
                      *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
 #define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
 
-
-
 static char *fd_passwd = NULL;
 static char *next_pw = NULL;
 static char *last_pw = NULL;
 
-#if defined (_WIN32)
-static int read_fd = 0;
-static int write_fd = 0;
-#endif
-
 static void hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create );
 
 int
@@ -100,10 +94,10 @@ have_static_passphrase()
 void
 set_next_passphrase( const char *s )
 {
-    m_free(next_pw);
+    xfree(next_pw);
     next_pw = NULL;
     if( s ) {
-       next_pw = m_alloc_secure( strlen(s)+1 );
+       next_pw = xmalloc_secure( strlen(s)+1 );
        strcpy(next_pw, s );
     }
 }
@@ -121,6 +115,19 @@ get_last_passphrase()
     return p;
 }
 
+/* Here's an interesting question: since this passphrase was passed in
+   on the command line, is there really any point in using secure
+   memory for it?  I'm going with 'yes', since it doesn't hurt, and
+   might help in some small way (swapping). */
+
+void
+set_passphrase_from_string(const char *pass)
+{
+  xfree( fd_passwd );
+  fd_passwd = xmalloc_secure(strlen(pass)+1);
+  strcpy(fd_passwd,pass);
+}
+
 
 void
 read_passphrase_from_fd( int fd )
@@ -148,11 +155,11 @@ read_passphrase_from_fd( int fd )
         {
           char *pw2 = pw;
           len += 100;
-          pw = m_alloc_secure( len );
+          pw = xmalloc_secure( len );
           if( pw2 )
             {
               memcpy(pw, pw2, i );
-              m_free (pw2);
+              xfree (pw2);
             }
           else
             i=0;
@@ -164,7 +171,7 @@ read_passphrase_from_fd( int fd )
   if (!opt.batch)
     tty_printf("\b\b\b   \n" );
 
-  m_free( fd_passwd );
+  xfree( fd_passwd );
   fd_passwd = pw;
 }
 
@@ -235,7 +242,7 @@ agent_send_all_options (assuan_context_t ctx)
 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
   old_lc = setlocale (LC_CTYPE, NULL);
   if (old_lc)
-    old_lc = m_strdup (old_lc);
+    old_lc = xstrdup (old_lc);
   dft_lc = setlocale (LC_CTYPE, "");
 #endif
   if (opt.lc_ctype || (dft_ttyname && dft_lc))
@@ -247,7 +254,7 @@ agent_send_all_options (assuan_context_t ctx)
   if (old_lc)
     {
       setlocale (LC_CTYPE, old_lc);
-      m_free (old_lc);
+      xfree (old_lc);
     }
 #endif
   if (rc)
@@ -256,7 +263,7 @@ agent_send_all_options (assuan_context_t ctx)
 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
   old_lc = setlocale (LC_MESSAGES, NULL);
   if (old_lc)
-    old_lc = m_strdup (old_lc);
+    old_lc = xstrdup (old_lc);
   dft_lc = setlocale (LC_MESSAGES, "");
 #endif
   if (opt.lc_messages || (dft_ttyname && dft_lc))
@@ -268,7 +275,7 @@ agent_send_all_options (assuan_context_t ctx)
   if (old_lc)
     {
       setlocale (LC_MESSAGES, old_lc);
-      m_free (old_lc);
+      xfree (old_lc);
     }
 #endif
   return rc;
@@ -278,12 +285,15 @@ agent_send_all_options (assuan_context_t ctx)
 
 /*
  * Open a connection to the agent and initializes the connection.
- * Returns: -1 on error; on success a file descriptor for that
- * connection is returned.
+ * Returns: -1 on error; on success an Assuan context for that
+ * connection is returned.  With TRY set to true, no error messages
+ * are printed and the use of the agent won't get disabled on failure.
+ * If ORIG_CODESET is not NULL, the function will swithc the codeset
+ * back to that one before printing error messages.
  */
 #ifdef ENABLE_AGENT_SUPPORT
-static assuan_context_t
-agent_open (void)
+assuan_context_t
+agent_open (int try, const char *orig_codeset)
 {
   int rc;
   assuan_context_t ctx;
@@ -298,8 +308,15 @@ agent_open (void)
       infostr = getenv ( "GPG_AGENT_INFO" );
       if (!infostr || !*infostr) 
         {
-          log_error (_("gpg-agent is not available in this session\n"));
-          opt.use_agent = 0;
+          if (!try)
+            {
+#ifdef ENABLE_NLS
+              if (orig_codeset)
+                bind_textdomain_codeset (PACKAGE, orig_codeset);
+#endif /*ENABLE_NLS*/
+              log_info (_("gpg-agent is not available in this session\n"));
+              opt.use_agent = 0;
+            }
           return NULL;
         }
       infostr = xstrdup ( infostr );
@@ -307,9 +324,16 @@ agent_open (void)
   
   if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
     {
-      log_error ( _("malformed GPG_AGENT_INFO environment variable\n"));
+      if (!try)
+        {
+#ifdef ENABLE_NLS
+          if (orig_codeset)
+            bind_textdomain_codeset (PACKAGE, orig_codeset);
+#endif /*ENABLE_NLS*/
+          log_error ( _("malformed GPG_AGENT_INFO environment variable\n"));
+          opt.use_agent = 0;
+        }
       xfree (infostr);
-      opt.use_agent = 0;
       return NULL;
     }
   *p++ = 0;
@@ -319,28 +343,50 @@ agent_open (void)
   prot = *p? atoi (p+1) : 0;
   if (prot != 1)
     {
-      log_error (_("gpg-agent protocol version %d is not supported\n"), prot);
+      if (!try)
+        {
+#ifdef ENABLE_NLS
+          if (orig_codeset)
+            bind_textdomain_codeset (PACKAGE, orig_codeset);
+#endif /*ENABLE_NLS*/
+          log_error (_("gpg-agent protocol version %d is not supported\n"),
+                     prot);
+          opt.use_agent = 0;
+        }
       xfree (infostr);
-      opt.use_agent = 0;
       return NULL;
     }
      
   rc = assuan_socket_connect (&ctx, infostr, pid);
   if (rc)
     {
-      log_error ( _("can't connect to `%s': %s\n"), 
-                  infostr, assuan_strerror (rc));
+      if (!try)
+        {
+#ifdef ENABLE_NLS
+          if (orig_codeset)
+            bind_textdomain_codeset (PACKAGE, orig_codeset);
+#endif /*ENABLE_NLS*/
+          log_error ( _("can't connect to `%s': %s\n"), 
+                      infostr, assuan_strerror (rc));
+          opt.use_agent = 0;
+        }
       xfree (infostr );
-      opt.use_agent = 0;
       return NULL;
     }
   xfree (infostr);
 
   if (agent_send_all_options (ctx))
     {
-      log_error (_("problem with the agent - disabling agent use\n"));
+      if (!try)
+        {
+#ifdef ENABLE_NLS
+          if (orig_codeset)
+            bind_textdomain_codeset (PACKAGE, orig_codeset);
+#endif /*ENABLE_NLS*/
+          log_error (_("problem with the agent - disabling agent use\n"));
+          opt.use_agent = 0;
+        }
       assuan_disconnect (ctx);
-      opt.use_agent = 0;
       return NULL;
     }
 
@@ -350,7 +396,7 @@ agent_open (void)
 
 
 #ifdef ENABLE_AGENT_SUPPORT
-static void
+void
 agent_close (assuan_context_t ctx)
 {
   assuan_disconnect (ctx);
@@ -439,7 +485,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *cacheid,
   char *atext = NULL;
   assuan_context_t ctx = NULL;
   char *pw = NULL;
-  PKT_public_key *pk = m_alloc_clear( sizeof *pk );
+  PKT_public_key *pk = xmalloc_clear( sizeof *pk );
   byte fpr[MAX_FINGERPRINT_LEN];
   int have_fpr = 0;
   char *orig_codeset = NULL;
@@ -468,13 +514,13 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *cacheid,
 #endif
   if (orig_codeset)
     { /* We only switch when we are able to restore the codeset later. */
-      orig_codeset = m_strdup (orig_codeset);
+      orig_codeset = xstrdup (orig_codeset);
       if (!bind_textdomain_codeset (PACKAGE, "utf-8"))
         orig_codeset = NULL; 
     }
 #endif
 
-  if ( !(ctx = agent_open ()) ) 
+  if ( !(ctx = agent_open (0, orig_codeset)) ) 
     goto failure;
 
   if (custom_description)
@@ -492,7 +538,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *cacheid,
 
 #define KEYIDSTRING _(" (main key ID %s)")
 
-      maink = m_alloc ( strlen (KEYIDSTRING) + keystrlen() + 20 );
+      maink = xmalloc ( strlen (KEYIDSTRING) + keystrlen() + 20 );
       if( keyid[2] && keyid[3] && keyid[0] != keyid[2] 
           && keyid[1] != keyid[3] )
         sprintf( maink, KEYIDSTRING, keystr(&keyid[2]) );
@@ -509,15 +555,15 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *cacheid,
                       "\"%.*s\"\n" \
                       "%u-bit %s key, ID %s, created %s%s\n" )
 
-      atext = m_alloc ( 100 + strlen (PROMPTSTRING)  
+      atext = xmalloc ( 100 + strlen (PROMPTSTRING)  
                         + uidlen + 15 + strlen(algo_name) + keystrlen()
                         + strlen (timestr) + strlen (maink) );
       sprintf (atext, PROMPTSTRING,
                (int)uidlen, uid,
                nbits_from_pk (pk), algo_name, keystr(&keyid[0]), timestr,
                maink  );
-      m_free (uid);
-      m_free (maink);
+      xfree (uid);
+      xfree (maink);
 
 #undef PROMPTSTRING
 
@@ -529,9 +575,9 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *cacheid,
       
     }
   else if (mode == 2 ) 
-    atext = m_strdup ( _("Repeat passphrase\n") );
+    atext = xstrdup ( _("Repeat passphrase\n") );
   else
-    atext = m_strdup ( _("Enter passphrase\n") );
+    atext = xstrdup ( _("Enter passphrase\n") );
                 
   { 
       char *line, *p;
@@ -622,7 +668,10 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *cacheid,
  failure:
 #ifdef ENABLE_NLS
   if (orig_codeset)
-    bind_textdomain_codeset (PACKAGE, orig_codeset);
+    {
+      bind_textdomain_codeset (PACKAGE, orig_codeset);
+      xfree (orig_codeset);
+    }
 #endif
   xfree (atext);
   agent_close (ctx);
@@ -672,7 +721,7 @@ passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo )
   else
     pk = NULL;
     
-  if ( !(ctx = agent_open ()) ) 
+  if ( !(ctx = agent_open (0, NULL)) ) 
     goto failure;
 
   { 
@@ -729,7 +778,16 @@ ask_passphrase (const char *description,
     *canceled = 0;
 
   if (!opt.batch && description)
-    tty_printf ("\n%s\n",description);
+    {
+      if (strchr (description, '%'))
+        {
+          char *tmp = unescape_percent_string (description);
+          tty_printf ("\n%s\n", tmp);
+          xfree (tmp);
+        }
+      else
+        tty_printf ("\n%s\n",description);
+    }
                
  agent_died:
   if ( opt.use_agent ) 
@@ -746,7 +804,7 @@ ask_passphrase (const char *description,
     }
   else if (fd_passwd) 
     {
-      pw = m_alloc_secure (strlen(fd_passwd)+1);
+      pw = xmalloc_secure (strlen(fd_passwd)+1);
       strcpy (pw, fd_passwd);
     }
   else if (opt.batch)
@@ -816,7 +874,7 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
 
             us = get_long_user_id_string( keyid );
             write_status_text( STATUS_USERID_HINT, us );
-            m_free(us);
+            xfree(us);
 
            sprintf( buf, "%08lX%08lX %08lX%08lX %d 0",
                      (ulong)keyid[0], (ulong)keyid[1],
@@ -836,14 +894,14 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
        ignore the passphrase cache (mode!=1), print a prompt with
        information on that key. */
     if( keyid && !opt.batch && !next_pw && mode!=1 ) {
-       PKT_public_key *pk = m_alloc_clear( sizeof *pk );
+       PKT_public_key *pk = xmalloc_clear( sizeof *pk );
        char *p;
 
        p=get_user_id_native(keyid);
        tty_printf("\n");
        tty_printf(_("You need a passphrase to unlock the secret key for\n"
                     "user: \"%s\"\n"),p);
-       m_free(p);
+       xfree(p);
 
        if( !get_pubkey( pk, keyid ) ) {
            const char *s = pubkey_algo_to_string( pk->pubkey_algo );
@@ -884,7 +942,7 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
           {
             if (!opt.use_agent)
               goto agent_died;
-            pw = m_strdup ("");
+            pw = xstrdup ("");
           }
         if( *pw && mode == 2 ) {
             char *pw2 = agent_get_passphrase ( keyid, 2, NULL, NULL, NULL,
@@ -893,29 +951,29 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
               {
                 if (!opt.use_agent)
                   {
-                    m_free (pw);
+                    xfree (pw);
                     pw = NULL;
                     goto agent_died;
                   }
-                pw2 = m_strdup ("");
+                pw2 = xstrdup ("");
               }
            if( strcmp(pw, pw2) ) {
-               m_free(pw2);
-               m_free(pw);
+               xfree(pw2);
+               xfree(pw);
                return NULL;
            }
-           m_free(pw2);
+           xfree(pw2);
        }
     }
     else if( fd_passwd ) {
         /* Return the passphrase we have store in FD_PASSWD. */
-       pw = m_alloc_secure( strlen(fd_passwd)+1 );
+       pw = xmalloc_secure( strlen(fd_passwd)+1 );
        strcpy( pw, fd_passwd );
     }
     else if( opt.batch )
       {
        log_error(_("can't query passphrase in batch mode\n"));
-       pw = m_strdup( "" ); /* return an empty passphrase */
+       pw = xstrdup( "" ); /* return an empty passphrase */
       }
     else {
         /* Read the passphrase from the tty or the command-fd. */
@@ -926,11 +984,11 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
                                       _("Repeat passphrase: ") );
            tty_kill_prompt();
            if( strcmp(pw, pw2) ) {
-               m_free(pw2);
-               m_free(pw);
+               xfree(pw2);
+               xfree(pw);
                return NULL;
            }
-           m_free(pw2);
+           xfree(pw2);
        }
     }
 
@@ -940,13 +998,13 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
     /* Hash the passphrase and store it in a newly allocated DEK
        object.  Keep a copy of the passphrase in LAST_PW for use by
        get_last_passphrase(). */
-    dek = m_alloc_secure_clear ( sizeof *dek );
+    dek = xmalloc_secure_clear ( sizeof *dek );
     dek->algo = cipher_algo;
     if( !*pw && mode == 2 )
        dek->keylen = 0;
     else
        hash_passphrase( dek, pw, s2k, mode==2 );
-    m_free(last_pw);
+    xfree(last_pw);
     last_pw = pw;
     return dek;
 }