last local commit
authorWerner Koch <wk@gnupg.org>
Fri, 16 Oct 1998 16:00:17 +0000 (16:00 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 16 Oct 1998 16:00:17 +0000 (16:00 +0000)
49 files changed:
ChangeLog
NEWS
README
THANKS
TODO
acconfig.h
cipher/ChangeLog
cipher/Makefile.am
cipher/dynload.c
cipher/rand-unix.c
configure.in
doc/DETAILS
g10/ChangeLog
g10/armor.c
g10/build-packet.c
g10/encode.c
g10/export.c
g10/filter.h
g10/free-packet.c
g10/g10.c
g10/getkey.c
g10/import.c
g10/keydb.h
g10/keygen.c
g10/keyid.c
g10/keylist.c
g10/mainproc.c
g10/options.h
g10/packet.h
g10/parse-packet.c
g10/ringedit.c
g10/sig-check.c
g10/sign.c
g10/tdbio.c
g10/tdbio.h
g10/textfilter.c
g10/trustdb.c
g10/trustdb.h
include/ChangeLog
include/cipher.h
include/iobuf.h
mpi/ChangeLog
mpi/config.links
scripts/ChangeLog [new file with mode: 0644]
scripts/config.guess
scripts/config.sub
scripts/distfiles
util/ChangeLog
util/iobuf.c

index 6a64647..6a1ac49 100644 (file)
--- 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 40d763c..9fb6282 100644 (file)
--- 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 e566703..823cc52 100644 (file)
--- 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) <dd9jn@gnu.org>"
     "Key fingerprint = 6BD9 050F D8FC 941B 4341  2DCC 68B7 AB89 5754 8DCD"
 
@@ -25,7 +25,7 @@
     "pub  1024D/621CC013 1998-07-07 Werner Koch <werner.koch@guug.de>"
     "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.
 
     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.
 
        "#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:
 
     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.
        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 81aae8e..baaf5f1 100644 (file)
--- 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 60cc105..744af32 100644 (file)
--- 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
 
     * -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.
 
index 9f8550c..b17d22d 100644 (file)
@@ -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
index ddd34b6..99cd301 100644 (file)
@@ -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  <steve@altair.xemacs.org>
 
        * Makefile.am: fix sed -O substitutions to catch -O6, etc.
index 298e0f3..e151de5 100644 (file)
@@ -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]*/  /' `
 
 
index 0cbbda2..ff40daf 100644 (file)
@@ -25,6 +25,8 @@
 #include <unistd.h>
 #ifdef HAVE_DL_DLOPEN
   #include <dlfcn.h>
+#elif defined(HAVE_DLD_DLD_LINK)
+  #include <dld.h>
 #endif
 #include "util.h"
 #include "cipher.h"
 
 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;
index 33f964d..b9423e0 100644 (file)
@@ -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 {
index ae674ae..543748f 100644 (file)
@@ -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
index dca87af..5a3dccb 100644 (file)
@@ -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
index 93a21e2..4bc2220 100644 (file)
@@ -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.
 
index df67712..aa56090 100644 (file)
@@ -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();
index a877b7e..11edb33 100644 (file)
@@ -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 );
index bc47426..0d8a84c 100644 (file)
@@ -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 */
index 301cb5e..46413ff 100644 (file)
@@ -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) );
index d48b756..1cf8f8e 100644 (file)
@@ -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;
index e6b2281..c3b516d 100644 (file)
@@ -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;
index 9195d21..569d411 100644 (file)
--- 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);
index 6e4c345..90bd09a 100644 (file)
 #define MAX_PK_CACHE_ENTRIES   50
 #define MAX_UID_CACHE_ENTRIES  50
 
+static struct {
+    int any;
+    int okay_count;
+    int nokey_count;
+    int error_count;
+} lkup_stats[21];
 
