Fixes for CVE-2006-6235

This commit is contained in:
Werner Koch 2006-12-06 10:16:50 +00:00
parent 114b20e8be
commit 0173cd5a98
31 changed files with 542 additions and 337 deletions

View File

@ -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> 2006-11-28 Werner Koch <wk@g10code.com>
Released 2.0.1. Released 2.0.1.

13
NEWS
View File

@ -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) 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 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) Noteworthy changes in version 2.0.0 (2006-11-11)

View File

@ -3,7 +3,9 @@ If you are building from Subversion, run the script
./autogen.sh ./autogen.sh
first, to make sure that you have all the necessary maintainer tools 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 ./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 Please don't use autopoint, libtoolize or autoreconf unless you are
the current maintainer and want to update the standard configuration 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 if the maintainer decides that newer versions are required. The
maintainer should also make sure that the required version of automake 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 et al. are properly indicated at the top of configure.ac and take care
to copy the files and not merely use symlinks. to copy the files and not merely use symlinks.

View File

@ -26,8 +26,8 @@ min_automake_version="1.9.3"
# Remember to change the version number immediately *after* a release. # Remember to change the version number immediately *after* a release.
# Set my_issvn to "yes" for non-released code. Remember to run an # Set my_issvn to "yes" for non-released code. Remember to run an
# "svn up" and "autogen.sh" right before creating a distribution. # "svn up" and "autogen.sh" right before creating a distribution.
m4_define([my_version], [2.0.1]) m4_define([my_version], [2.0.2])
m4_define([my_issvn], [no]) m4_define([my_issvn], [yes])
m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ 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. # Check wether it is necessary to link against libdl.
# #
gnupg_dlopen_save_libs="$LIBS"
LIBS="" LIBS=""
AC_SEARCH_LIBS(dlopen, c dl,,,) AC_SEARCH_LIBS(dlopen, c dl,,,)
DL_LIBS=$LIBS DL_LIBS=$LIBS
AC_SUBST(DL_LIBS) AC_SUBST(DL_LIBS)
LIBS="$gnupg_dlopen_save_libs"
# #
# Checks for symcryptrun: # Checks for symcryptrun:

View 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> 2006-12-02 David Shaw <dshaw@jabberwocky.com>
* gpg.texi (GPG Esoteric Options): Document --passphrase-repeat. * gpg.texi (GPG Esoteric Options): Document --passphrase-repeat.

View File

@ -28,7 +28,7 @@ EXTRA_DIST = DETAILS HACKING TRANSLATE OpenPGP KEYSERVER samplekeys.asc \
gnupg-card-architecture.pdf \ gnupg-card-architecture.pdf \
faq.raw FAQ faq.html gnupg7.texi \ faq.raw FAQ faq.html gnupg7.texi \
opt-homedir.texi see-also-note.texi specify-user-id.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 \ BUILT_SOURCES = gnupg-card-architecture.eps gnupg-card-architecture.png \
gnupg-card-architecture.pdf FAQ faq.html gnupg-card-architecture.pdf FAQ faq.html

