diff options
Diffstat (limited to '')
-rw-r--r-- | g10/trustdb.c | 636 |
1 files changed, 273 insertions, 363 deletions
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]; |