Fixes for CVE-2006-6235
authorWerner Koch <wk@gnupg.org>
Wed, 6 Dec 2006 10:16:50 +0000 (10:16 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 6 Dec 2006 10:16:50 +0000 (10:16 +0000)
31 files changed:
ChangeLog
NEWS
README.SVN
configure.ac
doc/ChangeLog
doc/Makefile.am
doc/gpg.texi
doc/tools.texi
g10/ChangeLog
g10/armor.c
g10/cipher.c
g10/dearmor.c
g10/decrypt.c
g10/encode.c
g10/encr-data.c
g10/export.c
g10/filter.h
g10/gpg.c
g10/import.c
g10/keyedit.c
g10/keygen.c
g10/keyserver.c
g10/mainproc.c
g10/passphrase.c
g10/plaintext.c
g10/progress.c
g10/revoke.c
g10/sign.c
g10/verify.c
jnlib/ChangeLog
jnlib/utf8conv.c

index 0829b34..5303f35 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2006-11-30  Werner Koch  <wk@g10code.com>
+
+       * configure.ac: Save original LIBS when testing for dlopen.
+
 2006-11-28  Werner Koch  <wk@g10code.com>
 
        Released 2.0.1.
diff --git a/NEWS b/NEWS
index 786cb8b..2ce9b93 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,14 @@
+Noteworthy changes in version 2.0.2 (unreleased)
+------------------------------------------------
+
+ * Fixed a serious and exploitable bug in processing encrypted
+   packages. [CVE-2006-6235].
+
+ * Added --passphrase-repeat to set the number of times GPG will
+   prompt for a new passphrase to be repeated.  This is useful to help
+   memorize a new passphrase.  The default is 1 repetition.
+
+
 Noteworthy changes in version 2.0.1 (2006-11-28)
 ------------------------------------------------
 
@@ -8,7 +19,7 @@ Noteworthy changes in version 2.0.1 (2006-11-28)
 
  * Fixed build problems on some some platforms and crashes on amd64.
 
- * Fixed a buffer overflow in gpg2. [bug#728]
+ * Fixed a buffer overflow in gpg2. [bug#728,CVE-2006-6169]
 
 
 Noteworthy changes in version 2.0.0 (2006-11-11)
index af4f49d..c642282 100644 (file)
@@ -3,7 +3,9 @@ If you are building from Subversion, run the script
 ./autogen.sh
 
 first, to make sure that you have all the necessary maintainer tools
-are installed and to build the actual configuration files.  Then run
+are installed and to build the actual configuration files.  If you
+have just updated from SVN, you should add the option "--force" to
+autogen.sh so that meta data from SVN is noticed.  Then run
 
 ./configure --enable-maintainer-mode
 
@@ -40,12 +42,10 @@ knowledge about the actual tools used by autgen.sh.
 
 Please don't use autopoint, libtoolize or autoreconf unless you are
 the current maintainer and want to update the standard configuration
-files.  All those files should be in the CVS and only updated manually
+files.  All those files should be in the SVN and only updated manually
 if the maintainer decides that newer versions are required.  The
 maintainer should also make sure that the required version of automake
 et al. are properly indicated at the top of configure.ac and take care
 to copy the files and not merely use symlinks.
 
 
-
-
index 81758b1..bfe4fe8 100644 (file)
@@ -26,8 +26,8 @@ min_automake_version="1.9.3"
 # Remember to change the version number immediately *after* a release.
 # Set my_issvn to "yes" for non-released code.  Remember to run an
 # "svn up" and "autogen.sh" right before creating a distribution.
-m4_define([my_version], [2.0.1])
-m4_define([my_issvn], [no])
+m4_define([my_version], [2.0.2])
+m4_define([my_issvn], [yes])
 
 
 m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \
@@ -619,10 +619,12 @@ AC_CHECK_FUNCS(usb_create_match)
 #
 # Check wether it is necessary to link against libdl.
 #
+gnupg_dlopen_save_libs="$LIBS"
 LIBS=""
 AC_SEARCH_LIBS(dlopen, c dl,,,)
 DL_LIBS=$LIBS
 AC_SUBST(DL_LIBS)
+LIBS="$gnupg_dlopen_save_libs"
 
 #
 # Checks for symcryptrun:
index bbaa6f4..aac2a91 100644 (file)
@@ -1,3 +1,8 @@
+2006-12-04  Werner Koch  <wk@g10code.com>
+
+       * gpgv.texi: New.
+       * tools.texi: Include new file.
+
 2006-12-02  David Shaw  <dshaw@jabberwocky.com>
 
        * gpg.texi (GPG Esoteric Options): Document --passphrase-repeat.
index ab8543b..c93df6f 100644 (file)
@@ -28,7 +28,7 @@ EXTRA_DIST = DETAILS HACKING TRANSLATE OpenPGP KEYSERVER samplekeys.asc \
              gnupg-card-architecture.pdf \
              faq.raw FAQ faq.html gnupg7.texi \
              opt-homedir.texi see-also-note.texi specify-user-id.texi \
-            texi.css $(examples)
+            gpgv.texi texi.css $(examples)
 
 BUILT_SOURCES = gnupg-card-architecture.eps gnupg-card-architecture.png \
                 gnupg-card-architecture.pdf FAQ faq.html
index 524e0cc..a8e213c 100644 (file)
@@ -1070,6 +1070,9 @@ the filename does not contain a slash, it is assumed to be in the GnuPG
 home directory (@file{~/.gnupg} if @option{--homedir} or $GNUPGHOME is
 not used).
 
+@ifset gpgone
+@anchor{option --homedir}
+@end ifset
 @include opt-homedir.texi
 
 
@@ -1130,6 +1133,9 @@ encoded in the character set as specified by
 @option{--display-charset}. These options affect all following
 arguments. Both options may be used multiple times.
 
+@ifset gpgone
+@anchor{option --options}
+@end ifset
 @item --options @code{file}
 Read options from @code{file} and do not try to read them from the
 default options file in the homedir (see @option{--homedir}). This
@@ -2497,8 +2503,11 @@ name may be changed on the command line (@pxref{option
 @c man:.RE
 Note that on larger installations, it is useful to put predefined files
 into the directory @file{/etc/skel/.gnupg/} so that newly created users
-start up with a working configuration.  For existing users the a small
+start up with a working configuration.
+@ifclear gpgone
+For existing users the a small
 helper script is provided to create these files (@pxref{addgnupghome}).
+@end ifclear
 
 For internal purposes @command{@gpgname} creates and maintaines a few other
 files; They all live in in the current home directory (@pxref{option
@@ -2678,7 +2687,9 @@ as locked memory is allocated.
 @mansect see also
 @ifset isman
 @command{gpgv}(1), 
+@ifclear gpgone
 @command{gpgsm}(1), 
 @command{gpg-agent}(1)
+@end ifclear
 @end ifset
 @include see-also-note.texi
index dec5489..914a121 100644 (file)
@@ -92,130 +92,7 @@ Display a brief help page and exit
 @c
 @c  GPGV
 @c
-@manpage gpgv2.1
-@node gpgv
-@section Verify OpenPGP signatures
-@ifset manverb
-.B gpgv
-\- Verify OpenPGP signatures
-@end ifset
-
-@mansect synopsis
-@ifset manverb
-.B  gpgv2
-.RI [ options ]
-.I signed_files
-@end ifset
-
-@mansect description
-@code{gpgv2} is an OpenPGP signature verification tool.
-
-This program is actually a stripped down version of @code{gpg} which is
-only able to check signatures. It is somewhat smaller than the fully blown
-@code{gpg} and uses a different (and simpler) way to check that
-the public keys used to make the signature are valid. There are
-no configuration files and only a few options are implemented.
-
-@code{gpgv2} assumes that all keys in the keyring are trustworthy.
-By default it uses a keyring named @file{trustedkeys.gpg} which is
-assumed to be in the home directory as defined by GnuPG or set by an
-option or an environment variable. An option may be used to specify
-another keyring or even multiple keyrings.
-
-@noindent
-@mansect options
-@code{gpgv2} recognizes these options:
-
-@table @gnupgtabopt
-
-@item --verbose
-@itemx -v
-@opindex verbose
-Gives more information during processing. If used
-twice, the input data is listed in detail.
-
-@item --quiet
-@itemx -q
-@opindex quiet
-Try to be as quiet as possible.
-
-@item --keyring @var{file}
-@opindex keyring
-Add @var{file} to the list of keyrings.
-If @var{file} begins with a tilde and a slash, these
-are replaced by the HOME directory. If the filename
-does not contain a slash, it is assumed to be in the
-home-directory ("~/.gnupg" if --homedir is not used).
-
-@item --status-fd @var{n}
-@opindex status-fd
-Write special status strings to the file descriptor @var{n}.  See the
-file DETAILS in the documentation for a listing of them.
-
-@item --logger-fd @code{n}
-@opindex logger-fd
-Write log output to file descriptor @code{n} and not to stderr.
-
-@item --ignore-time-conflict
-@opindex ignore-time-conflict
-GnuPG normally checks that the timestamps associated with keys and
-signatures have plausible values. However, sometimes a signature seems to
-be older than the key due to clock problems. This option turns these
-checks into warnings.
-
-@include opt-homedir.texi
-
-@end table
-
-@mansect return value
-
-The program returns 0 if everything was fine, 1 if at least
-one signature was bad, and other error codes for fatal errors.
-
-@mansect examples
-@subsection Examples
-
-@table @asis
-
-@item gpgv2 @code{pgpfile}
-@itemx gpgv2 @code{sigfile} 
-Verify the signature of the file. The second form
-is used for detached signatures, where @code{sigfile} is the detached
-signature (either ASCII armored or binary) and are the signed
-data; if this is not given the name of the file holding the signed data is
-constructed by cutting off the extension (".asc", ".sig" or ".sign") from
-@code{sigfile}.
-
-@end table
-
-@mansect environment
-@subsection Environment
-
-@table @asis
-
-@item HOME
-Used to locate the default home directory.
-
-@item GNUPGHOME
-If set directory used instead of "~/.gnupg".
-
-@end table
-
-@mansect files
-@subsection FILES
-
-@table @asis
-
-@item ~/.gnupg/trustedkeys.gpg
-The default keyring with the allowed keys
-
-@end table
-
-@mansect see also
-@command{gpg2}(1)
-@include see-also-note.texi
-
-
+@include gpgv.texi
 
 
 @c
index a94d005..ed5b399 100644 (file)
@@ -1,3 +1,58 @@
+2006-12-05  Werner Koch  <wk@g10code.com>
+
+       * passphrase.c (passphrase_to_dek): Handle a Cancel request
+       correctly.  [Bug#737]
+       * mainproc.c (proc_symkey_enc): Removed workaround for bogus cancel
+       processing.
+       * encode.c (encode_simple): Distinguish error message between
+       cancel and invalid passphrase.
+       (setup_symkey): Ditto.
+       * sign.c (sign_symencrypt_file): Ditto
+       * keyedit.c (change_passphrase): Allow cancellation.
+       * keygen.c (do_ask_passphrase): New arg R_CANCELED.
+       (generate_keypair): Handle a passphrase cancellation.
+       (generate_raw_key): Ditto.
+       (generate_subkeypair): Ditto.
+
+2006-12-04  Werner Koch  <wk@g10code.com>
+
+       * filter.h (armor_filter_context_t): New element REFCOUNT.
+       * armor.c (armor_filter): Made static.
+       (push_armor_filter, release_armor_context, new_armor_context): New.
+       (armor_filter): Release the context.
+       * gpg.c (main): Use new armor context functions and
+       push_armor_filter.
+       * export.c (do_export): Ditto.
+       * encode.c (encode_simple, encode_crypt): Ditto.
+       * decrypt.c (decrypt_message, decrypt_messages): Ditto.
+       * dearmor.c (dearmor_file, enarmor_file): Ditto.
+       * verify.c (verify_signatures, verify_one_file): Ditto.
+       * sign.c (sign_file, clearsign_file, sign_symencrypt_file): Ditto.
+       * revoke.c (gen_desig_revoke, gen_revoke): Ditto.
+       * keyserver.c (keyserver_spawn): Ditto.
+       * keygen.c (output_control_s): Turn AFX fields into pointers.
+       (read_parameter_file): Allocate and release AFX fields.
+       (do_generate_keypair): Use push_armor_filter.
+       * import.c (import): Replace iobuf_push_filter2 hack by the new
+       armor context stuff.
+
+2006-12-03  Werner Koch  <wk@g10code.com>
+
+       * filter.h: New element REFCOUNT.
+       (handle_progress): Remove prototype.
+       * progress.c (new_progress_context, release_progress_context): New.
+       (progress_filter): Use new function to release context.  Made static.
+       (handle_progress): Bumb reference counter.  No more check for
+       enabled progress as this is handled by new_progress_context.
+       * verify.c (verify_signatures, verify_one_file): Replace stack
+       based progress context by a heap based one.
+       * sign.c (sign_file, clearsign_file, sign_symencrypt_file): Ditto.
+       * plaintext.c (ask_for_detached_datafile, hash_datafiles): Ditto.
+       * encode.c (encode_simple, encode_crypt): Ditto.
+       * decrypt.c (decrypt_message, decrypt_messages): Ditto. 
+
+       * keyedit.c (menu_clean): Made strings translatable.
+
 2006-12-03  David Shaw  <dshaw@jabberwocky.com>
 
        * keyedit.c (menu_clean): Show "already minimized" rather than
        re-prompt for a passphrase to ensure the user has typed it
        correctly.  Defaults to 1.
 
+2006-12-02  Werner Koch  <wk@g10code.com>
+
+       * encr-data.c: Allocate DFX context on the heap and not on the
+       stack.  Changes at several places.  Fixes CVE-2006-6235.
+       
 2006-11-27  Werner Koch  <wk@g10code.com>
 
        * openfile.c (ask_outfile_name): Fixed buffer overflow occurring
        * compress.c (release_context): New.
        (handle_compressed): Allocate the context and setup a closure to
        release the context.  This is required because there is no
-       guarabntee that the filter gets popped from the chain at the end
+       guarantee that the filter gets popped from the chain at the end
        of the function.  Problem noted by Timo and probably also the
        cause for a couple of other reports.
        (compress_filter): Use the release function if set.
        (unarmor_pump): New. 
        * pipemode.c (pipemode_filter): Use the unarmor_pump to handle
        armored or non-armored detached signatures.  We can't use the
-       regular armor_filter becuase this does only chack for armored
+       regular armor_filter because this does only check for armored
        signatures the very first time.  In pipemode we may have a mix of
        armored and binary detached signatures.
        * mainproc.c (proc_tree): Do not print the "old style" notice when
index e9efa77..8f22f31 100644 (file)
@@ -114,6 +114,54 @@ static char *tail_strings[] = {
 };
 
 
+static int armor_filter ( void *opaque, int control,
+                          iobuf_t chain, byte *buf, size_t *ret_len);
+
+
+
+\f
+/* Create a new context for armor filters.  */
+armor_filter_context_t *
+new_armor_context (void)
+{
+  armor_filter_context_t *afx;
+
+  afx = xcalloc (1, sizeof *afx);
+  afx->refcount = 1;
+
+  return afx;
+}
+
+/* Release an armor filter context.  Passing NULL is explicitly
+   allowed and a no-op.  */
+void
+release_armor_context (armor_filter_context_t *afx)
+{
+  if (!afx)
+    return;
+  assert (afx->refcount);
+  if ( --afx->refcount )
+    return;
+  xfree (afx);
+}
+
+/* Push the armor filter onto the iobuf stream IOBUF.  */
+int
+push_armor_filter (armor_filter_context_t *afx, iobuf_t iobuf)
+{
+  int rc; 
+
+  afx->refcount++;
+  rc = iobuf_push_filter (iobuf, armor_filter, afx);
+  if (rc)
+    afx->refcount--;
+  return rc;
+}
+
+
+
+
+
 static void
 initialize(void)
 {
@@ -862,7 +910,7 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
 /****************
  * This filter is used to handle the armor stuff
  */
-int
+static int
 armor_filter( void *opaque, int control,
             IOBUF a, byte *buf, size_t *ret_len)
 {
@@ -1168,6 +1216,7 @@ armor_filter( void *opaque, int control,
                        "probably a buggy MTA has been used\n") );
        xfree( afx->buffer );
        afx->buffer = NULL;
+        release_armor_context (afx);
     }
     else if( control == IOBUFCTRL_DESC )
        *(char**)buf = "armor_filter";
index 0839557..802c019 100644 (file)
@@ -44,7 +44,7 @@
 static void
 write_header( cipher_filter_context_t *cfx, IOBUF a )
 {
-     gcry_error_t err;
+    gcry_error_t err;
     PACKET pkt;
     PKT_encrypted ed;
     byte temp[18];
index ae89e8e..23c3f74 100644 (file)
 int
 dearmor_file( const char *fname )
 {
-    armor_filter_context_t afx;
+    armor_filter_context_t *afx;
     IOBUF inp = NULL, out = NULL;
     int rc = 0;
     int c;
 
-    memset( &afx, 0, sizeof afx);
+    afx = new_armor_context ();
 
     /* prepare iobufs */
     inp = iobuf_open(fname);
@@ -64,23 +64,21 @@ dearmor_file( const char *fname )
        goto leave;
     }
 
-    iobuf_push_filter( inp, armor_filter, &afx );
+    push_armor_filter ( afx, inp );
 
     if( (rc = open_outfile( fname, 0, &out )) )
        goto leave;
 
-
-
     while( (c = iobuf_get(inp)) != -1 )
        iobuf_put( out, c );
 
-
   leave:
     if( rc )
        iobuf_cancel(out);
     else
        iobuf_close(out);
     iobuf_close(inp);
+    release_armor_context (afx);
     return rc;
 }
 
@@ -91,12 +89,12 @@ dearmor_file( const char *fname )
 int
 enarmor_file( const char *fname )
 {
-    armor_filter_context_t afx;
+    armor_filter_context_t *afx;
     IOBUF inp = NULL, out = NULL;
     int rc = 0;
     int c;
 
-    memset( &afx, 0, sizeof afx);
+    afx = new_armor_context ();
 
     /* prepare iobufs */
     inp = iobuf_open(fname);
@@ -117,9 +115,9 @@ enarmor_file( const char *fname )
     if( (rc = open_outfile( fname, 1, &out )) )
        goto leave;
 
-    afx.what = 4;
-    afx.hdrlines = "Comment: Use \"gpg --dearmor\" for unpacking\n";
-    iobuf_push_filter( out, armor_filter, &afx );
+    afx->what = 4;
+    afx->hdrlines = "Comment: Use \"gpg --dearmor\" for unpacking\n";
+    push_armor_filter ( afx, out );
 
     while( (c = iobuf_get(inp)) != -1 )
        iobuf_put( out, c );
@@ -131,6 +129,7 @@ enarmor_file( const char *fname )
     else
        iobuf_close(out);
     iobuf_close(inp);
+    release_armor_context (afx);
     return rc;
 }
 
index 3907142..4af7c4a 100644 (file)
@@ -52,10 +52,12 @@ int
 decrypt_message( const char *filename )
 {
     IOBUF fp;
-    armor_filter_context_t afx;
-    progress_filter_context_t pfx;
+    armor_filter_context_t *afx = NULL;
+    progress_filter_context_t *pfx;
     int rc;
-    int no_out=0;
+    int no_out = 0;
+
+    pfx = new_progress_context ();
 
     /* Open the message file.  */
     fp = iobuf_open(filename);
@@ -69,15 +71,16 @@ decrypt_message( const char *filename )
         rc = gpg_error_from_syserror ();
        log_error (_("can't open `%s': %s\n"), print_fname_stdin(filename),
                    gpg_strerror (rc));
+        release_progress_context (pfx);
        return rc;
     }
 
-    handle_progress (&pfx, fp, filename);
+    handle_progress (pfx, fp, filename);
 
     if( !opt.no_armor ) {
        if( use_armor_filter( fp ) ) {
-           memset( &afx, 0, sizeof afx);
-           iobuf_push_filter( fp, armor_filter, &afx );
+            afx = new_armor_context ();
+           push_armor_filter ( afx, fp );
        }
     }
 
@@ -89,6 +92,8 @@ decrypt_message( const char *filename )
     if( no_out )
        opt.outfile = NULL;
     iobuf_close(fp);
+    release_armor_context (afx);
+    release_progress_context (pfx);
     return rc;
 }
 
@@ -96,8 +101,8 @@ void
 decrypt_messages(int nfiles, char *files[])
 {
   IOBUF fp;
-  armor_filter_context_t afx;  
-  progress_filter_context_t pfx;
+  armor_filter_context_t *afx = NULL;  
+  progress_filter_context_t *pfx;
   char *p, *output = NULL;
   int rc=0,use_stdin=0;
   unsigned int lno=0;
@@ -106,9 +111,10 @@ decrypt_messages(int nfiles, char *files[])
     {
       log_error(_("--output doesn't work for this command\n"));
       return;
-        
     }
 
+  pfx = new_progress_context ();
+
   if(!nfiles)
     use_stdin=1;
 
@@ -163,14 +169,14 @@ decrypt_messages(int nfiles, char *files[])
           goto next_file;
         }
 
-      handle_progress (&pfx, fp, filename);
+      handle_progress (pfx, fp, filename);
 
       if (!opt.no_armor)
         {
           if (use_armor_filter(fp))
             {
-              memset(&afx, 0, sizeof afx);
-              iobuf_push_filter(fp, armor_filter, &afx);
+              afx = new_armor_context ();
+              push_armor_filter ( afx, fp );
             }
         }
       rc = proc_packets(NULL, fp);
@@ -189,4 +195,6 @@ decrypt_messages(int nfiles, char *files[])
     }
 
   set_next_passphrase(NULL);  
+  release_armor_context (afx);
+  release_progress_context (pfx);
 }
index f55f473..41bfafe 100644 (file)
@@ -169,14 +169,14 @@ encode_simple( const char *filename, int mode, int use_seskey )
     int seskeylen = 0;
     u32 filesize;
     cipher_filter_context_t cfx;
-    armor_filter_context_t afx;
+    armor_filter_context_t  *afx = NULL;
     compress_filter_context_t zfx;
     text_filter_context_t tfx;
-    progress_filter_context_t pfx;
+    progress_filter_context_t *pfx;
     int do_compress = !RFC1991 && default_compress_algo();
 
+    pfx = new_progress_context ();
     memset( &cfx, 0, sizeof cfx);
-    memset( &afx, 0, sizeof afx);
     memset( &zfx, 0, sizeof zfx);
     memset( &tfx, 0, sizeof tfx);
     init_packet(&pkt);
@@ -195,10 +195,11 @@ encode_simple( const char *filename, int mode, int use_seskey )
         rc = gpg_error_from_syserror ();
        log_error(_("can't open `%s': %s\n"), filename? filename: "[stdin]",
                   strerror(errno) );
+        release_progress_context (pfx);
        return rc;
     }
 
-    handle_progress (&pfx, inp, filename);
+    handle_progress (pfx, inp, filename);
 
     if( opt.textmode )
        iobuf_push_filter( inp, text_filter, &tfx );
@@ -211,18 +212,21 @@ encode_simple( const char *filename, int mode, int use_seskey )
     
     cfx.dek = NULL;
     if( mode ) {
+        int canceled;
+
        s2k = xmalloc_clear( sizeof *s2k );
        s2k->mode = RFC1991? 0:opt.s2k_mode;
        s2k->hash_algo=S2K_DIGEST_ALGO;
        cfx.dek = passphrase_to_dek( NULL, 0,
                                     default_cipher_algo(), s2k, 2,
-                                     NULL, NULL);
+                                     NULL, &canceled);
        if( !cfx.dek || !cfx.dek->keylen ) {
-           rc = gpg_error (GPG_ERR_INV_PASSPHRASE);
+           rc = gpg_error (canceled? GPG_ERR_CANCELED:GPG_ERR_INV_PASSPHRASE);
            xfree(cfx.dek);
            xfree(s2k);
            iobuf_close(inp);
            log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc));
+            release_progress_context (pfx);
            return rc;
        }
         if (use_seskey && s2k->mode != 1 && s2k->mode != 3) {
@@ -259,11 +263,15 @@ encode_simple( const char *filename, int mode, int use_seskey )
        iobuf_cancel(inp);
        xfree(cfx.dek);
        xfree(s2k);
+        release_progress_context (pfx);
        return rc;
     }
 
-    if( opt.armor )
-       iobuf_push_filter( out, armor_filter, &afx );
+    if ( opt.armor )
+      {
+        afx = new_armor_context ();
+       push_armor_filter (afx, out);
+      }
 
     if( s2k && !RFC1991 ) {
        PKT_symkey_enc *enc = xmalloc_clear( sizeof *enc + seskeylen + 1 );
@@ -376,23 +384,27 @@ encode_simple( const char *filename, int mode, int use_seskey )
     free_packet(&pkt);
     xfree(cfx.dek);
     xfree(s2k);
+    release_armor_context (afx);
+    release_progress_context (pfx);
     return rc;
 }
 
 int
 setup_symkey(STRING2KEY **symkey_s2k,DEK **symkey_dek)
 {
+  int canceled;
+
   *symkey_s2k=xmalloc_clear(sizeof(STRING2KEY));
   (*symkey_s2k)->mode = opt.s2k_mode;
   (*symkey_s2k)->hash_algo = S2K_DIGEST_ALGO;
 
   *symkey_dek=passphrase_to_dek(NULL,0,opt.s2k_cipher_algo,
-                               *symkey_s2k,2,NULL,NULL);
+                               *symkey_s2k,2,NULL, &canceled);
   if(!*symkey_dek || !(*symkey_dek)->keylen)
     {
       xfree(*symkey_dek);
       xfree(*symkey_s2k);
-      return gpg_error (GPG_ERR_BAD_PASSPHRASE);
+      return gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_BAD_PASSPHRASE);
     }
 
   return 0;
@@ -441,25 +453,31 @@ encode_crypt( const char *filename, strlist_t remusr, int use_symkey )
     int rc = 0, rc2 = 0;
     u32 filesize;
     cipher_filter_context_t cfx;
-    armor_filter_context_t afx;
+    armor_filter_context_t *afx = NULL;
     compress_filter_context_t zfx;
     text_filter_context_t tfx;
-    progress_filter_context_t pfx;
+    progress_filter_context_t *pfx;
     PK_LIST pk_list,work_list;
     int do_compress = opt.compress_algo && !RFC1991;
 
+    pfx = new_progress_context ();
     memset( &cfx, 0, sizeof cfx);
-    memset( &afx, 0, sizeof afx);
     memset( &zfx, 0, sizeof zfx);
     memset( &tfx, 0, sizeof tfx);
     init_packet(&pkt);
 
     if(use_symkey
        && (rc=setup_symkey(&symkey_s2k,&symkey_dek)))
-      return rc;
+      {
+        release_progress_context (pfx);
+        return rc;
+      }
 
     if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) )
