Trust stuff works partly.
authorWerner Koch <wk@gnupg.org>
Sat, 24 Jan 1998 16:32:27 +0000 (16:32 +0000)
committerWerner Koch <wk@gnupg.org>
Sat, 24 Jan 1998 16:32:27 +0000 (16:32 +0000)
18 files changed:
README
VERSION
acconfig.h
cipher/random.c
config.h.in
configure.in
g10/build-packet.c
g10/comment.c
g10/g10.c
g10/options.h
g10/pkclist.c
g10/trustdb.c
g10/trustdb.h
include/iobuf.h
include/util.h
mpi/longlong.h
mpi/mpi-bit.c
util/argparse.c

diff --git a/README b/README
index 55be1b2..1f2879c 100644 (file)
--- a/README
+++ b/README
 
     4) You end up with a binary "g10" in /usr/local/bin
 
+    5) create a directory ".g10" under your hoem directory ("mkdir ~/.g10")
 
 
 
-    Resources
-    ---------
-    G10 needs a directory "~/.g10" to store the default keyrings
-    and other files.
-
-
     Key Generation
     --------------
 
@@ -75,8 +70,9 @@
     good random numbers for prime number generation, it uses a /dev/random
     which will emit only bytes if the kernel can gather enough entropy.
     If you see no progress, you should start some other activities such
-    as mouse moves or a "find /".  Because we have no hardware device
-    to generate random we have to use this method.
+    as mouse moves, "find /" or using the keyboard (on another window).
+    Because we have no hardware device to generate random we have to use
+    this method.
 
     Key generation shows progress by printing different characters to
     stderr:
 
        g10 --sign-key Donald
 
-    To sign the key of of "Donald" with your default userid
+    This let you sign the key of "Donald" with your default userid.
 
        g10 --sign-key -u Karl -u Joe Donald
 
-    To sign the key of of "Donald" with the userids of "Karl" and "Joe".
+    This let you sign the key of of "Donald" with the userids of "Karl"
+    and "Joe".
     All existing signatures are checked, if some are invalid, a menu is
     offered to delete some of them, and the you are asked for every user
     wether you want to sign this key.
 
-    You may remove a signature at any time by usiing the option "--edit-sig",
-    which also asks for the sigs to remove.
+    You may remove a signature at any time using the option "--edit-sig",
+    which asks for the sigs to remove.
 
 
     Sign
     Ditto, but sign the file with the user id "Suttner"
 
 
-
-    Examine a data or key file
-    --------------------------
-
-       g10 --list-packets datafile
-
-    Use this to list the contents of a data file. If the file is encrypted
-    you are asked for the passphrase, so that G10 is able to look at the
-    inner structure of a encrypted packet.
-
-
     Batch mode
     ----------
     If you use the option "--batch", G10 runs in non-interactive mode and
     you can use the option "--passhrase-fd n", which works like PGPs
     PGPPASSFD.
 
-    Batch mode also causes PGP to terminate as soon as a BAD signature is
+    Batch mode also causes G10 to terminate as soon as a BAD signature is
     detected.
 
 
     stderr to get detailed informations about the errors.
 
 
+    Esoteric commands
+    -----------------
+
+       g10 --list-packets datafile
+
+    Use this to list the contents of a data file. If the file is encrypted
+    you are asked for the passphrase, so that G10 is able to look at the
+    inner structure of a encrypted packet.
+
+       --quick-random
+
+    Do not use the stroing random generator but a faster one.  This can be
+    used to generate keys for tests; those are marked as insecure.
+
+       --list-trustdb
+
+    List the contents of the trustdb in a human readable format
+
+       --list-trustdb  <usernames>
+
+    List the tree of certificates for the given usernames
+
+       --list-trust-path  depth  username
+
+    List the possible trust paths for the given username, up to the specified
+    depth.  If depth is negative, duplicate introducers are not listed,
+    because those would increase the trust probabilty only minimal.
+    (you must use the special option "--" to stop option parsing when
+     using a negative number)
+
+       --print-mds  filenames
+
+    List all available message digest values for the fiven filenames
+
+       --gen-prime n
+
+    Generate and print a simple prime number of size n
+
+       --gen-prime n q
+
+    Generate a prime number suitable for ElGamal signatures of size n with
+    a q as largest primefactor of n-1.
+
+       --gen-prime n q 1
+
+    Ditto, but calculate a generator too.
+
+
+    For more options/commands see the file g10/OPTIONS.
+
 
     Debug Flags
     -----------
          32    memory allocation stuff
          64    caching
          128   show memory statistics at exit
-
+         256   trust verification stuff
 
 
     Other Notes
diff --git a/VERSION b/VERSION
index b1e80bb..845639e 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.3
+0.1.4
index 113ec9f..3f83ef1 100644 (file)
 @BOTTOM@
 
 
+/* The AC_CHECK_SIZEOF() fails for some machines.
+ * we provide some fallback values here */
+#if !SIZEOF_UNSIGNED_SHORT
+  #undef SIZEOF_UNSIGNED_SHORT
+  #define SIZEOF_UNSIGNED_SHORT 2
+#endif
+#if !SIZEOF_UNSIGNED_INT
+  #undef SIZEOF_UNSIGNED_INT
+  #define SIZEOF_UNSIGNED_INT 4
+#endif
+#if !SIZEOF_UNSIGNED_LONG
+  #undef SIZEOF_UNSIGNED_LONG
+  #define SIZEOF_UNSIGNED_LONG 4
+#endif
+
+
 #endif /*G10_CONFIG_H*/
