Ready to test version 0.2.0
authorWerner Koch <wk@gnupg.org>
Sun, 25 Jan 1998 18:56:33 +0000 (18:56 +0000)
committerWerner Koch <wk@gnupg.org>
Sun, 25 Jan 1998 18:56:33 +0000 (18:56 +0000)
NEWS
README
TODO
VERSION
doc/DETAILS
g10/g10.c
g10/options.h
g10/trustdb.c

diff --git a/NEWS b/NEWS
index f228208..c5fbdaf 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,12 @@
 
+    * The logic to handle the web of trust is now implemented. It is
+      has some bugs; but I'm going to change the algorithm anyway.
+      It works by calculating the trustlevel on the fly.  It may ask
+      you to provide trust parameters if the calculated trust probability
+      is too low.  I will write a paper which discusses this new approach.
+
+    * a couple of changes to the configure script.
+
     * New option "--quick-random" which uses a much quicker random
       number generator.  Keys generated while this option is in effect
       are flags with "INSECURE!" in the user-id.  This is a development
diff --git a/README b/README
index 1f2879c..4aa3f6e 100644 (file)
--- a/README
+++ b/README
     * Some features are not yet implemented
 
 
-    I provide this version as a reality check to start discussion.
     Please subscribe to g10@net.lut.ac.uk by sending a mail with
     the word "subscribe" in the body to "g10-request@net.lut.ac.uk".
 
-
     See the file COPYING for copyright and warranty information.
 
-
     Due to the fact that G10 does not use use any patented algorithm,
     it cannot be compatible to old PGP versions, because those use
     IDEA (which is worldwide patented) and RSA (which is patented in
     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)
+     using a negative number). This option may create new entries in the
+    trustdb.
 
        --print-mds  filenames
 
diff --git a/TODO b/TODO
index 9e76209..65079b6 100644 (file)
--- a/TODO
+++ b/TODO
@@ -39,4 +39,9 @@
 
     * Burn the buffers used by fopen().
 
+    * bug: g10/trustdb.c#build_sigrecs caled to often by do_list_path
+      and remove the bad kludge. Maybe we should put all sigs into the trustdb
+      and mark them as valid/invalid/nopubkey, and how do we check, that
+      we have a self-signature -> put this stuff into a kind of directory
+      record, as it does not belong to the pubkey record?
 
diff --git a/VERSION b/VERSION
index 845639e..0ea3a94 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.4
+0.2.0
index d5d1abe..37d0a02 100644 (file)
@@ -11,6 +11,8 @@
 
 Layout of the TrustDB
 =====================
+FIXME: use a directory record as top node instead of the pubkey record
+
 The TrustDB is build from fixed length records, where the first bytes
 describes the record type.  All numeric values are stored in network
 byte order. The length of each record is 40 bytes. The first record of
@@ -74,7 +76,9 @@ Record type 2:
                   we have control over the secret key too.
              Bit 3: set if key is revoked; do not use it.
              Bit 7-4: reserved
-     3 byte reserved
+     1 byte  No signatures (used to avoid duplicate building).
+            FIXME: this should be moved to the cahce record
+     2 byte reserved
 
 
 Record type 3: (cache record)
index d36717a..b9ce925 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -191,6 +191,8 @@ main( int argc, char **argv )
     { 532, "quick-random", 0, "\r"},
     { 533, "list-trust-path",0, "\r"},
     { 534, "no-comment", 0,   "do not write comment packets"},
+    { 535, "completes_needed", 1, "(default is 1)"},
+    { 536, "marginals_needed", 1, "(default is 3)"},
 
     {0} };
     ARGPARSE_ARGS pargs;
@@ -219,6 +221,8 @@ main( int argc, char **argv )
     opt.def_cipher_algo = CIPHER_ALGO_BLOWFISH;
     opt.def_pubkey_algo = PUBKEY_ALGO_ELGAMAL;
     opt.def_digest_algo = DIGEST_ALGO_RMD160;
+    opt.completes_needed = 1;
+    opt.marginals_needed = 3;
 
     /* check wether we have a config file on the commandline */
     orig_argc = argc;
@@ -338,6 +342,8 @@ main( int argc, char **argv )
          case 532: quick_random_gen(1); break;
          case 533: set_cmd( &cmd, aListTrustPath); break;
          case 534: opt.no_comment=1; break;