View 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 home directory (@file{~/.gnupg} if @option{--homedir} or $GNUPGHOME is
not used). not used).
@ifset gpgone
@anchor{option --homedir}
@end ifset
@include opt-homedir.texi @include opt-homedir.texi
@ -1130,6 +1133,9 @@ encoded in the character set as specified by
@option{--display-charset}. These options affect all following @option{--display-charset}. These options affect all following
arguments. Both options may be used multiple times. arguments. Both options may be used multiple times.
@ifset gpgone
@anchor{option --options}
@end ifset
@item --options @code{file} @item --options @code{file}
Read options from @code{file} and do not try to read them from the Read options from @code{file} and do not try to read them from the
default options file in the homedir (see @option{--homedir}). This 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 @c man:.RE
Note that on larger installations, it is useful to put predefined files Note that on larger installations, it is useful to put predefined files
into the directory @file{/etc/skel/.gnupg/} so that newly created users 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}). helper script is provided to create these files (@pxref{addgnupghome}).
@end ifclear
For internal purposes @command{@gpgname} creates and maintaines a few other For internal purposes @command{@gpgname} creates and maintaines a few other
files; They all live in in the current home directory (@pxref{option files; They all live in in the current home directory (@pxref{option
@ -2678,7 +2687,9 @@ as locked memory is allocated.
@mansect see also @mansect see also
@ifset isman @ifset isman
@command{gpgv}(1), @command{gpgv}(1),
@ifclear gpgone
@command{gpgsm}(1), @command{gpgsm}(1),
@command{gpg-agent}(1) @command{gpg-agent}(1)
@end ifclear
@end ifset @end ifset
@include see-also-note.texi @include see-also-note.texi

View File

@ -92,130 +92,7 @@ Display a brief help page and exit
@c @c
@c GPGV @c GPGV
@c @c
@manpage gpgv2.1 @include gpgv.texi
@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
@c @c

View 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> 2006-12-03 David Shaw <dshaw@jabberwocky.com>
* keyedit.c (menu_clean): Show "already minimized" rather than * keyedit.c (menu_clean): Show "already minimized" rather than
@ -11,6 +66,11 @@
re-prompt for a passphrase to ensure the user has typed it re-prompt for a passphrase to ensure the user has typed it
correctly. Defaults to 1. 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> 2006-11-27 Werner Koch <wk@g10code.com>
* openfile.c (ask_outfile_name): Fixed buffer overflow occurring * openfile.c (ask_outfile_name): Fixed buffer overflow occurring
@ -4166,7 +4226,7 @@
* compress.c (release_context): New. * compress.c (release_context): New.
(handle_compressed): Allocate the context and setup a closure to (handle_compressed): Allocate the context and setup a closure to
release the context. This is required because there is no 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 of the function. Problem noted by Timo and probably also the
cause for a couple of other reports. cause for a couple of other reports.
(compress_filter): Use the release function if set. (compress_filter): Use the release function if set.
@ -5983,7 +6043,7 @@
(unarmor_pump): New. (unarmor_pump): New.
* pipemode.c (pipemode_filter): Use the unarmor_pump to handle * pipemode.c (pipemode_filter): Use the unarmor_pump to handle
armored or non-armored detached signatures. We can't use the 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 signatures the very first time. In pipemode we may have a mix of
armored and binary detached signatures. armored and binary detached signatures.
* mainproc.c (proc_tree): Do not print the "old style" notice when * mainproc.c (proc_tree): Do not print the "old style" notice when

View 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);
/* 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 static void
initialize(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 * This filter is used to handle the armor stuff
*/ */
int static int
armor_filter( void *opaque, int control, armor_filter( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len) 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") ); "probably a buggy MTA has been used\n") );
xfree( afx->buffer ); xfree( afx->buffer );
afx->buffer = NULL; afx->buffer = NULL;
release_armor_context (afx);
} }
else if( control == IOBUFCTRL_DESC ) else if( control == IOBUFCTRL_DESC )
*(char**)buf = "armor_filter"; *(char**)buf = "armor_filter";

View File

@ -44,7 +44,7 @@
static void static void
write_header( cipher_filter_context_t *cfx, IOBUF a ) write_header( cipher_filter_context_t *cfx, IOBUF a )
{ {
gcry_error_t err; gcry_error_t err;
PACKET pkt; PACKET pkt;
PKT_encrypted ed; PKT_encrypted ed;
byte temp[18]; byte temp[18];

View File

@ -42,12 +42,12 @@
int int
dearmor_file( const char *fname ) dearmor_file( const char *fname )
{ {
armor_filter_context_t afx; armor_filter_context_t *afx;
IOBUF inp = NULL, out = NULL; IOBUF inp = NULL, out = NULL;
int rc = 0; int rc = 0;
int c; int c;
memset( &afx, 0, sizeof afx); afx = new_armor_context ();
/* prepare iobufs */ /* prepare iobufs */
inp = iobuf_open(fname); inp = iobuf_open(fname);
@ -64,23 +64,21 @@ dearmor_file( const char *fname )
goto leave; goto leave;
} }
iobuf_push_filter( inp, armor_filter, &afx ); push_armor_filter ( afx, inp );
if( (rc = open_outfile( fname, 0, &out )) ) if( (rc = open_outfile( fname, 0, &out )) )
goto leave; goto leave;
while( (c = iobuf_get(inp)) != -1 ) while( (c = iobuf_get(inp)) != -1 )
iobuf_put( out, c ); iobuf_put( out, c );
leave: leave:
if( rc ) if( rc )
iobuf_cancel(out); iobuf_cancel(out);
else else
iobuf_close(out); iobuf_close(out);
iobuf_close(inp); iobuf_close(inp);
release_armor_context (afx);
return rc; return rc;
} }
@ -91,12 +89,12 @@ dearmor_file( const char *fname )
int int
enarmor_file( const char *fname ) enarmor_file( const char *fname )
{ {
armor_filter_context_t afx; armor_filter_context_t *afx;
IOBUF inp = NULL, out = NULL; IOBUF inp = NULL, out = NULL;
int rc = 0; int rc = 0;
int c; int c;
memset( &afx, 0, sizeof afx); afx = new_armor_context ();
/* prepare iobufs */ /* prepare iobufs */
inp = iobuf_open(fname); inp = iobuf_open(fname);
@ -117,9 +115,9 @@ enarmor_file( const char *fname )
if( (rc = open_outfile( fname, 1, &out )) ) if( (rc = open_outfile( fname, 1, &out )) )
goto leave; goto leave;
afx.what = 4; afx->what = 4;
afx.hdrlines = "Comment: Use \"gpg --dearmor\" for unpacking\n"; afx->hdrlines = "Comment: Use \"gpg --dearmor\" for unpacking\n";
iobuf_push_filter( out, armor_filter, &afx ); push_armor_filter ( afx, out );
while( (c = iobuf_get(inp)) != -1 ) while( (c = iobuf_get(inp)) != -1 )
iobuf_put( out, c ); iobuf_put( out, c );
@ -131,6 +129,7 @@ enarmor_file( const char *fname )
else else
iobuf_close(out); iobuf_close(out);
iobuf_close(inp); iobuf_close(inp);
release_armor_context (afx);
return rc; return rc;
} }

View File

@ -52,10 +52,12 @@ int
decrypt_message( const char *filename ) decrypt_message( const char *filename )
{ {
IOBUF fp; IOBUF fp;
armor_filter_context_t afx; armor_filter_context_t *afx = NULL;
progress_filter_context_t pfx; progress_filter_context_t *pfx;
int rc; int rc;
int no_out=0; int no_out = 0;
pfx = new_progress_context ();
/* Open the message file. */ /* Open the message file. */
fp = iobuf_open(filename); fp = iobuf_open(filename);
@ -69,15 +71,16 @@ decrypt_message( const char *filename )
rc = gpg_error_from_syserror (); rc = gpg_error_from_syserror ();
log_error (_("can't open `%s': %s\n"), print_fname_stdin(filename), log_error (_("can't open `%s': %s\n"), print_fname_stdin(filename),
gpg_strerror (rc)); gpg_strerror (rc));
release_progress_context (pfx);
return rc; return rc;
} }
handle_progress (&pfx, fp, filename); handle_progress (pfx, fp, filename);
if( !opt.no_armor ) { if( !opt.no_armor ) {
if( use_armor_filter( fp ) ) { if( use_armor_filter( fp ) ) {
memset( &afx, 0, sizeof afx); afx = new_armor_context ();
iobuf_push_filter( fp, armor_filter, &afx ); push_armor_filter ( afx, fp );
} }
} }
@ -89,6 +92,8 @@ decrypt_message( const char *filename )
if( no_out ) if( no_out )
opt.outfile = NULL; opt.outfile = NULL;
iobuf_close(fp); iobuf_close(fp);
release_armor_context (afx);
release_progress_context (pfx);
return rc; return rc;
} }
@ -96,8 +101,8 @@ void
decrypt_messages(int nfiles, char *files[]) decrypt_messages(int nfiles, char *files[])
{ {
IOBUF fp; IOBUF fp;
armor_filter_context_t afx; armor_filter_context_t *afx = NULL;
progress_filter_context_t pfx; progress_filter_context_t *pfx;
char *p, *output = NULL; char *p, *output = NULL;
int rc=0,use_stdin=0; int rc=0,use_stdin=0;
unsigned int lno=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")); log_error(_("--output doesn't work for this command\n"));
return; return;
} }
pfx = new_progress_context ();
if(!nfiles) if(!nfiles)
use_stdin=1; use_stdin=1;
@ -163,14 +169,14 @@ decrypt_messages(int nfiles, char *files[])
goto next_file; goto next_file;
} }
handle_progress (&pfx, fp, filename); handle_progress (pfx, fp, filename);
if (!opt.no_armor) if (!opt.no_armor)
{ {
if (use_armor_filter(fp)) if (use_armor_filter(fp))
{ {
memset(&afx, 0, sizeof afx); afx = new_armor_context ();
iobuf_push_filter(fp, armor_filter, &afx); push_armor_filter ( afx, fp );
} }
} }
rc = proc_packets(NULL, fp); rc = proc_packets(NULL, fp);
@ -189,4 +195,6 @@ decrypt_messages(int nfiles, char *files[])
} }
set_next_passphrase(NULL); set_next_passphrase(NULL);
release_armor_context (afx);
release_progress_context (pfx);
} }

View File

