added some trust model stuff
authorWerner Koch <wk@gnupg.org>
Fri, 16 Jan 1998 21:15:24 +0000 (21:15 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 16 Jan 1998 21:15:24 +0000 (21:15 +0000)
49 files changed:
Makefile.in
NEWS
cipher/blowfish.c
cipher/md.c
cipher/md5.c
cipher/misc.c
cipher/primegen.c
cipher/random.c
configure.in
g10/Makefile.am
g10/Makefile.in
g10/armor.c
g10/build-packet.c
g10/compress.c
g10/encode.c
g10/g10.c
g10/import.c [new file with mode: 0644]
g10/keydb.h
g10/keygen.c
g10/keyid.c
g10/main.h
g10/mainproc.c
g10/packet.h
g10/parse-packet.c
g10/passphrase.c
g10/pkclist.c
g10/ringedit.c
g10/seckey-cert.c
g10/seskey.c
g10/sig-check.c
g10/sign.c
g10/skclist.c
g10/trustdb.c
g10/trustdb.h
include/cipher.h
include/errors.h
include/iobuf.h
include/mpi.h
include/util.h
mpi/mpi-bit.c
mpi/mpi-internal.h
mpi/mpi-pow.c
mpi/mpicoder.c
mpi/mpiutil.c
util/argparse.c
util/errors.c
util/iobuf.c
util/logger.c
util/ttyio.c

index b25badf..ff52314 100644 (file)
@@ -45,8 +45,8 @@ CONFIG_HEADER_IN = config.h.in
 mkinstalldirs = $(top_srcdir)/scripts/mkinstalldirs
 CONFIG_HEADER = ./config.h
 DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \
-Makefile.in NEWS README TODO acconfig.h config.h.in configure.in \
-stamp-h.in
+Makefile.in NEWS README TODO acconfig.h config.h.in configure \
+configure.in stamp-h.in
 
 
 PACKAGE = @PACKAGE@
diff --git a/NEWS b/NEWS
index eeee0dc..f228208 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,15 @@
 
+    * 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
+      only option.
+
+    * Read support for new version packets (OpenPGP).
+
+    * Comment packets are now of coorect OpenPGP type 16. Old comment
+      packets writen by G10 are detected because they always start with
+      a hash which is an invalid version byte.
+
     * The string "(INSECURE!)" is appended to a new user-id if this
       is generated on a system without a good random number generator.
 
index 5dbaf71..81e33d0 100644 (file)
@@ -412,7 +412,7 @@ selftest()
 void
 blowfish_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
 {
-    int i, j, k;
+    int i, j;
     u32 data, datal, datar;
     static int initialized;
 
index e88a45c..eb7b7b8 100644 (file)
@@ -144,7 +144,7 @@ md_read( MD_HANDLE a, int algo )
        if( algo == DIGEST_ALGO_MD5 )
            return md5_read( &a->md5 );
     }
-    log_bug(NULL);
+    BUG();
 }
 
 int
index 6906503..c9f9a86 100644 (file)
@@ -73,7 +73,6 @@
 #endif
 
 
-static void Init( MD5_CONTEXT *mdContext);
 static void Transform(u32 *buf,u32 *in);
 
 static byte PADDING[64] = {
index cd0d31a..7c8f2e3 100644 (file)
@@ -67,7 +67,7 @@ string_to_cipher_algo( const char *string )
     int i;
     const char *s;
 
-    for(i=0; s=cipher_names[i].name; i++ )
+    for(i=0; (s=cipher_names[i].name); i++ )
        if( !stricmp( s, string ) )
            return cipher_names[i].algo;
     return 0;
@@ -83,7 +83,7 @@ string_to_pubkey_algo( const char *string )
     int i;
     const char *s;
 
-    for(i=0; s=pubkey_names[i].name; i++ )
+    for(i=0; (s=pubkey_names[i].name); i++ )
        if( !stricmp( s, string ) )
            return pubkey_names[i].algo;
     return 0;
@@ -98,7 +98,7 @@ string_to_digest_algo( const char *string )
     int i;
     const char *s;
 
-    for(i=0; s=digest_names[i].name; i++ )
+    for(i=0; (s=digest_names[i].name); i++ )
        if( !stricmp( s, string ) )
            return digest_names[i].algo;
     return 0;
index 3f6c1f3..9514fda 100644 (file)
@@ -319,8 +319,6 @@ check_prime( MPI prime )
     int i;
     unsigned x;
     int count=0;
-    MPI result;
-    MPI val_2;
 
     /* check against small primes */
     for(i=0; (x = small_prime_numbers[i]); i++ ) {
@@ -431,7 +429,7 @@ m_out_of_n( char *array, int m, int n )
                array[i] = 1;
                return;
            }
-       log_bug(NULL);
+       BUG();
     }
 
     for(j=1; j < n; j++ ) {
index 41f001e..b082022 100644 (file)
@@ -30,6 +30,7 @@
 #include <fcntl.h>
 #include "util.h"
 #include "cipher.h"
+#include "ttyio.h"
 
 struct cache {
     int len;
@@ -41,6 +42,18 @@ static struct cache cache[3];
 
 
 static void fill_buffer( byte *buffer, size_t length, int level );
+static int quick_test;
+
+
+int
+quick_random_gen( int onoff )
+{
+    int last = quick_test;
+    if( onoff != -1 )
+       quick_test = onoff;
+    return last;
+}
+
 
 /****************
  * Fill the buffer with LENGTH bytes of cryptologic strong
@@ -95,14 +108,13 @@ open_device( const char *name, int minor )
 static void
 fill_buffer( byte *buffer, size_t length, int level )
 {
-    FILE *fp;
     static int fd_urandom = -1;
     static int fd_random = -1;
     int fd;
     int n;
     int warn=0;
 
-    if( level == 2 ) {
+    if( level == 2 && !quick_test ) {
        if( fd_random == -1 )
            fd_random = open_device( "/dev/random", 8 );
        fd = fd_random;
index f01033b..6a97d41 100644 (file)
@@ -19,8 +19,8 @@ AC_ARG_ENABLE(m-debug,
 [  --enable-m-debug    Enable debugging of memory allocation])
 if test "$enableval" = y || test "$enableval" = yes; then
     AC_DEFINE(M_DEBUG)
-    CFLAGS=-g
 fi
+CFLAGS="-g -Wall"
 
 dnl some additional macros
 
index b6b9ce5..5c22b4b 100644 (file)
@@ -40,6 +40,7 @@ g10_SOURCES = g10.c           \
              seckey-cert.c     \
              seskey.c          \
              sign.c            \
+             import.c          \
              comment.c         \
              sig-check.c
 
index 7e5ef73..1212499 100644 (file)
@@ -78,6 +78,7 @@ g10_SOURCES = g10.c           \
              seckey-cert.c     \
              seskey.c          \
              sign.c            \
+             import.c          \
              comment.c         \
              sig-check.c
 
@@ -103,7 +104,8 @@ g10_OBJECTS = g10.o build-packet.o compress.o encode.o encr-data.o \
 free-packet.o getkey.o pkclist.o skclist.o ringedit.o kbnode.o keygen.o \
 mainproc.o armor.o mdfilter.o textfilter.o cipher.o elg.o rsa.o \
 openfile.o keyid.o trustdb.o parse-packet.o passphrase.o plaintext.o \
-pubkey-enc.o seckey-cert.o seskey.o sign.o comment.o sig-check.o
+pubkey-enc.o seckey-cert.o seskey.o sign.o import.o comment.o \
+sig-check.o
 EXTRA_g10_SOURCES =
 g10_LDADD = $(LDADD)
 DIST_COMMON = Makefile.am Makefile.in
@@ -123,17 +125,17 @@ $(srcdir)/.deps/cipher.P $(srcdir)/.deps/comment.P \
 $(srcdir)/.deps/compress.P $(srcdir)/.deps/elg.P \
 $(srcdir)/.deps/encode.P $(srcdir)/.deps/encr-data.P \
 $(srcdir)/.deps/free-packet.P $(srcdir)/.deps/g10.P \
-$(srcdir)/.deps/getkey.P $(srcdir)/.deps/kbnode.P \
-$(srcdir)/.deps/keygen.P $(srcdir)/.deps/keyid.P \
-$(srcdir)/.deps/mainproc.P $(srcdir)/.deps/mdfilter.P \
-$(srcdir)/.deps/openfile.P $(srcdir)/.deps/parse-packet.P \
-$(srcdir)/.deps/passphrase.P $(srcdir)/.deps/pkclist.P \
-$(srcdir)/.deps/plaintext.P $(srcdir)/.deps/pubkey-enc.P \
-$(srcdir)/.deps/ringedit.P $(srcdir)/.deps/rsa.P \
-$(srcdir)/.deps/seckey-cert.P $(srcdir)/.deps/seskey.P \
-$(srcdir)/.deps/sig-check.P $(srcdir)/.deps/sign.P \
-$(srcdir)/.deps/skclist.P $(srcdir)/.deps/textfilter.P \
-$(srcdir)/.deps/trustdb.P
+$(srcdir)/.deps/getkey.P $(srcdir)/.deps/import.P \
+$(srcdir)/.deps/kbnode.P $(srcdir)/.deps/keygen.P \
+$(srcdir)/.deps/keyid.P $(srcdir)/.deps/mainproc.P \
+$(srcdir)/.deps/mdfilter.P $(srcdir)/.deps/openfile.P \
+$(srcdir)/.deps/parse-packet.P $(srcdir)/.deps/passphrase.P \
+$(srcdir)/.deps/pkclist.P $(srcdir)/.deps/plaintext.P \
+$(srcdir)/.deps/pubkey-enc.P $(srcdir)/.deps/ringedit.P \
+$(srcdir)/.deps/rsa.P $(srcdir)/.deps/seckey-cert.P \
+$(srcdir)/.deps/seskey.P $(srcdir)/.deps/sig-check.P \
+$(srcdir)/.deps/sign.P $(srcdir)/.deps/skclist.P \
+$(srcdir)/.deps/textfilter.P $(srcdir)/.deps/trustdb.P
 SOURCES = $(g10_SOURCES)
 OBJECTS = $(g10_OBJECTS)
 
index f6e6305..6a432d3 100644 (file)
@@ -275,7 +275,7 @@ check_input( armor_filter_context_t *afx, IOBUF a )
 {
     int rc = 0;
     int c;
-    size_t n = 0, nn=0, nn_limit=0;
+    size_t n = 0, nn=0;
     struct fhdr_struct fhdr;
 
     assert( DIM(afx->helpbuf) >= 50 );
@@ -339,7 +339,7 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
 {
     int rc = 0;
     int c;
-    size_t n = 0, nn=0, nn_limit=0;
+    size_t n = 0;
     struct fhdr_struct *fhdr = afx->fake;
     byte *helpbuf = afx->helpbuf;
     int helpidx = afx->helpidx;
@@ -347,7 +347,6 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
     byte *tempbuf = afx->tempbuf;
     int tempidx = afx->tempidx;
     int templen = afx->templen;
-    int defer=1;
 
     /* FIXME: have to read one ahead or do some other mimic to
      * get rid of the lf before the "begin signed message"
@@ -417,7 +416,7 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
     int c, c2;
     int checkcrc=0;
     int rc = 0;
-    size_t n = 0, nn=0;
+    size_t n = 0;
     int  idx, i;
     u32 crc;
 
@@ -450,7 +449,7 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
        idx = (idx+1) % 4;
     }
     for(i=0; i < n; i++ )
-       crc = (crc << 8) ^ crc_table[(crc >> 16)&0xff ^ buf[i]];
+       crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
     crc &= 0x00ffffff;
     afx->crc = crc;
     afx->idx = idx;
@@ -533,7 +532,7 @@ armor_filter( void *opaque, int control,
 {
     size_t size = *ret_len;
     armor_filter_context_t *afx = opaque;
-    int rc=0, i, c, c2;
+    int rc=0, i, c;
     byte radbuf[3];
     int  idx, idx2;
     size_t n=0;
@@ -553,7 +552,7 @@ armor_filter( void *opaque, int control,
     }
     else if( control == IOBUFCTRL_UNDERFLOW ) {
        if( size < 20 )
-           log_bug(NULL); /* supplied buffer maybe too short */
+           BUG(); /* supplied buffer maybe too short */
 
        if( afx->inp_eof ) {
            *ret_len = 0;
@@ -608,7 +607,7 @@ armor_filter( void *opaque, int control,
            radbuf[i] = afx->radbuf[i];
 
        for(i=0; i < size; i++ )
-           crc = (crc << 8) ^ crc_table[(crc >> 16)&0xff ^ buf[i]];
+           crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
        crc &= 0x00ffffff;
 
        for( ; size; buf++, size-- ) {
index 5bacf3f..a541c8c 100644 (file)
@@ -50,7 +50,8 @@ static int calc_header_length( u32 len );
 static int write_16(IOBUF inp, u16 a);
 static int write_32(IOBUF inp, u32 a);
 static int write_header( IOBUF out, int ctb, u32 len );
-static int write_header2( IOBUF out, int ctb, u32 len, int blkmode );
+static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode );
+static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen );
 static int write_version( IOBUF out, int ctb );
 
 /****************
@@ -67,7 +68,10 @@ build_packet( IOBUF out, PACKET *pkt )
     if( DBG_PACKET )
        log_debug("build_packet() type=%d\n", pkt->pkttype );
     assert( pkt->pkt.generic );
-    ctb = 0x80 | ((pkt->pkttype & 15)<<2);
+    if( pkt->pkttype > 15 ) /* new format */
+       ctb = 0xc0 | (pkt->pkttype & 0x3f);
+    else
+       ctb = 0x80 | ((pkt->pkttype & 15)<<2);
     switch( pkt->pkttype ) {
       case PKT_USER_ID:
        rc = do_user_id( out, ctb, pkt->pkt.user_id );
@@ -164,7 +168,10 @@ do_public_cert( IOBUF out, int ctb, PKT_public_cert *pkc )
     int rc = 0;
     IOBUF a = iobuf_temp();
 
-    write_version( a, ctb );
+    if( !pkc->version )
+       iobuf_put( a, 3 );
+    else
+       iobuf_put( a, pkc->version );
     write_32(a, pkc->timestamp );
     write_16(a, pkc->valid_days );
     iobuf_put(a, pkc->pubkey_algo );
@@ -182,7 +189,7 @@ do_public_cert( IOBUF out, int ctb, PKT_public_cert *pkc )
        goto leave;
     }
 
-    write_header(out, ctb, iobuf_get_temp_length(a) );
+    write_header2(out, ctb, iobuf_get_temp_length(a), pkc->hdrbytes, 1 );
     if( iobuf_write_temp( out, a ) )
        rc = G10ERR_WRITE_FILE;
 
@@ -202,6 +209,7 @@ hash_public_cert( MD_HANDLE md, PKT_public_cert *pkc )
     int rc = 0;
     int c;
     IOBUF a = iobuf_temp();
+    FILE *fp = fopen("dump.pkc", "a");
 
     /* build the packet */
     init_packet(&pkt);
@@ -209,9 +217,11 @@ hash_public_cert( MD_HANDLE md, PKT_public_cert *pkc )
     pkt.pkt.public_cert = pkc;
     if( (rc = build_packet( a, &pkt )) )
        log_fatal("build public_cert for hashing failed: %s\n", g10_errstr(rc));
-    while( (c=iobuf_get(a)) != -1 )
+    while( (c=iobuf_get(a)) != -1 ) {
+       putc( c, fp);
        md_putc( md, c );
-
+    }
+    fclose(fp);
     iobuf_cancel(a);
 }
 
@@ -222,7 +232,10 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
     int rc = 0;
     IOBUF a = iobuf_temp();
 
-    write_version( a, ctb );
+    if( !skc->version )
+       iobuf_put( a, 3 );
+    else
+       iobuf_put( a, skc->version );
     write_32(a, skc->timestamp );
     write_16(a, skc->valid_days );
     iobuf_put(a, skc->pubkey_algo );
@@ -262,7 +275,7 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
        goto leave;
     }
 
-    write_header(out, ctb, iobuf_get_temp_length(a) );
+    write_header2(out, ctb, iobuf_get_temp_length(a), skc->hdrbytes, 1 );
     if( iobuf_write_temp( out, a ) )
        rc = G10ERR_WRITE_FILE;
 
@@ -365,7 +378,7 @@ do_compressed( IOBUF out, int ctb, PKT_compressed *cd )
     int rc = 0;
 
     /* we must use the old convention and don't use blockmode */
-    write_header2(out, ctb, 0, 0 );
+    write_header2(out, ctb, 0, 0, 0 );
     iobuf_put(out, cd->algorithm );
 
     /* This is all. The caller has to write the real data */
@@ -433,7 +446,6 @@ do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops )
     if( iobuf_write_temp( out, a ) )
        rc = G10ERR_WRITE_FILE;
 