index b082022..dbf7147 100644 (file)
@@ -167,6 +167,10 @@ the OS a chance to collect more entropy! (Need %d more bytes)\n", length );
 #else /* not HAVE_DEV_RANDOM */
 
 
+#ifndef RAND_MAX   /* for SunOS */
+  #define RAND_MAX 32767
+#endif
+
 static void
 fill_buffer( byte *buffer, size_t length, int level )
 {
@@ -178,11 +182,20 @@ fill_buffer( byte *buffer, size_t length, int level )
                   "it compile - it is in no way a strong RNG!\n\n"
                   "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n");
        initialized=1;
+      #ifdef HAVE_RAND
        srand(make_timestamp()*getpid());
+      #else
+       srandom(make_timestamp()*getpid());
+      #endif
     }
 
+  #ifdef HAVE_RAND
     while( length-- )
        *buffer++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
+  #else
+    while( length-- )
+       *buffer++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
+  #endif
 }
 
 #endif
index 2a3bd36..94550cc 100644 (file)
@@ -72,6 +72,9 @@
 /* The number of bytes in a unsigned short.  */
 #undef SIZEOF_UNSIGNED_SHORT
 
+/* Define if you have the rand function.  */
+#undef HAVE_RAND
+
 /* Define if you have the stpcpy function.  */
 #undef HAVE_STPCPY
 
@@ -81,6 +84,9 @@
 /* Define if you have the strlwr function.  */
 #undef HAVE_STRLWR
 
+/* Define if you have the strtoul function.  */
+#undef HAVE_STRTOUL
+
 /* Define if you have the tcgetattr function.  */
 #undef HAVE_TCGETATTR
 
 #undef HAVE_ZLIB_H
 
 
+/* The AC_CHECK_SIZEOF() fails for some machines.
+ * we provide some fallback values here */
+#if !SIZEOF_UNSIGNED_SHORT
+  #undef SIZEOF_UNSIGNED_SHORT
+  #define SIZEOF_UNSIGNED_SHORT 2
+#endif
+#if !SIZEOF_UNSIGNED_INT
+  #undef SIZEOF_UNSIGNED_INT
+  #define SIZEOF_UNSIGNED_INT 4
+#endif
+#if !SIZEOF_UNSIGNED_LONG
+  #undef SIZEOF_UNSIGNED_LONG
+  #define SIZEOF_UNSIGNED_LONG 4
+#endif
+
+
 #endif /*G10_CONFIG_H*/
index 6a97d41..39e8776 100644 (file)
@@ -8,7 +8,7 @@ AC_CONFIG_AUX_DIR(scripts)
 AC_CONFIG_HEADER(config.h)
 
 
-VERSION=`cat ./VERSION`
+VERSION=`cat $srcdir/VERSION`
 PACKAGE=g10
 AC_SUBST(VERSION)
 AC_SUBST(PACKAGE)
@@ -90,10 +90,6 @@ dnl Checks for libraries.
 dnl Checks for header files.
 AC_HEADER_STDC
 AC_CHECK_HEADERS(unistd.h)
-AC_CHECK_HEADERS(zlib.h,
-                [LIBS="$LIBS -lz"],
-                AC_MSG_WARN([zlib missing - creating without ZLIB support!])
-               )
 
 
 dnl Checks for typedefs, structures, and compiler characteristics.
@@ -150,12 +146,20 @@ AC_CHECK_SIZEOF(unsigned short, 2)
 AC_CHECK_SIZEOF(unsigned int, 4)
 AC_CHECK_SIZEOF(unsigned long, 4)
 
+if test "$ac_cv_sizeof_unsigned_short" = "0" \
+   || test "$ac_cv_sizeof_unsigned_int" = "0" \
+   || test "$ac_cv_sizeof_unsigned_long" = "0"; then
+    AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]);
+fi
 
 
 
 dnl Checks for library functions.
 AC_FUNC_VPRINTF
