From e81e0970f7ab6c815f3396168d47fc6ab57fdf30 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 16 Oct 1998 16:00:17 +0000 Subject: [PATCH] last local commit --- ChangeLog | 5 + NEWS | 19 +++ README | 24 +-- THANKS | 2 + TODO | 57 ++++--- acconfig.h | 3 + cipher/ChangeLog | 8 + cipher/Makefile.am | 6 +- cipher/dynload.c | 84 +++++++++- cipher/rand-unix.c | 8 +- configure.in | 25 ++- doc/DETAILS | 3 +- g10/ChangeLog | 31 +++- g10/armor.c | 40 +++-- g10/build-packet.c | 20 ++- g10/encode.c | 5 +- g10/export.c | 22 +-- g10/filter.h | 1 + g10/free-packet.c | 4 +- g10/g10.c | 45 +++-- g10/getkey.c | 157 +++++++----------- g10/import.c | 1 + g10/keydb.h | 7 +- g10/keygen.c | 57 ++++--- g10/keyid.c | 17 +- g10/keylist.c | 20 ++- g10/mainproc.c | 8 +- g10/options.h | 6 +- g10/packet.h | 4 +- g10/parse-packet.c | 20 ++- g10/ringedit.c | 83 ++++++++-- g10/sig-check.c | 8 +- g10/sign.c | 2 + g10/tdbio.c | 344 ++++++++++++++++++++++++++++++-------- g10/tdbio.h | 1 + g10/textfilter.c | 4 +- g10/trustdb.c | 386 ++++++++++++++++++++++++++++--------------- g10/trustdb.h | 1 + include/ChangeLog | 5 + include/cipher.h | 2 +- include/iobuf.h | 10 +- mpi/ChangeLog | 4 + mpi/config.links | 12 +- scripts/ChangeLog | 5 + scripts/config.guess | 90 +++++----- scripts/config.sub | 2 +- scripts/distfiles | 1 + util/ChangeLog | 4 + util/iobuf.c | 125 ++++++++++++-- 49 files changed, 1253 insertions(+), 545 deletions(-) create mode 100644 scripts/ChangeLog diff --git a/ChangeLog b/ChangeLog index 6a6464750..6a1ac49e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Wed Oct 14 12:11:34 1998 Werner Koch (wk@isil.d.shuttle.de) + + * configure.in (NAME_OF_DEV_RANDOM): New. + (DYNLINK_MOD_CFLAGS): New. + Thu Oct 8 10:55:15 1998 Werner Koch (wk@isil.d.shuttle.de) * Makefile.am (g10defs.h): creates include file diff --git a/NEWS b/NEWS index 40d763c42..9fb628234 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,25 @@ Noteworthy changes in version 0.4.2 ----------------------------------- * Fixed this huge memory leak. + * Redesigned the trust database: You should run "gpgm --check-trustdb". + New command --update-trustdb, which adds new key from the public + keyring into your trustdb + + * Fixed a bug in the armor code, leading to invalid packet errors. + (a workaround for this was to use --no-armor). + + * comment packets are not anymore generated. "--export" filters + them out. One Exception: The comment packets in a secret keyring + are still used because they carry the factorization of the public + prime product. + + * --import now only looks for KEYBLOCK headers, so you can now simply + remove the "- " in front of such a header if someone accdently signed + such a message or the keyblock is part of a cleartext signed message. + + * --with-colons now lists the key expiration time and not anymore + the valid period. + Noteworthy changes in version 0.4.1 ----------------------------------- diff --git a/README b/README index e5667035b..823cc527a 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ - GNUPG - The GNU Privacy Guard + GnuPG - The GNU Privacy Guard ------------------------------- Version 0.4 @@ -8,12 +8,12 @@ On a Linux box (version 2.x.x, alpha or x86 CPU) it should work reliably. You may create your key on such a machine and - use it. Please verify the tar file; there is a PGP and a GNUPG + use it. Please verify the tar file; there is a PGP and a GnuPG signature available. My PGP 2 key is well known and published in the "Global Trust Register for 1998", ISBN 0-9532397-0-5. I have included my pubring as "g10/pubring.asc", which contains - the key used to make GNUPG signatures: + the key used to make GnuPG signatures: "pub 1024D/57548DCD 1998-07-07 Werner Koch (gnupg sig) " "Key fingerprint = 6BD9 050F D8FC 941B 4341 2DCC 68B7 AB89 5754 8DCD" @@ -25,7 +25,7 @@ "pub 1024D/621CC013 1998-07-07 Werner Koch " "Key fingerprint = ECAF 7590 EB34 43B5 C7CF 3ACB 6C7E E1B8 621C C013" - You may add it to your GNUPG pubring and use it in the future to + You may add it to your GnuPG pubring and use it in the future to verify new releases. Because you verified this README file and _checked_that_it_is_really_my PGP2 key 0C9857A5, you can be sure that the above fingerprints are correct. @@ -36,17 +36,17 @@ See the file COPYING for copyright and warranty information. - Due to the fact that GNUPG does not use use any patented algorithm, + Due to the fact that GnuPG does not use use any patented algorithm, it cannot be compatible with old PGP versions, because those use IDEA (which is patented worldwide) and RSA (which is patented in the United States until Sep 20, 2000). - GNUPG is in almost all aspects compatible with other OpenPGP + GnuPG is in almost all aspects compatible with other OpenPGP implementations. The default algorithms are now DSA and ELGamal. ELGamal for signing is still available, but due to the larger size of such signatures it - is depreciated (Please note that the GNUPG implementation of ElGamal + is depreciated (Please note that the GnuPG implementation of ElGamal signatures is *not* insecure). Symmetric algorithms are: 3DES, Blowfish and CAST5, Digest algorithms are MD5, RIPEMD160, SHA1 and TIGER/192. @@ -230,7 +230,7 @@ "#34" This can be used by a MUA to specify an exact key after selecting - a key from GNUPG (by the use of a special option or an extra utility) + a key from GnuPG (by the use of a special option or an extra utility) * Or by the usual substring: @@ -245,19 +245,19 @@ Batch mode ---------- - If you use the option "--batch", GNUPG runs in non-interactive mode and + If you use the option "--batch", GnuPG runs in non-interactive mode and never prompts for input data. This does not even allow entering the passphrase; until we have a better solution (something like ssh-agent), you can use the option "--passhrase-fd n", which works like PGPs PGPPASSFD. - Batch mode also causes GNUPG to terminate as soon as a BAD signature is + Batch mode also causes GnuPG to terminate as soon as a BAD signature is detected. Exit status ----------- - GNUPG returns with an exit status of 1 if in batch mode and a bad signature + GnuPG returns with an exit status of 1 if in batch mode and a bad signature has been detected or 2 or higher for all other errors. You should parse stderr or the output of the fd specified with --status-fd to get detailed information about the errors. @@ -269,7 +269,7 @@ gpg --list-packets datafile Use this to list the contents of a data file. If the file is encrypted - you are asked for the passphrase, so that GNUPG is able to look at the + you are asked for the passphrase, so that GnuPG is able to look at the inner structure of a encrypted packet. gpgm --list-trustdb diff --git a/THANKS b/THANKS index 81aae8e1d..baaf5f1fc 100644 --- a/THANKS +++ b/THANKS @@ -26,12 +26,14 @@ Jean-loup Gailly gzip@prep.ai.mit.edu Jens Bachem bachem@rrz.uni-koeln.de John A. Martin jam@jamux.com Jörg Schilling schilling@fokus.gmd.de +Jun Kuriyama kuriyama@sky.rim.or.jp Karl Fogel kfogel@guanabana.onshore.com Karsten Thygesen karthy@kom.auc.dk Kazu Yamamoto kazu@iijlab.net Lars Kellogg-Stedman lars@bu.edu Marco d'Itri md@linux.it Mark Adler madler@alumni.caltech.edu +Markus Friedl Markus.Friedl@informatik.uni-erlangen.de Martin Schulte schulte@thp.uni-koeln.de Matthew Skala mskala@ansuz.sooke.bc.ca Max Valianskiy maxcom@maxcom.ml.org diff --git a/TODO b/TODO index 60cc105b8..744af3226 100644 --- a/TODO +++ b/TODO @@ -1,30 +1,41 @@ + * change ringedit: + - avoid all copy operations + - delete for update by changing the packet type to a + special unused packet. (export most know about this) + - do an append instead of an update or insert + - export may be used to compress a keyring. + - keep track of all offset in the trustbd and index them + by keyid. + - If the lookup does not find a public key block at the + stored offset disable this keyid. + - If the keyid was not found or is disabled, walk thru + the pubring. + - use ftruncate to recover from keyring errors. + maybe a new option to do this or simply mark the + wrong part as unused. + This makes signature checks and imports much faster; only keys + given by a userid or a fingerprint (RSA only) have to walk tru + the ring. + + * There is a new memory leak in update-trustdb + + * OpenBSD: dynamic loading with dlopen works on OpenBSD, but: + OpenBSD binaries are a.out, so every symbol begins with "_" + + * use dld if we don't have dlopen. + + * should we flush the getkey.c caches while doing an import? + + * prefer a type 16 subkey for encryption because pgp cannot handle + type 20. * calculation of marginals never yields a completely trusted key. - * list-keys: change valid-days to key expiration date - - * disable comments but those in secret keyrings. - - * abgelaufene secret keys verhinder ein korrektes initialisieren der - Trustdb. - - * import should skip all ascii armored messages headers which are - not keys (some folks are mailing signed public keyblocks :-) - * The critical bit of signature subpackets is not yet supported; i.e. it is ignored. - * Read more records at once in tdbio.c and provide a lazy write cache. - * Exportable Certification Flag is ignored - * Why does OpenPGP say: The algorithm byte is included in the - checksum of an encoded key, but the actual implementaion does - not do this but works - According to Hal Finney, this is a bug - in the specs. - - * fix armor problems (see mails by Brian Moore). - * write a tool to extract selected keys from a file. * new menu to delete signatures and list signature in menu @@ -33,10 +44,6 @@ * -rdynamic auf Solaris Problem - * if --libdir is used, the extensions are put in a wrong place. - How does GNOME handle this or make a new option for this directory. - Hmmm, I don´ like to pass ot as a commandline option to cc. - * Replace the SIGUSR1 stuff by semaphores to avoid loss of a signal. * add test cases for invalid data (scrambled armor or other random data) @@ -61,8 +68,8 @@ can also hold the localid and extend the localid to hold information of the subkey number because two subkeys may have the same keyid. - * add an option to re-create a public key from a secret key. Think about - a backup system of only the secret part of the secret key. + * add an option to re-create a public key from a secret key; we + can do this in trustdb.c:verify_own_keys. * OpenBSD has sometimes problems reading from /dev/random. diff --git a/acconfig.h b/acconfig.h index 9f8550ca8..b17d22de4 100644 --- a/acconfig.h +++ b/acconfig.h @@ -71,6 +71,9 @@ #undef USE_RAND_W32 /* defined if we have a /dev/random and /dev/urandom */ #undef HAVE_DEV_RANDOM +/* and the real names of the random devices */ +#undef NAME_OF_DEV_RANDOM +#undef NAME_OF_DEV_URANDOM #undef USE_DYNAMIC_LINKING #undef HAVE_DL_DLOPEN diff --git a/cipher/ChangeLog b/cipher/ChangeLog index ddd34b65c..99cd30128 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,11 @@ +Thu Oct 15 11:47:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dynload.c: Support for DLD + +Wed Oct 14 12:13:07 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c: Now uses names from configure for /dev/random. + 1998-10-10 SL Baur * Makefile.am: fix sed -O substitutions to catch -O6, etc. diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 298e0f32d..e151de578 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -11,6 +11,8 @@ else pkglib_PROGRAMS = endif +DYNLINK_MOD_CFLAGS = @DYNLINK_MOD_CFLAGS@ + libcipher_a_SOURCES = cipher.c \ pubkey.c \ @@ -48,11 +50,11 @@ EXTRA_twofish_SOURCES = twofish.c tiger: $(srcdir)/tiger.c - `echo $(COMPILE) -shared -fPIC -lc -o tiger $(srcdir)/tiger.c | \ + `echo $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o tiger $(srcdir)/tiger.c | \ sed -e 's/-O[2-9]*/-O1/' ` twofish: $(srcdir)/twofish.c - `echo $(COMPILE) -shared -fPIC -lc -o twofish $(srcdir)/twofish.c | \ + `echo $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o twofish $(srcdir)/twofish.c | \ sed -e 's/-O[0-9]*/ /' ` diff --git a/cipher/dynload.c b/cipher/dynload.c index 0cbbda2c1..ff40dafff 100644 --- a/cipher/dynload.c +++ b/cipher/dynload.c @@ -25,6 +25,8 @@ #include #ifdef HAVE_DL_DLOPEN #include +#elif defined(HAVE_DLD_DLD_LINK) + #include #endif #include "util.h" #include "cipher.h" @@ -37,7 +39,11 @@ typedef struct ext_list { struct ext_list *next; + #ifdef HAVE_DL_DLOPEN void *handle; /* handle from dlopen() */ + #else + int handle; /* if the function has been loaded, this is true */ + #endif int failed; /* already tried but failed */ void * (*enumfunc)(int, int*, int*, int*); char *hintstr; /* pointer into name */ @@ -53,6 +59,14 @@ typedef struct { void *sym; } ENUMCONTEXT; + +#ifdef HAVE_DLD_DLD_LINK +static char *mainpgm_path; +static int did_dld_init; +static int dld_available; +#endif + + /**************** * Register an extension module. The last registered module will * be loaded first. A name may have a list of classes @@ -62,13 +76,20 @@ typedef struct { * algorithms 20 and 109. This is only a hint but if it is there the * loader may decide to only load a module which claims to have a * requested algorithm. + * + * mainpgm is the path to the program which wants to load a module + * it is only used in some environments. */ void -register_cipher_extension( const char *fname ) +register_cipher_extension( const char *mainpgm, const char *fname ) { EXTLIST r, el; char *p, *pe; + #ifdef HAVE_DLD_DLD_LINK + if( !mainpgm_path && mainpgm && *mainpgm ) + mainpgm_path = m_strdup(mainpgm); + #endif if( *fname != '/' ) { /* do tilde expansion etc */ char *p ; @@ -110,16 +131,22 @@ load_extension( EXTLIST el ) { #ifdef USE_DYNAMIC_LINKING char **name; - void *sym; + #ifdef HAVE_DL_DLOPEN const char *err; int seq = 0; int class, vers; + void *sym; + #else + unsigned long addr; + int rc; + #endif /* make sure we are not setuid */ if( getuid() != geteuid() ) log_bug("trying to load an extension while still setuid\n"); /* now that we are not setuid anymore, we can safely load modules */ + #ifdef HAVE_DL_DLOPEN el->handle = dlopen(el->name, RTLD_NOW); if( !el->handle ) { log_error("%s: error loading extension: %s\n", el->name, dlerror() ); @@ -130,6 +157,38 @@ load_extension( EXTLIST el ) log_error("%s: not a gnupg extension: %s\n", el->name, err ); goto failure; } + #else /* have dld */ + if( !did_dld_init ) { + did_dld_init = 1; + if( !mainpgm_path ) + log_error("DLD is not correctly initialized\n"); + else { + rc = dld_init( dld_find_executable(mainpgm_path) ); + if( rc ) + log_error("DLD init failed: %s\n", dld_strerror(rc) ); + else + dld_available = 1; + } + } + if( !dld_available ) { + log_error("%s: DLD not available\n", el->name ); + goto failure; + } + + rc = dld_link( el->name ); + if( rc ) { + log_error("%s: error loading extension: %s\n", + el->name, dld_strerror(rc) ); + goto failure; + } + addr = dld_get_symbol("gnupgext_version"); + if( !addr ) { + log_error("%s: not a gnupg extension: %s\n", + el->name, dld_strerror(dld_errno) ); + goto failure; + } + name = (char**)addr; + #endif if( g10_opt_verbose ) log_info("%s: %s%s%s%s\n", el->name, *name, @@ -137,13 +196,31 @@ load_extension( EXTLIST el ) el->hintstr? el->hintstr:"", el->hintstr? ")":""); + #ifdef HAVE_DL_DLOPEN sym = dlsym(el->handle, "gnupgext_enum_func"); if( (err=dlerror()) ) { log_error("%s: invalid gnupg extension: %s\n", el->name, err ); goto failure; } el->enumfunc = (void *(*)(int,int*,int*,int*))sym; + #else /* dld */ + addr = dld_get_func("gnupgext_enum_func"); + if( !addr ) { + log_error("%s: invalid gnupg extension: %s\n", + el->name, dld_strerror(dld_errno) ); + goto failure; + } + rc = dld_function_executable_p("gnupgext_enum_func"); + if( rc ) { + log_error("%s: extension function is not executable: %s\n", + el->name, dld_strerror(rc) ); + goto failure; + } + el->enumfunc = (void *(*)(int,int*,int*,int*))addr; + el->handle = 1; /* mark as usable */ + #endif + #ifdef HAVE_DL_DLOPEN if( g10_opt_verbose > 1 ) { /* list the contents of the module */ while( (sym = (*el->enumfunc)(0, &seq, &class, &vers)) ) { @@ -166,13 +243,16 @@ load_extension( EXTLIST el ) } } } + #endif return 0; failure: + #ifdef HAVE_DL_DLOPEN if( el->handle ) { dlclose(el->handle); el->handle = NULL; } + #endif el->failed = 1; #endif /*USE_DYNAMIC_LINKING*/ return -1; diff --git a/cipher/rand-unix.c b/cipher/rand-unix.c index 33f964d58..b9423e0d1 100644 --- a/cipher/rand-unix.c +++ b/cipher/rand-unix.c @@ -89,10 +89,10 @@ fast_random_poll() } -#ifdef HAVE_DEV_RANDOM /* we have the /dev/random device */ +#ifdef HAVE_DEV_RANDOM /* we have the /dev/random devices */ /**************** - * Used to open the Linux /dev/random device + * Used to open the Linux and xBSD /dev/random devices */ static int open_device( const char *name, int minor ) @@ -126,12 +126,12 @@ read_random_source( byte *buffer, size_t length, int level ) if( level >= 2 ) { if( fd_random == -1 ) - fd_random = open_device( "/dev/random", 8 ); + fd_random = open_device( NAME_OF_DEV_RANDOM, 8 ); fd = fd_random; } else { if( fd_urandom == -1 ) - fd_urandom = open_device( "/dev/urandom", 9 ); + fd_urandom = open_device( NAME_OF_DEV_URANDOM, 9 ); fd = fd_urandom; } do { diff --git a/configure.in b/configure.in index ae674ae2b..543748fba 100644 --- a/configure.in +++ b/configure.in @@ -76,6 +76,7 @@ AC_PROG_INSTALL AM_CYGWIN32 + case "${target}" in i386--mingw32) # special stuff for Windoze NT @@ -104,6 +105,23 @@ case "${target}" in esac AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME") +dnl Fixme: Are these the best flags for OpenBSD???? +case "${target}" in + *-openbsd*) + NAME_OF_DEV_RANDOM="/dev/srandom" + 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" + DYNLINK_MOD_CFLAGS="-shared -fPIC -lc" + ;; +esac +AC_DEFINE_UNQUOTED(NAME_OF_DEV_RANDOM, "$NAME_OF_DEV_RANDOM") +AC_DEFINE_UNQUOTED(NAME_OF_DEV_URANDOM, "$NAME_OF_DEV_URANDOM") + + dnl Checks for libraries. @@ -126,12 +144,15 @@ fi else AC_MSG_CHECKING(for dynamic loading) DYNLINK_LDFLAGS= + DYNLINK_MOD_CFLAGS= use_gnupg_extensions=no AC_MSG_RESULT(has been disabled) fi AM_CONDITIONAL(ENABLE_GNUPG_EXTENSIONS, test "$use_gnupg_extensions" = yes ) AC_SUBST(DYNLINK_LDFLAGS) +AC_SUBST(DYNLINK_MOD_CFLAGS) + dnl Checks for header files. AC_HEADER_STDC @@ -182,7 +203,7 @@ fi dnl check whether we have a random device if test "$try_dev_random" = yes ; then AC_CACHE_CHECK(for random device, ac_cv_have_dev_random, -[if test -c /dev/random && test -c /dev/urandom ; then +[if test -c "$NAME_OF_DEV_RANDOM" && test -c "$NAME_OF_DEV_URANDOM" ; then ac_cv_have_dev_random=yes; else ac_cv_have_dev_random=no; fi]) if test "$ac_cv_have_dev_random" = yes; then AC_DEFINE(HAVE_DEV_RANDOM) @@ -194,8 +215,6 @@ else fi - - dnl setup assembler stuff AC_MSG_CHECKING(for mpi assembler functions) if test -f $srcdir/mpi/config.links ; then diff --git a/doc/DETAILS b/doc/DETAILS index dca87afff..5a3dccbb6 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -22,8 +22,7 @@ ssb::1536:20:5CE086B5B5A18FF4:1998-07-07:0::: 20 = ElGamal (sign and encrypt) 5. Field: KeyID 6. Field: Creation Date (in UTC) - 7. Field: key expieres n days after creation. - (I will change this to a key exiration date) + 7. Field: Key expiration date or empty if none. 8. Field: Local ID: record number of the dir record in the trustdb this value is only valid as long as the trustdb is not deleted. May be later used to lookup the key: You will be diff --git a/g10/ChangeLog b/g10/ChangeLog index 93a21e241..4bc222084 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,6 +1,35 @@ +Fri Oct 16 10:24:47 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c: Rewrote most. + * tdbio.c: Add cache and generalized hash tables. + + * options.h (ENABLE_COMMENT_PACKETS): New but undef'ed. + * encode.c, sign.c, keygen.c: Disabled comment packets. + * export.c (do_export): Comment packets are never exported, + except for those in the secret keyring. + + * g10.c (main): Removed option do-no-export-rsa; should be + be replaced by a secpial tool. + * export.c (do_export): Removed the code for the above option. + + * armor.c (find_header): Support for new only_keyblocks. + * import.c (import_keys): Only looks for keyblock armors. + + * packet.h: replaced valid_days by expiredate and changed all users. + * build-packet.c (do_public_key): calculates valid-days + (do_secret_key): Ditto. + * parse-packet.c (parse_key): expiredate is calucated from the + valid_period in v3 packets. + * keyid.c (do_fingerprint_md): calculates valid_dates. + + * keygen.c (add_key_expire): fixed key expiration time for v4 packets. + + * armor.c (find_header): A LF in the first 28 bytes + was skipped for non-armored data. + Thu Oct 8 11:35:51 1998 Werner Koch (wk@isil.d.shuttle.de) - * armor.c (is_armored): Ad test on old comment packets. + * armor.c (is_armored): Add test on old comment packets. * tdbio.c (tdbio_search_dir_bypk): fixed memory leak. diff --git a/g10/armor.c b/g10/armor.c index df67712a4..aa5609018 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -109,7 +109,8 @@ static char *tail_strings[] = { static fhdr_state_t find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, IOBUF a, size_t n, - unsigned *r_empty, int *r_hashes ); + unsigned *r_empty, int *r_hashes, + int only_keyblocks ); static void @@ -260,7 +261,8 @@ parse_hash_header( const char *line ) */ static fhdr_state_t find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, - IOBUF a, size_t n, unsigned *r_empty, int *r_hashes ) + IOBUF a, size_t n, unsigned *r_empty, int *r_hashes, + int only_keyblocks ) { int c=0, i; const char *s; @@ -273,7 +275,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, buflen = *r_buflen; assert(buflen >= 100 ); - buflen -= 3; /* reserved room for CR,LF and one extra */ + buflen -= 4; /* reserved room for CR,LF, and two extra */ do { switch( state ) { @@ -281,14 +283,17 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, /* read at least the first byte to check whether it is armored * or not */ c = 0; - for(n=0; n < 28 && (c=iobuf_get2(a)) != -1 && c != '\n'; ) + for(n=0; n < 28 && (c=iobuf_get(a)) != -1 && c != '\n'; ) buf[n++] = c; if( !n && c == '\n' ) state = fhdrCHECKBegin; else if( !n || c == -1 ) state = fhdrNOArmor; /* too short */ - else if( !is_armored( buf ) ) + else if( !is_armored( buf ) ) { state = fhdrNOArmor; + if( c == '\n' ) + buf[n++] = c; + } else if( c == '\n' ) state = fhdrCHECKBegin; else @@ -299,7 +304,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, n = 0; case fhdrINITCont: /* read more stuff into buffer */ c = 0; - for(; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; ) + for(; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; ) buf[n++] = c; state = c == '\n' ? fhdrCHECKBegin : c == -1 ? fhdrEOF : fhdrINITSkip; @@ -309,21 +314,21 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, if( c == '\n' ) n = 0; else { - while( (c=iobuf_get2(a)) != -1 && c != '\n' ) + while( (c=iobuf_get(a)) != -1 && c != '\n' ) ; } state = c == -1? fhdrEOF : fhdrINIT; break; case fhdrSKIPHeader: - while( (c=iobuf_get2(a)) != -1 && c != '\n' ) + while( (c=iobuf_get(a)) != -1 && c != '\n' ) ; state = c == -1? fhdrEOF : fhdrWAITHeader; break; case fhdrWAITHeader: /* wait for Header lines */ c = 0; - for(n=0; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; ) + for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; ) buf[n++] = c; buf[n] = 0; if( n < buflen || c == '\n' ) { @@ -388,7 +393,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, case fhdrWAITClearsig: /* skip the empty line (for clearsig) */ c = 0; - for(n=0; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; ) + for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; ) buf[n++] = c; if( n < buflen || c == '\n' ) { buf[n] = 0; @@ -432,6 +437,9 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, break; if( !s ) break; /* unknown begin line */ + if( only_keyblocks && i != 1 && i != 5 && i != 6 ) + break; /* not a keyblock armor */ + /* found the begin line */ hdr_line = i; state = fhdrWAITHeader; @@ -448,7 +456,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, * we have to look for a header line or dashed escaped text*/ n = 0; c = 0; - while( n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n' ) + while( n < buflen && (c=iobuf_get(a)) != -1 && c != '\n' ) buf[n++] = c; buf[n] = 0; if( c == -1 ) @@ -516,7 +524,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, * for dashed escaped text of headers */ c = 0; n = 0; - while( n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n' ) + while( n < buflen && (c=iobuf_get(a)) != -1 && c != '\n' ) buf[n++] = c; buf[n] = 0; if( c == -1 ) @@ -534,7 +542,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, * counting spaces is not enough, because it may be a * mix of different white space characters */ IOBUF b = iobuf_temp(); - while( (c=iobuf_get2(a)) != -1 && c != '\n' ) { + while( (c=iobuf_get(a)) != -1 && c != '\n' ) { iobuf_put(b,c); if( c != ' ' && c != '\t' && c != '\r' ) break; @@ -622,7 +630,8 @@ check_input( armor_filter_context_t *afx, IOBUF a ) n = DIM(afx->helpbuf); state = find_header( state, afx->helpbuf, &n, a, - afx->helplen, &emplines, &afx->hashes); + afx->helplen, &emplines, &afx->hashes, + afx->only_keyblocks ); switch( state ) { case fhdrNOArmor: afx->inp_checked = 1; @@ -708,7 +717,8 @@ fake_packet( armor_filter_context_t *afx, IOBUF a, afx->helpidx = 0; state = find_header( state, afx->helpbuf, &n, a, state == fhdrNullClearsig? afx->helplen:0, - &emplines, &afx->hashes ); + &emplines, &afx->hashes, + afx->only_keyblocks ); switch( state) { case fhdrERROR: invalid_armor(); diff --git a/g10/build-packet.c b/g10/build-packet.c index a877b7e3c..11edb33e6 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -209,8 +209,14 @@ do_public_key( IOBUF out, int ctb, PKT_public_key *pk ) else iobuf_put( a, pk->version ); write_32(a, pk->timestamp ); - if( pk->version < 4 ) - write_16(a, pk->valid_days ); + if( pk->version < 4 ) { + u16 ndays; + if( pk->expiredate ) + ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L); + else + ndays = 0; + write_16(a, 0 ); + } iobuf_put(a, pk->pubkey_algo ); n = pubkey_get_npkey( pk->pubkey_algo ); if( !n ) @@ -280,8 +286,14 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk ) else iobuf_put( a, sk->version ); write_32(a, sk->timestamp ); - if( sk->version < 4 ) - write_16(a, sk->valid_days ); + if( sk->version < 4 ) { + u16 ndays; + if( sk->expiredate ) + ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L); + else + ndays = 0; + write_16(a, 0 ); + } iobuf_put(a, sk->pubkey_algo ); nskey = pubkey_get_nskey( sk->pubkey_algo ); npkey = pubkey_get_npkey( sk->pubkey_algo ); diff --git a/g10/encode.c b/g10/encode.c index bc4742607..0d8a84c94 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -118,12 +118,14 @@ encode_simple( const char *filename, int mode ) if( opt.armor ) iobuf_push_filter( out, armor_filter, &afx ); + #ifdef ENABLE_COMMENT_PACKETS else { write_comment( out, "#created by GNUPG v" VERSION " (" PRINTABLE_OS_NAME ")"); if( opt.comment_string ) write_comment( out, opt.comment_string ); } + #endif if( s2k && !opt.rfc1991 ) { PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc ); enc->version = 4; @@ -224,13 +226,14 @@ encode_crypt( const char *filename, STRLIST remusr ) if( opt.armor ) iobuf_push_filter( out, armor_filter, &afx ); + #ifdef ENABLE_COMMENT_PACKETS else { write_comment( out, "#created by GNUPG v" VERSION " (" PRINTABLE_OS_NAME ")"); if( opt.comment_string ) write_comment( out, opt.comment_string ); } - + #endif /* create a session key */ cfx.dek = m_alloc_secure( sizeof *cfx.dek ); if( !opt.def_cipher_algo ) { /* try to get it from the prefs */ diff --git a/g10/export.c b/g10/export.c index 301cb5ece..46413fff2 100644 --- a/g10/export.c +++ b/g10/export.c @@ -124,24 +124,10 @@ do_export( STRLIST users, int secret ) /* and write it */ for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) { - if( opt.do_not_export_rsa ) { - int algo; - switch( node->pkt->pkttype ) { - /* note: we can´ do this for subkeys here */ - case PKT_PUBLIC_KEY: - algo = node->pkt->pkt.public_key->pubkey_algo; - break; - case PKT_SECRET_KEY: - algo = node->pkt->pkt.secret_key->pubkey_algo; - break; - case PKT_SIGNATURE: - algo = node->pkt->pkt.signature->pubkey_algo; - break; - default: algo = 0; - } - if( is_RSA(algo) ) - continue; - } + /* don't export any comment packets but those in the + * secret keyring */ + if( !secret && node->pkt->pkttype == PKT_COMMENT ) + continue; if( (rc = build_packet( out, node->pkt )) ) { log_error("build_packet(%d) failed: %s\n", node->pkt->pkttype, g10_errstr(rc) ); diff --git a/g10/filter.h b/g10/filter.h index d48b75627..1cf8f8e42 100644 --- a/g10/filter.h +++ b/g10/filter.h @@ -31,6 +31,7 @@ typedef struct { typedef struct { int status; int what; + int only_keyblocks; /* skip all headers but ".... key block" */ byte radbuf[4]; int idx, idx2; u32 crc; diff --git a/g10/free-packet.c b/g10/free-packet.c index e6b228117..c3b516dbd 100644 --- a/g10/free-packet.c +++ b/g10/free-packet.c @@ -354,7 +354,7 @@ cmp_public_keys( PKT_public_key *a, PKT_public_key *b ) if( a->timestamp != b->timestamp ) return -1; - if( a->valid_days != b->valid_days ) + if( a->expiredate != b->expiredate ) return -1; if( a->pubkey_algo != b->pubkey_algo ) return -1; @@ -380,7 +380,7 @@ cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk ) if( pk->timestamp != sk->timestamp ) return -1; - if( pk->valid_days != sk->valid_days ) + if( pk->expiredate != sk->expiredate ) return -1; if( pk->pubkey_algo != sk->pubkey_algo ) return -1; diff --git a/g10/g10.c b/g10/g10.c index 9195d21a8..569d4112d 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -1,4 +1,4 @@ -/* g10.c - The GNUPG utility (main for gpg) +/* g10.c - The GnuPG utility (main for gpg) * Copyright (C) 1998 Free Software Foundation, Inc. * * This file is part of GNUPG. @@ -88,6 +88,7 @@ enum cmd_and_opt_values { aNull = 0, aPrintMD, aPrintMDs, aCheckTrustDB, + aUpdateTrustDB, aFixTrustDB, aListTrustDB, aListTrustPath, @@ -98,7 +99,6 @@ enum cmd_and_opt_values { aNull = 0, aGenRandom, oFingerprint, - oDoNotExportRSA, oAnswerYes, oAnswerNo, oKeyring, @@ -172,13 +172,17 @@ static ARGPARSE_OPTS opts[] = { #endif { aExport, "export" , 256, N_("export keys") }, { aExportSecret, "export-secret-keys" , 256, "@" }, - { oDoNotExportRSA, "do-not-export-rsa", 0, "@" }, { aImport, "import", 256 , N_("import/merge keys")}, { aListPackets, "list-packets",256,N_("list only the sequence of packets")}, #ifdef IS_G10MAINT - { aExportOwnerTrust, "export-ownertrust", 256, N_("export the ownertrust values")}, - { aImportOwnerTrust, "import-ownertrust", 256 , N_("import ownertrust values")}, - { aCheckTrustDB, "check-trustdb",0 , N_("|[NAMES]|check the trust database")}, + { aExportOwnerTrust, + "export-ownertrust", 256, N_("export the ownertrust values")}, + { aImportOwnerTrust, + "import-ownertrust", 256 , N_("import ownertrust values")}, + { aUpdateTrustDB, + "update-trustdb",0 , N_("|[NAMES]|update the trust database")}, + { aCheckTrustDB, + "check-trustdb",0 , N_("|[NAMES]|check the trust database")}, { aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")}, { aDeArmor, "dearmor", 256, N_("De-Armor a file or stdin") }, { aEnArmor, "enarmor", 256, N_("En-Armor a file or stdin") }, @@ -302,9 +306,9 @@ strusage( int level ) switch( level ) { case 11: p = #ifdef IS_G10MAINT - "gpgm (GNUPG)"; + "gpgm (GnuPG)"; #else - "gpg (GNUPG)"; + "gpg (GnuPG)"; #endif break; case 13: p = VERSION; break; @@ -323,7 +327,7 @@ strusage( int level ) case 41: p = #ifdef IS_G10MAINT _("Syntax: gpgm [options] [files]\n" - "GNUPG maintenance utility\n"); + "GnuPG maintenance utility\n"); #else _("Syntax: gpg [options] [files]\n" "sign, check, encrypt or decrypt\n" @@ -638,6 +642,7 @@ main( int argc, char **argv ) case aPrintMDs: set_cmd( &cmd, aPrintMDs); break; case aListTrustDB: set_cmd( &cmd, aListTrustDB); break; case aCheckTrustDB: set_cmd( &cmd, aCheckTrustDB); break; + case aUpdateTrustDB: set_cmd( &cmd, aUpdateTrustDB); break; case aFixTrustDB: set_cmd( &cmd, aFixTrustDB); break; case aListTrustPath: set_cmd( &cmd, aListTrustPath); break; case aDeArmor: set_cmd( &cmd, aDeArmor); break; @@ -692,10 +697,12 @@ main( int argc, char **argv ) case oCompressKeys: opt.compress_keys = 1; break; case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break; case oAlwaysTrust: opt.always_trust = 1; break; - case oLoadExtension: register_cipher_extension(pargs.r.ret_str); break; + case oLoadExtension: + register_cipher_extension(orig_argc? *orig_argv:NULL, + pargs.r.ret_str); + break; case oRFC1991: opt.rfc1991 = 1; opt.no_comment = 1; break; case oEmuChecksumBug: opt.emulate_bugs |= EMUBUG_GPGCHKSUM; break; - case oDoNotExportRSA: opt.do_not_export_rsa = 1; break; case oCompressSigs: opt.compress_sigs = 1; break; case oRunAsShmCP: #ifndef USE_SHM_COPROCESSING @@ -835,13 +842,13 @@ main( int argc, char **argv ) && !(cmd == aKMode && argc == 2 ) ) { if( !sec_nrings || default_keyring ) /* add default secret rings */ - add_secret_keyring("secring.gpg"); + add_keyblock_resource("secring.gpg", 0, 1); for(sl = sec_nrings; sl; sl = sl->next ) - add_secret_keyring( sl->d ); + add_keyblock_resource( sl->d, 0, 1 ); if( !nrings || default_keyring ) /* add default ring */ - add_keyring("pubring.gpg"); + add_keyblock_resource("pubring.gpg", 0, 0); for(sl = nrings; sl; sl = sl->next ) - add_keyring( sl->d ); + add_keyblock_resource( sl->d, 0, 0 ); } FREE_STRLIST(nrings); FREE_STRLIST(sec_nrings); @@ -996,7 +1003,7 @@ main( int argc, char **argv ) else { /* add keyring (default keyrings are not registered in this * special case */ - add_keyring( argv[1] ); + add_keyblock_resource( argv[1], 0, 0 ); public_key_list( **argv?1:0, argv ); } } @@ -1160,6 +1167,12 @@ main( int argc, char **argv ) } break; + case aUpdateTrustDB: + if( argc ) + wrong_args("--update-trustdb"); + update_trustdb(); + break; + case aCheckTrustDB: if( !argc ) check_trustdb(NULL); diff --git a/g10/getkey.c b/g10/getkey.c index 6e4c34592..90bd09a25 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -37,16 +37,15 @@ #define MAX_PK_CACHE_ENTRIES 50 #define MAX_UID_CACHE_ENTRIES 50 - -typedef struct enum_seckey_context { - int eof; - STRLIST sl; - IOBUF iobuf; -} enum_seckey_context_t; +static struct { + int any; + int okay_count; + int nokey_count; + int error_count; +} lkup_stats[21]; + -static STRLIST keyrings; -static STRLIST secret_keyrings; #if MAX_UNK_CACHE_ENTRIES typedef struct keyid_list { @@ -89,92 +88,24 @@ static int lookup( PKT_public_key *pk, static int lookup_sk( PKT_secret_key *sk, int mode, u32 *keyid, const char *name, int primary ); -/* note this function may be called before secure memory is - * available - * The first keyring which is added by this function is - * created if it does not exist. - */ -void -add_keyring( const char *name ) + + +static void +print_stats() { - STRLIST sl; - int rc, force = !keyrings; - - if( *name != '/' ) { /* do tilde expansion etc */ - char *p ; - - if( strchr(name, '/') ) - p = make_filename(name, NULL); - else - p = make_filename(opt.homedir, name, NULL); - sl = append_to_strlist( &keyrings, p ); - m_free(p); + int i; + for(i=0; i < DIM(lkup_stats); i++ ) { + if( lkup_stats[i].any ) + fprintf(stderr, + "lookup stats: mode=%-2d ok=%-6d nokey=%-6d err=%-6d\n", + i, + lkup_stats[i].okay_count, + lkup_stats[i].nokey_count, + lkup_stats[i].error_count ); } - else - sl = append_to_strlist( &keyrings, name ); - - /* fixme: We should remove much out of this module and - * combine it with the keyblock stuff from ringedit.c - * For now we will simple add the filename as keyblock resource - */ - rc = add_keyblock_resource( sl->d, force, 0 ); - if( rc ) - log_error("keyblock resource '%s': %s\n", sl->d, g10_errstr(rc) ); } -/**************** - * Get the name of the keyrings, start with a sequence number of 0. - */ -const char * -get_keyring( int sequence ) -{ - STRLIST sl; - - for(sl = keyrings; sl && sequence; sl = sl->next, sequence-- ) - ; - return sl? sl->d : NULL; -} - -const char * -get_secret_keyring( int sequence ) -{ - STRLIST sl; - - for(sl = secret_keyrings; sl && sequence; sl = sl->next, sequence-- ) - ; - return sl? sl->d : NULL; -} - - -void -add_secret_keyring( const char *name ) -{ - STRLIST sl; - int rc, force = !secret_keyrings; - - if( *name != '/' ) { /* do tilde expansion etc */ - char *p ; - - if( strchr(name, '/') ) - p = make_filename(name, NULL); - else - p = make_filename(opt.homedir, name, NULL); - sl = append_to_strlist( &secret_keyrings, p ); - m_free(p); - } - else - sl = append_to_strlist( &secret_keyrings, name ); - - /* fixme: We should remove much out of this module and - * combine it with the keyblock stuff from ringedit.c - * For now we will simple add the filename as keyblock resource - */ - rc = add_keyblock_resource( sl->d, force, 1 ); - if( rc ) - log_error("secret keyblock resource '%s': %s\n", sl->d, g10_errstr(rc)); -} - static void cache_public_key( PKT_public_key *pk ) @@ -690,7 +621,7 @@ merge_one_pk_and_selfsig( KBNODE keyblock, KBNODE knode ) */ const byte *p; p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL ); - pk->valid_days = p? ((buffer_to_u32(p)+86399L)/86400L):0; + pk->expiredate = p? buffer_to_u32(p):0; /* fixme: add usage etc. to pk */ break; } @@ -739,12 +670,12 @@ merge_keys_and_selfsig( KBNODE keyblock ) const byte *p; p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL ); if( pk ) { - pk->valid_days = p? ((buffer_to_u32(p)+86399L)/86400L):0; + pk->expiredate = p? buffer_to_u32(p):0; /* fixme: add usage etc. */ pk = NULL; /* use only the first self signature */ } else { - sk->valid_days = p? ((buffer_to_u32(p)+86399L)/86400L):0; + sk->expiredate = p? buffer_to_u32(p):0; sk = NULL; /* use only the first self signature */ } } @@ -756,7 +687,7 @@ merge_keys_and_selfsig( KBNODE keyblock ) /**************** - * Lookup a key by scanning all keyrings + * Lookup a key by scanning all keyresources * mode 1 = lookup by NAME (exact) * 2 = lookup by NAME (substring) * 3 = lookup by NAME (email address) @@ -949,6 +880,24 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid, enum_keyblocks( 2, &kbpos, &keyblock ); /* close */ release_kbnode( keyblock ); set_packet_list_mode(oldmode); + if( opt.debug & DBG_MEMSTAT_VALUE ) { + static int initialized; + + if( !initialized ) { + initialized = 1; + atexit( print_stats ); + } + + assert( mode < DIM(lkup_stats) ); + lkup_stats[mode].any = 1; + if( !rc ) + lkup_stats[mode].okay_count++; + else if ( rc == G10ERR_NO_PUBKEY ) + lkup_stats[mode].nokey_count++; + else + lkup_stats[mode].error_count++; + } + return rc; } @@ -1107,12 +1056,19 @@ enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys ) int rc=0; PACKET pkt; int save_mode; - enum_seckey_context_t *c = *context; + struct { + int eof; + int sequence; + const char *name; + IOBUF iobuf; + } *c = *context; + if( !c ) { /* make a new context */ c = m_alloc_clear( sizeof *c ); *context = c; - c->sl = secret_keyrings; + c->sequence = 0; + c->name = enum_keyblock_resources( &c->sequence, 1 ); } if( !sk ) { /* free the context */ @@ -1126,10 +1082,11 @@ enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys ) if( c->eof ) return -1; - for( ; c->sl; c->sl = c->sl->next ) { + /* FIXME: This assumes a plain keyring file */ + for( ; c->name; c->name = enum_keyblock_resources( &c->sequence, 1 ) ) { if( !c->iobuf ) { - if( !(c->iobuf = iobuf_open( c->sl->d ) ) ) { - log_error("enum_secret_keys: can't open '%s'\n", c->sl->d ); + if( !(c->iobuf = iobuf_open( c->name ) ) ) { + log_error("enum_secret_keys: can't open '%s'\n", c->name ); continue; /* try next file */ } } @@ -1165,7 +1122,7 @@ get_user_id_string( u32 *keyid ) user_id_db_t r; char *p; int pass=0; - /* try it two times; second pass reads from keyrings */ + /* try it two times; second pass reads from key resources */ do { for(r=user_id_db; r; r = r->next ) if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) { @@ -1185,7 +1142,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 keyrings */ + /* try it two times; second pass reads from key resources */ do { for(r=user_id_db; r; r = r->next ) if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) { diff --git a/g10/import.c b/g10/import.c index ccfbccaad..374843363 100644 --- a/g10/import.c +++ b/g10/import.c @@ -96,6 +96,7 @@ import_keys( const char *fname ) memset( &afx, 0, sizeof afx); memset( &cfx, 0, sizeof cfx); + afx.only_keyblocks = 1; /* open file */ inp = iobuf_open(fname); diff --git a/g10/keydb.h b/g10/keydb.h index c7fb26db1..efb371cec 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -106,10 +106,6 @@ void set_next_passphrase( const char *s ); char *get_last_passphrase(void); /*-- getkey.c --*/ -void add_keyring( const char *name ); -const char *get_keyring( int sequence ); -const char *get_secret_keyring( int sequence ); -void add_secret_keyring( const char *name ); int get_pubkey( PKT_public_key *pk, u32 *keyid ); int get_pubkey_byname( PKT_public_key *pk, const char *name ); int get_seckey( PKT_secret_key *sk, u32 *keyid ); @@ -156,7 +152,8 @@ int commit_kbnode( KBNODE *root ); void dump_kbnode( KBNODE node ); /*-- ringedit.c --*/ -int add_keyblock_resource( const char *filename, int force, int secret ); +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 ); int find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos ); diff --git a/g10/keygen.c b/g10/keygen.c index 3a7582013..9f1d8df9f 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -58,8 +58,8 @@ add_key_expire( PKT_signature *sig, void *opaque ) byte buf[8]; u32 u; - if( sk->valid_days ) { - u = sk->valid_days * 86400L; + if( sk->expiredate ) { + u = sk->expiredate; buf[0] = (u >> 24) & 0xff; buf[1] = (u >> 16) & 0xff; buf[2] = (u >> 8) & 0xff; @@ -192,7 +192,7 @@ write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *sk ) static int gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, u16 valid_days, + STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expiredate, int version ) { int rc; @@ -214,7 +214,9 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, pk = m_alloc_clear( sizeof *pk ); sk->timestamp = pk->timestamp = make_timestamp(); sk->version = pk->version = version; - sk->valid_days = pk->valid_days = valid_days; + if( expiredate && expiredate < sk->timestamp ) + expiredate = sk->timestamp; /* key generatio may take long */ + sk->expiredate = pk->expiredate = expiredate; sk->pubkey_algo = pk->pubkey_algo = algo; pk->pkey[0] = mpi_copy( skey[0] ); pk->pkey[1] = mpi_copy( skey[1] ); @@ -266,7 +268,7 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, */ static int gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, u16 valid_days ) + STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expiredate ) { int rc; int i; @@ -289,7 +291,9 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, pk = m_alloc_clear( sizeof *pk ); sk->timestamp = pk->timestamp = make_timestamp(); sk->version = pk->version = 4; - sk->valid_days = pk->valid_days = valid_days; + if( expiredate && expiredate < pk->timestamp ) + expiredate = pk->timestamp; /* key generation may take long */ + sk->expiredate = pk->expiredate = expiredate; sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA; pk->pkey[0] = mpi_copy( skey[0] ); pk->pkey[1] = mpi_copy( skey[1] ); @@ -477,11 +481,12 @@ ask_keysize( int algo ) } -static int -ask_valid_days() +static u32 +ask_expiredate() { char *answer; int valid_days=0; + u32 expiredate = 0; tty_printf(_("Please specify how long the key should be valid.\n" " 0 = key does not expire\n" @@ -513,12 +518,14 @@ ask_valid_days() continue; } - if( !valid_days ) + if( !valid_days ) { tty_printf(_("Key does not expire at all\n")); + expiredate = 0; + } else { + expiredate = make_timestamp() + valid_days * 86400L; /* print the date when the key expires */ - tty_printf(_("Key expires at %s\n"), strtimestamp( - add_days_to_timestamp( make_timestamp(), valid_days ))); + tty_printf(_("Key expires at %s\n"), asctimestamp(expiredate) ); } if( !cpr_enabled() @@ -527,7 +534,7 @@ ask_valid_days() break; } m_free(answer); - return valid_days; + return expiredate; } @@ -713,7 +720,7 @@ ask_passphrase( STRING2KEY **ret_s2k ) static int do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, - DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, int valid_days, + DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, u32 expiredate, int v4_packet ) { int rc=0; @@ -726,11 +733,13 @@ do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, if( algo == PUBKEY_ALGO_ELGAMAL || algo == PUBKEY_ALGO_ELGAMAL_E ) rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k, - sk, valid_days, v4_packet? 4:3 ); + sk, expiredate, v4_packet? 4:3 ); else if( algo == PUBKEY_ALGO_DSA ) - rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, valid_days); + rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, expiredate); else BUG(); + + #ifdef ENABLE_COMMENT_PACKETS if( !rc ) { add_kbnode( pub_root, make_comment_node("#created by GNUPG v" VERSION " (" @@ -739,6 +748,7 @@ do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, make_comment_node("#created by GNUPG v" VERSION " (" PRINTABLE_OS_NAME ")")); } + #endif return rc; } @@ -781,7 +791,7 @@ generate_keypair() STRING2KEY *s2k; int rc; int algo; - int ndays; + u32 expiredate; int v4; int both = 0; @@ -797,7 +807,7 @@ generate_keypair() tty_printf(_("DSA keypair will have 1024 bits.\n")); } nbits = ask_keysize( algo ); - ndays = ask_valid_days(); + expiredate = ask_expiredate(); uid = ask_user_id(0); if( !uid ) { log_error(_("Key generation cancelled.\n")); @@ -824,10 +834,10 @@ generate_keypair() if( both ) rc = do_create( PUBKEY_ALGO_DSA, 1024, pub_root, sec_root, - dek, s2k, &sk, ndays, 1); + dek, s2k, &sk, expiredate, 1); else rc = do_create( algo, nbits, pub_root, sec_root, - dek, s2k, &sk, ndays, v4); + dek, s2k, &sk, expiredate, v4); if( !rc ) write_uid(pub_root, uid ); if( !rc ) @@ -839,7 +849,7 @@ generate_keypair() if( both ) { rc = do_create( algo, nbits, pub_root, sec_root, - dek, s2k, NULL, ndays, 1 ); + dek, s2k, NULL, expiredate, 1 ); if( !rc ) rc = write_keybinding(pub_root, pub_root, sk); if( !rc ) @@ -927,7 +937,8 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) int okay=0, rc=0; KBNODE node; PKT_secret_key *sk = NULL; /* this is the primary sk */ - int v4, algo, ndays; + int v4, algo; + u32 expiredate; unsigned nbits; char *passphrase = NULL; DEK *dek = NULL; @@ -964,7 +975,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) algo = ask_algo( &v4, 1 ); assert(algo); nbits = ask_keysize( algo ); - ndays = ask_valid_days(); + expiredate = ask_expiredate(); if( !cpr_enabled() && !cpr_get_answer_is_yes(N_("keygen.sub.okay"), _("Really create? ") ) ) goto leave; @@ -978,7 +989,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) } rc = do_create( algo, nbits, pub_keyblock, sec_keyblock, - dek, s2k, NULL, ndays, v4 ); + dek, s2k, NULL, expiredate, v4 ); if( !rc ) rc = write_keybinding(pub_keyblock, pub_keyblock, sk); if( !rc ) diff --git a/g10/keyid.c b/g10/keyid.c index 387c3fa9a..fa5b9237e 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -82,7 +82,12 @@ do_fingerprint_md( PKT_public_key *pk ) md_putc( md, a ); } if( pk->version < 4 ) { - u16 a = pk->valid_days; + u16 a; + + if( pk->expiredate ) + a = (u16)((pk->expiredate - pk->timestamp) / 86400L); + else + a = 0; md_putc( md, a >> 8 ); md_putc( md, a ); } @@ -108,7 +113,7 @@ do_fingerprint_md_sk( PKT_secret_key *sk ) pk.pubkey_algo = sk->pubkey_algo; pk.version = sk->version; pk.timestamp = sk->timestamp; - pk.valid_days = sk->valid_days; + pk.expiredate = sk->expiredate; pk.pubkey_algo = sk->pubkey_algo; for( i=0; i < npkey; i++ ) pk.pkey[i] = sk->skey[i]; @@ -303,9 +308,9 @@ expirestr_from_pk( PKT_public_key *pk ) struct tm *tp; time_t atime; - if( !pk->valid_days ) + if( !pk->expiredate ) return "never "; - atime = add_days_to_timestamp( pk->timestamp, pk->valid_days ); + atime = pk->expiredate; tp = gmtime( &atime ); sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday ); return buffer; @@ -318,9 +323,9 @@ expirestr_from_sk( PKT_secret_key *sk ) struct tm *tp; time_t atime; - if( !sk->valid_days ) + if( !sk->expiredate ) return "never "; - atime = add_days_to_timestamp( sk->timestamp, sk->valid_days ); + atime = sk->expiredate; tp = gmtime( &atime ); sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday ); return buffer; diff --git a/g10/keylist.c b/g10/keylist.c index 04d79b1ec..69e9b523b 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -74,7 +74,8 @@ list_all( int secret ) const char *s; IOBUF a; - while( (s=secret? get_secret_keyring(seq++):get_keyring(seq++)) ) { + /* FIXME: this assumes a keyring resource is a plain keyring file */ + while( (s = enum_keyblock_resources( &seq, secret )) ) { if( !(a = iobuf_open(s)) ) { log_error(_("can't open %s: %s\n"), s, strerror(errno)); continue; @@ -133,12 +134,12 @@ list_one( const char *name, int secret ) sk = node->pkt->pkt.secret_key; keyid_from_sk( sk, keyid ); if( opt.with_colons ) - printf("sec::%u:%d:%08lX%08lX:%s:%u:::", + printf("sec::%u:%d:%08lX%08lX:%s:%s:::", nbits_from_sk( sk ), sk->pubkey_algo, (ulong)keyid[0],(ulong)keyid[1], datestr_from_sk( sk ), - (unsigned)sk->valid_days + sk->expiredate? strtimestamp(sk->expiredate):"" /* fixme: add LID here */ ); else printf("sec %4u%c/%08lX %s ", nbits_from_sk( sk ), @@ -152,13 +153,14 @@ list_one( const char *name, int secret ) keyid_from_pk( pk, keyid ); if( opt.with_colons ) { trustletter = query_trust_info( pk ); - printf("pub:%c:%u:%d:%08lX%08lX:%s:%u:", + printf("pub:%c:%u:%d:%08lX%08lX:%s:%s:", trustletter, nbits_from_pk( pk ), pk->pubkey_algo, (ulong)keyid[0],(ulong)keyid[1], datestr_from_pk( pk ), - (unsigned)pk->valid_days ); + pk->expiredate? strtimestamp(pk->expiredate):"" + ); if( pk->local_id ) printf("%lu", pk->local_id ); putchar(':'); @@ -206,13 +208,13 @@ list_one( const char *name, int secret ) keyid_from_pk( pk2, keyid2 ); if( opt.with_colons ) { - printf("sub:%c:%u:%d:%08lX%08lX:%s:%u:", + printf("sub:%c:%u:%d:%08lX%08lX:%s:%s:", trustletter, nbits_from_pk( pk2 ), pk2->pubkey_algo, (ulong)keyid2[0],(ulong)keyid2[1], datestr_from_pk( pk2 ), - (unsigned)pk2->valid_days + pk2->expiredate? strtimestamp(pk2->expiredate):"" /* fixme: add LID and ownertrust here */ ); if( pk->local_id ) /* use the local_id of the main key??? */ @@ -242,12 +244,12 @@ list_one( const char *name, int secret ) keyid_from_sk( sk2, keyid2 ); if( opt.with_colons ) - printf("ssb::%u:%d:%08lX%08lX:%s:%u:::\n", + printf("ssb::%u:%d:%08lX%08lX:%s:%s:::\n", nbits_from_sk( sk2 ), sk2->pubkey_algo, (ulong)keyid2[0],(ulong)keyid2[1], datestr_from_sk( sk2 ), - (unsigned)sk2->valid_days + sk2->expiredate? strtimestamp(sk2->expiredate):"" /* fixme: add LID */ ); else diff --git a/g10/mainproc.c b/g10/mainproc.c index a47885b74..dd1546c6b 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -471,14 +471,14 @@ list_node( CTX c, KBNODE node ) c->local_id = pk->local_id; c->trustletter = query_trust_info( pk ); } - printf("%s:%c:%u:%d:%08lX%08lX:%s:%u:", + printf("%s:%c:%u:%d:%08lX%08lX:%s:%s:", mainkey? "pub":"sub", c->trustletter, nbits_from_pk( pk ), pk->pubkey_algo, (ulong)keyid[0],(ulong)keyid[1], datestr_from_pk( pk ), - (unsigned)pk->valid_days ); + pk->expiredate? strtimestamp(pk->expiredate):"" ); if( c->local_id ) printf("%lu", c->local_id ); putchar(':'); @@ -541,13 +541,13 @@ list_node( CTX c, KBNODE node ) if( opt.with_colons ) { u32 keyid[2]; keyid_from_sk( sk, keyid ); - printf("%s::%u:%d:%08lX%08lX:%s:%u:::", + printf("%s::%u:%d:%08lX%08lX:%s:%s:::", mainkey? "sec":"ssb", nbits_from_sk( sk ), sk->pubkey_algo, (ulong)keyid[0],(ulong)keyid[1], datestr_from_sk( sk ), - (unsigned)sk->valid_days + sk->expiredate? strtimestamp(sk->expiredate):"" /* fixme: add LID */ ); } else diff --git a/g10/options.h b/g10/options.h index d674ada12..ac7629631 100644 --- a/g10/options.h +++ b/g10/options.h @@ -20,6 +20,10 @@ #ifndef G10_OPTIONS_H #define G10_OPTIONS_H + +#undef ENABLE_COMMENT_PACKETS /* don't create comment packets */ + + struct { int verbose; unsigned debug; @@ -37,7 +41,7 @@ struct { int no_armor; int list_packets; /* list-packets mode */ int def_cipher_algo; - int do_not_export_rsa; + int reserved1; int def_digest_algo; int def_compress_algo; const char *def_secret_key; diff --git a/g10/packet.h b/g10/packet.h index 5bb383c86..4898027a2 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -111,7 +111,7 @@ typedef struct { */ typedef struct { u32 timestamp; /* key made */ - u16 valid_days; /* valid for this number of days */ + u32 expiredate; /* expires at this date or 0 if not at all */ byte hdrbytes; /* number of header bytes */ byte version; byte pubkey_algo; /* algorithm used for public key scheme */ @@ -124,7 +124,7 @@ typedef struct { typedef struct { u32 timestamp; /* key made */ - u16 valid_days; /* valid for this number of days */ + u32 expiredate; /* expires at this date or 0 if not at all */ byte hdrbytes; /* number of header bytes */ byte version; byte pubkey_algo; /* algorithm used for public key scheme */ diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 41afe5b9a..c17f2c5c9 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -917,8 +917,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, { int i, version, algorithm; unsigned n; - unsigned long timestamp; - unsigned short valid_period; + unsigned long timestamp, expiredate; int npkey, nskey; int is_v4=0; int rc=0; @@ -956,25 +955,30 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, timestamp = read_32(inp); pktlen -= 4; if( is_v4 ) - valid_period = 0; + expiredate = 0; /* have to get it from the selfsignature */ else { - valid_period = read_16(inp); pktlen -= 2; + unsigned short ndays; + ndays = read_16(inp); pktlen -= 2; + if( ndays ) + expiredate = timestamp + ndays * 86400L; + else + expiredate = 0; } algorithm = iobuf_get_noeof(inp); pktlen--; if( list_mode ) printf(":%s key packet:\n" - "\tversion %d, algo %d, created %lu, valid for %hu days\n", + "\tversion %d, algo %d, created %lu, expires %lu\n", pkttype == PKT_PUBLIC_KEY? "public" : pkttype == PKT_SECRET_KEY? "secret" : pkttype == PKT_PUBLIC_SUBKEY? "public sub" : pkttype == PKT_SECRET_SUBKEY? "secret sub" : "??", - version, algorithm, timestamp, valid_period ); + version, algorithm, timestamp, expiredate ); if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) { PKT_secret_key *sk = pkt->pkt.secret_key; sk->timestamp = timestamp; - sk->valid_days = valid_period; + sk->expiredate = expiredate; sk->hdrbytes = hdrlen; sk->version = version; sk->pubkey_algo = algorithm; @@ -984,7 +988,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, PKT_public_key *pk = pkt->pkt.public_key; pk->timestamp = timestamp; - pk->valid_days = valid_period; + pk->expiredate = expiredate; pk->hdrbytes = hdrlen; pk->version = version; pk->pubkey_algo = algorithm; diff --git a/g10/ringedit.c b/g10/ringedit.c index 677420e25..6b6f6c855 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -48,6 +48,7 @@ #include #include #include +#include /* for truncate */ #include #include "util.h" #include "packet.h" @@ -55,8 +56,8 @@ #include "mpi.h" #include "iobuf.h" #include "keydb.h" +#include "options.h" #include "i18n.h" -#include /* for truncate */ struct resource_table_struct { @@ -96,30 +97,76 @@ check_pos( KBPOS *kbpos ) ****************** public functions **************************** ****************************************************************/ +/**************** + * Get the name of the keyrings, start with a sequence number pointing to a 0. + */ +const char * +enum_keyblock_resources( int *sequence, int secret ) +{ + int i = *sequence; + const char *name = NULL; + + for(; i < MAX_RESOURCES; i++ ) + if( resource_table[i].used && !resource_table[i].secret == !secret ) { + if( resource_table[i].fname ) { + name = resource_table[i].fname; + break; + } + } + *sequence = ++i; + return NULL; /* not found */ +} + + + /**************** * Register a resource (which currently may only be a keyring file). + * The first keyring which is added by this function is + * created if it does not exist. + * Note: this function may be called before secure memory is + * available. */ int -add_keyblock_resource( const char *filename, int force, int secret ) +add_keyblock_resource( const char *resname, int force, int secret ) { + static int any_secret, any_public; IOBUF iobuf; - int i; + int i, force; + char *filename; + int rc = 0; + + if( *resname != '/' ) { /* do tilde expansion etc */ + if( strchr(resname, '/') ) + filename = make_filename(resname, NULL); + else + filename = make_filename(opt.homedir, resname, NULL); + } + else + filename = m_strdup( resname ); + + if( !force ) + force = secret? !any_secret : !any_public; for(i=0; i < MAX_RESOURCES; i++ ) if( !resource_table[i].used ) break; - if( i == MAX_RESOURCES ) - return G10ERR_RESOURCE_LIMIT; + if( i == MAX_RESOURCES ) { + rc = G10ERR_RESOURCE_LIMIT; + goto leave; + } - iobuf = iobuf_open( filename ); - if( !iobuf && !force ) - return G10ERR_OPEN_FILE; + iobuf = iobuf_fopen( filename, "rb" ); + if( !iobuf && !force ) { + rc = G10ERR_OPEN_FILE; + goto leave; + } if( !iobuf ) { iobuf = iobuf_create( filename ); if( !iobuf ) { log_error("%s: can't create: %s\n", filename, strerror(errno)); - return G10ERR_OPEN_FILE; + rc = G10ERR_OPEN_FILE; + goto leave; } else log_info("%s: keyring created\n", filename ); @@ -135,7 +182,15 @@ add_keyblock_resource( const char *filename, int force, int secret ) resource_table[i].secret = !!secret; resource_table[i].fname = m_strdup(filename); resource_table[i].iobuf = iobuf; - return 0; + leave: + if( rc ) + log_error("keyblock resource '%s': %s\n", filename, g10_errstr(rc) ); + else if( secret ) + any_secret = 1; + else + any_public = 1; + m_free( filename ); + return rc; } /**************** @@ -362,7 +417,7 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root ) return -1; /* no resources */ kbpos->resno = i; rentry = check_pos( kbpos ); - kbpos->fp = iobuf_open( rentry->fname ); + kbpos->fp = iobuf_fopen( rentry->fname, "rb" ); if( !kbpos->fp ) { log_error("can't open '%s'\n", rentry->fname ); return G10ERR_OPEN_FILE; @@ -528,7 +583,6 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) PKT_secret_key *sk = pkt.pkt.secret_key; if( req_sk->timestamp == sk->timestamp - && req_sk->valid_days == sk->valid_days && req_sk->pubkey_algo == sk->pubkey_algo && !cmp_seckey( req_sk, sk) ) break; /* found */ @@ -537,7 +591,6 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) PKT_public_key *pk = pkt.pkt.public_key; if( req_pk->timestamp == pk->timestamp - && req_pk->valid_days == pk->valid_days && req_pk->pubkey_algo == pk->pubkey_algo && !cmp_pubkey( req_pk, pk ) ) break; /* found */ @@ -572,7 +625,7 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root ) if( !(rentry=check_pos(kbpos)) ) return G10ERR_GENERAL; - a = iobuf_open( rentry->fname ); + a = iobuf_fopen( rentry->fname, "rb" ); if( !a ) { log_error("can't open '%s'\n", rentry->fname ); return G10ERR_OPEN_FILE; @@ -732,7 +785,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root ) BUG(); /* not allowed with such a handle */ /* open the source file */ - fp = iobuf_open( rentry->fname ); + fp = iobuf_fopen( rentry->fname, "rb" ); if( mode == 1 && !fp && errno == ENOENT ) { /* no file yet */ KBNODE kbctx, node; diff --git a/g10/sig-check.c b/g10/sig-check.c index b983bb42c..fd476f767 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -166,11 +166,9 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest ) return G10ERR_TIME_CONFLICT; } - if( pk->valid_days && add_days_to_timestamp(pk->timestamp, - pk->valid_days) < cur_time ) { - log_info(_("warning: signature key expired %s\n"), strtimestamp( - add_days_to_timestamp(pk->timestamp, - pk->valid_days))); + if( pk->expiredate && pk->expiredate < cur_time ) { + log_info(_("warning: signature key expired %s\n"), + asctimestamp( pk->expiredate ) ); write_status(STATUS_SIGEXPIRED); } diff --git a/g10/sign.c b/g10/sign.c index 349b2f34d..304843f59 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -225,12 +225,14 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, if( opt.armor && !outfile ) iobuf_push_filter( out, armor_filter, &afx ); + #ifdef ENABLE_COMMENT_PACKETS else { write_comment( out, "#created by GNUPG v" VERSION " (" PRINTABLE_OS_NAME ")"); if( opt.comment_string ) write_comment( out, opt.comment_string ); } + #endif if( encrypt ) { efx.pk_list = pk_list; /* fixme: set efx.cfx.datalen if known */ diff --git a/g10/tdbio.c b/g10/tdbio.c index 82b22b43a..425919338 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -39,6 +39,27 @@ #include "trustdb.h" #include "tdbio.h" + +/**************** + * Yes, this is a very simple implementation. We should really + * use a page aligned buffer and read complete pages. + * To implement a simple trannsaction system, this is sufficient. + */ +typedef struct cache_ctrl_struct *CACHE_CTRL; +struct cache_ctrl_struct { + CACHE_CTRL next; + struct { + unsigned used:1; + unsigned dirty:1; + } flags; + ulong recno; + char data[TRUST_RECORD_LEN]; +}; + +#define MAX_CACHE_ENTRIES 200 +static CACHE_CTRL cache_list; +static int cache_entries; + /* a type used to pass infomation to cmp_krec_fpr */ struct cmp_krec_fpr_struct { int pubkey_algo; @@ -59,6 +80,184 @@ static int db_fd = -1; static void open_db(void); + +/************************************* + ************* record cache ********** + *************************************/ + +/**************** + * Get the data from therecord cache and return a + * pointer into that cache. Caller should copy + * the return data. NULL is returned on a cache miss. + */ +static const char * +get_record_from_cache( ulong recno ) +{ + CACHE_CTRL r; + + for( r = cache_list; r; r = r->next ) { + if( r->flags.used && r->recno == recno ) + return r->data; + } + return NULL; +} + + +static int +write_cache_item( CACHE_CTRL r ) +{ + int n; + + if( lseek( db_fd, r->recno * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { + log_error(_("trustdb rec %lu: lseek failed: %s\n"), + r->recno, strerror(errno) ); + return G10ERR_WRITE_FILE; + } + n = write( db_fd, r->data, TRUST_RECORD_LEN); + if( n != TRUST_RECORD_LEN ) { + log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"), + r->recno, n, strerror(errno) ); + return G10ERR_WRITE_FILE; + } + r->flags.dirty = 0; + return 0; +} + +/**************** + * Put data into the cache. This function may flush the + * some cache entries if there is not enough space available. + */ +int +put_record_into_cache( ulong recno, const char *data ) +{ + CACHE_CTRL r, unused; + int dirty_count = 0; + int clean_count = 0; + + /* see whether we already cached this one */ + for( unused = NULL, r = cache_list; r; r = r->next ) { + if( !r->flags.used ) { + if( !unused ) + unused = r; + } + else if( r->recno == recno ) { + if( !r->flags.dirty ) { + /* Hmmm: should we use a a copy and compare? */ + if( memcmp(r->data, data, TRUST_RECORD_LEN ) ) + r->flags.dirty = 1; + } + memcpy( r->data, data, TRUST_RECORD_LEN ); + return 0; + } + if( r->flags.used ) { + if( r->flags.dirty ) + dirty_count++; + else + clean_count++; + } + } + /* not in the cache: add a new entry */ + if( unused ) { /* reuse this entry */ + r = unused; + r->flags.used = 1; + r->recno = recno; + memcpy( r->data, data, TRUST_RECORD_LEN ); + r->flags.dirty = 1; + cache_entries++; + return 0; + } + /* see whether we reached the limit */ + if( cache_entries < MAX_CACHE_ENTRIES ) { /* no */ + r = m_alloc( sizeof *r ); + r->flags.used = 1; + r->recno = recno; + memcpy( r->data, data, TRUST_RECORD_LEN ); + r->flags.dirty = 1; + r->next = cache_list; + cache_list = r; + cache_entries++; + return 0; + } + /* cache is full: discard some clean entries */ + if( clean_count ) { + int n = clean_count / 3; /* discard a third of the clean entries */ + if( !n ) + n = 1; + for( unused = NULL, r = cache_list; r; r = r->next ) { + if( r->flags.used && !r->flags.dirty ) { + if( !unused ) + unused = r; + r->flags.used = 0; + cache_entries--; + if( !--n ) + break; + } + } + assert( unused ); + r = unused; + r->flags.used = 1; + r->recno = recno; + memcpy( r->data, data, TRUST_RECORD_LEN ); + r->flags.dirty = 1; + cache_entries++; + return 0; + } + /* no clean entries: have to flush some dirty entries */ + if( dirty_count ) { + int n = dirty_count / 5; /* discard some dirty entries */ + if( !n ) + n = 1; + for( unused = NULL, r = cache_list; r; r = r->next ) { + if( r->flags.used && r->flags.dirty ) { + int rc = write_cache_item( r ); + if( rc ) + return rc; + if( !unused ) + unused = r; + r->flags.used = 0; + cache_entries--; + if( !--n ) + break; + } + } + assert( unused ); + r = unused; + r->flags.used = 1; + r->recno = recno; + memcpy( r->data, data, TRUST_RECORD_LEN ); + r->flags.dirty = 1; + cache_entries++; + return 0; + } + BUG(); +} + + + +/**************** + * Sync the cache to disk + */ + +int +tdbio_sync() +{ + CACHE_CTRL r; + + for( r = cache_list; r; r = r->next ) { + if( r->flags.used && r->flags.dirty ) { + int rc = write_cache_item( r ); + if( rc ) + return rc; + } + } + return 0; +} + + + +/******************************************************** + **************** cached I/O functions ****************** + ********************************************************/ int tdbio_set_dbname( const char *new_dbname, int create ) @@ -118,6 +317,8 @@ tdbio_set_dbname( const char *new_dbname, int create ) rec.rectype = RECTYPE_VER; rec.recnum = 0; rc = tdbio_write_record( &rec ); + if( !rc ) + tdbio_sync(); if( rc ) log_fatal_f( fname, _("failed to create version record: %s"), g10_errstr(rc)); @@ -185,7 +386,7 @@ create_hashtable( TRUSTREC *vr, int type ) n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD; for(i=0; i < n; i++, recnum++ ) { memset( &rec, 0, sizeof rec ); - rec.rectype = RECTYPE_HTBL; /* free record */ + rec.rectype = RECTYPE_HTBL; rec.recnum = recnum; rc = tdbio_write_record( &rec ); if( rc ) @@ -194,6 +395,8 @@ create_hashtable( TRUSTREC *vr, int type ) } /* update the version record */ rc = tdbio_write_record( vr ); + if( !rc ) + rc = tdbio_sync(); if( rc ) log_fatal_f( db_name, _("error updating version record: %s\n"), g10_errstr(rc)); @@ -208,21 +411,21 @@ static ulong get_keyhashrec() { static ulong keyhashtbl; /* record number of the key hashtable */ - TRUSTREC vr; - int rc; - if( keyhashtbl ) - return keyhashtbl; + if( !keyhashtbl ) { + TRUSTREC vr; + int rc; - rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); - if( rc ) - log_fatal_f( db_name, _("error reading version record: %s\n"), - g10_errstr(rc) ); - if( !vr.r.ver.keyhashtbl ) - create_hashtable( &vr, 0 ); + rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); + if( rc ) + log_fatal_f( db_name, _("error reading version record: %s\n"), + g10_errstr(rc) ); + if( !vr.r.ver.keyhashtbl ) + create_hashtable( &vr, 0 ); - - return vr.r.ver.keyhashtbl; + keyhashtbl = vr.r.ver.keyhashtbl; + } + return keyhashtbl; } /**************** @@ -233,20 +436,21 @@ static ulong get_sdirhashrec() { static ulong sdirhashtbl; /* record number of the hashtable */ - TRUSTREC vr; - int rc; - if( sdirhashtbl ) - return sdirhashtbl; + if( !sdirhashtbl ) { + TRUSTREC vr; + int rc; - rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); - if( rc ) - log_fatal_f( db_name, _("error reading version record: %s\n"), - g10_errstr(rc) ); - if( !vr.r.ver.sdirhashtbl ) - create_hashtable( &vr, 1 ); + rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); + if( rc ) + log_fatal_f( db_name, _("error reading version record: %s\n"), + g10_errstr(rc) ); + if( !vr.r.ver.sdirhashtbl ) + create_hashtable( &vr, 1 ); - return vr.r.ver.sdirhashtbl; + sdirhashtbl = vr.r.ver.sdirhashtbl; + } + return sdirhashtbl; } @@ -289,15 +493,16 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) lastrec = rec; rc = tdbio_read_record( item, &rec, 0 ); if( rc ) { - log_error( db_name, "upd_hashtable: read item failed: %s\n", + log_error( "upd_hashtable: read item failed: %s\n", g10_errstr(rc) ); return rc; } + if( rec.rectype == RECTYPE_HTBL ) { hashrec = item; level++; if( level >= keylen ) { - log_error( db_name, "hashtable has invalid indirections.\n"); + log_error( "hashtable has invalid indirections.\n"); return G10ERR_TRUSTDB; } goto next_level; @@ -314,8 +519,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_read_record( rec.r.hlst.next, &rec, RECTYPE_HLST); if( rc ) { - log_error( db_name, - "scan keyhashtbl read hlst failed: %s\n", + log_error( "scan keyhashtbl read hlst failed: %s\n", g10_errstr(rc) ); return rc; } @@ -330,8 +534,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rec.r.hlst.rnum[i] = newrecnum; rc = tdbio_write_record( &rec ); if( rc ) - log_error( db_name, - "upd_hashtable: write hlst failed: %s\n", + log_error( "upd_hashtable: write hlst failed: %s\n", g10_errstr(rc) ); return rc; /* done */ } @@ -340,8 +543,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_read_record( rec.r.hlst.next, &rec, RECTYPE_HLST ); if( rc ) { - log_error( db_name, - "upd_hashtable: read hlst failed: %s\n", + log_error( "upd_hashtable: read hlst failed: %s\n", g10_errstr(rc) ); return rc; } @@ -350,8 +552,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rec.r.hlst.next = item = tdbio_new_recnum(); rc = tdbio_write_record( &rec ); if( rc ) { - log_error( db_name, - "upd_hashtable: write hlst failed: %s\n", + log_error( "upd_hashtable: write hlst failed: %s\n", g10_errstr(rc) ); return rc; } @@ -361,14 +562,14 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rec.r.hlst.rnum[0] = newrecnum; rc = tdbio_write_record( &rec ); if( rc ) - log_error( db_name, - "upd_hashtable: write ext hlst failed: %s\n", + log_error( "upd_hashtable: write ext hlst failed: %s\n", g10_errstr(rc) ); return rc; /* done */ } } /* end loop over hlst slots */ } else if( rec.rectype == RECTYPE_KEY + || rec.rectype == RECTYPE_DIR || rec.rectype == RECTYPE_SDIR ) { /* insert a list record */ if( rec.recnum == newrecnum ) { return 0; @@ -381,8 +582,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rec.r.hlst.rnum[1] = newrecnum; /* and new one */ rc = tdbio_write_record( &rec ); if( rc ) { - log_error( db_name, - "upd_hashtable: write new hlst failed: %s\n", + log_error( "upd_hashtable: write new hlst failed: %s\n", g10_errstr(rc) ); return rc; } @@ -390,12 +590,12 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum; rc = tdbio_write_record( &lastrec ); if( rc ) - log_error( db_name, "upd_hashtable: update htbl failed: %s\n", + log_error( "upd_hashtable: update htbl failed: %s\n", g10_errstr(rc) ); return rc; /* ready */ } else { - log_error( db_name, "hashtbl %lu points to an invalid record\n", + log_error( "hashtbl %lu points to an invalid record\n", item); return G10ERR_TRUSTDB; } @@ -637,23 +837,29 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp ) int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) { - byte buf[TRUST_RECORD_LEN], *p; + byte readbuf[TRUST_RECORD_LEN]; + const byte *buf, *p; int rc = 0; int n, i; if( db_fd == -1 ) open_db(); - if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { - log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) ); - return G10ERR_READ_FILE; - } - n = read( db_fd, buf, TRUST_RECORD_LEN); - if( !n ) { - return -1; /* eof */ - } - else if( n != TRUST_RECORD_LEN ) { - log_error(_("trustdb: read failed (n=%d): %s\n"), n, strerror(errno) ); - return G10ERR_READ_FILE; + buf = get_record_from_cache( recnum ); + if( !buf ) { + if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { + log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) ); + return G10ERR_READ_FILE; + } + n = read( db_fd, readbuf, TRUST_RECORD_LEN); + if( !n ) { + return -1; /* eof */ + } + else if( n != TRUST_RECORD_LEN ) { + log_error(_("trustdb: read failed (n=%d): %s\n"), n, + strerror(errno) ); + return G10ERR_READ_FILE; + } + buf = readbuf; } rec->recnum = recnum; rec->dirty = 0; @@ -791,14 +997,12 @@ tdbio_write_record( TRUSTREC *rec ) { byte buf[TRUST_RECORD_LEN], *p; int rc = 0; - int i, n; + int i; ulong recnum = rec->recnum; if( db_fd == -1 ) open_db(); -tdbio_dump_record( rec, stdout ); - memset(buf, 0, TRUST_RECORD_LEN); p = buf; *p++ = rec->rectype; p++; @@ -900,16 +1104,10 @@ tdbio_dump_record( rec, stdout ); BUG(); } - if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { - log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) ); - return G10ERR_WRITE_FILE; - } - n = write( db_fd, buf, TRUST_RECORD_LEN); - if( n != TRUST_RECORD_LEN ) { - log_error(_("trustdb: write failed (n=%d): %s\n"), n, strerror(errno) ); - return G10ERR_WRITE_FILE; - } - else if( rec->rectype == RECTYPE_KEY ) + rc = put_record_into_cache( recnum, buf ); + if( rc ) + ; + if( rec->rectype == RECTYPE_KEY ) rc = update_keyhashtbl( rec ); else if( rec->rectype == RECTYPE_SDIR ) rc = update_sdirhashtbl( rec ); @@ -990,7 +1188,21 @@ tdbio_new_recnum() memset( &rec, 0, sizeof rec ); rec.rectype = 0; /* unused record */ rec.recnum = recnum; - rc = tdbio_write_record( &rec ); + rc = 0; + if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { + log_error(_("trustdb rec %lu: lseek failed: %s\n"), + recnum, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + } + else { + int n = write( db_fd, &rec, TRUST_RECORD_LEN); + if( n != TRUST_RECORD_LEN ) { + log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"), + recnum, n, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + } + } + if( rc ) log_fatal_f(db_name,_("failed to append a record: %s\n"), g10_errstr(rc)); diff --git a/g10/tdbio.h b/g10/tdbio.h index 66579ad14..42bb4aa48 100644 --- a/g10/tdbio.h +++ b/g10/tdbio.h @@ -166,6 +166,7 @@ const char *tdbio_get_dbname(void); void tdbio_dump_record( TRUSTREC *rec, FILE *fp ); int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ); int tdbio_write_record( TRUSTREC *rec ); +int tdbio_sync(void); int tdbio_delete_record( ulong recnum ); ulong tdbio_new_recnum(void); int tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec ); diff --git a/g10/textfilter.c b/g10/textfilter.c index 804b48505..fc81a9136 100644 --- a/g10/textfilter.c +++ b/g10/textfilter.c @@ -48,7 +48,7 @@ read_line( byte *buf, size_t *r_buflen, IOBUF a ) assert(buflen >= 20 ); buflen -= 3; /* leave some room for CR,LF and one extra */ - for(c=0, n=0; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; ) + for(c=0, n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; ) buf[n++] = c; buf[n] = 0; if( c == -1 ) { @@ -58,7 +58,7 @@ read_line( byte *buf, size_t *r_buflen, IOBUF a ) } else if( c != '\n' ) { IOBUF b = iobuf_temp(); - while( (c=iobuf_get2(a)) != -1 && c != '\n' ) { + while( (c=iobuf_get(a)) != -1 && c != '\n' ) { iobuf_put(b,c); if( c != ' ' && c != '\t' && c != '\r' ) break; diff --git a/g10/trustdb.c b/g10/trustdb.c index 18726f151..eb6ea3ca6 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -71,11 +71,6 @@ struct trust_seg_list { }; -typedef struct { - TRUST_SEG_LIST tsl; - int index; -} ENUM_TRUST_WEB_CONTEXT; - struct recno_list_struct { struct recno_list_struct *next; @@ -171,6 +166,19 @@ delete_record( ulong recno ) die_invalid_db(); } +/**************** + * sync the db + */ +static void +do_sync( ) +{ + int rc = tdbio_sync(); + if( !rc ) + return; + log_error("trust db: sync failed: %s\n", g10_errstr(rc) ); + g10_exit(2); +} + /********************************************** @@ -425,15 +433,15 @@ verify_own_keys() memset( pk, 0, sizeof *pk ); rc = get_pubkey( pk, keyid ); if( rc ) { - log_error(_("key %08lX: secret key without public key\n"), + log_info(_("key %08lX: secret key without public key - skipped\n"), (ulong)keyid[1] ); - goto leave; + goto skip; } + if( cmp_public_secret_key( pk, sk ) ) { - log_error(_("key %08lX: secret and public key don't match\n"), + log_info(_("key %08lX: secret and public key don't match\n"), (ulong)keyid[1] ); - rc = G10ERR_GENERAL; - goto leave; + goto skip; } /* make sure that the pubkey is in the trustdb */ @@ -443,12 +451,12 @@ verify_own_keys() if( rc ) { log_error(_("key %08lX: can't put it into the trustdb\n"), (ulong)keyid[1] ); - goto leave; + goto skip; } } else if( rc ) { log_error(_("key %08lX: query record failed\n"), (ulong)keyid[1] ); - goto leave; + goto skip; } @@ -456,9 +464,12 @@ verify_own_keys() log_debug("key %08lX.%lu: stored into ultikey_table\n", (ulong)keyid[1], pk->local_id ); if( ins_lid_table_item( ultikey_table, pk->local_id, 0 ) ) - log_error(_("key %08lX: already in ultikey_table\n"), + log_error(_("key %08lX: already in secret key table\n"), (ulong)keyid[1]); - + else if( opt.verbose ) + log_info(_("key %08lX: accepted as secret key.\n"), + (ulong)keyid[1]); + skip: release_secret_key_parts( sk ); release_public_key_parts( pk ); } @@ -467,7 +478,6 @@ verify_own_keys() else rc = 0; - leave: enum_secret_keys( &enum_context, NULL, 0 ); /* free context */ free_secret_key( sk ); free_public_key( pk ); @@ -695,6 +705,13 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth, TRUST_SEG_LIST tsl, t2, tl; int i; + if( !(sx.sig_flag & SIGF_CHECKED) ) + continue; /* only checked sigs */ + if( !(sx.sig_flag & SIGF_VALID) ) + continue; /* and, of course, only valid sigs */ + if( (sx.sig_flag & SIGF_REVOKED) ) + continue; /* and skip revoked sigs */ + stack[depth].lid = sx.sig_lid; stack[depth].trust = 0; if( qry_lid_table_flag( lids, sx.sig_lid, &last_depth) ) { @@ -782,8 +799,13 @@ make_tsl( ulong lid, TRUST_SEG_LIST *ret_tslist ) release_lid_table(work); *ret_tslist = tslist; } - else - ; /* FIXME: release tslist */ + else { /* error: release tslist */ + while( tslist ) { + tsl = tslist->next; + m_free(tslist); + tslist = tsl; + } + } release_lid_table(lids); return rc; } @@ -865,7 +887,7 @@ do_check( TRUSTREC *dr, unsigned *trustlevel ) if( dr->r.dir.dirflags & DIRF_REVOKED ) tflags |= TRUST_FLAG_REVOKED; - #if 0 + #if 0 /* Do we still need this?? */ if( !rc && !dr->r.dir.siglist ) { /* We do not have any signatures; check whether it is one of our * secret keys */ @@ -1153,6 +1175,7 @@ import_ownertrust( const char *fname ) log_error_f(fname, _("read error: %s\n"), strerror(errno) ); if( !is_stdin ) fclose(fp); + do_sync(); } @@ -1247,8 +1270,6 @@ list_trust_path( int max_depth, const char *username ) /**************** * Check the complete trustdb or only the entries for the given username. - * Special hack: A username "REBUILD" inserts all records from the public - * key rings into the trustdb. */ void check_trustdb( const char *username ) @@ -1257,9 +1278,8 @@ check_trustdb( const char *username ) KBNODE keyblock = NULL; KBPOS kbpos; int rc; - int rebuild = username && !strcmp(username, "REBUILD"); - if( username && !rebuild ) { + if( username ) { rc = find_keyblock_byname( &kbpos, username ); if( !rc ) rc = read_keyblock( &kbpos, &keyblock ); @@ -1315,46 +1335,51 @@ check_trustdb( const char *username ) release_kbnode( keyblock ); keyblock = NULL; } } - if( rebuild ) { - log_info("adding new entries.\n"); - - rc = enum_keyblocks( 0, &kbpos, &keyblock ); - if( !rc ) { - while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) { - rc = update_trust_record( keyblock ); - if( rc == -1 ) { /* not yet in trustdb: insert */ - PKT_public_key *pk = - find_kbnode( keyblock, PKT_PUBLIC_KEY - ) ->pkt->pkt.public_key; - rc = insert_trust_record( pk ); - if( rc && !pk->local_id ) - log_error("lid ?: insert failed: %s\n", - g10_errstr(rc) ); - else if( rc ) - log_error("lid %lu: insert failed: %s\n", - pk->local_id, g10_errstr(rc) ); - else - log_info("lid %lu: inserted\n", pk->local_id ); - } - else if( rc ) - log_error("lid %lu: update failed: %s\n", - lid_from_keyblock(keyblock), g10_errstr(rc) ); - else - log_info("lid %lu: updated\n", - lid_from_keyblock(keyblock) ); - } - } - if( rc && rc != -1 ) - log_error("enum_keyblocks failed: %s\n", g10_errstr(rc)); - - enum_keyblocks( 2, &kbpos, &keyblock ); /* close */ - release_kbnode( keyblock ); - } - } } +void +update_trustdb( ) +{ + KBNODE keyblock = NULL; + KBPOS kbpos; + int rc; + + rc = enum_keyblocks( 0, &kbpos, &keyblock ); + if( !rc ) { + while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) { + rc = update_trust_record( keyblock ); + if( rc == -1 ) { /* not yet in trustdb: insert */ + PKT_public_key *pk = + find_kbnode( keyblock, PKT_PUBLIC_KEY + ) ->pkt->pkt.public_key; + rc = insert_trust_record( pk ); + if( rc && !pk->local_id ) + log_error("lid ?: insert failed: %s\n", + g10_errstr(rc) ); + else if( rc ) + log_error("lid %lu: insert failed: %s\n", + pk->local_id, g10_errstr(rc) ); + else + log_info("lid %lu: inserted\n", pk->local_id ); + } + else if( rc ) + log_error("lid %lu: update failed: %s\n", + lid_from_keyblock(keyblock), g10_errstr(rc) ); + else + log_info("lid %lu: updated\n", + lid_from_keyblock(keyblock) ); + } + } + if( rc && rc != -1 ) + log_error("enum_keyblocks failed: %s\n", g10_errstr(rc)); + + enum_keyblocks( 2, &kbpos, &keyblock ); /* close */ + release_kbnode( keyblock ); +} + + /**************** * Get the trustlevel for this PK. @@ -1418,12 +1443,10 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel ) return G10ERR_TIME_CONFLICT; } - if( pk->valid_days && add_days_to_timestamp(pk->timestamp, - pk->valid_days) < cur_time ) { + if( pk->expiredate && pk->expiredate <= cur_time ) { log_info(_("key %08lX.%lu: expired at %s\n"), (ulong)keyid[1], pk->local_id, - asctimestamp( add_days_to_timestamp(pk->timestamp, - pk->valid_days))); + asctimestamp( pk->expiredate) ); trustlevel = TRUST_EXPIRED; } else { @@ -1485,7 +1508,10 @@ query_trust_info( PKT_public_key *pk ) int enum_trust_web( void **context, ulong *lid ) { - ENUM_TRUST_WEB_CONTEXT *c = *context; + struct { + TRUST_SEG_LIST tsl; + int index; + } *c = *context; if( !c ) { /* make a new context */ c = m_alloc_clear( sizeof *c ); @@ -1652,7 +1678,7 @@ query_trust_record( PKT_public_key *pk ) return get_dir_record( pk, &rec ); } - +/* FIXME: Brauchen wir das?? */ int clear_trust_checked_flag( PKT_public_key *pk ) { @@ -1669,6 +1695,7 @@ clear_trust_checked_flag( PKT_public_key *pk ) /* reset the flag */ rec.r.dir.dirflags &= ~DIRF_CHECKED; write_record( &rec ); + do_sync(); return 0; } @@ -1684,6 +1711,8 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash, byte uhash[20]; int is_selfsig; PKT_signature *sigpkt = NULL; + TRUSTREC tmp; + u32 sigkid[2]; if( sigrec->r.sig.sig[sigidx].flag & SIGF_CHECKED ) log_info(_("note: sig rec %lu[%d] in hintlist " @@ -1694,6 +1723,23 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash, "of %lu but not marked\n"), sigrec->recnum, sigidx, hint_owner ); + read_record( sigrec->r.sig.sig[sigidx].lid, &tmp, 0 ); + if( tmp.rectype != RECTYPE_DIR ) { + /* we need the dir record */ + log_error(_("sig rec %lu[%d] in hintlist " + "of %u does not point to a dir record\n"), + sigrec->recnum, sigidx, hint_owner ); + return; + } + if( !tmp.r.dir.keylist ) { + log_error(_("lid %lu: no primary key\n"), tmp.r.dir.lid ); + return; + } + read_record(tmp.r.dir.keylist, &tmp, RECTYPE_KEY ); + keyid_from_fingerprint( tmp.r.key.fingerprint, + tmp.r.key.fingerprint_len, sigkid ); + + /* find the correct signature packet */ for( node=keyblock; node; node = node->next ) { if( node->pkt->pkttype == PKT_USER_ID ) { @@ -1707,8 +1753,8 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash, } else if( state && node->pkt->pkttype == PKT_SIGNATURE ) { sigpkt = node->pkt->pkt.signature; - if( sigpkt->keyid[0] == keyid[0] - && sigpkt->keyid[1] == keyid[1] + if( sigpkt->keyid[0] == sigkid[0] + && sigpkt->keyid[1] == sigkid[1] && (sigpkt->sig_class&~3) == 0x10 ) break; /* found */ } @@ -1723,23 +1769,28 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash, rc = check_key_signature( keyblock, node, &is_selfsig ); if( is_selfsig ) { log_error(_("lid %lu: self-signature in hintlist\n"), lid ); - return ; + return; } if( !rc ) { /* valid signature */ + if( opt.verbose ) + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "good signature (3)\n"), + (ulong)keyid[1], lid, uhash[18], uhash[19], + (ulong)sigpkt->keyid[1] ); sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED | SIGF_VALID; } else if( rc == G10ERR_NO_PUBKEY ) { - log_info(_("key %08lX.%lu, uid %02X%02X: " - "very strange: no public key for signature %08lX\n"), + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "very strange: no public key\n"), (ulong)keyid[1], lid, uhash[18], uhash[19], (ulong)sigpkt->keyid[1] ); sigrec->r.sig.sig[sigidx].flag = SIGF_NOPUBKEY; } else { - log_info(_("key %08lX.%lu, uid %02X%02X: " + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " "invalid signature: %s\n"), - (ulong)keyid[1], lid, - uhash[18], uhash[19], g10_errstr(rc)); + (ulong)keyid[1], lid, uhash[18], uhash[19], + (ulong)sigpkt->keyid[1], g10_errstr(rc) ); sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED; } sigrec->dirty = 1; @@ -1930,7 +1981,7 @@ upd_uid_record( PKT_user_id *uid, TRUSTREC *drec, RECNO_LIST *recno_list, static void upd_pref_record( PKT_signature *sig, TRUSTREC *drec, - u32 *keyid, ulong *uidrecno, byte *uidhash ) + u32 *keyid, TRUSTREC *urec, byte *uidhash ) { static struct { sigsubpkttype_t subpkttype; @@ -1941,7 +1992,7 @@ upd_pref_record( PKT_signature *sig, TRUSTREC *drec, { SIGSUBPKT_PREF_COMPR, PREFTYPE_COMPR }, { 0, 0 } }; - TRUSTREC urec, prec; + TRUSTREC prec; const byte *s; size_t n; int k, i; @@ -1949,13 +2000,10 @@ upd_pref_record( PKT_signature *sig, TRUSTREC *drec, int recno_idx = 0; ulong recno; - /* we need the uid record */ - read_record( *uidrecno, &urec, RECTYPE_UID ); - /* First delete all pref records * This is much simpler than checking whether we have to * do update the record at all - the record cache may care about it */ - for( recno=urec.r.uid.prefrec; recno; recno = prec.r.pref.next ) { + for( recno=urec->r.uid.prefrec; recno; recno = prec.r.pref.next ) { read_record( recno, &prec, RECTYPE_PREF ); delete_record( recno ); } @@ -1999,8 +2047,8 @@ upd_pref_record( PKT_signature *sig, TRUSTREC *drec, write_record( &prec ); } /* don't need to write the last one, but update the uid */ - urec.r.uid.prefrec = recno_idx? recno_tbl[0] : 0; - write_record( &urec ); + urec->r.uid.prefrec = recno_idx? recno_tbl[0] : 0; + urec->dirty = 1; } @@ -2014,25 +2062,41 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, u32 *keyid, ulong *uidrecno, byte *uidhash, KBNODE keyblock, KBNODE signode ) { + TRUSTREC urec; int rc; ulong lid = drec->recnum; + if( !*uidrecno ) { + /* fixme: handle direct key signatures */ + log_error("key %08lX: signature without user id\n", (ulong)keyid[1] ); + return; + } + read_record( *uidrecno, &urec, RECTYPE_UID ); + if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) { if( (sig->sig_class&~3) == 0x10 ) { /* must verify this selfsignature here, so that we can * build the preference record and validate the uid record */ - if( !*uidrecno ) { - log_error("key %08lX: self-signature without user id\n", - (ulong)keyid[1] ); - } - else if( (rc = check_key_signature( keyblock, signode, NULL ))) { - log_error("key %08lX, uid %02X%02X: " - "invalid self-signature: %s\n", (ulong)keyid[1], - uidhash[18], uidhash[19], g10_errstr(rc) ); - } - else { /* valid sig (may be revoked, but that doesn't matter here) */ - upd_pref_record( sig, drec, keyid, uidrecno, uidhash ); + if( !(urec.r.uid.uidflags & UIDF_CHECKED) ) { + rc = check_key_signature( keyblock, signode, NULL ); + if( !rc ) { + if( opt.verbose ) + log_info(_( + "key %08lX.%lu, uid %02X%02X: " + "good self-signature\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19] ); + upd_pref_record( sig, drec, keyid, &urec, uidhash ); + urec.r.uid.uidflags = UIDF_CHECKED | UIDF_VALID; + } + else { + log_error("key %08lX, uid %02X%02X: " + "invalid self-signature: %s\n", (ulong)keyid[1], + uidhash[18], uidhash[19], g10_errstr(rc) ); + urec.r.uid.uidflags = UIDF_CHECKED; + } + urec.dirty = 1; } } else {/* is revocation sig etc */ @@ -2051,18 +2115,43 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, * be converted to a dir record as soon as a new public key is * inserted into the trustdb. */ - TRUSTREC urec, rec; + TRUSTREC rec; ulong recno; TRUSTREC delrec; int delrecidx; int newflag = 0; ulong newlid = 0; PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + ulong pk_lid = 0; + int found_sig = 0; + int found_delrec = 0; delrec.recnum = 0; - /* we need the uid record */ - read_record( *uidrecno, &urec, RECTYPE_UID ); + rc = get_pubkey( pk, sig->keyid ); + if( !rc ) { + if( pk->local_id ) + pk_lid = pk->local_id; + else { + rc = tdbio_search_dir_bypk( pk, &rec ); + if( !rc ) + pk_lid = rec.recnum; + else if( rc == -1 ) { /* see whether there is a sdir instead */ + u32 akid[2]; + + keyid_from_pk( pk, akid ); + rc = tdbio_search_sdir( akid, pk->pubkey_algo, &rec ); + if( !rc ) + pk_lid = rec.recnum; + } + } + } + free_public_key( pk ); pk = NULL; + + /* Loop over all signatures just in case one is not correctly + * marked. If we see the correct signature, set a flag. + * delete duplicate signatures (should not happen but...) + */ for( recno = urec.r.uid.siglist; recno; recno = rec.r.sig.next ) { int i; @@ -2070,12 +2159,25 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, for(i=0; i < SIGS_PER_RECORD; i++ ) { TRUSTREC tmp; if( !rec.r.sig.sig[i].lid ) { - if( !delrec.recnum ) { + if( !found_delrec && !delrec.recnum ) { delrec = rec; delrecidx = i; + found_delrec=1; } continue; /* skip deleted sigs */ } + if( rec.r.sig.sig[i].lid == pk_lid ) { + if( found_sig ) { + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "duplicated signature - deleted\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1] ); + rec.r.sig.sig[i].lid = 0; + rec.dirty = 1; + } + else + found_sig = 1; + } if( rec.r.sig.sig[i].flag & SIGF_CHECKED ) continue; /* we already checked this signature */ if( rec.r.sig.sig[i].flag & SIGF_NOPUBKEY ) @@ -2087,24 +2189,30 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, * the signature: */ rc = check_key_signature( keyblock, signode, NULL ); if( !rc ) { /* valid signature */ + if( opt.verbose ) + log_info(_( + "key %08lX.%lu, uid %02X%02X, sig %08lX: " + "good signature (1)\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1] ); rec.r.sig.sig[i].flag = SIGF_CHECKED | SIGF_VALID; } else if( rc == G10ERR_NO_PUBKEY ) { - log_info(_("key %08lX.%lu, uid %02X%02X: " - "weird: no public key for signature %08lX\n"), + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "weird: no public key\n"), (ulong)keyid[1], lid, uidhash[18], uidhash[19], (ulong)sig->keyid[1] ); rec.r.sig.sig[i].flag = SIGF_NOPUBKEY; } else { - log_info(_("key %08lX.%lu, uid %02X%02X: " + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " "invalid signature: %s\n"), - (ulong)keyid[1], lid, - uidhash[18], uidhash[19], g10_errstr(rc)); + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1], + g10_errstr(rc)); rec.r.sig.sig[i].flag = SIGF_CHECKED; } - write_record( &rec ); - goto ready; + rec.dirty = 1; } else if( tmp.rectype == RECTYPE_SDIR ) { /* must check that it is the right one */ @@ -2117,11 +2225,10 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, (ulong)keyid[1], lid, uidhash[18], uidhash[19], tmp.recnum ); rec.r.sig.sig[i].flag = SIGF_NOPUBKEY; - write_record( &rec ); + rec.dirty = 1; /* fixme: should we verify that the record is * in the hintlist? - This case here should anyway * never occur */ - goto ready; } } else { @@ -2130,48 +2237,52 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, die_invalid_db(); } } + if( found_delrec && delrec.recnum ) { + delrec = rec; + found_delrec = 0; /* we onyl want the first one */ + } + if( rec.dirty ) + write_record( &rec ); } + + if( found_sig ) + goto leave; + /* at this point, we have verified, that the signature is not in * our list of signatures. Add a new record with that signature * and if the public key is there, check the signature. */ - rc = get_pubkey( pk, sig->keyid ); - if( !rc ) { - /* check that we already have the record in the trustdb; - * if not we should not check the signature, because we do - * not have the lid of the signature and therefore can't add - * a signature record. We will fake a no_pubkey error, so - * that this is handled, like we do not have the publick key at - * at all. The alternative would be a recursive insert of - * records - but that is not good. - */ - rc = query_trust_record( pk ); - if( rc == -1 ) - rc = G10ERR_NO_PUBKEY; - else - rc = check_key_signature( keyblock, signode, NULL ); - } + + if( !pk_lid ) + rc = G10ERR_NO_PUBKEY; + else + rc = check_key_signature( keyblock, signode, NULL ); + if( !rc ) { /* valid signature */ - newlid = pk->local_id; /* this is the pk of the signature */ + if( opt.verbose ) + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "good signature (2)\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1] ); + newlid = pk_lid; /* this is the pk of the signature */ if( !newlid ) BUG(); newflag = SIGF_CHECKED | SIGF_VALID; } else if( rc == G10ERR_NO_PUBKEY ) { - if( opt.verbose ) - log_info(_("key %08lX.%lu, uid %02X%02X: " - "no public key for signature %08lX\n"), + if( opt.verbose > 1 ) + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "no public key\n"), (ulong)keyid[1], lid, uidhash[18], uidhash[19], (ulong)sig->keyid[1] ); newflag = SIGF_NOPUBKEY; } else { - log_info(_("key %08lX.%lu, uid %02X%02X: " + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " "invalid signature: %s\n"), (ulong)keyid[1], lid, uidhash[18], uidhash[19], - g10_errstr(rc)); + (ulong)sig->keyid[1], g10_errstr(rc)); newflag = SIGF_CHECKED; } - free_public_key( pk ); if( !newlid ) { /* create a shadow dir record */ TRUSTREC sdir, hlst, tmphlst; @@ -2250,16 +2361,17 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, tmp.r.sig.sig[0].flag= newflag; write_record( &tmp ); urec.r.uid.siglist = tmp.recnum; - write_record( &urec ); + urec.dirty = 1; } - ready: - ; } else { /* handle other sig classes */ } + leave: + if( urec.dirty ) + write_record( &urec ); } @@ -2389,7 +2501,7 @@ update_trust_record( KBNODE keyblock ) else if( drec.dirty ) { drec.r.dir.dirflags &= ~DIRF_CHECKED; /* reset flag */ write_record( &drec ); - /* fixme: commit_transaction */ + do_sync(); } rel_recno_list( &recno_list ); return rc; @@ -2437,9 +2549,17 @@ insert_trust_record( PKT_public_key *pk ) /* check that we used the primary key (we are little bit paranoid) */ { PKT_public_key *a_pk; + u32 akid[2], bkid[2]; + node = find_kbnode( keyblock, PKT_PUBLIC_KEY ); a_pk = node->pkt->pkt.public_key; - if( cmp_public_keys( a_pk, pk ) ) { + + /* we can't use cmp_public_keys here because some parts (expiredate) + * might not be set in pk <--- but why (fixme) */ + keyid_from_pk( a_pk, akid ); + keyid_from_pk( pk, bkid ); + + if( akid[0] != bkid[0] || akid[1] != bkid[1] ) { log_error("did not use primary key for insert_trust_record()\n"); rc = G10ERR_GENERAL; goto leave; @@ -2492,6 +2612,7 @@ insert_trust_record( PKT_public_key *pk ) if( rc && hintlist ) ; /* fixme: the hintlist is not anymore anchored */ release_kbnode( keyblock ); + do_sync(); return rc; } @@ -2504,6 +2625,7 @@ update_ownertrust( ulong lid, unsigned new_trust ) read_record( lid, &rec, RECTYPE_DIR ); rec.r.dir.ownertrust = new_trust; write_record( &rec ); + do_sync(); return 0; } diff --git a/g10/trustdb.h b/g10/trustdb.h index b0f39770f..8cdf50ec1 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -46,6 +46,7 @@ void list_trust_path( int max_depth, const char *username ); void export_ownertrust(void); void import_ownertrust(const char *fname); void check_trustdb( const char *username ); +void update_trustdb( void ); int init_trustdb( int level, const char *dbname ); int check_trust( PKT_public_key *pk, unsigned *r_trustlevel ); int query_trust_info( PKT_public_key *pk ); diff --git a/include/ChangeLog b/include/ChangeLog index 627449c34..9274ee962 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +Tue Oct 13 12:40:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * iobuf.h (iobuf_get): Now uses .nofast + (iobuf_get2): Removed. + Mon Sep 14 09:17:22 1998 Werner Koch (wk@(none)) * util.h (HAVE_ATEXIT): New. diff --git a/include/cipher.h b/include/cipher.h index dce7262c6..38050efa5 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -97,7 +97,7 @@ int g10c_debug_mode; int g10_opt_verbose; /*-- dynload.c --*/ -void register_cipher_extension( const char *fname ); +void register_cipher_extension( const char *mainpgm, const char *fname ); /*-- md.c --*/ int string_to_digest_algo( const char *string ); diff --git a/include/iobuf.h b/include/iobuf.h index c84254d73..f09d701fb 100644 --- a/include/iobuf.h +++ b/include/iobuf.h @@ -41,6 +41,8 @@ struct iobuf_struct { unsigned long nlimit; unsigned long nbytes; /* used together with nlimit */ unsigned long ntotal; /* total bytes read (position of stream) */ + int nofast; /* used by the iobuf_get() */ + void *directfp; struct { size_t size; /* allocated size */ size_t start; /* number of invalid bytes at the begin of the buffer */ @@ -70,6 +72,7 @@ int iobuf_debug_mode; IOBUF iobuf_alloc(int usage, size_t bufsize); IOBUF iobuf_temp(void); IOBUF iobuf_open( const char *fname ); +IOBUF iobuf_fopen( const char *fname, const char *mode ); IOBUF iobuf_create( const char *fname ); IOBUF iobuf_append( const char *fname ); IOBUF iobuf_openrw( const char *fname ); @@ -114,15 +117,10 @@ int iobuf_in_block_mode( IOBUF a ); * returned value to be in the range 0 ..255. */ #define iobuf_get(a) \ - ( ((a)->nlimit || (a)->d.start >= (a)->d.len )? \ + ( ((a)->nofast || (a)->d.start >= (a)->d.len )? \ iobuf_readbyte((a)) : ( (a)->nbytes++, (a)->d.buf[(a)->d.start++] ) ) #define iobuf_get_noeof(a) (iobuf_get((a))&0xff) -/* use this if you have ungetted stuff */ -#define iobuf_get2(a) \ - ( ( (a)->unget.buf || (a)->nlimit || (a)->d.start >= (a)->d.len )? \ - iobuf_readbyte((a)) : ( (a)->nbytes++, (a)->d.buf[(a)->d.start++] ) ) - /* write a byte to the iobuf and return true on write error * This macro does only write the low order byte */ diff --git a/mpi/ChangeLog b/mpi/ChangeLog index b2e8296ad..73f296d69 100644 --- a/mpi/ChangeLog +++ b/mpi/ChangeLog @@ -1,3 +1,7 @@ +Wed Oct 14 09:59:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config-links (freebsd): ELF patches from Jun Kuriyama. + Thu Oct 8 13:28:17 1998 Werner Koch (wk@isil.d.shuttle.de) * mpi-mpow.c (mpi_mulpowm): Fixed mem leak (m_free/mpi_free). diff --git a/mpi/config.links b/mpi/config.links index bd525abc1..5c3f960df 100644 --- a/mpi/config.links +++ b/mpi/config.links @@ -10,6 +10,16 @@ test -d ./mpi || mkdir ./mpi echo '/* created by config.links - do not edit */' >./mpi/asm-syntax.h case "${target}" in + i[34]86*-*-freebsd*-elf) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i[56]86*-*-freebsd*-elf) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i586 i386" + ;; i[34]86*-*-linuxaout* | i[34]86*-*-linuxoldld* | i[34]86*-*-*bsd*) echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h echo '#define X86_BROKEN_ALIGN' >>./mpi/asm-syntax.h @@ -122,7 +132,7 @@ case "${target}" in *-*-linuxaout* | *-*-linuxoldld* | *-*-linux-gnuoldld*) needs_underscore="y" ;; - *-*-linux* | *-sysv* | *-solaris* | *-gnu*) + *-*-linux* | *-sysv* | *-solaris* | *-gnu* | *-freebsd*-elf) needs_underscore="n" ;; *) diff --git a/scripts/ChangeLog b/scripts/ChangeLog new file mode 100644 index 000000000..bf6032324 --- /dev/null +++ b/scripts/ChangeLog @@ -0,0 +1,5 @@ +Wed Oct 14 09:55:25 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.guess (FreeBSD): Changes from Jun Kuriyama to support ELF + * config.sub: (freebsd): Add to maybe_os + diff --git a/scripts/config.guess b/scripts/config.guess index b6f37c991..a33e7a5f1 100755 --- a/scripts/config.guess +++ b/scripts/config.guess @@ -9,7 +9,7 @@ # # This program 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 +# 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 @@ -169,7 +169,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) - sed 's/^ //' << EOF >dummy.c + sed 's/^ //' << EOF >dummy.c int main (argc, argv) int argc; char **argv; { #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) @@ -204,19 +204,19 @@ EOF echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \ -o ${TARGET_BINARY_INTERFACE}x = x ] ; then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi - else echo i586-dg-dgux${UNAME_RELEASE} - fi - exit 0 ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) + else echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) @@ -234,13 +234,13 @@ EOF exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i?86:AIX:*:*) echo i386-ibm-aix exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - sed 's/^ //' << EOF >dummy.c + sed 's/^ //' << EOF >dummy.c #include main() @@ -279,9 +279,9 @@ EOF ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit 0 ;; # report: romp-ibm BSD 4.3 + exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; @@ -296,16 +296,16 @@ EOF exit 0 ;; 9000/[3478]??:HP-UX:*:*) case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; 9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;; - 9000/8?? ) HP_ARCH=hppa1.0 ;; + 9000/8?? ) HP_ARCH=hppa1.0 ;; esac HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) - sed 's/^ //' << EOF >dummy.c + sed 's/^ //' << EOF >dummy.c #include int main () @@ -313,7 +313,7 @@ EOF long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ + results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) @@ -358,25 +358,25 @@ EOF exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd - exit 0 ;; + exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit 0 ;; + exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd - exit 0 ;; + exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd - exit 0 ;; + exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd - exit 0 ;; + exit 0 ;; CRAY*X-MP:*:*:*) echo xmp-cray-unicos - exit 0 ;; + exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} exit 0 ;; @@ -390,12 +390,12 @@ EOF exit 0 ;; CRAY-2:*:*:*) echo cray2-cray-unicos - exit 0 ;; + exit 0 ;; F300:UNIX_System_V:*:*) - FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; + FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; F301:UNIX_System_V:*:*) echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'` exit 0 ;; @@ -409,7 +409,17 @@ EOF echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + rel_number=`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//' 2>/dev/null` + if test "$rel_number" = "3.0"; then + ld_help_string=`ld --help 2>&1` + if echo "$ld_help_string"|grep >/dev/null 2>&1 "supported emulations: elf_i.86"; then + echo ${UNAME_MACHINE}-unknown-freebsd${rel_number}-elf + else + echo ${UNAME_MACHINE}-unknown-freebsd${rel_number}-aout + fi + else + echo ${UNAME_MACHINE}-unknown-freebsd${rel_number} + fi exit 0 ;; *:NetBSD:*:*) echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` @@ -542,8 +552,8 @@ EOF /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; @@ -574,9 +584,9 @@ EOF fi exit 0 ;; PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit 0 ;; + # says + echo i586-unisys-sysv4 + exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm @@ -591,11 +601,11 @@ EOF exit 0 ;; R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv${UNAME_RELEASE} else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv${UNAME_RELEASE} fi - exit 0 ;; + exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 @@ -617,11 +627,11 @@ main () #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 - "4" + "4" #else "" #endif - ); exit (0); + ); exit (0); #endif #endif diff --git a/scripts/config.sub b/scripts/config.sub index 055e54582..a0deddae0 100755 --- a/scripts/config.sub +++ b/scripts/config.sub @@ -68,7 +68,7 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - linux-gnu*) + linux-gnu*|freebsd*-*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; diff --git a/scripts/distfiles b/scripts/distfiles index d2b99010b..d2518076d 100644 --- a/scripts/distfiles +++ b/scripts/distfiles @@ -5,3 +5,4 @@ mkinstalldirs mkdiff missing gnupg.spec +ChangeLog diff --git a/util/ChangeLog b/util/ChangeLog index 0f444d990..6904c9333 100644 --- a/util/ChangeLog +++ b/util/ChangeLog @@ -1,3 +1,7 @@ +Tue Oct 13 12:40:13 1998 Werner Koch (wk@isil.d.shuttle.de) + + * util.c (.nofast): set this variable + Wed Oct 7 19:27:50 1998 Werner Koch (wk@isil.d.shuttle.de) * memory.c (m_print_stats): New. diff --git a/util/iobuf.c b/util/iobuf.c index b7ccd1ecd..515a5f8a3 100644 --- a/util/iobuf.c +++ b/util/iobuf.c @@ -431,6 +431,13 @@ iobuf_close( IOBUF a ) size_t dummy_len; int rc=0; + if( a->directfp ) { + fclose( a->directfp ); + if( DBG_IOBUF ) + log_debug("iobuf-close -> %p\n", a->directfp ); + return 0; + } + for( ; a && !rc ; a = a2 ) { a2 = a->chain; if( a->usage == 2 && (rc=iobuf_flush(a)) ) @@ -602,6 +609,39 @@ iobuf_openrw( const char *fname ) return a; } + + +/**************** + * You can overwrite the normal iobuf behaviour by using this function. + * If used, the crwated iobuf is a simple wrapper around stdio. + * NULL if an error occures and sets errno + */ +IOBUF +iobuf_fopen( const char *fname, const char *mode ) +{ + IOBUF a; + FILE *fp; + int print_only = 0; + + if( !fname || (*fname=='-' && !fname[1]) ) { + fp = stdin; /* fixme: set binary mode for msdoze */ + fname = "[stdin]"; + print_only = 1; + } + else if( !(fp = fopen(fname, mode) ) ) + return NULL; + a = iobuf_alloc(1, 8192 ); + a->directfp = fp; + + if( DBG_IOBUF ) + log_debug("iobuf_fopen -> %p\n", a->directfp ); + + return a; +} + + + + /**************** * Register an i/o filter. */ @@ -614,6 +654,9 @@ iobuf_push_filter( IOBUF a, size_t dummy_len=0; int rc=0; + if( a->directfp ) + BUG(); + if( a->usage == 2 && (rc=iobuf_flush(a)) ) return rc; /* make a copy of the current stream, so that @@ -640,6 +683,7 @@ iobuf_push_filter( IOBUF a, /* disable nlimit for the new stream */ a->ntotal = b->ntotal + b->nbytes; a->nlimit = a->nbytes = 0; + a->nofast &= ~1; /* make a link from the new stream to the original stream */ a->chain = b; a->opaque = b->opaque; @@ -675,6 +719,9 @@ iobuf_pop_filter( IOBUF a, int (*f)(void *opaque, int control, size_t dummy_len=0; int rc=0; + if( a->directfp ) + BUG(); + if( DBG_IOBUF ) log_debug("iobuf-%d.%d: pop '%s'\n", a->no, a->subno, a->desc ); if( !a->filter ) { /* this is simple */ @@ -744,6 +791,7 @@ underflow(IOBUF a) assert( a->d.start == a->d.len ); if( a->usage == 3 ) return -1; /* EOF because a temp buffer can't do an underflow */ + if( a->filter_eof ) { if( DBG_IOBUF ) log_debug("iobuf-%d.%d: filter eof\n", a->no, a->subno ); @@ -755,6 +803,22 @@ underflow(IOBUF a) return -1; } + if( a->directfp ) { + FILE *fp = a->directfp; + + len = fread( a->d.buf, 1, a->d.size, fp); + if( len < a->d.size ) { + if( ferror(fp) ) + a->error = 1; + else if( feof( fp ) ) + a->filter_eof = 1; + } + a->d.len = len; + a->d.start = 0; + return len? a->d.buf[a->d.start++] : -1; + } + + if( a->filter ) { len = a->d.size; rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain, @@ -790,6 +854,9 @@ underflow(IOBUF a) void iobuf_clear_eof(IOBUF a) { + if( a->directfp ) + return; + assert(a->usage == 1); if( a->filter ) @@ -806,6 +873,9 @@ iobuf_flush(IOBUF a) size_t len; int rc; + if( a->directfp ) + return 0; + /*log_debug("iobuf-%d.%d: flush\n", a->no, a->subno );*/ if( a->usage == 3 ) log_bug("temp buffer too short\n"); @@ -842,6 +912,7 @@ iobuf_readbyte(IOBUF a) return a->unget.buf[a->unget.start++]; m_free(a->unget.buf); a->unget.buf = NULL; + a->nofast &= ~2; } if( a->nlimit && a->nbytes >= a->nlimit ) @@ -924,6 +995,10 @@ iobuf_peek(IOBUF a, byte *buf, unsigned buflen ) int iobuf_writebyte(IOBUF a, unsigned c) { + + if( a->directfp ) + BUG(); + if( a->d.len == a->d.size ) if( iobuf_flush(a) ) return -1; @@ -937,6 +1012,10 @@ iobuf_writebyte(IOBUF a, unsigned c) int iobuf_write(IOBUF a, byte *buf, unsigned buflen ) { + + if( a->directfp ) + BUG(); + do { for( ; buflen && a->d.len < a->d.size; buflen--, buf++ ) a->d.buf[a->d.len++] = *buf; @@ -996,9 +1075,11 @@ iobuf_unget_and_close_temp( IOBUF a, IOBUF temp ) /* not yet cleaned up; do it now */ m_free(a->unget.buf); a->unget.buf = NULL; + a->nofast &= ~2; } a->unget.size = temp->d.len; a->unget.buf = m_alloc( a->unget.size ); + a->nofast |= 2; a->unget.len = temp->d.len; memcpy( a->unget.buf, temp->d.buf, a->unget.len ); iobuf_close(temp); @@ -1012,6 +1093,10 @@ iobuf_unget_and_close_temp( IOBUF a, IOBUF temp ) void iobuf_set_limit( IOBUF a, unsigned long nlimit ) { + if( nlimit ) + a->nofast |= 1; + else + a->nofast &= ~1; a->nlimit = nlimit; a->ntotal += a->nbytes; a->nbytes = 0; @@ -1027,6 +1112,15 @@ iobuf_get_filelength( IOBUF a ) { struct stat st; + if( a->directfp ) { + FILE *fp = a->directfp; + + if( !fstat(fileno(fp), &st) ) + return st.st_size; + log_error("fstat() failed: %s\n", strerror(errno) ); + return 0; + } + for( ; a; a = a->chain ) if( !a->chain && a->filter == file_filter ) { file_filter_ctx_t *b = a->filter_ov; @@ -1061,30 +1155,39 @@ iobuf_seek( IOBUF a, ulong newpos ) { file_filter_ctx_t *b = NULL; - for( ; a; a = a->chain ) { - if( !a->chain && a->filter == file_filter ) { - b = a->filter_ov; - break; + if( a->directfp ) { + FILE *fp = a->directfp; + if( fseek( fp, newpos, SEEK_SET ) ) { + log_error("can't seek to %lu: %s\n", newpos, strerror(errno) ); + return -1; } + clearerr(fp); } - if( !a ) - return -1; - - if( fseek( b->fp, newpos, SEEK_SET ) ) { - log_error("can't seek to %lu: %s\n", newpos, strerror(errno) ); - return -1; + else { + for( ; a; a = a->chain ) { + if( !a->chain && a->filter == file_filter ) { + b = a->filter_ov; + break; + } + } + if( !a ) + return -1; + if( fseek( b->fp, newpos, SEEK_SET ) ) { + log_error("can't seek to %lu: %s\n", newpos, strerror(errno) ); + return -1; + } } a->d.len = 0; /* discard buffer */ a->d.start = 0; a->nbytes = 0; a->nlimit = 0; + a->nofast &= ~1; a->ntotal = newpos; a->error = 0; /* remove filters, but the last */ while( a->chain ) iobuf_pop_filter( a, a->filter, NULL ); - return 0; }