backup
authorWerner Koch <wk@gnupg.org>
Mon, 12 Oct 1998 20:16:38 +0000 (20:16 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 12 Oct 1998 20:16:38 +0000 (20:16 +0000)
48 files changed:
ChangeLog
INSTALL
Makefile.am
NEWS
README
THANKS
TODO
VERSION
acconfig.h
checks/run-gpg.patterns
cipher/ChangeLog
cipher/Makefile.am
cipher/dsa.c
cipher/md.c
configure.in
doc/DETAILS
doc/FAQ
doc/gpg.1pod
g10/ChangeLog
g10/Makefile.am
g10/armor.c
g10/g10.c
g10/getkey.c
g10/kbnode.c
g10/keyedit.c
g10/keyid.c
g10/mainproc.c
g10/revoke.c
g10/ringedit.c
g10/tdbio.c
g10/tdbio.h
g10/trustdb.c
g10/trustdb.h
include/memory.h
mpi/ChangeLog
mpi/mpi-div.c
mpi/mpi-inv.c
mpi/mpi-mpow.c
mpi/mpiutil.c
po/ChangeLog
po/de.po
po/fr.po
po/it.po
scripts/gnupg.spec
util/ChangeLog
util/Makefile.am
util/dotlock.c [new file with mode: 0644]
util/memory.c

index 330ede5..6a64647 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Thu Oct  8 10:55:15 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * Makefile.am (g10defs.h): creates include file
+       * acconfig.h: now includes g10defs.h
+       * configure.in: Removed G10_LOCALEDIR and GNUPG_LIB
+
 Thu Sep 17 18:49:40 1998  Werner Koch  (wk@(none))
 
        * Makefile.am (dist-hook): Now creates RPM file.
diff --git a/INSTALL b/INSTALL
index 863cc4d..60252d1 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -63,7 +63,7 @@ The Linux files should look like this:
     cr--r--r--  1 root     sys        1,   9 Feb 16 08:23 /dev/urandom
 You can create them with:
     mknod /dev/random c 1 8
-    mknod /dev/random c 1 8
+    mknod /dev/urandom c 1 9
 
 The FreeBSD files [from the 970202 snapshot]:
     crw-r--r-- 1 root  wheel    2,   3 Feb 25 16:54 /dev/random
index 138f0d3..49aa438 100644 (file)
@@ -3,6 +3,22 @@
 SUBDIRS =  intl po zlib util mpi cipher tools g10 doc checks
 EXTRA_DIST = VERSION  PROJECTS
 
+all-am: g10defs.h
+all-recursive-am: g10defs.h
+
+
+g10defs.h : config.h
+       @( set -e; \
+       echo "/* Generated automatically by Makefile */" ; \
+       echo "#ifdef __MINGW32__"; \
+       echo "#define G10_LOCALEDIR \"c:/lib/gnupg/locale\""; \
+       echo "#define GNUPG_LIBDIR \"c:/lib/gnupg\""; \
+       echo "#else";\
+       echo "#define G10_LOCALEDIR \"$(prefix)/$(DATADIRNAME)/locale\""; \
+       echo "#define GNUPG_LIBDIR \"$(libdir)/gnupg\""; \
+       echo "#endif";\
+       ) >g10defs.h
+
 
 dist-hook:
        @set -e; \
diff --git a/NEWS b/NEWS
index 52691f8..40d763c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+Noteworthy changes in version 0.4.2
+-----------------------------------
+    * Fixed this huge memory leak.
+
+
 Noteworthy changes in version 0.4.1
 -----------------------------------
     * A secondary key is used when the primary key is specified but cannot
diff --git a/README b/README
index ad836c3..e566703 100644 (file)
--- a/README
+++ b/README
@@ -1,5 +1,3 @@
------BEGIN PGP SIGNED MESSAGE-----
-
                  GNUPG - The GNU Privacy Guard
                 -------------------------------
                          Version 0.4
     post them to the mailing list <g10@net.lut.ac.uk> (this is a closed list,
     please subscribe before posting, see above (~line 33)).
 
------BEGIN PGP SIGNATURE-----
-Version: GNUPG v0.4.0a (GNU/Linux)
-Comment: For info finger gcrypt@ftp.guug.de
 
-iQB1AwUBNhtSpB0Z9MEMmFelAQHWNQMAuPaj71rzjjtVNlYDV0MYljPFZqAK7tvmbH3i9Lti
-UuvGPCpx1/ej7jwZ2LSQ61O8c/xRwV07chHa5MGmSGT4KZg5g5MejUOliMQJIJwjY5PoZAVb
-6F7+hZf5Bt5Jl2J7
-=6Mbb
------END PGP SIGNATURE-----
+    Supported targets:
+    ------------------
+      powerpc-unknown-linux-gnu  (linuxppc)
+      hppa1.1-hp-hpux10.20
+
+
+
+
diff --git a/THANKS b/THANKS
index c6013c9..81aae8e 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -28,6 +28,7 @@ John A. Martin                jam@jamux.com
 Jörg Schilling         schilling@fokus.gmd.de
 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
@@ -46,6 +47,7 @@ QingLong              qinglong@bolizm.ihep.su
 Ralph Gillen           gillen@theochem.uni-duesseldorf.de
 Roland Rosenfeld       roland@spinnaker.rhein.de
 Serge Munhoven         munhoven@mema.ucl.ac.be
+SL Baur                steve@xemacs.org
 Steffen Ullrich        ccrlphr@xensei.com
 Steffen Zahn           zahn@berlin.snafu.de
 Thomas Roessler        roessler@guug.de
diff --git a/TODO b/TODO
index c1da628..60cc105 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,4 +1,16 @@
 
+    * 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.
 
diff --git a/VERSION b/VERSION
index 267577d..39bbca7 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.4.1
+0.4.1a
index 7bd2614..9f8550c 100644 (file)
@@ -31,9 +31,7 @@
 #undef M_GUARD
 #undef VERSION
 #undef PACKAGE
-#undef G10_LOCALEDIR
 #undef PRINTABLE_OS_NAME
-#undef GNUPG_LIBDIR
 
 /* Define if your locale.h file contains LC_MESSAGES.  */
 #undef HAVE_LC_MESSAGES
@@ -85,4 +83,6 @@
 
 @BOTTOM@
 
+#include "g10defs.h"
+
 #endif /*G10_CONFIG_H*/
index 7fd9f2c..5bb349c 100644 (file)
@@ -4,3 +4,4 @@ gpg: note: cipher algorithm 3 not found in preferences
 gpg: note: cipher algorithm 4 not found in preferences
 gpg: note: secret key 2E5FA4F4 is NOT protected.
 gpg: note: secret key 439F02CA is NOT protected.
+gpg: warning: using insecure random number generator
index ad6a76a..ddd34b6 100644 (file)
@@ -1,3 +1,7 @@
+1998-10-10  SL Baur  <steve@altair.xemacs.org>
+
+       * Makefile.am: fix sed -O substitutions to catch -O6, etc.
+
 Tue Oct  6 10:06:32 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
        * rand-unix.c (HAVE_GETTIMEOFDAY): Fixed (was ..GETTIMEOFTIME :-)
index 26c625d..298e0f3 100644 (file)
@@ -49,11 +49,11 @@ EXTRA_twofish_SOURCES = twofish.c
 
 tiger: $(srcdir)/tiger.c
        `echo $(COMPILE) -shared  -fPIC -lc -o tiger $(srcdir)/tiger.c | \
-           sed -e 's/-O2/-O1/' `
+           sed -e 's/-O[2-9]*/-O1/' `
 
 twofish: $(srcdir)/twofish.c
        `echo $(COMPILE) -shared  -fPIC -lc -o twofish $(srcdir)/twofish.c | \
-           sed -e 's/-O2/  /' `
+           sed -e 's/-O[0-9]*/  /' `
 
 
 install-exec-hook:
index accbca9..2d5c173 100644 (file)
@@ -293,6 +293,7 @@ verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey )
     /* u2 = r * w mod q  */
     mpi_mulm( u2, r, w, pkey->q );
 
+
     /* v =  g^u1 * y^u2 mod p mod q */
     base[0] = pkey->g; exp[0] = u1;
     base[1] = pkey->y; exp[1] = u2;
index 0ec6d60..819cc1d 100644 (file)
@@ -495,7 +495,7 @@ md_stop_debug( MD_HANDLE md )
   #ifdef HAVE_U64_TYPEDEF
     {  /* a kludge to pull in the __muldi3 for Solaris */
        volatile u32 a = (u32)(ulong)md;
-       volatile u32 b = 42;
+       volatile u64 b = 42;
        volatile u64 c;
        c = a * b;
     }
index 633b333..ae674ae 100644 (file)
@@ -8,17 +8,6 @@ AC_CONFIG_AUX_DIR(scripts)
 AM_CONFIG_HEADER(config.h)
 
 
-if test "x$exec_prefix" = xNONE ; then
-    if test "x$prefix" = xNONE ; then
-       g10_prefix="$ac_default_prefix"
-    else
-       g10_prefix="$prefix"
-    fi
-else
-    g10_prefix="$exec_prefix"
-fi
-
-
 VERSION=`cat $srcdir/VERSION`
 PACKAGE=gnupg
 ALL_LINGUAS="en de it fr"
@@ -84,6 +73,8 @@ AC_PROG_CPP
 AC_ISC_POSIX
 AC_PROG_RANLIB
 AC_PROG_INSTALL
+AM_CYGWIN32
+
 
 case "${target}" in
     i386--mingw32)
@@ -94,14 +85,11 @@ case "${target}" in
        RANLIB="i386--mingw32-ranlib"
        ac_cv_have_dev_random=no
        AC_DEFINE(USE_RAND_W32)
-       GNUPG_LIBDIR="c:/lib/gnupg"
        ;;
     *)
        AC_DEFINE(USE_RAND_UNIX)
-       GNUPG_LIBDIR="$g10_prefix/lib/gnupg"
        ;;
 esac
-AC_DEFINE_UNQUOTED(GNUPG_LIBDIR, "$GNUPG_LIBDIR")
 
 case "${target}" in
     i386--mingw32)
@@ -254,10 +242,7 @@ fi
 AC_SUBST(ZLIBS)
 
 
-G10_LOCALEDIR="$g10_prefix/$DATADIRNAME/locale"
-AC_SUBST(G10_LOCALEDIR)
-AC_DEFINE_UNQUOTED(G10_LOCALEDIR, "$G10_LOCALEDIR")
-dnl WK_LINK_FILES($nls_cv_header_libgt, $nls_cv_header_intl )
+WK_LINK_FILES($nls_cv_header_libgt, $nls_cv_header_intl )
 
 WK_DO_LINK_FILES
 
@@ -275,5 +260,7 @@ doc/Makefile
 tools/Makefile
 zlib/Makefile
 checks/Makefile
-],[echo timestamp >stamp-h; sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile])
+],[echo timestamp >stamp-h; \
+   sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile
+])
 
index efd412c..dca87af 100644 (file)
@@ -1,16 +1,44 @@
 
-
-    * For packet version 3 we calculate the keyids this way:
-       RSA     := low 64 bits of n
-       ELGAMAL := build a v3 pubkey packet (with CTB 0x99) and calculate
-                  a rmd160 hash value from it. This is used as the
-                  fingerprint and the low 64 bits are the keyid.
-
-    * Revocation certificates consist only of the signature packet;
-      "import" knows how to handle this.  The rationale behind it is
-      to keep them small.
-
-
+Format of "---with-colons" listings
+===================================
+
+sec::1024:17:6C7EE1B8621CC013:1998-07-07:0:::Werner Koch <werner.koch@guug.de>:
+ssb::1536:20:5CE086B5B5A18FF4:1998-07-07:0:::
+
+ 1. Field:  Type of record
+           pub = public key
+           sub = subkey (secondary key)
+           sec = secret key
+           ssb = secret subkey (secondary key)
+           uid = user id (only field 10 is used).
+           fpr = fingerprint: (fingerprint is in field 10)
+
+ 2. Field:  A letter describing the calculated trust, see doc/FAQ
+           (not used for secret keys)
+ 3. Field:  length of key in bits.
+ 4. Field:  Algorithm: 1 = RSA
+                      16 = ElGamal (encrypt only)
+                      17 = DSA (sometimes called DH, sign only)
+                      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)
+ 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
+           able to use "#<local-id> as the user id.  This is needed
+           because keyids may not be unique - a program may use this
+           number to access keys later.
+ 9. Field:  Ownertrust (primary public keys only)
+10. Field:  User-ID.  The value is quoted like a C string to avoid
+           control characters (the colon is quoted "\x3a").
+
+More fields may be added later.
+
+
+Key generation
+==============
     Key generation shows progress by printing different characters to
     stderr:
             "."  Last 10 Miller-Rabin tests failed
@@ -38,7 +66,6 @@
 
 
 
-
 Layout of the TrustDB
 =====================
 The TrustDB is built from fixed length records, where the first byte
@@ -66,7 +93,10 @@ Record type 1:
             against the pubring)
      1 u32  record number of keyhashtable
      1 u32  first free record
-     8 bytes reserved
+     1 u32  record number of shadow directory hash table
+           It does not make sense to combine this table with the key table
+           becuase the keyid is not in every case a part of the fingerprint.
+     4 bytes reserved for version extension record
 
 
 Record type 2: (directory record)
@@ -131,17 +161,46 @@ Record type 5: (pref record)
 
 Record type 6  (sigrec)
 -------------
-    Used to keep track of valid key signatures. Self-signatures are not
-    stored.
+    Used to keep track of key signatures. Self-signatures are not
+    stored.  If a public key is not in the DB, the signature points to
+    a shadow dir record, which in turn has a list of records which
+    might be interested in this key (and the signature record here
+    is one).
 
      1 byte   value 6
      1 byte   reserved
      1 u32    LID          points back to the dir record
-     1 u32    next   next sigrec of this owner or 0 to indicate the
+     1 u32    next   next sigrec of this uid or 0 to indicate the
                     last sigrec.
      6 times
-       1 u32  Local_id of signators dir record
-       1 byte reserved
+       1 u32  Local_id of signators dir or shadow dir record
+       1 byte Flag: Bit 0 = checked: Bit 1 is valid (we have a real
+                             directory record for this)
+                        1 = valid is set (but my be revoked)
+
+
+
+Record type 8: (shadow directory record)
+--------------
+    This record is used to reserved a LID for a public key.  We
+    need this to create the sig records of other keys, even if we
+    do not yet have the public key of the signature.
+    This record (the record number to be more precise) will be reused
+    as the dir record when we import the real public key.
+
+     1 byte value 8
+     1 byte  reserved
+     1 u32   LID      (This is simply the record number of this record.)
+     2 u32   keyid
+     1 byte  pubkey algorithm
+     3 byte reserved
+     1 u32   hintlist  A list of records which have references to
+                       this key.  This is used for fast access to
+                       signature records which are not yet checked.
+                       Note, that this is only a hint and the actual records
+                       may not anymore hold signature records for that key
+                       but that the code cares about this.
+    18 byte reserved
 
 
 
@@ -191,6 +250,9 @@ Record Type 10 (hash table)
     big table. The hash value is simple the 1st, 2nd, ... byte of
     the fingerprint (depending on the indirection level).
 
+    When used to hash shadow directory records, a different table is used
+    and indexed by the keyid.
+
      1 byte value 10
      1 byte reserved
      n u32  recnum; n depends on the record length:
@@ -214,6 +276,7 @@ Record Type 10 (hash table)
 Record type 11 (hash list)
 --------------
     see hash table for an explanation.
+    This is also used for other purposes.
 
     1 byte value 11
     1 byte reserved
@@ -223,7 +286,11 @@ Record type 11 (hash list)
 
     For the current record length of 40, n is 7
 
-Record type 254: (free record)
+
+
+Record type 254 (free record)
+---------------
+    All these records form a linked list of unused records.
      1 byte  value 254
      1 byte  reserved (0)
      1 u32   next_free
@@ -285,6 +352,20 @@ There is one enhancement used with the old style packet headers:
 
 
 
+Other Notes
+===========
+    * For packet version 3 we calculate the keyids this way:
+       RSA     := low 64 bits of n
+       ELGAMAL := build a v3 pubkey packet (with CTB 0x99) and calculate
+                  a rmd160 hash value from it. This is used as the
+                  fingerprint and the low 64 bits are the keyid.
+
+    * Revocation certificates consist only of the signature packet;
+      "import" knows how to handle this.  The rationale behind it is
+      to keep them small.
+
+
+
 
 
 
diff --git a/doc/FAQ b/doc/FAQ
index 62003e2..ee7f810 100644 (file)
--- a/doc/FAQ
+++ b/doc/FAQ
   (ownertrust) to a key.  I have plans to use a cache for calculated
   trust values to speed up calcualtion.
 
-  You can see the calculated trust value using this command:
+  You can see the validity (calculated trust value) using this command:
 
       gpgm --list-keys --with-colons
 
         is only used for keys for which
         the secret key is also available.
 