@ -169,14 +169,14 @@ encode_simple( const char *filename, int mode, int use_seskey )
int seskeylen = 0; int seskeylen = 0;
u32 filesize; u32 filesize;
cipher_filter_context_t cfx; cipher_filter_context_t cfx;
armor_filter_context_t afx; armor_filter_context_t *afx = NULL;
compress_filter_context_t zfx; compress_filter_context_t zfx;
text_filter_context_t tfx; text_filter_context_t tfx;
progress_filter_context_t pfx; progress_filter_context_t *pfx;
int do_compress = !RFC1991 && default_compress_algo(); int do_compress = !RFC1991 && default_compress_algo();
pfx = new_progress_context ();
memset( &cfx, 0, sizeof cfx); memset( &cfx, 0, sizeof cfx);
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx); memset( &zfx, 0, sizeof zfx);
memset( &tfx, 0, sizeof tfx); memset( &tfx, 0, sizeof tfx);
init_packet(&pkt); init_packet(&pkt);
@ -195,10 +195,11 @@ encode_simple( const char *filename, int mode, int use_seskey )
rc = gpg_error_from_syserror (); rc = gpg_error_from_syserror ();
log_error(_("can't open `%s': %s\n"), filename? filename: "[stdin]", log_error(_("can't open `%s': %s\n"), filename? filename: "[stdin]",
strerror(errno) ); strerror(errno) );
release_progress_context (pfx);
return rc; return rc;
} }
handle_progress (&pfx, inp, filename); handle_progress (pfx, inp, filename);
if( opt.textmode ) if( opt.textmode )
iobuf_push_filter( inp, text_filter, &tfx ); iobuf_push_filter( inp, text_filter, &tfx );
@ -211,18 +212,21 @@ encode_simple( const char *filename, int mode, int use_seskey )
cfx.dek = NULL; cfx.dek = NULL;
if( mode ) { if( mode ) {
int canceled;
s2k = xmalloc_clear( sizeof *s2k ); s2k = xmalloc_clear( sizeof *s2k );
s2k->mode = RFC1991? 0:opt.s2k_mode; s2k->mode = RFC1991? 0:opt.s2k_mode;
s2k->hash_algo=S2K_DIGEST_ALGO; s2k->hash_algo=S2K_DIGEST_ALGO;
cfx.dek = passphrase_to_dek( NULL, 0, cfx.dek = passphrase_to_dek( NULL, 0,
default_cipher_algo(), s2k, 2, default_cipher_algo(), s2k, 2,
NULL, NULL); NULL, &canceled);
if( !cfx.dek || !cfx.dek->keylen ) { 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(cfx.dek);
xfree(s2k); xfree(s2k);
iobuf_close(inp); iobuf_close(inp);
log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc)); log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc));
release_progress_context (pfx);
return rc; return rc;
} }
if (use_seskey && s2k->mode != 1 && s2k->mode != 3) { 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); iobuf_cancel(inp);
xfree(cfx.dek); xfree(cfx.dek);
xfree(s2k); xfree(s2k);
release_progress_context (pfx);
return rc; return rc;
} }
if( opt.armor ) if ( opt.armor )
iobuf_push_filter( out, armor_filter, &afx ); {
afx = new_armor_context ();
push_armor_filter (afx, out);
}
if( s2k && !RFC1991 ) { if( s2k && !RFC1991 ) {
PKT_symkey_enc *enc = xmalloc_clear( sizeof *enc + seskeylen + 1 ); 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); free_packet(&pkt);
xfree(cfx.dek); xfree(cfx.dek);
xfree(s2k); xfree(s2k);
release_armor_context (afx);
release_progress_context (pfx);
return rc; return rc;
} }
int int
setup_symkey(STRING2KEY **symkey_s2k,DEK **symkey_dek) setup_symkey(STRING2KEY **symkey_s2k,DEK **symkey_dek)
{ {
int canceled;
*symkey_s2k=xmalloc_clear(sizeof(STRING2KEY)); *symkey_s2k=xmalloc_clear(sizeof(STRING2KEY));
(*symkey_s2k)->mode = opt.s2k_mode; (*symkey_s2k)->mode = opt.s2k_mode;
(*symkey_s2k)->hash_algo = S2K_DIGEST_ALGO; (*symkey_s2k)->hash_algo = S2K_DIGEST_ALGO;
*symkey_dek=passphrase_to_dek(NULL,0,opt.s2k_cipher_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) if(!*symkey_dek || !(*symkey_dek)->keylen)
{ {
xfree(*symkey_dek); xfree(*symkey_dek);
xfree(*symkey_s2k); xfree(*symkey_s2k);
return gpg_error (GPG_ERR_BAD_PASSPHRASE); return gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_BAD_PASSPHRASE);
} }
return 0; return 0;
@ -441,25 +453,31 @@ encode_crypt( const char *filename, strlist_t remusr, int use_symkey )
int rc = 0, rc2 = 0; int rc = 0, rc2 = 0;
u32 filesize; u32 filesize;
cipher_filter_context_t cfx; cipher_filter_context_t cfx;
armor_filter_context_t afx; armor_filter_context_t *afx = NULL;
compress_filter_context_t zfx; compress_filter_context_t zfx;
text_filter_context_t tfx; text_filter_context_t tfx;
progress_filter_context_t pfx; progress_filter_context_t *pfx;
PK_LIST pk_list,work_list; PK_LIST pk_list,work_list;
int do_compress = opt.compress_algo && !RFC1991; int do_compress = opt.compress_algo && !RFC1991;
pfx = new_progress_context ();
memset( &cfx, 0, sizeof cfx); memset( &cfx, 0, sizeof cfx);
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx); memset( &zfx, 0, sizeof zfx);
memset( &tfx, 0, sizeof tfx); memset( &tfx, 0, sizeof tfx);
init_packet(&pkt); init_packet(&pkt);
if(use_symkey if(use_symkey
&& (rc=setup_symkey(&symkey_s2k,&symkey_dek))) && (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)) ) if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) )
{
release_progress_context (pfx);
return rc; return rc;
}
if(PGP2) { if(PGP2) {
for(work_list=pk_list; work_list; work_list=work_list->next) 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 ) else if( opt.verbose )
log_info(_("reading from `%s'\n"), filename? filename: "[stdin]"); log_info(_("reading from `%s'\n"), filename? filename: "[stdin]");
handle_progress (&pfx, inp, filename); handle_progress (pfx, inp, filename);
if( opt.textmode ) if( opt.textmode )
iobuf_push_filter( inp, text_filter, &tfx ); 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 )) ) if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) )
goto leave; goto leave;
if( opt.armor ) if ( opt.armor )
iobuf_push_filter( out, armor_filter, &afx ); {
afx = new_armor_context ();
push_armor_filter (afx, out);
}
/* create a session key */ /* create a session key */
cfx.dek = xmalloc_secure_clear (sizeof *cfx.dek); 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_dek);
xfree(symkey_s2k); xfree(symkey_s2k);
release_pk_list( pk_list ); release_pk_list( pk_list );
release_armor_context (afx);
release_progress_context (pfx);
return rc; return rc;
} }