+      {
+        release_progress_context (pfx);
        return rc;
+      }
 
     if(PGP2) {
       for(work_list=pk_list; work_list; work_list=work_list->next)
@@ -493,7 +511,7 @@ encode_crypt( const char *filename, strlist_t remusr, int use_symkey )
     else if( opt.verbose )
        log_info(_("reading from `%s'\n"), filename? filename: "[stdin]");
 
-    handle_progress (&pfx, inp, filename);
+    handle_progress (pfx, inp, filename);
 
     if( opt.textmode )
        iobuf_push_filter( inp, text_filter, &tfx );
@@ -501,8 +519,11 @@ encode_crypt( const char *filename, strlist_t remusr, int use_symkey )
     if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) )
        goto leave;
 
-    if( opt.armor )
-       iobuf_push_filter( out, armor_filter, &afx );
+    if ( opt.armor )
+      {
+        afx = new_armor_context ();
+       push_armor_filter (afx, out);
+      }
 
     /* create a session key */
     cfx.dek = xmalloc_secure_clear (sizeof *cfx.dek);
@@ -695,6 +716,8 @@ encode_crypt( const char *filename, strlist_t remusr, int use_symkey )
     xfree(symkey_dek);
     xfree(symkey_s2k);
     release_pk_list( pk_list );
