* passphrase.c (read_passphrase_from_fd): Do a dummy read if the
authorWerner Koch <wk@gnupg.org>
Thu, 10 Apr 2003 09:56:47 +0000 (09:56 +0000)
committerWerner Koch <wk@gnupg.org>
Thu, 10 Apr 2003 09:56:47 +0000 (09:56 +0000)
agent is to be used.  Noted by Ingo Kl�cker.
(agent_get_passphrase): Inhibit caching when we have no
fingerprint.  This is required for key generation as well as for
symmetric only encryption.

* passphrase .c (agent_get_passphrase): New arg CANCELED.
(passphrase_to_dek): Ditto.  Passed to above.  Changed all
callers to pass NULL.
* seckey-cert.c (do_check): New arg CANCELED.
(check_secret_key): Terminate loop when canceled.

* keyedit.c (change_passphrase): Pass ERRTEXT untranslated to
passphrase_to_dek and translate where appropriate.
* seckey-cert.c (check_secret_key): Ditto.
* keygen.c (ask_passphrase): Ditto.
* passphrase.c (agent_get_passphrase): Translate the TRYAGAIN_TEXT.
Switch the codeset to utf-8.

g10/ChangeLog
g10/decrypt.c
g10/encode.c
g10/gpgv.c
g10/keydb.h
g10/keyedit.c
g10/keygen.c
g10/mainproc.c
g10/passphrase.c
g10/seckey-cert.c
g10/sign.c

index 95c0669..eb358b1 100644 (file)
@@ -1,3 +1,30 @@
+2003-04-10  Werner Koch  <wk@gnupg.org>
+
+       * passphrase.c (read_passphrase_from_fd): Do a dummy read if the
+       agent is to be used.  Noted by Ingo Klöcker.
+       (agent_get_passphrase): Inhibit caching when we have no
+       fingerprint.  This is required for key generation as well as for
+       symmetric only encryption.
+
+       * passphrase .c (agent_get_passphrase): New arg CANCELED.
+       (passphrase_to_dek): Ditto.  Passed to above.  Changed all
+       callers to pass NULL.
+       * seckey-cert.c (do_check): New arg CANCELED.
+       (check_secret_key): Terminate loop when canceled.
+
+       * keyedit.c (change_passphrase): Pass ERRTEXT untranslated to
+       passphrase_to_dek and translate where appropriate.
+       * seckey-cert.c (check_secret_key): Ditto.
+       * keygen.c (ask_passphrase): Ditto.
+       * passphrase.c (agent_get_passphrase): Translate the TRYAGAIN_TEXT.
+       Switch the codeset to utf-8.
+
+2003-04-09  Werner Koch  <wk@gnupg.org>
+
+       * decrypt.c (decrypt_messages): Fixed error handling; the function
+       used to re-loop with same file after an error.  Reported by Joseph
+       Walton.
+
 2003-04-08  David Shaw  <dshaw@jabberwocky.com>
 
        * main.h, g10.c (main), import.c (parse_import_options,
index 297ee34..bea16b7 100644 (file)
@@ -1,5 +1,5 @@
 /* decrypt.c - verify signed data
- * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -99,12 +99,12 @@ decrypt_messages(int nfiles, char **files)
       print_file_status(STATUS_FILE_START, *files, 3);      
       output = make_outfile_name(*files);
       if (!output)
-        continue;
+        goto next_file;
       fp = iobuf_open(*files);
       if (!fp)
         {
           log_error(_("can't open `%s'\n"), print_fname_stdin(*files));
-          continue;
+          goto next_file;
         }
       if (!opt.no_armor)
         {
@@ -122,17 +122,13 @@ decrypt_messages(int nfiles, char **files)
       p = get_last_passphrase();
       set_next_passphrase(p);
       m_free (p);
-      files++;
-      m_free(output);
+
+    next_file:
+      /* Note that we emit file_done even after an error. */
       write_status( STATUS_FILE_DONE );
+      m_free(output);
+      files++;
     }
   set_next_passphrase(NULL);  
 }
 