-  You can get a list of the assigned ownertrust values (how far you trust
-  the owner to correctly sign another another ones key)
+  You can get a list of the assigned trust values (how far you trust
+  the owner to correctly sign another one's key)
 
       gpgm --list-ownertrust
 
    gpg [--options] --sign --encrypt foo.txt
 
 
+  Q: What kind of output is this: "key C26EE891.298, uid 09FB: ...."?
+  A: This is the internal representaion of a user id in the trustdb.
+     "C26EE891" is the keyid, "298" is the local id (a record number
+     in the trustdb) and "09FB" are the last two bytes of a ripe-md-160
+     hash of the user id for this key.
+
+
+  Q: What is trust, validity and ownertrust?
+  A: "ownertrust" is used instead of "trust" to make clear that
+     this is the value you have assigned to key to express, how far you
+     trust the owner of this key to correctly sign (and so introduce)
+     other keys.  "validity" or calculated trust is a value which
+     says, how far the gnupg thinks a key is valid (that it really belongs
+     to the one who claims to be the owner of the key).
+     For more see the chapter "The Web of Trust" in the
+     Manual [gpg: Oops: Internal error: manual not found - sorry]
+
+
+
 
-[That's it for now.)]
index 5a21722..2f76e80 100644 (file)
@@ -12,7 +12,7 @@ B<gpgm> [--homedir name] [--options file] [options] command [args]
 
 B<gpg> is the main program for the GNUPG system. B<gpgm> is a maintenance
 tool which has some commands B<gpgm> does not have; it is there because
-it does not handle sensitive data ans therefore has no need to allocate
+it does not handle sensitive data and therefore has no need to allocate
 secure memory.
 
 =head1 COMMANDS
@@ -315,13 +315,13 @@ B<--marginals-needed> I<n>
 
 B<--cipher-algo> I<name>
     Use I<name> as cipher algorithm. Running the program
-    with the option B<--verbose> yields a list of supported
+    with the command B<--version> yields a list of supported
     algorithms. If this is not used the cipher algorithm is
     selected from the preferences stored with the key.
 
 B<--digest-algo> I<name>
     Use I<name> as message digest algorithm. Running the
-    program with the option B<--verbose> yields a list of
+    program with the command B<--version> yields a list of
     supported algorithms.  Please note that using this
     option may violate the OpenPGP requirement, that a
     160 bit hash is to be used for DSA.
@@ -357,7 +357,7 @@ B<--compress-algo> I<number>
 
 B<--digest-algo> I<name>
     Use I<name> as message digest algorithm. Running the
-    program with the option B<--verbose> yields a list of
+    program with the command B<--version> yields a list of
     supported algorithms.
 
 
index 6e420e5..93a21e2 100644 (file)
@@ -1,3 +1,15 @@
+Thu Oct  8 11:35:51 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * armor.c (is_armored): Ad test on old comment packets.
+
+       * tdbio.c (tdbio_search_dir_bypk): fixed memory leak.
+
+       * getkey.c: Changed the caching algorithms.
+
+Wed Oct  7 19:33:28 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * kbnodes.c (unused_nodes): New.
+
 Wed Oct  7 11:15:36 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
        * keyedit.c (sign_uids): Fixed a problem with SK which could caused
index b38037d..da04fec 100644 (file)
@@ -86,3 +86,4 @@ g10maint.o: $(srcdir)/g10.c
 
 $(PROGRAMS): $(needed_libs)
 
+
index c72526a..df67712 100644 (file)
@@ -165,6 +165,7 @@ is_armored( byte *buf )
       case PKT_PUBKEY_ENC:
       case PKT_SIGNATURE:
       case PKT_COMMENT:
+      case PKT_OLD_COMMENT:
       case PKT_PLAINTEXT:
       case PKT_COMPRESSED:
       case PKT_ENCRYPTED:
index ca9b44d..9195d21 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -41,6 +41,7 @@
 #include "ttyio.h"
 #include "i18n.h"
 #include "status.h"
+#include "g10defs.h"
 
 #ifndef IS_G10MAINT
   #define IS_G10 1
@@ -503,8 +504,8 @@ main( int argc, char **argv )
     log_set_name("gpg");
     secure_random_alloc(); /* put random number into secure memory */
     disable_core_dumps();
-    init_signals();
   #endif
+    init_signals();
     i18n_init();
     opt.compress = -1; /* defaults to standard compress level */
     /* fixme: set the next two to zero and decide where used */
@@ -571,7 +572,6 @@ main( int argc, char **argv )
     /* Okay, we are now working under our real uid */
   #endif
 
-
     if( default_config )
        configname = make_filename(opt.homedir, "options", NULL );
 
@@ -1232,6 +1232,8 @@ main( int argc, char **argv )
 void
 g10_exit( int rc )
 {
+    if( opt.debug & DBG_MEMSTAT_VALUE )
+       m_print_stats("on exit");
     if( opt.debug )
        secmem_dump_stats();
     secmem_term();
index 886d53c..6e4c345 100644 (file)
 #include "main.h"
 #include "i18n.h"
 
-#define MAX_PK_CACHE_ENTRIES 500
+#define MAX_UNK_CACHE_ENTRIES 1000
+#define MAX_PK_CACHE_ENTRIES   50
+#define MAX_UID_CACHE_ENTRIES  50
 
 
-typedef struct keyid_list {
-    struct keyid_list *next;
-    u32 keyid[2];
-} *keyid_list_t;
-
-typedef struct user_id_db {
-    struct user_id_db *next;
-    u32 keyid[2];
-    int len;
-    char name[1];
-} *user_id_db_t;
-
-typedef struct pk_cache_entry {
-    struct pk_cache_entry *next;
-    u32 keyid[2];
-    PKT_public_key *pk;
-} *pk_cache_entry_t;
-
 typedef struct enum_seckey_context {
     int eof;
     STRLIST sl;
@@ -64,10 +48,39 @@ typedef struct enum_seckey_context {
 static STRLIST keyrings;
 static STRLIST secret_keyrings;
 
-static keyid_list_t unknown_keyids;
+#if MAX_UNK_CACHE_ENTRIES
+  typedef struct keyid_list {
+      struct keyid_list *next;
+      u32 keyid[2];
+  } *keyid_list_t;
+  static keyid_list_t unknown_keyids;
+  static int unk_cache_entries;   /* number of entries in unknown keys cache */
+  static int unk_cache_disabled;
+#endif
+
+#if MAX_PK_CACHE_ENTRIES
+  typedef struct pk_cache_entry {
+      struct pk_cache_entry *next;
+      u32 keyid[2];
+      PKT_public_key *pk;
+  } *pk_cache_entry_t;
+  static pk_cache_entry_t pk_cache;
+  static int pk_cache_entries;  /* number of entries in pk cache */
+  static int pk_cache_disabled;
+#endif
+
+#if MAX_UID_CACHE_ENTRIES < 5
+    #error we really need the userid cache
+#endif
+typedef struct user_id_db {
+    struct user_id_db *next;
+    u32 keyid[2];
+    int len;
+    char name[1];
+} *user_id_db_t;
 static user_id_db_t user_id_db;
-static pk_cache_entry_t pk_cache;
-static int pk_cache_entries;   /* number of entries in pk cache */
+static int uid_cache_entries;  /* number of entries in uid cache */
+
 
 
 static int lookup( PKT_public_key *pk,
@@ -166,9 +179,13 @@ add_secret_keyring( const char *name )
 static void
 cache_public_key( PKT_public_key *pk )
 {
+  #if MAX_PK_CACHE_ENTRIES
     pk_cache_entry_t ce;
     u32 keyid[2];
 
+    if( pk_cache_disabled )
+       return;
+
     if( is_ELGAMAL(pk->pubkey_algo)
        || pk->pubkey_algo == PUBKEY_ALGO_DSA
        || is_RSA(pk->pubkey_algo) ) {
@@ -184,24 +201,20 @@ cache_public_key( PKT_public_key *pk )
            return;
        }
 
-    if( pk_cache_entries > MAX_PK_CACHE_ENTRIES ) {
-       /* FIMXE: use another algorithm to free some cache slots */
-       if( pk_cache_entries == MAX_PK_CACHE_ENTRIES )  {
-           pk_cache_entries++;
-           log_info("too many entries in pk cache - disabled\n");
-       }
-       ce = pk_cache;
-       free_public_key( ce->pk );
-    }
-    else {
-       pk_cache_entries++;
-       ce = m_alloc( sizeof *ce );
-       ce->next = pk_cache;
-       pk_cache = ce;
+    if( pk_cache_entries >= MAX_PK_CACHE_ENTRIES ) {
+       /* fixme: use another algorithm to free some cache slots */
+       pk_cache_disabled=1;
+       log_info("too many entries in pk cache - disabled\n");
+       return;
     }
+    pk_cache_entries++;
+    ce = m_alloc( sizeof *ce );
+    ce->next = pk_cache;
+    pk_cache = ce;
     ce->pk = copy_public_key( NULL, pk );
     ce->keyid[0] = keyid[0];
     ce->keyid[1] = keyid[1];
+  #endif
 }
 
 
@@ -220,6 +233,13 @@ cache_user_id( PKT_user_id *uid, u32 *keyid )
            return;
        }
 
+    if( uid_cache_entries >= MAX_UID_CACHE_ENTRIES ) {
+       /* fixme: use another algorithm to free some cache slots */
+       r = user_id_db;
+       user_id_db = r->next;
+       m_free(r);
+       uid_cache_entries--;
+    }
     r = m_alloc( sizeof *r + uid->len-1 );
     r->keyid[0] = keyid[0];
     r->keyid[1] = keyid[1];
@@ -227,6 +247,7 @@ cache_user_id( PKT_user_id *uid, u32 *keyid )
     memcpy(r->name, uid->name, r->len);
     r->next = user_id_db;
     user_id_db = r;
+    uid_cache_entries++;
 }
 
 
@@ -239,23 +260,30 @@ cache_user_id( PKT_user_id *uid, u32 *keyid )
 int
 get_pubkey( PKT_public_key *pk, u32 *keyid )
 {
-    keyid_list_t kl;
     int internal = 0;
     int rc = 0;
-    pk_cache_entry_t ce;
 
-    /* let's see whether we checked the keyid already */
-    for( kl = unknown_keyids; kl; kl = kl->next )
-       if( kl->keyid[0] == keyid[0] && kl->keyid[1] == keyid[1] )
-           return G10ERR_NO_PUBKEY; /* already checked and not found */
-
-    /* Try to get it from our cache */
-    for( ce = pk_cache; ce; ce = ce->next )
-       if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) {
-           if( pk )
-               copy_public_key( pk, ce->pk );
-           return 0;
+  #if MAX_UNK_CACHE_ENTRIES
+    {  /* let's see whether we checked the keyid already */
+       keyid_list_t kl;
+       for( kl = unknown_keyids; kl; kl = kl->next )
+           if( kl->keyid[0] == keyid[0] && kl->keyid[1] == keyid[1] )
+               return G10ERR_NO_PUBKEY; /* already checked and not found */
+    }
+  #endif
+
+  #if MAX_PK_CACHE_ENTRIES
+    {  /* Try to get it from the cache */
+       pk_cache_entry_t ce;
+       for( ce = pk_cache; ce; ce = ce->next ) {
+           if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) {
+               if( pk )
+                   copy_public_key( pk, ce->pk );
+               return 0;
+           }
        }
+    }
+  #endif
     /* more init stuff */
     if( !pk ) {
        pk = m_alloc_clear( sizeof *pk );
@@ -268,12 +296,24 @@ get_pubkey( PKT_public_key *pk, u32 *keyid )
     if( !rc )
        goto leave;
 
+  #if MAX_UNK_CACHE_ENTRIES
     /* not found: store it for future reference */
-    kl = m_alloc( sizeof *kl );
-    kl->keyid[0] = keyid[0];
-    kl->keyid[1] = keyid[1];
-    kl->next = unknown_keyids;
-    unknown_keyids = kl;
+    if( unk_cache_disabled )
+       ;
+    else if( ++unk_cache_entries > MAX_UNK_CACHE_ENTRIES ) {
+       unk_cache_disabled = 1;
+       log_info("too many entries in unk cache - disabled\n");
+    }
+    else {
+       keyid_list_t kl;
+
+       kl = m_alloc( sizeof *kl );
+       kl->keyid[0] = keyid[0];
+       kl->keyid[1] = keyid[1];
+       kl->next = unknown_keyids;
+       unknown_keyids = kl;
+    }
+  #endif
     rc = G10ERR_NO_PUBKEY;
 
   leave:
@@ -829,9 +869,10 @@ lookup( PKT_public_key *pk, int mode,  u32 *keyid,
                            break;
                    }
                    else if( mode == 16 || mode == 20 ) {
+                       byte afp[MAX_FINGERPRINT_LEN];
                        size_t an;
-                       byte *afp = fingerprint_from_pk(
-                                       k->pkt->pkt.public_key, NULL, &an );
+
+                       fingerprint_from_pk(k->pkt->pkt.public_key, afp, &an );
 
                        if( DBG_CACHE ) {
                            u32 aki[2];
@@ -845,10 +886,8 @@ lookup( PKT_public_key *pk, int mode,  u32 *keyid,
                            && ( !pk->pubkey_algo
                                 || pk->pubkey_algo
                                    == k->pkt->pkt.public_key->pubkey_algo) ) {
-                           m_free(afp);
                            break;
                        }
-                       m_free(afp);
                    }
                    else
                        BUG();
@@ -1008,16 +1047,15 @@ lookup_sk( PKT_secret_key *sk, int mode,  u32 *keyid, const char *name,
                    }
                    else if( mode == 16 || mode == 20 ) {
                        size_t an;
-                       byte *afp = fingerprint_from_sk(
-                                       k->pkt->pkt.secret_key, NULL, &an );
+                       byte afp[MAX_FINGERPRINT_LEN];
+
+                       fingerprint_from_sk(k->pkt->pkt.secret_key, afp, &an );
                        if( an == mode && !memcmp( afp, name, an)
                            && ( !sk->pubkey_algo
                                 || sk->pubkey_algo
                                    == k->pkt->pkt.secret_key->pubkey_algo) ) {
-                           m_free(afp);
                            break;
                        }
-                       m_free(afp);
                    }
                    else
                        BUG();
index 4287681..18b16d0 100644 (file)
 #include "packet.h"
 #include "keydb.h"
 
+#define USE_UNUSED_NODES 1
 
+static KBNODE unused_nodes;
 
 KBNODE
 new_kbnode( PACKET *pkt )
 {
-    KBNODE n = m_alloc( sizeof *n );
+    KBNODE n;
+
+    n = unused_nodes;
+    if( n )
+       unused_nodes = n->next;
+    else
+       n = m_alloc( sizeof *n );
     n->next = NULL;
     n->pkt = pkt;
     n->flag = 0;
@@ -45,7 +53,13 @@ new_kbnode( PACKET *pkt )
 KBNODE
 clone_kbnode( KBNODE node )
 {
-    KBNODE n = m_alloc( sizeof *n );
+    KBNODE n;
+
+    n = unused_nodes;
+    if( n )
+       unused_nodes = n->next;
+    else
+       n = m_alloc( sizeof *n );
     n->next = NULL;
     n->pkt = node->pkt;
     n->flag = 0;
@@ -61,9 +75,16 @@ release_kbnode( KBNODE n )
 
     while( n ) {
        n2 = n->next;
-       if( !(n->private_flag & 2) )
+       if( !(n->private_flag & 2) ) {
            free_packet( n->pkt );
+           m_free( n->pkt );
+       }
+      #if USE_UNUSED_NODES
+       n->next = unused_nodes;
+       unused_nodes = n;
+      #else
        m_free( n );
+      #endif
        n = n2;
     }
 }
@@ -230,9 +251,16 @@ commit_kbnode( KBNODE *root )
                *root = nl = n->next;
            else
                nl->next = n->next;
-           if( !(n->private_flag & 2) )
+           if( !(n->private_flag & 2) ) {
                free_packet( n->pkt );
+               m_free( n->pkt );
+           }
+         #if USE_UNUSED_NODES
+           n->next = unused_nodes;
+           unused_nodes = n;
+         #else
            m_free( n );
+         #endif
            changed = 1;
        }
        else
index 6f9c1c7..ea64d38 100644 (file)
@@ -902,10 +902,11 @@ show_key_and_fingerprint( KBNODE keyblock )
 static void
 show_fingerprint( PKT_public_key *pk )
 {
-    byte *array, *p;
+    byte array[MAX_FINGERPRINT_LEN], *p;
     size_t i, n;
 
-    p = array = fingerprint_from_pk( pk, NULL, &n );
+    fingerprint_from_pk( pk, array, &n );
+    p = array;
     tty_printf("             Fingerprint:");
     if( n == 20 ) {
        for(i=0; i < n ; i++, i++, p += 2 ) {
@@ -922,7 +923,6 @@ show_fingerprint( PKT_public_key *pk )
        }
     }
     tty_printf("\n");
-    m_free(array);
 }
 
 
index 2de67cc..387c3fa 100644 (file)
@@ -330,7 +330,7 @@ expirestr_from_sk( PKT_secret_key *sk )
 /**************** .
  * Return a byte array with the fingerprint for the given PK/SK
  * The length of the array is returned in ret_len. Caller must free
- * the array or provide array as buffer of length MAX_FINGERPRINT_LEN
+ * the array or provide an array of length MAX_FINGERPRINT_LEN.
  */
 
 byte *
index e5c8328..a47885b 100644 (file)
@@ -413,11 +413,14 @@ print_userid( PACKET *pkt )
 static void
 print_fingerprint( PKT_public_key *pk, PKT_secret_key *sk )
 {
-    byte *array, *p;
+    byte array[MAX_FINGERPRINT_LEN], *p;
     size_t i, n;
 
-    p = array = sk? fingerprint_from_sk( sk, NULL, &n )
-                  : fingerprint_from_pk( pk, NULL, &n );
+    if( sk )
+       fingerprint_from_sk( sk, array, &n );
+    else
+       fingerprint_from_pk( pk, array, &n );
+    p = array;
     if( opt.with_colons ) {
        printf("fpr:::::::::");
        for(i=0; i < n ; i++, p++ )
@@ -442,7 +445,6 @@ print_fingerprint( PKT_public_key *pk, PKT_secret_key *sk )
        }
     }
     putchar('\n');
-    m_free(array);
 }
 
 
index 61d1e4c..74c11cb 100644 (file)
@@ -57,7 +57,7 @@ gen_revoke( const char *uname )
     KBPOS kbpos;
 
     if( opt.batch ) {
-       log_error("sorry, can't do this in batch mode\n");
+       log_error(_("sorry, can't do this in batch mode\n"));
        return G10ERR_GENERAL;
     }
 
@@ -70,21 +70,21 @@ gen_revoke( const char *uname )
     /* search the userid */
     rc = find_secret_keyblock_byname( &kbpos, uname );
     if( rc ) {
-       log_error("secret key for user '%s' not found\n", uname );
+       log_error(_("secret key for user '%s' not found\n"), uname );
        goto leave;
     }
 
     /* read the keyblock */
     rc = read_keyblock( &kbpos, &keyblock );
     if( rc ) {
-       log_error("error reading the certificate: %s\n", g10_errstr(rc) );
+       log_error(_("error reading the certificate: %s\n"), g10_errstr(rc) );
        goto leave;
     }
 
     /* get the keyid from the keyblock */
     node = find_kbnode( keyblock, PKT_SECRET_KEY );
     if( !node ) { /* maybe better to use log_bug ? */
-       log_error("Oops; secret key not found anymore!\n");
+       log_error(_("Oops; secret key not found anymore!\n"));
        rc = G10ERR_GENERAL;
        goto leave;
     }
@@ -107,11 +107,11 @@ gen_revoke( const char *uname )
     pk = m_alloc_clear( sizeof *pk );
     rc = get_pubkey( pk, sk_keyid );
     if( rc ) {
-       log_error("no corresponding public key: %s\n", g10_errstr(rc) );
+       log_error(_("no corresponding public key: %s\n"), g10_errstr(rc) );
        goto leave;
     }
     if( cmp_public_secret_key( pk, sk ) ) {
-       log_error("public key does not match secret key!\n" );
+       log_error(_("public key does not match secret key!\n") );
        rc = G10ERR_GENERAL;
        goto leave;
     }
@@ -125,11 +125,11 @@ gen_revoke( const char *uname )
 
     switch( is_secret_key_protected( sk ) ) {
       case -1:
-       log_error("unknown protection algorithm\n");
+       log_error(_("unknown protection algorithm\n"));
        rc = G10ERR_PUBKEY_ALGO;
        break;
       case 0:
-       tty_printf("Warning: This key is not protected!\n");
+       tty_printf(_("note: This key is not protected!\n"));
        break;
       default:
        rc = check_secret_key( sk, 0 );
@@ -140,7 +140,7 @@ gen_revoke( const char *uname )
 
 
     if( !opt.armor )
-       tty_printf("ASCII armored output forced.\n");
+       tty_printf(_("ASCII armored output forced.\n"));
 
     if( (rc = open_outfile( NULL, 0, &out )) )
        goto leave;
@@ -155,7 +155,7 @@ gen_revoke( const char *uname )
     /* create it */
     rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0, NULL, NULL);
     if( rc ) {
-       log_error("make_keysig_packet failed: %s\n", g10_errstr(rc));
+       log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc));
        goto leave;
     }
     init_packet( &pkt );
@@ -164,17 +164,17 @@ gen_revoke( const char *uname )
 
     rc = build_packet( out, &pkt );
     if( rc ) {
-       log_error("build_packet failed: %s\n", g10_errstr(rc) );
+       log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
        goto leave;
     }
 
     /* and issue a usage notice */
-    tty_printf("Revocation certificate created.\n\n"
+    tty_printf(_("Revocation certificate created.\n\n"
 "Please move it to a medium which you can hide away; if Mallory gets\n"
 "access to this certificate he can use it to make your key unusable.\n"
 "It is smart to print this certificate and store it away, just in case\n"
 "your media become unreadable.  But have some caution:  The print system of\n"
-"your machine might store the data and make it available to others!\n");
+"your machine might store the data and make it available to others!\n"));
 
 
 
index ace7adc..677420e 100644 (file)
@@ -679,9 +679,11 @@ keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
            /* skip pakets at the beginning of a keyring, until we find
             * a start packet; issue a warning if it is not a comment */
            if( !root && pkt->pkttype != PKT_COMMENT
-                     && pkt->pkttype != PKT_OLD_COMMENT )
+                     && pkt->pkttype != PKT_OLD_COMMENT ) {
                log_info("keyring_enum: skipped packet of type %d\n",
                            pkt->pkttype );
+               break;
+           }
            if( !root || (skipsigs && ( pkt->pkttype == PKT_SIGNATURE
                                      ||pkt->pkttype == PKT_COMMENT
                                      ||pkt->pkttype == PKT_OLD_COMMENT )) ) {
@@ -704,6 +706,7 @@ keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
        *ret_root = root;
     free_packet( pkt );
     m_free( pkt );
+
     return rc;
 }
 
index 70cf4a1..82b22b4 100644 (file)
 #include "trustdb.h"
 #include "tdbio.h"
 
+/* a type used to pass infomation to cmp_krec_fpr */
+struct cmp_krec_fpr_struct {
+    int pubkey_algo;
+    const char *fpr;
+    int fprlen;
+};
+
+/* a type used to pass infomation to cmp_sdir */
+struct cmp_sdir_struct {
+    int pubkey_algo;
+    u32 keyid[2];
+};
 
 
 static char *db_name;
@@ -149,6 +161,47 @@ open_db()
 
 
 /****************
+ * Make a hashtable: type 0 = key hash, 1 = sdir hash
+ */
+static void
+create_hashtable( TRUSTREC *vr, int type )
+{
+    TRUSTREC rec;
+    off_t offset;
+    ulong recnum;
+    int i, n, rc;
+
+    offset = lseek( db_fd, 0, SEEK_END );
+    if( offset == -1 )
+       log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
+    recnum = offset / TRUST_RECORD_LEN;
+    assert(recnum); /* this is will never be the first record */
+
+    if( !type )
+       vr->r.ver.keyhashtbl = recnum;
+    else
+       vr->r.ver.sdirhashtbl = recnum;
+    /* Now write the records */
+    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.recnum = recnum;
+        rc = tdbio_write_record( &rec );
+        if( rc )
+            log_fatal_f(db_name,_("failed to create hashtable: %s\n"),
+                                                g10_errstr(rc));
+    }
+    /* update the version record */
+    rc = tdbio_write_record( vr );
+    if( rc )
+       log_fatal_f( db_name, _("error updating version record: %s\n"),
+                                                            g10_errstr(rc));
+}
+
+
+
+/****************
  * Return the record number of the keyhash tbl or create a new one.
  */
 static ulong
@@ -165,48 +218,45 @@ get_keyhashrec()
     if( rc )
        log_fatal_f( db_name, _("error reading version record: %s\n"),
                                                        g10_errstr(rc) );
-    if( vr.r.ver.keyhashtbl )
-       keyhashtbl = vr.r.ver.keyhashtbl;
-    else {
-       TRUSTREC rec;
-       off_t offset;
-       ulong recnum;
-       int i, n;
+    if( !vr.r.ver.keyhashtbl )
+       create_hashtable( &vr, 0 );
 
-       offset = lseek( db_fd, 0, SEEK_END );
-       if( offset == -1 )
-           log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
-       recnum = offset / TRUST_RECORD_LEN;
-       assert(recnum); /* this is will never be the first record */
 
-       keyhashtbl = recnum;
-       /* Now write the records */
-       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.recnum = recnum;
-            rc = tdbio_write_record( &rec );
-            if( rc )
-                log_fatal_f(db_name,_("failed to create hashtable: %s\n"),
-                                                    g10_errstr(rc));
-       }
-       /* update the version record */
-       vr.r.ver.keyhashtbl = keyhashtbl;
-       rc = tdbio_write_record( &vr );
-       if( rc )
-           log_fatal_f( db_name, _("error updating version record: %s\n"),
-                                                            g10_errstr(rc));
-    }
-    return keyhashtbl;
+    return vr.r.ver.keyhashtbl;
+}
+
+/****************
+ * Return the record number of the shadow direcory hash table
+ * or create a new one.
+ */
+static ulong
+get_sdirhashrec()
+{
+    static ulong sdirhashtbl; /* record number of the hashtable */
+    TRUSTREC vr;
+    int rc;
+
+    if( sdirhashtbl )
+       return sdirhashtbl;
+
+    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;
 }
 
 
 /****************
- * Update the key hashtbl or create the table if it does not exist
+ * Update a hashtable.
+ * table gives the start of the table, key and keylen is the key,
+ * newrecnum is the record number to insert.
  */
 static int