+    release_armor_context (afx);
+    release_progress_context (pfx);
     return rc;
 }
 
index c56e017..696f8af 100644 (file)
@@ -39,14 +39,35 @@ static int mdc_decode_filter ( void *opaque, int control, IOBUF a,
 static int decode_filter ( void *opaque, int control, IOBUF a,
                                        byte *buf, size_t *ret_len);
 
-typedef struct 
+typedef struct decode_filter_context_s
 {
   gcry_cipher_hd_t cipher_hd;
   gcry_md_hd_t mdc_hash;
   char defer[22];
   int  defer_filled;
   int  eof_seen;
-} decode_filter_ctx_t;
+  int  refcount;
+} *decode_filter_ctx_t;
+
+
+/* Helper to release the decode context.  */
+static void
+release_dfx_context (decode_filter_ctx_t dfx)
+{
+  if (!dfx)
+    return;
+
+  assert (dfx->refcount);
+  if ( !--dfx->refcount )
+    {
+      gcry_cipher_close (dfx->cipher_hd);
+      dfx->cipher_hd = NULL;
+      gcry_md_close (dfx->mdc_hash);
+      dfx->mdc_hash = NULL;
+      xfree (dfx);
+    }
+}
+
 
 
 /****************
@@ -62,7 +83,11 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
   unsigned blocksize;
   unsigned nprefix;
   
-  memset( &dfx, 0, sizeof dfx );
+  dfx = xtrycalloc (1, sizeof *dfx);
+  if (!dfx)
+    return gpg_error_from_syserror ();
+  dfx->refcount = 1;
+
   if ( opt.verbose && !dek->algo_info_printed )
     {
       const char *s = gcry_cipher_algo_name (dek->algo);
@@ -77,20 +102,20 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
     goto leave;
   blocksize = gcry_cipher_get_algo_blklen (dek->algo);
   if ( !blocksize || blocksize > 16 )
-    log_fatal("unsupported blocksize %u\n", blocksize );
+    log_fatal ("unsupported blocksize %u\n", blocksize );
   nprefix = blocksize;
   if ( ed->len && ed->len < (nprefix+2) )
     BUG();
 
   if ( ed->mdc_method ) 
     {
-      if (gcry_md_open (&dfx.mdc_hash, ed->mdc_method, 0 ))
+      if (gcry_md_open (&dfx->mdc_hash, ed->mdc_method, 0 ))
         BUG ();
       if ( DBG_HASHING )
-        gcry_md_start_debug (dfx.mdc_hash, "checkmdc");
+        gcry_md_start_debug (dfx->mdc_hash, "checkmdc");
     }
 
-  rc = gcry_cipher_open (&dfx.cipher_hd, dek->algo,
+  rc = gcry_cipher_open (&dfx->cipher_hd, dek->algo,
                          GCRY_CIPHER_MODE_CFB,
                          (GCRY_CIPHER_SECURE
                           | ((ed->mdc_method || dek->algo >= 100)?
@@ -104,7 +129,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
 
 
   /* log_hexdump( "thekey", dek->key, dek->keylen );*/