-
-
-
-
-
-
-
index e705a6f..d1b0cdb 100644 (file)
@@ -194,7 +194,8 @@ encode_simple( const char *filename, int mode, int compat )
        s2k->mode = opt.rfc1991? 0:opt.s2k_mode;
        s2k->hash_algo = opt.s2k_digest_algo;
        cfx.dek = passphrase_to_dek( NULL, 0,
-                                    default_cipher_algo(), s2k, 2, NULL );
+                                    default_cipher_algo(), s2k, 2,
+                                     NULL, NULL);
        if( !cfx.dek || !cfx.dek->keylen ) {
            rc = G10ERR_PASSPHRASE;
            m_free(cfx.dek);
index eba6f8d..caa6691 100644 (file)
@@ -314,9 +314,11 @@ check_secret_key( PKT_secret_key *sk, int n )
 DEK *
 passphrase_to_dek( u32 *keyid, int pubkey_algo,
                   int cipher_algo, STRING2KEY *s2k, int mode,
-                   const char *tmp)
+                   const char *tmp, int *canceled)
 {
-    return NULL;
+  if (canceled)
+    *canceled = 0;
+  return NULL;
 }
 
 /* Stubs to avoid linking to photoid.c */
index b506af6..8395c11 100644 (file)
@@ -187,7 +187,7 @@ void read_passphrase_from_fd( int fd );
 void passphrase_clear_cache ( u32 *keyid, int algo );
 DEK *passphrase_to_dek( u32 *keyid, int pubkey_algo,
                        int cipher_algo, STRING2KEY *s2k, int mode,
-                        const char *tryagain_text);
+                        const char *tryagain_text, int *canceled);
 void set_next_passphrase( const char *s );
 char *get_last_passphrase(void);
 
index 9186bd9..2b954e2 100644 (file)
@@ -915,10 +915,10 @@ change_passphrase( KBNODE keyblock )
            s2k->mode = opt.s2k_mode;
            s2k->hash_algo = opt.s2k_digest_algo;
            dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo,
-                                     s2k, 2, errtext);
+                                     s2k, 2, errtext, NULL);
            if( !dek ) {
-               errtext = _("passphrase not correctly repeated; try again");
-               tty_printf ("%s.\n", errtext);
+               errtext = N_("passphrase not correctly repeated; try again");
+               tty_printf ("%s.\n", _(errtext));
            }
            else if( !dek->keylen ) {
                rc = 0;
index 3e5bc4f..ef4b422 100644 (file)
@@ -1479,10 +1479,11 @@ ask_passphrase( STRING2KEY **ret_s2k )
     for(;;) {
        s2k->mode = opt.s2k_mode;
        s2k->hash_algo = opt.s2k_digest_algo;
-       dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k,2,errtext);
+       dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k,2,
+                                 errtext, NULL);
        if( !dek ) {
-           errtext = _("passphrase not correctly repeated; try again");
-           tty_printf(_("%s.\n"), errtext);
+           errtext = N_("passphrase not correctly repeated; try again");
+           tty_printf(_("%s.\n"), _(errtext));
        }
        else if( !dek->keylen ) {
            m_free(dek); dek = NULL;
@@ -1809,7 +1810,8 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
        s2k->mode = opt.s2k_mode;
        s2k->hash_algo = opt.s2k_digest_algo;
        set_next_passphrase( r->u.value );
-       dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2, NULL );
+       dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2,
+                                 NULL, NULL);
        set_next_passphrase( NULL );
        assert( dek );
        memset( r->u.value, 0, strlen(r->u.value) );
@@ -2476,7 +2478,8 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
        s2k->mode = opt.s2k_mode;
        s2k->hash_algo = opt.s2k_digest_algo;
        set_next_passphrase( passphrase );
-       dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2, NULL );
+       dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2,
+                                 NULL, NULL );
     }
 
     rc = do_create( algo, nbits, pub_keyblock, sec_keyblock,
index 97af595..1911d00 100644 (file)
@@ -292,7 +292,7 @@ proc_symkey_enc( CTX c, PACKET *pkt )
        c->last_was_session_key = 2;
        if ( opt.list_only )
            goto leave;
-       c->dek = passphrase_to_dek( NULL, 0, algo, &enc->s2k, 0, NULL );
+       c->dek = passphrase_to_dek( NULL, 0, algo, &enc->s2k, 0, NULL, NULL );
         if (c->dek)
             c->dek->algo_info_printed = 1;
         if ( c->dek && enc->seskeylen )
@@ -486,7 +486,7 @@ proc_encrypted( CTX c, PACKET *pkt )
             log_info (_("assuming %s encrypted data\n"), "IDEA");
         }
 