-update_keyhashtbl( TRUSTREC *kr )
+upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
 {
     TRUSTREC lastrec, rec;
     ulong hashrec, item;
@@ -214,40 +264,40 @@ update_keyhashtbl( TRUSTREC *kr )
     int level=0;
     int rc, i;
 
-    hashrec = get_keyhashrec();
+    hashrec = table;
   next_level:
-    msb = kr->r.key.fingerprint[level];
+    msb = key[level];
     hashrec += msb / ITEMS_PER_HTBL_RECORD;
     rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL );
     if( rc ) {
-       log_error( db_name, "update_keyhashtbl read failed: %s\n",
+       log_error( db_name, "upd_hashtable: read failed: %s\n",
                                                        g10_errstr(rc) );
        return rc;
     }
 
     item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
-    if( !item ) { /* insert new one */
-       rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = kr->recnum;
+    if( !item ) { /* insert a new item into the hash table */
+       rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = newrecnum;
        rc = tdbio_write_record( &rec );
        if( rc ) {
-           log_error( db_name, "update_keyhashtbl write htbl failed: %s\n",
+           log_error( db_name, "upd_hashtable: write htbl failed: %s\n",
                                                            g10_errstr(rc) );
            return rc;
        }
     }
-    else if( item != kr->recnum ) {  /* must do an update */
+    else if( item != newrecnum ) {  /* must do an update */
        lastrec = rec;
        rc = tdbio_read_record( item, &rec, 0 );
        if( rc ) {
-           log_error( db_name, "update_keyhashtbl read item failed: %s\n",
+           log_error( db_name, "upd_hashtable: read item failed: %s\n",
                                                            g10_errstr(rc) );
            return rc;
        }
        if( rec.rectype == RECTYPE_HTBL ) {
            hashrec = item;
            level++;
-           if( level >= kr->r.key.fingerprint_len ) {
-               log_error( db_name, "keyhashtbl has invalid indirections\n");
+           if( level >= keylen ) {
+               log_error( db_name, "hashtable has invalid indirections.\n");
                return G10ERR_TRUSTDB;
            }
            goto next_level;
@@ -256,15 +306,13 @@ update_keyhashtbl( TRUSTREC *kr )
            /* see whether the key is already in this list */
            for(;;) {
                for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
-                   if( rec.r.hlst.rnum[i] == kr->recnum ) {
-                       log_debug("HTBL: no update needed for keyrec %lu\n",
-                                   kr->recnum );
-                       return 0;
+                   if( rec.r.hlst.rnum[i] == newrecnum ) {
+                       return 0; /* okay, already in the list */
                    }
                }
                if( rec.r.hlst.next ) {
                    rc = tdbio_read_record( rec.r.hlst.next,
-                                                       &rec, RECTYPE_HLST);
+                                                      &rec, RECTYPE_HLST);
                    if( rc ) {
                        log_error( db_name,
                                   "scan keyhashtbl read hlst failed: %s\n",
@@ -279,13 +327,13 @@ update_keyhashtbl( TRUSTREC *kr )
            for(;;) {
                for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
                    if( !rec.r.hlst.rnum[i] ) {
-                       rec.r.hlst.rnum[i] = kr->recnum;
+                       rec.r.hlst.rnum[i] = newrecnum;
                        rc = tdbio_write_record( &rec );
                        if( rc )
                            log_error( db_name,
-                                  "update_keyhashtbl write hlst failed: %s\n",
+                                  "upd_hashtable: write hlst failed: %s\n",
                                                              g10_errstr(rc) );
-                       return rc; /* ready */
+                       return rc; /* done */
                    }
                }
                if( rec.r.hlst.next ) {
@@ -293,7 +341,7 @@ update_keyhashtbl( TRUSTREC *kr )
                                                      &rec, RECTYPE_HLST );
                    if( rc ) {
                        log_error( db_name,
-                                  "update_keyhashtbl read hlst failed: %s\n",
+                                  "upd_hashtable: read hlst failed: %s\n",
                                                             g10_errstr(rc) );
                        return rc;
                    }
@@ -303,26 +351,26 @@ update_keyhashtbl( TRUSTREC *kr )
                    rc = tdbio_write_record( &rec );
                    if( rc ) {
                        log_error( db_name,
-                              "update_keyhashtbl write hlst failed: %s\n",
+                              "upd_hashtable: write hlst failed: %s\n",
                                                          g10_errstr(rc) );
                        return rc;
                    }
                    memset( &rec, 0, sizeof rec );
                    rec.rectype = RECTYPE_HLST;
                    rec.recnum = item;
-                   rec.r.hlst.rnum[0] = kr->recnum;
+                   rec.r.hlst.rnum[0] = newrecnum;
+                   rc = tdbio_write_record( &rec );
                    if( rc )
                        log_error( db_name,
-                              "update_keyhashtbl write ext hlst failed: %s\n",
+                              "upd_hashtable: write ext hlst failed: %s\n",
                                                          g10_errstr(rc) );
-                   return rc; /* ready */
+                   return rc; /* done */
                }
-           }
+           } /* end loop over hlst slots */
        }
-       else if( rec.rectype == RECTYPE_KEY ) { /* insert a list record */
-           if( rec.recnum == kr->recnum ) {
-               log_debug("HTBL: no update needed for keyrec %lu\n",
-                                                        kr->recnum );
+       else if( rec.rectype == RECTYPE_KEY
+                || rec.rectype == RECTYPE_SDIR ) { /* insert a list record */
+           if( rec.recnum == newrecnum ) {
                return 0;
            }
            item = rec.recnum; /* save number of key record */
@@ -330,11 +378,11 @@ update_keyhashtbl( TRUSTREC *kr )
            rec.rectype = RECTYPE_HLST;
            rec.recnum = tdbio_new_recnum();
            rec.r.hlst.rnum[0] = item;       /* old keyrecord */
-           rec.r.hlst.rnum[1] = kr->recnum; /* and new one */
+           rec.r.hlst.rnum[1] = newrecnum; /* and new one */
            rc = tdbio_write_record( &rec );
            if( rc ) {
                log_error( db_name,
-                      "update_keyhashtbl write new hlst failed: %s\n",
+                      "upd_hashtable: write new hlst failed: %s\n",
                                                  g10_errstr(rc) );
                return rc;
            }
@@ -342,13 +390,12 @@ update_keyhashtbl( TRUSTREC *kr )
            lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum;
            rc = tdbio_write_record( &lastrec );
            if( rc )
-               log_error( db_name,
-                      "update_keyhashtbl update htbl failed: %s\n",
-                                                 g10_errstr(rc) );
+               log_error( db_name, "upd_hashtable: update htbl failed: %s\n",
+                                                            g10_errstr(rc) );
            return rc; /* ready */
        }
        else {
-           log_error( db_name, "keyhashtbl %lu points to an invalid record\n",
+           log_error( db_name, "hashtbl %lu points to an invalid record\n",
                                                                    item);
            return G10ERR_TRUSTDB;
        }
@@ -359,6 +406,119 @@ update_keyhashtbl( TRUSTREC *kr )
 
 
 
+/****************
+ * Lookup a record via the hashtable tablewith key/keylen and return the
+ * result in rec.  cmp() should return if the record is the desired one.
+ * Returns -1 if not found, 0 if found or another errocode
+ */
+static int
+lookup_hashtable( ulong table, const byte *key, size_t keylen,
+                 int (*cmpfnc)(void*, const TRUSTREC *), void *cmpdata,
+                                               TRUSTREC *rec )
+{
+    int rc;
+    ulong hashrec, item;
+    int msb;
+    int level=0;
+
+    hashrec = table;
+  next_level:
+    msb = key[level];
+    hashrec += msb / ITEMS_PER_HTBL_RECORD;
+    rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL );
+    if( rc ) {
+       log_error( db_name, "lookup_hashtable failed: %s\n", g10_errstr(rc) );
+       return rc;
+    }
+
+    item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
+    if( !item )
+       return -1; /* not found */
+
+    rc = tdbio_read_record( item, rec, 0 );
+    if( rc ) {
+       log_error( db_name, "hashtable read 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");
+           return G10ERR_TRUSTDB;
+       }
+       goto next_level;
+    }
+    else if( rec->rectype == RECTYPE_HLST ) {
+       for(;;) {
+           int i;
+
+           for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
+               if( rec->r.hlst.rnum[i] ) {
+                   TRUSTREC tmp;
+
+                   rc = tdbio_read_record( rec->r.hlst.rnum[i], &tmp, 0 );
+                   if( rc ) {
+                       log_error( "lookup_hashtable: read item failed: %s\n",
+                                                             g10_errstr(rc) );
+                       return rc;
+                   }
+                   if( (*cmpfnc)( cmpdata, &tmp ) ) {
+                       *rec = tmp;
+                       return 0;
+                   }
+               }
+           }
+           if( rec->r.hlst.next ) {
+               rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST );
+               if( rc ) {
+                   log_error( "lookup_hashtable: read hlst failed: %s\n",
+                                                        g10_errstr(rc) );
+                   return rc;
+               }
+           }
+           else
+               return -1; /* not found */
+       }
+    }
+
+
+    if( (*cmpfnc)( cmpdata, rec ) )
+       return 0; /* really found */
+
+    return -1; /* no: not found */
+}
+
+
+
+
+/****************
+ * Update the key hashtbl or create the table if it does not exist
+ */
+static int
+update_keyhashtbl( TRUSTREC *kr )
+{
+    return upd_hashtable( get_keyhashrec(),
+                         kr->r.key.fingerprint,
+                         kr->r.key.fingerprint_len, kr->recnum );
+}
+
+/****************
+ * Update the shadow dir hashtbl or create the table if it does not exist
+ */
+static int
+update_sdirhashtbl( TRUSTREC *sr )
+{
+    byte key[8];
+
+    u32tobuf( key   , sr->r.sdir.keyid[0] );
+    u32tobuf( key+4 , sr->r.sdir.keyid[1] );
+    return upd_hashtable( get_sdirhashrec(), key, 8, sr->recnum );
+}
+
+
+
+
 void
 tdbio_dump_record( TRUSTREC *rec, FILE *fp  )
 {
@@ -371,8 +531,9 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp  )
     switch( rec->rectype ) {
       case 0: fprintf(fp, "blank\n");
        break;
-      case RECTYPE_VER: fprintf(fp, "version, keyhashtbl=%lu, firstfree=%lu\n",
-           rec->r.ver.keyhashtbl, rec->r.ver.firstfree );
+      case RECTYPE_VER: fprintf(fp, "version, kd=%lu, sd=%lu, free=%lu\n",
+           rec->r.ver.keyhashtbl, rec->r.ver.sdirhashtbl,
+                                  rec->r.ver.firstfree );
        break;
       case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next );
        break;
@@ -411,6 +572,10 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp  )
                    rec->r.uid.prefrec,
                    rec->r.uid.siglist,
                    rec->r.uid.namehash[18], rec->r.uid.namehash[19]);
+       if( rec->r.uid.uidflags & UIDF_CHECKED )
+           fputs(", checked", fp );
+       if( rec->r.uid.uidflags & UIDF_VALID )
+           fputs(", valid", fp );
        if( rec->r.uid.uidflags & UIDF_REVOKED )
            fputs(", revoked", fp );
        putc('\n', fp);
@@ -436,6 +601,14 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp  )
        }
        putc('\n', fp);
        break;
+      case RECTYPE_SDIR:
+       fprintf(fp, "sdir %lu, keyid=%08lX%08lX, algo=%d, hint=%lu\n",
+                   rec->r.sdir.lid,
+                   (ulong)rec->r.sdir.keyid[0],
+                   (ulong)rec->r.sdir.keyid[1],
+                   rec->r.sdir.pubkey_algo,
+                   (ulong)rec->r.sdir.hintlist );
+       break;
       case RECTYPE_CACH:
        fprintf(fp, "cach\n");
        break;
@@ -483,6 +656,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
        return G10ERR_READ_FILE;
     }
     rec->recnum = recnum;
+    rec->dirty = 0;
     p = buf;
     rec->rectype = *p++;
     if( expected && rec->rectype != expected ) {
@@ -508,6 +682,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
        rec->r.ver.validated= buftoulong(p); p += 4;
        rec->r.ver.keyhashtbl=buftoulong(p); p += 4;
        rec->r.ver.firstfree =buftoulong(p); p += 4;
+       rec->r.ver.sdirhashtbl =buftoulong(p); p += 4;
        if( recnum ) {
            log_error_f( db_name, "version record with recnum %lu\n",
                                                             (ulong)recnum );
@@ -568,6 +743,19 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
            rec->r.sig.sig[i].flag = *p++;
        }
        break;
+      case RECTYPE_SDIR:   /* shadow directory record */
+       rec->r.sdir.lid     = buftoulong(p); p += 4;
+       rec->r.sdir.keyid[0]= buftou32(p); p += 4;
+       rec->r.sdir.keyid[1]= buftou32(p); p += 4;
+       rec->r.sdir.pubkey_algo = *p++;
+       p += 3;
+       rec->r.sdir.hintlist = buftoulong(p);
+       if( rec->r.sdir.lid != recnum ) {
+           log_error_f( db_name, "sdir LID != recnum (%lu,%lu)\n",
+                                        rec->r.sdir.lid, (ulong)recnum );
+           rc = G10ERR_TRUSTDB;
+       }
+       break;
       case RECTYPE_CACH:   /* cache record (FIXME)*/
        rec->r.cache.lid    = buftoulong(p); p += 4;
        memcpy(rec->r.cache.blockhash, p, 20); p += 20;
@@ -609,6 +797,8 @@ tdbio_write_record( TRUSTREC *rec )
     if( db_fd == -1 )
        open_db();
 
+tdbio_dump_record( rec, stdout );
+
     memset(buf, 0, TRUST_RECORD_LEN);
     p = buf;
     *p++ = rec->rectype; p++;
@@ -626,6 +816,7 @@ tdbio_write_record( TRUSTREC *rec )
        ulongtobuf(p, rec->r.ver.validated); p += 4;
        ulongtobuf(p, rec->r.ver.keyhashtbl); p += 4;
        ulongtobuf(p, rec->r.ver.firstfree ); p += 4;
+       ulongtobuf(p, rec->r.ver.sdirhashtbl ); p += 4;
        break;
 
       case RECTYPE_FREE:
@@ -677,6 +868,15 @@ tdbio_write_record( TRUSTREC *rec )
        }
        break;
 
+      case RECTYPE_SDIR:
+       ulongtobuf( p, rec->r.sdir.lid); p += 4;
+       u32tobuf( p, rec->r.sdir.keyid[0] ); p += 4;
+       u32tobuf( p, rec->r.sdir.keyid[1] ); p += 4;
+       *p++ = rec->r.sdir.pubkey_algo;
+       p += 3;
+       ulongtobuf( p, rec->r.sdir.hintlist );
+       break;
+
       case RECTYPE_CACH:   /* FIXME*/
        ulongtobuf(p, rec->r.cache.lid); p += 4;
        memcpy(p, rec->r.cache.blockhash, 20); p += 20;
@@ -711,6 +911,8 @@ tdbio_write_record( TRUSTREC *rec )
     }
     else if( rec->rectype == RECTYPE_KEY )
        rc = update_keyhashtbl( rec );
+    else if( rec->rectype == RECTYPE_SDIR )
+       rc = update_sdirhashtbl( rec );
 
     return rc;
 }
@@ -805,13 +1007,13 @@ tdbio_new_recnum()
 int
 tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec )
 {
-    byte *fingerprint;
+    byte fingerprint[MAX_FINGERPRINT_LEN];
     size_t fingerlen;
     u32 keyid[2];
     int rc;
 
     keyid_from_pk( pk, keyid );
-    fingerprint = fingerprint_from_pk( pk, NULL, &fingerlen );
+    fingerprint_from_pk( pk, fingerprint, &fingerlen );
     rc = tdbio_search_dir_byfpr( fingerprint, fingerlen,
                                 pk->pubkey_algo, rec );
 
@@ -827,185 +1029,74 @@ tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec )
 }
 
 
+static int
+cmp_krec_fpr( void *dataptr, const TRUSTREC *rec )
+{
+    const struct cmp_krec_fpr_struct *d = dataptr;
+
+    return rec->rectype == RECTYPE_KEY
+          && ( !d->pubkey_algo || rec->r.key.pubkey_algo == d->pubkey_algo )
+          && rec->r.key.fingerprint_len == d->fprlen
+          && !memcmp( rec->r.key.fingerprint, d->fpr, d->fprlen );
+}
+
 int
 tdbio_search_dir_byfpr( const byte *fingerprint, size_t fingerlen,
                        int pubkey_algo, TRUSTREC *rec )
 {
+    struct cmp_krec_fpr_struct cmpdata;
     ulong recnum;
     int rc;
-    ulong hashrec, item;
-    int msb;
-    int level=0;
 
     assert( fingerlen == 20 || fingerlen == 16 );
 
     /* locate the key using the hash table */
-    hashrec = get_keyhashrec();
-  next_level:
-    msb = fingerprint[level];
-    hashrec += msb / ITEMS_PER_HTBL_RECORD;
-    rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL );
-    if( rc ) {
-       log_error( db_name, "scan keyhashtbl failed: %s\n", g10_errstr(rc) );
-       return rc;
-    }
-
-    item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
-    if( !item )
-       return -1; /* not found */
-
-    rc = tdbio_read_record( item, rec, 0 );
-    if( rc ) {
-       log_error( db_name, "keyhashtbl read failed: %s\n", g10_errstr(rc) );
-       return rc;
-    }
-    if( rec->rectype == RECTYPE_HTBL ) {
-       hashrec = item;
-       level++;
-       if( level >= fingerlen ) {
-           log_error( db_name, "keyhashtbl has invalid indirections\n");
-           return G10ERR_TRUSTDB;
-       }
-       goto next_level;
-    }
-    else if( rec->rectype == RECTYPE_HLST ) {
-       for(;;) {
-           int i;
-
-           for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
-               if( rec->r.hlst.rnum[i] ) {
-                   TRUSTREC tmp;
-
-                   rc = tdbio_read_record( rec->r.hlst.rnum[i],
-                                            &tmp, RECTYPE_KEY );
-                   if( rc ) {
-                       log_error( db_name,
-                                  "scan keyhashtbl read key failed: %s\n",
-                                                            g10_errstr(rc) );
-                       return rc;
-                   }
-                   if( (!pubkey_algo || tmp.r.key.pubkey_algo == pubkey_algo)
-                       && tmp.r.key.fingerprint_len == fingerlen
-                       && !memcmp(tmp.r.key.fingerprint,
-                                           fingerprint, fingerlen) ) {
-                       *rec = tmp;
-                       goto found;
-                   }
-               }
-           }
-           if( rec->r.hlst.next ) {
-               rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST );
-               if( rc ) {
-                   log_error( db_name,
-                              "scan keyhashtbl read hlst failed: %s\n",
-                                                        g10_errstr(rc) );
-                   return rc;
-               }
-           }
-           else
-               return -1; /* not found */
-       }
-      found:
-       ;
-    }
-    else if( rec->rectype == RECTYPE_KEY ) {
-       /* must check that it is the requested key */
-       if( (pubkey_algo && rec->r.key.pubkey_algo != pubkey_algo)
-           || rec->r.key.fingerprint_len != fingerlen
-           || memcmp(rec->r.key.fingerprint, fingerprint, fingerlen) )
-           return -1; /* no: not found */
-    }
-    else {
-       log_error( db_name, "keyhashtbl %lu points to an invalid record\n",
-                                                               item);
-       return G10ERR_TRUSTDB;
+    cmpdata.pubkey_algo = pubkey_algo;
+    cmpdata.fpr = fingerprint;
+    cmpdata.fprlen = fingerlen;
+    rc = lookup_hashtable( get_keyhashrec(), fingerprint, fingerlen,
+                          cmp_krec_fpr, &cmpdata, rec );
+    if( !rc ) {
+       recnum = rec->r.key.lid;
+       /* Now read the dir record */
+       rc = tdbio_read_record( recnum, rec, RECTYPE_DIR);
+       if( rc )
+           log_error_f(db_name, "can't read dirrec %lu: %s\n",
+                                                   recnum, g10_errstr(rc) );
     }
-
-    recnum = rec->r.key.lid;
-    /* Now read the dir record */
-    rc = tdbio_read_record( recnum, rec, RECTYPE_DIR);
-    if( rc )
-       log_error_f(db_name, "can't read dirrec %lu: %s\n",
-                                               recnum, g10_errstr(rc) );
-
     return rc;
 }
 
+
+
 static int
-del_reclist( ulong recno, int type )
+cmp_sdir( void *dataptr, const TRUSTREC *rec )
 {
-    TRUSTREC rec;
-    int rc;
+    const struct cmp_sdir_struct *d = dataptr;
 
-    while( recno ) {
-       rc = tdbio_read_record( recno, &rec, type);
-       if( rc ) {
-           log_error_f(db_name, "can't read record %lu: %s\n",
-                                               recno, g10_errstr(rc));
-           return rc;
-       }
-       switch( type ) {
-           case RECTYPE_PREF: recno = rec.r.pref.next; break;
-           case RECTYPE_UID:  recno = rec.r.uid.next;  break;
-           default: BUG();
-       }
-       rc = tdbio_delete_record( rec.recnum );
-       if( rc ) {
-           log_error_f(db_name, "can't delete record %lu: %s\n",
-                                               rec.recnum, g10_errstr(rc));
-           return rc;
-       }
-    }
-    return 0;
+    return rec->rectype == RECTYPE_SDIR
+          && ( !d->pubkey_algo || rec->r.sdir.pubkey_algo == d->pubkey_algo )
+          && rec->r.sdir.keyid[0] == d->keyid[0]
+          && rec->r.sdir.keyid[1] == d->keyid[1];
 }
 
-/****************
- * Delete the Userid UIDLID from DIRLID
- */
+
 int
-tdbio_delete_uidrec( ulong dirlid, ulong uidlid )
+tdbio_search_sdir( u32 *keyid, int pubkey_algo, TRUSTREC *rec )
 {
-    TRUSTREC dirrec, rec;
-    ulong recno;
+    struct cmp_sdir_struct cmpdata;
     int rc;
-
-    rc = tdbio_read_record( dirlid, &dirrec, RECTYPE_DIR);
-    if( rc ) {
-       log_error_f(db_name, "can't read dirrec %lu: %s\n", dirlid, g10_errstr(rc));
-       return rc;
-    }
-    recno = dirrec.r.dir.uidlist;
-    for( ; recno; recno = rec.r.uid.next ) {
-       rc = tdbio_read_record( recno, &rec, RECTYPE_UID);
-       if( rc ) {
-           log_error_f(db_name, "can't read uidrec %lu: %s\n",
-                                                   recno, g10_errstr(rc));
-           return rc;
-       }
-       if( recno == uidlid ) {
-           rc = del_reclist( rec.r.uid.prefrec, RECTYPE_PREF );
-           if( rc )
-               return rc;
-           rc = del_reclist( rec.r.uid.siglist, RECTYPE_SIG );
-           if( rc )
-               return rc;
-           rc = tdbio_delete_record( recno );
-           if( rc ) {
-               log_error_f(db_name, "can't delete uidrec %lu: %s\n",
-                                                   recno, g10_errstr(rc));
-               return rc;
-           }
-           dirrec.r.dir.uidlist = 0;
-           rc = tdbio_write_record( &dirrec );
-           if( rc ) {
-               log_error_f(db_name, "can't update dirrec %lu: %s\n",
-                                                 dirrec.recnum, g10_errstr(rc));
-               return rc;
-           }
-           return 0;
-       }
-    }
-    return -1; /* not found */
+    byte key[8];
+
+    /* locate the shadow dir record using the hash table */
+    u32tobuf( key   , keyid[0] );
+    u32tobuf( key+4 , keyid[1] );
+    cmpdata.pubkey_algo = pubkey_algo;
+    cmpdata.keyid[0] = keyid[0];
+    cmpdata.keyid[1] = keyid[1];
+    rc = lookup_hashtable( get_sdirhashrec(), key, 8,
+                          cmp_sdir, &cmpdata, rec );
+    return rc;
 }
 
 
index b59b4e4..66579ad 100644 (file)
@@ -39,6 +39,7 @@
 #define RECTYPE_UID  4
 #define RECTYPE_PREF 5
 #define RECTYPE_SIG  6
+#define RECTYPE_SDIR 8
 #define RECTYPE_CACH 9
 #define RECTYPE_HTBL 10
 #define RECTYPE_HLST 11
 
 #define DIRF_CHECKED  1 /* everything has been checked, the other bits are
                           valid */
-#define DIRF_MISKEY   2 /* some keys are missing, so they could not be checked*/
+#define DIRF_MISKEY   2 /* not all signatures are checked */
+                       /* this flag is used as a quick hint, that we */
+                       /* do not need to look at the sig records */
 #define DIRF_ERROR    4 /* severe errors: the key is not valid for some reasons
                           but we mark it to avoid duplicate checks */
 #define DIRF_REVOKED  8 /* the complete key has been revoked */
 
