See ChangeLog: Thu Jan 21 06:22:10 CET 1999 Werner Koch
[gnupg.git] / g10 / trustdb.c
index fbfb807..674240a 100644 (file)
@@ -1,14 +1,14 @@
 /* trustdb.c
  *     Copyright (C) 1998 Free Software Foundation, Inc.
  *
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
  *
- * GNUPG is free software; you can redistribute it and/or modify
+ * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * GNUPG is distributed in the hope that it will be useful,
+ * GnuPG is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -81,6 +81,13 @@ struct trust_seg_list {
 };
 
 
+struct enum_cert_paths_ctx {
+   int init;
+   TRUST_SEG_LIST tsl_head;
+   TRUST_SEG_LIST tsl;
+   int idx;
+};
+
 
 struct recno_list_struct {
     struct recno_list_struct *next;
@@ -98,6 +105,7 @@ 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 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 get_dir_record( PKT_public_key *pk, TRUSTREC *rec );
@@ -131,7 +139,7 @@ static void
 die_invalid_db()
 {
     log_error(_(
-       "The trust DB is corrupted; please run \"gpgm --fix-trust-db\".\n") );
+       "The trustdb is corrupted; please run \"gpgm --fix-trustdb\".\n") );
     g10_exit(2);
 }
 
@@ -187,7 +195,7 @@ do_sync( )
     int rc = tdbio_sync();
     if( !rc )
        return;
-    log_error(_("trust db: sync failed: %s\n"), g10_errstr(rc) );
+    log_error(_("trustdb: sync failed: %s\n"), g10_errstr(rc) );
     g10_exit(2);
 }
 
@@ -890,17 +898,23 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
            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) )
-                   continue; /* skip unchecked signatures */
-               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 */
+               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) */
@@ -923,7 +937,7 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
                                                        trust_seg_head );
                nt &= TRUST_MASK;
 