-       c->dek = passphrase_to_dek ( NULL, 0, algo, s2k, 0, NULL );
+       c->dek = passphrase_to_dek ( NULL, 0, algo, s2k, 0, NULL, NULL );
         if (c->dek)
             c->dek->algo_info_printed = 1;
     }
index 5345fb9..7692762 100644 (file)
@@ -1,5 +1,5 @@
 /* passphrase.c -  Get a passphrase
- * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -36,6 +36,9 @@
 #ifdef HAVE_LOCALE_H
 #include <locale.h>
 #endif
+#ifdef HAVE_LANGINFO_CODESET
+#include <langinfo.h>
+#endif
 
 #include "util.h"
 #include "memory.h"
@@ -144,33 +147,44 @@ get_last_passphrase()
 void
 read_passphrase_from_fd( int fd )
 {
-    int i, len;
-    char *pw;
+  int i, len;
+  char *pw;
+  
+  if ( opt.use_agent ) 
+    { /* Not used but we have to do a dummy read, so that it won't end
+         up at the begin of the message if the quite usual trick to
+         prepend the passphtrase to the message is used. */
+      char buf[1];
 
-    if ( opt.use_agent ) 
-        return;  /* not used here */
+      while (!(read (fd, buf, 1) != 1 || *buf == '\n' ))
+        ;
+      *buf = 0;
+      return; 
+    }
 
-    if( !opt.batch )
+  if (!opt.batch )
        tty_printf("Reading passphrase from file descriptor %d ...", fd );
-    for( pw = NULL, i = len = 100; ; i++ ) {
-       if( i >= len-1 ) {
-           char *pw2 = pw;
-           len += 100;
-           pw = m_alloc_secure( len );
-           if( pw2 )
-               memcpy(pw, pw2, i );
-           else
-               i=0;
+  for (pw = NULL, i = len = 100; ; i++ ) 
+    {
+      if (i >= len-1 ) 
+        {
+          char *pw2 = pw;
+          len += 100;
+          pw = m_alloc_secure( len );
+          if( pw2 )
+            memcpy(pw, pw2, i );
+          else
+            i=0;
        }
-       if( read( fd, pw+i, 1) != 1 || pw[i] == '\n' )
-           break;
+      if (read( fd, pw+i, 1) != 1 || pw[i] == '\n' )
+        break;
     }
-    pw[i] = 0;
-    if( !opt.batch )
-       tty_printf("\b\b\b   \n" );
+  pw[i] = 0;
+  if (!opt.batch)
+    tty_printf("\b\b\b   \n" );
 
-    m_free( fd_passwd );
-    fd_passwd = pw;
+  m_free( fd_passwd );
+  fd_passwd = pw;
 }
 
 static int
@@ -590,15 +604,20 @@ agent_close ( int fd )
  * Mode 0:  Allow cached passphrase
  *      1:  No cached passphrase FIXME: Not really implemented
  *      2:  Ditto, but change the text to "repeat entry"
+ *
+ * Note that TRYAGAIN_TEXT must not be translated.  If canceled is not
+ * NULL, the function does set it to 1 if the user canceled the
+ * operation.
  */
 static char *
-agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text )
+agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
+                       int *canceled)
 {
 #if defined(__riscos__)
   return NULL;
 #else
   size_t n;
-  char *atext;
+  char *atext = NULL;
   char buf[50];
   int fd = -1;
   int nread;
@@ -606,7 +625,12 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text )
   char *pw = NULL;
   PKT_public_key *pk = m_alloc_clear( sizeof *pk );
   byte fpr[MAX_FINGERPRINT_LEN];
+  int have_fpr = 0;
   int prot;
+  char *orig_codeset = NULL;
+
+  if (canceled)
+    *canceled = 0;
 
 #if MAX_FINGERPRINT_LEN < 20
 #error agent needs a 20 byte fingerprint