-#define KEYF_REVOKED DIRF_REVOKED   /* this key has been revoked
-                                      (only useful on subkeys)*/
-#define UIDF_REVOKED DIRF_REVOKED   /* this user id has been revoked */
+#define KEYF_REVOKED  8 /* this key has been revoked (only useful on subkeys)*/
 
+#define UIDF_CHECKED  1 /* user id has been checked - other bits are valid */
+#define UIDF_VALID    2 /* this is a valid user id */
+#define UIDF_REVOKED  8 /* this user id has been revoked */
+
+#define SIGF_CHECKED  1 /* signature has been checked - bits 0..6 are valid */
+#define SIGF_VALID    2 /* the signature is valid */
+#define SIGF_REVOKED  8 /* this signature has been revoked */
+#define SIGF_NOPUBKEY 128 /* there is no pubkey for this sig */
 
 struct trust_record {
     int  rectype;
     int  mark;
+    int  dirty;                /* for now only used internal by functions */
     struct trust_record *next; /* help pointer to build lists in memory */
     ulong recnum;
     union {
@@ -70,6 +80,7 @@ struct trust_record {
            ulong validated; /* timestamp of last validation   */
            ulong keyhashtbl;
            ulong firstfree;
+           ulong sdirhashtbl;
        } ver;
        struct {            /* free record */
            ulong next;
@@ -109,9 +120,15 @@ struct trust_record {
            ulong next;   /* recnno of next record or NULL for last one */
            struct {
                ulong lid;       /* of pubkey record of signator (0=unused) */
-               byte flag;       /* SIGRF_xxxxx */
+               byte flag;       /* SIGF_xxxxx */
            } sig[SIGS_PER_RECORD];
        } sig;
+       struct {
+           ulong lid;
+           u32  keyid[2];
+           byte pubkey_algo;
+           u32  hintlist;
+       } sdir;
        struct {            /* cache record */
            ulong lid;
            byte blockhash[20];
@@ -122,7 +139,7 @@ struct trust_record {
        } htbl;
        struct {
            ulong next;
-           ulong rnum[ITEMS_PER_HLST_RECORD]; /* of a key record */
+           ulong rnum[ITEMS_PER_HLST_RECORD]; /* of another record */
        } hlst;
     } r;
 };
@@ -154,7 +171,7 @@ ulong tdbio_new_recnum(void);
 int tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec );
 int tdbio_search_dir_byfpr( const byte *fingerprint, size_t fingerlen,
                                        int pubkey_algo, TRUSTREC *rec );
-int tdbio_delete_uidrec( ulong dirlid, ulong uidlid );
+int tdbio_search_sdir( u32 *keyid, int pubkey_algo, TRUSTREC *rec );
 
 
 #define buftoulong( p )  ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \
index 78b7b0a..18726f1 100644 (file)
@@ -85,7 +85,7 @@ struct recno_list_struct {
 typedef struct recno_list_struct *RECNO_LIST;
 
 
-static int walk_sigrecs( SIGREC_CONTEXT *c, int create );
+static int walk_sigrecs( SIGREC_CONTEXT *c );
 
 static LOCAL_ID_INFO *new_lid_table(void);
 static void release_lid_table( LOCAL_ID_INFO *tbl );
@@ -96,11 +96,11 @@ static void upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag );
 static void print_user_id( const char *text, u32 *keyid );
 static int do_list_path( TRUST_INFO *stack, int depth, int max_depth,
                         LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist );
-static int update_sigs_by_lid( ulong lid );
 
 static int list_sigs( ulong pubkey_id );
 static int propagate_trust( TRUST_SEG_LIST tslist );
 static int do_check( TRUSTREC *drec, unsigned *trustlevel );
+static int get_dir_record( PKT_public_key *pk, TRUSTREC *rec );
 
 
 /* a table used to keep track of ultimately trusted keys
@@ -282,34 +282,6 @@ upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag )
     BUG();
 }
 
-/****************
- * If we do not have a local_id in a signature packet, find the owner of
- * the signature packet in our trustdb or insert them into the trustdb
- */
-static int
-set_signature_packets_lid( PKT_signature *sig )
-{
-    PKT_public_key *pk = m_alloc_clear( sizeof *pk );
-    TRUSTREC rec;
-    int rc;
-
-    rc = get_pubkey( pk, sig->keyid );
-    if( rc)
-       goto leave;
-    if( !pk->local_id ) {
-       rc = tdbio_search_dir_bypk( pk, &rec );
-       if( rc == -1 )
-           rc = insert_trust_record( pk );
-       if( rc )
-           goto leave;
-    }
-    sig->local_id = pk->local_id;
-
-  leave:
-    free_public_key( pk );
-    return rc;
-}
-
 
 
 /****************
@@ -343,6 +315,24 @@ keyid_from_lid( ulong lid, u32 *keyid )
     return 0;
 }
 
+
+ulong
+lid_from_keyblock( KBNODE keyblock )
+{
+    KBNODE node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
+    PKT_public_key *pk;
+    if( !node )
+       BUG();
+    pk = node->pkt->pkt.public_key;
+    if( !pk->local_id ) {
+       TRUSTREC rec;
+
+       get_dir_record( pk, &rec );
+    }
+    return pk->local_id;
+}
+
+
 \f
 
 /****************
@@ -356,9 +346,8 @@ keyid_from_lid( ulong lid, u32 *keyid )
  * Returns: 0 - okay, -1 for eof (no more sigs) or any other errorcode
  */
 static int
-walk_sigrecs( SIGREC_CONTEXT *c, int create )
+walk_sigrecs( SIGREC_CONTEXT *c )
 {
-    int rc=0;
     TRUSTREC *r;
     ulong rnum;
 
@@ -380,20 +369,6 @@ walk_sigrecs( SIGREC_CONTEXT *c, int create )
            rnum = r->r.sig.next;
            if( !rnum && c->ctl.nextuid ) { /* read next uid record */
                read_record( c->ctl.nextuid, r, RECTYPE_UID );
-               if( !r->r.uid.siglist && create ) {
-                   rc = update_sigs_by_lid( c->lid );
-                   if( rc ) {
-                       if( rc == G10ERR_BAD_CERT )
-                           rc = -1;  /* maybe no selfsignature */
-                       if( rc != -1 )
-                           log_info("LID %lu: "
-                                    "error building sigs on the fly: %s\n",
-                                     c->lid, g10_errstr(rc) );
-                       c->ctl.eof = 1;
-                       return rc;
-                   }
-                   read_record( c->ctl.nextuid, r, RECTYPE_UID );
-               }
                c->ctl.nextuid = r->r.uid.next;
                rnum = r->r.uid.siglist;
            }
@@ -557,7 +532,7 @@ do_list_sigs( ulong root, ulong pubkey, int depth,
     memset( &sx, 0, sizeof sx );
     sx.lid = pubkey;
     for(;;) {
-       rc = walk_sigrecs( &sx, 0 );
+       rc = walk_sigrecs( &sx );
        if( rc )
            break;
        rc = keyid_from_lid( sx.sig_lid, keyid );
@@ -716,7 +691,7 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth,
     memset( &sx, 0, sizeof sx );
     sx.lid = stack[depth-1].lid;
     /* loop over all signatures. If we do not have any, try to create them */
-    while( !(rc = walk_sigrecs( &sx, 1 )) ) {
+    while( !(rc = walk_sigrecs( &sx )) ) {
        TRUST_SEG_LIST tsl, t2, tl;
        int i;
 
@@ -767,291 +742,6 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth,
 
 
 /****************
- * find the uid record given the uid packet and the dir-record.
- * Returns: 0 = found
- *        -1 = No such uid-record
- *        or other error
- */
-static int
-find_urec( TRUSTREC *dir, PKT_user_id *uid, TRUSTREC *urec )
-{
-    byte nhash[20];
-    ulong recno;
-
-    assert(dir->rectype == RECTYPE_DIR );
-    rmd160_hash_buffer( nhash, uid->name, uid->len );
-    for( recno=dir->r.dir.uidlist; recno; recno = urec->r.uid.next ) {
-       read_record( recno, urec, RECTYPE_UID );
-       if( !memcmp( nhash, urec->r.uid.namehash, 20 ) )
-           return 0;
-    }
-
-    return -1;
-}
-
-
-/****************
- * Test whether zthe signature lid is already in the (in mem) list.
- * Returns: True if it is a duplicate
- */
-static int
-test_dupsig( TRUSTREC *rec, ulong lid )
-{
-    int i;
-    ulong alid;
-
-    for( ; rec; rec = rec->next ) {
-       for(i=0; i < SIGS_PER_RECORD && (alid = rec->r.sig.sig[i].lid); i++ )
-           if( alid == lid )
-               return 1;
-    }
-    return 0;
-}
-
-
-/****************
- * release the sigrec from the uidlist
- */
-static void
-rel_uidsigs( TRUSTREC *urec )
-{
-    TRUSTREC *r2, *rec;
-    assert( urec->rectype == RECTYPE_UID );
-
-    for(rec=urec->next ; rec; rec = r2 ) {
-       assert( rec->rectype == RECTYPE_SIG );
-       r2 = rec->next;
-       m_free( rec );
-    }
-    urec->next = NULL;
-}
-
-static int
-no_selfsig_del( ulong lid, u32 *keyid, TRUSTREC *urec )
-{
-    int rc;
-
-    log_error("key %08lX.%lu, uid %02X%02X: "
-             "no self-signature - user id removed\n",
-             (ulong)keyid[1], lid, urec->r.uid.namehash[18],
-             urec->r.uid.namehash[19] );
-    rel_uidsigs( urec );
-    rc = tdbio_delete_uidrec( lid, urec->recnum );
-    if( rc )
-       log_error("no_selfsig_del: delete_uid %lu failed: %s\n",
-                                       lid, g10_errstr(rc) );
-    return rc;
-}
-
-/****************
- * Write the signature records from the in-mem list at urec
- * (The sequence of signatures does not matter)
- */
-static int
-write_sigs_from_urec( ulong lid, u32 *keyid, TRUSTREC *urec )
-{
-    TRUSTREC *rec, srec;
-    ulong nextrecno;
-    ulong recno;
-
-    nextrecno = urec->r.uid.siglist;
-    urec->r.uid.siglist = 0; /* end of list marker */
-    for( rec = urec->next; rec; rec = rec->next ) {
-       assert( rec->rectype == RECTYPE_SIG );
-       if( nextrecno ) { /* read the sig record, so it can be reused */
-           read_record( nextrecno, &srec, RECTYPE_SIG );
-           recno = nextrecno;
-           nextrecno = srec.r.sig.next;
-       }
-       else
-           recno = tdbio_new_recnum();
-
-       /* link together (the sequence of signatures does not matter) */
-       rec->r.sig.next = urec->r.uid.siglist;
-       urec->r.uid.siglist = recno;
-       rec->r.sig.lid = lid;
-       /* and write */
-       rec->recnum = recno;
-       write_record( rec );
-    }
-
-    /* write the urec back */
-    write_record( urec );
-
-    /* delete remaining old sigrecords */
-    while( nextrecno ) {
-       read_record( nextrecno, &srec, RECTYPE_SIG );
-       delete_record( nextrecno );
-       nextrecno = srec.r.sig.next;
-    }
-
-    return 0;
-}
-
-/****************
- * If we do not have sigrecs for the given key, build them and write them
- * to the trustdb
- */
-static int
-update_sigs( TRUSTREC *dir )
-{
-    TRUSTREC *rec, krec;
-    TRUSTREC urec;
-    TRUSTREC *sigrec_list;
-    KBNODE keyblock = NULL;
-    KBNODE node;
-    int i, sigidx, have_urec ;
-    ulong lid = dir->r.dir.lid;
-    u32 keyid[2];
-    int miskey=0;
-    int rc=0;
-
-    if( DBG_TRUST )
-       log_debug("update_sigs for %lu\n", lid );
-
-    read_record( dir->r.dir.keylist, &krec, RECTYPE_KEY );
-    rc = get_keyblock_byfprint( &keyblock, krec.r.key.fingerprint,
-                                          krec.r.key.fingerprint_len );
-    if( rc ) {
-       log_error( "update_sigs: keyblock for %lu not found: %s\n",
-                                                   lid, g10_errstr(rc) );
-       goto leave;
-    }
-
-    /* check all key signatures */
-    assert( keyblock->pkt->pkttype == PKT_PUBLIC_KEY );
-    have_urec = 0;
-    sigrec_list = NULL;
-    sigidx = 0;
-    for( node=keyblock; node; node = node->next ) {
-       if( node->pkt->pkttype == PKT_PUBLIC_KEY )
-           keyid_from_pk( node->pkt->pkt.public_key, keyid );
-       else if( node->pkt->pkttype == PKT_USER_ID ) {
-           if( have_urec && !(urec.mark & 1) ) {
-              if( (rc = no_selfsig_del(lid, keyid, &urec )) )
-                  goto leave;
-               have_urec = 0;
-           }
-           if( have_urec ) {
-               rc = write_sigs_from_urec( lid, keyid, &urec );
-               if( rc )
-                   goto leave;
-               rel_uidsigs( &urec );
-           }
-           rc = find_urec( dir, node->pkt->pkt.user_id, &urec );
-           urec.next = NULL;
-           urec.mark = 0;
-           have_urec = sigidx = 0;
-           if( rc == -1 ) {
-               log_info("update_sigs: new user id for %lu\n", lid );
-               /* fixme: we should add the new user id here */
-           }
-           else if( rc ) {
-               log_error("update_sigs: find_urec %lu failed: %s\n",
-                                               lid, g10_errstr(rc) );
-               goto leave;
-           }
-           else
-               have_urec = 1;
-       }
-       else if( have_urec && node->pkt->pkttype == PKT_SIGNATURE ) {
-           PKT_signature *sig = node->pkt->pkt.signature;
-
-           if( (sig->sig_class&~3) == 0x10 ) {
-               rc = check_key_signature( keyblock, node, &i );
-               if( rc == G10ERR_NO_PUBKEY ) {
-                   if( opt.verbose )
-                       log_info(_("key %08lX.%lu, uid %02X%02X: "
-                                  "no public key for signature %08lX\n"),
-                             (ulong)keyid[1], lid, urec.r.uid.namehash[18],
-                             urec.r.uid.namehash[19], (ulong)sig->keyid[1] );
-                   miskey = 1;
-               }
-               else if( rc )
-                   log_info(_("key %08lX.%lu, uid %02X%02X: "
-                              "invalid %ssignature: %s\n"),
-                             (ulong)keyid[1], lid, urec.r.uid.namehash[18],
-                             urec.r.uid.namehash[19],
-                             i?"self-":"",g10_errstr(rc));
-               else if( i ) /* mark that we have a valid selfsignature */
-                   urec.mark |= 1;
-               else if( (rc = set_signature_packets_lid( sig )) )
-                   log_error("key %08lX.%lu, uid %02X%02X: "
-                             "can't get LID of signer: %s\n",
-                             (ulong)keyid[1], lid, urec.r.uid.namehash[18],
-                             urec.r.uid.namehash[19], g10_errstr(rc));
-               else if( !test_dupsig( urec.next, sig->local_id ) ) {
-                   /* put the valid signature into a list */
-                   rec = urec.next;
-                   if( !rec || sigidx == SIGS_PER_RECORD ) {
-                       rec = m_alloc_clear( sizeof *rec );
-                       rec->rectype = RECTYPE_SIG;
-                       rec->next = urec.next;
-                       urec.next = rec;
-                       sigidx = 0;
-                   }
-                   rec->r.sig.sig[sigidx].lid = sig->local_id;
-                   rec->r.sig.sig[sigidx].flag = 0;
-                   sigidx++;
-                   if( DBG_TRUST )
-                       log_debug("key %08lX.%lu, uid %02X%02X: "
-                             "signed by LID %lu\n",
-                             (ulong)keyid[1], lid, urec.r.uid.namehash[18],
-                             urec.r.uid.namehash[19], sig->local_id);
-               }
-               else if( DBG_TRUST )
-                   log_debug("key %08lX.%lu, uid %02X%02X: "
-                             "duplicate signature by LID %lu\n",
-                             (ulong)keyid[1], lid, urec.r.uid.namehash[18],
-                             urec.r.uid.namehash[19], sig->local_id );
-               rc = 0;
-           }
-           else {
-               /* fixme: handle other sig classes here */
-               /* FIXME: Revocations!!! */
-           }
-       }
-    }
-    if( have_urec && !(urec.mark & 1) ) {
-       if( (rc = no_selfsig_del(lid, keyid, &urec )) )
-           goto leave;
-       have_urec = 0;
-    }
-    if( have_urec ) {
-       rc = write_sigs_from_urec( lid, keyid, &urec );
-       if( rc )
-           goto leave;
-       rel_uidsigs( &urec );
-    }
-    dir->r.dir.dirflags |= DIRF_CHECKED;
-    if( miskey )
-       dir->r.dir.dirflags |= DIRF_MISKEY;
-    else
-       dir->r.dir.dirflags &= ~DIRF_MISKEY;
-    write_record( dir );
-
-  leave:
-    /* fixme: need more cleanup in case of an error */
-    release_kbnode( keyblock );
-    if( DBG_TRUST )
-       log_debug("update_sigs for %lu: %s\n", lid, g10_errstr(rc) );
-    return rc;
-}
-
-
-static int
-update_sigs_by_lid( ulong lid )
-{
-    int rc;
-    TRUSTREC rec;
-
-    read_record( lid, &rec, RECTYPE_DIR );
-    if( !(rec.r.dir.dirflags & DIRF_CHECKED) )
-       rc = update_sigs( &rec );
-    return rc;
-}
-
-/****************
  * Make a list of trust paths
  */
 static int
@@ -1170,8 +860,7 @@ do_check( TRUSTREC *dr, unsigned *trustlevel )
     }
 
     /* did we already check the signatures */
-    if( !(dr->r.dir.dirflags & DIRF_CHECKED) ) /* no - do it now */
-       rc = update_sigs( dr );
+    /* fixme:.... */
 
     if( dr->r.dir.dirflags & DIRF_REVOKED )
        tflags |= TRUST_FLAG_REVOKED;
@@ -1557,55 +1246,111 @@ list_trust_path( int max_depth, const char *username )
 
 
 /****************
- * Check the complete trustdb or only the entries for the given username
- * FIXME: We need a mode which only looks at keys with the MISKEY flag set.
+ * 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 )
 {
     TRUSTREC rec;
+    KBNODE keyblock = NULL;
+    KBPOS kbpos;
     int rc;
+    int rebuild = username && !strcmp(username, "REBUILD");
 
-    if( username && *username == '#' ) {
-       int rc;
-       ulong lid = atoi(username+1);
+    if( username && !rebuild ) {
+       rc = find_keyblock_byname( &kbpos, username );
+       if( !rc )
+           rc = read_keyblock( &kbpos, &keyblock );
+       if( rc ) {
+           log_error("%s: keyblock read problem: %s\n",
+                                   username, g10_errstr(rc));
+       }
+       else {
+           rc = update_trust_record( keyblock );
+           if( rc == -1 ) { /* not yet in trustdb: insert */
+               rc = insert_trust_record(
+                           find_kbnode( keyblock, PKT_PUBLIC_KEY
+                                      ) ->pkt->pkt.public_key );
 
-       if( (rc = update_sigs_by_lid( lid )) )
-           log_error("lid %lu: check failed: %s\n",
-                                       lid, g10_errstr(rc));
-       else
-           log_info("lid %lu: checked: %s\n", lid, g10_errstr(rc));
-    }
-    else if( username ) {
-       PKT_public_key *pk = m_alloc_clear( sizeof *pk );
+           }
+           if( rc )
+               log_error("%s: update failed: %s\n",
+                                          username, g10_errstr(rc) );
+           else
+               log_info("%s: updated\n", username );
 
-       if( (rc = get_pubkey_byname( pk, username )) )
-           log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
-       else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
-           log_error("problem finding '%s' in trustdb: %s\n",
-                                               username, g10_errstr(rc));
-       else if( rc == -1 )
-           log_error("user '%s' not in trustdb\n", username);
-       else if( (rc = update_sigs( &rec )) )
-           log_error("lid %lu: check failed: %s\n",
-                                       rec.recnum, g10_errstr(rc));
-       else
-           log_info("lid %lu: checked: %s\n", rec.recnum, g10_errstr(rc));
-       free_public_key( pk );
+       }
+       release_kbnode( keyblock ); keyblock = NULL;
     }
     else {
        ulong recnum;
 
        for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
            if( rec.rectype == RECTYPE_DIR ) {
-               rc = update_sigs( &rec );
+               TRUSTREC tmp;
+               if( !rec.r.dir.keylist ) {
+                   log_info("lid %lu: dir record w/o key - skipped\n", recnum);
+                   continue;
+               }
+
+               read_record( rec.r.dir.keylist, &tmp, RECTYPE_KEY );
+
+               rc = get_keyblock_byfprint( &keyblock,
+                                           tmp.r.key.fingerprint,
+                                           tmp.r.key.fingerprint_len );
+               if( rc ) {
+                   log_error("lid %lu: keyblock not found: %s\n",
+                                                recnum, g10_errstr(rc) );
+                   continue;
+               }
+               rc = update_trust_record( keyblock );
                if( rc )
-                   log_error("lid %lu: check failed: %s\n",
+                   log_error("lid %lu: update failed: %s\n",
                                                 recnum, g10_errstr(rc) );
                else
-                   log_info("lid %lu: checked\n", recnum );
+                   log_info("lid %lu: updated\n", recnum );
+
+               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 );
+       }
+
     }
 }
 
@@ -1929,11 +1674,601 @@ clear_trust_checked_flag( PKT_public_key *pk )
 
 
 
+
+static void
+check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash,
+               TRUSTREC *sigrec, int sigidx, ulong hint_owner )
+{
+    KBNODE node;
+    int rc, state=0;
+    byte uhash[20];
+    int is_selfsig;
+    PKT_signature *sigpkt = NULL;
+
+    if( sigrec->r.sig.sig[sigidx].flag & SIGF_CHECKED )
+       log_info(_("note: sig rec %lu[%d] in hintlist "
+                  "of %lu but marked as checked\n"),
+                   sigrec->recnum, sigidx, hint_owner );
+    if( !(sigrec->r.sig.sig[sigidx].flag & SIGF_NOPUBKEY) )
+       log_info(_("note: sig rec %lu[%d] in hintlist "
+                  "of %lu but not marked\n"),
+                   sigrec->recnum, sigidx, hint_owner );
+
+    /* find the correct signature packet */
+    for( node=keyblock; node; node = node->next ) {
+       if( node->pkt->pkttype == PKT_USER_ID ) {
+           PKT_user_id *uidpkt = node->pkt->pkt.user_id;
+
+           if( state )
+               break;
+           rmd160_hash_buffer( uhash, uidpkt->name, uidpkt->len );
+           if( !memcmp( uhash, uidrec_hash, 20 ) )
+               state = 1;
+       }
+       else if( state && node->pkt->pkttype == PKT_SIGNATURE ) {
+           sigpkt = node->pkt->pkt.signature;
+           if( sigpkt->keyid[0] == keyid[0]
+               && sigpkt->keyid[1] == keyid[1]
+               && (sigpkt->sig_class&~3) == 0x10 )
+               break; /* found */
+       }
+    }
+
+    if( !node ) {
+       log_error(_("lid %lu: user id not found in keyblock\n"), lid );
+       return ;
+    }
+
+    /* and check the sig */
+    rc = check_key_signature( keyblock, node, &is_selfsig );
+    if( is_selfsig ) {
+       log_error(_("lid %lu: self-signature in hintlist\n"), lid );
+       return ;
+    }
+    if( !rc ) { /* valid signature */
+       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"),
+             (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: "
+                  "invalid signature: %s\n"),
+                   (ulong)keyid[1], lid,
+                   uhash[18], uhash[19], g10_errstr(rc));
+       sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED;
+    }
+    sigrec->dirty = 1;
+}
+
+
+/****************
+ * Process a hintlist.
+ * Fixme: this list is not anymore anchored to another
+ *       record, so it should be put elsewehere in case of an error
+ */
+static void
+process_hintlist( ulong hintlist, ulong hint_owner )
+{
+    ulong hlst_rn;
+    int rc;
+
+    for( hlst_rn = hintlist; hlst_rn; ) {
+       TRUSTREC hlstrec;
+       int hlst_idx;
+
+       read_record( hlst_rn, &hlstrec, RECTYPE_HLST );
+
+       for( hlst_idx=0; hlst_idx < ITEMS_PER_HLST_RECORD; hlst_idx++ ) {
+           TRUSTREC dirrec;
+           TRUSTREC uidrec;
+           TRUSTREC tmprec;
+           KBNODE keyblock = NULL;
+           u32 keyid[2];
+           ulong lid;
+           ulong r1, r2;
+
+           lid = hlstrec.r.hlst.rnum[hlst_idx];
+           if( !lid )
+               continue;
+
+           read_record( lid, &dirrec, 0 );
+           /* make sure it points to a dir record:
+            * this should be true because it only makes sense to
+            * call this function if the dir record is available */
+           if( dirrec.rectype != RECTYPE_DIR )  {
+               log_error(_("hintlist %lu[%d] of %lu "
+                           "does not point to a dir record\n"),
+                           hlst_rn, hlst_idx, hint_owner );
+               continue;
+           }
+           if( !dirrec.r.dir.keylist ) {
+               log_error(_("lid %lu does not have a key\n"), lid );
+               continue;
+           }
+
+           /* get the keyblock */
+           read_record( dirrec.r.dir.keylist, &tmprec, RECTYPE_KEY );
+           rc = get_keyblock_byfprint( &keyblock,
+                                       tmprec.r.key.fingerprint,
+                                       tmprec.r.key.fingerprint_len );
+           if( rc ) {
+               log_error(_("lid %lu: can't get keyblock: %s\n"),
+                                                   lid, g10_errstr(rc) );
+               continue;
+           }
+           keyid_from_fingerprint( tmprec.r.key.fingerprint,
+                                   tmprec.r.key.fingerprint_len, keyid );
+
+           /* Walk over all user ids and their signatures and check all
+            * the signature which are created by hint_owner */
+           for( r1 = dirrec.r.dir.uidlist; r1; r1 = uidrec.r.uid.next ) {
+               TRUSTREC sigrec;
+
+               read_record( r1, &uidrec, RECTYPE_UID );
+               for( r2 = uidrec.r.uid.siglist; r2; r2 = sigrec.r.sig.next ) {
+                   int i;
+
+                   read_record( r2, &sigrec, RECTYPE_SIG );
+                   sigrec.dirty = 0;
+                   for(i=0; i < SIGS_PER_RECORD; i++ ) {
+                       if( !sigrec.r.sig.sig[i].lid )
+                           continue; /* skip deleted sigs */
+                       if( sigrec.r.sig.sig[i].lid != hint_owner )
+                           continue; /* not for us */
+                       /* some diagnostic messages */
+                       /* and do the signature check */
+                       check_hint_sig( lid, keyblock, keyid,
+                                       uidrec.r.uid.namehash,
+                                       &sigrec, i, hint_owner );
+                   }
+                   if( sigrec.dirty )
+                       write_record( &sigrec );
+               }
+           }
+           release_kbnode( keyblock );
+       } /* loop over hlst entries */
+
+       /* delete this hlst record */
+       hlst_rn = hlstrec.r.hlst.next;
+       delete_record( hlstrec.recnum );
+    } /* loop over hintlist */
+}
+
+
+
+static void
+upd_key_record( PKT_public_key *pk, TRUSTREC *drec, RECNO_LIST *recno_list )
+{
+    TRUSTREC krec;
+    byte fpr[MAX_FINGERPRINT_LEN];
+    size_t fprlen;
+    ulong recno, newrecno;
+
+    fingerprint_from_pk( pk, fpr, &fprlen );
+    /* do we already have this key? */
+    for( recno=drec->r.dir.keylist; recno; recno = krec.r.key.next ) {
+       read_record( recno, &krec, RECTYPE_KEY );
+       if( krec.r.key.fingerprint_len == fprlen
+           && !memcmp( krec.r.key.fingerprint, fpr, fprlen ) )
+           break;
+    }
+    if( recno ) { /* yes */
+       ins_recno_list( recno_list, recno, RECTYPE_KEY );
+       /* here we would compare/update the keyflags */
+    }
+    else { /* no: insert this new key */
+       memset( &krec, 0, sizeof(krec) );
+       krec.rectype = RECTYPE_KEY;
+       krec.r.key.lid = drec->recnum;
+       krec.r.key.pubkey_algo = pk->pubkey_algo;
+       krec.r.key.fingerprint_len = fprlen;
+       memcpy(krec.r.key.fingerprint, fpr, fprlen );
+       krec.recnum = newrecno = tdbio_new_recnum();
+       write_record( &krec );
+       ins_recno_list( recno_list, newrecno, RECTYPE_KEY );
+       /* and put this new record at the end of the keylist */
+       if( !(recno=drec->r.dir.keylist) ) {
+           /* this is the first key */
+           drec->r.dir.keylist = newrecno;
+           drec->dirty = 1;
+       }
+       else { /* we already have a key, append it to the list */
+           for( ; recno; recno = krec.r.key.next )
+               read_record( recno, &krec, RECTYPE_KEY );
+           krec.r.key.next = newrecno;
+           write_record( &krec );
+       }
+    }
+}
+
+
+static void
+upd_uid_record( PKT_user_id *uid, TRUSTREC *drec, RECNO_LIST *recno_list,
+               u32 *keyid, ulong *uidrecno, byte *uidhash )
+{
+    TRUSTREC urec;
+    ulong recno, newrecno;
+
+    rmd160_hash_buffer( uidhash, uid->name, uid->len );
+    for( recno=drec->r.dir.uidlist; recno; recno = urec.r.uid.next ) {
+       read_record( recno, &urec, RECTYPE_UID );
+       if( !memcmp( uidhash, urec.r.uid.namehash, 20 ) )
+           break;
+    }
+    if( recno ) {
+       ins_recno_list( recno_list, recno, RECTYPE_UID );
+       *uidrecno = recno;
+    }
+    else { /* new user id */
+       memset( &urec, 0 , sizeof(urec) );
+       urec.rectype = RECTYPE_UID;
+       urec.r.uid.lid = drec->recnum;
+       memcpy(urec.r.uid.namehash, uidhash, 20 );
+       urec.recnum = newrecno = tdbio_new_recnum();
+       write_record( &urec );
+       ins_recno_list( recno_list, newrecno, RECTYPE_UID );
+       /* and put this new record at the end of the uidlist */
+       if( !(recno=drec->r.dir.uidlist) ) { /* this is the first uid */
+           drec->r.dir.uidlist = newrecno;
+           drec->dirty = 1;
+       }
+       else { /* we already have an uid, append it to the list */
+           for( ; recno; recno = urec.r.key.next )
+               read_record( recno, &urec, RECTYPE_UID );
+           urec.r.uid.next = newrecno;
+           write_record( &urec );
+       }
+       *uidrecno = newrecno;
+    }
+}
+
+
+static void
+upd_pref_record( PKT_signature *sig, TRUSTREC *drec,
+                u32 *keyid, ulong *uidrecno, byte *uidhash )
+{
+    static struct {
+       sigsubpkttype_t subpkttype;
+       int preftype;
+    } prefs[] = {
+       { SIGSUBPKT_PREF_SYM,   PREFTYPE_SYM    },
+       { SIGSUBPKT_PREF_HASH,  PREFTYPE_HASH   },
+       { SIGSUBPKT_PREF_COMPR, PREFTYPE_COMPR  },
+       { 0, 0 }
+    };
+    TRUSTREC urec, prec;
+    const byte *s;
+    size_t n;
+    int k, i;
+    ulong recno_tbl[10];
+    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 ) {
+       read_record( recno, &prec, RECTYPE_PREF );
+       delete_record( recno );
+    }
+
+    /* and write the new ones */
+    i = 0;
+    for(k=0; prefs[k].subpkttype; k++ ) {
+       s = parse_sig_subpkt2( sig, prefs[k].subpkttype, &n );
+       if( s ) {
+           while( n ) {
+               if( !i || i >= ITEMS_PER_PREF_RECORD ) {
+                   if( recno_idx >= DIM(recno_tbl)-1 ) {
+                       log_info("too many preferences\n");
+                       break;
+                   }
+                   if( i ) {
+                       recno_tbl[recno_idx]=tdbio_new_recnum();
+                       prec.recnum = recno_tbl[recno_idx++];
+                       write_record( &prec );
+                   }
+                   memset( &prec, 0, sizeof prec );
+                   prec.rectype = RECTYPE_PREF;
+                   prec.r.pref.lid = drec->recnum;
+                   i = 0;
+               }
+               prec.r.pref.data[i++] = prefs[k].preftype;
+               prec.r.pref.data[i++] = *s++;
+               n--;
+           }
+       }
+    }
+    if( i ) { /* write the last one */
+       recno_tbl[recno_idx]=tdbio_new_recnum();
+       prec.recnum = recno_tbl[recno_idx++];
+       write_record( &prec );
+    }
+    /* now link them together */
+    for(i=0; i < recno_idx-1; i++ ) {
+       read_record( recno_tbl[i], &prec, RECTYPE_PREF );
+       prec.r.pref.next = recno_tbl[i+1];
+       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 );
+}
+
+
+
 /****************
- * Update all the info from the public keyblock,  the signatures-checked
- * flag is reset. The key must already exist in the keydb.
- *
- * Implementation of this function needs a cache for tdbio record updates
+ * Note: A signature made with a secondayr key is not considered a
+ *      self-signature.
+ */
+static void
+upd_sig_record( PKT_signature *sig, TRUSTREC *drec,
+               u32 *keyid, ulong *uidrecno, byte *uidhash,
+               KBNODE keyblock, KBNODE signode )
+{
+    int rc;
+    ulong lid = drec->recnum;
+
+    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 );
+           }
+       }
+       else {/* is revocation sig etc */
+           /* FIXME */
+       }
+    }
+    else if( !*uidrecno )
+       ; /* skip record with direct key signatures here */
+    else if( (sig->sig_class&~3) == 0x10 ) {
+       /* We simply insert the signature into the sig records but
+        * avoid duplicate ones.  We do not check them here because
+        * there is a big chance, that we import required public keys
+        * later.  The problem with this is that we must somewhere store
+        * the information about this signature (we need a record id).
+        * We do this by using the record type shadow dir, which will
+        * be converted to a dir record as soon as a new public key is
+        * inserted into the trustdb.
+        */
+       TRUSTREC urec, rec;
+       ulong recno;
+       TRUSTREC delrec;
+       int delrecidx;
+       int newflag = 0;
+       ulong newlid = 0;
+       PKT_public_key *pk = m_alloc_clear( sizeof *pk );
+
+       delrec.recnum = 0;
+       /* we need the uid record */
+       read_record( *uidrecno, &urec, RECTYPE_UID );
+
+       for( recno = urec.r.uid.siglist; recno; recno = rec.r.sig.next ) {
+           int i;
+
+           read_record( recno, &rec, RECTYPE_SIG );
+           for(i=0; i < SIGS_PER_RECORD; i++ ) {
+               TRUSTREC tmp;
+               if( !rec.r.sig.sig[i].lid ) {
+                   if( !delrec.recnum ) {
+                       delrec = rec;
+                       delrecidx = i;
+                   }
+                   continue; /* skip deleted sigs */
+               }
+               if( rec.r.sig.sig[i].flag & SIGF_CHECKED )
+                   continue; /* we already checked this signature */
+               if( rec.r.sig.sig[i].flag & SIGF_NOPUBKEY )
+                   continue; /* we do not have the public key */
+
+               read_record( rec.r.sig.sig[i].lid, &tmp, 0 );
+               if( tmp.rectype == RECTYPE_DIR ) {
+                   /* In this case we should now be able to check
+                    * the signature: */
+                   rc = check_key_signature( keyblock, signode, NULL );
+                   if( !rc ) { /* valid signature */
+                       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"),
+                             (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: "
+                                  "invalid signature: %s\n"),
+                                   (ulong)keyid[1], lid,
+                                   uidhash[18], uidhash[19], g10_errstr(rc));
+                       rec.r.sig.sig[i].flag = SIGF_CHECKED;
+                   }
+                   write_record( &rec );
+                   goto ready;
+               }
+               else if( tmp.rectype == RECTYPE_SDIR ) {
+                   /* must check that it is the right one */
+                   if( tmp.r.sdir.keyid[0] == sig->keyid[0]
+                       && tmp.r.sdir.keyid[1] == sig->keyid[1]
+                       && (!tmp.r.sdir.pubkey_algo
+                            || tmp.r.sdir.pubkey_algo == sig->pubkey_algo )) {
+                       log_info(_("key %08lX.%lu, uid %02X%02X: "
+                                  "has shadow dir %lu but not yet marked.\n"),
+                                   (ulong)keyid[1], lid,
+                                   uidhash[18], uidhash[19], tmp.recnum );
+                       rec.r.sig.sig[i].flag = SIGF_NOPUBKEY;
+                       write_record( &rec );
+                       /* fixme: should we verify that the record is
+                        * in the hintlist? - This case here should anyway
+                        * never occur */
+                       goto ready;
+                   }
+               }
+               else {
+                   log_error("sig record %lu[%d] points to wrong record.\n",
+                               rec.r.sig.sig[i].lid, i );
+                   die_invalid_db();
+               }
+           }
+       }
+       /* 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( !rc ) { /* valid signature */
+           newlid = pk->local_id;  /* 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"),
+                             (ulong)keyid[1], lid, uidhash[18],
+                              uidhash[19], (ulong)sig->keyid[1] );
+           newflag = SIGF_NOPUBKEY;
+       }
+       else {
+           log_info(_("key %08lX.%lu, uid %02X%02X: "
+                      "invalid signature: %s\n"),
+                       (ulong)keyid[1], lid, uidhash[18], uidhash[19],
+                                                      g10_errstr(rc));
+           newflag = SIGF_CHECKED;
+       }
+       free_public_key( pk );
+
+       if( !newlid ) { /* create a shadow dir record */
+           TRUSTREC sdir, hlst, tmphlst;
+           int tmpidx;
+           /* first see whether we already have such a record */
+           rc = tdbio_search_sdir( sig->keyid, sig->pubkey_algo, &sdir );
+           if( rc && rc != -1 ) {
+               log_error("tdbio_search_dir failed: %s\n", g10_errstr(rc));
+               die_invalid_db();
+           }
+           if( rc == -1 ) { /* not found: create */
+               memset( &sdir, 0, sizeof sdir );
+               sdir.recnum = tdbio_new_recnum();
+               sdir.rectype= RECTYPE_SDIR;
+               sdir.r.sdir.lid = sdir.recnum;
+               sdir.r.sdir.keyid[0] = sig->keyid[0];
+               sdir.r.sdir.keyid[1] = sig->keyid[1];
+               sdir.r.sdir.pubkey_algo = sig->pubkey_algo;
+               sdir.r.sdir.hintlist = 0;
+               write_record( &sdir );
+           }
+           newlid = sdir.recnum;
+           /* Put the record number into the hintlist.
+            * (It is easier to use the lid and not the record number of the
+            *  key to save some space (assuming that a signator has
+            *  signed more than one user id - and it is easier to implement.)
+            */
+           tmphlst.recnum = 0;
+           for( recno=sdir.r.sdir.hintlist; recno; recno = hlst.r.hlst.next) {
+               int i;
+               read_record( recno, &hlst, RECTYPE_HLST );
+               for( i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
+                   if( !hlst.r.hlst.rnum[i] ) {
+                       if( !tmphlst.recnum ) {
+                           tmphlst = hlst;
+                           tmpidx = i;
+                       }
+                   }
+                   else if( hlst.r.hlst.rnum[i] == lid )
+                       goto have_hint;
+               }
+           }
+           /* not yet in the hint list, write it */
+           if( tmphlst.recnum ) { /* we have an empty slot */
+               tmphlst.r.hlst.rnum[tmpidx] = lid;
+               write_record( &tmphlst );
+           }
+           else { /* must append a new hlst record */
+               memset( &hlst, 0, sizeof hlst );
+               hlst.recnum = tdbio_new_recnum();
+               hlst.rectype = RECTYPE_HLST;
+               hlst.r.hlst.next = sdir.r.sdir.hintlist;
+               hlst.r.hlst.rnum[0] = lid;
+               write_record( &hlst );
+               sdir.r.sdir.hintlist = hlst.recnum;
+               write_record( &sdir );
+           }
+         have_hint:  /* "goto considered useful" (don't tell Dijkstra) */
+           ;
+       }
+
+       if( delrec.recnum ) { /* we can reuse a deleted slot */
+           delrec.r.sig.sig[delrecidx].lid = newlid;
+           delrec.r.sig.sig[delrecidx].flag= newflag;
+           write_record( &delrec );
+       }
+       else { /* must insert a new sig record */
+           TRUSTREC tmp;
+
+           memset( &tmp, 0, sizeof tmp );
+           tmp.recnum = tdbio_new_recnum();
+           tmp.rectype = RECTYPE_SIG;
+           tmp.r.sig.lid = lid;
+           tmp.r.sig.next = urec.r.uid.siglist;
+           tmp.r.sig.sig[0].lid = newlid;
+           tmp.r.sig.sig[0].flag= newflag;
+           write_record( &tmp );
+           urec.r.uid.siglist = tmp.recnum;
+           write_record( &urec );
+       }
+
+      ready:
+       ;
+    }
+    else {
+       /* handle other sig classes */
+    }
+
+}
+
+
+/****************
+ * Update all the info from the public keyblock.
+ * The key must already exist in the keydb.
+ * This function is responsible for checking the signatures in cases
+ * where the public key is already available.  If we no not have the public
+ * key, the check is done by some special code in insert_trust_record().
  */
 int
 update_trust_record( KBNODE keyblock )