-               if( nt < TRUST_MARGINAL ) {
+               if( nt < TRUST_MARGINAL || unchecked ) {
                    continue;
                }
 
@@ -1175,7 +1189,7 @@ import_ownertrust( const char *fname )
            continue;
        n = strlen(line);
        if( line[n-1] != '\n' ) {
-           log_error_f(fname, _("line to long\n") );
+           log_error_f(fname, _("line too long\n") );
            /* ... or last line does not have a LF */
            break; /* can't continue */
        }
@@ -1206,10 +1220,10 @@ import_ownertrust( const char *fname )
        rc = tdbio_search_dir_byfpr( line, fprlen, 0, &rec );
        if( !rc ) { /* found: update */
            if( rec.r.dir.ownertrust )
-               log_info(_("LID %lu: changing trust from %u to %u\n"),
+               log_info("LID %lu: changing trust from %u to %u\n",
                          rec.r.dir.lid, rec.r.dir.ownertrust, otrust );
            else
-               log_info(_("LID %lu: setting trust to %u\n"),
+               log_info("LID %lu: setting trust to %u\n",
                                   rec.r.dir.lid, otrust );
            rec.r.dir.ownertrust = otrust;
            write_record( &rec );
@@ -1249,7 +1263,7 @@ import_ownertrust( const char *fname )
 
 
 static void
-print_path( int pathlen, TRUST_INFO *path )
+print_path( int pathlen, TRUST_INFO *path, FILE *fp, ulong highlight )
 {
     int rc, c, i;
     u32 keyid[2];
@@ -1257,35 +1271,67 @@ print_path( int pathlen, TRUST_INFO *path )
     size_t n;
 
     for( i = 0; i < pathlen; i++ )  {
-       printf("%*s", i*2, "" );
+       if( highlight )
+           fputs(highlight == path[i].lid? "* ":"  ", fp );
        rc = keyid_from_lid( path[i].lid, keyid );
        if( rc )
-           printf("????????.%lu:", path[i].lid );
+           fprintf(fp, "????????.%lu:", path[i].lid );
        else
-           printf("%08lX.%lu:", (ulong)keyid[1], path[i].lid );
+           fprintf(fp,"%08lX.%lu:", (ulong)keyid[1], path[i].lid );
        c = trust_letter(path[i].otrust);
        if( c )
-           putchar( c );
+           putc( c, fp );
        else
-           printf( "%02x", path[i].otrust );
-       putchar('/');
+           fprintf( fp, "%02x", path[i].otrust );
+       putc('/', fp);
        c = trust_letter(path[i].trust);
        if( c )
-           putchar( c );
+           putc( c, fp );
        else
-           printf( "%02x", path[i].trust );
-       putchar(' ');
+           fprintf( fp, "%02x", path[i].trust );
+       putc(' ', fp);
        p = get_user_id( keyid, &n );
-       putchar(' ');
-       putchar('\"');
-       print_string( stdout, p, n > 40? 40:n, 0 );
-       putchar('\"');
+       putc(' ', fp);
+       putc('\"', fp);
+       print_string( fp, p, n > 40? 40:n, 0 );
+       putc('\"', fp);
        m_free(p);
-       putchar('\n');
+       putc('\n', fp );
     }
 }
 
 
+static int
+cmp_tsl_array( const void *xa, const void *xb )
+{
+    TRUST_SEG_LIST a = *(TRUST_SEG_LIST*)xa;
+    TRUST_SEG_LIST b = *(TRUST_SEG_LIST*)xb;
+    return a->pathlen - b->pathlen;
+}
+
+
+static void
+sort_tsl_list( TRUST_SEG_LIST *trust_seg_list )
+{
+    TRUST_SEG_LIST *array, *tail, tsl;
+    size_t n;
+
+    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 );
+}
+
 
 void
 list_trust_path( const char *username )
@@ -1318,9 +1364,12 @@ list_trust_path( const char *username )
     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 );
+       print_path( tsl->pathlen, tsl->path, stdout, 0 );
+       if( tsl->next )
+           putchar('\n');
     }
 
     /* release the list */
@@ -1638,12 +1687,7 @@ int
 enum_cert_paths( void **context, ulong *lid,
                 unsigned *ownertrust, unsigned *validity )
 {
-    struct {
-       int init;
-       TRUST_SEG_LIST tsl_head;
-       TRUST_SEG_LIST tsl;
-       int idx;
-    } *ctx;
+    struct enum_cert_paths_ctx *ctx;
     TRUST_SEG_LIST tsl;
 
     if( !lid ) {  /* release the context */
@@ -1675,7 +1719,8 @@ enum_cert_paths( void **context, ulong *lid,
        tsl = NULL;
        collect_paths( 0, opt.max_cert_depth, 1, &rec, tmppath, &tsl );
        m_free( tmppath );
-       /* and now print them */
+       sort_tsl_list( &tsl );
+       /* setup the context */
        ctx->tsl_head = tsl;
        ctx->tsl = ctx->tsl_head;
        ctx->idx = 0;
@@ -1702,6 +1747,50 @@ enum_cert_paths( void **context, ulong *lid,
 
 
 /****************
+ * Print the current path
+ */
+void
+enum_cert_paths_print( void **context, FILE *fp,
+                                      int refresh, ulong selected_lid )
+{
+    struct enum_cert_paths_ctx *ctx;
+    TRUST_SEG_LIST tsl;
+
+    if( !*context )
+       return;
+    ctx = *context;
+    if( !ctx->tsl )
+       return;
+    tsl = ctx->tsl;
+
+    if( !fp )
+       fp = stderr;
+
+    if( refresh ) { /* update the ownertrust and if possible the validity */
+       int i;
+       int match = tdbio_db_matches_options();
+
+       for( i = 0; i < tsl->pathlen; i++ )  {
+           TRUSTREC rec;
+
+           read_record( tsl->path[i].lid, &rec, RECTYPE_DIR );
+           tsl->path[i].otrust = rec.r.dir.ownertrust;
+           /* update validity only if we have it in the cache
+            * calculation is too time consuming */
+           if( match && (rec.r.dir.dirflags & DIRF_VALVALID)
+                     && rec.r.dir.validity ) {
+               tsl->path[i].trust = rec.r.dir.validity;
+               if( rec.r.dir.dirflags & DIRF_REVOKED )
+                   tsl->path[i].trust = TRUST_FLAG_REVOKED;
+           }
+       }
+    }
+
+    print_path( tsl->pathlen, tsl->path, fp, selected_lid );
+}
+
+
+/****************
  * Return the assigned ownertrust value for the given LID
  */
 unsigned
@@ -2850,9 +2939,18 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
     /* delete keyrecords from the trustdb which are not anymore used */
     /* should we really do this, or is it better to keep them and */
     /* mark as unused? */
+    /* And set the revocation flag into the dir record */
+    drec.r.dir.dirflags &= ~DIRF_REVOKED;
     lastrecno = 0;
     for( recno=drec.r.dir.keylist; recno; recno = krec.r.key.next ) {
        read_record( recno, &krec, RECTYPE_KEY );
+       if( recno == drec.r.dir.keylist ) { /* this is the primary key */
+           if( (krec.r.key.keyflags & KEYF_REVOKED) ) {
+               drec.r.dir.dirflags |= DIRF_REVOKED;
+               drec.dirty = 1;
+           }
+       }
+
        if( !qry_recno_list( recno_list, recno, RECTYPE_KEY ) ) {
            /* delete this one */
            if( !lastrecno ) {
@@ -2905,11 +3003,11 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
     if( rc )
        rc = tdbio_cancel_transaction();
     else {
+       if( modified && tdbio_is_dirty() )
+           *modified = 1;
        drec.r.dir.dirflags |= DIRF_CHECKED;
        drec.r.dir.dirflags &= ~DIRF_VALVALID;
        write_record( &drec );
-       if( modified && tdbio_is_dirty() )
-           *modified = 1;
        rc = tdbio_end_transaction();
     }
     rel_recno_list( &recno_list );