View 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, static int decode_filter ( void *opaque, int control, IOBUF a,
byte *buf, size_t *ret_len); byte *buf, size_t *ret_len);
typedef struct typedef struct decode_filter_context_s
{ {
gcry_cipher_hd_t cipher_hd; gcry_cipher_hd_t cipher_hd;
gcry_md_hd_t mdc_hash; gcry_md_hd_t mdc_hash;
char defer[22]; char defer[22];
int defer_filled; int defer_filled;
int eof_seen; 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 blocksize;
unsigned nprefix; 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 ) if ( opt.verbose && !dek->algo_info_printed )
{ {
const char *s = gcry_cipher_algo_name (dek->algo); const char *s = gcry_cipher_algo_name (dek->algo);
@ -77,20 +102,20 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
goto leave; goto leave;
blocksize = gcry_cipher_get_algo_blklen (dek->algo); blocksize = gcry_cipher_get_algo_blklen (dek->algo);
if ( !blocksize || blocksize > 16 ) if ( !blocksize || blocksize > 16 )
log_fatal("unsupported blocksize %u\n", blocksize ); log_fatal ("unsupported blocksize %u\n", blocksize );
nprefix = blocksize; nprefix = blocksize;
if ( ed->len && ed->len < (nprefix+2) ) if ( ed->len && ed->len < (nprefix+2) )
BUG(); BUG();
if ( ed->mdc_method ) 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 (); BUG ();
if ( DBG_HASHING ) 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_MODE_CFB,
(GCRY_CIPHER_SECURE (GCRY_CIPHER_SECURE
| ((ed->mdc_method || dek->algo >= 100)? | ((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 );*/ /* 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 ) if ( gpg_err_code (rc) == GPG_ERR_WEAK_KEY )
{ {
log_info(_("WARNING: message was encrypted with" log_info(_("WARNING: message was encrypted with"
@ -123,7 +148,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
goto leave; goto leave;
} }
gcry_cipher_setiv (dfx.cipher_hd, NULL, 0); gcry_cipher_setiv (dfx->cipher_hd, NULL, 0);
if ( ed->len ) if ( ed->len )
{ {
@ -144,8 +169,8 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
temp[i] = c; temp[i] = c;
} }
gcry_cipher_decrypt (dfx.cipher_hd, temp, nprefix+2, NULL, 0); gcry_cipher_decrypt (dfx->cipher_hd, temp, nprefix+2, NULL, 0);
gcry_cipher_sync (dfx.cipher_hd); gcry_cipher_sync (dfx->cipher_hd);
p = temp; p = temp;
/* log_hexdump( "prefix", temp, nprefix+2 ); */ /* log_hexdump( "prefix", temp, nprefix+2 ); */
if (dek->symmetric if (dek->symmetric
@ -155,17 +180,18 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
goto leave; goto leave;
} }
if ( dfx.mdc_hash ) if ( dfx->mdc_hash )
gcry_md_write (dfx.mdc_hash, temp, nprefix+2); gcry_md_write (dfx->mdc_hash, temp, nprefix+2);
dfx->refcount++;
if ( ed->mdc_method ) if ( ed->mdc_method )
iobuf_push_filter( ed->buf, mdc_decode_filter, &dfx ); iobuf_push_filter ( ed->buf, mdc_decode_filter, dfx );
else else
iobuf_push_filter( ed->buf, decode_filter, &dfx ); iobuf_push_filter ( ed->buf, decode_filter, dfx );
proc_packets ( procctx, ed->buf ); proc_packets ( procctx, ed->buf );
ed->buf = NULL; 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); rc = gpg_error (GPG_ERR_INV_PACKET);
else if ( ed->mdc_method ) else if ( ed->mdc_method )
{ {
@ -184,26 +210,28 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
bytes are appended. */ bytes are appended. */
int datalen = gcry_md_get_algo_dlen (ed->mdc_method); int datalen = gcry_md_get_algo_dlen (ed->mdc_method);
gcry_cipher_decrypt (dfx.cipher_hd, dfx.defer, 22, NULL, 0); assert (dfx->cipher_hd);
gcry_md_write (dfx.mdc_hash, dfx.defer, 2); assert (dfx->mdc_hash);
gcry_md_final (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"); log_error("mdc_packet with invalid encoding\n");
rc = gpg_error (GPG_ERR_INV_PACKET); rc = gpg_error (GPG_ERR_INV_PACKET);
} }
else if (datalen != 20 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); rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
/* log_printhex("MDC message:", dfx.defer, 22); */ /* log_printhex("MDC message:", dfx->defer, 22); */
/* log_printhex("MDC calc:", gcry_md_read (dfx.mdc_hash,0), datalen); */ /* log_printhex("MDC calc:", gcry_md_read (dfx->mdc_hash,0), datalen); */
} }
leave: leave:
gcry_cipher_close (dfx.cipher_hd); release_dfx_context (dfx);
gcry_md_close (dfx.mdc_hash);
return rc; return rc;
} }
@ -214,7 +242,7 @@ static int
mdc_decode_filter (void *opaque, int control, IOBUF a, mdc_decode_filter (void *opaque, int control, IOBUF a,
byte *buf, size_t *ret_len) byte *buf, size_t *ret_len)
{ {
decode_filter_ctx_t *dfx = opaque; decode_filter_ctx_t dfx = opaque;
size_t n, size = *ret_len; size_t n, size = *ret_len;
int rc = 0; int rc = 0;
int c; int c;
@ -226,11 +254,11 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
} }
else if( control == IOBUFCTRL_UNDERFLOW ) else if( control == IOBUFCTRL_UNDERFLOW )
{ {
assert(a); assert (a);
assert( size > 44 ); assert ( size > 44 );
/* Get at least 22 bytes and put it somewhere ahead in the buffer. */ /* 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 ) if( (c = iobuf_get(a)) == -1 )
break; break;
@ -279,8 +307,10 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
if ( n ) if ( n )
{ {
gcry_cipher_decrypt (dfx->cipher_hd, buf, n, NULL, 0); if ( dfx->cipher_hd )
gcry_md_write (dfx->mdc_hash, buf, n); gcry_cipher_decrypt (dfx->cipher_hd, buf, n, NULL, 0);
if ( dfx->mdc_hash )
gcry_md_write (dfx->mdc_hash, buf, n);
} }
else else
{ {
@ -289,6 +319,10 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
} }
*ret_len = n; *ret_len = n;
} }
else if ( control == IOBUFCTRL_FREE )
{
release_dfx_context (dfx);
}
else if ( control == IOBUFCTRL_DESC ) else if ( control == IOBUFCTRL_DESC )
{ {
*(char**)buf = "mdc_decode_filter"; *(char**)buf = "mdc_decode_filter";
@ -300,7 +334,7 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
static int static int
decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len) 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; size_t n, size = *ret_len;
int rc = 0; int rc = 0;
@ -311,11 +345,18 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
if ( n == -1 ) if ( n == -1 )
n = 0; n = 0;
if ( n ) 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 else
rc = -1; /* EOF */ rc = -1; /* EOF */
*ret_len = n; *ret_len = n;
} }
else if ( control == IOBUFCTRL_FREE )
{
release_dfx_context (fc);
}
else if ( control == IOBUFCTRL_DESC ) else if ( control == IOBUFCTRL_DESC )
{ {
*(char**)buf = "decode_filter"; *(char**)buf = "decode_filter";

View File

@ -137,10 +137,9 @@ do_export( strlist_t users, int secret, unsigned int options )
{ {
IOBUF out = NULL; IOBUF out = NULL;
int any, rc; int any, rc;
armor_filter_context_t afx; armor_filter_context_t *afx = NULL;
compress_filter_context_t zfx; compress_filter_context_t zfx;
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx); memset( &zfx, 0, sizeof zfx);
rc = open_outfile( NULL, 0, &out ); rc = open_outfile( NULL, 0, &out );
@ -151,8 +150,9 @@ do_export( strlist_t users, int secret, unsigned int options )
{ {
if ( opt.armor ) if ( opt.armor )
{ {
afx.what = secret?5:1; afx = new_armor_context ();
iobuf_push_filter ( out, armor_filter, &afx ); afx->what = secret? 5 : 1;
push_armor_filter (afx, out);
} }
if ( opt.compress_keys ) if ( opt.compress_keys )
push_compress_filter (out,&zfx,default_compress_algo()); 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); iobuf_cancel (out);
else else
iobuf_close (out); iobuf_close (out);
release_armor_context (afx);
return rc; return rc;
} }

View File

@ -32,12 +32,14 @@ typedef struct {
} md_filter_context_t; } md_filter_context_t;
typedef struct { typedef struct {
int refcount; /* Initialized to 1. */
/* these fields may be initialized */ /* these fields may be initialized */
int what; /* what kind of armor headers to write */ int what; /* what kind of armor headers to write */
int only_keyblocks; /* skip all headers but ".... key block" */ int only_keyblocks; /* skip all headers but ".... key block" */
const char *hdrlines; /* write these headerlines */ 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" */ int no_openpgp_data; /* output flag: "No valid OpenPGP data found" */
/* the following fields must be initialized to zero */ /* the following fields must be initialized to zero */
@ -121,6 +123,7 @@ typedef struct {
unsigned long last; /* last amount reported */ unsigned long last; /* last amount reported */
unsigned long offset; /* current amount */ unsigned long offset; /* current amount */
unsigned long total; /* total amount */ unsigned long total; /* total amount */
int refcount;
} progress_filter_context_t; } progress_filter_context_t;
/* encrypt_filter_context_t defined in main.h */ /* 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 ); void free_md_filter_context( md_filter_context_t *mfx );
/*-- armor.c --*/ /*-- 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 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); UnarmorPump unarmor_pump_new (void);
void unarmor_pump_release (UnarmorPump x); void unarmor_pump_release (UnarmorPump x);
int unarmor_pump (UnarmorPump x, int c); 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); int escape_dash, int escape_from, int pgp2mode);
/*-- progress.c --*/ /*-- progress.c --*/
int progress_filter (void *opaque, int control, progress_filter_context_t *new_progress_context (void);
iobuf_t a, byte *buf, size_t *ret_len); void release_progress_context (progress_filter_context_t *pfx);
void handle_progress (progress_filter_context_t *pfx, void handle_progress (progress_filter_context_t *pfx,
iobuf_t inp, const char *name); iobuf_t inp, const char *name);

View File

@ -1753,7 +1753,7 @@ main (int argc, char **argv )
int may_coredump; int may_coredump;
strlist_t sl, remusr= NULL, locusr=NULL; strlist_t sl, remusr= NULL, locusr=NULL;
strlist_t nrings=NULL, sec_nrings=NULL; strlist_t nrings=NULL, sec_nrings=NULL;
armor_filter_context_t afx; armor_filter_context_t *afx = NULL;
int detached_sig = 0; int detached_sig = 0;
FILE *configfp = NULL; FILE *configfp = NULL;
char *configname = NULL; char *configname = NULL;
@ -3826,8 +3826,8 @@ main (int argc, char **argv )
if( !opt.no_armor ) { if( !opt.no_armor ) {
if( use_armor_filter( a ) ) { if( use_armor_filter( a ) ) {
memset( &afx, 0, sizeof afx); afx = new_armor_context ();
iobuf_push_filter( a, armor_filter, &afx ); push_armor_filter (afx, a);
} }
} }
if( cmd == aListPackets ) { if( cmd == aListPackets ) {
@ -3843,6 +3843,7 @@ main (int argc, char **argv )
} }
/* cleanup */ /* cleanup */
release_armor_context (afx);
FREE_STRLIST(remusr); FREE_STRLIST(remusr);
FREE_STRLIST(locusr); FREE_STRLIST(locusr);
g10_exit(0); g10_exit(0);

View File

@ -251,9 +251,12 @@ import( IOBUF inp, const char* fname,struct stats_s *stats,
getkey_disable_caches(); getkey_disable_caches();
if( !opt.no_armor ) { /* armored reading is not disabled */ 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; 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) )) { while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) {

View File

@ -1187,11 +1187,17 @@ change_passphrase( KBNODE keyblock )
set_next_passphrase( NULL ); set_next_passphrase( NULL );
for(;;) { for(;;) {
int canceled;
s2k->mode = opt.s2k_mode; s2k->mode = opt.s2k_mode;
s2k->hash_algo = S2K_DIGEST_ALGO; s2k->hash_algo = S2K_DIGEST_ALGO;
dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo,
s2k, 2, errtext, NULL); s2k, 2, errtext, &canceled);
if( !dek ) { if (!dek && canceled) {
rc = GPG_ERR_CANCELED;
break;
}
else if( !dek ) {
errtext = N_("passphrase not correctly repeated; try again"); errtext = N_("passphrase not correctly repeated; try again");
tty_printf ("%s.\n", _(errtext)); tty_printf ("%s.\n", _(errtext));
} }
@ -3235,25 +3241,25 @@ menu_clean(KBNODE keyblock,int self_only)
else else
reason=_("invalid"); reason=_("invalid");
tty_printf("User ID \"%s\" compacted: %s\n",user,reason); tty_printf (_("User ID \"%s\" compacted: %s\n"), user, reason);
modified=1; modified=1;
} }
else if(sigs) else if(sigs)
{ {
tty_printf(sigs==1? tty_printf(sigs==1?
"User ID \"%s\": %d signature removed\n": _("User ID \"%s\": %d signature removed\n") :
"User ID \"%s\": %d signatures removed\n", _("User ID \"%s\": %d signatures removed\n"),
user,sigs); user,sigs);
modified=1; modified=1;
} }
else else
{ {
tty_printf(self_only==1? tty_printf (self_only==1?
"User ID \"%s\": already minimized\n": _("User ID \"%s\": already minimized\n") :
"User ID \"%s\": already clean\n", _("User ID \"%s\": already clean\n"),
user); user);
} }
xfree(user); xfree(user);

View File

@ -96,13 +96,13 @@ struct output_control_s {
char *fname; char *fname;
char *newfname; char *newfname;
IOBUF stream; IOBUF stream;
armor_filter_context_t afx; armor_filter_context_t *afx;
} pub; } pub;
struct { struct {
char *fname; char *fname;
char *newfname; char *newfname;
IOBUF stream; IOBUF stream;
armor_filter_context_t afx; armor_filter_context_t *afx;
} sec; } sec;
}; };
@ -2045,9 +2045,8 @@ ask_user_id( int mode )
} }
/* FIXME: We need a way to cancel this prompt. */
static DEK * static DEK *
do_ask_passphrase( STRING2KEY **ret_s2k ) do_ask_passphrase ( STRING2KEY **ret_s2k, int *r_canceled )
{ {
DEK *dek = NULL; DEK *dek = NULL;
STRING2KEY *s2k; STRING2KEY *s2k;
@ -2060,8 +2059,13 @@ do_ask_passphrase( STRING2KEY **ret_s2k )
s2k->mode = opt.s2k_mode; s2k->mode = opt.s2k_mode;
s2k->hash_algo = S2K_DIGEST_ALGO; s2k->hash_algo = S2K_DIGEST_ALGO;
dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k,2, dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k,2,
errtext, NULL); errtext, r_canceled);
if( !dek ) { if (!dek && *r_canceled) {
xfree(dek); dek = NULL;
xfree(s2k); s2k = NULL;
break;
}
else if( !dek ) {
errtext = N_("passphrase not correctly repeated; try again"); errtext = N_("passphrase not correctly repeated; try again");
tty_printf(_("%s.\n"), _(errtext)); tty_printf(_("%s.\n"), _(errtext));
} }
@ -2541,6 +2545,8 @@ read_parameter_file( const char *fname )
struct output_control_s outctrl; struct output_control_s outctrl;
memset( &outctrl, 0, sizeof( outctrl ) ); memset( &outctrl, 0, sizeof( outctrl ) );
outctrl.pub.afx = new_armor_context ();
outctrl.sec.afx = new_armor_context ();
if( !fname || !*fname) if( !fname || !*fname)
fname = "-"; fname = "-";
@ -2705,6 +2711,8 @@ read_parameter_file( const char *fname )
release_parameter_list( para ); release_parameter_list( para );
iobuf_close (fp); 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 *para = NULL;
struct para_data_s *r; struct para_data_s *r;
struct output_control_s outctrl; struct output_control_s outctrl;
int canceled;
memset( &outctrl, 0, sizeof( outctrl ) ); memset( &outctrl, 0, sizeof( outctrl ) );
@ -2886,7 +2895,8 @@ generate_keypair (const char *fname, const char *card_serialno,
r->next = para; r->next = para;
para = r; para = r;
dek = card_serialno? NULL : do_ask_passphrase( &s2k ); canceled = 0;
dek = card_serialno? NULL : do_ask_passphrase ( &s2k, &canceled );
if( dek ) if( dek )
{ {
r = xmalloc_clear( sizeof *r ); r = xmalloc_clear( sizeof *r );
@ -2900,8 +2910,11 @@ generate_keypair (const char *fname, const char *card_serialno,
r->next = para; r->next = para;
para = r; 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 ); release_parameter_list( para );
} }
@ -2923,6 +2936,7 @@ generate_raw_key (int algo, unsigned int nbits, u32 created_at,
int i; int i;
size_t nskey, npkey; size_t nskey, npkey;
gcry_sexp_t s_parms, s_key; gcry_sexp_t s_parms, s_key;
int canceled;
npkey = pubkey_get_npkey (algo); npkey = pubkey_get_npkey (algo);
nskey = pubkey_get_nskey (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 ); 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 = xmalloc_clear (sizeof *sk);
sk->timestamp = created_at; sk->timestamp = created_at;
@ -3050,9 +3069,8 @@ do_generate_keypair( struct para_data_s *para,
return; return;
} }
if( opt.armor ) { if( opt.armor ) {
outctrl->pub.afx.what = 1; outctrl->pub.afx->what = 1;
iobuf_push_filter( outctrl->pub.stream, armor_filter, push_armor_filter (outctrl->pub.afx, outctrl->pub.stream);
&outctrl->pub.afx );
} }
} }
if( outctrl->sec.newfname ) { if( outctrl->sec.newfname ) {
@ -3080,9 +3098,8 @@ do_generate_keypair( struct para_data_s *para,
return; return;
} }
if( opt.armor ) { if( opt.armor ) {
outctrl->sec.afx.what = 5; outctrl->sec.afx->what = 5;
iobuf_push_filter( outctrl->sec.stream, armor_filter, push_armor_filter (outctrl->sec.afx, outctrl->sec.stream);
&outctrl->sec.afx );
} }
} }
assert( outctrl->pub.stream ); assert( outctrl->pub.stream );
@ -3337,6 +3354,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
STRING2KEY *s2k = NULL; STRING2KEY *s2k = NULL;
u32 cur_time; u32 cur_time;
int ask_pass = 0; int ask_pass = 0;
int canceled;
/* break out the primary secret key */ /* break out the primary secret key */
node = find_kbnode( sec_keyblock, PKT_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) "))) _("Really create? (y/N) ")))
goto leave; goto leave;
canceled = 0;
if (ask_pass) if (ask_pass)
dek = do_ask_passphrase (&s2k); dek = do_ask_passphrase (&s2k, &canceled);
else if (passphrase) { else if (passphrase) {
s2k = xmalloc_secure( sizeof *s2k ); s2k = xmalloc_secure( sizeof *s2k );
s2k->mode = opt.s2k_mode; s2k->mode = opt.s2k_mode;
@ -3415,8 +3434,12 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
NULL, NULL ); NULL, NULL );
} }
rc = do_create( algo, nbits, pub_keyblock, sec_keyblock, if (canceled)
dek, s2k, &sub_sk, expire, 1 ); rc = GPG_ERR_CANCELED;
if (!rc)
rc = do_create (algo, nbits, pub_keyblock, sec_keyblock,
dek, s2k, &sub_sk, expire, 1 );
if( !rc ) if( !rc )
rc = write_keybinding(pub_keyblock, pub_keyblock, pri_sk, sub_sk, use); rc = write_keybinding(pub_keyblock, pub_keyblock, pri_sk, sub_sk, use);
if( !rc ) if( !rc )