@@ -1942,13 +2277,12 @@ update_trust_record( KBNODE keyblock )
     KBNODE node;
     TRUSTREC drec;
     TRUSTREC krec;
-    TRUSTREC prec;
     TRUSTREC urec;
+    TRUSTREC prec;
     TRUSTREC helprec;
-    int modified = 0;
     int rc = 0;
     u32 keyid[2]; /* keyid of primary key */
-    ulong recno, newrecno, lastrecno;
+    ulong recno, lastrecno;
     ulong uidrecno = 0;
     byte uidhash[20];
     RECNO_LIST recno_list = NULL; /* list of verified records */
@@ -1958,189 +2292,46 @@ update_trust_record( KBNODE keyblock )
     rc = get_dir_record( primary_pk, &drec );
     if( rc )
        return rc;
+    if( !primary_pk->local_id )
+       primary_pk->local_id = drec.recnum;
 
     keyid_from_pk( primary_pk, keyid );
 
     /* fixme: start a transaction */
     /* now update keys and user ids */
     for( node=keyblock; node; node = node->next ) {
-       if( node->pkt->pkttype == PKT_PUBLIC_KEY
-           || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
-           PKT_public_key *pk = node->pkt->pkt.public_key;
-           byte fpr[MAX_FINGERPRINT_LEN];
-           size_t fprlen;
-
+       switch( node->pkt->pkttype ) {
+         case PKT_PUBLIC_KEY:
+         case PKT_PUBLIC_SUBKEY:
            uidrecno = 0;
+           upd_key_record( node->pkt->pkt.public_key, &drec, &recno_list );
+           break;
 
-           fingerprint_from_pk( pk, fpr, &fprlen );
-           /* do we already have this key? */
-           for( recno=drec.r.dir.keylist; recno; recno = krec.r.key.next ) {
-               read_record( recno, &krec, RECTYPE_KEY );
-               if( krec.r.key.fingerprint_len == fprlen
-                   && !memcmp( krec.r.key.fingerprint, fpr, fprlen ) )
-                   break;
+         case PKT_USER_ID:
+           if( drec.dirty ) { /* upd_pref_record may read the drec */
+               write_record( &drec );
+               drec.dirty = 0;
            }
-           if( recno ) { /* yes */
-               ins_recno_list( &recno_list, recno, RECTYPE_KEY );
-               /* here we would compare/update the keyflags */
-           }
-           else { /* no: insert this new key */
-               memset( &krec, 0, sizeof(krec) );
-               krec.rectype = RECTYPE_KEY;
-               krec.r.key.lid = drec.recnum;
-               krec.r.key.pubkey_algo = pk->pubkey_algo;
-               krec.r.key.fingerprint_len = fprlen;
-               memcpy(krec.r.key.fingerprint, fpr, fprlen );
-               krec.recnum = newrecno = tdbio_new_recnum();
-               write_record( &krec );
-               ins_recno_list( &recno_list, newrecno, RECTYPE_KEY );
-               /* and put this new record at the end of the keylist */
-               if( !(recno=drec.r.dir.keylist) ) {
-                   /* this is the first key */
-                   drec.r.dir.keylist = newrecno;
-                   modified = 1;
-               }
-               else { /* we already have key, append it to the list */
-                   for( ; recno; recno = krec.r.key.next )
-                       read_record( recno, &krec, RECTYPE_KEY );
-                   krec.r.key.next = newrecno;
-                   write_record( &krec );
-               }
-           } /* end insert new key */
-       } /* end packet type public key packet */
-       else if( node->pkt->pkttype == PKT_USER_ID ) {
-           PKT_user_id *uid = node->pkt->pkt.user_id;
-           TRUSTREC urec;
-
-           rmd160_hash_buffer( uidhash, uid->name, uid->len );
-           for( recno=drec.r.dir.uidlist; recno; recno = urec.r.uid.next ) {
-               read_record( recno, &urec, RECTYPE_UID );
-               if( !memcmp( uidhash, urec.r.uid.namehash, 20 ) )
-                   break;
-           }
-           if( recno ) {
-               ins_recno_list( &recno_list, recno, RECTYPE_UID );
-               uidrecno = recno;
-           }
-           else { /* new user id */
-               memset( &urec, 0 , sizeof(urec) );
-               urec.rectype = RECTYPE_UID;
-               urec.r.uid.lid = drec.recnum;
-               memcpy(urec.r.uid.namehash, uidhash, 20 );
-               urec.recnum = newrecno = tdbio_new_recnum();
-               write_record( &urec );
-               ins_recno_list( &recno_list, newrecno, RECTYPE_UID );
-               /* and put this new record at the end of the uidlist */
-               if( !(recno=drec.r.dir.uidlist) ) {
-                   /* this is the first uid */
-                   drec.r.dir.uidlist = newrecno;
-                   modified = 1;
-               }
-               else { /* we already have an uid, append it to the list */
-                   for( ; recno; recno = urec.r.key.next )
-                       read_record( recno, &urec, RECTYPE_UID );
-                   urec.r.uid.next = newrecno;
-                   write_record( &urec );
-               }
-               uidrecno = newrecno;
-           }
-       }
-       else if( node->pkt->pkttype == PKT_SIGNATURE ) {
-           PKT_signature *sig = node->pkt->pkt.signature;
-
-           if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
-               && (node->pkt->pkt.signature->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, node, NULL ))) {
-                   log_error("key %08lX, uid %02X%02X: "
-                             "invalid self-signature: %s\n", (ulong)keyid[1],
-                                   uidhash[18], uidhash[19], g10_errstr(rc) );
-                   rc = 0;
-               }
-               else { /* build the prefrecord */
-                   static struct {
-                       sigsubpkttype_t subpkttype;
-                       int preftype;
-                   } prefs[] = {
-                       { SIGSUBPKT_PREF_SYM,   PREFTYPE_SYM    },
-                       { SIGSUBPKT_PREF_HASH,  PREFTYPE_HASH   },
-                       { SIGSUBPKT_PREF_COMPR, PREFTYPE_COMPR  },
-                       { 0, 0 }
-                   };
-                   const byte *s;
-                   size_t n;
-                   int k, i;
-                   ulong recno_tbl[10];
-                   int recno_idx = 0;
-
-                   read_record( uidrecno, &urec, RECTYPE_UID );
-
-                   /* first delete all pref records */
-                   for(recno=urec.r.uid.prefrec ; recno;
-                                                  recno = prec.r.pref.next ) {
-                       read_record( recno, &prec, RECTYPE_PREF );
-                       delete_record( recno );
-                   }
+           upd_uid_record( node->pkt->pkt.user_id, &drec, &recno_list,
+                           keyid, &uidrecno, uidhash );
+           break;
 
-                   /* and write the new ones */
-                   i = 0;
-                   for(k=0; prefs[k].subpkttype; k++ ) {
-                       s = parse_sig_subpkt2( sig, prefs[k].subpkttype, &n );
-                       if( s ) {
-                           while( n ) {
-                               if( !i || i >= ITEMS_PER_PREF_RECORD ) {
-                                   if( recno_idx >= DIM(recno_tbl)-1 ) {
-                                       log_info("too many preferences\n");
-                                       break;
-                                   }
-                                   if( i ) {
-                                       recno_tbl[recno_idx]=tdbio_new_recnum();
-                                       prec.recnum = recno_tbl[recno_idx++];
-                                       write_record( &prec );
-                                   }
-                                   memset( &prec, 0, sizeof prec );
-                                   prec.rectype = RECTYPE_PREF;
-                                   prec.r.pref.lid = drec.recnum;
-                                   i = 0;
-                               }
-                               prec.r.pref.data[i++] = prefs[k].preftype;
-                               prec.r.pref.data[i++] = *s++;
-                               n--;
-                           }
-                       }
-                   }
-                   if( i ) { /* write the last one */
-                       recno_tbl[recno_idx]=tdbio_new_recnum();
-                       prec.recnum = recno_tbl[recno_idx++];
-                       write_record( &prec );
-                   }
-                   /* now link them together */
-                   for(i=0; i < recno_idx-1; i++ ) {
-                       read_record( recno_tbl[i], &prec, RECTYPE_PREF );
-                       prec.r.pref.next = recno_tbl[i+1];
-                       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 );
-               }
-           }
-           else if( 0 /* is revocation sig etc */ ) {
-               /* handle it here */
-           }
-           else { /* not a selfsignature */
+         case PKT_SIGNATURE:
+           if( drec.dirty ) { /* upd_sig_recrod may read the drec */
+               write_record( &drec );
+               drec.dirty = 0;
            }
+           upd_sig_record( node->pkt->pkt.signature, &drec,
+                           keyid, &uidrecno, uidhash, keyblock, node );
+           break;
+
+         default:
+           break;
        }
     } /* end loop over all nodes */
 
 