-  rc = gcry_cipher_setkey (dfx.cipher_hd, dek->key, dek->keylen);
+  rc = gcry_cipher_setkey (dfx->cipher_hd, dek->key, dek->keylen);
   if ( gpg_err_code (rc) == GPG_ERR_WEAK_KEY )
     {
       log_info(_("WARNING: message was encrypted with"
@@ -123,7 +148,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
       goto leave;
     }
 
-  gcry_cipher_setiv (dfx.cipher_hd, NULL, 0);
+  gcry_cipher_setiv (dfx->cipher_hd, NULL, 0);
 
   if ( ed->len )
     {
@@ -144,8 +169,8 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
           temp[i] = c;
     }
   
-  gcry_cipher_decrypt (dfx.cipher_hd, temp, nprefix+2, NULL, 0);
-  gcry_cipher_sync (dfx.cipher_hd);
+  gcry_cipher_decrypt (dfx->cipher_hd, temp, nprefix+2, NULL, 0);
+  gcry_cipher_sync (dfx->cipher_hd);
   p = temp;
   /* log_hexdump( "prefix", temp, nprefix+2 ); */
   if (dek->symmetric
@@ -155,17 +180,18 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
       goto leave;
     }
   
-  if ( dfx.mdc_hash )
-    gcry_md_write (dfx.mdc_hash, temp, nprefix+2);
-  
+  if ( dfx->mdc_hash )
+    gcry_md_write (dfx->mdc_hash, temp, nprefix+2);
+
+  dfx->refcount++;
   if ( ed->mdc_method )
-    iobuf_push_filter( ed->buf, mdc_decode_filter, &dfx );
+    iobuf_push_filter ( ed->buf, mdc_decode_filter, dfx );
   else
-    iobuf_push_filter( ed->buf, decode_filter, &dfx );
+    iobuf_push_filter ( ed->buf, decode_filter, dfx );
 
   proc_packets ( procctx, ed->buf );
   ed->buf = NULL;
-  if ( ed->mdc_method && dfx.eof_seen == 2 )
+  if ( ed->mdc_method && dfx->eof_seen == 2 )
     rc = gpg_error (GPG_ERR_INV_PACKET);
   else if ( ed->mdc_method )
     { 
@@ -184,26 +210,28 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
          bytes are appended.  */
       int datalen = gcry_md_get_algo_dlen (ed->mdc_method);
 
-      gcry_cipher_decrypt (dfx.cipher_hd, dfx.defer, 22, NULL, 0);
-      gcry_md_write (dfx.mdc_hash, dfx.defer, 2);
-      gcry_md_final (dfx.mdc_hash);
+      assert (dfx->cipher_hd);
+      assert (dfx->mdc_hash);
+      gcry_cipher_decrypt (dfx->cipher_hd, dfx->defer, 22, NULL, 0);
+      gcry_md_write (dfx->mdc_hash, dfx->defer, 2);
+      gcry_md_final (dfx->mdc_hash);
 
-      if (dfx.defer[0] != '\xd3' || dfx.defer[1] != '\x14' )
+      if (dfx->defer[0] != '\xd3' || dfx->defer[1] != '\x14' )
         {
           log_error("mdc_packet with invalid encoding\n");
           rc = gpg_error (GPG_ERR_INV_PACKET);
         }
       else if (datalen != 20
-               || memcmp (gcry_md_read (dfx.mdc_hash, 0),dfx.defer+2,datalen))
+               || memcmp (gcry_md_read (dfx->mdc_hash, 0),
+                          dfx->defer+2,datalen ))
         rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
-      /* log_printhex("MDC message:", dfx.defer, 22); */
-      /* log_printhex("MDC calc:", gcry_md_read (dfx.mdc_hash,0), datalen); */
+      /* log_printhex("MDC message:", dfx->defer, 22); */
+      /* log_printhex("MDC calc:", gcry_md_read (dfx->mdc_hash,0), datalen); */
     }
   
   
  leave:
-  gcry_cipher_close (dfx.cipher_hd);
-  gcry_md_close (dfx.mdc_hash);
+  release_dfx_context (dfx);
   return rc;
 }
 
