diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/ChangeLog | 31 | ||||
-rw-r--r-- | g10/armor.c | 40 | ||||
-rw-r--r-- | g10/build-packet.c | 20 | ||||
-rw-r--r-- | g10/encode.c | 5 | ||||
-rw-r--r-- | g10/export.c | 22 | ||||
-rw-r--r-- | g10/filter.h | 1 | ||||
-rw-r--r-- | g10/free-packet.c | 4 | ||||
-rw-r--r-- | g10/g10.c | 45 | ||||
-rw-r--r-- | g10/getkey.c | 153 | ||||
-rw-r--r-- | g10/import.c | 1 | ||||
-rw-r--r-- | g10/keydb.h | 7 | ||||
-rw-r--r-- | g10/keygen.c | 57 | ||||
-rw-r--r-- | g10/keyid.c | 17 | ||||
-rw-r--r-- | g10/keylist.c | 20 | ||||
-rw-r--r-- | g10/mainproc.c | 8 | ||||
-rw-r--r-- | g10/options.h | 6 | ||||
-rw-r--r-- | g10/packet.h | 4 | ||||
-rw-r--r-- | g10/parse-packet.c | 20 | ||||
-rw-r--r-- | g10/ringedit.c | 83 | ||||
-rw-r--r-- | g10/sig-check.c | 8 | ||||
-rw-r--r-- | g10/sign.c | 2 | ||||
-rw-r--r-- | g10/tdbio.c | 344 | ||||
-rw-r--r-- | g10/tdbio.h | 1 | ||||
-rw-r--r-- | g10/textfilter.c | 4 | ||||
-rw-r--r-- | g10/trustdb.c | 382 | ||||
-rw-r--r-- | g10/trustdb.h | 1 |
26 files changed, 855 insertions, 431 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog index 93a21e241..4bc222084 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,6 +1,35 @@ +Fri Oct 16 10:24:47 1998 Werner Koch ([email protected]) + + * trustdb.c: Rewrote most. + * tdbio.c: Add cache and generalized hash tables. + + * options.h (ENABLE_COMMENT_PACKETS): New but undef'ed. + * encode.c, sign.c, keygen.c: Disabled comment packets. + * export.c (do_export): Comment packets are never exported, + except for those in the secret keyring. + + * g10.c (main): Removed option do-no-export-rsa; should be + be replaced by a secpial tool. + * export.c (do_export): Removed the code for the above option. + + * armor.c (find_header): Support for new only_keyblocks. + * import.c (import_keys): Only looks for keyblock armors. + + * packet.h: replaced valid_days by expiredate and changed all users. + * build-packet.c (do_public_key): calculates valid-days + (do_secret_key): Ditto. + * parse-packet.c (parse_key): expiredate is calucated from the + valid_period in v3 packets. + * keyid.c (do_fingerprint_md): calculates valid_dates. + + * keygen.c (add_key_expire): fixed key expiration time for v4 packets. + + * armor.c (find_header): A LF in the first 28 bytes + was skipped for non-armored data. + Thu Oct 8 11:35:51 1998 Werner Koch ([email protected]) - * armor.c (is_armored): Ad test on old comment packets. + * armor.c (is_armored): Add test on old comment packets. * tdbio.c (tdbio_search_dir_bypk): fixed memory leak. diff --git a/g10/armor.c b/g10/armor.c index df67712a4..aa5609018 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -109,7 +109,8 @@ static char *tail_strings[] = { static fhdr_state_t find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, IOBUF a, size_t n, - unsigned *r_empty, int *r_hashes ); + unsigned *r_empty, int *r_hashes, + int only_keyblocks ); static void @@ -260,7 +261,8 @@ parse_hash_header( const char *line ) */ static fhdr_state_t find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, - IOBUF a, size_t n, unsigned *r_empty, int *r_hashes ) + IOBUF a, size_t n, unsigned *r_empty, int *r_hashes, + int only_keyblocks ) { int c=0, i; const char *s; @@ -273,7 +275,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, buflen = *r_buflen; assert(buflen >= 100 ); - buflen -= 3; /* reserved room for CR,LF and one extra */ + buflen -= 4; /* reserved room for CR,LF, and two extra */ do { switch( state ) { @@ -281,14 +283,17 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, /* read at least the first byte to check whether it is armored * or not */ c = 0; - for(n=0; n < 28 && (c=iobuf_get2(a)) != -1 && c != '\n'; ) + for(n=0; n < 28 && (c=iobuf_get(a)) != -1 && c != '\n'; ) buf[n++] = c; if( !n && c == '\n' ) state = fhdrCHECKBegin; else if( !n || c == -1 ) state = fhdrNOArmor; /* too short */ - else if( !is_armored( buf ) ) + else if( !is_armored( buf ) ) { state = fhdrNOArmor; + if( c == '\n' ) + buf[n++] = c; + } else if( c == '\n' ) state = fhdrCHECKBegin; else @@ -299,7 +304,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, n = 0; case fhdrINITCont: /* read more stuff into buffer */ c = 0; - for(; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; ) + for(; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; ) buf[n++] = c; state = c == '\n' ? fhdrCHECKBegin : c == -1 ? fhdrEOF : fhdrINITSkip; @@ -309,21 +314,21 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, if( c == '\n' ) n = 0; else { - while( (c=iobuf_get2(a)) != -1 && c != '\n' ) + while( (c=iobuf_get(a)) != -1 && c != '\n' ) ; } state = c == -1? fhdrEOF : fhdrINIT; break; case fhdrSKIPHeader: - while( (c=iobuf_get2(a)) != -1 && c != '\n' ) + while( (c=iobuf_get(a)) != -1 && c != '\n' ) ; state = c == -1? fhdrEOF : fhdrWAITHeader; break; case fhdrWAITHeader: /* wait for Header lines */ c = 0; - for(n=0; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; ) + for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; ) buf[n++] = c; buf[n] = 0; if( n < buflen || c == '\n' ) { @@ -388,7 +393,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, case fhdrWAITClearsig: /* skip the empty line (for clearsig) */ c = 0; - for(n=0; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; ) + for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; ) buf[n++] = c; if( n < buflen || c == '\n' ) { buf[n] = 0; @@ -432,6 +437,9 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, break; if( !s ) break; /* unknown begin line */ + if( only_keyblocks && i != 1 && i != 5 && i != 6 ) + break; /* not a keyblock armor */ + /* found the begin line */ hdr_line = i; state = fhdrWAITHeader; @@ -448,7 +456,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, * we have to look for a header line or dashed escaped text*/ n = 0; c = 0; - while( n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n' ) + while( n < buflen && (c=iobuf_get(a)) != -1 && c != '\n' ) buf[n++] = c; buf[n] = 0; if( c == -1 ) @@ -516,7 +524,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, * for dashed escaped text of headers */ c = 0; n = 0; - while( n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n' ) + while( n < buflen && (c=iobuf_get(a)) != -1 && c != '\n' ) buf[n++] = c; buf[n] = 0; if( c == -1 ) @@ -534,7 +542,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, * counting spaces is not enough, because it may be a * mix of different white space characters */ IOBUF b = iobuf_temp(); - while( (c=iobuf_get2(a)) != -1 && c != '\n' ) { + while( (c=iobuf_get(a)) != -1 && c != '\n' ) { iobuf_put(b,c); if( c != ' ' && c != '\t' && c != '\r' ) break; @@ -622,7 +630,8 @@ check_input( armor_filter_context_t *afx, IOBUF a ) n = DIM(afx->helpbuf); state = find_header( state, afx->helpbuf, &n, a, - afx->helplen, &emplines, &afx->hashes); + afx->helplen, &emplines, &afx->hashes, + afx->only_keyblocks ); switch( state ) { case fhdrNOArmor: afx->inp_checked = 1; @@ -708,7 +717,8 @@ fake_packet( armor_filter_context_t *afx, IOBUF a, afx->helpidx = 0; state = find_header( state, afx->helpbuf, &n, a, state == fhdrNullClearsig? afx->helplen:0, - &emplines, &afx->hashes ); + &emplines, &afx->hashes, + afx->only_keyblocks ); switch( state) { case fhdrERROR: invalid_armor(); diff --git a/g10/build-packet.c b/g10/build-packet.c index a877b7e3c..11edb33e6 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -209,8 +209,14 @@ do_public_key( IOBUF out, int ctb, PKT_public_key *pk ) else iobuf_put( a, pk->version ); write_32(a, pk->timestamp ); - if( pk->version < 4 ) - write_16(a, pk->valid_days ); + if( pk->version < 4 ) { + u16 ndays; + if( pk->expiredate ) + ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L); + else + ndays = 0; + write_16(a, 0 ); + } iobuf_put(a, pk->pubkey_algo ); n = pubkey_get_npkey( pk->pubkey_algo ); if( !n ) @@ -280,8 +286,14 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk ) else iobuf_put( a, sk->version ); write_32(a, sk->timestamp ); - if( sk->version < 4 ) - write_16(a, sk->valid_days ); + if( sk->version < 4 ) { + u16 ndays; + if( sk->expiredate ) + ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L); + else + ndays = 0; + write_16(a, 0 ); + } iobuf_put(a, sk->pubkey_algo ); nskey = pubkey_get_nskey( sk->pubkey_algo ); npkey = pubkey_get_npkey( sk->pubkey_algo ); diff --git a/g10/encode.c b/g10/encode.c index bc4742607..0d8a84c94 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -118,12 +118,14 @@ encode_simple( const char *filename, int mode ) if( opt.armor ) iobuf_push_filter( out, armor_filter, &afx ); + #ifdef ENABLE_COMMENT_PACKETS else { write_comment( out, "#created by GNUPG v" VERSION " (" PRINTABLE_OS_NAME ")"); if( opt.comment_string ) write_comment( out, opt.comment_string ); } + #endif if( s2k && !opt.rfc1991 ) { PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc ); enc->version = 4; @@ -224,13 +226,14 @@ encode_crypt( const char *filename, STRLIST remusr ) if( opt.armor ) iobuf_push_filter( out, armor_filter, &afx ); + #ifdef ENABLE_COMMENT_PACKETS else { write_comment( out, "#created by GNUPG v" VERSION " (" PRINTABLE_OS_NAME ")"); if( opt.comment_string ) write_comment( out, opt.comment_string ); } - + #endif /* create a session key */ cfx.dek = m_alloc_secure( sizeof *cfx.dek ); if( !opt.def_cipher_algo ) { /* try to get it from the prefs */ diff --git a/g10/export.c b/g10/export.c index 301cb5ece..46413fff2 100644 --- a/g10/export.c +++ b/g10/export.c @@ -124,24 +124,10 @@ do_export( STRLIST users, int secret ) /* and write it */ for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) { - if( opt.do_not_export_rsa ) { - int algo; - switch( node->pkt->pkttype ) { - /* note: we can� do this for subkeys here */ - case PKT_PUBLIC_KEY: - algo = node->pkt->pkt.public_key->pubkey_algo; - break; - case PKT_SECRET_KEY: - algo = node->pkt->pkt.secret_key->pubkey_algo; - break; - case PKT_SIGNATURE: - algo = node->pkt->pkt.signature->pubkey_algo; - break; - default: algo = 0; - } - if( is_RSA(algo) ) - continue; - } + /* don't export any comment packets but those in the + * secret keyring */ + if( !secret && node->pkt->pkttype == PKT_COMMENT ) + continue; if( (rc = build_packet( out, node->pkt )) ) { log_error("build_packet(%d) failed: %s\n", node->pkt->pkttype, g10_errstr(rc) ); diff --git a/g10/filter.h b/g10/filter.h index d48b75627..1cf8f8e42 100644 --- a/g10/filter.h +++ b/g10/filter.h @@ -31,6 +31,7 @@ typedef struct { typedef struct { int status; int what; + int only_keyblocks; /* skip all headers but ".... key block" */ byte radbuf[4]; int idx, idx2; u32 crc; diff --git a/g10/free-packet.c b/g10/free-packet.c index e6b228117..c3b516dbd 100644 --- a/g10/free-packet.c +++ b/g10/free-packet.c @@ -354,7 +354,7 @@ cmp_public_keys( PKT_public_key *a, PKT_public_key *b ) if( a->timestamp != b->timestamp ) return -1; - if( a->valid_days != b->valid_days ) + if( a->expiredate != b->expiredate ) return -1; if( a->pubkey_algo != b->pubkey_algo ) return -1; @@ -380,7 +380,7 @@ cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk ) if( pk->timestamp != sk->timestamp ) return -1; - if( pk->valid_days != sk->valid_days ) + if( pk->expiredate != sk->expiredate ) return -1; if( pk->pubkey_algo != sk->pubkey_algo ) return -1; @@ -1,4 +1,4 @@ -/* g10.c - The GNUPG utility (main for gpg) +/* g10.c - The GnuPG utility (main for gpg) * Copyright (C) 1998 Free Software Foundation, Inc. * * This file is part of GNUPG. @@ -88,6 +88,7 @@ enum cmd_and_opt_values { aNull = 0, aPrintMD, aPrintMDs, aCheckTrustDB, + aUpdateTrustDB, aFixTrustDB, aListTrustDB, aListTrustPath, @@ -98,7 +99,6 @@ enum cmd_and_opt_values { aNull = 0, aGenRandom, oFingerprint, - oDoNotExportRSA, oAnswerYes, oAnswerNo, oKeyring, @@ -172,13 +172,17 @@ static ARGPARSE_OPTS opts[] = { #endif { aExport, "export" , 256, N_("export keys") }, { aExportSecret, "export-secret-keys" , 256, "@" }, - { oDoNotExportRSA, "do-not-export-rsa", 0, "@" }, { aImport, "import", 256 , N_("import/merge keys")}, { aListPackets, "list-packets",256,N_("list only the sequence of packets")}, #ifdef IS_G10MAINT - { aExportOwnerTrust, "export-ownertrust", 256, N_("export the ownertrust values")}, - { aImportOwnerTrust, "import-ownertrust", 256 , N_("import ownertrust values")}, - { aCheckTrustDB, "check-trustdb",0 , N_("|[NAMES]|check the trust database")}, + { aExportOwnerTrust, + "export-ownertrust", 256, N_("export the ownertrust values")}, + { aImportOwnerTrust, + "import-ownertrust", 256 , N_("import ownertrust values")}, + { aUpdateTrustDB, + "update-trustdb",0 , N_("|[NAMES]|update the trust database")}, + { aCheckTrustDB, + "check-trustdb",0 , N_("|[NAMES]|check the trust database")}, { aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")}, { aDeArmor, "dearmor", 256, N_("De-Armor a file or stdin") }, { aEnArmor, "enarmor", 256, N_("En-Armor a file or stdin") }, @@ -302,9 +306,9 @@ strusage( int level ) switch( level ) { case 11: p = #ifdef IS_G10MAINT - "gpgm (GNUPG)"; + "gpgm (GnuPG)"; #else - "gpg (GNUPG)"; + "gpg (GnuPG)"; #endif break; case 13: p = VERSION; break; @@ -323,7 +327,7 @@ strusage( int level ) case 41: p = #ifdef IS_G10MAINT _("Syntax: gpgm [options] [files]\n" - "GNUPG maintenance utility\n"); + "GnuPG maintenance utility\n"); #else _("Syntax: gpg [options] [files]\n" "sign, check, encrypt or decrypt\n" @@ -638,6 +642,7 @@ main( int argc, char **argv ) case aPrintMDs: set_cmd( &cmd, aPrintMDs); break; case aListTrustDB: set_cmd( &cmd, aListTrustDB); break; case aCheckTrustDB: set_cmd( &cmd, aCheckTrustDB); break; + case aUpdateTrustDB: set_cmd( &cmd, aUpdateTrustDB); break; case aFixTrustDB: set_cmd( &cmd, aFixTrustDB); break; case aListTrustPath: set_cmd( &cmd, aListTrustPath); break; case aDeArmor: set_cmd( &cmd, aDeArmor); break; @@ -692,10 +697,12 @@ main( int argc, char **argv ) case oCompressKeys: opt.compress_keys = 1; break; case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break; case oAlwaysTrust: opt.always_trust = 1; break; - case oLoadExtension: register_cipher_extension(pargs.r.ret_str); break; + case oLoadExtension: + register_cipher_extension(orig_argc? *orig_argv:NULL, + pargs.r.ret_str); + break; case oRFC1991: opt.rfc1991 = 1; opt.no_comment = 1; break; case oEmuChecksumBug: opt.emulate_bugs |= EMUBUG_GPGCHKSUM; break; - case oDoNotExportRSA: opt.do_not_export_rsa = 1; break; case oCompressSigs: opt.compress_sigs = 1; break; case oRunAsShmCP: #ifndef USE_SHM_COPROCESSING @@ -835,13 +842,13 @@ main( int argc, char **argv ) && !(cmd == aKMode && argc == 2 ) ) { if( !sec_nrings || default_keyring ) /* add default secret rings */ - add_secret_keyring("secring.gpg"); + add_keyblock_resource("secring.gpg", 0, 1); for(sl = sec_nrings; sl; sl = sl->next ) - add_secret_keyring( sl->d ); + add_keyblock_resource( sl->d, 0, 1 ); if( !nrings || default_keyring ) /* add default ring */ - add_keyring("pubring.gpg"); + add_keyblock_resource("pubring.gpg", 0, 0); for(sl = nrings; sl; sl = sl->next ) - add_keyring( sl->d ); + add_keyblock_resource( sl->d, 0, 0 ); } FREE_STRLIST(nrings); FREE_STRLIST(sec_nrings); @@ -996,7 +1003,7 @@ main( int argc, char **argv ) else { /* add keyring (default keyrings are not registered in this * special case */ - add_keyring( argv[1] ); + add_keyblock_resource( argv[1], 0, 0 ); public_key_list( **argv?1:0, argv ); } } @@ -1160,6 +1167,12 @@ main( int argc, char **argv ) } break; + case aUpdateTrustDB: + if( argc ) + wrong_args("--update-trustdb"); + update_trustdb(); + break; + case aCheckTrustDB: if( !argc ) check_trustdb(NULL); diff --git a/g10/getkey.c b/g10/getkey.c index 6e4c34592..90bd09a25 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -37,16 +37,15 @@ #define MAX_PK_CACHE_ENTRIES 50 #define MAX_UID_CACHE_ENTRIES 50 +static struct { + int any; + int okay_count; + int nokey_count; + int error_count; +} lkup_stats[21]; -typedef struct enum_seckey_context { - int eof; - STRLIST sl; - IOBUF iobuf; -} enum_seckey_context_t; -static STRLIST keyrings; -static STRLIST secret_keyrings; #if MAX_UNK_CACHE_ENTRIES typedef struct keyid_list { @@ -89,93 +88,25 @@ static int lookup( PKT_public_key *pk, static int lookup_sk( PKT_secret_key *sk, int mode, u32 *keyid, const char *name, int primary ); -/* note this function may be called before secure memory is - * available - * The first keyring which is added by this function is - * created if it does not exist. - */ -void -add_keyring( const char *name ) -{ - STRLIST sl; - int rc, force = !keyrings; - - if( *name != '/' ) { /* do tilde expansion etc */ - char *p ; - - if( strchr(name, '/') ) - p = make_filename(name, NULL); - else - p = make_filename(opt.homedir, name, NULL); - sl = append_to_strlist( &keyrings, p ); - m_free(p); - } - else - sl = append_to_strlist( &keyrings, name ); - - /* fixme: We should remove much out of this module and - * combine it with the keyblock stuff from ringedit.c - * For now we will simple add the filename as keyblock resource - */ - rc = add_keyblock_resource( sl->d, force, 0 ); - if( rc ) - log_error("keyblock resource '%s': %s\n", sl->d, g10_errstr(rc) ); -} -/**************** - * Get the name of the keyrings, start with a sequence number of 0. - */ -const char * -get_keyring( int sequence ) -{ - STRLIST sl; - - for(sl = keyrings; sl && sequence; sl = sl->next, sequence-- ) - ; - return sl? sl->d : NULL; -} - -const char * -get_secret_keyring( int sequence ) -{ - STRLIST sl; - - for(sl = secret_keyrings; sl && sequence; sl = sl->next, sequence-- ) - ; - return sl? sl->d : NULL; -} - - -void -add_secret_keyring( const char *name ) +static void +print_stats() { - STRLIST sl; - int rc, force = !secret_keyrings; - - if( *name != '/' ) { /* do tilde expansion etc */ - char *p ; - - if( strchr(name, '/') ) - p = make_filename(name, NULL); - else - p = make_filename(opt.homedir, name, NULL); - sl = append_to_strlist( &secret_keyrings, p ); - m_free(p); + int i; + for(i=0; i < DIM(lkup_stats); i++ ) { + if( lkup_stats[i].any ) + fprintf(stderr, + "lookup stats: mode=%-2d ok=%-6d nokey=%-6d err=%-6d\n", + i, + lkup_stats[i].okay_count, + lkup_stats[i].nokey_count, + lkup_stats[i].error_count ); } - else - sl = append_to_strlist( &secret_keyrings, name ); - - /* fixme: We should remove much out of this module and - * combine it with the keyblock stuff from ringedit.c - * For now we will simple add the filename as keyblock resource - */ - rc = add_keyblock_resource( sl->d, force, 1 ); - if( rc ) - log_error("secret keyblock resource '%s': %s\n", sl->d, g10_errstr(rc)); } + static void cache_public_key( PKT_public_key *pk ) { @@ -690,7 +621,7 @@ merge_one_pk_and_selfsig( KBNODE keyblock, KBNODE knode ) */ const byte *p; p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL ); - pk->valid_days = p? ((buffer_to_u32(p)+86399L)/86400L):0; + pk->expiredate = p? buffer_to_u32(p):0; /* fixme: add usage etc. to pk */ break; } @@ -739,12 +670,12 @@ merge_keys_and_selfsig( KBNODE keyblock ) const byte *p; p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL ); if( pk ) { - pk->valid_days = p? ((buffer_to_u32(p)+86399L)/86400L):0; + pk->expiredate = p? buffer_to_u32(p):0; /* fixme: add usage etc. */ pk = NULL; /* use only the first self signature */ } else { - sk->valid_days = p? ((buffer_to_u32(p)+86399L)/86400L):0; + sk->expiredate = p? buffer_to_u32(p):0; sk = NULL; /* use only the first self signature */ } } @@ -756,7 +687,7 @@ merge_keys_and_selfsig( KBNODE keyblock ) /**************** - * Lookup a key by scanning all keyrings + * Lookup a key by scanning all keyresources * mode 1 = lookup by NAME (exact) * 2 = lookup by NAME (substring) * 3 = lookup by NAME (email address) @@ -949,6 +880,24 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid, enum_keyblocks( 2, &kbpos, &keyblock ); /* close */ release_kbnode( keyblock ); set_packet_list_mode(oldmode); + if( opt.debug & DBG_MEMSTAT_VALUE ) { + static int initialized; + + if( !initialized ) { + initialized = 1; + atexit( print_stats ); + } + + assert( mode < DIM(lkup_stats) ); + lkup_stats[mode].any = 1; + if( !rc ) + lkup_stats[mode].okay_count++; + else if ( rc == G10ERR_NO_PUBKEY ) + lkup_stats[mode].nokey_count++; + else + lkup_stats[mode].error_count++; + } + return rc; } @@ -1107,12 +1056,19 @@ enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys ) int rc=0; PACKET pkt; int save_mode; - enum_seckey_context_t *c = *context; + struct { + int eof; + int sequence; + const char *name; + IOBUF iobuf; + } *c = *context; + if( !c ) { /* make a new context */ c = m_alloc_clear( sizeof *c ); *context = c; - c->sl = secret_keyrings; + c->sequence = 0; + c->name = enum_keyblock_resources( &c->sequence, 1 ); } if( !sk ) { /* free the context */ @@ -1126,10 +1082,11 @@ enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys ) if( c->eof ) return -1; - for( ; c->sl; c->sl = c->sl->next ) { + /* FIXME: This assumes a plain keyring file */ + for( ; c->name; c->name = enum_keyblock_resources( &c->sequence, 1 ) ) { if( !c->iobuf ) { - if( !(c->iobuf = iobuf_open( c->sl->d ) ) ) { - log_error("enum_secret_keys: can't open '%s'\n", c->sl->d ); + if( !(c->iobuf = iobuf_open( c->name ) ) ) { + log_error("enum_secret_keys: can't open '%s'\n", c->name ); continue; /* try next file */ } } @@ -1165,7 +1122,7 @@ get_user_id_string( u32 *keyid ) user_id_db_t r; char *p; int pass=0; - /* try it two times; second pass reads from keyrings */ + /* try it two times; second pass reads from key resources */ do { for(r=user_id_db; r; r = r->next ) if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) { @@ -1185,7 +1142,7 @@ get_user_id( u32 *keyid, size_t *rn ) user_id_db_t r; char *p; int pass=0; - /* try it two times; second pass reads from keyrings */ + /* try it two times; second pass reads from key resources */ do { for(r=user_id_db; r; r = r->next ) if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) { diff --git a/g10/import.c b/g10/import.c index ccfbccaad..374843363 100644 --- a/g10/import.c +++ b/g10/import.c @@ -96,6 +96,7 @@ import_keys( const char *fname ) memset( &afx, 0, sizeof afx); memset( &cfx, 0, sizeof cfx); + afx.only_keyblocks = 1; /* open file */ inp = iobuf_open(fname); diff --git a/g10/keydb.h b/g10/keydb.h index c7fb26db1..efb371cec 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -106,10 +106,6 @@ void set_next_passphrase( const char *s ); char *get_last_passphrase(void); /*-- getkey.c --*/ -void add_keyring( const char *name ); -const char *get_keyring( int sequence ); -const char *get_secret_keyring( int sequence ); -void add_secret_keyring( const char *name ); int get_pubkey( PKT_public_key *pk, u32 *keyid ); int get_pubkey_byname( PKT_public_key *pk, const char *name ); int get_seckey( PKT_secret_key *sk, u32 *keyid ); @@ -156,7 +152,8 @@ int commit_kbnode( KBNODE *root ); void dump_kbnode( KBNODE node ); /*-- ringedit.c --*/ -int add_keyblock_resource( const char *filename, int force, int secret ); +const char *enum_keyblock_resources( int *sequence, int secret ); +int add_keyblock_resource( const char *resname, int force, int secret ); const char *keyblock_resource_name( KBPOS *kbpos ); int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos ); int find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos ); diff --git a/g10/keygen.c b/g10/keygen.c index 3a7582013..9f1d8df9f 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -58,8 +58,8 @@ add_key_expire( PKT_signature *sig, void *opaque ) byte buf[8]; u32 u; - if( sk->valid_days ) { - u = sk->valid_days * 86400L; + if( sk->expiredate ) { + u = sk->expiredate; buf[0] = (u >> 24) & 0xff; buf[1] = (u >> 16) & 0xff; buf[2] = (u >> 8) & 0xff; @@ -192,7 +192,7 @@ write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *sk ) static int gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, u16 valid_days, + STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expiredate, int version ) { int rc; @@ -214,7 +214,9 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, pk = m_alloc_clear( sizeof *pk ); sk->timestamp = pk->timestamp = make_timestamp(); sk->version = pk->version = version; - sk->valid_days = pk->valid_days = valid_days; + if( expiredate && expiredate < sk->timestamp ) + expiredate = sk->timestamp; /* key generatio may take long */ + sk->expiredate = pk->expiredate = expiredate; sk->pubkey_algo = pk->pubkey_algo = algo; pk->pkey[0] = mpi_copy( skey[0] ); pk->pkey[1] = mpi_copy( skey[1] ); @@ -266,7 +268,7 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, */ static int gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, u16 valid_days ) + STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expiredate ) { int rc; int i; @@ -289,7 +291,9 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, pk = m_alloc_clear( sizeof *pk ); sk->timestamp = pk->timestamp = make_timestamp(); sk->version = pk->version = 4; - sk->valid_days = pk->valid_days = valid_days; + if( expiredate && expiredate < pk->timestamp ) + expiredate = pk->timestamp; /* key generation may take long */ + sk->expiredate = pk->expiredate = expiredate; sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA; pk->pkey[0] = mpi_copy( skey[0] ); pk->pkey[1] = mpi_copy( skey[1] ); @@ -477,11 +481,12 @@ ask_keysize( int algo ) } -static int -ask_valid_days() +static u32 +ask_expiredate() { char *answer; int valid_days=0; + u32 expiredate = 0; tty_printf(_("Please specify how long the key should be valid.\n" " 0 = key does not expire\n" @@ -513,12 +518,14 @@ ask_valid_days() continue; } - if( !valid_days ) + if( !valid_days ) { tty_printf(_("Key does not expire at all\n")); + expiredate = 0; + } else { + expiredate = make_timestamp() + valid_days * 86400L; /* print the date when the key expires */ - tty_printf(_("Key expires at %s\n"), strtimestamp( - add_days_to_timestamp( make_timestamp(), valid_days ))); + tty_printf(_("Key expires at %s\n"), asctimestamp(expiredate) ); } if( !cpr_enabled() @@ -527,7 +534,7 @@ ask_valid_days() break; } m_free(answer); - return valid_days; + return expiredate; } @@ -713,7 +720,7 @@ ask_passphrase( STRING2KEY **ret_s2k ) static int do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, - DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, int valid_days, + DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, u32 expiredate, int v4_packet ) { int rc=0; @@ -726,11 +733,13 @@ do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, if( algo == PUBKEY_ALGO_ELGAMAL || algo == PUBKEY_ALGO_ELGAMAL_E ) rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k, - sk, valid_days, v4_packet? 4:3 ); + sk, expiredate, v4_packet? 4:3 ); else if( algo == PUBKEY_ALGO_DSA ) - rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, valid_days); + rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, expiredate); else BUG(); + + #ifdef ENABLE_COMMENT_PACKETS if( !rc ) { add_kbnode( pub_root, make_comment_node("#created by GNUPG v" VERSION " (" @@ -739,6 +748,7 @@ do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, make_comment_node("#created by GNUPG v" VERSION " (" PRINTABLE_OS_NAME ")")); } + #endif return rc; } @@ -781,7 +791,7 @@ generate_keypair() STRING2KEY *s2k; int rc; int algo; - int ndays; + u32 expiredate; int v4; int both = 0; @@ -797,7 +807,7 @@ generate_keypair() tty_printf(_("DSA keypair will have 1024 bits.\n")); } nbits = ask_keysize( algo ); - ndays = ask_valid_days(); + expiredate = ask_expiredate(); uid = ask_user_id(0); if( !uid ) { log_error(_("Key generation cancelled.\n")); @@ -824,10 +834,10 @@ generate_keypair() if( both ) rc = do_create( PUBKEY_ALGO_DSA, 1024, pub_root, sec_root, - dek, s2k, &sk, ndays, 1); + dek, s2k, &sk, expiredate, 1); else rc = do_create( algo, nbits, pub_root, sec_root, - dek, s2k, &sk, ndays, v4); + dek, s2k, &sk, expiredate, v4); if( !rc ) write_uid(pub_root, uid ); if( !rc ) @@ -839,7 +849,7 @@ generate_keypair() if( both ) { rc = do_create( algo, nbits, pub_root, sec_root, - dek, s2k, NULL, ndays, 1 ); + dek, s2k, NULL, expiredate, 1 ); if( !rc ) rc = write_keybinding(pub_root, pub_root, sk); if( !rc ) @@ -927,7 +937,8 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) int okay=0, rc=0; KBNODE node; PKT_secret_key *sk = NULL; /* this is the primary sk */ - int v4, algo, ndays; + int v4, algo; + u32 expiredate; unsigned nbits; char *passphrase = NULL; DEK *dek = NULL; @@ -964,7 +975,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) algo = ask_algo( &v4, 1 ); assert(algo); nbits = ask_keysize( algo ); - ndays = ask_valid_days(); + expiredate = ask_expiredate(); if( !cpr_enabled() && !cpr_get_answer_is_yes(N_("keygen.sub.okay"), _("Really create? ") ) ) goto leave; @@ -978,7 +989,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) } rc = do_create( algo, nbits, pub_keyblock, sec_keyblock, - dek, s2k, NULL, ndays, v4 ); + dek, s2k, NULL, expiredate, v4 ); if( !rc ) rc = write_keybinding(pub_keyblock, pub_keyblock, sk); if( !rc ) diff --git a/g10/keyid.c b/g10/keyid.c index 387c3fa9a..fa5b9237e 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -82,7 +82,12 @@ do_fingerprint_md( PKT_public_key *pk ) md_putc( md, a ); } if( pk->version < 4 ) { - u16 a = pk->valid_days; + u16 a; + + if( pk->expiredate ) + a = (u16)((pk->expiredate - pk->timestamp) / 86400L); + else + a = 0; md_putc( md, a >> 8 ); md_putc( md, a ); } @@ -108,7 +113,7 @@ do_fingerprint_md_sk( PKT_secret_key *sk ) pk.pubkey_algo = sk->pubkey_algo; pk.version = sk->version; pk.timestamp = sk->timestamp; - pk.valid_days = sk->valid_days; + pk.expiredate = sk->expiredate; pk.pubkey_algo = sk->pubkey_algo; for( i=0; i < npkey; i++ ) pk.pkey[i] = sk->skey[i]; @@ -303,9 +308,9 @@ expirestr_from_pk( PKT_public_key *pk ) struct tm *tp; time_t atime; - if( !pk->valid_days ) + if( !pk->expiredate ) return "never "; - atime = add_days_to_timestamp( pk->timestamp, pk->valid_days ); + atime = pk->expiredate; tp = gmtime( &atime ); sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday ); return buffer; @@ -318,9 +323,9 @@ expirestr_from_sk( PKT_secret_key *sk ) struct tm *tp; time_t atime; - if( !sk->valid_days ) + if( !sk->expiredate ) return "never "; - atime = add_days_to_timestamp( sk->timestamp, sk->valid_days ); + atime = sk->expiredate; tp = gmtime( &atime ); sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday ); return buffer; diff --git a/g10/keylist.c b/g10/keylist.c index 04d79b1ec..69e9b523b 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -74,7 +74,8 @@ list_all( int secret ) const char *s; IOBUF a; - while( (s=secret? get_secret_keyring(seq++):get_keyring(seq++)) ) { + /* FIXME: this assumes a keyring resource is a plain keyring file */ + while( (s = enum_keyblock_resources( &seq, secret )) ) { if( !(a = iobuf_open(s)) ) { log_error(_("can't open %s: %s\n"), s, strerror(errno)); continue; @@ -133,12 +134,12 @@ list_one( const char *name, int secret ) sk = node->pkt->pkt.secret_key; keyid_from_sk( sk, keyid ); if( opt.with_colons ) - printf("sec::%u:%d:%08lX%08lX:%s:%u:::", + printf("sec::%u:%d:%08lX%08lX:%s:%s:::", nbits_from_sk( sk ), sk->pubkey_algo, (ulong)keyid[0],(ulong)keyid[1], datestr_from_sk( sk ), - (unsigned)sk->valid_days + sk->expiredate? strtimestamp(sk->expiredate):"" /* fixme: add LID here */ ); else printf("sec %4u%c/%08lX %s ", nbits_from_sk( sk ), @@ -152,13 +153,14 @@ list_one( const char *name, int secret ) keyid_from_pk( pk, keyid ); if( opt.with_colons ) { trustletter = query_trust_info( pk ); - printf("pub:%c:%u:%d:%08lX%08lX:%s:%u:", + printf("pub:%c:%u:%d:%08lX%08lX:%s:%s:", trustletter, nbits_from_pk( pk ), pk->pubkey_algo, (ulong)keyid[0],(ulong)keyid[1], datestr_from_pk( pk ), - (unsigned)pk->valid_days ); + pk->expiredate? strtimestamp(pk->expiredate):"" + ); if( pk->local_id ) printf("%lu", pk->local_id ); putchar(':'); @@ -206,13 +208,13 @@ list_one( const char *name, int secret ) keyid_from_pk( pk2, keyid2 ); if( opt.with_colons ) { - printf("sub:%c:%u:%d:%08lX%08lX:%s:%u:", + printf("sub:%c:%u:%d:%08lX%08lX:%s:%s:", trustletter, nbits_from_pk( pk2 ), pk2->pubkey_algo, (ulong)keyid2[0],(ulong)keyid2[1], datestr_from_pk( pk2 ), - (unsigned)pk2->valid_days + pk2->expiredate? strtimestamp(pk2->expiredate):"" /* fixme: add LID and ownertrust here */ ); if( pk->local_id ) /* use the local_id of the main key??? */ @@ -242,12 +244,12 @@ list_one( const char *name, int secret ) keyid_from_sk( sk2, keyid2 ); if( opt.with_colons ) - printf("ssb::%u:%d:%08lX%08lX:%s:%u:::\n", + printf("ssb::%u:%d:%08lX%08lX:%s:%s:::\n", nbits_from_sk( sk2 ), sk2->pubkey_algo, (ulong)keyid2[0],(ulong)keyid2[1], datestr_from_sk( sk2 ), - (unsigned)sk2->valid_days + sk2->expiredate? strtimestamp(sk2->expiredate):"" /* fixme: add LID */ ); else diff --git a/g10/mainproc.c b/g10/mainproc.c index a47885b74..dd1546c6b 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -471,14 +471,14 @@ list_node( CTX c, KBNODE node ) c->local_id = pk->local_id; c->trustletter = query_trust_info( pk ); } - printf("%s:%c:%u:%d:%08lX%08lX:%s:%u:", + printf("%s:%c:%u:%d:%08lX%08lX:%s:%s:", mainkey? "pub":"sub", c->trustletter, nbits_from_pk( pk ), pk->pubkey_algo, (ulong)keyid[0],(ulong)keyid[1], datestr_from_pk( pk ), - (unsigned)pk->valid_days ); + pk->expiredate? strtimestamp(pk->expiredate):"" ); if( c->local_id ) printf("%lu", c->local_id ); putchar(':'); @@ -541,13 +541,13 @@ list_node( CTX c, KBNODE node ) if( opt.with_colons ) { u32 keyid[2]; keyid_from_sk( sk, keyid ); - printf("%s::%u:%d:%08lX%08lX:%s:%u:::", + printf("%s::%u:%d:%08lX%08lX:%s:%s:::", mainkey? "sec":"ssb", nbits_from_sk( sk ), sk->pubkey_algo, (ulong)keyid[0],(ulong)keyid[1], datestr_from_sk( sk ), - (unsigned)sk->valid_days + sk->expiredate? strtimestamp(sk->expiredate):"" /* fixme: add LID */ ); } else diff --git a/g10/options.h b/g10/options.h index d674ada12..ac7629631 100644 --- a/g10/options.h +++ b/g10/options.h @@ -20,6 +20,10 @@ #ifndef G10_OPTIONS_H #define G10_OPTIONS_H + +#undef ENABLE_COMMENT_PACKETS /* don't create comment packets */ + + struct { int verbose; unsigned debug; @@ -37,7 +41,7 @@ struct { int no_armor; int list_packets; /* list-packets mode */ int def_cipher_algo; - int do_not_export_rsa; + int reserved1; int def_digest_algo; int def_compress_algo; const char *def_secret_key; diff --git a/g10/packet.h b/g10/packet.h index 5bb383c86..4898027a2 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -111,7 +111,7 @@ typedef struct { */ typedef struct { u32 timestamp; /* key made */ - u16 valid_days; /* valid for this number of days */ + u32 expiredate; /* expires at this date or 0 if not at all */ byte hdrbytes; /* number of header bytes */ byte version; byte pubkey_algo; /* algorithm used for public key scheme */ @@ -124,7 +124,7 @@ typedef struct { typedef struct { u32 timestamp; /* key made */ - u16 valid_days; /* valid for this number of days */ + u32 expiredate; /* expires at this date or 0 if not at all */ byte hdrbytes; /* number of header bytes */ byte version; byte pubkey_algo; /* algorithm used for public key scheme */ diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 41afe5b9a..c17f2c5c9 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -917,8 +917,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, { int i, version, algorithm; unsigned n; - unsigned long timestamp; - unsigned short valid_period; + unsigned long timestamp, expiredate; int npkey, nskey; int is_v4=0; int rc=0; @@ -956,25 +955,30 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, timestamp = read_32(inp); pktlen -= 4; if( is_v4 ) - valid_period = 0; + expiredate = 0; /* have to get it from the selfsignature */ else { - valid_period = read_16(inp); pktlen -= 2; + unsigned short ndays; + ndays = read_16(inp); pktlen -= 2; + if( ndays ) + expiredate = timestamp + ndays * 86400L; + else + expiredate = 0; } algorithm = iobuf_get_noeof(inp); pktlen--; if( list_mode ) printf(":%s key packet:\n" - "\tversion %d, algo %d, created %lu, valid for %hu days\n", + "\tversion %d, algo %d, created %lu, expires %lu\n", pkttype == PKT_PUBLIC_KEY? "public" : pkttype == PKT_SECRET_KEY? "secret" : pkttype == PKT_PUBLIC_SUBKEY? "public sub" : pkttype == PKT_SECRET_SUBKEY? "secret sub" : "??", - version, algorithm, timestamp, valid_period ); + version, algorithm, timestamp, expiredate ); if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) { PKT_secret_key *sk = pkt->pkt.secret_key; sk->timestamp = timestamp; - sk->valid_days = valid_period; + sk->expiredate = expiredate; sk->hdrbytes = hdrlen; sk->version = version; sk->pubkey_algo = algorithm; @@ -984,7 +988,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, PKT_public_key *pk = pkt->pkt.public_key; pk->timestamp = timestamp; - pk->valid_days = valid_period; + pk->expiredate = expiredate; pk->hdrbytes = hdrlen; pk->version = version; pk->pubkey_algo = algorithm; diff --git a/g10/ringedit.c b/g10/ringedit.c index 677420e25..6b6f6c855 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -48,6 +48,7 @@ #include <errno.h> #include <sys/types.h> #include <sys/stat.h> +#include <unistd.h> /* for truncate */ #include <assert.h> #include "util.h" #include "packet.h" @@ -55,8 +56,8 @@ #include "mpi.h" #include "iobuf.h" #include "keydb.h" +#include "options.h" #include "i18n.h" -#include <unistd.h> /* for truncate */ struct resource_table_struct { @@ -97,29 +98,75 @@ check_pos( KBPOS *kbpos ) ****************************************************************/ /**************** + * Get the name of the keyrings, start with a sequence number pointing to a 0. + */ +const char * +enum_keyblock_resources( int *sequence, int secret ) +{ + int i = *sequence; + const char *name = NULL; + + for(; i < MAX_RESOURCES; i++ ) + if( resource_table[i].used && !resource_table[i].secret == !secret ) { + if( resource_table[i].fname ) { + name = resource_table[i].fname; + break; + } + } + *sequence = ++i; + return NULL; /* not found */ +} + + + +/**************** * Register a resource (which currently may only be a keyring file). + * The first keyring which is added by this function is + * created if it does not exist. + * Note: this function may be called before secure memory is + * available. */ int -add_keyblock_resource( const char *filename, int force, int secret ) +add_keyblock_resource( const char *resname, int force, int secret ) { + static int any_secret, any_public; IOBUF iobuf; - int i; + int i, force; + char *filename; + int rc = 0; + + if( *resname != '/' ) { /* do tilde expansion etc */ + if( strchr(resname, '/') ) + filename = make_filename(resname, NULL); + else + filename = make_filename(opt.homedir, resname, NULL); + } + else + filename = m_strdup( resname ); + + if( !force ) + force = secret? !any_secret : !any_public; for(i=0; i < MAX_RESOURCES; i++ ) if( !resource_table[i].used ) break; - if( i == MAX_RESOURCES ) - return G10ERR_RESOURCE_LIMIT; + if( i == MAX_RESOURCES ) { + rc = G10ERR_RESOURCE_LIMIT; + goto leave; + } - iobuf = iobuf_open( filename ); - if( !iobuf && !force ) - return G10ERR_OPEN_FILE; + iobuf = iobuf_fopen( filename, "rb" ); + if( !iobuf && !force ) { + rc = G10ERR_OPEN_FILE; + goto leave; + } if( !iobuf ) { iobuf = iobuf_create( filename ); if( !iobuf ) { log_error("%s: can't create: %s\n", filename, strerror(errno)); - return G10ERR_OPEN_FILE; + rc = G10ERR_OPEN_FILE; + goto leave; } else log_info("%s: keyring created\n", filename ); @@ -135,7 +182,15 @@ add_keyblock_resource( const char *filename, int force, int secret ) resource_table[i].secret = !!secret; resource_table[i].fname = m_strdup(filename); resource_table[i].iobuf = iobuf; - return 0; + leave: + if( rc ) + log_error("keyblock resource '%s': %s\n", filename, g10_errstr(rc) ); + else if( secret ) + any_secret = 1; + else + any_public = 1; + m_free( filename ); + return rc; } /**************** @@ -362,7 +417,7 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root ) return -1; /* no resources */ kbpos->resno = i; rentry = check_pos( kbpos ); - kbpos->fp = iobuf_open( rentry->fname ); + kbpos->fp = iobuf_fopen( rentry->fname, "rb" ); if( !kbpos->fp ) { log_error("can't open '%s'\n", rentry->fname ); return G10ERR_OPEN_FILE; @@ -528,7 +583,6 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) PKT_secret_key *sk = pkt.pkt.secret_key; if( req_sk->timestamp == sk->timestamp - && req_sk->valid_days == sk->valid_days && req_sk->pubkey_algo == sk->pubkey_algo && !cmp_seckey( req_sk, sk) ) break; /* found */ @@ -537,7 +591,6 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) PKT_public_key *pk = pkt.pkt.public_key; if( req_pk->timestamp == pk->timestamp - && req_pk->valid_days == pk->valid_days && req_pk->pubkey_algo == pk->pubkey_algo && !cmp_pubkey( req_pk, pk ) ) break; /* found */ @@ -572,7 +625,7 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root ) if( !(rentry=check_pos(kbpos)) ) return G10ERR_GENERAL; - a = iobuf_open( rentry->fname ); + a = iobuf_fopen( rentry->fname, "rb" ); if( !a ) { log_error("can't open '%s'\n", rentry->fname ); return G10ERR_OPEN_FILE; @@ -732,7 +785,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root ) BUG(); /* not allowed with such a handle */ /* open the source file */ - fp = iobuf_open( rentry->fname ); + fp = iobuf_fopen( rentry->fname, "rb" ); if( mode == 1 && !fp && errno == ENOENT ) { /* no file yet */ KBNODE kbctx, node; diff --git a/g10/sig-check.c b/g10/sig-check.c index b983bb42c..fd476f767 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -166,11 +166,9 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest ) return G10ERR_TIME_CONFLICT; } - if( pk->valid_days && add_days_to_timestamp(pk->timestamp, - pk->valid_days) < cur_time ) { - log_info(_("warning: signature key expired %s\n"), strtimestamp( - add_days_to_timestamp(pk->timestamp, - pk->valid_days))); + if( pk->expiredate && pk->expiredate < cur_time ) { + log_info(_("warning: signature key expired %s\n"), + asctimestamp( pk->expiredate ) ); write_status(STATUS_SIGEXPIRED); } diff --git a/g10/sign.c b/g10/sign.c index 349b2f34d..304843f59 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -225,12 +225,14 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, if( opt.armor && !outfile ) iobuf_push_filter( out, armor_filter, &afx ); + #ifdef ENABLE_COMMENT_PACKETS else { write_comment( out, "#created by GNUPG v" VERSION " (" PRINTABLE_OS_NAME ")"); if( opt.comment_string ) write_comment( out, opt.comment_string ); } + #endif if( encrypt ) { efx.pk_list = pk_list; /* fixme: set efx.cfx.datalen if known */ diff --git a/g10/tdbio.c b/g10/tdbio.c index 82b22b43a..425919338 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -39,6 +39,27 @@ #include "trustdb.h" #include "tdbio.h" + +/**************** + * Yes, this is a very simple implementation. We should really + * use a page aligned buffer and read complete pages. + * To implement a simple trannsaction system, this is sufficient. + */ +typedef struct cache_ctrl_struct *CACHE_CTRL; +struct cache_ctrl_struct { + CACHE_CTRL next; + struct { + unsigned used:1; + unsigned dirty:1; + } flags; + ulong recno; + char data[TRUST_RECORD_LEN]; +}; + +#define MAX_CACHE_ENTRIES 200 +static CACHE_CTRL cache_list; +static int cache_entries; + /* a type used to pass infomation to cmp_krec_fpr */ struct cmp_krec_fpr_struct { int pubkey_algo; @@ -59,6 +80,184 @@ static int db_fd = -1; static void open_db(void); + +/************************************* + ************* record cache ********** + *************************************/ + +/**************** + * Get the data from therecord cache and return a + * pointer into that cache. Caller should copy + * the return data. NULL is returned on a cache miss. + */ +static const char * +get_record_from_cache( ulong recno ) +{ + CACHE_CTRL r; + + for( r = cache_list; r; r = r->next ) { + if( r->flags.used && r->recno == recno ) + return r->data; + } + return NULL; +} + + +static int +write_cache_item( CACHE_CTRL r ) +{ + int n; + + if( lseek( db_fd, r->recno * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { + log_error(_("trustdb rec %lu: lseek failed: %s\n"), + r->recno, strerror(errno) ); + return G10ERR_WRITE_FILE; + } + n = write( db_fd, r->data, TRUST_RECORD_LEN); + if( n != TRUST_RECORD_LEN ) { + log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"), + r->recno, n, strerror(errno) ); + return G10ERR_WRITE_FILE; + } + r->flags.dirty = 0; + return 0; +} + +/**************** + * Put data into the cache. This function may flush the + * some cache entries if there is not enough space available. + */ +int +put_record_into_cache( ulong recno, const char *data ) +{ + CACHE_CTRL r, unused; + int dirty_count = 0; + int clean_count = 0; + + /* see whether we already cached this one */ + for( unused = NULL, r = cache_list; r; r = r->next ) { + if( !r->flags.used ) { + if( !unused ) + unused = r; + } + else if( r->recno == recno ) { + if( !r->flags.dirty ) { + /* Hmmm: should we use a a copy and compare? */ + if( memcmp(r->data, data, TRUST_RECORD_LEN ) ) + r->flags.dirty = 1; + } + memcpy( r->data, data, TRUST_RECORD_LEN ); + return 0; + } + if( r->flags.used ) { + if( r->flags.dirty ) + dirty_count++; + else + clean_count++; + } + } + /* not in the cache: add a new entry */ + if( unused ) { /* reuse this entry */ + r = unused; + r->flags.used = 1; + r->recno = recno; + memcpy( r->data, data, TRUST_RECORD_LEN ); + r->flags.dirty = 1; + cache_entries++; + return 0; + } + /* see whether we reached the limit */ + if( cache_entries < MAX_CACHE_ENTRIES ) { /* no */ + r = m_alloc( sizeof *r ); + r->flags.used = 1; + r->recno = recno; + memcpy( r->data, data, TRUST_RECORD_LEN ); + r->flags.dirty = 1; + r->next = cache_list; + cache_list = r; + cache_entries++; + return 0; + } + /* cache is full: discard some clean entries */ + if( clean_count ) { + int n = clean_count / 3; /* discard a third of the clean entries */ + if( !n ) + n = 1; + for( unused = NULL, r = cache_list; r; r = r->next ) { + if( r->flags.used && !r->flags.dirty ) { + if( !unused ) + unused = r; + r->flags.used = 0; + cache_entries--; + if( !--n ) + break; + } + } + assert( unused ); + r = unused; + r->flags.used = 1; + r->recno = recno; + memcpy( r->data, data, TRUST_RECORD_LEN ); + r->flags.dirty = 1; + cache_entries++; + return 0; + } + /* no clean entries: have to flush some dirty entries */ + if( dirty_count ) { + int n = dirty_count / 5; /* discard some dirty entries */ + if( !n ) + n = 1; + for( unused = NULL, r = cache_list; r; r = r->next ) { + if( r->flags.used && r->flags.dirty ) { + int rc = write_cache_item( r ); + if( rc ) + return rc; + if( !unused ) + unused = r; + r->flags.used = 0; + cache_entries--; + if( !--n ) + break; + } + } + assert( unused ); + r = unused; + r->flags.used = 1; + r->recno = recno; + memcpy( r->data, data, TRUST_RECORD_LEN ); + r->flags.dirty = 1; + cache_entries++; + return 0; + } + BUG(); +} + + + +/**************** + * Sync the cache to disk + */ + +int +tdbio_sync() +{ + CACHE_CTRL r; + + for( r = cache_list; r; r = r->next ) { + if( r->flags.used && r->flags.dirty ) { + int rc = write_cache_item( r ); + if( rc ) + return rc; + } + } + return 0; +} + + + +/******************************************************** + **************** cached I/O functions ****************** + ********************************************************/ int tdbio_set_dbname( const char *new_dbname, int create ) @@ -118,6 +317,8 @@ tdbio_set_dbname( const char *new_dbname, int create ) rec.rectype = RECTYPE_VER; rec.recnum = 0; rc = tdbio_write_record( &rec ); + if( !rc ) + tdbio_sync(); if( rc ) log_fatal_f( fname, _("failed to create version record: %s"), g10_errstr(rc)); @@ -185,7 +386,7 @@ create_hashtable( TRUSTREC *vr, int type ) n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD; for(i=0; i < n; i++, recnum++ ) { memset( &rec, 0, sizeof rec ); - rec.rectype = RECTYPE_HTBL; /* free record */ + rec.rectype = RECTYPE_HTBL; rec.recnum = recnum; rc = tdbio_write_record( &rec ); if( rc ) @@ -194,6 +395,8 @@ create_hashtable( TRUSTREC *vr, int type ) } /* update the version record */ rc = tdbio_write_record( vr ); + if( !rc ) + rc = tdbio_sync(); if( rc ) log_fatal_f( db_name, _("error updating version record: %s\n"), g10_errstr(rc)); @@ -208,21 +411,21 @@ static ulong get_keyhashrec() { static ulong keyhashtbl; /* record number of the key hashtable */ - TRUSTREC vr; - int rc; - if( keyhashtbl ) - return keyhashtbl; - - rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); - if( rc ) - log_fatal_f( db_name, _("error reading version record: %s\n"), - g10_errstr(rc) ); - if( !vr.r.ver.keyhashtbl ) - create_hashtable( &vr, 0 ); + if( !keyhashtbl ) { + TRUSTREC vr; + int rc; + rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); + if( rc ) + log_fatal_f( db_name, _("error reading version record: %s\n"), + g10_errstr(rc) ); + if( !vr.r.ver.keyhashtbl ) + create_hashtable( &vr, 0 ); - return vr.r.ver.keyhashtbl; + keyhashtbl = vr.r.ver.keyhashtbl; + } + return keyhashtbl; } /**************** @@ -233,20 +436,21 @@ static ulong get_sdirhashrec() { static ulong sdirhashtbl; /* record number of the hashtable */ - TRUSTREC vr; - int rc; - if( sdirhashtbl ) - return sdirhashtbl; + if( !sdirhashtbl ) { + TRUSTREC vr; + int rc; - rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); - if( rc ) - log_fatal_f( db_name, _("error reading version record: %s\n"), - g10_errstr(rc) ); - if( !vr.r.ver.sdirhashtbl ) - create_hashtable( &vr, 1 ); + rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); + if( rc ) + log_fatal_f( db_name, _("error reading version record: %s\n"), + g10_errstr(rc) ); + if( !vr.r.ver.sdirhashtbl ) + create_hashtable( &vr, 1 ); - return vr.r.ver.sdirhashtbl; + sdirhashtbl = vr.r.ver.sdirhashtbl; + } + return sdirhashtbl; } @@ -289,15 +493,16 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) lastrec = rec; rc = tdbio_read_record( item, &rec, 0 ); if( rc ) { - log_error( db_name, "upd_hashtable: read item failed: %s\n", + log_error( "upd_hashtable: read item failed: %s\n", g10_errstr(rc) ); return rc; } + if( rec.rectype == RECTYPE_HTBL ) { hashrec = item; level++; if( level >= keylen ) { - log_error( db_name, "hashtable has invalid indirections.\n"); + log_error( "hashtable has invalid indirections.\n"); return G10ERR_TRUSTDB; } goto next_level; @@ -314,8 +519,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_read_record( rec.r.hlst.next, &rec, RECTYPE_HLST); if( rc ) { - log_error( db_name, - "scan keyhashtbl read hlst failed: %s\n", + log_error( "scan keyhashtbl read hlst failed: %s\n", g10_errstr(rc) ); return rc; } @@ -330,8 +534,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rec.r.hlst.rnum[i] = newrecnum; rc = tdbio_write_record( &rec ); if( rc ) - log_error( db_name, - "upd_hashtable: write hlst failed: %s\n", + log_error( "upd_hashtable: write hlst failed: %s\n", g10_errstr(rc) ); return rc; /* done */ } @@ -340,8 +543,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_read_record( rec.r.hlst.next, &rec, RECTYPE_HLST ); if( rc ) { - log_error( db_name, - "upd_hashtable: read hlst failed: %s\n", + log_error( "upd_hashtable: read hlst failed: %s\n", g10_errstr(rc) ); return rc; } @@ -350,8 +552,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rec.r.hlst.next = item = tdbio_new_recnum(); rc = tdbio_write_record( &rec ); if( rc ) { - log_error( db_name, - "upd_hashtable: write hlst failed: %s\n", + log_error( "upd_hashtable: write hlst failed: %s\n", g10_errstr(rc) ); return rc; } @@ -361,14 +562,14 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rec.r.hlst.rnum[0] = newrecnum; rc = tdbio_write_record( &rec ); if( rc ) - log_error( db_name, - "upd_hashtable: write ext hlst failed: %s\n", + log_error( "upd_hashtable: write ext hlst failed: %s\n", g10_errstr(rc) ); return rc; /* done */ } } /* end loop over hlst slots */ } else if( rec.rectype == RECTYPE_KEY + || rec.rectype == RECTYPE_DIR || rec.rectype == RECTYPE_SDIR ) { /* insert a list record */ if( rec.recnum == newrecnum ) { return 0; @@ -381,8 +582,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rec.r.hlst.rnum[1] = newrecnum; /* and new one */ rc = tdbio_write_record( &rec ); if( rc ) { - log_error( db_name, - "upd_hashtable: write new hlst failed: %s\n", + log_error( "upd_hashtable: write new hlst failed: %s\n", g10_errstr(rc) ); return rc; } @@ -390,12 +590,12 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum; rc = tdbio_write_record( &lastrec ); if( rc ) - log_error( db_name, "upd_hashtable: update htbl failed: %s\n", + log_error( "upd_hashtable: update htbl failed: %s\n", g10_errstr(rc) ); return rc; /* ready */ } else { - log_error( db_name, "hashtbl %lu points to an invalid record\n", + log_error( "hashtbl %lu points to an invalid record\n", item); return G10ERR_TRUSTDB; } @@ -637,23 +837,29 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp ) int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) { - byte buf[TRUST_RECORD_LEN], *p; + byte readbuf[TRUST_RECORD_LEN]; + const byte *buf, *p; int rc = 0; int n, i; if( db_fd == -1 ) open_db(); - if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { - log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) ); - return G10ERR_READ_FILE; - } - n = read( db_fd, buf, TRUST_RECORD_LEN); - if( !n ) { - return -1; /* eof */ - } - else if( n != TRUST_RECORD_LEN ) { - log_error(_("trustdb: read failed (n=%d): %s\n"), n, strerror(errno) ); - return G10ERR_READ_FILE; + buf = get_record_from_cache( recnum ); + if( !buf ) { + if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { + log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) ); + return G10ERR_READ_FILE; + } + n = read( db_fd, readbuf, TRUST_RECORD_LEN); + if( !n ) { + return -1; /* eof */ + } + else if( n != TRUST_RECORD_LEN ) { + log_error(_("trustdb: read failed (n=%d): %s\n"), n, + strerror(errno) ); + return G10ERR_READ_FILE; + } + buf = readbuf; } rec->recnum = recnum; rec->dirty = 0; @@ -791,14 +997,12 @@ tdbio_write_record( TRUSTREC *rec ) { byte buf[TRUST_RECORD_LEN], *p; int rc = 0; - int i, n; + int i; ulong recnum = rec->recnum; if( db_fd == -1 ) open_db(); -tdbio_dump_record( rec, stdout ); - memset(buf, 0, TRUST_RECORD_LEN); p = buf; *p++ = rec->rectype; p++; @@ -900,16 +1104,10 @@ tdbio_dump_record( rec, stdout ); BUG(); } - if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { - log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) ); - return G10ERR_WRITE_FILE; - } - n = write( db_fd, buf, TRUST_RECORD_LEN); - if( n != TRUST_RECORD_LEN ) { - log_error(_("trustdb: write failed (n=%d): %s\n"), n, strerror(errno) ); - return G10ERR_WRITE_FILE; - } - else if( rec->rectype == RECTYPE_KEY ) + rc = put_record_into_cache( recnum, buf ); + if( rc ) + ; + if( rec->rectype == RECTYPE_KEY ) rc = update_keyhashtbl( rec ); else if( rec->rectype == RECTYPE_SDIR ) rc = update_sdirhashtbl( rec ); @@ -990,7 +1188,21 @@ tdbio_new_recnum() memset( &rec, 0, sizeof rec ); rec.rectype = 0; /* unused record */ rec.recnum = recnum; - rc = tdbio_write_record( &rec ); + rc = 0; + if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { + log_error(_("trustdb rec %lu: lseek failed: %s\n"), + recnum, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + } + else { + int n = write( db_fd, &rec, TRUST_RECORD_LEN); + if( n != TRUST_RECORD_LEN ) { + log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"), + recnum, n, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + } + } + if( rc ) log_fatal_f(db_name,_("failed to append a record: %s\n"), g10_errstr(rc)); diff --git a/g10/tdbio.h b/g10/tdbio.h index 66579ad14..42bb4aa48 100644 --- a/g10/tdbio.h +++ b/g10/tdbio.h @@ -166,6 +166,7 @@ const char *tdbio_get_dbname(void); void tdbio_dump_record( TRUSTREC *rec, FILE *fp ); int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ); int tdbio_write_record( TRUSTREC *rec ); +int tdbio_sync(void); int tdbio_delete_record( ulong recnum ); ulong tdbio_new_recnum(void); int tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec ); diff --git a/g10/textfilter.c b/g10/textfilter.c index 804b48505..fc81a9136 100644 --- a/g10/textfilter.c +++ b/g10/textfilter.c @@ -48,7 +48,7 @@ read_line( byte *buf, size_t *r_buflen, IOBUF a ) assert(buflen >= 20 ); buflen -= 3; /* leave some room for CR,LF and one extra */ - for(c=0, n=0; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; ) + for(c=0, n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; ) buf[n++] = c; buf[n] = 0; if( c == -1 ) { @@ -58,7 +58,7 @@ read_line( byte *buf, size_t *r_buflen, IOBUF a ) } else if( c != '\n' ) { IOBUF b = iobuf_temp(); - while( (c=iobuf_get2(a)) != -1 && c != '\n' ) { + while( (c=iobuf_get(a)) != -1 && c != '\n' ) { iobuf_put(b,c); if( c != ' ' && c != '\t' && c != '\r' ) break; diff --git a/g10/trustdb.c b/g10/trustdb.c index 18726f151..eb6ea3ca6 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -71,11 +71,6 @@ struct trust_seg_list { }; -typedef struct { - TRUST_SEG_LIST tsl; - int index; -} ENUM_TRUST_WEB_CONTEXT; - struct recno_list_struct { struct recno_list_struct *next; @@ -171,6 +166,19 @@ delete_record( ulong recno ) die_invalid_db(); } +/**************** + * sync the db + */ +static void +do_sync( ) +{ + int rc = tdbio_sync(); + if( !rc ) + return; + log_error("trust db: sync failed: %s\n", g10_errstr(rc) ); + g10_exit(2); +} + /********************************************** @@ -425,15 +433,15 @@ verify_own_keys() memset( pk, 0, sizeof *pk ); rc = get_pubkey( pk, keyid ); if( rc ) { - log_error(_("key %08lX: secret key without public key\n"), + log_info(_("key %08lX: secret key without public key - skipped\n"), (ulong)keyid[1] ); - goto leave; + goto skip; } + if( cmp_public_secret_key( pk, sk ) ) { - log_error(_("key %08lX: secret and public key don't match\n"), + log_info(_("key %08lX: secret and public key don't match\n"), (ulong)keyid[1] ); - rc = G10ERR_GENERAL; - goto leave; + goto skip; } /* make sure that the pubkey is in the trustdb */ @@ -443,12 +451,12 @@ verify_own_keys() if( rc ) { log_error(_("key %08lX: can't put it into the trustdb\n"), (ulong)keyid[1] ); - goto leave; + goto skip; } } else if( rc ) { log_error(_("key %08lX: query record failed\n"), (ulong)keyid[1] ); - goto leave; + goto skip; } @@ -456,9 +464,12 @@ verify_own_keys() log_debug("key %08lX.%lu: stored into ultikey_table\n", (ulong)keyid[1], pk->local_id ); if( ins_lid_table_item( ultikey_table, pk->local_id, 0 ) ) - log_error(_("key %08lX: already in ultikey_table\n"), + log_error(_("key %08lX: already in secret key table\n"), (ulong)keyid[1]); - + else if( opt.verbose ) + log_info(_("key %08lX: accepted as secret key.\n"), + (ulong)keyid[1]); + skip: release_secret_key_parts( sk ); release_public_key_parts( pk ); } @@ -467,7 +478,6 @@ verify_own_keys() else rc = 0; - leave: enum_secret_keys( &enum_context, NULL, 0 ); /* free context */ free_secret_key( sk ); free_public_key( pk ); @@ -695,6 +705,13 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth, TRUST_SEG_LIST tsl, t2, tl; int i; + if( !(sx.sig_flag & SIGF_CHECKED) ) + continue; /* only checked sigs */ + if( !(sx.sig_flag & SIGF_VALID) ) + continue; /* and, of course, only valid sigs */ + if( (sx.sig_flag & SIGF_REVOKED) ) + continue; /* and skip revoked sigs */ + stack[depth].lid = sx.sig_lid; stack[depth].trust = 0; if( qry_lid_table_flag( lids, sx.sig_lid, &last_depth) ) { @@ -782,8 +799,13 @@ make_tsl( ulong lid, TRUST_SEG_LIST *ret_tslist ) release_lid_table(work); *ret_tslist = tslist; } - else - ; /* FIXME: release tslist */ + else { /* error: release tslist */ + while( tslist ) { + tsl = tslist->next; + m_free(tslist); + tslist = tsl; + } + } release_lid_table(lids); return rc; } @@ -865,7 +887,7 @@ do_check( TRUSTREC *dr, unsigned *trustlevel ) if( dr->r.dir.dirflags & DIRF_REVOKED ) tflags |= TRUST_FLAG_REVOKED; - #if 0 + #if 0 /* Do we still need this?? */ if( !rc && !dr->r.dir.siglist ) { /* We do not have any signatures; check whether it is one of our * secret keys */ @@ -1153,6 +1175,7 @@ import_ownertrust( const char *fname ) log_error_f(fname, _("read error: %s\n"), strerror(errno) ); if( !is_stdin ) fclose(fp); + do_sync(); } @@ -1247,8 +1270,6 @@ list_trust_path( int max_depth, const char *username ) /**************** * Check the complete trustdb or only the entries for the given username. - * Special hack: A username "REBUILD" inserts all records from the public - * key rings into the trustdb. */ void check_trustdb( const char *username ) @@ -1257,9 +1278,8 @@ check_trustdb( const char *username ) KBNODE keyblock = NULL; KBPOS kbpos; int rc; - int rebuild = username && !strcmp(username, "REBUILD"); - if( username && !rebuild ) { + if( username ) { rc = find_keyblock_byname( &kbpos, username ); if( !rc ) rc = read_keyblock( &kbpos, &keyblock ); @@ -1315,43 +1335,48 @@ check_trustdb( const char *username ) release_kbnode( keyblock ); keyblock = NULL; } } - if( rebuild ) { - log_info("adding new entries.\n"); - - rc = enum_keyblocks( 0, &kbpos, &keyblock ); - if( !rc ) { - while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) { - rc = update_trust_record( keyblock ); - if( rc == -1 ) { /* not yet in trustdb: insert */ - PKT_public_key *pk = - find_kbnode( keyblock, PKT_PUBLIC_KEY - ) ->pkt->pkt.public_key; - rc = insert_trust_record( pk ); - if( rc && !pk->local_id ) - log_error("lid ?: insert failed: %s\n", - g10_errstr(rc) ); - else if( rc ) - log_error("lid %lu: insert failed: %s\n", - pk->local_id, g10_errstr(rc) ); - else - log_info("lid %lu: inserted\n", pk->local_id ); - } - else if( rc ) - log_error("lid %lu: update failed: %s\n", - lid_from_keyblock(keyblock), g10_errstr(rc) ); - else - log_info("lid %lu: updated\n", - lid_from_keyblock(keyblock) ); - } - } - if( rc && rc != -1 ) - log_error("enum_keyblocks failed: %s\n", g10_errstr(rc)); + } +} - enum_keyblocks( 2, &kbpos, &keyblock ); /* close */ - release_kbnode( keyblock ); - } +void +update_trustdb( ) +{ + KBNODE keyblock = NULL; + KBPOS kbpos; + int rc; + + rc = enum_keyblocks( 0, &kbpos, &keyblock ); + if( !rc ) { + while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) { + rc = update_trust_record( keyblock ); + if( rc == -1 ) { /* not yet in trustdb: insert */ + PKT_public_key *pk = + find_kbnode( keyblock, PKT_PUBLIC_KEY + ) ->pkt->pkt.public_key; + rc = insert_trust_record( pk ); + if( rc && !pk->local_id ) + log_error("lid ?: insert failed: %s\n", + g10_errstr(rc) ); + else if( rc ) + log_error("lid %lu: insert failed: %s\n", + pk->local_id, g10_errstr(rc) ); + else + log_info("lid %lu: inserted\n", pk->local_id ); + } + else if( rc ) + log_error("lid %lu: update failed: %s\n", + lid_from_keyblock(keyblock), g10_errstr(rc) ); + else + log_info("lid %lu: updated\n", + lid_from_keyblock(keyblock) ); + } } + if( rc && rc != -1 ) + log_error("enum_keyblocks failed: %s\n", g10_errstr(rc)); + + enum_keyblocks( 2, &kbpos, &keyblock ); /* close */ + release_kbnode( keyblock ); } @@ -1418,12 +1443,10 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel ) return G10ERR_TIME_CONFLICT; } - if( pk->valid_days && add_days_to_timestamp(pk->timestamp, - pk->valid_days) < cur_time ) { + if( pk->expiredate && pk->expiredate <= cur_time ) { log_info(_("key %08lX.%lu: expired at %s\n"), (ulong)keyid[1], pk->local_id, - asctimestamp( add_days_to_timestamp(pk->timestamp, - pk->valid_days))); + asctimestamp( pk->expiredate) ); trustlevel = TRUST_EXPIRED; } else { @@ -1485,7 +1508,10 @@ query_trust_info( PKT_public_key *pk ) int enum_trust_web( void **context, ulong *lid ) { - ENUM_TRUST_WEB_CONTEXT *c = *context; + struct { + TRUST_SEG_LIST tsl; + int index; + } *c = *context; if( !c ) { /* make a new context */ c = m_alloc_clear( sizeof *c ); @@ -1652,7 +1678,7 @@ query_trust_record( PKT_public_key *pk ) return get_dir_record( pk, &rec ); } - +/* FIXME: Brauchen wir das?? */ int clear_trust_checked_flag( PKT_public_key *pk ) { @@ -1669,6 +1695,7 @@ clear_trust_checked_flag( PKT_public_key *pk ) /* reset the flag */ rec.r.dir.dirflags &= ~DIRF_CHECKED; write_record( &rec ); + do_sync(); return 0; } @@ -1684,6 +1711,8 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash, byte uhash[20]; int is_selfsig; PKT_signature *sigpkt = NULL; + TRUSTREC tmp; + u32 sigkid[2]; if( sigrec->r.sig.sig[sigidx].flag & SIGF_CHECKED ) log_info(_("note: sig rec %lu[%d] in hintlist " @@ -1694,6 +1723,23 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash, "of %lu but not marked\n"), sigrec->recnum, sigidx, hint_owner ); + read_record( sigrec->r.sig.sig[sigidx].lid, &tmp, 0 ); + if( tmp.rectype != RECTYPE_DIR ) { + /* we need the dir record */ + log_error(_("sig rec %lu[%d] in hintlist " + "of %u does not point to a dir record\n"), + sigrec->recnum, sigidx, hint_owner ); + return; + } + if( !tmp.r.dir.keylist ) { + log_error(_("lid %lu: no primary key\n"), tmp.r.dir.lid ); + return; + } + read_record(tmp.r.dir.keylist, &tmp, RECTYPE_KEY ); + keyid_from_fingerprint( tmp.r.key.fingerprint, + tmp.r.key.fingerprint_len, sigkid ); + + /* find the correct signature packet */ for( node=keyblock; node; node = node->next ) { if( node->pkt->pkttype == PKT_USER_ID ) { @@ -1707,8 +1753,8 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash, } else if( state && node->pkt->pkttype == PKT_SIGNATURE ) { sigpkt = node->pkt->pkt.signature; - if( sigpkt->keyid[0] == keyid[0] - && sigpkt->keyid[1] == keyid[1] + if( sigpkt->keyid[0] == sigkid[0] + && sigpkt->keyid[1] == sigkid[1] && (sigpkt->sig_class&~3) == 0x10 ) break; /* found */ } @@ -1723,23 +1769,28 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash, rc = check_key_signature( keyblock, node, &is_selfsig ); if( is_selfsig ) { log_error(_("lid %lu: self-signature in hintlist\n"), lid ); - return ; + return; } if( !rc ) { /* valid signature */ + if( opt.verbose ) + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "good signature (3)\n"), + (ulong)keyid[1], lid, uhash[18], uhash[19], + (ulong)sigpkt->keyid[1] ); sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED | SIGF_VALID; } else if( rc == G10ERR_NO_PUBKEY ) { - log_info(_("key %08lX.%lu, uid %02X%02X: " - "very strange: no public key for signature %08lX\n"), + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "very strange: no public key\n"), (ulong)keyid[1], lid, uhash[18], uhash[19], (ulong)sigpkt->keyid[1] ); sigrec->r.sig.sig[sigidx].flag = SIGF_NOPUBKEY; } else { - log_info(_("key %08lX.%lu, uid %02X%02X: " + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " "invalid signature: %s\n"), - (ulong)keyid[1], lid, - uhash[18], uhash[19], g10_errstr(rc)); + (ulong)keyid[1], lid, uhash[18], uhash[19], + (ulong)sigpkt->keyid[1], g10_errstr(rc) ); sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED; } sigrec->dirty = 1; @@ -1930,7 +1981,7 @@ upd_uid_record( PKT_user_id *uid, TRUSTREC *drec, RECNO_LIST *recno_list, static void upd_pref_record( PKT_signature *sig, TRUSTREC *drec, - u32 *keyid, ulong *uidrecno, byte *uidhash ) + u32 *keyid, TRUSTREC *urec, byte *uidhash ) { static struct { sigsubpkttype_t subpkttype; @@ -1941,7 +1992,7 @@ upd_pref_record( PKT_signature *sig, TRUSTREC *drec, { SIGSUBPKT_PREF_COMPR, PREFTYPE_COMPR }, { 0, 0 } }; - TRUSTREC urec, prec; + TRUSTREC prec; const byte *s; size_t n; int k, i; @@ -1949,13 +2000,10 @@ upd_pref_record( PKT_signature *sig, TRUSTREC *drec, int recno_idx = 0; ulong recno; - /* we need the uid record */ - read_record( *uidrecno, &urec, RECTYPE_UID ); - /* First delete all pref records * This is much simpler than checking whether we have to * do update the record at all - the record cache may care about it */ - for( recno=urec.r.uid.prefrec; recno; recno = prec.r.pref.next ) { + for( recno=urec->r.uid.prefrec; recno; recno = prec.r.pref.next ) { read_record( recno, &prec, RECTYPE_PREF ); delete_record( recno ); } @@ -1999,8 +2047,8 @@ upd_pref_record( PKT_signature *sig, TRUSTREC *drec, write_record( &prec ); } /* don't need to write the last one, but update the uid */ - urec.r.uid.prefrec = recno_idx? recno_tbl[0] : 0; - write_record( &urec ); + urec->r.uid.prefrec = recno_idx? recno_tbl[0] : 0; + urec->dirty = 1; } @@ -2014,25 +2062,41 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, u32 *keyid, ulong *uidrecno, byte *uidhash, KBNODE keyblock, KBNODE signode ) { + TRUSTREC urec; int rc; ulong lid = drec->recnum; + if( !*uidrecno ) { + /* fixme: handle direct key signatures */ + log_error("key %08lX: signature without user id\n", (ulong)keyid[1] ); + return; + } + read_record( *uidrecno, &urec, RECTYPE_UID ); + if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) { if( (sig->sig_class&~3) == 0x10 ) { /* must verify this selfsignature here, so that we can * build the preference record and validate the uid record */ - if( !*uidrecno ) { - log_error("key %08lX: self-signature without user id\n", - (ulong)keyid[1] ); - } - else if( (rc = check_key_signature( keyblock, signode, NULL ))) { - log_error("key %08lX, uid %02X%02X: " - "invalid self-signature: %s\n", (ulong)keyid[1], - uidhash[18], uidhash[19], g10_errstr(rc) ); - } - else { /* valid sig (may be revoked, but that doesn't matter here) */ - upd_pref_record( sig, drec, keyid, uidrecno, uidhash ); + if( !(urec.r.uid.uidflags & UIDF_CHECKED) ) { + rc = check_key_signature( keyblock, signode, NULL ); + if( !rc ) { + if( opt.verbose ) + log_info(_( + "key %08lX.%lu, uid %02X%02X: " + "good self-signature\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19] ); + upd_pref_record( sig, drec, keyid, &urec, uidhash ); + urec.r.uid.uidflags = UIDF_CHECKED | UIDF_VALID; + } + else { + log_error("key %08lX, uid %02X%02X: " + "invalid self-signature: %s\n", (ulong)keyid[1], + uidhash[18], uidhash[19], g10_errstr(rc) ); + urec.r.uid.uidflags = UIDF_CHECKED; + } + urec.dirty = 1; } } else {/* is revocation sig etc */ @@ -2051,18 +2115,43 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, * be converted to a dir record as soon as a new public key is * inserted into the trustdb. */ - TRUSTREC urec, rec; + TRUSTREC rec; ulong recno; TRUSTREC delrec; int delrecidx; int newflag = 0; ulong newlid = 0; PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + ulong pk_lid = 0; + int found_sig = 0; + int found_delrec = 0; delrec.recnum = 0; - /* we need the uid record */ - read_record( *uidrecno, &urec, RECTYPE_UID ); + rc = get_pubkey( pk, sig->keyid ); + if( !rc ) { + if( pk->local_id ) + pk_lid = pk->local_id; + else { + rc = tdbio_search_dir_bypk( pk, &rec ); + if( !rc ) + pk_lid = rec.recnum; + else if( rc == -1 ) { /* see whether there is a sdir instead */ + u32 akid[2]; + + keyid_from_pk( pk, akid ); + rc = tdbio_search_sdir( akid, pk->pubkey_algo, &rec ); + if( !rc ) + pk_lid = rec.recnum; + } + } + } + free_public_key( pk ); pk = NULL; + + /* Loop over all signatures just in case one is not correctly + * marked. If we see the correct signature, set a flag. + * delete duplicate signatures (should not happen but...) + */ for( recno = urec.r.uid.siglist; recno; recno = rec.r.sig.next ) { int i; @@ -2070,12 +2159,25 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, for(i=0; i < SIGS_PER_RECORD; i++ ) { TRUSTREC tmp; if( !rec.r.sig.sig[i].lid ) { - if( !delrec.recnum ) { + if( !found_delrec && !delrec.recnum ) { delrec = rec; delrecidx = i; + found_delrec=1; } continue; /* skip deleted sigs */ } + if( rec.r.sig.sig[i].lid == pk_lid ) { + if( found_sig ) { + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "duplicated signature - deleted\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1] ); + rec.r.sig.sig[i].lid = 0; + rec.dirty = 1; + } + else + found_sig = 1; + } if( rec.r.sig.sig[i].flag & SIGF_CHECKED ) continue; /* we already checked this signature */ if( rec.r.sig.sig[i].flag & SIGF_NOPUBKEY ) @@ -2087,24 +2189,30 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, * the signature: */ rc = check_key_signature( keyblock, signode, NULL ); if( !rc ) { /* valid signature */ + if( opt.verbose ) + log_info(_( + "key %08lX.%lu, uid %02X%02X, sig %08lX: " + "good signature (1)\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1] ); rec.r.sig.sig[i].flag = SIGF_CHECKED | SIGF_VALID; } else if( rc == G10ERR_NO_PUBKEY ) { - log_info(_("key %08lX.%lu, uid %02X%02X: " - "weird: no public key for signature %08lX\n"), + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "weird: no public key\n"), (ulong)keyid[1], lid, uidhash[18], uidhash[19], (ulong)sig->keyid[1] ); rec.r.sig.sig[i].flag = SIGF_NOPUBKEY; } else { - log_info(_("key %08lX.%lu, uid %02X%02X: " + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " "invalid signature: %s\n"), - (ulong)keyid[1], lid, - uidhash[18], uidhash[19], g10_errstr(rc)); + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1], + g10_errstr(rc)); rec.r.sig.sig[i].flag = SIGF_CHECKED; } - write_record( &rec ); - goto ready; + rec.dirty = 1; } else if( tmp.rectype == RECTYPE_SDIR ) { /* must check that it is the right one */ @@ -2117,11 +2225,10 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, (ulong)keyid[1], lid, uidhash[18], uidhash[19], tmp.recnum ); rec.r.sig.sig[i].flag = SIGF_NOPUBKEY; - write_record( &rec ); + rec.dirty = 1; /* fixme: should we verify that the record is * in the hintlist? - This case here should anyway * never occur */ - goto ready; } } else { @@ -2130,48 +2237,52 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, die_invalid_db(); } } + if( found_delrec && delrec.recnum ) { + delrec = rec; + found_delrec = 0; /* we onyl want the first one */ + } + if( rec.dirty ) + write_record( &rec ); } + + if( found_sig ) + goto leave; + /* at this point, we have verified, that the signature is not in * our list of signatures. Add a new record with that signature * and if the public key is there, check the signature. */ - rc = get_pubkey( pk, sig->keyid ); - if( !rc ) { - /* check that we already have the record in the trustdb; - * if not we should not check the signature, because we do - * not have the lid of the signature and therefore can't add - * a signature record. We will fake a no_pubkey error, so - * that this is handled, like we do not have the publick key at - * at all. The alternative would be a recursive insert of - * records - but that is not good. - */ - rc = query_trust_record( pk ); - if( rc == -1 ) - rc = G10ERR_NO_PUBKEY; - else - rc = check_key_signature( keyblock, signode, NULL ); - } + + if( !pk_lid ) + rc = G10ERR_NO_PUBKEY; + else + rc = check_key_signature( keyblock, signode, NULL ); + if( !rc ) { /* valid signature */ - newlid = pk->local_id; /* this is the pk of the signature */ + if( opt.verbose ) + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "good signature (2)\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1] ); + newlid = pk_lid; /* this is the pk of the signature */ if( !newlid ) BUG(); newflag = SIGF_CHECKED | SIGF_VALID; } else if( rc == G10ERR_NO_PUBKEY ) { - if( opt.verbose ) - log_info(_("key %08lX.%lu, uid %02X%02X: " - "no public key for signature %08lX\n"), + if( opt.verbose > 1 ) + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "no public key\n"), (ulong)keyid[1], lid, uidhash[18], uidhash[19], (ulong)sig->keyid[1] ); newflag = SIGF_NOPUBKEY; } else { - log_info(_("key %08lX.%lu, uid %02X%02X: " + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " "invalid signature: %s\n"), (ulong)keyid[1], lid, uidhash[18], uidhash[19], - g10_errstr(rc)); + (ulong)sig->keyid[1], g10_errstr(rc)); newflag = SIGF_CHECKED; } - free_public_key( pk ); if( !newlid ) { /* create a shadow dir record */ TRUSTREC sdir, hlst, tmphlst; @@ -2250,16 +2361,17 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, tmp.r.sig.sig[0].flag= newflag; write_record( &tmp ); urec.r.uid.siglist = tmp.recnum; - write_record( &urec ); + urec.dirty = 1; } - ready: - ; } else { /* handle other sig classes */ } + leave: + if( urec.dirty ) + write_record( &urec ); } @@ -2389,7 +2501,7 @@ update_trust_record( KBNODE keyblock ) else if( drec.dirty ) { drec.r.dir.dirflags &= ~DIRF_CHECKED; /* reset flag */ write_record( &drec ); - /* fixme: commit_transaction */ + do_sync(); } rel_recno_list( &recno_list ); return rc; @@ -2437,9 +2549,17 @@ insert_trust_record( PKT_public_key *pk ) /* check that we used the primary key (we are little bit paranoid) */ { PKT_public_key *a_pk; + u32 akid[2], bkid[2]; + node = find_kbnode( keyblock, PKT_PUBLIC_KEY ); a_pk = node->pkt->pkt.public_key; - if( cmp_public_keys( a_pk, pk ) ) { + + /* we can't use cmp_public_keys here because some parts (expiredate) + * might not be set in pk <--- but why (fixme) */ + keyid_from_pk( a_pk, akid ); + keyid_from_pk( pk, bkid ); + + if( akid[0] != bkid[0] || akid[1] != bkid[1] ) { log_error("did not use primary key for insert_trust_record()\n"); rc = G10ERR_GENERAL; goto leave; @@ -2492,6 +2612,7 @@ insert_trust_record( PKT_public_key *pk ) if( rc && hintlist ) ; /* fixme: the hintlist is not anymore anchored */ release_kbnode( keyblock ); + do_sync(); return rc; } @@ -2504,6 +2625,7 @@ update_ownertrust( ulong lid, unsigned new_trust ) read_record( lid, &rec, RECTYPE_DIR ); rec.r.dir.ownertrust = new_trust; write_record( &rec ); + do_sync(); return 0; } diff --git a/g10/trustdb.h b/g10/trustdb.h index b0f39770f..8cdf50ec1 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -46,6 +46,7 @@ void list_trust_path( int max_depth, const char *username ); void export_ownertrust(void); void import_ownertrust(const char *fname); void check_trustdb( const char *username ); +void update_trustdb( void ); int init_trustdb( int level, const char *dbname ); int check_trust( PKT_public_key *pk, unsigned *r_trustlevel ); int query_trust_info( PKT_public_key *pk ); |