-AC_CHECK_FUNCS(strerror stpcpy strlwr tcgetattr)
+AC_CHECK_FUNCS(strerror stpcpy strlwr tcgetattr rand strtoul)
+
+
+
 
 dnl check wether we have a random device
 AC_CACHE_CHECK(for random device, ac_cv_have_dev_random,
@@ -175,8 +179,8 @@ if test "$ac_cv_mpi_config_done" = yes; then
     AC_MSG_RESULT(done)
 else
 ac_cv_mpi_config_done=""
-if test -f ./mpi/config.links ; then
-    . ./mpi/config.links
+if test -f $srcdir/mpi/config.links ; then
+    . $srcdir/mpi/config.links
     ac_cv_mpi_extra_asm_modules="$mpi_extra_modules"
     AC_LINK_FILES( ${mpi_ln_src}, ${mpi_ln_dst} )
     ac_cv_mpi_config_done="yes"
@@ -198,11 +202,18 @@ fi
 AC_SUBST(MPI_EXTRA_ASM_OBJS)
 
 
+dnl Do we have zlib? Must do it here because Solaris failed
+dnl when compiling a conftest (due to the "-lz" from LIBS).
+AC_CHECK_HEADERS(zlib.h,
+                [LIBS="$LIBS -lz"],
+                AC_MSG_WARN([zlib missing - creating without ZLIB support!])
+               )
+
 dnl checking whether we have other cipher source files
 CIPHER_EXTRA_OBJS=""
 CIPHER_EXTRA_DIST=""
 AC_CACHE_CHECK(for extra cipher modules, ac_cv_have_rsa_cipher,
-[if test -f cipher/rsa.c && test -f cipher/rsa.h; then
+[if test -f $srcdir/cipher/rsa.c && test -f $srcdir/cipher/rsa.h; then
   ac_cv_have_rsa_cipher=yes; else ac_cv_have_rsa_cipher=no; fi])
 if test $ac_cv_have_rsa_cipher = yes; then
     AC_DEFINE(HAVE_RSA_CIPHER)
index a541c8c..b0fd085 100644 (file)
@@ -147,9 +147,11 @@ calc_packet_length( PACKET *pkt )
 static int
 do_comment( IOBUF out, int ctb, PKT_comment *rem )
 {
-    write_header(out, ctb, rem->len);
-    if( iobuf_write( out, rem->data, rem->len ) )
-       return G10ERR_WRITE_FILE;
+    if( !opt.no_comment ) {
+       write_header(out, ctb, rem->len);
+       if( iobuf_write( out, rem->data, rem->len ) )
+           return G10ERR_WRITE_FILE;
+    }
     return 0;
 }
 
index 4d50452..00bbac7 100644 (file)
@@ -57,9 +57,10 @@ write_comment( IOBUF out, const char *s )
 KBNODE
 make_comment_node( const char *s )
 {
-    PACKET *pkt = m_alloc_clear( sizeof *pkt );
+    PACKET *pkt;
     size_t n = strlen(s);
 
+    pkt = m_alloc_clear( sizeof *pkt );
     pkt->pkttype = PKT_COMMENT;
     pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n - 1 );
     pkt->pkt.comment->len = n;
index a00a3f9..d36717a 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -190,6 +190,7 @@ main( int argc, char **argv )
     { 531, "list-trustdb",0 , "\r"},
     { 532, "quick-random", 0, "\r"},
     { 533, "list-trust-path",0, "\r"},
+    { 534, "no-comment", 0,   "do not write comment packets"},
 
     {0} };
     ARGPARSE_ARGS pargs;
@@ -336,6 +337,7 @@ main( int argc, char **argv )
          case 531: set_cmd( &cmd, aListTrustDB); break;
          case 532: quick_random_gen(1); break;
          case 533: set_cmd( &cmd, aListTrustPath); break;
+         case 534: opt.no_comment=1; break;
          default : errors++; pargs.err = configfp? 1:2; break;
        }
     }
index 3b72547..7a9a4c5 100644 (file)
@@ -39,7 +39,7 @@ struct {
     int def_cipher_algo;
     int def_pubkey_algo;
     int def_digest_algo;
-    int reserved9;
+    int no_comment;
     int reserved10;
     int reserved11;
     int reserved12;
index bd871a9..5381ac3 100644 (file)
 #include "trustdb.h"
 #include "ttyio.h"
 
+/****************
+ * Returns true if a ownertrust has changed.
+ */
 static int
-query_ownertrust( PKT_public_cert *pkc )
+query_ownertrust( ulong lid )
 {
     char *p;
+    int rc;
     size_t n;
     u32 keyid[2];
+    PKT_public_cert *pkc ;
+    int changed=0;
+
+    rc = keyid_from_trustdb( lid, keyid );
+    if( rc ) {
+       log_error("ooops: can't get keyid for lid %lu\n", lid);
+       return 0;
+    }
+
+    pkc = m_alloc_clear( sizeof *pkc );
+    rc = get_pubkey( pkc, keyid );
+    if( rc ) {
+       log_error("keyid %08lX: pubkey not found: %s\n",
+                               (ulong)keyid[1], g10_errstr(rc) );
+       return 0;
+    }
 
-    keyid_from_pkc( pkc, keyid );
-    tty_printf("No ownertrust specified for:\n"
-              "%4u%c/%08lX %s \"",
+    tty_printf("No ownertrust defined for %lu:\n"
+              "%4u%c/%08lX %s \"", lid,
              nbits_from_pkc( pkc ), pubkey_letter( pkc->pubkey_algo ),
              (ulong)keyid[1], datestr_from_pkc( pkc ) );
     p = get_user_id( keyid, &n );
@@ -72,7 +91,16 @@ query_ownertrust( PKT_public_cert *pkc )
 "to do with the (implicitly created) web-of-certificates.\n");
        }
        else if( !p[1] && (*p >= '1' && *p <= '4') ) {
-           /* okay */
+           unsigned trust;
+           switch( *p ) {
+             case '1': trust = TRUST_UNDEFINED; break;
+             case '2': trust = TRUST_NEVER    ; break;
+             case '3': trust = TRUST_MARGINAL ; break;
+             case '4': trust = TRUST_FULLY    ; break;
+             default: BUG();
+           }
+           if( !update_ownertrust( lid, trust ) )
+               changed++;
            break;
        }
        else if( *p == 's' || *p == 'S' ) {
@@ -81,10 +109,53 @@ query_ownertrust( PKT_public_cert *pkc )
        m_free(p); p = NULL;
     }
     m_free(p);
-    return 0;
+    m_free(pkc);
+    return changed;
 }
 
 