View 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) for(key=list;key!=NULL;key=key->next)
{ {
armor_filter_context_t afx; armor_filter_context_t *afx;
IOBUF buffer=iobuf_temp(); IOBUF buffer = iobuf_temp ();
KBNODE block; KBNODE block;
temp=NULL; temp=NULL;
add_to_strlist(&temp,key->d); add_to_strlist(&temp,key->d);
memset(&afx,0,sizeof(afx)); afx = new_armor_context ();
afx.what=1; afx->what = 1;
/* Tell the armor filter to use Unix-style \n line /* Tell the armor filter to use Unix-style \n line
endings, since we're going to fprintf this to a file endings, since we're going to fprintf this to a file
that (on Win32) is open in text mode. The win32 stdio 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 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 proper line endings on win32. This is a no-op on
Unix. */ Unix. */
afx.eol[0]='\n'; afx->eol[0] = '\n';
iobuf_push_filter(buffer,armor_filter,&afx); push_armor_filter (afx, buffer);
release_armor_context (afx);
/* TODO: Remove Comment: lines from keys exported this /* TODO: Remove Comment: lines from keys exported this
way? */ way? */

View File

@ -290,23 +290,8 @@ proc_symkey_enc( CTX c, PACKET *pkt )
} }
else else
{ {
int canceled;
c->dek = passphrase_to_dek (NULL, 0, algo, &enc->s2k, 0, c->dek = passphrase_to_dek (NULL, 0, algo, &enc->s2k, 0,
NULL, &canceled); NULL, NULL);
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;
}
if(c->dek) if(c->dek)
{ {
c->dek->symmetric=1; c->dek->symmetric=1;

View File

@ -482,7 +482,9 @@ ask_passphrase (const char *description,
/* Return a new DEK object Using the string-to-key sepcifier S2K. Use /* 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 MODE 0: Allow cached passphrase
1: Ignore cached passphrase 1: Ignore cached passphrase
@ -496,9 +498,11 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
char *pw = NULL; char *pw = NULL;
DEK *dek; DEK *dek;
STRING2KEY help_s2k; STRING2KEY help_s2k;
int dummy_canceled;
if (canceled)
*canceled = 0; if (!canceled)
canceled = &dummy_canceled;
*canceled = 0;
if ( !s2k ) if ( !s2k )
{ {
@ -600,7 +604,7 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
} }
else if ( have_static_passphrase () ) 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 ); pw = xmalloc_secure ( strlen(fd_passwd)+1 );
strcpy ( pw, fd_passwd ); strcpy ( pw, fd_passwd );
} }
@ -609,6 +613,11 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
/* Divert to the gpg-agent. */ /* Divert to the gpg-agent. */
pw = passphrase_get ( keyid, mode == 2? 1: 0, NULL, pw = passphrase_get ( keyid, mode == 2? 1: 0, NULL,
tryagain_text, NULL, NULL, canceled ); tryagain_text, NULL, NULL, canceled );
if (*canceled)
{
xfree (pw);
return NULL;
}
if (!pw) if (!pw)
pw = xstrdup (""); pw = xstrdup ("");
if ( *pw && mode == 2 ) 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, char *pw2 = passphrase_get ( keyid, 2, NULL, NULL, NULL,
NULL, canceled ); NULL, canceled );
if (*canceled)
{
xfree (pw);
xfree (pw2);
return NULL;
}
if (!pw2) if (!pw2)
pw2 = xstrdup (""); pw2 = xstrdup ("");
if ( strcmp(pw, pw2) ) if ( strcmp(pw, pw2) )

View File

@ -449,18 +449,20 @@ int
ask_for_detached_datafile (gcry_md_hd_t md, gcry_md_hd_t md2, ask_for_detached_datafile (gcry_md_hd_t md, gcry_md_hd_t md2,
const char *inname, int textmode ) const char *inname, int textmode )
{ {
progress_filter_context_t pfx; progress_filter_context_t *pfx;
char *answer = NULL; char *answer = NULL;
IOBUF fp; IOBUF fp;
int rc = 0; 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 ) { if( !fp && !opt.batch ) {
int any=0; int any=0;
tty_printf(_("Detached signature.\n")); tty_printf(_("Detached signature.\n"));
do { do {
char *name; char *name;
xfree(answer); xfree(answer);
tty_enable_completion(NULL); tty_enable_completion(NULL);
name = cpr_get("detached_signature.filename", 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: leave:
xfree(answer); xfree(answer);
release_progress_context (pfx);
return rc; return rc;
} }
@ -518,19 +521,23 @@ int
hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2, strlist_t files, hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2, strlist_t files,
const char *sigfilename, int textmode ) const char *sigfilename, int textmode )
{ {
progress_filter_context_t pfx; progress_filter_context_t *pfx;
IOBUF fp; IOBUF fp;
strlist_t sl; strlist_t sl;
pfx = new_progress_context ();
if( !files ) { if( !files ) {
/* check whether we can open the signed material */ /* check whether we can open the signed material */
fp = open_sigfile( sigfilename, &pfx ); fp = open_sigfile( sigfilename, pfx );
if( fp ) { if( fp ) {
do_hash( md, md2, fp, textmode ); do_hash( md, md2, fp, textmode );
iobuf_close(fp); iobuf_close(fp);
release_progress_context (pfx);
return 0; return 0;
} }
log_error (_("no signed data\n")); log_error (_("no signed data\n"));
release_progress_context (pfx);
return gpg_error (GPG_ERR_NO_DATA); 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 (); int rc = gpg_error_from_syserror ();
log_error(_("can't open signed data `%s'\n"), log_error(_("can't open signed data `%s'\n"),
print_fname_stdin(sl->d)); print_fname_stdin(sl->d));
release_progress_context (pfx);
return rc; return rc;
} }
handle_progress (&pfx, fp, sl->d); handle_progress (pfx, fp, sl->d);
do_hash( md, md2, fp, textmode ); do_hash( md, md2, fp, textmode );
iobuf_close(fp); iobuf_close(fp);
} }
release_progress_context (pfx);
return 0; return 0;
} }

View File

@ -1,5 +1,5 @@
/* progress.c - emit progress status lines /* 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. * This file is part of GnuPG.
* *
@ -21,6 +21,7 @@
#include <config.h> #include <config.h>
#include <stdio.h> #include <stdio.h>
#include <assert.h>
#include "gpg.h" #include "gpg.h"
#include "iobuf.h" #include "iobuf.h"
@ -29,10 +30,54 @@
#include "util.h" #include "util.h"
#include "options.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. * The filter is used to report progress to the user.
*/ */
int static int
progress_filter (void *opaque, int control, progress_filter (void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len) IOBUF a, byte *buf, size_t *ret_len)
{ {
@ -85,11 +130,7 @@ progress_filter (void *opaque, int control,
} }
else if (control == IOBUFCTRL_FREE) else if (control == IOBUFCTRL_FREE)
{ {
/* Note, that we must always dealloc resources of a filter release_progress_context (pfx);
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;
} }
else if (control == IOBUFCTRL_DESC) else if (control == IOBUFCTRL_DESC)
*(char**)buf = "progress_filter"; *(char**)buf = "progress_filter";
@ -101,11 +142,11 @@ handle_progress (progress_filter_context_t *pfx, IOBUF inp, const char *name)
{ {
off_t filesize = 0; off_t filesize = 0;
if (!opt.enable_progress_filter) if (!pfx)
return; return;
if (!is_status_enabled ()) assert (opt.enable_progress_filter);
return; assert (is_status_enabled ());
if ( !iobuf_is_pipe_filename (name) && *name ) if ( !iobuf_is_pipe_filename (name) && *name )
filesize = iobuf_get_filelength (inp, NULL); 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 */ /* register the progress filter */
pfx->what = xstrdup (name ? name : "stdin"); pfx->what = xstrdup (name ? name : "stdin");
pfx->total = filesize; pfx->total = filesize;
pfx->refcount++;
iobuf_push_filter (inp, progress_filter, pfx); iobuf_push_filter (inp, progress_filter, pfx);
} }

View File

@ -200,7 +200,7 @@ int
gen_desig_revoke( const char *uname, strlist_t locusr ) gen_desig_revoke( const char *uname, strlist_t locusr )
{ {
int rc = 0; int rc = 0;
armor_filter_context_t afx; armor_filter_context_t *afx;
PKT_public_key *pk = NULL; PKT_public_key *pk = NULL;
PKT_secret_key *sk = NULL; PKT_secret_key *sk = NULL;
PKT_signature *sig = NULL; PKT_signature *sig = NULL;
@ -219,7 +219,7 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
return G10ERR_GENERAL; return G10ERR_GENERAL;
} }
memset( &afx, 0, sizeof afx); afx = new_armor_context ();
kdbhd = keydb_new (0); kdbhd = keydb_new (0);
classify_user_id (uname, &desc); 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 )) ) if( (rc = open_outfile( NULL, 0, &out )) )
goto leave; goto leave;
afx.what = 1; afx->what = 1;
afx.hdrlines = "Comment: A designated revocation certificate" afx->hdrlines = "Comment: A designated revocation certificate"
" should follow\n"; " should follow\n";
iobuf_push_filter( out, armor_filter, &afx ); push_armor_filter (afx, out);
/* create it */ /* create it */
rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0, 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 else
iobuf_close(out); iobuf_close(out);
release_revocation_reason_info( reason ); release_revocation_reason_info( reason );
release_armor_context (afx);
return rc; return rc;
} }
@ -438,7 +439,7 @@ int
gen_revoke( const char *uname ) gen_revoke( const char *uname )
{ {
int rc = 0; int rc = 0;
armor_filter_context_t afx; armor_filter_context_t *afx;
PACKET pkt; PACKET pkt;
PKT_secret_key *sk; /* used as pointer into a kbnode */ PKT_secret_key *sk; /* used as pointer into a kbnode */
PKT_public_key *pk = NULL; PKT_public_key *pk = NULL;
@ -457,7 +458,7 @@ gen_revoke( const char *uname )
return G10ERR_GENERAL; return G10ERR_GENERAL;
} }
memset( &afx, 0, sizeof afx); afx = new_armor_context ();
init_packet( &pkt ); init_packet( &pkt );
/* search the userid: /* search the userid:
@ -556,9 +557,9 @@ gen_revoke( const char *uname )
if( (rc = open_outfile( NULL, 0, &out )) ) if( (rc = open_outfile( NULL, 0, &out )) )
goto leave; goto leave;
afx.what = 1; afx->what = 1;
afx.hdrlines = "Comment: A revocation certificate should follow\n"; afx->hdrlines = "Comment: A revocation certificate should follow\n";
iobuf_push_filter( out, armor_filter, &afx ); push_armor_filter (afx, out);
/* create it */ /* create it */
rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0, rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
@ -609,6 +610,7 @@ gen_revoke( const char *uname )
else else
iobuf_close(out); iobuf_close(out);
release_revocation_reason_info( reason ); release_revocation_reason_info( reason );
release_armor_context (afx);
return rc; return rc;
} }