@@ -214,7 +242,7 @@ static int
 mdc_decode_filter (void *opaque, int control, IOBUF a,
                    byte *buf, size_t *ret_len)
 {
-  decode_filter_ctx_t *dfx = opaque;
+  decode_filter_ctx_t dfx = opaque;
   size_t n, size = *ret_len;
   int rc = 0;
   int c;
@@ -226,11 +254,11 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
     }
   else if( control == IOBUFCTRL_UNDERFLOW )
     {
-      assert(a);
-      assert( size > 44 );
+      assert (a);
+      assert ( size > 44 );
       
       /* Get at least 22 bytes and put it somewhere ahead in the buffer. */
-      for(n=22; n < 44 ; n++ )
+      for (n=22; n < 44 ; n++ )
         {
           if( (c = iobuf_get(a)) == -1 )
             break;
@@ -279,8 +307,10 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
 
       if ( n )
         {
-          gcry_cipher_decrypt (dfx->cipher_hd, buf, n, NULL, 0);
-          gcry_md_write (dfx->mdc_hash, buf, n);
+          if ( dfx->cipher_hd )
+            gcry_cipher_decrypt (dfx->cipher_hd, buf, n, NULL, 0);
+          if ( dfx->mdc_hash )
+            gcry_md_write (dfx->mdc_hash, buf, n);
        }
       else
         {
@@ -289,6 +319,10 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
        }
       *ret_len = n;
     }
+  else if ( control == IOBUFCTRL_FREE ) 
+    {
+      release_dfx_context (dfx);
+    }
   else if ( control == IOBUFCTRL_DESC ) 
     {
       *(char**)buf = "mdc_decode_filter";
@@ -300,7 +334,7 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
 static int
 decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
 {
-  decode_filter_ctx_t *fc = opaque;
+  decode_filter_ctx_t fc = opaque;
   size_t n, size = *ret_len;
   int rc = 0;
   
@@ -311,11 +345,18 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
       if ( n == -1 )
         n = 0;
       if ( n )
-        gcry_cipher_decrypt (fc->cipher_hd, buf, n, NULL, 0);
+        {
+          if (fc->cipher_hd)
+            gcry_cipher_decrypt (fc->cipher_hd, buf, n, NULL, 0);
+        }
       else
         rc = -1; /* EOF */
       *ret_len = n;
     }
+  else if ( control == IOBUFCTRL_FREE ) 
+    {
+      release_dfx_context (fc);
+    }
   else if ( control == IOBUFCTRL_DESC )
     {
       *(char**)buf = "decode_filter";
index afc7fd7..78def57 100644 (file)
@@ -137,10 +137,9 @@ do_export( strlist_t users, int secret, unsigned int options )
 {
   IOBUF out = NULL;
   int any, rc;
-  armor_filter_context_t afx;
+  armor_filter_context_t *afx = NULL;
   compress_filter_context_t zfx;
   
-  memset( &afx, 0, sizeof afx);
   memset( &zfx, 0, sizeof zfx);
   
   rc = open_outfile( NULL, 0, &out );
@@ -151,8 +150,9 @@ do_export( strlist_t users, int secret, unsigned int options )
     {
       if ( opt.armor )
         {
-          afx.what = secret?5:1;
-          iobuf_push_filter ( out, armor_filter, &afx );
+          afx = new_armor_context ();
+          afx->what = secret? 5 : 1;
+          push_armor_filter (afx, out);
         }
       if ( opt.compress_keys )
         push_compress_filter (out,&zfx,default_compress_algo());
@@ -164,6 +164,7 @@ do_export( strlist_t users, int secret, unsigned int options )
     iobuf_cancel (out);
   else
     iobuf_close (out);
+  release_armor_context (afx);
   return rc;
 }
 
index 5c1b937..13f6b38 100644 (file)
@@ -32,12 +32,14 @@ typedef struct {
 } md_filter_context_t;
 
 typedef struct {
+    int  refcount;          /* Initialized to 1.  */
+
     /* these fields may be initialized */
     int what;              /* what kind of armor headers to write */
     int only_keyblocks;     /* skip all headers but ".... key block" */
     const char *hdrlines;   /* write these headerlines */
 
-    /* these fileds must be initialized to zero */
+    /* these fields must be initialized to zero */
     int no_openpgp_data;    /* output flag: "No valid OpenPGP data found" */
 
     /* the following fields must be initialized to zero */
@@ -121,6 +123,7 @@ typedef struct {
     unsigned long last;                /* last amount reported */
     unsigned long offset;      /* current amount */
     unsigned long total;       /* total amount */
+    int  refcount;              
 } progress_filter_context_t;
 
 /* encrypt_filter_context_t defined in main.h */
@@ -130,9 +133,10 @@ int md_filter( void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len)
 void free_md_filter_context( md_filter_context_t *mfx );
 
 /*-- armor.c --*/
+armor_filter_context_t *new_armor_context (void);
+void release_armor_context (armor_filter_context_t *afx);
+int push_armor_filter (armor_filter_context_t *afx, iobuf_t iobuf);
 int use_armor_filter( iobuf_t a );
-int armor_filter( void *opaque, int control,
-                 iobuf_t chain, byte *buf, size_t *ret_len);
 UnarmorPump unarmor_pump_new (void);
 void        unarmor_pump_release (UnarmorPump x);
 int         unarmor_pump (UnarmorPump x, int c);
@@ -153,8 +157,8 @@ int copy_clearsig_text (iobuf_t out, iobuf_t inp, gcry_md_hd_t md,
                         int escape_dash, int escape_from, int pgp2mode);
 
 /*-- progress.c --*/
-int progress_filter (void *opaque, int control,
-                    iobuf_t a, byte *buf, size_t *ret_len);
+progress_filter_context_t *new_progress_context (void);
+void release_progress_context (progress_filter_context_t *pfx);
 void handle_progress (progress_filter_context_t *pfx,
                      iobuf_t inp, const char *name);
 
index dde5c6e..8468420 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -1753,7 +1753,7 @@ main (int argc, char **argv )
     int may_coredump;
     strlist_t sl, remusr= NULL, locusr=NULL;
     strlist_t nrings=NULL, sec_nrings=NULL;
-    armor_filter_context_t afx;
+    armor_filter_context_t *afx = NULL;
     int detached_sig = 0;
     FILE *configfp = NULL;
     char *configname = NULL;
@@ -3826,8 +3826,8 @@ main (int argc, char **argv )
 
            if( !opt.no_armor ) {
                if( use_armor_filter( a ) ) {
-                   memset( &afx, 0, sizeof afx);
-                   iobuf_push_filter( a, armor_filter, &afx );
+                   afx = new_armor_context ();
+                   push_armor_filter (afx, a);
                }
            }
            if( cmd == aListPackets ) {
@@ -3843,6 +3843,7 @@ main (int argc, char **argv )
       }
 
     /* cleanup */
+    release_armor_context (afx);
     FREE_STRLIST(remusr);
     FREE_STRLIST(locusr);
     g10_exit(0);
index 8481d7b..b3857fc 100644 (file)
@@ -251,9 +251,12 @@ import( IOBUF inp, const char* fname,struct stats_s *stats,
     getkey_disable_caches();
 
     if( !opt.no_armor ) { /* armored reading is not disabled */
-       armor_filter_context_t *afx = xmalloc_clear( sizeof *afx );
+       armor_filter_context_t *afx;
+
+        afx = new_armor_context ();
        afx->only_keyblocks = 1;
-       iobuf_push_filter2( inp, armor_filter, afx, 1 );
+       push_armor_filter (afx, inp);
+        release_armor_context (afx);
     }
 
     while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) {
index 758ae94..bb8e63a 100644 (file)
@@ -1187,11 +1187,17 @@ change_passphrase( KBNODE keyblock )
 
        set_next_passphrase( NULL );
        for(;;) {
+            int canceled;
+
            s2k->mode = opt.s2k_mode;
            s2k->hash_algo = S2K_DIGEST_ALGO;
            dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo,
-                                     s2k, 2, errtext, NULL);
-           if( !dek ) {
+                                     s2k, 2, errtext, &canceled);
+            if (!dek && canceled) {
+                rc = GPG_ERR_CANCELED;
+                break;
+            }
+           else if( !dek ) {
                errtext = N_("passphrase not correctly repeated; try again");
                tty_printf ("%s.\n", _(errtext));
            }
@@ -3235,25 +3241,25 @@ menu_clean(KBNODE keyblock,int self_only)
              else
                reason=_("invalid");
 
-             tty_printf("User ID \"%s\" compacted: %s\n",user,reason);
+             tty_printf (_("User ID \"%s\" compacted: %s\n"), user, reason);
 
              modified=1;
            }
          else if(sigs)
            {
              tty_printf(sigs==1?
-                        "User ID \"%s\": %d signature removed\n":
-                        "User ID \"%s\": %d signatures removed\n",
+                        _("User ID \"%s\": %d signature removed\n") :
+                        _("User ID \"%s\": %d signatures removed\n"),
                         user,sigs);
 
              modified=1;
            }
          else
            {
-             tty_printf(self_only==1?
-                        "User ID \"%s\": already minimized\n":
-                        "User ID \"%s\": already clean\n",
-                        user);
+             tty_printf (self_only==1?
+                          _("User ID \"%s\": already minimized\n") :
+                          _("User ID \"%s\": already clean\n"),
+                          user);
            }
 
          xfree(user);
index 2594137..1335eaf 100644 (file)
@@ -96,13 +96,13 @@ struct output_control_s {
        char  *fname;
        char  *newfname;
        IOBUF stream;
-       armor_filter_context_t afx;
+       armor_filter_context_t *afx;
     } pub;
     struct {
        char  *fname;
        char  *newfname;
        IOBUF stream;
-       armor_filter_context_t afx;
+       armor_filter_context_t *afx;
     } sec;
 };
 
@@ -2045,9 +2045,8 @@ ask_user_id( int mode )
 }
 
 
-/* FIXME: We need a way to cancel this prompt. */
 static DEK *
-do_ask_passphrase( STRING2KEY **ret_s2k )
+do_ask_passphrase ( STRING2KEY **ret_s2k, int *r_canceled )
 {
     DEK *dek = NULL;
     STRING2KEY *s2k;
@@ -2060,8 +2059,13 @@ do_ask_passphrase( STRING2KEY **ret_s2k )
        s2k->mode = opt.s2k_mode;
        s2k->hash_algo = S2K_DIGEST_ALGO;
        dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k,2,
-                                 errtext, NULL);
-       if( !dek ) {
+                                 errtext, r_canceled);
+        if (!dek && *r_canceled) {
+           xfree(dek); dek = NULL;
+           xfree(s2k); s2k = NULL;
+            break;
+        }
+       else if( !dek ) {
            errtext = N_("passphrase not correctly repeated; try again");
            tty_printf(_("%s.\n"), _(errtext));
        }
@@ -2541,6 +2545,8 @@ read_parameter_file( const char *fname )
     struct output_control_s outctrl;
 
     memset( &outctrl, 0, sizeof( outctrl ) );
+    outctrl.pub.afx = new_armor_context ();
+    outctrl.sec.afx = new_armor_context ();
 
     if( !fname || !*fname)
       fname = "-";
@@ -2705,6 +2711,8 @@ read_parameter_file( const char *fname )
 
     release_parameter_list( para );
     iobuf_close (fp);
+    release_armor_context (outctrl.pub.afx);
+    release_armor_context (outctrl.sec.afx);
 }
 
 
@@ -2731,6 +2739,7 @@ generate_keypair (const char *fname, const char *card_serialno,
   struct para_data_s *para = NULL;
   struct para_data_s *r;
   struct output_control_s outctrl;
+  int canceled;
   
   memset( &outctrl, 0, sizeof( outctrl ) );
   
@@ -2886,7 +2895,8 @@ generate_keypair (const char *fname, const char *card_serialno,
   r->next = para;
   para = r;
     
-  dek = card_serialno? NULL : do_ask_passphrase( &s2k );
+  canceled = 0;
+  dek = card_serialno? NULL : do_ask_passphrase ( &s2k, &canceled );
   if( dek )
     {
       r = xmalloc_clear( sizeof *r );
@@ -2900,8 +2910,11 @@ generate_keypair (const char *fname, const char *card_serialno,
       r->next = para;
       para = r;
     }
-    
-  proc_parameter_file( para, "[internal]", &outctrl, !!card_serialno);
+
+  if (canceled) 
+    log_error (_("Key generation canceled.\n"));
+  else
+    proc_parameter_file( para, "[internal]", &outctrl, !!card_serialno);
   release_parameter_list( para );
 }
 
@@ -2923,6 +2936,7 @@ generate_raw_key (int algo, unsigned int nbits, u32 created_at,
   int i;
   size_t nskey, npkey;
   gcry_sexp_t s_parms, s_key;
+  int canceled;
 
   npkey = pubkey_get_npkey (algo);
   nskey = pubkey_get_nskey (algo);
@@ -2940,7 +2954,12 @@ generate_raw_key (int algo, unsigned int nbits, u32 created_at,
       log_info(_("keysize rounded up to %u bits\n"), nbits );
     }
 
-  dek = do_ask_passphrase (&s2k);
+  dek = do_ask_passphrase (&s2k, &canceled);
+  if (canceled)
+    {
+      rc = gpg_error (GPG_ERR_CANCELED);
+      goto leave;
+    }
 
   sk = xmalloc_clear (sizeof *sk);
   sk->timestamp = created_at;
@@ -3050,9 +3069,8 @@ do_generate_keypair( struct para_data_s *para,
                return;
            }
            if( opt.armor ) {
-               outctrl->pub.afx.what = 1;
-               iobuf_push_filter( outctrl->pub.stream, armor_filter,
-                                                   &outctrl->pub.afx );
+               outctrl->pub.afx->what = 1;
+               push_armor_filter (outctrl->pub.afx, outctrl->pub.stream);
            }
        }
        if( outctrl->sec.newfname ) {
@@ -3080,9 +3098,8 @@ do_generate_keypair( struct para_data_s *para,
                return;
            }
            if( opt.armor ) {
-               outctrl->sec.afx.what = 5;
-               iobuf_push_filter( outctrl->sec.stream, armor_filter,
-                                                   &outctrl->sec.afx );
+               outctrl->sec.afx->what = 5;
+               push_armor_filter (outctrl->sec.afx, outctrl->sec.stream);
            }
        }
        assert( outctrl->pub.stream );
@@ -3337,6 +3354,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
     STRING2KEY *s2k = NULL;
     u32 cur_time;
     int ask_pass = 0;
+    int canceled;
 
     /* break out the primary secret key */
     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
@@ -3404,8 +3422,9 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
                                                  _("Really create? (y/N) ")))
        goto leave;
 
+    canceled = 0;
     if (ask_pass)
-        dek = do_ask_passphrase (&s2k);
+        dek = do_ask_passphrase (&s2k, &canceled);
     else if (passphrase) {
        s2k = xmalloc_secure( sizeof *s2k );
        s2k->mode = opt.s2k_mode;
@@ -3415,8 +3434,12 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
                                  NULL, NULL );
     }
 
-    rc = do_create( algo, nbits, pub_keyblock, sec_keyblock,
-                   dek, s2k, &sub_sk, expire, 1 );
+    if (canceled)
+      rc = GPG_ERR_CANCELED;
+    
+    if (!rc)
+      rc = do_create (algo, nbits, pub_keyblock, sec_keyblock,
+                      dek, s2k, &sub_sk, expire, 1 );
     if( !rc )
        rc = write_keybinding(pub_keyblock, pub_keyblock, pri_sk, sub_sk, use);
     if( !rc )
index 98086c3..049b971 100644 (file)
@@ -1196,23 +1196,24 @@ keyserver_spawn(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
 
        for(key=list;key!=NULL;key=key->next)
          {
-           armor_filter_context_t afx;
-           IOBUF buffer=iobuf_temp();
+           armor_filter_context_t *afx;
+           IOBUF buffer = iobuf_temp ();
            KBNODE block;
 
            temp=NULL;
            add_to_strlist(&temp,key->d);
 
-           memset(&afx,0,sizeof(afx));
-           afx.what=1;
+           afx = new_armor_context ();
+           afx->what = 1;
            /* Tell the armor filter to use Unix-style \n line
               endings, since we're going to fprintf this to a file
               that (on Win32) is open in text mode.  The win32 stdio
               will transform the \n to \r\n and we'll end up with the
               proper line endings on win32.  This is a no-op on
               Unix. */
-           afx.eol[0]='\n';
-           iobuf_push_filter(buffer,armor_filter,&afx);
+           afx->eol[0] = '\n';
+           push_armor_filter (afx, buffer);
+            release_armor_context (afx);
 
            /* TODO: Remove Comment: lines from keys exported this
               way? */
index c4eb3b0..dc79889 100644 (file)
@@ -290,23 +290,8 @@ proc_symkey_enc( CTX c, PACKET *pkt )
          }
        else
          {
-            int canceled;
-
            c->dek = passphrase_to_dek (NULL, 0, algo, &enc->s2k, 0,
-                                        NULL, &canceled);
-            if (canceled)
-              {
-                /* For unknown reasons passphrase_to_dek does only
-                   return NULL if a new passphrase has been requested
-                   and has not been repeated correctly.  Thus even
-                   with a cancel requested (by means of the gpg-agent)
-                   it won't return NULL but an empty passphrase.  We
-                   take the most conservative approach for now and
-                   work around it right here. */
-                xfree (c->dek);
-                c->dek = NULL;
-              }
-
+                                        NULL, NULL);
            if(c->dek)
              {
                c->dek->symmetric=1;
index ae22074..f4015ef 100644 (file)
@@ -482,7 +482,9 @@ ask_passphrase (const char *description,
 
 
 /* Return a new DEK object Using the string-to-key sepcifier S2K.  Use
- * KEYID and PUBKEY_ALGO to prompt the user.
+   KEYID and PUBKEY_ALGO to prompt the user.  Returns NULL is the user
+   selected to cancel the passphrase entry and it CANCELED is not
+   NULL, sets it to true.
 
    MODE 0:  Allow cached passphrase
         1:  Ignore cached passphrase 
@@ -496,9 +498,11 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
   char *pw = NULL;
   DEK *dek;
   STRING2KEY help_s2k;
-  
-  if (canceled)
-    *canceled = 0;
+  int dummy_canceled;
+
+  if (!canceled)
+    canceled = &dummy_canceled;
+  *canceled = 0;
   
   if ( !s2k )
     {
@@ -600,7 +604,7 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
     }
   else if ( have_static_passphrase () ) 
     {
-      /* Return the passphrase we have store in FD_PASSWD. */
+      /* Return the passphrase we have stored in FD_PASSWD. */
       pw = xmalloc_secure ( strlen(fd_passwd)+1 );
       strcpy ( pw, fd_passwd );
     }
@@ -609,6 +613,11 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
       /* Divert to the gpg-agent. */
       pw = passphrase_get ( keyid, mode == 2? 1: 0, NULL,
                             tryagain_text, NULL, NULL, canceled );
+      if (*canceled)
+        {
+          xfree (pw);
+          return NULL;
+        }
       if (!pw)
         pw = xstrdup ("");
       if ( *pw && mode == 2 )
@@ -618,6 +627,12 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
            {
              char *pw2 = passphrase_get ( keyid, 2, NULL, NULL, NULL,
                                           NULL, canceled );
+              if (*canceled)
+                {
+                  xfree (pw);
+                  xfree (pw2);
+                  return NULL;
+                }
              if (!pw2)
                pw2 = xstrdup ("");
              if ( strcmp(pw, pw2) )
index 2d516a3..cab4d6d 100644 (file)
@@ -449,18 +449,20 @@ int
 ask_for_detached_datafile (gcry_md_hd_t md, gcry_md_hd_t md2,
                           const char *inname, int textmode )
 {
-    progress_filter_context_t pfx;
+    progress_filter_context_t *pfx;
     char *answer = NULL;
     IOBUF fp;
     int rc = 0;
 
-    fp = open_sigfile( inname, &pfx ); /* open default file */
+    pfx = new_progress_context ();
+    fp = open_sigfile ( inname, pfx ); /* Open default file. */
 
     if( !fp && !opt.batch ) {
        int any=0;
        tty_printf(_("Detached signature.\n"));
        do {
            char *name;
+
            xfree(answer);
            tty_enable_completion(NULL);
            name = cpr_get("detached_signature.filename",
@@ -505,6 +507,7 @@ ask_for_detached_datafile (gcry_md_hd_t md, gcry_md_hd_t md2,
 
   leave:
     xfree(answer);
+    release_progress_context (pfx);
     return rc;
 }
 
@@ -518,19 +521,23 @@ int
 hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2, strlist_t files,
                const char *sigfilename, int textmode )
 {
-    progress_filter_context_t pfx;
+    progress_filter_context_t *pfx;
     IOBUF fp;
     strlist_t sl;
 
+    pfx = new_progress_context ();
+
     if( !files ) {
        /* check whether we can open the signed material */
-       fp = open_sigfile( sigfilename, &pfx );
+       fp = open_sigfile( sigfilename, pfx );
        if( fp ) {
            do_hash( md, md2, fp, textmode );
            iobuf_close(fp);
+            release_progress_context (pfx);
            return 0;
        }
         log_error (_("no signed data\n"));
+        release_progress_context (pfx);
         return gpg_error (GPG_ERR_NO_DATA);
     }
 
@@ -547,13 +554,15 @@ hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2, strlist_t files,
             int rc = gpg_error_from_syserror ();
            log_error(_("can't open signed data `%s'\n"),
                                                print_fname_stdin(sl->d));
+            release_progress_context (pfx);
            return rc;
        }
-        handle_progress (&pfx, fp, sl->d);
+        handle_progress (pfx, fp, sl->d);
        do_hash( md, md2, fp, textmode );
        iobuf_close(fp);
     }
 
+    release_progress_context (pfx);
     return 0;
 }
 
index 148bf7e..8ccc453 100644 (file)
@@ -1,5 +1,5 @@
 /* progress.c - emit progress status lines
- * Copyright (C) 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2003, 2006 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -21,6 +21,7 @@
 
 #include <config.h>
 #include <stdio.h>
+#include <assert.h>
 
 #include "gpg.h"
 #include "iobuf.h"
 #include "util.h"
 #include "options.h"
 
+/* Create a new context for use with the progress filter.  We need to
+   allocate such contexts on the heap because there is no guarantee
+   that at the end of a function the filter has already been popped
+   off.  In general this will happen but with malformed packets it is
+   possible that a filter has not yet reached the end-of-stream when
+   the function has done all processing.  Checking in each function
+   that end-of-stream has been reached would be to cumbersome.
+
+   What we also do is to shortcut the progress handler by having this
+   function return NULL if progress information has not been
+   requested.
+*/
+progress_filter_context_t *
+new_progress_context (void)
+{
+  progress_filter_context_t *pfx;
+
+  if (!opt.enable_progress_filter)
+    return NULL;
+
+  if (!is_status_enabled ())
+    return NULL;
+
+  pfx = xcalloc (1, sizeof *pfx);
+  pfx->refcount = 1;
+
+  return pfx;
+}
+
+/* Release a progress filter context.  Passing NULL is explicitly
+   allowed and a no-op.  */
+void
+release_progress_context (progress_filter_context_t *pfx)
+{
+  if (!pfx)
+    return;
+  assert (pfx->refcount);
+  if ( --pfx->refcount )
+    return;
+  xfree (pfx->what);
+  xfree (pfx);
+}
+
+
 /****************
  * The filter is used to report progress to the user.
  */
-int
+static int
 progress_filter (void *opaque, int control,
                 IOBUF a, byte *buf, size_t *ret_len)
 {
@@ -85,11 +130,7 @@ progress_filter (void *opaque, int control,
     }
   else if (control == IOBUFCTRL_FREE)
     {
-      /* Note, that we must always dealloc resources of a filter
-         within the filter handler and not anywhere else.  (We set it
-         to NULL and check all uses just in case.) */
-      xfree (pfx->what);
-      pfx->what = NULL;
+      release_progress_context (pfx);
     }
   else if (control == IOBUFCTRL_DESC)
     *(char**)buf = "progress_filter";
@@ -101,11 +142,11 @@ handle_progress (progress_filter_context_t *pfx, IOBUF inp, const char *name)
 {
   off_t filesize = 0;
 
-  if (!opt.enable_progress_filter)
+  if (!pfx)
     return;
 
-  if (!is_status_enabled ())
-    return;
+  assert (opt.enable_progress_filter);
+  assert (is_status_enabled ());
 
   if ( !iobuf_is_pipe_filename (name) && *name )
     filesize = iobuf_get_filelength (inp, NULL);
@@ -115,5 +156,6 @@ handle_progress (progress_filter_context_t *pfx, IOBUF inp, const char *name)
   /* register the progress filter */
   pfx->what = xstrdup (name ? name : "stdin");
   pfx->total = filesize;
+  pfx->refcount++;
   iobuf_push_filter (inp, progress_filter, pfx);
 }
index 29f4b8d..4d7b8c3 100644 (file)
@@ -200,7 +200,7 @@ int
 gen_desig_revoke( const char *uname, strlist_t locusr )
 {
     int rc = 0;
-    armor_filter_context_t afx;
+    armor_filter_context_t *afx;
     PKT_public_key *pk = NULL;
     PKT_secret_key *sk = NULL;
     PKT_signature *sig = NULL;
@@ -219,7 +219,7 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
        return G10ERR_GENERAL;
       }
 
-    memset( &afx, 0, sizeof afx);
+    afx = new_armor_context ();
 
     kdbhd = keydb_new (0);
     classify_user_id (uname, &desc);
@@ -331,10 +331,10 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
            if( (rc = open_outfile( NULL, 0, &out )) )
              goto leave;
 
-           afx.what = 1;
-           afx.hdrlines = "Comment: A designated revocation certificate"
+           afx->what = 1;
+           afx->hdrlines = "Comment: A designated revocation certificate"
              " should follow\n";
-           iobuf_push_filter( out, armor_filter, &afx );
+           push_armor_filter (afx, out);
 
            /* create it */
            rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
@@ -427,6 +427,7 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
     else
        iobuf_close(out);
     release_revocation_reason_info( reason );
+    release_armor_context (afx);
     return rc;
 }
 
@@ -438,7 +439,7 @@ int
 gen_revoke( const char *uname )
 {
     int rc = 0;
-    armor_filter_context_t afx;
+    armor_filter_context_t *afx;
     PACKET pkt;
     PKT_secret_key *sk; /* used as pointer into a kbnode */
     PKT_public_key *pk = NULL;
@@ -457,7 +458,7 @@ gen_revoke( const char *uname )
        return G10ERR_GENERAL;
       }
 
-    memset( &afx, 0, sizeof afx);
+    afx = new_armor_context ();
     init_packet( &pkt );
 
     /* search the userid: 
@@ -556,9 +557,9 @@ gen_revoke( const char *uname )
     if( (rc = open_outfile( NULL, 0, &out )) )
        goto leave;
 
-    afx.what = 1;
-    afx.hdrlines = "Comment: A revocation certificate should follow\n";
-    iobuf_push_filter( out, armor_filter, &afx );
+    afx->what = 1;
+    afx->hdrlines = "Comment: A revocation certificate should follow\n";
+    push_armor_filter (afx, out);
 
     /* create it */
     rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
@@ -609,6 +610,7 @@ gen_revoke( const char *uname )
     else
        iobuf_close(out);
     release_revocation_reason_info( reason );
+    release_armor_context (afx);
     return rc;
 }
 
index 32f15c5..8ae9c0b 100644 (file)
@@ -739,11 +739,11 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
           int encryptflag, strlist_t remusr, const char *outfile )
 {
     const char *fname;
-    armor_filter_context_t afx;
+    armor_filter_context_t *afx;
     compress_filter_context_t zfx;
     md_filter_context_t mfx;
     text_filter_context_t tfx;
-    progress_filter_context_t pfx;
+    progress_filter_context_t *pfx;
     encrypt_filter_context_t efx;
     IOBUF inp = NULL, out = NULL;
     PACKET pkt;
@@ -754,7 +754,8 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
     int multifile = 0;
     u32 duration=0;
 
-    memset( &afx, 0, sizeof afx);
+    pfx = new_progress_context ();
+    afx = new_armor_context ();
     memset( &zfx, 0, sizeof zfx);
     memset( &mfx, 0, sizeof mfx);
     memset( &efx, 0, sizeof efx);
@@ -814,7 +815,7 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
           goto leave;
        }
 
-        handle_progress (&pfx, inp, fname);
+        handle_progress (pfx, inp, fname);
     }
 
     if( outfile ) {
@@ -933,10 +934,10 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
        iobuf_push_filter( inp, md_filter, &mfx );
 
     if( detached && !encryptflag && !RFC1991 )
-       afx.what = 2;
+       afx->what = 2;
 
     if( opt.armor && !outfile  )
-       iobuf_push_filter( out, armor_filter, &afx );
+       push_armor_filter (afx, out);
 
     if( encryptflag ) {
        efx.pk_list = pk_list;
@@ -1008,7 +1009,7 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
                              sl->d,strerror(errno));
                    goto leave;
                  }
-                handle_progress (&pfx, inp, sl->d);
+                handle_progress (pfx, inp, sl->d);
                if( opt.verbose )
                    fprintf(stderr, " `%s'", sl->d );
                if(opt.textmode)
@@ -1060,6 +1061,8 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
     release_sk_list( sk_list );
     release_pk_list( pk_list );
     recipient_digest_algo=0;
+    release_progress_context (pfx);
+    release_armor_context (afx);
     return rc;
 }
 
@@ -1071,8 +1074,8 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
 int
 clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
 {
-    armor_filter_context_t afx;
-    progress_filter_context_t pfx;
+    armor_filter_context_t *afx;
+    progress_filter_context_t *pfx;
     gcry_md_hd_t textmd = NULL;
     IOBUF inp = NULL, out = NULL;
     PACKET pkt;
@@ -1083,7 +1086,8 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
     int only_md5 = 0;
     u32 duration=0;
 
-    memset( &afx, 0, sizeof afx);
+    pfx = new_progress_context ();
+    afx = new_armor_context ();
     init_packet( &pkt );
 
     if(!opt.force_v3_sigs && !RFC1991)
@@ -1121,7 +1125,7 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
                    fname? fname: "[stdin]", strerror(errno) );
        goto leave;
     }