+/****************
+ * Try to add some more owner trusts (interactive)
+ * Returns: -1 if no ownertrust were added.
+ */
+static int
+add_ownertrust( PKT_public_cert *pkc )
+{
+    int rc;
+    void *context = NULL;
+    ulong lid;
+    unsigned trust;
+    int any=0;
+
+    tty_printf(
+"Could not find a valid trust path to the key.  Lets see, wether we\n"
+"can assign some missing owner trust values.\n\n");
+
+    rc = query_trust_record( pkc );
+    if( rc ) {
+       log_error("Ooops: not in trustdb\n");
+       return -1;
+    }
+
+    lid = pkc->local_id;
+    while( !(rc=enum_trust_web( &context, &lid )) ) {
+       rc = get_ownertrust( lid, &trust );
+       if( rc )
+           log_fatal("Ooops: couldn't get ownertrust for %lu\n", lid);
+       if( trust == TRUST_UNDEFINED || trust == TRUST_EXPIRED ||
+           trust == TRUST_UNKNOWN ) {
+           if( query_ownertrust( lid ) )
+               any=1;
+       }
+    }
+    if( rc == -1 )
+       rc = 0;
+    enum_trust_web( &context, NULL ); /* close */
+
+
+    return rc? rc : any? 0:-1;
+}
+
 
 /****************
  * Check wether we can trust this pkc which has a trustlevel of TRUSTLEVEL
@@ -119,7 +190,15 @@ do_we_trust( PKT_public_cert *pkc, int trustlevel )
        if( opt.batch || opt.answer_no )
            log_info("no info to calculate a trust probability\n");
        else {
-           query_ownertrust( pkc );
+           rc = add_ownertrust( pkc );
+           if( !rc ) {
+               rc = check_trust( pkc, &trustlevel );
+               if( rc )
+                   log_fatal("trust check after add_ownertrust failed: %s\n",
+                                                             g10_errstr(rc) );
+               /* FIXME: this is recursive; we better should unroll it */
+               return do_we_trust( pkc, trustlevel );
+           }
        }
        return 0; /* no */
 
@@ -137,7 +216,7 @@ do_we_trust( PKT_public_cert *pkc, int trustlevel )
        return 1; /* yes */
 
       case TRUST_ULTIMATE:
-       log_info("Our own key is always good.\n");
+       log_info("Our own keys is always good.\n");
        return 1; /* yes */
 
       default: BUG();
index 51ee9b8..4f89751 100644 (file)
@@ -110,15 +110,28 @@ struct local_id_info {
 };
 
 
+typedef struct trust_info TRUST_INFO;
+struct trust_info {
+    ulong    lid;
+    unsigned trust;
+};
+
+
 typedef struct trust_seg_list *TRUST_SEG_LIST;
 struct trust_seg_list {
     TRUST_SEG_LIST next;
     int   nseg;     /* number of segmens */
     int   dup;
-    ulong seg[1];   /* segment list */
+    TRUST_INFO seg[1];  /* segment list */
 };
 
 
+typedef struct {
+    TRUST_SEG_LIST tsl;
+    int index;
+} ENUM_TRUST_WEB_CONTEXT;
+
+
 static void create_db( const char *fname );
 static void open_db(void);
 static int  read_record( ulong recnum, TRUSTREC *rec );
@@ -134,11 +147,12 @@ static int qry_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned *flag );
 static void upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag );
 
 static void print_user_id( const char *text, u32 *keyid );
-static int do_list_path( ulong *stack, int depth, int max_depth,
+static int do_list_path( TRUST_INFO *stack, int depth, int max_depth,
                         LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist );
 
 static int list_sigs( ulong pubkey_id );
-static int do_check( ulong pubkeyid, int *trustlevel );
+static int propagate_trust( TRUST_SEG_LIST tslist );
+static int do_check( ulong pubkeyid, unsigned *trustlevel );
 
 
 static char *db_name;
@@ -147,6 +161,9 @@ static int  db_fd = -1;
  * which are the ones from our secrings */
 static LOCAL_ID_INFO *ultikey_table;
 
+static ulong last_trust_web_key;
+static TRUST_SEG_LIST last_trust_web_tslist;
+
 #define buftoulong( p )  ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \
                       (*((byte*)(p)+2) << 8) | (*((byte*)(p)+3)))
 #define buftoushort( p )  ((*((byte*)(p)) << 8) | (*((byte*)(p)+1)))