View File

@ -739,11 +739,11 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
int encryptflag, strlist_t remusr, const char *outfile ) int encryptflag, strlist_t remusr, const char *outfile )
{ {
const char *fname; const char *fname;
armor_filter_context_t afx; armor_filter_context_t *afx;
compress_filter_context_t zfx; compress_filter_context_t zfx;
md_filter_context_t mfx; md_filter_context_t mfx;
text_filter_context_t tfx; text_filter_context_t tfx;
progress_filter_context_t pfx; progress_filter_context_t *pfx;
encrypt_filter_context_t efx; encrypt_filter_context_t efx;
IOBUF inp = NULL, out = NULL; IOBUF inp = NULL, out = NULL;
PACKET pkt; PACKET pkt;
@ -754,7 +754,8 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
int multifile = 0; int multifile = 0;
u32 duration=0; u32 duration=0;
memset( &afx, 0, sizeof afx); pfx = new_progress_context ();
afx = new_armor_context ();
memset( &zfx, 0, sizeof zfx); memset( &zfx, 0, sizeof zfx);
memset( &mfx, 0, sizeof mfx); memset( &mfx, 0, sizeof mfx);
memset( &efx, 0, sizeof efx); memset( &efx, 0, sizeof efx);
@ -814,7 +815,7 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
goto leave; goto leave;
} }
handle_progress (&pfx, inp, fname); handle_progress (pfx, inp, fname);
} }
if( outfile ) { if( outfile ) {
@ -933,10 +934,10 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
iobuf_push_filter( inp, md_filter, &mfx ); iobuf_push_filter( inp, md_filter, &mfx );
if( detached && !encryptflag && !RFC1991 ) if( detached && !encryptflag && !RFC1991 )
afx.what = 2; afx->what = 2;
if( opt.armor && !outfile ) if( opt.armor && !outfile )
iobuf_push_filter( out, armor_filter, &afx ); push_armor_filter (afx, out);
if( encryptflag ) { if( encryptflag ) {
efx.pk_list = pk_list; efx.pk_list = pk_list;
@ -1008,7 +1009,7 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
sl->d,strerror(errno)); sl->d,strerror(errno));
goto leave; goto leave;
} }
handle_progress (&pfx, inp, sl->d); handle_progress (pfx, inp, sl->d);
if( opt.verbose ) if( opt.verbose )
fprintf(stderr, " `%s'", sl->d ); fprintf(stderr, " `%s'", sl->d );
if(opt.textmode) if(opt.textmode)
@ -1060,6 +1061,8 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
release_sk_list( sk_list ); release_sk_list( sk_list );
release_pk_list( pk_list ); release_pk_list( pk_list );
recipient_digest_algo=0; recipient_digest_algo=0;
release_progress_context (pfx);
release_armor_context (afx);
return rc; return rc;
} }
@ -1071,8 +1074,8 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
int int
clearsign_file( const char *fname, strlist_t locusr, const char *outfile ) clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
{ {
armor_filter_context_t afx; armor_filter_context_t *afx;
progress_filter_context_t pfx; progress_filter_context_t *pfx;
gcry_md_hd_t textmd = NULL; gcry_md_hd_t textmd = NULL;
IOBUF inp = NULL, out = NULL; IOBUF inp = NULL, out = NULL;
PACKET pkt; PACKET pkt;
@ -1083,7 +1086,8 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
int only_md5 = 0; int only_md5 = 0;
u32 duration=0; u32 duration=0;
memset( &afx, 0, sizeof afx); pfx = new_progress_context ();
afx = new_armor_context ();
init_packet( &pkt ); init_packet( &pkt );
if(!opt.force_v3_sigs && !RFC1991) 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) ); fname? fname: "[stdin]", strerror(errno) );
goto leave; goto leave;
} }
handle_progress (&pfx, inp, fname); handle_progress (pfx, inp, fname);
if( outfile ) { if( outfile ) {
if (is_secured_filename (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 */ /* fixme: check for read errors */
/* now write the armor */ /* now write the armor */
afx.what = 2; afx->what = 2;
iobuf_push_filter( out, armor_filter, &afx ); push_armor_filter (afx, out);
/* write the signatures */ /* write the signatures */
rc=write_signature_packets (sk_list, out, textmd, 0x01, 0, duration, 'C'); 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); iobuf_close(inp);
gcry_md_close ( textmd ); gcry_md_close ( textmd );
release_sk_list( sk_list ); release_sk_list( sk_list );
release_progress_context (pfx);
release_armor_context (afx);
return rc; return rc;
} }
@ -1225,8 +1231,8 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
int int
sign_symencrypt_file (const char *fname, strlist_t locusr) sign_symencrypt_file (const char *fname, strlist_t locusr)
{ {
armor_filter_context_t afx; armor_filter_context_t *afx;
progress_filter_context_t pfx; progress_filter_context_t *pfx;
compress_filter_context_t zfx; compress_filter_context_t zfx;
md_filter_context_t mfx; md_filter_context_t mfx;
text_filter_context_t tfx; text_filter_context_t tfx;
@ -1239,8 +1245,10 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
SK_LIST sk_rover = NULL; SK_LIST sk_rover = NULL;
int algo; int algo;
u32 duration=0; u32 duration=0;
int canceled;
memset( &afx, 0, sizeof afx); pfx = new_progress_context ();
afx = new_armor_context ();
memset( &zfx, 0, sizeof zfx); memset( &zfx, 0, sizeof zfx);
memset( &mfx, 0, sizeof mfx); memset( &mfx, 0, sizeof mfx);
memset( &tfx, 0, sizeof tfx); memset( &tfx, 0, sizeof tfx);
@ -1273,7 +1281,7 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
fname? fname: "[stdin]", strerror(errno) ); fname? fname: "[stdin]", strerror(errno) );
goto leave; goto leave;
} }
handle_progress (&pfx, inp, fname); handle_progress (pfx, inp, fname);
/* prepare key */ /* prepare key */
s2k = xmalloc_clear( sizeof *s2k ); s2k = xmalloc_clear( sizeof *s2k );
@ -1284,10 +1292,10 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
if (!opt.quiet || !opt.batch) if (!opt.quiet || !opt.batch)
log_info (_("%s encryption will be used\n"), log_info (_("%s encryption will be used\n"),
gcry_cipher_algo_name (algo) ); 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) { 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) ); log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc) );
goto leave; goto leave;
} }
@ -1321,7 +1329,7 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
/* Push armor output filter */ /* Push armor output filter */
if (opt.armor) if (opt.armor)
iobuf_push_filter (out, armor_filter, &afx); push_armor_filter (afx, out);
/* Write the symmetric key packet */ /* Write the symmetric key packet */
/*(current filters: armor)*/ /*(current filters: armor)*/
@ -1382,6 +1390,8 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
gcry_md_close( mfx.md ); gcry_md_close( mfx.md );
xfree(cfx.dek); xfree(cfx.dek);
xfree(s2k); xfree(s2k);
release_progress_context (pfx);
release_armor_context (afx);
return rc; return rc;
} }