-    handle_progress (&pfx, inp, fname);
+    handle_progress (pfx, inp, fname);
 
     if( outfile ) {
         if (is_secured_filename (outfile) ) {
@@ -1199,8 +1203,8 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
     /* fixme: check for read errors */
 
     /* now write the armor */
-    afx.what = 2;
-    iobuf_push_filter( out, armor_filter, &afx );
+    afx->what = 2;
+    push_armor_filter (afx, out);
 
     /* write the signatures */
     rc=write_signature_packets (sk_list, out, textmd, 0x01, 0, duration, 'C');
@@ -1215,6 +1219,8 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
     iobuf_close(inp);
     gcry_md_close ( textmd );
     release_sk_list( sk_list );
+    release_progress_context (pfx);
+    release_armor_context (afx); 
     return rc;
 }
 
@@ -1225,8 +1231,8 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
 int
 sign_symencrypt_file (const char *fname, strlist_t locusr)
 {
-    armor_filter_context_t afx;
-    progress_filter_context_t pfx;
+    armor_filter_context_t *afx;
+    progress_filter_context_t *pfx;
     compress_filter_context_t zfx;
     md_filter_context_t mfx;
     text_filter_context_t tfx;
@@ -1239,8 +1245,10 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
     SK_LIST sk_rover = NULL;
     int algo;
     u32 duration=0;
+    int canceled;
 
-    memset( &afx, 0, sizeof afx);
+    pfx = new_progress_context ();
+    afx = new_armor_context ();
     memset( &zfx, 0, sizeof zfx);
     memset( &mfx, 0, sizeof mfx);
     memset( &tfx, 0, sizeof tfx);
@@ -1273,7 +1281,7 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
                    fname? fname: "[stdin]", strerror(errno) );
        goto leave;
     }