-  leave:
     iobuf_close(a);
     return rc;
 }
@@ -482,20 +494,39 @@ calc_header_length( u32 len )
 static int
 write_header( IOBUF out, int ctb, u32 len )
 {
-    return write_header2( out, ctb, len, 1 );
+    return write_header2( out, ctb, len, 0, 1 );
 }
 
+/****************
+ * if HDRLEN is > 0, try to build a header of this length.
+ * we need this, so hat we can hash packets without reading them again.
+ */
 static int
-write_header2( IOBUF out, int ctb, u32 len, int blkmode )
+write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode )
 {
-    if( !len )
-       ctb |= 3;
-    else if( len < 256 )
-       ;
-    else if( len < 65536 )
-       ctb |= 1;
-    else
-       ctb |= 2;
+    if( ctb & 0x40 )
+       return write_new_header( out, ctb, len, hdrlen );
+
+    if( hdrlen ) {
+       if( !len )
+           ctb |= 3;
+       else if( hdrlen == 2 && len < 256 )
+           ;
+       else if( hdrlen == 3 && len < 65536 )
+           ctb |= 1;
+       else
+           ctb |= 2;
+    }
+    else {
+       if( !len )
+           ctb |= 3;
+       else if( len < 256 )
+           ;
+       else if( len < 65536 )
+           ctb |= 1;
+       else
+           ctb |= 2;
+    }
     if( iobuf_put(out, ctb ) )
        return -1;
     if( !len ) {
@@ -515,6 +546,36 @@ write_header2( IOBUF out, int ctb, u32 len, int blkmode )
     return 0;
 }
 
+
+static int
+write_new_header( IOBUF out, int ctb, u32 len, int hdrlen )
+{
+    if( hdrlen )
+       log_bug("can't cope with hdrlen yet\n");
+
+    if( iobuf_put(out, ctb ) )
+       return -1;
+    if( !len ) {
+       log_bug("can't write partial headers yet\n");
+    }
+    else {
+       if( len < 192 ) {
+           if( iobuf_put(out, len ) )
+               return -1;
+       }
+       else if( len < 8384 ) {
+           len -= 192;
+           if( iobuf_put( out, (len / 256) + 192) )
+               return -1;
+           if( iobuf_put( out, (len % 256) )  )
+               return -1;
+       }
+       else
+           log_bug("need a partial header to code a length %lu\n", (ulong)len);
+    }
+    return 0;
+}
+
 static int
 write_version( IOBUF out, int ctb )
 {
index 0502b36..8f8b5e6 100644 (file)
@@ -41,7 +41,6 @@ static void
 init_compress( compress_filter_context_t *zfx, z_stream *zs )
 {
     int rc;
-    byte *inbuf, *outbuf;
     int level;
 
 
@@ -102,9 +101,6 @@ static void
 init_uncompress( compress_filter_context_t *zfx, z_stream *zs )
 {
     int rc;
-    byte *inbuf, *outbuf;
-    int level;
-
 
     /****************
      * PGP uses a windowsize of 13 bits. Using a negative value for
@@ -175,7 +171,7 @@ compress_filter( void *opaque, int control,
     size_t size = *ret_len;
     compress_filter_context_t *zfx = opaque;
     z_stream *zs = zfx->opaque;
-    int zrc, rc=0;
+    int rc=0;
 
     if( control == IOBUFCTRL_UNDERFLOW ) {
        if( !zfx->status ) {
index ff12507..04aebef 100644 (file)
@@ -265,7 +265,7 @@ encrypt_filter( void *opaque, int control,
     int rc=0;
 
     if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */
-       log_bug(NULL); /* not used */
+       BUG(); /* not used */
     }
     else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
        if( !efx->header_okay ) {
@@ -317,7 +317,7 @@ write_pubkey_enc_from_list( PKC_LIST pkc_list, DEK *dek, IOBUF out )
        else if( enc->pubkey_algo == PUBKEY_ALGO_RSA )
            g10_rsa_encrypt( pkc, enc, dek );
        else
-           log_bug(NULL);
+           BUG();
        /* and write it */
        init_packet(&pkt);
        pkt.pkttype = PKT_PUBKEY_ENC;
index 2002e69..a00a3f9 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -22,6 +22,7 @@
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 
 #include "packet.h"
 #include "cipher.h"
 #include "filter.h"
 #include "trustdb.h"
+#include "ttyio.h"
 
 enum cmd_values { aNull = 0,
     aSym, aStore, aEncr, aPrimegen, aKeygen, aSign, aSignEncr,
     aPrintMDs, aSignKey, aClearsig, aListPackets, aEditSig,
-    aKMode, aKModeC, aChangePass,
+    aKMode, aKModeC, aChangePass, aImport, aListTrustDB,
+    aListTrustPath,
 aTest };
 
 
@@ -89,6 +92,15 @@ strusage( int level )
 }
 
 static void
+wrong_args( const char *text)
+{
+    fputs("Usage: g10 [options] ",stderr);
+    fputs(text,stderr);
+    putc('\n',stderr);
+    exit(2);
+}
+
+static void
 set_debug(void)
 {
     if( opt.debug & DBG_MEMORY_VALUE )
@@ -174,11 +186,15 @@ main( int argc, char **argv )
     { 527, "cipher-algo", 2 , "select default cipher algorithm" },
     { 528, "pubkey-algo", 2 , "select default puplic key algorithm" },
     { 529, "digest-algo", 2 , "select default message digest algorithm" },
+    { 530, "import",      0 , "put public keys into the trustdb" },
+    { 531, "list-trustdb",0 , "\r"},
+    { 532, "quick-random", 0, "\r"},
+    { 533, "list-trust-path",0, "\r"},
 
     {0} };
     ARGPARSE_ARGS pargs;
     IOBUF a;
-    int rc;
+    int rc=0;
     int orig_argc;
     char **orig_argv;
     const char *fname, *fname_print;
@@ -316,9 +332,10 @@ main( int argc, char **argv )
          case 529:
            opt.def_digest_algo = string_to_digest_algo(pargs.r.ret_str);
            break;
-
-
-           break;
+         case 530: set_cmd( &cmd, aImport); break;
+         case 531: set_cmd( &cmd, aListTrustDB); break;
+         case 532: quick_random_gen(1); break;
+         case 533: set_cmd( &cmd, aListTrustPath); break;
          default : errors++; pargs.err = configfp? 1:2; break;
        }
     }
@@ -393,11 +410,15 @@ main( int argc, char **argv )
        }
     }
 