+         case 535: opt.completes_needed = pargs.r.ret_int; break;
+         case 536: opt.marginals_needed = pargs.r.ret_int; break;
          default : errors++; pargs.err = configfp? 1:2; break;
        }
     }
@@ -360,9 +366,18 @@ main( int argc, char **argv )
        log_error("selected digest algorithm is invalid\n");
        errors++;
     }
+    if( opt.completes_needed < 1 ) {
+       log_error("completes_needed must be greater than 0\n");
+       errors++;
+    }
+    if( opt.marginals_needed < 2 ) {
+       log_error("marginals_needed must be greater than 1\n");
+       errors++;
+    }
     if( errors )
        exit(2);
 
+
     set_debug();
     if( cmd == aKMode || cmd == aKModeC ) { /* kludge to be compatible to pgp */
        if( cmd == aKModeC ) {
index 7a9a4c5..ed0cc65 100644 (file)
@@ -40,8 +40,8 @@ struct {
     int def_pubkey_algo;
     int def_digest_algo;
     int no_comment;
-    int reserved10;
-    int reserved11;
+    int marginals_needed;
+    int completes_needed;
     int reserved12;
     int reserved13;
     int reserved14;
index 4f89751..f3396ab 100644 (file)
@@ -66,6 +66,7 @@ struct trust_record {
            byte reserved;
            byte fingerprint[20];
            byte ownertrust;
+           byte no_sigs;
            /* fixme: indicate a flag to */
        } pubkey;
        struct {            /* cache record */
@@ -94,7 +95,7 @@ typedef struct trust_record TRUSTREC;
 typedef struct {
     ulong     pubkey_id;   /* localid of the pubkey */
     ulong     sig_id;     /* returned signature id */
-    unsigned  sig_flag;    /* returned signaure record flag */
+    unsigned  sig_flag;    /* returned signature record flag */
     struct {              /* internal data */
        int eof;
        TRUSTREC rec;
@@ -138,7 +139,7 @@ static int  read_record( ulong recnum, TRUSTREC *rec );
 static int  write_record( ulong recnum, TRUSTREC *rec );
 static ulong new_recnum(void);
 static void dump_record( ulong rnum, TRUSTREC *rec, FILE *fp );
-static int walk_sigrecs( SIGREC_CONTEXT *c );
+static int walk_sigrecs( SIGREC_CONTEXT *c, int create );
 
 static LOCAL_ID_INFO *new_lid_table(void);
 static void release_lid_table( LOCAL_ID_INFO *tbl );
@@ -151,9 +152,11 @@ 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 build_sigrecs( ulong pubkeyid, int kludge );
 static int propagate_trust( TRUST_SEG_LIST tslist );
 static int do_check( ulong pubkeyid, unsigned *trustlevel );
 
+static int update_no_sigs( ulong lid, int no_sigs );
 
 static char *db_name;
 static int  db_fd = -1;
@@ -329,6 +332,7 @@ read_record( ulong recnum, TRUSTREC *rec )
        rec->r.pubkey.reserved = *p++;
        memcpy( rec->r.pubkey.fingerprint, p, 20); p += 20;
        rec->r.pubkey.ownertrust = *p++;
+       rec->r.pubkey.no_sigs = *p++;
        if( rec->r.pubkey.local_id != recnum ) {
            log_error("%s: pubkey local_id != recnum (%lu,%lu)\n",
                                        db_name,
@@ -399,6 +403,7 @@ write_record( ulong recnum, TRUSTREC *rec )
        *p++ = rec->r.pubkey.reserved;
        memcpy( p, rec->r.pubkey.fingerprint, 20); p += 20;
        *p++ = rec->r.pubkey.ownertrust;
+       *p++ = rec->r.pubkey.no_sigs;
        assert( rec->r.pubkey.local_id == recnum );
        break;
       case 3:
@@ -563,8 +568,9 @@ dump_record( ulong rnum, TRUSTREC *rec, FILE *fp  )
        break;
       case 1: fprintf(fp, "version\n");
        break;
-      case 2: fprintf(fp, "pubkey, keyid=%08lX, ownertrust=%02x\n",
-                  rec->r.pubkey.keyid[1], rec->r.pubkey.ownertrust );
+      case 2: fprintf(fp, "pubkey, keyid=%08lX, ownertrust=%02x%s\n",
+                  rec->r.pubkey.keyid[1], rec->r.pubkey.ownertrust,
+                  rec->r.pubkey.no_sigs?"  (inv sigs)":"");
        break;
       case 3: fprintf(fp, "cache\n");
       case 4:
@@ -674,9 +680,17 @@ list_trust_path( int max_depth, const char *username )
     else if( (rc=scan_record_by_pkc( pkc, &rec, 2 )) && rc != -1 )
        log_error("problem finding '%s' in trustdb: %s\n",
                                            username, g10_errstr(rc));
-    else if( rc == -1 )
-       log_error("user '%s' not in trustdb\n", username);
-    else {
+    else if( rc == -1 ) {
+       log_info("user '%s' not in trustdb - inserting\n", username);
+       rc = insert_trust_record( pkc );
+       if( rc )
+           log_error("failed to put '%s' into trustdb: %s\n", username, g10_errstr(rc));
+       else {
+           assert( pkc->local_id );
+       }
+    }
+
+    if( !rc ) {
        TRUST_SEG_LIST tsl, tslist = NULL;
 
        if( !qry_lid_table_flag( ultikey_table, pkc->local_id, NULL ) ) {
@@ -742,7 +756,7 @@ list_trust_path( int max_depth, const char *username )
  * Returns: 0 - okay, -1 for eof (no more sigs) or any other errorcode
  */
 static int
-walk_sigrecs( SIGREC_CONTEXT *c )
+walk_sigrecs( SIGREC_CONTEXT *c, int create )
 {
     int rc=0;
     TRUSTREC *r;
@@ -753,6 +767,17 @@ walk_sigrecs( SIGREC_CONTEXT *c )
     r = &c->ctl.rec;
     if( !r->rectype ) { /* this is the first call */
        rc = scan_record( c->pubkey_id, r, 4, &rnum );
+       if( rc == -1 && create ) { /* no signature records */
+           rc = build_sigrecs( c->pubkey_id, 1 );
+           if( rc ) {
+               if( rc != -1 )
+                   log_info("%lu: error building sigs on the fly: %s\n",
+                          c->pubkey_id, g10_errstr(rc) );
+               rc = -1;
+           }
+           else /* once more */
+               rc = scan_record( c->pubkey_id, r, 4, &rnum );
+       }
        if( rc == -1 ) { /* no signature records */
            c->ctl.eof = 1;
            return -1;  /* return eof */
@@ -997,7 +1022,7 @@ do_list_sigs( ulong root, ulong pubkey, int depth,
     memset( &sx, 0, sizeof sx );
     sx.pubkey_id = pubkey;
     for(;;) {
-       rc = walk_sigrecs( &sx );
+       rc = walk_sigrecs( &sx, 0 );
        if( rc )
            break;
        rc = keyid_from_local_id( sx.sig_id, keyid );
@@ -1090,7 +1115,9 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth,
     }
     memset( &sx, 0, sizeof sx );
     sx.pubkey_id = stack[depth-1].lid;
-    while( !(rc = walk_sigrecs( &sx )) ) {
+    /* loop over all signatures. If we do not have any, try to
+     * create them */
+    while( !(rc = walk_sigrecs( &sx, 1 )) ) {
        TRUST_SEG_LIST tsl, t2, tl;
        int i;
 
@@ -1181,7 +1208,7 @@ check_sigs( KBNODE keyblock, int *selfsig_okay )
  * to the trustdb
  */
 static int
-build_sigrecs( ulong pubkeyid )
+build_sigrecs( ulong pubkeyid, int kludge )
 {
     TRUSTREC rec, rec2;
     PUBKEY_FIND_INFO finfo=NULL;
@@ -1201,6 +1228,10 @@ build_sigrecs( ulong pubkeyid )
        log_error("build_sigrecs: can't read pubkey record\n");
        goto leave;
     }
+    if( kludge && rec.r.pubkey.no_sigs ) {
+       rc = -1;
+       goto leave;
+    }
     finfo = m_alloc_clear( sizeof *finfo );
     finfo->keyid[0] = rec.r.pubkey.keyid[0];
     finfo->keyid[1] = rec.r.pubkey.keyid[1];
@@ -1224,10 +1255,12 @@ build_sigrecs( ulong pubkeyid )
     }
     if( !selfsig ) {
        log_error("build_sigrecs: self-certificate missing\n" );
+       update_no_sigs( pubkeyid, 1 );
        rc = G10ERR_BAD_CERT;
        goto leave;
     }
 
+    update_no_sigs( pubkeyid, 0 );
     /* valid key signatures are now marked; we can now build the
      * sigrecs */
     memset( &rec, 0, sizeof rec );
@@ -1241,7 +1274,9 @@ build_sigrecs( ulong pubkeyid )
                /* the next function should always succeed, because
                 * we have already checked the signature, and for this
                 * it was necessary to have the pubkey. The only reason
-                * this can fail are I/o erros of the trustdb. */
+                * this can fail are I/o errors of the trustdb or a
+                * remove operation on the pubkey database - which should
+                * not disturb us, because we have to chace them anyway. */
                rc = set_signature_packets_local_id( node->pkt->pkt.signature );
                if( rc )
                    log_fatal("set_signature_packets_local_id failed: %s\n",
@@ -1401,8 +1436,11 @@ do_check( ulong pubkeyid, unsigned *trustlevel )
     TRUSTREC rec;
     TRUST_SEG_LIST tsl, tsl2, tslist;
     int marginal, fully;
-    int fully_needed = 4;
-    int marginal_needed = 6;
+    int fully_needed = opt.completes_needed;
+    int marginal_needed = opt.marginals_needed;
+
+    assert( fully_needed > 0 && marginal_needed > 1 );
+
 
     *trustlevel = TRUST_UNDEFINED;
 
@@ -1411,7 +1449,7 @@ do_check( ulong pubkeyid, unsigned *trustlevel )
     /* do we have sigrecs */
     rc = scan_record( pubkeyid, &rec, 4, &rnum );
     if( rc == -1 ) { /* no sigrecs, so build them */
-       rc = build_sigrecs( pubkeyid );
+       rc = build_sigrecs( pubkeyid, 1 );
        if( !rc ) /* and read again */
            rc = scan_record( pubkeyid, &rec, 4, &rnum );
     }
@@ -1575,8 +1613,14 @@ check_trust( PKT_public_cert *pkc, unsigned *r_trustlevel )
            return rc;
        }
        else if( rc == -1 ) {
-           log_error("check_trust: pubkey not in TrustDB\n");
-           goto leave;
+           rc = insert_trust_record( pkc );
+           if( rc ) {
+               log_error("failed to insert pubkey into trustdb: %s\n",
+                                                           g10_errstr(rc));
+               goto leave;
+           }
+           log_info("pubkey not in trustdb - inserted as %lu\n",
+                                   pkc->local_id );
        }
     }
     /* fixme: do some additional checks on the pubkey record */
@@ -1735,6 +1779,7 @@ insert_trust_record( PKT_public_cert *pkc )
     rec.r.pubkey.pubkey_algo = pkc->pubkey_algo;
     memcpy(rec.r.pubkey.fingerprint, fingerprint, fingerlen );
     rec.r.pubkey.ownertrust = 0;
+    rec.r.pubkey.no_sigs = 0;
     if( write_record( recnum, &rec ) ) {
        log_error("insert_trust_record: write failed\n");
        return G10ERR_TRUSTDB;
@@ -1771,6 +1816,36 @@ update_ownertrust( ulong lid, unsigned new_trust )
 }
 
 
+
+/****************
+ * Kludge to prevent duplicate build_sigrecs() due to an invalid
+ * certificate (no selfsignature or something like this)
+ */
+static int
+update_no_sigs( ulong lid, int no_sigs )
+{
+    TRUSTREC rec;
+
+    if( read_record( lid, &rec ) ) {
+       log_error("update_no_sigs: read failed\n");
+       return G10ERR_TRUSTDB;
+    }
+    /* check keyid, fingerprint etc ? */
+    if( rec.rectype != 2 ) {
+       log_error("update_no_sigs: invalid record type\n");
+       return G10ERR_TRUSTDB;
+    }
+
+    rec.r.pubkey.no_sigs = !!no_sigs;
+    if( write_record( lid, &rec ) ) {
+       log_error("update_no_sigs: write failed\n");
+       return G10ERR_TRUSTDB;
+    }
+
+    return 0;
+}
+
+
 int
 verify_private_data()
 {