View File

@ -55,13 +55,14 @@ int
verify_signatures( int nfiles, char **files ) verify_signatures( int nfiles, char **files )
{ {
IOBUF fp; IOBUF fp;
armor_filter_context_t afx; armor_filter_context_t *afx;
progress_filter_context_t pfx; progress_filter_context_t *pfx;
const char *sigfile; const char *sigfile;
int i, rc; int i, rc;
strlist_t sl; 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, /* 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 * 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 * 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 (); rc = gpg_error_from_syserror ();
log_error(_("can't open `%s': %s\n"), log_error(_("can't open `%s': %s\n"),
print_fname_stdin(sigfile), strerror (errno)); print_fname_stdin(sigfile), strerror (errno));
release_progress_context (pfx);
return rc; return rc;
} }
handle_progress (&pfx, fp, sigfile); handle_progress (pfx, fp, sigfile);
if( !opt.no_armor && use_armor_filter( fp ) ) if( !opt.no_armor && use_armor_filter( fp ) )
iobuf_push_filter( fp, armor_filter, &afx ); push_armor_filter (afx, fp);
sl = NULL; sl = NULL;
for(i=nfiles-1 ; i > 0 ; i-- ) 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 ); rc = proc_signature_packets( NULL, fp, sl, sigfile );
free_strlist(sl); free_strlist(sl);
iobuf_close(fp); 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" log_error(_("the signature could not be verified.\n"
"Please remember that the signature file (.sig or .asc)\n" "Please remember that the signature file (.sig or .asc)\n"
"should be the first file given on the command line.\n") ); "should be the first file given on the command line.\n") );
rc = 0; rc = 0;
} }
release_armor_context (afx);
release_progress_context (pfx);
return rc; return rc;
} }
@ -139,10 +143,11 @@ static int
verify_one_file( const char *name ) verify_one_file( const char *name )
{ {
IOBUF fp; IOBUF fp;
armor_filter_context_t afx; armor_filter_context_t *afx = NULL;
progress_filter_context_t pfx; progress_filter_context_t *pfx;
int rc; int rc;
pfx = new_progress_context ();
print_file_status( STATUS_FILE_START, name, 1 ); print_file_status( STATUS_FILE_START, name, 1 );
fp = iobuf_open(name); fp = iobuf_open(name);
if (fp) if (fp)
@ -158,20 +163,23 @@ verify_one_file( const char *name )
log_error(_("can't open `%s': %s\n"), log_error(_("can't open `%s': %s\n"),
print_fname_stdin(name), strerror (errno)); print_fname_stdin(name), strerror (errno));
print_file_status( STATUS_FILE_ERROR, name, 1 ); print_file_status( STATUS_FILE_ERROR, name, 1 );
release_progress_context (pfx);
return rc; return rc;
} }
handle_progress (&pfx, fp, name); handle_progress (pfx, fp, name);
if( !opt.no_armor ) { if( !opt.no_armor ) {
if( use_armor_filter( fp ) ) { if( use_armor_filter( fp ) ) {
memset( &afx, 0, sizeof afx); afx = new_armor_context ();
iobuf_push_filter( fp, armor_filter, &afx ); push_armor_filter (afx, fp);
} }
} }
rc = proc_signature_packets( NULL, fp, NULL, name ); rc = proc_signature_packets( NULL, fp, NULL, name );
iobuf_close(fp); iobuf_close(fp);
write_status( STATUS_FILE_DONE ); write_status( STATUS_FILE_DONE );
release_armor_context (afx);
release_progress_context (pfx);
return rc; return rc;
} }

View 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> 2006-11-15 Werner Koch <wk@g10code.com>
* logging.c (my_funopen_hook_ret_t): New. * logging.c (my_funopen_hook_ret_t): New.

View File

@ -102,7 +102,7 @@ set_native_charset (const char *newset)
if (!newset) if (!newset)
{ {
#ifdef HABE_W32_SYSTEM #ifdef HAVE_W32_SYSTEM
static char codepage[30]; static char codepage[30];
unsigned int cpno; unsigned int cpno;
const char *aliases; const char *aliases;