-    if( cmd != aPrimegen && cmd != aPrintMDs ) {
-       rc = check_trustdb(0);
-       if( rc )
-           log_error("failed to initialize the TrustDB: %s\n", g10_errstr(rc));
+    switch( cmd ) {
+      case aPrimegen:
+      case aPrintMDs:
+       break;
+      case aListTrustDB: rc = init_trustdb( argc? 1:0 ); break;
+      default: rc = init_trustdb(1); break;
     }
+    if( rc )
+       log_error("failed to initialize the TrustDB: %s\n", g10_errstr(rc));
 
 
     switch( cmd ) {
@@ -487,7 +508,7 @@ main( int argc, char **argv )
            int i, seq=0;
            const char *s;
 
-           while( s=get_keyring(seq++) ) {
+           while( (s=get_keyring(seq++)) ) {
                if( !(a = iobuf_open(s)) ) {
                    log_error("can't open '%s'\n", s);
                    continue;
@@ -554,6 +575,32 @@ main( int argc, char **argv )
 
       case aTest: do_test( argc? atoi(*argv): 0 ); break;
 
+      case aImport:
+       if( !argc  )
+           usage(1);
+       for( ; argc; argc--, argv++ ) {
+           rc = import_pubkeys( *argv );
+           if( rc )
+               log_error("import from '%s' failed: %s\n",
+                                               *argv, g10_errstr(rc) );
+       }
+       break;
+
+      case aListTrustDB:
+       if( !argc )
+           list_trustdb(NULL);
+       else {
+           for( ; argc; argc--, argv++ )
+               list_trustdb( *argv );
+       }
+       break;
+
+      case aListTrustPath:
+       if( argc != 2 )
+           wrong_args("--list-trust-path  <maxdepth> <username>");
+       list_trust_path( atoi(*argv), argv[1] );
+       break;
+
       case aListPackets:
        opt.list_packets=1;
       default:
@@ -631,8 +678,6 @@ print_mds( const char *fname )
     if( ferror(fp) )
        log_error("%s: %s\n", fname, strerror(errno) );
     else {
-       byte *p;
-
        md_final(md);
        printf(  "%s:    MD5 =", fname ); print_hex(md_read(md, DIGEST_ALGO_MD5), 16 );
        printf("\n%s: RMD160 =", fname ); print_hex(md_read(md, DIGEST_ALGO_RMD160), 20 );
diff --git a/g10/import.c b/g10/import.c
new file mode 100644 (file)
index 0000000..91140d4
--- /dev/null
@@ -0,0 +1,146 @@
+/* import.c
+ *     Copyright (c) 1998 by Werner Koch (dd9jn)
+ *
+ * This file is part of G10.
+ *
+ * G10 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.
+ *
+ * G10 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "options.h"
+#include "packet.h"
+#include "errors.h"
+#include "keydb.h"
+#include "memory.h"
+#include "util.h"
+#include "trustdb.h"
+
+
+/****************
+ * Import the public keys from the given filename.
+ * Import is a somewhat misleading name, as we (only) add informations
+ * about the public keys into aout trustdb.
+ *
+ * NOTE: this function is not really needed and will be changed to
+ *     a function which reads a plain textfile, describing a public
+ *     key and its associated ownertrust.  This can be used (together
+ *     with the export function) to make a backup of the assigned
+ *     ownertrusts.
+ */
+int
+import_pubkeys( const char *filename )
+{
+    int rc;
+    PACKET pkt;
+    int save_mode;
+    ulong offset;
+    IOBUF iobuf = NULL;
+
+    init_packet(&pkt);
+    save_mode = set_packet_list_mode(0);
+
+    if( !(iobuf = iobuf_open( filename )) ) {
+       rc = G10ERR_KEYRING_OPEN;
+       goto leave;
+    }
+
+    while( !(rc=search_packet(iobuf, &pkt, PKT_PUBLIC_CERT, &offset)) ) {
+       PKT_public_cert *pkc = pkt.pkt.public_cert;
+       u32 keyid[2];
+       int otrust;
+
+       assert( pkt.pkttype == PKT_PUBLIC_CERT );
+
+       keyid_from_pkc( pkc, keyid );
+       rc = get_ownertrust( pkc, &otrust );
+       if( rc && rc != -1  ) {
+           log_error("error getting otrust of %08lX: %s\n",
+                                             keyid[1], g10_errstr(rc) );
+       }
+       else if( rc == -1 ) { /* No pubkey in trustDB: Insert */
+           rc = insert_trust_record( pkc );
+           if( rc ) {
+               log_error("failed to insert it into the trustdb: %s\n",
+                                                         g10_errstr(rc) );
+           }
+           else {
+               rc = get_ownertrust( pkc, &otrust );
+               if( rc )
+                   log_fatal("failed to reread the pubkey record: %s\n",
+                                                             g10_errstr(rc) );
+               log_info("key %08lX inserted in trustdb (localid=%lu)\n",
+                                                keyid[1], pkc->local_id );
+           }
+       }
+       else
+           log_info("key %08lX  already in trustdb (localid=%lu)\n",
+                                            keyid[1], pkc->local_id );
+
+       free_packet(&pkt);
+    }
+
+    iobuf_close(iobuf);
+    if( !(iobuf = iobuf_open( filename )) ) {
+       rc = G10ERR_KEYRING_OPEN;
+       goto leave;
+    }
+
+    while( !(rc=search_packet(iobuf, &pkt, PKT_PUBLIC_CERT, &offset)) ) {
+       PKT_public_cert *pkc = pkt.pkt.public_cert;
+       u32 keyid[2];
+       int trustlevel;
+
+       assert( pkt.pkttype == PKT_PUBLIC_CERT );
+
+       keyid_from_pkc( pkc, keyid );
+       rc = check_pkc_trust( pkc, &trustlevel );
+       if( rc ) {
+           log_error("error checking trust of %08lX: %s\n",
+                                             keyid[1], g10_errstr(rc) );
+       }
+       else if( trustlevel & TRUST_NO_PUBKEY ) {
+           /* No pubkey in trustDB: Insert and check again */
+           rc = insert_trust_record( pkc );
+           if( rc ) {
+               log_error("failed to insert it into the trustdb: %s\n",
+                                                         g10_errstr(rc) );
+           }
+           else {
+               rc = check_pkc_trust( pkc, &trustlevel );
+               if( rc )
+                   log_fatal("trust check after insert failed: %s\n",
+                                                             g10_errstr(rc) );
+               if( trustlevel & TRUST_NO_PUBKEY )
+                   BUG();
+           }
+       }
+
+       free_packet(&pkt);
+    }
+
+  leave:
+    iobuf_close(iobuf);
+    free_packet(&pkt);
+    set_packet_list_mode(save_mode);
+    return rc;
+}
+
+
index 8eb4947..818b643 100644 (file)
@@ -72,6 +72,17 @@ struct skc_list {
     int mark;
 };
 
+/* structure to collect all informations which can be used to
+ * identify a public key */
+typedef struct pubkey_find_info *PUBKEY_FIND_INFO;
+struct pubkey_find_info {
+    u32  keyid[2];
+    unsigned nbits;
+    byte pubkey_algo;
+    byte fingerprint[20];
+    char userid[1];
+};
+
 
 /*-- pkclist.c --*/
 void release_pkc_list( PKC_LIST pkc_list );
@@ -128,9 +139,9 @@ void clear_kbnode_flags( KBNODE n );
 /*-- ringedit.c --*/
 int add_keyblock_resource( const char *filename, int force, int secret );
 int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos );
-int search_keyblock( PACKET *pkt, KBPOS *kbpos, int secret );
-int search_keyblock_byname( KBPOS *kbpos, const char *username );
-int search_secret_keyblock_byname( KBPOS *kbpos, const char *username );
+int find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos );
+int find_keyblock_byname( KBPOS *kbpos, const char *username );
+int find_secret_keyblock_byname( KBPOS *kbpos, const char *username );
 int lock_keyblock( KBPOS *kbpos );
 void unlock_keyblock( KBPOS *kbpos );
 int read_keyblock( KBPOS *kbpos, KBNODE *ret_root );
index c83d866..1f932f7 100644 (file)
@@ -113,7 +113,7 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc )
            break;
     }
     if( !node )
-       log_bug(NULL); /* no user id packet in tree */
+       BUG(); /* no user id packet in tree */
     uid = node->pkt->pkt.user_id;
     /* get the pkc packet from the pub_tree */
     for( kbctx=NULL; (node=walk_kbtree( pub_root, &kbctx)) ; ) {
@@ -121,7 +121,7 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc )
            break;
     }
     if( !node )
-       log_bug(NULL);
+       BUG();
     pkc = node->pkt->pkt.public_cert;
 
     /* and make the signature */
@@ -149,12 +149,11 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
     PKT_public_cert *pkc;
     ELG_public_key pk;
     ELG_secret_key sk;
-    unsigned nbytes;
 
     elg_generate( &pk, &sk, nbits );
 
-    skc = m_alloc( sizeof *skc );
-    pkc = m_alloc( sizeof *pkc );
+    skc = m_alloc_clear( sizeof *skc );
+    pkc = m_alloc_clear( sizeof *pkc );
     skc->timestamp = pkc->timestamp = make_timestamp();
     skc->valid_days = pkc->valid_days = 0; /* fixme: make it configurable*/
     skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_ELGAMAL;
@@ -217,8 +216,8 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io, DEK *dek,
 
     rsa_generate( &pk, &sk, nbits );
 
-    skc = m_alloc( sizeof *skc );
-    pkc = m_alloc( sizeof *pkc );
+    skc = m_alloc_clear( sizeof *skc );
+    pkc = m_alloc_clear( sizeof *pkc );
     skc->timestamp = pkc->timestamp = make_timestamp();
     skc->valid_days = pkc->valid_days = 0; /* fixme: make it configurable*/
     skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_RSA;
@@ -297,8 +296,6 @@ generate_keypair()
     char *pub_fname = NULL;
     char *sec_fname = NULL;
     char *uid = NULL;
-    IOBUF pub_io = NULL;
-    IOBUF sec_io = NULL;
     KBNODE pub_root = NULL;
     KBNODE sec_root = NULL;
     PKT_secret_cert *skc = NULL;
@@ -473,9 +470,14 @@ generate_keypair()
            p = stpcpy(stpcpy(stpcpy(p," ("), acomment),")");
        if( *amail )
            p = stpcpy(stpcpy(stpcpy(p," <"), amail),">");
-      #ifndef HAVE_DEV_RANDOM
-       strcpy(p, " (INSECURE!)" );
+
+       /* append a warning if we do not have dev/random
+        * or it is switched into  quick testmode */
+      #ifdef HAVE_DEV_RANDOM
+       if( quick_random_gen(-1) )
       #endif
+           strcpy(p, " (INSECURE!)" );
+
 
        tty_printf("You selected this USER-ID:\n    \"%s\"\n\n", uid);
        for(;;) {
@@ -570,7 +572,7 @@ generate_keypair()
     else if( algo == PUBKEY_ALGO_DSA )
        rc = gen_dsa(nbits, pub_root, sec_root, dek, &skc );
     else
-       log_bug(NULL);
+       BUG();
     if( !rc )
        write_uid(pub_root, uid );
     if( !rc )
index 01604df..5d5a043 100644 (file)
@@ -106,7 +106,6 @@ static MD_HANDLE
 v3_elg_fingerprint_md_skc( PKT_secret_cert *skc )
 {
     PKT_public_cert pkc;
-    byte *p;
 
     pkc.pubkey_algo = skc->pubkey_algo;
     pkc.timestamp = skc->timestamp;
index a1a13e4..273e7a8 100644 (file)
@@ -48,7 +48,7 @@ int edit_keysigs( const char *username );
 int change_passphrase( const char *username );
 
 /*-- sig-check.c --*/
-int check_key_signature( KBNODE root, KBNODE node );
+int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig );
 
 /*-- keygen.c --*/
 void generate_keypair(void);
@@ -77,5 +77,8 @@ void g10_elg_sign( PKT_secret_cert *skc, PKT_signature *sig, MD_HANDLE md );
 void g10_rsa_encrypt( PKT_public_cert *pkc, PKT_pubkey_enc *enc, DEK *dek );
 void g10_rsa_sign( PKT_secret_cert *skc, PKT_signature *sig, MD_HANDLE md );
 
+/*-- import.c --*/
+int import_pubkeys( const char *filename );
+
 
 #endif /*G10_MAIN_H*/
index f64a2cd..36c3381 100644 (file)
@@ -110,7 +110,6 @@ add_secret_cert( CTX c, PACKET *pkt )
 static int
 add_user_id( CTX c, PACKET *pkt )
 {
-    u32 keyid[2];
     KBNODE node, n1, n2;
 
     if( !c->cert ) {
@@ -142,7 +141,6 @@ add_user_id( CTX c, PACKET *pkt )
 static int
 add_signature( CTX c, PACKET *pkt )
 {
-    u32 keyid[2];
     KBNODE node, n1, n2;
 
     if( !c->cert ) {
@@ -329,7 +327,7 @@ do_check_sig( CTX c, KBNODE node )
                if( c->cert->pkt->pkt.public_cert->mfx.md )
                    md = md_copy( c->cert->pkt->pkt.public_cert->mfx.md );
                else
-                   log_bug(NULL);
+                   BUG();
                md_write( md, n1->pkt->pkt.user_id->name, n1->pkt->pkt.user_id->len);
            }
            else {
@@ -356,7 +354,7 @@ static void
 print_userid( PACKET *pkt )
 {
     if( !pkt )
-       log_bug(NULL);
+       BUG();
     if( pkt->pkttype != PKT_USER_ID ) {
        printf("ERROR: unexpected packet type %d", pkt->pkttype );
        return;
@@ -493,9 +491,7 @@ proc_packets( IOBUF a )
 {
     CTX c = m_alloc_clear( sizeof *c );
     PACKET *pkt = m_alloc( sizeof *pkt );
-    int rc, result;
-    int lvl0, lvl1;
-    u32 keyid[2];
+    int rc;
     int newpkt;
 
     c->iobuf = a;
index 6326c43..2856952 100644 (file)
@@ -42,9 +42,8 @@ typedef enum {
        PKT_PLAINTEXT     =11, /* plaintext data with filename and mode */
        PKT_RING_TRUST    =12, /* keyring trust packet */
        PKT_USER_ID       =13, /* user id packet */
-       PKT_COMMENT       =14, /* comment packet */
        PKT_PUBKEY_SUBCERT=14, /* subkey certificate (OpenPGP) */
-       PKT_NEW_COMMENT   =16  /* new comment packet (OpenPGP) */
+       PKT_COMMENT       =16  /* new comment packet (OpenPGP) */
 } pkttype_t;
 
 typedef struct packet_struct PACKET;
@@ -74,6 +73,7 @@ typedef struct {
 
 typedef struct {
     u32     keyid[2];      /* 64 bit keyid */
+    ulong   local_id;      /* internal use, valid if > 0 */
     u32     timestamp;     /* signature made */
     byte    sig_class;     /* sig classification, append for MD calculation*/
     byte    pubkey_algo;    /* algorithm used for public key scheme */
@@ -96,9 +96,11 @@ typedef struct {
 typedef struct {
     u32     timestamp;     /* certificate made */
     u16     valid_days;     /* valid for this number of days */
+    byte    hdrbytes;      /* number of header bytes */
+    byte    version;
     byte    pubkey_algo;    /* algorithm used for public key scheme */
     md_filter_context_t mfx;
-    u32     local_id;      /* internal use, valid if > 0 */
+    ulong   local_id;      /* internal use, valid if > 0 */
     union {
       struct {
        MPI p;              /* prime */
@@ -115,6 +117,8 @@ typedef struct {
 typedef struct {
     u32     timestamp;     /* certificate made */
     u16     valid_days;     /* valid for this number of days */
+    byte    hdrbytes;      /* number of header bytes */
+    byte    version;
     byte    pubkey_algo;    /* algorithm used for public key scheme */
     union {
       struct {
index 1d056d8..5d96756 100644 (file)
@@ -50,6 +50,7 @@ static int  parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
                                      byte *hdr, int hdrlen, PACKET *packet );
 static int  parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
                                                           PACKET *packet );
+static void parse_subkey( IOBUF inp, int pkttype, unsigned long pktlen );
 static void parse_comment( IOBUF inp, int pkttype, unsigned long pktlen );
 static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen );
 static int  parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
@@ -58,7 +59,7 @@ static int  parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
                                                           PACKET *packet );
 static int  parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
                                                           PACKET *packet );
-
+#if 0
 static u16
 checksum( byte *p )
 {
@@ -70,6 +71,7 @@ checksum( byte *p )
        a += *p++;
     return a;
 }
+#endif
 
 static unsigned short
 read_16(IOBUF inp)
@@ -143,10 +145,11 @@ search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos )
 static int
 parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos, int *skip )
 {
-    int rc, ctb, pkttype, lenbytes;
+    int rc, c, ctb, pkttype, lenbytes;
     unsigned long pktlen;
     byte hdr[5];
     int hdrlen;
+    int pgp3 = 0;
 
     *skip = 0;
     assert( !pkt->pkt.generic );
@@ -157,22 +160,49 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos, int *skip )
     hdrlen=0;
     hdr[hdrlen++] = ctb;
     if( !(ctb & 0x80) ) {
-       log_error("invalid packet at '%s'\n", iobuf_where(inp) );
+       log_error("%s: invalid packet (ctb=%02x)\n", iobuf_where(inp), ctb );
        return G10ERR_INVALID_PACKET;
     }
-    /* we handle the pgp 3 extensions here, so that we can skip such packets*/
-    pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
-    lenbytes = (ctb & 0x40) || ((ctb&3)==3)? 0 : (1<<(ctb & 3));
     pktlen = 0;
-    if( !lenbytes ) {
-       pktlen = 0; /* don't know the value */
-       if( pkttype != PKT_COMPRESSED )
-           iobuf_set_block_mode(inp, 1);
+    pgp3 = !!(ctb & 0x40);
+    if( pgp3 ) {
+       pkttype =  ctb & 0x3f;
+       if( (c = iobuf_get(inp)) == -1 ) {
+           log_error("%s: 1st length byte missing\n", iobuf_where(inp) );
+           return G10ERR_INVALID_PACKET;
+       }
+       hdr[hdrlen++] = c;
+       if( c < 192 )
+           pktlen = c;
+       else if( c < 224 ) {
+           pktlen = (c - 192) * 256;
+           if( (c = iobuf_get(inp)) == -1 ) {
+               log_error("%s: 2nd length byte missing\n", iobuf_where(inp) );
+               return G10ERR_INVALID_PACKET;
+           }
+           hdr[hdrlen++] = c;
+           pktlen += c + 192;
+       }
+       else { /* partial body length */
+           pktlen = 1 << (c & 0x1f);
+           log_debug("partial body length of %lu bytes\n", pktlen );
+           iobuf_set_partial_block_mode(inp, pktlen);
+           pktlen = 0;/* to indicate partial length */
+       }
     }
     else {
-       for( ; lenbytes; lenbytes-- ) {
-           pktlen <<= 8;
-           pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
+       pkttype = (ctb>>2)&0xf;
+       lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
+       if( !lenbytes ) {
+           pktlen = 0; /* don't know the value */
+           if( pkttype != PKT_COMPRESSED )
+               iobuf_set_block_mode(inp, 1);
+       }
+       else {
+           for( ; lenbytes; lenbytes-- ) {
+               pktlen <<= 8;
+               pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
+           }
        }
     }
 
@@ -183,10 +213,10 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos, int *skip )
     }
 
     if( DBG_PACKET )
-       log_debug("parse_packet(iob=%d): type=%d length=%lu\n",
-                                           iobuf_id(inp), pkttype, pktlen );
+       log_debug("parse_packet(iob=%d): type=%d length=%lu%s\n",
+                  iobuf_id(inp), pkttype, pktlen, pgp3?" (pgp3)":"" );
     pkt->pkttype = pkttype;
-    rc = G10ERR_UNKNOWN_PACKET; /* default to no error */
+    rc = G10ERR_UNKNOWN_PACKET; /* default error */
     switch( pkttype ) {
       case PKT_PUBLIC_CERT:
        pkt->pkt.public_cert = m_alloc_clear(sizeof *pkt->pkt.public_cert );
@@ -211,6 +241,9 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos, int *skip )
       case PKT_USER_ID:
        rc = parse_user_id(inp, pkttype, pktlen, pkt );
        break;
+      case PKT_PUBKEY_SUBCERT:
+       parse_subkey(inp, pkttype, pktlen);
+       break;
       case PKT_COMMENT:
        parse_comment(inp, pkttype, pktlen);
        break;
@@ -234,12 +267,43 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos, int *skip )
     return rc;
 }
 
+static void
+dump_hex_line( int c, int *i )
+{
+    if( *i && !(*i%8) ) {
+       if( *i && !(*i%24) )
+           printf("\n%4d:", *i );
+       else
+           putchar(' ');
+    }
+    if( c == -1 )
+       printf(" EOF" );
+    else
+       printf(" %02x", c );
+    ++*i;
+}
+
 
 static void
 skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
 {
-    if( list_mode )
+    if( list_mode ) {
        printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen );
+       if( pkttype ) {
+           int c, i=0 ;
+           printf("dump:");
+           if( iobuf_in_block_mode(inp) ) {
+               while( (c=iobuf_get(inp)) != -1 )
+                   dump_hex_line(c, &i);
+           }
+           else {
+               for( ; pktlen; pktlen-- )
+                   dump_hex_line(iobuf_get(inp), &i);
+           }
+           putchar('\n');
+           return;
+       }
+    }
     skip_rest(inp,pktlen);
 }
 
@@ -278,7 +342,7 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
     k->keyid[1] = read_32(inp); pktlen -= 4;
     k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
     if( list_mode )
-       printf(":public key packet: keyid %08lX%08lX\n",
+       printf(":public key encoded packet: keyid %08lX%08lX\n",
                                        k->keyid[0], k->keyid[1]);
     if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
        n = pktlen;
@@ -394,7 +458,6 @@ parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
                                             PKT_onepass_sig *ops )
 {
     int version;
-    unsigned n;
 
     if( pktlen < 13 ) {
        log_error("packet(%d) too short\n", pkttype);
@@ -461,22 +524,27 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
     timestamp = read_32(inp); pktlen -= 4;
     if( is_v4 )
        valid_period = 0;
-    else
+    else {
        valid_period = read_16(inp); pktlen -= 2;
+    }
     algorithm = iobuf_get_noeof(inp); pktlen--;
     if( list_mode )
-       printf(":%s key certification packet:\n"
+       printf(":%s key packet:\n"
               "\tversion %d, created %lu, valid for %hu days\n",
                pkttype == PKT_PUBLIC_CERT? "public": "secret",
                version, timestamp, valid_period );
     if( pkttype == PKT_SECRET_CERT )  {
        pkt->pkt.secret_cert->timestamp = timestamp;
        pkt->pkt.secret_cert->valid_days = valid_period;
+       pkt->pkt.secret_cert->hdrbytes = hdrlen;
+       pkt->pkt.secret_cert->version = version;
        pkt->pkt.secret_cert->pubkey_algo = algorithm;
     }
     else {
        pkt->pkt.public_cert->timestamp = timestamp;
        pkt->pkt.public_cert->valid_days = valid_period;
+       pkt->pkt.public_cert->hdrbytes    = hdrlen;
+       pkt->pkt.public_cert->version     = version;
        pkt->pkt.public_cert->pubkey_algo = algorithm;
     }
 
@@ -486,7 +554,7 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
        n = pktlen; elg_g = mpi_read(inp, &n, 0 ); pktlen -=n;
        n = pktlen; elg_y = mpi_read(inp, &n, 0 ); pktlen -=n;
        if( list_mode ) {
-           printf(  "\telg p:  ");
+           printf(  "\telg p: ");
            mpi_print(stdout, elg_p, mpi_print_mode  );
            printf("\n\telg g: ");
            mpi_print(stdout, elg_g, mpi_print_mode  );
@@ -502,7 +570,6 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
        else {
            PKT_secret_cert *cert = pkt->pkt.secret_cert;
            byte temp[8];
-           byte *mpibuf;
 
            pkt->pkt.secret_cert->d.elg.p = elg_p;
            pkt->pkt.secret_cert->d.elg.g = elg_g;
@@ -558,7 +625,6 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
        else {
            PKT_secret_cert *cert = pkt->pkt.secret_cert;
            byte temp[8];
-           byte *mpibuf;
 
            pkt->pkt.secret_cert->d.rsa.rsa_n = rsa_pub_mod;
            pkt->pkt.secret_cert->d.rsa.rsa_e = rsa_pub_exp;
@@ -636,6 +702,39 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
     return 0;
 }
 
+
+static void
+parse_subkey( IOBUF inp, int pkttype, unsigned long pktlen )
+{
+    int version;
+
+    version = iobuf_get_noeof(inp); pktlen--;
+    if( pkttype == PKT_PUBKEY_SUBCERT && version == '#' ) {
+       /* early versions of G10 use old comments packets; luckily all those
+        * comments are are started by a hash */
+       if( list_mode ) {
+           printf(":old comment packet: \"" );
+           for( ; pktlen; pktlen-- ) {
+               int c;
+               c = iobuf_get_noeof(inp);
+               if( c >= ' ' && c <= 'z' )
+                   putchar(c);
+               else
+                   printf("\\x%02x", c );
+           }
+           printf("\"\n");
+       }
+       skip_rest(inp, pktlen);
+       return;
+    }
+
+    if( list_mode )
+       printf(":public subkey packet: \"" );
+    skip_rest(inp, pktlen);
+}
+
+
+
 static void
 parse_comment( IOBUF inp, int pkttype, unsigned long pktlen )
 {
@@ -749,7 +848,6 @@ static int
 parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
 {
     PKT_compressed *zd;
-    int algorithm;
 
     /* pktlen is here 0, but data follows
      * (this should be the last object in a file or
index 462c7c7..d1b9146 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <assert.h>
 #include "util.h"
 #include "memory.h"
index 3fd2254..7feea8a 100644 (file)
@@ -56,7 +56,7 @@ do_we_trust( PKT_public_cert *pkc, int trustlevel )
            log_fatal("trust check after insert failed: %s\n",
                                                      g10_errstr(rc) );
        if( trustlevel & TRUST_NO_PUBKEY )
-           log_bug(NULL);
+           BUG();
     }
 
 
@@ -84,7 +84,6 @@ int
 build_pkc_list( STRLIST remusr, PKC_LIST *ret_pkc_list )
 {
     PKC_LIST pkc_list = NULL;
-    PKC_LIST pkc_rover = NULL;
     int rc;
 
     if( !remusr ) { /* ask!!! */
index 8b74319..ad5706c 100644 (file)
@@ -68,7 +68,12 @@ typedef struct resource_table_struct RESTBL;
 static RESTBL resource_table[MAX_RESOURCES];
 
 
+static int search( PACKET *pkt, KBPOS *kbpos, int secret );
+
+
 static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf );
+static int keyring_search2( PUBKEY_FIND_INFO info, KBPOS *kbpos,
+                                                  const char *fname);
 static int keyring_read( KBPOS *kbpos, KBNODE *ret_root );
 static int keyring_insert( KBPOS *kbpos, KBNODE root );
 static int keyring_delete( KBPOS *kbpos );
@@ -138,6 +143,37 @@ get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos )
     return -1; /* not found */
 }
 
+
+/****************
+ * Find a keyblock from the informations provided in INFO
+ * This can only be used fro public keys
+ */
+int
+find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos )
+{
+    int i, rc, last_rc=-1;
+
+    for(i=0; i < MAX_RESOURCES; i++ ) {
+       if( resource_table[i].used && !resource_table[i].secret ) {
+           /* note: here we have to add different search functions,
+            * depending on the type of the resource */
+           rc = keyring_search2( info, kbpos, resource_table[i].fname );
+           if( !rc ) {
+               kbpos->resno = i;
+               return 0;
+           }
+           if( rc != -1 ) {
+               log_error("error searching resource %d: %s\n",
+                                                 i, g10_errstr(rc));
+               last_rc = rc;
+           }
+       }
+    }
+    return last_rc;
+}
+
+
+
 /****************
  * Search a keyblock which starts with the given packet and put all
  * informations into KBPOS, which can be used later to access this key block.
@@ -149,8 +185,8 @@ get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos )
  *
  * Returns: 0 if found, -1 if not found or an errorcode.
  */
-int
-search_keyblock( PACKET *pkt, KBPOS *kbpos, int secret )
+static int
+search( PACKET *pkt, KBPOS *kbpos, int secret )
 {
     int i, rc, last_rc=-1;
 
@@ -179,7 +215,7 @@ search_keyblock( PACKET *pkt, KBPOS *kbpos, int secret )
  * of the keyblock.
  */
 int
-search_keyblock_byname( KBPOS *kbpos, const char *username )
+find_keyblock_byname( KBPOS *kbpos, const char *username )
 {
     PACKET pkt;
     PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
@@ -194,7 +230,7 @@ search_keyblock_byname( KBPOS *kbpos, const char *username )
     init_packet( &pkt );
     pkt.pkttype = PKT_PUBLIC_CERT;
     pkt.pkt.public_cert = pkc;
-    rc = search_keyblock( &pkt, kbpos, 0 );
+    rc = search( &pkt, kbpos, 0 );
     free_public_cert(pkc);
     return rc;
 }
@@ -204,7 +240,7 @@ search_keyblock_byname( KBPOS *kbpos, const char *username )
  * of the keyblock. This function does not unprotect the secret key.
  */
 int
-search_secret_keyblock_byname( KBPOS *kbpos, const char *username )
+find_secret_keyblock_byname( KBPOS *kbpos, const char *username )
 {
     PACKET pkt;
     PKT_secret_cert *skc = m_alloc_clear( sizeof *skc );
@@ -219,7 +255,7 @@ search_secret_keyblock_byname( KBPOS *kbpos, const char *username )
     init_packet( &pkt );
     pkt.pkttype = PKT_SECRET_CERT;
     pkt.pkt.secret_cert = skc;
-    rc = search_keyblock( &pkt, kbpos, 1 );
+    rc = search( &pkt, kbpos, 1 );
     free_secret_cert(skc);
     return rc;
 }
@@ -229,13 +265,11 @@ search_secret_keyblock_byname( KBPOS *kbpos, const char *username )
  * Lock the keyblock; wait until it's available
  * This function may change the internal data in kbpos, in cases
  * when the to be locked keyblock has been modified.
- * fixme: remove this function and add an option to search_keyblock()?
+ * fixme: remove this function and add an option to search()?
  */
 int
 lock_keyblock( KBPOS *kbpos )
 {
-    int rc;
-
     if( !check_pos(kbpos) )
        return G10ERR_GENERAL;
     return 0;
@@ -248,7 +282,7 @@ void
 unlock_keyblock( KBPOS *kbpos )
 {
     if( !check_pos(kbpos) )
-       log_bug(NULL);
+       BUG();
 }
 
 /****************
@@ -389,13 +423,75 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf )
                break; /* found */
        }
        else
-           log_bug(NULL);
+           BUG();
+       free_packet(&pkt);
+    }
+    if( !rc )
+       kbpos->offset = offset;
+
+  leave:
+    free_packet(&pkt);
+    set_packet_list_mode(save_mode);
+    return rc;
+}
+
+/****************
+ * search one keyring, return 0 if found, -1 if not found or an errorcode.
+ * this version uses the finger print and other informations
+ */
+static int
+keyring_search2( PUBKEY_FIND_INFO info, KBPOS *kbpos, const char *fname )
+{
+    int rc;
+    PACKET pkt;
+    int save_mode;
+    ulong offset;
+    IOBUF iobuf;
+
+    init_packet(&pkt);
+    save_mode = set_packet_list_mode(0);
+
+  #if 0
+    if( iobuf_seek( iobuf, 0 ) ) {
+       log_error("can't rewind keyring file: %s\n", g10_errstr(rc));
+       rc = G10ERR_KEYRING_OPEN;
+       goto leave;
+    }
+  #else
+    iobuf = iobuf_open( fname );
+    if( !iobuf ) {
+       log_error("can't open '%s'\n", fname );
+       rc = G10ERR_OPEN_FILE;
+       goto leave;
+    }
+  #endif
+
+    while( !(rc=search_packet(iobuf, &pkt, PKT_PUBLIC_CERT, &offset)) ) {
+       PKT_public_cert *pkc = pkt.pkt.public_cert;
+       u32 keyid[2];
+
+       assert( pkt.pkttype == PKT_PUBLIC_CERT );
+       keyid_from_pkc( pkc, keyid );
+       if( keyid[0] == info->keyid[0] && keyid[1] == info->keyid[1]
+           && pkc->pubkey_algo == info->pubkey_algo ) {
+           /* fixme: shall we check nbits too? (good for rsa keys) */
+           /* fixme: check userid???? */
+           size_t len;
+           byte *fp = fingerprint_from_pkc( pkc, &len );
+
+           if( !memcmp( fp, info->fingerprint, len ) ) {
+               m_free(fp);
+               break; /* found */
+           }
+           m_free(fp);
+       }
        free_packet(&pkt);
     }
     if( !rc )
        kbpos->offset = offset;
 
   leave:
+    iobuf_close(iobuf);
     free_packet(&pkt);
     set_packet_list_mode(save_mode);
     return rc;
@@ -562,7 +658,6 @@ keyring_delete( KBPOS *kbpos )
 {
     RESTBL *rentry;
     IOBUF fp;
-    KBNODE kbctx, node;
     int rc;
     u32 len;
     int ctb;
@@ -588,7 +683,7 @@ keyring_delete( KBPOS *kbpos )
     /*log_debug("writing a dummy packet of length %lu\n", (ulong)len);*/
 
     if( len < 2 )
-       log_bug(NULL);
+       BUG();
 
     if( len < 256 ) {
        ctb = 0x80;
index 7f76b31..ab10340 100644 (file)
@@ -60,7 +60,7 @@ static int
 check_elg( PKT_secret_cert *cert )
 {
     byte *buffer;
-    u16 n, csum=0;
+    u16 csum=0;
     int res;
     unsigned nbytes;
     u32 keyid[2];
@@ -73,7 +73,7 @@ check_elg( PKT_secret_cert *cert )
        BLOWFISH_context *blowfish_ctx=NULL;
 
        switch( cert->d.elg.protect_algo ) {
-         case CIPHER_ALGO_NONE: log_bug(NULL); break;
+         case CIPHER_ALGO_NONE: BUG(); break;
          case CIPHER_ALGO_BLOWFISH:
            keyid_from_skc( cert, keyid );
            dek = get_passphrase_hash( keyid, NULL );
@@ -142,7 +142,7 @@ protect_elg( PKT_secret_cert *cert, DEK *dek )
        BLOWFISH_context *blowfish_ctx=NULL;
 
        switch( cert->d.elg.protect_algo ) {
-         case CIPHER_ALGO_NONE: log_bug(NULL); break;
+         case CIPHER_ALGO_NONE: BUG(); break;
          case CIPHER_ALGO_BLOWFISH:
            blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
            blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
@@ -171,7 +171,7 @@ static int
 check_rsa( PKT_secret_cert *cert )
 {
     byte *buffer;
-    u16 n, csum=0;
+    u16 csum=0;
     int res;
     unsigned nbytes;
     u32 keyid[2];
@@ -183,7 +183,7 @@ check_rsa( PKT_secret_cert *cert )
 
        switch( cert->d.rsa.protect_algo ) {
            /* FIXME: use test variables to check for the correct key */
-         case CIPHER_ALGO_NONE: log_bug(NULL); break;
+         case CIPHER_ALGO_NONE: BUG(); break;
          case CIPHER_ALGO_BLOWFISH:
            keyid_from_skc( cert, keyid );
            dek = get_passphrase_hash( keyid, NULL );
index c99bed5..63e7b28 100644 (file)
@@ -46,7 +46,7 @@ make_session_key( DEK *dek )
        randomize_buffer( dek->key, dek->keylen, 1 );
        break;
 
-      default: log_bug("invalid algo %d in make_session_key()\n");
+      default: log_bug("invalid algo %d in make_session_key()\n", dek->algo);
     }
 }
 
@@ -116,9 +116,8 @@ encode_rmd160_value( byte *md, unsigned len, unsigned nbits )
          { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
            0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
     int nframe = (nbits+7) / 8;
-    byte *p;
     MPI frame;
-    int i,n,c;
+    int i,n;
 
     if( (nbits % BITS_PER_MPI_LIMB) || nframe < 42 || len != 20 )
        log_bug("can't encode a %d bit MD into a %d bits frame\n",len*8, nbits);
@@ -156,9 +155,8 @@ encode_sha1_value( byte *md, unsigned len, unsigned nbits )
          { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
            0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
     int nframe = (nbits+7) / 8;
-    byte *p;
     MPI frame;
-    int i,n,c;
+    int i,n;
 
     if( (nbits % BITS_PER_MPI_LIMB) || nframe < 42 || len != 20 )
        log_bug("can't encode a %d bit MD into a %d bits frame\n",len*8, nbits);
@@ -197,9 +195,8 @@ encode_md5_value( byte *md, unsigned len, unsigned nbits )
          { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48,
            0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
     int nframe = (nbits+7) / 8;
-    byte *p;
     MPI frame;
-    int i,n,c;
+    int i,n;
 
     if( (nbits % BITS_PER_MPI_LIMB) || nframe < 38 || len != 16 )
        log_bug("can't encode a %d bit MD into a %d bits frame\n",len*8, nbits);
@@ -236,7 +233,7 @@ encode_md_value( MD_HANDLE md, unsigned nbits )
       case DIGEST_ALGO_SHA1:
        return encode_sha1_value( md_read(md, DIGEST_ALGO_SHA1), 20, nbits );
       default:
-       log_bug(NULL);
+       BUG();
     }
 }
 
index 7451750..54ccae9 100644 (file)
@@ -143,7 +143,7 @@ signature_check( PKT_signature *sig, MD_HANDLE digest )
                md_putc( digest,  a        & 0xff );
            }
            md_final( digest );
-           dp = md_read( digest, 0 );
+           dp = md_read( digest, DIGEST_ALGO_RMD160 );
            for(i=19; i >= 0; i--, dp++ )
                if( mpi_getbyte( result, i ) != *dp ) {
                    rc = G10ERR_BAD_SIGN;
@@ -187,7 +187,7 @@ signature_check( PKT_signature *sig, MD_HANDLE digest )
                md_putc( digest,  a        & 0xff );
            }
            md_final( digest );
-           dp = md_read( digest, 0 );
+           dp = md_read( digest, DIGEST_ALGO_MD5 );
            for(i=15; i >= 0; i--, dp++ )
                if( mpi_getbyte( result, i ) != *dp ) {
                    rc = G10ERR_BAD_SIGN;
@@ -220,7 +220,7 @@ signature_check( PKT_signature *sig, MD_HANDLE digest )
  * check the signature pointed to by NODE. This is a key signatures
  */
 int
-check_key_signature( KBNODE root, KBNODE node )
+check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
 {
     KBNODE unode;
     MD_HANDLE md;
@@ -229,6 +229,8 @@ check_key_signature( KBNODE root, KBNODE node )
     int algo;
     int rc;
 
+    if( is_selfsig )
+       *is_selfsig = 0;
     assert( node->pkt->pkttype == PKT_SIGNATURE );
     assert( (node->pkt->pkt.signature->sig_class&~3) == 0x10 );
     assert( root->pkt->pkttype == PKT_PUBLIC_CERT );
@@ -250,6 +252,13 @@ check_key_signature( KBNODE root, KBNODE node )
     if( unode && unode->pkt->pkttype == PKT_USER_ID ) {
        PKT_user_id *uid = unode->pkt->pkt.user_id;
 
+       if( is_selfsig ) {
+           u32 keyid[2];
+
+           keyid_from_pkc( pkc, keyid );
+           if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
+               *is_selfsig = 1;
+       }
        md = md_open( algo, 0 );
        hash_public_cert( md, pkc );
        md_write( md, uid->name, uid->len );
index 9e8275a..247b30e 100644 (file)
@@ -52,7 +52,7 @@ complete_sig( PKT_signature *sig, PKT_secret_cert *skc, MD_HANDLE md )
     else if( sig->pubkey_algo == PUBKEY_ALGO_RSA )
        g10_rsa_sign( skc, sig, md );
     else
-       log_bug(NULL);
+       BUG();
 
     /* fixme: should we check wether the signature is okay? */
 
@@ -89,7 +89,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
     PACKET pkt;
     PKT_plaintext *pt = NULL;
     u32 filesize;
-    int last_rc, rc = 0;
+    int rc = 0;
     PKC_LIST pkc_list = NULL;
     SKC_LIST skc_list = NULL;
     SKC_LIST skc_rover = NULL;
@@ -318,7 +318,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
        }
       #endif/*HAVE_RSA_CIPHER*/
        else
-           log_bug(NULL);
+           BUG();
 
        md_close( md );
 
@@ -428,7 +428,7 @@ check_all_keysigs( KBNODE keyblock )
            int sigrc;
 
            tty_printf("sig");
-           switch( (rc = check_key_signature( keyblock, node )) ) {
+           switch( (rc = check_key_signature( keyblock, node,NULL)) ) {
              case 0:                node->flag = 0; sigrc = '!'; break;
              case G10ERR_BAD_SIGN:  inv_sigs++; node->flag = 1; sigrc = '-'; break;
              case G10ERR_NO_PUBKEY: no_key++;   node->flag = 2; sigrc = '?'; break;
@@ -478,7 +478,6 @@ remove_keysigs( KBNODE keyblock, int all )
            && node->pkt->pkttype == PKT_SIGNATURE
            && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
            PKT_signature *sig = node->pkt->pkt.signature;
-           int sigrc;
 
            if( all ) {
                /* fixme: skip self-sig */
@@ -546,14 +545,13 @@ sign_key( const char *username, STRLIST locusr )
     KBNODE kbctx, node;
     KBPOS kbpos;
     PKT_public_cert *pkc;
-    int any;
     u32 pkc_keyid[2];
     char *answer;
 
     memset( &mfx, 0, sizeof mfx);
 
     /* search the userid */
-    rc = search_keyblock_byname( &kbpos, username );
+    rc = find_keyblock_byname( &kbpos, username );
     if( rc ) {
        log_error("user '%s' not found\n", username );
        goto leave;
@@ -687,12 +685,10 @@ edit_keysigs( const char *username )
     KBNODE kbctx, node;
     KBPOS kbpos;
     PKT_public_cert *pkc;
-    int any;
     u32 pkc_keyid[2];
-    char *answer;
 
     /* search the userid */
-    rc = search_keyblock_byname( &kbpos, username );
+    rc = find_keyblock_byname( &kbpos, username );
     if( rc ) {
        log_error("user '%s' not found\n", username );
        goto leave;
@@ -755,13 +751,12 @@ change_passphrase( const char *username )
     KBNODE kbctx, node;
     KBPOS kbpos;
     PKT_secret_cert *skc;
-    int any;
     u32 skc_keyid[2];
     char *answer;
     int changed=0;
 
     /* search the userid */
-    rc = search_secret_keyblock_byname( &kbpos, username );
+    rc = find_secret_keyblock_byname( &kbpos, username );
     if( rc ) {
        log_error("secret key for user '%s' not found\n", username );
        goto leave;
index e7c9071..f906fc6 100644 (file)
@@ -49,7 +49,6 @@ int
 build_skc_list( STRLIST locusr, SKC_LIST *ret_skc_list, int unlock )
 {
     SKC_LIST skc_list = NULL;
-    SKC_LIST skc_rover = NULL;
     int rc;
 
     if( !locusr ) { /* use the default one */
index 092e98f..9f5bef7 100644 (file)
 #include "util.h"
 #include "trustdb.h"
 #include "options.h"
+#include "packet.h"
+#include "main.h"
 
 
 #define TRUST_RECORD_LEN 40
 #define SIGS_PER_RECORD ((TRUST_RECORD_LEN-10)/5)
+#define MAX_LIST_SIGS_DEPTH  20
 
 struct trust_record {
     byte rectype;
@@ -47,27 +50,27 @@ struct trust_record {
            byte magic[2];
            byte version;   /* should be 1 */
            byte reserved[3];
-           u32  locked;    /* pid of process which holds a lock */
-           u32  created;   /* timestamp of trustdb creation  */
-           u32  modified;  /* timestamp of last modification */
-           u32  validated; /* timestamp of last validation   */
-           u32  local_id_counter;
+           ulong locked;    /* pid of process which holds a lock */
+           ulong created;   /* timestamp of trustdb creation  */
+           ulong modified;  /* timestamp of last modification */
+           ulong validated; /* timestamp of last validation   */
+           ulong local_id_counter;
            byte marginals_needed;
            byte completes_needed;
            byte max_cert_depth;
        } version;
        struct {            /* public key record */
-           u32 local_id;
-           u32 keyid[2];
-           byte algo;
+           ulong local_id;
+           u32   keyid[2];
+           byte pubkey_algo;
            byte reserved;
            byte fingerprint[20];
            byte ownertrust;
            /* fixme: indicate a flag to */
        } pubkey;
        struct {            /* cache record */
-           u32 owner;
-           u32 keyid[2];       /* needed?? */
+           ulong owner;
+           u32   keyid[2];       /* needed?? */
            byte valid;
            byte reserved;
            byte blockhash[20];
@@ -77,10 +80,10 @@ struct trust_record {
            byte trustlevel;
        } cache;
        struct {
-           u32 owner;  /* local_id of record owner (pubkey record) */
-           u32 chain;  /* offset of next record or NULL for last one */
+           ulong owner;  /* local_id of record owner (pubkey record) */
+           ulong chain;  /* offset of next record or NULL for last one */
            struct {
-               u32  local_id; /* of pubkey record of signator (0=unused) */
+               ulong  local_id; /* of pubkey record of signator (0=unused) */
                byte flag;     /* reserved */
            } sig[SIGS_PER_RECORD];
        } sigrec;
@@ -88,29 +91,67 @@ struct trust_record {
 };
 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 */
+    struct {              /* internal data */
+       int eof;
+       TRUSTREC rec;
+       int index;
+    } ctl;
+} SIGREC_CONTEXT;
+
+typedef struct local_id_info *LOCAL_ID_INFO;
+struct local_id_info {
+    LOCAL_ID_INFO next;
+    ulong lid;
+    unsigned flag;
+};
+
+
 
 static void create_db( const char *fname );
 static void open_db(void);
-static int  read_record( u32 recnum, TRUSTREC *rec );
-static u32 new_local_id(void);
+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 LOCAL_ID_INFO *new_lid_table(void);
+static void release_lid_table( LOCAL_ID_INFO *tbl );
+static int get_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 pubkey, int depth, int max_depth,
+                        LOCAL_ID_INFO *lids, ulong *stack );
+
+static int list_sigs( ulong pubkey_id );
+
 
 static char *db_name;
 static int  db_fd = -1;
 static int no_io_dbg = 0;
+/* a table used to keep track of ultimately trusted keys
+ * which are the ones from our secrings */
+static LOCAL_ID_INFO *ultikey_table;
 
-#define buftou32( p )  ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \
+#define buftoulong( p )  ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \
                       (*((byte*)(p)+2) << 8) | (*((byte*)(p)+3)))
-#define buftou16( p )  ((*((byte*)(p)) << 8) | (*((byte*)(p)+1)))
-#define u32tobuf( p, a ) do {                          \
+#define buftoushort( p )  ((*((byte*)(p)) << 8) | (*((byte*)(p)+1)))
+#define ulongtobuf( p, a ) do {                          \
                            ((byte*)p)[0] = a >> 24;    \
                            ((byte*)p)[1] = a >> 16;    \
                            ((byte*)p)[2] = a >>  8;    \
                            ((byte*)p)[3] = a      ;    \
                        } while(0)
-#define u16tobuf( p, a ) do {                          \
+#define ushorttobuf( p, a ) do {                          \
                            ((byte*)p)[0] = a >>  8;    \
                            ((byte*)p)[1] = a      ;    \
                        } while(0)
+#define buftou32( p)   buftoulong( (p) )
+#define u32tobuf( p, a) ulongtobuf( (p), (a) )
 
 
 /**************************************************
@@ -124,25 +165,18 @@ fwrite_8(FILE *fp, byte a)
        log_fatal("error writing byte to trustdb: %s\n", strerror(errno) );
 }
 
-static void
-fwrite_16(FILE *fp, u16 a)
-{
-    putc( (a>>8) & 0x0ff , fp );
-    if( putc( a & 0xff, fp ) == EOF )
-       log_fatal("error writing u16 to trustdb: %s\n", strerror(errno) );
-}
 
-static int
-fwrite_32( FILE*fp, u32 a)
+static void
+fwrite_32( FILE*fp, ulong a)
 {
     putc( (a>>24) & 0xff, fp );
     putc( (a>>16) & 0xff, fp );
     putc( (a>> 8) & 0xff, fp );
     if( putc( a & 0xff, fp ) == EOF )
-       log_fatal("error writing u32 to trustdb: %s\n", strerror(errno) );
+       log_fatal("error writing ulong to trustdb: %s\n", strerror(errno) );
 }
 
-static int
+static void
 fwrite_zeros( FILE *fp, size_t n)
 {
     while( n-- )
@@ -163,8 +197,6 @@ static void
 create_db( const char *fname )
 {
     FILE *fp;
-    u32 along;
-    u16 ashort;
 
     fp =fopen( fname, "w" );
     if( !fp )
@@ -207,7 +239,7 @@ open_db()
  * returns: -1 on error, 0 on success
  */
 static int
-read_record( u32 recnum, TRUSTREC *rec )
+read_record( ulong recnum, TRUSTREC *rec )
 {
     byte buf[TRUST_RECORD_LEN], *p;
     int rc = 0;
@@ -242,11 +274,11 @@ read_record( u32 recnum, TRUSTREC *rec )
        rec->r.version.magic[1] = *p++;
        rec->r.version.version  = *p++;
        memcpy( rec->r.version.reserved, p, 3); p += 3;
-       rec->r.version.locked   = buftou32(p); p += 4;
-       rec->r.version.created  = buftou32(p); p += 4;
-       rec->r.version.modified = buftou32(p); p += 4;
-       rec->r.version.validated= buftou32(p); p += 4;
-       rec->r.version.local_id_counter = buftou32(p); p += 4;
+       rec->r.version.locked   = buftoulong(p); p += 4;
+       rec->r.version.created  = buftoulong(p); p += 4;
+       rec->r.version.modified = buftoulong(p); p += 4;
+       rec->r.version.validated= buftoulong(p); p += 4;
+       rec->r.version.local_id_counter = buftoulong(p); p += 4;
        rec->r.version.marginals_needed = *p++;
        rec->r.version.completes_needed = *p++;
        rec->r.version.max_cert_depth = *p++;
@@ -267,10 +299,10 @@ read_record( u32 recnum, TRUSTREC *rec )
        }
        break;
       case 2:
-       rec->r.pubkey.local_id = buftou32(p); p += 4;
+       rec->r.pubkey.local_id = buftoulong(p); p += 4;
        rec->r.pubkey.keyid[0] = buftou32(p); p += 4;
        rec->r.pubkey.keyid[1] = buftou32(p); p += 4;
-       rec->r.pubkey.algo = *p++;
+       rec->r.pubkey.pubkey_algo = *p++;
        rec->r.pubkey.reserved = *p++;
        memcpy( rec->r.pubkey.fingerprint, p, 20); p += 20;
        rec->r.pubkey.ownertrust = *p++;
@@ -283,7 +315,7 @@ read_record( u32 recnum, TRUSTREC *rec )
        }
        break;
       case 3:
-       rec->r.cache.local_id = buftou32(p); p += 4;
+       rec->r.cache.owner    = buftoulong(p); p += 4;
        rec->r.cache.keyid[0] = buftou32(p); p += 4;
        rec->r.cache.keyid[1] = buftou32(p); p += 4;
        rec->r.cache.valid = *p++;
@@ -296,10 +328,10 @@ read_record( u32 recnum, TRUSTREC *rec )
        break;
       case 4:
       case 5:
-       rec->r.sigrec.owner   = buftou32(p); p += 4;
-       rec->r.sigrec.chain   = buftou32(p); p += 4;
+       rec->r.sigrec.owner   = buftoulong(p); p += 4;
+       rec->r.sigrec.chain   = buftoulong(p); p += 4;
        for(i=0; i < SIGS_PER_RECORD; i++ ) {
-           rec->r.sigrec.sig[i].local_id = buftou32(p); p += 4;
+           rec->r.sigrec.sig[i].local_id = buftoulong(p); p += 4;
            rec->r.sigrec.sig[i].flag = *p++;
        }
        break;
@@ -309,7 +341,10 @@ read_record( u32 recnum, TRUSTREC *rec )
        rc = G10ERR_TRUSTDB;
        break;
     }
-
+    if( DBG_TRUST && !rc && !no_io_dbg ) {
+       log_debug("trustdb: ");
+       dump_record( recnum, rec, stderr);
+    }
 
     return rc;
 }
@@ -318,7 +353,7 @@ read_record( u32 recnum, TRUSTREC *rec )
  * Write the record at RECNUM
  */
 static int
-write_record( u32 recnum, TRUSTREC *rec )
+write_record( ulong recnum, TRUSTREC *rec )
 {
     byte buf[TRUST_RECORD_LEN], *p;
     int rc = 0;
@@ -337,20 +372,20 @@ write_record( u32 recnum, TRUSTREC *rec )
       case 0:  /* unused record */
        break;
       case 1: /* version record */
-       log_bug(NULL);
+       BUG();
        break;
       case 2:
-       u32tobuf(p, rec->r.pubkey.local_id); p += 4;
+       ulongtobuf(p, rec->r.pubkey.local_id); p += 4;
        u32tobuf(p, rec->r.pubkey.keyid[0]); p += 4;
        u32tobuf(p, rec->r.pubkey.keyid[1]); p += 4;
-       *p++ = rec->r.pubkey.algo;
+       *p++ = rec->r.pubkey.pubkey_algo;
        *p++ = rec->r.pubkey.reserved;
        memcpy( p, rec->r.pubkey.fingerprint, 20); p += 20;
        *p++ = rec->r.pubkey.ownertrust;
        assert( rec->r.pubkey.local_id == recnum );
        break;
       case 3:
-       u32tobuf(p, rec->r.cache.local_id); p += 4;
+       ulongtobuf(p, rec->r.cache.owner); p += 4;
        u32tobuf(p, rec->r.cache.keyid[0]); p += 4;
        u32tobuf(p, rec->r.cache.keyid[1]); p += 4;
        *p++ = rec->r.cache.valid;
@@ -363,15 +398,15 @@ write_record( u32 recnum, TRUSTREC *rec )
        break;
       case 4:
       case 5:
-       u32tobuf(p, rec->r.sigrec.owner); p += 4;
-       u32tobuf(p, rec->r.sigrec.chain); p += 4;
+       ulongtobuf(p, rec->r.sigrec.owner); p += 4;
+       ulongtobuf(p, rec->r.sigrec.chain); p += 4;
        for(i=0; i < SIGS_PER_RECORD; i++ ) {
-           u32tobuf(p, rec->r.sigrec.sig[i].local_id); p += 4;
+           ulongtobuf(p, rec->r.sigrec.sig[i].local_id); p += 4;
            *p++ = rec->r.sigrec.sig[i].flag;
        }
        break;
       default:
-       log_bug(NULL);
+       BUG();
     }
 
     if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
@@ -387,11 +422,18 @@ write_record( u32 recnum, TRUSTREC *rec )
     return rc;
 }
 
-static u32
-new_local_id()
+
+
+/****************
+ * create a new record and return its record number
+ */
+static ulong
+new_recnum()
 {
     off_t offset;
-    u32 recnum;
+    ulong recnum;
+    TRUSTREC rec;
+    int rc;
 
     /* fixme: look for unused records */
     offset = lseek( db_fd, 0, SEEK_END );
@@ -399,6 +441,15 @@ new_local_id()
        log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
     recnum = offset / TRUST_RECORD_LEN;
     assert(recnum); /* this is will never be the first record */
+
+    /* we must write a record, so that the next call to this function
+     * returns another recnum */
+    memset( &rec, 0, sizeof rec );
+    rec.rectype = 0; /* free record */
+    rc = write_record(recnum, &rec );
+    if( rc )
+       log_fatal("%s: failed to append a record: %s\n",
+                                           db_name, g10_errstr(rc));
     return recnum ;
 }
 
@@ -409,11 +460,10 @@ new_local_id()
 static int
 scan_record_by_pkc( PKT_public_cert *pkc, TRUSTREC *rec, int rectype )
 {
-    u32 recnum;
+    ulong recnum;
     u32 keyid[2];
     byte *fingerprint;
     size_t fingerlen;
-    int dbg = DBG_TRUST;
     int rc;
 
     assert( rectype == 2 || rectype == 3 );
@@ -431,7 +481,7 @@ scan_record_by_pkc( PKT_public_cert *pkc, TRUSTREC *rec, int rectype )
        if( rec->rectype == 2 ) {
            if( rec->r.pubkey.keyid[0] == keyid[0]
                && rec->r.pubkey.keyid[1] == keyid[1]
-               && rec->r.pubkey.algo     == pkc->pubkey_algo
+               && rec->r.pubkey.pubkey_algo == pkc->pubkey_algo
                && !memcmp(rec->r.pubkey.fingerprint, fingerprint, fingerlen)
              ) { /* found */
                /* store the local_id */
@@ -460,11 +510,9 @@ scan_record_by_pkc( PKT_public_cert *pkc, TRUSTREC *rec, int rectype )
  * with LOCAL_ID
  */
 static int
-scan_record( u32 local_id, TRUSTREC *rec, int rectype, u32 *r_recnum )
+scan_record( ulong local_id, TRUSTREC *rec, int rectype, ulong *r_recnum )
 {
-    u32 recnum;
-    u32 keyid[2];
-    int dbg = DBG_TRUST;
+    ulong recnum;
     int rc;
 
     assert( rectype == 3 || rectype == 4 );
@@ -502,11 +550,292 @@ scan_record( u32 local_id, TRUSTREC *rec, int rectype, u32 *r_recnum )
 }
 
 
+static void
+dump_record( ulong rnum, TRUSTREC *rec, FILE *fp  )
+{
+    int i, any;
+
+    fprintf(fp, "trust record %lu, type=", rnum );
+
+    switch( rec->rectype ) {
+      case 0: fprintf(fp, "free\n");
+       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 );
+       break;
+      case 3: fprintf(fp, "cache\n");
+      case 4:
+      case 5:
+       fprintf(fp, "sigrec, owner=%lu, chain=%lu%s\n",
+                        rec->r.sigrec.owner, rec->r.sigrec.chain,
+                        rec->rectype == 4?"":" (extend)");
+       for(i=any=0; i < SIGS_PER_RECORD; i++ ) {
+           if( rec->r.sigrec.sig[i].local_id ) {
+               if( !any ) {
+                   putc('\t', fp);
+                   any++;
+               }
+               fprintf(fp, "  %lu:%02x", rec->r.sigrec.sig[i].local_id,
+                                             rec->r.sigrec.sig[i].flag );
+           }
+       }
+       if( any )
+           putc('\n', fp);
+       break;
+      default:
+       fprintf(fp, "%d (unknown)\n", rec->rectype );
+       break;
+    }
+}
+
+
+/****************
+ * If we do not have a local_id in a signature packet, find the owner of
+ * the signature packet in our trustdb or insert him into the trustdb
+ */
+static int
+set_signature_packets_local_id( PKT_signature *sig )
+{
+    PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
+    TRUSTREC rec;
+    int rc;
+
+    rc = get_pubkey( pkc, sig->keyid );
+    if( rc)
+       goto leave;
+    if( !pkc->local_id ) {
+       rc = scan_record_by_pkc( pkc, &rec, 2 );
+       if( rc == -1 )
+           rc = insert_trust_record( pkc );
+       if( rc )
+           goto leave;
+       /* fixme: we should propagate the local_id to all copies of the PKC */
+    }
+    sig->local_id = pkc->local_id;
+
+  leave:
+    free_public_cert( pkc );
+    return rc;
+}
+
+
+void
+list_trustdb( const char *username )
+{
+    TRUSTREC rec;
+
+    if( username ) {
+       PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
+       int rc;
+
+       if( (rc = get_pubkey_byname( pkc, username )) )
+           log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
+       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 if( (rc = list_sigs( pkc->local_id )) )
+           log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
+       free_public_cert( pkc );
+    }
+    else {
+       ulong recnum;
+       int i;
+
+       printf("TrustDB: %s\n", db_name );
+       for(i=9+strlen(db_name); i > 0; i-- )
+           putchar('-');
+       putchar('\n');
+       no_io_dbg = 1;
+       for(recnum=0; !read_record( recnum, &rec); recnum++ )
+           dump_record( recnum, &rec, stdout );
+       no_io_dbg = 0;
+    }
+}
+
+void
+list_trust_path( int max_depth, const char *username )
+{
+    int rc;
+    TRUSTREC rec;
+    PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
+
+    if( max_depth < 1 )
+       max_depth = MAX_LIST_SIGS_DEPTH+1;
+
+
+    if( (rc = get_pubkey_byname( pkc, username )) )
+       log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
+    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 {
+       LOCAL_ID_INFO *lids;
+       ulong stack[MAX_LIST_SIGS_DEPTH];
+
+       lids = new_lid_table();
+       stack[0] = pkc->local_id;
+       rc = do_list_path( pkc->local_id, 1, max_depth, lids, stack );
+       putchar('\n');
+
+       release_lid_table(lids);
+       if( rc )
+           log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
+    }
+
+    free_public_cert( pkc );
+}
+
+/****************
+ * Walk throug the signatures of a public key.
+ * The caller must provide a context structure, with all fields set
+ * to zero, but the pubkeyid filed set to the requested pubkey;
+ * This function does not change this field.  On return the context
+ * is filled with the local-id of the signature and the signature flag.
+ * No fields should be changed (clearing all fields and setting
+ * pubkeyid is okay to continue with an other pubkey)
+ * Returns: 0 - okay, -1 for eof (no more sigs) or any other errorcode
+ */
+static int
+walk_sigrecs( SIGREC_CONTEXT *c )
+{
+    int rc=0;
+    TRUSTREC *r;
+    ulong rnum;
+
+    if( c->ctl.eof )
+       return -1;
+    r = &c->ctl.rec;
+    if( !r->rectype ) { /* this is the first call */
+       rc = scan_record( c->pubkey_id, r, 4, &rnum );
+       if( rc == -1 ) { /* no signature records */
+           c->ctl.eof = 1;
+           return -1;  /* return eof */
+       }
+       if( rc ) {
+           log_error("scan_record(sigrec) failed: %s\n", g10_errstr(rc));
+           c->ctl.eof = 1;
+           return rc;
+       }
+       c->ctl.index = 0;
+    }
+    /* enter loop to skip deleted sigs */
+    do {
+       if( c->ctl.index >= SIGS_PER_RECORD ) {
+           /* read the next record */
+           if( !r->r.sigrec.chain ) {
+               c->ctl.eof = 1;
+               return -1;  /* return eof */
+           }
+           rnum = r->r.sigrec.chain;
+           rc = read_record( rnum, r );
+           if( rc ) {
+               log_error("error reading next sigrec: %s\n", g10_errstr(rc));
+               c->ctl.eof = 1;
+               return rc;
+           }
+           if( r->r.sigrec.owner != c->pubkey_id ) {
+               log_error("chained sigrec %lu has a wrong owner\n", rnum );
+               c->ctl.eof = 1;
+               return G10ERR_TRUSTDB;
+           }
+           c->ctl.index = 0;
+       }
+    } while( !r->r.sigrec.sig[c->ctl.index++].local_id );
+    c->sig_id = r->r.sigrec.sig[c->ctl.index-1].local_id;
+    c->sig_flag = r->r.sigrec.sig[c->ctl.index-1].flag;
+    return 0;
+}
 
 /***********************************************
  ************* trust logic  *******************
  ***********************************************/
 
+static LOCAL_ID_INFO *
+new_lid_table(void)
+{
+    return m_alloc_clear( 16 * sizeof(LOCAL_ID_INFO));
+}
+
+static void
+release_lid_table( LOCAL_ID_INFO *tbl )
+{
+    LOCAL_ID_INFO a, a2;
+    int i;
+
+    for(i=0; i < 16; i++ ) {
+       for(a=tbl[i]; a; a = a2 ) {
+           a2 = a->next;
+           m_free(a);
+       }
+    }
+    m_free(tbl);
+}
+
+/****************
+ * Add a new item to the table or return 1 if we aread have this item
+ * fixme: maybe its a good idea to tage items from an unused item list.
+ */
+static int
+add_lid_table_item( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag )
+{
+    LOCAL_ID_INFO a;
+
+    for( a = tbl[lid & 0x0f]; a; a = a->next )
+       if( a->lid == lid )
+           return 1;
+    a = m_alloc( sizeof *a );
+    a->lid = lid;
+    a->flag = flag;
+    a->next = tbl[lid & 0x0f];
+    tbl[lid & 0x0f] = a;
+    return 0;
+}
+
+static int
+get_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned *flag )
+{
+    LOCAL_ID_INFO a;
+
+    for( a = tbl[lid & 0x0f]; a; a = a->next )
+       if( a->lid == lid ) {
+           if( flag )
+               *flag = a->flag;
+           return 0;
+       }
+    return -1;
+}
+
+
+
+
+static int
+keyid_from_local_id( ulong lid, u32 *keyid )
+{
+    TRUSTREC rec;
+    int rc;
+
+    rc = read_record( lid, &rec );
+    if( rc ) {
+       log_error("error reading record with local_id %lu: %s\n",
+                                                   lid, g10_errstr(rc));
+       return G10ERR_TRUSTDB;
+    }
+    if( rec.rectype != 2 ) {
+       log_error("record with local_id %lu is not a pubkey record\n", lid);
+       return G10ERR_TRUSTDB;
+    }
+    keyid[0] = rec.r.pubkey.keyid[0];
+    keyid[1] = rec.r.pubkey.keyid[1];
+    return 0;
+}
+
+
 /****************
  * Verify, that all our public keys are in the trustDB and marked as
  * ultimately trusted.
@@ -522,7 +851,7 @@ verify_own_certs()
     int trust;
 
     while( !(rc=enum_secret_keys( &enum_context, skc) ) ) {
-       /* fixme: to be sure that it is a secret key of our own,
+       /* fixed: to be sure that it is a secret key of our own,
         *        we should check it, but this needs a passphrase
         *        for every key and this boring for the user.
         *        Solution:  Sign the secring and the trustring
@@ -557,12 +886,26 @@ verify_own_certs()
        }
        if( trust & TRUST_NO_PUBKEY ) {
            log_info("keyid %08lX: not yet in trustdb\n", (ulong)keyid[1] );
-           /* FIXME: insert */
+           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] );
        }
        else if( (trust & TRUST_MASK) != TRUST_ULT_TRUST )  {
-           log_error("keyid %08lX: not marked as ultimately trusted\n",
+         /*log_error("keyid %08lX: not marked as ultimately trusted\n",
                                                           (ulong)keyid[1] );
-           /* FIXME: mark */
+              FIXME: mark */
+       }
+
+       if( !(trust & TRUST_NO_PUBKEY) ) {
+           if( DBG_TRUST )
+               log_debug("putting %08lX(%lu) into ultikey_table\n",
+                                       (ulong)keyid[1], pkc->local_id );
+           if( add_lid_table_item( ultikey_table, pkc->local_id, 0 ) )
+               log_error("keyid %08lX: already in ultikey_table\n",
+                                                           (ulong)keyid[1]);
        }
 
        release_secret_cert_parts( skc );
@@ -579,6 +922,156 @@ verify_own_certs()
     return rc;
 }
 
+static void
+print_user_id( const char *text, u32 *keyid )
+{
+    char *p;
+    size_t n;
+
+    p = get_user_id( keyid, &n );
+    if( *text ) {
+       fputs( text, stdout);
+       putchar(' ');
+    }
+    putchar('\"');
+    print_string( stdout, p, n );
+    putchar('\"');
+    putchar('\n');
+    m_free(p);
+}
+
+/* (a non-recursive algorithm would be easier) */
+static int
+do_list_sigs( ulong root, ulong pubkey, int depth,
+             LOCAL_ID_INFO *lids, unsigned *lineno )
+{
+    SIGREC_CONTEXT sx;
+    int rc;
+    u32 keyid[2];
+
+    memset( &sx, 0, sizeof sx );
+    sx.pubkey_id = pubkey;
+    for(;;) {
+       rc = walk_sigrecs( &sx );
+       if( rc )
+           break;
+       rc = keyid_from_local_id( sx.sig_id, keyid );
+       if( rc ) {
+           printf("%6u: %*s????????(%lu:%02x)\n", *lineno, depth*4, "",
+                                                  sx.sig_id, sx.sig_flag );
+           ++*lineno;
+       }
+       else {
+           printf("%6u: %*s%08lX(%lu:%02x) ", *lineno, depth*4, "",
+                             (ulong)keyid[1], sx.sig_id, sx.sig_flag );
+           /* check wether we already checked this pubkey */
+           if( !get_lid_table_flag( ultikey_table, sx.sig_id, NULL ) ) {
+               print_user_id("[ultimately trusted]", keyid);
+               ++*lineno;
+           }
+           else if( sx.sig_id == pubkey ) {
+               printf("[self-signature]\n");
+               ++*lineno;
+           }
+           else if( sx.sig_id == root ) {
+               printf("[closed]\n");
+               ++*lineno;
+           }
+           else if( add_lid_table_item( lids, sx.sig_id, *lineno ) ) {
+               unsigned refline;
+               get_lid_table_flag( lids, sx.sig_id, &refline );
+               printf("[see line %u]\n", refline);
+               ++*lineno;
+           }
+           else if( depth+1 >= MAX_LIST_SIGS_DEPTH  ) {
+               print_user_id( "[too deeply nested]", keyid );
+               ++*lineno;
+           }
+           else {
+               print_user_id( "", keyid );
+               ++*lineno;
+               rc = do_list_sigs( root, sx.sig_id, depth+1, lids, lineno );
+               if( rc )
+                   break;
+           }
+       }
+    }
+    return rc==-1? 0 : rc;
+}
+
+/****************
+ * List all signatures of a public key
+ */
+static int
+list_sigs( ulong pubkey_id )
+{
+    int rc;
+    u32 keyid[2];
+    LOCAL_ID_INFO *lids;
+    unsigned lineno = 1;
+
+    rc = keyid_from_local_id( pubkey_id, keyid );
+    if( rc ) {
+       log_error("Hmmm, no pubkey record for local_id %lu\n", pubkey_id);
+       return rc;
+    }
+    printf("Signatures of %08lX(%lu) ", (ulong)keyid[1], pubkey_id );
+    print_user_id("", keyid);
+    printf("----------------------\n");
+
+    lids = new_lid_table();
+    rc = do_list_sigs( pubkey_id, pubkey_id, 0, lids, &lineno );
+    putchar('\n');
+    release_lid_table(lids);
+    return rc;
+}
+
+
+
+
+
+static int
+do_list_path( ulong pubkey, int depth, int max_depth,
+             LOCAL_ID_INFO *lids, ulong *stack )
+{
+    SIGREC_CONTEXT sx;
+    int rc;
+
+    if( depth > max_depth || depth >= MAX_LIST_SIGS_DEPTH  )
+       return 0;
+    if( !get_lid_table_flag( ultikey_table, pubkey, NULL ) ) {
+       /* found a path */
+       int i;
+       u32 keyid[2];
+
+       for(i=0; i < depth; i++ ) {
+           if( keyid_from_local_id( stack[i], keyid ) )
+               printf("%*s????????(%lu) ", i*4,"", stack[i] );
+           else {
+               printf("%*s%08lX(%lu) ", i*4,"", keyid[1], stack[i] );
+               print_user_id("", keyid );
+           }
+       }
+       putchar('\n');
+       return 0;
+    }
+
+    if( add_lid_table_item( lids, pubkey, 0 ) )
+       return 0;
+
+    memset( &sx, 0, sizeof sx );
+    sx.pubkey_id = pubkey;
+    do {
+       rc = walk_sigrecs( &sx );
+       if( !rc ) {
+           stack[depth] = sx.sig_id;
+           rc = do_list_path( sx.sig_id, depth+1, max_depth, lids, stack );
+       }
+    } while( !rc );
+    return rc==-1? 0 : rc;
+}
+
+
 
 
 /****************
@@ -586,23 +1079,30 @@ verify_own_certs()
  * as checked.
  */
 static int
-check_sigs( KBNODE keyblock )
+check_sigs( KBNODE keyblock, int *selfsig_okay )
 {
     KBNODE kbctx;
     KBNODE node;
     int rc;
 
+    *selfsig_okay = 0;
     for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
        if( node->pkt->pkttype == PKT_SIGNATURE
            && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
-           PKT_signature *sig = node->pkt->pkt.signature;
-
-           rc = check_key_signature( keyblock, node );
-           if( !rc )
-               node->flag |= 1; /* mark signature valid */
+           int selfsig;
+           rc = check_key_signature( keyblock, node, &selfsig );
+           if( !rc ) {
+               if( selfsig ) {
+                   node->flag |= 2; /* mark signature valid */
+                   *selfsig_okay = 1;
+               }
+               else
+                   node->flag |= 1; /* mark signature valid */
+           }
            if( DBG_TRUST )
                log_debug("trustdb: sig from %08lX: %s\n",
-                                               rc? g10_errstr(rc): "okay" );
+                               (ulong)node->pkt->pkt.signature->keyid[1],
+                                                   g10_errstr(rc) );
        }
     }
     return 0;
@@ -614,8 +1114,124 @@ check_sigs( KBNODE keyblock )
  * to the trustdb
  */
 static int
-build_sigrecs( KBNODE keyblock )
+build_sigrecs( ulong pubkeyid )
 {
+    TRUSTREC rec, rec2;
+    PUBKEY_FIND_INFO finfo=NULL;
+    KBPOS kbpos;
+    KBNODE keyblock = NULL;
+    KBNODE kbctx;
+    KBNODE node;
+    int rc=0;
+    int i, selfsig;
+    ulong rnum, rnum2;
+
+    if( DBG_TRUST )
+       log_debug("trustdb: build_sigrecs for pubkey %lu\n", (ulong)pubkeyid );
+
+    /* get the keyblock */
+    if( (rc=read_record( pubkeyid, &rec )) ) {
+       log_error("build_sigrecs: can't read pubkey record\n");
+       goto leave;
+    }
+    finfo = m_alloc_clear( sizeof *finfo );
+    finfo->keyid[0] = rec.r.pubkey.keyid[0];
+    finfo->keyid[1] = rec.r.pubkey.keyid[1];
+    finfo->pubkey_algo = rec.r.pubkey.pubkey_algo;
+    memcpy( finfo->fingerprint, rec.r.pubkey.fingerprint, 20);
+    rc = find_keyblock( finfo, &kbpos );
+    if( rc ) {
+       log_error("build_sigrecs: find_keyblock failed\n" );
+       goto leave;
+    }
+    rc = read_keyblock( &kbpos, &keyblock );
+    if( rc ) {
+       log_error("build_sigrecs: read_keyblock failed\n" );
+       goto leave;
+    }
+    /* check all key signatures */
+    rc = check_sigs( keyblock, &selfsig );
+    if( rc ) {
+       log_error("build_sigrecs: check_sigs failed\n" );
+       goto leave;
+    }
+    if( !selfsig ) {
+       log_error("build_sigrecs: self-certificate missing\n" );
+       rc = G10ERR_BAD_CERT;
+       goto leave;
+    }
+
+    /* valid key signatures are now marked; we can now build the
+     * sigrecs */
+    memset( &rec, 0, sizeof rec );
+    rec.rectype = 4;
+    i = 0;
+    rnum = rnum2 = 0;
+    for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
+       if( node->flag & 1 ) {
+           assert( node->pkt->pkttype == PKT_SIGNATURE );
+           if( !node->pkt->pkt.signature->local_id )  {
+               /* 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. */
+               rc = set_signature_packets_local_id( node->pkt->pkt.signature );
+               if( rc )
+                   log_fatal("set_signature_packets_local_id failed: %s\n",
+                                                             g10_errstr(rc));
+           }
+           if( i == SIGS_PER_RECORD ) {
+               /* write the record */
+               rnum = new_recnum();
+               if( rnum2 ) { /* write the stored record */
+                   rec2.r.sigrec.owner = pubkeyid;
+                   rec2.r.sigrec.chain = rnum; /* the next record number */
+                   rc = write_record( rnum2, &rec2 );
+                   if( rc ) {
+                       log_error("build_sigrecs: write_record failed\n" );
+                       goto leave;
+                   }
+               }
+               rec2 = rec;
+               rnum2 = rnum;
+               memset( &rec, 0, sizeof rec );
+               rec.rectype = 5;
+               i = 0;
+           }
+           rec.r.sigrec.sig[i].local_id = node->pkt->pkt.signature->local_id;
+           rec.r.sigrec.sig[i].flag = 0;
+           i++;
+       }
+    }
+    if( i || rnum2 ) {
+       /* write the record */
+       rnum = new_recnum();
+       if( rnum2 ) { /* write the stored record */
+           rec2.r.sigrec.owner = pubkeyid;
+           rec2.r.sigrec.chain = rnum;
+           rc = write_record( rnum2, &rec2 );
+           if( rc ) {
+               log_error("build_sigrecs: write_record failed\n" );
+               goto leave;
+           }
+       }
+       if( i ) { /* write the pending record */
+           rec.r.sigrec.owner = pubkeyid;
+           rec.r.sigrec.chain = 0;
+           rc = write_record( rnum, &rec );
+           if( rc ) {
+               log_error("build_sigrecs: write_record failed\n" );
+               goto leave;
+           }
+       }
+    }
+
+  leave:
+    m_free( finfo );
+    release_kbnode( keyblock );
+    if( DBG_TRUST )
+       log_debug("trustdb: build_sigrecs: %s\n", g10_errstr(rc) );
+    return rc;
 }
 
 
@@ -624,6 +1240,7 @@ build_sigrecs( KBNODE keyblock )
 /****************
  * Recursive check the signatures.
  */
+ #if 0
 static int
 walk( KBNODE keyblock, int levels )
 {
@@ -640,9 +1257,9 @@ walk( KBNODE keyblock, int levels )
            }
        }
     }
-
+    return -1;
 }
-
+#endif
 
 
 
@@ -651,10 +1268,25 @@ walk( KBNODE keyblock, int levels )
  *
  */
 static int
-check_trust()
+check_trust( ulong pubkeyid )
 {
-    /* check the ca
+    int rc=0;
+    ulong rnum;
+    TRUSTREC rec;
+
+    /* verify the cache */
+
+    /* do we have sigrecs */
+    rc = scan_record( pubkeyid, &rec, 4, &rnum );
+    if( rc == -1 ) { /* no sigrecs, so build them */
+       rc = build_sigrecs( pubkeyid );
+       if( !rc ) /* and read again */
+           rc = scan_record( pubkeyid, &rec, 4, &rnum );
+    }
+    if( rc )
+       return rc;  /* error while looking for sigrec or building sigrecs */
 
+    return 0;
 }
 
 
@@ -665,26 +1297,34 @@ check_trust()
 
 /****************
  * Perform some checks over the trustdb
- *  level 0: used for initial program startup
+ *  level 0: only open the db
+ *       1: used for initial program startup
  */
 int
-check_trustdb( int level )
+init_trustdb( int level )
 {
     int rc=0;
 
-    if( !level ) {
-       char *fname = make_filename("~/.g10", "trustDB", NULL );
+    if( !ultikey_table )
+       ultikey_table = new_lid_table();
+
+    if( !level || level==1 ) {
+       char *fname = make_filename("~/.g10", "trustdb.g10", NULL );
        if( access( fname, R_OK ) ) {
            if( errno != ENOENT ) {
                log_error("can't access %s: %s\n", fname, strerror(errno) );
                m_free(fname);
                return G10ERR_TRUSTDB;
            }
-           create_db( fname );
+           if( level )
+               create_db( fname );
        }
        m_free(db_name);
        db_name = fname;
 
+       if( !level )
+           return 0;
+
        /* we can verify a signature about our local data (secring and trustdb)
         * in ~/.g10/ here */
        rc = verify_private_data();
@@ -699,7 +1339,7 @@ check_trustdb( int level )
        }
     }
     else
-       log_bug(NULL);
+       BUG();
 
     return rc;
 }
@@ -747,7 +1387,7 @@ check_pkc_trust( PKT_public_cert *pkc, int *r_trustlevel )
        if( (rc=scan_record_by_pkc( pkc, &rec, 2 )) && rc != -1 ) {
            log_error("check_pkc_trust: scan_record_by_pkc(2) failed: %s\n",
                                                            g10_errstr(rc));
-           return G10ERR_TRUSTDB;
+           return rc;
        }
        else if( rc == -1 ) {
            log_error("check_pkc_trust: pubkey not in TrustDB\n");
@@ -757,7 +1397,11 @@ check_pkc_trust( PKT_public_cert *pkc, int *r_trustlevel )
     }
     /* fixme: do some additional checks on the pubkey record */
 
-    /* see wether we have a cache record */
+    rc = check_trust( pkc->local_id );
+    if( rc ) {
+       log_error("check_pkc_trust: check_trust failed: %s\n", g10_errstr(rc));
+       return rc;
+    }
 
 
   leave:
@@ -768,6 +1412,33 @@ check_pkc_trust( PKT_public_cert *pkc, int *r_trustlevel )
 }
 
 
+int
+get_ownertrust( PKT_public_cert *pkc, int *r_otrust )
+{
+    TRUSTREC rec;
+    int rc;
+
+    /* get the pubkey record */
+    if( pkc->local_id ) {
+       if( read_record( pkc->local_id, &rec ) ) {
+           log_error("get_ownertrust: 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",
+                                                           g10_errstr(rc));
+           return rc;
+       }
+       else if( rc == -1 )
+           return rc;
+    }
+    *r_otrust = rec.r.pubkey.ownertrust;
+    return 0;
+}
+
+
 /****************
  * Insert a trust record into the TrustDB
  * This function failes if this record already exists.
@@ -777,7 +1448,7 @@ insert_trust_record( PKT_public_cert *pkc )
 {
     TRUSTREC rec;
     u32 keyid[2];
-    u32 recnum;
+    ulong recnum;
     byte *fingerprint;
     size_t fingerlen;
 
@@ -785,21 +1456,22 @@ insert_trust_record( PKT_public_cert *pkc )
     if( DBG_TRUST )
        log_debug("trustdb: insert_record\n");
 
-    assert( !pkc->local_id );
+    if( pkc->local_id )
+       log_bug("pkc->local_id=%lu\n", (ulong)pkc->local_id );
 
     keyid_from_pkc( pkc, keyid );
     fingerprint = fingerprint_from_pkc( pkc, &fingerlen );
 
     /* FIXME: check that we do not have this record. */
 
-    recnum = new_local_id();
+    recnum = new_recnum();
     /* build record */
     memset( &rec, 0, sizeof rec );
     rec.rectype = 2; /* the pubkey record */
     rec.r.pubkey.local_id = recnum;
     rec.r.pubkey.keyid[0] = keyid[0];
     rec.r.pubkey.keyid[1] = keyid[1];
-    rec.r.pubkey.algo = pkc->pubkey_algo;
+    rec.r.pubkey.pubkey_algo = pkc->pubkey_algo;
     memcpy(rec.r.pubkey.fingerprint, fingerprint, fingerlen );
     rec.r.pubkey.ownertrust = 0;
     if( write_record( recnum, &rec ) ) {
@@ -817,8 +1489,7 @@ int
 update_trust_record( PKT_public_cert *pkc, int new_trust )
 {
     TRUSTREC rec;
-    u32 keyid[2];
-    u32 recnum;
+    ulong recnum;
 
     if( DBG_TRUST )
        log_debug("trustdb: update_record\n");
index aff668e..bd15d25 100644 (file)
 
 
 /*-- trustdb.c --*/
-int check_trustdb( int level );
+void list_trustdb(const char *username);
+void list_trust_path( int max_depth, const char *username );
+int init_trustdb( int level );
 int check_pkc_trust( PKT_public_cert *pkc, int *r_trustlevel );
+int get_ownertrust( PKT_public_cert *pkc, int *r_otrust );
+int insert_trust_record( PKT_public_cert *pkc );
 int verify_private_data(void);
 int sign_private_data(void);
 
index 1f615e5..52d1a75 100644 (file)
@@ -78,6 +78,7 @@ int check_pubkey_algo( int algo );
 int check_digest_algo( int algo );
 
 /*-- random.c --*/
+int  quick_random_gen( int onoff );
 void randomize_buffer( byte *buffer, size_t length, int level );
 byte get_random_byte( int level );
 
index 450d910..305a147 100644 (file)
@@ -53,5 +53,6 @@
 #define G10ERR_RESOURCE_LIMIT 31
 #define G10ERR_INV_KEYRING    32
 #define G10ERR_TRUSTDB       33 /* a problem with the trustdb */
+#define G10ERR_BAD_CERT       34 /* bad certicate */
 
 #endif /*G10_ERRORS_H*/
index d29e0a0..e381445 100644 (file)
@@ -93,6 +93,7 @@ u32 iobuf_get_filelength( IOBUF a );
 const char *iobuf_get_fname( IOBUF a );
 
 void iobuf_set_block_mode( IOBUF a, size_t n );
+void iobuf_set_partial_block_mode( IOBUF a, size_t len );
 int  iobuf_in_block_mode( IOBUF a );
 
 /* get a byte form the iobuf; must check for eof prior to this function
index 7c4639f..7a43b30 100644 (file)
@@ -41,7 +41,6 @@ int mpi_debug_mode;
 
 #define BITS_PER_MPI_LIMB    (8*SIZEOF_UNSIGNED_LONG)
 #define BYTES_PER_MPI_LIMB   SIZEOF_UNSIGNED_LONG
-#define BYTES_PER_MPI_LIMB2  (2*SIZEOF_UNSIGNED_LONG)
 typedef unsigned long int mpi_limb_t;
 typedef   signed long int mpi_limb_signed_t;
 
index 7f25930..a33b7f2 100644 (file)
@@ -58,20 +58,38 @@ typedef struct {
 /*-- logger.c --*/
 void log_set_pid( int pid );
 int  log_get_errorcount( int clear );
-void printstr( int level, const char *fmt, ... );
-void log_bug( const char *fmt, ... );
-void log_fatal( const char *fmt, ... );
-void log_error( const char *fmt, ... );
-void log_info( const char *fmt, ... );
-void log_debug( const char *fmt, ... );
 void log_hexdump( const char *text, char *buf, size_t len );
 void log_mpidump( const char *text, MPI a );
 
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
+  void printstr( int level, const char *fmt, ... )
+                           __attribute__ ((format (printf,2,3)));
+  void log_bug( const char *fmt, ... )
+                           __attribute__ ((noreturn, format (printf,1,2)));
+  void log_bug0( void ) __attribute__ ((noreturn));
+  void log_fatal( const char *fmt, ... )
+                           __attribute__ ((noreturn, format (printf,1,2)));
+  void log_error( const char *fmt, ... ) __attribute__ ((format (printf,1,2)));
+  void log_info( const char *fmt, ... )  __attribute__ ((format (printf,1,2)));
+  void log_debug( const char *fmt, ... ) __attribute__ ((format (printf,1,2)));
+#else
+  void printstr( int level, const char *fmt, ... );
+  void log_bug( const char *fmt, ... );
+  void log_bug0( void );
+  void log_fatal( const char *fmt, ... );
+  void log_error( const char *fmt, ... );
+  void log_info( const char *fmt, ... );
+  void log_debug( const char *fmt, ... );
+#endif
+
+
 /*-- errors.c --*/
 const char * g10_errstr( int no );
 
 /*-- argparse.c --*/
 int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts);
+int optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
+                  ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts);
 void usage( int level );
 const char *default_strusage( int level );
 
@@ -112,5 +130,6 @@ char *strlwr(char *a);
 #define STR2(v) STR(v)
 #define DIM(v) (sizeof(v)/sizeof((v)[0]))
 #define DIMof(type,member)   DIM(((type *)0)->member)
+#define BUG() log_bug0()
 
 #endif /*G10_UTIL_H*/
index 1eb63a0..864dc02 100644 (file)
@@ -32,8 +32,7 @@
 unsigned
 mpi_get_nbits( MPI a )
 {
-    unsigned nbits;
-    unsigned n, count = 0;
+    unsigned n;
 
     if( a->nlimbs ) {
        mpi_limb_t alimb = a->d[a->nlimbs-1];
index f084c7e..638d980 100644 (file)
@@ -193,7 +193,7 @@ void mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size );
 void mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size,
                                                mpi_ptr_t tspace);
 
-/*-- mpihelp-mul_1.c (or xxx/cpu/*.S) --*/
+/*-- mpihelp-mul_1.c (or xxx/cpu/ *.S) --*/
 mpi_limb_t mpihelp_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
                          mpi_size_t s1_size, mpi_limb_t s2_limb);
 
index fcf500c..2df34b7 100644 (file)
@@ -52,7 +52,7 @@ mpi_powm( MPI res, MPI base, MPI exp, MPI mod)
     mpi_ptr_t xp_marker=NULL;
     int assign_rp=0;
     mpi_ptr_t tspace = NULL;
-    mpi_size_t tsize;
+    mpi_size_t tsize=0;   /* to avoid compiler warning, fixme: check */
 
     esize = exp->nlimbs;
     msize = mod->nlimbs;
index 43b97be..7558399 100644 (file)
 int
 mpi_write( IOBUF out, MPI a )
 {
-    int i;
-    unsigned nbits = a->nlimbs * BITS_PER_MPI_LIMB;
-    mpi_limb_t limb;
+    int rc;
+    unsigned nbits = mpi_get_nbits(a);
+    byte *p, *buf;
+    unsigned n;
 
-    /* fixme: use a->nbits if valid */
     if( nbits > MAX_EXTERN_MPI_BITS )
        log_bug("mpi_encode: mpi too large (%u bits)\n", nbits);
+
     iobuf_put(out, (nbits >>8) );
     iobuf_put(out, (nbits) );
-    for(i=a->nlimbs-1; i >= 0; i-- ) {
-       limb = a->d[i];
-      #if BYTES_PER_MPI_LIMB == 4
-       iobuf_put(out, (limb >> 24) );
-       iobuf_put(out, (limb >> 16) );
-       iobuf_put(out, (limb >>  8) );
-       iobuf_put(out, (limb      ) );
-      #elif BYTES_PER_MPI_LIMB == 8
-       iobuf_put(out, (limb >> 56) );
-       iobuf_put(out, (limb >> 48) );
-       iobuf_put(out, (limb >> 40) );
-       iobuf_put(out, (limb >> 32) );
-       iobuf_put(out, (limb >> 24) );
-       iobuf_put(out, (limb >> 16) );
-       iobuf_put(out, (limb >>  8) );
-       iobuf_put(out, (limb      ) );
-      #else
-       #error Make this function work with other LIMB sizes
-      #endif
-    }
-    return 0;
+
+    p = buf = mpi_get_buffer( a, &n, NULL );
+    for( ; !*p && n; p++, n-- )
+       ;
+    rc = iobuf_write( out, p, n );
+    m_free(buf);
+    return rc;
 }
 
 
@@ -225,13 +212,22 @@ mpi_print( FILE *fp, MPI a, int mode )
     if( a == MPI_NULL )
        return fprintf(fp, "[MPI_NULL]");
     if( !mode )
-       n += fprintf(fp, "[%d bits]", a->nlimbs * BITS_PER_MPI_LIMB );
+       n += fprintf(fp, "[%u bits]", mpi_get_nbits(a) );
     else {
        if( a->sign )
            putc('-', fp);
+       #if BYTES_PER_MPI_LIMB == 2
+         #define X "4"
+       #elif BYTES_PER_MPI_LIMB == 4
+         #define X "8"
+       #elif BYTES_PER_MPI_LIMB == 8
+         #define X "16"
+       #else
+         #error please define the format here
+       #endif
        for(i=a->nlimbs; i > 0 ; i-- ) {
-           n += fprintf(fp, i!=a->nlimbs? "%0" STR2(BYTES_PER_MPI_LIMB2)
-                               "lX":"%lX", (unsigned long)a->d[i-1] );
+           n += fprintf(fp, i!=a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]);
+       #undef X
        }
        if( !a->nlimbs )
            putc('0', fp );
index 0c8e648..068a9a3 100644 (file)
@@ -45,7 +45,7 @@ mpi_alloc( unsigned nlimbs )
     MPI a;
 
     if( DBG_MEMORY )
-       log_debug("mpi_alloc(%lu)\n", nlimbs*BITS_PER_MPI_LIMB );
+       log_debug("mpi_alloc(%u)\n", nlimbs*BITS_PER_MPI_LIMB );
   #ifdef M_DEBUG
     a = m_debug_alloc( sizeof *a, info );
     a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 0, info ) : NULL;
@@ -77,7 +77,7 @@ mpi_alloc_secure( unsigned nlimbs )
     MPI a;
 
     if( DBG_MEMORY )
-       log_debug("mpi_alloc_secure(%lu)\n", nlimbs*BITS_PER_MPI_LIMB );
+       log_debug("mpi_alloc_secure(%u)\n", nlimbs*BITS_PER_MPI_LIMB );
   #ifdef M_DEBUG
     a = m_debug_alloc( sizeof *a, info );
     a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 1, info ) : NULL;
index 80b7fcd..c6c0302 100644 (file)
@@ -188,7 +188,6 @@ int
 optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
               ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
 {
-    char *s, *s2;
     int state, i, c;
     int index=0;
     char keyword[100];
index 46797df..9b8848f 100644 (file)
@@ -33,6 +33,8 @@ g10_errstr( int err )
 
   #define X(n,s) case G10ERR_##n : p = s; break;
     switch( err ) {
+      case -1:         p = "eof"; break;
+      case 0:          p = "okay"; break;
       X(GENERAL,       "General error")
       X(UNKNOWN_PACKET, "Unknown packet type")
       X(UNKNOWN_VERSION,"Unknown version")
@@ -46,6 +48,7 @@ g10_errstr( int err )
       X(NO_PUBKEY      ,"Public key not found")
       X(CIPHER_ALGO    ,"Unknown cipher algorithm")
       X(KEYRING_OPEN   ,"Can't open the keyring")
+      X(INVALID_PACKET ,"Invalid packet")
       X(BAD_RING       ,"Broken keyring")
       X(NO_USER_ID     ,"No such user id found")
       X(NO_SECKEY      ,"Secret key not available")
@@ -61,8 +64,10 @@ g10_errstr( int err )
       X(NI_PUBKEY      ,"Unimplemented pubkey algorithm")
       X(NI_CIPHER      ,"Unimplemented cipher algorithm")
       X(SIG_CLASS      ,"Unknown signature class")
+      X(TRUSTDB        ,"TrustDB error")
+      X(BAD_CERT       ,"Bad certificate")
 
-      default: p = buf; sprintf(buf, "Error code %d", err); break;
+      default: p = buf; sprintf(buf, "g10err=%d", err); break;
     }
   #undef X
     return p;
index ad98219..72a14f5 100644 (file)
@@ -40,6 +40,7 @@ typedef struct {
     int usage;
     size_t size;
     size_t count;
+    int partial;  /* 1 = partial header, 2 in last partial packet */
     int eof;
 } block_filter_ctx_t;
 
@@ -143,20 +144,64 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
            rc = -1;
        while( !rc && size ) {
            if( !a->size ) { /* get the length bytes */
-               c = iobuf_get(chain);
-               a->size = c << 8;
-               c = iobuf_get(chain);
-               a->size |= c;
-               if( c == -1 ) {
-                   log_error("block_filter: error reading length info\n");
-                   rc = G10ERR_READ_FILE;
-               }
-               if( !a->size ) {
+               if( a->partial == 2 ) {
                    a->eof = 1;
                    if( !n )
                        rc = -1;
                    break;
                }
+               else if( a->partial ) {
+                   if( (c = iobuf_get(chain)) == -1 ) {
+                       log_error("block_filter: 1st length byte missing\n");
+                       rc = G10ERR_READ_FILE;
+                       break;
+                   }
+                   if( c < 192 ) {
+                       a->size = c;
+                       a->partial = 2;
+                       if( !a->size ) {
+                           a->eof = 1;
+                           if( !n )
+                               rc = -1;
+                           break;
+                       }
+                   }
+                   else if( c < 224 ) {
+                       a->size = (c - 192) * 256;
+                       if( (c = iobuf_get(chain)) == -1 ) {
+                           log_error("block_filter: 2nd length byte missing\n");
+                           rc = G10ERR_READ_FILE;
+                           break;
+                       }
+                       a->size += c + 192;
+                       a->partial = 2;
+                       if( !a->size ) {
+                           a->eof = 1;
+                           if( !n )
+                               rc = -1;
+                           break;
+                       }
+                   }
+                   else { /* next partial body length */
+                       a->size = 1 << (c & 0x1f);
+                   }
+               }
+               else {
+                   c = iobuf_get(chain);
+                   a->size = c << 8;
+                   c = iobuf_get(chain);
+                   a->size |= c;
+                   if( c == -1 ) {
+                       log_error("block_filter: error reading length info\n");
+                       rc = G10ERR_READ_FILE;
+                   }
+                   if( !a->size ) {
+                       a->eof = 1;
+                       if( !n )
+                           rc = -1;
+                       break;
+                   }
+               }
            }
 
            for(; !rc && size && a->size; size--, a->size-- ) {
@@ -176,6 +221,7 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
     else if( control == IOBUFCTRL_FLUSH ) {
        size_t avail, n;
 
+       assert( !a->partial );
        for(p=buf; !rc && size; ) {
            n = size;
            avail = a->size - a->count;
@@ -205,7 +251,9 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
     else if( control == IOBUFCTRL_INIT ) {
        if( DBG_IOBUF )
            log_debug("init block_filter %p\n", a );
-       if( a->usage == 1 )
+       if( a->partial )
+           a->count = 0;
+       else if( a->usage == 1 )
            a->count = a->size = 0;
        else
            a->count = a->size; /* force first length bytes */
@@ -216,8 +264,12 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
     }
     else if( control == IOBUFCTRL_FREE ) {
        if( a->usage == 2 ) { /* write the end markers */
-           iobuf_writebyte(chain, 0);
-           iobuf_writebyte(chain, 0);
+           if( a->partial ) {
+           }
+           else {
+               iobuf_writebyte(chain, 0);
+               iobuf_writebyte(chain, 0);
+           }
        }
        else if( a->size ) {
            log_error("block_filter: pending bytes!\n");
@@ -784,7 +836,10 @@ iobuf_seek( IOBUF a, ulong newpos )
        return -1;
     }
     a->ntotal = newpos;
-    /* FIXME: flush all buffers (and remove filters?)*/
+    /* remove filters, but the last */
+    while( a->chain )
+       iobuf_pop_filter( a, a->filter, NULL );
+
 
     return 0;
 }
@@ -800,8 +855,6 @@ iobuf_seek( IOBUF a, ulong newpos )
 const char *
 iobuf_get_fname( IOBUF a )
 {
-    struct stat st;
-
     for( ; a; a = a->chain )
        if( !a->chain && a->filter == file_filter ) {
            file_filter_ctx_t *b = a->filter_ov;
@@ -832,6 +885,27 @@ iobuf_set_block_mode( IOBUF a, size_t n )
     }
 }
 
+/****************
+ * enable patial block mode as descriped in the OpenPGP draft.
+ * LEN is the first length
+ */
+void
+iobuf_set_partial_block_mode( IOBUF a, size_t len )
+{
+    block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx );
+
+    assert( a->usage == 1 || a->usage == 2 );
+    ctx->usage = a->usage;
+    if( !len ) {
+       iobuf_pop_filter(a, block_filter, NULL );
+    }
+    else {
+       ctx->partial = 1;
+       ctx->size = len;
+       iobuf_push_filter(a, block_filter, ctx );
+    }
+}
+
 
 /****************
  * Checks wether the stream is in block mode
@@ -841,7 +915,7 @@ int
 iobuf_in_block_mode( IOBUF a )
 {
     if( a && a->filter == block_filter )
-           return 1; /* yes */
+       return 1; /* yes */
     return 0; /* no */
 }
 
index c32332b..2355b62 100644 (file)
@@ -120,18 +120,20 @@ log_bug( const char *fmt, ... )
     va_list arg_ptr ;
 
     fprintf(stderr, "\nInternal Error%s: ", pidstring  ) ;
-    if( fmt ) {
-       va_start( arg_ptr, fmt ) ;
-       vfprintf(stderr,fmt,arg_ptr) ;
-       va_end(arg_ptr);
-    }
-    else
-       fputs("Ohhh jeeee ...\n", stderr);
+    va_start( arg_ptr, fmt ) ;
+    vfprintf(stderr,fmt,arg_ptr) ;
+    va_end(arg_ptr);
     fflush(stderr);
     abort();
 }
 
 void
+log_bug0()
+{
+    log_bug("Ohhhh jeeee ...\n");
+}
+
+void
 log_debug( const char *fmt, ... )
 {
     va_list arg_ptr ;
index 2cb5244..ec7b650 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
+#include <unistd.h>
 #ifdef HAVE_TCGETATTR
   #include <termios.h>
 #endif
@@ -99,7 +100,6 @@ do_get( const char *prompt, int hidden )
     char *buf;
     byte cbuf[1];
     int c, n, i;
-    FILE *fp;
   #ifdef HAVE_TCGETATTR
     struct termios termsave;
   #endif