@@ -642,13 +659,15 @@ void
 list_trust_path( int max_depth, const char *username )
 {
     int rc;
+    int wipe=0;
     int i;
     TRUSTREC rec;
     PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
 
-    if( max_depth < 0 )
-       max_depth = MAX_LIST_SIGS_DEPTH+1;
-
+    if( max_depth < 0 ) {
+       wipe = 1;
+       max_depth = -max_depth;
+    }
 
     if( (rc = get_pubkey_byname( pkc, username )) )
        log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
@@ -658,37 +677,53 @@ list_trust_path( int max_depth, const char *username )
     else if( rc == -1 )
        log_error("user '%s' not in trustdb\n", username);
     else {
-       LOCAL_ID_INFO *lids;
-       LOCAL_ID_INFO *work;
-       ulong stack[MAX_LIST_SIGS_DEPTH];
        TRUST_SEG_LIST tsl, tslist = NULL;
 
-       lids = new_lid_table();
-       stack[0] = pkc->local_id;
-       rc = do_list_path( stack, 1, max_depth, lids, &tslist );
-       /* wipe out duplicates */
-       work = new_lid_table();
-       for( tsl=tslist; tsl; tsl = tsl->next ) {
-           for(i=1; i < tsl->nseg-1; i++ ) {
-               if( ins_lid_table_item( work, tsl->seg[i], 0 ) ) {
-                   tsl->dup = 1; /* mark as duplicate */
-                   break;
+       if( !qry_lid_table_flag( ultikey_table, pkc->local_id, NULL ) ) {
+           tslist = m_alloc( sizeof *tslist );
+           tslist->nseg = 1;
+           tslist->dup = 0;
+           tslist->seg[0].lid = pkc->local_id;
+           tslist->seg[0].trust = 0;
+           tslist->next = NULL;
+           rc = 0;
+       }
+       else {
+           LOCAL_ID_INFO *lids = new_lid_table();
+           TRUST_INFO stack[MAX_LIST_SIGS_DEPTH];
+
+           stack[0].lid = pkc->local_id;
+           stack[0].trust = 0;
+           rc = do_list_path( stack, 1, max_depth, lids, &tslist );
+           if( wipe ) { /* wipe out duplicates */
+               LOCAL_ID_INFO *work;
+
+               work = new_lid_table();
+               for( tsl=tslist; tsl; tsl = tsl->next ) {
+                   for(i=1; i < tsl->nseg-1; i++ ) {
+                       if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) {
+                           tsl->dup = 1; /* mark as duplicate */
+                           break;
+                       }
+                   }
                }
+               release_lid_table(work);
            }
+           release_lid_table(lids);
        }
-       release_lid_table(work);
-
-       release_lid_table(lids);
        if( rc )
            log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
+       rc = propagate_trust( tslist );
+       if( rc )
+           log_error("user '%s' trust problem: %s\n", username, g10_errstr(rc));
        for(tsl = tslist; tsl; tsl = tsl->next ) {
            int i;
 
            if( tsl->dup )
                continue;
-           printf("tslist segs:" );
+           printf("trust path:" );
            for(i=0; i < tsl->nseg; i++ )
-               printf("  %lu", tsl->seg[i]);
+               printf("  %lu/%02x", tsl->seg[i].lid, tsl->seg[i].trust );
            putchar('\n');
        }
     }
@@ -855,8 +890,7 @@ keyid_from_local_id( ulong lid, u32 *keyid )
 
 
 /****************
- * Verify, that all our public keys are in the trustDB and marked as
- * ultimately trusted.
+ * Verify, that all our public keys are in the trustDB.
  */
 static int
 verify_own_certs()
@@ -866,7 +900,6 @@ verify_own_certs()
     PKT_secret_cert *skc = m_alloc_clear( sizeof *skc );
     PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
     u32 keyid[2];
-    int trust;
 
     while( !(rc=enum_secret_keys( &enum_context, skc) ) ) {
        /* fixed: to be sure that it is a secret key of our own,
@@ -895,23 +928,21 @@ verify_own_certs()
            rc = G10ERR_GENERAL;
            goto leave;
        }
-       /* look into the trustdb */
-       rc = check_trust( pkc, &trust );
-       if( rc ) {
-           log_info("keyid %08lX: problem in trustdb: %s\n", (ulong)keyid[1],
-                                                             g10_errstr(rc) );
-           goto leave;
-       }
-       if( trust == TRUST_UNKNOWN ) {
+
+       /* make sure that the pubkey is in the trustdb */
+       rc = query_trust_record( pkc );
+       if( rc == -1 ) { /* put it into the trustdb */
            rc = insert_trust_record( pkc );
-           if( rc )
-               log_error("keyid %08lX: insert failed: %s\n",
-                                           (ulong)keyid[1], g10_errstr(rc) );
-           else
-               log_info("keyid %08lX: inserted\n", (ulong)keyid[1] );
+           if( rc ) {
+               log_error("keyid %08lX: can't put it into the trustdb\n",
+                                                           (ulong)keyid[1] );
+               goto leave;
+           }
        }
-       else {
-           /* FIXME: we should chek the other values */
+       else if( rc ) {
+           log_error("keyid %08lX: query record failed\n", (ulong)keyid[1] );
+           goto leave;
+
        }
 
        if( DBG_TRUST )
@@ -921,6 +952,7 @@ verify_own_certs()
            log_error("keyid %08lX: already in ultikey_table\n",
                                                        (ulong)keyid[1]);
 
+
        release_secret_cert_parts( skc );
        release_public_cert_parts( pkc );
     }
@@ -1042,7 +1074,7 @@ list_sigs( ulong pubkey_id )
 
 
 static int
-do_list_path( ulong *stack, int depth, int max_depth,
+do_list_path( TRUST_INFO *stack, int depth, int max_depth,
              LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist )
 {
     SIGREC_CONTEXT sx;
@@ -1057,12 +1089,13 @@ do_list_path( ulong *stack, int depth, int max_depth,
        return 0;
     }
     memset( &sx, 0, sizeof sx );
-    sx.pubkey_id = stack[depth-1];
+    sx.pubkey_id = stack[depth-1].lid;
     while( !(rc = walk_sigrecs( &sx )) ) {
        TRUST_SEG_LIST tsl, t2, tl;
        int i;
 
-       stack[depth] = sx.sig_id;
+       stack[depth].lid = sx.sig_id;
+       stack[depth].trust = 0;
        if( qry_lid_table_flag( lids, sx.sig_id, &last_depth) ) {
            /*printf("%2lu/%d: marked\n", sx.sig_id, depth );*/
            ins_lid_table_item( lids, sx.sig_id, depth);
@@ -1078,7 +1111,7 @@ do_list_path( ulong *stack, int depth, int max_depth,
            /*printf("%2lu/%d: already visited\n", sx.sig_id, depth)*/;
        else if( !qry_lid_table_flag( ultikey_table, sx.sig_id, NULL ) ) {
            /* found end of path; store it, ordered by path length */
-           tsl = m_alloc( sizeof *tsl + depth*sizeof(ulong) );
+           tsl = m_alloc( sizeof *tsl + depth*sizeof(TRUST_INFO) );
            tsl->nseg = depth+1;
            tsl->dup = 0;
            for(i=0; i <= depth; i++ )
@@ -1268,19 +1301,110 @@ build_sigrecs( ulong pubkeyid )
     return rc;
 }
 
+/****************
+ * Make a list of trust paths
+ */
+static int
+make_tsl( ulong pubkey_id, TRUST_SEG_LIST *ret_tslist )
+{
+    int i, rc;
+    LOCAL_ID_INFO *lids = new_lid_table();
+    TRUST_INFO stack[MAX_LIST_SIGS_DEPTH];
+    TRUST_SEG_LIST tsl, tslist;
+    int max_depth = 4;
+
+    tslist = *ret_tslist = NULL;
+
+    if( !qry_lid_table_flag( ultikey_table, pubkey_id, NULL ) ) {
+       tslist = m_alloc( sizeof *tslist );
+       tslist->nseg = 1;
+       tslist->dup = 0;
+       tslist->seg[0].lid = pubkey_id;
+       tslist->seg[0].trust = 0;
+       tslist->next = NULL;
+       rc = 0;
+    }
+    else {
+       stack[0].lid = pubkey_id;
+       stack[0].trust = 0;
+       rc = do_list_path( stack, 1, max_depth, lids, &tslist );
+    }
+    if( !rc ) { /* wipe out duplicates */
+       LOCAL_ID_INFO *work = new_lid_table();
+       for( tsl=tslist; tsl; tsl = tsl->next ) {
+           for(i=1; i < tsl->nseg-1; i++ ) {
+               if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) {
+                   tsl->dup = 1; /* mark as duplicate */
+                   break;
+               }
+           }
+       }
+       release_lid_table(work);
+       *ret_tslist = tslist;
+    }
+    else
+       ; /* FIXME: release tslist */
+    release_lid_table(lids);
+    return rc;
+}
+
 
+/****************
+ * Given a trust segment list tslist, walk over all paths and fill in
+ * the trust information for each segment.  What this function does is
+ * to assign a trustvalue to the first segment (which is the requested key)
+ * of each path.
+ *
+ * FIXME: We have to do more thinks here. e.g. we should never increase
+ *       the trust value.
+ *
+ * Do not do it for duplicates.
+ */
+static int
+propagate_trust( TRUST_SEG_LIST tslist )
+{
+    int i, rc;
+    unsigned trust;
+    TRUST_SEG_LIST tsl;
 
+    for(tsl = tslist; tsl; tsl = tsl->next ) {
+       if( tsl->dup )
+           continue;
+       assert( tsl->nseg );
+       /* the last segment is always a ultimately trusted one, so we can
+        * assign a fully trust to the next one */
+       i = tsl->nseg-1;
+       tsl->seg[i].trust = TRUST_ULTIMATE;
+       trust = TRUST_FULLY;
+       for(i-- ; i >= 0; i-- ) {
+           tsl->seg[i].trust = trust;
+           if( i > 0 ) {
+               /* get the trust of this pubkey */
+               rc = get_ownertrust( tsl->seg[i].lid, &trust );
+               if( rc )
+                   return rc;
+           }
+       }
+    }
+    return 0;
+}
 
 
 /****************
- *
+ * we have the pubkey record but nothing more is known
  */
 static int
-do_check( ulong pubkeyid, int *trustlevel )
+do_check( ulong pubkeyid, unsigned *trustlevel )
 {
-    int rc=0;
+    int i, rc=0;
     ulong rnum;
     TRUSTREC rec;
+    TRUST_SEG_LIST tsl, tsl2, tslist;
+    int marginal, fully;
+    int fully_needed = 4;
+    int marginal_needed = 6;
+
+    *trustlevel = TRUST_UNDEFINED;
 
     /* verify the cache */
 
@@ -1294,11 +1418,64 @@ do_check( ulong pubkeyid, int *trustlevel )
     if( rc )
        return rc;  /* error while looking for sigrec or building sigrecs */
 
+    /* fixme: take it from the cache if it is valid */
+
+    /* Make a list of all possible trust-paths */
+    rc = make_tsl( pubkeyid, &tslist );
+    if( rc )
+       return rc;
+    rc = propagate_trust( tslist );
+    if( rc )
+       return rc;
+    for(tsl = tslist; tsl; tsl = tsl->next ) {
+       if( tsl->dup )
+           continue;
+
+       log_debug("tslist segs:" );
+       for(i=0; i < tsl->nseg; i++ )
+           fprintf(stderr, "  %lu/%02x", tsl->seg[i].lid, tsl->seg[i].trust );
+       putc('\n',stderr);
+    }
+
+    /* and look wether there is a trusted path.
+     * We only have to look at the first segment, because
+     * propagate_trust has investigated all other segments */
+    marginal = fully = 0;
+    for(tsl = tslist; tsl; tsl = tsl->next ) {
+       if( tsl->dup )
+           continue;
+       if( tsl->seg[0].trust == TRUST_ULTIMATE ) {
+           *trustlevel = TRUST_ULTIMATE; /* our own key */
+           break;
+       }
+       if( tsl->seg[0].trust == TRUST_FULLY ) {
+           marginal++;
+           fully++;
+       }
+       else if( tsl->seg[0].trust == TRUST_MARGINAL )
+           marginal++;
+
+       if( fully >= fully_needed ) {
+           *trustlevel = TRUST_FULLY;
+           break;
+       }
+    }
+    if( !tsl && marginal >= marginal_needed )
+       *trustlevel = TRUST_MARGINAL;
+
+    /* cache the tslist */
+    if( last_trust_web_key ) {
+       for( tsl = last_trust_web_tslist; tsl; tsl = tsl2 ) {
+           tsl2 = tsl->next;
+           m_free(tsl);
+       }
+    }
+    last_trust_web_key = pubkeyid;
+    last_trust_web_tslist = tslist;
     return 0;
 }
 
 
-
 /*********************************************************
  ****************  API Interface  ************************
  *********************************************************/
@@ -1375,10 +1552,10 @@ init_trustdb( int level )
  *          is not necessary to check this if we use a local pubring. Hmmmm.
  */
 int
-check_trust( PKT_public_cert *pkc, int *r_trustlevel )
+check_trust( PKT_public_cert *pkc, unsigned *r_trustlevel )
 {
     TRUSTREC rec;
-    int trustlevel = TRUST_UNKNOWN;
+    unsigned trustlevel = TRUST_UNKNOWN;
     int rc=0;
 
     if( DBG_TRUST )
@@ -1409,10 +1586,6 @@ check_trust( PKT_public_cert *pkc, int *r_trustlevel )
        log_error("check_trust: do_check failed: %s\n", g10_errstr(rc));
        return rc;
     }
-    if( !rec.r.pubkey.ownertrust )
-       trustlevel = TRUST_UNDEFINED;
-    else
-       trustlevel = TRUST_EXPIRED;
 
 
   leave:
@@ -1423,29 +1596,109 @@ check_trust( PKT_public_cert *pkc, int *r_trustlevel )
 }
 
 
+
+
+/****************
+ * Enumerate all keys, which are needed to build all trust paths for
+ * the given key.  This function dies not return the key itself or
+ * the ultimate key.
+ *
+ *  1) create a void pointer and initialize it to NULL
+ *  2) pass this void pointer by reference to this function.
+ *     Set lid to the key you want to enumerate and pass it by reference.
+ *  3) call this function as long as it does not return -1
+ *     to indicate EOF. LID does contain the next key used to build the web
+ *  4) Always call this function a last time with LID set to NULL,
+ *     so that it can free it's context.
+ */
+int
+enum_trust_web( void **context, ulong *lid )
+{
+    ENUM_TRUST_WEB_CONTEXT *c = *context;
+
+    if( !c ) { /* make a new context */
+       c = m_alloc_clear( sizeof *c );
+       *context = c;
+       if( *lid != last_trust_web_key )
+           log_bug("enum_trust_web: nyi\n");
+       c->tsl = last_trust_web_tslist;
+       c->index = 1;
+    }
+
+    if( !lid ) { /* free the context */
+       m_free( c );
+       *context = NULL;
+       return 0;
+    }
+
+    while( c->tsl ) {
+       if( !c->tsl->dup && c->index < c->tsl->nseg-1 ) {
+           *lid = c->tsl->seg[c->index].lid;
+           c->index++;
+           return 0;
+       }
+       c->index = 1;
+       c->tsl = c->tsl->next;
+    }
+    return -1; /* eof */
+}
+
+
+/****************
+ * Return the assigned ownertrust value for the given LID
+ */
+int
+get_ownertrust( ulong lid, unsigned *r_otrust )
+{
+    TRUSTREC rec;
+
+    if( read_record( lid, &rec ) ) {
+       log_error("get_ownertrust: read record failed\n");
+       return G10ERR_TRUSTDB;
+    }
+    if( r_otrust )
+       *r_otrust = rec.r.pubkey.ownertrust;
+    return 0;
+}
+
+int
+keyid_from_trustdb( ulong lid, u32 *keyid )
+{
+    TRUSTREC rec;
+
+    if( read_record( lid, &rec ) ) {
+       log_error("keyid_from_trustdb: read record failed\n");
+       return G10ERR_TRUSTDB;
+    }
+    if( keyid ) {
+       keyid[0] = rec.r.pubkey.keyid[0];
+       keyid[1] = rec.r.pubkey.keyid[1];
+    }
+    return 0;
+}
+
+
 int
-get_ownertrust( PKT_public_cert *pkc, int *r_otrust )
+query_trust_record( PKT_public_cert *pkc )
 {
     TRUSTREC rec;
-    int rc;
+    int rc=0;
 
-    /* get the pubkey record */
     if( pkc->local_id ) {
        if( read_record( pkc->local_id, &rec ) ) {
-           log_error("get_ownertrust: read record failed\n");
+           log_error("query_trust_record: read record failed\n");
            return G10ERR_TRUSTDB;
        }
     }
     else { /* no local_id: scan the trustdb */
        if( (rc=scan_record_by_pkc( pkc, &rec, 2 )) && rc != -1 ) {
-           log_error("get_ownertrust: scan_record_by_pkc(2) failed: %s\n",
+           log_error("query_trust_record: scan_record_by_pkc(2) failed: %s\n",
                                                            g10_errstr(rc));
            return rc;
        }
        else if( rc == -1 )
            return rc;
     }
-    *r_otrust = rec.r.pubkey.ownertrust;
     return 0;
 }
 
@@ -1494,23 +1747,23 @@ insert_trust_record( PKT_public_cert *pkc )
 
 
 int
-update_trust_record( PKT_public_cert *pkc, int new_trust )
+update_ownertrust( ulong lid, unsigned new_trust )
 {
     TRUSTREC rec;
-    ulong recnum;
-
-
-    assert( pkc->local_id );
 
-    if( read_record( pkc->local_id, &rec ) ) {
-       log_error("update_trust_record: read failed\n");
+    if( read_record( lid, &rec ) ) {
+       log_error("update_ownertrust: read failed\n");
        return G10ERR_TRUSTDB;
     }
     /* check keyid, fingerprint etc ? */
+    if( rec.rectype != 2 ) {
+       log_error("update_ownertrust: invalid record type\n");
+       return G10ERR_TRUSTDB;
+    }
 
-    rec.r.pubkey.ownertrust = 0;
-    if( write_record( recnum, &rec ) ) {
-       log_error("insert_trust_record: write failed\n");
+    rec.r.pubkey.ownertrust = new_trust;
+    if( write_record( lid, &rec ) ) {
+       log_error("update_ownertrust: write failed\n");
        return G10ERR_TRUSTDB;
     }
 
index 75ead66..ee604de 100644 (file)
 void list_trustdb(const char *username);
 void list_trust_path( int max_depth, const char *username );
 int init_trustdb( int level );
-int check_trust( PKT_public_cert *pkc, int *r_trustlevel );
-int get_ownertrust( PKT_public_cert *pkc, int *r_otrust );
+int check_trust( PKT_public_cert *pkc, unsigned *r_trustlevel );
+int enum_trust_web( void **context, ulong *lid );
+int get_ownertrust( ulong lid, unsigned *r_otrust );
+int keyid_from_trustdb( ulong lid, u32 *keyid );
+int query_trust_record( PKT_public_cert *pkc );
 int insert_trust_record( PKT_public_cert *pkc );
+int update_ownertrust( ulong lid, unsigned new_trust );
 int verify_private_data(void);
 int sign_private_data(void);
 
index e381445..81e23f2 100644 (file)
@@ -54,7 +54,7 @@ struct iobuf_struct {
     IOBUF chain;       /* next iobuf used for i/o if any (passed to filter) */
     int no, subno;
     const char *desc;
-    void *opaque;      /* can be used to old any information   */
+    void *opaque;      /* can be used to hold any information   */
                       /* this value is copied to all instances */
 };
 
index a33b7f2..fe834e1 100644 (file)
@@ -121,7 +121,9 @@ char *stpcpy(char *a,const char *b);
 #ifndef HAVE_STRLWR
 char *strlwr(char *a);
 #endif
-
+#ifndef HAVE_STRTOUL
+  #define strtoul(a,b,c)  ((unsigned long)strtol((a),(b),(c)))
+#endif
 
 /******** some macros ************/
 #ifndef STR
index c341c3d..c924355 100644 (file)
@@ -1,4 +1,5 @@
 /* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
+   Note: I added some stuff for use with g10
 
 Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
 
@@ -1440,6 +1441,7 @@ extern
 const
 #endif
 unsigned char __clz_tab[];
+#define MPI_INTERNAL_NEED_CLZ_TAB 1
 #define count_leading_zeros(count, x) \
   do {                                                                 \
     UWtype __xr = (x);                                                 \
index 864dc02..d1f440a 100644 (file)
 #include "longlong.h"
 
 
+#ifdef MPI_INTERNAL_NEED_CLZ_TAB
+unsigned char
+__clz_tab[] =
+{
+  0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+};
+#endif
+
+
+
+
+
+
+
+
 /****************
  * Return the number of bits in A.
  */
index c6c0302..89c873c 100644 (file)
@@ -286,7 +286,7 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
        else if( state == 3 ) { /* skip leading spaces of the argument */
            if( !isspace(c) ) {
                i = 0;
-               keyword[i] = c;
+               keyword[i++] = c;
                state = 4;
            }
        }