diff --git a/THANKS b/THANKS index 70a82744e..b30466c18 100644 --- a/THANKS +++ b/THANKS @@ -14,7 +14,7 @@ Ernst Molitor ernst.molitor@uni-bonn.de Frank Heckenbach heckenb@mi.uni-erlangen.de Hendrik Buschkamp buschkamp@rheumanet.org Ian McKellar imckellar@harvestroad.com.au -James Troup J.J.Troup@scm.brad.ac.uk +James Troup james@nocrew.org Jean-loup Gailly gzip@prep.ai.mit.edu Jens Bachem bachem@rrz.uni-koeln.de Jörg Schilling schilling@fokus.gmd.de diff --git a/TODO b/TODO index 73ed027fb..3c05ad040 100644 --- a/TODO +++ b/TODO @@ -33,12 +33,6 @@ * add checking of armor trailers * remove all "Fixmes" - * bug: g10/trustdb.c#build_sigrecs called to often by do_list_path - and remove the bad kludge. Maybe we should put all sigs into the trustdb - and mark them as valid/invalid/nopubkey, and how do we check, that - we have a self-signature -> put this stuff into a kind of directory - record, as it does not belong to the pubkey record? - * add an option to create a new user id. * add an option to re-create a public key from a secret key. Think about diff --git a/doc/DETAILS b/doc/DETAILS index 1be782a1d..661a4a1ef 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -100,7 +100,8 @@ Record type 3: (key record) 1 byte reserved 1 u32 LID 1 u32 next - next key record - 8 bytes reserved + 7 bytes reserved + 1 byte keyflags 1 byte pubkey algorithm 1 byte length of the fingerprint (in bytes) 20 bytes fingerprint of the public key @@ -118,7 +119,8 @@ Record type 4: (uid record) 1 u32 next next userid 1 u32 pointer to preference record 1 u32 siglist list of valid signatures - 2 byte reserved + 1 byte uidflags + 1 byte reserved 20 bytes ripemd160 hash of the username. diff --git a/g10/ChangeLog b/g10/ChangeLog index f6f935a57..badb5cd32 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,19 @@ +Tue Jul 21 14:37:09 1998 Werner Koch (wk@(none)) + + * import.c (import_one): Now creates a trustdb record. + + * g10.c (main): New command --check-trustdb + +Mon Jul 20 11:15:07 1998 Werner Koch (wk@(none)) + + * genkey.c (generate_keypair): Default key is now DSA with + encryption only ElGamal subkey. + +Thu Jul 16 10:58:33 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keyid.c (keyid_from_fingerprint): New. + * getkey.c (get_pubkey_byfprint): New. + Tue Jul 14 18:09:51 1998 Werner Koch (wk@isil.d.shuttle.de) * keyid.c (fingerprint_from_pk): Add argument and changed all callers. diff --git a/g10/Makefile.am b/g10/Makefile.am index be695d895..e97fb8cf4 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -6,7 +6,7 @@ OMIT_DEPENDENCIES = zlib.h zconf.h LDFLAGS = @LDFLAGS@ @DYNLINK_LDFLAGS@ needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a -noinst_PROGRAMS = gpgd +#noinst_PROGRAMS = gpgd bin_PROGRAMS = gpg gpgm common_source = \ @@ -67,10 +67,10 @@ gpg_SOURCES = g10.c \ gpgm_SOURCES = dearmor.c \ $(common_source) -gpgd_SOURCES = gpgd.c \ - ks-proto.h \ - ks-proto.c \ - $(common_source) +#gpgd_SOURCES = gpgd.c \ +# ks-proto.h \ +# ks-proto.c \ +# $(common_source) LDADD = @INTLLIBS@ $(needed_libs) @ZLIBS@ diff --git a/g10/OPTIONS b/g10/OPTIONS index 8e9cf8a6c..aa8b46d6e 100644 --- a/g10/OPTIONS +++ b/g10/OPTIONS @@ -36,6 +36,14 @@ list-secret-keys export-secret-keys # export secret keys (which may be usefuil in some cases) +check-trustdb + + + + + + + #----------------------------------------------- #--- options #----------------------------------------------- diff --git a/g10/g10.c b/g10/g10.c index 308b58227..dbd277d63 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -52,43 +52,44 @@ static ARGPARSE_OPTS opts[] = { { 300, NULL, 0, N_("@Commands:\n ") }, #ifdef IS_G10 - { 's', "sign", 0, N_("|[file]|make a signature")}, - { 539, "clearsign", 0, N_("|[file]|make a clear text signature") }, - { 'b', "detach-sign", 0, N_("make a detached signature")}, - { 'e', "encrypt", 0, N_("encrypt data")}, - { 'c', "symmetric", 0, N_("encryption only with symmetric cipher")}, - { 507, "store", 0, N_("store only")}, - { 'd', "decrypt", 0, N_("decrypt data (default)")}, - { 550, "verify" , 0, N_("verify a signature")}, + { 's', "sign", 256, N_("|[file]|make a signature")}, + { 539, "clearsign", 256, N_("|[file]|make a clear text signature") }, + { 'b', "detach-sign", 256, N_("make a detached signature")}, + { 'e', "encrypt", 256, N_("encrypt data")}, + { 'c', "symmetric", 256, N_("encryption only with symmetric cipher")}, + { 507, "store", 256, N_("store only")}, + { 'd', "decrypt", 256, N_("decrypt data (default)")}, + { 550, "verify" , 256, N_("verify a signature")}, #endif - { 551, "list-keys", 0, N_("list keys")}, - { 552, "list-sigs", 0, N_("list keys and signatures")}, - { 508, "check-sigs",0, N_("check key signatures")}, - { 515, "fingerprint", 0, N_("list keys and fingerprints")}, - { 558, "list-secret-keys", 0, N_("list secret keys")}, + { 551, "list-keys", 256, N_("list keys")}, + { 552, "list-sigs", 256, N_("list keys and signatures")}, + { 508, "check-sigs",256, N_("check key signatures")}, + { 515, "fingerprint", 256, N_("list keys and fingerprints")}, + { 558, "list-secret-keys", 256, N_("list secret keys")}, #ifdef IS_G10 - { 503, "gen-key", 0, N_("generate a new key pair")}, - { 554, "add-key", 0, N_("add a subkey to a key pair")}, - { 506, "sign-key" ,0, N_("make a signature on a key in the keyring")}, - { 505, "delete-key",0, N_("remove key from the public keyring")}, - { 524, "edit-key" ,0, N_("edit a key signature")}, - { 525, "change-passphrase", 0, N_("change the passphrase of your secret keyring")}, - { 542, "gen-revoke",0, N_("generate a revocation certificate")}, + { 503, "gen-key", 256, N_("generate a new key pair")}, + { 554, "add-key", 256, N_("add a subkey to a key pair")}, + { 506, "sign-key" ,256, N_("make a signature on a key in the keyring")}, + { 505, "delete-key",256, N_("remove key from the public keyring")}, + { 524, "edit-key" ,256, N_("edit a key signature")}, + { 525, "change-passphrase", 256, N_("change the passphrase of your secret keyring")}, + { 542, "gen-revoke",256, N_("generate a revocation certificate")}, #endif - { 537, "export" , 0, N_("export keys") }, - { 563, "export-secret-keys" , 0, "@" }, + { 537, "export" , 256, N_("export keys") }, + { 563, "export-secret-keys" , 256, "@" }, { 565, "do-not-export-rsa", 0, "@" }, - { 530, "import", 0 , N_("import/merge keys")}, - { 521, "list-packets",0,N_("list only the sequence of packets")}, + { 530, "import", 256 , N_("import/merge keys")}, + { 521, "list-packets",256,N_("list only the sequence of packets")}, #ifdef IS_G10MAINT - { 564, "list-ownertrust", 0, "list the ownertrust values"}, - { 546, "dearmor", 0, N_("De-Armor a file or stdin") }, - { 547, "enarmor", 0, N_("En-Armor a file or stdin") }, - { 555, "print-md" , 0, N_("|algo [files]|print message digests")}, - { 516, "print-mds" , 0, N_("print all message digests")}, + { 564, "list-ownertrust", 256, N_("list the ownertrust values")}, + { 567, "check-trustdb",0 , N_("|[NAMES]|check the trust database")}, + { 546, "dearmor", 256, N_("De-Armor a file or stdin") }, + { 547, "enarmor", 256, N_("En-Armor a file or stdin") }, + { 555, "print-md" , 256, N_("|algo [files]|print message digests")}, + { 516, "print-mds" , 256, N_("print all message digests")}, #ifdef MAINTAINER_OPTIONS - { 513, "gen-prime" , 0, "@" }, - { 548, "gen-random" , 0, "@" }, + { 513, "gen-prime" , 256, "@" }, + { 548, "gen-random" , 256, "@" }, #endif #endif @@ -143,6 +144,7 @@ static ARGPARSE_OPTS opts[] = { #ifdef IS_G10MAINT { 514, "test" , 0, "@" }, { 564, "list-ownertrust",0 , "@"}, + { 567, "check-trustdb",0 , "@"}, { 531, "list-trustdb",0 , "@"}, { 533, "list-trust-path",0, "@"}, #endif @@ -182,7 +184,7 @@ enum cmd_values { aNull = 0, aListSigs, aKeyadd, aListSecretKeys, aExport, aExportSecret, aCheckKeys, aGenRevoke, aPrimegen, aPrintMD, aPrintMDs, - aListTrustDB, aListTrustPath, aListOwnerTrust, + aCheckTrustDB, aListTrustDB, aListTrustPath, aListOwnerTrust, aDeArmor, aEnArmor, aGenRandom, aTest }; @@ -195,7 +197,6 @@ static void set_cmd( enum cmd_values *ret_cmd, #ifdef IS_G10MAINT static void print_hex( byte *p, size_t n ); static void print_mds( const char *fname, int algo ); -static void do_test(int); #endif const char * @@ -541,6 +542,7 @@ main( int argc, char **argv ) #endif case 516: set_cmd( &cmd, aPrintMDs); break; case 531: set_cmd( &cmd, aListTrustDB); break; + case 567: set_cmd( &cmd, aCheckTrustDB); break; case 533: set_cmd( &cmd, aListTrustPath); break; case 540: break; /* dummy */ case 546: set_cmd( &cmd, aDeArmor); break; @@ -1032,6 +1034,15 @@ main( int argc, char **argv ) } break; + case aCheckTrustDB: + if( !argc ) + check_trustdb(NULL); + else { + for( ; argc; argc--, argv++ ) + check_trustdb( *argv ); + } + break; + case aListTrustPath: if( argc != 2 ) wrong_args("--list-trust-path [-- -] "); diff --git a/g10/getkey.c b/g10/getkey.c index b73a00616..912c91906 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -464,6 +464,20 @@ get_pubkey_byname( PKT_public_key *pk, const char *name ) } +/**************** + * Search for a key with the given fingerprint. + */ +int +get_pubkey_byfprint( PKT_public_key *pk, const byte *fprint, size_t fprint_len) +{ + int rc; + + if( fprint_len == 20 || fprint_len == 16 ) + rc = lookup( pk, fprint_len, NULL, fprint, NULL ); + else + rc = G10ERR_GENERAL; /* Oops */ + return rc; +} /**************** * Search for a key with the given fingerprint and return the diff --git a/g10/import.c b/g10/import.c index d32852cf0..ec143dce2 100644 --- a/g10/import.c +++ b/g10/import.c @@ -381,6 +381,17 @@ import_one( const char *fname, KBNODE keyblock ) else log_info_f(fname, _("key %08lX: not changed\n"), (ulong)keyid[1] ); } + if( !rc ) { + rc = query_trust_record( pk_orig ); + if( rc && rc != -1 ) + log_error("trustdb error: %s\n", g10_errstr(rc) ); + else if( rc == -1 ) { + rc = insert_trust_record( pk_orig ); + if( rc ) + log_error("key %08lX: trustdb insert failed: %s\n", + (ulong)keyid[1], g10_errstr(rc) ); + } + } leave: release_kbnode( keyblock_orig ); diff --git a/g10/keydb.h b/g10/keydb.h index 51da9a628..bbd803fbe 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -112,6 +112,8 @@ void add_secret_keyring( const char *name ); int get_pubkey( PKT_public_key *pk, u32 *keyid ); int get_pubkey_byname( PKT_public_key *pk, const char *name ); int get_seckey( PKT_secret_key *sk, u32 *keyid ); +int get_pubkey_byfprint( PKT_public_key *pk, const byte *fprint, + size_t fprint_len ); int get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint, size_t fprint_len ); int seckey_available( u32 *keyid ); @@ -125,12 +127,13 @@ int pubkey_letter( int algo ); u32 keyid_from_sk( PKT_secret_key *sk, u32 *keyid ); u32 keyid_from_pk( PKT_public_key *pk, u32 *keyid ); u32 keyid_from_sig( PKT_signature *sig, u32 *keyid ); +u32 keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid ); unsigned nbits_from_pk( PKT_public_key *pk ); unsigned nbits_from_sk( PKT_secret_key *sk ); const char *datestr_from_pk( PKT_public_key *pk ); const char *datestr_from_sk( PKT_secret_key *sk ); const char *datestr_from_sig( PKT_signature *sig ); -byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf; size_t *ret_len ); +byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf, size_t *ret_len ); byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len ); /*-- kbnode.c --*/ diff --git a/g10/keygen.c b/g10/keygen.c index b114b8444..0eaeafeae 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -371,7 +371,7 @@ check_valid_days( const char *s ) /**************** - * Returns o to create both a DSA and a ElGamal key. + * Returns: 0 to create both a DSA and a ElGamal key. */ static int ask_algo( int *ret_v4, int addmode ) @@ -756,7 +756,7 @@ generate_keypair() algo = ask_algo( &v4, 0 ); if( !algo ) { - algo = PUBKEY_ALGO_ELGAMAL; + algo = PUBKEY_ALGO_ELGAMAL_E; both = 1; tty_printf(_("DSA keypair will have 1024 bits.\n")); } diff --git a/g10/keyid.c b/g10/keyid.c index 2e5c6aad6..de0319fe3 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -189,6 +189,43 @@ keyid_from_pk( PKT_public_key *pk, u32 *keyid ) } +/**************** + * Get the keyid from the fingerprint. This function is simple for most + * keys, but has to do a keylookup for old stayle keys. + */ +u32 +keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid ) +{ + u32 dummy_keyid[2]; + + if( !keyid ) + keyid = dummy_keyid; + + if( fprint_len != 20 ) { + /* This is special as we have to lookup the key first */ + PKT_public_key pk; + int rc; + + memset( &pk, 0, sizeof pk ); + rc = get_pubkey_byfprint( &pk, fprint, fprint_len ); + if( rc ) { + log_error("Oops: keyid_from_fingerprint: no pubkey\n"); + keyid[0] = 0; + keyid[1] = 0; + } + else + keyid_from_pk( &pk, keyid ); + } + else { + const byte *dp = fprint; + keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ; + keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ; + } + + return keyid[1]; +} + + u32 keyid_from_sig( PKT_signature *sig, u32 *keyid ) { diff --git a/g10/pkclist.c b/g10/pkclist.c index e509f0064..7fbe065b6 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -49,7 +49,7 @@ query_ownertrust( ulong lid ) PKT_public_key *pk ; int changed=0; - rc = keyid_from_trustdb( lid, keyid ); + rc = keyid_from_lid( lid, keyid ); if( rc ) { log_error("ooops: can't get keyid for lid %lu\n", lid); return 0; diff --git a/g10/tdbio.c b/g10/tdbio.c index 9355f4c6e..ac1266147 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -147,11 +147,11 @@ create_db( const char *fname ) fp =fopen( fname, "w" ); if( !fp ) log_fatal_f( fname, _("can't create %s: %s\n"), strerror(errno) ); - fwrite_8( fp, 2 ); + fwrite_8( fp, 1 ); /* record type */ fwrite_8( fp, 'g' ); fwrite_8( fp, 'p' ); fwrite_8( fp, 'g' ); - fwrite_8( fp, 1 ); /* version */ + fwrite_8( fp, 2 ); /* version */ fwrite_zeros( fp, 3 ); /* reserved */ fwrite_32( fp, 0 ); /* not locked */ fwrite_32( fp, make_timestamp() ); /* created */ @@ -183,11 +183,12 @@ open_db() void -tdbio_dump_record( ulong rnum, TRUSTREC *rec, FILE *fp ) +tdbio_dump_record( TRUSTREC *rec, FILE *fp ) { int i, any; + ulong rnum = rec->recnum; - fprintf(fp, "rec %5lu, type=", rnum ); + fprintf(fp, "rec %5lu, ", rnum ); switch( rec->rectype ) { case 0: fprintf(fp, "free\n"); @@ -201,30 +202,36 @@ tdbio_dump_record( ulong rnum, TRUSTREC *rec, FILE *fp ) rec->r.dir.uidlist, rec->r.dir.cacherec, rec->r.dir.ownertrust ); - if( rec->r.dir.sigflag == 1 ) - fputs(", (none)", fp ); - else if( rec->r.dir.sigflag == 2 ) - fputs(", (invalid)", fp ); - else if( rec->r.dir.sigflag == 3 ) - fputs(", (revoked)", fp ); - else if( rec->r.dir.sigflag ) - fputs(", (??)", fp ); + if( rec->r.dir.dirflags & DIRF_ERROR ) + fputs(", error", fp ); + if( rec->r.dir.dirflags & DIRF_CHECKED ) + fputs(", checked", fp ); + if( rec->r.dir.dirflags & DIRF_REVOKED ) + fputs(", revoked", fp ); + if( rec->r.dir.dirflags & DIRF_MISKEY ) + fputs(", miskey", fp ); putc('\n', fp); break; case RECTYPE_KEY: - fprintf(fp, "key %lu, next=%lu, algo=%d, flen=%d\n", + fprintf(fp, "key %lu, next=%lu, algo=%d, flen=%d", rec->r.key.lid, rec->r.key.next, rec->r.key.pubkey_algo, rec->r.key.fingerprint_len ); + if( rec->r.key.keyflags & KEYF_REVOKED ) + fputs(", revoked", fp ); + putc('\n', fp); break; case RECTYPE_UID: - fprintf(fp, "uid %lu, next=%lu, pref=%lu, sig=%lu, hash=%02X%02X\n", + fprintf(fp, "uid %lu, next=%lu, pref=%lu, sig=%lu, hash=%02X%02X", rec->r.uid.lid, rec->r.uid.next, rec->r.uid.prefrec, rec->r.uid.siglist, rec->r.uid.namehash[18], rec->r.uid.namehash[19]); + if( rec->r.uid.uidflags & UIDF_REVOKED ) + fputs(", revoked", fp ); + putc('\n', fp); break; case RECTYPE_PREF: fprintf(fp, "pref %lu, next=%lu\n", @@ -253,11 +260,11 @@ tdbio_dump_record( ulong rnum, TRUSTREC *rec, FILE *fp ) case RECTYPE_HTBL: fprintf(fp, "htbl\n"); break; - case RECTYPE_HTBL: + case RECTYPE_HLST: fprintf(fp, "hlst\n"); break; default: - fprintf(fp, "%d (unknown)\n", rec->rectype ); + fprintf(fp, "unknown type %d\n", rec->rectype ); break; } } @@ -330,7 +337,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) rec->r.dir.uidlist = buftoulong(p); p += 4; rec->r.dir.cacherec = buftoulong(p); p += 4; rec->r.dir.ownertrust = *p++; - rec->r.dir.sigflag = *p++; + rec->r.dir.dirflags = *p++; if( rec->r.dir.lid != recnum ) { log_error_f( db_name, "dir LID != recnum (%lu,%lu)\n", rec->r.dir.lid, (ulong)recnum ); @@ -340,7 +347,8 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) case RECTYPE_KEY: /* public key record */ rec->r.key.lid = buftoulong(p); p += 4; rec->r.key.next = buftoulong(p); p += 4; - p += 8; + p += 7; + rec->r.key.keyflags = *p++; rec->r.key.pubkey_algo = *p++; rec->r.key.fingerprint_len = *p++; if( rec->r.key.fingerprint_len < 1 || rec->r.key.fingerprint_len > 20 ) @@ -352,7 +360,8 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) rec->r.uid.next = buftoulong(p); p += 4; rec->r.uid.prefrec = buftoulong(p); p += 4; rec->r.uid.siglist = buftoulong(p); p += 4; - p += 2; + rec->r.uid.uidflags = *p++; + p ++; memcpy( rec->r.uid.namehash, p, 20); break; case RECTYPE_PREF: /* preference record */ @@ -413,14 +422,15 @@ tdbio_write_record( TRUSTREC *rec ) ulongtobuf(p, rec->r.dir.uidlist); p += 4; ulongtobuf(p, rec->r.dir.cacherec); p += 4; *p++ = rec->r.dir.ownertrust; - *p++ = rec->r.dir.sigflag; + *p++ = rec->r.dir.dirflags; assert( rec->r.dir.lid == recnum ); break; case RECTYPE_KEY: ulongtobuf(p, rec->r.key.lid); p += 4; ulongtobuf(p, rec->r.key.next); p += 4; - p += 8; + p += 7; + *p++ = rec->r.key.keyflags; *p++ = rec->r.key.pubkey_algo; *p++ = rec->r.key.fingerprint_len; memcpy( p, rec->r.key.fingerprint, 20); p += 20; @@ -431,7 +441,8 @@ tdbio_write_record( TRUSTREC *rec ) ulongtobuf(p, rec->r.uid.next); p += 4; ulongtobuf(p, rec->r.uid.prefrec); p += 4; ulongtobuf(p, rec->r.uid.siglist); p += 4; - p += 2; + *p++ = rec->r.uid.uidflags; + p++; memcpy( p, rec->r.uid.namehash, 20 ); p += 20; break; @@ -472,6 +483,15 @@ tdbio_write_record( TRUSTREC *rec ) return rc; } +int +tdbio_delete_record( ulong recnum ) +{ + TRUSTREC rec; + + rec.recnum = recnum; + rec.rectype = 0; + return tdbio_write_record( &rec ); +} /**************** * create a new record and return its record number @@ -495,7 +515,8 @@ tdbio_new_recnum() * returns another recnum */ memset( &rec, 0, sizeof rec ); rec.rectype = 0; /* free record */ - rc = tdbio_write_record(recnum, &rec ); + rec.recnum = recnum; + rc = tdbio_write_record( &rec ); if( rc ) log_fatal_f(db_name,_("failed to append a record: %s\n"), g10_errstr(rc)); @@ -530,10 +551,10 @@ tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec ) if( rec->r.key.pubkey_algo == pk->pubkey_algo && !memcmp(rec->r.key.fingerprint, fingerprint, fingerlen) ) { /* found: read the dir record for this key */ - rc = tdbio_read_record( rec->r.key.lid, rec, RECTYPE_DIR); + recnum = rec->r.key.lid; + rc = tdbio_read_record( recnum, rec, RECTYPE_DIR); if( rc ) break; - if( pk->local_id && pk->local_id != recnum ) log_error_f(db_name, "found record, but LID from memory does " @@ -549,22 +570,13 @@ tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec ) } +/**************** + * Delete the Userid UIDLID from DIRLID + */ int -tdbio_update_sigflag( ulong lid, int sigflag ) +tdbio_delete_uidrec( ulong dirlid, ulong uidlid ) { - TRUSTREC rec; - - if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) { - log_error("update_sigflag: read failed\n"); - return G10ERR_TRUSTDB; - } - - rec.r.dir.sigflag = sigflag; - if( tdbio_write_record( lid, &rec ) ) { - log_error("update_sigflag: write failed\n"); - return G10ERR_TRUSTDB; - } - - return 0; + return G10ERR_GENERAL; /* not implemented */ } + diff --git a/g10/tdbio.h b/g10/tdbio.h index 2d28131cd..8eec40e4a 100644 --- a/g10/tdbio.h +++ b/g10/tdbio.h @@ -40,11 +40,23 @@ #define RECTYPE_HLST 11 + +#define DIRF_CHECKED 1 /* everything has been checked, the other bits are + valid */ +#define DIRF_MISKEY 2 /* some keys are missing, so they could not be checked*/ +#define DIRF_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 */ + + struct trust_record { int rectype; struct trust_record *next; /* help pointer to build lists in memory */ struct trust_record *help_pref; - struct trust_record *help_sig; int mark; ulong recnum; union { @@ -64,11 +76,12 @@ struct trust_record { ulong uidlist; /* list of uid records */ ulong cacherec; /* the cache record */ byte ownertrust; - byte sigflag; + byte dirflags; } dir; struct { /* primary public key record */ ulong lid; ulong next; /* next key */ + byte keyflags; byte pubkey_algo; byte fingerprint_len; byte fingerprint[20]; @@ -78,6 +91,7 @@ struct trust_record { ulong next; /* points to next user id record */ ulong prefrec; /* recno of preference record */ ulong siglist; /* list of valid signatures (w/o self-sig)*/ + byte uidflags; byte namehash[20]; /* ripemd hash of the username */ } uid; struct { /* preference reord */ @@ -90,7 +104,7 @@ 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; /* reserved */ + byte flag; /* SIGRF_xxxxx */ } sig[SIGS_PER_RECORD]; } sig; struct { /* cache record */ @@ -113,14 +127,15 @@ struct trust_record { typedef struct trust_record TRUSTREC; typedef struct { - ulong local_id; /* localid of the pubkey */ + ulong lid; /* localid */ ulong sigrec; - ulong sig_id; /* returned signature id */ + ulong sig_lid; /* returned signatures LID */ unsigned sig_flag; /* returned signature record flag */ struct { /* internal data */ int init_done; int eof; TRUSTREC rec; + ulong nextuid; int index; } ctl; } SIGREC_CONTEXT; @@ -129,12 +144,13 @@ typedef struct { /*-- tdbio.c --*/ int tdbio_set_dbname( const char *new_dbname, int create ); const char *tdbio_get_dbname(void); -void tdbio_dump_record( ulong rnum, TRUSTREC *rec, FILE *fp ); +void tdbio_dump_record( TRUSTREC *rec, FILE *fp ); int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ); int tdbio_write_record( TRUSTREC *rec ); +int tdbio_delete_record( ulong recnum ); ulong tdbio_new_recnum(void); int tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec ); -int tdbio_update_sigflag( ulong lid, int sigflag ); +int tdbio_delete_uidrec( ulong dirlid, ulong uidlid ); #define buftoulong( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \ diff --git a/g10/trustdb.c b/g10/trustdb.c index b2e478ceb..b82d26a1e 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -87,9 +87,9 @@ 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 build_sigrecs( ulong local_id ); static int propagate_trust( TRUST_SEG_LIST tslist ); static int do_check( TRUSTREC *drec, unsigned *trustlevel ); @@ -179,7 +179,7 @@ upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag ) * the signature packet in our trustdb or insert them into the trustdb */ static int -set_signature_packets_local_id( PKT_signature *sig ) +set_signature_packets_lid( PKT_signature *sig ) { PKT_public_key *pk = m_alloc_clear( sizeof *pk ); TRUSTREC rec; @@ -204,24 +204,34 @@ set_signature_packets_local_id( PKT_signature *sig ) -static int -keyid_from_local_id( ulong lid, u32 *keyid ) +/**************** + * Return the keyid from the primary key identified by LID. + */ +int +keyid_from_lid( ulong lid, u32 *keyid ) { TRUSTREC rec; int rc; rc = tdbio_read_record( lid, &rec, RECTYPE_DIR ); if( rc ) { - log_error(_("error reading record with local_id %lu: %s\n"), + log_error("error reading dir record for LID %lu: %s\n", lid, g10_errstr(rc)); return G10ERR_TRUSTDB; } - if( rec.rectype != RECTYPE_DIR ) { - log_error(_("record with local_id %lu is not a dir record\n"), lid); + if( !rec.r.dir.keylist ) { + log_error("no primary key for LID %lu\n", lid ); return G10ERR_TRUSTDB; } - keyid[0] = rec.r.dir.keyid[0]; - keyid[1] = rec.r.dir.keyid[1]; + rc = tdbio_read_record( rec.r.dir.keylist, &rec, RECTYPE_KEY ); + if( rc ) { + log_error("error reading primary key for LID %lu: %s\n", + lid, g10_errstr(rc)); + return G10ERR_TRUSTDB; + } + keyid_from_fingerprint( rec.r.key.fingerprint, rec.r.key.fingerprint_len, + keyid ); + return 0; } @@ -247,48 +257,52 @@ walk_sigrecs( SIGREC_CONTEXT *c, int create ) r = &c->ctl.rec; if( !c->ctl.init_done ) { c->ctl.init_done = 1; - if( !c->sigrec ) { - rc = tdbio_read_record( c->local_id, r, RECTYPE_DIR ); - if( rc ) { - log_error(_("%lu: error reading dir record: %s\n"), - c->local_id, g10_errstr(rc)); - return rc; - } - c->sigrec = r->r.dir.sigrec; - if( !c->sigrec && create && !r->r.dir.no_sigs ) { - rc = build_sigrecs( c->local_id ); + rc = tdbio_read_record( c->lid, r, RECTYPE_DIR ); + if( rc ) { + log_error("LID %lu: error reading dir record: %s\n", + c->lid, g10_errstr(rc)); + return rc; + } + c->ctl.nextuid = r->r.dir.uidlist; + /* force a read (what a bad bad hack) */ + c->ctl.index = SIGS_PER_RECORD; + r->r.sig.next = 0; + } + + /* need a loop to skip over deleted sigs */ + do { + if( c->ctl.index >= SIGS_PER_RECORD ) { /* read the record */ + rnum = r->r.sig.next; + if( !rnum && c->ctl.nextuid ) { /* read next uid record */ + rc = tdbio_read_record( c->ctl.nextuid, r, RECTYPE_UID ); if( rc ) { - if( rc == G10ERR_BAD_CERT ) - rc = -1; /* maybe no selfsignature */ - if( rc != -1 ) - log_info(_("%lu: error building sigs on the fly: %s\n"), - c->local_id, g10_errstr(rc) ); + log_error("error reading next uidrec: %s\n", + g10_errstr(rc)); c->ctl.eof = 1; return rc; } - rc = tdbio_read_record( c->local_id, r, RECTYPE_DIR ); - if( rc ) { - log_error(_("%lu: error re-reading dir record: %s\n"), - c->local_id, g10_errstr(rc)); - return rc; + 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; + } + rc = tdbio_read_record( c->ctl.nextuid, r, RECTYPE_UID ); + if( rc ) { + log_error("LID %lu: error re-reading uid record: %s\n", + c->lid, g10_errstr(rc)); + return rc; + } } - c->sigrec = r->r.dir.sigrec; + c->ctl.nextuid = r->r.uid.next; + rnum = r->r.uid.siglist; } - if( !c->sigrec ) { - c->ctl.eof = 1; - return -1; - } - } - /* force a read */ - c->ctl.index = SIGS_PER_RECORD; - r->r.sig.chain = c->sigrec; - } - - /* enter loop to skip deleted sigs */ - do { - if( c->ctl.index >= SIGS_PER_RECORD ) { - /* read the record */ - rnum = r->r.sig.chain; if( !rnum ) { c->ctl.eof = 1; return -1; /* return eof */ @@ -299,15 +313,16 @@ walk_sigrecs( SIGREC_CONTEXT *c, int create ) c->ctl.eof = 1; return rc; } - if( r->r.sig.owner != c->local_id ) { + if( r->r.sig.lid != c->lid ) { log_error(_("chained sigrec %lu has a wrong owner\n"), rnum ); c->ctl.eof = 1; return G10ERR_TRUSTDB; } c->ctl.index = 0; } - } while( !r->r.sig.sig[c->ctl.index++].local_id ); - c->sig_id = r->r.sig.sig[c->ctl.index-1].local_id; + } while( !r->r.sig.sig[c->ctl.index++].lid ); + + c->sig_lid = r->r.sig.sig[c->ctl.index-1].lid; c->sig_flag = r->r.sig.sig[c->ctl.index-1].flag; return 0; } @@ -333,13 +348,6 @@ verify_own_keys() u32 keyid[2]; while( !(rc=enum_secret_keys( &enum_context, sk) ) ) { - /* To be sure that it is a secret key of our own, - * we should check it, but this needs a passphrase - * for every key and this is boring for the user. - * Anyway, access to the seret keyring should be - * granted to the user only as it is poosible to - * crack it with dictionary attacks. - */ keyid_from_sk( sk, keyid ); if( DBG_TRUST ) @@ -383,7 +391,6 @@ verify_own_keys() log_error(_("key %08lX: already in ultikey_table\n"), (ulong)keyid[1]); - release_secret_key_parts( sk ); release_public_key_parts( pk ); } @@ -421,7 +428,7 @@ static void print_keyid( FILE *fp, ulong lid ) { u32 ki[2]; - if( keyid_from_trustdb( lid, ki ) ) + if( keyid_from_lid( lid, ki ) ) fprintf(fp, "????????.%lu", lid ); else fprintf(fp, "%08lX.%lu", (ulong)ki[1], lid ); @@ -454,36 +461,36 @@ do_list_sigs( ulong root, ulong pubkey, int depth, u32 keyid[2]; memset( &sx, 0, sizeof sx ); - sx.local_id = pubkey; + sx.lid = pubkey; for(;;) { rc = walk_sigrecs( &sx, 0 ); if( rc ) break; - rc = keyid_from_local_id( sx.sig_id, keyid ); + rc = keyid_from_lid( sx.sig_lid, keyid ); if( rc ) { printf("%6u: %*s????????.%lu:%02x\n", *lineno, depth*4, "", - sx.sig_id, sx.sig_flag ); + sx.sig_lid, sx.sig_flag ); ++*lineno; } else { printf("%6u: %*s%08lX.%lu:%02x ", *lineno, depth*4, "", - (ulong)keyid[1], sx.sig_id, sx.sig_flag ); + (ulong)keyid[1], sx.sig_lid, sx.sig_flag ); /* check whether we already checked this pubkey */ - if( !qry_lid_table_flag( ultikey_table, sx.sig_id, NULL ) ) { + if( !qry_lid_table_flag( ultikey_table, sx.sig_lid, NULL ) ) { print_user_id("[ultimately trusted]", keyid); ++*lineno; } - else if( sx.sig_id == pubkey ) { + else if( sx.sig_lid == pubkey ) { printf("[self-signature]\n"); ++*lineno; } - else if( sx.sig_id == root ) { + else if( sx.sig_lid == root ) { printf("[closed]\n"); ++*lineno; } - else if( ins_lid_table_item( lids, sx.sig_id, *lineno ) ) { + else if( ins_lid_table_item( lids, sx.sig_lid, *lineno ) ) { unsigned refline; - qry_lid_table_flag( lids, sx.sig_id, &refline ); + qry_lid_table_flag( lids, sx.sig_lid, &refline ); printf("[see line %u]\n", refline); ++*lineno; } @@ -494,7 +501,7 @@ do_list_sigs( ulong root, ulong pubkey, int depth, else { print_user_id( "", keyid ); ++*lineno; - rc = do_list_sigs( root, sx.sig_id, depth+1, lids, lineno ); + rc = do_list_sigs( root, sx.sig_lid, depth+1, lids, lineno ); if( rc ) break; } @@ -514,11 +521,9 @@ list_sigs( ulong pubkey_id ) LOCAL_ID_INFO *lids; unsigned lineno = 1; - rc = keyid_from_local_id( pubkey_id, keyid ); - if( rc ) { - log_error("Hmmm, no pubkey record for local_id %lu\n", pubkey_id); + rc = keyid_from_lid( pubkey_id, keyid ); + if( rc ) return rc; - } printf("Signatures of %08lX.%lu ", (ulong)keyid[1], pubkey_id ); print_user_id("", keyid); printf("----------------------\n"); @@ -530,6 +535,70 @@ list_sigs( ulong pubkey_id ) return rc; } +/**************** + * List all records of a public key + */ +static int +list_records( ulong lid ) +{ + int rc; + TRUSTREC dr, ur, rec; + ulong recno; + + rc = tdbio_read_record( lid, &dr, RECTYPE_DIR ); + if( rc ) { + log_error("lid %lu: read dir record failed: %s\n", lid, g10_errstr(rc)); + return rc; + } + tdbio_dump_record( &dr, stdout ); + + for( recno=dr.r.dir.keylist; recno; recno = rec.r.key.next ) { + rc = tdbio_read_record( recno, &rec, RECTYPE_KEY ); + if( rc ) { + log_error("lid %lu: read key record failed: %s\n", + lid, g10_errstr(rc)); + return rc; + } + tdbio_dump_record( &rec, stdout ); + } + + for( recno=dr.r.dir.uidlist; recno; recno = ur.r.uid.next ) { + rc = tdbio_read_record( recno, &ur, RECTYPE_UID ); + if( rc ) { + log_error("lid %lu: read uid record failed: %s\n", + lid, g10_errstr(rc)); + return rc; + } + tdbio_dump_record( &ur, stdout ); + /* preference records */ + for(recno=ur.r.uid.prefrec; recno; recno = rec.r.pref.next ) { + rc = tdbio_read_record( recno, &rec, RECTYPE_PREF ); + if( rc ) { + log_error("lid %lu: read pref record failed: %s\n", + lid, g10_errstr(rc)); + return rc; + } + tdbio_dump_record( &rec, stdout ); + } + /* sig records */ + for(recno=ur.r.uid.siglist; recno; recno = rec.r.sig.next ) { + rc = tdbio_read_record( recno, &rec, RECTYPE_SIG ); + if( rc ) { + log_error("lid %lu: read sig record failed: %s\n", + lid, g10_errstr(rc)); + return rc; + } + tdbio_dump_record( &rec, stdout ); + } + } + + /* add cache record dump here */ + + + + return rc; +} + /**************** @@ -551,29 +620,28 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth, return 0; } memset( &sx, 0, sizeof sx ); - sx.local_id = stack[depth-1].lid; - /* loop over all signatures. If we do not have any, try to - * create them */ + 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 )) ) { TRUST_SEG_LIST tsl, t2, tl; int i; - stack[depth].lid = sx.sig_id; + stack[depth].lid = sx.sig_lid; stack[depth].trust = 0; - if( qry_lid_table_flag( lids, sx.sig_id, &last_depth) ) { - /*printf("%2lu/%d: marked\n", sx.sig_id, depth );*/ - ins_lid_table_item( lids, sx.sig_id, depth); + if( qry_lid_table_flag( lids, sx.sig_lid, &last_depth) ) { + /*printf("%2lu/%d: marked\n", sx.sig_lid, depth );*/ + ins_lid_table_item( lids, sx.sig_lid, depth); last_depth = depth; } else if( depth < last_depth ) { - /*printf("%2lu/%d: last_depth=%u - updated\n", sx.sig_id, depth, last_depth);*/ + /*printf("%2lu/%d: last_depth=%u - updated\n", sx.sig_lid, depth, last_depth);*/ last_depth = depth; - upd_lid_table_flag( lids, sx.sig_id, depth); + upd_lid_table_flag( lids, sx.sig_lid, depth); } if( last_depth < depth ) - /*printf("%2lu/%d: already visited\n", sx.sig_id, depth)*/; - else if( !qry_lid_table_flag( ultikey_table, sx.sig_id, NULL ) ) { + /*printf("%2lu/%d: already visited\n", sx.sig_lid, depth)*/; + else if( !qry_lid_table_flag( ultikey_table, sx.sig_lid, NULL ) ) { /* found end of path; store it, ordered by path length */ tsl = m_alloc( sizeof *tsl + depth*sizeof(TRUST_INFO) ); tsl->nseg = depth+1; @@ -592,7 +660,7 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth, tl->next = tsl; } /*putchar('.'); fflush(stdout);*/ - /*printf("%2lu/%d: found\n", sx.sig_id, depth);*/ + /*printf("%2lu/%d: found\n", sx.sig_lid, depth);*/ } else { rc = do_list_path( stack, depth+1, max_depth, lids, tslist); @@ -604,209 +672,327 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth, } - /**************** - * Check all the sigs of the given keyblock and mark them - * as checked. Valid signatures which are duplicates are - * also marked [shall we check them at all?] - * FIXME: what shall we do if we have duplicate signatures where only - * some of them are bad? + * 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 -check_sigs( KBNODE keyblock, int *selfsig_okay, int *revoked ) +find_urec( TRUSTREC *dir, PKT_user_id *uid, TRUSTREC *urec ) { - KBNODE node; + byte nhash[20]; + ulong recno; int rc; - LOCAL_ID_INFO *dups = NULL; - *selfsig_okay = 0; - *revoked = 0; - for( node=keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_SIGNATURE - && ( (node->pkt->pkt.signature->sig_class&~3) == 0x10 - || node->pkt->pkt.signature->sig_class == 0x20 - || node->pkt->pkt.signature->sig_class == 0x30) ) { - int selfsig; - rc = check_key_signature( keyblock, node, &selfsig ); - if( !rc ) { - rc = set_signature_packets_local_id( node->pkt->pkt.signature ); - if( rc ) - log_fatal("set_signature_packets_local_id failed: %s\n", - g10_errstr(rc)); - if( selfsig ) { - node->flag |= 2; /* mark signature valid */ - *selfsig_okay = 1; - } - else if( node->pkt->pkt.signature->sig_class == 0x20 ) - *revoked = 1; - else - node->flag |= 1; /* mark signature valid */ - - if( node->pkt->pkt.signature->sig_class != 0x20 ) { - if( !dups ) - dups = new_lid_table(); - if( ins_lid_table_item( dups, - node->pkt->pkt.signature->local_id, 0) ) - node->flag |= 4; /* mark as duplicate */ - } - } - if( DBG_TRUST ) - log_debug("trustdb: sig from %08lX.%lu: %s%s\n", - (ulong)node->pkt->pkt.signature->keyid[1], - node->pkt->pkt.signature->local_id, - g10_errstr(rc), (node->flag&4)?" (dup)":"" ); - } + 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 ) { + rc = tdbio_read_record( recno, urec, RECTYPE_UID ); + if( rc ) + return rc == -1 ? G10ERR_READ_FILE : rc; + 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; } - if( dups ) - release_lid_table(dups); 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 ) +{ + int rc; + 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 */ + rc = tdbio_read_record( nextrecno, &srec, RECTYPE_SIG ); + if( rc ) { + log_error("write_sig_from_urec: read sigrecno %lu failed: %s\n", + nextrecno, g10_errstr(rc) ); + return rc; + } + 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; + rc = tdbio_write_record( rec ); + if( rc ) { + log_error("write_sig_from_urec: write sigrecno %lu failed: %s\n", + recno, g10_errstr(rc) ); + return rc; + } + } + + /* write the urec back */ + rc = tdbio_write_record( urec ); + if( rc ) { + log_error("write_sig_from_urec: write urec %lu failed: %s\n", + urec->recnum, g10_errstr(rc) ); + return rc; + } + + /* delete remaining old sigrecords */ + while( nextrecno ) { + rc = tdbio_read_record( nextrecno, &srec, RECTYPE_SIG ); + if( rc ) { + log_error("write_sig_from_urec: read sigrecno %lu failed: %s\n", + nextrecno, g10_errstr(rc) ); + return rc; + } + rc = tdbio_delete_record( nextrecno ); + if( rc ) { + log_error("write_sig_from_urec: delete old %lu failed: %s\n", + nextrecno, g10_errstr(rc) ); + return rc; + + } + nextrecno = srec.r.sig.next; + } + + return rc; +} + /**************** * If we do not have sigrecs for the given key, build them and write them * to the trustdb */ static int -build_sigrecs( ulong lid ) +update_sigs( TRUSTREC *dir ) { - TRUSTREC rec, krec, rec2; - KBNODE keyblock = NULL; - KBNODE node; + 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; - int i, selfsig, revoked; - ulong rnum, rnum2; - ulong first_sigrec = 0; if( DBG_TRUST ) - log_debug("trustdb: build_sigrecs for LID %lu\n", lid ); + log_debug("update_sigs for %lu\n", lid ); - /* get the keyblock */ - if( (rc=tdbio_read_record( lid, &rec, RECTYPE_DIR )) ) { - log_error( "build_sigrecs: can't read dir record %lu\n"), lid ); - goto leave; - } - if( (rc=tdbio_read_record( rec.r.dir.keylist, &krec, RECTYPE_KEY )) ) { - log_error("build_sigrecs: can't read primary key record %lu\n"), lid); + if( (rc=tdbio_read_record( dir->r.dir.keylist, &krec, RECTYPE_KEY )) ) { + log_error("update_sigs: can't read primary key for %lu\n", lid); goto leave; } rc = get_keyblock_byfprint( &keyblock, krec.r.key.fingerprint, krec.r.key.fingerprint_len ); if( rc ) { - log_error( "build_sigrecs: keyblock for %lu not found: %s\n", + log_error( "update_sigs: keyblock for %lu not found: %s\n", lid, g10_errstr(rc) ); goto leave; } /* check all key signatures */ - rc = check_sigs( keyblock, &selfsig, &revoked ); - if( rc ) { - log_error(_("build_sigrecs: check_sigs failed\n") ); - goto leave; - } - if( !selfsig ) { - log_error(_("build_sigrecs: self-signature missing\n") ); - tdbio_update_sigflag( lid, 2 ); - rc = G10ERR_BAD_CERT; - goto leave; - } - if( revoked ) { - log_info(_("build_sigrecs: key has been revoked\n") ); - tdbio_update_sigflag( lid, 3 ); - } - else - tdbio_update_sigflag( lid, 0 ); /* assume we have sigs */ - - /* valid key signatures are now marked; we can now build the sigrecs */ - memset( &rec, 0, sizeof rec ); - rec.rectype = RECTYPE_SIG; - i = 0; - rnum = rnum2 = 0; + assert( keyblock->pkt->pkttype == PKT_PUBLIC_KEY ); + have_urec = 0; + sigrec_list = NULL; + sigidx = 0; for( node=keyblock; node; node = node->next ) { - /* insert sigs which are not a selfsig nor a duplicate */ - if( (node->flag & 1) && !(node->flag & 4) ) { - assert( node->pkt->pkttype == PKT_SIGNATURE ); - if( !node->pkt->pkt.signature->local_id ) { - /* the next function should always succeed, because - * we have already checked the signature, and for this - * it was necessary to have the pubkey. The only reason - * this can fail are I/O errors of the trustdb or a - * remove operation on the pubkey database - which should - * not disturb us, because we have to change them anyway. */ - rc = set_signature_packets_local_id( node->pkt->pkt.signature ); + 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 ) - log_fatal(_("set_signature_packets_local_id failed: %s\n"), - g10_errstr(rc)); + goto leave; + rel_uidsigs( &urec ); } - if( i == SIGS_PER_RECORD ) { - /* write the record */ - rnum = tdbio_new_recnum(); - if( rnum2 ) { /* write the stored record */ - rec2.r.sig.lid = lid; - rec2.r.sig.next = rnum; /* the next record number */ - rc = tdbio_write_record( rnum2, &rec2 ); - if( rc ) { - log_error(_("build_sigrecs: write_record failed\n") ); - goto leave; - } - if( !first_sigrec ) - first_sigrec = rnum2; + 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 ) { + 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; } - rec2 = rec; - rnum2 = rnum; - memset( &rec, 0, sizeof rec ); - rec.rectype = RECTYPE_SIG; - i = 0; + else if( rc ) + log_error("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++; + 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 */ } - rec.r.sig.sig[i].lid = node->pkt->pkt.signature->local_id; - rec.r.sig.sig[i].flag = 0; - i++; } } - if( i || rnum2 ) { - /* write the record */ - rnum = tdbio_new_recnum(); - if( rnum2 ) { /* write the stored record */ - rec2.r.sig.lid = lid; - rec2.r.sig.next = rnum; - rc = tdbio_write_record( rnum2, &rec2 ); - if( rc ) { - log_error(_("build_sigrecs: write_record failed\n") ); - goto leave; - } - if( !first_sigrec ) - first_sigrec = rnum2; - } - if( i ) { /* write the pending record */ - rec.r.sig.lid = lid; - rec.r.sig.next = 0; - rc = tdbio_write_record( rnum, &rec ); - if( rc ) { - log_error(_("build_sigrecs: write_record failed\n") ); - goto leave; - } - if( !first_sigrec ) - first_sigrec = rnum; - } - } - if( first_sigrec ) { /* update the uid records */ - if( (rc =tdbio_read_record( pubkeyid, &rec, RECTYPE_DIR )) ) { - log_error(_("update_dir_record: read failed\n")); + if( have_urec && !(urec.mark & 1) ) { + if( (rc = no_selfsig_del(lid, keyid, &urec )) ) goto leave; - } - rec.r.dir.sigrec = first_sigrec; - if( (rc=tdbio_write_record( pubkeyid, &rec )) ) { - log_error(_("update_dir_record: write failed\n")); - 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 - tdbio_update_sigflag( lid, revoked? 3:1 ); /* no signatures */ + dir->r.dir.dirflags &= ~DIRF_MISKEY; + rc = tdbio_write_record( dir ); + if( rc ) { + log_error("update_sigs: write dir record failed: %s\n", g10_errstr(rc)); + return rc; + } leave: + /* fixme: need more cleanup in case of an error */ release_kbnode( keyblock ); if( DBG_TRUST ) - log_debug(_("trustdb: build_sigrecs: %s\n"), g10_errstr(rc) ); + 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; + + rc = tdbio_read_record( lid, &rec, RECTYPE_DIR ); + if( rc ) { + log_error("LID %lu: error reading dir record: %s\n", + lid, g10_errstr(rc)); + return rc; + } + if( !(rec.r.dir.dirflags & DIRF_CHECKED) ) + rc = update_sigs( &rec ); return rc; } @@ -814,7 +1000,7 @@ build_sigrecs( ulong lid ) * Make a list of trust paths */ static int -make_tsl( ulong pubkey_id, TRUST_SEG_LIST *ret_tslist ) +make_tsl( ulong lid, TRUST_SEG_LIST *ret_tslist ) { int i, rc; LOCAL_ID_INFO *lids = new_lid_table(); @@ -824,17 +1010,17 @@ make_tsl( ulong pubkey_id, TRUST_SEG_LIST *ret_tslist ) tslist = *ret_tslist = NULL; - if( !qry_lid_table_flag( ultikey_table, pubkey_id, NULL ) ) { + if( !qry_lid_table_flag( ultikey_table, lid, NULL ) ) { tslist = m_alloc( sizeof *tslist ); tslist->nseg = 1; tslist->dup = 0; - tslist->seg[0].lid = pubkey_id; + tslist->seg[0].lid = lid; tslist->seg[0].trust = 0; tslist->next = NULL; rc = 0; } else { - stack[0].lid = pubkey_id; + stack[0].lid = lid; stack[0].trust = 0; rc = do_list_path( stack, 1, max_depth, lids, &tslist ); } @@ -901,17 +1087,6 @@ propagate_trust( TRUST_SEG_LIST tslist ) } - -/**************** - * check whether we already build signature records - * Return: true if we have. - */ -static int -do_we_have_sigs( TRUSTREC *dr ) -{ -} - - /**************** * we have the pubkey record and all needed informations are in the trustdb * but nothing more is known. @@ -934,41 +1109,36 @@ do_check( TRUSTREC *dr, unsigned *trustlevel ) if( !dr->r.dir.keylist ) { log_error("Ooops, no keys\n"); - return G10ERR_TRUSTDB + return G10ERR_TRUSTDB; } if( !dr->r.dir.uidlist ) { log_error("Ooops, no user ids\n"); - return G10ERR_TRUSTDB + return G10ERR_TRUSTDB; } - /* verify the cache */ + /* did we already check the signatures */ + if( !(dr->r.dir.dirflags & DIRF_CHECKED) ) /* no - do it now */ + rc = update_sigs( dr ); - /* do we have sigrecs */ - if( !do_we_have_sigs( dr ) ) { /* no sigrecs, so build them */ - rc = build_sigrecs( dr->lid ); - if( !rc ) /* and read again */ - rc = tdbio_read_record( dr->lid, dr, RECTYPE_DIR ); - } - - - !!!!WORK!!!! - - if( dr->r.dir.no_sigs == 3 ) + if( dr->r.dir.dirflags & DIRF_REVOKED ) tflags |= TRUST_FLAG_REVOKED; - if( !rc && !dr->r.dir.sigrec ) { - /* See whether this is our own key */ - if( !qry_lid_table_flag( ultikey_table, pubkeyid, NULL ) ) + #if 0 + if( !rc && !dr->r.dir.siglist ) { + /* We do not have any signatures; check whether it is one of our + * secret keys */ + if( !qry_lid_table_flag( ultikey_table, dr->r.dir.lid, NULL ) ) *trustlevel = tflags | TRUST_ULTIMATE; return 0; } + #endif if( rc ) return rc; /* error while looking for sigrec or building sigrecs */ /* fixme: take it from the cache if it is valid */ /* Make a list of all possible trust-paths */ - rc = make_tsl( pubkeyid, &tslist ); + rc = make_tsl( dr->r.dir.lid, &tslist ); if( rc ) return rc; rc = propagate_trust( tslist ); @@ -1023,7 +1193,7 @@ do_check( TRUSTREC *dr, unsigned *trustlevel ) m_free(tsl); } } - last_trust_web_key = pubkeyid; + last_trust_web_key = dr->r.dir.lid; last_trust_web_tslist = tslist; return 0; } @@ -1079,11 +1249,13 @@ list_trustdb( const char *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_record( pk, &rec )) && rc != -1 ) + else if( (rc=tdbio_search_dir_record( 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 = list_records( pk->local_id)) ) + log_error("user '%s' read problem: %s\n", username, g10_errstr(rc)); else if( (rc = list_sigs( pk->local_id )) ) log_error("user '%s' list problem: %s\n", username, g10_errstr(rc)); free_public_key( pk ); @@ -1097,27 +1269,40 @@ list_trustdb( const char *username ) putchar('-'); putchar('\n'); for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) - tdbio_dump_record( recnum, &rec, stdout ); + tdbio_dump_record( &rec, stdout ); } } /**************** - * make a list of all owner trust value. + * make a list of all defined owner trust value. */ void list_ownertrust() { TRUSTREC rec; + TRUSTREC rec2; ulong recnum; int i; byte *p; + int rc; for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) { - if( rec.rectype == RECTYPE_KEY ) { - p = rec.r.key.fingerprint; - for(i=0; i < rec.r.key.fingerprint_len; i++, p++ ) + if( rec.rectype == RECTYPE_DIR ) { + if( !rec.r.dir.keylist ) { + log_error("Oops; directory record w/o primary key\n"); + continue; + } + if( !rec.r.dir.ownertrust ) + continue; + rc = tdbio_read_record( rec.r.dir.keylist, &rec2, RECTYPE_KEY); + if( rc ) { + log_error("error reading key record: %s\n", g10_errstr(rc)); + continue; + } + p = rec2.r.key.fingerprint; + for(i=0; i < rec2.r.key.fingerprint_len; i++, p++ ) printf("%02X", *p ); - printf(":%u:\n", (unsigned)rec.r.key.ownertrust ); + printf(":%u:\n", (unsigned)rec.r.dir.ownertrust ); } } } @@ -1138,7 +1323,7 @@ list_trust_path( int max_depth, const char *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_record( pk, &rec )) && rc != -1 ) + else if( (rc=tdbio_search_dir_record( pk, &rec )) && rc != -1 ) log_error("problem finding '%s' in trustdb: %s\n", username, g10_errstr(rc)); else if( rc == -1 ) { @@ -1211,6 +1396,48 @@ list_trust_path( int max_depth, const char *username ) } +/**************** + * Check the complete trustdb or only the entries for the given username + */ +void +check_trustdb( const char *username ) +{ + TRUSTREC rec; + int rc; + + if( username ) { + PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + + 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_record( 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 ); + } + else { + ulong recnum; + + for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) { + if( rec.rectype == RECTYPE_DIR ) { + rc = update_sigs( &rec ); + if( rc ) + log_error("lid %lu: check failed: %s\n", + recnum, g10_errstr(rc) ); + else + log_info("lid %lu: checked\n", recnum ); + } + } + } +} + /**************** * Get the trustlevel for this PK. * Note: This does not ask any questions @@ -1385,35 +1612,15 @@ get_ownertrust( ulong lid, unsigned *r_otrust ) log_error("get_ownertrust: read dir record failed\n"); return G10ERR_TRUSTDB; } - if( tdbio_read_record( rec.r.dir.keyrec, &rec, RECTYPE_KEY ) ) { - log_error("get_ownertrust: read key record failed\n"); - return G10ERR_TRUSTDB; - } if( r_otrust ) - *r_otrust = rec.r.key.ownertrust; - return 0; -} - -int -keyid_from_trustdb( ulong lid, u32 *keyid ) -{ - TRUSTREC rec; - - if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) { - log_error("keyid_from_trustdb: read record failed\n"); - return G10ERR_TRUSTDB; - } - if( keyid ) { - keyid[0] = rec.r.dir.keyid[0]; - keyid[1] = rec.r.dir.keyid[1]; - } + *r_otrust = rec.r.dir.ownertrust; return 0; } /**************** * This function simply looks for the key in the trustdb - * and sets PK->local_id. + * and makes sure that pk->local_id is set to the coreect value. * Return: 0 = found * -1 = not found * other = error @@ -1431,7 +1638,7 @@ query_trust_record( PKT_public_key *pk ) } } else { /* no local_id: scan the trustdb */ - if( (rc=tdbio_search_record( pk, &rec )) && rc != -1 ) { + if( (rc=tdbio_search_dir_record( pk, &rec )) && rc != -1 ) { log_error("query_trust_record: search_record failed: %s\n", g10_errstr(rc)); return rc; @@ -1457,10 +1664,6 @@ rel_mem_uidnode( u32 *keyid, int err, TRUSTREC *rec ) r2 = r->next; m_free(r); } - for(r=rec->help_sig; r; r = r2 ) { - r2 = r->next; - m_free(r); - } m_free(rec); } @@ -1469,17 +1672,19 @@ rel_mem_uidnode( u32 *keyid, int err, TRUSTREC *rec ) /**************** * 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. */ int insert_trust_record( PKT_public_key *orig_pk ) { TRUSTREC dirrec, *rec, *rec2; - TRUSTREC *keylist_head, **keylist_tail; - TRUSTREC *uidlist_head, **uidlist_tail, uidlist; + TRUSTREC *keylist_head, **keylist_tail, *keylist; + TRUSTREC *uidlist_head, **uidlist_tail, *uidlist; KBNODE keyblock = NULL; KBNODE node; u32 keyid[2]; /* of primary key */ - ulong knum, dnum; byte *fingerprint; size_t fingerlen; int rc = 0; @@ -1489,9 +1694,9 @@ insert_trust_record( PKT_public_key *orig_pk ) dirrec.rectype = RECTYPE_DIR; if( orig_pk->local_id ) - log_bug("pk->local_id=%lu\n", (ulong)pk->local_id ); + log_bug("pk->local_id=%lu\n", (ulong)orig_pk->local_id ); - fingerprint = fingerprint_from_pk( orig_pk, &fingerlen ); + fingerprint = fingerprint_from_pk( orig_pk, NULL, &fingerlen ); /* fixme: assert that we do not have this record. * we can do this by searching for the primary keyid @@ -1506,9 +1711,8 @@ insert_trust_record( PKT_public_key *orig_pk ) } /* build data structure as linked lists in memory */ - keylist_head = NULL; keylist_tail = &keylist_head; - uidlist_head = NULL; uidlist_tail = &uidlist_head; - uidlist = NULL; + keylist_head = NULL; keylist_tail = &keylist_head; keylist = NULL; + uidlist_head = NULL; uidlist_tail = &uidlist_head; uidlist = NULL; keyid[0] = keyid[1] = 0; for( node=keyblock; node; node = node->next ) { if( node->pkt->pkttype == PKT_PUBLIC_KEY @@ -1520,7 +1724,7 @@ insert_trust_record( PKT_public_key *orig_pk ) BUG(); /* more than one primary key */ keyid_from_pk( pk, keyid ); } - fingerprint = fingerprint_from_pk( orig_pk, &fingerlen ); + fingerprint = fingerprint_from_pk( orig_pk, NULL, &fingerlen ); rec = m_alloc_clear( sizeof *rec ); rec->rectype = RECTYPE_KEY; rec->r.key.pubkey_algo = pk->pubkey_algo; @@ -1554,8 +1758,8 @@ insert_trust_record( PKT_public_key *orig_pk ) else if( (rc = check_key_signature( keyblock, node, NULL ))) { log_error("key %08lX, uid %02X%02X: " "invalid self-signature: %s\n", - (ulong)keyid[1], uidlist->namehash[18], - uidlist->namehash[19], g10_errstr(rc) ); + (ulong)keyid[1], uidlist->r.uid.namehash[18], + uidlist->r.uid.namehash[19], g10_errstr(rc) ); rc = 0; } else { /* build the prefrecord */ @@ -1567,10 +1771,6 @@ insert_trust_record( PKT_public_key *orig_pk ) /* handle it here */ } else { /* not a selfsignature */ - /* put all this sigs into a list and mark them as unchecked - * we can't check here because we probably have not - * all keys of other signators - we do it on deman - */ } } } @@ -1592,7 +1792,7 @@ insert_trust_record( PKT_public_key *orig_pk ) /* check that we have at least one userid */ if( !uidlist_head ) { log_error("key %08lX: no user ids - rejected\n", (ulong)keyid[1] ); - rc = G10ERR_BAD_CERT, + rc = G10ERR_BAD_CERT; goto leave; } @@ -1600,7 +1800,6 @@ insert_trust_record( PKT_public_key *orig_pk ) /* fixme: should start a transaction here */ dirrec.recnum = tdbio_new_recnum(); dirrec.r.dir.lid = dirrec.recnum; - /* fixme: how do we set sigflag???*/ /* (list of keys) */ for(rec=keylist_head; rec; rec = rec->next ) { rec->r.key.lid = dirrec.recnum; @@ -1620,15 +1819,7 @@ insert_trust_record( PKT_public_key *orig_pk ) } for( rec2 = rec->help_pref; rec2; rec2 = rec2->next ) rec2->r.pref.next = rec2->next? rec2->next->recnum : 0; - rec->r.uid.prefrec = rec->help_pref->recnum; - /* (signature list) */ - for( rec2 = rec->help_sig; rec2; rec2 = rec2->next ) { - rec2->r.sig.lid = dirrec.recnum; - rec2->recnum = tdbio_new_recnum(); - } - for( rec2 = rec->help_sig; rec2; rec2 = rec2->next ) - rec2->r.sig.next = rec2->next? rec2->next->recnum : 0; - rec->r.uid.siglist = rec->help_sig->recnum; + rec->r.uid.prefrec = rec->help_pref? rec->help_pref->recnum : 0; } for(rec=uidlist_head; rec; rec = rec->next ) rec->r.uid.next = rec->next? rec->next->recnum : 0; @@ -1650,7 +1841,7 @@ insert_trust_record( PKT_public_key *orig_pk ) rc = G10ERR_TRUSTDB; goto leave; } - for( rec2=rec->help_pref; rec2; rec2 = rec2->next ); { + for( rec2=rec->help_pref; rec2; rec2 = rec2->next ) { assert( rec2->rectype == RECTYPE_PREF ); if( tdbio_write_record( rec2 ) ) { log_error("writing pref record failed\n"); @@ -1658,29 +1849,33 @@ insert_trust_record( PKT_public_key *orig_pk ) goto leave; } } - for( rec2=rec->help_sig; rec2; rec2 = rec2->next ); { - assert( rec2->rectype == RECTYPE_SIG ); - if( tdbio_write_record( rec2 ) ) { - log_error("writing sig record failed\n"); - rc = G10ERR_TRUSTDB; - goto leave; - } - } } - if( tdbio_write_record( dirrec.r.dir.lid, &dirrec ) ) { + if( tdbio_write_record( &dirrec ) ) { log_error("writing dir record failed\n"); return G10ERR_TRUSTDB; } /* and store the LID */ orig_pk->local_id = dirrec.r.dir.lid; + 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; + pk->local_id = dirrec.r.dir.lid; + } + else if( node->pkt->pkttype == PKT_SIGNATURE ) { + PKT_signature *sig = node->pkt->pkt.signature; + sig->local_id = dirrec.r.dir.lid; + } + } + leave: - for( rec=dirrec.r.dir.uidlist; rec; rec = rec2 ) { + for(rec=uidlist_head; rec; rec = rec->next ) { rec2 = rec->next; - rel_mem_uidnode(rec); + rel_mem_uidnode(NULL, 0, rec ); } - for( rec=dirrec.r.dir.keylist; rec; rec = rec2 ) { + for(rec=keylist_head; rec; rec = rec->next ) { rec2 = rec->next; m_free(rec); } @@ -1693,29 +1888,17 @@ int update_ownertrust( ulong lid, unsigned new_trust ) { TRUSTREC rec; - ulong recnum; if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) { log_error("update_ownertrust: read dir failed\n"); return G10ERR_TRUSTDB; } - recnum = rec.r.dir.keyrec; - if( tdbio_read_record( recnum, &rec, RECTYPE_KEY ) ) { - log_error("update_ownertrust: read key failed\n"); - return G10ERR_TRUSTDB; - } - /* check keyid, fingerprint etc ? */ - - rec.r.key.ownertrust = new_trust; - if( tdbio_write_record( recnum, &rec ) ) { + rec.r.dir.ownertrust = new_trust; + if( tdbio_write_record( &rec ) ) { log_error("update_ownertrust: write failed\n"); return G10ERR_TRUSTDB; } - return 0; } - - - diff --git a/g10/trustdb.h b/g10/trustdb.h index 705ffaf80..aaf0d4a8d 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -39,12 +39,13 @@ void list_trustdb(const char *username); void list_trust_path( int max_depth, const char *username ); void list_ownertrust(void); +void check_trustdb( const char *username ); int init_trustdb( int level, const char *dbname ); int check_trust( PKT_public_key *pk, unsigned *r_trustlevel ); int query_trust_info( PKT_public_key *pk ); int enum_trust_web( void **context, ulong *lid ); int get_ownertrust( ulong lid, unsigned *r_otrust ); -int keyid_from_trustdb( ulong lid, u32 *keyid ); +int keyid_from_lid( ulong lid, u32 *keyid ); int query_trust_record( PKT_public_key *pk ); int insert_trust_record( PKT_public_key *pk ); int update_ownertrust( ulong lid, unsigned new_trust ); diff --git a/tools/mk-tdata b/tools/mk-tdata deleted file mode 100755 index 7fcfb389f..000000000 Binary files a/tools/mk-tdata and /dev/null differ diff --git a/util/ChangeLog b/util/ChangeLog index 6b4a76fd8..a52ea0a69 100644 --- a/util/ChangeLog +++ b/util/ChangeLog @@ -1,3 +1,11 @@ +Tue Jul 21 10:35:48 1998 Werner Koch (wk@(none)) + + * argparse.c: New option flag to distinguish options and commands. + +Sat Jul 18 19:49:30 1998 Werner Koch (wk@(none)) + + * argparse.c (arg_parse): Added -? as alias for -h + Thu Jul 9 14:47:20 1998 Werner Koch (wk@isil.d.shuttle.de) * secmem.c (secmem_init): Drops setuid if called with 0. diff --git a/util/argparse.c b/util/argparse.c index 9a9909e30..766d461f9 100644 --- a/util/argparse.c +++ b/util/argparse.c @@ -83,11 +83,12 @@ * 4 = takes ulong argument * Bit 3 : argument is optional (r_type will the be set to 0) * Bit 4 : allow 0x etc. prefixed values. + * Bit 7 : this is an command and not an option * If can stop the option processing by setting opts to NULL, the function will * then return 0. * @Return Value * Returns the args.r_opt or 0 if ready - * r_opt may be -2 to indicate an unknown option. + * r_opt may be -2/-7 to indicate an unknown option/command. * @See Also * ArgExpand * @Notes @@ -157,6 +158,8 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno ) s = "%s:%u: keyword too long\n"; else if( arg->r_opt == -3 ) s = "%s:%u: missing argument\n"; + else if( arg->r_opt == -7 ) + s = "%s:%u: invalid command\n"; else s = "%s:%u: invalid option\n"; log_error(s, filename, *lineno ); @@ -164,6 +167,8 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno ) else { if( arg->r_opt == -3 ) s = "Missing argument for option \"%.50s\"\n"; + else if( arg->r_opt == -7 ) + s = "Invalid command \"%.50s\"\n"; else s = "Invalid option \"%.50s\"\n"; log_error(s, arg->internal.last? arg->internal.last:"[??]" ); @@ -220,8 +225,8 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno, arg->r_opt = opts[index].short_opt; if( inverse ) arg->r_opt = -arg->r_opt; - if( !opts[index].short_opt ) - arg->r_opt = -2; /* unknown option */ + if( !opts[index].short_opt ) /* unknown command/option */ + arg->r_opt = (opts[index].flags & 256)? -7:-2; else if( (opts[index].flags & 8) ) /* no argument */ arg->r_opt = -3; /* error */ else /* no or optiona argument */ @@ -279,7 +284,7 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno, index = i; arg->r_opt = opts[index].short_opt; if( !opts[index].short_opt ) { - arg->r_opt = -2; /* unknown option */ + arg->r_opt = (opts[index].flags & 256)? -7:-2; state = -1; /* skip rest of line and leave */ } else @@ -390,7 +395,7 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) arg->r_opt = opts[i].short_opt; if( !opts[i].short_opt ) { - arg->r_opt = -2; /* unknown option */ + arg->r_opt = (opts[i].flags & 256)? -7:-2; arg->r.ret_str = s+2; } else if( (opts[i].flags & 7) ) { @@ -438,12 +443,12 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) break; } - if( !opts[i].short_opt && *s == 'h' ) + if( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) ) show_help(opts, arg->flags); arg->r_opt = opts[i].short_opt; if( !opts[i].short_opt ) { - arg->r_opt = -2; /* unknown option */ + arg->r_opt = (opts[i].flags & 256)? -7:-2; arg->internal.inarg++; /* point to the next arg */ arg->r.ret_str = s; }