-typedef struct enum_seckey_context {
-    int eof;
-    STRLIST sl;
-    IOBUF iobuf;
-} enum_seckey_context_t;
 
 
-static STRLIST keyrings;
-static STRLIST secret_keyrings;
 
 #if MAX_UNK_CACHE_ENTRIES
   typedef struct keyid_list {
@@ -89,93 +88,25 @@ 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 )
-{
-    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);
-    }
-    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 )
+static void
+print_stats()
 {
-    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);
+    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( &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] ) {
index ccfbcca..3748433 100644 (file)
@@ -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);
index c7fb26d..efb371c 100644 (file)
@@ -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 );
index 3a75820..9f1d8df 100644 (file)
@@ -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 )
index 387c3fa..fa5b923 100644 (file)
@@ -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;
index 04d79b1..69e9b52 100644 (file)
@@ -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
index a47885b..dd1546c 100644 (file)
@@ -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
index d674ada..ac76296 100644 (file)
 #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;
index 5bb383c..4898027 100644 (file)
@@ -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 */
index 41afe5b..c17f2c5 100644 (file)
@@ -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;
index 677420e..6b6f6c8 100644 (file)
@@ -48,6 +48,7 @@
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h> /* for truncate */
 #include <assert.h>
 #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 <unistd.h> /* for truncate */
 
 
 struct resource_table_struct {
@@ -97,29 +98,75 @@ check_pos( KBPOS *kbpos )
  ****************************************************************/
 
 /****************
+ * 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;
 
index b983bb4..fd476f7 100644 (file)
@@ -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);
     }
 
index 349b2f3..304843f 100644 (file)
@@ -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 */
index 82b22b4..4259193 100644 (file)
 #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);
 
+\f
+/*************************************
+ ************* 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;
+}
+
+
+\f
+/********************************************************
+ **************** 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;
-
-    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 );
+    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 );
 
-    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));
index 66579ad..42bb4aa 100644 (file)
@@ -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 );
index 804b485..fc81a91 100644 (file)
@@ -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;
index 18726f1..eb6ea3c 100644 (file)
@@ -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);
+}
+
 
 \f
 /**********************************************
@@ -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,43 +1335,48 @@ 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 );
 }
 
 
@@ -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;
 }
 
index b0f3977..8cdf50e 100644 (file)
@@ -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 );
index 627449c..9274ee9 100644 (file)
@@ -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.
index dce7262..38050ef 100644 (file)
@@ -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 );
index c84254d..f09d701 100644 (file)
@@ -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
  */
index b2e8296..73f296d 100644 (file)
@@ -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).
index bd525ab..5c3f960 100644 (file)
@@ -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 (file)
index 0000000..bf60323
--- /dev/null
@@ -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
+
index b6f37c9..a33e7a5 100755 (executable)
@@ -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 <sys/systemcfg.h>
 
                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 <unistd.h>
        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 <Richard.M.Bartel@ccMail.Census.GOV>
-        echo i586-unisys-sysv4
-        exit 0 ;;
+                          # says <Richard.M.Bartel@ccMail.Census.GOV>
+       echo i586-unisys-sysv4
+       exit 0 ;;
     *:UNIX_System_V:4*:FTX*)
        # From Gerald Hewes <hewes@openmarket.com>.
        # 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 <sys/param.h>
   printf ("m68k-sony-newsos%s\n",
 #ifdef NEWSOS4
-          "4"
+         "4"
 #else
          ""
 #endif
-         ); exit (0);
+        ); exit (0);
 #endif
 #endif
 
index 055e545..a0dedda 100755 (executable)
@@ -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/'`
     ;;
index d2b9901..d251807 100644 (file)
@@ -5,3 +5,4 @@ mkinstalldirs
 mkdiff
 missing
 gnupg.spec
+ChangeLog
index 0f444d9..6904c93 100644 (file)
@@ -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.
index b7ccd1e..515a5f8 100644 (file)
@@ -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;
 }