diff --git a/ChangeLog b/ChangeLog index 330ede5c8..6a6464750 100644 --- 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 863cc4d5b..60252d126 100644 --- 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 diff --git a/Makefile.am b/Makefile.am index 138f0d372..49aa43817 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 52691f829..40d763c42 100644 --- 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 ad836c3d7..e5667035b 100644 --- a/README +++ b/README @@ -1,5 +1,3 @@ ------BEGIN PGP SIGNED MESSAGE----- - GNUPG - The GNU Privacy Guard ------------------------------- Version 0.4 @@ -332,12 +330,12 @@ post them to the mailing list (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 c6013c9ce..81aae8e1d 100644 --- 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 c1da6284e..60cc105b8 100644 --- 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 267577d47..39bbca703 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.4.1 +0.4.1a diff --git a/acconfig.h b/acconfig.h index 7bd261441..9f8550ca8 100644 --- a/acconfig.h +++ b/acconfig.h @@ -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*/ diff --git a/checks/run-gpg.patterns b/checks/run-gpg.patterns index 7fd9f2c49..5bb349cff 100644 --- a/checks/run-gpg.patterns +++ b/checks/run-gpg.patterns @@ -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 diff --git a/cipher/ChangeLog b/cipher/ChangeLog index ad6a76a37..ddd34b65c 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,7 @@ +1998-10-10 SL Baur + + * 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 :-) diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 26c625dcb..298e0f32d 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -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: diff --git a/cipher/dsa.c b/cipher/dsa.c index accbca9e8..2d5c17344 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -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; diff --git a/cipher/md.c b/cipher/md.c index 0ec6d6067..819cc1d08 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -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; } diff --git a/configure.in b/configure.in index 633b33354..ae674ae2b 100644 --- a/configure.in +++ b/configure.in @@ -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 +]) diff --git a/doc/DETAILS b/doc/DETAILS index efd412ca7..dca87afff 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -1,16 +1,44 @@ +Format of "---with-colons" listings +=================================== + +sec::1024:17:6C7EE1B8621CC013:1998-07-07:0:::Werner Koch : +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 "# 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. + - * 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. - - +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 62003e2ec..ee7f8107b 100644 --- a/doc/FAQ +++ b/doc/FAQ @@ -171,7 +171,7 @@ (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 @@ -187,8 +187,8 @@ 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 @@ -259,5 +259,23 @@ 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.)] diff --git a/doc/gpg.1pod b/doc/gpg.1pod index 5a2172205..2f76e80a3 100644 --- a/doc/gpg.1pod +++ b/doc/gpg.1pod @@ -12,7 +12,7 @@ B [--homedir name] [--options file] [options] command [args] B is the main program for the GNUPG system. B is a maintenance tool which has some commands B 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 B<--cipher-algo> I Use I 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 Use I 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 B<--digest-algo> I Use I 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. diff --git a/g10/ChangeLog b/g10/ChangeLog index 6e420e5e1..93a21e241 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -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 diff --git a/g10/Makefile.am b/g10/Makefile.am index b38037d28..da04fece3 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -86,3 +86,4 @@ g10maint.o: $(srcdir)/g10.c $(PROGRAMS): $(needed_libs) + diff --git a/g10/armor.c b/g10/armor.c index c72526a98..df67712a4 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -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: diff --git a/g10/g10.c b/g10/g10.c index ca9b44dac..9195d21a8 100644 --- 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(); diff --git a/g10/getkey.c b/g10/getkey.c index 886d53cc9..6e4c34592 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -33,27 +33,11 @@ #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 */ + #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 - /* 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_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(); diff --git a/g10/kbnode.c b/g10/kbnode.c index 428768105..18b16d0bd 100644 --- a/g10/kbnode.c +++ b/g10/kbnode.c @@ -28,12 +28,20 @@ #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 diff --git a/g10/keyedit.c b/g10/keyedit.c index 6f9c1c7c1..ea64d3870 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -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); } diff --git a/g10/keyid.c b/g10/keyid.c index 2de67ccf2..387c3fa9a 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -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 * diff --git a/g10/mainproc.c b/g10/mainproc.c index e5c83287a..a47885b74 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -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); } diff --git a/g10/revoke.c b/g10/revoke.c index 61d1e4c5c..74c11cb01 100644 --- a/g10/revoke.c +++ b/g10/revoke.c @@ -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")); diff --git a/g10/ringedit.c b/g10/ringedit.c index ace7adc5f..677420e25 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -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; } diff --git a/g10/tdbio.c b/g10/tdbio.c index 70cf4a1ba..82b22b43a 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -39,6 +39,18 @@ #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; @@ -148,6 +160,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. */ @@ -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; + 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) ); } - - 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; - } - - 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; + byte key[8]; - 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 */ + /* 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; } diff --git a/g10/tdbio.h b/g10/tdbio.h index b59b4e40e..66579ad14 100644 --- a/g10/tdbio.h +++ b/g10/tdbio.h @@ -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 @@ -47,19 +48,28 @@ #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) | \ diff --git a/g10/trustdb.c b/g10/trustdb.c index 78b7b0aa0..18726f151 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -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; +} + + /**************** @@ -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; @@ -766,291 +741,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 */ @@ -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; +} + + /**************** - * 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 + * 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 ); +} + + + +/**************** + * 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; + upd_uid_record( node->pkt->pkt.user_id, &drec, &recno_list, + keyid, &uidrecno, uidhash ); + break; - 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; + case PKT_SIGNATURE: + if( drec.dirty ) { /* upd_sig_recrod may read the drec */ + write_record( &drec ); + drec.dirty = 0; } - 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; + upd_sig_record( node->pkt->pkt.signature, &drec, + keyid, &uidrecno, uidhash, keyblock, node ); + break; - 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 ); - } - - /* 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 */ - } + 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; } diff --git a/g10/trustdb.h b/g10/trustdb.h index db2743fbf..b0f39770f 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -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 ); diff --git a/include/memory.h b/include/memory.h index 08bccd5ec..84b7337c6 100644 --- a/include/memory.h +++ b/include/memory.h @@ -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 ); diff --git a/mpi/ChangeLog b/mpi/ChangeLog index 696fba4dc..b2e8296ad 100644 --- a/mpi/ChangeLog +++ b/mpi/ChangeLog @@ -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 diff --git a/mpi/mpi-div.c b/mpi/mpi-div.c index 62ac87158..b5f5809f1 100644 --- a/mpi/mpi-div.c +++ b/mpi/mpi-div.c @@ -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); } } diff --git a/mpi/mpi-inv.c b/mpi/mpi-inv.c index 150d87ca1..fca609600 100644 --- a/mpi/mpi-inv.c +++ b/mpi/mpi-inv.c @@ -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 } diff --git a/mpi/mpi-mpow.c b/mpi/mpi-mpow.c index e0ed53109..0a7ef50e9 100644 --- a/mpi/mpi-mpow.c +++ b/mpi/mpi-mpow.c @@ -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<\n" +"Language-Team: German \n" +"MIME-Version: 1.0\n" "Content-Type: text/plain; charset=\n" "Date: 1998-01-26 22:08:36+0100\n" "From: Werner Koch \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" diff --git a/po/fr.po b/po/fr.po index 8d0e34644..9208502ce 100644 --- 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 \n" "Language-Team: French \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" diff --git a/po/it.po b/po/it.po index 2dbfb0882..3cb54c339 100644 --- 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 \n" "Language-Team: Italian \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 .\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" diff --git a/scripts/gnupg.spec b/scripts/gnupg.spec index 075f0bf69..f654ab1a0 100644 --- a/scripts/gnupg.spec +++ b/scripts/gnupg.spec @@ -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 diff --git a/util/ChangeLog b/util/ChangeLog index 05c624430..0f444d990 100644 --- a/util/ChangeLog +++ b/util/ChangeLog @@ -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. diff --git a/util/Makefile.am b/util/Makefile.am index baef6045a..eee154ed7 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -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 index 000000000..42bb7270a --- /dev/null +++ b/util/dotlock.c @@ -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 +#include +#include +#include +#include +#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.. 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." + * + * 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 diff --git a/util/memory.c b/util/memory.c index 013bd55cc..586a744ec 100644 --- a/util/memory.c +++ b/util/memory.c @@ -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);