@@ -619,6 +643,24 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text )
       pk = NULL; /* oops: no key for some reason */
     }
   
+#ifdef ENABLE_NLS
+  /* The Assuan agent protol requires us to trasnmit utf-8 strings */
+  orig_codeset = bind_textdomain_codeset (PACKAGE, NULL);
+#ifdef HAVE_LANGINFO_CODESET
+  if (!orig_codeset)
+    orig_codeset = nl_langinfo (CODESET);
+#endif
+  if (orig_codeset)
+    { /* We only switch when we are able to restore the codeset later. */
+      orig_codeset = m_strdup (orig_codeset);
+      if (!bind_textdomain_codeset (PACKAGE, "utf-8"))
+        orig_codeset = NULL; 
+    }
+#endif
+
+  if ( (fd = agent_open (&prot)) == -1 ) 
+    goto failure;
+
   if ( !mode && pk && keyid )
     { 
       char *uid;
@@ -658,6 +700,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text )
       { 
         size_t dummy;
         fingerprint_from_pk( pk, fpr, &dummy );
+        have_fpr = 1;
       }
       
     }
@@ -666,9 +709,6 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text )
   else
     atext = m_strdup ( _("Enter passphrase\n") );
                 
-  if ( (fd = agent_open (&prot)) == -1 ) 
-    goto failure;
-
   if (!prot)
     { /* old style protocol */
       n = 4 + 20 + strlen (atext);
@@ -724,10 +764,19 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text )
           pw[pwlen] = 0; /* make a C String */
           agent_close (fd);
           free_public_key( pk );
+#ifdef ENABLE_NLS
+          if (orig_codeset)
+            bind_textdomain_codeset (PACKAGE, orig_codeset);
+#endif
+          m_free (orig_codeset);
           return pw;
         }
       else if ( reply == GPGA_PROT_CANCELED ) 
-        log_info ( _("cancelled by user\n") );
+        {
+          log_info ( _("cancelled by user\n") );
+          if (canceled)
+            *canceled = 1;
+        }
       else 
         log_error ( _("problem with the agent: agent returns 0x%lx\n"),
                     (ulong)reply );
@@ -740,6 +789,8 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text )
 
       if (!tryagain_text)
         tryagain_text = "X";
+      else
+        tryagain_text = _(tryagain_text);
 
       /* We allocate 2 time the needed space for atext so that there
          is nenough space for escaping */
@@ -747,7 +798,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text )
                       +  3*strlen (tryagain_text) + 3*strlen (atext) + 2);
       strcpy (line, "GET_PASSPHRASE ");
       p = line+15;
-      if (!mode)
+      if (!mode && have_fpr)
         {
           for (i=0; i < 20; i++, p +=2 )
             sprintf (p, "%02X", fpr[i]);
@@ -805,11 +856,20 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text )
           pw[pwlen] = 0; /* make a C String */
           agent_close (fd);
           free_public_key( pk );
+#ifdef ENABLE_NLS
+          if (orig_codeset)
+            bind_textdomain_codeset (PACKAGE, orig_codeset);
+#endif
+          m_free (orig_codeset);
           return pw;
         }
       else if (nread > 7 && !memcmp (pw, "ERR 111", 7)
                && (pw[7] == ' ' || pw[7] == '\n') ) 
-        log_info (_("cancelled by user\n") );
+        {
+          log_info (_("cancelled by user\n") );
+          if (canceled)
+            *canceled = 1;
+        }
       else 
         {
           log_error (_("problem with the agent - disabling agent use\n"));
@@ -819,6 +879,10 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text )
       
         
  failure:
+#ifdef ENABLE_NLS
+  if (orig_codeset)
+    bind_textdomain_codeset (PACKAGE, orig_codeset);
+#endif
   m_free (atext);
   if ( fd != -1 )
     agent_close (fd);
@@ -945,17 +1009,25 @@ passphrase_clear_cache ( u32 *keyid, int algo )
  *         (only for mode 2)
  *         a dek->keylen of 0 means: no passphrase entered.
  *         (only for mode 2)
