diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/ChangeLog | 14 | ||||
-rw-r--r-- | g10/getkey.c | 197 | ||||
-rw-r--r-- | g10/keyedit.c | 2 | ||||
-rw-r--r-- | g10/keylist.c | 13 | ||||
-rw-r--r-- | g10/mainproc.c | 2 | ||||
-rw-r--r-- | g10/pkclist.c | 29 | ||||
-rw-r--r-- | g10/seckey-cert.c | 2 | ||||
-rw-r--r-- | g10/sig-check.c | 7 | ||||
-rw-r--r-- | g10/trustdb.c | 636 | ||||
-rw-r--r-- | g10/trustdb.h | 4 |
10 files changed, 330 insertions, 576 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog index 034041849..9e3e460bd 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,17 @@ +Mon Mar 8 20:47:17 CET 1999 Werner Koch <[email protected]> + + * getkey.c (classify_user_id): Add new mode 12 (#<lid>). + + * seckey-cert.c (check_secret_key): replaced error by info. + + * trustdb.c (query_trust_info): Add another arg, changed all callers. + (check_trust): Ditto. + (do_check): Ditto. + (verify_key): Handle namehash. + * keylist.c (list_keyblock): print trust info for user ids. + + * sig-check.c (signature_check): Add sig-created to status output. + Tue Mar 2 16:44:57 CET 1999 Werner Koch <[email protected]> * textfilter.c (copy_clearsig_text): New. diff --git a/g10/getkey.c b/g10/getkey.c index 01ffe0111..424590ed2 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -506,6 +506,7 @@ hextobyte( const byte *s ) * 6 = word match mode * 10 = it is a short KEYID (don't care about keyid[0]) * 11 = it is a long KEYID + * 12 = it is a trustdb index (keyid is looked up) * 16 = it is a 16 byte fingerprint * 20 = it is a 20 byte fingerprint * @@ -624,7 +625,12 @@ classify_user_id( const char *name, u32 *keyid, byte *fprint, s++; } else if( *s == '#' ) { /* use local id */ - return 0; + mode = 12; + s++; + if( keyid ) { + if( keyid_from_lid( strtoul( s, NULL, 10), keyid ) ) + keyid[0] = keyid[1] = 0; + } } else if( !*s ) /* empty string */ return 0; @@ -1561,54 +1567,6 @@ finish_lookup_sk( KBNODE keyblock, PKT_secret_key *sk, KBNODE k, int primary ) } -/****** old code from lookup_read ******/ -#if 0 /* can't use it anymore - invent a more general approach */ - /* try the quick functions */ - if( !ctx->count ) { - k = NULL; - switch( ctx->mode ) { - case 10: - case 11: - rc = locate_keyblock_by_keyid( &ctx->kbpos, ctx->keyid, - ctx->mode==10, 0 ); - if( !rc ) - rc = read_keyblock( &ctx->kbpos, &ctx->keyblock ); - if( !rc ) - k = find_by_keyid( ctx->keyblock, pk, ctx->keyid, ctx->mode ); - break; - - case 16: - case 20: - rc = locate_keyblock_by_fpr( &ctx->kbpos, ctx->name, ctx->mode, 0 ); - if( !rc ) - rc = read_keyblock( &ctx->kbpos, &ctx->keyblock ); - if( !rc ) - k = find_by_fpr( ctx->keyblock, pk, ctx->name, ctx->mode ); - break; - - default: rc = G10ERR_UNSUPPORTED; - } - if( !rc ) { - if( !k ) { - log_error("lookup: key has been located but was not found\n"); - rc = G10ERR_INV_KEYRING; - } - else - finish_lookup( ctx->keyblock, pk, k, namehash, 0, ctx->primary ); - } - } - else - rc = G10ERR_UNSUPPORTED; - - /* if this was not possible, loop over all keyblocks - * fixme: If one of the resources in the quick functions above - * works, but the key was not found, we will not find it - * in the other resources */ - if( rc == G10ERR_UNSUPPORTED ) { - } -#endif - - static int lookup_pk( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock ) { @@ -1636,7 +1594,7 @@ lookup_pk( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock ) k = find_by_name( ctx->keyblock, pk, item->name, item->mode, namehash, &use_namehash ); - else if( item->mode == 10 || item->mode == 11 ) + else if( item->mode >= 10 && item->mode <= 12 ) k = find_by_keyid( ctx->keyblock, pk, item->keyid, item->mode ); else if( item->mode == 15 ) @@ -1723,7 +1681,7 @@ lookup_sk( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock ) if( item->mode < 10 ) k = find_by_name_sk( ctx->keyblock, sk, item->name, item->mode ); - else if( item->mode == 10 || item->mode == 11 ) + else if( item->mode >= 10 && item->mode <= 12 ) k = find_by_keyid_sk( ctx->keyblock, sk, item->keyid, item->mode ); else if( item->mode == 15 ) @@ -1765,143 +1723,6 @@ lookup_sk( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock ) } -#if 0 -OLD/************ -OLD * Ditto for secret keys WORK!!!!!! -OLD */ -OLDstatic int -OLDlookup_sk( PKT_secret_key *sk, int mode, u32 *keyid, const char *name, -OLD int primary ) -OLD{ -OLD int rc; -OLD KBNODE keyblock = NULL; -OLD KBPOS kbpos; -OLD int oldmode = set_packet_list_mode(0); -OLD -OLD rc = enum_keyblocks( 5 /* open secret */, &kbpos, &keyblock ); -OLD if( rc ) { -OLD if( rc == -1 ) -OLD rc = G10ERR_NO_SECKEY; -OLD else if( rc ) -OLD log_error("enum_keyblocks(open secret) failed: %s\n", g10_errstr(rc) ); -OLD goto leave; -OLD } -OLD -OLD while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) { -OLD KBNODE k, kk; -OLD if( mode < 10 ) { /* name lookup */ -OLD for(k=keyblock; k; k = k->next ) { -OLD if( k->pkt->pkttype == PKT_USER_ID -OLD && !compare_name( k->pkt->pkt.user_id->name, -OLD k->pkt->pkt.user_id->len, name, mode)) { -OLD /* we found a matching name, look for the key */ -OLD for(kk=keyblock; kk; kk = kk->next ) { -OLD if( ( kk->pkt->pkttype == PKT_SECRET_KEY -OLD || kk->pkt->pkttype == PKT_SECRET_SUBKEY ) -OLD && ( !sk->pubkey_algo -OLD || sk->pubkey_algo -OLD == kk->pkt->pkt.secret_key->pubkey_algo) -OLD && ( !sk->pubkey_usage -OLD || !check_pubkey_algo2( -OLD kk->pkt->pkt.secret_key->pubkey_algo, -OLD sk->pubkey_usage )) -OLD ) -OLD break; -OLD } -OLD if( kk ) { -OLD u32 aki[2]; -OLD keyid_from_sk( kk->pkt->pkt.secret_key, aki ); -OLD cache_user_id( k->pkt->pkt.user_id, aki ); -OLD k = kk; -OLD break; -OLD } -OLD else -OLD log_error("No key for userid (in sk)\n"); -OLD } -OLD } -OLD } -OLD else { /* keyid or fingerprint lookup */ -OLD if( DBG_CACHE && (mode== 10 || mode==11) ) { -OLD log_debug("lookup_sk keyid=%08lx%08lx req_algo=%d mode=%d\n", -OLD (ulong)keyid[0], (ulong)keyid[1], -OLD sk->pubkey_algo, mode ); -OLD } -OLD for(k=keyblock; k; k = k->next ) { -OLD if( k->pkt->pkttype == PKT_SECRET_KEY -OLD || k->pkt->pkttype == PKT_SECRET_SUBKEY ) { -OLD if( mode == 10 || mode == 11 ) { -OLD u32 aki[2]; -OLD keyid_from_sk( k->pkt->pkt.secret_key, aki ); -OLD if( DBG_CACHE ) { -OLD log_debug(" aki=%08lx%08lx algo=%d\n", -OLD (ulong)aki[0], (ulong)aki[1], -OLD k->pkt->pkt.secret_key->pubkey_algo ); -OLD } -OLD if( aki[1] == keyid[1] -OLD && ( mode == 10 || aki[0] == keyid[0] ) -OLD && ( !sk->pubkey_algo -OLD || sk->pubkey_algo -OLD == k->pkt->pkt.secret_key->pubkey_algo) ){ -OLD /* cache the userid */ -OLD for(kk=keyblock; kk; kk = kk->next ) -OLD if( kk->pkt->pkttype == PKT_USER_ID ) -OLD break; -OLD if( kk ) -OLD cache_user_id( kk->pkt->pkt.user_id, aki ); -OLD else -OLD log_error("No userid for key\n"); -OLD break; /* found */ -OLD } -OLD } -OLD else if( mode == 15 ) { /* get the first key */ -OLD if( !sk->pubkey_algo -OLD || sk->pubkey_algo -OLD == k->pkt->pkt.secret_key->pubkey_algo ) -OLD break; -OLD } -OLD else if( mode == 16 || mode == 20 ) { -OLD size_t an; -OLD byte afp[MAX_FINGERPRINT_LEN]; -OLD -OLD fingerprint_from_sk(k->pkt->pkt.secret_key, afp, &an ); -OLD if( an == mode && !memcmp( afp, name, an) -OLD && ( !sk->pubkey_algo -OLD || sk->pubkey_algo -OLD == k->pkt->pkt.secret_key->pubkey_algo) ) { -OLD break; -OLD } -OLD } -OLD else -OLD BUG(); -OLD } /* end compare secret keys */ -OLD } -OLD } -OLD if( k ) { /* found */ -OLD assert( k->pkt->pkttype == PKT_SECRET_KEY -OLD || k->pkt->pkttype == PKT_SECRET_SUBKEY ); -OLD assert( keyblock->pkt->pkttype == PKT_SECRET_KEY ); -OLD if( primary && !sk->pubkey_usage ) -OLD copy_secret_key( sk, keyblock->pkt->pkt.secret_key ); -OLD else -OLD copy_secret_key( sk, k->pkt->pkt.secret_key ); -OLD break; /* enumeration */ -OLD } -OLD release_kbnode( keyblock ); -OLD keyblock = NULL; -OLD } -OLD if( rc == -1 ) -OLD rc = G10ERR_NO_SECKEY; -OLD else if( rc ) -OLD log_error("enum_keyblocks(read) failed: %s\n", g10_errstr(rc)); -OLD -OLD leave: -OLD enum_keyblocks( 2, &kbpos, &keyblock ); /* close */ -OLD release_kbnode( keyblock ); -OLD set_packet_list_mode(oldmode); -OLD return rc; -OLD} -#endif - /**************** * fixme: replace by the generic function diff --git a/g10/keyedit.c b/g10/keyedit.c index f16a19cb6..f818b35df 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -889,7 +889,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { /* do it here, so that debug messages don't clutter the * output */ - trust = query_trust_info(pk); + trust = query_trust_info(pk, NULL); otrust = get_ownertrust_info( pk->local_id ); } diff --git a/g10/keylist.c b/g10/keylist.c index 1861cd824..1462dbb2f 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -196,7 +196,7 @@ list_keyblock( KBNODE keyblock, int secret ) sk = NULL; keyid_from_pk( pk, keyid ); if( opt.with_colons ) { - trustletter = query_trust_info( pk ); + trustletter = query_trust_info( pk, NULL ); printf("pub:%c:%u:%d:%08lX%08lX:%s:%s:", trustletter, nbits_from_pk( pk ), @@ -222,8 +222,15 @@ list_keyblock( KBNODE keyblock, int secret ) for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { if( node->pkt->pkttype == PKT_USER_ID ) { if( any ) { - if( opt.with_colons ) - printf("uid:::::::::"); + if( opt.with_colons ) { + byte namehash[20]; + + rmd160_hash_buffer( namehash, + node->pkt->pkt.user_id->name, + node->pkt->pkt.user_id->len ); + trustletter = query_trust_info( pk, namehash ); + printf("uid:%c::::::::", trustletter); + } else printf("uid%*s", 28, ""); } diff --git a/g10/mainproc.c b/g10/mainproc.c index fcb9f5db5..8ef802b63 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -481,7 +481,7 @@ list_node( CTX c, KBNODE node ) keyid_from_pk( pk, keyid ); if( mainkey ) { c->local_id = pk->local_id; - c->trustletter = query_trust_info( pk ); + c->trustletter = query_trust_info( pk, NULL ); } printf("%s:%c:%u:%d:%08lX%08lX:%s:%s:", mainkey? "pub":"sub", diff --git a/g10/pkclist.c b/g10/pkclist.c index ca22736a7..fffaef821 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -50,7 +50,7 @@ show_paths( ulong lid, int only_first ) last_level = 0; while( (level=enum_cert_paths( &context, &lid, &otrust, &validity)) != -1){ char *p; - int rc; + int c, rc; size_t n; u32 keyid[2]; PKT_public_key *pk ; @@ -77,7 +77,7 @@ show_paths( ulong lid, int only_first ) level*2, "", nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), (ulong)keyid[1], lid, datestr_from_pk( pk ) ); - #if 0 + c = trust_letter(otrust); if( c ) putchar( c ); @@ -90,8 +90,6 @@ show_paths( ulong lid, int only_first ) else printf( "%02x", validity ); putchar(' '); - #endif - p = get_user_id( keyid, &n ); tty_print_string( p, n ), @@ -230,7 +228,6 @@ _("Could not find a valid trust path to the key. Let's see whether we\n" } lid = pk->local_id; - #if 0 /* FIXME: enable this when trustdb stuff works again */ while( enum_cert_paths( &context, &lid, &otrust, &validity ) != -1 ) { if( lid == pk->local_id ) continue; @@ -242,6 +239,7 @@ _("Could not find a valid trust path to the key. Let's see whether we\n" * those values from then on */ otrust = get_ownertrust( lid ); + /* fixme: and the validity? */ } if( otrust == TRUST_UNDEFINED ) { any_undefined=1; @@ -257,7 +255,6 @@ _("Could not find a valid trust path to the key. Let's see whether we\n" } } enum_cert_paths( &context, NULL, NULL, NULL ); /* release context */ - #endif if( !any ) tty_printf(_("No path leading to one of our keys found.\n\n") ); @@ -298,12 +295,14 @@ do_we_trust( PKT_public_key *pk, int trustlevel ) g10_errstr(rc) ); return 0; /* no */ } - rc = check_trust( pk, &trustlevel ); + rc = check_trust( pk, &trustlevel, NULL ); if( rc ) log_fatal("trust check after insert failed: %s\n", g10_errstr(rc) ); - if( trustlevel == TRUST_UNKNOWN || trustlevel == TRUST_EXPIRED ) - BUG(); + if( trustlevel == TRUST_UNKNOWN || trustlevel == TRUST_EXPIRED ) { + log_debug("do_we_trust: oops at %d\n", __LINE__ ); + return 0; + } return do_we_trust( pk, trustlevel ); case TRUST_EXPIRED: @@ -320,7 +319,7 @@ do_we_trust( PKT_public_key *pk, int trustlevel ) rc = add_ownertrust( pk, &quit ); if( !rc && !quit ) { - rc = check_trust( pk, &trustlevel ); + rc = check_trust( pk, &trustlevel, NULL ); if( rc ) log_fatal("trust check after add_ownertrust failed: %s\n", g10_errstr(rc) ); @@ -431,7 +430,7 @@ check_signatures_trust( PKT_signature *sig ) } retry: - rc = check_trust( pk, &trustlevel ); + rc = check_trust( pk, &trustlevel, NULL ); if( rc ) { log_error("check trust failed: %s\n", g10_errstr(rc)); goto leave; @@ -452,7 +451,7 @@ check_signatures_trust( PKT_signature *sig ) g10_errstr(rc) ); goto leave; } - rc = check_trust( pk, &trustlevel ); + rc = check_trust( pk, &trustlevel, NULL ); if( rc ) log_fatal("trust check after insert failed: %s\n", g10_errstr(rc) ); @@ -592,7 +591,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use ) else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) { int trustlevel; - rc = check_trust( pk, &trustlevel ); + rc = check_trust( pk, &trustlevel, NULL ); if( rc ) { log_error("error checking pk of `%s': %s\n", answer, g10_errstr(rc) ); @@ -631,7 +630,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use ) else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) { int trustlevel; - rc = check_trust( pk, &trustlevel ); + rc = check_trust( pk, &trustlevel, NULL ); if( rc ) { free_public_key( pk ); pk = NULL; log_error(_("%s: error checking key: %s\n"), @@ -712,7 +711,7 @@ select_algo_from_prefs( PK_LIST pk_list, int preftype ) memset( mask, 0, 8 * sizeof *mask ); if( !pkr->pk->local_id ) { /* try to set the local id */ - query_trust_info( pkr->pk ); + query_trust_info( pkr->pk, NULL ); if( !pkr->pk->local_id ) { log_debug("select_algo_from_prefs: can't get LID\n"); continue; diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index cab99b65b..661f1da43 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -173,7 +173,7 @@ check_secret_key( PKT_secret_key *sk, int n ) for(i=0; i < n && rc == G10ERR_BAD_PASS; i++ ) { if( i ) - log_error(_("Invalid passphrase; please try again ...\n")); + log_info(_("Invalid passphrase; please try again ...\n")); rc = do_check( sk ); if( have_static_passphrase() ) break; diff --git a/g10/sig-check.c b/g10/sig-check.c index 2de2f7818..885a5b587 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -76,7 +76,7 @@ signature_check( PKT_signature *sig, MD_HANDLE digest ) MD_HANDLE md; u32 a = sig->timestamp; int i, nsig = pubkey_get_nsig( sig->pubkey_algo ); - byte *p; + byte *p, *buffer; md = md_open( DIGEST_ALGO_RMD160, 0); md_putc( digest, sig->pubkey_algo ); @@ -96,7 +96,10 @@ signature_check( PKT_signature *sig, MD_HANDLE digest ) } md_final( md ); p = make_radix64_string( md_read( md, 0 ), 20 ); - write_status_text( STATUS_SIG_ID, p ); + buffer = m_alloc( strlen(p) + 40 ); + sprintf( buffer, "%s %s", p, strtimestamp( sig->timestamp ) ); + write_status_text( STATUS_SIG_ID, buffer ); + m_free(buffer); m_free(p); md_close(md); } diff --git a/g10/trustdb.c b/g10/trustdb.c index c40976523..2a37641aa 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -1,5 +1,5 @@ /* trustdb.c - * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -66,25 +66,8 @@ struct local_id_table { typedef struct local_id_table *LOCAL_ID_TABLE; -typedef struct trust_info TRUST_INFO; -struct trust_info { - ulong lid; - byte otrust; /* ownertrust (assigned trust) */ - byte trust; /* calculated trust (validity) */ -}; - -typedef struct trust_seg_list *TRUST_SEG_LIST; -struct trust_seg_list { - TRUST_SEG_LIST next; - int pathlen; - TRUST_INFO path[1]; -}; - - struct enum_cert_paths_ctx { int init; - TRUST_SEG_LIST tsl_head; - TRUST_SEG_LIST tsl; int idx; }; @@ -97,6 +80,35 @@ struct recno_list_struct { typedef struct recno_list_struct *RECNO_LIST; + +typedef struct trust_node *TN; +struct trust_node { + TN back; /* parent */ + TN list; /* list of other node (should all be of the same type)*/ + TN next; /* used to build the list */ + int is_uid; /* set if this is an uid node */ + ulong lid; /* key or uid recordnumber */ + union { + struct { + int ownertrust; + int validity; + /* helper */ + int buckstop; + } k; + struct { + int marginal_count; + int fully_count; + int validity; + } u; + } n; +}; + + +static TN used_tns; +static int alloced_tns; +static int max_alloced_tns; + + static int walk_sigrecs( SIGREC_CONTEXT *c ); static LOCAL_ID_TABLE new_lid_table(void); @@ -105,11 +117,11 @@ static int ins_lid_table_item( LOCAL_ID_TABLE tbl, ulong lid, unsigned flag ); static int qry_lid_table_flag( LOCAL_ID_TABLE tbl, ulong lid, unsigned *flag ); +static int propagate_validity( TN node ); static void print_user_id( const char *text, u32 *keyid ); -static void sort_tsl_list( TRUST_SEG_LIST *trust_seg_list ); static int list_sigs( ulong pubkey_id ); -static int do_check( TRUSTREC *drec, unsigned *trustlevel ); +static int do_check( TRUSTREC *drec, unsigned *trustlevel, const char *nhash); static int get_dir_record( PKT_public_key *pk, TRUSTREC *rec ); static void upd_pref_record( TRUSTREC *urec, u32 *keyid, PKT_signature *sig ); @@ -450,7 +462,7 @@ walk_sigrecs( SIGREC_CONTEXT *c ) ************* Trust stuff ****************** ***********************************************/ -static int +int trust_letter( unsigned value ) { switch( value ) { @@ -639,35 +651,6 @@ print_user_id( const char *text, u32 *keyid ) m_free(p); } -#if 0 -static int -print_keyid( FILE *fp, ulong lid ) -{ - u32 ki[2]; - if( keyid_from_lid( lid, ki ) ) - return fprintf(fp, "????????.%lu", lid ); - else - return fprintf(fp, "%08lX.%lu", (ulong)ki[1], lid ); -} - -static int -print_trust( FILE *fp, unsigned trust ) -{ - int c; - switch( trust ) { - case TRUST_UNKNOWN: c = 'o'; break; - case TRUST_EXPIRED: c = 'e'; break; - case TRUST_UNDEFINED: c = 'q'; break; - case TRUST_NEVER: c = 'n'; break; - case TRUST_MARGINAL: c = 'm'; break; - case TRUST_FULLY: c = 'f'; break; - case TRUST_ULTIMATE: c = 'u'; break; - default: fprintf(fp, "%02x", trust ); return 2; - } - putc(c, fp); - return 1; -} -#endif static int print_sigflags( FILE *fp, unsigned flags ) @@ -698,7 +681,7 @@ do_list_sigs( ulong root, ulong pk_lid, int depth, sx.lid = pk_lid; for(;;) { rc = walk_sigrecs( &sx ); /* should we replace it and use */ - if( rc ) /* use a loop like in collect_paths ??*/ + if( rc ) break; rc = keyid_from_lid( sx.sig_lid, keyid ); if( rc ) { @@ -839,199 +822,45 @@ list_records( ulong lid ) - -/**************** - * stack is an array of (max_path+1) elements. If trust_seg_head is not - * NULL it is a pointer to a variable which will receive a linked list - * of trust paths - The caller has to free the memory. - */ -static int -collect_paths( int depth, int max_depth, int all, TRUSTREC *drec, - TRUST_INFO *stack, TRUST_SEG_LIST *trust_seg_head ) +static TN +new_tn(void) { - ulong rn, uidrn; - int marginal=0; - int fully=0; - /*LOCAL_ID_TABLE sigs_seen = NULL;*/ - - if( depth >= max_depth ) /* max cert_depth reached */ - return TRUST_UNDEFINED; - - /* loop over all user-ids */ - /*if( !all ) sigs_seen = new_lid_table();*/ - for( rn = drec->r.dir.uidlist; rn; rn = uidrn ) { - TRUSTREC rec; /* used for uids and sigs */ - ulong sigrn; - - read_record( rn, &rec, RECTYPE_UID ); - uidrn = rec.r.uid.next; - if( !(rec.r.uid.uidflags & UIDF_CHECKED) ) - continue; /* user id has not been checked */ - if( !(rec.r.uid.uidflags & UIDF_VALID) ) - continue; /* user id is not valid */ - if( (rec.r.uid.uidflags & UIDF_REVOKED) ) - continue; /* user id has been revoked */ - - stack[depth].lid = drec->r.dir.lid; - stack[depth].otrust = drec->r.dir.ownertrust; - stack[depth].trust = 0; - { int i; - - for(i=0; i < depth; i++ ) - if( stack[i].lid == drec->r.dir.lid ) - return TRUST_UNDEFINED; /* closed (we already visited this lid) */ - } - if( !qry_lid_table_flag( ultikey_table, drec->r.dir.lid, NULL ) ) { - /* we are at the end of a path */ - TRUST_SEG_LIST tsl; - int i; + TN t; - stack[depth].trust = TRUST_ULTIMATE; - stack[depth].otrust = TRUST_ULTIMATE; - if( trust_seg_head ) { - /* we can now put copy our current stack to the trust_seg_list */ - tsl = m_alloc( sizeof *tsl + (depth+1)*sizeof( TRUST_INFO ) ); - for(i=0; i <= depth; i++ ) - tsl->path[i] = stack[i]; - tsl->pathlen = i; - tsl->next = *trust_seg_head; - *trust_seg_head = tsl; - } - return TRUST_ULTIMATE; - } - - - /* loop over all signature records of this user id */ - for( rn = rec.r.uid.siglist; rn; rn = sigrn ) { - int i; - - read_record( rn, &rec, RECTYPE_SIG ); - sigrn = rec.r.sig.next; - - for(i=0; i < SIGS_PER_RECORD; i++ ) { - TRUSTREC tmp; - int ot, nt; - int unchecked = 0; - - if( !rec.r.sig.sig[i].lid ) - continue; /* skip deleted sigs */ - if( !(rec.r.sig.sig[i].flag & SIGF_CHECKED) ) { - if( !all ) - continue; /* skip unchecked signatures */ - unchecked = 1; - } - else { - if( !(rec.r.sig.sig[i].flag & SIGF_VALID) ) - continue; /* skip invalid signatures */ - if( (rec.r.sig.sig[i].flag & SIGF_EXPIRED) ) - continue; /* skip expired signatures */ - if( (rec.r.sig.sig[i].flag & SIGF_REVOKED) ) - continue; /* skip revoked signatures */ - } - - /* visit every signer only once (a signer may have - * signed more than one user ID) - * if( sigs_seen && ins_lid_table_item( sigs_seen, - * rec.r.sig.sig[i].lid, 0) ) - * continue; we already have this one - */ - read_record( rec.r.sig.sig[i].lid, &tmp, 0 ); - if( tmp.rectype != RECTYPE_DIR ) { - if( tmp.rectype != RECTYPE_SDIR ) - log_info("oops: lid %lu: sig %lu has rectype %d" - " - skipped\n", - drec->r.dir.lid, tmp.recnum, tmp.rectype ); - continue; - } - ot = tmp.r.dir.ownertrust & TRUST_MASK; - if( ot >= TRUST_FULLY ) - ot = TRUST_FULLY; /* just in case */ - nt = collect_paths( depth+1, max_depth, all, &tmp, stack, - trust_seg_head ); - nt &= TRUST_MASK; - - if( nt < TRUST_MARGINAL || unchecked ) { - continue; - } - - if( nt == TRUST_ULTIMATE ) { - /* we have signed this key and only in this special case - * we assume that this one is fully trusted */ - if( !all ) { - /*if( sigs_seen ) release_lid_table( sigs_seen );*/ - return (stack[depth].trust = TRUST_FULLY); - } - } - - if( nt > ot ) - nt = ot; - - if( nt >= TRUST_FULLY ) - fully++; - if( nt >= TRUST_MARGINAL ) - marginal++; - - if( fully >= opt.completes_needed - || marginal >= opt.marginals_needed ) { - if( !all ) { - /*if( sigs_seen ) release_lid_table( sigs_seen );*/ - return (stack[depth].trust = TRUST_FULLY); - } - } - } - } - } - /*if( sigs_seen ) release_lid_table( sigs_seen ); */ - if( all && ( fully >= opt.completes_needed - || marginal >= opt.marginals_needed ) ) { - return (stack[depth].trust = TRUST_FULLY ); + if( used_tns ) { + t = used_tns; + used_tns = t->next; + memset( t, 0, sizeof *t ); } - if( marginal ) { - return (stack[depth].trust = TRUST_MARGINAL); - } - return (stack[depth].trust=TRUST_UNDEFINED); + else + t = m_alloc_clear( sizeof *t ); + if( ++alloced_tns > max_alloced_tns ) + max_alloced_tns = alloced_tns; + return t; } -typedef struct { - ulong lid; - ulong uid; - byte uid_flags; - byte uid_validity; - byte dir_flags; - byte ownertrust; -} CERT_ITEM; - -/* structure to hold certification chains. Item[nitems-1] is the - * ultimateley trusted key, item[0] is the key which - * is introduced, indices [1,(nitems-2)] are all introducers. - */ -typedef struct cert_chain *CERT_CHAIN; -struct cert_chain { - CERT_CHAIN next; - int dups; - int nitems; - CERT_ITEM items[1]; -}; - +static void +release_tn( TN t ) +{ + if( t ) { + t->next = used_tns; + used_tns = t; + alloced_tns--; + } +} -/**************** - * Copy all items to the set SET_HEAD in a way that the requirements - * of a CERT_CHAIN are met. - */ static void -add_cert_items_to_set( CERT_CHAIN *set_head, CERT_ITEM *items, int nitems ) +release_tn_tree( TN kr ) { - CERT_CHAIN ac; - int i; + TN kr2; - ac = m_alloc_clear( sizeof *ac + (nitems-1)*sizeof(CERT_ITEM) ); - ac->nitems = nitems; - for(i=0; i < nitems; i++ ) - ac->items[i] = items[i]; - ac->next = *set_head; - *set_head = ac; + for( ; kr; kr = kr2 ) { + release_tn_tree( kr->list ); + kr2 = kr->next; + release_tn( kr ); + } } @@ -1041,57 +870,51 @@ add_cert_items_to_set( CERT_CHAIN *set_head, CERT_ITEM *items, int nitems ) * should have been allocated with size max_depth, stack[0] should * be setup to the key we are investigating, so the minimal depth * we should ever see in this function is 1. - * Returns: -1 max_depth reached - * 0 no paths found - * 1 ultimately trusted key found + * Returns: a new tree * certchain_set must be a valid set or point to NULL; this function * may modifiy it. */ -static int -find_cert_chain( ulong lid, int depth, int max_depth, - CERT_ITEM *stack, CERT_CHAIN *cert_chain_set ) +static TN +build_cert_tree( ulong lid, int depth, int max_depth, TN helproot ) { TRUSTREC dirrec; TRUSTREC uidrec; ulong uidrno; + TN keynode; if( depth >= max_depth ) - return -1; - - stack[depth].lid = lid; - stack[depth].uid = 0; + return NULL; + keynode = new_tn(); + if( !helproot ) + helproot = keynode; + keynode->lid = lid; if( !qry_lid_table_flag( ultikey_table, lid, NULL ) ) { /* this is an ultimately trusted key; * which means that we have found the end of the chain: - * copy the chain to the set */ - add_cert_items_to_set( cert_chain_set, stack, depth+1 ); - return 1; + * We do this here prior to reading the dir record + * because we don't really need the info from that record */ + keynode->n.k.ownertrust = TRUST_ULTIMATE; + keynode->n.k.buckstop = 1; + return keynode; } - - read_record( lid, &dirrec, 0 ); if( dirrec.rectype != RECTYPE_DIR ) { if( dirrec.rectype != RECTYPE_SDIR ) log_debug("lid %lu, has rectype %d" " - skipped\n", lid, dirrec.rectype ); - return 0; + m_free(keynode); + return NULL; } - /* Performance hint: add stuff to ignore this one when the - * assigned validity of the key is bad */ - - stack[depth].dir_flags = dirrec.r.dir.dirflags; - stack[depth].ownertrust = dirrec.r.dir.ownertrust; + keynode->n.k.ownertrust = dirrec.r.dir.ownertrust; /* loop over all user ids */ for( uidrno = dirrec.r.dir.uidlist; uidrno; uidrno = uidrec.r.uid.next ) { TRUSTREC sigrec; ulong sigrno; + TN uidnode = NULL; - stack[depth].uid = uidrno; read_record( uidrno, &uidrec, RECTYPE_UID ); - stack[depth].uid_flags = uidrec.r.uid.uidflags; - stack[depth].uid_validity = uidrec.r.uid.validity; if( !(uidrec.r.uid.uidflags & UIDF_CHECKED) ) continue; /* user id has not been checked */ @@ -1102,7 +925,8 @@ find_cert_chain( ulong lid, int depth, int max_depth, /* loop over all signature records */ for(sigrno=uidrec.r.uid.siglist; sigrno; sigrno = sigrec.r.sig.next ) { - int i, j; + int i; + TN tn; read_record( sigrno, &sigrec, RECTYPE_SIG ); @@ -1117,25 +941,48 @@ find_cert_chain( ulong lid, int depth, int max_depth, continue; /* skip expired signatures */ if( (sigrec.r.sig.sig[i].flag & SIGF_REVOKED) ) continue; /* skip revoked signatures */ - for(j=0; j < depth; j++ ) { - if( stack[j].lid == sigrec.r.sig.sig[i].lid ) - break; + /* check for cycles */ + for( tn=keynode; tn && tn->lid != sigrec.r.sig.sig[i].lid; + tn = tn->back ) + ; + if( tn ) + continue; /* cycle found */ + + tn = build_cert_tree( sigrec.r.sig.sig[i].lid, + depth+1, max_depth, helproot ); + if( !tn ) + continue; /* cert chain too deep or error */ + + if( !uidnode ) { + uidnode = new_tn(); + uidnode->back = keynode; + uidnode->lid = uidrno; + uidnode->is_uid = 1; + uidnode->next = keynode->list; + keynode->list = uidnode; } - if( j < depth ) - continue; /* avoid cycles as soon as possible */ - if( find_cert_chain( sigrec.r.sig.sig[i].lid, - depth+1, max_depth, - stack, cert_chain_set ) > 0 ) { + tn->back = uidnode; + tn->next = uidnode->list; + uidnode->list = tn; + #if 0 /* optimazation - fixme: reenable this later */ + if( tn->n.k.buckstop ) { /* ultimately trusted key found: * no need to check more signatures of this uid */ sigrec.r.sig.next = 0; break; } + #endif } } /* end loop over sig recs */ } /* end loop over user ids */ - return 0; + + if( !keynode->list ) { + release_tn_tree( keynode ); + keynode = NULL; + } + + return keynode; } @@ -1147,14 +994,33 @@ find_cert_chain( ulong lid, int depth, int max_depth, * checking all key signatures up to a some depth. */ static int -verify_key( int max_depth, TRUSTREC *drec ) +verify_key( int max_depth, TRUSTREC *drec, const char *namehash ) { - TRUST_INFO *tmppath = m_alloc_clear( (max_depth+1)* sizeof *tmppath ); - int tr; + TN tree; + int trust; + + tree = build_cert_tree( drec->r.dir.lid, 0, opt.max_cert_depth, NULL ); + if( !tree ) + return TRUST_UNDEFINED; + trust = propagate_validity( tree ); + if( namehash ) { + /* find the matching user id. + * FIXME: the way we handle this is too inefficient */ + TN ur; + TRUSTREC rec; - tr = collect_paths( 0, max_depth, 0, drec, tmppath, NULL ); - m_free( tmppath ); - return tr; + trust = 0; + for( ur=tree->list; ur; ur = ur->next ) { + read_record( ur->lid, &rec, RECTYPE_UID ); + if( !memcmp( namehash, rec.r.uid.namehash, 20 ) ) { + trust = ur->n.u.validity; + break; + } + } + } + + release_tn_tree( tree ); + return trust; } @@ -1165,7 +1031,7 @@ verify_key( int max_depth, TRUSTREC *drec ) * but nothing more is known. */ static int -do_check( TRUSTREC *dr, unsigned *validity ) +do_check( TRUSTREC *dr, unsigned *validity, const char *namehash ) { if( !dr->r.dir.keylist ) { log_error(_("Ooops, no keys\n")); @@ -1176,15 +1042,21 @@ do_check( TRUSTREC *dr, unsigned *validity ) return G10ERR_TRUSTDB; } - if( tdbio_db_matches_options() + if( namehash ) { + /* Fixme: use the cache */ + *validity = verify_key( opt.max_cert_depth, dr, namehash ); + } + else if( tdbio_db_matches_options() && (dr->r.dir.dirflags & DIRF_VALVALID) && dr->r.dir.validity ) *validity = dr->r.dir.validity; else { - *validity = verify_key( opt.max_cert_depth, dr ); + *validity = verify_key( opt.max_cert_depth, dr, NULL ); if( (*validity & TRUST_MASK) >= TRUST_UNDEFINED && tdbio_db_matches_options() ) { /* update the cached validity value */ + /* FIXME: Move this to another place so that we can + * update the validity of the uids too */ dr->r.dir.validity = (*validity & TRUST_MASK); dr->r.dir.dirflags |= DIRF_VALVALID; write_record( dr ); @@ -1437,9 +1309,9 @@ import_ownertrust( const char *fname ) - +#if 0 static void -print_path( int pathlen, TRUST_INFO *path, FILE *fp, ulong highlight ) +print_path( int pathlen, TN ME .........., FILE *fp, ulong highlight ) { int rc, c, i; u32 keyid[2]; @@ -1475,37 +1347,89 @@ print_path( int pathlen, TRUST_INFO *path, FILE *fp, ulong highlight ) putc('\n', fp ); } } +#endif + static int -cmp_tsl_array( const void *xa, const void *xb ) +propagate_validity( TN node ) { - TRUST_SEG_LIST a = *(TRUST_SEG_LIST*)xa; - TRUST_SEG_LIST b = *(TRUST_SEG_LIST*)xb; - return a->pathlen - b->pathlen; + TN kr, ur; + int max_validity = 0; + + assert( !node->is_uid ); + if( node->n.k.ownertrust == TRUST_ULTIMATE ) { + /* this is one of our keys */ + assert( !node->list ); /* This should be a leaf */ + return TRUST_ULTIMATE; + } + + /* loop over all user ids */ + for( ur=node->list; ur; ur = ur->next ) { + assert( ur->is_uid ); + /* loop over all signators */ + for(kr=ur->list; kr; kr = kr->next ) { + int val = propagate_validity( kr ); + + if( val == TRUST_ULTIMATE ) { + ur->n.u.fully_count = opt.completes_needed; + } + else if( val == TRUST_FULLY ) { + if( kr->n.k.ownertrust == TRUST_FULLY ) + ur->n.u.fully_count++; + else if( kr->n.k.ownertrust == TRUST_MARGINAL ) + ur->n.u.marginal_count++; + } + } + /* fixme: We can move this test into the loop to stop as soon as + * we have a level of FULLY and return from this function + * We dont do this now to get better debug output */ + if( ur->n.u.fully_count >= opt.completes_needed + || ur->n.u.marginal_count >= opt.marginals_needed ) + ur->n.u.validity = TRUST_FULLY; + else if( ur->n.u.fully_count || ur->n.u.marginal_count ) + ur->n.u.validity = TRUST_MARGINAL; + + if( ur->n.u.validity >= max_validity ) + max_validity = ur->n.u.validity; + } + + node->n.k.validity = max_validity; + return max_validity; } static void -sort_tsl_list( TRUST_SEG_LIST *trust_seg_list ) +print_default_uid( ulong lid ) { - TRUST_SEG_LIST *array, *tail, tsl; - size_t n; + u32 keyid[2]; + + if( !keyid_from_lid( lid, keyid ) ) + print_user_id( "", keyid ); +} + - for(n=0, tsl = *trust_seg_list; tsl; tsl = tsl->next ) - n++; - array = m_alloc( (n+1) * sizeof *array ); - for(n=0, tsl = *trust_seg_list; tsl; tsl = tsl->next ) - array[n++] = tsl; - array[n] = NULL; - qsort( array, n, sizeof *array, cmp_tsl_array ); - *trust_seg_list = NULL; - tail = trust_seg_list; - for(n=0; (tsl=array[n]); n++ ) { - *tail = tsl; - tail = &tsl->next; - } - m_free( array ); +static void +dump_tn_tree( int indent, TN tree ) +{ + TN kr, ur; + + for( kr=tree; kr; kr = kr->next ) { + printf("%*s", indent*4, "" ); + printf("K%lu(ot=%d,val=%d) ", kr->lid, + kr->n.k.ownertrust, + kr->n.k.validity ); + print_default_uid( kr->lid ); + for( ur=kr->list; ur; ur = ur->next ) { + printf("%*s ", indent*4, "" ); + printf("U%lu(mc=%d,fc=%d,val=%d)\n", ur->lid, + ur->n.u.marginal_count, + ur->n.u.fully_count, + ur->n.u.validity + ); + dump_tn_tree( indent+1, ur->list ); + } + } } @@ -1515,10 +1439,7 @@ list_trust_path( const char *username ) int rc; ulong lid; TRUSTREC rec; - #if 0 - TRUST_INFO *tmppath; - TRUST_SEG_LIST trust_seg_list, tsl, tsl2; - #endif + TN tree; PKT_public_key *pk = m_alloc_clear( sizeof *pk ); INIT_TRUSTDB(); @@ -1540,49 +1461,12 @@ list_trust_path( const char *username ) lid = pk->local_id; free_public_key( pk ); - #if 0 - /* collect the paths */ - tmppath = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *tmppath ); - trust_seg_list = NULL; - collect_paths( 0, opt.max_cert_depth, 1, &rec, tmppath, &trust_seg_list ); - m_free( tmppath ); - sort_tsl_list( &trust_seg_list ); - /* and now print them */ - for(tsl = trust_seg_list; tsl; tsl = tsl->next ) { - print_path( tsl->pathlen, tsl->path, stdout, 0 ); - if( tsl->next ) - putchar('\n'); - } - - /* release the list */ - for(tsl = trust_seg_list; tsl; tsl = tsl2 ) { - tsl2 = tsl->next; - m_free( tsl ); - } - trust_seg_list = NULL; - #else /* test code */ - { - CERT_ITEM *stack; - CERT_CHAIN chains, r; - int i; - - chains = NULL; - stack = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *stack ); - find_cert_chain( lid, 0, opt.max_cert_depth, stack, &chains); - m_free( stack ); - /* dump chains */ - printf("lid/uid(ownertrust,validity):\n"); - for(r=chains; r ; r = r->next ) { - printf("chain:" ); - for(i=0; i < r->nitems; i++ ) - printf(" %lu/%lu(%d,%d)", r->items[i].lid, r->items[i].uid, - r->items[i].ownertrust, - (r->items[i].uid_flags & UIDF_VALVALID )? - r->items[i].uid_validity : 0 ); - putchar('\n'); - } - } - #endif + tree = build_cert_tree( lid, 0, opt.max_cert_depth, NULL ); + if( tree ) + propagate_validity( tree ); + dump_tn_tree( 0, tree ); + printf("(alloced tns=%d max=%d)\n", alloced_tns, max_alloced_tns ); + release_tn_tree( tree ); } @@ -1789,7 +1673,7 @@ update_trustdb( ) * is not necessary to check this if we use a local pubring. Hmmmm. */ int -check_trust( PKT_public_key *pk, unsigned *r_trustlevel ) +check_trust( PKT_public_key *pk, unsigned *r_trustlevel, const byte *namehash ) { TRUSTREC rec; unsigned trustlevel = TRUST_UNKNOWN; @@ -1839,7 +1723,7 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel ) trustlevel = TRUST_EXPIRED; } else { - rc = do_check( &rec, &trustlevel ); + rc = do_check( &rec, &trustlevel, namehash ); if( rc ) { log_error(_("key %08lX.%lu: trust check failed: %s\n"), (ulong)keyid[1], pk->local_id, g10_errstr(rc)); @@ -1859,13 +1743,13 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel ) int -query_trust_info( PKT_public_key *pk ) +query_trust_info( PKT_public_key *pk, const byte *namehash ) { unsigned trustlevel; int c; INIT_TRUSTDB(); - if( check_trust( pk, &trustlevel ) ) + if( check_trust( pk, &trustlevel, namehash ) ) return '?'; if( trustlevel & TRUST_FLAG_REVOKED ) return 'r'; @@ -1899,13 +1783,15 @@ int enum_cert_paths( void **context, ulong *lid, unsigned *ownertrust, unsigned *validity ) { + return -1; + #if 0 struct enum_cert_paths_ctx *ctx; - TRUST_SEG_LIST tsl; + fixme: ..... tsl; INIT_TRUSTDB(); if( !lid ) { /* release the context */ if( *context ) { - TRUST_SEG_LIST tsl2; + FIXME: ........tsl2; ctx = *context; for(tsl = ctx->tsl_head; tsl; tsl = tsl2 ) { @@ -1918,7 +1804,7 @@ enum_cert_paths( void **context, ulong *lid, } if( !*context ) { - TRUST_INFO *tmppath; + FIXME .... *tmppath; TRUSTREC rec; if( !*lid ) @@ -1927,12 +1813,14 @@ enum_cert_paths( void **context, ulong *lid, ctx = m_alloc_clear( sizeof *ctx ); *context = ctx; /* collect the paths */ + #if 0 read_record( *lid, &rec, RECTYPE_DIR ); tmppath = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *tmppath ); tsl = NULL; collect_paths( 0, opt.max_cert_depth, 1, &rec, tmppath, &tsl ); m_free( tmppath ); sort_tsl_list( &tsl ); + #endif /* setup the context */ ctx->tsl_head = tsl; ctx->tsl = ctx->tsl_head; @@ -1956,6 +1844,7 @@ enum_cert_paths( void **context, ulong *lid, *lid = tsl->path[ctx->idx].lid; ctx->idx++; return ctx->idx-1; + #endif } @@ -1966,8 +1855,10 @@ void enum_cert_paths_print( void **context, FILE *fp, int refresh, ulong selected_lid ) { + return; + #if 0 struct enum_cert_paths_ctx *ctx; - TRUST_SEG_LIST tsl; + FIXME......... tsl; if( !*context ) return; @@ -2001,6 +1892,7 @@ enum_cert_paths_print( void **context, FILE *fp, } print_path( tsl->pathlen, tsl->path, fp, selected_lid ); + #endif } @@ -2035,7 +1927,7 @@ get_ownertrust_info( ulong lid ) * Return an allocated buffer with the preference values for * the key with LID and the userid which is identified by the * HAMEHASH or the firstone if namehash is NULL. ret_n receives - * the length of the allcoated buffer. Structure of the buffer is + * the length of the allocated buffer. Structure of the buffer is * a repeated sequences of 2 bytes; where the first byte describes the * type of the preference and the second one the value. The constants * PREFTYPE_xxxx should be used to reference a type. @@ -2616,6 +2508,10 @@ upd_uid_record( KBNODE keyblock, KBNODE uidnode, u32 *keyid, ulong recno, newrecno; int rc; + if( DBG_TRUST ) + log_debug("upd_uid_record for %08lX/%02X%02X\n", + (ulong)keyid[1], uidhash[18], uidhash[19]); + /* see whether we already have an uid record */ rmd160_hash_buffer( uidhash, uid->name, uid->len ); for( recno=drec->r.dir.uidlist; recno; recno = urec.r.uid.next ) { @@ -2785,6 +2681,11 @@ upd_pref_record( TRUSTREC *urec, u32 *keyid, PKT_signature *sig ) byte prefs_rec[200]; int n_prefs_rec = 0; + if( DBG_TRUST ) + log_debug("upd_pref_record for %08lX.%lu/%02X%02X\n", + (ulong)keyid[1], lid, uidhash[18], uidhash[19] ); + + /* check for changed preferences */ for(k=0; ptable[k].subpkttype; k++ ) { s = parse_sig_subpkt2( sig, ptable[k].subpkttype, &n ); @@ -2884,8 +2785,8 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid, * later. The problem with this is that we must somewhere store * the information about this signature (we need a record id). * We do this by using the record type shadow dir, which will - * be converted to a dir record as soon as a new public key is - * inserted into the trustdb. + * be converted to a dir record as soon as the missing public key + * gets inserted into the trustdb. */ ulong lid = drec->recnum; PKT_signature *sig = signode->pkt->pkt.signature; @@ -2901,6 +2802,12 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid, int found_delrec = 0; int rc; + + if( DBG_TRUST ) + log_debug("upd_cert_record for %08lX.?/%02X%02X/%08lX\n", + (ulong)keyid[1], uidhash[18], + uidhash[19], (ulong)sig->keyid[1] ); + delrec.recnum = 0; /* get the LID of the pubkey of the signature under verification */ @@ -2976,13 +2883,12 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid, rec.r.sig.sig[i].flag |= SIGF_REVOKED; } else if( rc == G10ERR_NO_PUBKEY ) { - #if 0 /* fixme: For some reason this really happens? */ + /* fixme: For some reason this really happens? */ if( (rec.r.sig.sig[i].flag & SIGF_CHECKED) ) log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n", (ulong)keyid[1], lid, uidhash[18], uidhash[19], (ulong)sig->keyid[1], _("Hmmm, public key lost?") ); - #endif rec.r.sig.sig[i].flag = SIGF_NOPUBKEY; if( revoked ) rec.r.sig.sig[i].flag |= SIGF_REVOKED; @@ -3061,7 +2967,7 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid, newflag |= SIGF_REVOKED; } else if( rc == G10ERR_NO_PUBKEY ) { - if( opt.verbose > 1 ) + if( opt.verbose > 1 || DBG_TRUST ) log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n", (ulong)keyid[1], lid, uidhash[18], uidhash[19], (ulong)sig->keyid[1], g10_errstr(rc) ); @@ -3266,9 +3172,6 @@ insert_trust_record( PKT_public_key *pk ) INIT_TRUSTDB(); - if( pk->local_id ) - log_bug("pk->local_id=%lu\n", pk->local_id ); - fingerprint_from_pk( pk, fingerprint, &fingerlen ); /* fixme: assert that we do not have this record. @@ -3289,6 +3192,13 @@ insert_trust_record( PKT_public_key *pk ) goto leave; } + if( pk->local_id ) { + log_debug("insert_trust_reord with pk->local_id=%lu\n", pk->local_id ); + rc = update_trust_record( keyblock, 1, NULL ); + release_kbnode( keyblock ); + return rc; + } + /* check that we used the primary key (we are little bit paranoid) */ { PKT_public_key *a_pk; u32 akid[2], bkid[2]; diff --git a/g10/trustdb.h b/g10/trustdb.h index 3dd6b6203..303ffc761 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -49,8 +49,8 @@ void register_trusted_key( const char *string ); 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 ); +int check_trust( PKT_public_key *pk, unsigned *r_trustlevel, const byte* nh ); +int query_trust_info( PKT_public_key *pk, const byte *nh ); int enum_cert_paths( void **context, ulong *lid, unsigned *ownertrust, unsigned *validity ); void enum_cert_paths_print( void **context, FILE *fp, |