-    /* now delete keyrecords from the trustdb which are not anymore used */
+    /* delete keyrecords from the trustdb which are not anymore used */
     lastrecno = 0;
     for( recno=drec.r.dir.keylist; recno; recno = krec.r.key.next ) {
        read_record( recno, &krec, RECTYPE_KEY );
@@ -2148,7 +2339,7 @@ update_trust_record( KBNODE keyblock )
            /* delete this one */
            if( !lastrecno ) {
                drec.r.dir.keylist = krec.r.key.next;
-               modified = 1;
+               drec.dirty = 1;
            }
            else {
                read_record( lastrecno, &helprec, RECTYPE_KEY );
@@ -2160,7 +2351,7 @@ update_trust_record( KBNODE keyblock )
        else
            lastrecno = recno;
     }
-    /* now delete uid records and their pref records from the
+    /* delete uid records and sig and their pref records from the
      * trustdb which are not anymore used */
     lastrecno = 0;
     for( recno=drec.r.dir.uidlist; recno; recno = urec.r.uid.next ) {
@@ -2170,7 +2361,7 @@ update_trust_record( KBNODE keyblock )
            /* delete this one */
            if( !lastrecno ) {
                drec.r.dir.uidlist = urec.r.uid.next;
-               modified = 1;
+               drec.dirty = 1;
            }
            else {
                read_record( lastrecno, &helprec, RECTYPE_UID );
@@ -2181,6 +2372,10 @@ update_trust_record( KBNODE keyblock )
                read_record( r2, &prec, RECTYPE_PREF );
                delete_record( r2 );
            }
+           for(r2=urec.r.uid.siglist ; r2; r2 = helprec.r.sig.next ) {
+               read_record( r2, &helprec, RECTYPE_SIG );
+               delete_record( r2 );
+           }
            delete_record( recno );
        }
        else
@@ -2191,7 +2386,7 @@ update_trust_record( KBNODE keyblock )
 
     if( rc )
        ; /* fixme: cancel transaction */
-    else if( modified ) {
+    else if( drec.dirty ) {
        drec.r.dir.dirflags &= ~DIRF_CHECKED; /* reset flag */
        write_record( &drec );
        /* fixme: commit_transaction */
@@ -2203,29 +2398,33 @@ update_trust_record( KBNODE keyblock )
 
 /****************
  * Insert a trust record into the TrustDB
- * This function fails if this record already exists.
- *
- * We build everything we can do at this point. We cannot build
- * the sig records, because their LIDs are needed and we may not have them.
+ * This function assumes that the record does not yet exist.
  */
 int
 insert_trust_record( PKT_public_key *pk )
 {
     TRUSTREC dirrec;
+    TRUSTREC shadow;
     KBNODE keyblock = NULL;
     KBNODE node;
-    byte *fingerprint;
+    byte fingerprint[MAX_FINGERPRINT_LEN];
     size_t fingerlen;
     int rc = 0;
-
+    ulong hintlist = 0;
 
     if( pk->local_id )
        log_bug("pk->local_id=%lu\n", pk->local_id );
 
-    fingerprint = fingerprint_from_pk( pk, NULL, &fingerlen );
+    fingerprint_from_pk( pk, fingerprint, &fingerlen );
 
     /* fixme: assert that we do not have this record.
      * we can do this by searching for the primary keyid
+     *
+     * fixme: If there is no such key we should look whether one
+     * of the subkeys has been used to sign another key and in this case
+     * we got the key anyway.  Because a secondary key can't be used
+     * without a primary key (it is needed to bind the secondary one
+     * to the primary one which has the user ids etc.)
      */
 
     /* get the keyblock which has the key */
@@ -2236,9 +2435,37 @@ insert_trust_record( PKT_public_key *pk )
        goto leave;
     }
 
+    /* check that we used the primary key (we are little bit paranoid) */
+    {  PKT_public_key *a_pk;
+       node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
+       a_pk = node->pkt->pkt.public_key;
+       if( cmp_public_keys( a_pk, pk ) ) {
+           log_error("did not use primary key for insert_trust_record()\n");
+           rc = G10ERR_GENERAL;
+           goto leave;
+       }
+    }
+
+    /* We have to look for a shadow dir record which must be reused
+     * as the dir record. And: check all signatures which are listed
+     * in the hintlist of the shadow dir record.
+     */
+    rc = tdbio_search_sdir( pk->keyid, pk->pubkey_algo, &shadow );
+    if( rc && rc != -1 ) {
+       log_error("tdbio_search_dir failed: %s\n", g10_errstr(rc));
+       die_invalid_db();
+    }
     memset( &dirrec, 0, sizeof dirrec );
     dirrec.rectype = RECTYPE_DIR;
-    dirrec.recnum = tdbio_new_recnum();
+    if( !rc ) {
+       /* hey, great: this key has already signed other keys
+        * convert this to a real directory entry */
+       hintlist = shadow.r.sdir.hintlist;
+       dirrec.recnum = shadow.recnum;
+    }
+    else {
+       dirrec.recnum = tdbio_new_recnum();
+    }
     dirrec.r.dir.lid = dirrec.recnum;
     write_record( &dirrec );
 
@@ -2258,10 +2485,12 @@ insert_trust_record( PKT_public_key *pk )
 
     /* and put all the other stuff into the keydb */
     rc = update_trust_record( keyblock );
-
+    if( !rc )
+       process_hintlist( hintlist, dirrec.r.dir.lid );
 
   leave:
-    m_free(fingerprint);
+    if( rc && hintlist )
+       ; /* fixme: the hintlist is not anymore anchored */
     release_kbnode( keyblock );
     return rc;
 }
index db2743f..b0f3977 100644 (file)
@@ -55,6 +55,7 @@ int get_ownertrust_info( ulong lid );
 byte *get_pref_data( ulong lid, const byte *namehash, size_t *ret_n );
 int is_algo_in_prefs( ulong lid, int preftype, int algo );
 int keyid_from_lid( ulong lid, u32 *keyid );
+ulong lid_from_keyblock( KBNODE keyblock );
 int query_trust_record( PKT_public_key *pk );
 int clear_trust_checked_flag( PKT_public_key *pk );
 int insert_trust_record( PKT_public_key *pk );
index 08bccd5..84b7337 100644 (file)
@@ -59,6 +59,7 @@ char *m_strdup( const char * a);
 #endif
 
 size_t m_size( const void *a );
+void m_print_stats(const char *prefix);
 
 /*-- secmem.c --*/
 void secmem_init( size_t npool );
index 696fba4..b2e8296 100644 (file)
@@ -1,3 +1,7 @@
+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).
+
 Thu Sep 17 18:08:50 1998  Werner Koch  (wk@(none))
 
        * hppa1.1/udiv-qrnnd.S: Fix from Steffen Zahn for HPUX 10.20
index 62ac871..b5f5809 100644 (file)
@@ -146,8 +146,7 @@ mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
      * We need space for an extra limb in the remainder, because it's
      * up-shifted (normalized) below.  */
     rsize = nsize + 1;
-    if( rem->alloced < rsize )
-       mpi_resize( rem, rsize);
+    mpi_resize( rem, rsize);
 
     qsize = rsize - dsize;       /* qsize cannot be bigger than this.  */
     if( qsize <= 0 ) {
@@ -165,7 +164,7 @@ mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
        return;
     }
 
-    if( quot && quot->alloced < qsize )
+    if( quot )
        mpi_resize( quot, qsize);
 
     /* Read pointers here, when reallocation is finished.  */
@@ -198,7 +197,8 @@ mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
        /* Make sure QP and NP point to different objects.  Otherwise the
         * numerator would be gradually overwritten by the quotient limbs.  */
        if(qp == np) { /* Copy NP object to temporary space.  */
-           np = marker[markidx++] = mpi_alloc_limb_space(nsize,mpi_is_secure(quot));
+           np = marker[markidx++] = mpi_alloc_limb_space(nsize,
+                                                         mpi_is_secure(quot));
            MPN_COPY(np, qp, nsize);
        }
     }
index 150d87c..fca6096 100644 (file)
@@ -260,6 +260,9 @@ mpi_invm( MPI x, MPI a, MPI n )
     mpi_free(u3);
     mpi_free(v3);
     mpi_free(t3);
+
+    mpi_free(u);
+    mpi_free(v);
   #endif
 }
 
index e0ed531..0a7ef50 100644 (file)
@@ -111,7 +111,7 @@ mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m)
     }
 
     /* cleanup */
-    m_free(tmp);
+    mpi_free(tmp);
     for(i=0; i < (1<<k); i++ )
        mpi_free(G[i]);
     m_free(G);
index 5dd65ae..a94cbb4 100644 (file)
@@ -372,4 +372,3 @@ mpi_swap( MPI a, MPI b)
     tmp = *a; *a = *b; *b = tmp;
 }
 
-
index f72651f..5c4611e 100644 (file)
@@ -1,3 +1,12 @@
+Mon Oct 12 09:08:09 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * it.po: Imported new version.
+       * de.po: Imported new version.
+
+Sun Oct 11 16:24:27 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * fr.po: Imported new version
+
 Wed Oct  7 13:12:00 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
        * Makefile.in.in: Fixed mkinstalldirs problems
index 92a1d7f..1424ce8 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -1,6 +1,10 @@
 msgid ""
 msgstr ""
 "POT-Creation-Date: 1998-10-07 14:24+0200\n"
+"PO-Revision-Date: 1998-10-11 20:10+0200\n"
+"Last-Translator: Walter Koch <walterk@mail.dip.de>\n"
+"Language-Team: German <de@li.org>\n"
+"MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=\n"
 "Date: 1998-01-26 22:08:36+0100\n"
 "From: Werner Koch <wk@frodo>\n"
@@ -61,7 +65,7 @@ msgstr "Falsche Signatur"
 
 #: util/errors.c:62
 msgid "Checksum error"
-msgstr "Prüfsummen Fehler"
+msgstr "Prüfsummen-Fehler"
 
 #: util/errors.c:63
 msgid "Bad passphrase"
@@ -311,7 +315,7 @@ msgstr "Schl
 
 #: g10/g10.c:169
 msgid "sign or edit a key"
-msgstr ""
+msgstr "Unterschreiben oder Bearbeiten eines Schlüssels"
 
 #: g10/g10.c:170
 msgid "generate a revocation certificate"
@@ -341,11 +345,11 @@ msgstr "Keine \"Owner trust\" Werte ge
 
 #: g10/g10.c:180
 msgid "|[NAMES]|check the trust database"
-msgstr ""
+msgstr "|[NAMES]|Überprüfen der \"Trust\"-Datenbank"
 
 #: g10/g10.c:181
 msgid "fix a corrupted trust database"
-msgstr ""
+msgstr "Reparieren einer beschädigten \"Trust\"-Datenbank"
 
 #: g10/g10.c:182
 msgid "De-Armor a file or stdin"
@@ -357,7 +361,7 @@ msgstr "Datei oder stdin in eine ASCII-H
 
 #: g10/g10.c:184
 msgid "|algo [files]|print message digests"
-msgstr "|algo [files]|Hashwerte der Dateien ausgeben"
+msgstr "|algo [files]|Message-Digests für die Dateien ausgeben"
 
 #: g10/g10.c:185
 msgid "print all message digests"
@@ -471,7 +475,7 @@ msgstr "Fehler beim Erzeugen der \"Passphrase\": %s\n"
 #: g10/g10.c:222
 #, fuzzy
 msgid "|NAME|use message digest algorithm NAME for passphrases"
-msgstr "|NAME|Die Hashmethode NAME benutzen"
+msgstr "|NAME|Die Hashmethode NAME für die \"Passphrase\" benutzen"
 
 #: g10/g10.c:224
 #, fuzzy
@@ -2013,7 +2017,7 @@ msgstr "Eine abgetrennte Signatur erzeugen"
 
 #: g10/plaintext.c:215
 msgid "Please enter name of data file: "
-msgstr ""
+msgstr "Bitte geben Sie den Namen der Datendatei ein: "
 
 #: g10/plaintext.c:299
 #, c-format
@@ -2031,12 +2035,12 @@ msgstr "Ung
 
 #: g10/seckey-cert.c:215
 msgid "Warning: Weak key detected - please change passphrase again.\n"
-msgstr ""
+msgstr "Warnung: Unsicherer Schlüssel entdeckt - bitte die \"Passphrase\" nochmal eingeben.\n"
 
 #: g10/sig-check.c:155
 msgid ""
 "this is a PGP generated ElGamal key which is NOT secure for signatures!\n"
-msgstr ""
+msgstr "Dieser durch PGP erzeugte ElGamal-Schlüssel ist für Signaturen NICHT sicher genug!\n"
 
 #: g10/sig-check.c:165
 msgid "public key created in future (time warp or clock problem)\n"
@@ -2051,12 +2055,12 @@ msgstr "Achtung: Schl
 
 #: g10/trustdb.c:127
 msgid "The trust DB is corrupted; please run \"gpgm --fix-trust-db\".\n"
-msgstr ""
+msgstr "Die \"Trust\"-Datenbank ist beschädigt; verwenden Sie \"gpgm --fix-trust-db\".\n"
 
 #: g10/trustdb.c:406
 #, c-format
 msgid "chained sigrec %lu has a wrong owner\n"
-msgstr ""
+msgstr "Verketteter Signatursatz %lu hat einen falschen Besitzer\n"
 
 #: g10/trustdb.c:453
 #, c-format
@@ -2138,11 +2142,11 @@ msgstr "Keine Hilfe f
 #: g10/pubkey-enc.c:78
 #, c-format
 msgid "anonymous receiver; trying secret key %08lX ...\n"
-msgstr ""
+msgstr "Ungenannter Empfänger: Versuch mit geheimen Schlüssel %08lX ...\n"
 
 #: g10/pubkey-enc.c:84
 msgid "okay, we are the anonymous receiver.\n"
-msgstr ""
+msgstr "Gut, wir sind der ungenannte Empfänger.\n"
 
 #: g10/pubkey-enc.c:183
 #, c-format
@@ -2167,15 +2171,18 @@ msgstr "
 msgid ""
 "Warning: Message was encrypted with a weak key in the symmetric cipher.\n"
 msgstr ""
+"Warnung: Botschaft wurde mit einem unsicheren Schlüssel verschlüsselt.\n"
 
 #: g10/seskey.c:52
 msgid "weak key created - retrying\n"
-msgstr ""
+msgstr "Unsicherer Schlüssel erzeugt - neuer Versuch\n"
 
 #: g10/seskey.c:57
 #, c-format
 msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n"
 msgstr ""
+"Trotz %d-fachen Versuch konnte die Erzeugung eines unsicheren Schlüssel" 
+"für sym.Verschlüsselung nicht vermieden werden!\n"
 
 #, fuzzy
 #~ msgid "error reading sigrec: %s\n"
index 8d0e346..9208502 100644 (file)
--- a/po/fr.po
+++ b/po/fr.po
@@ -4,9 +4,9 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: gnupg-0.4.0\n"
-"POT-Creation-Date: 1998-10-07 14:24+0200\n"
-"PO-Revision-Date: 1998-09-17 03:14+0200\n"
+"Project-Id-Version: gnupg-0.4.1\n"
+"POT-Creation-Date: 1998-10-10 20:37+0200\n"
+"PO-Revision-Date: 1998-10-11 00:21+0200\n"
 "Last-Translator: Gaël Quéri <gqueri@mail.dotcom.fr>\n"
 "Language-Team: French <fr@li.org>\n"
 "MIME-Version: 1.0\n"
@@ -27,205 +27,183 @@ msgstr "oO"
 
 #: util/errors.c:54
 msgid "General error"
-msgstr ""
+msgstr "Erreur Générale"
 
 #: util/errors.c:55
 msgid "Unknown packet type"
-msgstr ""
+msgstr "Type de paquet inconnu"
 
 #: util/errors.c:56
 msgid "Unknown version"
-msgstr ""
+msgstr "Version inconnue"
 
 #: util/errors.c:57
 msgid "Unknown pubkey algorithm"
-msgstr ""
+msgstr "Algorithme de clé publique inconnu"
 
 #: util/errors.c:58
 msgid "Unknown digest algorithm"
-msgstr ""
+msgstr "Algorithme de hachage inconnu"
 
 #: util/errors.c:59
-#, fuzzy
 msgid "Bad public key"
-msgstr "pas de porte-clés public par défaut\n"
+msgstr "Mauvaise clé publique"
 
 #: util/errors.c:60
-#, fuzzy
 msgid "Bad secret key"
-msgstr "lister les clés secrètes"
+msgstr "Mauvaise clé secrète"
 
 #: util/errors.c:61
-#, fuzzy
 msgid "Bad signature"
-msgstr "une mauvaise signature\n"
+msgstr "Mauvaise signature"
 
 #: util/errors.c:62
 msgid "Checksum error"
-msgstr ""
+msgstr "Erreur de somme de vérification"
 
 #: util/errors.c:63
-#, fuzzy
 msgid "Bad passphrase"
-msgstr "Répétez le mot de passe: "
+msgstr "Mauvais mot de passe"
 
 #: util/errors.c:64
-#, fuzzy
 msgid "Public key not found"
-msgstr "clé %08lX: clé publique pas trouvée: %s\n"
+msgstr "Clé publique non trouvée"
 
 #: util/errors.c:65
-#, fuzzy
 msgid "Unknown cipher algorithm"
-msgstr "|NOM|utiliser l'algorithme de cryptage NOM"
+msgstr "Algorithme de chiffrement inconnu"
 
 #: util/errors.c:66
-#, fuzzy
 msgid "Can't open the keyring"
-msgstr "ne peut écrire le porte-clés\n"
+msgstr "Ne peut ouvrir le porte-clés"
 
 #: util/errors.c:67
-#, fuzzy
 msgid "Invalid packet"
-msgstr "valeur invalide\n"
+msgstr "Paquet invalide"
 
 #: util/errors.c:68
 msgid "Invalid armor"
-msgstr ""
+msgstr "Armure invalide"
 
 #: util/errors.c:69
-#, fuzzy
 msgid "No such user id"
-msgstr "Pas de tel utilisateur.\n"
+msgstr "Pas de tel utilisateur."
 
 #: util/errors.c:70
-#, fuzzy
 msgid "Secret key not available"
-msgstr "La clé secrète est disponible.\n"
+msgstr "La clé secrète n'est pas disponible."
 
 #: util/errors.c:71