- * pubkey_algo is only informational.
+ *
+ * pubkey_algo is only informational.  Note that TRYAGAIN_TEXT must
+ * not be translated as this is done within this function (required to
+ * switch to utf-8 when the agent is in use).  If CANCELED is not
+ * NULL, it is set to 1 if the user choosed to cancel the operation,
+ * otherwise it will be set to 0.
  */
 DEK *
 passphrase_to_dek( u32 *keyid, int pubkey_algo,
                   int cipher_algo, STRING2KEY *s2k, int mode,
-                   const char *tryagain_text)
+                   const char *tryagain_text, int *canceled)
 {
     char *pw = NULL;
     DEK *dek;
     STRING2KEY help_s2k;
 
+    if (canceled)
+      *canceled = 0;
+
     if( !s2k ) {
         /* This is used for the old rfc1991 mode 
          * Note: This must match the code in encode.c with opt.rfc1991 set */
@@ -1030,7 +1102,8 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
        next_pw = NULL;
     }
     else if ( opt.use_agent ) {
-       pw = agent_get_passphrase ( keyid, mode == 2? 1: 0, tryagain_text );
+       pw = agent_get_passphrase ( keyid, mode == 2? 1: 0,
+                                    tryagain_text, canceled );
         if (!pw)
           {
             if (!opt.use_agent)
@@ -1038,7 +1111,7 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
             pw = m_strdup ("");
           }
         if( *pw && mode == 2 ) {
-           char *pw2 = agent_get_passphrase ( keyid, 2, NULL );
+           char *pw2 = agent_get_passphrase ( keyid, 2, NULL, canceled );
             if (!pw2)
               {
                 if (!opt.use_agent)
index 4984c88..32c5449 100644 (file)
@@ -36,7 +36,8 @@
 
 
 static int
-do_check( PKT_secret_key *sk, const char *tryagain_text, int mode )
+do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
+          int *canceled )
 {
     byte *buffer;
     u16 csum=0;
@@ -69,7 +70,11 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode )
             keyid[3] = sk->main_keyid[1];
        }
        dek = passphrase_to_dek( keyid, sk->pubkey_algo, sk->protect.algo,
-                                &sk->protect.s2k, mode, tryagain_text );
+                                &sk->protect.s2k, mode,
+                                 tryagain_text, canceled );
+        if (!dek && canceled && *canceled)
+           return G10ERR_GENERAL;
+
        cipher_hd = cipher_open( sk->protect.algo,
                                 CIPHER_MODE_AUTO_CFB, 1);
        cipher_setkey( cipher_hd, dek->key, dek->keylen );
@@ -229,12 +234,13 @@ check_secret_key( PKT_secret_key *sk, int n )
        n = (opt.batch && !opt.use_agent)? 1 : 3; /* use the default value */
 
     for(i=0; i < n && rc == G10ERR_BAD_PASS; i++ ) {
+        int canceled = 0;
         const char *tryagain = NULL;
        if (i) {
-            tryagain = _("Invalid passphrase; please try again");
-            log_info (_("%s ...\n"), tryagain);
+            tryagain = N_("Invalid passphrase; please try again");
+            log_info (_("%s ...\n"), _(tryagain));
         }
-       rc = do_check( sk, tryagain, mode );
+       rc = do_check( sk, tryagain, mode, &canceled );
        if( rc == G10ERR_BAD_PASS && is_status_enabled() ) {
            u32 kid[2];
            char buf[50];
@@ -243,7 +249,7 @@ check_secret_key( PKT_secret_key *sk, int n )
            sprintf(buf, "%08lX%08lX", (ulong)kid[0], (ulong)kid[1]);
            write_status_text( STATUS_BAD_PASSPHRASE, buf );
        }
-       if( have_static_passphrase() )
+       if( have_static_passphrase() || canceled)
            break;
     }
 
index cbc93af..9dad9b3 100644 (file)
@@ -1059,7 +1059,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr)
     if (!opt.quiet || !opt.batch)
         log_info (_("%s encryption will be used\n"),
                    cipher_algo_to_string(algo) );
-    cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL );
+    cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL, NULL);
 
     if (!cfx.dek || !cfx.dek->keylen) {
         rc = G10ERR_PASSPHRASE;