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>
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)
------------------------------------------------
@ -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)

View 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.

View 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:

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>
* 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 \
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

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
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

View 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

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>
* 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
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
@ -4166,7 +4226,7 @@
* 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.
@ -5983,7 +6043,7 @@
(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

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
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";

View 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];

View File

@ -42,12 +42,12 @@
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;
}

View 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);
}

View 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;
}

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,
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";

View 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;
}

View 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);

View File

@ -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);

View 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) )) {

View 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);

View 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 )

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)
{
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? */

View 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;

View 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) )

View 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;
}

View 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"
@ -29,10 +30,54 @@
#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);
}

View 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;
}

View 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;
}

View 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;
}

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>
* logging.c (my_funopen_hook_ret_t): New.

View 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;