See ChangeLog: Fri Jul 14 19:38:23 CEST 2000 Werner Koch

This commit is contained in:
Werner Koch 2000-07-14 17:34:53 +00:00
parent d1648b4d7a
commit 92cd255508
104 changed files with 5871 additions and 1540 deletions

View File

@ -1,6 +1,69 @@
Fri Jul 14 19:38:23 CEST 2000 Werner Koch <wk@>
The big merge between this one and the stable branch 1.0. Still need
to merge TNANKS, AUTHORS and such. It probaly does not compile yet.
* acinclude.m4 (GNUPG_CHECK_MLOCK): Fixed syntax error in C code.
* configure.in: Add check for termio.h, wait unctiosn and sigaction.
* acinclude.m4, configure.in (GNUPG_CHECK_GNUMAKE): New.
* acinclude.m4 (MKDIR_TAKES_ONE_ARG): Check some headers. By Gaël Quéri.
* configure.in (AM_INIT_AUTOMAKE): Use this now. By Gaël.
* acinclude.m4 (GNUPG_CHECK_EXPORTDYNAMIC): Replacement for
GNUPG_CHECK_RDYNAMIC which should handle gcc with non GNU ld nicer.
Contributed by Dave Dykstra.
* configure.in (GNYPG_CHECK_RDYNAMIC): Replaced by the new check.
* configure.in: Add a test for unisgned long long.
* configure.in (DYNLINK_MOD_CFLAGS): Set different for NetBSD.
* configure.in: Add check for clock_gettime
* configure.in (ALL_LINGUAS): Add nl.
* configure.in (ALL_LINGUAS): Add Esperanto.
* configure.in (ALL_LINGUAS): Add sv and ja.
* configure.in: Use /usr/local for CFLAGS and LDFLAGS when
target is freebsd. By Rémi.
* configure.in: Do not set development version when the version has
a dash in it. Suggested by Dave Dykstra.
* configure.in: Removed substitution for doc/gph/Makefile.
Do all the gcc warning only in maintainer mode.
* configure.in (dlopen): Use CHECK_FUNC for a test of dlopen in libc.
Suggested by Alexandre Oliva.
(-Wall): Moved the settting of gcc warning options near to the end
so that tests don't get confused. Suggested by Paul D. Smith.
* acinclude.m4 (GNUPG_SYS_NM_PARSE): Added BSDI support.
(GNUPG_CHECK_RDYNAMIC): Ditto.
* acinclude.m4 (GNUPG_CHECK_MLOCK): Changed the way to test for
librt. Test suggested by Jeff Long.
* acinclude.m4 (GNUPG_CHECK_MLOCK): Do librt check only when
we can't link a test program. This way GNU systems don't need
to link against linrt.
(GNUPG_CHECK_IPC): Fixed use of TRY_COMPILE macro. From Tim Mooney.
* acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Add support for
DJGPP.
(GNUPG_CHECK_MLOCK): Check whether mlock sits in librt.
* acinclude.m4 (GNUPG_CHECK_RDYNAMIC): Add NetBSD. By Thomas Klausner.
* acconfig.h (HAVE_MLOCK): Added
Mon Mar 13 19:22:46 CET 2000 Werner Koch <wk@openit.de>
* configure.in: Now uses the Docbook M$s from GPH.
* configure.in: Now uses the Docbook M4s from GPH.
Mon Jan 31 17:46:35 CET 2000 Werner Koch <wk@>

View File

@ -53,6 +53,8 @@
#undef HAVE_STPCPY
#undef HAVE_MLOCK
#undef BIG_ENDIAN_HOST
#undef LITTLE_ENDIAN_HOST

View File

@ -50,6 +50,25 @@ AC_DEFUN(GNUPG_FIX_HDR_VERSION,
])
dnl GNUPG_CHECK_GNUMAKE
dnl
AC_DEFUN(GNUPG_CHECK_GNUMAKE,
[
if ${MAKE-make} --version 2>/dev/null | grep '^GNU ' >/dev/null 2>&1; then
:
else
AC_MSG_WARN([[
***
*** It seems that you are not using GNU make. Some make tools have serious
*** flaws and you may not be able to build this software at all. Before you
*** complain, please try GNU make: GNU make is easy to build and available
*** at all GNU archives. It is always available from ftp.gnu.org:/gnu/make.
***]])
fi
])
dnl GNUPG_LINK_FILES( SRC, DEST )
dnl same as AC_LINK_FILES, but collect the files to link in
dnl some special variables and do the link
@ -212,39 +231,38 @@ define(GNUPG_CHECK_PIC,
######################################################################
# Check for rdynamic flag
# This sets CFLAGS_RDYNAMIC to the required flags
# Check for export-dynamic flag
# This sets CFLAGS_EXPORTDYNAMIC to the required flags
######################################################################
dnl GNUPG_CHECK_RDYNAMIC
dnl GNUPG_CHECK_EXPORTDYNAMIC
dnl
define(GNUPG_CHECK_RDYNAMIC,
[ AC_MSG_CHECKING(how to specify -rdynamic)
CFLAGS_RDYNAMIC=
define(GNUPG_CHECK_EXPORTDYNAMIC,
[ AC_MSG_CHECKING(how to specify -export-dynamic)
if test "$cross_compiling" = yes; then
AC_MSG_RESULT(assume none)
AC_MSG_RESULT(assume none)
CFLAGS_EXPORTDYNAMIC=""
else
case "$host_os" in
solaris* )
CFLAGS_RDYNAMIC="-Wl,-dy"
;;
hpux* )
CFLAGS_RDYNAMIC="-Wl,-E"
;;
openbsd* | freebsd2* | osf4* | irix* )
CFLAGS_RDYNAMIC=""
;;
* )
CFLAGS_RDYNAMIC="-Wl,-export-dynamic"
;;
esac
AC_MSG_RESULT($CFLAGS_RDYNAMIC)
AC_CACHE_VAL(gnupg_cv_export_dynamic,[
if AC_TRY_COMMAND([${CC-cc} $CFLAGS -Wl,--version 2>&1 |
grep "GNU ld" >/dev/null]); then
# using gnu's linker
gnupg_cv_export_dynamic="-Wl,-export-dynamic"
else
case "$host_os" in
hpux* )
gnupg_cv_export_dynamic="-Wl,-E"
;;
* )
gnupg_cv_export_dynamic=""
;;
esac
fi
])
AC_MSG_RESULT($gnupg_cv_export_dynamic)
CFLAGS_EXPORTDYNAMIC="$gnupg_cv_export_dynamic"
fi
])
#####################################################################
# Check for SysV IPC (from GIMP)
# And see whether we have a SHM_LOCK (FreeBSD does not have it).
@ -299,7 +317,8 @@ define(GNUPG_CHECK_IPC,
AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>],[
int foo( int shm_id ) { shmctl(shm_id, SHM_LOCK, 0); }
int shm_id;
shmctl(shm_id, SHM_LOCK, 0);
],
gnupg_cv_ipc_have_shm_lock="yes",
gnupg_cv_ipc_have_shm_lock="no"
@ -318,11 +337,46 @@ define(GNUPG_CHECK_IPC,
######################################################################
# Check whether mlock is broken (hpux 10.20 raises a SIGBUS if mlock
# is not called from uid 0 (not tested whether uid 0 works)
# For DECs Tru64 we have also to check whether mlock is in librt
# mlock is there a macro using memlk()
######################################################################
dnl GNUPG_CHECK_MLOCK
dnl
define(GNUPG_CHECK_MLOCK,
[ AC_CHECK_FUNCS(mlock)
if test "$ac_cv_func_mlock" = "no"; then
AC_CHECK_HEADERS(sys/mman.h)
if test "$ac_cv_header_sys_mman_h" = "yes"; then
# Add librt to LIBS:
AC_CHECK_LIB(rt, memlk)
AC_CACHE_CHECK([whether mlock is in sys/mman.h],
gnupg_cv_mlock_is_in_sys_mman,
[AC_TRY_LINK([
#include <assert.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
], [
int i;
mkdir ("foo", 0);
/* glibc defines this for functions which it implements
* to always fail with ENOSYS. Some functions are actually
* named something starting with __ and the normal name
* is an alias. */
#if defined (__stub_mlock) || defined (__stub___mlock)
choke me
#else
mlock(&i, 4);
#endif
; return 0;
],
gnupg_cv_mlock_is_in_sys_mman=yes,
gnupg_cv_mlock_is_in_sys_mman=no)])
if test "$gnupg_cv_mlock_is_in_sys_mman" = "yes"; then
AC_DEFINE(HAVE_MLOCK)
fi
fi
fi
if test "$ac_cv_func_mlock" = "yes"; then
AC_MSG_CHECKING(whether mlock is broken)
AC_CACHE_VAL(gnupg_cv_have_broken_mlock,
@ -372,9 +426,10 @@ define(GNUPG_CHECK_MLOCK,
])
################################################################
################################################################
# GNUPG_PROG_NM - find the path to a BSD-compatible name lister
################################################################
AC_DEFUN(GNUPG_PROG_NM,
[AC_MSG_CHECKING([for BSD-compatible nm])
AC_CACHE_VAL(ac_cv_path_NM,
@ -433,7 +488,7 @@ case "$host_os" in
aix*)
ac_symcode='[BCDTU]'
;;
freebsd* | netbsd* | openbsd* | sunos* | cygwin32* | mingw32*)
freebsd* | netbsd* | openbsd* | bsdi* | sunos* | cygwin32* | mingw32*)
ac_sympat='_\([_A-Za-z][_A-Za-z0-9]*\)'
ac_symxfrm='_\1 \1'
;;
@ -586,7 +641,7 @@ AC_CHECK_TOOL(AS, as, false)
AC_DEFUN(GNUPG_SYS_SYMBOL_UNDERSCORE,
[tmp_do_check="no"
case "${target}" in
i386-emx-os2 | i[3456]86-pc-os2*emx )
i386-emx-os2 | i[3456]86-pc-os2*emx | i386-pc-msdosdjgpp)
ac_cv_sys_symbol_underscore=yes
;;
*)
@ -645,7 +700,8 @@ dnl Stolen from gcc
dnl Define MKDIR_TAKES_ONE_ARG if mkdir accepts only one argument instead
dnl of the usual 2.
AC_DEFUN(GNUPG_FUNC_MKDIR_TAKES_ONE_ARG,
[AC_CACHE_CHECK([if mkdir takes one argument], gnupg_cv_mkdir_takes_one_arg,
[AC_CHECK_HEADERS(sys/stat.h unistd.h direct.h)
AC_CACHE_CHECK([if mkdir takes one argument], gnupg_cv_mkdir_takes_one_arg,
[AC_TRY_COMPILE([
#include <sys/types.h>
#ifdef HAVE_SYS_STAT_H
@ -663,7 +719,6 @@ if test $gnupg_cv_mkdir_takes_one_arg = yes ; then
fi
])
dnl GPH_PROG_DOCBOOK()
dnl Check whether we have the needed Docbook environment
dnl and issue a warning if this is not the case.

View File

@ -1,3 +1,85 @@
Fri Jul 14 19:38:23 CEST 2000 Werner Koch <wk@>
* md.c (gcry_md_ctl): Support GCRYCTL_{START,STOP}_DUMP.
* Makefile.am: Never compile mingw32 as module.
* Makefile.am: Tweaked module build and removed libtool
* Makefile.am: Replaced -O1 by -O. Suggested by Alec Habig.
* elgamal.c (sign): Removed inactive code.
* rsa.c, rsa.h: New based on the old module version (only in CVS for now).
* pubkey.c (setup_pubkey_table): Added commented support for RSA.
* rndunix.c (waitpid): New. For UTS 2.1. All by Dave Dykstra.
(my_popen): Do the FD_CLOEXEC only if it is available
(start_gatherer): Cope with missing _SC_OPEN_MAX
* rndunix.c: Add some more headers for QNX. By Sam Roberts.
* rndegd.c (gather_random): Shortcut level 0.
* rndunix.c (gather_random): Ditto.
* rndw32.c (gather_random): Ditto.
* rndw32.c: Replaced with code from Cryptlib and commented the old stuff.
* rndw32.c: Add some debuging code enabled by an environment variable.
* random.c (read_seed_file): Binary open for DOSish system
(update_random_seed_file): Ditto.
* random.c [MINGW32]: Include process.h for getpid.
* random.c (fast_random_poll): Add clock_gettime() as fallback for
system which support this POSIX.4 fucntion. By Sam Roberts.
* random.c (read_seed_file): Removed the S_ISLNK test becuase it
is already covered by !S_ISREG and is not defined in Unixware.
Reported by Dave Dykstra.
(update_random_seed_file): Silently ignore update request when pool
is not filled.
* random.c (read_seed_file): New.
(set_random_seed_file): New.
(read_pool): Try to read the seeding file.
(update_random_seed_file): New.
(read_pool): Do an initial extra seeding when level 2 quality random
is requested the first time. This requestes at least POOLSIZE/2 bytes
of entropy. Compined with the seeding file this should make normal
random bytes cheaper and increase the quality of the random bytes
used for key generation.
* random.c (read_pool): Print a more friendly error message in
cases when too much random is requested in one call.
* random.c (fast_random_poll): Check whether RUSAGE_SELF is defined;
this is not the case for some ESIX and Unixware, although they have
getrusage().
* primegen.c (generate_elg_prime): All primes are now generated with
the lowest random quality level. Because they are public anyway we
don't need stronger random and by this we do not drain the systems
entropy so much.
* primegen.c (register_primegen_progress): New.
* dsa.c (register_pk_dsa_progress): New.
* elgamal.c (register_pk_elg_progress): New.
* elgamal.c (wiener_map): New.
(gen_k): Use a much smaller k.
(generate): Calculate the qbits using the wiener map and
choose an x at a size comparable to the one choosen in gen_k
* rmd160.c (rmd160_get_info): Moved casting to the left side due to a
problem with UTS4.3. Suggested by Dave Dykstra.
* sha1.c (sha1_get_info): Ditto.
* tiger.c (tiger_get_info): Ditto.
* md5.c (md5_get_info): Ditto
* des.c (des_get_info): Ditto.
* blowfish.c (blowfish_get_info): Ditto.
* cast5.c (cast5_get_info): Ditto.
* twofish.c (twofish_get_info): Ditto.
Fri Mar 24 11:25:45 CET 2000 Werner Koch <wk@openit.de>
* md.c (md_open): Add hmac arg and allocate space for the pads.

View File

@ -5,15 +5,8 @@ INCLUDES = -I$(top_srcdir)/gcrypt
noinst_LTLIBRARIES = libcipher.la
# The configure script greps the module names from the following lines.
# You must also add all these names to EXTRA_PROGRAMS some lines below
# and EXTRA_foo_SOURCES entries.
# Hmmm is there a more easy way to do this? (EXTRA_PROGRAMS
# might also list programs which are not modules)
# MODULES: rndunix rndlinux rndegd rndw32
# MODULES: sha1 rmd160 md5 tiger
EXTRA_PROGRAMS = rndunix rndlinux rndegd rndw32 \
sha1 rmd160 md5 tiger
# The configure script greps the module names from the EXTRA_PROGRAMS line
EXTRA_PROGRAMS = rndlinux rndunix rndegd rndw32 sha1 rmd160 md5 tiger
EXTRA_rndlinux_SOURCES = rndlinux.c
EXTRA_rndunix_SOURCES = rndunix.c
@ -73,7 +66,7 @@ libcipher_la_LIBADD = @STATIC_CIPHER_OBJS@
tiger: $(srcdir)/tiger.c
`echo $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o tiger $(srcdir)/tiger.c | \
sed -e 's/-O[2-9s]*/-O1/g' `
sed -e 's/-O[2-9s]*/-O/g' `
tiger.o: $(srcdir)/tiger.c
`echo $(COMPILE) -c $(srcdir)/tiger.c | sed -e 's/-O[2-9s]*/-O1/g' `
@ -98,9 +91,3 @@ rndlinux: $(srcdir)/rndlinux.c
rndegd: $(srcdir)/rndegd.c
$(COMPILE) $(DYNLINK_MOD_CFLAGS) -o rndegd $(srcdir)/rndegd.c
# We need to have a better system for selection which modules
# to compile. For now this works.
rndw32: $(srcdir)/rndw32.c
echo "#!/bin/sh" >rndw32
echo "Not usable as a module" >>rndw32

View File

@ -584,9 +584,12 @@ blowfish_get_info( int algo, size_t *keylen,
*keylen = 128;
*blocksize = BLOWFISH_BLOCKSIZE;
*contextsize = sizeof(BLOWFISH_context);
*r_setkey = FNCCAST_SETKEY(bf_setkey);
*r_encrypt= FNCCAST_CRYPT(encrypt_block);
*r_decrypt= FNCCAST_CRYPT(decrypt_block);
*(int (**)(BLOWFISH_context*, byte*, unsigned))r_setkey
= bf_setkey;
*(void (**)(BLOWFISH_context*, byte*, byte*))r_encrypt
= encrypt_block;
*(void (**)(BLOWFISH_context*, byte*, byte*))r_decrypt
= decrypt_block;
if( algo == CIPHER_ALGO_BLOWFISH )
return "BLOWFISH";

View File

@ -610,9 +610,13 @@ cast5_get_info( int algo, size_t *keylen,
*keylen = 128;
*blocksize = CAST5_BLOCKSIZE;
*contextsize = sizeof(CAST5_context);
*r_setkey = FNCCAST_SETKEY(cast_setkey);
*r_encrypt= FNCCAST_CRYPT(encrypt_block);
*r_decrypt= FNCCAST_CRYPT(decrypt_block);
*(int (**)(CAST5_context*, byte*, unsigned))r_setkey
= cast_setkey;
*(void (**)(CAST5_context*, byte*, byte*))r_encrypt
= encrypt_block;
*(void (**)(CAST5_context*, byte*, byte*))r_decrypt
= decrypt_block;
if( algo == CIPHER_ALGO_CAST5 )
return "CAST5";

View File

@ -1001,9 +1001,12 @@ des_get_info( int algo, size_t *keylen,
*keylen = 192;
*blocksize = 8;
*contextsize = sizeof(struct _tripledes_ctx);
*r_setkey = FNCCAST_SETKEY(do_tripledes_setkey);
*r_encrypt= FNCCAST_CRYPT(do_tripledes_encrypt);
*r_decrypt= FNCCAST_CRYPT(do_tripledes_decrypt);
*(int (**)(struct _tripledes_ctx*, byte*, unsigned))r_setkey
= do_tripledes_setkey;
*(void (**)(struct _tripledes_ctx*, byte*, byte*))r_encrypt
= do_tripledes_encrypt;
*(void (**)(struct _tripledes_ctx*, byte*, byte*))r_decrypt
= do_tripledes_decrypt;
return "3DES";
}
return NULL;

View File

@ -1,5 +1,5 @@
/* dsa.c - DSA signature scheme
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -52,13 +52,28 @@ static void generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors );
static void sign(MPI r, MPI s, MPI input, DSA_secret_key *skey);
static int verify(MPI r, MPI s, MPI input, DSA_public_key *pkey);
static void (*progress_cb) ( void *, int );
static void *progress_cb_data;
void
register_pk_dsa_progress ( void (*cb)( void *, int), void *cb_data )
{
progress_cb = cb;
progress_cb_data = cb_data;
}
static void
progress( int c )
{
fputc( c, stderr );
if ( progress_cb )
progress_cb ( progress_cb_data, c );
else
fputc( c, stderr );
}
/****************
* Generate a random secret exponent k less than q
*/

View File

@ -1,5 +1,5 @@
/* elgamal.c - ElGamal Public Key encryption
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
*
* For a description of the algorithm, see:
* Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996.
@ -56,13 +56,67 @@ static void sign(MPI a, MPI b, MPI input, ELG_secret_key *skey);
static int verify(MPI a, MPI b, MPI input, ELG_public_key *pkey);
static void (*progress_cb) ( void *, int );
static void *progress_cb_data;
void
register_pk_elg_progress ( void (*cb)( void *, int), void *cb_data )
{
progress_cb = cb;
progress_cb_data = cb_data;
}
static void
progress( int c )
{
fputc( c, stderr );
if ( progress_cb )
progress_cb ( progress_cb_data, c );
else
fputc( c, stderr );
}
/****************
* Michael Wiener's table on subgroup sizes to match field sizes
* (floating around somewhere - Fixme: need a reference)
*/
static unsigned int
wiener_map( unsigned int n )
{
static struct { unsigned int p_n, q_n; } t[] =
{ /* p q attack cost */
{ 512, 119 }, /* 9 x 10^17 */
{ 768, 145 }, /* 6 x 10^21 */
{ 1024, 165 }, /* 7 x 10^24 */
{ 1280, 183 }, /* 3 x 10^27 */
{ 1536, 198 }, /* 7 x 10^29 */
{ 1792, 212 }, /* 9 x 10^31 */
{ 2048, 225 }, /* 8 x 10^33 */
{ 2304, 237 }, /* 5 x 10^35 */
{ 2560, 249 }, /* 3 x 10^37 */
{ 2816, 259 }, /* 1 x 10^39 */
{ 3072, 269 }, /* 3 x 10^40 */
{ 3328, 279 }, /* 8 x 10^41 */
{ 3584, 288 }, /* 2 x 10^43 */
{ 3840, 296 }, /* 4 x 10^44 */
{ 4096, 305 }, /* 7 x 10^45 */
{ 4352, 313 }, /* 1 x 10^47 */
{ 4608, 320 }, /* 2 x 10^48 */
{ 4864, 328 }, /* 2 x 10^49 */
{ 5120, 335 }, /* 3 x 10^50 */
{ 0, 0 }
};
int i;
for(i=0; t[i].p_n; i++ ) {
if( n <= t[i].p_n )
return t[i].q_n;
}
/* not in table - use some arbitrary high number ;-) */
return n / 8 + 200;
}
static void
test_keys( ELG_secret_key *sk, unsigned nbits )
{
@ -104,38 +158,44 @@ gen_k( MPI p )
MPI k = mpi_alloc_secure( 0 );
MPI temp = mpi_alloc( mpi_get_nlimbs(p) );
MPI p_1 = mpi_copy(p);
unsigned int nbits = mpi_get_nbits(p);
unsigned int nbytes = (nbits+7)/8;
unsigned int orig_nbits = mpi_get_nbits(p);
unsigned int nbits, nbytes;
char *rndbuf = NULL;
/* IMO using a k much lesser than p is sufficient and it greatly
* improves the encryption performance. We use Wiener's table
* and add a large safety margin.
*/
nbits = wiener_map( orig_nbits ) * 3 / 2;
if( nbits >= orig_nbits )
BUG();
nbytes = (nbits+7)/8;
if( DBG_CIPHER )
log_debug("choosing a random k ");
mpi_sub_ui( p_1, p, 1);
for(;;) {
if( DBG_CIPHER )
progress('.');
if( !rndbuf || nbits < 32 ) {
g10_free(rndbuf);
rndbuf = gcry_random_bytes_secure( nbytes, GCRY_STRONG_RANDOM );
}
else { /* change only some of the higher bits */
/* we could imporove this by directly requesting more memory
/* we could improve this by directly requesting more memory
* at the first call to get_random_bytes() and use this the here
* maybe it is easier to do this directly in random.c */
* maybe it is easier to do this directly in random.c
* Anyway, it is highly inlikely that we will ever reach this code
*/
char *pp = gcry_random_bytes_secure( 4, GCRY_STRONG_RANDOM );
memcpy( rndbuf, pp, 4 );
g10_free(pp);
log_debug("gen_k: tsss, never expected to reach this\n");
}
mpi_set_buffer( k, rndbuf, nbytes, 0 );
for(;;) {
/* make sure that the number is of the exact lenght */
if( mpi_test_bit( k, nbits-1 ) )
mpi_set_highbit( k, nbits-1 );
else {
mpi_set_highbit( k, nbits-1 );
mpi_clear_bit( k, nbits-1 );
}
/* Hmm, actually we don't need this step here
* because we use k much smaller than p - we do it anyway
* just in case the keep on adding a one to k ;) */
if( !(mpi_cmp( k, p_1 ) < 0) ) { /* check: k < (p-1) */
if( DBG_CIPHER )
progress('+');
@ -149,6 +209,8 @@ gen_k( MPI p )
if( mpi_gcd( temp, k, p_1 ) )
goto found; /* okay, k is relatively prime to (p-1) */
mpi_add_ui( k, k, 1 );
if( DBG_CIPHER )
progress('.');
}
}
found:
@ -167,7 +229,7 @@ gen_k( MPI p )
* and an array with n-1 factors of (p-1)
*/
static void
generate( ELG_secret_key *sk, unsigned nbits, MPI **ret_factors )
generate( ELG_secret_key *sk, unsigned int nbits, MPI **ret_factors )
{
MPI p; /* the prime */
MPI p_min1;
@ -175,19 +237,15 @@ generate( ELG_secret_key *sk, unsigned nbits, MPI **ret_factors )
MPI x; /* the secret exponent */
MPI y;
MPI temp;
unsigned qbits;
unsigned int qbits;
unsigned int xbits;
byte *rndbuf;
p_min1 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
temp = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
if( nbits < 512 )
qbits = 120;
else if( nbits <= 1024 )
qbits = 160;
else if( nbits <= 2048 )
qbits = 200;
else
qbits = 240;
qbits = wiener_map( nbits );
if( qbits & 1 ) /* better have a even one */
qbits++;
g = mpi_alloc(1);
p = generate_elg_prime( 0, nbits, qbits, g, ret_factors );
mpi_sub_ui(p_min1, p, 1);
@ -198,18 +256,26 @@ generate( ELG_secret_key *sk, unsigned nbits, MPI **ret_factors )
* This must be a very good random number because this is the
* secret part. The prime is public and may be shared anyway,
* so a random generator level of 1 is used for the prime.
*
* I don't see a reason to have a x of about the same size
* as the p. It should be sufficient to have one about the size
* of q or the later used k plus a large safety margin. Decryption
* will be much faster with such an x.
*/
x = mpi_alloc_secure( nbits/BITS_PER_MPI_LIMB );
xbits = qbits * 3 / 2;
if( xbits >= nbits )
BUG();
x = mpi_alloc_secure( xbits/BITS_PER_MPI_LIMB );
if( DBG_CIPHER )
log_debug("choosing a random x ");
log_debug("choosing a random x of size %u", xbits );
rndbuf = NULL;
do {
if( DBG_CIPHER )
progress('.');
if( rndbuf ) { /* change only some of the higher bits */
if( nbits < 16 ) {/* should never happen ... */
if( xbits < 16 ) {/* should never happen ... */
g10_free(rndbuf);
rndbuf = gcry_random_bytes_secure( (nbits+7)/8,
rndbuf = gcry_random_bytes_secure( (xbits+7)/8,
GCRY_VERY_STRONG_RANDOM );
}
else {
@ -220,11 +286,11 @@ generate( ELG_secret_key *sk, unsigned nbits, MPI **ret_factors )
}
}
else {
rndbuf = gcry_random_bytes_secure( (nbits+7)/8,
rndbuf = gcry_random_bytes_secure( (xbits+7)/8,
GCRY_VERY_STRONG_RANDOM );
}
mpi_set_buffer( x, rndbuf, (nbits+7)/8, 0 );
mpi_clear_highbit( x, nbits+1 );
mpi_set_buffer( x, rndbuf, (xbits+7)/8, 0 );
mpi_clear_highbit( x, xbits+1 );
} while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) );
g10_free(rndbuf);
@ -311,7 +377,6 @@ decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey )
MPI t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) );
/* output = b/(a^x) mod p */
gcry_mpi_powm( t1, a, skey->x, skey->p );
mpi_invm( t1, t1, skey->p );
mpi_mulm( output, b, t1, skey->p );
@ -351,10 +416,6 @@ sign(MPI a, MPI b, MPI input, ELG_secret_key *skey )
gcry_mpi_powm( a, skey->g, k, skey->p );
mpi_mul(t, skey->x, a );
mpi_subm(t, input, t, p_1 );
while( mpi_is_neg(t) ) {
BUG(); /* That is nonsense code - left over from a very early test?*/
mpi_add(t, t, p_1);
}
mpi_invm(inv, k, p_1 );
mpi_mulm(b, t, inv, p_1 );
@ -557,7 +618,7 @@ elg_verify( int algo, MPI hash, MPI *data, MPI *pkey,
unsigned
unsigned int
elg_get_nbits( int algo, MPI *pkey )
{
if( !is_ELGAMAL(algo) )
@ -587,10 +648,10 @@ elg_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig,
*nsig = 2;
switch( algo ) {
case PUBKEY_ALGO_ELGAMAL:
case GCRY_PK_ELG:
*use = GCRY_PK_USAGE_SIGN|GCRY_PK_USAGE_ENCR;
return "ELG";
case PUBKEY_ALGO_ELGAMAL_E:
case GCRY_PK_ELG_E:
*use = GCRY_PK_USAGE_SIGN|GCRY_PK_USAGE_ENCR;
return "ELG-E";
default: *use = 0; return NULL;

View File

@ -562,6 +562,12 @@ gcry_md_ctl( GCRY_MD_HD hd, int cmd, byte *buffer, size_t buflen)
else if ( !(rc = prepare_macpads( hd, buffer, buflen )) )
gcry_md_reset( hd );
}
else if( cmd == GCRYCTL_START_DUMP ) {
md_start_debug( hd, buffer );
}
else if( cmd == GCRYCTL_STOP_DUMP ) {
md_stop_debug( hd );
}
else
rc = GCRYERR_INV_OP;
return set_lasterr( rc );
@ -834,7 +840,7 @@ gcry_md_algo_info( int algo, int what, void *buffer, size_t *nbytes)
void
static void
md_start_debug( GCRY_MD_HD md, const char *suffix )
{
static int idx=0;
@ -851,7 +857,7 @@ md_start_debug( GCRY_MD_HD md, const char *suffix )
log_debug("md debug: can't open %s\n", buf );
}
void
static void
md_stop_debug( GCRY_MD_HD md )
{
if( md->ctx->debug ) {

View File

@ -344,10 +344,10 @@ md5_get_info( int algo, size_t *contextsize,
*r_asnoid = asn;
*r_asnlen = DIM(asn);
*r_mdlen = 16;
*r_init = (void (*)(void *))md5_init;
*r_write = (void (*)(void *, byte*, size_t))md5_write;
*r_final = (void (*)(void *))md5_final;
*r_read = (byte *(*)(void *))md5_read;
*(void (**)(MD5_CONTEXT *))r_init = md5_init;
*(void (**)(MD5_CONTEXT *, byte*, size_t))r_write = md5_write;
*(void (**)(MD5_CONTEXT *))r_final = md5_final;
*(byte *(**)(MD5_CONTEXT *))r_read = md5_read;
return "MD5";
}

View File

@ -1,5 +1,5 @@
/* primegen.c - prime number generator
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -38,11 +38,24 @@ static int check_prime( MPI prime, MPI val_2 );
static int is_prime( MPI n, int steps, int *count );
static void m_out_of_n( char *array, int m, int n );
static void (*progress_cb) ( void *, int );
static void *progress_cb_data;
void
register_primegen_progress ( void (*cb)( void *, int), void *cb_data )
{
progress_cb = cb;
progress_cb_data = cb_data;
}
static void
progress( int c )
{
fputc( c, stderr );
if ( progress_cb )
progress_cb ( progress_cb_data, c );
else
fputc( c, stderr );
}
@ -117,8 +130,8 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
log_debug("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n",
pbits, req_qbits, qbits, fbits, n );
prime = mpi_alloc( (pbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB );
q = gen_prime( qbits, 0, 1 );
q_factor = mode==1? gen_prime( req_qbits, 0, 1 ) : NULL;
q = gen_prime( qbits, 0, 0 );
q_factor = mode==1? gen_prime( req_qbits, 0, 0 ) : NULL;
/* allocate an array to hold the factors + 2 for later usage */
factors = g10_xcalloc( n+2, sizeof *factors );
@ -177,7 +190,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
count1 = 0;
qbits++;
progress('>');
q = gen_prime( qbits, 0, 1 );
q = gen_prime( qbits, 0, 0 );
goto next_try;
}
}
@ -188,7 +201,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
count2 = 0;
qbits--;
progress('<');
q = gen_prime( qbits, 0, 1 );
q = gen_prime( qbits, 0, 0 );
goto next_try;
}
}

View File

@ -1,5 +1,5 @@
/* pubkey.c - pubkey dispatcher
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -30,6 +30,9 @@
#include "cipher.h"
#include "elgamal.h"
#include "dsa.h"
#if 0
#include "rsa.h"
#endif
#include "dynload.h"
/* FIXME: use set_lasterr() */
@ -193,6 +196,60 @@ setup_pubkey_table(void)
BUG();
i++;
#if 0
pubkey_table[i].algo = PUBKEY_ALGO_RSA;
pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo,
&pubkey_table[i].npkey,
&pubkey_table[i].nskey,
&pubkey_table[i].nenc,
&pubkey_table[i].nsig,
&pubkey_table[i].use );
pubkey_table[i].generate = rsa_generate;
pubkey_table[i].check_secret_key = rsa_check_secret_key;
pubkey_table[i].encrypt = rsa_encrypt;
pubkey_table[i].decrypt = rsa_decrypt;
pubkey_table[i].sign = rsa_sign;
pubkey_table[i].verify = rsa_verify;
pubkey_table[i].get_nbits = rsa_get_nbits;
if( !pubkey_table[i].name )
BUG();
i++;
pubkey_table[i].algo = PUBKEY_ALGO_RSA_E;
pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo,
&pubkey_table[i].npkey,
&pubkey_table[i].nskey,
&pubkey_table[i].nenc,
&pubkey_table[i].nsig,
&pubkey_table[i].use );
pubkey_table[i].generate = rsa_generate;
pubkey_table[i].check_secret_key = rsa_check_secret_key;
pubkey_table[i].encrypt = rsa_encrypt;
pubkey_table[i].decrypt = rsa_decrypt;
pubkey_table[i].sign = dummy_sign;
pubkey_table[i].verify = dummy_verify;
pubkey_table[i].get_nbits = rsa_get_nbits;
if( !pubkey_table[i].name )
BUG();
i++;
pubkey_table[i].algo = PUBKEY_ALGO_RSA_S;
pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo,
&pubkey_table[i].npkey,
&pubkey_table[i].nskey,
&pubkey_table[i].nenc,
&pubkey_table[i].nsig,
&pubkey_table[i].use );
pubkey_table[i].generate = rsa_generate;
pubkey_table[i].check_secret_key = rsa_check_secret_key;
pubkey_table[i].encrypt = dummy_encrypt;
pubkey_table[i].decrypt = dummy_decrypt;
pubkey_table[i].sign = rsa_sign;
pubkey_table[i].verify = rsa_verify;
pubkey_table[i].get_nbits = rsa_get_nbits;
if( !pubkey_table[i].name )
BUG();
i++;
#endif
for( ; i < TABLE_SIZE; i++ )
pubkey_table[i].name = NULL;
}

View File

@ -1,5 +1,5 @@
/* random.c - random number generator
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -36,15 +36,22 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef HAVE_GETHRTIME
#include <sys/times.h>
#endif
#ifdef HAVE_GETTIMEOFDAY
#include <sys/times.h>
#endif
#ifdef HAVE_CLOCK_GETTIME
#include <time.h>
#endif
#ifdef HAVE_GETRUSAGE
#include <sys/resource.h>
#endif
#ifdef __MINGW32__
#include <process.h>
#endif
#include "g10lib.h"
#include "rmd.h"
#include "random.h"
@ -89,6 +96,9 @@ static size_t pool_writepos;
static int pool_filled;
static int pool_balance;
static int just_mixed;
static int did_initial_extra_seeding;
static char *seed_file_name;
static int allow_seed_file_update;
static int secure_alloc;
static int quick_test;
@ -274,6 +284,139 @@ mix_pool(byte *pool)
}
}
void
set_random_seed_file( const char *name )
{
if( seed_file_name )
BUG();
seed_file_name = g10_xstrdup( name );
}
/****************
* Read in a seed form the random_seed file
* and return true if this was successful
*/
static int
read_seed_file()
{
int fd;
struct stat sb;
unsigned char buffer[POOLSIZE];
int n;
if( !seed_file_name )
return 0;
#ifdef HAVE_DOSISH_SYSTEM
fd = open( seed_file_name, O_RDONLY | O_BINARY );
#else
fd = open( seed_file_name, O_RDONLY );
#endif
if( fd == -1 && errno == ENOENT) {
allow_seed_file_update = 1;
return 0;
}
if( fd == -1 ) {
log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) );
return 0;
}
if( fstat( fd, &sb ) ) {
log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) );
close(fd);
return 0;
}
if( !S_ISREG(sb.st_mode) ) {
log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name );
close(fd);
return 0;
}
if( !sb.st_size ) {
log_info(_("note: random_seed file is empty\n") );
close(fd);
allow_seed_file_update = 1;
return 0;
}
if( sb.st_size != POOLSIZE ) {
log_info(_("warning: invalid size of random_seed file - not used\n") );
close(fd);
return 0;
}
do {
n = read( fd, buffer, POOLSIZE );
} while( n == -1 && errno == EINTR );
if( n != POOLSIZE ) {
log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) );
close(fd);
return 0;
}
close(fd);
add_randomness( buffer, POOLSIZE, 0 );
/* add some minor entropy to the pool now (this will also force a mixing) */
{ pid_t x = getpid();
add_randomness( &x, sizeof(x), 0 );
}
{ time_t x = time(NULL);
add_randomness( &x, sizeof(x), 0 );
}
{ clock_t x = clock();
add_randomness( &x, sizeof(x), 0 );
}
/* And read a few bytes from our entropy source. By using
* a level of 0 this will not block and might not return anything
* with some entropy drivers, however the rndlinux driver will use
* /dev/urandom and return some stuff - Do not read to much as we
* want to be friendly to the scare system entropy resource. */
read_random_source( 0, 16, 0 );
allow_seed_file_update = 1;
return 1;
}
void
update_random_seed_file()
{
ulong *sp, *dp;
int fd, i;
if( !seed_file_name || !is_initialized || !pool_filled )
return;
if( !allow_seed_file_update ) {
log_info(_("note: random_seed file not updated\n"));
return;
}
/* copy the entropy pool to a scratch pool and mix both of them */
for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
i < POOLWORDS; i++, dp++, sp++ ) {
*dp = *sp + ADD_VALUE;
}
mix_pool(rndpool); rndstats.mixrnd++;
mix_pool(keypool); rndstats.mixkey++;
#ifdef HAVE_DOSISH_SYSTEM
fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
S_IRUSR|S_IWUSR );
#else
fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
#endif
if( fd == -1 ) {
log_info(_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
return;
}
do {
i = write( fd, keypool, POOLSIZE );
} while( i == -1 && errno == EINTR );
if( i != POOLSIZE ) {
log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno) );
}
if( close(fd) )
log_info(_("can't close `%s': %s\n"), seed_file_name, strerror(errno) );
}
static void
read_pool( byte *buffer, size_t length, int level )
@ -281,8 +424,31 @@ read_pool( byte *buffer, size_t length, int level )
int i;
ulong *sp, *dp;
if( length >= POOLSIZE )
BUG(); /* not allowed */
if( length >= POOLSIZE ) {
log_fatal(_("too many random bits requested; the limit is %d\n"),
POOLSIZE*8-1 );
}
if( !pool_filled ) {
if( read_seed_file() )
pool_filled = 1;
}
/* For level 2 quality (key generation) we alwas make
* sure that the pool has been seeded enough initially */
if( level == 2 && !did_initial_extra_seeding ) {
size_t needed;
pool_balance = 0;
needed = length - pool_balance;
if( needed < POOLSIZE/2 )
needed = POOLSIZE/2;
else if( needed > POOLSIZE )
BUG();
read_random_source( 3, needed, 2 );
pool_balance += needed;
did_initial_extra_seeding=1;
}
/* for level 2 make sure that there is enough random in the pool */
if( level == 2 && pool_balance < length ) {
@ -347,6 +513,12 @@ read_pool( byte *buffer, size_t length, int level )
/****************
* Add LENGTH bytes of randomness from buffer to the pool.
* source may be used to specify the randomness source.
* Source is:
* 0 - used ony for initialization
* 1 - fast random poll function
* 2 - normal poll function
* 3 - used when level 2 random quality has been requested
* to do an extra pool seed.
*/
static void
add_randomness( const void *buffer, size_t length, int source )
@ -410,6 +582,13 @@ fast_random_poll()
add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 );
}
#elif HAVE_CLOCK_GETTIME
{ struct timespec tv;
if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 )
BUG();
add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 );
}
#else /* use times */
#ifndef HAVE_DOSISH_SYSTEM
{ struct tms buf;
@ -419,13 +598,28 @@ fast_random_poll()
#endif
#endif
#ifdef HAVE_GETRUSAGE
#ifndef RUSAGE_SELF
#ifdef __GCC__
#warning There is no RUSAGE_SELF on this system
#endif
#else
{ struct rusage buf;
if( getrusage( RUSAGE_SELF, &buf ) )
BUG();
add_randomness( &buf, sizeof buf, 1 );
memset( &buf, 0, sizeof buf );
}
#endif
#endif
/* time and clock are availabe on all systems - so
* we better do it just in case one of the above functions
* didn't work */
{ time_t x = time(NULL);
add_randomness( &x, sizeof(x), 1 );
}
{ clock_t x = clock();
add_randomness( &x, sizeof(x), 1 );
}
}
@ -472,9 +666,9 @@ gather_faked( void (*add)(const void*, size_t, int), int requester,
#endif
initialized=1;
#ifdef HAVE_RAND
srand( time(NULL) * getpid());
srand(make_timestamp()*getpid());
#else
srandom( time(NULL) * getpid());
srandom(make_timestamp()*getpid());
#endif
}

View File

@ -562,10 +562,10 @@ rmd160_get_info( int algo, size_t *contextsize,
*r_asnoid = asn;
*r_asnlen = DIM(asn);
*r_mdlen = 20;
*r_init = (void (*)(void *))rmd160_init;
*r_write = (void (*)(void *, byte*, size_t))rmd160_write;
*r_final = (void (*)(void *))rmd160_final;
*r_read = (byte *(*)(void *))rmd160_read;
*(void (**)(RMD160_CONTEXT *))r_init = rmd160_init;
*(void (**)(RMD160_CONTEXT *, byte*, size_t))r_write = rmd160_write;
*(void (**)(RMD160_CONTEXT *))r_final = rmd160_final;
*(byte *(**)(RMD160_CONTEXT *))r_read = rmd160_read;
return "RIPEMD160";
}

View File

@ -1,5 +1,5 @@
/* rndegd.c - interface to the EGD
* Copyright (C) 1999 Free Software Foundation, Inc.
* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -117,9 +117,13 @@ do_read( int fd, void *buf, size_t nbytes )
/* Note: we always use the highest level.
/****************
* Note: we always use the highest level.
* TO boost the performance we may want to add some
* additional code for level 1
*
* Using a level of 0 should never block and better add nothing
* to the pool. So this is just a dummy for EGD.
*/
static int
gather_random( void (*add)(const void*, size_t, int), int requester,
@ -133,7 +137,8 @@ gather_random( void (*add)(const void*, size_t, int), int requester,
if( !length )
return 0;
if( !level )
return 0;
restart:
if( do_restart ) {

View File

@ -77,7 +77,7 @@
#ifndef __QNX__
#include <sys/resource.h>
#endif /* __QNX__ */
#ifdef _AIX
#if defined( _AIX ) || defined( __QNX__ )
#include <sys/select.h>
#endif /* _AIX */
#ifndef __QNX__
@ -91,6 +91,10 @@
#endif /* __hpux 9.x, after that it's in unistd.h */
#include <sys/wait.h>
/* #include <kitchensink.h> */
#ifdef __QNX__
#include <signal.h>
#include <process.h>
#endif /* __QNX__ */
#include <errno.h>
#include "types.h" /* for byte and u32 typedefs */
@ -100,7 +104,13 @@
#include "g10lib.h"
#ifndef EAGAIN
#define EAGAIN EWOULDBLOCK
#define EAGAIN EWOULDBLOCK
#endif
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#define GATHER_BUFSIZE 49152 /* Usually about 25K are filled */
@ -306,6 +316,32 @@ typedef struct {
char data[500]; /* gathered data */
} GATHER_MSG;
#ifndef HAVE_WAITPID
pid_t
waitpid(pid_t pid, int *statptr, int options)
{
#ifdef HAVE_WAIT4
return wait4(pid, statptr, options, NULL);
#else
/* If wait4 is also not available, try wait3 for SVR3 variants */
/* Less ideal because can't actually request a specific pid */
/* For that reason, first check to see if pid is for an */
/* existing process. */
int tmp_pid, dummystat;;
if (kill(pid, 0) == -1) {
errno = ECHILD;
return -1;
}
if (statptr == NULL)
statptr = &dummystat;
while (((tmp_pid = wait3(statptr, options, 0)) != pid) &&
(tmp_pid != -1) && (tmp_pid != 0) && (pid != -1))
;
return tmp_pid;
#endif
}
#endif
/* Under SunOS popen() doesn't record the pid of the child process. When
* pclose() is called, instead of calling waitpid() for the correct child, it
* calls wait() repeatedly until the right child is reaped. The problem is
@ -376,7 +412,9 @@ my_popen(struct RI *entry)
* close on exec, so new children won't see it */
close(pipedes[STDOUT_FILENO]);
#ifdef FD_CLOEXEC
fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
#endif
stream = fdopen(pipedes[STDIN_FILENO], "r");
@ -616,6 +654,7 @@ start_gatherer( int pipefd )
}
/* close all files but the ones we need */
{ int nmax, n1, n2, i;
#ifdef _SC_OPEN_MAX
if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) {
#ifdef _POSIX_OPEN_MAX
nmax = _POSIX_OPEN_MAX;
@ -623,6 +662,9 @@ start_gatherer( int pipefd )
nmax = 20; /* assume a reasonable value */
#endif
}
#else
nmax = 20; /* assume a reasonable value */
#endif
n1 = fileno( stderr );
n2 = dbgfp? fileno( dbgfp ) : -1;
for(i=0; i < nmax; i++ ) {
@ -718,6 +760,10 @@ read_a_msg( int fd, GATHER_MSG *msg )
}
/****************
* Using a level of 0 should never block and better add nothing
* to the pool. So this is just a dummy for this gatherer.
*/
static int
gather_random( void (*add)(const void*, size_t, int), int requester,
size_t length, int level )
@ -727,6 +773,9 @@ gather_random( void (*add)(const void*, size_t, int), int requester,
GATHER_MSG msg;
size_t n;
if( !level )
return 0;
if( !gatherer_pid ) {
/* make sure we are not setuid */
if( getuid() != geteuid() )

View File

@ -1,5 +1,6 @@
/* rndw32.c - interface to the Winseed DLL
* Copyright (C) 1999 Free Software Foundation, Inc.
/* rndw32.c - W32 entropy gatherer
* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
* Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-1999
*
* This file is part of GnuPG.
*
@ -16,6 +17,46 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
*************************************************************************
* The code here is based on code from Cryptlib 3.0 beta by Peter Gutmann.
* Source file misc/rndwin32.c "Win32 Randomness-Gathering Code" with this
* copyright notice:
*
* This module is part of the cryptlib continuously seeded pseudorandom
* number generator. For usage conditions, see lib_rand.c
*
* [Here is the notice from lib_rand.c, which is now called dev_sys.c]
*
* This module and the misc/rnd*.c modules represent the cryptlib
* continuously seeded pseudorandom number generator (CSPRNG) as described in
* my 1998 Usenix Security Symposium paper "The generation of random numbers
* for cryptographic purposes".
*
* The CSPRNG code is copyright Peter Gutmann (and various others) 1996,
* 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG
* modules and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice
* and this permission notice in its entirety.
*
* 2. Redistributions in binary form must reproduce the copyright notice in
* the documentation and/or other materials provided with the distribution.
*
* 3. A copy of any bugfixes or enhancements made must be provided to the
* author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the
* baseline version of the code.
*
* ALTERNATIVELY, the code may be distributed under the terms of the GNU
* General Public License, version 2 or any later version published by the
* Free Software Foundation, in which case the provisions of the GNU GPL are
* required INSTEAD OF the above restrictions.
*
* Although not required under the terms of the GPL, it would still be nice if
* you could make any changes available to the author to allow a consistent
* code base to be maintained
*************************************************************************
*/
#include <config.h>
@ -27,10 +68,16 @@
#include <windows.h>
#include "types.h"
#include "g10lib.h"
#include "dynload.h"
/* We do not use the netropy DLL anymore because a standalone program is
* easier to maintain and */
/*#define USE_ENTROPY_DLL*/
#ifdef IS_MODULE
#define _(a) (a)
@ -39,6 +86,10 @@
#endif
static int debug_me;
#ifdef USE_ENTROPY_DLL
#define WIN32_SLOW_SEEDER 0
#define WIN32_FAST_SEEDER 1
@ -53,6 +104,17 @@
#define PCP_DLL_FUNC 8
#define PCP_UNKNOWN_SEEDER_TYPE 9
/****************
* We sometimes get a SEEDER_TOO_SMALL error, in which case we increment
* the internal buffer by SEEDER_INC_CHUNK until we reach MAX_SEEDER_SIZE
* MAX_SEEDER_SIZE is used as an arbitrary limit to protect against
* bugs in Winseed.
*/
#define MAX_SEEDER_SIZE 500000
#define SEEDER_INC_CHUNK 50000
typedef void *WIN32_SEEDER;
static WIN32_SEEDER (WINAPI *create_instance)( byte type, unsigned int *reason);
@ -68,8 +130,6 @@ static WIN32_SEEDER slow_seeder, fast_seeder;
static byte *entropy_buffer;
static size_t entropy_buffer_size;
static char *entropy_dll;
/****************
* Load and initialize the winseed DLL
* NOTE: winseed is not part of the GnuPG distribution. It should be available
@ -80,11 +140,17 @@ static char *entropy_dll;
static void
load_and_init_winseed( void )
{
int hInstance;
HANDLE hInstance;
void *addr;
unsigned int reason = 0;
unsigned int n1, n2;
const char *dllname = entropy_dll? entropy_dll : "c:/gnupg/entropy.dll";
const char *dllname;
dllname = read_w32_registry_string( "HKEY_LOCAL_MACHINE",
"Software\\GNU\\GnuPG",
"EntropyDLL" );
if( !dllname )
dllname = "c:/gnupg/entropy.dll";
hInstance = LoadLibrary( dllname );
if( !hInstance )
@ -119,15 +185,14 @@ load_and_init_winseed( void )
g10_log_fatal("error creating winseed fast seeder: rc=%u\n", reason );
goto failure;
}
g10_log_info("slow and fast seeders created.\n");
n1 = get_internal_seed_size( slow_seeder );
g10_log_info("slow buffer size=%u\n", n1);
/*g10_log_info("slow buffer size=%u\n", n1);*/
n2 = get_internal_seed_size( fast_seeder );
g10_log_info("fast buffer size=%u\n", n2);
/*g10_log_info("fast buffer size=%u\n", n2);*/
entropy_buffer_size = n1 > n2? n1: n2;
entropy_buffer = g10_xmalloc( entropy_buffer_size );
g10_log_info("using a buffer of size=%u\n", entropy_buffer_size );
entropy_buffer = m_alloc( entropy_buffer_size );
/*g10_log_info("using a buffer of size=%u\n", entropy_buffer_size );*/
return;
@ -150,13 +215,16 @@ gather_random( void (*add)(const void*, size_t, int), int requester,
unsigned int result;
unsigned int nbytes;
if( !level )
return 0;
if( !slow_seeder )
load_and_init_winseed();
/* Our estimation on how much entropy we should use is very vague.
* Winseed delivers some amount of entropy on each slow poll and
* we add it to our random pool. Depending on the required quality
* level we adjust the requested length so that for higer quality
* level we adjust the requested length so that for higher quality
* we make sure to add more entropy to our pool. However, as we don't
* like to waste any entropy collected by winseed, we always add
* at least everything we got from winseed.
@ -169,17 +237,35 @@ gather_random( void (*add)(const void*, size_t, int), int requester,
for(;;) {
nbytes = entropy_buffer_size;
result = get_seed( slow_seeder, entropy_buffer, &nbytes);
if( result == PCP_SEEDER_TOO_SMALL ) {
unsigned int n1 = get_internal_seed_size( slow_seeder );
if( n1 > MAX_SEEDER_SIZE ) {
g10_log_fatal("rndw32: internal seeder problem (size=%u)\n",
n1);
return -1; /* actually never reached */
}
n1 += SEEDER_INC_CHUNK;
set_internal_seed_size( slow_seeder, n1 );
if( n1 > entropy_buffer_size ) {
entropy_buffer_size = n1;
entropy_buffer = m_realloc( entropy_buffer,
entropy_buffer_size );
}
continue;
}
if( result ) {
g10_log_fatal("rndw32: get_seed(slow) failed: rc=%u\n", result);
return -1; /* actually never reached */
}
g10_log_info("rndw32: slow poll level %d, need %u, got %u\n",
level, (unsigned int)length, (unsigned int)nbytes );
/*g10_log_info("rndw32: slow poll level %d, need %u, got %u\n",
level, (unsigned int)length, (unsigned int)nbytes );*/
(*add)( entropy_buffer, nbytes, requester );
if( length <= nbytes )
return 0; /* okay */
length -= nbytes;
g10_log_info("rndw32: need more\n");
}
}
@ -206,6 +292,619 @@ gather_random_fast( void (*add)(const void*, size_t, int), int requester )
return 0;
}
#else /* !USE_ENTROPY_DLL */
/* This is the new code which does not require the entropy.dll */
/*
* Definitions which are missing from the current GNU Windows32Api
*/
#define TH32CS_SNAPHEAPLIST 1
#define TH32CS_SNAPPROCESS 2
#define TH32CS_SNAPTHREAD 4
#define TH32CS_SNAPMODULE 8
#define TH32CS_SNAPALL (1|2|4|8)
#define TH32CS_INHERIT 0x80000000
#define IOCTL_DISK_PERFORMANCE 0x00070020
#define VER_PLATFORM_WIN32_WINDOWS 1
typedef struct {
DWORD dwSize;
DWORD th32ProcessID;
DWORD th32HeapID;
DWORD dwFlags;
} HEAPLIST32;
typedef struct {
DWORD dwSize;
HANDLE hHandle;
DWORD dwAddress;
DWORD dwBlockSize;
DWORD dwFlags;
DWORD dwLockCount;
DWORD dwResvd;
DWORD th32ProcessID;
DWORD th32HeapID;
} HEAPENTRY32;
typedef struct {
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID;
DWORD th32DefaultHeapID;
DWORD th32ModuleID;
DWORD cntThreads;
DWORD th32ParentProcessID;
LONG pcPriClassBase;
DWORD dwFlags;
char szExeFile[260];
} PROCESSENTRY32;
typedef struct {
DWORD dwSize;
DWORD cntUsage;
DWORD th32ThreadID;
DWORD th32OwnerProcessID;
LONG tpBasePri;
LONG tpDeltaPri;
DWORD dwFlags;
} THREADENTRY32;
typedef struct {
DWORD dwSize;
DWORD th32ModuleID;
DWORD th32ProcessID;
DWORD GlblcntUsage;
DWORD ProccntUsage;
BYTE *modBaseAddr;
DWORD modBaseSize;
HMODULE hModule;
char szModule[256];
char szExePath[260];
} MODULEENTRY32;
/* Type definitions for function pointers to call Toolhelp32 functions
* used with the windows95 gatherer */
typedef BOOL (WINAPI * MODULEWALK) (HANDLE hSnapshot, MODULEENTRY32 *lpme);
typedef BOOL (WINAPI * THREADWALK) (HANDLE hSnapshot, THREADENTRY32 *lpte);
typedef BOOL (WINAPI * PROCESSWALK) (HANDLE hSnapshot, PROCESSENTRY32 *lppe);
typedef BOOL (WINAPI * HEAPLISTWALK) (HANDLE hSnapshot, HEAPLIST32 *lphl);
typedef BOOL (WINAPI * HEAPFIRST) (HEAPENTRY32 *lphe, DWORD th32ProcessID,
DWORD th32HeapID);
typedef BOOL (WINAPI * HEAPNEXT) (HEAPENTRY32 *lphe);
typedef HANDLE (WINAPI * CREATESNAPSHOT) (DWORD dwFlags, DWORD th32ProcessID);
/* Type definitions for function pointers to call NetAPI32 functions */
typedef DWORD (WINAPI * NETSTATISTICSGET) (LPWSTR szServer, LPWSTR szService,
DWORD dwLevel, DWORD dwOptions,
LPBYTE * lpBuffer);
typedef DWORD (WINAPI * NETAPIBUFFERSIZE) (LPVOID lpBuffer, LPDWORD cbBuffer);
typedef DWORD (WINAPI * NETAPIBUFFERFREE) (LPVOID lpBuffer);
/* When we query the performance counters, we allocate an initial buffer and
* then reallocate it as required until RegQueryValueEx() stops returning
* ERROR_MORE_DATA. The following values define the initial buffer size and
* step size by which the buffer is increased
*/
#define PERFORMANCE_BUFFER_SIZE 65536 /* Start at 64K */
#define PERFORMANCE_BUFFER_STEP 16384 /* Step by 16K */
static void
slow_gatherer_windows95( void (*add)(const void*, size_t, int), int requester )
{
static CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL;
static MODULEWALK pModule32First = NULL;
static MODULEWALK pModule32Next = NULL;
static PROCESSWALK pProcess32First = NULL;
static PROCESSWALK pProcess32Next = NULL;
static THREADWALK pThread32First = NULL;
static THREADWALK pThread32Next = NULL;
static HEAPLISTWALK pHeap32ListFirst = NULL;
static HEAPLISTWALK pHeap32ListNext = NULL;
static HEAPFIRST pHeap32First = NULL;
static HEAPNEXT pHeap32Next = NULL;
HANDLE hSnapshot;
/* initialize the Toolhelp32 function pointers */
if ( !pCreateToolhelp32Snapshot ) {
HANDLE hKernel;
if ( debug_me )
log_debug ("rndw32#slow_gatherer_95: init toolkit\n" );
/* Obtain the module handle of the kernel to retrieve the addresses
* of the Toolhelp32 functions */
if ( ( !(hKernel = GetModuleHandle ("KERNEL32.DLL"))) ) {
g10_log_fatal ( "rndw32: can't get module handle\n" );
}
/* Now get pointers to the functions */
pCreateToolhelp32Snapshot = (CREATESNAPSHOT) GetProcAddress (hKernel,
"CreateToolhelp32Snapshot");
pModule32First = (MODULEWALK) GetProcAddress (hKernel, "Module32First");
pModule32Next = (MODULEWALK) GetProcAddress (hKernel, "Module32Next");
pProcess32First = (PROCESSWALK) GetProcAddress (hKernel,
"Process32First");
pProcess32Next = (PROCESSWALK) GetProcAddress (hKernel,
"Process32Next");
pThread32First = (THREADWALK) GetProcAddress (hKernel, "Thread32First");
pThread32Next = (THREADWALK) GetProcAddress (hKernel, "Thread32Next");
pHeap32ListFirst = (HEAPLISTWALK) GetProcAddress (hKernel,
"Heap32ListFirst");
pHeap32ListNext = (HEAPLISTWALK) GetProcAddress (hKernel,
"Heap32ListNext");
pHeap32First = (HEAPFIRST) GetProcAddress (hKernel, "Heap32First");
pHeap32Next = (HEAPNEXT) GetProcAddress (hKernel, "Heap32Next");
if ( !pCreateToolhelp32Snapshot
|| !pModule32First || !pModule32Next
|| !pProcess32First || !pProcess32Next
|| !pThread32First || !pThread32Next
|| !pHeap32ListFirst || !pHeap32ListNext
|| !pHeap32First || !pHeap32Next ) {
g10_log_fatal ( "rndw32: failed to get a toolhep function\n" );
}
}
/* Take a snapshot of everything we can get to which is currently
* in the system */
if ( !(hSnapshot = pCreateToolhelp32Snapshot (TH32CS_SNAPALL, 0)) ) {
g10_log_fatal ( "rndw32: failed to take a toolhelp snapshot\n" );
}
/* Walk through the local heap */
{ HEAPLIST32 hl32;
hl32.dwSize = sizeof (HEAPLIST32);
if (pHeap32ListFirst (hSnapshot, &hl32)) {
if ( debug_me )
log_debug ("rndw32#slow_gatherer_95: walk heap\n" );
do {
HEAPENTRY32 he32;
/* First add the information from the basic Heaplist32 struct */
(*add) ( &hl32, sizeof (hl32), requester );
/* Now walk through the heap blocks getting information
* on each of them */
he32.dwSize = sizeof (HEAPENTRY32);
if (pHeap32First (&he32, hl32.th32ProcessID, hl32.th32HeapID)){
do {
(*add) ( &he32, sizeof (he32), requester );
} while (pHeap32Next (&he32));
}
} while (pHeap32ListNext (hSnapshot, &hl32));
}
}
/* Walk through all processes */
{ PROCESSENTRY32 pe32;
pe32.dwSize = sizeof (PROCESSENTRY32);
if (pProcess32First (hSnapshot, &pe32)) {
if ( debug_me )
log_debug ("rndw32#slow_gatherer_95: walk processes\n" );
do {
(*add) ( &pe32, sizeof (pe32), requester );
} while (pProcess32Next (hSnapshot, &pe32));
}
}
/* Walk through all threads */
{ THREADENTRY32 te32;
te32.dwSize = sizeof (THREADENTRY32);
if (pThread32First (hSnapshot, &te32)) {
if ( debug_me )
log_debug ("rndw32#slow_gatherer_95: walk threads\n" );
do {
(*add) ( &te32, sizeof (te32), requester );
} while (pThread32Next (hSnapshot, &te32));
}
}
/* Walk through all modules associated with the process */
{ MODULEENTRY32 me32;
me32.dwSize = sizeof (MODULEENTRY32);
if (pModule32First (hSnapshot, &me32)) {
if ( debug_me )
log_debug ("rndw32#slow_gatherer_95: walk modules\n" );
do {
(*add) ( &me32, sizeof (me32), requester );
} while (pModule32Next (hSnapshot, &me32));
}
}
CloseHandle (hSnapshot);
}
static void
slow_gatherer_windowsNT( void (*add)(const void*, size_t, int), int requester )
{
static int is_initialized = 0;
static NETSTATISTICSGET pNetStatisticsGet = NULL;
static NETAPIBUFFERSIZE pNetApiBufferSize = NULL;
static NETAPIBUFFERFREE pNetApiBufferFree = NULL;
static int is_workstation = 1;
static int cbPerfData = PERFORMANCE_BUFFER_SIZE;
PERF_DATA_BLOCK *pPerfData;
HANDLE hDevice, hNetAPI32 = NULL;
DWORD dwSize, status;
int nDrive;
if ( !is_initialized ) {
HKEY hKey;
if ( debug_me )
log_debug ("rndw32#slow_gatherer_nt: init toolkit\n" );
/* Find out whether this is an NT server or workstation if necessary */
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
BYTE szValue[32];
dwSize = sizeof (szValue);
if ( debug_me )
log_debug ("rndw32#slow_gatherer_nt: check product options\n" );
status = RegQueryValueEx (hKey, "ProductType", 0, NULL,
szValue, &dwSize);
if (status == ERROR_SUCCESS && stricmp (szValue, "WinNT")) {
/* Note: There are (at least) three cases for ProductType:
* WinNT = NT Workstation, ServerNT = NT Server, LanmanNT =
* NT Server acting as a Domain Controller */
is_workstation = 0;
if ( debug_me )
log_debug ("rndw32: this is a NT server\n");
}
RegCloseKey (hKey);
}
/* Initialize the NetAPI32 function pointers if necessary */
if ( (hNetAPI32 = LoadLibrary ("NETAPI32.DLL")) ) {
if ( debug_me )
log_debug ("rndw32#slow_gatherer_nt: netapi32 loaded\n" );
pNetStatisticsGet = (NETSTATISTICSGET) GetProcAddress (hNetAPI32,
"NetStatisticsGet");
pNetApiBufferSize = (NETAPIBUFFERSIZE) GetProcAddress (hNetAPI32,
"NetApiBufferSize");
pNetApiBufferFree = (NETAPIBUFFERFREE) GetProcAddress (hNetAPI32,
"NetApiBufferFree");
if ( !pNetStatisticsGet
|| !pNetApiBufferSize || !pNetApiBufferFree ) {
FreeLibrary (hNetAPI32);
hNetAPI32 = NULL;
g10_log_debug ("rndw32: No NETAPI found\n" );
}
}
is_initialized = 1;
}
/* Get network statistics. Note: Both NT Workstation and NT Server by
* default will be running both the workstation and server services. The
* heuristic below is probably useful though on the assumption that the
* majority of the network traffic will be via the appropriate service.
* In any case the network statistics return almost no randomness */
{ LPBYTE lpBuffer;
if (hNetAPI32 && !pNetStatisticsGet (NULL,
is_workstation ? L"LanmanWorkstation" :
L"LanmanServer", 0, 0, &lpBuffer) ) {
if ( debug_me )
log_debug ("rndw32#slow_gatherer_nt: get netstats\n" );
pNetApiBufferSize (lpBuffer, &dwSize);
(*add) ( lpBuffer, dwSize,requester );
pNetApiBufferFree (lpBuffer);
}
}
/* Get disk I/O statistics for all the hard drives */
for (nDrive = 0;; nDrive++) {
DISK_PERFORMANCE diskPerformance;
char szDevice[50];
/* Check whether we can access this device */
sprintf (szDevice, "\\\\.\\PhysicalDrive%d", nDrive);
hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
break;
/* Note: This only works if you have turned on the disk performance
* counters with 'diskperf -y'. These counters are off by default */
if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
&diskPerformance, sizeof (DISK_PERFORMANCE),
&dwSize, NULL))
{
if ( debug_me )
log_debug ("rndw32#slow_gatherer_nt: iostats drive %d\n",
nDrive );
(*add) ( &diskPerformance, dwSize, requester );
}
else {
log_info ("NOTE: you should run 'diskperf -y' "
"to enable the disk statistics\n");
}
CloseHandle (hDevice);
}
#if 0 /* we don't need this in GnuPG */
/* Wait for any async keyset driver binding to complete. You may be
* wondering what this call is doing here... the reason it's necessary is
* because RegQueryValueEx() will hang indefinitely if the async driver
* bind is in progress. The problem occurs in the dynamic loading and
* linking of driver DLL's, which work as follows:
*
* hDriver = LoadLibrary( DRIVERNAME );
* pFunction1 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC1 );
* pFunction2 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC2 );
*
* If RegQueryValueEx() is called while the GetProcAddress()'s are in
* progress, it will hang indefinitely. This is probably due to some
* synchronisation problem in the NT kernel where the GetProcAddress()
* calls affect something like a module reference count or function
* reference count while RegQueryValueEx() is trying to take a snapshot
* of the statistics, which include the reference counts. Because of
* this, we have to wait until any async driver bind has completed
* before we can call RegQueryValueEx() */
waitSemaphore (SEMAPHORE_DRIVERBIND);
#endif
/* Get information from the system performance counters. This can take
* a few seconds to do. In some environments the call to
* RegQueryValueEx() can produce an access violation at some random time
* in the future, adding a short delay after the following code block
* makes the problem go away. This problem is extremely difficult to
* reproduce, I haven't been able to get it to occur despite running it
* on a number of machines. The best explanation for the problem is that
* on the machine where it did occur, it was caused by an external driver
* or other program which adds its own values under the
* HKEY_PERFORMANCE_DATA key. The NT kernel calls the required external
* modules to map in the data, if there's a synchronisation problem the
* external module would write its data at an inappropriate moment,
* causing the access violation. A low-level memory checker indicated
* that ExpandEnvironmentStrings() in KERNEL32.DLL, called an
* interminable number of calls down inside RegQueryValueEx(), was
* overwriting memory (it wrote twice the allocated size of a buffer to a
* buffer allocated by the NT kernel). This may be what's causing the
* problem, but since it's in the kernel there isn't much which can be
* done.
*
* In addition to these problems the code in RegQueryValueEx() which
* estimates the amount of memory required to return the performance
* counter information isn't very accurate, since it always returns a
* worst-case estimate which is usually nowhere near the actual amount
* required. For example it may report that 128K of memory is required,
* but only return 64K of data */
{ pPerfData = m_alloc (cbPerfData);
for (;;) {
dwSize = cbPerfData;
if ( debug_me )
log_debug ("rndw32#slow_gatherer_nt: get perf data\n" );
status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL,
NULL, (LPBYTE) pPerfData, &dwSize);
if (status == ERROR_SUCCESS) {
if (!memcmp (pPerfData->Signature, L"PERF", 8)) {
(*add) ( pPerfData, dwSize, requester );
}
else
g10_log_debug ( "rndw32: no PERF signature\n");
break;
}
else if (status == ERROR_MORE_DATA) {
cbPerfData += PERFORMANCE_BUFFER_STEP;
pPerfData = m_realloc (pPerfData, cbPerfData);
}
else {
g10_log_debug ( "rndw32: get performance data problem\n");
break;
}
}
m_free (pPerfData);
}
/* Although this isn't documented in the Win32 API docs, it's necessary
to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's
implicitly opened on the first call to RegQueryValueEx()). If this
isn't done then any system components which provide performance data
can't be removed or changed while the handle remains active */
RegCloseKey (HKEY_PERFORMANCE_DATA);
}
static int
gather_random( void (*add)(const void*, size_t, int), int requester,
size_t length, int level )
{
static int is_initialized;
static int is_windows95;
if( !level )
return 0;
/* We don't differentiate between level 1 and 2 here because
* there is no nternal entropy pool as a scary resource. It may
* all work slower, but because our entropy source will never
* block but deliver some not easy to measure entropy, we assume level 2
*/
if ( !is_initialized ) {
OSVERSIONINFO osvi = { sizeof( osvi ) };
DWORD platform;
GetVersionEx( &osvi );
platform = osvi.dwPlatformId;
is_windows95 = platform == VER_PLATFORM_WIN32_WINDOWS;
if ( platform == VER_PLATFORM_WIN32s ) {
g10_log_fatal("can't run on a W32s platform\n" );
}
is_initialized = 1;
if ( debug_me )
log_debug ("rndw32#gather_random: platform=%d\n", (int)platform );
}
if ( debug_me )
log_debug ("rndw32#gather_random: req=%d len=%u lvl=%d\n",
requester, (unsigned int)length, level );
if (is_windows95 ) {
slow_gatherer_windows95( add, requester );
}
else {
slow_gatherer_windowsNT( add, requester );
}
return 0;
}
static int
gather_random_fast( void (*add)(const void*, size_t, int), int requester )
{
static int addedFixedItems = 0;
if ( debug_me )
log_debug ("rndw32#gather_random_fast: req=%d\n", requester );
/* Get various basic pieces of system information: Handle of active
* window, handle of window with mouse capture, handle of clipboard owner
* handle of start of clpboard viewer list, pseudohandle of current
* process, current process ID, pseudohandle of current thread, current
* thread ID, handle of desktop window, handle of window with keyboard
* focus, whether system queue has any events, cursor position for last
* message, 1 ms time for last message, handle of window with clipboard
* open, handle of process heap, handle of procs window station, types of
* events in input queue, and milliseconds since Windows was started */
{ byte buffer[20*sizeof(ulong)], *bufptr;
bufptr = buffer;
#define ADD(f) do { ulong along = (ulong)(f); \
memcpy (bufptr, &along, sizeof (along) ); \
bufptr += sizeof (along); } while (0)
ADD ( GetActiveWindow ());
ADD ( GetCapture ());
ADD ( GetClipboardOwner ());
ADD ( GetClipboardViewer ());
ADD ( GetCurrentProcess ());
ADD ( GetCurrentProcessId ());
ADD ( GetCurrentThread ());
ADD ( GetCurrentThreadId ());
ADD ( GetDesktopWindow ());
ADD ( GetFocus ());
ADD ( GetInputState ());
ADD ( GetMessagePos ());
ADD ( GetMessageTime ());
ADD ( GetOpenClipboardWindow ());
ADD ( GetProcessHeap ());
ADD ( GetProcessWindowStation ());
ADD ( GetQueueStatus (QS_ALLEVENTS));
ADD ( GetTickCount ());
assert ( bufptr-buffer < sizeof (buffer) );
(*add) ( buffer, bufptr-buffer, requester );
#undef ADD
}
/* Get multiword system information: Current caret position, current
* mouse cursor position */
{ POINT point;
GetCaretPos (&point);
(*add) ( &point, sizeof (point), requester );
GetCursorPos (&point);
(*add) ( &point, sizeof (point), requester );
}
/* Get percent of memory in use, bytes of physical memory, bytes of free
* physical memory, bytes in paging file, free bytes in paging file, user
* bytes of address space, and free user bytes */
{ MEMORYSTATUS memoryStatus;
memoryStatus.dwLength = sizeof (MEMORYSTATUS);
GlobalMemoryStatus (&memoryStatus);
(*add) ( &memoryStatus, sizeof (memoryStatus), requester );
}
/* Get thread and process creation time, exit time, time in kernel mode,
and time in user mode in 100ns intervals */
{ HANDLE handle;
FILETIME creationTime, exitTime, kernelTime, userTime;
DWORD minimumWorkingSetSize, maximumWorkingSetSize;
handle = GetCurrentThread ();
GetThreadTimes (handle, &creationTime, &exitTime,
&kernelTime, &userTime);
(*add) ( &creationTime, sizeof (creationTime), requester );
(*add) ( &exitTime, sizeof (exitTime), requester );
(*add) ( &kernelTime, sizeof (kernelTime), requester );
(*add) ( &userTime, sizeof (userTime), requester );
handle = GetCurrentProcess ();
GetProcessTimes (handle, &creationTime, &exitTime,
&kernelTime, &userTime);
(*add) ( &creationTime, sizeof (creationTime), requester );
(*add) ( &exitTime, sizeof (exitTime), requester );
(*add) ( &kernelTime, sizeof (kernelTime), requester );
(*add) ( &userTime, sizeof (userTime), requester );
/* Get the minimum and maximum working set size for the current process */
GetProcessWorkingSetSize (handle, &minimumWorkingSetSize,
&maximumWorkingSetSize);
(*add) ( &minimumWorkingSetSize,
sizeof (&minimumWorkingSetSize), requester );
(*add) ( &maximumWorkingSetSize,
sizeof (&maximumWorkingSetSize), requester );
}
/* The following are fixed for the lifetime of the process so we only
* add them once */
if (!addedFixedItems) {
STARTUPINFO startupInfo;
/* Get name of desktop, console window title, new window position and
* size, window flags, and handles for stdin, stdout, and stderr */
startupInfo.cb = sizeof (STARTUPINFO);
GetStartupInfo (&startupInfo);
(*add) ( &startupInfo, sizeof (STARTUPINFO), requester );
addedFixedItems = 1;
}
/* The performance of QPC varies depending on the architecture it's
* running on and on the OS. Under NT it reads the CPU's 64-bit timestamp
* counter (at least on a Pentium and newer '486's, it hasn't been tested
* on anything without a TSC), under Win95 it reads the 1.193180 MHz PIC
* timer. There are vague mumblings in the docs that it may fail if the
* appropriate hardware isn't available (possibly '386's or MIPS machines
* running NT), but who's going to run NT on a '386? */
{ LARGE_INTEGER performanceCount;
if (QueryPerformanceCounter (&performanceCount)) {
if ( debug_me )
log_debug ("rndw32#gather_random_fast: perf data\n");
(*add) (&performanceCount, sizeof (&performanceCount), requester);
}
else { /* Millisecond accuracy at best... */
DWORD aword = GetTickCount ();
(*add) (&aword, sizeof (aword), requester );
}
}
return 0;
}
#endif /* !USE_ENTROPY_DLL */
#ifndef IS_MODULE
@ -232,6 +931,8 @@ gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
void *ret;
int i = *sequence;
debug_me = !!getenv("DEBUG_RNDW32");
do {
if ( i >= DIM(func_table) || i < 0 ) {
return NULL;
@ -246,14 +947,6 @@ gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
return ret;
}
#ifdef USE_STATIC_RNDW32
void
rndw32_set_dll_name( const char *name )
{
entropy_dll = m_strdup( name );
}
#endif
#ifndef IS_MODULE
void
rndw32_constructor(void)

375
cipher/rsa.c Normal file
View File

@ -0,0 +1,375 @@
/* rsa.c - RSA function
* Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn)
* Copyright (C) 2000 Free Software Foundation, Inc.
***********************************************************************
* ATTENTION: This code should not be used in the United States
* before the U.S. Patent #4,405,829 expires on September 20, 2000!
***********************************************************************
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"
#include "mpi.h"
#include "cipher.h"
#include "rsa.h"
typedef struct {
MPI n; /* modulus */
MPI e; /* exponent */
} RSA_public_key;
typedef struct {
MPI n; /* public modulus */
MPI e; /* public exponent */
MPI d; /* exponent */
MPI p; /* prime p. */
MPI q; /* prime q. */
MPI u; /* inverse of p mod q. */
} RSA_secret_key;
static void test_keys( RSA_secret_key *sk, unsigned nbits );
static void generate( RSA_secret_key *sk, unsigned nbits );
static int check_secret_key( RSA_secret_key *sk );
static void public(MPI output, MPI input, RSA_public_key *skey );
static void secret(MPI output, MPI input, RSA_secret_key *skey );
static void
test_keys( RSA_secret_key *sk, unsigned nbits )
{
RSA_public_key pk;
MPI test = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
MPI out1 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
MPI out2 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
pk.n = sk->n;
pk.e = sk->e;
{ char *p = get_random_bits( nbits, 0, 0 );
mpi_set_buffer( test, p, (nbits+7)/8, 0 );
m_free(p);
}
public( out1, test, &pk );
secret( out2, out1, sk );
if( mpi_cmp( test, out2 ) )
log_fatal("RSA operation: public, secret failed\n");
secret( out1, test, sk );
public( out2, out1, &pk );
if( mpi_cmp( test, out2 ) )
log_fatal("RSA operation: secret, public failed\n");
mpi_free( test );
mpi_free( out1 );
mpi_free( out2 );
}
/****************
* Generate a key pair with a key of size NBITS
* Returns: 2 structures filles with all needed values
*/
static void
generate( RSA_secret_key *sk, unsigned nbits )
{
MPI p, q; /* the two primes */
MPI d; /* the private key */
MPI u;
MPI t1, t2;
MPI n; /* the public key */
MPI e; /* the exponent */
MPI phi; /* helper: (p-a)(q-1) */
MPI g;
MPI f;
/* select two (very secret) primes */
p = generate_secret_prime( nbits / 2 );
q = generate_secret_prime( nbits / 2 );
if( mpi_cmp( p, q ) > 0 ) /* p shall be smaller than q (for calc of u)*/
mpi_swap(p,q);
/* calculate Euler totient: phi = (p-1)(q-1) */
t1 = mpi_alloc_secure( mpi_get_nlimbs(p) );
t2 = mpi_alloc_secure( mpi_get_nlimbs(p) );
phi = mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
g = mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
f = mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
mpi_sub_ui( t1, p, 1 );
mpi_sub_ui( t2, q, 1 );
mpi_mul( phi, t1, t2 );
mpi_gcd(g, t1, t2);
mpi_fdiv_q(f, phi, g);
/* multiply them to make the private key */
n = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
mpi_mul( n, p, q );
/* find a public exponent */
e = mpi_alloc( (6+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
mpi_set_ui( e, 17); /* start with 17 */
while( !mpi_gcd(t1, e, phi) ) /* (while gcd is not 1) */
mpi_add_ui( e, e, 2);
/* calculate the secret key d = e^1 mod phi */
d = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
mpi_invm(d, e, f );
/* calculate the inverse of p and q (used for chinese remainder theorem)*/
u = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
mpi_invm(u, p, q );
if( DBG_CIPHER ) {
log_mpidump(" p= ", p );
log_mpidump(" q= ", q );
log_mpidump("phi= ", phi );
log_mpidump(" g= ", g );
log_mpidump(" f= ", f );
log_mpidump(" n= ", n );
log_mpidump(" e= ", e );
log_mpidump(" d= ", d );
log_mpidump(" u= ", u );
}
mpi_free(t1);
mpi_free(t2);
mpi_free(phi);
mpi_free(f);
mpi_free(g);
sk->n = n;
sk->e = e;
sk->p = p;
sk->q = q;
sk->d = d;
sk->u = u;
/* now we can test our keys (this should never fail!) */
test_keys( sk, nbits - 64 );
}
/****************
* Test wether the secret key is valid.
* Returns: true if this is a valid key.
*/
static int
check_secret_key( RSA_secret_key *sk )
{
int rc;
MPI temp = mpi_alloc( mpi_get_nlimbs(sk->p)*2 );
mpi_mul(temp, sk->p, sk->q );
rc = mpi_cmp( temp, sk->n );
mpi_free(temp);
return !rc;
}
/****************
* Public key operation. Encrypt INPUT with PKEY and put result into OUTPUT.
*
* c = m^e mod n
*
* Where c is OUTPUT, m is INPUT and e,n are elements of PKEY.
*/
static void
public(MPI output, MPI input, RSA_public_key *pkey )
{
if( output == input ) { /* powm doesn't like output and input the same */
MPI x = mpi_alloc( mpi_get_nlimbs(input)*2 );
mpi_powm( x, input, pkey->e, pkey->n );
mpi_set(output, x);
mpi_free(x);
}
else
mpi_powm( output, input, pkey->e, pkey->n );
}
/****************
* Secret key operation. Encrypt INPUT with SKEY and put result into OUTPUT.
*
* m = c^d mod n
*
* Where m is OUTPUT, c is INPUT and d,n are elements of PKEY.
*
* FIXME: We should better use the Chinese Remainder Theorem
*/
static void
secret(MPI output, MPI input, RSA_secret_key *skey )
{
mpi_powm( output, input, skey->d, skey->n );
}
/*********************************************
************** interface ******************
*********************************************/
int
rsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
{
RSA_secret_key sk;
if( !is_RSA(algo) )
return G10ERR_PUBKEY_ALGO;
generate( &sk, nbits );
skey[0] = sk.n;
skey[1] = sk.e;
skey[2] = sk.d;
skey[3] = sk.p;
skey[4] = sk.q;
skey[5] = sk.u;
/* make an empty list of factors */
*retfactors = m_alloc_clear( 1 * sizeof **retfactors );
return 0;
}
int
rsa_check_secret_key( int algo, MPI *skey )
{
RSA_secret_key sk;
if( !is_RSA(algo) )
return G10ERR_PUBKEY_ALGO;
sk.n = skey[0];
sk.e = skey[1];
sk.d = skey[2];
sk.p = skey[3];
sk.q = skey[4];
sk.u = skey[5];
if( !check_secret_key( &sk ) )
return G10ERR_BAD_SECKEY;
return 0;
}
int
rsa_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
{
RSA_public_key pk;
if( algo != 1 && algo != 2 )
return G10ERR_PUBKEY_ALGO;
pk.n = pkey[0];
pk.e = pkey[1];
resarr[0] = mpi_alloc( mpi_get_nlimbs( pk.n ) );
public( resarr[0], data, &pk );
return 0;
}
int
rsa_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
{
RSA_secret_key sk;
if( algo != 1 && algo != 2 )
return G10ERR_PUBKEY_ALGO;
sk.n = skey[0];
sk.e = skey[1];
sk.d = skey[2];
sk.p = skey[3];
sk.q = skey[4];
sk.u = skey[5];
*result = mpi_alloc_secure( mpi_get_nlimbs( sk.n ) );
secret( *result, data[0], &sk );
return 0;
}
int
rsa_sign( int algo, MPI *resarr, MPI data, MPI *skey )
{
RSA_secret_key sk;
if( algo != 1 && algo != 3 )
return G10ERR_PUBKEY_ALGO;
sk.n = skey[0];
sk.e = skey[1];
sk.d = skey[2];
sk.p = skey[3];
sk.q = skey[4];
sk.u = skey[5];
resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.n ) );
secret( resarr[0], data, &sk );
return 0;
}
int
rsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
int (*cmp)(void *opaque, MPI tmp), void *opaquev )
{
RSA_public_key pk;
MPI result;
int rc;
if( algo != 1 && algo != 3 )
return G10ERR_PUBKEY_ALGO;
pk.n = pkey[0];
pk.e = pkey[1];
result = mpi_alloc( (160+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB);
public( result, data[0], &pk );
/*rc = (*cmp)( opaquev, result );*/
rc = mpi_cmp( result, hash )? G10ERR_BAD_SIGN:0;
mpi_free(result);
return rc;
}
unsigned int
rsa_get_nbits( int algo, MPI *pkey )
{
if( !is_RSA(algo) )
return 0;
return mpi_get_nbits( pkey[0] );
}
/****************
* Return some information about the algorithm. We need algo here to
* distinguish different flavors of the algorithm.
* Returns: A pointer to string describing the algorithm or NULL if
* the ALGO is invalid.
* Usage: Bit 0 set : allows signing
* 1 set : allows encryption
*/
const char *
rsa_get_info( int algo,
int *npkey, int *nskey, int *nenc, int *nsig, int *usage )
{
*npkey = 2;
*nskey = 6;
*nenc = 1;
*nsig = 1;
switch( algo ) {
case 1: *usage = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC; return "RSA";
case 2: *usage = PUBKEY_USAGE_ENC; return "RSA-E";
case 3: *usage = PUBKEY_USAGE_SIG; return "RSA-S";
default:*usage = 0; return NULL;
}
}

36
cipher/rsa.h Normal file
View File

@ -0,0 +1,36 @@
/* rsa.h
* Copyright (C) 1997,1998 by Werner Koch (dd9jn)
* Copyright (C) 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef G10_RSA_H
#define G10_RSA_H
int rsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
int rsa_check_secret_key( int algo, MPI *skey );
int rsa_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey );
int rsa_decrypt( int algo, MPI *result, MPI *data, MPI *skey );
int rsa_sign( int algo, MPI *resarr, MPI data, MPI *skey );
int rsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
int (*cmp)(void *, MPI), void *opaquev );
unsigned rsa_get_nbits( int algo, MPI *pkey );
const char *rsa_get_info( int algo, int *npkey, int *nskey,
int *nenc, int *nsig, int *use );
#endif /*G10_RSA_H*/

View File

@ -337,10 +337,10 @@ sha1_get_info( int algo, size_t *contextsize,
*r_asnoid = asn;
*r_asnlen = DIM(asn);
*r_mdlen = 20;
*r_init = (void (*)(void *))sha1_init;
*r_write = (void (*)(void *, byte*, size_t))sha1_write;
*r_final = (void (*)(void *))sha1_final;
*r_read = (byte *(*)(void *))sha1_read;
*(void (**)(SHA1_CONTEXT *))r_init = sha1_init;
*(void (**)(SHA1_CONTEXT *, byte*, size_t))r_write = sha1_write;
*(void (**)(SHA1_CONTEXT *))r_final = sha1_final;
*(byte *(**)(SHA1_CONTEXT *))r_read = sha1_read;
return "SHA1";
}

View File

@ -899,10 +899,10 @@ tiger_get_info( int algo, size_t *contextsize,
*r_asnoid = asn;
*r_asnlen = DIM(asn);
*r_mdlen = 24;
*r_init = (void (*)(void *))tiger_init;
*r_write = (void (*)(void *, byte*, size_t))tiger_write;
*r_final = (void (*)(void *))tiger_final;
*r_read = (byte *(*)(void *))tiger_read;
*(void (**)(TIGER_CONTEXT *))r_init = tiger_init;
*(void (**)(TIGER_CONTEXT *, byte*, size_t))r_write = tiger_write;
*(void (**)(TIGER_CONTEXT *))r_final = tiger_final;
*(byte *(**)(TIGER_CONTEXT *))r_read = tiger_read;
return "TIGER";
}

View File

@ -34,10 +34,6 @@
/* Prototype for the self-test function. */
static const char *selftest(void);
/* Macros used by the info function. */
#define FNCCAST_SETKEY(f) ((int(*)(void*, byte*, unsigned))(f))
#define FNCCAST_CRYPT(f) ((void(*)(void*, byte*, byte*))(f))
/* Structure for an expanded Twofish key. s contains the key-dependent
* S-boxes composed with the MDS matrix; w contains the eight "whitening"
* subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys. Note
@ -990,16 +986,20 @@ twofish_get_info (int algo, size_t *keylen,
*keylen = algo==10? 256 : 128;
*blocksize = 16;
*contextsize = sizeof (TWOFISH_context);
*r_setkey = FNCCAST_SETKEY (twofish_setkey);
*r_encrypt= FNCCAST_CRYPT (twofish_encrypt);
*r_decrypt= FNCCAST_CRYPT (twofish_decrypt);
if( algo == 10 )
return "TWOFISH";
if (algo == 102) /* This algorithm number is assigned for
* experiments, so we can use it */
return "TWOFISH128";
return NULL;
*(int (**)(TWOFISH_context*, const byte*, const unsigned))r_setkey
= twofish_setkey;
*(void (**)(const TWOFISH_context*, byte*, const byte*))r_encrypt
= twofish_encrypt;
*(void (**)(const TWOFISH_context*, byte*, const byte*))r_decrypt
= twofish_decrypt;
if( algo == 10 )
return "TWOFISH";
if (algo == 102) /* This algorithm number is assigned for
* experiments, so we can use it */
return "TWOFISH128";
return NULL;
}

View File

@ -11,19 +11,17 @@ AC_PREREQ(2.13)
AC_INIT(g10/gpg.c)
AC_CONFIG_AUX_DIR(scripts)
AM_CONFIG_HEADER(config.h)
AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE(gnupg,`cat $srcdir/VERSION`)
VERSION=`cat $srcdir/VERSION`
PACKAGE=gnupg
ALL_LINGUAS="de es_ES fr it pl pt_BR pt_PT ru"
ALL_LINGUAS="da de eo es_ES fr id it ja nl pl pt_BR pt_PT ru sv"
static_modules="sha1 md5 rmd160"
AC_SUBST(VERSION)
AC_SUBST(PACKAGE)
AC_DEFINE_UNQUOTED(VERSION, "$VERSION")
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
static_random_module=""
MODULES_IN_CIPHER=`awk '/# MODULES: / { for(i=3;i<=NF;i++) print $i}' \
$srcdir/cipher/Makefile.am`
AC_PROG_AWK
MODULES_IN_CIPHER=`$AWK '/^EXTRA_PROGRAMS/ { for(i=3;i<=NF;i++) print $i}' \
$srcdir/cipher/Makefile.am`
dnl
dnl Check for random module options
@ -132,7 +130,6 @@ AM_MAINTAINER_MODE
dnl Checks for programs.
AC_CANONICAL_SYSTEM
dnl
dnl Setup some stuff depending on host/target.
dnl
@ -145,8 +142,10 @@ case "${target}" in
CC="${target}-gcc"
CPP="${target}-gcc -E"
RANLIB="${target}-ranlib"
disallowed_modules="rndunix rndlinux rndegd"
;;
*)
disallowed_modules="rndw32"
;;
esac
@ -177,9 +176,6 @@ AM_PROG_LIBTOOL
MPI_OPT_FLAGS=""
if test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes"
fi
try_gettext=yes
@ -213,6 +209,12 @@ case "${target}" in
try_gdbm="no"
;;
*-*-freebsd*)
# FreeBSD
CPPFLAGS="$CPPFLAGS -I/usr/local/include"
LDFLAGS="$LDFLAGS -L/usr/local/lib"
;;
*-*-hpux*)
if test -z "$GCC" ; then
CFLAGS="$CFLAGS -Ae -D_HPUX_SOURCE"
@ -234,7 +236,7 @@ esac
AC_SUBST(MPI_OPT_FLAGS)
GNUPG_SYS_SYMBOL_UNDERSCORE
GNUPG_CHECK_PIC
GNUPG_CHECK_RDYNAMIC
GNUPG_CHECK_EXPORTDYNAMIC
if test "$NO_PIC" = yes; then
try_dynload=no
fi
@ -272,6 +274,13 @@ case "${target}" in
NAME_OF_DEV_URANDOM="/dev/urandom"
DYNLINK_MOD_CFLAGS="-shared -rdynamic -fpic -Wl,-Bshareable -Wl,-x"
;;
*-netbsd*)
NAME_OF_DEV_RANDOM="/dev/random"
NAME_OF_DEV_URANDOM="/dev/urandom"
DYNLINK_MOD_CFLAGS="-shared -rdynamic -fpic -Wl,-Bshareable -Wl,-x"
;;
*)
NAME_OF_DEV_RANDOM="/dev/random"
NAME_OF_DEV_URANDOM="/dev/urandom"
@ -327,21 +336,21 @@ if test "$try_dynload" = yes ; then
if test "$ac_cv_lib_dl_dlopen" = "yes"; then
AC_DEFINE(USE_DYNAMIC_LINKING)
AC_DEFINE(HAVE_DL_DLOPEN)
DYNLINK_LDFLAGS="$CFLAGS_RDYNAMIC"
DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC"
use_gnupg_extensions=yes
else
AC_CHECK_LIB(c,dlopen)
if test "$ac_cv_lib_c_dlopen" = "yes"; then
AC_CHECK_FUNCS(dlopen)
if test "$ac_cv_func_dlopen" = "yes"; then
AC_DEFINE(USE_DYNAMIC_LINKING)
AC_DEFINE(HAVE_DL_DLOPEN)
DYNLINK_LDFLAGS="$CFLAGS_RDYNAMIC"
DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC"
use_gnupg_extensions=yes
else
AC_CHECK_LIB(dld,shl_load)
if test "$ac_cv_lib_dld_shl_load" = "yes"; then
AC_DEFINE(USE_DYNAMIC_LINKING)
AC_DEFINE(HAVE_DL_SHL_LOAD)
DYNLINK_LDFLAGS="$CFLAGS_RDYNAMIC"
DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC"
use_gnupg_extensions=yes
dnl -----------------
dnl DLD is not ready for use. So I better disable this test
@ -350,7 +359,7 @@ dnl AC_CHECK_LIB(dld,dld_link)
dnl if test "$ac_cv_lib_dld_dld_link" = "yes"; then
dnl AC_DEFINE(USE_DYNAMIC_LINKING)
dnl AC_DEFINE(HAVE_DLD_DLD_LINK)
dnl DYNLINK_LDFLAGS="$CFLAGS_RDYNAMIC"
dnl DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC"
dnl use_gnupg_extensions=yes
dnl ---------------
fi
@ -371,7 +380,7 @@ AC_SUBST(DYNLINK_MOD_CFLAGS)
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(unistd.h langinfo.h)
AC_CHECK_HEADERS(unistd.h langinfo.h termio.h)
dnl Checks for typedefs, structures, and compiler characteristics.
@ -393,6 +402,7 @@ GNUPG_CHECK_TYPEDEF(u32, HAVE_U32_TYPEDEF)
AC_CHECK_SIZEOF(unsigned short, 2)
AC_CHECK_SIZEOF(unsigned int, 4)
AC_CHECK_SIZEOF(unsigned long, 4)
AC_CHECK_SIZEOF(unsigned long long, 0)
if test "$ac_cv_sizeof_unsigned_short" = "0" \
|| test "$ac_cv_sizeof_unsigned_int" = "0" \
@ -405,8 +415,9 @@ fi
dnl Checks for library functions.
AC_FUNC_VPRINTF
AC_CHECK_FUNCS(strerror stpcpy strlwr stricmp tcgetattr rand strtoul mmap)
AC_CHECK_FUNCS(memmove gettimeofday getrusage gethrtime setrlimit)
AC_CHECK_FUNCS(memmove gettimeofday getrusage gethrtime setrlimit clock_gettime)
AC_CHECK_FUNCS(memicmp atexit raise getpagesize strftime nl_langinfo)
AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask)
GNUPG_CHECK_MLOCK
GNUPG_FUNC_MKDIR_TAKES_ONE_ARG
@ -483,29 +494,27 @@ fi
dnl
dnl Figure out the default linkage mode for cipher modules
dnl
dnl (We always need a static rmd160)
print_egd_notice=no
static_modules="$static_modules rmd160"
if test "$use_static_rnd" = default; then
if test "$ac_cv_have_dev_random" = yes; then
static_modules="$static_modules rndlinux"
static_random_module="rndlinux"
else
case "${target}" in
*-*-mingw32)
static_modules="$static_modules rndw32"
static_random_module="rndw32"
AC_DEFINE(USE_STATIC_RNDW32)
;;
i?86-emx-os2|i?86-*-os2*emx)
static_modules="$static_modules rndos2"
static_random_module="rndos2"
;;
m68k-atari-mint)
static_modules="$static_modules rndatari"
static_random_module="rndatari"
;;
i?86-*-msdosdjgpp*)
static_modules="$static_modules"
:
;;
*)
static_modules="$static_modules rndunix"
static_random_module="rndunix"
print_egd_notice=yes
;;
esac
@ -514,7 +523,7 @@ else
if test "$use_static_rnd" = none; then
:
else
static_modules="$static_modules rnd$use_static_rnd"
static_random_module="rnd$use_static_rnd"
if test "$use_static_rnd" = "unix"; then
print_egd_notice=yes
fi
@ -547,23 +556,31 @@ dnl
dnl Parse the modules list and build the list
dnl of static and dymically linked modules
dnl
dnl (We always need a static rmd160)
static_modules="$static_modules rmd160 $static_random_module"
STATIC_CIPHER_NAMES=""
STATIC_CIPHER_OBJS=""
DYNAMIC_CIPHER_MODS=""
GNUPG_MSG_PRINT([dynamically linked cipher modules:])
for name in $MODULES_IN_CIPHER; do
x="no"
for i in $static_modules; do
if test "$name" = "$i" ; then
x="yes"
fi
x="yes"
for i in $disallowed_modules; do
if test "$name" = "$i" ; then x="no" ; fi
done;
if test $x = yes; then
STATIC_CIPHER_NAMES="$STATIC_CIPHER_NAMES $name"
STATIC_CIPHER_OBJS="$STATIC_CIPHER_OBJS $name.lo"
else
DYNAMIC_CIPHER_MODS="$DYNAMIC_CIPHER_MODS $name"
GNUPG_MSG_PRINT([$name])
x="no"
for i in $static_modules; do
if test "$name" = "$i" ; then
x="yes"
fi
done;
if test $x = yes; then
STATIC_CIPHER_NAMES="$STATIC_CIPHER_NAMES $name"
STATIC_CIPHER_OBJS="$STATIC_CIPHER_OBJS $name.o"
else
DYNAMIC_CIPHER_MODS="$DYNAMIC_CIPHER_MODS $name"
GNUPG_MSG_PRINT([$name])
fi
fi
done
AC_MSG_RESULT()
@ -663,6 +680,9 @@ fi
AC_SUBST(ZLIBS)
# Allow users to append something to the version string without
# flagging it as development version. The user version parts is
# considered everything after a dash.
changequote(,)dnl
tmp_pat='[a-zA-Z]'
changequote([,])dnl
@ -678,12 +698,26 @@ AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes)
GNUPG_DO_LINK_FILES
GNUPG_CHECK_GNUMAKE
if test "$GCC" = yes; then
if test "$MAINTAINER_MODE" = "yes"; then
CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes"
else
CFLAGS="$CFLAGS -Wall"
fi
fi
dnl
dnl Make the version number in gcrypt/gcrypt.h the same as the one here.
dnl (this is easier than to have a .in file just for one substitution)
dnl
GNUPG_FIX_HDR_VERSION(gcrypt/gcrypt.h, GCRYPT_VERSION)
GCRYPT_LIBS="-L${libdir} -lgcrypt"
GCRYPT_CFLAGS=""
AC_SUBST(GCRYPT_LIBS)
AC_SUBST(GCRYPT_CFLAGS)
AC_OUTPUT_COMMANDS([
chmod +x scripts/db2html

View File

@ -1,231 +1,710 @@
Thu May 25 18:39:11 CEST 2000 Werner Koch <wk@openit.de>
Fri Jul 14 19:38:23 CEST 2000 Werner Koch <wk@>
* kbxio.c: New.
Replaced everything with the code from the STABLE-BRANCH-1-0 and
started to backport the changes from the 1.1 development branch
which are dated according to the ChangeLog of the 1.1 from
Sat Sep 18 12:16:08 CEST 1999 to Thu May 25 18:39:11 CEST 2000.
Here are those changes, some of them are duplicates because they
have been done on both branch simultaneously.
* kbxfile.c (print_kbxfile): Add a loop
(do_print_kbxfile): Fixed passing to kbx_dump_blob.
* gpg.c (print_mds): Add arg keys as a kludge to print hmacs
(main): New option --print-hmac.
Fri Mar 24 11:25:45 CET 2000 Werner Koch <wk@openit.de>
* trustdb.c (verify_own_keys): Do not print warning about unprotected
key when in quiet mode.
* gpg.c (print_mds): Add arg keys as a kludge to print hmacs
(main): New option --print-hmac.
* build-paket.c (do_user_id): Save offset where name has been stored.
* ringedit.c : Add new access method KBXF
* kbxfile.c: New.
* kbx.h: New.
* kbxblob.c: Started to work on the keybox stuff.
* keygen.c (gen_dsa): Modified to work with gcry_pk_genkey.
* Removed dummy-cipher.h from all files.
* keygen.c (gen_elg): Modified to work with gcry_pk_genkey.
(key_from_sexp): New.
(factors_from_sexp): New.
* g10.c : Renamed to ...
* gpg.c : ... this
* Makefile.am: And fixed it here.
* Changed all "g10_"/"GPG_" prefixes to "gpg_"/"GPG_".
* misc.c (mpi_read_opaque): Fixed double counting.
* seckey-cert.c (do_check): Removed buffer and the unmotivated free
on it.
* pubkey-enc.c (pk_decrypt): New wrapper for the gcry_ function.
* seckey-cert.c (pk_check_secret_key): Likewise.
* encode.c (pk_encrypt): Likewise.
* parse-packet.c (parse_key): Fixed case of unencrypted secret keys.
* misc.c (mpi_print): Use gcry_mpi_aprint.
(pubkey_nbits): Kludge to use the gcry_pk_ API.
* seskey.c (encode_session_key): Replaced mpi_set_buffer by *_scan.
(do_encode_md): Ditto.
(encode_md_value): Ditto.
* seckey-cert.c (protect_secret_key): Ditto.
* comment.c (make_mpi_comment_node): Replaced mpi_get_buffer by _print.
* pubkey-enc.c (get_it): Ditto.
* sig-check.c (do_signature_check): Ditto.
* keyid.c (do_fingerprint_md): Replaced mpi_get_buffer by gcry_mpi_print.
(v3_keyid): New.
(keyid_from_sk): And use it here.
(keyid_from_pk): Ditto.
(fingerprint_from_sk): Ditto.
(fingerprint_from_pk): Ditto.
* misc.c (mpi_print): New.
* misc.c (checksum_mpi): Now uses gcry_mpi_print to get the data.
* seckey-cert.c (do_check): Replaced mpi_read_from_buffer.
* armor.c (armor_filter): Made the "Comment:" header translatable.
* seckey-cert.c: Removed obsolete mpi_*_protect_flag.
* parse-packet.c: Ditto.
* misc.c (mpi_read): Removed the secure argumet becuase it is
never used. Changed all Callers.
(mpi_read_opaque): New.
(mpi_write_opaque): New.
* parse-packet.c (parse_key): Use the opaque method also for
v3 keys.
* build-packet.c (do_secret_key): Likewise.
* g10.c (main): Check libgcrypt version.
* packet.h: replaced inclusion of mpi.h by a plain typeedef of the
gcry_mpi structure and removed all inclusions of "mpi.h" in all
sources.
* g10.c: Add --delete-secret-key to the help page.
* g10.c (main): Changed the default homedir to "~/.gnupg-test" so
that we don't mess up with the stable version.
* misc.c (mpi_write): New.
(mpi_write): New.
* misc.c (checksum_u16_nobug): Removed.
(checksum_mpi_counted_nbits): Renamed to ...
(checksum_mpi): ... this to superseed the old one. Changed all
callers. This is because we do not emulate the old gpg bug anymore.
* g10.c (oEmuChecksumBug): Removed.
* g10.c (register_extension): New...
(main): Use it here instead of register_cipher_extesnion.
(strusage): s/strusage/my_strusage/ . Made static.
(main): Use set_strusage().
* tdbdump.c (HEXTOBIN): Changed the name of the argument, so that
traditional cpp don't mess up the macros. Suggested by Jos Backus.
* armor.c (parse_header_line): Stop parsing on a only WS line too.
Suggested by Aric Cyr.
* misc.c (pull_in_libs): Removed.
* mainproc.c (list_node): Print the PK algo in the --with-colon mode.
* keylist.c (list_keyblock): Ditto.
* misc.c (pull_in_libs): Removed pull in of g10c.
* misc.c (map_gcry_rc): Removed here and chnaged all users.
* getkey.c: Replaced check_pubkey_algo by openpgp_pk_test_algo.
* import.c (delete_inv_parts): Ditto.
* pkclist.c: Ditto.
* skclist.c: Ditto.
* pubkey-enc.c: Ditto.
* g10.c (main): Replaced the function to diable PK algos.
* g10.c (main): Replaced get_random_bits by gcry_random_bytes.
* seskey.c (encode_session_key): Likewise.
(make_session_key): Renamed randomize_buffer to gcry_randomize
and use the GCRY_xxx_RANDOM constants.
* cipher.c (write_header): Ditto.
* passphrase.c (hash_passphrase): Ditto.
* seckey-cert.c (protect_secret_key): Ditto.
* getkey.c (find_by_name): Replaced rmd160_hash_buffer
by gcry_md_hash_buffer.
* keyedit.c (show_prefs): Ditto.
* keylist.c (list_keyblock): Ditto.
* trustdb.c (print_uid_from_keyblock): Ditto.
(make_uid_records): Ditto.
* skclist.c (build_sk_list): Removed the test on faked RNGs.
(is_insecure): Removed.
* g10.c (--quick-random): Removed this option.
* Replaced all PUBKEY_ALGO_xxx by GCRY_PK_xxxx.
* misc.c (pubkey_algo_npkey): New as a wrapper around the gcry fucntion.
(pubkey_algo_nskey): Ditto.
(pubkey_algo_nsig): Ditto.
(pubkey_algo_nenc): Ditto.
* Makefile.am (basicdefs.h): Added.
(install-data-local): Removed the handling for historic gpgm.
* misc.c (openpgp_cipher_test_algo): New.
(openpgp_pk_test_algo): New.
(openpgp_md_test_algo): New.
* g10.c (build_list): Changed to use the new functions from libgcrypt.
* ringedit.c (enum_keyblocks): Set .rt to 0 on open.
* encode.c (encode_simple): Use new CTB when we don't have the
length of the file. This is somewhat strange as the comment above
indicates that this part is actually fixed for PGP 5 - maybe I simply
lost the source line, tsss.
* sign.c (clearsign_file): Avoid duplicated Entries in the "Hash:"
line. Those headers are now only _not_ printed when there are
only old-style keys _and_ all hashs are MD5.
(clearsign_file): Use gcry_md_test_algo() and gcry_md_algo_name().
* openfile.c (make_outfile_name): Use case-insenstive compare for
DOS systems. Add ".pgp" to the list of know extensions.
(open_outfile): For DOS systems try to replace the suffix instead of
appending it.
* encr-data.c (decrypt_data): Reset error on a weak key.
* cipher.c: Replaced the cipher and digest functions by the gcry_ ones.
* seckey-cert.c: Ditto.
* seskey.c: Ditto.
* g10.c (print_mds): Replaced digst functions with the new gcry_ ones.
* keyid.c: Ditto.
* mainproc.c: Ditto.
* passphrase.c: Ditto.
* sig-check.c: Ditto.
* sign.c: Ditto.
* pkclist.c (do_edit_ownertrust): Made the answer string const.
* basicdefs.h: New. Move some defs and decl to this header.
* openfile.c (open_outfile): Fixed the 8dot3 handling.
* passphrase.c (passphrase_to_dek): Print uid using utf8 func.
* delkey.c (delete_key): Ditto.
* pkclist.c (show_paths,do_edit_ownertrust,do_we_trust): Ditto
(do_we_trust_pre): Ditto.
* trustdb.c (print_user_id,check_uidsigs): Ditto.
* revoke.c (gen_revoke,ask_revoke_sig): Ditto.
* filter.h: Changed cipher handle types to the the GCRY_xxx ones.
replaces include cipher by system header include gcrypt.h.
* cipher.c: replaced the cipher functions by the gcry_ ones.
Ditto for the md functions.
* misc.c (map_gcry_rc): New.
Wed Jun 28 11:54:44 CEST 2000 Werner Koch <wk@>
* armor.c (armor_filter): Set sigclass to 0 in case of non-dash-escaped
clearsig. This makes this mode work again.
* mainproc.c (proc_tree): Fixed handling of one-pass-sig packets in textmode.
Disabled the ugly workaround for PGP 5 - let's see whether thi breaks less
cases. Found by Ted Cabeen.
* options.h (DBG_HASHING): New. All commented md_start_debug are now
controlled by this debug option.
* sign.c (print_status_sig_created): New and called from 2 places.
* keygen.c (gen_rsa): New, but commented.
(ask_algo): Commented support for RSA.
* seckey-cert.c (protect_secret_key): Started to fix the code for v4 RSA
keys - it is not solved yet. However, we have time until, Sep 20th ;)
Wed Jun 14 12:27:09 CEST 2000 Werner Koch <wk@openit.de>
* status.c (init_shm_coprocessing): Changed the sequence of the get,attach
to cope with the changes in newer Linux kernels. This bug has been found
by <dmitri@advantrix.com> who also proposed this solution. Hopefully
this does not break gpg on to many systems.
* cipher.c (write_header): Protect the IV with the MDC too.
* encr-data.c (decrypt_data): Likewise.
Fri Jun 9 10:09:52 CEST 2000 Werner Koch <wk@openit.de>
* g10.c: New options --no-auto-key-retrieve
* options.h (auto_key_retrieve): New.
* mainproc.c (check_sig_and_print): Implemented that.
Wed Jun 7 19:19:09 CEST 2000 Werner Koch <wk@openit.de>
* sig-check.c (do_check): Use EMULATE_MDENCODE also on v4 paclets.
Wed Jun 7 17:25:38 CEST 2000 Werner Koch <wk@openit.de>
* cipher.c (write_header): Use plain CFB mode for MDC encrypted packets.
* encr-data.c (decrypt_data): Ditto.
Mon Jun 5 23:41:54 CEST 2000 Werner Koch <wk@openit.de>
* seskey.c (do_encode_md, encode_md_value): Add new arg v3compathack to work
around a bug in old versions.
* sig-check.c (do_check): use the aboved workaround when enabled.
* g10.c: New option --emulate-md-decode-bug
Mon Jun 5 12:37:43 CEST 2000 Werner Koch <wk@openit.de>
* build-packet.c (do_mdc): New.
(do_encrypted_mdc): Changed for the new proposal.
* parse-packet.c (parse_mdc): New.
(parse_encrypted): Fixed for the new proposal.
* packet.h (PKT_MDC): New.
* cipher.c (cipher_filter): Build the MDC packet here.
* g10.c (main): Enable --force-mdc.
* encr-data.c (mdc_decode_filter): Fixed for new MDC method
* options.h(rfc2440): New.
* g10.c (main): Changed the selected values for --openpgp to not include
optional algorithms.
Thu May 18 11:38:54 CEST 2000 Werner Koch <wk@openit.de>
* keyedit.c (keyedit_menu): Add a keyword arg to the prompt.
* status.c, status.h: Added 3 new status tokens.
* status.c (do_get_from_fd): New.
(cpr_enabled,cpr_get,cpr_get_hidden,cpr_kill_prompt,
cpr_get_answer_is_yes,cpr_get_answer_yes_no_quit): Modified to work
with the new function.
* g10.c: Add new option --command-fd.
* status.c (progress_cb): New.
(set_status_fd): Register progress functions
Fri May 12 14:01:20 CEST 2000 Werner Koch <wk@openit.de>
* delkey.c (delete_key): Add 2 new status messages
* status.c, status.h (STATUS_DELETE_PROBLEM): New.
Fixed years of copyright in all source files.
Mon May 1 17:08:14 CEST 2000 Werner Koch <wk@openit.de>
* trustdb.c (propagate_validity): Fixed the bug that only one uid
gets fully trusted even when all are signed by an ultimate key.
Mon May 1 15:38:04 CEST 2000 Werner Koch <wk@openit.de>
* getkey.c (key_byname): Always returned a defined context. Fixed
a segv for invalid user id specifications. Reported by Walter Koch.
* getkey.c (get_user_id): I18ned "no user id" string. By Walter.
* pkclist.c (do_show_revocation_reason): Typo fixes.
* helptext.c: Ditto.
* armor.c (armor_filter): Fixed some CRLF issues. By Mike McEwan.
Fri Apr 14 19:37:08 CEST 2000 Werner Koch <wk@openit.de>
* pkclist.c (do_show_revocation_reason): New.
(show_revocation_reason): New and called at various places.
* g10.c (main): Fixed small typo.
* pkclist.c (do_we_trust): Act on always_trust but not for revoked
keys. Suggested by Chip Salzenberg.
* g10.c: New option --lock-never.
* ringedit.c (get_writable_keyblock_file): New.
* keygen.c (do_generate_keypair): Use this instead of the hardwired one.
* keygen.c (ask_user_id): Check that the email address is in the
correct field. Suggested by Christian Kurz.
Mon Apr 10 13:34:19 CEST 2000 Werner Koch <wk@openit.de>
* keyedit.c (show_key_with_all_names): s/sbb/ssb/
Tue Mar 28 14:26:58 CEST 2000 Werner Koch <wk@openit.de>
* trustdb.c (verify_own_keys): Do not print warning about unprotected
key when in quiet mode.
Mon Mar 13 19:22:46 CET 2000 Werner Koch <wk@openit.de>
Wed Mar 22 13:50:24 CET 2000 Werner Koch <wk@openit.de>
* build-paket.c (do_user_id): Save offset where name has been stored.
* mainproc.c (print_userid): Do UTF8 conversion before printing.
* import.c (import_one): Ditto.
(import_secret_one): Ditto.
(delete_inv_parts): Ditto.
* ringedit.c : Add new access method KBXF
Thu Mar 16 16:20:23 CET 2000 Werner Koch <wk@openit.de>
* kbxfile.c: New.
* keylist.c (print_key_data): Handle a NULL pk gracefully.
Mon Feb 21 22:43:01 CET 2000 Werner Koch <wk@>
* getkey.c (merge_one_pk_and_selfsig): Fixed silly code for
getting the primary keys keyID but kept using the one from the
subkey.
* pubkey-enc.c (get_it): Print a note for expired subkeys.
* kbx.h: New.
* kbxblob.c: Started to work on the keybox stuff.
* getkey.c (has_expired): New.
(subkeys_expiretime): New.
(finish_lookup): Check for expired subkeys needed for encryption.
(merge_keys_and_selfsig): Fixed expiration date merging for subkeys.
Mon Jan 31 16:37:34 CET 2000 Werner Koch <wk@gnupg.de>
* keylist.c (list_keyblock): Print expiration time for "sub".
(list_one): Add missing merging for public keys.
* mainproc.c (list_node): Ditto.
* keygen.c (gen_dsa): Modified to work with gcry_pk_genkey.
2000-03-14 13:49:38 Werner Koch (wk@habibti.openit.de)
* Removed dummy-cipher.h from all files.
* keygen.c (keyedit_menu): Do not allow to use certain commands
while the secret key is selected.
Thu Jan 27 18:00:44 CET 2000 Werner Koch <wk@gnupg.de>
2000-03-09 12:53:09 Werner Koch (wk@habibti.openit.de)
* keygen.c (gen_elg): Modified to work with gcry_pk_genkey.
(key_from_sexp): New.
(factors_from_sexp): New.
* keygen.c (ask_expire_interval): Movede parsig to ...
(parse_expire_string): ... this new function. And some new control
commands.
(proc_parameter_file): Add expire date parsing.
(do_generate_keypair): Allow the use of specified output files.
* g10.c : Renamed to ...
* gpg.c : ... this
* Makefile.am: And fixed it here.
2000-03-08 10:38:38 Werner Koch (wk@habibti.openit.de)
* Changed all "g10_"/"GPG_" prefixes to "gpg_"/"GPG_".
* keygen.c (ask_algo): Removed is_v4 return value and the commented
code to create Elg keys in a v3 packet. Removed the rounding
of key sizes here.
(do_create): Likewise removed arg v4_packet.
(gen_elg): Likewise removed arg version. Now rounding keysizes here.
(gen_dsa): Rounding keysize now here.
(release_parameter_list): New
(get_parameter*): New.
(proc_parameter_file): New.
(read_parameter_file): New.
(generate_keypair): Splitted. Now uses read_parameter_file when in
batch mode. Additional argument to specify a parameter file.
(do_generate_keypair): Main bulk of above fucntion and uses the
parameter list.
(do_create): Don't print long notice in batch mode.
* g10.c (main): Allow batched key generation.
Mon Jan 24 22:24:38 CET 2000 Werner Koch <wk@gnupg.de>
Thu Mar 2 15:37:46 CET 2000 Werner Koch <wk@gnupg.de>
* misc.c (mpi_read_opaque): Fixed double counting.
* pubkey-enc.c (get_it): Print a note about unknown cipher algos.
* seckey-cert.c (do_check): Removed buffer and the unmotivated free
on it.
* g10.c (opts): Add a note to the help listing about the man page
and removed some options from the help listing.
* pubkey-enc.c (pk_decrypt): New wrapper for the gcry_ function.
* seckey-cert.c (pk_check_secret_key): Likewise.
* encode.c (pk_encrypt): Likewise.
* keyedit.c (print_and_check_one_sig): Use a new function to truncate
the output of the user ID. Suggested by Jan-Benedict Glaw.
* parse-packet.c (parse_key): Fixed case of unencrypted secret keys.
Wed Feb 23 10:07:57 CET 2000 Werner Koch <wk@gnupg.de>
Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de>
* helptext.c: typo fix.
* misc.c (mpi_print): Use gcry_mpi_aprint.
(pubkey_nbits): Kludge to use the gcry_pk_ API.
Thu Feb 17 13:39:32 CET 2000 Werner Koch <wk@gnupg.de>
* seskey.c (encode_session_key): Replaced mpi_set_buffer by *_scan.
(do_encode_md): Ditto.
(encode_md_value): Ditto.
* seckey-cert.c (protect_secret_key): Ditto.
* comment.c (make_mpi_comment_node): Replaced mpi_get_buffer by _print.
* pubkey-enc.c (get_it): Ditto.
* sig-check.c (do_signature_check): Ditto.
* revoke.c: Removed a bunch of commented code.
Fri Dec 31 12:48:31 CET 1999 Werner Koch <wk@gnupg.de>
* packet.h (SIGSUBPKT_REVOC_REASON): New.
* build-packet.c (build_sig_subpkt): Support new sub packet.
* parse-packet.c (parse_one_sig_subpkt): Ditto.
(dump_sig_subpkt): Ditto.
* revoke.c (ask_revocation_reason): New.
(release_revocation_reason_info): New.
(revocation_reason_build_cb): New.
(gen_revoke): Ask for reason.
* main.h (struct revocation_reason_info): Add declaration.
* keyedit.c (menu_revsig): Add support for revocation reason.
(menu_revkey): Ditto.
(sign_uid_mk_attrib): Renamed to ...
(sign_mk_attrib): ... this, made static and add support for reasons.
* keyid.c (do_fingerprint_md): Replaced mpi_get_buffer by gcry_mpi_print.
(v3_keyid): New.
(keyid_from_sk): And use it here.
(keyid_from_pk): Ditto.
(fingerprint_from_sk): Ditto.
(fingerprint_from_pk): Ditto.
Tue Feb 15 08:48:13 CET 2000 Werner Koch <wk@gnupg.de>
* misc.c (mpi_print): New.
* build-packet.c (build_packet): Fixed fixing of old comment packets.
* misc.c (checksum_mpi): Now uses gcry_mpi_print to get the data.
* import.c (import_keys): Fixed importing from stdin when called with
nnames set to zero as it normally happens.
* seckey-cert.c (do_check): Replaced mpi_read_from_buffer.
Mon Feb 14 14:30:20 CET 2000 Werner Koch <wk@gnupg.de>
* sig-check.c (check_key_signature2): Add new arg r_expired.
(do_signature_check): New arg to pass it down to ...
(do_check): New arg r-expire which is set when the signature
has expired.
* trustdb.c (check_sig_record): Set SIGF_EXPIRED flag and set
the expiretime to zero so that thi signature will not be checked
anymore.
Fri Feb 11 17:44:40 CET 2000 Werner Koch <wk@gnupg.de>
* g10.c (g10_exit): Update the random seed_file.
(main): Set the random seed file. New option --no-random-seed-file.
Thu Feb 10 17:39:44 CET 2000 Werner Koch <wk@gnupg.de>
* keyedit.c (menu_expire): Fixed segv due to unitialized sub_pk.
By Rémi.
Thu Feb 10 11:39:41 CET 2000 Werner Koch <wk@gnupg.de>
* keylist.c (list_keyblock): Don't print warnings in the middle of
regulat output lines. By Rémi.
* sig-check.c: Include options.h
Wed Feb 9 15:33:44 CET 2000 Werner Koch <wk@gnupg.de>
* gpg.c: New option --ignore-time-conflict
* sig-check.c (do_check): Implemented this option.
* trustdb.c (check_trust): Ditto.
* sign.c (do_sign): Ditto.
* keygen.c (generate_subkeypair): Ditto.
* encode.c (encode_simple): use iobuf_cancel after open failure.
Reported by Huy Le.
Fri Jan 14 18:32:01 CET 2000 Werner Koch <wk@gnupg.de>
* packet.h (STRING2KEY): Changed mode from byte to int.
* parse-packet.c (parse_key): Add the special GNU protection stuff
* build-packet.c (so_secret_key): Ditto.
* seckey-cert.c (do_check): Ditto.
* keyedit.c (change_passphrase): Ditto.
* export.c (export_secsubkeys): New.
(do_export_stream): Hack to export the primary key using mode 1001.
* g10.c: New command --export-secret-subkeys
Thu Jan 13 19:31:58 CET 2000 Werner Koch <wk@gnupg.de>
* armor.c (is_armored): Check for 1-pass-sig packets. Reported by
David Hallinan <hallinan@rtd.com>.
(armor_filter): Replaced one LF by the LF macro. Reported by
Wolfgang Redtenbacher.
Wed Jan 5 11:51:17 CET 2000 Werner Koch <wk@gnupg.de>
* g10.c (main): Reset new global flag opt.pgp2_workarounds
when --openpgp is used.
* mainproc.c (proc_plaintext): Do the PGP2,5 workarounds only
when the global flag is set.
(proc_tree): Ditto.
* textfilter.c (copy_clearsig_text): Ditto.
* armor.c (armor_filter): Ditto.
* g10.c: New option --list-only
* mainproc.c (proc_tree): Don't do it if opt.list_only is active.
(proc_pubkey_enc): Implement option.
* status.h, status.c ({BEGIN,END}_{EN,DE}CRYPTION): New.
* cipher.c (cipher_filter): New status outputs.
* mainproc.c (proc_encrypted): New status outputs.
Fri Dec 31 14:08:15 CET 1999 Werner Koch <wk@gnupg.de>
* armor.c (armor_filter): Made the "Comment:" header translatable.
Wed Dec 8 21:58:32 CET 1999 Werner Koch <wk@gnupg.de>
* hkp.c (hkp_import): Make sure that the program does not return
success when there is a connection problem. Reported by Phillip Jones.
* seckey-cert.c: Removed obsolete mpi_*_protect_flag.
* parse-packet.c: Ditto.
Sun Dec 19 15:22:26 CET 1999 Werner Koch <wk@gnupg.de>
* misc.c (mpi_read): Removed the secure argumet becuase it is
never used. Changed all Callers.
(mpi_read_opaque): New.
(mpi_write_opaque): New.
* parse-packet.c (parse_key): Use the opaque method also for
v3 keys.
* build-packet.c (do_secret_key): Likewise.
* armor.c (LF): Use this new macro at all places where a line LF
is needed. This way DOSish textfiles should be created when the
input data is also in dos mode.
* sign.c (LF): Ditto.
* textfilter.c (LF): Ditto.
(copy_clearsig_text): Disabled the forcing of CR,LF sequences
for DOS systems.
* g10.c (main): Check libgcrypt version.
* plaintext.c (handle_plaintext): Fixes for line endings on DOS.
and react on a LF in cleartext.
* armor.c (fake_packet): Restore the original line ending after
removing trailing spaces.
* packet.h: replaced inclusion of mpi.h by a plain typeedef of the
gcry_mpi structure and removed all inclusions of "mpi.h" in all
sources.
* signal.c (got_fatal_signal): DOS fix.
Thu Dec 16 10:07:58 CET 1999 Werner Koch <wk@gnupg.de>
* mainproc.c (print_failed_pkenc): Fix for unknown algorithm.
Found by fygrave@epr0.org.
Thu Dec 9 10:31:05 CET 1999 Werner Koch <wk@gnupg.de>
* hkp.c: i18n the strings.
Sat Dec 4 15:32:20 CET 1999 Werner Koch <wk@gnupg.de>
* trustdb.c (verify_key): Shortcut for ultimately trusted keys.
Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de>
* pkclist.c (build_pk_list): Validate the trust using the namehash
if this one has been set by the key lookup.
* g10.c: Add --delete-secret-key to the help page.
* g10.c (main): Changed the default homedir to "~/.gnupg-test" so
that we don't mess up with the stable version.
* openfile.c (copy_options_file): Made static.
(try_make_homedir): New.
* ringedit.c (add_keyblock_resource): Use the try_make_hoemdir logic.
* tdbio.c (tdbio_set_dbname): Likewise.
* misc.c (mpi_write): New.
(mpi_write): New.
* keygen.c (generate_user_id): Use m_alloc_clear() here. We should
better use an allocation function specific to the user_id packet.
* misc.c (checksum_u16_nobug): Removed.
(checksum_mpi_counted_nbits): Renamed to ...
(checksum_mpi): ... this to superseed the old one. Changed all
callers. This is because we do not emulate the old gpg bug anymore.
* g10.c (oEmuChecksumBug): Removed.
* keygen.c (keygen_add_std_prefs): Changed symmetric preferences
to include Blowfish again. This is due to it's better speed compared
to CAST5.
Fri Nov 19 17:15:20 CET 1999 Werner Koch <wk@gnupg.de>
* g10.c (strusage): Print the home directory.
* g10.c (register_extension): New...
(main): Use it here instead of register_cipher_extesnion.
(strusage): s/strusage/my_strusage/ . Made static.
(main): Use set_strusage().
* armor.c (armor_filter): Take action on the cancel control msg.
* filter.h (armor_filter_context_t): Add cancel flag.
Mon Nov 29 21:52:11 CET 1999 Werner Koch <wk@gnupg.de>
* g10.c: New option --fast-list-mode ..
* keylist.c (list_keyblock): .. and implemented.
* mainproc.c (list_node): Ditto.
* import.c (mark_non_selfsigned_uids_valid): Fixed the case that there
is a uid without any packet following.
Mon Nov 22 11:14:53 CET 1999 Werner Koch <wk@gnupg.de>
* mainproc.c (proc_plaintext): Never enable the hash processing
when skip_verify is active.
* armor.c (parse_header_line): Stop parsing on a WS line too.
Suggested by Aric Cyr.
* tdbdump.c (HEXTOBIN): Changed the name of the argument, so that
traditional cpp don't mess up the macros. Suggested by Jos Backus.
* armor.c (parse_header_line): Stop parsing on a only WS line too.
Suggested by Aric Cyr.
Mon Nov 15 21:36:02 CET 1999 Werner Koch <wk@gnupg.de>
* misc.c (pull_in_libs): Removed.
Sat Nov 13 17:44:23 CET 1999 Werner Koch <wk@gnupg.de>
* mainproc.c (list_node): Print the PK algo in the --with-colon mode.
* keylist.c (list_keyblock): Ditto.
* misc.c (pull_in_libs): Removed pull in of g10c.
* signal.c (got_fatal_signal): Found the reason why exit(8) did not
work - it is better to set the disposition back to default before
raising the signal. Print the notice on stderr always.
* misc.c (map_gcry_rc): Removed here and chnaged all users.
Fri Nov 12 20:33:19 CET 1999 Werner Koch <wk@gnupg.de>
* getkey.c: Replaced check_pubkey_algo by openpgp_pk_test_algo.
* import.c (delete_inv_parts): Ditto.
* pkclist.c: Ditto.
* skclist.c: Ditto.
* pubkey-enc.c: Ditto.
* g10.c (make_username): Swapped the logic.
* keylist.c (public_key_list): Now takes a STRLIST as arg and moved
the creation ot this list to the caller, so that he can copy with
UTF-conversion of user IDs. Changed all callers.
(secret_key_list): Likewise.
* g10.c (main): Replaced the function to diable PK algos.
* getkey.c (get_user_id_string_native): New and ...
* encode.c (write_pubkey_enc_from_list): ... use it here.
* g10.c (main): Replaced get_random_bits by gcry_random_bytes.
* seskey.c (encode_session_key): Likewise.
(make_session_key): Renamed randomize_buffer to gcry_randomize
and use the GCRY_xxx_RANDOM constants.
* cipher.c (write_header): Ditto.
* passphrase.c (hash_passphrase): Ditto.
* seckey-cert.c (protect_secret_key): Ditto.
* pubring.asc: Updated.
* getkey.c (find_by_name): Replaced rmd160_hash_buffer
by gcry_md_hash_buffer.
* packet.h (PKT_PHOTO_ID): New.
* parse-packet.c (parse_photo_id): New.
* build-packet.c (do_user_id: Handle photo IDs.
(build_packet): Change CTB for photo IDs
* free-packet.c (free_user_id): Release memory used for photo IDs
* sig-check.c (hash_uid_node): Handle photo IDs too.
* trustdb.c (print_uid_from_keyblock): Hash photo ID.
(make_uid_records): Ditto.
* getkey.c (find_by_name): Ditto.
* keyedit.c (show_prefs): Ditto.
* keylist.c (list_keyblock): Ditto.
* trustdb.c (print_uid_from_keyblock): Ditto.
(make_uid_records): Ditto.
* skclist.c (build_sk_list): Removed the test on faked RNGs.
(is_insecure): Removed.
* g10.c (--quick-random): Removed this option.
Thu Oct 28 16:08:20 CEST 1999 Werner Koch <wk@gnupg.de>
* Replaced all PUBKEY_ALGO_xxx by GCRY_PK_xxxx.
* keygen.c (ask_expire_interval): Print a warning for systems
with a signed 32 time_t if the exiration time is beyoind 2038.
* misc.c (pubkey_algo_npkey): New as a wrapper around the gcry fucntion.
(pubkey_algo_nskey): Ditto.
(pubkey_algo_nsig): Ditto.
(pubkey_algo_nenc): Ditto.
Fri Oct 8 20:40:50 CEST 1999 Werner Koch <wk@gnupg.de>
Tue Oct 26 20:03:44 CEST 1999 Werner Koch <wk@gnupg.de>
* ringedit.c (enum_keyblocks): The last fix way really stupid;
reverted and set rt to Unknown.
* Makefile.am (basicdefs.h): Added.
(install-data-local): Removed the handling for historic gpgm.
Fri Oct 8 20:32:01 CEST 1999 Werner Koch <wk@gnupg.de>
Tue Oct 26 14:10:21 CEST 1999 Werner Koch <wk@gnupg.de>
* ringedit.c (enum_keyblocks): Zero the entire kbpos out on open.
* misc.c (openpgp_cipher_test_algo): New.
(openpgp_pk_test_algo): New.
(openpgp_md_test_algo): New.
* g10.c (oEntropyDLL): Removed option.
(main): Made the warning on development versions more verbose.
* g10.c (build_list): Changed to use the new functions from libgcrypt.
* g10.c (oHonorHttpProxy): New option.
* hkp.c (hkp_ask_import,hkp_export): Implement this option.
* options.skel: Enable this option for new installations
* ringedit.c (enum_keyblocks): Set .rt to 0 on open.
Mon Oct 4 21:23:04 CEST 1999 Werner Koch <wk@gnupg.de>
* import.c (import_keys): Changed calling interface, adjusted caller.
(import): Moved printing of stats out ...
(print_stats): New. ... to here.
(import_keys_stream): Call stats print here.
(import_keys): Print stats as totals for all files.
* tdbio.h (DIRF_NEWKEYS): New
* tdbio.c (tdbio_dump_record): Print the new flag.
* trustdb.c (check_trust_record): New arg sigs_only. Adapted all
callers.
(do_update_trust_record): Removed recheck arg and add a new sigs_only
do we can later improve on the performance. Changed all callers too.
(check_trustdb): Evalutate the new flag and add a status output.
Do a check when the dir record has not been checked.
(build_cert_tree): Evaluate the new flag.
(check_trust): Ditto. Do a trust_record check, when the dir record
is not marked as checked.
(mark_fresh_keys): New.
(clear_lid_table): New.
(sync_trustdb): New.
* import.c (import_keys): Call sync_trustdb() after processing.
(import_keys_stream): Ditto.
* tdbdump.c (import_ownertrust): Ditto.
* import.c (import_revoke_cert): Notify the trust DB.
(do_update_trust_record): Use |= to set the REVOKED bit and not &=;
shame on me for this bad copy+paste introduced bug.
(do_we_trust): Add trustmask to allow revoked key override to work.
Chnaged are to allow return of a mofified trustlevel. Adapted the
one caller.
* g10.c: New options --emulate-3des-s2k-bug
* passphrase.c (hash_passphrase): Implemented above.
* mainproc.c (proc_tree): Check for standalone signatures.
(do_check_sig): Print a notice for a standalone revocation
(check_sig_and_print): Do not print an error for unchecked standalone
revocations.
Tue Sep 28 20:54:37 CEST 1999 Werner Koch <wk@gnupg.de>
* encode.c (encode_simple): Use new CTB when we don't have the
length of the file. This is somewhat strange as the comment above
indicates that this part is actually fixed for PGP 5 - maybe I simply
lost the source line, tsss.
* sign.c (clearsign_file): Avoid duplicated Entries in the "Hash:"
line. Those headers are now only _not_ printed when there are
only old-style keys _and_ all hashs are MD5.
* armor.c (armor_filter): Set a flag if no OpenPGP data has been found.
* verify.c (verify_signatures): Add an error helptext.
(clearsign_file): Use gcry_md_test_algo() and gcry_md_algo_name().
* openfile.c (make_outfile_name): Use case-insenstive compare for
DOS systems. Add ".pgp" to the list of know extensions.
(open_outfile): For DOS systems try to replace the suffix instead of
appending it.
* encr-data.c (decrypt_data): Reset error on a weak key.
* cipher.c: Replaced the cipher and digest functions by the gcry_ ones.
* seckey-cert.c: Ditto.
* seskey.c: Ditto.
* g10.c (print_mds): Replaced digst functions with the new gcry_ ones.
* keyid.c: Ditto.
* mainproc.c: Ditto.
* passphrase.c: Ditto.
* sig-check.c: Ditto.
* sign.c: Ditto.
* pkclist.c (do_edit_ownertrust): Made the answer string const.
* basicdefs.h: New. Move some defs and decl to this header.
Thu Sep 23 19:24:30 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* openfile.c (open_outfile): Fixed the 8dot3 handling.
@ -236,18 +715,34 @@ Tue Oct 26 14:10:21 CEST 1999 Werner Koch <wk@gnupg.de>
* trustdb.c (print_user_id,check_uidsigs): Ditto.
* revoke.c (gen_revoke,ask_revoke_sig): Ditto.
Sat Sep 18 12:16:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
Thu Sep 23 09:52:58 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* filter.h: Changed cipher handle types to the the GCRY_xxx ones.
replaces include cipher by system header include gcrypt.h.
* cipher.c: replaced the cipher functions by the gcry_ ones.
Ditto for the md functions.
* verify.c (print_file_status): New.
(verify_one_file): Moved status print to th new fnc. Add error status.
* status.c, status.h (STATUS_FILE_ERROR): New
* misc.c (map_gcry_rc): New.
Wed Sep 22 10:14:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* openfile.c (make_outfile_name): Use case-insenstive compare for
DOS systems. Add ".pgp" to the list of know extensions.
(open_outfile): For DOS systems try to replace the suffiy instead of
appending it.
* status.c, status.h: Add STATUS_FILE_{START,DONE}.
* verify.c (verify_one_file): Emit these new stati.
* sign.c (clearsign_file): Avoid duplicated Entries in the "Hash:"
line. Those headers are now only _not_ printed when there are
only old-style keys _and_ all hashs are MD5.
Mon Sep 20 12:24:41 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* verify.c (verify_files, ferify_one_file): New.
* g10.c: New command --verify-files
Fri Sep 17 12:56:42 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* g10.c: Add UK spelling as alias for armor options ;-)
* import.c (append_uid): Fixed a SEGV when there is no selfsig and
@ -256,16 +751,13 @@ Fri Sep 17 12:56:42 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
Wed Sep 15 16:22:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* g10.c: New option --entropy-dll-name
Mon Sep 13 10:51:29 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* signal.c (got_fatal_signal): Print message using write(2) and
only for development versions.
Mon Sep 6 19:59:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* tdbio.c (tdbio_set_dbname): Use mkdir macro

View File

@ -6,10 +6,11 @@ OMIT_DEPENDENCIES = zlib.h zconf.h
LDFLAGS = -static @LDFLAGS@ @DYNLINK_LDFLAGS@
# we need to add libutil.la a second time because we have to resolve
# gpg_log_ in some libjnlib modules. - very ugly - should be removed soon.
needed_libs = ../util/libutil.la ../gcrypt/libgcrypt.la ../jnlib/libjnlib.la ../util/libutil.la
needed_libs = ../util/libutil.la ../gcrypt/libgcrypt.la \
../jnlib/libjnlib.la ../util/libutil.la
#noinst_PROGRAMS = gpgd
bin_PROGRAMS = gpg kbxutil
bin_PROGRAMS = gpg kbxutil
common_source = \
build-packet.c \

View File

@ -1,5 +1,5 @@
/* armor.c - Armor flter
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -37,6 +37,11 @@
#include "status.h"
#include "i18n.h"
#ifdef HAVE_DOSISH_SYSTEM
#define LF "\r\n"
#else
#define LF "\n"
#endif
#define MAX_LINELEN 20000
@ -162,6 +167,7 @@ is_armored( const byte *buf )
switch( pkttype ) {
case PKT_MARKER:
case PKT_SYMKEY_ENC:
case PKT_ONEPASS_SIG:
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
case PKT_PUBKEY_ENC:
@ -485,13 +491,26 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
if( !maxlen )
afx->truncated++;
if( !afx->not_dash_escaped ) {
int crlf;
p = afx->buffer;
n = afx->buffer_len;
crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n';
/* PGP2 does not treat a tab as white space character */
afx->buffer_len =
trim_trailing_chars( afx->buffer, afx->buffer_len,
afx->buffer_len = trim_trailing_chars( p, n,
afx->pgp2mode ? " \r\n" : " \t\r\n");
/* the buffer is always allocated with enough space to append
* a CR, LF, Nul */
afx->buffer[afx->buffer_len++] = '\r';
* the removed [CR], LF and a Nul
* The reason for this complicated procedure is to keep at least
* the original tupe of lineending - handling of the removed
* trailing spaces seems to be impossible in our method
* of faking a packet; either we have to use a temporary file
* or calculate the hash here in this module and somehow find
* a way to send the hash down the processing line (well, a special
* faked packet could do the job).
*/
if( crlf )
afx->buffer[afx->buffer_len++] = '\r';
afx->buffer[afx->buffer_len++] = '\n';
afx->buffer[afx->buffer_len] = 0;
}
@ -819,7 +838,8 @@ armor_filter( void *opaque, int control,
hashes &= 1|2|4|8;
if( !hashes ) {
hashes |= 4; /* default to MD 5 */
afx->pgp2mode = 1;
if( opt.pgp2_workarounds )
afx->pgp2mode = 1;
}
n=0;
do {
@ -827,7 +847,7 @@ armor_filter( void *opaque, int control,
buf[n++] = 0x90; /* old format, type 4, 1 length byte */
buf[n++] = 13; /* length */
buf[n++] = 3; /* version */
buf[n++] = 0x01; /* sigclass 0x01 (canonical text mode)*/
buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
if( hashes & 1 ) {
hashes &= ~1;
buf[n++] = GCRY_MD_RMD160;
@ -874,7 +894,7 @@ armor_filter( void *opaque, int control,
#endif
*ret_len = n;
}
else if( control == IOBUFCTRL_FLUSH ) {
else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) {
if( !afx->status ) { /* write the header line */
const char *s;
@ -882,10 +902,10 @@ armor_filter( void *opaque, int control,
log_bug("afx->what=%d", afx->what);
iobuf_writestr(a, "-----");
iobuf_writestr(a, head_strings[afx->what] );
iobuf_writestr(a, "-----\n");
iobuf_writestr(a, "-----" LF );
if( !opt.no_version )
iobuf_writestr(a, "Version: GnuPG v" VERSION " ("
PRINTABLE_OS_NAME ")\n");
PRINTABLE_OS_NAME ")" LF );
/* write the comment string or a default one */
s = opt.comment_string ? opt.comment_string
@ -902,16 +922,17 @@ armor_filter( void *opaque, int control,
else
iobuf_put(a, *s );
}
iobuf_put(a, '\n' );
iobuf_writestr(a, LF );
}
if( afx->hdrlines )
iobuf_writestr(a, afx->hdrlines);
iobuf_put(a, '\n');
iobuf_writestr(a, LF );
afx->status++;
afx->idx = 0;
afx->idx2 = 0;
afx->crc = CRCINIT;
}
crc = afx->crc;
idx = afx->idx;
@ -936,7 +957,7 @@ armor_filter( void *opaque, int control,
c = bintoasc[radbuf[2]&077];
iobuf_put(a, c);
if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
iobuf_put(a, '\n');
iobuf_writestr(a, LF );
idx2=0;
}
}
@ -951,8 +972,13 @@ armor_filter( void *opaque, int control,
if( !is_initialized )
initialize();
}
else if( control == IOBUFCTRL_CANCEL ) {
afx->cancel = 1;
}
else if( control == IOBUFCTRL_FREE ) {
if( afx->status ) { /* pad, write cecksum, and bottom line */
if( afx->cancel )
;
else if( afx->status ) { /* pad, write cecksum, and bottom line */
crc = afx->crc;
idx = afx->idx;
idx2 = afx->idx2;
@ -975,13 +1001,13 @@ armor_filter( void *opaque, int control,
iobuf_put(a, '=');
}
if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
iobuf_put(a, '\n');
iobuf_writestr(a, LF );
idx2=0;
}
}
/* may need a linefeed */
if( idx2 )
iobuf_put(a, '\n');
iobuf_writestr(a, LF );
/* write the CRC */
iobuf_put(a, '=');
radbuf[0] = crc >>16;
@ -995,16 +1021,17 @@ armor_filter( void *opaque, int control,
iobuf_put(a, c);
c = bintoasc[radbuf[2]&077];
iobuf_put(a, c);
iobuf_put(a, '\n');
iobuf_writestr(a, LF );
/* and the the trailer */
if( afx->what >= DIM(tail_strings) )
log_bug("afx->what=%d", afx->what);
iobuf_writestr(a, "-----");
iobuf_writestr(a, tail_strings[afx->what] );
iobuf_writestr(a, "-----\n");
iobuf_writestr(a, "-----" LF );
}
else if( !afx->any_data && !afx->inp_bypass ) {
log_error(_("no valid OpenPGP data found.\n"));
afx->no_openpgp_data = 1;
write_status_text( STATUS_NODATA, "1" );
}
if( afx->truncated )

View File

@ -1,5 +1,5 @@
/* build-packet.c - assemble packets and write them
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -24,11 +24,11 @@
#include <string.h>
#include <assert.h>
#include <gcrypt.h>
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "util.h"
#include <gcrypt.h>
#include "options.h"
#include "main.h"
@ -43,6 +43,7 @@ static u32 calc_plaintext( PKT_plaintext *pt );
static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt );
static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed );
static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed );
static int do_mdc( IOBUF out, PKT_mdc *mdc );
static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd );
static int do_signature( IOBUF out, int ctb, PKT_signature *sig );
static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops );
@ -66,25 +67,31 @@ int
build_packet( IOBUF out, PACKET *pkt )
{
int new_ctb=0, rc=0, ctb;
int pkttype;
if( DBG_PACKET )
log_debug("build_packet() type=%d\n", pkt->pkttype );
assert( pkt->pkt.generic );
switch( pkt->pkttype ) {
case PKT_OLD_COMMENT: pkt->pkttype = PKT_COMMENT; break;
switch( (pkttype = pkt->pkttype) ) {
case PKT_OLD_COMMENT: pkttype = pkt->pkttype = PKT_COMMENT; break;
case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break;
case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break;
case PKT_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break;
case PKT_USER_ID:
if( pkt->pkt.user_id->photo )
pkttype = PKT_PHOTO_ID;
break;
default: break;
}
if( new_ctb || pkt->pkttype > 15 ) /* new format */
ctb = 0xc0 | (pkt->pkttype & 0x3f);
if( new_ctb || pkttype > 15 ) /* new format */
ctb = 0xc0 | (pkttype & 0x3f);
else
ctb = 0x80 | ((pkt->pkttype & 15)<<2);
switch( pkt->pkttype ) {
ctb = 0x80 | ((pkttype & 15)<<2);
switch( pkttype ) {
case PKT_PHOTO_ID:
case PKT_USER_ID:
rc = do_user_id( out, ctb, pkt->pkt.user_id );
break;
@ -114,6 +121,9 @@ build_packet( IOBUF out, PACKET *pkt )
case PKT_ENCRYPTED_MDC:
rc = do_encrypted_mdc( out, ctb, pkt->pkt.encrypted );
break;
case PKT_MDC:
rc = do_mdc( out, pkt->pkt.mdc );
break;
case PKT_COMPRESSED:
rc = do_compressed( out, ctb, pkt->pkt.compressed );
break;
@ -148,6 +158,7 @@ calc_packet_length( PACKET *pkt )
n = calc_plaintext( pkt->pkt.plaintext );
new_ctb = pkt->pkt.plaintext->new_ctb;
break;
case PKT_PHOTO_ID:
case PKT_USER_ID:
case PKT_COMMENT:
case PKT_PUBLIC_KEY:
@ -172,11 +183,11 @@ static void
write_fake_data( IOBUF out, MPI a )
{
if( a ) {
size_t i;
int i;
void *p;
p = gcry_mpi_get_opaque( a, &i );
iobuf_write( out, p, (i+7)/8 );
p = mpi_get_opaque( a, &i );
iobuf_write( out, p, i );
}
}
@ -195,11 +206,20 @@ do_comment( IOBUF out, int ctb, PKT_comment *rem )
static int
do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
{
write_header(out, ctb, uid->len);
uid->stored_at = iobuf_get_temp_length ( out ); /* what a hack ... */
/* ... and it does only work when used with a temp iobuf */
if( iobuf_write( out, uid->name, uid->len ) )
return GPGERR_WRITE_FILE;
if( uid->photo ) {
write_header(out, ctb, uid->photolen);
uid->stored_at = iobuf_get_temp_length ( out ); /* what a hack ... */
/* ... and it does only work when used with a temp iobuf */
if( iobuf_write( out, uid->photo, uid->photolen ) )
return GPGERR_WRITE_FILE;
}
else {
write_header(out, ctb, uid->len);
uid->stored_at = iobuf_get_temp_length ( out ); /* what a hack ... */
/* ... and it does only work when used with a temp iobuf */
if( iobuf_write( out, uid->name, uid->len ) )
return GPGERR_WRITE_FILE;
}
return 0;
}
@ -358,19 +378,30 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
else {
iobuf_put(a, 0xff );
iobuf_put(a, sk->protect.algo );
iobuf_put(a, sk->protect.s2k.mode );
iobuf_put(a, sk->protect.s2k.hash_algo );
if( sk->protect.s2k.mode >= 1000 ) {
iobuf_put(a, 101 );
iobuf_put(a, sk->protect.s2k.hash_algo );
iobuf_write(a, "GNU", 3 );
iobuf_put(a, sk->protect.s2k.mode - 1000 );
}
else {
iobuf_put(a, sk->protect.s2k.mode );
iobuf_put(a, sk->protect.s2k.hash_algo );
}
if( sk->protect.s2k.mode == 1
|| sk->protect.s2k.mode == 3 )
iobuf_write(a, sk->protect.s2k.salt, 8 );
if( sk->protect.s2k.mode == 3 )
iobuf_put(a, sk->protect.s2k.count );
iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
if( sk->protect.s2k.mode != 1001 )
iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
}
}
else
iobuf_put(a, 0 );
if( sk->is_protected && sk->version >= 4 ) {
if( sk->protect.s2k.mode == 1001 )
;
else if( sk->is_protected && sk->version >= 4 ) {
byte *p;
size_t n;
assert( gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
@ -379,7 +410,7 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
}
else {
for( ; i < nskey; i++ )
mpi_write_opaque(a, sk->skey[i] );
mpi_write(a, sk->skey[i] );
write_16(a, sk->csum );
}
@ -527,13 +558,24 @@ do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed )
n = ed->len ? (ed->len + 10) : 0;
write_header(out, ctb, n );
iobuf_put(out, 1 ); /* version */
iobuf_put(out, ed->mdc_method );
/* This is all. The caller has to write the real data */
return rc;
}
static int
do_mdc( IOBUF out, PKT_mdc *mdc )
{
/* This packet requires a fixed header encoding */
iobuf_put( out, 0xd3 ); /* packet ID and 1 byte length */
iobuf_put( out, 0x14 ); /* length = 20 */
if( iobuf_write( out, mdc->hash, sizeof(mdc->hash) ) )
return GPGERR_WRITE_FILE;
return 0;
}
static int
do_compressed( IOBUF out, int ctb, PKT_compressed *cd )
{
@ -623,7 +665,6 @@ void
build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
const byte *buffer, size_t buflen )
{
byte *data;
size_t hlen, dlen, nlen;
int found=0;
@ -659,6 +700,7 @@ build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
case SIGSUBPKT_KEY_EXPIRE:
case SIGSUBPKT_NOTATION:
case SIGSUBPKT_POLICY:
case SIGSUBPKT_REVOC_REASON:
hashed = 1; break;
default: hashed = 0; break;
}

View File

@ -1,5 +1,5 @@
/* cipher.c - En-/De-ciphering filter
* Copyright (C) 1998,1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -33,6 +33,7 @@
#include "packet.h"
#include "options.h"
#include "main.h"
#include "status.h"
#define MIN_PARTIAL_SIZE 512
@ -44,10 +45,18 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
PACKET pkt;
PKT_encrypted ed;
byte temp[18];
int blocksize;
unsigned nprefix;
int use_mdc = opt.force_mdc;
unsigned int blocksize;
unsigned int nprefix;
int rc;
int use_mdc = opt.force_mdc;
blocksize = gcry_cipher_get_algo_blklen( cfx->dek->algo );
if( blocksize < 8 || blocksize > 16 )
log_fatal("unsupported blocksize %u\n", blocksize );
if( blocksize != 8 )
use_mdc = 1; /* enable it for all modern ciphers */
if( opt.rfc2440 )
use_mdc = 0; /* override - rfc2440 does not know about MDC */
memset( &ed, 0, sizeof ed );
ed.len = cfx->datalen;
@ -55,18 +64,16 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
if( use_mdc ) {
ed.mdc_method = GCRY_MD_SHA1;
cfx->mdc_hash = gcry_md_open( GCRY_MD_SHA1, 0 );
/*should we check the function works, or is it better to provide
a flag which makes the function die itself ?? FIXME */
/*md_start_debug( cfx->mdc_hash, "mdccreat" );*/
if( !cfx->mdc_hash )
BUG();
if ( DBG_HASHING )
gcry_md_start_debug( cfx->mdc_hash, "creatmdc" );
}
init_packet( &pkt );
pkt.pkttype = use_mdc? PKT_ENCRYPTED_MDC : PKT_ENCRYPTED;
pkt.pkt.encrypted = &ed;
if( build_packet( a, &pkt ))
log_bug("build_packet(ENCR_DATA) failed\n");
blocksize = gcry_cipher_get_algo_blklen( cfx->dek->algo );
if( blocksize < 8 || blocksize > 16 )
log_fatal("unsupported blocksize %d\n", blocksize );
nprefix = blocksize;
gcry_randomize( temp, nprefix, GCRY_STRONG_RANDOM );
temp[nprefix] = temp[nprefix-2];
@ -75,7 +82,7 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
if( !(cfx->cipher_hd = gcry_cipher_open( cfx->dek->algo,
GCRY_CIPHER_MODE_CFB,
GCRY_CIPHER_SECURE
| (cfx->dek->algo >= 100 ?
| ((use_mdc || cfx->dek->algo >= 100) ?
0 : GCRY_CIPHER_ENABLE_SYNC)))
) {
/* we should never get an error here cause we already checked, that
@ -83,6 +90,7 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
BUG();
}
/* log_hexdump( "thekey", cfx->dek->key, cfx->dek->keylen );*/
rc = gcry_cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen );
if( !rc )
@ -99,6 +107,7 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
log_fatal("encrypt failed: %s\n", gcry_strerror(rc) );
iobuf_write(a, temp, nprefix+2);
cfx->header=1;
}
@ -120,6 +129,7 @@ cipher_filter( void *opaque, int control,
else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
assert(a);
if( !cfx->header ) {
write_status( STATUS_BEGIN_ENCRYPTION );
write_header( cfx, a );
}
if( cfx->mdc_hash )
@ -134,15 +144,26 @@ cipher_filter( void *opaque, int control,
if( cfx->mdc_hash ) {
byte *hash;
int hashlen = gcry_md_get_algo_dlen( gcry_md_get_algo( cfx->mdc_hash ) );
byte temp[22];
assert( hashlen == 20 );
/* we must hash the prefix of the MDC packet here */
temp[0] = 0xd3;
temp[1] = 0x14;
gcry_md_putc( cfx->mdc_hash, temp[0] );
gcry_md_putc( cfx->mdc_hash, temp[1] );
hash = gcry_md_read( cfx->mdc_hash, 0 );
rc = gcry_cipher_encrypt( cfx->cipher_hd, hash, hashlen, NULL, 0 );
memcpy(temp+2, hash, 20);
rc = gcry_cipher_encrypt( cfx->cipher_hd, temp, 22, NULL, 0 );
if( rc )
log_fatal("encrypt failed: %s\n", gcry_strerror(rc) );
if( iobuf_write( a, hash, hashlen ) )
rc = GPGERR_WRITE_FILE;
gcry_md_close( cfx->mdc_hash ); cfx->mdc_hash = NULL;
if( iobuf_write( a, temp, 22 ) )
log_error("writing MDC packet failed\n" );
}
gcry_cipher_close(cfx->cipher_hd);
write_status( STATUS_END_ENCRYPTION );
}
else if( control == IOBUFCTRL_DESC ) {
*(char**)buf = "cipher_filter";

View File

@ -1,5 +1,5 @@
/* comment.c - write comment stuff
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*

View File

@ -1,5 +1,5 @@
/* compress.c - compress filter
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -27,8 +27,8 @@
#include <errno.h>
#include <zlib.h>
#include "util.h"
#include <gcrypt.h>
#include "util.h"
#include "packet.h"
#include "filter.h"
#include "options.h"

View File

@ -1,5 +1,5 @@
/* dearmor.c - Armor utility
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -25,9 +25,9 @@
#include <errno.h>
#include <assert.h>
#include <gcrypt.h>
#include "errors.h"
#include "iobuf.h"
#include <gcrypt.h>
#include "util.h"
#include "filter.h"
#include "packet.h"

View File

@ -1,5 +1,5 @@
/* decrypt.c - verify signed data
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -25,12 +25,12 @@
#include <errno.h>
#include <assert.h>
#include <gcrypt.h>
#include "options.h"
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include <gcrypt.h>
#include "util.h"
#include "main.h"
#include "i18n.h"

View File

@ -1,5 +1,5 @@
/* delkey.c - delete keys
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -62,6 +62,7 @@ delete_key( const char *username, int secret )
: find_keyblock_byname( &kbpos, username );
if( rc ) {
log_error(_("%s: user not found\n"), username );
write_status_text( STATUS_DELETE_PROBLEM, "1" );
goto leave;
}
@ -93,10 +94,12 @@ delete_key( const char *username, int secret )
"there is a secret key for this public key!\n"));
log_info(_(
"use option \"--delete-secret-key\" to delete it first.\n"));
write_status_text( STATUS_DELETE_PROBLEM, "2" );
rc = -1;
}
else if( rc != GPGERR_NO_SECKEY )
else if( rc != GPGERR_NO_SECKEY ) {
log_error("%s: get secret key: %s\n", username, gpg_errstr(rc) );
}
else
rc = 0;
}

View File

@ -1,5 +1,5 @@
/* encode.c - encode data
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -41,6 +41,7 @@
static int encode_simple( const char *filename, int mode );
static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out );
/****************
* Emulate our old PK interface here - sometime in the future we might
* change the internal design to directly fit to libgcrypt.
@ -162,7 +163,7 @@ encode_simple( const char *filename, int mode )
}
if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) {
iobuf_close(inp);
iobuf_cancel(inp);
gcry_free(cfx.dek);
gcry_free(s2k);
return rc;
@ -510,7 +511,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
* number of bits we have to use. We then encode the session
* key in some way and we get it back in the big intger value
* FRAME. Then we use FRAME, the public key PK->PKEY and the
* algorithm number PK->PUBKEY_ALGO and pass it to pk_encrypt
* algorithm number PK->PUBKEY_ALGO and pass it to pubkey_encrypt
* which returns the encrypted value in the array ENC->DATA.
* This array has a size which depends on the used algorithm
* (e.g. 2 for ElGamal). We don't need frame anymore because we
@ -525,7 +526,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
log_error("pubkey_encrypt failed: %s\n", gpg_errstr(rc) );
else {
if( opt.verbose ) {
char *ustr = get_user_id_string( enc->keyid );
char *ustr = get_user_id_string_native( enc->keyid );
log_info(_("%s/%s encrypted for: %s\n"),
gcry_pk_algo_name(enc->pubkey_algo),
gcry_cipher_algo_name(dek->algo), ustr );

View File

@ -1,5 +1,5 @@
/* encr-data.c - process an encrypted data packet
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -23,6 +23,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <gcrypt.h>
#include "util.h"
#include "packet.h"
@ -30,9 +31,9 @@
#include "i18n.h"
static int decode_filter( void *opaque, int control, IOBUF a,
byte *buf, size_t *ret_len);
static int mdc_decode_filter( void *opaque, int control, IOBUF a,
byte *buf, size_t *ret_len);
static int decode_filter( void *opaque, int control, IOBUF a,
byte *buf, size_t *ret_len);
typedef struct {
@ -54,8 +55,8 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
byte *p;
int rc=0, c, i;
byte temp[32];
int blocksize;
unsigned nprefix;
unsigned int blocksize;
unsigned int nprefix;
memset( &dfx, 0, sizeof dfx );
if( gcry_cipher_test_algo( dek->algo ) ) {
@ -68,7 +69,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
log_info(_("%s encrypted data\n"), gcry_cipher_algo_name( dek->algo ) );
blocksize = gcry_cipher_get_algo_blklen( dek->algo );
if( blocksize < 1 || blocksize > 16 )
if( !blocksize || blocksize > 16 )
log_fatal("unsupported blocksize %u\n", blocksize );
nprefix = blocksize;
if( ed->len && ed->len < (nprefix+2) )
@ -76,13 +77,13 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
if( ed->mdc_method ) {
dfx.mdc_hash = gcry_md_open( ed->mdc_method, 0 );
if( !dfx.mdc_hash )
BUG();
if ( DBG_HASHING )
gcry_md_start_debug(dfx.mdc_hash, "checkmdc");
}
if( !(dfx.cipher_hd = gcry_cipher_open( dek->algo,
GCRY_CIPHER_MODE_CFB,
GCRY_CIPHER_SECURE
| (dek->algo >= 100 ?
| ((ed->mdc_method || dek->algo >= 100)?
0 : GCRY_CIPHER_ENABLE_SYNC) ))
) {
/* we should never get an error here cause we already checked, that
@ -122,8 +123,6 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
temp[i] = c;
}
gcry_cipher_decrypt( dfx.cipher_hd, temp, nprefix+2, NULL, 0 );
if( dfx.mdc_hash )
gcry_md_write( dfx.mdc_hash, temp, nprefix+2 );
gcry_cipher_sync( dfx.cipher_hd );
p = temp;
/* log_hexdump( "prefix", temp, nprefix+2 ); */
@ -131,22 +130,30 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
rc = GPGERR_BAD_KEY;
goto leave;
}
if( dfx.mdc_hash )
gcry_md_write( dfx.mdc_hash, temp, nprefix+2 );
if( ed->mdc_method )
iobuf_push_filter( ed->buf, mdc_decode_filter, &dfx );
else
iobuf_push_filter( ed->buf, decode_filter, &dfx );
proc_packets( procctx, ed->buf);
proc_packets( procctx, ed->buf );
ed->buf = NULL;
if( ed->mdc_method && dfx.eof_seen == 2 )
rc = GPGERR_INVALID_PACKET;
else if( ed->mdc_method ) { /* check the mdc */
int datalen = gcry_md_get_algo_dlen( ed->mdc_method );
gcry_cipher_decrypt( dfx.cipher_hd, dfx.defer, 20, NULL, 0);
if( datalen != 20
|| memcmp(gcry_md_read( dfx.mdc_hash, 0 ), dfx.defer, datalen) )
rc = GPGERR_BAD_SIGN;
log_hexdump("MDC calculated:", gcry_md_read( dfx.mdc_hash, 0), datalen);
log_hexdump("MDC message :", dfx.defer, 20);
/*log_hexdump("MDC calculated:", md_read( dfx.mdc_hash, 0), datalen);*/
/*log_hexdump("MDC message :", dfx.defer, 20);*/
}
leave:
gcry_cipher_close(dfx.cipher_hd);
gcry_md_close( dfx.mdc_hash );
@ -154,6 +161,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
}
/* I think we should merge this with cipher_filter */
static int
mdc_decode_filter( void *opaque, int control, IOBUF a,
@ -180,11 +188,14 @@ mdc_decode_filter( void *opaque, int control, IOBUF a,
}
if( n == 40 ) {
/* we have enough stuff - flush the deferred stuff */
/* (we have asserted that the buffer is large enough */
if( !dfx->defer_filled ) /* the first time */
/* (we have asserted that the buffer is large enough) */
if( !dfx->defer_filled ) { /* the first time */
memcpy(buf, buf+20, 20 );
else
n = 20;
}
else {
memcpy(buf, dfx->defer, 20 );
}
/* now fill up */
for(; n < size; n++ ) {
if( (c = iobuf_get(a)) == -1 )
@ -198,7 +209,7 @@ mdc_decode_filter( void *opaque, int control, IOBUF a,
dfx->defer_filled = 1;
}
else if( !dfx->defer_filled ) { /* eof seen buf empty defer */
/* this is very bad because there is an incomplete hash */
/* this is bad because there is an incomplete hash */
n -= 20;
memcpy(buf, buf+20, n );
dfx->eof_seen = 2; /* eof with incomplete hash */
@ -238,7 +249,7 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
n = iobuf_read( a, buf, size );
if( n == -1 ) n = 0;
if( n )
gcry_cipher_decrypt( fc->cipher_hd, buf, n, NULL, 0);
gcry_cipher_decrypt( fc->cipher_hd, buf, n, NULL, 0 );
else
rc = -1; /* eof */
*ret_len = n;

View File

@ -1,5 +1,5 @@
/* export.c
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -25,11 +25,11 @@
#include <errno.h>
#include <assert.h>
#include <gcrypt.h>
#include "options.h"
#include "packet.h"
#include "errors.h"
#include "keydb.h"
#include <gcrypt.h>
#include "util.h"
#include "main.h"
#include "i18n.h"
@ -71,6 +71,12 @@ export_seckeys( STRLIST users )
return do_export( users, 1, 0 );
}
int
export_secsubkeys( STRLIST users )
{
return do_export( users, 2, 0 );
}
static int
do_export( STRLIST users, int secret, int onlyrfc )
{
@ -168,6 +174,16 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
}
}
/* we can't apply GNU mode 1001 on an unprotected key */
if( secret == 2
&& (node = find_kbnode( keyblock, PKT_SECRET_KEY ))
&& !node->pkt->pkt.secret_key->is_protected )
{
log_info(_("key %08lX: not protected - skipped\n"),
(ulong)keyid_from_sk( node->pkt->pkt.secret_key, NULL) );
continue;
}
/* and write it */
for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) {
/* don't export any comment packets but those in the
@ -183,7 +199,20 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
continue; /* not exportable */
}
if( (rc = build_packet( out, node->pkt )) ) {
if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY ) {
/* we don't want to export the secret parts of the
* primary key, this is done by using GNU protection mode 1001
*/
int save_mode = node->pkt->pkt.secret_key->protect.s2k.mode;
node->pkt->pkt.secret_key->protect.s2k.mode = 1001;
rc = build_packet( out, node->pkt );
node->pkt->pkt.secret_key->protect.s2k.mode = save_mode;
}
else {
rc = build_packet( out, node->pkt );
}
if( rc ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, gpg_errstr(rc) );
rc = GPGERR_WRITE_FILE;

View File

@ -1,5 +1,5 @@
/* filter.h
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -26,7 +26,6 @@
#include "iobuf.h"
typedef struct {
GCRY_MD_HD md; /* catch all */
GCRY_MD_HD md2; /* if we want to calculate an alternate hash */
@ -39,6 +38,9 @@ typedef struct {
int only_keyblocks; /* skip all headers but ".... key block" */
const char *hdrlines; /* write these headerlines */
/* these fileds must be initialized to zero */
int no_openpgp_data; /* output flag: "No valid OpenPGP data found" */
/* the following fields must be initialized to zero */
int inp_checked; /* set if the input has been checked */
int inp_bypass; /* set if the input is not armored */
@ -60,6 +62,7 @@ typedef struct {
u32 crc;
int status; /* an internal state flag */
int cancel;
int any_data; /* any valid armored data seen */
int pending_lf; /* used together with faked */
} armor_filter_context_t;
@ -83,6 +86,8 @@ typedef struct {
GCRY_CIPHER_HD cipher_hd;
int header;
GCRY_MD_HD mdc_hash;
byte enchash[20];
int create_mdc; /* flag will be set by the cipher filter */
} cipher_filter_context_t;
@ -93,7 +98,6 @@ typedef struct {
} encrypt_filter_context_t;
typedef struct {
byte *buffer; /* malloced buffer */
unsigned buffer_size; /* and size of this buffer */
@ -108,8 +112,6 @@ typedef struct {
} text_filter_context_t;
/* encrypt_filter_context_t defined in main.h */
/*-- mdfilter.c --*/
int md_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len);
void free_md_filter_context( md_filter_context_t *mfx );

View File

@ -1,5 +1,5 @@
/* free-packet.c - cleanup stuff for packets
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -24,10 +24,10 @@
#include <string.h>
#include <assert.h>
#include <gcrypt.h>
#include "packet.h"
#include "iobuf.h"
#include "util.h"
#include <gcrypt.h>
#include "options.h"
#include "main.h"
@ -219,6 +219,8 @@ free_comment( PKT_comment *rem )
void
free_user_id( PKT_user_id *uid )
{
if( uid->photo )
gcry_free( uid->photo );
gcry_free(uid);
}

View File

@ -1,5 +1,5 @@
/* getkey.c - Get a key from the database
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -24,9 +24,10 @@
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <gcrypt.h>
#include "util.h"
#include "packet.h"
#include <gcrypt.h>
#include "iobuf.h"
#include "keydb.h"
#include "options.h"
@ -45,7 +46,11 @@
* that they are all valid.
* Note: We must use numerical values here in case that this program
* will be converted to those little blue HAL9000s with their strange
* EBCDIC character set (user ids are UTF-8). */
* EBCDIC character set (user ids are UTF-8).
* wk 2000-04-13: Hmmm, does this really make sense, given the fact that
* we can run gpg now on a S/390 running GNU/Linux, where the code
* translation is done by the device drivers?
*/
static const byte word_match_chars[256] = {
/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -154,6 +159,7 @@ static int uid_cache_entries; /* number of entries in uid cache */
static char* prepare_word_match( const byte *name );
static int lookup_pk( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_kb );
static int lookup_sk( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_kb );
static u32 subkeys_expiretime( KBNODE node, u32 *mainkid );
#if 0
@ -696,6 +702,8 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
STRLIST r;
GETKEY_CTX ctx;
if( retctx ) /* reset the returned context in case of error */
*retctx = NULL;
assert( !pk ^ !sk );
/* build the search context */
@ -941,7 +949,7 @@ get_seckey_bynames( GETKEY_CTX *retctx, PKT_secret_key *sk,
if( !sk ) {
/* Performance Hint: key_byname should not need a sk here */
sk = gcry_xcalloc_secure( 1, sizeof *sk );
sk = gcry_xcalloc_secure( 1, sizeof *sk );
rc = key_byname( retctx, names, NULL, sk, ret_keyblock );
free_secret_key( sk );
}
@ -959,7 +967,7 @@ get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock )
if( !sk ) {
/* Performance Hint: lookup_read should not need a pk in this case */
sk = gcry_xcalloc_secure( 1, sizeof *sk );
sk = gcry_xcalloc_secure( 1, sizeof *sk );
rc = lookup_sk( ctx, sk, ret_keyblock );
free_secret_key( sk );
}
@ -1150,7 +1158,7 @@ merge_one_pk_and_selfsig( KBNODE keyblock, KBNODE knode,
k = find_kbnode( keyblock, PKT_PUBLIC_KEY );
if( !k )
BUG(); /* keyblock without primary key!!! */
keyid_from_pk( knode->pkt->pkt.public_key, kid );
keyid_from_pk( k->pkt->pkt.public_key, kid );
}
else
keyid_from_pk( pk, kid );
@ -1208,6 +1216,10 @@ merge_keys_and_selfsig( KBNODE keyblock )
pk = NULL; /* not needed for old keys */
else if( k->pkt->pkttype == PKT_PUBLIC_KEY )
keyid_from_pk( pk, kid );
else if( !pk->expiredate ) { /* and subkey */
/* insert the expiration date here */
pk->expiredate = subkeys_expiretime( k, kid );
}
sigdate = 0;
}
else if( k->pkt->pkttype == PKT_SECRET_KEY
@ -1222,8 +1234,11 @@ merge_keys_and_selfsig( KBNODE keyblock )
else if( (pk || sk ) && k->pkt->pkttype == PKT_SIGNATURE
&& (sig=k->pkt->pkt.signature)->sig_class >= 0x10
&& sig->sig_class <= 0x30 && sig->version > 3
&& !(sig->sig_class == 0x18 || sig->sig_class == 0x28)
&& sig->keyid[0] == kid[0] && sig->keyid[1] == kid[1] ) {
/* okay this is a self-signature which can be used.
* This is not used for subkey binding signature, becuase this
* is done above.
* FIXME: We should only use this if the signature is valid
* but this is time consuming - we must provide another
* way to handle this
@ -1279,9 +1294,16 @@ find_by_name( KBNODE keyblock, PKT_public_key *pk, const char *name,
u32 aki[2];
keyid_from_pk( kk->pkt->pkt.public_key, aki );
cache_user_id( k->pkt->pkt.user_id, aki );
gcry_md_hash_buffer( GCRY_MD_RMD160, namehash,
k->pkt->pkt.user_id->name,
k->pkt->pkt.user_id->len );
if( k->pkt->pkt.user_id->photo ) {
gcry_md_hash_buffer( GCRY_MD_RMD160, namehash,
k->pkt->pkt.user_id->photo,
k->pkt->pkt.user_id->photolen );
}
else {
gcry_md_hash_buffer( GCRY_MD_RMD160, namehash,
k->pkt->pkt.user_id->name,
k->pkt->pkt.user_id->len );
}
*use_namehash = 1;
return kk;
}
@ -1516,6 +1538,56 @@ find_by_fpr_sk( KBNODE keyblock, PKT_secret_key *sk,
}
/****************
* Return the expiretime of a subkey.
*/
static u32
subkeys_expiretime( KBNODE node, u32 *mainkid )
{
KBNODE k;
PKT_signature *sig;
u32 expires = 0, sigdate = 0;
assert( node->pkt->pkttype == PKT_PUBLIC_SUBKEY );
for(k=node->next; k; k = k->next ) {
if( k->pkt->pkttype == PKT_SIGNATURE
&& (sig=k->pkt->pkt.signature)->sig_class == 0x18
&& sig->keyid[0] == mainkid[0]
&& sig->keyid[1] == mainkid[1]
&& sig->version > 3
&& sig->timestamp > sigdate ) {
/* okay this is a key-binding which can be used.
* We use the latest self-signature.
* FIXME: We should only use this if the binding signature is valid
* but this is time consuming - we must provide another
* way to handle this
*/
const byte *p;
u32 ed;
p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL );
ed = p? node->pkt->pkt.public_key->timestamp + buffer_to_u32(p):0;
sigdate = sig->timestamp;
expires = ed;
}
else if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY )
break; /* stop at the next subkey */
}
return expires;
}
/****************
* Check whether the subkey has expired. Node must point to the subkey
*/
static int
has_expired( KBNODE node, u32 *mainkid, u32 cur_time )
{
u32 expires = subkeys_expiretime( node, mainkid );
return expires && expires <= cur_time;
}
static void
finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash,
int use_namehash, int primary )
@ -1534,6 +1606,10 @@ finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash,
pk->pubkey_usage ) == GPGERR_WR_PUBKEY_ALGO ) {
/* if the usage is not correct, try to use a subkey */
KBNODE save_k = k;
u32 mainkid[2];
u32 cur_time = make_timestamp();
keyid_from_pk( keyblock->pkt->pkt.public_key, mainkid );
k = NULL;
/* kludge for pgp 5: which doesn't accept type 20:
@ -1545,7 +1621,8 @@ finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash,
== GCRY_PK_ELG_E
&& !openpgp_pk_test_algo(
k->pkt->pkt.public_key->pubkey_algo,
pk->pubkey_usage ) )
pk->pubkey_usage )
&& !has_expired(k, mainkid, cur_time) )
break;
}
}
@ -1555,7 +1632,10 @@ finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash,
if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY
&& !openpgp_pk_test_algo(
k->pkt->pkt.public_key->pubkey_algo,
pk->pubkey_usage ) )
pk->pubkey_usage )
&& ( pk->pubkey_usage != GCRY_PK_USAGE_ENCR
|| !has_expired( k, mainkid, cur_time ) )
)
break;
}
}
@ -1887,6 +1967,18 @@ get_user_id_string( u32 *keyid )
return p;
}
char*
get_user_id_string_native( u32 *keyid )
{
char *p = get_user_id_string( keyid );
char *p2 = utf8_to_native( p, strlen(p) );
gcry_free(p);
return p2;
}
char*
get_long_user_id_string( u32 *keyid )
{
@ -1914,6 +2006,7 @@ get_user_id( u32 *keyid, size_t *rn )
user_id_db_t r;
char *p;
int pass=0;
/* try it two times; second pass reads from key resources */
do {
for(r=user_id_db; r; r = r->next )
@ -1924,9 +2017,8 @@ get_user_id( u32 *keyid, size_t *rn )
return p;
}
} while( ++pass < 2 && !get_pubkey( NULL, keyid ) );
p = gcry_xmalloc( 19 );
memcpy(p, "[User id not found]", 19 );
*rn = 19;
p = gcry_xstrdup( _("[User id not found]") );
*rn = strlen(p);
return p;
}

279
g10/gpg.c
View File

@ -26,8 +26,8 @@
#include <ctype.h>
#include <unistd.h>
#include <gcrypt.h>
#include <gcrypt.h>
#include "packet.h"
#include "iobuf.h"
#include "util.h"
@ -77,6 +77,7 @@ enum cmd_and_opt_values { aNull = 0,
aImport,
aFastImport,
aVerify,
aVerifyFiles,
aListKeys,
aListSigs,
aListSecretKeys,
@ -85,12 +86,13 @@ enum cmd_and_opt_values { aNull = 0,
aExport,
aExportAll,
aExportSecret,
aExportSecretSub,
aCheckKeys,
aGenRevoke,
aPrimegen,
aPrintMD,
aPrintHMAC,
aPrintMDs,
aPrintHMAC,
aCheckTrustDB,
aUpdateTrustDB,
aFixTrustDB,
@ -130,6 +132,7 @@ enum cmd_and_opt_values { aNull = 0,
oDigestAlgo,
oCompressAlgo,
oPasswdFD,
oCommandFD,
oNoVerbose,
oTrustDBName,
oNoSecmemWarn,
@ -146,7 +149,6 @@ enum cmd_and_opt_values { aNull = 0,
oCompressKeys,
oCompressSigs,
oAlwaysTrust,
oEmuChecksumBug,
oRunAsShmCP,
oSetFilename,
oSetPolicyURL,
@ -164,6 +166,7 @@ enum cmd_and_opt_values { aNull = 0,
oEscapeFrom,
oLockOnce,
oLockMultiple,
oLockNever,
oKeyServer,
oEncryptTo,
oNoEncryptTo,
@ -175,7 +178,14 @@ enum cmd_and_opt_values { aNull = 0,
oAllowNonSelfsignedUID,
oNoLiteral,
oSetFilesize,
oEntropyDLLName,
oHonorHttpProxy,
oFastListMode,
oListOnly,
oIgnoreTimeConflict,
oNoRandomSeedFile,
oNoAutoKeyRetrieve,
oEmu3DESS2KBug, /* will be removed in 1.1 */
oEmuMDEncodeBug,
aTest };
@ -191,6 +201,7 @@ static ARGPARSE_OPTS opts[] = {
{ aStore, "store", 256, N_("store only")},
{ aDecrypt, "decrypt", 256, N_("decrypt data (default)")},
{ aVerify, "verify" , 256, N_("verify a signature")},
{ aVerifyFiles, "verify-files" , 256, "@" },
{ aListKeys, "list-keys", 256, N_("list keys")},
{ aListKeys, "list-public-keys", 256, "@" },
{ aListSigs, "list-sigs", 256, N_("list keys and signatures")},
@ -210,6 +221,7 @@ static ARGPARSE_OPTS opts[] = {
{ aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") },
{ aExportAll, "export-all" , 256, "@" },
{ aExportSecret, "export-secret-keys" , 256, "@" },
{ aExportSecretSub, "export-secret-subkeys" , 256, "@" },
{ aImport, "import", 256 , N_("import/merge keys")},
{ aFastImport, "fast-import", 256 , "@"},
{ aListPackets, "list-packets",256,N_("list only the sequence of packets")},
@ -266,12 +278,12 @@ static ARGPARSE_OPTS opts[] = {
{ oCharset, "charset" , 2, N_("|NAME|set terminal charset to NAME") },
{ oOptions, "options" , 2, N_("read options from file")},
{ oDebug, "debug" ,4|16, N_("set debugging flags")},
{ oDebugAll, "debug-all" ,0, N_("enable full debugging")},
{ oDebug, "debug" ,4|16, "@"},
{ oDebugAll, "debug-all" ,0, "@"},
{ oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") },
{ oNoComment, "no-comment", 0, N_("do not write comment packets")},
{ oCompletesNeeded, "completes-needed", 1, N_("(default is 1)")},
{ oMarginalsNeeded, "marginals-needed", 1, N_("(default is 3)")},
{ oNoComment, "no-comment", 0, "@"},
{ oCompletesNeeded, "completes-needed", 1, "@"},
{ oMarginalsNeeded, "marginals-needed", 1, "@"},
{ oMaxCertDepth, "max-cert-depth", 1, "@" },
{ oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")},
{ oRFC1991, "rfc1991", 0, N_("emulate the mode described in RFC1991")},
@ -287,7 +299,11 @@ static ARGPARSE_OPTS opts[] = {
{ oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")},
{ oNotation, "notation-data", 2, N_("|NAME=VALUE|use this notation data")},
{ 302, NULL, 0, N_("@\nExamples:\n\n"
{ 302, NULL, 0, N_(
"@\n(See the man page for a complete listing of all commands and options)\n"
)},
{ 303, NULL, 0, N_("@\nExamples:\n\n"
" -se -r Bob [file] sign and encrypt for user Bob\n"
" --clearsign [file] make a clear text signature\n"
" --detach-sign [file] make a detached signature\n"
@ -301,6 +317,7 @@ static ARGPARSE_OPTS opts[] = {
{ aListTrustPath, "list-trust-path",0, "@"},
{ oKOption, NULL, 0, "@"},
{ oPasswdFD, "passphrase-fd",1, "@" },
{ oCommandFD, "command-fd",1, "@" },
{ oNoVerbose, "no-verbose", 0, "@"},
{ oTrustDBName, "trustdb-name", 2, "@" },
{ oNoSecmemWarn, "no-secmem-warning", 0, "@" }, /* used only by regression tests */
@ -331,6 +348,7 @@ static ARGPARSE_OPTS opts[] = {
{ oEscapeFrom, "escape-from-lines", 0, "@" },
{ oLockOnce, "lock-once", 0, "@" },
{ oLockMultiple, "lock-multiple", 0, "@" },
{ oLockNever, "lock-never", 0, "@" },
{ oLoggerFD, "logger-fd",1, "@" },
{ oUseEmbeddedFilename, "use-embedded-filename", 0, "@" },
{ oUtf8Strings, "utf8-strings", 0, "@" },
@ -341,7 +359,14 @@ static ARGPARSE_OPTS opts[] = {
{ oAllowNonSelfsignedUID, "allow-non-selfsigned-uid", 0, "@" },
{ oNoLiteral, "no-literal", 0, "@" },
{ oSetFilesize, "set-filesize", 20, "@" },
{ oEntropyDLLName, "entropy-dll-name", 2, "@" },
{ oHonorHttpProxy,"honor-http-proxy", 0, "@" },
{ oFastListMode,"fast-list-mode", 0, "@" },
{ oListOnly, "list-only", 0, "@"},
{ oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" },
{ oNoRandomSeedFile, "no-random-seed-file", 0, "@" },
{ oNoAutoKeyRetrieve, "no-auto-key-retrieve", 0, "@" },
{ oEmu3DESS2KBug, "emulate-3des-s2k-bug", 0, "@"},
{ oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"},
{0} };
@ -351,8 +376,8 @@ int gpg_errors_seen = 0;
static int utf8_strings = 0;
static int maybe_setuid = 1;
static char *build_list( const char *text, const char * (*mapf)(int),
int (*chkf)(int) );
static char *build_list( const char *text,
const char *(*mapf)(int), int (*chkf)(int) );
static void set_cmd( enum cmd_and_opt_values *ret_cmd,
enum cmd_and_opt_values new_cmd );
static void print_hex( byte *p, size_t n );
@ -360,13 +385,13 @@ static void print_mds( const char *fname, int algo, const char *key );
static void add_notation_data( const char *string );
static int check_policy_url( const char *s );
static int
our_pk_test_algo( int algo )
{
return openpgp_pk_test_algo( algo, 0 );
}
static const char *
my_strusage( int level )
{
@ -390,26 +415,29 @@ my_strusage( int level )
"default operation depends on the input data\n");
break;
case 31: p = _("\nSupported algorithms:\n"); break;
case 32:
case 31: p = "\nHome: "; break;
case 32: p = opt.homedir; break;
case 33: p = _("\nSupported algorithms:\n"); break;
case 34:
if( !ciphers )
ciphers = build_list("Cipher: ", gcry_cipher_algo_name,
openpgp_cipher_test_algo );
p = ciphers;
break;
case 33:
case 35:
if( !pubkeys )
pubkeys = build_list("Pubkey: ", gcry_pk_algo_name,
our_pk_test_algo );
p = pubkeys;
break;
case 34:
case 36:
if( !digests )
digests = build_list("Hash: ", gcry_md_algo_name,
openpgp_md_test_algo );
p = digests;
break;
default: p = NULL;
}
return p;
@ -465,27 +493,6 @@ i18n_init(void)
#endif
}
static void
wrong_args( const char *text)
{
fputs(_("usage: gpg [options] "),stderr);
fputs(text,stderr);
putc('\n',stderr);
gpg_exit(2);
}
static char *
make_username( const char *string )
{
char *p;
if( utf8_strings )
p = native_to_utf8( string );
else
p = gcry_xstrdup(string);
return p;
}
static void
register_extension( const char *mainpgm, const char *fname )
@ -509,16 +516,38 @@ register_extension( const char *mainpgm, const char *fname )
static void
wrong_args( const char *text)
{
fputs(_("usage: gpg [options] "),stderr);
fputs(text,stderr);
putc('\n',stderr);
gpg_exit(2);
}
static char *
make_username( const char *string )
{
char *p;
if( utf8_strings )
p = gcry_xstrdup(string);
else
p = native_to_utf8( string );
return p;
}
static void
set_debug(void)
{
#if 0
#warning memory debuggig not enabled
#if 0
#warning memory debugging not enabled
if( opt.debug & DBG_MEMORY_VALUE )
memory_debug_mode = 1;
if( opt.debug & DBG_MEMSTAT_VALUE )
memory_stat_debug_mode = 1;
#endif
#endif
if( opt.debug & DBG_MPI_VALUE )
gcry_control( GCRYCTL_SET_DEBUG_FLAGS, 2 );
@ -579,6 +608,7 @@ main( int argc, char **argv )
int default_keyring = 1;
int greeting = 0;
int nogreeting = 0;
int use_random_seed = 1;
enum cmd_and_opt_values cmd = 0;
const char *trustdb_name = NULL;
char *def_cipher_string = NULL;
@ -611,6 +641,7 @@ main( int argc, char **argv )
init_signals();
create_dotlock(NULL); /* register locking cleanup */
i18n_init();
opt.command_fd = -1; /* no command fd */
opt.compress = -1; /* defaults to standard compress level */
/* note: if you change these lines, look at oOpenPGP */
opt.def_cipher_algo = 0;
@ -622,7 +653,13 @@ main( int argc, char **argv )
opt.completes_needed = 1;
opt.marginals_needed = 3;
opt.max_cert_depth = 5;
opt.pgp2_workarounds = 1;
opt.auto_key_retrieve = 1;
#ifdef __MINGW32__
opt.homedir = read_w32_registry_string( NULL, "Software\\GNU\\GnuPG", "HomeDir" );
#else
opt.homedir = getenv("GNUPGHOME");
#endif
if( !opt.homedir || !*opt.homedir ) {
#ifdef HAVE_DRIVE_LETTERS
opt.homedir = "c:/gnupg-test";
@ -679,7 +716,6 @@ main( int argc, char **argv )
if( default_config )
configname = make_filename(opt.homedir, "options", NULL );
argc = orig_argc;
argv = orig_argv;
pargs.argc = &argc;
@ -721,13 +757,16 @@ main( int argc, char **argv )
case aListKeys: set_cmd( &cmd, aListKeys); break;
case aListSigs: set_cmd( &cmd, aListSigs); break;
case aExportSecret: set_cmd( &cmd, aExportSecret); break;
case aExportSecretSub: set_cmd( &cmd, aExportSecretSub); break;
case aDeleteSecretKey: set_cmd( &cmd, aDeleteSecretKey);
greeting=1; break;
case aDeleteKey: set_cmd( &cmd, aDeleteKey); greeting=1; break;
case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break;
case aSym: set_cmd( &cmd, aSym); break;
case aDecrypt: set_cmd( &cmd, aDecrypt); break;
case aEncr: set_cmd( &cmd, aEncr); break;
case aSign: set_cmd( &cmd, aSign ); break;
case aKeygen: set_cmd( &cmd, aKeygen); greeting=1; break;
@ -738,11 +777,12 @@ main( int argc, char **argv )
case aClearsign: set_cmd( &cmd, aClearsign); break;
case aGenRevoke: set_cmd( &cmd, aGenRevoke); break;
case aVerify: set_cmd( &cmd, aVerify); break;
case aVerifyFiles: set_cmd( &cmd, aVerifyFiles); break;
case aPrimegen: set_cmd( &cmd, aPrimegen); break;
case aGenRandom: set_cmd( &cmd, aGenRandom); break;
case aPrintMD: set_cmd( &cmd, aPrintMD); break;
case aPrintHMAC: set_cmd( &cmd, aPrintHMAC); break;
case aPrintMDs: set_cmd( &cmd, aPrintMDs); break;
case aPrintHMAC: set_cmd( &cmd, aPrintHMAC); break;
case aListTrustDB: set_cmd( &cmd, aListTrustDB); break;
case aCheckTrustDB: set_cmd( &cmd, aCheckTrustDB); break;
case aUpdateTrustDB: set_cmd( &cmd, aUpdateTrustDB); break;
@ -828,11 +868,14 @@ main( int argc, char **argv )
break;
case oRFC1991:
opt.rfc1991 = 1;
opt.rfc2440 = 0;
opt.no_comment = 1;
opt.escape_from = 1;
break;
case oOpenPGP:
opt.rfc1991 = 0;
opt.rfc2440 = 1;
opt.pgp2_workarounds = 0;
opt.escape_from = 0;
opt.force_v3_sigs = 0;
opt.compress_keys = 0; /* not mandated but we do it */
@ -840,11 +883,13 @@ main( int argc, char **argv )
opt.not_dash_escaped = 0;
opt.def_cipher_algo = 0;
opt.def_digest_algo = 0;
opt.def_compress_algo = 2;
opt.def_compress_algo = 1;
opt.s2k_mode = 3; /* iterated+salted */
opt.s2k_digest_algo = GCRY_MD_RMD160;
opt.s2k_cipher_algo = GCRY_CIPHER_BLOWFISH;
opt.s2k_digest_algo = GCRY_MD_SHA1;
opt.s2k_cipher_algo = GCRY_CIPHER_CAST5;
break;
case oEmu3DESS2KBug: opt.emulate_bugs |= EMUBUG_3DESS2K; break;
case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break;
case oCompressSigs: opt.compress_sigs = 1; break;
case oRunAsShmCP:
#ifndef USE_SHM_COPROCESSING
@ -880,6 +925,7 @@ main( int argc, char **argv )
break;
case oCompress: opt.compress = pargs.r.ret_int; break;
case oPasswdFD: pwfd = pargs.r.ret_int; break;
case oCommandFD: opt.command_fd = pargs.r.ret_int; break;
case oCipherAlgo: def_cipher_string = gcry_xstrdup(pargs.r.ret_str); break;
case oDigestAlgo: def_digest_string = gcry_xstrdup(pargs.r.ret_str); break;
case oNoSecmemWarn: gcry_control( GCRYCTL_DISABLE_SECMEM_WARN ); break;
@ -891,6 +937,10 @@ main( int argc, char **argv )
case oNotDashEscaped: opt.not_dash_escaped = 1; break;
case oEscapeFrom: opt.escape_from = 1; break;
case oLockOnce: opt.lock_once = 1; break;
#if 0
#warning no disable_dotlock() yet
case oLockNever: disable_dotlock(); break;
#endif
case oLockMultiple: opt.lock_once = 0; break;
case oKeyServer: opt.keyserver_name = pargs.r.ret_str; break;
case oNotation: add_notation_data( pargs.r.ret_str ); break;
@ -908,22 +958,15 @@ main( int argc, char **argv )
&algo, sizeof algo );
}
break;
case oAllowNonSelfsignedUID:
opt.allow_non_selfsigned_uid = 1;
break;
case oNoLiteral:
opt.no_literal = 1;
break;
case oSetFilesize:
opt.set_filesize = pargs.r.ret_ulong;
break;
case oEntropyDLLName:
#ifdef USE_STATIC_RNDW32
log_info("set dllname to `%s'\n", pargs.r.ret_str );
rndw32_set_dll_name( pargs.r.ret_str );
#endif
break;
case oAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid = 1; break;
case oNoLiteral: opt.no_literal = 1; break;
case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break;
case oHonorHttpProxy: opt.honor_http_proxy = 1; break;
case oFastListMode: opt.fast_list_mode = 1; break;
case oListOnly: opt.list_only=1; break;
case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
case oNoRandomSeedFile: use_random_seed = 0; break;
case oNoAutoKeyRetrieve: opt.auto_key_retrieve = 0; break;
default : pargs.err = configfp? 1:2; break;
}
@ -946,14 +989,12 @@ main( int argc, char **argv )
fprintf(stderr, "%s\n", strusage(15) );
}
#ifdef IS_DEVELOPMENT_VERSION
if( !opt.batch )
log_info("NOTE: this is a development version!\n");
#endif
if( opt.force_mdc ) {
log_info("--force-mdc ignored because"
" the OpenPGP WG has not yet aggreed on MDCs\n");
opt.force_mdc = 0;
if( !opt.batch ) {
log_info("NOTE: THIS IS A DEVELOPMENT VERSION!\n");
log_info("It is only intended for test purposes and should NOT be\n");
log_info("used in a production environment or with production keys!\n");
}
#endif
if (opt.no_literal) {
log_info(_("NOTE: %s is not for normal use!\n"), "--no-literal");
if (opt.textmode)
@ -975,7 +1016,7 @@ main( int argc, char **argv )
* gpg_opt_homedir = opt.homedir; */
/* must do this after dropping setuid, because string_to...
* may try to load a module */
* may try to load an module */
if( def_cipher_string ) {
opt.def_cipher_algo = gcry_cipher_map_name(def_cipher_string);
gcry_free(def_cipher_string); def_cipher_string = NULL;
@ -1025,8 +1066,19 @@ main( int argc, char **argv )
if( log_get_errorcount(0) )
gpg_exit(2);
if( !cmd && opt.fingerprint && !with_fpr )
/* set the random seed file */
if( use_random_seed ) {
char *p = make_filename(opt.homedir, "random_seed", NULL );
#if 0
#warning set_random_seed_file missing
set_random_seed_file(p);
#endif
gcry_free(p);
}
if( !cmd && opt.fingerprint && !with_fpr ) {
set_cmd( &cmd, aListKeys);
}
if( cmd == aKMode || cmd == aKModeC ) { /* kludge to be compatible to pgp */
if( cmd == aKModeC ) {
@ -1077,8 +1129,8 @@ main( int argc, char **argv )
switch( cmd ) {
case aPrimegen:
case aPrintMD:
case aPrintHMAC:
case aPrintMDs:
case aPrintHMAC:
case aGenRandom:
case aDeArmor:
case aEnArmor:
@ -1167,6 +1219,11 @@ main( int argc, char **argv )
log_error("verify signatures failed: %s\n", gpg_errstr(rc) );
break;
case aVerifyFiles:
if( (rc = verify_files( argc, argv ) ))
log_error("verify files failed: %s\n", gpg_errstr(rc) );
break;
case aDecrypt:
if( argc > 1 )
wrong_args(_("--decrypt [filename]"));
@ -1225,16 +1282,28 @@ main( int argc, char **argv )
case aListSigs:
opt.list_sigs = 1;
case aListKeys:
/* fixme: we chnaged this in 1.0 */
public_key_list( argc, argv );
sl = NULL;
for( ; argc; argc--, argv++ )
add_to_strlist2( &sl, *argv, utf8_strings );
public_key_list( sl );
free_strlist(sl);
break;
case aListSecretKeys:
secret_key_list( argc, argv );
sl = NULL;
for( ; argc; argc--, argv++ )
add_to_strlist2( &sl, *argv, utf8_strings );
secret_key_list( sl );
free_strlist(sl);
break;
case aKMode: /* list keyring -- NOTE: This will be removed soon */
if( argc < 2 ) /* -kv [userid] */
public_key_list( (argc && **argv)? 1:0, argv );
if( argc < 2 ) { /* -kv [userid] */
sl = NULL;
if (argc && **argv)
add_to_strlist2( &sl, *argv, utf8_strings );
public_key_list( sl );
free_strlist(sl);
}
else if( argc == 2 ) { /* -kv userid keyring */
if( access( argv[1], R_OK ) ) {
log_error(_("can't open %s: %s\n"),
@ -1244,32 +1313,33 @@ main( int argc, char **argv )
/* add keyring (default keyrings are not registered in this
* special case */
add_keyblock_resource( argv[1], 0, 0 );
public_key_list( **argv?1:0, argv );
sl = NULL;
if (**argv)
add_to_strlist2( &sl, *argv, utf8_strings );
public_key_list( sl );
free_strlist(sl);
}
}
else
wrong_args(_("-k[v][v][v][c] [user-id] [keyring]") );
break;
case aKeygen: /* generate a key (interactive) */
if( argc )
wrong_args("--gen-key");
generate_keypair();
case aKeygen: /* generate a key */
if( opt.batch ) {
if( argc > 1 )
wrong_args("--gen-key [parameterfile]");
generate_keypair( argc? *argv : NULL );
}
else {
if( argc )
wrong_args("--gen-key");
generate_keypair(NULL);
}
break;
case aFastImport:
case aImport:
if( !argc ) {
rc = import_keys( NULL, (cmd == aFastImport) );
if( rc )
log_error("import failed: %s\n", gpg_errstr(rc) );
}
for( ; argc; argc--, argv++ ) {
rc = import_keys( *argv, (cmd == aFastImport) );
if( rc )
log_error("import from `%s' failed: %s\n",
*argv, gpg_errstr(rc) );
}
import_keys( argc? argv:NULL, argc, (cmd == aFastImport) );
break;
case aExport:
@ -1296,6 +1366,14 @@ main( int argc, char **argv )
free_strlist(sl);
break;
case aExportSecretSub:
sl = NULL;
for( ; argc; argc--, argv++ )
add_to_strlist2( &sl, *argv, utf8_strings );
export_secsubkeys( sl );
free_strlist(sl);
break;
case aGenRevoke:
if( argc != 1 )
wrong_args("--gen-revoke user-id");
@ -1342,7 +1420,7 @@ main( int argc, char **argv )
mpi_print( stdout, factors[0], 1 ); /* print q */
}
else if( mode == 4 && argc == 3 ) {
MPI g = mpi_new(8);
MPI g = mpi_alloc(1);
mpi_print( stdout, generate_elg_prime(
0, atoi(argv[1]),
atoi(argv[2]), g, NULL ), 1);
@ -1424,6 +1502,7 @@ main( int argc, char **argv )
}
break;
case aPrintMDs: /* old option */
if( !argc )
print_mds(NULL,0,NULL);
@ -1461,11 +1540,9 @@ main( int argc, char **argv )
break;
case aFixTrustDB:
log_error("this command is not yet implemented.\"\n");
log_error("this command is not yet implemented.\n");
log_error("A workaround is to use \"--export-ownertrust\", remove\n");
log_error("the trustdb file and do an \"--import-ownertrust\".\n" );
#warning removed the next line
export_as_kbxfile();
break;
case aListTrustPath:
@ -1533,6 +1610,10 @@ main( int argc, char **argv )
void
gpg_exit( int rc )
{
#if 0
#warning no update_random_seed_file
update_random_seed_file();
#endif
if( opt.debug & DBG_MEMSTAT_VALUE ) {
gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
@ -1629,7 +1710,7 @@ print_mds( const char *fname, int algo, const char *key )
if( algo ) {
if( fname )
fputs( pname, stdout );
print_hex( gcry_md_read(md, algo), gcry_md_get_algo_dlen(algo) );
print_hex(gcry_md_read(md, algo), gcry_md_get_algo_dlen(algo) );
}
else {
printf( "%s MD5 = ", fname?pname:"" );

View File

@ -1,4 +1,4 @@
/* gpg.c - The GnuPG daemon (keyserver)
/* ggpd.c - The GnuPG daemon (keyserver)
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
@ -38,6 +38,7 @@
#include <sys/stat.h>
#include "util.h"
#include "cipher.h"
#include "options.h"
#include "main.h"
@ -84,7 +85,7 @@ strusage( int level )
case 33:
if( !pubkeys )
pubkeys = build_list("Supported pubkeys: ", pubkey_algo_to_string,
openpgp_pk_test_algo );
check_pubkey_algo );
p = pubkeys;
break;
case 34:
@ -137,7 +138,7 @@ set_debug(void)
if( opt.debug & DBG_MPI_VALUE )
mpi_debug_mode = 1;
if( opt.debug & DBG_CIPHER_VALUE )
gpgc_debug_mode = 1;
g10c_debug_mode = 1;
if( opt.debug & DBG_IOBUF_VALUE )
iobuf_debug_mode = 1;
}

View File

@ -1,5 +1,5 @@
/* helptext.c - English help texts
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -224,6 +224,29 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = {
"file (which is shown in brackets) will be used."
)},
/* revoke.c (ask_revocation_reason) */
{ "ask_revocation_reason.code", N_(
"You should specify a reason for the certification. Depending on the\n"
"context you have the ability to choose from this list:\n"
" \"Key has been compromised\"\n"
" Use this if you have a reason to believe that unauthorized persons\n"
" got access to your secret key.\n"
" \"Key is superseeded\"\n"
" Use this if you have replaced this key with a newer one.\n"
" \"Key is no longer used\"\n"
" Use this if you have retired this key.\n"
" \"User ID is no longer valid\"\n"
" Use this to state that the user ID should not longer be used;\n"
" this is normally used to mark an email address invalid.\n"
)},
/* revoke.c (ask_revocation_reason) */
{ "ask_revocation_reason.text", N_(
"If you like, you can enter a text describing why you issue this\n"
"revocation certificate. Please keep this text concise.\n"
"An empty line ends the text.\n"
)},
/* end of list */
{ NULL, NULL } };

View File

@ -30,7 +30,6 @@
#include "util.h"
#include "ttyio.h"
#include "i18n.h"
#include <gcrypt.h>
#include "options.h"
#include "filter.h"
#include "http.h"
@ -56,19 +55,24 @@ hkp_ask_import( u32 *keyid )
struct http_context hd;
char *request;
int rc;
unsigned int hflags = opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY : 0;
if( !opt.keyserver_name )
return -1;
log_info("requesting key %08lX from %s ...\n", (ulong)keyid[1],
log_info(_("requesting key %08lX from %s ...\n"), (ulong)keyid[1],
opt.keyserver_name );
request = gcry_xmalloc( strlen( opt.keyserver_name ) + 100 );
/* hkp does not accept the long keyid - we should really write a
* nicer one */
* nicer one :-)
* FIXME: request binary mode - need to pass no_armor mode
* down to the import function. Marc told that there is such a
* binary mode ... how?
*/
sprintf( request, "x-hkp://%s:11371/pks/lookup?op=get&search=0x%08lX",
opt.keyserver_name, (ulong)keyid[1] );
rc = http_open_document( &hd, request, 0 );
rc = http_open_document( &hd, request, hflags );
if( rc ) {
log_info("can't get key from keyserver: %s\n",
log_info(_("can't get key from keyserver: %s\n"),
rc == GPGERR_NETWORK? strerror(errno)
: gpg_errstr(rc) );
}
@ -91,7 +95,7 @@ hkp_import( STRLIST users )
return -1;
#else
if( !opt.keyserver_name ) {
log_error("no keyserver known (use option --keyserver)\n");
log_error(_("no keyserver known (use option --keyserver)\n"));
return -1;
}
@ -99,10 +103,15 @@ hkp_import( STRLIST users )
u32 kid[2];
int type = classify_user_id( users->d, kid, NULL, NULL, NULL );
if( type != 10 && type != 11 ) {
log_info("%s: not a valid key ID\n", users->d );
log_info(_("%s: not a valid key ID\n"), users->d );
continue;
}
hkp_ask_import( kid );
/* because the function may use log_info in some situations, the
* errorcounter ist not increaed and the program will return
* with success - which is not good when this function is used.
*/
if( hkp_ask_import( kid ) )
log_inc_errorcount();
}
return 0;
#endif
@ -121,9 +130,10 @@ hkp_export( STRLIST users )
struct http_context hd;
char *request;
unsigned int status;
unsigned int hflags = opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY : 0;
if( !opt.keyserver_name ) {
log_error("no keyserver known (use option --keyserver)\n");
log_error(_("no keyserver known (use option --keyserver)\n"));
return -1;
}
@ -143,9 +153,9 @@ hkp_export( STRLIST users )
request = gcry_xmalloc( strlen( opt.keyserver_name ) + 100 );
sprintf( request, "x-hkp://%s:11371/pks/add", opt.keyserver_name );
rc = http_open( &hd, HTTP_REQ_POST, request , 0 );
rc = http_open( &hd, HTTP_REQ_POST, request , hflags );
if( rc ) {
log_error("can't connect to `%s': %s\n",
log_error(_("can't connect to `%s': %s\n"),
opt.keyserver_name,
rc == GPGERR_NETWORK? strerror(errno)
: gpg_errstr(rc) );
@ -169,7 +179,7 @@ hkp_export( STRLIST users )
rc = http_wait_response( &hd, &status );
if( rc ) {
log_error("error sending to `%s': %s\n",
log_error(_("error sending to `%s': %s\n"),
opt.keyserver_name, gpg_errstr(rc) );
}
else {
@ -181,10 +191,10 @@ hkp_export( STRLIST users )
}
#endif
if( (status/100) == 2 )
log_info("success sending to `%s' (status=%u)\n",
log_info(_("success sending to `%s' (status=%u)\n"),
opt.keyserver_name, status );
else
log_error("failed sending to `%s': status=%u\n",
log_error(_("failed sending to `%s': status=%u\n"),
opt.keyserver_name, status );
}
http_close( &hd );

View File

@ -1,5 +1,5 @@
/* hkp.h - Horrowitz Keyserver Protocol
* Copyright (C) 1999 Free Software Foundation, Inc.
* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*

View File

@ -1,5 +1,5 @@
/* import.c
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -38,6 +38,7 @@
static struct {
ulong count;
ulong no_user_id;
ulong imported;
ulong imported_rsa;
@ -53,6 +54,7 @@ static struct {
static int import( IOBUF inp, int fast, const char* fname );
static void print_stats(void);
static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root );
static int import_one( const char *fname, KBNODE keyblock, int fast );
static int import_secret_one( const char *fname, KBNODE keyblock );
@ -105,30 +107,51 @@ static int merge_keysigs( KBNODE dst, KBNODE src, int *n_sigs,
* Key revocation certificates have special handling.
*
*/
int
import_keys( const char *fname, int fast )
void
import_keys( char **fnames, int nnames, int fast )
{
IOBUF inp = NULL;
int rc;
int i;
inp = iobuf_open(fname);
if( !fname )
fname = "[stdin]";
if( !inp ) {
log_error(_("can't open `%s': %s\n"), fname, strerror(errno) );
return GPGERR_OPEN_FILE;
/* fixme: don't use static variables */
memset( &stats, 0, sizeof( stats ) );
if( !fnames && !nnames )
nnames = 1; /* Ohh what a ugly hack to jump into the loop */
for(i=0; i < nnames; i++ ) {
const char *fname = fnames? fnames[i] : NULL;
IOBUF inp = iobuf_open(fname);
if( !fname )
fname = "[stdin]";
if( !inp )
log_error(_("can't open `%s': %s\n"), fname, strerror(errno) );
else {
int rc = import( inp, fast, fname );
iobuf_close(inp);
if( rc )
log_error("import from `%s' failed: %s\n", fname,
gpg_errstr(rc) );
}
if( !fname )
break;
}
rc = import( inp, fast, fname );
iobuf_close(inp);
return rc;
print_stats();
if( !fast )
sync_trustdb();
}
int
import_keys_stream( IOBUF inp, int fast )
{
return import( inp, fast, "[stream]" );
int rc = 0;
/* fixme: don't use static variables */
memset( &stats, 0, sizeof( stats ) );
rc = import( inp, fast, "[stream]" );
print_stats();
if( !fast )
sync_trustdb();
return rc;
}
static int
@ -137,10 +160,6 @@ import( IOBUF inp, int fast, const char* fname )
PACKET *pending_pkt = NULL;
KBNODE keyblock;
int rc = 0;
ulong count=0;
/* fixme: don't use static variables */
memset( &stats, 0, sizeof( stats ) );
getkey_disable_caches();
@ -165,16 +184,23 @@ import( IOBUF inp, int fast, const char* fname )
release_kbnode(keyblock);
if( rc )
break;
if( !(++count % 100) && !opt.quiet )
log_info(_("%lu keys so far processed\n"), count );
if( !(++stats.count % 100) && !opt.quiet )
log_info(_("%lu keys so far processed\n"), stats.count );
}
if( rc == -1 )
rc = 0;
else if( rc && rc != GPGERR_INV_KEYRING )
log_error( _("error reading `%s': %s\n"), fname, gpg_errstr(rc));
return rc;
}
static void
print_stats()
{
if( !opt.quiet ) {
log_info(_("Total number processed: %lu\n"), count );
log_info(_("Total number processed: %lu\n"), stats.count );
if( stats.no_user_id )
log_info(_(" w/o user IDs: %lu\n"), stats.no_user_id );
if( stats.imported || stats.imported_rsa ) {
@ -202,9 +228,9 @@ import( IOBUF inp, int fast, const char* fname )
}
if( is_status_enabled() ) {
char buf[12*16];
char buf[12*20];
sprintf(buf, "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
count,
stats.count,
stats.no_user_id,
stats.imported,
stats.imported_rsa,
@ -218,8 +244,6 @@ import( IOBUF inp, int fast, const char* fname )
stats.secret_dups);
write_status_text( STATUS_IMPORT_RES, buf );
}
return rc;
}
@ -354,8 +378,8 @@ import_one( const char *fname, KBNODE keyblock, int fast )
pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1], datestr_from_pk(pk) );
if( uidnode )
print_string( stderr, uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len, 0 );
print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len );
putc('\n', stderr);
}
if( !uidnode ) {
@ -545,8 +569,8 @@ import_secret_one( const char *fname, KBNODE keyblock )
pubkey_letter( sk->pubkey_algo ),
(ulong)keyid[1], datestr_from_sk(sk) );
if( uidnode )
print_string( stderr, uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len, 0 );
print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len );
putc('\n', stderr);
}
stats.secret_read++;
@ -678,6 +702,15 @@ import_revoke_cert( const char *fname, KBNODE node )
log_info( _("key %08lX: revocation certificate imported\n"),
(ulong)keyid[1]);
stats.n_revoc++;
if( clear_trust_checked_flag( pk ) ) {
/* seems that we have to insert the record first */
rc = insert_trust_record( keyblock );
if( rc )
log_error("key %08lX: trustdb insert failed: %s\n",
(ulong)keyid[1], gpg_errstr(rc) );
else
rc = clear_trust_checked_flag( pk );
}
leave:
release_kbnode( keyblock );
@ -764,7 +797,8 @@ mark_non_selfsigned_uids_valid( KBNODE keyblock, u32 *kid )
KBNODE node;
for(node=keyblock->next; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID && !(node->flag & 1) ) {
if( node->next && node->next->pkt->pkttype == PKT_SIGNATURE ) {
if( (node->next && node->next->pkt->pkttype == PKT_SIGNATURE)
|| !node->next ) {
node->flag |= 1;
log_info( _("key %08lX: accepted non self-signed user ID '"),
(ulong)kid[1]);
@ -797,8 +831,8 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
if( opt.verbose ) {
log_info( _("key %08lX: skipped user ID '"),
(ulong)keyid[1]);
print_string( stderr, node->pkt->pkt.user_id->name,
node->pkt->pkt.user_id->len, 0 );
print_utf8_string( stderr, node->pkt->pkt.user_id->name,
node->pkt->pkt.user_id->len );
fputs("'\n", stderr );
}
delete_kbnode( node ); /* the user-id */
@ -831,7 +865,7 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
}
}
else if( node->pkt->pkttype == PKT_SIGNATURE
&& openpgp_pk_test_algo( node->pkt->pkt.signature->pubkey_algo, 0)
&& openpgp_pk_test_algo( node->pkt->pkt.signature->pubkey_algo, 0 )
&& node->pkt->pkt.signature->pubkey_algo != GCRY_PK_RSA )
delete_kbnode( node ); /* build_packet() can't handle this */
else if( node->pkt->pkttype == PKT_SIGNATURE

View File

@ -1,5 +1,5 @@
/* kbnode.c - keyblock node utility functions
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -23,8 +23,9 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "util.h"
#include <gcrypt.h>
#include "util.h"
#include "packet.h"
#include "keydb.h"
@ -165,7 +166,7 @@ find_prev_kbnode( KBNODE root, KBNODE node, int pkttype )
KBNODE n1;
for(n1=NULL ; root && root != node; root = root->next )
if( !pkttype || root->pkt->pkttype == pkttype )
if( !pkttype || root->pkt->pkttype == pkttype )
n1 = root;
return n1;
}

View File

@ -511,7 +511,7 @@ kbx_create_blob ( KBXBLOB *r_blob, KBNODE keyblock )
KBXBLOB blob;
*r_blob = NULL;
blob = gcry_calloc (1, sizeof *blob );
blob = gcry_xcalloc (1, sizeof *blob );
if( !blob )
return GCRYERR_NO_MEM;
@ -529,9 +529,9 @@ kbx_create_blob ( KBXBLOB *r_blob, KBNODE keyblock )
default: break;
}
}
blob->keys = gcry_calloc ( blob->nkeys, sizeof ( *blob->keys ) );
blob->uids = gcry_calloc ( blob->nuids, sizeof ( *blob->uids ) );
blob->sigs = gcry_calloc ( blob->nsigs, sizeof ( *blob->sigs ) );
blob->keys = gcry_xcalloc ( blob->nkeys, sizeof ( *blob->keys ) );
blob->uids = gcry_xcalloc ( blob->nuids, sizeof ( *blob->uids ) );
blob->sigs = gcry_xcalloc ( blob->nsigs, sizeof ( *blob->sigs ) );
if ( !blob->keys || !blob->uids || !blob->sigs ) {
rc = GCRYERR_NO_MEM;
goto leave;
@ -581,7 +581,7 @@ kbx_new_blob ( KBXBLOB *r_blob, char *image, size_t imagelen )
KBXBLOB blob;
*r_blob = NULL;
blob = gcry_calloc (1, sizeof *blob );
blob = gcry_xcalloc (1, sizeof *blob );
if( !blob )
return GCRYERR_NO_MEM;
blob->blob = image;

View File

@ -321,7 +321,7 @@ print_kbxfile( const char *filename )
fp = fopen ( filename, "rb" );
if( !fp ) {
log_error(_("can't open `%s': %s\n"), filename, strerror(errno) );
return 1;
return;
}
while ( !do_print_kbxfile( filename, fp ) )

View File

@ -1,5 +1,5 @@
/* keydb.h - Key database
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -25,6 +25,7 @@
#include <gdbm.h>
#endif
#include "types.h"
#include "basicdefs.h"
#include "packet.h"
@ -156,6 +157,7 @@ void get_seckey_end( GETKEY_CTX ctx );
int enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys );
void merge_keys_and_selfsig( KBNODE keyblock );
char*get_user_id_string( u32 *keyid );
char*get_user_id_string_native( u32 *keyid );
char*get_long_user_id_string( u32 *keyid );
char*get_user_id( u32 *keyid, size_t *rn );
@ -197,6 +199,7 @@ const char *enum_keyblock_resources( int *sequence, int secret );
int add_keyblock_resource( const char *resname, int force, int secret );
const char *keyblock_resource_name( KBPOS *kbpos );
int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos );
char *get_writable_keyblock_file( int secret );
int locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr,
int fprlen, int secret );
int locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid,

View File

@ -1,5 +1,5 @@
/* keyedit.c - keyedit stuff
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -74,8 +74,9 @@ static int enable_disable_key( KBNODE keyblock, int disable );
#define NODFLG_SELSIG (1<<10) /* indicate a selected signature */
struct sign_uid_attrib {
struct sign_attrib {
int non_exportable;
struct revocation_reason_info *reason;
};
@ -157,7 +158,7 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node,
else {
size_t n;
char *p = get_user_id( sig->keyid, &n );
tty_print_utf8_string( p, n > 40? 40 : n );
tty_print_utf8_string2( p, n, 40 );
gcry_free(p);
}
tty_printf("\n");
@ -239,16 +240,18 @@ check_all_keysigs( KBNODE keyblock, int only_selected )
int
sign_uid_mk_attrib( PKT_signature *sig, void *opaque )
static int
sign_mk_attrib( PKT_signature *sig, void *opaque )
{
struct sign_uid_attrib *attrib = opaque;
struct sign_attrib *attrib = opaque;
byte buf[8];
if( attrib->non_exportable ) {
buf[0] = 0; /* not exportable */
build_sig_subpkt( sig, SIGSUBPKT_EXPORTABLE, buf, 1 );
}
if( attrib->reason )
revocation_reason_build_cb( sig, attrib->reason );
return 0;
}
@ -353,7 +356,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int local )
&& (node->flag & NODFLG_MARK_A) ) {
PACKET *pkt;
PKT_signature *sig;
struct sign_uid_attrib attrib;
struct sign_attrib attrib;
assert( primary_pk );
memset( &attrib, 0, sizeof attrib );
@ -364,7 +367,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int local )
NULL,
sk,
0x10, 0,
sign_uid_mk_attrib,
sign_mk_attrib,
&attrib );
if( rc ) {
log_error(_("signing failed: %s\n"), gpg_errstr(rc));
@ -407,6 +410,7 @@ change_passphrase( KBNODE keyblock )
KBNODE node;
PKT_secret_key *sk;
char *passphrase = NULL;
int no_primary_secrets = 0;
node = find_kbnode( keyblock, PKT_SECRET_KEY );
if( !node ) {
@ -423,10 +427,16 @@ change_passphrase( KBNODE keyblock )
tty_printf(_("This key is not protected.\n"));
break;
default:
tty_printf(_("Key is protected.\n"));
rc = check_secret_key( sk, 0 );
if( !rc )
passphrase = get_last_passphrase();
if( sk->protect.s2k.mode == 1001 ) {
tty_printf(_("Secret parts of primary key are not available.\n"));
no_primary_secrets = 1;
}
else {
tty_printf(_("Key is protected.\n"));
rc = check_secret_key( sk, 0 );
if( !rc )
passphrase = get_last_passphrase();
}
break;
}
@ -436,6 +446,8 @@ change_passphrase( KBNODE keyblock )
PKT_secret_key *subsk = node->pkt->pkt.secret_key;
set_next_passphrase( passphrase );
rc = check_secret_key( subsk, 0 );
if( !rc && !passphrase )
passphrase = get_last_passphrase();
}
}
@ -465,9 +477,12 @@ change_passphrase( KBNODE keyblock )
break;
}
else { /* okay */
sk->protect.algo = dek->algo;
sk->protect.s2k = *s2k;
rc = protect_secret_key( sk, dek );
rc = 0;
if( !no_primary_secrets ) {
sk->protect.algo = dek->algo;
sk->protect.s2k = *s2k;
rc = protect_secret_key( sk, dek );
}
for(node=keyblock; !rc && node; node = node->next ) {
if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
PKT_secret_key *subsk = node->pkt->pkt.secret_key;
@ -558,41 +573,42 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
static struct { const char *name;
enum cmdids id;
int need_sk;
int not_with_sk;
int signmode;
const char *desc;
} cmds[] = {
{ N_("quit") , cmdQUIT , 0,1, N_("quit this menu") },
{ N_("q") , cmdQUIT , 0,1, NULL },
{ N_("save") , cmdSAVE , 0,1, N_("save and quit") },
{ N_("help") , cmdHELP , 0,1, N_("show this help") },
{ "?" , cmdHELP , 0,1, NULL },
{ N_("fpr") , cmdFPR , 0,1, N_("show fingerprint") },
{ N_("list") , cmdLIST , 0,1, N_("list key and user IDs") },
{ N_("l") , cmdLIST , 0,1, NULL },
{ N_("uid") , cmdSELUID , 0,1, N_("select user ID N") },
{ N_("key") , cmdSELKEY , 0,0, N_("select secondary key N") },
{ N_("check") , cmdCHECK , 0,1, N_("list signatures") },
{ N_("c") , cmdCHECK , 0,1, NULL },
{ N_("sign") , cmdSIGN , 0,1, N_("sign the key") },
{ N_("s") , cmdSIGN , 0,1, NULL },
{ N_("lsign") , cmdLSIGN , 0,1, N_("sign the key locally") },
{ N_("debug") , cmdDEBUG , 0,0, NULL },
{ N_("adduid") , cmdADDUID , 1,0, N_("add a user ID") },
{ N_("deluid") , cmdDELUID , 0,0, N_("delete user ID") },
{ N_("addkey") , cmdADDKEY , 1,0, N_("add a secondary key") },
{ N_("delkey") , cmdDELKEY , 0,0, N_("delete a secondary key") },
{ N_("delsig") , cmdDELSIG , 0,0, N_("delete signatures") },
{ N_("expire") , cmdEXPIRE , 1,0, N_("change the expire date") },
{ N_("toggle") , cmdTOGGLE , 1,0, N_("toggle between secret "
"and public key listing") },
{ N_("t" ) , cmdTOGGLE , 1,0, NULL },
{ N_("pref") , cmdPREF , 0,0, N_("list preferences") },
{ N_("passwd") , cmdPASSWD , 1,0, N_("change the passphrase") },
{ N_("trust") , cmdTRUST , 0,0, N_("change the ownertrust") },
{ N_("revsig") , cmdREVSIG , 0,0, N_("revoke signatures") },
{ N_("revkey") , cmdREVKEY , 1,0, N_("revoke a secondary key") },
{ N_("disable") , cmdDISABLEKEY, 0,0, N_("disable a key") },
{ N_("enable") , cmdENABLEKEY , 0,0, N_("enable a key") },
{ N_("quit") , cmdQUIT , 0,0,1, N_("quit this menu") },
{ N_("q") , cmdQUIT , 0,0,1, NULL },
{ N_("save") , cmdSAVE , 0,0,1, N_("save and quit") },
{ N_("help") , cmdHELP , 0,0,1, N_("show this help") },
{ "?" , cmdHELP , 0,0,1, NULL },
{ N_("fpr") , cmdFPR , 0,0,1, N_("show fingerprint") },
{ N_("list") , cmdLIST , 0,0,1, N_("list key and user IDs") },
{ N_("l") , cmdLIST , 0,0,1, NULL },
{ N_("uid") , cmdSELUID , 0,0,1, N_("select user ID N") },
{ N_("key") , cmdSELKEY , 0,0,0, N_("select secondary key N") },
{ N_("check") , cmdCHECK , 0,0,1, N_("list signatures") },
{ N_("c") , cmdCHECK , 0,0,1, NULL },
{ N_("sign") , cmdSIGN , 0,1,1, N_("sign the key") },
{ N_("s") , cmdSIGN , 0,1,1, NULL },
{ N_("lsign") , cmdLSIGN , 0,1,1, N_("sign the key locally") },
{ N_("debug") , cmdDEBUG , 0,1,0, NULL },
{ N_("adduid") , cmdADDUID , 1,1,0, N_("add a user ID") },
{ N_("deluid") , cmdDELUID , 0,1,0, N_("delete user ID") },
{ N_("addkey") , cmdADDKEY , 1,1,0, N_("add a secondary key") },
{ N_("delkey") , cmdDELKEY , 0,1,0, N_("delete a secondary key") },
{ N_("delsig") , cmdDELSIG , 0,1,0, N_("delete signatures") },
{ N_("expire") , cmdEXPIRE , 1,1,0, N_("change the expire date") },
{ N_("toggle") , cmdTOGGLE , 1,0,0, N_("toggle between secret "
"and public key listing") },
{ N_("t" ) , cmdTOGGLE , 1,0,0, NULL },
{ N_("pref") , cmdPREF , 0,1,0, N_("list preferences") },
{ N_("passwd") , cmdPASSWD , 1,1,0, N_("change the passphrase") },
{ N_("trust") , cmdTRUST , 0,1,0, N_("change the ownertrust") },
{ N_("revsig") , cmdREVSIG , 0,1,0, N_("revoke signatures") },
{ N_("revkey") , cmdREVKEY , 1,1,0, N_("revoke a secondary key") },
{ N_("disable") , cmdDISABLEKEY, 0,1,0, N_("disable a key") },
{ N_("enable") , cmdENABLEKEY , 0,1,0, N_("enable a key") },
{ NULL, cmdNONE } };
enum cmdids cmd = 0;
@ -678,7 +694,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
have_commands = 0;
}
if( !have_commands ) {
answer = cpr_get("", _("Command> "));
answer = cpr_get("keyedit.prompt", _("Command> "));
cpr_kill_prompt();
}
trim_spaces(answer);
@ -711,6 +727,10 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
tty_printf(_("Need the secret key to do this.\n"));
cmd = cmdNOP;
}
else if( cmds[i].not_with_sk && sec_keyblock && toggle ) {
tty_printf(_("Please use the command \"toggle\" first.\n"));
cmd = cmdNOP;
}
else
cmd = cmds[i].id;
}
@ -763,6 +783,11 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
if( !sign_uids( keyblock, locusr, &modified, cmd == cmdLSIGN )
&& sign_mode )
goto do_cmd_save;
/* Actually we should do a update_trust_record() here so that
* the trust gets displayed correctly. however this is not possible
* because we would have to save the keyblock first - something
* we don't want to do without an explicit save command.
*/
break;
case cmdDEBUG:
@ -1005,7 +1030,13 @@ show_prefs( KBNODE keyblock, PKT_user_id *uid )
return;
}
gcry_md_hash_buffer( GCRY_MD_RMD160, namehash, uid->name, uid->len );
if( uid->photo ) {
gcry_md_hash_buffer( GCRY_MD_RMD160, namehash, uid->photo,
uid->photolen );
}
else {
gcry_md_hash_buffer( GCRY_MD_RMD160, namehash, uid->name, uid->len );
}
p = get_pref_data( pk->local_id, namehash, &n );
if( !p )
@ -1049,7 +1080,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
otrust = get_ownertrust_info( pk->local_id );
}
tty_printf("%s%c %4u%c/%08lX created: %s expires: %s",
tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"),
node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
(node->flag & NODFLG_SELKEY)? '*':' ',
nbits_from_pk( pk ),
@ -1058,7 +1089,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
datestr_from_pk(pk),
expirestr_from_pk(pk) );
if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
tty_printf(" trust: %c/%c", otrust, trust );
tty_printf(_(" trust: %c/%c"), otrust, trust );
if( node->pkt->pkttype == PKT_PUBLIC_KEY
&& (get_ownertrust( pk->local_id )&TRUST_FLAG_DISABLED)) {
tty_printf("\n*** ");
@ -1075,14 +1106,15 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
else if( node->pkt->pkttype == PKT_SECRET_KEY
|| (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
PKT_secret_key *sk = node->pkt->pkt.secret_key;
tty_printf("%s%c %4u%c/%08lX created: %s expires: %s\n",
node->pkt->pkttype == PKT_SECRET_KEY? "sec":"sbb",
tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"),
node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
(node->flag & NODFLG_SELKEY)? '*':' ',
nbits_from_sk( sk ),
pubkey_letter( sk->pubkey_algo ),
(ulong)keyid_from_sk(sk,NULL),
datestr_from_sk(sk),
expirestr_from_sk(sk) );
tty_printf("\n");
}
else if( with_subkeys && node->pkt->pkttype == PKT_SIGNATURE
&& node->pkt->pkt.signature->sig_class == 0x28 ) {
@ -1090,12 +1122,12 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
rc = check_key_signature( keyblock, node, NULL );
if( !rc )
tty_printf( "rev! subkey has been revoked: %s\n",
tty_printf( _("rev! subkey has been revoked: %s\n"),
datestr_from_sig( sig ) );
else if( rc == GPGERR_BAD_SIGN )
tty_printf( "rev- faked revocation found\n" );
tty_printf( _("rev- faked revocation found\n") );
else if( rc )
tty_printf( "rev? problem checking revocation: %s\n",
tty_printf( _("rev? problem checking revocation: %s\n"),
gpg_errstr(rc) );
}
}
@ -1156,7 +1188,7 @@ show_fingerprint( PKT_public_key *pk )
fingerprint_from_pk( pk, array, &n );
p = array;
tty_printf(" Fingerprint:");
tty_printf(_(" Fingerprint:"));
if( n == 20 ) {
for(i=0; i < n ; i++, i++, p += 2 ) {
if( i == 10 )
@ -1471,7 +1503,8 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
}
else if( node->pkt->pkttype == PKT_USER_ID )
uid = node->pkt->pkt.user_id;
else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE ) {
else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE
&& sub_pk != NULL ) {
PKT_signature *sig = node->pkt->pkt.signature;
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
&& ( (mainkey && uid && (sig->sig_class&~3) == 0x10)
@ -1535,6 +1568,7 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
gcry_free( sn->pkt );
sn->pkt = newpkt;
}
sub_pk = NULL;
}
}
}
@ -1735,6 +1769,7 @@ menu_revsig( KBNODE keyblock )
int changed = 0;
int upd_trust = 0;
int rc, any;
struct revocation_reason_info *reason = NULL;
/* FIXME: detect duplicates here */
tty_printf(_("You have signed these user IDs:\n"));
@ -1797,6 +1832,10 @@ menu_revsig( KBNODE keyblock )
_("Really create the revocation certificates? (y/N)")) )
return 0; /* forget it */
reason = ask_revocation_reason( 0, 1, 0 );
if( !reason ) { /* user decided to cancel */
return 0;
}
/* now we can sign the user ids */
reloop: /* (must use this, because we are modifing the list) */
@ -1804,7 +1843,7 @@ menu_revsig( KBNODE keyblock )
for( node=keyblock; node; node = node->next ) {
KBNODE unode;
PACKET *pkt;
struct sign_uid_attrib attrib;
struct sign_attrib attrib;
PKT_secret_key *sk;
if( !(node->flag & NODFLG_MARK_A)
@ -1814,8 +1853,10 @@ menu_revsig( KBNODE keyblock )
assert( unode ); /* we already checked this */
memset( &attrib, 0, sizeof attrib );
attrib.reason = reason;
node->flag &= ~NODFLG_MARK_A;
sk = gcry_xcalloc_secure( 1, sizeof *sk );
sk = gcry_xcalloc_secure( 1, sizeof *sk );
if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) {
log_info(_("no secret key\n"));
continue;
@ -1825,11 +1866,12 @@ menu_revsig( KBNODE keyblock )
NULL,
sk,
0x30, 0,
sign_uid_mk_attrib,
sign_mk_attrib,
&attrib );
free_secret_key(sk);
if( rc ) {
log_error(_("signing failed: %s\n"), gpg_errstr(rc));
release_revocation_reason_info( reason );
return changed;
}
changed = 1; /* we changed the keyblock */
@ -1844,7 +1886,7 @@ menu_revsig( KBNODE keyblock )
if( upd_trust )
clear_trust_checked_flag( primary_pk );
release_revocation_reason_info( reason );
return changed;
}
@ -1861,6 +1903,13 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
int changed = 0;
int upd_trust = 0;
int rc;
struct revocation_reason_info *reason = NULL;
reason = ask_revocation_reason( 1, 0, 0 );
if( !reason ) { /* user decided to cancel */
return 0;
}
reloop: /* (better this way because we are modifing the keyring) */
mainpk = pub_keyblock->pkt->pkt.public_key;
@ -1871,14 +1920,20 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
PKT_signature *sig;
PKT_secret_key *sk;
PKT_public_key *subpk = node->pkt->pkt.public_key;
struct sign_attrib attrib;
memset( &attrib, 0, sizeof attrib );
attrib.reason = reason;
node->flag &= ~NODFLG_SELKEY;
sk = copy_secret_key( NULL, sec_keyblock->pkt->pkt.secret_key );
rc = make_keysig_packet( &sig, mainpk, NULL, subpk, sk, 0x28, 0,
NULL, NULL );
sign_mk_attrib,
&attrib );
free_secret_key(sk);
if( rc ) {
log_error(_("signing failed: %s\n"), gpg_errstr(rc));
release_revocation_reason_info( reason );
return changed;
}
changed = 1; /* we changed the keyblock */
@ -1897,6 +1952,7 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
if( upd_trust )
clear_trust_checked_flag( mainpk );
release_revocation_reason_info( reason );
return changed;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* keyid.c - jeyid and fingerprint handling
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -25,12 +25,14 @@
#include <errno.h>
#include <time.h>
#include <assert.h>
#include <gcrypt.h>
#include "util.h"
#include "main.h"
#include "packet.h"
#include "options.h"
#include "keydb.h"
#include "i18n.h"
int
@ -52,7 +54,7 @@ static GCRY_MD_HD
do_fingerprint_md( PKT_public_key *pk )
{
GCRY_MD_HD md;
unsigned n;
unsigned int n;
unsigned int nn[GNUPG_MAX_NPKEY];
byte *pp[GNUPG_MAX_NPKEY];
int i;
@ -339,7 +341,7 @@ expirestr_from_pk( PKT_public_key *pk )
time_t atime;
if( !pk->expiredate )
return "never ";
return _("never ");
atime = pk->expiredate;
tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
@ -354,7 +356,7 @@ expirestr_from_sk( PKT_secret_key *sk )
time_t atime;
if( !sk->expiredate )
return "never ";
return _("never ");
atime = sk->expiredate;
tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );

View File

@ -1,5 +1,5 @@
/* keylist.c
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -43,34 +43,24 @@ static void fingerprint( PKT_public_key *pk, PKT_secret_key *sk );
/****************
* List the keys
* If NNAMES is 0; all available keys are listed
* If list is NULL, all available keys are listed
*/
void
public_key_list( int nnames, char **names )
public_key_list( STRLIST list )
{
if( !nnames )
if( !list )
list_all(0);
else { /* List by user id */
STRLIST list = NULL;
for( ; nnames ; nnames--, names++ )
add_to_strlist( &list, *names );
else
list_one( list, 0 );
free_strlist( list );
}
}
void
secret_key_list( int nnames, char **names )
secret_key_list( STRLIST list )
{
if( !nnames )
if( !list )
list_all(1);
else { /* List by user id */
STRLIST list = NULL;
for( ; nnames ; nnames--, names++ )
add_to_strlist( &list, *names );
else /* List by user id */
list_one( list, 1 );
free_strlist( list );
}
}
@ -145,6 +135,7 @@ list_one( STRLIST names, int secret )
return;
}
do {
merge_keys_and_selfsig( keyblock );
list_keyblock( keyblock, 0 );
release_kbnode( keyblock );
} while( !get_pubkey_next( ctx, NULL, &keyblock ) );
@ -155,7 +146,7 @@ list_one( STRLIST names, int secret )
static void
print_key_data( PKT_public_key *pk, u32 *keyid )
{
int n = pubkey_get_npkey( pk->pubkey_algo );
int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
int i;
for(i=0; i < n; i++ ) {
@ -211,21 +202,26 @@ list_keyblock( KBNODE keyblock, int secret )
sk = NULL;
keyid_from_pk( pk, keyid );
if( opt.with_colons ) {
trustletter = query_trust_info( pk, NULL );
if( trustletter == 'u' )
ulti_hack = 1;
printf("pub:%c:%u:%d:%08lX%08lX:%s:%s:",
trustletter,
if ( opt.fast_list_mode ) {
fputs( "pub::", stdout );
trustletter = 0;
}
else {
trustletter = query_trust_info( pk, NULL );
if( trustletter == 'u' )
ulti_hack = 1;
printf("pub:%c:", trustletter );
}
printf("%u:%d:%08lX%08lX:%s:%s:",
nbits_from_pk( pk ),
pk->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
datestr_from_pk( pk ),
pk->expiredate? strtimestamp(pk->expiredate):""
);
pk->expiredate? strtimestamp(pk->expiredate):"" );
if( pk->local_id )
printf("%lu", pk->local_id );
putchar(':');
if( pk->local_id )
if( pk->local_id && !opt.fast_list_mode )
putchar( get_ownertrust_info( pk->local_id ) );
putchar(':');
}
@ -237,15 +233,22 @@ list_keyblock( KBNODE keyblock, int secret )
}
for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) {
if( any ) {
if( opt.with_colons ) {
if ( opt.with_colons ) {
byte namehash[20];
if( pk && !ulti_hack ) {
gcry_md_hash_buffer( GCRY_MD_RMD160, namehash,
node->pkt->pkt.user_id->name,
node->pkt->pkt.user_id->len );
if( node->pkt->pkt.user_id->photo ) {
gcry_md_hash_buffer( GCRY_MD_RMD160, namehash,
node->pkt->pkt.user_id->name,
node->pkt->pkt.user_id->len );
}
else {
gcry_md_hash_buffer( GCRY_MD_RMD160, namehash,
node->pkt->pkt.user_id->name,
node->pkt->pkt.user_id->len );
}
trustletter = query_trust_info( pk, namehash );
}
else
@ -288,8 +291,13 @@ list_keyblock( KBNODE keyblock, int secret )
keyid_from_pk( pk2, keyid2 );
if( opt.with_colons ) {
printf("sub:%c:%u:%d:%08lX%08lX:%s:%s:",
trustletter,
if ( opt.fast_list_mode ) {
fputs( "sub::", stdout );
}
else {
printf("sub:%c:", trustletter );
}
printf("%u:%d:%08lX%08lX:%s:%s:",
nbits_from_pk( pk2 ),
pk2->pubkey_algo,
(ulong)keyid2[0],(ulong)keyid2[1],
@ -303,11 +311,16 @@ list_keyblock( KBNODE keyblock, int secret )
putchar(':');
putchar('\n');
}
else
printf("sub %4u%c/%08lX %s\n", nbits_from_pk( pk2 ),
else {
printf("sub %4u%c/%08lX %s", nbits_from_pk( pk2 ),
pubkey_letter( pk2->pubkey_algo ),
(ulong)keyid2[1],
datestr_from_pk( pk2 ) );
if( pk2->expiredate ) {
printf(_(" [expires: %s]"), expirestr_from_pk( pk2 ) );
}
putchar('\n');
}
if( opt.fingerprint > 1 )
fingerprint( pk2, NULL );
if( opt.with_key_data )
@ -346,6 +359,7 @@ list_keyblock( KBNODE keyblock, int secret )
else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
int sigrc;
char *sigstr;
if( !any ) { /* no user id, (maybe a revocation follows)*/
if( sig->sig_class == 0x20 )
@ -363,11 +377,11 @@ list_keyblock( KBNODE keyblock, int secret )
if( sig->sig_class == 0x20 || sig->sig_class == 0x28
|| sig->sig_class == 0x30 )
fputs("rev", stdout);
sigstr = "rev";
else if( (sig->sig_class&~3) == 0x10 )
fputs("sig", stdout);
sigstr = "sig";
else if( sig->sig_class == 0x18 )
fputs("sig", stdout);
sigstr = "sig";
else {
if( opt.with_colons )
printf("sig::::::::::%02x:\n",sig->sig_class );
@ -390,6 +404,7 @@ list_keyblock( KBNODE keyblock, int secret )
rc = 0;
sigrc = ' ';
}
fputs( sigstr, stdout );
if( opt.with_colons ) {
putchar(':');
if( sigrc != ' ' )
@ -405,7 +420,7 @@ list_keyblock( KBNODE keyblock, int secret )
printf("[%s] ", gpg_errstr(rc) );
else if( sigrc == '?' )
;
else {
else if ( !opt.fast_list_mode ) {
size_t n;
char *p = get_user_id( sig->keyid, &n );
if( opt.with_colons )

View File

@ -1,5 +1,5 @@
/* ks-proto.h
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*

View File

@ -1,5 +1,5 @@
/* main.h
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -73,7 +73,6 @@ int pubkey_get_nsig( int algo );
int pubkey_get_nenc( int algo );
unsigned int pubkey_nbits( int algo, MPI *pkey );
/*-- helptext.c --*/
void display_online_help( const char *keyword );
@ -94,7 +93,7 @@ int clearsign_file( const char *fname, STRLIST locusr, const char *outfile );
/*-- sig-check.c --*/
int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig );
int check_key_signature2( KBNODE root, KBNODE node,
int *is_selfsig, u32 *r_expire );
int *is_selfsig, u32 *r_expiredate, int *r_expired );
/*-- delkey.c --*/
int delete_key( const char *username, int secure );
@ -105,7 +104,7 @@ void keyedit_menu( const char *username, STRLIST locusr, STRLIST cmds,
/*-- keygen.c --*/
u32 ask_expiredate(void);
void generate_keypair(void);
void generate_keypair( const char *fname );
int keygen_add_key_expire( PKT_signature *sig, void *opaque );
int keygen_add_std_prefs( PKT_signature *sig, void *opaque );
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
@ -116,20 +115,20 @@ char *make_outfile_name( const char *iname );
char *ask_outfile_name( const char *name, size_t namelen );
int open_outfile( const char *iname, int mode, IOBUF *a );
IOBUF open_sigfile( const char *iname );
void copy_options_file( const char *destdir );
void try_make_homedir( const char *fname );
/*-- seskey.c --*/
void make_session_key( DEK *dek );
MPI encode_session_key( DEK *dek, unsigned nbits );
MPI encode_md_value( int pubkey_algo, GCRY_MD_HD md,
int hash_algo, unsigned nbits );
int hash_algo, unsigned nbits, int v3compathack );
/*-- comment.c --*/
KBNODE make_comment_node( const char *s );
KBNODE make_mpi_comment_node( const char *s, MPI a );
/*-- import.c --*/
int import_keys( const char *filename, int fast );
void import_keys( char **fnames, int nnames, int fast );
int import_keys_stream( IOBUF inp, int fast );
int collapse_uids( KBNODE *keyblock );
@ -137,20 +136,27 @@ int collapse_uids( KBNODE *keyblock );
int export_pubkeys( STRLIST users, int onlyrfc );
int export_pubkeys_stream( IOBUF out, STRLIST users, int onlyrfc );
int export_seckeys( STRLIST users );
int export_secsubkeys( STRLIST users );
/* dearmor.c --*/
int dearmor_file( const char *fname );
int enarmor_file( const char *fname );
/*-- revoke.c --*/
struct revocation_reason_info;
int gen_revoke( const char *uname );
int revocation_reason_build_cb( PKT_signature *sig, void *opaque );
struct revocation_reason_info *
ask_revocation_reason( int key_rev, int cert_rev, int hint );
void release_revocation_reason_info( struct revocation_reason_info *reason );
/*-- keylist.c --*/
void public_key_list( int nnames, char **names );
void secret_key_list( int nnames, char **names );
void public_key_list( STRLIST list );
void secret_key_list( STRLIST list );
/*-- verify.c --*/
int verify_signatures( int nfiles, char **files );
int verify_files( int nfiles, char **files );
/*-- decrypt.c --*/
int decrypt_message( const char *filename );

View File

@ -1,5 +1,5 @@
/* mainproc.c - handle packets
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -160,11 +160,11 @@ add_signature( CTX c, PACKET *pkt )
if( pkt->pkttype == PKT_SIGNATURE && !c->list ) {
/* This is the first signature for the following datafile.
* gpg does not write such packets; instead it always uses
* GPG does not write such packets; instead it always uses
* onepass-sig packets. The drawback of PGP's method
* of prepending the signature to the data is
* that it is not possible to make a signature from data read
* from stdin. (gpg is able to read PGP stuff anyway.) */
* from stdin. (GPG is able to read PGP stuff anyway.) */
node = new_kbnode( pkt );
c->list = node;
return 1;
@ -224,10 +224,14 @@ proc_pubkey_enc( CTX c, PACKET *pkt )
|| is_RSA(enc->pubkey_algo) ) {
if ( !c->dek && ((!enc->keyid[0] && !enc->keyid[1])
|| !seckey_available( enc->keyid )) ) {
c->dek = gcry_xmalloc_secure( sizeof *c->dek );
if( (result = get_session_key( enc, c->dek )) ) {
/* error: delete the DEK */
gcry_free(c->dek); c->dek = NULL;
if( opt.list_only )
result = -1;
else {
c->dek = gcry_xmalloc_secure( sizeof *c->dek );
if( (result = get_session_key( enc, c->dek )) ) {
/* error: delete the DEK */
gcry_free(c->dek); c->dek = NULL;
}
}
}
else
@ -267,6 +271,8 @@ print_failed_pkenc( struct kidlist_item *list )
PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
const char *algstr = gcry_pk_algo_name( list->pubkey_algo );
if( !algstr )
algstr = "[?]";
pk->pubkey_algo = list->pubkey_algo;
if( !get_pubkey( pk, list->kid ) ) {
size_t n;
@ -309,10 +315,14 @@ proc_encrypted( CTX c, PACKET *pkt )
print_failed_pkenc( c->failed_pkenc );
write_status( STATUS_BEGIN_DECRYPTION );
/*log_debug("dat: %sencrypted data\n", c->dek?"":"conventional ");*/
if( !c->dek && !c->last_was_session_key ) {
if( opt.list_only )
result = -1;
else if( !c->dek && !c->last_was_session_key ) {
/* assume this is old conventional encrypted data
* Actually we should use IDEA and MD5 in this case, but becuase
* Actually we should use IDEA and MD5 in this case, but because
* IDEA is patented we can't do so */
c->dek = passphrase_to_dek( NULL, 0,
opt.def_cipher_algo ? opt.def_cipher_algo
@ -322,6 +332,7 @@ proc_encrypted( CTX c, PACKET *pkt )
result = GPGERR_NO_SECKEY;
if( !result )
result = decrypt_data( c, pkt->pkt.encrypted, c->dek );
gcry_free(c->dek); c->dek = NULL;
if( result == -1 )
;
@ -339,11 +350,12 @@ proc_encrypted( CTX c, PACKET *pkt )
else {
write_status( STATUS_DECRYPTION_FAILED );
log_error(_("decryption failed: %s\n"), gpg_errstr(result));
/* Hmmm: does this work when we have encrypted using a multiple
/* Hmmm: does this work when we have encrypted using multiple
* ways to specify the session key (symmmetric and PK)*/
}
free_packet(pkt);
c->last_was_session_key = 0;
write_status( STATUS_END_DECRYPTION );
}
@ -360,7 +372,8 @@ proc_plaintext( CTX c, PACKET *pkt )
else if( opt.verbose )
log_info(_("original file name='%.*s'\n"), pt->namelen, pt->name);
free_md_filter_context( &c->mfx );
if( !(c->mfx.md = gcry_md_open( 0, 0)) )
c->mfx.md = gcry_md_open( 0, 0);
if( !c->mfx.md )
BUG();
/* fixme: we may need to push the textfilter if we have sigclass 1
* and no armoring - Not yet tested
@ -372,8 +385,7 @@ proc_plaintext( CTX c, PACKET *pkt )
for(n=c->list; n; n = n->next ) {
if( n->pkt->pkttype == PKT_ONEPASS_SIG ) {
if( n->pkt->pkt.onepass_sig->digest_algo ) {
gcry_md_enable( c->mfx.md,
n->pkt->pkt.onepass_sig->digest_algo );
gcry_md_enable( c->mfx.md, n->pkt->pkt.onepass_sig->digest_algo );
if( !any && n->pkt->pkt.onepass_sig->digest_algo
== GCRY_MD_MD5 )
only_md5 = 1;
@ -398,24 +410,28 @@ proc_plaintext( CTX c, PACKET *pkt )
clearsig = 1;
}
}
if( !any ) { /* no onepass sig packet: enable all standard algos */
if( !any && !opt.skip_verify ) {
/* no onepass sig packet: enable all standard algos */
gcry_md_enable( c->mfx.md, GCRY_MD_RMD160 );
gcry_md_enable( c->mfx.md, GCRY_MD_SHA1 );
gcry_md_enable( c->mfx.md, GCRY_MD_MD5 );
}
if( only_md5 ) {
if( opt.pgp2_workarounds && only_md5 && !opt.skip_verify ) {
/* This is a kludge to work around a bug in pgp2. It does only
* catch those mails which are armored. To catch the non-armored
* pgp mails we could see whether there is the signature packet
* in front of the plaintext. If someone needs this, send me a patch.
*/
if( !(c->mfx.md2 = gcry_md_open( GCRY_MD_MD5, 0)) )
c->mfx.md2 = gcry_md_open( GCRY_MD_MD5, 0);
if( !c->mfx.md2 )
BUG();
}
#if 0
#warning md_start_debug is enabled
md_start_debug( c->mfx.md, "verify" );
#endif
if ( DBG_HASHING ) {
gcry_md_start_debug( c->mfx.md, "verify" );
if ( c->mfx.md2 )
gcry_md_start_debug( c->mfx.md2, "verify2" );
}
rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig );
if( rc == GPGERR_CREATE_FILE && !c->sigs_only) {
/* can't write output but we hash it anyway to
@ -494,12 +510,17 @@ do_check_sig( CTX c, KBNODE node, int *is_selfsig )
* in canonical mode ??? (calculating both modes???) */
if( c->mfx.md ) {
md = gcry_md_copy( c->mfx.md );
if( c->mfx.md2 )
if( !md )
BUG();
if( c->mfx.md2 ) {
md2 = gcry_md_copy( c->mfx.md2 );
if( !md2 )
BUG();
}
}
else { /* detached signature */
log_debug("Do we really need this here?");
md = gcry_md_open( 0, 0 ); /* signature_check() will enable the md*/
log_debug("Do we really need this here?");
md = gcry_md_open( 0, 0 ); /* signature_check() will enable the md*/
md2 = gcry_md_open( 0, 0 );
if( !md || !md2 )
BUG();
@ -513,6 +534,11 @@ do_check_sig( CTX c, KBNODE node, int *is_selfsig )
|| c->list->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
return check_key_signature( c->list, node, is_selfsig );
}
else if( sig->sig_class == 0x20 ) {
log_info(_("standalone revocation - "
"use \"gpg --import\" to apply\n"));
return GPGERR_NOT_PROCESSED;
}
else {
log_error("invalid root packet for sigclass %02x\n",
sig->sig_class);
@ -540,8 +566,12 @@ print_userid( PACKET *pkt )
printf("ERROR: unexpected packet type %d", pkt->pkttype );
return;
}
print_string( stdout, pkt->pkt.user_id->name, pkt->pkt.user_id->len,
opt.with_colons );
if( opt.with_colons )
print_string( stdout, pkt->pkt.user_id->name,
pkt->pkt.user_id->len, ':');
else
print_utf8_string( stdout, pkt->pkt.user_id->name,
pkt->pkt.user_id->len );
}
@ -644,11 +674,13 @@ list_node( CTX c, KBNODE node )
keyid_from_pk( pk, keyid );
if( mainkey ) {
c->local_id = pk->local_id;
c->trustletter = query_trust_info( pk, NULL );
c->trustletter = opt.fast_list_mode?
0 : query_trust_info( pk, NULL );
}
printf("%s:%c:%u:%d:%08lX%08lX:%s:%s:",
mainkey? "pub":"sub",
c->trustletter,
printf("%s:", mainkey? "pub":"sub" );
if( c->trustletter )
putchar( c->trustletter );
printf(":%u:%d:%08lX%08lX:%s:%s:",
nbits_from_pk( pk ),
pk->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
@ -657,7 +689,7 @@ list_node( CTX c, KBNODE node )
if( c->local_id )
printf("%lu", c->local_id );
putchar(':');
if( c->local_id )
if( c->local_id && !opt.fast_list_mode )
putchar( get_ownertrust_info( c->local_id ) );
putchar(':');
if( node->next && node->next->pkt->pkttype == PKT_RING_TRUST) {
@ -675,6 +707,7 @@ list_node( CTX c, KBNODE node )
pubkey_letter( pk->pubkey_algo ),
(ulong)keyid_from_pk( pk, NULL ),
datestr_from_pk( pk ) );
if( mainkey ) {
/* and now list all userids with their signatures */
for( node = node->next; node; node = node->next ) {
@ -717,6 +750,10 @@ list_node( CTX c, KBNODE node )
}
}
}
else if( pk->expiredate ) { /* of subkey */
printf(_(" [expires: %s]"), expirestr_from_pk( pk ) );
}
if( !any )
putchar('\n');
if( !mainkey && opt.fingerprint > 1 )
@ -847,7 +884,7 @@ list_node( CTX c, KBNODE node )
if( opt.with_colons )
putchar(':');
}
else {
else if( !opt.fast_list_mode ) {
p = get_user_id( sig->keyid, &n );
print_string( stdout, p, n, opt.with_colons );
gcry_free(p);
@ -861,6 +898,7 @@ list_node( CTX c, KBNODE node )
}
int
proc_packets( void *anchor, IOBUF a )
{
@ -873,6 +911,8 @@ proc_packets( void *anchor, IOBUF a )
return rc;
}
int
proc_signature_packets( void *anchor, IOBUF a,
STRLIST signedfiles, const char *sigfilename )
@ -1027,7 +1067,7 @@ static int
check_sig_and_print( CTX c, KBNODE node )
{
PKT_signature *sig = node->pkt->pkt.signature;
const char *tstr;
const char *astr, *tstr;
int rc;
if( opt.skip_verify ) {
@ -1036,12 +1076,12 @@ check_sig_and_print( CTX c, KBNODE node )
}
tstr = asctimestamp(sig->timestamp);
astr = gcry_pk_algo_name( sig->pubkey_algo );
log_info(_("Signature made %.*s using %s key ID %08lX\n"),
(int)strlen(tstr), tstr, gcry_pk_algo_name( sig->pubkey_algo ),
(ulong)sig->keyid[1] );
(int)strlen(tstr), tstr, astr? astr: "?", (ulong)sig->keyid[1] );
rc = do_check_sig(c, node, NULL );
if( rc == GPGERR_NO_PUBKEY && opt.keyserver_name ) {
if( rc == GPGERR_NO_PUBKEY && opt.keyserver_name && opt.auto_key_retrieve) {
if( !hkp_ask_import( sig->keyid ) )
rc = do_check_sig(c, node, NULL );
}
@ -1121,7 +1161,8 @@ check_sig_and_print( CTX c, KBNODE node )
buf[16] = 0;
write_status_text( STATUS_NO_PUBKEY, buf );
}
log_error(_("Can't check signature: %s\n"), gpg_errstr(rc) );
if( rc != GPGERR_NOT_PROCESSED )
log_error(_("Can't check signature: %s\n"), gpg_errstr(rc) );
}
return rc;
}
@ -1136,7 +1177,7 @@ proc_tree( CTX c, KBNODE node )
KBNODE n1;
int rc;
if( opt.list_packets )
if( opt.list_packets || opt.list_only )
return;
c->local_id = 0;
@ -1155,7 +1196,7 @@ proc_tree( CTX c, KBNODE node )
if( !c->have_data ) {
free_md_filter_context( &c->mfx );
/* prepare to create all requested message digests */
if( !(c->mfx.md = gcry_md_open(0, 0)) )
if ( !(c->mfx.md = gcry_md_open(0, 0)) )
BUG();
/* fixme: why looking for the signature packet and not 1passpacket*/
@ -1163,13 +1204,16 @@ proc_tree( CTX c, KBNODE node )
gcry_md_enable( c->mfx.md, n1->pkt->pkt.signature->digest_algo);
}
/* ask for file and hash it */
if( c->sigs_only )
if( c->sigs_only ) {
rc = hash_datafiles( c->mfx.md, NULL,
c->signed_data, c->sigfilename,
n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 );
else
}
else {
rc = ask_for_detached_datafile( c->mfx.md, c->mfx.md2,
iobuf_get_fname(c->iobuf), 0 );
iobuf_get_fname(c->iobuf),
n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 );
}
if( rc ) {
log_error("can't hash datafile: %s\n", gpg_errstr(rc));
return;
@ -1182,15 +1226,22 @@ proc_tree( CTX c, KBNODE node )
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
if( !c->have_data ) {
if( sig->sig_class != 0x00 && sig->sig_class != 0x01 )
log_info(_("standalone signature of class 0x%02x\n"),
sig->sig_class);
else if( !c->have_data ) {
/* detached signature */
free_md_filter_context( &c->mfx );
if( !(c->mfx.md = gcry_md_open(sig->digest_algo, 0)) )
c->mfx.md = gcry_md_open(sig->digest_algo, 0);
if ( !c->mfx.md )
BUG();
if( sig->digest_algo == GCRY_MD_MD5
&& is_RSA( sig->pubkey_algo ) ) {
if( !opt.pgp2_workarounds )
;
else if( sig->digest_algo == GCRY_MD_MD5
&& is_RSA( sig->pubkey_algo ) ) {
/* enable a workaround for a pgp2 bug */
if( !(c->mfx.md2 = gcry_md_open( GCRY_MD_MD5, 0 )) )
c->mfx.md2 = gcry_md_open( GCRY_MD_MD5, 0 );
if ( !c->mfx.md2 )
BUG();
}
else if( sig->digest_algo == GCRY_MD_SHA1
@ -1198,9 +1249,11 @@ proc_tree( CTX c, KBNODE node )
&& sig->sig_class == 0x01 ) {
/* enable the workaround also for pgp5 when the detached
* signature has been created in textmode */
if( !(c->mfx.md2 = gcry_md_open( sig->digest_algo, 0 )) )
c->mfx.md2 = gcry_md_open( sig->digest_algo, 0 );
if ( !c->mfx.md2 )
BUG();
}
#if 0 /* workaround disabled */
/* Here we have another hack to work around a pgp 2 bug
* It works by not using the textmode for detached signatures;
* this will let the first signature check (on md) fail
@ -1208,14 +1261,18 @@ proc_tree( CTX c, KBNODE node )
* then produce the "correct" hash. This is very, very ugly
* hack but it may help in some cases (and break others)
*/
if( c->sigs_only )
/* c->mfx.md2? 0 :(sig->sig_class == 0x01) */
#endif
if( c->sigs_only ) {
rc = hash_datafiles( c->mfx.md, c->mfx.md2,
c->signed_data, c->sigfilename,
c->mfx.md2? 0 :(sig->sig_class == 0x01) );
else
(sig->sig_class == 0x01) );
}
else {
rc = ask_for_detached_datafile( c->mfx.md, c->mfx.md2,
iobuf_get_fname(c->iobuf),
c->mfx.md2? 0 :(sig->sig_class == 0x01) );
iobuf_get_fname(c->iobuf),
(sig->sig_class == 0x01) );
}
if( rc ) {
log_error("can't hash datafile: %s\n", gpg_errstr(rc));
return;

View File

@ -1,5 +1,5 @@
/* mdfilter.c - filter data and calculate a message digest
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -25,9 +25,9 @@
#include <errno.h>
#include <assert.h>
#include <gcrypt.h>
#include "errors.h"
#include "iobuf.h"
#include <gcrypt.h>
#include "util.h"
#include "filter.h"

View File

@ -1,5 +1,5 @@
/* misc.c - miscellaneous functions
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -23,7 +23,6 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
#include <asm/sysinfo.h>
#include <asm/unistd.h>
@ -32,6 +31,8 @@
#include <sys/time.h>
#include <sys/resource.h>
#endif
#include <assert.h>
#include <gcrypt.h>
#include "util.h"
#include "main.h"
@ -41,7 +42,6 @@
#define MAX_EXTERN_MPI_BITS 16384
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
#warning using trap_unaligned
static int
@ -246,6 +246,7 @@ mpi_print( FILE *fp, MPI a, int mode )
}
u16
checksum_u16( unsigned n )
{
@ -289,7 +290,6 @@ checksum_mpi( MPI a )
}
u32
buffer_to_u32( const byte *buffer )
{
@ -359,6 +359,7 @@ print_digest_algo_note( int algo )
}
/****************
* Wrapper around the libgcrypt function with addional checks on
* openPGP contrainst for the algo ID.

View File

@ -1,5 +1,5 @@
/* openfile.c
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -24,6 +24,9 @@
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "util.h"
#include <gcrypt.h>
@ -39,13 +42,16 @@
#define SKELEXT ".skel"
#endif
#ifdef HAVE_DRIVE_LETTERS
#define CMP_FILENAME(a,b) stricmp( (a), (b) )
#else
#define CMP_FILENAME(a,b) strcmp( (a), (b) )
#endif
#ifdef MKDIR_TAKES_ONE_ARG
# undef mkdir
# define mkdir(a,b) mkdir(a)
#endif
/* FIXME: Implement opt.interactive. */
@ -78,7 +84,6 @@ overwrite_filep( const char *fname )
}
/****************
* Strip know extensions from iname and return a newly allocated
* filename. Return NULL if we can't do that.
@ -176,7 +181,7 @@ open_outfile( const char *iname, int mode, IOBUF *a )
name = opt.outfile;
else {
#ifdef USE_ONLY_8DOT3
/* It is quite common for DOS system to have only one dot in a
/* It is quite common DOS system to have only one dot in a
* a filename So if we have something like this, we simple
* replace the suffix execpt in cases where the suffix is
* larger than 3 characters and not the same as.
@ -195,7 +200,7 @@ open_outfile( const char *iname, int mode, IOBUF *a )
strcpy(dot, newsfx );
}
else if( dot && !dot[1] ) /* don't duplicate a dot */
strcat( dot, newsfx+1 );
strcpy( dot, newsfx+1 );
else
strcat( buf, newsfx );
#else
@ -253,7 +258,7 @@ open_sigfile( const char *iname )
/****************
* Copy the option file skeleton to the given directory.
*/
void
static void
copy_options_file( const char *destdir )
{
const char *datadir = GNUPG_DATADIR;
@ -296,3 +301,23 @@ copy_options_file( const char *destdir )
gcry_free(fname);
}
void
try_make_homedir( const char *fname )
{
if( opt.dry_run )
return;
if( strlen(fname) >= 7
&& !strcmp(fname+strlen(fname)-7, "/.gnupg" ) ) {
if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
log_fatal( _("%s: can't create directory: %s\n"),
fname, strerror(errno) );
else if( !opt.quiet )
log_info( _("%s: directory created\n"), fname );
copy_options_file( fname );
log_info(_("you have to start GnuPG again, "
"so it can read the new options file\n") );
gpg_exit(1);
}
}

View File

@ -1,5 +1,5 @@
/* options.h
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -28,11 +28,12 @@
struct {
int verbose;
int quiet;
unsigned debug;
unsigned int debug;
int armor;
int compress;
char *outfile;
int dry_run;
int list_only;
int textmode;
int batch; /* run in batch mode */
int answer_yes; /* answer yes on most questions */
@ -63,7 +64,9 @@ struct {
int compress_sigs;
int always_trust;
int rfc1991;
unsigned emulate_bugs; /* bug emulation flags EMUBUG_xxxx */
int rfc2440;
int pgp2_workarounds;
unsigned int emulate_bugs; /* bug emulation flags EMUBUG_xxxx */
int shm_coprocess;
const char *set_filename;
const char *comment_string;
@ -83,9 +86,17 @@ struct {
int allow_non_selfsigned_uid;
int no_literal;
ulong set_filesize;
int honor_http_proxy;
int fast_list_mode;
int ignore_time_conflict;
int command_fd;
int auto_key_retrieve;
} opt;
#define EMUBUG_3DESS2K 2
#define EMUBUG_MDENCODE 4
#define DBG_PACKET_VALUE 1 /* debug packet reading/writing */
#define DBG_MPI_VALUE 2 /* debug mpi details */
#define DBG_CIPHER_VALUE 4 /* debug cipher handling */
@ -96,6 +107,7 @@ struct {
#define DBG_CACHE_VALUE 64 /* debug the cacheing */
#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
#define DBG_TRUST_VALUE 256 /* debug the trustdb */
#define DBG_HASHING_VALUE 512 /* debug hashing operations */
#define DBG_PACKET (opt.debug & DBG_PACKET_VALUE)
@ -104,6 +116,6 @@ struct {
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
#define DBG_TRUST (opt.debug & DBG_TRUST_VALUE)
#define DBG_CIPHER (opt.debug & DBG_CIPHER_VALUE)
#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
#endif /*GPG_OPTIONS_H*/

View File

@ -1,5 +1,5 @@
/* packet.h - packet read/write stuff
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -54,14 +54,16 @@ typedef enum {
PKT_USER_ID =13, /* user id packet */
PKT_PUBLIC_SUBKEY =14, /* public subkey (OpenPGP) */
PKT_OLD_COMMENT =16, /* comment packet from an OpenPGP draft */
PKT_PHOTO_ID =17, /* PGP's photo ID */
PKT_ENCRYPTED_MDC =18, /* integrity protected encrypted data */
PKT_MDC =19, /* manipulaion detection code packet */
PKT_COMMENT =61, /* new comment packet (private) */
PKT_ENCRYPTED_MDC =62, /* test: encrypted data with MDC */
} pkttype_t;
typedef struct packet_struct PACKET;
typedef struct {
byte mode;
int mode;
byte hash_algo;
byte salt[8];
u32 count;
@ -105,7 +107,7 @@ typedef struct {
byte version;
byte sig_class; /* sig classification, append for MD calculation*/
byte pubkey_algo; /* algorithm used for public key scheme */
/* (PUBKEY_ALGO_xxx) */
/* (GCRY_PK_xxx) */
byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */
byte *hashed_data; /* all subpackets with hashed data (v4 only) */
byte *unhashed_data; /* ditto for unhashed data */
@ -165,6 +167,8 @@ typedef struct {
ulong stored_at; /* the stream offset where it was stored
* by build-packet */
int len; /* length of the name */
char *photo; /* if this is not NULL, the packet is a photo ID */
int photolen; /* and the length of the photo */
char name[1];
} PKT_user_id;
@ -178,10 +182,14 @@ typedef struct {
typedef struct {
u32 len; /* length of encrypted data */
byte new_ctb; /* uses a new CTB */
byte mdc_method; /* test: > 0: this is is an encrypted_mdc packet */
byte mdc_method; /* > 0: integrity protected encrypted data packet */
IOBUF buf; /* IOBUF reference */
} PKT_encrypted;
typedef struct {
byte hash[20];
} PKT_mdc;
typedef struct {
unsigned int trustval;
} PKT_ring_trust;
@ -212,6 +220,7 @@ struct packet_struct {
PKT_user_id *user_id; /* PKT_USER_ID */
PKT_compressed *compressed; /* PKT_COMPRESSED */
PKT_encrypted *encrypted; /* PKT_ENCRYPTED[_MDC] */
PKT_mdc *mdc; /* PKT_MDC */
PKT_ring_trust *ring_trust; /* PKT_RING_TRUST */
PKT_plaintext *plaintext; /* PKT_PLAINTEXT */
} pkt;
@ -246,6 +255,7 @@ typedef enum {
SIGSUBPKT_POLICY =26, /* policy URL */
SIGSUBPKT_KEY_FLAGS =27, /* key flags */
SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */
SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */
SIGSUBPKT_PRIV_ADD_SIG =101,/* signatur is also valid for this uid */
SIGSUBPKT_FLAG_CRITICAL=128
@ -339,7 +349,6 @@ int handle_compressed( void *ctx, PKT_compressed *cd,
/*-- encr-data.c --*/
int decrypt_data( void *ctx, PKT_encrypted *ed, DEK *dek );
int encrypt_data( PKT_encrypted *ed, DEK *dek );
/*-- plaintext.c --*/
int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,

View File

@ -1,5 +1,5 @@
/* parse-packet.c - read packets
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -24,10 +24,10 @@
#include <string.h>
#include <assert.h>
#include <gcrypt.h>
#include "packet.h"
#include "iobuf.h"
#include "util.h"
#include <gcrypt.h>
#include "filter.h"
#include "options.h"
#include "main.h"
@ -59,6 +59,8 @@ static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
byte *hdr, int hdrlen, PACKET *packet );
static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
static int parse_photo_id( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen,
@ -69,6 +71,8 @@ static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet, int new_ctb );
static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet, int new_ctb);
static int parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet, int new_ctb);
static unsigned short
read_16(IOBUF inp)
@ -415,6 +419,10 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
case PKT_USER_ID:
rc = parse_user_id(inp, pkttype, pktlen, pkt );
break;
case PKT_PHOTO_ID:
pkt->pkttype = pkttype = PKT_USER_ID; /* must fix it */
rc = parse_photo_id(inp, pkttype, pktlen, pkt);
break;
case PKT_OLD_COMMENT:
case PKT_COMMENT:
rc = parse_comment(inp, pkttype, pktlen, pkt);
@ -433,6 +441,9 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
case PKT_ENCRYPTED_MDC:
rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb );
break;
case PKT_MDC:
rc = parse_mdc(inp, pkttype, pktlen, pkt, new_ctb );
break;
default:
skip_packet(inp, pkttype, pktlen);
break;
@ -803,6 +814,13 @@ dump_sig_subpkt( int hashed, int type, int critical,
case SIGSUBPKT_SIGNERS_UID:
p = "signer's user ID";
break;
case SIGSUBPKT_REVOC_REASON:
if( length ) {
printf("revocation reason 0x%02x (", *buffer );
print_string( stdout, buffer+1, length-1, ')' );
p = ")";
}
break;
case SIGSUBPKT_PRIV_ADD_SIG:
p = "signs additional user ID";
break;
@ -840,6 +858,10 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
if( n < 8 ) /* minimum length needed */
break;
return 0;
case SIGSUBPKT_REVOC_REASON:
if( !n )
break;
return 0;
case SIGSUBPKT_PREF_SYM:
case SIGSUBPKT_PREF_HASH:
case SIGSUBPKT_PREF_COMPR:
@ -877,7 +899,7 @@ can_handle_critical( const byte *buffer, size_t n, int type )
case SIGSUBPKT_PREF_COMPR:
return 1;
case SIGSUBPKT_POLICY: /* Is enough to show the policy? */
case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */
default:
return 0;
}
@ -896,8 +918,12 @@ enum_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype,
int seq = 0;
int reqseq = start? *start: 0;
if( !buffer || reqseq == -1 )
return NULL;
if( !buffer || reqseq == -1 ) {
/* return some value different from NULL to indicate that
* there is no crtitical bit we do not understand. The caller
* will never use the value. Yes I know, it is an ugly hack */
return reqtype == SIGSUBPKT_TEST_CRITICAL? (const byte*)&buffer : NULL;
}
buflen = (*buffer << 8) | buffer[1];
buffer += 2;
while( buflen ) {
@ -1131,8 +1157,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
unknown_pubkey_warning( sig->pubkey_algo );
/* we store the plain material in data[0], so that we are able
* to write it back with build_packet() */
sig->data[0] = gcry_mpi_set_opaque(NULL,
read_rest(inp, pktlen), pktlen*8 );
sig->data[0] = mpi_set_opaque(NULL, read_rest(inp, pktlen), pktlen );
pktlen = 0;
}
else {
@ -1317,6 +1342,24 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
sk->protect.s2k.mode = iobuf_get_noeof(inp); pktlen--;
sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
/* check for the special GNU extension */
if( is_v4 && sk->protect.s2k.mode == 101 ) {
for(i=0; i < 4 && pktlen; i++, pktlen-- )
temp[i] = iobuf_get_noeof(inp);
if( i < 4 || memcmp( temp, "GNU", 3 ) ) {
if( list_mode )
printf( "\tunknown S2K %d\n",
sk->protect.s2k.mode );
rc = GPGERR_INVALID_PACKET;
goto leave;
}
/* here we know that it is a gnu extension
* What follows is the GNU protection mode:
* All values have special meanings
* and they are mapped in the mode with a base of 1000.
*/
sk->protect.s2k.mode = 1000 + temp[3];
}
switch( sk->protect.s2k.mode ) {
case 1:
case 3:
@ -1332,10 +1375,13 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
break;
case 3: if( list_mode ) printf( "\titer+salt S2K" );
break;
case 1001: if( list_mode ) printf( "\tgnu-dummy S2K" );
break;
default:
if( list_mode )
printf( "\tunknown S2K %d\n",
sk->protect.s2k.mode );
printf( "\tunknown %sS2K %d\n",
sk->protect.s2k.mode < 1000? "":"GNU ",
sk->protect.s2k.mode );
rc = GPGERR_INVALID_PACKET;
goto leave;
}
@ -1388,6 +1434,9 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
default:
sk->protect.ivlen = 8;
}
if( sk->protect.s2k.mode == 1001 )
sk->protect.ivlen = 0;
if( pktlen < sk->protect.ivlen ) {
rc = GPGERR_INVALID_PACKET;
goto leave;
@ -1408,10 +1457,15 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
* If the user is so careless, not to protect his secret key,
* we can assume, that he operates an open system :=(.
* So we put the key into secure memory when we unprotect it. */
if( is_v4 && sk->is_protected ) {
if( sk->protect.s2k.mode == 1001 ) {
/* better set some dummy stuff here */
sk->skey[npkey] = mpi_set_opaque(NULL, gcry_xstrdup("dummydata"), 10);
pktlen = 0;
}
else if( is_v4 && sk->is_protected ) {
/* ugly; the length is encrypted too, so we read all
* stuff up to the end of the packet into the first
* skey element (which is the one indexed by npkey) */
* skey element */
sk->skey[npkey] = gcry_mpi_set_opaque(NULL,
read_rest(inp, pktlen), pktlen*8 );
pktlen = 0;
@ -1475,6 +1529,8 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
packet->pkt.user_id = gcry_xmalloc(sizeof *packet->pkt.user_id + pktlen);
packet->pkt.user_id->len = pktlen;
packet->pkt.user_id->photo = NULL;
packet->pkt.user_id->photolen = 0;
p = packet->pkt.user_id->name;
for( ; pktlen; pktlen--, p++ )
*p = iobuf_get_noeof(inp);
@ -1496,6 +1552,31 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
}
/****************
* PGP generates a packet of type 17. We assume this is a photo ID and
* simply store it here as a comment packet.
*/
static int
parse_photo_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
{
byte *p;
packet->pkt.user_id = gcry_xmalloc(sizeof *packet->pkt.user_id + 30);
sprintf( packet->pkt.user_id->name, "[image of size %lu]", pktlen );
packet->pkt.user_id->len = strlen(packet->pkt.user_id->name);
packet->pkt.user_id->photo = gcry_xmalloc(sizeof *packet->pkt.user_id + pktlen);
packet->pkt.user_id->photolen = pktlen;
p = packet->pkt.user_id->photo;
for( ; pktlen; pktlen--, p++ )
*p = iobuf_get_noeof(inp);
if( list_mode ) {
printf(":photo_id packet: %s\n", packet->pkt.user_id->name );
}
return 0;
}
static int
parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
@ -1624,9 +1705,8 @@ parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
ed->new_ctb = new_ctb;
ed->mdc_method = 0;
if( pkttype == PKT_ENCRYPTED_MDC ) {
/* test: this is the new encrypted_mdc packet */
/* fixme: add some pktlen sanity checks */
int version, method;
int version;
version = iobuf_get_noeof(inp); pktlen--;
if( version != 1 ) {
@ -1634,12 +1714,7 @@ parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
version);
goto leave;
}
method = iobuf_get_noeof(inp); pktlen--;
if( method != GCRY_MD_SHA1 ) {
log_error("encrypted_mdc does not use SHA1 method\n" );
goto leave;
}
ed->mdc_method = method;
ed->mdc_method = GCRY_MD_SHA1;
}
if( pktlen && pktlen < 10 ) { /* actually this is blocksize+2 */
log_error("packet(%d) too short\n", pkttype);
@ -1662,3 +1737,26 @@ parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
return 0;
}
static int
parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *pkt, int new_ctb )
{
PKT_mdc *mdc;
byte *p;
mdc = pkt->pkt.mdc= gcry_xmalloc(sizeof *pkt->pkt.mdc );
if( list_mode )
printf(":mdc packet: length=%lu\n", pktlen);
if( !new_ctb || pktlen != 20 ) {
log_error("mdc_packet with invalid encoding\n");
goto leave;
}
p = mdc->hash;
for( ; pktlen; pktlen--, p++ )
*p = iobuf_get_noeof(inp);
leave:
return 0;
}

View File

@ -1,5 +1,5 @@
/* passphrase.c - Get a passphrase
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -24,8 +24,9 @@
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include "util.h"
#include <gcrypt.h>
#include "util.h"
#include "options.h"
#include "ttyio.h"
#include "keydb.h"
@ -163,9 +164,9 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
tty_printf("\"\n");
if( !get_pubkey( pk, keyid ) ) {
const char *s = gcry_pk_algo_name( pk->pubkey_algo );
tty_printf( _("%u-bit %s key, ID %08lX, created %s"),
nbits_from_pk( pk ),
gcry_pk_algo_name( pk->pubkey_algo ), (ulong)keyid[1],
nbits_from_pk( pk ), s?s:"?", (ulong)keyid[1],
strtimestamp(pk->timestamp) );
if( keyid[2] && keyid[3] && keyid[0] != keyid[2]
&& keyid[1] != keyid[3] )

View File

@ -1,5 +1,5 @@
/* pkclist.c
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -24,11 +24,10 @@
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <gcrypt.h>
#include <gcrypt.h>
#include "options.h"
#include "packet.h"
#include "main.h"
#include "errors.h"
#include "keydb.h"
#include "util.h"
@ -36,6 +35,7 @@
#include "ttyio.h"
#include "status.h"
#include "i18n.h"
#include "main.h"
#define CONTROL_D ('D' - 'A' + 1)
@ -97,6 +97,112 @@ fpr_info( PKT_public_key *pk )
}
/****************
* Show the revocation reason as it is stored with the given signature
*/
static void
do_show_revocation_reason( PKT_signature *sig )
{
size_t n, nn;
const byte *p, *pp;
int seq = 0;
const char *text;
while( (p = enum_sig_subpkt( sig->hashed_data, SIGSUBPKT_REVOC_REASON,
&n, &seq )) ) {
if( !n )
continue; /* invalid - just skip it */
if( *p == 0 )
text = _("No reason specified");
else if( *p == 0x01 )
text = _("Key is superseeded");
else if( *p == 0x02 )
text = _("Key has been compromised");
else if( *p == 0x03 )
text = _("Key is no longer used");
else if( *p == 0x20 )
text = _("User ID is no longer valid");
else
text = NULL;
log_info( _("Reason for revocation: ") );
if( text )
fputs( text, log_stream() );
else
fprintf( log_stream(), "code=%02x", *p );
putc( '\n', log_stream() );
n--; p++;
pp = NULL;
do {
/* We don't want any empty lines, so skip them */
while( n && *p == '\n' ) {
p++;
n--;
}
if( n ) {
pp = memchr( p, '\n', n );
nn = pp? pp - p : n;
log_info( _("Revocation comment: ") );
print_string( log_stream(), p, nn, 0 );
putc( '\n', log_stream() );
p += nn; n -= nn;
}
} while( pp );
}
}
static void
show_revocation_reason( PKT_public_key *pk )
{
/* Hmmm, this is not so easy becuase we have to duplicate the code
* used in the trustbd to calculate the keyflags. We need to find
* a clean way to check revocation certificates on keys and signatures.
* And there should be no duplicate code. Because we enter this function
* only when the trustdb toldus, taht we have a revoked key, we could
* simplylook for a revocation cert and display this one, when there is
* only one. Let's try to do this until we have a better solution.
*/
KBNODE node, keyblock = NULL;
byte fingerprint[MAX_FINGERPRINT_LEN];
size_t fingerlen;
int rc;
/* get the keyblock */
fingerprint_from_pk( pk, fingerprint, &fingerlen );
rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen );
if( rc ) { /* that should never happen */
log_debug( "failed to get the keyblock\n");
return;
}
for( node=keyblock; node; node = node->next ) {
if( ( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
&& !cmp_public_keys( node->pkt->pkt.public_key, pk ) )
break;
}
if( !node ) {
log_debug("Oops, PK not in keyblock\n");
release_kbnode( keyblock );
return;
}
/* now find the revocation certificate */
for( node = node->next; node ; node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
break;
if( node->pkt->pkttype == PKT_SIGNATURE
&& (node->pkt->pkt.signature->sig_class == 0x20
|| node->pkt->pkt.signature->sig_class == 0x28 ) ) {
/* FIXME: we should check the signature here */
do_show_revocation_reason ( node->pkt->pkt.signature );
}
}
release_kbnode( keyblock );
}
static void
show_paths( ulong lid, int only_first )
@ -338,38 +444,53 @@ _("Could not find a valid trust path to the key. Let's see whether we\n"
/****************
* Check whether we can trust this pk which has a trustlevel of TRUSTLEVEL
* Returns: true if we trust.
* Returns: true if we trust. Might change the trustlevel
*/
static int
do_we_trust( PKT_public_key *pk, int trustlevel )
do_we_trust( PKT_public_key *pk, int *trustlevel )
{
int rc;
int did_add = 0;
int trustmask = 0;
retry:
if( (trustlevel & TRUST_FLAG_REVOKED) ) {
if( (*trustlevel & TRUST_FLAG_REVOKED) ) {
log_info(_("key %08lX: key has been revoked!\n"),
(ulong)keyid_from_pk( pk, NULL) );
show_revocation_reason( pk );
if( opt.batch )
return 0;
if( !cpr_get_answer_is_yes("revoked_key.override",
_("Use this key anyway? ")) )
return 0;
trustmask |= TRUST_FLAG_REVOKED;
}
else if( (trustlevel & TRUST_FLAG_SUB_REVOKED) ) {
else if( (*trustlevel & TRUST_FLAG_SUB_REVOKED) ) {
log_info(_("key %08lX: subkey has been revoked!\n"),
(ulong)keyid_from_pk( pk, NULL) );
show_revocation_reason( pk );
if( opt.batch )
return 0;
if( !cpr_get_answer_is_yes("revoked_key.override",
_("Use this key anyway? ")) )
return 0;
trustmask |= TRUST_FLAG_SUB_REVOKED;
}
*trustlevel &= ~trustmask;
if( opt.always_trust) {
if( opt.verbose )
log_info("No trust check due to --always-trust option\n");
/* The problem with this, is that EXPIRE can't be checked as
* this needs to insert a ne key into the trustdb first and
* we don't want that */
return 1;
}
switch( (trustlevel & TRUST_MASK) ) {
switch( (*trustlevel & TRUST_MASK) ) {
case TRUST_UNKNOWN: /* No pubkey in trustDB: Insert and check again */
rc = insert_trust_record_by_pk( pk );
if( rc ) {
@ -377,11 +498,12 @@ do_we_trust( PKT_public_key *pk, int trustlevel )
gpg_errstr(rc) );
return 0; /* no */
}
rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
rc = check_trust( pk, trustlevel, NULL, NULL, NULL );
*trustlevel &= ~trustmask;
if( rc )
log_fatal("trust check after insert failed: %s\n",
gpg_errstr(rc) );
if( trustlevel == TRUST_UNKNOWN || trustlevel == TRUST_EXPIRED ) {
if( *trustlevel == TRUST_UNKNOWN || *trustlevel == TRUST_EXPIRED ) {
log_debug("do_we_trust: oops at %d\n", __LINE__ );
return 0;
}
@ -399,7 +521,8 @@ do_we_trust( PKT_public_key *pk, int trustlevel )
else {
int quit;
rc = add_ownertrust( pk, &quit, &trustlevel );
rc = add_ownertrust( pk, &quit, trustlevel );
*trustlevel &= ~trustmask;
if( !rc && !did_add && !quit ) {
did_add = 1;
goto retry;
@ -445,7 +568,7 @@ do_we_trust_pre( PKT_public_key *pk, int trustlevel )
{
int rc;
rc = do_we_trust( pk, trustlevel );
rc = do_we_trust( pk, &trustlevel );
if( (trustlevel & TRUST_FLAG_REVOKED) && !rc )
return 0;
@ -528,10 +651,12 @@ check_signatures_trust( PKT_signature *sig )
write_status( STATUS_KEYREVOKED );
log_info(_("WARNING: This key has been revoked by its owner!\n"));
log_info(_(" This could mean that the signature is forgery.\n"));
show_revocation_reason( pk );
}
else if( (trustlevel & TRUST_FLAG_SUB_REVOKED) ) {
write_status( STATUS_KEYREVOKED );
log_info(_("WARNING: This subkey has been revoked by its owner!\n"));
show_revocation_reason( pk );
}
@ -770,7 +895,8 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
else {
int trustlevel;
rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
rc = check_trust( pk, &trustlevel, pk->namehash,
NULL, NULL );
if( rc ) {
log_error("error checking pk of `%s': %s\n",
answer, gpg_errstr(rc) );
@ -844,7 +970,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
else if( !(rc=openpgp_pk_test_algo(pk->pubkey_algo, use )) ) {
int trustlevel;
rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
rc = check_trust( pk, &trustlevel, pk->namehash, NULL, NULL );
if( rc ) {
free_public_key( pk ); pk = NULL;
log_error(_("%s: error checking key: %s\n"),

View File

@ -1,5 +1,5 @@
/* plaintext.c - process an plaintext packet
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -107,8 +107,10 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
}
if( mfx->md )
gcry_md_putc(mfx->md, c );
if( c == '\r' )
continue; /* fixme: this hack might be too simple */
#ifndef HAVE_DOSISH_SYSTEM
if( c == '\r' ) /* convert to native line ending */
continue; /* fixme: this hack might be too simple */
#endif
if( fp ) {
if( putc( c, fp ) == EOF ) {
log_error("Error writing to `%s': %s\n",
@ -152,8 +154,10 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
while( (c = iobuf_get(pt->buf)) != -1 ) {
if( mfx->md )
gcry_md_putc(mfx->md, c );
#ifndef HAVE_DOSISH_SYSTEM
if( convert && c == '\r' )
continue; /* fixme: this hack might be too simple */
#endif
if( fp ) {
if( putc( c, fp ) == EOF ) {
log_error("Error writing to `%s': %s\n",
@ -169,10 +173,10 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
int eof;
for( eof=0; !eof; ) {
/* Why do we check for len < 32768:
* If we won´ we would practically read 2 EOFS but
* If we won't, we would practically read 2 EOFs but
* the first one has already popped the block_filter
* off and therefore we don't catch the boundary.
* Always assume EOF if iobuf_read returns less bytes
* So, always assume EOF if iobuf_read returns less bytes
* then requested */
int len = iobuf_read( pt->buf, buffer, 32768 );
if( len == -1 )
@ -217,6 +221,8 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
if( !state ) {
if( c == '\r' )
state = 1;
else if( c == '\n' )
state = 2;
else
gcry_md_putc(mfx->md, c );
}

View File

@ -1,5 +1,5 @@
/* pubkey-enc.c - public key encoded packet handling
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -23,14 +23,15 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "util.h"
#include <gcrypt.h>
#include "util.h"
#include "packet.h"
#include "main.h"
#include "keydb.h"
#include "trustdb.h"
#include "status.h"
#include "options.h"
#include "main.h"
#include "i18n.h"
static int get_it( PKT_pubkey_enc *k,
@ -103,7 +104,6 @@ pk_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
}
/****************
* Get the session key from a pubkey enc paket and return
* it in DEK, which should have been allocated in secure memory.
@ -169,7 +169,7 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
int rc;
MPI plain_dek = NULL;
byte *frame = NULL;
unsigned n;
unsigned int n;
size_t nframe;
u16 csum, csum2;
@ -199,7 +199,7 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
* DEK is the encryption key (session key) with length k
* CSUM
*/
if( (opt.debug & DBG_CIPHER_VALUE) )
if( DBG_CIPHER )
log_hexdump("DEK frame:", frame, nframe );
n=0;
if( n + 7 > nframe )
@ -219,10 +219,14 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
dek->keylen = nframe - (n+1) - 2;
dek->algo = frame[n++];
if( dek->algo == GCRY_CIPHER_IDEA )
if( dek->algo == GCRY_CIPHER_IDEA )
write_status(STATUS_RSA_OR_IDEA);
rc = openpgp_cipher_test_algo( dek->algo );
if( rc ) {
if( !opt.quiet && rc == GPGERR_CIPHER_ALGO ) {
log_info(_("cipher algorithm %d is unknown or disabled\n"),
dek->algo);
}
dek->algo = 0;
goto leave;
}
@ -241,9 +245,9 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
rc = GPGERR_WRONG_SECKEY;
goto leave;
}
if( (opt.debug & DBG_CIPHER_VALUE) )
if( DBG_CIPHER )
log_hexdump("DEK is:", dek->key, dek->keylen );
/* check that the algo is in the preferences */
/* check that the algo is in the preferences and whether it has expired */
{
PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
if( (rc = get_pubkey( pk, keyid )) )
@ -262,10 +266,25 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
"NOTE: cipher algorithm %d not found in preferences\n"),
dek->algo );
}
if( !rc && pk->expiredate && pk->expiredate <= make_timestamp() ) {
log_info(_("NOTE: secret key %08lX expired at %s\n"),
(ulong)keyid[1], asctimestamp( pk->expiredate) );
}
/* FIXME: check wheter the key has been revoked and display
* the revocation reason. Actually the user should know this himself,
* but the sender might not know already and therefor the user
* should get a notice that an revoked key has been used to decode
* the message. The user can than watch out for snakes send by
* one of those Eves outside his paradise :-)
*/
free_public_key( pk );
rc = 0;
}
leave:
mpi_release(plain_dek);
gcry_free(frame);

View File

@ -1,5 +1,5 @@
/* revoke.c
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -24,6 +24,7 @@
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <ctype.h>
#include "options.h"
#include "packet.h"
@ -37,6 +38,38 @@
#include "i18n.h"
struct revocation_reason_info {
int code;
char *desc;
};
int
revocation_reason_build_cb( PKT_signature *sig, void *opaque )
{
struct revocation_reason_info *reason = opaque;
char *ud = NULL;
byte *buffer;
size_t buflen = 1;
if( reason->desc ) {
ud = native_to_utf8( reason->desc );
buflen += strlen(ud);
}
buffer = gcry_xmalloc( buflen );
*buffer = reason->code;
if( ud ) {
memcpy(buffer+1, ud, strlen(ud) );
gcry_free( ud );
}
build_sig_subpkt( sig, SIGSUBPKT_REVOC_REASON, buffer, buflen );
gcry_free( buffer );
return 0;
}
/****************
* Generate a revocation certificate for UNAME
*/
@ -55,6 +88,7 @@ gen_revoke( const char *uname )
KBNODE keyblock = NULL;
KBNODE node;
KBPOS kbpos;
struct revocation_reason_info *reason = NULL;
if( opt.batch ) {
log_error(_("sorry, can't do this in batch mode\n"));
@ -62,19 +96,6 @@ gen_revoke( const char *uname )
}
/* FIXME: ask for the reason of revocation
0x00 - No reason specified (key revocations or cert revocations)
Does not make sense!
0x01 - Key is superceded (key revocations)
0x02 - Key material has been compromised (key revocations)
0x03 - Key is no longer used (key revocations)
0x20 - User id information is no longer valid (cert revocations)
Following the revocation code is a string of octets which gives
information about the reason for revocation in human-readable form
*/
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
init_packet( &pkt );
@ -136,6 +157,13 @@ gen_revoke( const char *uname )
goto leave;
}
/* get the reason for the revocation */
reason = ask_revocation_reason( 1, 0, 1 );
if( !reason ) { /* user decided to cancel */
rc = 0;
goto leave;
}
switch( is_secret_key_protected( sk ) ) {
case -1:
log_error(_("unknown protection algorithm\n"));
@ -163,7 +191,9 @@ gen_revoke( const char *uname )
iobuf_push_filter( out, armor_filter, &afx );
/* create it */
rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0, NULL, NULL);
rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
revocation_reason_build_cb,
reason );
if( rc ) {
log_error(_("make_keysig_packet failed: %s\n"), gpg_errstr(rc));
goto leave;
@ -198,193 +228,127 @@ gen_revoke( const char *uname )
iobuf_cancel(out);
else
iobuf_close(out);
release_revocation_reason_info( reason );
return rc;
}
#if 0 /* The code is not complete but anyway, now we use */
/* the edit menu to revoke signature */
/****************
* Return true if there is already a revocation signature for KEYID
* in KEYBLOCK at point node.
*/
static int
already_revoked( const KBNODE keyblock, const KBNODE node, u32 *keyid ) ) {
{
const KBNODE n = find_prev_kbnode( keyblock, node, PKT_USER_ID );
for( ; n; n = n->next ) {
PKT_signature *sig;
if( n->pkt->pkttype == PKT_SIGNATURE
&& (sig = node->pkt->pkt.signature)->sig_class == 0x30
&& sig->keyid[0] == keyid[0]
&& sig->keyid[1] == keyid[1] )
return 1;
struct revocation_reason_info *
ask_revocation_reason( int key_rev, int cert_rev, int hint )
{
int code;
char *description = NULL;
struct revocation_reason_info *reason;
const char *text_1 = _("Key has been compromised");
const char *text_2 = _("Key is superseded");
const char *text_3 = _("Key is no longer used");
const char *text_4 = _("User ID is non longer valid");
const char *code_text = NULL;
do {
gcry_free(description);
description = NULL;
tty_printf(_("Please select the reason for the revocation:\n"));
if( key_rev )
tty_printf(" 1 = %s\n", text_1 );
if( key_rev )
tty_printf(" 2 = %s\n", text_2 );
if( key_rev )
tty_printf(" 3 = %s\n", text_3 );
if( cert_rev )
tty_printf(" 4 = %s\n", text_4 );
tty_printf( " 0 = %s\n", _("Cancel") );
if( hint )
tty_printf(_("(Probably you want to select %d here)\n"), hint );
for(code = 0; !code;) {
int n;
char *answer = cpr_get("ask_revocation_reason.code",
_("Your decision? "));
trim_spaces( answer );
cpr_kill_prompt();
if( *answer == 'q' || *answer == 'Q' )
n = 0;
else if( !isdigit( *answer ) )
n = -1;
else if( hint && !*answer )
n = hint;
else
n = atoi(answer);
gcry_free(answer);
if( !n )
return NULL; /* cancel */
else if( key_rev && n == 1 ) {
code = 0x02; /* key has been compromised */
code_text = text_1;
}
else if( key_rev && n == 2 ) {
code = 0x01; /* key is superseded */
code_text = text_2;
}
else if( key_rev && n == 3 ) {
code = 0x03; /* key is no longer used */
code_text = text_3;
}
else if( cert_rev && n == 4 ) {
code = 0x20; /* uid is non longer valid */
code_text = text_4;
}
else
tty_printf(_("Invalid selection.\n"));
}
else if( n->pkt->pkttype == PKT_USER_ID
break;
else if( n->pkt->pkttype == PKT_PUBLIC_SUBKEY
break;
}
return 0;
tty_printf(_("Enter an optional description; "
"end it with an empty line:\n") );
for(;;) {
char *answer = cpr_get("ask_revocation_reason.text", "> " );
trim_trailing_ws( answer, strlen(answer) );
cpr_kill_prompt();
if( !*answer ) {
gcry_free(answer);
break;
}
{
char *p = make_printable_string( answer, strlen(answer), 0 );
gcry_free(answer);
answer = p;
}
if( !description )
description = gcry_xstrdup(answer);
else {
char *p = gcry_xmalloc( strlen(description) + strlen(answer) + 2 );
strcpy(stpcpy(stpcpy( p, description),"\n"),answer);
gcry_free(description);
description = p;
}
gcry_free(answer);
}
tty_printf(_("Reason for revocation: %s\n"), code_text );
if( !description )
tty_printf(_("(No description given)\n") );
else
tty_printf("%s\n", description );
} while( !cpr_get_answer_is_yes("ask_revocation_reason.okay",
_("Is this okay? ")) );
reason = gcry_xmalloc( sizeof *reason );
reason->code = code;
reason->desc = description;
return reason;
}
/****************
* Ask whether the signature should be revoked. If the user commits this,
* flag bit 0 is set.
*/
static void
ask_revoke_sig( KBNODE keyblock, KBNODE node, PKT_signature *sig ) ) {
void
release_revocation_reason_info( struct revocation_reason_info *reason )
{
KBNODE unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
if( !unode ) {
log_error("Oops: no user ID for signature\n");
return;
}
tty_printf(_("user ID: \""));
tty_print_utf8_string( unode->pkt->pkt.user_id->name,
unode->pkt->pkt.user_id->len, 0 );
tty_printf(_("\"\nsigned with your key %08lX at %s\n"),
sig->keyid[1], datestr_from_sig(sig) );
if( cpr_get_answer_is_yes("ask_revoke_sig.one",
_("Create a revocation certificate for this signature? (y/N)")) ) {
node->flag |= 1;
if( reason ) {
gcry_free( reason->desc );
gcry_free( reason );
}
}
/****************
* Generate a signature revocation certificate for UNAME
*/
int
gen_sig_revoke( const char *uname )
{
int rc = 0;
armor_filter_context_t afx;
compress_filter_context_t zfx;
PACKET pkt;
IOBUF out = NULL;
KBNODE keyblock = NULL;
KBNODE node;
KBPOS kbpos;
int uidchg;
if( opt.batch ) {
log_error(_("sorry, can't do this in batch mode\n"));
return GPGERR_GENERAL;
}
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
init_packet( &pkt );
/* get the keyblock */
rc = find_keyblock_byname( &kbpos, uname );
if( rc ) {
log_error(_("public key for user `%s' not found\n"), uname );
goto leave;
}
/* read the keyblock */
rc = read_keyblock( &kbpos, &keyblock );
if( rc ) {
log_error(_("error reading the certificate: %s\n"), gpg_errstr(rc) );
goto leave;
}
/* get the keyid from the keyblock */
node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
if( !node ) {
log_error(_("Oops; public key lost!\n"));
rc = GPGERR_GENERAL;
goto leave;
}
if( (rc = open_outfile( NULL, 0, &out )) )
goto leave;
if( opt.armor ) {
afx.what = 1;
iobuf_push_filter( out, armor_filter, &afx );
}
/* Now walk over all signatures which we did with one of
* our secret keys. Hmmm: Should we check for duplicate signatures */
clear_kbnode_flags( flags );
for( node = keyblock; node; node = node->next ) {
PKT_signature *sig;
if( node->pkt->pkttype == PKT_SIGNATURE
&& ((sig = node->pkt->pkt.signature)->sig_class&~3) == 0x10
&& seckey_available( sig->keyid )
&& !already_revoked( keyblock, node, sig->keyid ) ) { ) {
ask_revoke_sig( keyblock, node, sig )
}
else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
break;
}
for( node = keyblock; node; node = node->next ) { {
if( (node->flag & 1) )
break;
}
if( !node ) {
log_info(_("nothing to revoke\n"));
iobuf_cancel(out);
out = NULL;
goto leave;
}
init_packet( &pkt );
pkt.pkttype = PKT_PUBLIC_KEY;
pkt.pkt.public_key = keyblock->pkt->pkt.public_key;
rc = build_packet( out, &pkt );
if( rc ) {
log_error(_("build_packet failed: %s\n"), gpg_errstr(rc) );
goto leave;
}
uidchg = 1;
for( node = keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID )
uidchg = 1;
if( !(node->flag & 1) )
continue;
if( uidchg ) {
/* create a user ID packet */
.......
uidchg = 0;
}
/* create it */
rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x30, 0, NULL, NULL);
if( rc ) {
log_error(_("make_keysig_packet failed: %s\n"), gpg_errstr(rc));
goto leave;
}
init_packet( &pkt );
pkt.pkttype = PKT_SIGNATURE;
pkt.pkt.signature = sig;
rc = build_packet( out, &pkt );
if( rc ) {
log_error(_("build_packet failed: %s\n"), gpg_errstr(rc) );
goto leave;
}
}
leave:
release_kbnode( keyblock );
if( !out )
;
else if( rc )
iobuf_cancel(out);
else
iobuf_close(out);
return rc;
}
#endif /* unused code */

View File

@ -1,5 +1,5 @@
/* ringedit.c - Function for key ring editing
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -51,9 +51,10 @@
#ifdef HAVE_LIBGDBM
#include <gdbm.h>
#endif
#include <gcrypt.h>
#include "util.h"
#include "packet.h"
#include <gcrypt.h>
#include "iobuf.h"
#include "keydb.h"
#include "host2net.h"
@ -63,10 +64,6 @@
#include "kbx.h"
#ifdef MKDIR_TAKES_ONE_ARG
# undef mkdir
# define mkdir(a,b) mkdir(a)
#endif
struct resource_table_struct {
@ -191,7 +188,6 @@ enum_keyblock_resources( int *sequence, int secret )
}
/****************
* Register a resource (which currently may only be a keyring file).
* The first keyring which is added by this function is
@ -312,24 +308,13 @@ add_keyblock_resource( const char *url, int force, int secret )
*last_slash_in_filename = 0;
if( access(filename, F_OK) ) {
if( strlen(filename) >= 7
&& !strcmp(filename+strlen(filename)-7, "/.gnupg") ) {
if( mkdir(filename, S_IRUSR|S_IWUSR|S_IXUSR) )
{
log_error( _("%s: can't create directory: %s\n"),
filename, strerror(errno));
rc = GPGERR_OPEN_FILE;
goto leave;
}
else if( !opt.quiet )
log_info( _("%s: directory created\n"), filename );
copy_options_file( filename );
}
else
{
rc = GPGERR_OPEN_FILE;
goto leave;
}
/* on the first time we try to create the default homedir and
* in this case the process will be terminated, so that on the
* next invocation it can read the options file in on startup
*/
try_make_homedir( filename );
rc = GPGERR_OPEN_FILE;
goto leave;
}
*last_slash_in_filename = '/';
@ -363,7 +348,6 @@ add_keyblock_resource( const char *url, int force, int secret )
#endif
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM:
resource_table[i].dbf = gdbm_open( filename, 0,
@ -457,6 +441,35 @@ get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos )
}
/****************
* Return the filename of the firstkeyblock resource which is intended
* for write access. This will either be the default resource or in
* case this is not writable one of the others. If no writable is found,
* the default filename in the homedirectory will be returned.
* Caller must free, will never return NULL.
*/
char *
get_writable_keyblock_file( int secret )
{
int i = secret? default_secret_resource : default_public_resource;
if( resource_table[i].used && !resource_table[i].secret == !secret ) {
if( !access( resource_table[i].fname, R_OK|W_OK ) ) {
return gcry_xstrdup( resource_table[i].fname );
}
}
for(i=0; i < MAX_RESOURCES; i++ ) {
if( resource_table[i].used && !resource_table[i].secret == !secret ) {
if( !access( resource_table[i].fname, R_OK|W_OK ) ) {
return gcry_xstrdup( resource_table[i].fname );
}
}
}
/* Assume the home dir is always writable */
return make_filename(opt.homedir, secret? "secring.gpg"
: "pubring.gpg", NULL );
}
/****************
* Search a keyblock which starts with the given packet and puts all

View File

@ -1,5 +1,5 @@
/* seckey-cert.c - secret key certificate packet handling
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -33,6 +33,7 @@
#include "i18n.h"
#include "status.h"
/****************
* Emulate our old PK interface here - sometime in the future we might
* change the internal design to directly fit to libgcrypt.
@ -82,9 +83,11 @@ pk_check_secret_key( int algo, MPI *skey )
return rc;
}
static int
do_check( PKT_secret_key *sk )
{
byte *buffer;
u16 csum=0;
int i, res;
unsigned nbytes;
@ -95,6 +98,10 @@ do_check( PKT_secret_key *sk )
GCRY_CIPHER_HD cipher_hd=NULL;
PKT_secret_key *save_sk;
if( sk->protect.s2k.mode == 1001 ) {
log_info(_("secret key parts are not available\n"));
return GPGERR_GENERAL;
}
if( sk->protect.algo == GCRY_CIPHER_NONE )
BUG();
if( openpgp_cipher_test_algo( sk->protect.algo ) ) {
@ -112,6 +119,7 @@ do_check( PKT_secret_key *sk )
}
dek = passphrase_to_dek( keyid, sk->pubkey_algo, sk->protect.algo,
&sk->protect.s2k, 0 );
/* Hmmm: Do we use sync mode here even for Twofish? */
if( !(cipher_hd = gcry_cipher_open( sk->protect.algo,
GCRY_CIPHER_MODE_CFB,
GCRY_CIPHER_SECURE
@ -198,7 +206,8 @@ do_check( PKT_secret_key *sk )
free_secret_key( save_sk );
return GPGERR_BAD_PASS;
}
/* the checksum may fail, so we also check the key itself */
/* the checksum may be correct in some cases,
* so we also check the key itself */
res = pk_check_secret_key( sk->pubkey_algo, sk->skey );
if( res ) {
copy_secret_key( sk, save_sk );
@ -300,8 +309,6 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
) {
BUG();
}
rc = gcry_cipher_setkey( cipher_hd, dek->key, dek->keylen );
if( rc == GCRYERR_WEAK_KEY ) {
log_info(_("WARNING: Weak key detected"
@ -316,18 +323,19 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
if( blocksize != 8 && blocksize != 16 )
log_fatal("unsupported blocksize %d\n", blocksize );
sk->protect.ivlen = blocksize;
assert( sk->protect.ivlen <= DIM(sk->protect.iv) );
}
assert( sk->protect.ivlen <= DIM(sk->protect.iv) );
gcry_randomize(sk->protect.iv, sk->protect.ivlen,
GCRY_STRONG_RANDOM);
GCRY_STRONG_RANDOM);
gcry_cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen );
#warning FIXME: replace set/get buffer
if( sk->version >= 4 ) {
#define NMPIS (GNUPG_MAX_NSKEY - GNUPG_MAX_NPKEY)
byte *bufarr[NMPIS];
unsigned narr[NMPIS];
unsigned nbits[NMPIS];
/* FIXME: There is a bug in this function for all algorithms
* where the secret MPIs are more than 1 */
byte *bufarr[GNUPG_MAX_NSKEY];
unsigned narr[GNUPG_MAX_NSKEY];
unsigned nbits[GNUPG_MAX_NSKEY];
int ndata=0;
byte *p, *data;
@ -342,13 +350,13 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
nbits[j] = gcry_mpi_get_nbits( sk->skey[i] );
ndata += narr[j] + 2;
}
for( ; j < NMPIS; j++ )
for( ; j < GNUPG_MAX_NSKEY; j++ )
bufarr[j] = NULL;
ndata += 2; /* for checksum */
data = gcry_xmalloc_secure( ndata );
p = data;
for(j=0; j < NMPIS && bufarr[j]; j++ ) {
for(j=0; j < GNUPG_MAX_NSKEY && bufarr[j]; j++ ) {
p[0] = nbits[j] >> 8 ;
p[1] = nbits[j];
p += 2;
@ -356,7 +364,6 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
p += narr[j];
gcry_free(bufarr[j]);
}
#undef NMPIS
csum = checksum( data, ndata-2);
sk->csum = csum;
*p++ = csum >> 8;

View File

@ -1,5 +1,5 @@
/* seskey.c - make sesssion keys etc.
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -152,7 +152,7 @@ encode_session_key( DEK *dek, unsigned nbits )
static MPI
do_encode_md( GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
const byte *asn, size_t asnlen )
const byte *asn, size_t asnlen, int v3compathack )
{
int nframe = (nbits+7) / 8;
byte *frame;
@ -165,7 +165,7 @@ do_encode_md( GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
/* We encode the MD in this way:
*
* 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
* 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
*
* PAD consists of FF bytes.
*/
@ -173,7 +173,7 @@ do_encode_md( GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
: gcry_xmalloc( nframe );
n = 0;
frame[n++] = 0;
frame[n++] = algo;
frame[n++] = v3compathack? algo : 1; /* block type */
i = nframe - len - asnlen -3 ;
assert( i > 1 );
memset( frame+n, 0xff, i ); n += i;
@ -188,8 +188,15 @@ do_encode_md( GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
}
/****************
* Encode a message digest into an MPI.
* v3compathack is used to work around a bug in old GnuPG versions
* which did put the algo identifier inseatd of the block type 1 into
* the encoded value. setting this vare force the old behaviour.
*/
MPI
encode_md_value( int pubkey_algo, GCRY_MD_HD md, int hash_algo, unsigned nbits )
encode_md_value( int pubkey_algo, GCRY_MD_HD md, int hash_algo,
unsigned nbits, int v3compathack )
{
int algo = hash_algo? hash_algo : gcry_md_get_algo(md);
MPI frame;
@ -211,9 +218,10 @@ encode_md_value( int pubkey_algo, GCRY_MD_HD md, int hash_algo, unsigned nbits )
if( gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, asn, &asnlen ) )
BUG();
frame = do_encode_md( md, algo, gcry_md_get_algo_dlen( algo ),
nbits, asn, asnlen );
nbits, asn, asnlen, v3compathack );
gcry_free( asn );
}
return frame;
}

View File

@ -1,5 +1,5 @@
/* sig-check.c - Check a signature
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -31,6 +31,7 @@
#include "main.h"
#include "status.h"
#include "i18n.h"
#include "options.h"
struct cmp_help_context_s {
PKT_signature *sig;
@ -39,9 +40,10 @@ struct cmp_help_context_s {
static int do_signature_check( PKT_signature *sig, GCRY_MD_HD digest,
u32 *r_expire );
u32 *r_expiredate, int *r_expired );
static int do_check( PKT_public_key *pk, PKT_signature *sig,
GCRY_MD_HD digest );
GCRY_MD_HD digest, int *r_expired );
/****************
@ -131,11 +133,13 @@ int
signature_check( PKT_signature *sig, GCRY_MD_HD digest )
{
u32 dummy;
return do_signature_check( sig, digest, &dummy );
int dum2;
return do_signature_check( sig, digest, &dummy, &dum2 );
}
static int
do_signature_check( PKT_signature *sig, GCRY_MD_HD digest, u32 *r_expire )
do_signature_check( PKT_signature *sig, GCRY_MD_HD digest,
u32 *r_expiredate, int *r_expired )
{
PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
int rc=0;
@ -143,12 +147,12 @@ do_signature_check( PKT_signature *sig, GCRY_MD_HD digest, u32 *r_expire )
if( is_RSA(sig->pubkey_algo) )
write_status(STATUS_RSA_OR_IDEA);
*r_expire = 0;
*r_expiredate = 0;
if( get_pubkey( pk, sig->keyid ) )
rc = GPGERR_NO_PUBKEY;
else {
*r_expire = pk->expiredate;
rc = do_check( pk, sig, digest );
*r_expiredate = pk->expiredate;
rc = do_check( pk, sig, digest, r_expired );
}
free_public_key( pk );
@ -199,97 +203,6 @@ do_signature_check( PKT_signature *sig, GCRY_MD_HD digest, u32 *r_expire )
}
#if 0 /* not anymore used */
/****************
* Check the MDC which is contained in SIG.
* The GCRY_MD_HD should be currently open, so that this function
* is able to append some data, before finalizing the digest.
*/
int
mdc_kludge_check( PKT_signature *sig, GCRY_MD_HD digest )
{
int rc=0;
if( (rc=check_digest_algo(sig->digest_algo)) )
return rc;
/* make sure the digest algo is enabled (in case of a detached mdc??) */
md_enable( digest, sig->digest_algo );
/* complete the digest */
if( sig->version >= 4 )
gcry_md_putc( digest, sig->version );
gcry_md_putc( digest, sig->sig_class );
if( sig->version < 4 ) {
u32 a = sig->timestamp;
gcry_md_putc( digest, (a >> 24) & 0xff );
gcry_md_putc( digest, (a >> 16) & 0xff );
gcry_md_putc( digest, (a >> 8) & 0xff );
gcry_md_putc( digest, a & 0xff );
}
else {
byte buf[6];
size_t n;
gcry_md_putc( digest, sig->pubkey_algo );
gcry_md_putc( digest, sig->digest_algo );
if( sig->hashed_data ) {
n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
gcry_md_write( digest, sig->hashed_data, n+2 );
n += 6;
}
else
n = 6;
/* add some magic */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24;
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
gcry_md_write( digest, buf, 6 );
}
md_final( digest );
rc = GPGERR_BAD_SIGN;
{ const byte *s1 = md_read( digest, sig->digest_algo );
int s1len = md_digest_length( sig->digest_algo );
log_hexdump( "MDC calculated", s1, s1len );
if( !sig->data[0] )
log_debug("sig_data[0] is NULL\n");
else {
unsigned s2len;
char *s2;
if( gcry_mpi_print( GCRYMPI_FMT_USG, &s2, &s2len, sig->data[0] ))
BUG();
log_hexdump( "MDC stored ", s2, s2len );
if( s2len != s1len )
log_debug("MDC check: len differ: %d/%d\n", s1len, s2len);
else if( memcmp( s1, s2, s1len ) )
log_debug("MDC check: hashs differ\n");
else
rc = 0;
gcry_free(s2);
}
}
if( !rc && sig->flags.unknown_critical ) {
log_info(_("assuming bad MDC due to an unknown critical bit\n"));
rc = GPGERR_BAD_SIGN;
}
sig->flags.checked = 1;
sig->flags.valid = !rc;
/* FIXME: check that we are actually in an encrypted packet */
return rc;
}
#endif
/****************
* This function gets called by pubkey_verify() if the algorithm needs it.
*/
@ -366,16 +279,18 @@ cmp_help( void *opaque, MPI result )
static int
do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest )
do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest,
int *r_expired )
{
MPI result = NULL;
int rc=0;
struct cmp_help_context_s ctx;
u32 cur_time;
*r_expired = 0;
if( pk->version == 4 && pk->pubkey_algo == GCRY_PK_ELG_E ) {
log_info(_("this is a PGP generated "
"ElGamal key which is NOT secure for signatures!\n"));
"ElGamal key which is NOT secure for signatures!\n"));
return GPGERR_PUBKEY_ALGO;
}
@ -385,7 +300,8 @@ do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest )
? _("public key is %lu second newer than the signature\n")
: _("public key is %lu seconds newer than the signature\n"),
d );
return GPGERR_TIME_CONFLICT; /* pubkey newer than signature */
if( !opt.ignore_time_conflict )
return GPGERR_TIME_CONFLICT; /* pubkey newer than signature */
}
cur_time = make_timestamp();
@ -395,13 +311,15 @@ do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest )
"in future (time warp or clock problem)\n")
: _("key has been created %lu seconds "
"in future (time warp or clock problem)\n"), d );
return GPGERR_TIME_CONFLICT;
if( !opt.ignore_time_conflict )
return GPGERR_TIME_CONFLICT;
}
if( pk->expiredate && pk->expiredate < cur_time ) {
log_info(_("NOTE: signature key expired %s\n"),
asctimestamp( pk->expiredate ) );
write_status(STATUS_SIGEXPIRED);
*r_expired = 1;
}
@ -448,13 +366,24 @@ do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest )
gcry_md_final( digest );
result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo,
gcry_mpi_get_nbits(pk->pkey[0]));
gcry_mpi_get_nbits(pk->pkey[0]), 0);
ctx.sig = sig;
ctx.md = digest;
rc = pk_verify( pk->pubkey_algo, result, sig->data, pk->pkey,
cmp_help, &ctx );
mpi_release( result );
if( (opt.emulate_bugs & EMUBUG_MDENCODE)
&& rc == GPGERR_BAD_SIGN && is_ELGAMAL(pk->pubkey_algo) ) {
/* In this case we try again because old GnuPG versions didn't encode
* the hash right. There is no problem with DSA however */
result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo,
gcry_mpi_get_nbits(pk->pkey[0]), (sig->version < 5) );
ctx.sig = sig;
ctx.md = digest;
rc = pk_verify( pk->pubkey_algo, result, sig->data, pk->pkey,
cmp_help, &ctx );
}
if( !rc && sig->flags.unknown_critical ) {
log_info(_("assuming bad signature due to an unknown critical bit\n"));
rc = GPGERR_BAD_SIGN;
@ -472,16 +401,30 @@ hash_uid_node( KBNODE unode, GCRY_MD_HD md, PKT_signature *sig )
PKT_user_id *uid = unode->pkt->pkt.user_id;
assert( unode->pkt->pkttype == PKT_USER_ID );
if( sig->version >=4 ) {
byte buf[5];
buf[0] = 0xb4; /* indicates a userid packet */
buf[1] = uid->len >> 24; /* always use 4 length bytes */
buf[2] = uid->len >> 16;
buf[3] = uid->len >> 8;
buf[4] = uid->len;
gcry_md_write( md, buf, 5 );
if( uid->photo ) {
if( sig->version >=4 ) {
byte buf[5];
buf[0] = 0xd1; /* packet of type 17 */
buf[1] = uid->photolen >> 24; /* always use 4 length bytes */
buf[2] = uid->photolen >> 16;
buf[3] = uid->photolen >> 8;
buf[4] = uid->photolen;
gcry_md_write( md, buf, 5 );
}
gcry_md_write( md, uid->photo, uid->photolen );
}
else {
if( sig->version >=4 ) {
byte buf[5];
buf[0] = 0xb4; /* indicates a userid packet */
buf[1] = uid->len >> 24; /* always use 4 length bytes */
buf[2] = uid->len >> 16;
buf[3] = uid->len >> 8;
buf[4] = uid->len;
gcry_md_write( md, buf, 5 );
}
gcry_md_write( md, uid->name, uid->len );
}
gcry_md_write( md, uid->name, uid->len );
}
/****************
@ -493,11 +436,13 @@ int
check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
{
u32 dummy;
return check_key_signature2(root, node, is_selfsig, &dummy );
int dum2;
return check_key_signature2(root, node, is_selfsig, &dummy, &dum2 );
}
int
check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, u32 *r_expire)
check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
u32 *r_expiredate, int *r_expired )
{
GCRY_MD_HD md;
PKT_public_key *pk;
@ -507,7 +452,8 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, u32 *r_expire)
if( is_selfsig )
*is_selfsig = 0;
*r_expire = 0;
*r_expiredate = 0;
*r_expired = 0;
assert( node->pkt->pkttype == PKT_SIGNATURE );
assert( root->pkt->pkttype == PKT_PUBLIC_KEY );
@ -528,7 +474,7 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, u32 *r_expire)
if( !(md = gcry_md_open( algo, 0 )) )
BUG();
hash_public_key( md, pk );
rc = do_check( pk, sig, md );
rc = do_check( pk, sig, md, r_expired );
gcry_md_close(md);
}
else if( sig->sig_class == 0x28 ) { /* subkey revocation */
@ -539,7 +485,7 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, u32 *r_expire)
BUG();
hash_public_key( md, pk );
hash_public_key( md, snode->pkt->pkt.public_key );
rc = do_check( pk, sig, md );
rc = do_check( pk, sig, md, r_expired );
gcry_md_close(md);
}
else {
@ -562,7 +508,7 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, u32 *r_expire)
BUG();
hash_public_key( md, pk );
hash_public_key( md, snode->pkt->pkt.public_key );
rc = do_check( pk, sig, md );
rc = do_check( pk, sig, md, r_expired );
gcry_md_close(md);
}
else {
@ -584,10 +530,11 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, u32 *r_expire)
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) {
if( is_selfsig )
*is_selfsig = 1;
rc = do_check( pk, sig, md );
rc = do_check( pk, sig, md, r_expired );
}
else {
rc = do_signature_check( sig, md, r_expiredate, r_expired );
}
else
rc = do_signature_check( sig, md, r_expire );
gcry_md_close(md);
}
else {

View File

@ -1,5 +1,5 @@
/* sign.c - sign data
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -36,9 +36,16 @@
#include "filter.h"
#include "ttyio.h"
#include "trustdb.h"
#include "status.h"
#include "i18n.h"
#ifdef HAVE_DOSISH_SYSTEM
#define LF "\r\n"
#else
#define LF "\n"
#endif
/****************
* Emulate our old PK interface here - sometime in the future we might
* change the internal design to directly fit to libgcrypt.
@ -163,7 +170,8 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
"in future (time warp or clock problem)\n")
: _("key has been created %lu seconds "
"in future (time warp or clock problem)\n"), d );
return GPGERR_TIME_CONFLICT;
if( !opt.ignore_time_conflict )
return GPGERR_TIME_CONFLICT;
}
@ -178,7 +186,7 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
sig->digest_start[0] = dp[0];
sig->digest_start[1] = dp[1];
frame = encode_md_value( sk->pubkey_algo, md,
digest_algo, gcry_mpi_get_nbits(sk->skey[0]));
digest_algo, gcry_mpi_get_nbits(sk->skey[0]), 0 );
rc = pk_sign( sk->pubkey_algo, sig->data, frame, sk->skey );
mpi_release(frame);
if( rc )
@ -240,6 +248,25 @@ only_old_style( SK_LIST sk_list )
}
static void
print_status_sig_created ( PKT_secret_key *sk, PKT_signature *sig, int what )
{
byte array[MAX_FINGERPRINT_LEN], *p;
char buf[100+MAX_FINGERPRINT_LEN*2];
size_t i, n;
sprintf(buf, "%c %d %d %02x %lu ",
what, sig->pubkey_algo, sig->digest_algo, sig->sig_class,
(ulong)sig->timestamp );
fingerprint_from_sk( sk, array, &n );
p = buf + strlen(buf);
for(i=0; i < n ; i++ )
sprintf(p+2*i, "%02X", array[i] );
write_status_text( STATUS_SIG_CREATED, buf );
}
/****************
* Sign the files whose names are in FILENAME.
@ -521,6 +548,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
sig->sig_class = opt.textmode && !outfile? 0x01 : 0x00;
md = gcry_md_copy( mfx.md );
if( !md )
BUG();
if( sig->version >= 4 ) {
build_sig_subpkt_from_sig( sig );
@ -573,12 +602,16 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
pkt.pkttype = PKT_SIGNATURE;
pkt.pkt.signature = sig;
rc = build_packet( out, &pkt );
if( !rc && is_status_enabled() ) {
print_status_sig_created ( sk, sig, detached ? 'D':'S');
}
free_packet( &pkt );
if( rc )
log_error("build signature packet failed: %s\n", gpg_errstr(rc) );
}
if( rc )
goto leave;
}
@ -640,7 +673,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
else if( (rc = open_outfile( fname, 1, &out )) )
goto leave;
iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----\n" );
iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----" LF );
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
PKT_secret_key *sk = sk_rover->sk;
@ -683,13 +716,15 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
}
if( !(textmd = gcry_md_open(0, 0)) )
textmd = gcry_md_open(0, 0);
if( !textmd )
BUG();
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
PKT_secret_key *sk = sk_rover->sk;
gcry_md_enable(textmd, hash_for(sk->pubkey_algo));
}
/*md_start_debug( textmd, "sign" );*/
if ( DBG_HASHING )
gcry_md_start_debug( textmd, "clearsign" );
copy_clearsig_text( out, inp, textmd,
!opt.not_dash_escaped, opt.escape_from, old_style );
/* fixme: check for read errors */
@ -717,6 +752,8 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
sig->sig_class = 0x01;
md = gcry_md_copy( textmd );
if( !md )
BUG();
if( sig->version >= 4 ) {
build_sig_subpkt_from_sig( sig );
gcry_md_putc( md, sig->version );
@ -768,6 +805,9 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
pkt.pkttype = PKT_SIGNATURE;
pkt.pkt.signature = sig;
rc = build_packet( out, &pkt );
if( !rc && is_status_enabled() ) {
print_status_sig_created ( sk, sig, 'C');
}
free_packet( &pkt );
if( rc )
log_error("build signature packet failed: %s\n", gpg_errstr(rc) );

View File

@ -1,5 +1,5 @@
/* signal.c - signal handling
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -27,9 +27,9 @@
#include <errno.h>
#include <assert.h>
#include <gcrypt.h>
#include "options.h"
#include "errors.h"
#include <gcrypt.h>
#include "util.h"
#include "main.h"
#include "ttyio.h"
@ -59,14 +59,23 @@ got_fatal_signal( int sig )
caught_fatal_sig = 1;
gcry_control( GCRYCTL_TERM_SECMEM );
#ifdef IS_DEVELOPMENT_VERSION
/* better don't transtale these messages */
write(2, "\n", 1 );
s = log_get_name(); if( s ) write(2, s, strlen(s) );
write(2, ": ", 2 );
s = get_signal_name(sig); write(2, s, strlen(s) );
write(2, " caught ... exiting\n", 21 );
#ifndef HAVE_DOSISH_SYSTEM
{ /* reset action to default action and raise signal again */
struct sigaction nact;
nact.sa_handler = SIG_DFL;
sigemptyset( &nact.sa_mask );
nact.sa_flags = 0;
sigaction( sig, &nact, NULL);
}
#endif
exit(8); /* Hmmm, for some reasons rais2e does not work */
raise( sig );
}

View File

@ -1,5 +1,5 @@
/* skclist.c
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -66,7 +66,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
}
else if( !(rc=openpgp_pk_test_algo(sk->pubkey_algo, use)) ) {
SK_LIST r;
if( sk->version == 4 && (use & GCRY_PK_USAGE_SIGN)
if( sk->version == 4 && (use & GCRY_PK_USAGE_SIGN )
&& sk->pubkey_algo == GCRY_PK_ELG_E ) {
log_info("this is a PGP generated "
"ElGamal key which is NOT secure for signatures!\n");

View File

@ -1,5 +1,5 @@
/* status.c
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -38,12 +38,13 @@
#include <sys/mman.h>
#endif
#endif
#include <gcrypt.h>
#include "util.h"
#include "status.h"
#include "ttyio.h"
#include "options.h"
#include "main.h"
#include <gcrypt.h>
#include "i18n.h"
static int fd = -1;
@ -54,10 +55,32 @@ static int fd = -1;
static int shm_is_locked;
#endif /*USE_SHM_COPROCESSING*/
static void
progress_cb ( void *ctx, int c )
{
char buf[50];
if ( c == '\n' )
sprintf ( buf, "%.20s X 100 100", (char*)ctx );
else
sprintf ( buf, "%.20s %c 0 0", (char*)ctx, c );
write_status_text ( STATUS_PROGRESS, buf );
}
void
set_status_fd ( int newfd )
{
fd = newfd;
if ( fd != -1 ) {
#if 0
#warning fixme - progress functions
register_primegen_progress ( progress_cb, "primegen" );
register_pk_dsa_progress ( progress_cb, "pk_dsa" );
register_pk_elg_progress ( progress_cb, "pk_elg" );
#endif
}
}
int
@ -96,6 +119,10 @@ write_status_text ( int no, const char *text)
case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL\n"; break;
case STATUS_TRUST_FULLY : s = "TRUST_FULLY\n"; break;
case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE\n"; break;
case STATUS_GET_BOOL : s = "GET_BOOL\n"; break;
case STATUS_GET_LINE : s = "GET_LINE\n"; break;
case STATUS_GET_HIDDEN : s = "GET_HIDDEN\n"; break;
case STATUS_GOT_IT : s = "GOT_IT\n"; break;
case STATUS_SHM_INFO : s = "SHM_INFO\n"; break;
case STATUS_SHM_GET : s = "SHM_GET\n"; break;
case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL\n"; break;
@ -118,6 +145,16 @@ write_status_text ( int no, const char *text)
case STATUS_ERRMDC : s = "ERRMDC\n"; break;
case STATUS_IMPORTED : s = "IMPORTED\n"; break;
case STATUS_IMPORT_RES : s = "IMPORT_RES\n"; break;
case STATUS_FILE_START : s = "FILE_START\n"; break;
case STATUS_FILE_DONE : s = "FILE_DONE\n"; break;
case STATUS_FILE_ERROR : s = "FILE_ERROR\n"; break;
case STATUS_BEGIN_DECRYPTION:s = "BEGIN_DECRYPTION\n"; break;
case STATUS_END_DECRYPTION : s = "END_DECRYPTION\n"; break;
case STATUS_BEGIN_ENCRYPTION:s = "BEGIN_ENCRYPTION\n"; break;
case STATUS_END_ENCRYPTION : s = "END_ENCRYPTION\n"; break;
case STATUS_DELETE_PROBLEM : s = "DELETE_PROBLEM\n"; break;
case STATUS_PROGRESS : s = "PROGRESS\n"; break;
case STATUS_SIG_CREATED : s = "SIG_CREATED\n"; break;
default: s = "?\n"; break;
}
@ -164,6 +201,10 @@ init_shm_coprocessing ( ulong requested_shm_size, int lock_mem )
if ( shm_id == -1 )
log_fatal("can't get %uk of shared memory: %s\n",
(unsigned)shm_size/1024, strerror(errno));
#if !defined(IPC_HAVE_SHM_LOCK) \
&& defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
/* part of the old code which uses mlock */
shm_area = shmat( shm_id, 0, 0 );
if ( shm_area == (char*)-1 )
log_fatal("can't attach %uk shared memory: %s\n",
@ -174,29 +215,17 @@ init_shm_coprocessing ( ulong requested_shm_size, int lock_mem )
#ifdef USE_CAPABILITIES
cap_set_proc( cap_from_text("cap_ipc_lock+ep") );
#endif
#ifdef IPC_HAVE_SHM_LOCK
if ( shmctl (shm_id, SHM_LOCK, 0) )
log_info("locking shared memory %d failed: %s\n",
shm_id, strerror(errno));
else
shm_is_locked = 1;
#elif defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
/* (need the cast for Solaris with Sun's workshop compilers) */
if ( mlock ( (char*)shm_area, shm_size) )
log_info("locking shared memory %d failed: %s\n",
shm_id, strerror(errno));
else
shm_is_locked = 1;
#else
log_info("Locking shared memory %d failed: No way to do it\n", shm_id );
#endif
#ifdef USE_CAPABILITIES
cap_set_proc( cap_from_text("cap_ipc_lock+p") );
#endif
}
#ifdef IPC_RMID_DEFERRED_RELEASE
if( shmctl( shm_id, IPC_RMID, 0) )
log_fatal("shmctl IPC_RMDID of %d failed: %s\n",
@ -213,13 +242,59 @@ init_shm_coprocessing ( ulong requested_shm_size, int lock_mem )
shm_id, strerror(errno));
}
#else /* this is the new code which handles the changes in the SHM semantics
* introduced with Linux 2.4. The changes is that we now change the
* permissions and then attach to the memory.
*/
if( lock_mem ) {
#ifdef USE_CAPABILITIES
cap_set_proc( cap_from_text("cap_ipc_lock+ep") );
#endif
#ifdef IPC_HAVE_SHM_LOCK
if ( shmctl (shm_id, SHM_LOCK, 0) )
log_info("locking shared memory %d failed: %s\n",
shm_id, strerror(errno));
else
shm_is_locked = 1;
#else
log_info("Locking shared memory %d failed: No way to do it\n", shm_id );
#endif
#ifdef USE_CAPABILITIES
cap_set_proc( cap_from_text("cap_ipc_lock+p") );
#endif
}
if( shmctl( shm_id, IPC_STAT, &shmds ) )
log_fatal("shmctl IPC_STAT of %d failed: %s\n",
shm_id, strerror(errno));
if( shmds.shm_perm.uid != getuid() ) {
shmds.shm_perm.uid = getuid();
if( shmctl( shm_id, IPC_SET, &shmds ) )
log_fatal("shmctl IPC_SET of %d failed: %s\n",
shm_id, strerror(errno));
}
shm_area = shmat( shm_id, 0, 0 );
if ( shm_area == (char*)-1 )
log_fatal("can't attach %uk shared memory: %s\n",
(unsigned)shm_size/1024, strerror(errno));
log_debug("mapped %uk shared memory at %p, id=%d\n",
(unsigned)shm_size/1024, shm_area, shm_id );
#ifdef IPC_RMID_DEFERRED_RELEASE
if( shmctl( shm_id, IPC_RMID, 0) )
log_fatal("shmctl IPC_RMDID of %d failed: %s\n",
shm_id, strerror(errno));
#endif
#endif
/* write info; Protocol version, id, size, locked size */
sprintf( buf, "pv=1 pid=%d shmid=%d sz=%u lz=%u", (int)getpid(),
shm_id, (unsigned)shm_size, shm_is_locked? (unsigned)shm_size:0 );
write_status_text( STATUS_SHM_INFO, buf );
}
/****************
* Request a string from client
* If bool, returns static string on true (do not free) or NULL for false
@ -269,10 +344,50 @@ do_shm_get( const char *keyword, int hidden, int bool )
#endif /* USE_SHM_COPROCESSING */
/****************
* Request a string from the client over the command-fd
* If bool, returns static string on true (do not free) or NULL for false
*/
static char *
do_get_from_fd( const char *keyword, int hidden, int bool )
{
int i, len;
char *string;
write_status_text( bool? STATUS_GET_BOOL :
hidden? STATUS_GET_HIDDEN : STATUS_GET_LINE, keyword );
for( string = NULL, i = len = 200; ; i++ ) {
if( i >= len-1 ) {
char *save = string;
len += 100;
string = hidden? gcry_xmalloc_secure ( len ) : gcry_malloc ( len );
if( save )
memcpy(string, save, i );
else
i=0;
}
/* Hmmm: why not use our read_line function here */
if( read( fd, string+i, 1) != 1 || string[i] == '\n' )
break;
}
string[i] = 0;
write_status( STATUS_GOT_IT );
if( bool ) /* Fixme: is this correct??? */
return string[0] == 'Y' ? "" : NULL;
return string;
}
int
cpr_enabled()
{
if( opt.command_fd != -1 )
return 1;
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return 1;
@ -285,6 +400,8 @@ cpr_get( const char *keyword, const char *prompt )
{
char *p;
if( opt.command_fd != -1 )
return do_get_from_fd ( keyword, 0, 0 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return do_shm_get( keyword, 0, 0 );
@ -318,6 +435,8 @@ cpr_get_hidden( const char *keyword, const char *prompt )
{
char *p;
if( opt.command_fd != -1 )
return do_get_from_fd ( keyword, 1, 0 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return do_shm_get( keyword, 1, 0 );
@ -336,6 +455,8 @@ cpr_get_hidden( const char *keyword, const char *prompt )
void
cpr_kill_prompt(void)
{
if( opt.command_fd != -1 )
return;
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return;
@ -350,6 +471,8 @@ cpr_get_answer_is_yes( const char *keyword, const char *prompt )
int yes;
char *p;
if( opt.command_fd != -1 )
return !!do_get_from_fd ( keyword, 0, 1 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return !!do_shm_get( keyword, 0, 1 );
@ -376,6 +499,8 @@ cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt )
int yes;
char *p;
if( opt.command_fd != -1 )
return !!do_get_from_fd ( keyword, 0, 1 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return !!do_shm_get( keyword, 0, 1 );

View File

@ -1,5 +1,5 @@
/* status.h
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -65,7 +65,22 @@
#define STATUS_ERRMDC 35
#define STATUS_IMPORTED 36
#define STATUS_IMPORT_RES 37
#define STATUS_FILE_START 38
#define STATUS_FILE_DONE 39
#define STATUS_FILE_ERROR 40
#define STATUS_BEGIN_DECRYPTION 41
#define STATUS_END_DECRYPTION 42
#define STATUS_BEGIN_ENCRYPTION 43
#define STATUS_END_ENCRYPTION 44
#define STATUS_DELETE_PROBLEM 45
#define STATUS_GET_BOOL 46
#define STATUS_GET_LINE 47
#define STATUS_GET_HIDDEN 48
#define STATUS_GOT_IT 49
#define STATUS_PROGRESS 50
#define STATUS_SIG_CREATED 51
/*-- status.c --*/
void set_status_fd ( int fd );

View File

@ -1,5 +1,5 @@
/* tdbdump.c
* Copyright (C) 1999 Free Software Foundation, Inc.
* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -520,5 +520,6 @@ import_ownertrust( const char *fname )
if( !is_stdin )
fclose(fp);
do_sync();
sync_trustdb();
}

View File

@ -1,5 +1,5 @@
/* tdbio.c
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -40,11 +40,6 @@
#include "tdbio.h"
#ifdef MKDIR_TAKES_ONE_ARG
# undef mkdir
# define mkdir(a,b) mkdir(a)
#endif
/****************
* Yes, this is a very simple implementation. We should really
* use a page aligned buffer and read complete pages.
@ -439,17 +434,8 @@ tdbio_set_dbname( const char *new_dbname, int create )
assert(p);
*p = 0;
if( access( fname, F_OK ) ) {
if( strlen(fname) >= 7
&& !strcmp(fname+strlen(fname)-7, "/.gnupg" ) ) {
if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
log_fatal( _("%s: can't create directory: %s\n"),
fname, strerror(errno) );
else if( !opt.quiet )
log_info( _("%s: directory created\n"), fname );
copy_options_file( fname );
}
else
log_fatal( _("%s: directory does not exist!\n"), fname );
try_make_homedir( fname );
log_fatal( _("%s: directory does not exist!\n"), fname );
}
*p = '/';
@ -1130,6 +1116,8 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
fputs(", expired", fp );
if( rec->r.dir.dirflags & DIRF_REVOKED )
fputs(", revoked", fp );
if( rec->r.dir.dirflags & DIRF_NEWKEYS )
fputs(", newkeys", fp );
}
putc('\n', fp);
break;

View File

@ -1,5 +1,5 @@
/* tdbio.h - Trust database I/O functions
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -52,6 +52,7 @@
/* one uid with a selfsignature or an revocation */
#define DIRF_EXPIRED 4 /* the complete key has expired */
#define DIRF_REVOKED 8 /* the complete key has been revoked */
#define DIRF_NEWKEYS 128 /* new keys are available: we can check the sigs */
#define KEYF_CHECKED 1 /* This key has been checked */
#define KEYF_VALID 2 /* This is a valid (sub)key */
@ -121,7 +122,7 @@ struct trust_record {
} uid;
struct { /* preference record */
ulong lid; /* point back to the directory record */
/* or 0 for a glocal pref record */
/* or 0 for a global pref record */
ulong next; /* points to next pref record */
byte data[ITEMS_PER_PREF_RECORD];
} pref;

View File

@ -1,5 +1,5 @@
/* textfilter.c
* Copyright (C) 1998,1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -31,7 +31,13 @@
#include "util.h"
#include "filter.h"
#include "i18n.h"
#include "options.h"
#ifdef HAVE_DOSISH_SYSTEM
#define LF "\r\n"
#else
#define LF "\n"
#endif
#define MAX_LINELEN 19995 /* a little bit smaller than in armor.c */
/* to make sure that a warning is displayed while */
@ -151,6 +157,9 @@ copy_clearsig_text( IOBUF out, IOBUF inp, GCRY_MD_HD md,
int truncated = 0;
int pending_lf = 0;
if( !opt.pgp2_workarounds )
pgp2mode = 0;
if( !escape_dash )
escape_from = 0;
@ -183,12 +192,37 @@ copy_clearsig_text( IOBUF out, IOBUF inp, GCRY_MD_HD md,
iobuf_put( out, '-' );
iobuf_put( out, ' ' );
}
#if 0 /*defined(HAVE_DOSISH_SYSTEM)*/
/* We don't use this anymore because my interpretation of rfc2440 7.1
* is that there is no conversion needed. If one decides to
* clearsign a unix file on a DOS box he will get a mixed line endings.
* If at some point it turns out, that a conversion is a nice feature
* we can make an option out of it.
*/
/* make sure the lines do end in CR,LF */
if( n > 1 && ( (buffer[n-2] == '\r' && buffer[n-1] == '\n' )
|| (buffer[n-2] == '\n' && buffer[n-1] == '\r'))) {
iobuf_write( out, buffer, n-2 );
iobuf_put( out, '\r');
iobuf_put( out, '\n');
}
else if( n && buffer[n-1] == '\n' ) {
iobuf_write( out, buffer, n-1 );
iobuf_put( out, '\r');
iobuf_put( out, '\n');
}
else
iobuf_write( out, buffer, n );
#else
iobuf_write( out, buffer, n );
#endif
}
/* at eof */
if( !pending_lf ) { /* make sure that the file ends with a LF */
iobuf_put( out, '\n');
iobuf_writestr( out, LF );
if( !escape_dash )
gcry_md_putc( md, '\n' );
}

View File

@ -1,5 +1,5 @@
/* trustdb.c
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -110,7 +110,6 @@ static int alloced_tns;
static int max_alloced_tns;
static LOCAL_ID_TABLE new_lid_table(void);
static int ins_lid_table_item( LOCAL_ID_TABLE tbl, ulong lid, unsigned flag );
static int qry_lid_table_flag( LOCAL_ID_TABLE tbl, ulong lid, unsigned *flag );
@ -125,13 +124,22 @@ static int do_check( TRUSTREC *drec, unsigned *trustlevel,
unsigned *retflgs);
static int get_dir_record( PKT_public_key *pk, TRUSTREC *rec );
static int do_update_trust_record( KBNODE keyblock, TRUSTREC *drec,
int recheck, int *modified );
static int check_trust_record( TRUSTREC *drec );
int sigs_only, int *modified );
static int check_trust_record( TRUSTREC *drec, int sigs_only );
static void mark_fresh_keys(void);
/* a table used to keep track of ultimately trusted keys
* which are the ones from our secrings and the trusted keys */
static LOCAL_ID_TABLE ultikey_table;
/* a table to keep track of newly importted keys. This one is
* create by the insert_trust_record function and from time to time
* used to verify key signature which have been done with these new keys */
static LOCAL_ID_TABLE fresh_imported_keys;
static int fresh_imported_keys_count;
#define FRESH_KEY_CHECK_THRESHOLD 200
/* list of unused lid items and tables */
static LOCAL_ID_TABLE unused_lid_tables;
static struct local_id_item *unused_lid_items;
@ -245,6 +253,27 @@ release_lid_table( LOCAL_ID_TABLE tbl )
}
#endif
/****************
* Remove all items from a LID table
*/
static void
clear_lid_table( LOCAL_ID_TABLE tbl )
{
struct local_id_item *a, *a2;
int i;
for(i=0; i < 16; i++ ) {
for(a=tbl->items[i]; a; a = a2 ) {
a2 = a->next;
a->next = unused_lid_items;
unused_lid_items = a;
}
tbl->items[i] = NULL;
}
}
/****************
* Add a new item to the table or return 1 if we already have this item
*/
@ -454,7 +483,7 @@ verify_own_keys(void)
if( DBG_TRUST )
log_debug("key %08lX: checking secret key\n", (ulong)keyid[1] );
if( is_secret_key_protected( sk ) < 1 )
if( !opt.quiet && is_secret_key_protected( sk ) < 1 )
log_info(_("NOTE: secret key %08lX is NOT protected.\n"),
(ulong)keyid[1] );
@ -572,6 +601,18 @@ init_trustdb()
/****************
* This function should be called in certain cases to sync the internal state
* of the trustdb with the file image. Currently it is needed after
* a sequence of insert_trust_record() calls.
*/
void
sync_trustdb()
{
if( fresh_imported_keys && fresh_imported_keys_count )
mark_fresh_keys();
}
/***********************************************
@ -652,7 +693,7 @@ print_path( int pathlen, TN ME .........., FILE *fp, ulong highlight )
p = get_user_id( keyid, &n );
putc(' ', fp);
putc('\"', fp);
print_utf8_string( fp, p, n > 40? 40:n, 0 );
print_utf8_string( fp, p, n > 40? 40:n );
putc('\"', fp);
gcry_free(p);
putc('\n', fp );
@ -683,8 +724,14 @@ print_uid_from_keyblock( FILE *fp, KBNODE keyblock, ulong urecno )
if( node->pkt->pkttype == PKT_USER_ID ) {
PKT_user_id *uidpkt = node->pkt->pkt.user_id;
gcry_md_hash_buffer( GCRY_MD_RMD160, uhash,
uidpkt->name, uidpkt->len );
if( uidpkt->photo ) {
gcry_md_hash_buffer( GCRY_MD_RMD160, uhash,
uidpkt->photo, uidpkt->photolen );
}
else {
gcry_md_hash_buffer( GCRY_MD_RMD160, uhash,
uidpkt->name, uidpkt->len );
}
if( !memcmp( uhash, urec.r.uid.namehash, 20 ) ) {
print_string( fp, uidpkt->name, uidpkt->len, ':' );
return;
@ -1001,7 +1048,7 @@ check_uidsigs( KBNODE keyblock, KBNODE keynode, u32 *mainkid, ulong lid,
(ulong)mainkid[1], lid );
assert(keynode->pkt->pkttype == PKT_USER_ID );
uid = keynode->pkt->pkt.user_id;
print_utf8_string( log_stream(), uid->name, uid->len );
print_string( log_stream(), uid->name, uid->len, '\"' );
fputs("\"\n", log_stream());
}
@ -1083,17 +1130,17 @@ check_uidsigs( KBNODE keyblock, KBNODE keynode, u32 *mainkid, ulong lid,
static unsigned int
check_sig_record( KBNODE keyblock, KBNODE signode,
ulong siglid, int sigidx, u32 *keyid, ulong lid,
u32 *r_expire )
u32 *r_expiretime, int *mod_down, int *mod_up )
{
PKT_signature *sig = signode->pkt->pkt.signature;
unsigned int sigflag = 0;
TRUSTREC tmp;
int revocation=0, rc;
int revocation=0, expired=0, rc;
if( DBG_TRUST )
log_debug("check_sig_record: %08lX.%lu %lu[%d]\n",
(ulong)keyid[1], lid, siglid, sigidx );
*r_expire = 0;
*r_expiretime = 0;
if( (sig->sig_class&~3) == 0x10 ) /* regular certification */
;
else if( sig->sig_class == 0x30 ) /* cert revocation */
@ -1104,7 +1151,8 @@ check_sig_record( KBNODE keyblock, KBNODE signode,
read_record( siglid, &tmp, 0 );
if( tmp.rectype == RECTYPE_DIR ) {
/* the public key is in the trustdb: check sig */
rc = check_key_signature2( keyblock, signode, NULL, r_expire );
rc = check_key_signature2( keyblock, signode, NULL,
r_expiretime, &expired );
if( !rc ) { /* valid signature */
if( opt.verbose )
log_info("sig %08lX.%lu/%lu[%d]/%08lX: %s\n",
@ -1113,18 +1161,25 @@ check_sig_record( KBNODE keyblock, KBNODE signode,
revocation? _("Valid certificate revocation")
: _("Good certificate") );
sigflag |= SIGF_CHECKED | SIGF_VALID;
if( expired ) {
sigflag |= SIGF_EXPIRED;
/* We have to reset the expiretime, so that this signature
* does not get checked over and over due to the reached
* expiretime */
*r_expiretime = 0;
}
if( revocation ) {
sigflag |= SIGF_REVOKED;
/**mod_down = 1;*/
*mod_down = 1;
}
else
/**mod_up = 1*/;
*mod_up = 1;
}
else if( rc == GPGERR_NO_PUBKEY ) {
/* This may happen if the key is still in the trustdb
* but not available in the keystorage */
sigflag |= SIGF_NOPUBKEY;
/**mod_down = 1;*/
*mod_down = 1;
if( revocation )
sigflag |= SIGF_REVOKED;
}
@ -1138,7 +1193,7 @@ check_sig_record( KBNODE keyblock, KBNODE signode,
sigflag |= SIGF_CHECKED;
if( revocation ) {
sigflag |= SIGF_REVOKED;
/**mod_down = 1;*/
*mod_down = 1;
}
}
}
@ -1169,14 +1224,15 @@ check_sig_record( KBNODE keyblock, KBNODE signode,
*/
static ulong
make_sig_records( KBNODE keyblock, KBNODE uidnode,
ulong lid, u32 *mainkid, u32 *min_expire )
ulong lid, u32 *mainkid, u32 *min_expire,
int *mod_down, int *mod_up )
{
TRUSTREC *srecs, **s_end, *s=NULL, *s2;
KBNODE node;
PKT_signature *sig;
ulong sigrecno, siglid;
int i, sigidx = 0;
u32 expire;
u32 expiretime;
srecs = NULL; s_end = &srecs;
for( node=uidnode->next; node; node = node->next ) {
@ -1191,6 +1247,12 @@ make_sig_records( KBNODE keyblock, KBNODE uidnode,
siglid = find_or_create_lid( sig );
/* smash dups */
/* FIXME: Here we have a problem:
* We can't distinguish between a certification and a certification
* revocation without looking at class of the signature - we have
* to see how we can store the sigclass in the sigrecord..
* Argg- I hope I can get rid of this ugly trustdb ASAP.
*/
for( s2 = s; s2 ; s2 = s2->next ) {
for(i=0; i < sigidx; i++ ) {
if( s2->r.sig.sig[i].lid == siglid )
@ -1219,7 +1281,8 @@ make_sig_records( KBNODE keyblock, KBNODE uidnode,
s->r.sig.sig[sigidx].lid = siglid;
s->r.sig.sig[sigidx].flag= check_sig_record( keyblock, node,
siglid, sigidx,
mainkid, lid, &expire );
mainkid, lid, &expiretime,
mod_down, mod_up );
sigidx++;
if( sigidx == SIGS_PER_RECORD ) {
@ -1229,8 +1292,8 @@ make_sig_records( KBNODE keyblock, KBNODE uidnode,
sigidx = 0;
}
/* keep track of signers pk expire time */
if( expire && (!*min_expire || *min_expire > expire ) )
*min_expire = expire;
if( expiretime && (!*min_expire || *min_expire > expiretime ) )
*min_expire = expiretime;
}
if( sigidx ) {
s->recnum = tdbio_new_recnum();
@ -1320,7 +1383,8 @@ make_pref_record( PKT_signature *sig, ulong lid )
static ulong
make_uid_records( KBNODE keyblock, ulong lid, u32 *keyid, u32 *min_expire )
make_uid_records( KBNODE keyblock, ulong lid, u32 *keyid, u32 *min_expire,
int *mod_down, int *mod_up )
{
TRUSTREC *urecs, **uend, *u, *u2;
KBNODE node;
@ -1335,7 +1399,14 @@ make_uid_records( KBNODE keyblock, ulong lid, u32 *keyid, u32 *min_expire )
if( node->pkt->pkttype != PKT_USER_ID )
continue;
uid = node->pkt->pkt.user_id;
gcry_md_hash_buffer( GCRY_MD_RMD160, uidhash, uid->name, uid->len );
if( uid->photo ) {
gcry_md_hash_buffer( GCRY_MD_RMD160, uidhash,
uid->photo, uid->photolen );
}
else {
gcry_md_hash_buffer( GCRY_MD_RMD160, uidhash,
uid->name, uid->len );
}
/* create the uid record */
u = gcry_xcalloc( 1, sizeof *u );
@ -1352,9 +1423,21 @@ make_uid_records( KBNODE keyblock, ulong lid, u32 *keyid, u32 *min_expire )
&& (u->r.uid.uidflags & UIDF_VALID) ) {
u->r.uid.prefrec = bestsig? make_pref_record( bestsig, lid ) : 0;
}
/* the next test is really bad because we should modify
* out modification timestamps only if we really have a change.
* But because we are deleting the uid records first it is somewhat
* difficult to track those changes. fixme */
if( !( u->r.uid.uidflags & UIDF_VALID )
|| ( u->r.uid.uidflags & UIDF_REVOKED ) )
*mod_down=1;
else
*mod_up=1;
/* create the list of signatures */
u->r.uid.siglist = make_sig_records( keyblock, node,
lid, keyid, min_expire );
lid, keyid, min_expire,
mod_down, mod_up );
}
uidrecno = urecs? urecs->recnum : 0;
@ -1381,6 +1464,8 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
TRUSTREC drec;
int rc;
/* NOTE: We don't need recheck anymore, but this might chnage again in
* the future */
if( opt.dry_run )
return 0;
if( modified )
@ -1391,26 +1476,27 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
if( rc )
return rc;
rc = do_update_trust_record( keyblock, &drec, recheck, modified );
rc = do_update_trust_record( keyblock, &drec, 0, modified );
return rc;
}
/****************
* Same as update_trust_record, but tghis functions expects the dir record.
* On exit the dirrecord will reflect any changes made.
* Same as update_trust_record, but this functions expects the dir record.
* On exit the dir record will reflect any changes made.
* With sigs_only set only foreign key signatures are checked.
*/
static int
do_update_trust_record( KBNODE keyblock, TRUSTREC *drec,
int recheck, int *modified )
int sigs_only, int *modified )
{
PKT_public_key *primary_pk;
TRUSTREC krec, urec, prec, helprec;
int i, rc = 0;
u32 keyid[2]; /* keyid of primary key */
/* int mod_up = 0;
int mod_down = 0; */
int mod_up = 0;
int mod_down = 0;
ulong recno, r2;
u32 expire;
u32 expiretime;
primary_pk = find_kbnode( keyblock, PKT_PUBLIC_KEY )->pkt->pkt.public_key;
if( !primary_pk->local_id )
@ -1425,7 +1511,7 @@ do_update_trust_record( KBNODE keyblock, TRUSTREC *drec,
if( rc )
return rc;
/* delete the old stuff */
/* delete the old stuff FIXME: implementend sigs_only */
for( recno=drec->r.dir.keylist; recno; recno = krec.r.key.next ) {
read_record( recno, &krec, RECTYPE_KEY );
delete_record( recno );
@ -1448,22 +1534,13 @@ do_update_trust_record( KBNODE keyblock, TRUSTREC *drec,
/* insert new stuff */
drec->r.dir.dirflags &= ~DIRF_REVOKED;
drec->r.dir.dirflags &= ~DIRF_NEWKEYS;
drec->r.dir.keylist = make_key_records( keyblock, drec->recnum, keyid, &i );
if( i ) /* primary key has been revoked */
drec->r.dir.dirflags &= DIRF_REVOKED;
expire = 0;
drec->r.dir.dirflags |= DIRF_REVOKED;
expiretime = 0;
drec->r.dir.uidlist = make_uid_records( keyblock, drec->recnum, keyid,
&expire );
#if 0
if( orig_uidflags != urec.r.uid.uidflags ) {
write_record( &urec );
if( !( urec.r.uid.uidflags & UIDF_VALID )
|| ( urec.r.uid.uidflags & UIDF_REVOKED ) )
*mod_down=1;
else
*mod_up=1; /*(maybe a new user id)*/
#endif
&expiretime, &mod_down, &mod_up );
if( rc )
rc = tdbio_cancel_transaction();
else {
@ -1471,9 +1548,9 @@ do_update_trust_record( KBNODE keyblock, TRUSTREC *drec,
*modified = 1;
drec->r.dir.dirflags |= DIRF_CHECKED;
drec->r.dir.valcheck = 0;
drec->r.dir.checkat = expire;
drec->r.dir.checkat = expiretime;
write_record( drec );
/*tdbio_write_modify_stamp( mod_up, mod_down );*/
tdbio_write_modify_stamp( mod_up, mod_down );
rc = tdbio_end_transaction();
}
return rc;
@ -1538,16 +1615,28 @@ insert_trust_record( KBNODE keyblock )
}
}
/* mark tdb as modified upwards */
tdbio_write_modify_stamp( 1, 0 );
/* and put all the other stuff into the keydb */
rc = do_update_trust_record( keyblock, &dirrec, 1, NULL );
rc = do_update_trust_record( keyblock, &dirrec, 0, NULL );
do_sync();
/* keep track of new keys */
if( !fresh_imported_keys )
fresh_imported_keys = new_lid_table();
ins_lid_table_item( fresh_imported_keys, pk->local_id, 0 );
if( ++fresh_imported_keys_count > FRESH_KEY_CHECK_THRESHOLD )
mark_fresh_keys();
return rc;
}
/****************
* Insert a trust record indentified by a PK into the TrustDB
*/
@ -1585,7 +1674,7 @@ insert_trust_record_by_pk( PKT_public_key *pk )
* Currently we only do an update_trust_record.
*/
static int
check_trust_record( TRUSTREC *drec )
check_trust_record( TRUSTREC *drec, int sigs_only )
{
KBNODE keyblock;
int modified, rc;
@ -1597,7 +1686,7 @@ check_trust_record( TRUSTREC *drec )
return rc;
}
rc = do_update_trust_record( keyblock, drec, 0, &modified );
rc = do_update_trust_record( keyblock, drec, sigs_only, &modified );
release_kbnode( keyblock );
return rc;
@ -1674,7 +1763,7 @@ update_trustdb()
/****************
* Do all required check in the trustdb. This function walks over all
* Do all required checks in the trustdb. This function walks over all
* records in the trustdb and does scheduled processing.
*/
void
@ -1682,7 +1771,7 @@ check_trustdb( const char *username )
{
TRUSTREC rec;
ulong recnum;
ulong count=0, upd_count=0, err_count=0, skip_count=0;
ulong count=0, upd_count=0, err_count=0, skip_count=0, sigonly_count=0;
ulong current_time = make_timestamp();
if( username )
@ -1691,15 +1780,25 @@ check_trustdb( const char *username )
init_trustdb();
for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
int sigs_only;
if( rec.rectype != RECTYPE_DIR )
continue; /* we only want the dir records */
if( count && !(count % 100) && !opt.quiet )
log_info(_("%lu keys so far processed\n"), count);
count++;
if( !rec.r.dir.checkat || rec.r.dir.checkat > current_time ) {
skip_count++;
continue; /* not scheduled for checking */
sigs_only = 0;
if( !(rec.r.dir.dirflags & DIRF_CHECKED) )
;
else if( !rec.r.dir.checkat || rec.r.dir.checkat > current_time ) {
if( !(rec.r.dir.dirflags & DIRF_NEWKEYS) ) {
skip_count++;
continue; /* not scheduled for checking */
}
sigs_only = 1; /* new public keys - check them */
sigonly_count++;
}
if( !rec.r.dir.keylist ) {
@ -1708,11 +1807,12 @@ check_trustdb( const char *username )
continue;
}
check_trust_record( &rec );
check_trust_record( &rec, sigs_only );
}
log_info(_("%lu keys processed\n"), count);
if( sigonly_count )
log_info(_("\t%lu due to new pubkeys\n"), sigonly_count);
if( skip_count )
log_info(_("\t%lu keys skipped\n"), skip_count);
if( err_count )
@ -1772,8 +1872,12 @@ build_cert_tree( ulong lid, int depth, int max_depth, TN helproot )
return NULL;
}
if( dirrec.r.dir.checkat && dirrec.r.dir.checkat <= make_timestamp() )
check_trust_record( &dirrec );
if( dirrec.r.dir.checkat && dirrec.r.dir.checkat <= make_timestamp() ) {
check_trust_record( &dirrec, 0 );
}
else if( (dirrec.r.dir.dirflags & DIRF_NEWKEYS) ) {
check_trust_record( &dirrec, 1 );
}
keynode->n.k.ownertrust = dirrec.r.dir.ownertrust & TRUST_MASK;
@ -1924,10 +2028,10 @@ propagate_validity( TN root, TN node, int (*add_fnc)(ulong), unsigned *retflgs )
}
/* loop over all user ids */
for( ur=node->list; ur && max_validity < TRUST_FULLY; ur = ur->next ) {
for( ur=node->list; ur && max_validity <= TRUST_FULLY; ur = ur->next ) {
assert( ur->is_uid );
/* loop over all signators */
for(kr=ur->list; kr && max_validity < TRUST_FULLY; kr = kr->next ) {
for(kr=ur->list; kr && max_validity <= TRUST_FULLY; kr = kr->next ) {
if( propagate_validity( root, kr, add_fnc, retflgs ) )
return -1; /* quit */
if( kr->n.k.validity == TRUST_ULTIMATE ) {
@ -2001,8 +2105,12 @@ verify_key( int max_depth, TRUSTREC *drec, const char *namehash,
if( !tree )
return TRUST_UNDEFINED;
pv_result = propagate_validity( tree, tree, add_fnc, retflgs );
if( namehash ) {
if( namehash && tree->n.k.validity != TRUST_ULTIMATE ) {
/* find the matching user id.
* We don't do this here if the key is ultimately trusted; in
* this case there will be no lids for the user IDs and frankly
* it does not make sense to compare by the name if we do
* have the secret key.
* fixme: the way we handle this is too inefficient */
TN ur;
TRUSTREC rec;
@ -2075,6 +2183,7 @@ do_check( TRUSTREC *dr, unsigned *validity,
}
else if( !add_fnc
&& tdbio_db_matches_options()
/* FIXME, TODO: This comparision is WRONG ! */
&& dr->r.dir.valcheck
> tdbio_read_modify_stamp( (dr->r.dir.validity < TRUST_FULLY) )
&& dr->r.dir.validity )
@ -2240,10 +2349,16 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel,
log_info(_("key %08lX.%lu: created in future "
"(time warp or clock problem)\n"),
(ulong)keyid[1], pk->local_id );
return GPGERR_TIME_CONFLICT;
if( !opt.ignore_time_conflict )
return GPGERR_TIME_CONFLICT;
}
if( rec.r.dir.checkat && rec.r.dir.checkat <= cur_time )
check_trust_record( &rec );
if( !(rec.r.dir.dirflags & DIRF_CHECKED) )
check_trust_record( &rec, 0 );
else if( rec.r.dir.checkat && rec.r.dir.checkat <= cur_time )
check_trust_record( &rec, 0 );
else if( (rec.r.dir.dirflags & DIRF_NEWKEYS) )
check_trust_record( &rec, 1 );
if( pk->expiredate && pk->expiredate <= cur_time ) {
log_info(_("key %08lX.%lu: expired at %s\n"),
@ -2299,6 +2414,51 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel,
}
/****************
* scan the whole trustdb and mark all signature records whose keys
* are freshly imported.
*/
static void
mark_fresh_keys()
{
TRUSTREC dirrec, rec;
ulong recnum, lid;
int i;
memset( &dirrec, 0, sizeof dirrec );
for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
if( rec.rectype != RECTYPE_SIG )
continue;
/* if we have already have the dir record, we can check it now */
if( dirrec.recnum == rec.r.sig.lid
&& (dirrec.r.dir.dirflags & DIRF_NEWKEYS) )
continue; /* flag is already set */
for(i=0; i < SIGS_PER_RECORD; i++ ) {
if( !(lid=rec.r.sig.sig[i].lid) )
continue; /* skip deleted sigs */
if( !(rec.r.sig.sig[i].flag & SIGF_CHECKED) )
continue; /* skip checked signatures */
if( qry_lid_table_flag( fresh_imported_keys, lid, NULL ) )
continue; /* not in the list of new keys */
read_record( rec.r.sig.lid, &dirrec, RECTYPE_DIR );
if( !(dirrec.r.dir.dirflags & DIRF_NEWKEYS) ) {
dirrec.r.dir.dirflags |= DIRF_NEWKEYS;
write_record( &dirrec );
}
break;
}
}
do_sync();
clear_lid_table( fresh_imported_keys );
fresh_imported_keys_count = 0;
}
int
query_trust_info( PKT_public_key *pk, const byte *namehash )
{
@ -2532,7 +2692,7 @@ enum_cert_paths_print( void **context, FILE *fp,
/*
* Return an allocated buffer with the preference values for
* the key with LID and the userid which is identified by the
* HAMEHASH or the firstone if namehash is NULL. ret_n receives
* HAMEHASH or the first one if namehash is NULL. ret_n receives
* the length of the allocated buffer. Structure of the buffer is
* a repeated sequences of 2 bytes; where the first byte describes the
* type of the preference and the second one the value. The constants

View File

@ -1,5 +1,5 @@
/* trustdb.h - Trust database
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -49,6 +49,7 @@ void check_trustdb( const char *username );
void update_trustdb( void );
int setup_trustdb( int level, const char *dbname );
void init_trustdb( void );
void sync_trustdb( void );
int check_trust( PKT_public_key *pk, unsigned *r_trustlevel,
const byte* nh, int (*add_fnc)(ulong), unsigned *retflgs );
int query_trust_info( PKT_public_key *pk, const byte *nh );

View File

@ -1,5 +1,5 @@
/* verify.c - verify signed data
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -25,14 +25,15 @@
#include <errno.h>
#include <assert.h>
#include <gcrypt.h>
#include "options.h"
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include <gcrypt.h>
#include "util.h"
#include "main.h"
#include "status.h"
#include "filter.h"
#include "ttyio.h"
#include "i18n.h"
@ -58,6 +59,7 @@ verify_signatures( int nfiles, char **files )
int i, rc;
STRLIST sl;
memset( &afx, 0, sizeof afx);
sigfile = nfiles? *files : NULL;
/* open the signature file */
@ -67,6 +69,51 @@ verify_signatures( int nfiles, char **files )
return GPGERR_OPEN_FILE;
}
if( !opt.no_armor && use_armor_filter( fp ) )
iobuf_push_filter( fp, armor_filter, &afx );
sl = NULL;
for(i=1 ; i < nfiles; i++ )
add_to_strlist( &sl, files[i] );
rc = proc_signature_packets( NULL, fp, sl, sigfile );
free_strlist(sl);
iobuf_close(fp);
if( afx.no_openpgp_data && rc == -1 ) {
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;
}
return rc;
}
static void
print_file_status( int status, const char *name, int what )
{
char *p = gcry_xmalloc(strlen(name)+10);
sprintf(p, "%d %s", what, name );
write_status_text( status, p );
gcry_free(p);
}
static int
verify_one_file( const char *name )
{
IOBUF fp;
armor_filter_context_t afx;
int rc;
print_file_status( STATUS_FILE_START, name, 1 );
fp = iobuf_open(name);
if( !fp ) {
print_file_status( STATUS_FILE_ERROR, name, 1 );
log_error(_("can't open `%s'\n"), print_fname_stdin(name));
return GPGERR_OPEN_FILE;
}
if( !opt.no_armor ) {
if( use_armor_filter( fp ) ) {
memset( &afx, 0, sizeof afx);
@ -74,14 +121,44 @@ verify_signatures( int nfiles, char **files )
}
}
sl = NULL;
for(i=1 ; i < nfiles; i++ )
add_to_strlist( &sl, files[i] );
rc = proc_signature_packets( NULL, fp, sl, sigfile );
free_strlist(sl);
rc = proc_signature_packets( NULL, fp, NULL, name );
iobuf_close(fp);
write_status( STATUS_FILE_DONE );
return rc;
}
/****************
* Verify each file given in the files array or read the names of the
* files from stdin.
* Note: This function can not handle detached signatures.
*/
int
verify_files( int nfiles, char **files )
{
int i;
if( !nfiles ) { /* read the filenames from stdin */
char line[2048];
unsigned int lno = 0;
while( fgets(line, DIM(line), stdin) ) {
lno++;
if( !*line || line[strlen(line)-1] != '\n' ) {
log_error(_("input line %u too long or missing LF\n"), lno );
return GPGERR_GENERAL;
}
/* This code does not work on MSDOS but how cares there are
* also no script languages available. We don't strip any
* spaces, so that we can process nearly all filenames */
line[strlen(line)-1] = 0;
verify_one_file( line );
}
}
else { /* take filenames from the array */
for(i=0; i < nfiles; i++ )
verify_one_file( files[i] );
}
return 0;
}

View File

@ -1,3 +1,13 @@
Fri Jul 14 19:38:23 CEST 2000 Werner Koch <wk@>
* http.h (HTTP_FLAG_TRY_PROXY): new.
* error.h (G10ERR_NOT_PROCESSED): New.
* iobuf.h (IOBUFCTRL_CANCEL): New.
* types.h (HAVE_U64_TYPEDEF): Defined depending on configure test.
Thu Jan 27 18:00:44 CET 2000 Werner Koch <wk@gnupg.de>
* Changed all "g10_"/"GPG_" prefixes to "gpg_"/"GPG_".

View File

@ -1,5 +1,5 @@
/* errors.h - erro code
* Copyright (C) 1998 Free Software Foundation, Inc.
/* errors.h - error codes fro GnuPG
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GNUPG.
*
@ -74,6 +74,7 @@
#define GPGERR_UNKNOWN_HOST 149
#define GPGERR_SELFTEST_FAILED 50
#define GPGERR_NOT_ENCRYPTED 151
#define GPGERR_NOT_PROCESSED 152
#ifndef HAVE_STRERROR
char *strerror( int n );

View File

@ -49,6 +49,10 @@ typedef enum {
HTTP_REQ_POST = 3
} HTTP_REQ_TYPE;
enum { /* put flag values into an enum, so that gdb can display them */
HTTP_FLAG_TRY_PROXY = 1
};
struct http_context {
int initialized;
unsigned int status_code;
@ -60,7 +64,8 @@ struct http_context {
PARSED_URI uri;
HTTP_REQ_TYPE req_type;
byte *buffer; /* line buffer */
unsigned buffer_size;
unsigned int buffer_size;
unsigned int flags;
};
typedef struct http_context *HTTP_HD;

View File

@ -32,6 +32,7 @@
#define IOBUFCTRL_UNDERFLOW 3
#define IOBUFCTRL_FLUSH 4
#define IOBUFCTRL_DESC 5
#define IOBUFCTRL_CANCEL 6
#define IOBUFCTRL_USER 16
typedef struct iobuf_struct *IOBUF;

View File

@ -83,6 +83,11 @@
#define HAVE_U32_TYPEDEF
#endif
/****************
* Warning: Some systems segfault when this u64 typedef and
* the dummy code in cipher/md.c is not available. Examples are
* Solaris and IRIX.
*/
#ifndef HAVE_U64_TYPEDEF
#undef u64 /* maybe there is a macro with this name */
#if SIZEOF_UNSIGNED_INT == 8
@ -91,7 +96,7 @@
#elif SIZEOF_UNSIGNED_LONG == 8
typedef unsigned long u64;
#define HAVE_U64_TYPEDEF
#elif __GNUC__ >= 2 || defined(__SUNPRO_C)
#elif SIZEOF_UNSIGNED_LONG_LONG == 8
typedef unsigned long long u64;
#define HAVE_U64_TYPEDEF
#endif

View File

@ -40,6 +40,7 @@ void gpg_log_print_prefix(const char *text);
void log_set_name( const char *name );
const char *log_get_name(void);
void log_set_pid( int pid );
void log_inc_errorcount(void);
int log_get_errorcount( int clear );
void gpg_log_hexdump( const char *text, const char *buf, size_t len );

View File

@ -1,3 +1,9 @@
Fri Jul 14 19:38:23 CEST 2000 Werner Koch <wk@>
* argparse.c (default_strusage): Changed year of default copyright.
* dotlock.c (disable_dotlock): New.
Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de>
* README: New.

View File

@ -1,5 +1,5 @@
/* [argparse.c wk 17.06.97] Argument Parser for option handling
* Copyright (C) 1998,1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
@ -899,7 +899,7 @@ strusage( int level )
switch( level ) {
case 11: p = "foo"; break;
case 13: p = "0.0"; break;
case 14: p = "Copyright (C) 1999 Free Software Foundation, Inc."; break;
case 14: p = "Copyright (C) 2000 Free Software Foundation, Inc."; break;
case 15: p =
"This program comes with ABSOLUTELY NO WARRANTY.\n"
"This is free software, and you are welcome to redistribute it\n"

View File

@ -1,5 +1,5 @@
/* dotlock.c - dotfile locking
* Copyright (C) 1998,2000 Free Software Foundation, Inc.
* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -42,14 +42,22 @@ struct dotlock_handle {
char *tname; /* name of lockfile template */
char *lockname; /* name of the real lockfile */
int locked; /* lock status */
int disable; /* locking */
};
static DOTLOCK all_lockfiles;
static int never_lock;
static int read_lockfile( const char *name );
static void remove_lockfiles(void);
void
disable_dotlock(void)
{
never_lock = 1;
}
/****************
* Create a lockfile with the given name and return an object of
* type DOTLOCK which may be used later to actually do the lock.
@ -88,6 +96,16 @@ create_dotlock( const char *file_to_lock )
return NULL;
h = jnlib_xcalloc( 1, sizeof *h );
if( never_lock ) {
h->disable = 1;
#ifdef _REENTRANT
/* fixme: aquire mutex on all_lockfiles */
#endif
h->next = all_lockfiles;
all_lockfiles = h;
return h;
}
#ifndef HAVE_DOSISH_SYSTEM
sprintf( pidstr, "%10d\n", (int)getpid() );
/* fixme: add the hostname to the second line (FQDN or IP addr?) */
@ -191,6 +209,10 @@ make_dotlock( DOTLOCK h, long timeout )
const char *maybe_dead="";
int backoff=0;
if( h->disable ) {
return 0;
}
if( h->locked ) {
log_debug("oops, `%s' is already locked\n", h->lockname );
return 0;
@ -259,6 +281,10 @@ release_dotlock( DOTLOCK h )
#else
int pid;
if( h->disable ) {
return 0;
}
if( !h->locked ) {
log_debug("oops, `%s' is not locked\n", h->lockname );
return 0;
@ -333,11 +359,13 @@ remove_lockfiles()
while( h ) {
h2 = h->next;
if( h->locked )
unlink( h->lockname );
unlink(h->tname);
jnlib_free(h->tname);
jnlib_free(h->lockname);
if( !h->disable ) {
if( h->locked )
unlink( h->lockname );
unlink(h->tname);
jnlib_free(h->tname);
jnlib_free(h->lockname);
}
jnlib_free(h);
h = h2;
}

View File

@ -24,6 +24,7 @@
struct dotlock_handle;
typedef struct dotlock_handle *DOTLOCK;
void disable_dotlock(void);
DOTLOCK create_dotlock( const char *file_to_lock );
int make_dotlock( DOTLOCK h, long timeout );
int release_dotlock( DOTLOCK h );

View File

@ -1,3 +1,28 @@
Fri Jul 14 19:38:23 CEST 2000 Werner Koch <wk@>
* iobuf.c (iobuf_cancel): Broadcast the new Cancel message to all
filters. Fix for MSDOS.
* miscutil.c (asctimestamp): Fix for possible buffer overflow by
a large system returned date format string.
* logger.c (log_inc_errorcount): New.
* w32reg.c: New.
* simple-gettext.c: Use the Registry to locate the mo file.
* http.c (send_request): Add support for proxys; suggested by
Walter Hofmann.
(http_open_document): Pass flags to http_open.
* ttyio.c (do_get): Replaced #if __MINGW32__ by #ifdef because
gcc 2.95.1 assigns a floating point value (0.2) to this macro,
which in turn can't be used in an expression.
* ttyio.c: Simulate termios with termios. By Dave Dykstra.
* ttyio.c (tty_print_utf8_string): Oops.
* ttyio.c (tty_print_utf8_string2): New to allow a max output size.
Thu Jan 27 18:00:44 CET 2000 Werner Koch <wk@gnupg.de>
* Changed all "g10_"/"GPG_" prefixes to "gpg_"/"GPG_".

View File

@ -8,7 +8,7 @@ noinst_LTLIBRARIES = libutil.la
libutil_la_LDFLAGS =
libutil_la_SOURCES = logger.c fileutil.c miscutil.c strgutil.c \
ttyio.c errors.c iobuf.c \
http.c simple-gettext.c
http.c simple-gettext.c w32reg.c
http-test: http.c

View File

@ -1,5 +1,5 @@
/* http.c - HTTP protocol handler
* Copyright (C) 1999 Free Software Foundation, Inc.
* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -26,7 +26,7 @@
#include <ctype.h>
#include <errno.h>
#ifndef HAVE_DOSISH_SYSTEM
#ifndef HAVE_DOSISH_SYSTEM /* fixme: add support W32 sockets */
#include <unistd.h>
#include <sys/types.h>
@ -76,7 +76,7 @@ http_open( HTTP_HD hd, HTTP_REQ_TYPE reqtype, const char *url,
{
int rc;
if( flags || !(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST) )
if( !(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST) )
return GPGERR_INV_ARG;
/* initialize the handle */
@ -84,6 +84,7 @@ http_open( HTTP_HD hd, HTTP_REQ_TYPE reqtype, const char *url,
hd->sock = -1;
hd->initialized = 1;
hd->req_type = reqtype;
hd->flags = flags;
rc = parse_uri( &hd->uri, url );
if( !rc ) {
@ -150,10 +151,7 @@ http_open_document( HTTP_HD hd, const char *document, unsigned int flags )
{
int rc;
if( flags )
return GPGERR_INV_ARG;
rc = http_open( hd, HTTP_REQ_GET, document, 0 );
rc = http_open( hd, HTTP_REQ_GET, document, flags );
if( rc )
return rc;
@ -429,21 +427,47 @@ send_request( HTTP_HD hd )
byte *request, *p;
ushort port;
int rc;
const char *http_proxy = NULL;
server = *hd->uri->host? hd->uri->host : "localhost";
port = hd->uri->port? hd->uri->port : 80;
hd->sock = connect_server( server, port );
if( (hd->flags & HTTP_FLAG_TRY_PROXY)
&& (http_proxy = getenv( "http_proxy" )) ) {
PARSED_URI uri;
rc = parse_uri( &uri, http_proxy );
if (rc) {
log_error("invalid $http_proxy: %s\n", gpg_errstr(rc));
release_parsed_uri( uri );
return GPGERR_NETWORK;
}
hd->sock = connect_server( *uri->host? uri->host : "localhost",
uri->port? uri->port : 80 );
release_parsed_uri( uri );
}
else
hd->sock = connect_server( server, port );
if( hd->sock == -1 )
return GPGERR_NETWORK;
p = build_rel_path( hd->uri );
request = gcry_xmalloc( strlen(p) + 20 );
sprintf( request, "%s %s%s HTTP/1.0\r\n",
if( http_proxy ) {
sprintf( request, "%s http://%s:%hu%s%s HTTP/1.0\r\n",
hd->req_type == HTTP_REQ_GET ? "GET" :
hd->req_type == HTTP_REQ_HEAD? "HEAD":
hd->req_type == HTTP_REQ_POST? "POST": "OOPS",
server, port, *p == '/'? "":"/", p );
}
else {
sprintf( request, "%s %s%s HTTP/1.0\r\n",
hd->req_type == HTTP_REQ_GET ? "GET" :
hd->req_type == HTTP_REQ_HEAD? "HEAD":
hd->req_type == HTTP_REQ_POST? "POST": "OOPS",
*p == '/'? "":"/", p );
}
gcry_free(p);
rc = write_server( hd->sock, request, strlen(request) );

View File

@ -1,5 +1,5 @@
/* iobuf.c - file handling
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -81,6 +81,8 @@ static int underflow(IOBUF a);
* IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
* *RET_LAN is the number of bytes in BUF.
*
* IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel. The
* filter may take appropriate action on this message.
*/
static int
file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
@ -494,19 +496,47 @@ iobuf_close( IOBUF a )
return rc;
}
int
iobuf_cancel( IOBUF a )
{
const char *s;
IOBUF a2;
int rc;
#ifdef HAVE_DOSISH_SYSTEM
char *remove_name = NULL;
#endif
if( a && a->use == 2 ) {
s = iobuf_get_real_fname(a);
if( s && *s )
remove(s); /* remove the file. Fixme: this will fail for MSDOZE*/
} /* because the file is still open */
return iobuf_close(a);
}
if( s && *s ) {
#ifdef HAVE_DOSISH_SYSTEM
remove_name = m_strdup ( s );
#else
remove(s);
#endif
}
}
/* send a cancel message to all filters */
for( a2 = a; a2 ; a2 = a2->chain ) {
size_t dummy;
if( a2->filter )
a2->filter( a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain,
NULL, &dummy );
}
rc = iobuf_close(a);
#ifdef HAVE_DOSISH_SYSTEM
if ( remove_name ) {
/* Argg, MSDOS does not allow to remove open files. So
* we have to do it here */
remove ( remove_name );
m_free ( remove_name );
}
#endif
return rc;
}
/****************
* create a temporary iobuf, which can be used to collect stuff

View File

@ -1,5 +1,5 @@
/* logger.c - log functions
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -102,6 +102,12 @@ log_get_errorcount( int clear)
return n;
}
void
log_inc_errorcount()
{
errorcount++;
}
void
gpg_log_print_prefix(const char *text)

Some files were not shown because too many files have changed in this diff Show More