-#, fuzzy
 msgid "Wrong secret key used"
-msgstr "lister les clés secrètes"
+msgstr "Mauvaise clé secrète utilisée"
 
 #: util/errors.c:72
 msgid "Not supported"
-msgstr ""
+msgstr "Non supporté"
 
 #: util/errors.c:73
-#, fuzzy
 msgid "Bad key"
-msgstr "aj.clé"
+msgstr "Mauvaise clé"
 
 #: util/errors.c:74
-#, fuzzy
 msgid "File read error"
-msgstr "erreur de lecture: %s\n"
+msgstr "Erreur de lecture"
 
 #: util/errors.c:75
 msgid "File write error"
-msgstr ""
+msgstr "Erreur d'écriture"
 
 #: util/errors.c:76
-#, fuzzy
 msgid "Unknown compress algorithm"
-msgstr "|N|utiliser l'algorithme de compression N"
+msgstr "Algorithme de compression inconnu"
 
 #: util/errors.c:77
 msgid "File open error"
-msgstr ""
+msgstr "Erreur d'ouverture de fichier"
 
 #: util/errors.c:78
 msgid "File create error"
-msgstr ""
+msgstr "Erreur de création de fichier"
 
 #: util/errors.c:79
-#, fuzzy
 msgid "Invalid passphrase"
-msgstr "Entrez le mot de passe: "
+msgstr "Mot de passe invalide"
 
 #: util/errors.c:80
 msgid "Unimplemented pubkey algorithm"
-msgstr ""
+msgstr "Algorithme de clé publique non implémenté"
 
 #: util/errors.c:81
-#, fuzzy
 msgid "Unimplemented cipher algorithm"
-msgstr "l'algorithme de cryptage sélectionné est invalide\n"
+msgstr "Algorithme de chiffrement non implémenté"
 
 #: util/errors.c:82
 msgid "Unknown signature class"
-msgstr ""
+msgstr "Classe de signature inconnue"
 
 #: util/errors.c:83
 msgid "Trust database error"
-msgstr ""
+msgstr "Erreur dans la base de confiance"
 
 #: util/errors.c:84
 msgid "Bad MPI"
-msgstr ""
+msgstr "Mauvais MPI"
 
 #: util/errors.c:85
 msgid "Resource limit"
-msgstr ""
+msgstr "Limite de ressources"
 
 #: util/errors.c:86
-#, fuzzy
 msgid "Invalid keyring"
-msgstr "Choix invalide.\n"
+msgstr "Porte-clés invalide"
 
 #: util/errors.c:87
 msgid "Bad certificate"
-msgstr ""
+msgstr "Mauvais certificat"
 
 #: util/errors.c:88
-#, fuzzy
 msgid "Malformed user id"
-msgstr "ajouter un utilisateur"
+msgstr "Nom d'utilisateur déformé"
 
 #: util/errors.c:89
 msgid "File close error"
-msgstr ""
+msgstr "Erreur de fermeture de fichier"
 
 #: util/errors.c:90
 msgid "File rename error"
-msgstr ""
+msgstr "Erreur pendant le changement de nom du fichier"
 
 #: util/errors.c:91
 msgid "File delete error"
-msgstr ""
+msgstr "Erreur pendant la suppression du fichier"
 
 #: util/errors.c:92
 msgid "Unexpected data"
-msgstr ""
+msgstr "Données inattendues"
 
 #: util/errors.c:93
 msgid "Timestamp conflict"
-msgstr ""
+msgstr "Conflit de dates"
 
 #: util/errors.c:94
-#, fuzzy
 msgid "Unusable pubkey algorithm"
-msgstr "|N|utiliser l'algorithme de compression N"
+msgstr "Algorithme de clés publiques inutilisable"
 
 #: util/errors.c:95
-#, fuzzy
 msgid "File exists"
-msgstr "Le fichier '%s' existe. "
+msgstr "Le fichier existe"
 
 #: util/errors.c:96
 msgid "Weak key"
-msgstr ""
+msgstr "Mauvaise clé"
 
 #: util/logger.c:177
-#, c-format
 msgid "Ohhhh jeeee ... this is a bug (%s:%d:%s)\n"
-msgstr ""
+msgstr "Ouais ... c'est un bug (%s:%d:%s)\n"
 
 #: util/logger.c:183
-#, c-format
 msgid "you found a bug ... (%s:%d)\n"
-msgstr ""
+msgstr "vous avez trouvé un bug ... (%s:%d)\n"
 
 #: cipher/rand-dummy.c:112
 msgid "warning: using insecure random number generator!!\n"
@@ -283,7 +261,7 @@ msgstr "crypter les donn
 
 #: g10/g10.c:154
 msgid "encryption only with symmetric cipher"
-msgstr "cryptage symétrique seumement"
+msgstr "chiffrement symétrique seumement"
 
 #: g10/g10.c:155
 msgid "store only"
@@ -359,7 +337,7 @@ msgstr "|[NOMS]|v
 
 #: g10/g10.c:181
 msgid "fix a corrupted trust database"
-msgstr ""
+msgstr "réparer une base de confiance corrompue"
 
 #: g10/g10.c:182
 msgid "De-Armor a file or stdin"
@@ -393,7 +371,7 @@ msgstr "cr
 
 #: g10/g10.c:196
 msgid "use this user-id to sign or decrypt"
-msgstr "utiliser ce nom d'utilisateur pour signer/décrypter"
+msgstr "utiliser ce nom pour signer ou décrypter"
 
 #: g10/g10.c:197
 msgid "use this user-id for encryption"
@@ -469,28 +447,24 @@ msgid "(default is 3)"
 msgstr "(3 par défaut)"
 
 #: g10/g10.c:218
-#, fuzzy
 msgid "|FILE|load extension module FILE"
-msgstr "|fich|charger un module d'extension"
+msgstr "|FICH|charger le module d'extension FICH"
 
 #: g10/g10.c:219
 msgid "emulate the mode described in RFC1991"
 msgstr "émuler le mode décrit dans la RFC1991"
 
 #: g10/g10.c:220
-#, fuzzy
 msgid "|N|use passphrase mode N"
-msgstr "Entrez le mot de passe: "
+msgstr "|N|utiliser le mode de mots de passe N"
 
 #: g10/g10.c:222
-#, fuzzy
 msgid "|NAME|use message digest algorithm NAME for passphrases"
-msgstr "|NOM|utiliser la fonction de hachage NOM"
+msgstr "|NOM|utiliser le hachage NOM pour les mots de passe"
 
 #: g10/g10.c:224
-#, fuzzy
 msgid "|NAME|use cipher algorithm NAME for passphrases"
-msgstr "|NOM|utiliser l'algorithme de cryptage NOM"
+msgstr "|NOM|utiliser le cryptage NOM pour les mots de passe"
 
 #: g10/g10.c:226
 msgid "|NAME|use cipher algorithm NAME"
@@ -506,10 +480,9 @@ msgstr "|N|utiliser l'algorithme de compression N"
 
 #: g10/g10.c:229
 msgid "throw keyid field of encrypted packets"
-msgstr "enlever l'idendification de la clé des paquets cryptés"
+msgstr "enlever l'identification des paquets cryptés"
 
 #: g10/g10.c:237
-#, fuzzy
 msgid ""
 "@\n"
 "Examples:\n"
@@ -617,11 +590,11 @@ msgstr "le nombre de singatures marginales minimal doit 
 
 #: g10/g10.c:796
 msgid "note: simple S2K mode (0) is strongly discouraged\n"
-msgstr ""
+msgstr "note: le mode S2K simple (0) est fortement déconseillé\n"
 
 #: g10/g10.c:800
 msgid "invalid S2K mode; must be 0, 1 or 3\n"
-msgstr ""
+msgstr "mode S2K invalide; doit être 0, 1 ou 3\n"
 
 #: g10/g10.c:876
 #, c-format
@@ -711,63 +684,61 @@ msgstr ""
 
 #: g10/armor.c:335 g10/armor.c:375
 msgid "armor header: "
-msgstr ""
+msgstr "entête d'armure: "
 
 #: g10/armor.c:340
-#, fuzzy
 msgid "invalid clearsig header\n"
-msgstr "Caractère invalide dans le nom\n"
+msgstr "entête de signature claire invalide\n"
 
 #: g10/armor.c:366
 msgid "invalid armor header: "
-msgstr ""
+msgstr "entête d'armure invalide: "
 
 #: g10/armor.c:440
-#, fuzzy, c-format
+#, c-format
 msgid "armor: %s\n"
-msgstr "erreur de lecture: %s\n"
+msgstr "armure: %s\n"
 
 #: g10/armor.c:484
 msgid "invalid dash escaped line: "
-msgstr ""
+msgstr "ligne d'échappement invalide: "
 
 #: g10/armor.c:553
 msgid "invalid clear text header: "
-msgstr ""
+msgstr "entête de texte clair invalide: "
 
 #: g10/armor.c:783
-#, fuzzy, c-format
 msgid "invalid radix64 character %02x skipped\n"
-msgstr "Caractère invalide dans le nom\n"
+msgstr "caractère %02x invalide en base 64 sauté\n"
 
 #: g10/armor.c:816
 msgid "premature eof (no CRC)\n"
-msgstr ""
+msgstr "fin de fichier prématurée (pas de CRC)\n"
 
 #: g10/armor.c:835
 msgid "premature eof (in CRC)\n"
-msgstr ""
+msgstr "fin de fichier prématurée (dans le CRC)\n"
 
 #: g10/armor.c:839
 msgid "malformed CRC\n"
-msgstr ""
+msgstr "CRC malformé\n"
 
 #: g10/armor.c:843
 #, c-format
 msgid "CRC error; %06lx - %06lx\n"
-msgstr ""
+msgstr "Erreur de CRC; 06lx - %06lx\n"
 
 #: g10/armor.c:862
 msgid "premature eof (in Trailer)\n"
-msgstr ""
+msgstr "fin de fichier prématurée (dans la remorque)\n"
 
 #: g10/armor.c:866
 msgid "error in trailer line\n"
-msgstr ""
+msgstr "erreur dans la ligne de remorque\n"
 
 #: g10/armor.c:1120
 msgid "no valid RFC1991 or OpenPGP data found.\n"
-msgstr ""
+msgstr "pas de donnée RFC1991 ou OpenPGP valide trouvée.\n"
 
 #: g10/pkclist.c:71
 #, c-format
@@ -775,7 +746,7 @@ msgid ""
 "No owner trust defined for %lu:\n"
 "%4u%c/%08lX %s \""
 msgstr ""
-"Pas de possesseur de confiance défini pour %lu:\n"
+"Pas de confiance définie pour %lu:\n"
 "%4u%c/%08lX %s"
 
 #: g10/pkclist.c:81
@@ -790,8 +761,8 @@ msgid ""
 " 4 = I trust fully\n"
 " s = please show me more information\n"
 msgstr ""
-"Décidez combien vous avez confiance en cet utilisateur pour vérifier\n"
-"correctement les clés des autres utilisateurs (en cherchant des passeports,\n"
+"Décidez à quel point vous avez confiance en cet utilisateur pour vérifier\n"
+"correctement les clés des autres utilisateurs (en regardant des passeports,\n"
 "en vérifiant les empreintes de diverses sources...)?\n"
 "\n"
 " 1 = Je ne sais pas\n"
@@ -1316,7 +1287,8 @@ msgstr "%s crypt
 #: g10/getkey.c:884
 #, c-format
 msgid "using secondary key %08lX instead of primary key %08lX\n"
-msgstr ""
+msgstr "utilisation de la clé secondaire %08lX à la place de la clé\n"
+"principale %08lX\n"
 
 #: g10/import.c:105 g10/trustdb.c:1389
 #, c-format
@@ -1442,9 +1414,9 @@ msgid "can't lock secret keyring: %s\n"
 msgstr "ne peut verrouiller le porte-clés secret: %s\n"
 
 #: g10/import.c:466
-#, fuzzy, c-format
+#, c-format
 msgid "can't write keyring: %s\n"
-msgstr "ne peut écrire sur le porte-clés: %s\n"
+msgstr "ne peut écrire le porte-clés: %s\n"
 
 #. we are ready
 #: g10/import.c:469
@@ -1467,7 +1439,7 @@ msgstr "cl
 #, c-format
 msgid "key %08lX: no public key - can't apply revocation certificate\n"
 msgstr ""
-"clé %08lX: pas de clé publique - ne peut appliquer le certificat de "
+"clé %08lX: pas de clé publique - ne peut appliquer le certificat de\n"
 "révocation\n"
 
 #: g10/import.c:538
@@ -1666,7 +1638,7 @@ msgstr "montrer cette aide"
 # g10/keyedit.c:556 ???
 #: g10/keyedit.c:455
 msgid "fpr"
-msgstr ""
+msgstr "fpr"
 
 #: g10/keyedit.c:455
 msgid "show fingerprint"
@@ -1686,7 +1658,7 @@ msgstr "l"
 
 #: g10/keyedit.c:458
 msgid "uid"
-msgstr ""
+msgstr "uid"
 
 #: g10/keyedit.c:458
 msgid "select user id N"
@@ -1710,7 +1682,7 @@ msgstr "lister les signatures"
 
 #: g10/keyedit.c:461
 msgid "c"
-msgstr ""
+msgstr "c"
 
 #: g10/keyedit.c:462
 msgid "sign"
@@ -1722,7 +1694,7 @@ msgstr "signer la cl
 
 #: g10/keyedit.c:463
 msgid "s"
-msgstr ""
+msgstr "s"
 
 #: g10/keyedit.c:464
 msgid "debug"
@@ -1770,11 +1742,11 @@ msgstr "passer de la liste des cl
 
 #: g10/keyedit.c:471
 msgid "t"
-msgstr ""
+msgstr "t"
 
 #: g10/keyedit.c:472
 msgid "pref"
-msgstr ""
+msgstr "préf"
 
 #: g10/keyedit.c:472
 msgid "list preferences"
@@ -1849,9 +1821,9 @@ msgid "Key not changed so no update needed.\n"
 msgstr "La clé n'a pas changé donc la mise à jour est inutile.\n"
 
 #: g10/keyedit.c:606 g10/keyedit.c:664
-#, fuzzy, c-format
+#, c-format
 msgid "update of trust db failed: %s\n"
-msgstr "la mise à jour de la clé secrète a échoué: %s\n"
+msgstr "la mise à jour de la base de confiance a échoué: %s\n"
 
 #: g10/keyedit.c:637
 msgid "keyedit.sign_all.okay"
@@ -1903,7 +1875,7 @@ msgstr "Voulez-vous vraiment supprimer cette cl
 
 #: g10/keyedit.c:746
 msgid "Invalid command  (try \"help\")\n"
-msgstr "Commande invalide  (essayez \"aide\")\n"
+msgstr "Commande invalide  (essayez \"help\")\n"
 
 #: g10/keyedit.c:1129
 #, c-format
@@ -1927,7 +1899,7 @@ msgstr "le d
 
 #: g10/mainproc.c:247
 msgid "note: sender requested \"for-your-eyes-only\"\n"
-msgstr ""
+msgstr "note: l'expéditeur a demandé \"pour vos yeux seulement\"\n"
 
 #: g10/mainproc.c:846
 #, c-format
@@ -1983,7 +1955,8 @@ msgstr "R
 
 #: g10/plaintext.c:102
 msgid "data not saved; use option \"--output\" to save it\n"
-msgstr ""
+msgstr "données non enregistrées; utilisez l'option \"--output\" pour\n"
+"les enregistrer\n"
 
 #: g10/plaintext.c:214
 msgid "detached_signature.filename"
@@ -2015,19 +1988,22 @@ msgstr "Attention: Mauvaise cl
 msgid ""
 "this is a PGP generated ElGamal key which is NOT secure for signatures!\n"
 msgstr ""
+"Cela est une clé ElGamal générée par PGP qui n'est PAS sûre pour les\n"
+"signatures!\n"
 
 #: g10/sig-check.c:165
 msgid "public key created in future (time warp or clock problem)\n"
-msgstr "clé publique créée dans le futur (problème d'horloge)\n"
+msgstr "clé publique créée dans le futur (voyage dans le temps ou problème\n"
+"d'horloge)\n"
 
 #: g10/sig-check.c:171
 #, c-format
 msgid "warning: signature key expired %s\n"
-msgstr "attention: la clé de signatute a expiré le %s\n"
+msgstr "attention: la clé de signature a expiré le %s\n"
 
 #: g10/trustdb.c:127
 msgid "The trust DB is corrupted; please run \"gpgm --fix-trust-db\".\n"
-msgstr ""
+msgstr "La base de confiance est corrompue; exécutez \"gpgm --fix-trust-db\".\n"
 
 #: g10/trustdb.c:406
 #, c-format
@@ -2065,14 +2041,14 @@ msgid "enum_secret_keys failed: %s\n"
 msgstr "enum_secret_keys a échoué: %s\n"
 
 #: g10/trustdb.c:964
-#, fuzzy, c-format
+#, c-format
 msgid "key %08lX.%lu, uid %02X%02X: no public key for signature %08lX\n"
-msgstr "clé %08lX: pas d'utilisateur pour la signature\n"
+msgstr "clé %08lX.%lu, uid %02X%02X: pas de clé publique pour la signature %08lX\n"
 
 #: g10/trustdb.c:971
-#, fuzzy, c-format
+#, c-format
 msgid "key %08lX.%lu, uid %02X%02X: invalid %ssignature: %s\n"
-msgstr "clé %08lX: auto-signature invalide\n"
+msgstr "clé %08lXi.%lu, uid %02X%02X: %ssignature invalide: %s\n"
 
 #: g10/trustdb.c:1658
 #, c-format
@@ -2154,6 +2130,3 @@ msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n"
 msgstr ""
 "ne peut éviter une mauvaise clé pour le chiffrement symétrique: \n"
 "%d essais ont eu lieu!\n"
-
-#~ msgid "error reading sigrec: %s\n"
-#~ msgstr "erreur pendant la lecture de l'enregistrement de signature: %s\n"
index 2dbfb08..3cb54c3 100644 (file)
--- a/po/it.po
+++ b/po/it.po
@@ -5,8 +5,8 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: gnupg-0.4.0\n"
-"POT-Creation-Date: 1998-10-07 14:24+0200\n"
-"PO-Revision-Date: 1998-09-20 16:15+02:00\n"
+"POT-Creation-Date: 1998-10-11 12:08+0200\n"
+"PO-Revision-Date: 1998-10-11 12:34+02:00\n"
 "Last-Translator: Marco d'Itri <md@linux.it>\n"
 "Language-Team: Italian <it@li.org>\n"
 "MIME-Version: 1.0\n"
@@ -27,204 +27,185 @@ msgstr "sS"
 
 #: util/errors.c:54
 msgid "General error"
-msgstr ""
+msgstr "Errore generale"
 
 #: util/errors.c:55
 msgid "Unknown packet type"
-msgstr ""
+msgstr "Tipo del pacchetto sconosciuto"
 
 #: util/errors.c:56
 msgid "Unknown version"
-msgstr ""
+msgstr "Versione sconosciuta"
 
 #: util/errors.c:57
 msgid "Unknown pubkey algorithm"
-msgstr ""
+msgstr "Algoritmo della chiave pubblica sconosciuto"
 
 #: util/errors.c:58
 msgid "Unknown digest algorithm"
-msgstr ""
+msgstr "Algoritmo del digest sconosciuto"
 
 #: util/errors.c:59
-#, fuzzy
 msgid "Bad public key"
-msgstr "nessun portachiavi pubblico predefinito\n"
+msgstr "Chiave pubblica errata o danneggiata"
 
 #: util/errors.c:60
-#, fuzzy
 msgid "Bad secret key"
-msgstr "elenca le chiavi segrete"
+msgstr "Chiave segreta errata o danneggiata"
 
 #: util/errors.c:61
-#, fuzzy
 msgid "Bad signature"
-msgstr "una firma non corretta\n"
+msgstr "Firma errata o danneggiata"
 
 #: util/errors.c:62
 msgid "Checksum error"
-msgstr ""
+msgstr "Checksum errato"
 
 #: util/errors.c:63
-#, fuzzy
 msgid "Bad passphrase"
-msgstr "Ripeti la passphrase: "
+msgstr "Passphrase errata"
 
 #: util/errors.c:64
-#, fuzzy
 msgid "Public key not found"
-msgstr "chiave %08lX: chiave pubblica non trovata: %s\n"
+msgstr "Chiave pubblica non trovata"
 
 #: util/errors.c:65
-#, fuzzy
 msgid "Unknown cipher algorithm"
-msgstr "|NAME|usa l'algoritmo di cifratura NOME"
+msgstr "Algoritmo di cifratura sconosciuto"
 
 #: util/errors.c:66
-#, fuzzy
 msgid "Can't open the keyring"
-msgstr "impossibile scrivere il portachiavi\n"
+msgstr "Impossibile aprire il portachiavi"
 
 #: util/errors.c:67
-#, fuzzy
 msgid "Invalid packet"
-msgstr "valore non valido\n"
+msgstr "Pacchetto non valido"
 
 #: util/errors.c:68
 msgid "Invalid armor"
-msgstr ""
+msgstr "Armatura non valida"
 
 #: util/errors.c:69
-#, fuzzy
 msgid "No such user id"
-msgstr "User ID inesistente.\n"
+msgstr "User id inesistente"
 
 #: util/errors.c:70
-#, fuzzy
 msgid "Secret key not available"
-msgstr "È disponibile una chiave segreta.\n"
+msgstr "La chiave segreta non è disponibile."
 
 #: util/errors.c:71
-#, fuzzy
 msgid "Wrong secret key used"
-msgstr "elenca le chiavi segrete"
+msgstr "È stata usata la chiave segreta sbagliata"
 
 #: util/errors.c:72
 msgid "Not supported"
-msgstr ""
+msgstr "Non gestito"
 
 #: util/errors.c:73
 msgid "Bad key"
-msgstr ""
+msgstr "Chiave danneggiata"
 
 #: util/errors.c:74
-#, fuzzy
 msgid "File read error"
-msgstr "errore di lettura: %s\n"
+msgstr "Errore durante la lettura del file"
 
 #: util/errors.c:75
 msgid "File write error"
-msgstr ""
+msgstr "Errore durante la scrittura del file"
 
 #: util/errors.c:76
-#, fuzzy
 msgid "Unknown compress algorithm"
-msgstr "|N|usa l'algoritmo di compressione N"
+msgstr "Algoritmo di compressione sconosciuto"
 
 #: util/errors.c:77
 msgid "File open error"
-msgstr ""
+msgstr "Errore durante l'apertura del file"
 
 #: util/errors.c:78
 msgid "File create error"
-msgstr ""
+msgstr "Errore durante la creazione del file"
 
 #: util/errors.c:79
-#, fuzzy
 msgid "Invalid passphrase"
-msgstr "Inserisci la passphrase: "
+msgstr "Passphrase non valida"
 
 #: util/errors.c:80
 msgid "Unimplemented pubkey algorithm"