-    handle_progress (&pfx, inp, fname);
+    handle_progress (pfx, inp, fname);
 
     /* prepare key */
     s2k = xmalloc_clear( sizeof *s2k );
@@ -1284,10 +1292,10 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
     if (!opt.quiet || !opt.batch)
         log_info (_("%s encryption will be used\n"),
                   gcry_cipher_algo_name (algo) );
-    cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL, NULL);
+    cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL, &canceled);
 
     if (!cfx.dek || !cfx.dek->keylen) {
-        rc = gpg_error (GPG_ERR_BAD_PASSPHRASE);
+        rc = gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_BAD_PASSPHRASE);
         log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc) );
         goto leave;
     }
@@ -1321,7 +1329,7 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
 
     /* Push armor output filter */
     if (opt.armor)
-       iobuf_push_filter (out, armor_filter, &afx);
+       push_armor_filter (afx, out);
 
     /* Write the symmetric key packet */
     /*(current filters: armor)*/
@@ -1382,6 +1390,8 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
     gcry_md_close( mfx.md );
     xfree(cfx.dek);
     xfree(s2k);
+    release_progress_context (pfx);
+    release_armor_context (afx);
     return rc;
 }
 
index e34ad7a..5145525 100644 (file)
@@ -55,13 +55,14 @@ int
 verify_signatures( int nfiles, char **files )
 {
     IOBUF fp;
-    armor_filter_context_t afx;
-    progress_filter_context_t pfx;
+    armor_filter_context_t *afx;
+    progress_filter_context_t *pfx;
     const char *sigfile;
     int i, rc;
     strlist_t sl;
 
-    memset( &afx, 0, sizeof afx);
+    pfx = new_progress_context ();
+    afx = new_armor_context ();
     /* decide whether we should handle a detached or a normal signature,
      * which is needed so that the code later can hash the correct data and
      * not have a normal signature act as detached signature and ignoring the
@@ -101,12 +102,13 @@ verify_signatures( int nfiles, char **files )
         rc = gpg_error_from_syserror ();
        log_error(_("can't open `%s': %s\n"),
                   print_fname_stdin(sigfile), strerror (errno));
+        release_progress_context (pfx);
        return rc;
     }
-    handle_progress (&pfx, fp, sigfile);
+    handle_progress (pfx, fp, sigfile);
 
     if( !opt.no_armor && use_armor_filter( fp ) )
-       iobuf_push_filter( fp, armor_filter, &afx );
+       push_armor_filter (afx, fp);
 
     sl = NULL;
     for(i=nfiles-1 ; i > 0 ; i-- )
@@ -114,13 +116,15 @@ verify_signatures( int nfiles, char **files )
     rc = proc_signature_packets( NULL, fp, sl, sigfile );
     free_strlist(sl);
     iobuf_close(fp);
-    if( (afx.no_openpgp_data && rc == -1) || rc == G10ERR_NO_DATA ) {
+    if( (afx->no_openpgp_data && rc == -1) || rc == G10ERR_NO_DATA ) {
        log_error(_("the signature could not be verified.\n"
                   "Please remember that the signature file (.sig or .asc)\n"
                   "should be the first file given on the command line.\n") );
        rc = 0;
     }
 
+    release_armor_context (afx);
+    release_progress_context (pfx);
     return rc;
 }
 
@@ -139,10 +143,11 @@ static int
 verify_one_file( const char *name )
 {
     IOBUF fp;
-    armor_filter_context_t afx;
-    progress_filter_context_t pfx;
+    armor_filter_context_t *afx = NULL;
+    progress_filter_context_t *pfx;
     int rc;
 
+    pfx = new_progress_context ();
     print_file_status( STATUS_FILE_START, name, 1 );
     fp = iobuf_open(name);
     if (fp)
@@ -158,20 +163,23 @@ verify_one_file( const char *name )
        log_error(_("can't open `%s': %s\n"),
                   print_fname_stdin(name), strerror (errno));
        print_file_status( STATUS_FILE_ERROR, name, 1 );
+        release_progress_context (pfx);
        return rc;
     }
-    handle_progress (&pfx, fp, name);
+    handle_progress (pfx, fp, name);
 
     if( !opt.no_armor ) {
        if( use_armor_filter( fp ) ) {
-           memset( &afx, 0, sizeof afx);
-           iobuf_push_filter( fp, armor_filter, &afx );
+            afx = new_armor_context ();
+           push_armor_filter (afx, fp);
        }
     }
 
     rc = proc_signature_packets( NULL, fp, NULL, name );
     iobuf_close(fp);
     write_status( STATUS_FILE_DONE );
+    release_armor_context (afx);
+    release_progress_context (pfx);
     return rc;
 }
 
index 6834089..e120319 100644 (file)
@@ -1,3 +1,8 @@
+2006-11-29  Werner Koch  <wk@g10code.com>
+
+       * utf8conv.c (set_native_charset) [HAVE_W32_SYSTEM]: Fixed typo in
+       macro name.
+
 2006-11-15  Werner Koch  <wk@g10code.com>
 
        * logging.c (my_funopen_hook_ret_t): New.
index ec04a52..9a2a98b 100644 (file)
@@ -102,7 +102,7 @@ set_native_charset (const char *newset)
 
   if (!newset) 
     {
-#ifdef HABE_W32_SYSTEM
+#ifdef HAVE_W32_SYSTEM
       static char codepage[30];
       unsigned int cpno;
       const char *aliases;