-msgstr ""
+msgstr "Algoritmo della chiave pubblica non implementato"
 
 #: util/errors.c:81
-#, fuzzy
 msgid "Unimplemented cipher algorithm"
-msgstr "l'algoritmo di cifratura selezionato non è valido\n"
+msgstr "Algoritmo di cifratura non implementato"
 
 #: util/errors.c:82
 msgid "Unknown signature class"
-msgstr ""
+msgstr "Classe della firma sconosciuta."
 
 #: util/errors.c:83
 msgid "Trust database error"
-msgstr ""
+msgstr "Errore nel database della fiducia"
 
 #: util/errors.c:84
 msgid "Bad MPI"
-msgstr ""
+msgstr "MPI danneggiato"
 
 #: util/errors.c:85
 msgid "Resource limit"
-msgstr ""
+msgstr "Limite della risorsa"
 
 #: util/errors.c:86
-#, fuzzy
 msgid "Invalid keyring"
-msgstr "Scelta non valida.\n"
+msgstr "Portachiavi non valido"
 
 #: util/errors.c:87
 msgid "Bad certificate"
-msgstr ""
+msgstr "Certificato danneggiato"
 
 #: util/errors.c:88
-#, fuzzy
 msgid "Malformed user id"
-msgstr "aggiungi un user id"
+msgstr "User id malformato"
 
 #: util/errors.c:89
 msgid "File close error"
-msgstr ""
+msgstr "Errore durante la chiusura del file"
 
 #: util/errors.c:90
 msgid "File rename error"
-msgstr ""
+msgstr "Errore durante la rinominazione del file"
 
 #: util/errors.c:91
 msgid "File delete error"
-msgstr ""
+msgstr "Errore durante la cancellazione del file"
 
 #: util/errors.c:92
 msgid "Unexpected data"
-msgstr ""
+msgstr "Dati inaspettati"
 
 #: util/errors.c:93
 msgid "Timestamp conflict"
-msgstr ""
+msgstr "Date in conflitto"
 
 #: util/errors.c:94
-#, fuzzy
 msgid "Unusable pubkey algorithm"
-msgstr "|N|usa l'algoritmo di compressione N"
+msgstr "Algoritmo della chiave pubblica non utilizzabile"
 
 #: util/errors.c:95
-#, fuzzy
 msgid "File exists"
-msgstr "Il file '%s' esiste. "
+msgstr "Il file esiste"
 
 #: util/errors.c:96
 msgid "Weak key"
-msgstr ""
+msgstr "Chiave debole"
 
 #: util/logger.c:177
 #, c-format
 msgid "Ohhhh jeeee ... this is a bug (%s:%d:%s)\n"
-msgstr ""
+msgstr "Ohhh... questo è un bug (%s:%d:%s)\n"
 
 #: util/logger.c:183
 #, c-format
 msgid "you found a bug ... (%s:%d)\n"
-msgstr ""
+msgstr "Hai trovato un bug... (%s:%d)\n"
 
 #: cipher/rand-dummy.c:112
 msgid "warning: using insecure random number generator!!\n"
@@ -356,7 +337,7 @@ msgstr "|[NAMES]|controlla il TrustDB"
 
 #: g10/g10.c:181
 msgid "fix a corrupted trust database"
-msgstr ""
+msgstr "ripara un database della fiducia rovinato"
 
 #: g10/g10.c:182
 msgid "De-Armor a file or stdin"
@@ -466,28 +447,24 @@ msgid "(default is 3)"
 msgstr "(predefinito è 3)"
 
 #: g10/g10.c:218
-#, fuzzy
 msgid "|FILE|load extension module FILE"
-msgstr "|file|carica un modulo di estensione"
+msgstr "|FILE|carica il modulo di estensione FILE"
 
 #: g10/g10.c:219
 msgid "emulate the mode described in RFC1991"
 msgstr "emula il modo descritto nel RFC1991"
 
 #: g10/g10.c:220
-#, fuzzy
 msgid "|N|use passphrase mode N"
-msgstr "Inserisci la passphrase: "
+msgstr "|N|usa il modo N per la passphrase"
 
 #: g10/g10.c:222
-#, fuzzy
 msgid "|NAME|use message digest algorithm NAME for passphrases"
 msgstr "|NAME|usa l'algoritmo di message digest NOME"
 
 #: g10/g10.c:224
-#, fuzzy
 msgid "|NAME|use cipher algorithm NAME for passphrases"
-msgstr "|NAME|usa l'algoritmo di cifratura NOME"
+msgstr "|NAME|usa l'algoritmo di cifratura NOME per le passphrase"
 
 #: g10/g10.c:226
 msgid "|NAME|use cipher algorithm NAME"
@@ -506,7 +483,6 @@ msgid "throw keyid field of encrypted packets"
 msgstr "elimina il campo keyid dei pacchetti crittografati"
 
 #: g10/g10.c:237
-#, fuzzy
 msgid ""
 "@\n"
 "Examples:\n"
@@ -523,8 +499,8 @@ msgstr ""
 " -se -r Bob [file]          firma e cifra per l'utente Bob\n"
 " --clearsign [file]         fai una firma mantenendo il testo in chiaro\n"
 " --detach-sign [file]       fai una firma separata\n"
-" --list-keys [names]        mostra le chiavi\n"
-" --fingerprint [names]      mostra le impronte digitali\n"
+" --list-keys [nomi]         mostra le chiavi\n"
+" --fingerprint [nomi]       mostra le impronte digitali\n"
 
 #: g10/g10.c:312
 msgid "Please report bugs to <gnupg-bugs@gnu.org>.\n"
@@ -614,11 +590,11 @@ msgstr "marginals-needed deve essere maggiore di 1\n"
 
 #: g10/g10.c:796
 msgid "note: simple S2K mode (0) is strongly discouraged\n"
-msgstr ""
+msgstr "nota: il modo S2K semplice (0) è fortemente scoraggiato\n"
 
 #: g10/g10.c:800
 msgid "invalid S2K mode; must be 0, 1 or 3\n"
-msgstr ""
+msgstr "modo S2K non valido; deve essere 0, 1 o 3\n"
 
 #: g10/g10.c:876
 #, c-format
@@ -708,63 +684,62 @@ msgstr ""
 
 #: g10/armor.c:335 g10/armor.c:375
 msgid "armor header: "
-msgstr ""
+msgstr "header dell'armatura: "
 
 #: g10/armor.c:340
-#, fuzzy
 msgid "invalid clearsig header\n"
-msgstr "Carattere non valido nel nome\n"
+msgstr "header della firma in chiaro non valido\n"
 
 #: g10/armor.c:366
 msgid "invalid armor header: "
-msgstr ""
+msgstr "header dell'armatura non valido: "
 
 #: g10/armor.c:440
-#, fuzzy, c-format
+#, c-format
 msgid "armor: %s\n"
-msgstr "errore di lettura: %s\n"
+msgstr "armatura: %s\n"
 
 #: g10/armor.c:484
 msgid "invalid dash escaped line: "
-msgstr ""
+msgstr "riga protetta con il trattino non valida: "
 
 #: g10/armor.c:553
 msgid "invalid clear text header: "
-msgstr ""
+msgstr "header del testo in chiaro non valido: "
 
 #: g10/armor.c:783
-#, fuzzy, c-format
+#, c-format
 msgid "invalid radix64 character %02x skipped\n"
-msgstr "Carattere non valido nel nome\n"
+msgstr "Carattere radix64 non valido %02x saltato\n"
 
 #: g10/armor.c:816
 msgid "premature eof (no CRC)\n"
-msgstr ""
+msgstr "eof prematura (nessun CRC)\n"
 
 #: g10/armor.c:835
 msgid "premature eof (in CRC)\n"
-msgstr ""
+msgstr "eof prematura (nel CRC)\n"
 
 #: g10/armor.c:839
 msgid "malformed CRC\n"
-msgstr ""
+msgstr "CRC malformato\n"
 
 #: g10/armor.c:843
 #, c-format
 msgid "CRC error; %06lx - %06lx\n"
-msgstr ""
+msgstr "errore nel CRC; %06lx - %06lx\n"
 
 #: g10/armor.c:862
 msgid "premature eof (in Trailer)\n"
-msgstr ""
+msgstr "eof prematura (nella coda)\n"
 
 #: g10/armor.c:866
 msgid "error in trailer line\n"
-msgstr ""
+msgstr "errore nella riga della coda\n"
 
 #: g10/armor.c:1120
 msgid "no valid RFC1991 or OpenPGP data found.\n"
-msgstr ""
+msgstr "Non sono stati trovati dati RFC1991 o OpenPGP validi.\n"
 
 #: g10/pkclist.c:71
 #, c-format
@@ -1302,7 +1277,7 @@ msgstr "%s crittografato per: %s\n"
 #: g10/getkey.c:884
 #, c-format
 msgid "using secondary key %08lX instead of primary key %08lX\n"
-msgstr ""
+msgstr "uso la chiave secondaria %08lX invece della chiave primaria %08lX\n"
 
 #: g10/import.c:105 g10/trustdb.c:1389
 #, c-format
@@ -1428,9 +1403,9 @@ msgid "can't lock secret keyring: %s\n"
 msgstr "impossibile bloccare il portachiavi segreto: %s\n"
 
 #: g10/import.c:466
-#, fuzzy, c-format
+#, c-format
 msgid "can't write keyring: %s\n"
-msgstr "impossibile scrivere sul portachiavi pubblico: %s\n"
+msgstr "impossibile scrivere il portachiavi: %s\n"
 
 #. we are ready
 #: g10/import.c:469
@@ -1833,9 +1808,9 @@ msgid "Key not changed so no update needed.\n"
 msgstr "La chiave non è cambiata quindi non sono necessari aggiornamenti.\n"
 
 #: g10/keyedit.c:606 g10/keyedit.c:664
-#, fuzzy, c-format
+#, c-format
 msgid "update of trust db failed: %s\n"
-msgstr "aggiornamento della chiave segreta fallito: %s\n"
+msgstr "aggiornamento del trustdb fallito: %s\n"
 
 #: g10/keyedit.c:637
 msgid "keyedit.sign_all.okay"
@@ -1911,7 +1886,7 @@ msgstr "decifratura fallita: %s\n"
 
 #: g10/mainproc.c:247
 msgid "note: sender requested \"for-your-eyes-only\"\n"
-msgstr ""
+msgstr "nota: il mittente ha richiesto \"solo-per-i-tuoi-occhi\"\n"
 
 #: g10/mainproc.c:846
 #, c-format
@@ -1964,7 +1939,7 @@ msgstr "Ripeti la passphrase: "
 
 #: g10/plaintext.c:102
 msgid "data not saved; use option \"--output\" to save it\n"
-msgstr ""
+msgstr "i dati non sono stati salvati; usa l'opzione \"--output\" per salvarli\n"
 
 #: g10/plaintext.c:214
 msgid "detached_signature.filename"
@@ -1997,7 +1972,7 @@ msgstr ""
 #: g10/sig-check.c:155
 msgid ""
 "this is a PGP generated ElGamal key which is NOT secure for signatures!\n"
-msgstr ""
+msgstr "questa è una chiave ElGamal generata da PGP che NON è sicura per le firme!\n"
 
 #: g10/sig-check.c:165
 msgid "public key created in future (time warp or clock problem)\n"
@@ -2012,7 +1987,7 @@ msgstr "attenzione: firma della chiave scaduta il %s\n"
 
 #: g10/trustdb.c:127
 msgid "The trust DB is corrupted; please run \"gpgm --fix-trust-db\".\n"
-msgstr ""
+msgstr "Il trustdb è rovinato; per favore esegui \"gpgm --fix-trust-db\".\n"
 
 #: g10/trustdb.c:406
 #, c-format
@@ -2050,14 +2025,14 @@ msgid "enum_secret_keys failed: %s\n"
 msgstr "enum_secret_keys fallito: %s\n"
 
 #: g10/trustdb.c:964
-#, fuzzy, c-format
+#, c-format
 msgid "key %08lX.%lu, uid %02X%02X: no public key for signature %08lX\n"
-msgstr "chiave %08lX: nessun user id per la firma\n"
+msgstr "chiave %08lX.%lu: uid %02X%02X: nessuna chiave pubblica per la firma %08lX\n"
 
 #: g10/trustdb.c:971
-#, fuzzy, c-format
+#, c-format
 msgid "key %08lX.%lu, uid %02X%02X: invalid %ssignature: %s\n"
-msgstr "chiave %08lX: autofirma non valida\n"
+msgstr "chiave %08lX.%lu, uid %02X%02X: firma %s non valida: %s\n"
 
 #: g10/trustdb.c:1658
 #, c-format
@@ -2140,6 +2115,3 @@ msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n"
 msgstr ""
 "Impossibile evitare una chiave debole per il cifrario simmetrico;\n"
 "ho provato %d volte!\n"
-
-#~ msgid "error reading sigrec: %s\n"
-#~ msgstr "errore leggendo la sigrec: %s\n"
index 075f0bf..f654ab1 100644 (file)
@@ -26,14 +26,12 @@ tar -xvzf $RPM_SOURCE_DIR/gnupg-@pkg_version@.tar.gz
 %build
 cd gnupg-@pkg_version@
 chown -R root.root *
-./configure
+./configure  --prefix=/usr
 make
 
 %install
 cd gnupg-@pkg_version@
 make install
-chmod +s /usr/local/bin/gpg
-chmod +s /usr/local/bin/gpgm
 
 %files
 %doc gnupg-@pkg_version@/doc/DETAILS
@@ -47,13 +45,16 @@ chmod +s /usr/local/bin/gpgm
 %doc gnupg-@pkg_version@/README
 %doc gnupg-@pkg_version@/THANKS
 %doc gnupg-@pkg_version@/TODO
-/usr/local/man/man1/gpg.1
-/usr/local/bin/gpg
-/usr/local/bin/gpgm
-/usr/local/share/locale/en/LC_MESSAGES/gnupg.mo
-/usr/local/share/locale/de/LC_MESSAGES/gnupg.mo
-/usr/local/share/locale/it/LC_MESSAGES/gnupg.mo
-/usr/local/share/locale/fr/LC_MESSAGES/gnupg.mo
-/usr/local/lib/gnupg/tiger
-/usr/local/lib/gnupg/twofish
+/usr/man/man1/gpg.1
+/usr/bin/gpg
+/usr/bin/gpgm
+/usr/share/locale/en/LC_MESSAGES/gnupg.mo
+/usr/share/locale/de/LC_MESSAGES/gnupg.mo
+/usr/share/locale/it/LC_MESSAGES/gnupg.mo
+/usr/share/locale/fr/LC_MESSAGES/gnupg.mo
+/usr/lib/gnupg/tiger
+/usr/lib/gnupg/twofish
+
+%attr (4755,root,root) /usr/bin/gpg
+%attr (4755,root,root) /usr/bin/gpgm
 
index 05c6244..0f444d9 100644 (file)
@@ -1,3 +1,7 @@
+Wed Oct  7 19:27:50 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * memory.c (m_print_stats): New.
+
 Tue Oct  6 09:53:56 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
        * strgutil.c (memicmp): Add HAVE_MEMICMP.
index baef604..eee154e 100644 (file)
@@ -6,7 +6,8 @@ noinst_LIBRARIES = libutil.a
 
 
 libutil_a_SOURCES = g10u.c logger.c fileutil.c miscutil.c strgutil.c  \
-                   ttyio.c  argparse.c memory.c secmem.c errors.c iobuf.c
+                   ttyio.c  argparse.c memory.c secmem.c errors.c iobuf.c \
+                   dotlock.c
 
 
 
diff --git a/util/dotlock.c b/util/dotlock.c
new file mode 100644 (file)
index 0000000..42bb727
--- /dev/null
@@ -0,0 +1,178 @@
+/* dotlock.c - dotfile locking
+ *     Copyright (C) 1998 Free Software Foundation, Inc.
+ *
+ * This file is part of GNUPG.
+ *
+ * GNUPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GNUPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include "types.h"
+#include "util.h"
+#include "memory.h"
+
+
+
+
+#if 0
+/****************
+ * Create a lockfile with the given name. A TIMEOUT of 0
+ * returns immediately, -1 waits forever (hopefully not), other
+ * values are timeouts in milliseconds.
+ * Returns: a char pointer used as handle for reelase lock
+ *         or NULL in case of an error.
+ *
+ * Notes: This function creates a lock file in the same directory
+ *       as file_to_lock with the name "file_to_lock.lock"
+ *       A temporary file ".#lk.<pid>.<hostname> is used.
+ *       This function does nothing for Windoze.
+ */
+int
+make_dotlock( const char *file_to_lock, long timeout )
+{
+    int rc=-1, fd=-1, pid;
+    char pidstr[16];
+    char *tname = NULL;
+    char *p;
+
+    log_debug("dotlock_make: lock='%s'\n", lockfile );
+    sprintf( pidstr, "%10d\n", getpid() );
+    /* add the hostname to the second line (FQDN or IP addr?) */
+
+    /* create a temporary file */
+    tname = CreateTmpFile2( p, ".#lk" );
+    free(p);
+    if( !tname )
+       log_fatal( "could not create temporary lock file '%s'\n");
+    log_debug( "dotlock_make: tmpname='%s'\n", tname );
+    chmod( tname, 0644 ); /* just in case an "umask" is set */
+    if( !(fd = open( tname, O_WRONLY )) )
+       log_fatal( "could not open temporary lock file '%s'\n", tname);
+    if( write(fd, pidstr, 11 ) != 11 )
+       log_fatal( "error writing to temporary lock file '%s'\n", tname);
+    if( close(fd) ) {
+       log_fatal( "error closing '%s'\n", tname);
+
+  retry:
+    if( !link(tname, lockfile) )
+       rc = 0; /* okay */
+    else if( errno != EEXIST )
+       log_error( "lock not made: link() failed: %s\n", strerror(errno) );
+    else { /* lock file already there */
+       if( (pid = read_lockfile(lockfile)) == -1 ) {
+           if( errno == ENOENT ) {
+               log_debug( "lockfile disappeared\n");
+               goto retry;
+           }
+           log_debug("cannot read lockfile\n");
+       }
+       else if( pid == getpid() ) {
+           log_info( "Oops: lock already hold by us\n");
+           rc = 0;  /* okay */
+       }
+       else if( kill(pid, 0) && errno == ESRCH ) {
+           log_info( "removing stale lockfile (created by %d)", (int)pid );
+           remove( lockfile );
+           goto retry;
+       }
+       log_debug( "lock not made: lock file exists\n" );
+    }
+
+    if( tname ) {
+       remove(tname);
+       free(tname);
+    }
+    if( !rc )
+       log_debug( "lock made\n");
+    return rc;
+}
+
+/****************
+ * Create a lockfile for a existing file
+ * Returns: a char pointer used as handle for release lock
+ *         or NULL in case of an error.
+ *
+ * Notes: This function creates a lock file in the same directory
+ *       as file_to_lock with the name "lock.<inode-no>"
+ *
+ * int
+ * make_inodelock( const char *file_to_lock )
+ *
+ */
+
+
+
+
+/****************
+ * release a lock
+ * Returns: 0 := success
+ */
+int
+release_dotlock( const char *lockfile )
+{
+    int pid = ReadLockfile( lockfile );
+    if( pid == -1 ) {
+       Log_printf( LERROR, "ReleaseLock: lockfile error");
+       return -1;
+    }
+    if( pid != getpid() ) {
+       Log_printf( LERROR, "ReleaseLock: not our lock (pid=%d)", pid);
+       return -1;
+    }
+    if( remove(lockfile) ) {
+       Log_printf( LERROR, "ReleaseLock: error removing lockfile '%s'",
+                                                           lockfile);
+       return -1;
+    }
+    Log_printf( LMESG, "ReleaseLock: released lockfile '%s'", lockfile);
+    return 0;
+}
+
+
+/****************
+ * Read the lock file and return the pid, returns -1 on error.
+ */
+static int
+read_lockfile( const char *name )
+{
+    int fd, pid;
+    char pidstr[16];
+
+    if( (fd = open(name, O_RDONLY)) == -1 ) {
+       int e = errno;
+       Log_printf(LJUNK, "error opening lockfile '%s'", name );
+       errno = e;  /* restore errno */
+       return -1;
+    }
+    if( read(fd, pidstr, 10 ) != 10 ) {
+       Log_printf(LNOISE, "error reading lockfile '%s'", name );
+       close(fd);
+       errno = 0;
+       return -1;
+    }
+    close(fd);
+    pid = atoi(pidstr);
+    if( !pid || pid == -1 ) {
+       Log_printf(LERROR, "invalid pid %d in lockfile '%s'", pid, name );
+       errno = 0;
+       return -1;
+    }
+    return pid;
+}
+#endif
index 013bd55..586a744 100644 (file)
@@ -80,6 +80,10 @@ const void membug( const char *fmt, ... );
 #endif
 
 
+#ifdef M_GUARD
+static long used_memory;
+#endif
+
 #ifdef M_DEBUG /* stuff used for memory debuging */
 
 struct info_entry {
@@ -302,6 +306,7 @@ dump_table( void)
                                                           sum, chunks );
 }
 
+
 static void
 check_allmem( const char *info )
 {
@@ -333,6 +338,40 @@ membug( const char *fmt, ... )
 }
 
 
+void
+m_print_stats( const char *prefix )
+{
+  #ifdef M_DEBUG
+    unsigned n;
+    struct memtbl_entry *e;
+    ulong sum = 0, chunks =0;
+
+    for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
+       if(e->inuse) {
+           sum += e->user_n;
+           chunks++;
+       }
+    }
+
+    log_debug( "%s%smemstat: %8lu bytes in %ld chunks used\n",
+               prefix? prefix:"", prefix? ": ":"", sum, chunks );
+  #elif defined(M_GUARD)
+    log_debug( "%s%smemstat: %8ld bytes\n",
+               prefix? prefix:"", prefix? ": ":"", used_memory );
+  #endif
+}
+
+void
+m_dump_table( const char *prefix )
+{
+  #if M_DEBUG
+    fprintf(stderr,"Memory-Table-Dump: %s\n", prefix);
+    dump_table();
+  #endif
+    m_print_stats( prefix );
+}
+
+
 static void
 out_of_core(size_t n, int secure)
 {
@@ -354,6 +393,7 @@ FNAME(alloc)( size_t n FNAMEPRT )
     if( !(p = malloc( n + EXTRA_ALIGN+5 )) )
        out_of_core(n,0);
     store_len(p,n,0);
+    used_memory += n;
     p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
     return p+EXTRA_ALIGN+4;
   #else
@@ -457,8 +497,10 @@ FNAME(free)( void *a FNAMEPRT )
     m_check(p);
     if( m_is_secure(a) )
        secmem_free(p-EXTRA_ALIGN-4);
-    else
+    else {
+       used_memory -= m_size(a);
        free(p-EXTRA_ALIGN-4);
+    }
   #else
     if( m_is_secure(a) )
        secmem_free(p);